diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d77071e669..2c7ce528c9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -107,7 +107,7 @@ git clone https://github.com/OpenTTD/OpenTTD-git-hooks.git openttd_hooks cd openttd git remote add upstream https://github.com/OpenTTD/OpenTTD.git cd .git/hooks -ln -s -t . ../../../openttd_hooks/hooks/* +ln -s ../../../openttd_hooks/hooks/* . ``` 2. If you cloned a while ago, get the latest changes from upstream: @@ -149,6 +149,16 @@ git push **IMPORTANT**: By submitting a patch, you agree to the [License](#license). +### Privacy Notice + +We would like to make you aware that contributing to OpenTTD via git will permanently store the name and email address you provide as well as the actual changes and the time and date you made it inside git's version history. + +This is inevitable, because it is a main feature of git. If you are concerned about your privacy, we strongly recommend to use "Anonymous <anonymous@openttd.org>" as the git commit author. We might refuse anonymous contributions if malicious intent is suspected. + +Please note that the contributor identity, once given, is used for copyright verification and to provide proof should a malicious commit be made. As such, the [EU GDPR](https://www.eugdpr.org/key-changes.html) "right to be forgotten" does not apply, as this is an overriding legitimate interest. + +Please also note that your commit is public and as such will potentially be processed by many third-parties. Git's distributed nature makes it impossible to track where exactly your commit, and thus your personal data, will be stored and be processed. If you would not like to accept this risk, please do either commit anonymously or refrain from contributing to the OpenTTD project. + ### Pull request validation Continuous integration (CI) tools monitor pull requests, and help us identify build and code quality issues. @@ -168,3 +178,4 @@ By contributing your code, you agree to license your contribution under the [GPL ### Attribution of this Contributing Guide This contributing guide is adapted from [Bootstrap](https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md) under the [Creative Commons Attribution 3.0 Unported License](https://github.com/twbs/bootstrap/blob/master/docs/LICENSE) terms for Bootstrap documentation. +The GDPR notice is adapted from [rsyslog](https://github.com/rsyslog/rsyslog/blob/master/CONTRIBUTING.md) under the [GNU General Public License](https://github.com/rsyslog/rsyslog/blob/master/COPYING). diff --git a/Makefile.lang.in b/Makefile.lang.in index fbed06b790..7ce331913d 100644 --- a/Makefile.lang.in +++ b/Makefile.lang.in @@ -6,7 +6,6 @@ # See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . STRGEN = !!STRGEN!! -ENDIAN_CHECK = !!ENDIAN_CHECK!! SRC_DIR = !!SRC_DIR!! LANG_DIR = !!LANG_DIR!! BIN_DIR = !!BIN_DIR!! @@ -25,11 +24,6 @@ ifeq ($(LANG_SUPPRESS), yes) LANG_ERRORS = >/dev/null 2>&1 endif -# Make sure endian_host.h is reachable as if it was in the src/ dir -CFLAGS_BUILD += -I $(LANG_OBJS_DIR) - -ENDIAN_TARGETS := endian_host.h endian_target.h $(ENDIAN_CHECK) - # Check if we want to show what we are doing ifdef VERBOSE Q = @@ -43,19 +37,19 @@ RES := $(shell mkdir -p $(BIN_DIR)/lang ) all: table/strings.h $(LANGS) -strgen_base.o: $(SRC_DIR)/strgen/strgen_base.cpp $(SRC_DIR)/strgen/strgen.h endian_host.h $(SRC_DIR)/table/control_codes.h $(SRC_DIR)/table/strgen_tables.h $(SRC_DIR)/safeguards.h +strgen_base.o: $(SRC_DIR)/strgen/strgen_base.cpp $(SRC_DIR)/strgen/strgen.h $(SRC_DIR)/table/control_codes.h $(SRC_DIR)/table/strgen_tables.h $(SRC_DIR)/safeguards.h $(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)' $(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSTRGEN -c -o $@ $< -strgen.o: $(SRC_DIR)/strgen/strgen.cpp $(SRC_DIR)/strgen/strgen.h endian_host.h $(SRC_DIR)/table/control_codes.h $(SRC_DIR)/table/strgen_tables.h $(SRC_DIR)/safeguards.h +strgen.o: $(SRC_DIR)/strgen/strgen.cpp $(SRC_DIR)/strgen/strgen.h $(SRC_DIR)/table/control_codes.h $(SRC_DIR)/table/strgen_tables.h $(SRC_DIR)/safeguards.h $(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)' $(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSTRGEN -c -o $@ $< -string.o: $(SRC_DIR)/string.cpp endian_host.h $(SRC_DIR)/safeguards.h +string.o: $(SRC_DIR)/string.cpp $(SRC_DIR)/safeguards.h $(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)' $(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSTRGEN -c -o $@ $< -alloc_func.o: $(SRC_DIR)/core/alloc_func.cpp endian_host.h $(SRC_DIR)/safeguards.h +alloc_func.o: $(SRC_DIR)/core/alloc_func.cpp $(SRC_DIR)/safeguards.h $(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)' $(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSTRGEN -c -o $@ $< @@ -80,21 +74,11 @@ $(LANGS): %.lng: $(LANG_DIR)/%.txt $(STRGEN) lang/english.txt $(E) '$(STAGE) Compiling language $(*F)' $(Q)./$(STRGEN) $(STRGEN_FLAGS) -s $(LANG_DIR) -d $(LANG_OBJS_DIR) $< $(LANG_ERRORS) && cp $@ $(BIN_DIR)/lang || true # Do not fail all languages when one fails -# The targets to compile the endian-code - -endian_host.h: $(ENDIAN_CHECK) - $(E) '$(STAGE) Testing endianness for host' - $(Q)./$(ENDIAN_CHECK) > $@ - -$(ENDIAN_CHECK): $(SRC_DIR)/endian_check.cpp - $(E) '$(STAGE) Compiling and Linking $@' - $(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) $(LDFLAGS_BUILD) $< -o $@ - depend: clean: $(E) '$(STAGE) Cleaning up language files' - $(Q)rm -f strgen.o string.o alloc_func.o getoptdata.o table/strings.h $(STRGEN) $(LANGS) $(LANGS:%=$(BIN_DIR)/lang/%) lang/english.* $(ENDIAN_TARGETS) + $(Q)rm -f strgen.o string.o alloc_func.o getoptdata.o table/strings.h $(STRGEN) $(LANGS) $(LANGS:%=$(BIN_DIR)/lang/%) lang/english.* mrproper: clean $(Q)rm -rf $(BIN_DIR)/lang diff --git a/Makefile.setting.in b/Makefile.setting.in index d89501d21b..656de05723 100644 --- a/Makefile.setting.in +++ b/Makefile.setting.in @@ -6,7 +6,6 @@ # See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . SETTINGSGEN = !!SETTINGSGEN!! -ENDIAN_CHECK = !!ENDIAN_CHECK!! SRC_DIR = !!SRC_DIR!! CXX_BUILD = !!CXX_BUILD!! CFLAGS_BUILD = !!CFLAGS_BUILD!! @@ -15,8 +14,6 @@ LDFLAGS_BUILD = !!LDFLAGS_BUILD!! STAGE = !!STAGE!! SETTING_OBJS_DIR = !!SETTING_OBJS_DIR!! -ENDIAN_TARGETS := endian_host.h endian_target.h $(ENDIAN_CHECK) - # Check if we want to show what we are doing ifdef VERBOSE Q = @@ -32,7 +29,7 @@ settingsgen.o: $(SRC_DIR)/settingsgen/settingsgen.cpp $(SRC_DIR)/string_func.h $ $(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)' $(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSETTINGSGEN -c -o $@ $< -alloc_func.o: $(SRC_DIR)/core/alloc_func.cpp endian_host.h $(SRC_DIR)/safeguards.h +alloc_func.o: $(SRC_DIR)/core/alloc_func.cpp $(SRC_DIR)/safeguards.h $(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)' $(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSETTINGSGEN -c -o $@ $< @@ -40,7 +37,7 @@ getoptdata.o: $(SRC_DIR)/misc/getoptdata.cpp $(SRC_DIR)/misc/getoptdata.h $(SRC_ $(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/misc/%.cpp=%.cpp)' $(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSETTINGSGEN -c -o $@ $< -string.o: $(SRC_DIR)/string.cpp endian_host.h $(SRC_DIR)/safeguards.h +string.o: $(SRC_DIR)/string.cpp $(SRC_DIR)/safeguards.h $(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)' $(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSETTINGSGEN -c -o $@ $< @@ -57,21 +54,11 @@ table/settings.h: $(SETTINGSGEN) $(SRC_DIR)/table/settings.h.preamble $(SRC_DIR) @mkdir -p table $(Q)./$(SETTINGSGEN) -o table/settings.h -b $(SRC_DIR)/table/settings.h.preamble -a $(SRC_DIR)/table/settings.h.postamble $(SRC_DIR)/table/*.ini -# The targets to compile the endian-code - -endian_host.h: $(ENDIAN_CHECK) - $(E) '$(STAGE) Testing endianness for host' - $(Q)./$(ENDIAN_CHECK) > $@ - -$(ENDIAN_CHECK): $(SRC_DIR)/endian_check.cpp - $(E) '$(STAGE) Compiling and Linking $@' - $(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) $(LDFLAGS_BUILD) $< -o $@ - depend: clean: $(E) '$(STAGE) Cleaning up settings files' - $(Q)rm -f settingsgen.o alloc_func.o getoptdata.o ini_load.o $(SETTINGSGEN) $(ENDIAN_TARGETS) table/settings.h + $(Q)rm -f settingsgen.o alloc_func.o getoptdata.o ini_load.o $(SETTINGSGEN) table/settings.h mrproper: clean diff --git a/Makefile.src.in b/Makefile.src.in index d92fa59c24..3317aa7fe6 100644 --- a/Makefile.src.in +++ b/Makefile.src.in @@ -29,9 +29,7 @@ SCRIPT_SRC_DIR = !!SCRIPT_SRC_DIR!! MEDIA_DIR = !!MEDIA_DIR!! TTD = !!TTD!! STRGEN = !!STRGEN!! -ENDIAN_CHECK = !!ENDIAN_CHECK!! DEPEND = !!DEPEND!! -ENDIAN_FORCE = !!ENDIAN_FORCE!! OS = !!OS!! STAGE = !!STAGE!! MAKEDEPEND = !!MAKEDEPEND!! @@ -41,7 +39,6 @@ AWK = !!AWK!! CONFIGURE_INVOCATION = !!CONFIGURE_INVOCATION!! CONFIG_CACHE_COMPILER = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_COMPILER!! CONFIG_CACHE_LINKER = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_LINKER!! -CONFIG_CACHE_ENDIAN = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_ENDIAN!! CONFIG_CACHE_SOURCE = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_SOURCE!! CONFIG_CACHE_VERSION = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_VERSION!! CONFIG_CACHE_INVOCATION = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_INVOCATION!! @@ -54,19 +51,16 @@ OBJS := $(OBJS_C) $(OBJS_CPP) $(OBJS_MM) $(OBJS_RC) SRCS := !!SRCS!! # All C-files depend on those 3 files -FILE_DEP := $(CONFIG_CACHE_COMPILER) endian_target.h +FILE_DEP := $(CONFIG_CACHE_COMPILER) # Create all dirs and subdirs RES := $(shell mkdir -p $(BIN_DIR) $(sort $(dir $(OBJS)))) -# Make sure endian_target.h is reasable as if it was in the src/ dir CFLAGS += -I $(SRC_OBJS_DIR) -I $(LANG_OBJS_DIR) -I $(SETTING_OBJS_DIR) CFLAGS_MAKEDEP += -I $(SRC_OBJS_DIR) -I $(LANG_OBJS_DIR) -I $(SETTING_OBJS_DIR) ifdef SCRIPT_SRC_DIR CFLAGS_MAKEDEP += -I $(SCRIPT_SRC_DIR) endif -ENDIAN_TARGETS := endian_target.h $(ENDIAN_CHECK) - # Check if we want to show what we are doing ifdef VERBOSE Q = @@ -110,7 +104,6 @@ endif # This helps to recompile if flags change RES := $(shell if [ "`cat $(CONFIG_CACHE_COMPILER) 2>/dev/null`" != "$(CFLAGS) $(CXXFLAGS)" ]; then echo "$(CFLAGS) $(CXXFLAGS)" > $(CONFIG_CACHE_COMPILER); fi ) RES := $(shell if [ "`cat $(CONFIG_CACHE_LINKER) 2>/dev/null`" != "$(LDFLAGS) $(LIBS)" ]; then echo "$(LDFLAGS) $(LIBS)" > $(CONFIG_CACHE_LINKER); fi ) -RES := $(shell if [ "`cat $(CONFIG_CACHE_ENDIAN) 2>/dev/null`" != "$(ENDIAN_FORCE)" ]; then echo "$(ENDIAN_FORCE)" > $(CONFIG_CACHE_ENDIAN); fi ) # If there is a change in the source-file-list, make sure we recheck the deps RES := $(shell if [ "`cat $(CONFIG_CACHE_SOURCE) 2>/dev/null`" != "$(SRCS)" ]; then echo "$(SRCS)" > $(CONFIG_CACHE_SOURCE); fi ) @@ -125,7 +118,7 @@ DEP_MASK := %.d DEPS := $(OBJS:%.o=%.d) # Only include the deps if we are compiling everything -ifeq ($(filter $(ENDIAN_TARGETS) %.o clean mrproper, $(MAKECMDGOALS)),) +ifeq ($(filter %.o clean mrproper, $(MAKECMDGOALS)),) -include $(DEPS) else # In case we want to compile a single target, include the .d file for it @@ -159,7 +152,7 @@ DEP_MASK := DEPS := Makefile.dep # Only include the deps if we are not cleaning -ifeq ($(filter $(ENDIAN_TARGETS) depend clean mrproper, $(MAKECMDGOALS)),) +ifeq ($(filter depend clean mrproper, $(MAKECMDGOALS)),) -include Makefile.dep endif @@ -268,14 +261,7 @@ endif $(TTD): $(OBJS) $(CONFIG_CACHE_LINKER) $(E) '$(STAGE) Linking $@' -ifeq ($(OS), PSP) - # Because of a bug in the PSP GCC tools, linking via CXX results - # in total chaos and more problems then you can handle. So we need - # CC to link OpenTTD for PSP - $(Q)+$(CC_HOST) $(LDFLAGS) $(OBJS) $(LIBS) -o $@ -else $(Q)+$(CXX_HOST) $(LDFLAGS) $(OBJS) $(LIBS) -o $@ -endif ifdef STRIP $(Q)$(STRIP) $@ endif @@ -284,16 +270,6 @@ ifeq ($(OS), DOS) $(Q)$(ROOT_DIR)/os/dos/make_dos_binary_selfcontained.sh $(SRC_OBJS_DIR)/$@ endif -# The targets to compile the endian-code - -endian_target.h: $(ENDIAN_CHECK) $(CONFIG_CACHE_ENDIAN) - $(E) '$(STAGE) Testing endianness for target' - $(Q)./$(ENDIAN_CHECK) $(ENDIAN_FORCE) > $@ - -$(ENDIAN_CHECK): $(SRC_DIR)/endian_check.cpp - $(E) '$(STAGE) Compiling and Linking $@' - $(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) $(LDFLAGS_BUILD) $< -o $@ - # Revision files $(SRC_DIR)/rev.cpp: $(CONFIG_CACHE_VERSION) $(CONFIG_CACHE_INVOCATION) $(SRC_DIR)/rev.cpp.in @@ -308,7 +284,7 @@ depend: $(DEPS) clean: $(E) '$(STAGE) Cleaning up object files' - $(Q)rm -f $(DEPS) $(OBJS) $(TTD) $(DEPEND) $(TTD:%=$(BIN_DIR)/%) $(BIN_DIR)/baseset/openttd.32.bmp $(CONFIG_CACHE_COMPILER) $(CONFIG_CACHE_LINKER) $(CONFIG_CACHE_ENDIAN) $(CONFIG_CACHE_SOURCE) $(ENDIAN_TARGETS) + $(Q)rm -f $(DEPS) $(OBJS) $(TTD) $(DEPEND) $(TTD:%=$(BIN_DIR)/%) $(BIN_DIR)/baseset/openttd.32.bmp $(CONFIG_CACHE_COMPILER) $(CONFIG_CACHE_LINKER) $(CONFIG_CACHE_SOURCE) mrproper: clean $(Q)rm -f $(SRC_DIR)/rev.cpp $(SRC_DIR)/os/windows/ottdres.rc diff --git a/README.md b/README.md index f8773ec25b..7ab63c9f4c 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ - 4.4) [Files in tar (archives)](#44-files-in-tar-archives) - 5.0) [OpenTTD features](#50-openttd-features) - 5.1) [Logging of potentially dangerous actions](#51-logging-of-potentially-dangerous-actions) + - 5.2) [Frame rate and performance metrics](#52-frame-rate-and-performance-metrics) - 6.0) [Configuration file](#60-configuration-file) - 7.0) [Compiling](#70-compiling) - 7.1) [Required/optional libraries](#71-requiredoptional-libraries) @@ -42,9 +43,10 @@ The easiest way to contact the OpenTTD team is by submitting bug reports or posting comments in our forums. You can also chat with us on IRC (#openttd on irc.oftc.net). -The OpenTTD homepage is [http://www.openttd.org/](http://www.openttd.org/). +The OpenTTD homepage is https://www.openttd.org. -You can also find the OpenTTD forums at [http://forum.openttd.org/](http://forum.openttd.org/). +You can also find the OpenTTD forums at +[https://www.tt-forums.net](https://www.tt-forums.net/viewforum.php?f=55). ### 2.1) Reporting bugs @@ -52,12 +54,12 @@ First of all, check whether the bug is not already known. Do this by looking through the file called 'known-bugs.txt' which is distributed with OpenTTD like this readme. -For tracking our bugs we are using Githubs issue tracker. You can find -the tracker at [https://github.com/OpenTTD/OpenTTD/issues](https://github.com/OpenTTD/OpenTTD/issues). Before actually reporting take a look -through the already reported bugs there to see if the bug is already known. -The 'known-bugs.txt' file might be a bit outdated at the moment you are -reading it as only bugs known before the release are documented there. Also -look through the recently closed bugs. +For tracking our bugs we are using GitHub's issue tracker. You can find +the tracker at https://github.com/OpenTTD/OpenTTD/issues. Before actually +reporting take a look through the already reported bugs there to see if +the bug is already known. The 'known-bugs.txt' file might be a bit outdated +at the moment you are reading it as only bugs known before the release +are documented there. Also look through the recently closed bugs. When you are sure it is not already reported you should: @@ -80,8 +82,8 @@ following information in your bug report: - Bug details, including instructions how to reproduce it - Platform (Windows, Linux, FreeBSD, …) and compiler (including version) if you compiled OpenTTD yourself. -- The processor architecture of your OS (32 bits Windows, 64 bits Windows, - Linux on an ARM, Mac OS X on a PowerPC, …) +- The processor architecture of your OS (32-bit Windows, 64-bit Windows, + Linux on an ARM, Mac OS X on a PowerPC, etc.) - Attach a saved game **and** a screenshot if possible - If this bug only occurred recently please note the last version without the bug and the first version including the bug. That way we can fix it @@ -154,7 +156,7 @@ platforms are: - DOS (Allegro) - FreeBSD (SDL) - Linux (SDL or Allegro) -- MacOS X (universal) (Cocoa video and sound drivers) +- macOS (universal) (Cocoa video and sound drivers) - MorphOS (SDL) - OpenBSD (SDL) - OS/2 (SDL) @@ -210,9 +212,9 @@ when using other versions of the game. The free data files, split into OpenGFX for graphics, OpenSFX for sounds and OpenMSX for music can be found at: -- [http://www.openttd.org/download-opengfx](http://www.openttd.org/download-opengfx) for OpenGFX -- [http://www.openttd.org/download-opensfx](http://www.openttd.org/download-opensfx) for OpenSFX -- [http://www.openttd.org/download-openmsx](http://www.openttd.org/download-openmsx) for OpenMSX +- https://www.openttd.org/download-opengfx for OpenGFX +- https://www.openttd.org/download-opensfx for OpenSFX +- https://www.openttd.org/download-openmsx for OpenMSX Please follow the readme of these packages about the installation procedure. The Windows installer can optionally download and install these packages. @@ -224,7 +226,6 @@ have to copy the data files from the CD-ROM into the baseset/ directory. It does not matter whether you copy them from the DOS or Windows version of Transport Tycoon Deluxe. The Windows install can optionally copy these files. You need to copy the following files: - - sample.cat - trg1r.grf or TRG1.GRF - trgcr.grf or TRGC.GRF @@ -234,11 +235,11 @@ You need to copy the following files: #### 4.1.3) Original Transport Tycoon Deluxe music -If you want the Transport Tycoon Deluxe music, copy the files from the gm/ -folder from the Windows version of Transport Tycoon Deluxe to the baseset -folder in your OpenTTD folder (also explained in the following sections). -The music from the DOS version as well as the original Transport Tycoon does -not work. +If you want the Transport Tycoon Deluxe music, copy the appropriate files from +the original game into the baseset folder. +- TTD for Windows: All files in the gm/ folder (gm_tt00.gm up to gm_tt21.gm) +- TTD for DOS: The GM.CAT file +- Transport Tycoon Original: The GM.CAT file, but rename it to GM-TTO.CAT #### 4.1.4) AIs @@ -247,10 +248,9 @@ not possible or you want to use an AI that has not been uploaded to the content download system download the tar file and place it in the ai/ directory. If the AI needs libraries you will have to download those too and put them in the ai/library/ directory. All AIs and AI Libraries that have been uploaded to -the content download system can be found at http://noai.openttd.org/downloads/ +the content download system can be found at https://noai.openttd.org/downloads. The AIs and libraries can be found their in the form of .tar.gz packages. -OpenTTD can read inside tar files but it does not extract .tar.gz files by -itself. +OpenTTD can read inside tar files but it does not extract .tar.gz files by itself. To figure out which libraries you need for an AI you have to start the AI and wait for an error message to pop up. The error message will tell you @@ -278,47 +278,50 @@ The main OpenTTD directories can be found in various locations, depending on your operating system: 1. The current working directory (from where you started OpenTTD) - For non-Windows operating systems OpenTTD will not scan for files in this - directory if it is your personal directory, i.e. '~/', or when it is the - root directory, i.e. '/'. + + For non-Windows operating systems OpenTTD will not scan for files in this + directory if it is your personal directory, i.e. '~/', or when it is the + root directory, i.e. '/'. + 2. Your personal directory - Windows: - `C:\My Documents\OpenTTD` (95, 98, ME) - `C:\Documents and Settings\\My Documents\OpenTTD` (2000, XP) - - `C:\Users\\Documents\OpenTTD` (Vista, 7) - - Mac OSX: `~/Documents/OpenTTD` + - `C:\Users\\Documents\OpenTTD` (Vista, 7, 8.1, 10) + - macOS: `~/Documents/OpenTTD` - Linux: `$XDG_DATA_HOME/openttd` which is usually `~/.local/share/openttd` - when built with XDG base directory support, otherwise `~/.openttd` + when built with XDG base directory support, otherwise `~/.openttd` 3. The shared directory - Windows: - `C:\Documents and Settings\All Users\Shared Documents\OpenTTD` (2000, XP) - - `C:\Users\Public\Documents\OpenTTD` (Vista, 7) - - Mac OSX: `/Library/Application Support/OpenTTD` + - `C:\Users\Public\Documents\OpenTTD` (Vista, 7, 8.1, 10) + - macOS: `/Library/Application Support/OpenTTD` - Linux: not available 4. The binary directory (where the OpenTTD executable is) - Windows: `C:\Program Files\OpenTTD` - Linux: `/usr/games` 5. The installation directory (Linux only) - Linux: `/usr/share/games/openttd` -6. The application bundle (Mac OSX only) - It includes the OpenTTD files (grf+lng) and it will work as long as they - are not touched +6. The application bundle (macOS only) + + It includes the OpenTTD files (grf+lng) and it will work as long as they + are not touched Different types of data or extensions go into different subdirectories of the chosen main OpenTTD directory: -| data type | directory | additional info | +| data type | directory | additional info | | --- | --- | --- | | Config File | (no subdirectory) | | | Screenshots | screenshot | | -| Base Graphics | baseset| (or a subdirectory thereof) | -| Sound Sets | baseset| (or a subdirectory thereof) | -| NewGRFs | newgrf| (or a subdirectory thereof) | -| 32bpp Sets | newgrf| (or a subdirectory thereof) | -| Music Sets | baseset| (or a subdirectory thereof) | -| AIs | ai| (or a subdirectory thereof) | -| AI Libraries | ai/library| (or a subdirectory thereof) | -| Game Scripts (GS) | game| (or a subdirectory thereof) | +| Base Graphics | baseset | (or a subdirectory thereof) | +| Sound Sets | baseset | (or a subdirectory thereof) | +| NewGRFs | newgrf | (or a subdirectory thereof) | +| 32bpp Sets | newgrf | (or a subdirectory thereof) | +| Music Sets | baseset | (or a subdirectory thereof) | +| AIs | ai | (or a subdirectory thereof) | +| AI Libraries | ai/library | (or a subdirectory thereof) | +| Game Scripts (GS) | game | (or a subdirectory thereof) | | GS Libraries | game/library | (or a subdirectory thereof) | | Savegames | save | | | Automatic Savegames | save/autosave | | @@ -330,16 +333,16 @@ use and no files should be added to it or its subdirectories manually. #### Notes: - Linux in the previous list means .deb, but most paths should be similar for - others. + others. - The previous search order is also used for NewGRFs and openttd.cfg. - If openttd.cfg is not found, then it will be created using the 2, 4, 1, 3, - 5 order. When built with XDG base directory support, openttd.cfg will be - created in $XDG_CONFIG_HOME/openttd which is usually ~/.config/openttd. + 5 order. When built with XDG base directory support, openttd.cfg will be + created in $XDG_CONFIG_HOME/openttd which is usually ~/.config/openttd. - Savegames will be relative to the config file only if there is no save/ - directory in paths with higher priority than the config file path, but - autosaves and screenshots will always be relative to the config file. - Unless the configuration file is in $XDG_CONFIG_HOME/openttd, then all - other files will be saved under $XDG_DATA_HOME/openttd. + directory in paths with higher priority than the config file path, but + autosaves and screenshots will always be relative to the config file. + Unless the configuration file is in $XDG_CONFIG_HOME/openttd, then all + other files will be saved under $XDG_DATA_HOME/openttd. #### The preferred setup: @@ -389,19 +392,18 @@ OpenTTD has a lot of features going beyond the original Transport Tycoon Deluxe emulation. Unfortunately, there is currently no comprehensive list of features, but there is a basic features list on the web, and some optional features can be controlled through the Advanced Settings dialog. We also implement some -features known from [TTDPatch](http://www.ttdpatch.net/). +features known from [TTDPatch](https://www.ttdpatch.net). Several important non-standard controls: - Ctrl modifies many commands and makes them more powerful. For example Ctrl - clicking on signals with the build signal tool changes their behaviour, holding - Ctrl while the track build tool is activated changes it to the track removal - tool, and so on. See [http://wiki.openttd.org/Hidden_features](http://wiki.openttd.org/Hidden_features) - for a non-comprehensive list or look at the tooltips. -- Ingame console. More information at - [http://wiki.openttd.org/index.php/Console](http://wiki.openttd.org/index.php/Console) + clicking on signals with the build signal tool changes their behaviour, + holding Ctrl while the track build tool is activated changes it to the track + removal tool, and so on. See https://wiki.openttd.org/Hidden_features + for a non-comprehensive list or look at the tooltips. +- Ingame console. More information at https://wiki.openttd.org/Console - Hovering over a GUI element shows tooltips. This can be changed to right click - via the advanced settings. + via the advanced settings. ### 5.1) Logging of potentially dangerous actions @@ -422,7 +424,7 @@ Information logged: - Changing NewGRF parameters, loading compatible NewGRF - Changing game mode (scenario editor <-> normal game) - Loading game saved in a different OpenTTD / TTDPatch / Transport Tycoon Deluxe / - original Transport Tycoon version + original Transport Tycoon version - Running a modified OpenTTD build - Changing settings affecting NewGRF behaviour (non-network-safe settings) - Triggering NewGRF bugs @@ -432,6 +434,70 @@ No personal information is stored. You can show the game log by typing 'gamelog' in the console or by running OpenTTD in debug mode. +### 5.2) Frame rate and performance metrics + +The Help menu in-game has a function to open the Frame rate window. This +window shows various real-time performance statistics, measuring what parts +of the game require the most processing power currently. + +A summary of the statistics can also be retrieved from the console with the +`fps` command. This is especially useful on dedicated servers, where the +administrator might want to determine what's limiting performance in a slow +game. + +The frame rate is given as two figures, the simulation rate and the graphics +frame rate. Usually these are identical, as the screen is rendered exactly +once per simulated tick, but in the future there might be support for graphics +and simulation running at different rates. When the game is paused, the +simulation rate drops to zero. + +In addition to the simulation rate, a game speed factor is also calculated. +This is based on the target simulation speed, which is 30 milliseconds per +game tick. At that speed, the expected frame rate is 33.33 frames/second, and +the game speed factor is how close to that target the actual rate is. When +the game is in fast forward mode, the game speed factor shows how much +speed up is achieved. + +The lower part of the window shows timing statistics for individual parts of +the game. The times shown are short-term and long-term averages of how long +it takes to process one tick of game time, all figures are in milliseconds. + +Clicking a line in the lower part of the window opens a graph window, giving +detailed readings on each tick simulated by the game. + +The following is an explanation of the different statistics: + +- *Game loop* - Total processing time used per simulated "tick" in the game. + This includes all pathfinding, world updates, and economy handling. +- *Cargo handling* - Time spent loading/unloading cargo at stations, and + industries and towns sending/retrieving cargo from stations. +- *Train ticks*, *Road vehicle ticks*, *Ship ticks*, *Aircraft ticks* - + Time spent on pathfinding and other processing for each player vehicle type. +- *World ticks* - Time spent on other world/landscape processing. This + includes towns growing, building animations, updates of farmland and trees, + and station rating updates. +- *Link graph delay* - Time overruns of the cargo distribution link graph + update thread. Usually the link graph is updated in a background thread, + but these updates need to synchronise with the main game loop occasionally, + if the time spent on link graph updates is longer than the time taken to + otherwise simulate the game while it was updating, these delays are counted + in this figure. +- *Graphics rendering* - Total time spent rendering all graphics, including + both GUI and world viewports. This typically spikes when panning the view + around, and when more things are happening on screen at once. +- *World viewport rendering* - Isolated time spent rendering just world + viewports. If this figure is significantly lower than the total graphics + rendering time, most time is spent rendering GUI than rendering world. +- *Video output* - Speed of copying the rendered graphics to the display + adapter. Usually this should be very fast (in the range of 0-3 ms), large + values for this can indicate a graphics driver problem. +- *Sound mixing* - Speed of mixing active audio samples together. Usually + this should be very fast (in the range of 0-3 ms), if it is slow, consider + switching to the NoSound set. + +If the frame rate window is shaded, the title bar will instead show just the +current simulation rate and the game speed factor. + ## 6.0) Configuration file The configuration file for OpenTTD (openttd.cfg) is in a simple Windows-like @@ -451,7 +517,7 @@ you need to add WITH_SDL to the project settings. PNG (WITH_PNG) and ZLIB (WITH_ZLIB) support is enabled by default. For these to work you need their development files. For best results, download the -openttd-useful.zip file from [http://www.openttd.org/download-openttd-useful](http://www.openttd.org/download-openttd-useful) +openttd-useful.zip file from https://www.openttd.org/download-openttd-useful. Put the header files into your compiler's include/ directory and the library (.lib) files into the lib/ directory. For more help with VS see docs/Readme_Windows_MSVC.txt. @@ -468,7 +534,7 @@ Use '`gmake`', but do a '`./configure`' before the first build. OpenTTD can be built with GNU '`make`'. On non-GNU systems it is called '`gmake`'. However, for the first build one has to do a '`./configure`' first. -### MacOS X: +### macOS: Use '`make`' or Xcode (which will then call make for you) This will give you a binary for your CPU type (PPC/Intel) @@ -509,19 +575,19 @@ The following libraries are used by OpenTTD for: - libSDL/liballegro: hardware access (video, sound, mouse) - zlib: (de)compressing of old (0.3.0-1.0.5) savegames, content downloads, - heightmaps + heightmaps - liblzo2: (de)compressing of old (pre 0.3.0) savegames - liblzma: (de)compressing of savegames (1.1.0 and later) - libpng: making screenshots and loading heightmaps - libfreetype: loading generic fonts and rendering them - libfontconfig: searching for fonts, resolving font names to actual fonts - libicu: handling of right-to-left scripts (e.g. Arabic and Persian) and - natural sorting of strings. + natural sorting of strings. OpenTTD does not require any of the libraries to be present, but without liblzma you cannot open most recent savegames and without zlib you cannot open most older savegames or use the content downloading system. -Without libSDL/liballegro on non-Windows and non-MacOS X machines you have +Without libSDL/liballegro on non-Windows and non-macOS machines you have no graphical user interface; you would be building a dedicated server. ### 7.2) Supported compilers @@ -529,25 +595,25 @@ no graphical user interface; you would be building a dedicated server. The following compilers are known to compile OpenTTD: - Microsoft Visual C++ (MSVC) 2005, 2008 and 2010. - Version 2005 gives bogus warnings about scoping issues. + Version 2005 gives bogus warnings about scoping issues. - GNU Compiler Collection (GCC) 3.3 - 4.4, 4.6 - 4.8. - Versions 4.1 and earlier give bogus warnings about uninitialised variables. - Versions 4.4, 4.6 give bogus warnings about freeing non-heap objects. - Versions 4.6 and later give invalid warnings when lto is enabled. - Intel C++ Compiler (ICC) 12.0. - Clang/LLVM 2.9 - 3.0 - Version 2.9 gives bogus warnings about code nonconformity. + Version 2.9 gives bogus warnings about code nonconformity. The following compilers are known not to compile OpenTTD: - Microsoft Visual C++ (MSVC) 2003 and earlier. - GNU Compiler Collection (GCC) 3.2 and earlier. - These old versions fail due to OpenTTD's template usage. + These old versions fail due to OpenTTD's template usage. - GNU Compiler Collection (GCC) 4.5. It optimizes enums too aggressively. - See http://bugs.openttd.org/task/5513 and references therein. + See https://github.com/OpenTTD/OpenTTD/issues/5513 and references therein. - Intel C++ Compiler (ICC) 11.1 and earlier. - Version 10.0 and earlier fail a configure check and fail with recent - system headers. + system headers. - Version 10.1 fails to compile station_gui.cpp. - Version 11.1 fails with an internal error when compiling network.cpp. - Clang/LLVM 2.8 and earlier. @@ -560,7 +626,7 @@ Patches to support more compilers are welcome. To recompile the extra graphics needed to play with the original Transport Tycoon Deluxe graphics you need GRFCodec (which includes NFORenum) as well. -GRFCodec can be found at: [http://www.openttd.org/download-grfcodec](http://www.openttd.org/download-grfcodec) +GRFCodec can be found at https://www.openttd.org/download-grfcodec. The compilation of these extra graphics does generally not happen, unless you remove the graphics file using '`make maintainer-clean`'. @@ -573,17 +639,16 @@ modification of the base set files by the build process. ## 8.0) Translating -See [http://www.openttd.org/development](http://www.openttd.org/development) for up-to-date information. +See https://www.openttd.org/development for up-to-date information. The use of the online Translator service, located at -[http://translator.openttd.org/](http://translator.openttd.org/), is highly -encouraged. For getting an account simply follow the guidelines in the FAQ of -the translator website. +https://translator.openttd.org, is highly encouraged. For getting an account +simply follow the guidelines in the FAQ of the translator website. If for some reason the website is down for a longer period of time, the information below might be of help. -Please contact the translations manager ([http://www.openttd.org/contact](http://www.openttd.org/contact)) +Please contact the translations manager (https://www.openttd.org/contact) before beginning the translation process! This avoids double work, as someone else may have already started translating to the same language. @@ -602,8 +667,8 @@ Note: Do not alter the following parts of the file: - String identifiers (the first word on each line) - Parts of the strings which are in curly braces (such as {STRING}) -- Lines beginning with ## (such as ##id), other than the first two lines of - the file +- Lines beginning with ## (such as ##id), other than the first two lines + of the file ### 8.2) Previewing @@ -635,7 +700,7 @@ If the game is acting strange and you feel adventurous you can try the debugging output. The 'name' variable can help you to display only some type of debugging messages. This is mostly undocumented so best is to look in the source code file debug.c for the various debugging types. For more information -look at [http://wiki.openttd.org/index.php/Command_line](http://wiki.openttd.org/index.php/Command_line). +look at https://wiki.openttd.org/Command_line. The most frequent problem is missing data files. Please install OpenGFX and possibly OpenSFX and OpenMSX. See section 4.1.1 for more information. @@ -659,16 +724,16 @@ and add a suitable font for the small, medium and / or large font, e.g.: You should use a font name like 'Tahoma' or a path to the desired font. -Any NewGRF file used in a game is stored inside the savegame and will refuse -to load if you do not have that NewGRF file available. A list of missing files -can be viewed in the NewGRF window accessible from the file load dialogue window. +Any NewGRF file used in a game is stored inside the savegame and will refuse to +load if you do not have that NewGRF file available. A list of missing files can +be viewed in the NewGRF window accessible from the file load dialogue window. You can try to obtain the missing files from that NewGRF dialogue or – if they -are not available online – you can search manually through our [forum's graphics -development section](http://www.tt-forums.net/viewforum.php?f=66) or GrfCrawler -(http://grfcrawler.tt-forums.net/). Put the NewGRF files in OpenTTD's newgrf folder -(see section 4.2 'OpenTTD directories') and rescan the list of available NewGRFs. -Once you have all missing files, you are set to go. +are not available online – you can search manually through our +[forum's graphics development section](https://www.tt-forums.net/viewforum.php?f=66) +or [GRFCrawler](https://grfcrawler.tt-forums.net). Put the NewGRF files in +OpenTTD's newgrf folder (see section 4.2 'OpenTTD directories') and rescan the +list of available NewGRFs. Once you have all missing files, you are set to go. ## 10.0) Licensing @@ -697,8 +762,14 @@ os/dos/exe2coff/copying.dj for the exact licensing terms. The CWSDPMI implementation in os/dos/cwsdpmi is distributed under a custom binary-only license that prohibits modification. The exact licensing terms can be found in os/dos/cwsdpmi/cwsdpmi.txt. The sources -for these files can be downloaded at its author site, at: -[http://homer.rice.edu/~sandmann/cwsdpmi/csdpmi5s.zip](http://homer.rice.edu/~sandmann/cwsdpmi/csdpmi5s.zip) +for these files can be downloaded at its author site, at +http://homer.rice.edu/~sandmann/cwsdpmi/csdpmi5s.zip. + +CONTRIBUTING.md is adapted from +[Bootstrap](https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md) +under the [Creative Commons Attribution 3.0 Unported +License](https://github.com/twbs/bootstrap/blob/master/docs/LICENSE) +terms for Bootstrap documentation. ## X.X) Credits @@ -721,7 +792,7 @@ for these files can be downloaded at its author site, at: ### Inactive Developers: - Jean-François Claeys (Belugas) - GUI, newindustries and more (0.4.5 - 1.0) -- Bjarni Corfitzen (Bjarni) - MacOSX port, coder and vehicles (0.3 - 0.7) +- Bjarni Corfitzen (Bjarni) - macOS port, coder and vehicles (0.3 - 0.7) - Victor Fischer (Celestar) - Programming everywhere you need him to (0.3 - 0.6) - Jaroslav Mazanec (KUDr) - YAPG (Yet Another Pathfinder God) ;) (0.4.5 - 0.6) - Jonathan Coome (Maedhros) - High priest of the NewGRF Temple (0.5 - 0.6) @@ -735,10 +806,10 @@ for these files can be downloaded at its author site, at: - Tamás Faragó (Darkvater) - Ex-Lead coder (0.3 - 0.5) - Dominik Scherer (dominik81) - Lead programmer, GUI expert (0.3 - 0.3) -- Emil Djupfeld (egladil) - MacOSX port (0.4 - 0.6) +- Emil Djupfeld (egladil) - macOS port (0.4 - 0.6) - Simon Sasburg (HackyKid) - Bug fixer (0.4 - 0.4.5) - Ludvig Strigeus (ludde) - Original author of OpenTTD, main coder (0.1 - 0.3) -- Cian Duffy (MYOB) - BeOS port / manual writing (0.1 - 0.3) +- Cian Duffy (MYOB) - BeOS port / manual writing (0.1 - 0.3) - Petr Baudiš (pasky) - Many patches, newgrf support, etc. (0.3 - 0.3) - Benedikt Brüggemeier (skidd13) - Bug fixer and code reworker (0.6 - 0.7) - Serge Paquet (vurlix) - 2nd contributor after ludde (0.1 - 0.3) @@ -760,4 +831,3 @@ for these files can be downloaded at its author site, at: - All Translators - For their support to make OpenTTD a truly international game - Bug Reporters - Thanks for all bug reports - Chris Sawyer - For an amazing game! - diff --git a/bin/baseset/orig_dos.obm b/bin/baseset/orig_dos.obm new file mode 100644 index 0000000000..cdacc8e7f5 --- /dev/null +++ b/bin/baseset/orig_dos.obm @@ -0,0 +1,76 @@ +; $Id$ +; +; This represents the original music as on the Transport +; Tycoon Deluxe for DOS CD. +; +[metadata] +name = original_dos +shortname = TTDD +version = 1 +description = Original Transport Tycoon Deluxe DOS edition music. + +[files] +theme = gm.cat +old_0 = gm.cat +old_1 = gm.cat +old_2 = gm.cat +old_3 = gm.cat +old_4 = gm.cat +old_5 = gm.cat +old_6 = gm.cat +old_7 = gm.cat +old_8 = +old_9 = +new_0 = gm.cat +new_1 = gm.cat +new_2 = gm.cat +new_3 = gm.cat +new_4 = gm.cat +new_5 = gm.cat +new_6 = gm.cat +new_7 = +new_8 = +new_9 = +ezy_0 = gm.cat +ezy_1 = gm.cat +ezy_2 = gm.cat +ezy_3 = gm.cat +ezy_4 = gm.cat +ezy_5 = gm.cat +ezy_6 = +ezy_7 = +ezy_8 = +ezy_9 = + +[md5s] +gm.cat = 7a29d2d0c4f7d2e03091ffa9b2bdfffb + +[catindex] +theme = 0 +old_0 = 1 +old_1 = 8 +old_2 = 2 +old_3 = 9 +old_4 = 14 +old_5 = 15 +old_6 = 19 +old_7 = 13 +new_0 = 6 +new_1 = 11 +new_2 = 10 +new_3 = 17 +new_4 = 21 +new_5 = 18 +new_6 = 5 +ezy_0 = 12 +ezy_1 = 7 +ezy_2 = 16 +ezy_3 = 3 +ezy_4 = 20 +ezy_5 = 4 + +[names] +; Names get read from the CAT file + +[origin] +default = You can find it on your Transport Tycoon Deluxe CD-ROM. diff --git a/bin/baseset/orig_tto.obm b/bin/baseset/orig_tto.obm new file mode 100644 index 0000000000..13b3efb110 --- /dev/null +++ b/bin/baseset/orig_tto.obm @@ -0,0 +1,71 @@ +; $Id$ +; +; This represents the original music as on the Transport +; Tycoon (with World Editor) for DOS CD. +; +[metadata] +name = original_tto +shortname = TTOD +version = 1 +description = Original Transport Tycoon (Original/World Editor) music. + +[files] +theme = gm-tto.cat +old_0 = gm-tto.cat +old_1 = gm-tto.cat +old_2 = gm-tto.cat +old_3 = gm-tto.cat +old_4 = gm-tto.cat +old_5 = gm-tto.cat +old_6 = gm-tto.cat +old_7 = gm-tto.cat +old_8 = +old_9 = +new_0 = gm-tto.cat +new_1 = gm-tto.cat +new_2 = gm-tto.cat +new_3 = gm-tto.cat +new_4 = gm-tto.cat +new_5 = gm-tto.cat +new_6 = gm-tto.cat +new_7 = gm-tto.cat +new_8 = +new_9 = +ezy_0 = +ezy_1 = +ezy_2 = +ezy_3 = +ezy_4 = +ezy_5 = +ezy_6 = +ezy_7 = +ezy_8 = +ezy_9 = + +[catindex] +theme = 0 +old_0 = 1 +old_1 = 6 +old_2 = 2 +old_3 = 7 +old_4 = 11 +old_5 = 12 +old_6 = 15 +old_7 = 10 +new_0 = 4 +new_1 = 5 +new_2 = 9 +new_3 = 8 +new_4 = 13 +new_5 = 16 +new_6 = 14 +new_7 = 3 + +[md5s] +gm-tto.cat = 26e85ff84b0063aa5da05dd4698fc76e + +[names] +; Names get read from the CAT file + +[origin] +default = You can find it on your Transport Tycoon CD-ROM. diff --git a/bin/baseset/orig_win.obm b/bin/baseset/orig_win.obm index 8e2053e043..c8c4923e0e 100644 --- a/bin/baseset/orig_win.obm +++ b/bin/baseset/orig_win.obm @@ -142,5 +142,17 @@ GM_TT19.GM = Funk Central GM_TT20.GM = Jammit GM_TT21.GM = Movin' On +; MIDI timecodes where the playback should attemp to start and stop short. +; This is to allow fixing undesired silences in original MIDI files. +; However not all music drivers may support this. +[timingtrim] +; Theme has two beats silence at the beginning which prevents clean looping. +GM_TT00.GM = 768:53760 +; Can't Get There From Here from the Windows version has a long silence at the end, +; followed by a solo repeat. This isn't in the original DOS version music and is likely +; unintentional from the people who converted the music from the DOS version. +; Actual song ends after measure 152. +GM_TT10.GM = 0:235008 + [origin] default = You can find it on your Transport Tycoon Deluxe CD-ROM. diff --git a/changelog.txt b/changelog.txt index 8edba15fb4..5e1540a1e0 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,44 @@ +1.8.0 (2018-04-01) +------------------------------------------------------------------------ +(None) + + +1.8.0-RC1 (2018-03-21) +------------------------------------------------------------------------ +- Feature: [GFX] Climate-specific Action5 extra airport sprites [FS#6664] (r27976) +- Feature: Draw vertical separators at tile distance in the train depot GUI (r27938, r27899) +- Feature: [Build] MSVC 2017 project file generator. Most noticeable, std:c++latest is enabled (r27920, r27919, r27918, r27917) +- Feature: [Build] Project file generator for kdevelop 4/5 [FS#6577] (r27897) +- Feature: Add option to close windows with right click [FS#4950] (r27826, r27825) +- Feature: Vehicle Group Info: Add profits and occupancy display to group vehicle list (r27822) +- Feature: Display aircraft type in vehicle preview/purchase/detail windows (r27802, r27799, r27797) +- Change: [NewGRF] Various performance improvements to resolving VA2 (r27989, r27985, r27984, r27983, r27982) +- Change: [NewGRF] Increase maximum allowed vehicle sprite size to reduce clipping of ships (r27987) +- Change: Check companies for bankruptcy before subtracting reoccuring monthly costs [FS#6679] (r27981) +- Change: [GFX] Replace the office building sprite on various toyland airports with a better fitting sprite [FS#6664] (r27977) +- Change: [GFX] The switch-toolbar icon contained pixels from the fire cycle. Replace the whole icon with a new version [FS#6654] (r27961) +- Change: Reword texts in industry view, when stockpiling is used (r27952) +- Change: Remove the gap between windows when positioning them after opening [FS#6568] (r27934, r27900) +- Change: [Build] Enable usage of static_assert for MSVC (r27916) +- Change: [Build] Preserve PKG_CONFIG_PATH and PKG_CONFIG_LIBDIR environment variables in config.cache file [FS#6614] (r27902) +- Change: Do not cancel headquarter construction and engine-preview-query when shift-clicking (r27889) +- Change: Parse extmidi command string for parameters to pass on (r27834) +- Change: Draw images in centre of buttons (r27829, r27821) +- Fix: Store the map variety setting in the savegame like the other mapgen settings, so restarting maps considers it [FS#6673] (r27978) +- Fix: Hair selection was missing one option [FS#6642] (r27975) +- Fix: Avoid tile operations outside map border when building lock [FS#6662] (r27973) +- Fix: Catenary sprites got mixed up for depots [FS#6670] (r27972) +- Fix: Make automatic window-positioning RTL-aware (r27934, r27900) +- Fix: Automatic window-positioning now uses GUI-scale/style dependent sizes/distances instead of fixed pixel values (r27934, r27900) +- Fix: [NewGRF] While executing random triggers, var 5F should include the new triggers (r27928) +- Fix: [NewGRF] Reset used random triggers only after all A123 chains have been resolved, so that all RA2 in all chains can test the shared triggers (r27928) +- Fix: [NewGRF] Industry random triggers are stored per tile, even when randomising the shared random bits of the parent industry (r27928) +- Fix: [NPF] Reserved track bits were not accounted for when trying to find any safe position (r27912) +- Fix: Do not modify argv[0] [FS#6575] (r27886) +- Fix: Do not search directories when opening ini files as we already have their full path [FS#6421] (r27816) +- Fix: Road tunnel/bridge heads have no trackbits wrt. catenary drawing (r27812) + + 1.7.2 (2017-12-24) ------------------------------------------------------------------------ (None) diff --git a/config.lib b/config.lib index f5852ea944..8de43ae929 100644 --- a/config.lib +++ b/config.lib @@ -31,7 +31,6 @@ set_default() { awk="awk" pkg_config="pkg-config" os="DETECT" - endian="AUTO" cpu_type="DETECT" config_log="config.log" prefix_dir="/usr/local" @@ -78,6 +77,7 @@ set_default() { enable_builtin_depend="1" with_makedepend="0" with_direct_music="1" + with_xaudio2="1" with_sort="1" with_iconv="1" with_midi="" @@ -88,7 +88,7 @@ set_default() { with_icu_layout="1" with_icu_sort="1" static_icu="0" - with_psp_config="1" + with_uniscribe="1" with_threads="1" with_distcc="1" with_ccache="1" @@ -112,7 +112,6 @@ set_default() { awk pkg_config os - endian cpu_type config_log prefix_dir @@ -158,6 +157,7 @@ set_default() { enable_builtin_depend with_makedepend with_direct_music + with_xaudio2 with_sort with_iconv with_midi @@ -168,7 +168,7 @@ set_default() { with_icu_layout with_icu_sort static_icu - with_psp_config + with_uniscribe with_threads with_distcc with_ccache @@ -230,9 +230,6 @@ detect_params() { --lipo) prev_p="lipo";; --lipo=*) lipo="$optarg";; - --endian) prev_p="endian";; - --endian=*) endian="$optarg";; - # Alias --prefix with --prefix-dir, for compatibility with GNU autotools @@ -412,9 +409,9 @@ detect_params() { --static-libicu) static_icu="1";; --static-libicu=*) static_icu="$optarg";; - --with-psp-config) with_psp_config="2";; - --without-psp-config) with_psp_config="0";; - --with-psp-config=*) with_psp_config="$optarg";; + --with-uniscribe) with_uniscribe="2";; + --without-uniscribe) with_uniscribe="0";; + --with-uniscribe=*) with_uniscribe="$optarg";; --disable-builtin-depend) enable_builtin_depend="0";; --enable-builtin-depend) enable_builtin_depend="2";; @@ -428,6 +425,10 @@ detect_params() { --without-direct-music) with_direct_music="0";; --with-direct-music=*) with_direct_music="$optarg";; + --with-xaudio2) with_xaudio2="2";; + --without-xaudio2) with_xaudio2="0";; + --with-xaudio2=*) with_xaudio2="$optarg";; + --with-sort) with_sort="2";; --without-sort) with_sort="0";; --with-sort=*) with_sort="$optarg";; @@ -561,7 +562,6 @@ check_params() { # Some params want to be in full uppercase, else they might not work as # expected.. fix that here - endian=`echo $endian | tr '[a-z]' '[A-Z]'` os=`echo $os | tr '[a-z]' '[A-Z]'` cpu_type=`echo $cpu_type | tr '[a-z]' '[A-Z]'` @@ -577,21 +577,10 @@ check_params() { # Check if all params have valid values - # Endian only allows AUTO, LE and, BE - if [ -z "`echo $endian | egrep '^(AUTO|LE|BE|PREPROCESSOR)$'`" ]; then - log 1 "configure: error: invalid option --endian=$endian" - log 1 " Available options are: --endian=[AUTO|LE|BE]" - exit 1 - fi - if [ "$endian" = "PREPROCESSOR" ] && [ "$os" != "OSX" ]; then - log 1 "configure: error: invalid option --endian=$endian" - log 1 " PREPROCESSOR is only available for OSX" - exit 1 - fi - # OS only allows DETECT, UNIX, OSX, FREEBSD, DRAGONFLY, OPENBSD, NETBSD, MORPHOS, BEOS, HAIKU, SUNOS, CYGWIN, MINGW, OS2, DOS, WINCE, and PSP - if [ -z "`echo $os | egrep '^(DETECT|UNIX|OSX|FREEBSD|DRAGONFLY|OPENBSD|NETBSD|HPUX|MORPHOS|BEOS|HAIKU|SUNOS|CYGWIN|MINGW|OS2|DOS|WINCE|PSP)$'`" ]; then + # OS only allows DETECT, UNIX, OSX, FREEBSD, DRAGONFLY, OPENBSD, NETBSD, MORPHOS, BEOS, HAIKU, SUNOS, CYGWIN, MINGW, OS2, and DOS + if [ -z "`echo $os | egrep '^(DETECT|UNIX|OSX|FREEBSD|DRAGONFLY|OPENBSD|NETBSD|HPUX|MORPHOS|BEOS|HAIKU|SUNOS|CYGWIN|MINGW|OS2|DOS)$'`" ]; then log 1 "configure: error: invalid option --os=$os" - log 1 " Available options are: --os=[DETECT|UNIX|OSX|FREEBSD|DRAGONFLY|OPENBSD|NETBSD|HPUX|MORPHOS|BEOS|HAIKU|SUNOS|CYGWIN|MINGW|OS2|DOS|WINCE|PSP]" + log 1 " Available options are: --os=[DETECT|UNIX|OSX|FREEBSD|DRAGONFLY|OPENBSD|NETBSD|HPUX|MORPHOS|BEOS|HAIKU|SUNOS|CYGWIN|MINGW|OS2|DOS]" exit 1 fi # cpu_type can be either 32 or 64 @@ -790,13 +779,13 @@ check_params() { exit 1 fi else - if [ "$os" = "MINGW" ] || [ "$os" = "CYGWIN" ] || [ "$os" = "WINCE" ]; then + if [ "$os" = "MINGW" ] || [ "$os" = "CYGWIN" ]; then log 1 "checking GDI video driver... found" else log 1 "checking GDI video driver... not Windows, skipping" fi - if [ -z "$allegro_config" ] && [ -z "$sdl_config" ] && [ "$with_cocoa" = 0 ] && [ "$os" != "MINGW" ] && [ "$os" != "CYGWIN" ] && [ "$os" != "WINCE" ]; then + if [ -z "$allegro_config" ] && [ -z "$sdl_config" ] && [ "$with_cocoa" = 0 ] && [ "$os" != "MINGW" ] && [ "$os" != "CYGWIN" ]; then log 1 "configure: error: no video driver development files found" log 1 " If you want a dedicated server use --enable-dedicated as parameter" exit 1 @@ -896,13 +885,34 @@ check_params() { fi fi + if [ "$with_uniscribe" != "0" ]; then + if [ "$os" != "MINGW" ]; then + if [ "$with_uniscribe" != "1" ]; then + log 1 "configure: error: Uniscribe is only supported on native Win32 targets" + exit 1 + fi + with_uniscribe="0" + + log 1 "checking Uniscribe text layout... not Windows, skipping" + else + log 1 "checking Uniscribe text layout... found" + + # Don't use ICU unless forced. + if [ "$with_icu_layout" = "1" ]; then + with_icu_layout="0" + fi + if [ "$with_icu_sort" = "1" ]; then + with_icu_sort="0" + fi + fi + fi + detect_xdg_basedir detect_png detect_freetype detect_fontconfig detect_icu_layout detect_icu_sort - detect_pspconfig detect_libtimidity if [ "$with_direct_music" != "0" ]; then @@ -919,13 +929,21 @@ check_params() { fi fi - detect_sort + if [ "$with_xaudio2" != "0" ]; then + if [ "$os" != "MINGW" ] && [ "$os" != "CYGWIN" ]; then + if [ "$with_xaudio2" != "1" ]; then + log 1 "configure: error: xaudio2 is only supported on Win32 targets" + exit 1 + fi + with_xaudio2="0" - if [ "$os" = "OSX" ] && [ "$endian" = "AUTO" ]; then - endian="PREPROCESSOR" + log 1 "checking xaudio2... not Windows, skipping" + else + check_xaudio2 + fi fi - log 1 "checking endianness... $endian" + detect_sort # Suppress language errors when there is a version defined, indicating a release # It just isn't pretty if any release produces warnings in the languages. @@ -1137,7 +1155,7 @@ check_params() { fi if [ "$personal_dir" = "1" ]; then - if [ "$os" = "MINGW" ] || [ "$os" = "CYGWIN" ] || [ "$os" = "WINCE" ] || [ "$os" = "DOS" ] || [ "$os" = "HAIKU" ]; then + if [ "$os" = "MINGW" ] || [ "$os" = "CYGWIN" ] || [ "$os" = "DOS" ] || [ "$os" = "HAIKU" ]; then personal_dir="OpenTTD" elif [ "$os" = "OSX" ]; then personal_dir="Documents/OpenTTD" @@ -1235,14 +1253,14 @@ make_compiler_cflags() { # $5 - name of the features variable # Get the compiler to tell us who it is - compiler="`$1 --version | head -n1 | cut -d' ' -f1`" + version_line="`$1 --version | head -n1`" eval eval "flags=\\\$$2" eval eval "cxxflags=\\\$$3" eval eval "ldflags=\\\$$4" eval eval "features=\\\$$5" - if [ "$compiler" = "icc" ]; then + if [ `echo "$version_line" | cut -d' ' -f1` = "icc" ]; then # Enable some things only for certain ICC versions cc_version=`$1 -dumpversion | cut -c 1-4 | sed s@\\\.@@g` @@ -1334,7 +1352,7 @@ make_compiler_cflags() { features="$features lto" fi fi - elif [ "$compiler" = "clang" ]; then + elif echo "$version_line" | grep -q "clang"; then # Enable some things only for certain clang versions cc_version="`$1 -v 2>&1 | head -n 1 | sed s@[^0-9]@@g | cut -c 1-2`" @@ -1591,9 +1609,6 @@ make_cflags_and_ldflags() { # Each debug level reduces the optimization by a bit if [ $enable_debug -ge 1 ]; then CFLAGS="$CFLAGS -g -D_DEBUG" - if [ "$os" = "PSP" ]; then - CFLAGS="$CFLAGS -G0" - fi fi if [ $enable_debug -ge 2 ]; then CFLAGS="$CFLAGS -fno-inline" @@ -1670,7 +1685,7 @@ make_cflags_and_ldflags() { fi fi - if [ "$os" != "CYGWIN" ] && [ "$os" != "HAIKU" ] && [ "$os" != "OPENBSD" ] && [ "$os" != "MINGW" ] && [ "$os" != "MORPHOS" ] && [ "$os" != "OSX" ] && [ "$os" != "DOS" ] && [ "$os" != "WINCE" ] && [ "$os" != "PSP" ] && [ "$os" != "OS2" ]; then + if [ "$os" != "CYGWIN" ] && [ "$os" != "HAIKU" ] && [ "$os" != "OPENBSD" ] && [ "$os" != "MINGW" ] && [ "$os" != "MORPHOS" ] && [ "$os" != "OSX" ] && [ "$os" != "DOS" ] && [ "$os" != "OS2" ]; then LIBS="$LIBS -lpthread" fi if [ "$os" != "CYGWIN" ] && [ "$os" != "HAIKU" ] && [ "$os" != "MINGW" ] && [ "$os" != "MORPHOS" ] && [ "$os" != "OSX" ] && [ "$os" != "DOS" ] && [ "$os" != "WINCE" ] && [ "$os" != "PSP" ] && [ "$os" != "OS2" ]; then @@ -1881,19 +1896,9 @@ EOL fi fi - if [ "$os" != "CYGWIN" ] && [ "$os" != "HAIKU" ] && [ "$os" != "MINGW" ] && [ "$os" != "DOS" ] && [ "$os" != "WINCE" ]; then + if [ "$os" != "CYGWIN" ] && [ "$os" != "HAIKU" ] && [ "$os" != "MINGW" ] && [ "$os" != "DOS" ]; then LIBS="$LIBS -lc" fi - if [ "$os" = "WINCE" ]; then - LIBS="$LIBS -lcoredll -lcorelibc -laygshell -lws2 -e WinMainCRTStartup" - fi - if [ "$os" = "PSP" ]; then - CFLAGS="$CFLAGS -I`$psp_config -p`/include" - LDFLAGS="$LDFLAGS -L`$psp_config -p`/lib" - - CFLAGS="$CFLAGS -fno-exceptions -fno-rtti -D_PSP_FW_VERSION=150" - LIBS="$LIBS -D_PSP_FW_VERSION=150 -lpspdebug -lpspdisplay -lpspge -lpspctrl -lpspsdk -lpspnet -lpspnet_inet -lpspnet_apctl -lpspnet_resolver -lpsputility -lpspuser -lpspkernel -lm" - fi if [ "$os" = "MORPHOS" ]; then # -Wstrict-prototypes generates much noise because of system headers @@ -1932,14 +1937,14 @@ EOL CFLAGS="$CFLAGS -DUNIX" fi # And others like Windows - if [ "$os" = "MINGW" ] || [ "$os" = "CYGWIN" ] || [ "$os" = "WINCE" ]; then + if [ "$os" = "MINGW" ] || [ "$os" = "CYGWIN" ]; then CFLAGS="$CFLAGS -DWIN" fi if [ -n "$allegro_config" ]; then CFLAGS="$CFLAGS -DWITH_ALLEGRO" CFLAGS="$CFLAGS `$allegro_config --cflags`" - if [ "$os" != "MINGW" ] && [ "$os" != "CYGWIN" ] && [ "$os" != "WINCE" ]; then + if [ "$os" != "MINGW" ] && [ "$os" != "CYGWIN" ]; then if [ "$enable_static" != "0" ]; then LIBS="$LIBS `$allegro_config --static --libs`" else @@ -1952,7 +1957,7 @@ EOL CFLAGS="$CFLAGS -DWITH_SDL" # SDL must not add _GNU_SOURCE as it breaks many platforms CFLAGS="$CFLAGS `$sdl_config --cflags | sed 's@-D_GNU_SOURCE[^ ]*@@'`" - if [ "$os" != "MINGW" ] && [ "$os" != "CYGWIN" ] && [ "$os" != "WINCE" ]; then + if [ "$os" != "MINGW" ] && [ "$os" != "CYGWIN" ]; then if [ "$enable_static" != "0" ]; then LIBS="$LIBS `$sdl_config --static-libs`" else @@ -2049,7 +2054,7 @@ EOL CFLAGS="$CFLAGS `$freetype_config --cflags | tr '\n\r' ' '`" if [ "$enable_static" != "0" ]; then - LIBS="$LIBS `$freetype_config --libs --static | tr '\n\r' ' '`" + LIBS="$LIBS `$freetype_config --libs --static | tr '\n\r' ' '` -lfreetype" else LIBS="$LIBS `$freetype_config --libs | tr '\n\r' ' '`" fi @@ -2077,6 +2082,10 @@ EOL fi fi + if [ "$with_uniscribe" != "0" ]; then + CFLAGS="$CFLAGS -DWITH_UNISCRIBE" + LIBS="$LIBS -lusp10" + fi if [ "$with_direct_music" != "0" ]; then CFLAGS="$CFLAGS -DWIN32_ENABLE_DIRECTMUSIC_SUPPORT" @@ -2088,6 +2097,10 @@ EOL fi fi + if [ "$with_xaudio2" != "0" ]; then + CFLAGS="$CFLAGS -DWITH_XAUDIO2" + fi + if [ -n "$libtimidity_config" ]; then CFLAGS="$CFLAGS -DLIBTIMIDITY" CFLAGS="$CFLAGS `$libtimidity_config --cflags | tr '\n\r' ' '`" @@ -2388,7 +2401,7 @@ check_cxx_host() { } check_windres() { - if [ "$os" = "MINGW" ] || [ "$os" = "CYGWIN" ] || [ "$os" = "WINCE" ]; then + if [ "$os" = "MINGW" ] || [ "$os" = "CYGWIN" ]; then check_compiler "host windres" "windres" "$host" "$windres" "$WINDRES" "windres" "windres" "2" "-V" fi } @@ -2455,9 +2468,7 @@ check_direct_music() { echo " #include #include - #include #include - #include int main(int argc, char *argv[]) { }" > direct_music.test.c $cxx_host $CFLAGS direct_music.test.c -o direct_music.test 2> /dev/null res=$? @@ -2476,6 +2487,35 @@ check_direct_music() { fi } +check_xaudio2() { + echo " + #include + + #undef NTDDI_VERSION + #undef _WIN32_WINNT + + #define NTDDI_VERSION NTDDI_WIN8 + #define _WIN32_WINNT _WIN32_WINNT_WIN8 + + #include + int main(int argc, char *argv[]) { }" > xaudio2.test.c + $cxx_host $CFLAGS xaudio2.test.c -o xaudio2.test 2> /dev/null + res=$? + rm -f xaudio2.test.c xaudio2.test + + if [ "$res" != "0" ]; then + if [ "$with_xaudio2" != "1" ]; then + log 1 "configure: error: xaudio2 is not available on this system" + exit 1 + fi + with_xaudio2="0" + + log 1 "checking xaudio2... not found" + else + log 1 "checking xaudio2... found" + fi +} + check_makedepend() { if [ "$enable_builtin_depend" != "0" ]; then with_makedepend="0" @@ -2594,7 +2634,7 @@ detect_awk() { detect_os() { if [ "$os" = "DETECT" ]; then - # Detect UNIX, OSX, FREEBSD, DRAGONFLY, OPENBSD, NETBSD, HPUX, MORPHOS, BEOS, SUNOS, CYGWIN, MINGW, OS2, DOS, WINCE, and PSP + # Detect UNIX, OSX, FREEBSD, DRAGONFLY, OPENBSD, NETBSD, HPUX, MORPHOS, BEOS, SUNOS, CYGWIN, MINGW, OS2, and DOS # Try first via dumpmachine, then via uname os=`echo "$host" | tr '[A-Z]' '[a-z]' | $awk ' @@ -2614,8 +2654,6 @@ detect_os() { /mingw/ { print "MINGW"; exit} /os2/ { print "OS2"; exit} /dos/ { print "DOS"; exit} - /wince/ { print "WINCE"; exit} - /psp/ { print "PSP"; exit} '` if [ -z "$os" ]; then @@ -2641,7 +2679,7 @@ detect_os() { if [ -z "$os" ]; then log 1 "detecting OS... none detected" log 1 "I couldn't detect your OS. Please use --os=OS to force one" - log 1 "Allowed values are: UNIX, OSX, FREEBSD, DRAGONFLY, OPENBSD, NETBSD, MORPHOS, HPUX, BEOS, HAIKU, SUNOS, CYGWIN, MINGW, OS2, DOS, WINCE, and PSP" + log 1 "Allowed values are: UNIX, OSX, FREEBSD, DRAGONFLY, OPENBSD, NETBSD, MORPHOS, HPUX, BEOS, HAIKU, SUNOS, CYGWIN, MINGW, OS2, and DOS" exit 1 fi @@ -2900,6 +2938,11 @@ detect_library() { eval "res=\$$2" if [ -z "$res" ]; then log 2 " trying /mingw/include/$4$5... no" + eval "$2=`ls -1 /mingw$cpu_type/include/$4*.h 2>/dev/null | egrep \"\/$5\$\"`" + fi + eval "res=\$$2" + if [ -z "$res" ]; then + log 2 " trying /mingw$cpu_type/include/$4$5... no" eval "$2=`ls -1 /opt/local/include/$4*.h 2>/dev/null | egrep \"\/$5\$\"`" fi eval "res=\$$2" @@ -2948,6 +2991,11 @@ detect_library() { eval "res=\$$2" if [ -z "$res" ]; then log 2 " trying /mingw/lib/$3... no" + eval "$2=`ls /mingw$cpu_type/lib/*.a 2>/dev/null | egrep \"\/$3\$\"`" + fi + eval "res=\$$2" + if [ -z "$res" ]; then + log 2 " trying /mingw$cpu_type/lib/$3... no" log 1 "configure: error: $2 couldn't be found" log 1 "configure: error: you requested a static link, but I can't find $3" @@ -3084,7 +3132,7 @@ detect_fontconfig() { fontconfig_config="" return 0 fi - if [ "$os" = "MINGW" ] || [ "$os" = "CYGWIN" ] || [ "$os" = "WINCE" ]; then + if [ "$os" = "MINGW" ] || [ "$os" = "CYGWIN" ]; then log 1 "checking libfontconfig... WIN32, skipping" fontconfig_config="" return 0 @@ -3107,55 +3155,6 @@ detect_icu_sort() { detect_pkg_config "$with_icu_sort" "icu-i18n" "icu_sort_config" "4.8" "1" } -detect_pspconfig() { - # 0 means no, 1 is auto-detect, 2 is force - if [ "$with_psp_config" = "0" ]; then - log 1 "checking psp-config... disabled" - - psp_config="" - return 0 - fi - - if [ "$with_psp_config" = "1" ] && [ "$os" != "PSP" ]; then - log 1 "checking psp-config... not PSP, skipping" - - psp_config=""; - return 0 - fi - - if [ "$os" != "PSP" ]; then - log 1 "checking psp-config... not PSP" - - log 1 "configure: error: psp-config is only supported for PSP" - exit 1 - fi - - if [ "$with_psp_config" = "1" ] || [ "$with_psp_config" = "" ] || [ "$with_psp_config" = "2" ]; then - psp_config="psp-config" - else - psp_config="$with_psp_config" - fi - - version=`$psp_config -p 2>/dev/null` - ret=$? - log 2 "executing $psp_config -p" - log 2 " returned $version" - log 2 " exit code $ret" - - if [ -z "$version" ] || [ "$ret" != "0" ]; then - log 1 "checking psp-config... not found" - log 1 "configure: error: psp-config couldn't be found" - - # It was forced, so it should be found. - if [ "$with_psp_config" != "1" ]; then - log 1 "configure: error: you supplied '$with_psp_config', but it seems invalid" - fi - exit 1 - fi - - log 1 "checking psp-config... found" -} - detect_iconv() { # 0 means no, 1 is auto-detect, 2 is force if [ "$with_iconv" = "0" ]; then @@ -3521,17 +3520,14 @@ make_sed() { s@!!INSTALL_DIR!!@$install_dir@g; s@!!BINARY_NAME!!@$binary_name@g; s@!!STRGEN!!@$STRGEN@g; - s@!!ENDIAN_CHECK!!@$ENDIAN_CHECK@g; s@!!DEPEND!!@$DEPEND@g; s@!!SETTINGSGEN!!@$SETTINGSGEN@g; - s@!!ENDIAN_FORCE!!@$endian@g; s@!!STAGE!!@$STAGE@g; s@!!MAKEDEPEND!!@$makedepend@g; s@!!CFLAGS_MAKEDEP!!@$cflags_makedep@g; s@!!SORT!!@$sort@g; s@!!CONFIG_CACHE_COMPILER!!@config.cache.compiler@g; s@!!CONFIG_CACHE_LINKER!!@config.cache.linker@g; - s@!!CONFIG_CACHE_ENDIAN!!@config.cache.endian@g; s@!!CONFIG_CACHE_SOURCE!!@config.cache.source@g; s@!!CONFIG_CACHE_VERSION!!@config.cache.version@g; s@!!CONFIG_CACHE_SOURCE_LIST!!@config.cache.source.list@g; @@ -3767,8 +3763,7 @@ showhelp() { echo " --os=OS the OS we are compiling for [DETECT]" echo " DETECT/UNIX/OSX/FREEBSD/DRAGONFLY/OPENBSD/" echo " NETBSD/MORPHOS/HPUX/BEOS/SUNOS/CYGWIN/" - echo " MINGW/OS2/DOS/WINCE/PSP/HAIKU" - echo " --endian=ENDIAN set the endian of the HOST (AUTO/LE/BE)" + echo " MINGW/OS2/DOS/HAIKU" echo "" echo "Paths:" echo " --prefix-dir=dir specifies the prefix for all installed" @@ -3864,7 +3859,6 @@ showhelp() { echo " --static-icu try to link statically (libsicu instead of" echo " libicu; can fail as the new name is guessed)" echo " --with-iconv[=iconv-path] enables iconv support" - echo " --with-psp-config[=psp-config] enables psp-config support (PSP ONLY)" echo " --disable-builtin-depend disable use of builtin deps finder" echo " --with-makedepend[=makedepend] enables makedepend support" echo " --with-ccache enables ccache support" diff --git a/configure b/configure index 5edbca1867..7ca36480d3 100755 --- a/configure +++ b/configure @@ -75,13 +75,12 @@ save_params make_cflags_and_ldflags EXE="" -if [ "$os" = "MINGW" ] || [ "$os" = "CYGWIN" ] || [ "$os" = "OS2" ] || [ "$os" = "DOS" ] || [ "$os" = "WINCE" ]; then +if [ "$os" = "MINGW" ] || [ "$os" = "CYGWIN" ] || [ "$os" = "OS2" ] || [ "$os" = "DOS" ]; then EXE=".exe" fi TTD="openttd$EXE" STRGEN="strgen$EXE" -ENDIAN_CHECK="endian_check$EXE" DEPEND="depend$EXE" SETTINGSGEN="settings_gen$EXE" @@ -114,7 +113,6 @@ AWKCOMMAND=' if ($0 == "PNG" && "'$png_config'" == "") { next; } if ($0 == "OSX" && "'$os'" != "OSX") { next; } if ($0 == "OS2" && "'$os'" != "OS2") { next; } - if ($0 == "PSP" && "'$os'" != "PSP") { next; } if ($0 == "DEDICATED" && "'$enable_dedicated'" != "1") { next; } if ($0 == "AI" && "'$enable_ai'" == "0") { next; } if ($0 == "COCOA" && "'$with_cocoa'" == "0") { next; } @@ -124,7 +122,6 @@ AWKCOMMAND=' if ($0 == "WIN32" && "'$os'" != "MINGW" && "'$os'" != "CYGWIN" && "'$os'" != "MSVC") { next; } if ($0 == "MORPHOS" && "'$os'" != "MORPHOS") { next; } - if ($0 == "WINCE" && "'$os'" != "WINCE") { next; } if ($0 == "MSVC" && "'$os'" != "MSVC") { next; } if ($0 == "DIRECTMUSIC" && "'$with_direct_music'" == "0") { next; } if ($0 == "LIBTIMIDITY" && "'$libtimidity'" == "" ) { next; } diff --git a/docs/Readme_Windows_MSVC.txt b/docs/Readme_Windows_MSVC.txt index 65701e0e86..00896f00b9 100644 --- a/docs/Readme_Windows_MSVC.txt +++ b/docs/Readme_Windows_MSVC.txt @@ -1,27 +1,24 @@ Compiling OpenTTD using Microsoft Visual C++ -Last updated: 2010-01-03 +Last updated: 2018-03-21 -------------------------------------------- PLEASE READ THE ENTIRE DOCUMENT BEFORE DOING ANY ACTUAL CHANGES!! SUPPORTED MSVC COMPILERS ------------------------ -OpenTTD includes projects for MSVC 2005.NET and MSVC 2008.NET. Both will -compile out of the box, providing you have the required libraries/headers; -which ones, see below. There is no support for VS6 or MSVC 2002, or -MSVC 2003.NET. You are therefore strongly encouraged to either upgrade to -MSVC 2008 Express (free) or use GCC. +OpenTTD includes projects for Microsoft Visual Studio 2005 and later. +This is the earliest compiler supported, Visual C++ 2003, Visual C++ 6.0, +or earlier, will not compile OpenTTD. +You can download the free Visual Studio Community Edition from Microsoft. 1) REQUIRED FILES ----------------- You might already have some of the files already installed, so check before -downloading; mostly because the DirectX SDK and Platform SDK are about -500MB each. +downloading; mostly because the Platform SDK is about 500MB. Download the following files: * openttd-useful.zip (http://binaries.openttd.org/extra/openttd-useful/) - * DirectX 8.1 SDK (http://neuron.tuke.sk/~mizanin/eng/Dx81sdk-include-lib.rar) (or alternatively the latest DirectX SDK from Microsoft) * MS Windows Platform SDK (http://www.microsoft.com/downloads/details.aspx?FamilyId=A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5&displaylang=en) * afxres.h (http://www-d0.fnal.gov/d0dist/dist/packages/d0ve/devel/windows/AFXRES.H) @@ -81,12 +78,16 @@ See section 4.1 of README.md for the required 3rdparty files and how to install 4) COMPILING ------------ -Open trunk/openttd_vs[89]0.sln +Open the appropriate "sln" (Solution) file for your version of Visual Studio: + - VS 2005: projects/openttd_vs80.sln + - VS 2008: projects/openttd_vs90.sln + - VS 2010: projects/openttd_vs100.sln + - VS 2015: projects/openttd_vs140.sln Set the build mode to 'Release' in Build > Configuration manager > Active solution configuration > select "Release" Compile... -If everything works well the binary should be in trunk/objs/Win[32|64]/Release/openttd.exe +If everything works well the binary should be in objs/Win[32|64]/Release/openttd.exe 5) EDITING, CHANGING SOURCE CODE diff --git a/docs/landscape.html b/docs/landscape.html index f60e859fc3..a345128ea4 100644 --- a/docs/landscape.html +++ b/docs/landscape.html @@ -226,7 +226,7 @@
  • m1 bits 4..0: owner of the tile
  • m2: see signals
  • m3 bits 7..4: see signals
  • -
  • m3 bits 3..0 = track type: +
  • m8 bits 5..0 = track type: @@ -626,7 +626,8 @@
  • m5 bit 6 set: level crossing
    • m1 bits 4..0: owner of the railway track
    • -
    • m3 bits 3..0: railway track type
    • +
    • m5 bit 5: set if crossing lights are on
    • +
    • m5 bit 4: pbs reservation state
    • m5 bit 0: direction
  • 0 
    @@ -639,9 +640,8 @@
  • -
  • m5 bit 5: set if crossing lights are on
  • m7 bits 4..0: owner of the road type 0 (normal road)
  • -
  • m5 bit 4: pbs reservation state
  • +
  • m8 bits 5..0: railway track type
  • @@ -860,7 +860,6 @@
  • m2: index into the array of stations
  • m3 bits 7..4: persistent random data for railway stations/waypoints and airports)
  • m3 bits 7..4: owner of tram tracks (road stop)
  • -
  • m3 bits 3..0: track type for railway stations/waypoints
  • m4: custom station id; 0 means standard graphics
  • m5: graphics index (range from 0..255 for each station type): @@ -979,6 +978,7 @@
  • m7 bits 4..0: owner of road (road stops)
  • m7 bits 7..6: present road types (road stops)
  • m7: animation frame (railway stations/waypoints, airports)
  • +
  • m8 bits 5..0: track type for railway stations/waypoints
  • @@ -1444,7 +1444,6 @@
    • m1 bits 4..0: owner
    • m3 bits 7..4: owner of tram
    • -
    • m3 bits 3..0: track type for railway
    • m5 bit 4: pbs reservation state for railway
    • m5 bits 7 clear: tunnel entrance/exit
    • m5 bit 7 set: bridge ramp @@ -1582,6 +1581,7 @@
    • m7 bits 4..0: owner of road
    • m7 bit 5 set = on snow or desert
    • m7 bits 7..6: present road types for road
    • +
    • m8 bits 5..0: track type for railway
    diff --git a/docs/landscape_grid.html b/docs/landscape_grid.html index d34fe9840c..b801b334dd 100644 --- a/docs/landscape_grid.html +++ b/docs/landscape_grid.html @@ -37,6 +37,7 @@ the array so you can quickly see what is used and what is not.
  • m5 - 8 bits in size, is used for general storage
  • m6 - 8 bits in size, is used for general storage
  • m7 - 8 bits in size, is used for general storage
  • +
  • m8 - 16 bits in size, is used for general storage
  • @@ -52,6 +53,7 @@ the array so you can quickly see what is used and what is not. + @@ -64,6 +66,7 @@ the array so you can quickly see what is used and what is not. + @@ -77,6 +80,7 @@ the array so you can quickly see what is used and what is not. + @@ -89,6 +93,7 @@ the array so you can quickly see what is used and what is not. + @@ -97,11 +102,12 @@ the array so you can quickly see what is used and what is not. - + + @@ -109,11 +115,12 @@ the array so you can quickly see what is used and what is not. - + + @@ -121,11 +128,12 @@ the array so you can quickly see what is used and what is not. - + + @@ -139,6 +147,7 @@ the array so you can quickly see what is used and what is not. + @@ -146,11 +155,12 @@ the array so you can quickly see what is used and what is not. - + - + + @@ -163,6 +173,7 @@ the array so you can quickly see what is used and what is not. + @@ -176,6 +187,7 @@ the array so you can quickly see what is used and what is not. + @@ -189,6 +201,7 @@ the array so you can quickly see what is used and what is not. + @@ -197,11 +210,12 @@ the array so you can quickly see what is used and what is not. - + + @@ -214,6 +228,7 @@ the array so you can quickly see what is used and what is not. + @@ -226,6 +241,7 @@ the array so you can quickly see what is used and what is not. + @@ -238,6 +254,7 @@ the array so you can quickly see what is used and what is not. + @@ -250,6 +267,7 @@ the array so you can quickly see what is used and what is not. + @@ -262,6 +280,7 @@ the array so you can quickly see what is used and what is not. + @@ -274,6 +293,7 @@ the array so you can quickly see what is used and what is not. + @@ -287,6 +307,7 @@ the array so you can quickly see what is used and what is not. + @@ -299,6 +320,7 @@ the array so you can quickly see what is used and what is not. + @@ -311,6 +333,7 @@ the array so you can quickly see what is used and what is not. + @@ -324,6 +347,7 @@ the array so you can quickly see what is used and what is not. + @@ -332,11 +356,12 @@ the array so you can quickly see what is used and what is not. - + + @@ -349,6 +374,7 @@ the array so you can quickly see what is used and what is not. + @@ -362,6 +388,7 @@ the array so you can quickly see what is used and what is not. +
    m5 (8) m6 (8) m7 (8)m8 (16)
    bits7654 3210 7654 3210 7654 3210FEDC BA98 7654 3210
    0XXXX XXXX OOOX XXOO OOOO OOOOOOOO OOOO OOOO OOOO
    farmland-inherit- OOOX XXOO OOOO OOOO-inherit-
    1XXXX XXXX OOOX XXXX OOOO XXXX OOOO OOOOOOOO XXXXOOOO OOOO OOOO XXXX XXXX XXXX OOOO OOOO OOOO OOOOOOOO OOOO OOXX XXXX
    rail with signals-inherit- -inherit- OOOO XXXX XXXX XXXXXXXX XXXXXXXX OOOO XXXX XXXX -inherit- OOOO OOOO OOOO OOOO-inherit-
    depot-inherit- -inherit- XXXX XXXX XXXX XXXXOOOO XXXX-inherit- OOOO XXXX XXOX OOXX OOOO OOOO OOOO OOOO-inherit-
    2XXXX XXXX OOXX XOOO XXXO XXXXOOOO OOOO OOOO OOOO
    level crossing-inherit- -inherit- -inherit-XXXX XXXXXXXX OOOO -inherit-XXXX OOOXXXXX OOOX OOXX XOOO XXXX XXXXOOOO OOOO OOXX XXXX
    road depotXXOO OOXX OOOO OOOO XXXO XXXX-inherit-
    3XXXX XXXX XXXX XXOO XXXX XXXXOOOO OOOO OOOO OOOO
    4XXOO OXXX OOOO OOOO OOOO OOOOOOOO OOOO OOOO OOOO
    5XXXX XXXX OXXX XXXX XXXX XXXX XXXX XXXXXXXX XXXXXXXX OOOO XXXX XXXX XXXX XXXX OOXX XXOO XXXX XXXXOOOO OOOO OOXX XXXX
    rail waypoint-inherit- -inherit- -inherit--inherit-
    road stop~~~~ ~XXX OOXX XOOO XXOX XXXX-inherit-
    dock~~~~ ~XXX OOXX XOOO OOOO OOOO-inherit-
    airportXXXX XXXX OOXX XOOO XXXX XXXX-inherit-
    buoy~~~~ ~~~~ OOXX XOOO OOOO OOOO-inherit-
    oilrig~~~~ ~~~~ OOXX XOOO OOOO OOOO-inherit-
    6X~~X XXXX OOOO OOOO OOOO OOOOOOOO OOOO OOOO OOOO
    canal, river-inherit- OOOO OOOO OOOO OOOO-inherit-
    shipdepot-inherit- OOOO OOOO OOOO OOOO-inherit-
    8XXXX XXXX OOXX XXOO XXXX XXXXOOOO OOOO OOOO OOOO
    9XXXX XXXX OOOX XXXX OOOO OOOO OOOO OOOOXXXX XXXXXXXX OOOO OOOO OOOO XOOX XXXX OOOO OOOO XXXX XXXXOOOO OOOO OOXX XXXX
    bridge ramp-inherit- OOXX XXOO -inherit--inherit-
    AXXXX XXXX OOOO OOOO XXXX XXXXOOOO OOOO OOOO OOOO
    diff --git a/docs/obm_format.txt b/docs/obm_format.txt index 40f829a522..45fe5f879e 100644 --- a/docs/obm_format.txt +++ b/docs/obm_format.txt @@ -45,12 +45,15 @@ description.en_US = howdie ; The file names are case sensitive. ; You can have empty file names; in that case no song will be loaded ; for that 'entry'. +; If you want to load music from the MPS DOS music driver "cat" format, +; specify just the name of the .cat file the song is located in, then +; fill out the "catindex" section. [files] ; The theme song for OpenTTD theme = THEME_SONG.GM ; The songs in the 'old style' category -old_0 = -old_1 = +old_0 = GM.CAT +old_1 = GM.CAT old_2 = old_3 = old_4 = @@ -86,9 +89,17 @@ ezy_9 = ; Note that the list of files is case sensitive. Each file listed in the ; files section must be listed here with it's song name, otherwise you ; will get a lot of warnings when starting OpenTTD. +; You don't need to fill this out for "cat" format music, the song names +; are loaded directly from the file in that case. [names] THEME_SONG.GM = Tycoon DELUXE Theme +; If you are loading music from the DOS version "cat" format, specify +; which index into the file the song has. +[catindex] +old_0 = 1 +old_1 = 3 + ; The md5s section lists the MD5 checksum for the files that replace them. ; Note that the list of files is case sensitive. Each file listed in the ; files section must be listed here with it's MD5 checksum, otherwise you @@ -96,6 +107,13 @@ THEME_SONG.GM = Tycoon DELUXE Theme [md5s] THEME_SONG.GM = 45cfec1b9d8c7a0ad45e755833cbf221 +; If a song needs to have parts of the start or end cut off to avoid long +; silences, you can specify MIDI tick codes for start:end of the actual +; music part for each file here. +; Not all music drivers might support this feature. +[timingtrim] +THEME_SONG.GM = 768:53760 + ; The origin section provides the possibility to put and extra line into ; the warning that a file is missing/corrupt. This can be used to tell ; them where to find it. It works on the filename specified in the diff --git a/known-bugs.txt b/known-bugs.txt index e76229e722..e12e0a19fe 100644 --- a/known-bugs.txt +++ b/known-bugs.txt @@ -17,7 +17,7 @@ that are the same as these. If you do, do not act surprised, because we WILL flame you!! The current list of known bugs that we intend to fix can be found in our -bug tracking system at: http://bugs.openttd.org +bug tracking system at: https://github.com/OpenTTD/OpenTTD/issues Also check the closed bugs when searching for your bug in this system as we might have fixed the bug in the mean time. diff --git a/media/baseset/orig_dos.obm b/media/baseset/orig_dos.obm new file mode 100644 index 0000000000..9920bfdbe1 --- /dev/null +++ b/media/baseset/orig_dos.obm @@ -0,0 +1,76 @@ +; $Id$ +; +; This represents the original music as on the Transport +; Tycoon Deluxe for DOS CD. +; +[metadata] +name = original_dos +shortname = TTDD +version = 1 +!! description STR_BASEMUSIC_DOS_DESCRIPTION + +[files] +theme = gm.cat +old_0 = gm.cat +old_1 = gm.cat +old_2 = gm.cat +old_3 = gm.cat +old_4 = gm.cat +old_5 = gm.cat +old_6 = gm.cat +old_7 = gm.cat +old_8 = +old_9 = +new_0 = gm.cat +new_1 = gm.cat +new_2 = gm.cat +new_3 = gm.cat +new_4 = gm.cat +new_5 = gm.cat +new_6 = gm.cat +new_7 = +new_8 = +new_9 = +ezy_0 = gm.cat +ezy_1 = gm.cat +ezy_2 = gm.cat +ezy_3 = gm.cat +ezy_4 = gm.cat +ezy_5 = gm.cat +ezy_6 = +ezy_7 = +ezy_8 = +ezy_9 = + +[md5s] +gm.cat = 7a29d2d0c4f7d2e03091ffa9b2bdfffb + +[catindex] +theme = 0 +old_0 = 1 +old_1 = 8 +old_2 = 2 +old_3 = 9 +old_4 = 14 +old_5 = 15 +old_6 = 19 +old_7 = 13 +new_0 = 6 +new_1 = 11 +new_2 = 10 +new_3 = 17 +new_4 = 21 +new_5 = 18 +new_6 = 5 +ezy_0 = 12 +ezy_1 = 7 +ezy_2 = 16 +ezy_3 = 3 +ezy_4 = 20 +ezy_5 = 4 + +[names] +; Names get read from the CAT file + +[origin] +default = You can find it on your Transport Tycoon Deluxe CD-ROM. diff --git a/media/baseset/orig_tto.obm b/media/baseset/orig_tto.obm new file mode 100644 index 0000000000..ff600d00f6 --- /dev/null +++ b/media/baseset/orig_tto.obm @@ -0,0 +1,71 @@ +; $Id$ +; +; This represents the original music as on the Transport +; Tycoon (with World Editor) for DOS CD. +; +[metadata] +name = original_tto +shortname = TTOD +version = 1 +!! description STR_BASEMUSIC_TTO_DESCRIPTION + +[files] +theme = gm-tto.cat +old_0 = gm-tto.cat +old_1 = gm-tto.cat +old_2 = gm-tto.cat +old_3 = gm-tto.cat +old_4 = gm-tto.cat +old_5 = gm-tto.cat +old_6 = gm-tto.cat +old_7 = gm-tto.cat +old_8 = +old_9 = +new_0 = gm-tto.cat +new_1 = gm-tto.cat +new_2 = gm-tto.cat +new_3 = gm-tto.cat +new_4 = gm-tto.cat +new_5 = gm-tto.cat +new_6 = gm-tto.cat +new_7 = gm-tto.cat +new_8 = +new_9 = +ezy_0 = +ezy_1 = +ezy_2 = +ezy_3 = +ezy_4 = +ezy_5 = +ezy_6 = +ezy_7 = +ezy_8 = +ezy_9 = + +[catindex] +theme = 0 +old_0 = 1 +old_1 = 6 +old_2 = 2 +old_3 = 7 +old_4 = 11 +old_5 = 12 +old_6 = 15 +old_7 = 10 +new_0 = 4 +new_1 = 5 +new_2 = 9 +new_3 = 8 +new_4 = 13 +new_5 = 16 +new_6 = 14 +new_7 = 3 + +[md5s] +gm-tto.cat = 26e85ff84b0063aa5da05dd4698fc76e + +[names] +; Names get read from the CAT file + +[origin] +default = You can find it on your Transport Tycoon CD-ROM. diff --git a/media/baseset/orig_win.obm b/media/baseset/orig_win.obm index 8b35b6de9d..b5d4b024ed 100644 --- a/media/baseset/orig_win.obm +++ b/media/baseset/orig_win.obm @@ -90,5 +90,17 @@ GM_TT19.GM = Funk Central GM_TT20.GM = Jammit GM_TT21.GM = Movin' On +; MIDI timecodes where the playback should attemp to start and stop short. +; This is to allow fixing undesired silences in original MIDI files. +; However not all music drivers may support this. +[timingtrim] +; Theme has two beats silence at the beginning which prevents clean looping. +GM_TT00.GM = 768:53760 +; Can't Get There From Here from the Windows version has a long silence at the end, +; followed by a solo repeat. This isn't in the original DOS version music and is likely +; unintentional from the people who converted the music from the DOS version. +; Actual song ends after measure 152. +GM_TT10.GM = 0:235008 + [origin] default = You can find it on your Transport Tycoon Deluxe CD-ROM. diff --git a/os/windows/installer/install.nsi b/os/windows/installer/install.nsi index cb93d4d04d..2c4c6f94b2 100644 --- a/os/windows/installer/install.nsi +++ b/os/windows/installer/install.nsi @@ -304,6 +304,7 @@ Section /o "Copy data from Transport Tycoon Deluxe CD-ROM" Section2 ; Let's copy the files with size approximation SetOutPath "$INSTDIR\baseset" CopyFiles "$CDDRIVE\gm\*.gm" "$INSTDIR\baseset\" 1028 + CopyFiles "$CDDRIVE\gm.cat" "$INSTDIR\baseset\gm.cat" 415 CopyFiles "$CDDRIVE\sample.cat" "$INSTDIR\baseset\sample.cat" 1566 ; Copy Windows files CopyFiles "$CDDRIVE\trg1r.grf" "$INSTDIR\baseset\trg1r.grf" 2365 @@ -426,6 +427,8 @@ Section "Uninstall" Delete "$INSTDIR\baseset\trgt.grf" Delete "$INSTDIR\baseset\trgc.grf" Delete "$INSTDIR\baseset\trgi.grf" + Delete "$INSTDIR\baseset\gm.cat" + Delete "$INSTDIR\baseset\gm-tto.cat" Delete "$INSTDIR\baseset\*.gm" Delete "$INSTDIR\data\sample.cat" @@ -467,8 +470,10 @@ Section "Uninstall" ; Base sets for music Delete "$INSTDIR\gm\orig_win.obm" + Delete "$INSTDIR\gm\orig_dos.obm" Delete "$INSTDIR\gm\no_music.obm" Delete "$INSTDIR\baseset\orig_win.obm" + Delete "$INSTDIR\baseset\orig_dos.obm" Delete "$INSTDIR\baseset\no_music.obm" ; Remove remaining directories diff --git a/projects/generate b/projects/generate index e82559a911..28fd255527 100755 --- a/projects/generate +++ b/projects/generate @@ -123,7 +123,6 @@ load_main_data() { if ($0 == "PNG" && "'$png_config'" == "") { next; } if ($0 == "OSX" && "'$os'" != "OSX") { next; } if ($0 == "OS2" && "'$os'" != "OS2") { next; } - if ($0 == "PSP" && "'$os'" != "PSP") { next; } if ($0 == "DOS" && "'$os'" != "DOS") { next; } if ($0 == "DEDICATED" && "'$enable_dedicated'" != "1") { next; } if ($0 == "AI" && "'$enable_ai'" == "0") { next; } @@ -131,7 +130,6 @@ load_main_data() { if ($0 == "BEOS" && "'$os'" != "BEOS") { next; } if ($0 == "WIN32" && "'$os'" != "MINGW" && "'$os'" != "CYGWIN" && "'$os'" != "MSVC" ) { next; } - if ($0 == "WINCE" && "'$os'" != "WINCE") { next; } if ($0 == "MSVC" && "'$os'" != "MSVC") { next; } if ($0 == "DIRECTMUSIC" && "'$enable_directmusic'" != "1") { next; } if ($0 == "LIBTIMIDITY" && "'$libtimidity'" == "" ) { next; } @@ -192,9 +190,11 @@ load_main_data() { load_lang_data() { RES="" - for i in `ls $1` + # Windows Folder sort and Linux Folder sort are slightly different. + # By removing the extension and sorting it on Linux, they are the same. + for i in `ls $1 | sed s~.txt$~~g | sort` do - i=`basename $i | sed s~.txt$~~g` + i=`basename $i` if [ "$i" == "english" ] then continue diff --git a/projects/langs_vs100.vcxproj b/projects/langs_vs100.vcxproj index fc77e03bec..88cce9e105 100644 --- a/projects/langs_vs100.vcxproj +++ b/projects/langs_vs100.vcxproj @@ -317,18 +317,18 @@ ..\src\lang\english.txt;..\objs\strgen\strgen.exe;%(AdditionalInputs) ..\bin\lang\slovenian.lng;%(Outputs) - - Generating spanish_MX language file - ..\objs\strgen\strgen.exe -s ..\src\lang -d ..\bin\lang "%(FullPath)" - ..\src\lang\english.txt;..\objs\strgen\strgen.exe;%(AdditionalInputs) - ..\bin\lang\spanish_MX.lng;%(Outputs) - Generating spanish language file ..\objs\strgen\strgen.exe -s ..\src\lang -d ..\bin\lang "%(FullPath)" ..\src\lang\english.txt;..\objs\strgen\strgen.exe;%(AdditionalInputs) ..\bin\lang\spanish.lng;%(Outputs) + + Generating spanish_MX language file + ..\objs\strgen\strgen.exe -s ..\src\lang -d ..\bin\lang "%(FullPath)" + ..\src\lang\english.txt;..\objs\strgen\strgen.exe;%(AdditionalInputs) + ..\bin\lang\spanish_MX.lng;%(Outputs) + Generating swedish language file ..\objs\strgen\strgen.exe -s ..\src\lang -d ..\bin\lang "%(FullPath)" diff --git a/projects/langs_vs100.vcxproj.filters b/projects/langs_vs100.vcxproj.filters index 0afc8c969a..bf5257ec82 100644 --- a/projects/langs_vs100.vcxproj.filters +++ b/projects/langs_vs100.vcxproj.filters @@ -142,10 +142,10 @@ Translations - + Translations - + Translations diff --git a/projects/langs_vs140.vcxproj b/projects/langs_vs140.vcxproj index 317fd34a11..25e7160bfb 100644 --- a/projects/langs_vs140.vcxproj +++ b/projects/langs_vs140.vcxproj @@ -317,18 +317,18 @@ ..\src\lang\english.txt;..\objs\strgen\strgen.exe;%(AdditionalInputs) ..\bin\lang\slovenian.lng;%(Outputs) - - Generating spanish_MX language file - ..\objs\strgen\strgen.exe -s ..\src\lang -d ..\bin\lang "%(FullPath)" - ..\src\lang\english.txt;..\objs\strgen\strgen.exe;%(AdditionalInputs) - ..\bin\lang\spanish_MX.lng;%(Outputs) - Generating spanish language file ..\objs\strgen\strgen.exe -s ..\src\lang -d ..\bin\lang "%(FullPath)" ..\src\lang\english.txt;..\objs\strgen\strgen.exe;%(AdditionalInputs) ..\bin\lang\spanish.lng;%(Outputs) + + Generating spanish_MX language file + ..\objs\strgen\strgen.exe -s ..\src\lang -d ..\bin\lang "%(FullPath)" + ..\src\lang\english.txt;..\objs\strgen\strgen.exe;%(AdditionalInputs) + ..\bin\lang\spanish_MX.lng;%(Outputs) + Generating swedish language file ..\objs\strgen\strgen.exe -s ..\src\lang -d ..\bin\lang "%(FullPath)" diff --git a/projects/langs_vs140.vcxproj.filters b/projects/langs_vs140.vcxproj.filters index 0afc8c969a..bf5257ec82 100644 --- a/projects/langs_vs140.vcxproj.filters +++ b/projects/langs_vs140.vcxproj.filters @@ -142,10 +142,10 @@ Translations - + Translations - + Translations diff --git a/projects/langs_vs141.vcxproj b/projects/langs_vs141.vcxproj index 2444b0e0e7..c554c6e378 100644 --- a/projects/langs_vs141.vcxproj +++ b/projects/langs_vs141.vcxproj @@ -317,18 +317,18 @@ ..\src\lang\english.txt;..\objs\strgen\strgen.exe;%(AdditionalInputs) ..\bin\lang\slovenian.lng;%(Outputs) - - Generating spanish_MX language file - ..\objs\strgen\strgen.exe -s ..\src\lang -d ..\bin\lang "%(FullPath)" - ..\src\lang\english.txt;..\objs\strgen\strgen.exe;%(AdditionalInputs) - ..\bin\lang\spanish_MX.lng;%(Outputs) - Generating spanish language file ..\objs\strgen\strgen.exe -s ..\src\lang -d ..\bin\lang "%(FullPath)" ..\src\lang\english.txt;..\objs\strgen\strgen.exe;%(AdditionalInputs) ..\bin\lang\spanish.lng;%(Outputs) + + Generating spanish_MX language file + ..\objs\strgen\strgen.exe -s ..\src\lang -d ..\bin\lang "%(FullPath)" + ..\src\lang\english.txt;..\objs\strgen\strgen.exe;%(AdditionalInputs) + ..\bin\lang\spanish_MX.lng;%(Outputs) + Generating swedish language file ..\objs\strgen\strgen.exe -s ..\src\lang -d ..\bin\lang "%(FullPath)" diff --git a/projects/langs_vs141.vcxproj.filters b/projects/langs_vs141.vcxproj.filters index 0afc8c969a..bf5257ec82 100644 --- a/projects/langs_vs141.vcxproj.filters +++ b/projects/langs_vs141.vcxproj.filters @@ -142,10 +142,10 @@ Translations - + Translations - + Translations diff --git a/projects/langs_vs80.vcproj b/projects/langs_vs80.vcproj index e683d57353..909613b59b 100644 --- a/projects/langs_vs80.vcproj +++ b/projects/langs_vs80.vcproj @@ -738,21 +738,6 @@ /> - - - - - @@ -768,6 +753,21 @@ /> + + + + + diff --git a/projects/langs_vs90.vcproj b/projects/langs_vs90.vcproj index c1f028233e..583e0f9a5d 100644 --- a/projects/langs_vs90.vcproj +++ b/projects/langs_vs90.vcproj @@ -739,21 +739,6 @@ /> - - - - - @@ -769,6 +754,21 @@ /> + + + + + diff --git a/projects/openttd_vs100.vcxproj b/projects/openttd_vs100.vcxproj index de117cc40a..019fde79aa 100644 --- a/projects/openttd_vs100.vcxproj +++ b/projects/openttd_vs100.vcxproj @@ -102,7 +102,7 @@ Size true ..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions) + WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions) true Sync MultiThreaded @@ -131,7 +131,7 @@ 0x0809 - winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies) true %(IgnoreSpecificDefaultLibraries) true @@ -162,7 +162,7 @@ /MP %(AdditionalOptions) Disabled ..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions) + WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug @@ -182,7 +182,7 @@ 0x0809 - winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies) true LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) true @@ -216,7 +216,7 @@ Size true ..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions) + WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions) true Sync MultiThreaded @@ -245,7 +245,7 @@ 0x0809 - winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies) true %(IgnoreSpecificDefaultLibraries) true @@ -274,7 +274,7 @@ /MP %(AdditionalOptions) Disabled ..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions) + WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug @@ -298,7 +298,7 @@ 0x0809 - winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies) true LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) true @@ -481,6 +481,7 @@ + @@ -569,6 +570,8 @@ + + @@ -630,6 +633,7 @@ + @@ -683,6 +687,7 @@ + @@ -730,6 +735,7 @@ + @@ -791,6 +797,7 @@ + @@ -1149,6 +1156,8 @@ + + @@ -1293,12 +1302,15 @@ + + + diff --git a/projects/openttd_vs100.vcxproj.filters b/projects/openttd_vs100.vcxproj.filters index ef11613ff8..911a53a864 100644 --- a/projects/openttd_vs100.vcxproj.filters +++ b/projects/openttd_vs100.vcxproj.filters @@ -600,6 +600,9 @@ Header Files + + Header Files + Header Files @@ -864,6 +867,12 @@ Header Files + + Header Files + + + Header Files + Header Files @@ -1047,6 +1056,9 @@ Header Files + + Header Files + Header Files @@ -1206,6 +1218,9 @@ Header Files + + Header Files + Header Files @@ -1347,6 +1362,9 @@ GUI Source Code + + GUI Source Code + GUI Source Code @@ -1530,6 +1548,9 @@ Widgets + + Widgets + Widgets @@ -2604,6 +2625,12 @@ Blitters + + Blitters + + + Blitters + Blitters @@ -3036,6 +3063,9 @@ Music + + Music + Music @@ -3048,12 +3078,18 @@ Sound + + Sound + Windows files Windows files + + Windows files + Windows files diff --git a/projects/openttd_vs100.vcxproj.in b/projects/openttd_vs100.vcxproj.in index ab2ae133af..b2eb33d316 100644 --- a/projects/openttd_vs100.vcxproj.in +++ b/projects/openttd_vs100.vcxproj.in @@ -102,7 +102,7 @@ Size true ..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions) + WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions) true Sync MultiThreaded @@ -131,7 +131,7 @@ 0x0809 - winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies) true %(IgnoreSpecificDefaultLibraries) true @@ -162,7 +162,7 @@ /MP %(AdditionalOptions) Disabled ..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions) + WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug @@ -182,7 +182,7 @@ 0x0809 - winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies) true LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) true @@ -216,7 +216,7 @@ Size true ..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions) + WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions) true Sync MultiThreaded @@ -245,7 +245,7 @@ 0x0809 - winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies) true %(IgnoreSpecificDefaultLibraries) true @@ -274,7 +274,7 @@ /MP %(AdditionalOptions) Disabled ..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions) + WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug @@ -298,7 +298,7 @@ 0x0809 - winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies) true LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) true diff --git a/projects/openttd_vs140.vcxproj b/projects/openttd_vs140.vcxproj index e4380931a3..01106b71f6 100644 --- a/projects/openttd_vs140.vcxproj +++ b/projects/openttd_vs140.vcxproj @@ -105,7 +105,7 @@ Size true ..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions) + WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions) true Sync MultiThreaded @@ -136,7 +136,7 @@ 0x0809 - winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies) true %(IgnoreSpecificDefaultLibraries) true @@ -170,7 +170,7 @@ Disabled true ..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions) + WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug @@ -192,7 +192,7 @@ 0x0809 - winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies) true LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) true @@ -228,7 +228,7 @@ Size true ..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions) + WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions) true Sync MultiThreaded @@ -259,7 +259,7 @@ 0x0809 - winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies) true %(IgnoreSpecificDefaultLibraries) true @@ -291,7 +291,7 @@ Disabled true ..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions) + WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug @@ -317,7 +317,7 @@ 0x0809 - winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies) true LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) true @@ -502,6 +502,7 @@ + @@ -590,6 +591,8 @@ + + @@ -651,6 +654,7 @@ + @@ -704,6 +708,7 @@ + @@ -751,6 +756,7 @@ + @@ -812,6 +818,7 @@ + @@ -1170,6 +1177,8 @@ + + @@ -1314,12 +1323,15 @@ + + + diff --git a/projects/openttd_vs140.vcxproj.filters b/projects/openttd_vs140.vcxproj.filters index ef11613ff8..911a53a864 100644 --- a/projects/openttd_vs140.vcxproj.filters +++ b/projects/openttd_vs140.vcxproj.filters @@ -600,6 +600,9 @@ Header Files + + Header Files + Header Files @@ -864,6 +867,12 @@ Header Files + + Header Files + + + Header Files + Header Files @@ -1047,6 +1056,9 @@ Header Files + + Header Files + Header Files @@ -1206,6 +1218,9 @@ Header Files + + Header Files + Header Files @@ -1347,6 +1362,9 @@ GUI Source Code + + GUI Source Code + GUI Source Code @@ -1530,6 +1548,9 @@ Widgets + + Widgets + Widgets @@ -2604,6 +2625,12 @@ Blitters + + Blitters + + + Blitters + Blitters @@ -3036,6 +3063,9 @@ Music + + Music + Music @@ -3048,12 +3078,18 @@ Sound + + Sound + Windows files Windows files + + Windows files + Windows files diff --git a/projects/openttd_vs140.vcxproj.in b/projects/openttd_vs140.vcxproj.in index 1e490d29e7..d6ba126b5f 100644 --- a/projects/openttd_vs140.vcxproj.in +++ b/projects/openttd_vs140.vcxproj.in @@ -105,7 +105,7 @@ Size true ..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions) + WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions) true Sync MultiThreaded @@ -136,7 +136,7 @@ 0x0809 - winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies) true %(IgnoreSpecificDefaultLibraries) true @@ -170,7 +170,7 @@ Disabled true ..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions) + WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug @@ -192,7 +192,7 @@ 0x0809 - winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies) true LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) true @@ -228,7 +228,7 @@ Size true ..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions) + WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions) true Sync MultiThreaded @@ -259,7 +259,7 @@ 0x0809 - winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies) true %(IgnoreSpecificDefaultLibraries) true @@ -291,7 +291,7 @@ Disabled true ..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions) + WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug @@ -317,7 +317,7 @@ 0x0809 - winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies) true LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) true diff --git a/projects/openttd_vs141.vcxproj b/projects/openttd_vs141.vcxproj index bba72864b2..ae3d7be78b 100644 --- a/projects/openttd_vs141.vcxproj +++ b/projects/openttd_vs141.vcxproj @@ -105,7 +105,7 @@ Size true ..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions) + WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions) true Sync MultiThreaded @@ -136,7 +136,7 @@ 0x0809 - winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies) true %(IgnoreSpecificDefaultLibraries) true @@ -170,7 +170,7 @@ Disabled true ..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions) + WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug @@ -192,7 +192,7 @@ 0x0809 - winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies) true LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) true @@ -228,7 +228,7 @@ Size true ..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions) + WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions) true Sync MultiThreaded @@ -259,7 +259,7 @@ 0x0809 - winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies) true %(IgnoreSpecificDefaultLibraries) true @@ -291,7 +291,7 @@ Disabled true ..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions) + WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug @@ -317,7 +317,7 @@ 0x0809 - winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies) true LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) true @@ -502,6 +502,7 @@ + @@ -590,6 +591,8 @@ + + @@ -650,6 +653,7 @@ + @@ -703,6 +707,7 @@ + @@ -748,6 +753,7 @@ + @@ -809,6 +815,7 @@ + @@ -1167,6 +1174,8 @@ + + @@ -1311,12 +1320,15 @@ + + + diff --git a/projects/openttd_vs141.vcxproj.filters b/projects/openttd_vs141.vcxproj.filters index d502733796..47f431e556 100644 --- a/projects/openttd_vs141.vcxproj.filters +++ b/projects/openttd_vs141.vcxproj.filters @@ -600,6 +600,9 @@ Header Files + + Header Files + Header Files @@ -864,6 +867,12 @@ Header Files + + Header Files + + + Header Files + Header Files @@ -1044,6 +1053,9 @@ Header Files + + Header Files + Header Files @@ -1203,6 +1215,9 @@ Header Files + + Header Files + Header Files @@ -1338,6 +1353,9 @@ GUI Source Code + + GUI Source Code + GUI Source Code @@ -1521,6 +1539,9 @@ Widgets + + Widgets + Widgets @@ -2595,6 +2616,12 @@ Blitters + + Blitters + + + Blitters + Blitters @@ -3027,6 +3054,9 @@ Music + + Music + Music @@ -3039,12 +3069,18 @@ Sound + + Sound + Windows files Windows files + + Windows files + Windows files diff --git a/projects/openttd_vs141.vcxproj.in b/projects/openttd_vs141.vcxproj.in index f4ec557c60..f231c6264d 100644 --- a/projects/openttd_vs141.vcxproj.in +++ b/projects/openttd_vs141.vcxproj.in @@ -105,7 +105,7 @@ Size true ..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions) + WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions) true Sync MultiThreaded @@ -136,7 +136,7 @@ 0x0809 - winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies) true %(IgnoreSpecificDefaultLibraries) true @@ -170,7 +170,7 @@ Disabled true ..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions) + WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug @@ -192,7 +192,7 @@ 0x0809 - winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies) true LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) true @@ -228,7 +228,7 @@ Size true ..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions) + WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions) true Sync MultiThreaded @@ -259,7 +259,7 @@ 0x0809 - winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies) true %(IgnoreSpecificDefaultLibraries) true @@ -291,7 +291,7 @@ Disabled true ..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions) + WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug @@ -317,7 +317,7 @@ 0x0809 - winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies) true LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) true diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj index aa08062ff3..ada6d84437 100644 --- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -52,7 +52,7 @@ FavorSizeOrSpeed="2" OmitFramePointers="true" AdditionalIncludeDirectories="..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include" - PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR=\"OpenTTD\";WITH_ASSERT" + PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR=\"OpenTTD\";WITH_ASSERT" StringPooling="true" ExceptionHandling="1" RuntimeLibrary="0" @@ -87,7 +87,7 @@ /> + + @@ -1462,6 +1466,14 @@ RelativePath=".\..\src\news_type.h" > + + + + @@ -1706,6 +1718,10 @@ RelativePath=".\..\src\string_type.h" > + + @@ -1918,6 +1934,10 @@ RelativePath=".\..\src\window_type.h" > + + @@ -2114,6 +2134,10 @@ RelativePath=".\..\src\fios_gui.cpp" > + + @@ -2362,6 +2386,10 @@ RelativePath=".\..\src\widgets\fios_widget.h" > + + @@ -3850,6 +3878,14 @@ RelativePath=".\..\src\blitter\32bpp_anim.hpp" > + + + + @@ -4470,6 +4506,10 @@ RelativePath=".\..\src\music\null_m.cpp" > + + @@ -4490,6 +4530,10 @@ RelativePath=".\..\src\sound\win32_s.cpp" > + + + + diff --git a/projects/openttd_vs80.vcproj.in b/projects/openttd_vs80.vcproj.in index 00c330d22f..3363d0d019 100644 --- a/projects/openttd_vs80.vcproj.in +++ b/projects/openttd_vs80.vcproj.in @@ -52,7 +52,7 @@ FavorSizeOrSpeed="2" OmitFramePointers="true" AdditionalIncludeDirectories="..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include" - PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR=\"OpenTTD\";WITH_ASSERT" + PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR=\"OpenTTD\";WITH_ASSERT" StringPooling="true" ExceptionHandling="1" RuntimeLibrary="0" @@ -87,7 +87,7 @@ /> + + @@ -1459,6 +1463,14 @@ RelativePath=".\..\src\news_type.h" > + + + + @@ -1703,6 +1715,10 @@ RelativePath=".\..\src\string_type.h" > + + @@ -1915,6 +1931,10 @@ RelativePath=".\..\src\window_type.h" > + + @@ -2111,6 +2131,10 @@ RelativePath=".\..\src\fios_gui.cpp" > + + @@ -2359,6 +2383,10 @@ RelativePath=".\..\src\widgets\fios_widget.h" > + + @@ -3847,6 +3875,14 @@ RelativePath=".\..\src\blitter\32bpp_anim.hpp" > + + + + @@ -4467,6 +4503,10 @@ RelativePath=".\..\src\music\null_m.cpp" > + + @@ -4487,6 +4527,10 @@ RelativePath=".\..\src\sound\win32_s.cpp" > + + + + diff --git a/projects/openttd_vs90.vcproj.in b/projects/openttd_vs90.vcproj.in index 0ebf4fcbed..b2d3fdeb9c 100644 --- a/projects/openttd_vs90.vcproj.in +++ b/projects/openttd_vs90.vcproj.in @@ -53,7 +53,7 @@ FavorSizeOrSpeed="2" OmitFramePointers="true" AdditionalIncludeDirectories="..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include" - PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR=\"OpenTTD\";WITH_ASSERT" + PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR=\"OpenTTD\";WITH_ASSERT" StringPooling="true" ExceptionHandling="1" RuntimeLibrary="0" @@ -88,7 +88,7 @@ /> 0) StringCat(exptypes,SQString::Create(_ss(this), "|", -1), exptypes); found ++; diff --git a/src/3rdparty/squirrel/squirrel/squtils.h b/src/3rdparty/squirrel/squirrel/squtils.h index 28c6cbec2b..b1138dcb1a 100644 --- a/src/3rdparty/squirrel/squirrel/squtils.h +++ b/src/3rdparty/squirrel/squirrel/squtils.h @@ -90,7 +90,7 @@ public: { _vals[idx].~T(); if(idx < (_size - 1)) { - memmove(&_vals[idx], &_vals[idx+1], sizeof(T) * (_size - (size_t)idx - 1)); + memmove(static_cast(&_vals[idx]), &_vals[idx+1], sizeof(T) * (_size - (size_t)idx - 1)); } _size--; } diff --git a/src/3rdparty/squirrel/squirrel/sqvm.cpp b/src/3rdparty/squirrel/squirrel/sqvm.cpp index c66c4aca59..03ffea2303 100644 --- a/src/3rdparty/squirrel/squirrel/sqvm.cpp +++ b/src/3rdparty/squirrel/squirrel/sqvm.cpp @@ -378,8 +378,7 @@ bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger args,SQIntege } if (!tailcall) { - CallInfo lc; - memset(&lc, 0, sizeof(lc)); + CallInfo lc = {}; lc._generator = NULL; lc._etraps = 0; lc._prevstkbase = (SQInt32) ( stackbase - _stackbase ); @@ -1159,8 +1158,7 @@ bool SQVM::CallNative(SQNativeClosure *nclosure,SQInteger nargs,SQInteger stackb SQInteger oldtop = _top; SQInteger oldstackbase = _stackbase; _top = stackbase + nargs; - CallInfo lci; - memset(&lci, 0, sizeof(lci)); + CallInfo lci = {}; lci._closure = nclosure; lci._generator = NULL; lci._etraps = 0; diff --git a/src/aircraft.h b/src/aircraft.h index f0ca1c4abb..d4deba5809 100644 --- a/src/aircraft.h +++ b/src/aircraft.h @@ -90,7 +90,7 @@ struct Aircraft FINAL : public SpecializedVehicle { virtual ~Aircraft() { this->PreDestructor(); } void MarkDirty(); - void UpdateDeltaXY(Direction direction); + void UpdateDeltaXY(); ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_AIRCRAFT_INC : EXPENSES_AIRCRAFT_RUN; } bool IsPrimaryVehicle() const { return this->IsNormalAircraft(); } void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const; @@ -137,7 +137,7 @@ struct Aircraft FINAL : public SpecializedVehicle { }; /** - * Macro for iterating over all aircrafts. + * Macro for iterating over all aircraft. */ #define FOR_ALL_AIRCRAFT(var) FOR_ALL_VEHICLES_OF_TYPE(Aircraft, var) diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index c9cddbf97d..de8e0ee324 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -37,12 +37,13 @@ #include "core/backup_type.hpp" #include "zoom_func.h" #include "disaster_vehicle.h" +#include "framerate_type.h" #include "table/strings.h" #include "safeguards.h" -void Aircraft::UpdateDeltaXY(Direction direction) +void Aircraft::UpdateDeltaXY() { this->x_offs = -1; this->y_offs = -1; @@ -303,10 +304,10 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, const Engine * u->engine_type = e->index; v->subtype = (avi->subtype & AIR_CTOL ? AIR_AIRCRAFT : AIR_HELICOPTER); - v->UpdateDeltaXY(INVALID_DIR); + v->UpdateDeltaXY(); u->subtype = AIR_SHADOW; - u->UpdateDeltaXY(INVALID_DIR); + u->UpdateDeltaXY(); v->reliability = e->reliability; v->reliability_spd_dec = e->reliability_spd_dec; @@ -363,7 +364,7 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, const Engine * w->random_bits = VehicleRandomBits(); /* Use rotor's air.state to store the rotor animation frame */ w->state = HRS_ROTOR_STOPPED; - w->UpdateDeltaXY(INVALID_DIR); + w->UpdateDeltaXY(); u->SetNext(w); w->UpdatePosition(); @@ -749,7 +750,7 @@ int GetAircraftFlightLevel(T *v, bool takeoff) GetAircraftFlightLevelBounds(v, &aircraft_min_altitude, &aircraft_max_altitude); int aircraft_middle_altitude = (aircraft_min_altitude + aircraft_max_altitude) / 2; - /* If those assumptions would be violated, aircrafts would behave fairly strange. */ + /* If those assumptions would be violated, aircraft would behave fairly strange. */ assert(aircraft_min_altitude < aircraft_middle_altitude); assert(aircraft_middle_altitude < aircraft_max_altitude); @@ -1361,7 +1362,7 @@ static void AircraftEntersTerminal(Aircraft *v) */ static void AircraftLandAirplane(Aircraft *v) { - v->UpdateDeltaXY(INVALID_DIR); + v->UpdateDeltaXY(); if (!PlayVehicleSound(v, VSE_TOUCHDOWN)) { SndPlayVehicleFx(SND_17_SKID_PLANE, v); @@ -1553,7 +1554,7 @@ static void AircraftEventHandler_TakeOff(Aircraft *v, const AirportFTAClass *apc static void AircraftEventHandler_StartTakeOff(Aircraft *v, const AirportFTAClass *apc) { v->state = ENDTAKEOFF; - v->UpdateDeltaXY(INVALID_DIR); + v->UpdateDeltaXY(); } static void AircraftEventHandler_EndTakeOff(Aircraft *v, const AirportFTAClass *apc) @@ -1566,7 +1567,7 @@ static void AircraftEventHandler_EndTakeOff(Aircraft *v, const AirportFTAClass * static void AircraftEventHandler_HeliTakeOff(Aircraft *v, const AirportFTAClass *apc) { v->state = FLYING; - v->UpdateDeltaXY(INVALID_DIR); + v->UpdateDeltaXY(); /* get the next position to go to, differs per airport */ AircraftNextAirportPos_and_Order(v); @@ -1632,7 +1633,7 @@ static void AircraftEventHandler_Landing(Aircraft *v, const AirportFTAClass *apc static void AircraftEventHandler_HeliLanding(Aircraft *v, const AirportFTAClass *apc) { v->state = HELIENDLANDING; - v->UpdateDeltaXY(INVALID_DIR); + v->UpdateDeltaXY(); } static void AircraftEventHandler_EndLanding(Aircraft *v, const AirportFTAClass *apc) @@ -2038,6 +2039,8 @@ bool Aircraft::Tick() { if (!this->IsNormalAircraft()) return true; + PerformanceAccumulator framerate(PFE_GL_AIRCRAFT); + this->tick_counter++; if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++; diff --git a/src/animated_tile.cpp b/src/animated_tile.cpp index 796c5f5e09..2a4cd89583 100644 --- a/src/animated_tile.cpp +++ b/src/animated_tile.cpp @@ -14,6 +14,7 @@ #include "core/smallvec_type.hpp" #include "tile_cmd.h" #include "viewport_func.h" +#include "framerate_type.h" #include "safeguards.h" @@ -50,6 +51,8 @@ void AddAnimatedTile(TileIndex tile) */ void AnimateAnimatedTiles() { + PerformanceAccumulator framerate(PFE_GL_LANDSCAPE); + const TileIndex *ti = _animated_tiles.Begin(); while (ti < _animated_tiles.End()) { const TileIndex curr = *ti; diff --git a/src/articulated_vehicles.cpp b/src/articulated_vehicles.cpp index 04c9f95a97..44ad587895 100644 --- a/src/articulated_vehicles.cpp +++ b/src/articulated_vehicles.cpp @@ -119,12 +119,12 @@ static inline uint16 GetVehicleDefaultCapacity(EngineID engine, CargoID *cargo_t * @param include_initial_cargo_type if true the default cargo type of the vehicle is included; if false only the refit_mask * @return bit set of CargoIDs */ -static inline uint32 GetAvailableVehicleCargoTypes(EngineID engine, bool include_initial_cargo_type) +static inline CargoTypes GetAvailableVehicleCargoTypes(EngineID engine, bool include_initial_cargo_type) { const Engine *e = Engine::Get(engine); if (!e->CanCarryCargo()) return 0; - uint32 cargoes = e->info.refit_mask; + CargoTypes cargoes = e->info.refit_mask; if (include_initial_cargo_type) { SetBit(cargoes, e->GetDefaultCargoType()); @@ -169,7 +169,7 @@ CargoArray GetCapacityOfArticulatedParts(EngineID engine) * @param[out] cargoes Total amount of units that can be transported, summed by cargo. * @param[out] refits Whether a (possibly partial) refit for each cargo is possible. */ -void GetArticulatedVehicleCargoesAndRefits(EngineID engine, CargoArray *cargoes, uint32 *refits) +void GetArticulatedVehicleCargoesAndRefits(EngineID engine, CargoArray *cargoes, CargoTypes *refits) { cargoes->Clear(); *refits = 0; @@ -228,12 +228,12 @@ bool IsArticulatedVehicleRefittable(EngineID engine) * @param union_mask returns bit mask of CargoIDs which are a refit option for at least one articulated part * @param intersection_mask returns bit mask of CargoIDs which are a refit option for every articulated part (with default capacity > 0) */ -void GetArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type, uint32 *union_mask, uint32 *intersection_mask) +void GetArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type, CargoTypes *union_mask, CargoTypes *intersection_mask) { const Engine *e = Engine::Get(engine); - uint32 veh_cargoes = GetAvailableVehicleCargoTypes(engine, include_initial_cargo_type); + CargoTypes veh_cargoes = GetAvailableVehicleCargoTypes(engine, include_initial_cargo_type); *union_mask = veh_cargoes; - *intersection_mask = (veh_cargoes != 0) ? veh_cargoes : UINT32_MAX; + *intersection_mask = (veh_cargoes != 0) ? veh_cargoes : ALL_CARGOTYPES; if (!e->IsGroundVehicle()) return; if (!HasBit(e->info.callback_mask, CBM_VEHICLE_ARTIC_ENGINE)) return; @@ -254,9 +254,9 @@ void GetArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type, * @param include_initial_cargo_type if true the default cargo type of the vehicle is included; if false only the refit_mask * @return bit mask of CargoIDs which are a refit option for at least one articulated part */ -uint32 GetUnionOfArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type) +CargoTypes GetUnionOfArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type) { - uint32 union_mask, intersection_mask; + CargoTypes union_mask, intersection_mask; GetArticulatedRefitMasks(engine, include_initial_cargo_type, &union_mask, &intersection_mask); return union_mask; } @@ -267,9 +267,9 @@ uint32 GetUnionOfArticulatedRefitMasks(EngineID engine, bool include_initial_car * @param include_initial_cargo_type if true the default cargo type of the vehicle is included; if false only the refit_mask * @return bit mask of CargoIDs which are a refit option for every articulated part (with default capacity > 0) */ -uint32 GetIntersectionOfArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type) +CargoTypes GetIntersectionOfArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type) { - uint32 union_mask, intersection_mask; + CargoTypes union_mask, intersection_mask; GetArticulatedRefitMasks(engine, include_initial_cargo_type, &union_mask, &intersection_mask); return intersection_mask; } @@ -314,16 +314,16 @@ void CheckConsistencyOfArticulatedVehicle(const Vehicle *v) { const Engine *engine = v->GetEngine(); - uint32 purchase_refit_union, purchase_refit_intersection; + CargoTypes purchase_refit_union, purchase_refit_intersection; GetArticulatedRefitMasks(v->engine_type, true, &purchase_refit_union, &purchase_refit_intersection); CargoArray purchase_default_capacity = GetCapacityOfArticulatedParts(v->engine_type); - uint32 real_refit_union = 0; - uint32 real_refit_intersection = UINT_MAX; + CargoTypes real_refit_union = 0; + CargoTypes real_refit_intersection = ALL_CARGOTYPES; CargoArray real_default_capacity; do { - uint32 refit_mask = GetAvailableVehicleCargoTypes(v->engine_type, true); + CargoTypes refit_mask = GetAvailableVehicleCargoTypes(v->engine_type, true); real_refit_union |= refit_mask; if (refit_mask != 0) real_refit_intersection &= refit_mask; diff --git a/src/articulated_vehicles.h b/src/articulated_vehicles.h index 46b4da3744..77322fb4c7 100644 --- a/src/articulated_vehicles.h +++ b/src/articulated_vehicles.h @@ -18,9 +18,9 @@ uint CountArticulatedParts(EngineID engine_type, bool purchase_window); CargoArray GetCapacityOfArticulatedParts(EngineID engine); void AddArticulatedParts(Vehicle *first); -void GetArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type, uint32 *union_mask, uint32 *intersection_mask); -uint32 GetUnionOfArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type); -uint32 GetIntersectionOfArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type); +void GetArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type, CargoTypes *union_mask, CargoTypes *intersection_mask); +CargoTypes GetUnionOfArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type); +CargoTypes GetIntersectionOfArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type); bool IsArticulatedVehicleCarryingDifferentCargoes(const Vehicle *v, CargoID *cargo_type); bool IsArticulatedVehicleRefittable(EngineID engine); bool IsArticulatedEngine(EngineID engine_type); diff --git a/src/autoreplace_cmd.cpp b/src/autoreplace_cmd.cpp index e69ac66eb2..96eada7345 100644 --- a/src/autoreplace_cmd.cpp +++ b/src/autoreplace_cmd.cpp @@ -37,8 +37,8 @@ extern void ChangeVehicleViewWindow(VehicleID from_index, VehicleID to_index); */ static bool EnginesHaveCargoInCommon(EngineID engine_a, EngineID engine_b) { - uint32 available_cargoes_a = GetUnionOfArticulatedRefitMasks(engine_a, true); - uint32 available_cargoes_b = GetUnionOfArticulatedRefitMasks(engine_b, true); + CargoTypes available_cargoes_a = GetUnionOfArticulatedRefitMasks(engine_a, true); + CargoTypes available_cargoes_b = GetUnionOfArticulatedRefitMasks(engine_b, true); return (available_cargoes_a == 0 || available_cargoes_b == 0 || (available_cargoes_a & available_cargoes_b) != 0); } @@ -173,9 +173,8 @@ static void TransferCargo(Vehicle *old_veh, Vehicle *new_head, bool part_of_chai */ static bool VerifyAutoreplaceRefitForOrders(const Vehicle *v, EngineID engine_type) { - - uint32 union_refit_mask_a = GetUnionOfArticulatedRefitMasks(v->engine_type, false); - uint32 union_refit_mask_b = GetUnionOfArticulatedRefitMasks(engine_type, false); + CargoTypes union_refit_mask_a = GetUnionOfArticulatedRefitMasks(v->engine_type, false); + CargoTypes union_refit_mask_b = GetUnionOfArticulatedRefitMasks(engine_type, false); const Order *o; const Vehicle *u = (v->type == VEH_TRAIN) ? v->First() : v; @@ -201,7 +200,7 @@ static bool VerifyAutoreplaceRefitForOrders(const Vehicle *v, EngineID engine_ty */ static CargoID GetNewCargoTypeForReplace(Vehicle *v, EngineID engine_type, bool part_of_chain) { - uint32 available_cargo_types, union_mask; + CargoTypes available_cargo_types, union_mask; GetArticulatedRefitMasks(engine_type, true, &union_mask, &available_cargo_types); if (union_mask == 0) return CT_NO_REFIT; // Don't try to refit an engine with no cargo capacity diff --git a/src/base_media_base.h b/src/base_media_base.h index 7614118b7f..b040abcf9d 100644 --- a/src/base_media_base.h +++ b/src/base_media_base.h @@ -26,6 +26,7 @@ struct ContentInfo; struct MD5File { /** The result of a checksum check */ enum ChecksumResult { + CR_UNKNOWN, ///< The file has not been checked yet CR_MATCH, ///< The file did exist and the md5 checksum did match CR_MISMATCH, ///< The file did exist, just the md5 checksum did not match CR_NO_FILE, ///< The file did not exist @@ -34,6 +35,7 @@ struct MD5File { const char *filename; ///< filename uint8 hash[16]; ///< md5 sum of the file const char *missing_warning; ///< warning when this file is missing + ChecksumResult check_result; ///< cached result of md5 check ChecksumResult CheckMD5(Subdirectory subdir, size_t max_size) const; }; @@ -285,11 +287,32 @@ static const uint NUM_SONGS_AVAILABLE = 1 + NUM_SONG_CLASSES * NUM_SONGS_CLASS; /** Maximum number of songs in the (custom) playlist */ static const uint NUM_SONGS_PLAYLIST = 32; +/* Functions to read DOS music CAT files, similar to but not quite the same as sound effect CAT files */ +char *GetMusicCatEntryName(const char *filename, size_t entrynum); +byte *GetMusicCatEntryData(const char *filename, size_t entrynum, size_t &entrylen); + +enum MusicTrackType { + MTT_STANDARDMIDI, ///< Standard MIDI file + MTT_MPSMIDI, ///< MPS GM driver MIDI format (contained in a CAT file) +}; + +/** Metadata about a music track. */ +struct MusicSongInfo { + char songname[32]; ///< name of song displayed in UI + byte tracknr; ///< track number of song displayed in UI + const char *filename; ///< file on disk containing song (when used in MusicSet class, this pointer is owned by MD5File object for the file) + MusicTrackType filetype; ///< decoder required for song file + int cat_index; ///< entry index in CAT file, for filetype==MTT_MPSMIDI + bool loop; ///< song should play in a tight loop if possible, never ending + int override_start; ///< MIDI ticks to skip over in beginning + int override_end; ///< MIDI tick to end the song at (0 if no override) +}; + /** All data of a music set. */ struct MusicSet : BaseSet { - /** The name of the different songs. */ - char song_name[NUM_SONGS_AVAILABLE][32]; - byte track_nr[NUM_SONGS_AVAILABLE]; + /** Data about individual songs in set. */ + MusicSongInfo songinfo[NUM_SONGS_AVAILABLE]; + /** Number of valid songs in set. */ byte num_available; bool FillSetDetails(struct IniFile *ini, const char *path, const char *full_filename); diff --git a/src/base_media_func.h b/src/base_media_func.h index f45956f765..f7afca0edb 100644 --- a/src/base_media_func.h +++ b/src/base_media_func.h @@ -40,8 +40,6 @@ template bool BaseSet::FillSetDetails(IniFile *ini, const char *path, const char *full_filename, bool allow_empty_filename) { - memset(this, 0, sizeof(*this)); - IniGroup *metadata = ini->GetGroup("metadata"); IniItem *item; @@ -129,7 +127,11 @@ bool BaseSet::FillSetDetails(IniFile *ini, const file->missing_warning = stredup(item->value); } - switch (T::CheckMD5(file, BASESET_DIR)) { + file->check_result = T::CheckMD5(file, BASESET_DIR); + switch (file->check_result) { + case MD5File::CR_UNKNOWN: + break; + case MD5File::CR_MATCH: this->valid_files++; this->found_files++; diff --git a/src/base_station_base.h b/src/base_station_base.h index 53e104a826..cd512c5177 100644 --- a/src/base_station_base.h +++ b/src/base_station_base.h @@ -71,7 +71,7 @@ struct BaseStation : StationPool::PoolItem<&_station_pool> { uint16 random_bits; ///< Random bits assigned to this station byte waiting_triggers; ///< Waiting triggers (NewGRF) for this station uint8 cached_anim_triggers; ///< NOSAVE: Combined animation trigger bitmask, used to determine if trigger processing should happen. - uint32 cached_cargo_triggers; ///< NOSAVE: Combined cargo trigger bitmask + CargoTypes cached_cargo_triggers; ///< NOSAVE: Combined cargo trigger bitmask TileArea train_station; ///< Tile area the train 'station' part covers StationRect rect; ///< NOSAVE: Station spread out rectangle maintained by StationRect::xxx() functions diff --git a/src/blitter/32bpp_anim.cpp b/src/blitter/32bpp_anim.cpp index 532ad23cc7..98ae22b00c 100644 --- a/src/blitter/32bpp_anim.cpp +++ b/src/blitter/32bpp_anim.cpp @@ -22,7 +22,7 @@ static FBlitter_32bppAnim iFBlitter_32bppAnim; Blitter_32bppAnim::~Blitter_32bppAnim() { - free(this->anim_buf); + free(this->anim_alloc); } template @@ -39,8 +39,7 @@ inline void Blitter_32bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel } Colour *dst = (Colour *)bp->dst + bp->top * bp->pitch + bp->left; - assert(_screen.pitch == this->anim_buf_pitch); // precondition for translating 'bp->dst' into an 'anim_buf' offset below. - uint16 *anim = this->anim_buf + ((uint32 *)bp->dst - (uint32 *)_screen.dst_ptr) + bp->top * this->anim_buf_pitch + bp->left; + uint16 *anim = this->anim_buf + this->ScreenToAnimOffset((uint32 *)bp->dst) + bp->top * this->anim_buf_pitch + bp->left; const byte *remap = bp->remap; // store so we don't have to access it via bp everytime @@ -280,8 +279,7 @@ void Blitter_32bppAnim::DrawColourMappingRect(void *dst, int width, int height, } Colour *udst = (Colour *)dst; - assert(_screen.pitch == this->anim_buf_pitch); // precondition for translating 'dst' into an 'anim_buf' offset below. - uint16 *anim = this->anim_buf + ((uint32 *)dst - (uint32 *)_screen.dst_ptr); + uint16 *anim = this->anim_buf + this->ScreenToAnimOffset((uint32 *)dst); if (pal == PALETTE_TO_TRANSPARENT) { do { @@ -319,8 +317,8 @@ void Blitter_32bppAnim::SetPixel(void *video, int x, int y, uint8 colour) /* Set the colour in the anim-buffer too, if we are rendering to the screen */ if (_screen_disable_anim) return; - assert(_screen.pitch == this->anim_buf_pitch); // precondition for translating 'video' into an 'anim_buf' offset below. - this->anim_buf[((uint32 *)video - (uint32 *)_screen.dst_ptr) + x + y * this->anim_buf_pitch] = colour | (DEFAULT_BRIGHTNESS << 8); + + this->anim_buf[this->ScreenToAnimOffset((uint32 *)video) + x + y * this->anim_buf_pitch] = colour | (DEFAULT_BRIGHTNESS << 8); } void Blitter_32bppAnim::DrawRect(void *video, int width, int height, uint8 colour) @@ -332,8 +330,7 @@ void Blitter_32bppAnim::DrawRect(void *video, int width, int height, uint8 colou } Colour colour32 = LookupColourInPalette(colour); - assert(_screen.pitch == this->anim_buf_pitch); // precondition for translating 'video' into an 'anim_buf' offset below. - uint16 *anim_line = ((uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf; + uint16 *anim_line = this->ScreenToAnimOffset((uint32 *)video) + this->anim_buf; do { Colour *dst = (Colour *)video; @@ -357,15 +354,14 @@ void Blitter_32bppAnim::CopyFromBuffer(void *video, const void *src, int width, assert(video >= _screen.dst_ptr && video <= (uint32 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch); Colour *dst = (Colour *)video; const uint32 *usrc = (const uint32 *)src; - assert(_screen.pitch == this->anim_buf_pitch); // precondition for translating 'video' into an 'anim_buf' offset below. - uint16 *anim_line = ((uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf; + uint16 *anim_line = this->ScreenToAnimOffset((uint32 *)video) + this->anim_buf; for (; height > 0; height--) { /* We need to keep those for palette animation. */ Colour *dst_pal = dst; uint16 *anim_pal = anim_line; - memcpy(dst, usrc, width * sizeof(uint32)); + memcpy(static_cast(dst), usrc, width * sizeof(uint32)); usrc += width; dst += _screen.pitch; /* Copy back the anim-buffer */ @@ -401,8 +397,7 @@ void Blitter_32bppAnim::CopyToBuffer(const void *video, void *dst, int width, in if (this->anim_buf == NULL) return; - assert(_screen.pitch == this->anim_buf_pitch); // precondition for translating 'video' into an 'anim_buf' offset below. - const uint16 *anim_line = ((const uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf; + const uint16 *anim_line = this->ScreenToAnimOffset((const uint32 *)video) + this->anim_buf; for (; height > 0; height--) { memcpy(udst, src, width * sizeof(uint32)); @@ -485,18 +480,22 @@ void Blitter_32bppAnim::PaletteAnimate(const Palette &palette) Colour *dst = (Colour *)_screen.dst_ptr; /* Let's walk the anim buffer and try to find the pixels */ + const int width = this->anim_buf_width; + const int pitch_offset = _screen.pitch - width; + const int anim_pitch_offset = this->anim_buf_pitch - width; for (int y = this->anim_buf_height; y != 0 ; y--) { - for (int x = this->anim_buf_width; x != 0 ; x--) { - uint colour = GB(*anim, 0, 8); + for (int x = width; x != 0 ; x--) { + uint16 value = *anim; + uint8 colour = GB(value, 0, 8); if (colour >= PALETTE_ANIM_START) { /* Update this pixel */ - *dst = this->AdjustBrightness(LookupColourInPalette(colour), GB(*anim, 8, 8)); + *dst = this->AdjustBrightness(LookupColourInPalette(colour), GB(value, 8, 8)); } dst++; anim++; } - dst += _screen.pitch - this->anim_buf_width; - anim += this->anim_buf_pitch - this->anim_buf_width; + dst += pitch_offset; + anim += anim_pitch_offset; } /* Make sure the backend redraws the whole screen */ @@ -513,10 +512,13 @@ void Blitter_32bppAnim::PostResize() if (_screen.width != this->anim_buf_width || _screen.height != this->anim_buf_height || _screen.pitch != this->anim_buf_pitch) { /* The size of the screen changed; we can assume we can wipe all data from our buffer */ - free(this->anim_buf); + free(this->anim_alloc); this->anim_buf_width = _screen.width; this->anim_buf_height = _screen.height; - this->anim_buf_pitch = _screen.pitch; - this->anim_buf = CallocT(this->anim_buf_height * this->anim_buf_pitch); + this->anim_buf_pitch = (_screen.width + 7) & ~7; + this->anim_alloc = CallocT(this->anim_buf_pitch * this->anim_buf_height + 8); + + /* align buffer to next 16 byte boundary */ + this->anim_buf = reinterpret_cast((reinterpret_cast(this->anim_alloc) + 0xF) & (~0xF)); } } diff --git a/src/blitter/32bpp_anim.hpp b/src/blitter/32bpp_anim.hpp index 1b35c17663..da33ec95bb 100644 --- a/src/blitter/32bpp_anim.hpp +++ b/src/blitter/32bpp_anim.hpp @@ -18,14 +18,16 @@ class Blitter_32bppAnim : public Blitter_32bppOptimized { protected: uint16 *anim_buf; ///< In this buffer we keep track of the 8bpp indexes so we can do palette animation + void *anim_alloc; ///< The raw allocated buffer, not necessarily aligned correctly int anim_buf_width; ///< The width of the animation buffer. int anim_buf_height; ///< The height of the animation buffer. - int anim_buf_pitch; ///< The pitch of the animation buffer. + int anim_buf_pitch; ///< The pitch of the animation buffer (width rounded up to 16 byte boundary). Palette palette; ///< The current palette. public: Blitter_32bppAnim() : anim_buf(NULL), + anim_alloc(NULL), anim_buf_width(0), anim_buf_height(0), anim_buf_pitch(0) @@ -58,6 +60,15 @@ public: return this->palette.palette[index]; } + inline int ScreenToAnimOffset(const uint32 *video) + { + int raw_offset = video - (const uint32 *)_screen.dst_ptr; + if (_screen.pitch == this->anim_buf_pitch) return raw_offset; + int lines = raw_offset / _screen.pitch; + int across = raw_offset % _screen.pitch; + return across + (lines * this->anim_buf_pitch); + } + template void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom); }; diff --git a/src/blitter/32bpp_anim_sse2.cpp b/src/blitter/32bpp_anim_sse2.cpp new file mode 100644 index 0000000000..d5fa4268a8 --- /dev/null +++ b/src/blitter/32bpp_anim_sse2.cpp @@ -0,0 +1,100 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file 32bpp_anim.cpp Implementation of a partially SSSE2 32bpp blitter with animation support. */ + +#ifdef WITH_SSE + +#include "../stdafx.h" +#include "../video/video_driver.hpp" +#include "32bpp_anim_sse2.hpp" +#include "32bpp_sse_func.hpp" + +#include "../safeguards.h" + +/** Instantiation of the partially SSSE2 32bpp with animation blitter factory. */ +static FBlitter_32bppSSE2_Anim iFBlitter_32bppSSE2_Anim; + +void Blitter_32bppSSE2_Anim::PaletteAnimate(const Palette &palette) +{ + assert(!_screen_disable_anim); + + this->palette = palette; + /* If first_dirty is 0, it is for 8bpp indication to send the new + * palette. However, only the animation colours might possibly change. + * Especially when going between toyland and non-toyland. */ + assert(this->palette.first_dirty == PALETTE_ANIM_START || this->palette.first_dirty == 0); + + const uint16 *anim = this->anim_buf; + Colour *dst = (Colour *)_screen.dst_ptr; + + bool screen_dirty = false; + + /* Let's walk the anim buffer and try to find the pixels */ + const int width = this->anim_buf_width; + const int screen_pitch = _screen.pitch; + const int anim_pitch = this->anim_buf_pitch; + __m128i anim_cmp = _mm_set1_epi16(PALETTE_ANIM_START - 1); + __m128i brightness_cmp = _mm_set1_epi16(Blitter_32bppBase::DEFAULT_BRIGHTNESS); + __m128i colour_mask = _mm_set1_epi16(0xFF); + for (int y = this->anim_buf_height; y != 0 ; y--) { + Colour *next_dst_ln = dst + screen_pitch; + const uint16 *next_anim_ln = anim + anim_pitch; + int x = width; + while (x > 0) { + __m128i data = _mm_load_si128((const __m128i *) anim); + + /* low bytes only, shifted into high positions */ + __m128i colour_data = _mm_and_si128(data, colour_mask); + + /* test if any colour >= PALETTE_ANIM_START */ + int colour_cmp_result = _mm_movemask_epi8(_mm_cmpgt_epi16(colour_data, anim_cmp)); + if (colour_cmp_result) { + /* test if any brightness is unexpected */ + if (x < 8 || colour_cmp_result != 0xFFFF || + _mm_movemask_epi8(_mm_cmpeq_epi16(_mm_srli_epi16(data, 8), brightness_cmp)) != 0xFFFF) { + /* slow path: < 8 pixels left or unexpected brightnesses */ + for (int z = min(x, 8); z != 0 ; z--) { + int value = _mm_extract_epi16(data, 0); + uint8 colour = GB(value, 0, 8); + if (colour >= PALETTE_ANIM_START) { + /* Update this pixel */ + *dst = AdjustBrightneSSE(LookupColourInPalette(colour), GB(value, 8, 8)); + screen_dirty = true; + } + data = _mm_srli_si128(data, 2); + dst++; + } + } else { + /* medium path: 8 pixels to animate all of expected brightnesses */ + for (int z = 0; z < 8; z++) { + *dst = LookupColourInPalette(_mm_extract_epi16(colour_data, 0)); + colour_data = _mm_srli_si128(colour_data, 2); + dst++; + } + screen_dirty = true; + } + } else { + /* fast path, no animation */ + dst += 8; + } + anim += 8; + x -= 8; + } + dst = next_dst_ln; + anim = next_anim_ln; + } + + if (screen_dirty) { + /* Make sure the backend redraws the whole screen */ + VideoDriver::GetInstance()->MakeDirty(0, 0, _screen.width, _screen.height); + } +} + +#endif /* WITH_SSE */ diff --git a/src/blitter/32bpp_anim_sse2.hpp b/src/blitter/32bpp_anim_sse2.hpp new file mode 100644 index 0000000000..0d4a5f1e65 --- /dev/null +++ b/src/blitter/32bpp_anim_sse2.hpp @@ -0,0 +1,43 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file 32bpp_anim.hpp A partially SSE2 32 bpp blitter with animation support. */ + +#ifndef BLITTER_32BPP_SSE2_ANIM_HPP +#define BLITTER_32BPP_SSE2_ANIM_HPP + +#ifdef WITH_SSE + +#ifndef SSE_VERSION +#define SSE_VERSION 2 +#endif + +#ifndef FULL_ANIMATION +#define FULL_ANIMATION 1 +#endif + +#include "32bpp_anim.hpp" +#include "32bpp_sse2.hpp" + +/** A partially 32 bpp blitter with palette animation. */ +class Blitter_32bppSSE2_Anim : public Blitter_32bppAnim { +public: + /* virtual */ void PaletteAnimate(const Palette &palette); + /* virtual */ const char *GetName() { return "32bpp-sse2-anim"; } +}; + +/** Factory for the partially 32bpp blitter with animation. */ +class FBlitter_32bppSSE2_Anim : public BlitterFactory { +public: + FBlitter_32bppSSE2_Anim() : BlitterFactory("32bpp-sse2-anim", "32bpp partially SSE2 Animation Blitter (palette animation)", HasCPUIDFlag(1, 3, 26)) {} + /* virtual */ Blitter *CreateInstance() { return new Blitter_32bppSSE2_Anim(); } +}; + +#endif /* WITH_SSE */ +#endif /* BLITTER_32BPP_ANIM_HPP */ diff --git a/src/blitter/32bpp_anim_sse4.cpp b/src/blitter/32bpp_anim_sse4.cpp index 987cb0c6ac..219fb466bb 100644 --- a/src/blitter/32bpp_anim_sse4.cpp +++ b/src/blitter/32bpp_anim_sse4.cpp @@ -35,8 +35,7 @@ inline void Blitter_32bppSSE4_Anim::Draw(const Blitter::BlitterParams *bp, ZoomL { const byte * const remap = bp->remap; Colour *dst_line = (Colour *) bp->dst + bp->top * bp->pitch + bp->left; - assert(_screen.pitch == this->anim_buf_pitch); // precondition for translating 'bp->dst' into an 'anim_buf' offset below. - uint16 *anim_line = this->anim_buf + ((uint32 *)bp->dst - (uint32 *)_screen.dst_ptr) + bp->top * this->anim_buf_pitch + bp->left; + uint16 *anim_line = this->anim_buf + this->ScreenToAnimOffset((uint32 *)bp->dst) + bp->top * this->anim_buf_pitch + bp->left; int effective_width = bp->width; /* Find where to start reading in the source sprite. */ diff --git a/src/blitter/32bpp_anim_sse4.hpp b/src/blitter/32bpp_anim_sse4.hpp index e2d4cfc231..9d9ad5dd92 100644 --- a/src/blitter/32bpp_anim_sse4.hpp +++ b/src/blitter/32bpp_anim_sse4.hpp @@ -23,13 +23,14 @@ #endif #include "32bpp_anim.hpp" +#include "32bpp_anim_sse2.hpp" #include "32bpp_sse4.hpp" #undef MARGIN_NORMAL_THRESHOLD #define MARGIN_NORMAL_THRESHOLD 4 /** The SSE4 32 bpp blitter with palette animation. */ -class Blitter_32bppSSE4_Anim FINAL : public Blitter_32bppAnim, public Blitter_32bppSSE_Base { +class Blitter_32bppSSE4_Anim FINAL : public Blitter_32bppSSE2_Anim, public Blitter_32bppSSE_Base { private: public: diff --git a/src/blitter/32bpp_base.cpp b/src/blitter/32bpp_base.cpp index 26dd2f037e..c396e45410 100644 --- a/src/blitter/32bpp_base.cpp +++ b/src/blitter/32bpp_base.cpp @@ -143,6 +143,36 @@ void Blitter_32bppBase::PaletteAnimate(const Palette &palette) /* By default, 32bpp doesn't have palette animation */ } +Colour Blitter_32bppBase::ReallyAdjustBrightness(Colour colour, uint8 brightness) +{ + assert(DEFAULT_BRIGHTNESS == 1 << 7); + + uint64 combined = (((uint64) colour.r) << 32) | (((uint64) colour.g) << 16) | ((uint64) colour.b); + combined *= brightness; + + uint16 r = GB(combined, 39, 9); + uint16 g = GB(combined, 23, 9); + uint16 b = GB(combined, 7, 9); + + if ((combined & 0x800080008000L) == 0L) { + return Colour(r, g, b, colour.a); + } + + uint16 ob = 0; + /* Sum overbright */ + if (r > 255) ob += r - 255; + if (g > 255) ob += g - 255; + if (b > 255) ob += b - 255; + + /* Reduce overbright strength */ + ob /= 2; + return Colour( + r >= 255 ? 255 : min(r + ob * (255 - r) / 256, 255), + g >= 255 ? 255 : min(g + ob * (255 - g) / 256, 255), + b >= 255 ? 255 : min(b + ob * (255 - b) / 256, 255), + colour.a); +} + Blitter::PaletteAnimation Blitter_32bppBase::UsePaletteAnimation() { return Blitter::PALETTE_ANIMATION_NONE; diff --git a/src/blitter/32bpp_base.hpp b/src/blitter/32bpp_base.hpp index 26c3dee3fd..9b76271704 100644 --- a/src/blitter/32bpp_base.hpp +++ b/src/blitter/32bpp_base.hpp @@ -146,30 +146,14 @@ public: static const int DEFAULT_BRIGHTNESS = 128; + static Colour ReallyAdjustBrightness(Colour colour, uint8 brightness); + static inline Colour AdjustBrightness(Colour colour, uint8 brightness) { /* Shortcut for normal brightness */ if (brightness == DEFAULT_BRIGHTNESS) return colour; - uint16 ob = 0; - uint16 r = colour.r * brightness / DEFAULT_BRIGHTNESS; - uint16 g = colour.g * brightness / DEFAULT_BRIGHTNESS; - uint16 b = colour.b * brightness / DEFAULT_BRIGHTNESS; - - /* Sum overbright */ - if (r > 255) ob += r - 255; - if (g > 255) ob += g - 255; - if (b > 255) ob += b - 255; - - if (ob == 0) return Colour(r, g, b, colour.a); - - /* Reduce overbright strength */ - ob /= 2; - return Colour( - r >= 255 ? 255 : min(r + ob * (255 - r) / 256, 255), - g >= 255 ? 255 : min(g + ob * (255 - g) / 256, 255), - b >= 255 ? 255 : min(b + ob * (255 - b) / 256, 255), - colour.a); + return ReallyAdjustBrightness(colour, brightness); } }; diff --git a/src/bridge_gui.cpp b/src/bridge_gui.cpp index 797ead1f51..768691f080 100644 --- a/src/bridge_gui.cpp +++ b/src/bridge_gui.cpp @@ -55,7 +55,7 @@ typedef GUIList GUIBridgeList; ///< List of bridges, used in #B * @param p1 packed start tile coords (~ dx) * @param p2 various bitstuffed elements * - p2 = (bit 0- 7) - bridge type (hi bh) - * - p2 = (bit 8-11) - rail type or road types. + * - p2 = (bit 8-13) - rail type or road types. * - p2 = (bit 15-16) - transport type. */ void CcBuildBridge(const CommandCost &result, TileIndex end_tile, uint32 p1, uint32 p2) diff --git a/src/bridge_map.h b/src/bridge_map.h index 74c6974db2..75b20498d1 100644 --- a/src/bridge_map.h +++ b/src/bridge_map.h @@ -131,11 +131,12 @@ static inline void MakeBridgeRamp(TileIndex t, Owner o, BridgeType bridgetype, D SetTileType(t, MP_TUNNELBRIDGE); SetTileOwner(t, o); _m[t].m2 = 0; - _m[t].m3 = rt; + _m[t].m3 = 0; _m[t].m4 = 0; _m[t].m5 = 1 << 7 | tt << 2 | d; SB(_me[t].m6, 2, 4, bridgetype); _me[t].m7 = 0; + _me[t].m8 = rt; } /** diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index 655a18d7f8..51247e84ba 100644 --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -524,7 +524,7 @@ const StringID _engine_sort_listing[][12] = {{ static bool CDECL CargoFilter(const EngineID *eid, const CargoID cid) { if (cid == CF_ANY) return true; - uint32 refit_mask = GetUnionOfArticulatedRefitMasks(*eid, true) & _standard_cargo_mask; + CargoTypes refit_mask = GetUnionOfArticulatedRefitMasks(*eid, true) & _standard_cargo_mask; return (cid == CF_NONE ? refit_mask == 0 : HasBit(refit_mask, cid)); } @@ -535,7 +535,7 @@ static GUIEngineList::FilterFunction * const _filter_funcs[] = { static int DrawCargoCapacityInfo(int left, int right, int y, EngineID engine) { CargoArray cap; - uint32 refits; + CargoTypes refits; GetArticulatedVehicleCargoesAndRefits(engine, &cap, &refits); for (CargoID c = 0; c < NUM_CARGO; c++) { diff --git a/src/cargo_type.h b/src/cargo_type.h index 7b7168a102..1eca0edff6 100644 --- a/src/cargo_type.h +++ b/src/cargo_type.h @@ -22,7 +22,7 @@ typedef byte CargoID; /** Available types of cargo */ -enum CargoTypes { +enum CargoType { /* Temperate */ CT_PASSENGERS = 0, CT_COAL = 1, @@ -63,13 +63,17 @@ enum CargoTypes { CT_PLASTIC = 10, CT_FIZZY_DRINKS = 11, - NUM_CARGO = 32, ///< Maximal number of cargo types in a game. + NUM_CARGO = 64, ///< Maximal number of cargo types in a game. CT_AUTO_REFIT = 0xFD, ///< Automatically choose cargo type when doing auto refitting. CT_NO_REFIT = 0xFE, ///< Do not refit cargo of a vehicle (used in vehicle orders and auto-replace/auto-new). CT_INVALID = 0xFF, ///< Invalid cargo type. }; +typedef uint64 CargoTypes; + +static const CargoTypes ALL_CARGOTYPES = (CargoTypes)UINT64_MAX; + /** Class for storing amounts of cargo */ struct CargoArray { private: diff --git a/src/cargotype.cpp b/src/cargotype.cpp index 863c585616..6cc02f63a3 100644 --- a/src/cargotype.cpp +++ b/src/cargotype.cpp @@ -28,12 +28,12 @@ CargoSpec CargoSpec::array[NUM_CARGO]; * Bitmask of cargo types available. This includes phony cargoes like regearing cargoes. * Initialized during a call to #SetupCargoForClimate. */ -uint32 _cargo_mask; +CargoTypes _cargo_mask; /** * Bitmask of real cargo types available. Phony cargoes like regearing cargoes are excluded. */ -uint32 _standard_cargo_mask; +CargoTypes _standard_cargo_mask; /** * Set up the default cargo types for the given landscape type. diff --git a/src/cargotype.h b/src/cargotype.h index fee461d7fb..71cd932bbf 100644 --- a/src/cargotype.h +++ b/src/cargotype.h @@ -129,8 +129,8 @@ private: friend void SetupCargoForClimate(LandscapeID l); }; -extern uint32 _cargo_mask; -extern uint32 _standard_cargo_mask; +extern CargoTypes _cargo_mask; +extern CargoTypes _standard_cargo_mask; void SetupCargoForClimate(LandscapeID l); CargoID GetCargoIDByLabel(CargoLabel cl); @@ -156,7 +156,7 @@ static inline bool IsCargoInClass(CargoID c, CargoClass cc) if ((var = CargoSpec::Get(cargospec_index))->IsValid()) #define FOR_ALL_CARGOSPECS(var) FOR_ALL_CARGOSPECS_FROM(var, 0) -#define FOR_EACH_SET_CARGO_ID(var, cargo_bits) FOR_EACH_SET_BIT_EX(CargoID, var, uint, cargo_bits) +#define FOR_EACH_SET_CARGO_ID(var, cargo_bits) FOR_EACH_SET_BIT_EX(CargoID, var, CargoTypes, cargo_bits) /** * Loop header for iterating over cargoes, sorted by name. This includes phony cargoes like regearing cargoes. diff --git a/src/company_base.h b/src/company_base.h index 4d76e6251a..1bc4b7f83c 100644 --- a/src/company_base.h +++ b/src/company_base.h @@ -67,8 +67,6 @@ struct CompanyProperties { byte colour; ///< Company colour. - RailTypes avail_railtypes; ///< Rail types available to the company. - byte block_preview; ///< Number of quarters that the company is not allowed to get new exclusive engine previews (see CompaniesGenStatistics). TileIndex location_of_HQ; ///< Northern tile of HQ; #INVALID_TILE when there is none. @@ -98,7 +96,13 @@ struct CompanyProperties { CompanyEconomyEntry old_economy[MAX_HISTORY_QUARTERS]; ///< Economic data of the company of the last #MAX_HISTORY_QUARTERS quarters. byte num_valid_stat_ent; ///< Number of valid statistical entries in #old_economy. - CompanyProperties() : name(NULL), president_name(NULL) {} + // TODO: Change some of these member variables to use relevant INVALID_xxx constants + CompanyProperties() + : name_2(0), name_1(0), name(NULL), president_name_1(0), president_name_2(0), president_name(NULL), + face(0), money(0), money_fraction(0), current_loan(0), colour(0), block_preview(0), + location_of_HQ(0), last_build_coordinate(0), share_owners(), inaugurated_year(0), + months_of_bankruptcy(0), bankrupt_asked(0), bankrupt_timeout(0), bankrupt_value(0), + terraform_limit(0), clear_limit(0), tree_limit(0), is_ai(false) {} ~CompanyProperties() { @@ -112,6 +116,7 @@ struct Company : CompanyPool::PoolItem<&_company_pool>, CompanyProperties { ~Company(); Livery livery[LS_END]; + RailTypes avail_railtypes; ///< Rail types available to this company. RoadTypes avail_roadtypes; ///< Road types available to this company. class AIInstance *ai_instance; diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 68ef036c13..8e95c6355b 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -1908,6 +1908,37 @@ static void IConsoleDebugLibRegister() } #endif +DEF_CONSOLE_CMD(ConFramerate) +{ + extern void ConPrintFramerate(); // framerate_gui.cpp + + if (argc == 0) { + IConsoleHelp("Show frame rate and game speed information"); + return true; + } + + ConPrintFramerate(); + return true; +} + +DEF_CONSOLE_CMD(ConFramerateWindow) +{ + extern void ShowFramerateWindow(); + + if (argc == 0) { + IConsoleHelp("Open the frame rate window"); + return true; + } + + if (_network_dedicated) { + IConsoleError("Can not open frame rate window on a dedicated server"); + return false; + } + + ShowFramerateWindow(); + return true; +} + /******************************* * console command registration *******************************/ @@ -2038,6 +2069,9 @@ void IConsoleStdLibRegister() #ifdef _DEBUG IConsoleDebugLibRegister(); #endif + IConsoleCmdRegister("fps", ConFramerate); + IConsoleCmdRegister("fps_wnd", ConFramerateWindow); + IConsoleCmdRegister("dump_command_log", ConDumpCommandLog, nullptr, true); /* NewGRF development stuff */ diff --git a/src/core/alloc_func.hpp b/src/core/alloc_func.hpp index c7e17421f7..c33e733016 100644 --- a/src/core/alloc_func.hpp +++ b/src/core/alloc_func.hpp @@ -125,7 +125,7 @@ static inline T *ReallocT(T *t_ptr, size_t num_elements) /* Ensure the size does not overflow. */ CheckAllocationConstraints(num_elements); - t_ptr = (T*)realloc(t_ptr, num_elements * sizeof(T)); + t_ptr = (T*)realloc(static_cast(t_ptr), num_elements * sizeof(T)); if (t_ptr == NULL) ReallocError(num_elements * sizeof(T)); return t_ptr; } diff --git a/src/core/backup_type.hpp b/src/core/backup_type.hpp index 60799170f7..7e3771b70f 100644 --- a/src/core/backup_type.hpp +++ b/src/core/backup_type.hpp @@ -53,7 +53,7 @@ struct Backup { { /* We cannot assert here, as missing restoration is 'normal' when exceptions are thrown. * Exceptions are especially used to abort world generation. */ - DEBUG(misc, 0, "%s:%d: Backupped value was not restored!", this->file, this->line); + DEBUG(misc, 0, "%s:%d: Backed-up value was not restored!", this->file, this->line); this->Restore(); } } diff --git a/src/core/endian_type.hpp b/src/core/endian_type.hpp index dbb7faec66..453bf5402c 100644 --- a/src/core/endian_type.hpp +++ b/src/core/endian_type.hpp @@ -27,14 +27,21 @@ /* Windows has always LITTLE_ENDIAN */ #if defined(WIN32) || defined(__OS2__) || defined(WIN64) - #define TTD_ENDIAN TTD_LITTLE_ENDIAN +# define TTD_ENDIAN TTD_LITTLE_ENDIAN +#elif defined(OSX) +# include +# if __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN +# define TTD_ENDIAN TTD_LITTLE_ENDIAN +# else +# define TTD_ENDIAN TTD_BIG_ENDIAN +# endif #elif !defined(TESTING) - /* Else include endian[target/host].h, which has the endian-type, autodetected by the Makefile */ - #if defined(STRGEN) || defined(SETTINGSGEN) - #include "endian_host.h" - #else - #include "endian_target.h" - #endif +# include +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define TTD_ENDIAN TTD_LITTLE_ENDIAN +# else +# define TTD_ENDIAN TTD_BIG_ENDIAN +# endif #endif /* WIN32 || __OS2__ || WIN64 */ #endif /* ENDIAN_TYPE_HPP */ diff --git a/src/cpu.cpp b/src/cpu.cpp index c48b8cbd4d..9393ea0613 100644 --- a/src/cpu.cpp +++ b/src/cpu.cpp @@ -18,7 +18,7 @@ /* rdtsc for MSC_VER, uses simple inline assembly, or _rdtsc * from external win64.asm because VS2005 does not support inline assembly */ -#if defined(_MSC_VER) && !defined(RDTSC_AVAILABLE) && !defined(WINCE) +#if defined(_MSC_VER) && !defined(RDTSC_AVAILABLE) #include uint64 ottd_rdtsc() { @@ -71,10 +71,7 @@ uint64 ottd_rdtsc() /* In all other cases we have no support for rdtsc. No major issue, * you just won't be able to profile your code with TIC()/TOC() */ #if !defined(RDTSC_AVAILABLE) -/* MSVC (in case of WinCE) can't handle #warning */ -# if !defined(_MSC_VER) #warning "(non-fatal) No support for rdtsc(), you won't be able to profile with TIC/TOC" -# endif uint64 ottd_rdtsc() {return 0;} #endif diff --git a/src/debug.cpp b/src/debug.cpp index 1846152254..f8f3f0ad56 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -17,6 +17,10 @@ #include "fileio_func.h" #include "settings_type.h" +#if defined(WIN32) || defined(WIN64) +#include "os/windows/win32.h" +#endif + #include #if defined(ENABLE_NETWORK) @@ -135,10 +139,10 @@ static void debug_print(const char *dbg, const char *buf) } else { char buffer[512]; seprintf(buffer, lastof(buffer), "%sdbg: [%s] %s\n", GetLogPrefix(), dbg, buf); -#if defined(WINCE) - NKDbgPrintfW(OTTD2FS(buffer)); -#elif defined(WIN32) || defined(WIN64) - _fputts(OTTD2FS(buffer, true), stderr); +#if defined(WIN32) || defined(WIN64) + TCHAR system_buf[512]; + convert_to_fs(buffer, system_buf, lengthof(system_buf), true); + _fputts(system_buf, stderr); #else fputs(buffer, stderr); #endif diff --git a/src/disaster_vehicle.cpp b/src/disaster_vehicle.cpp index 98978ddfb0..64ebcd3fa1 100644 --- a/src/disaster_vehicle.cpp +++ b/src/disaster_vehicle.cpp @@ -164,7 +164,7 @@ DisasterVehicle::DisasterVehicle(int x, int y, Direction direction, DisasterSubT this->direction = direction; this->tile = TileVirtXY(x, y); this->subtype = subtype; - this->UpdateDeltaXY(INVALID_DIR); + this->UpdateDeltaXY(); this->owner = OWNER_NONE; this->image_override = 0; this->current_order.Free(); @@ -973,7 +973,7 @@ void ReleaseDisastersTargetingVehicle(VehicleID vehicle) } } -void DisasterVehicle::UpdateDeltaXY(Direction direction) +void DisasterVehicle::UpdateDeltaXY() { this->x_offs = -1; this->y_offs = -1; diff --git a/src/disaster_vehicle.h b/src/disaster_vehicle.h index 06fb36c1e3..e86d96e97d 100644 --- a/src/disaster_vehicle.h +++ b/src/disaster_vehicle.h @@ -48,7 +48,7 @@ struct DisasterVehicle FINAL : public SpecializedVehicleold_economy[1], &c->old_economy[0], sizeof(c->old_economy) - sizeof(c->old_economy[0])); + /* Drop the oldest history off the end */ + std::copy_backward(c->old_economy, c->old_economy + MAX_HISTORY_QUARTERS - 1, c->old_economy + MAX_HISTORY_QUARTERS); c->old_economy[0] = c->cur_economy; - memset(&c->cur_economy, 0, sizeof(c->cur_economy)); + c->cur_economy = {}; if (c->num_valid_stat_ent != MAX_HISTORY_QUARTERS) c->num_valid_stat_ent++; @@ -1366,14 +1367,14 @@ struct IsEmptyAction struct PrepareRefitAction { CargoArray &consist_capleft; ///< Capacities left in the consist. - uint32 &refit_mask; ///< Bitmask of possible refit cargoes. + CargoTypes &refit_mask; ///< Bitmask of possible refit cargoes. /** * Create a refit preparation action. * @param consist_capleft Capacities left in consist, to be updated here. * @param refit_mask Refit mask to be constructed from refit information of vehicles. */ - PrepareRefitAction(CargoArray &consist_capleft, uint32 &refit_mask) : + PrepareRefitAction(CargoArray &consist_capleft, CargoTypes &refit_mask) : consist_capleft(consist_capleft), refit_mask(refit_mask) {} /** @@ -1469,7 +1470,7 @@ static void HandleStationRefit(Vehicle *v, CargoArray &consist_capleft, Station Backup cur_company(_current_company, v->owner, FILE_LINE); - uint32 refit_mask = v->GetEngine()->info.refit_mask; + CargoTypes refit_mask = v->GetEngine()->info.refit_mask; /* Remove old capacity from consist capacity and collect refit mask. */ IterateVehicleParts(v_start, PrepareRefitAction(consist_capleft, refit_mask)); @@ -1627,10 +1628,10 @@ static void LoadUnloadVehicle(Vehicle *front) bool completely_emptied = true; bool anything_unloaded = false; bool anything_loaded = false; - uint32 full_load_amount = 0; - uint32 cargo_not_full = 0; - uint32 cargo_full = 0; - uint32 reservation_left = 0; + CargoTypes full_load_amount = 0; + CargoTypes cargo_not_full = 0; + CargoTypes cargo_full = 0; + CargoTypes reservation_left = 0; front->cur_speed = 0; @@ -1838,7 +1839,7 @@ static void LoadUnloadVehicle(Vehicle *front) /* if the aircraft carries passengers and is NOT full, then * continue loading, no matter how much mail is in */ if ((front->type == VEH_AIRCRAFT && IsCargoInClass(front->cargo_type, CC_PASSENGERS) && front->cargo_cap > front->cargo.StoredCount()) || - (cargo_not_full && (cargo_full & ~cargo_not_full) == 0)) { // There are still non-full cargoes + (cargo_not_full != 0 && (cargo_full & ~cargo_not_full) == 0)) { // There are still non-full cargoes finished_loading = false; } } else if (cargo_not_full != 0) { diff --git a/src/economy_type.h b/src/economy_type.h index 7e7a572413..31f74aacc7 100644 --- a/src/economy_type.h +++ b/src/economy_type.h @@ -152,12 +152,12 @@ enum ExpensesType { EXPENSES_NEW_VEHICLES, ///< New vehicles. EXPENSES_TRAIN_RUN, ///< Running costs trains. EXPENSES_ROADVEH_RUN, ///< Running costs road vehicles. - EXPENSES_AIRCRAFT_RUN, ///< Running costs aircrafts. + EXPENSES_AIRCRAFT_RUN, ///< Running costs aircraft. EXPENSES_SHIP_RUN, ///< Running costs ships. EXPENSES_PROPERTY, ///< Property costs. EXPENSES_TRAIN_INC, ///< Income from trains. EXPENSES_ROADVEH_INC, ///< Income from road vehicles. - EXPENSES_AIRCRAFT_INC, ///< Income from aircrafts. + EXPENSES_AIRCRAFT_INC, ///< Income from aircraft. EXPENSES_SHIP_INC, ///< Income from ships. EXPENSES_LOAN_INT, ///< Interest payments over the loan. EXPENSES_OTHER, ///< Other expenses. diff --git a/src/effectvehicle.cpp b/src/effectvehicle.cpp index 5921cd190e..4d8f58acb8 100644 --- a/src/effectvehicle.cpp +++ b/src/effectvehicle.cpp @@ -603,7 +603,7 @@ EffectVehicle *CreateEffectVehicle(int x, int y, int z, EffectVehicleType type) v->y_pos = y; v->z_pos = z; v->tile = 0; - v->UpdateDeltaXY(INVALID_DIR); + v->UpdateDeltaXY(); v->vehstatus = VS_UNCLICKABLE; _effect_init_procs[type](v); @@ -647,7 +647,7 @@ bool EffectVehicle::Tick() return _effect_tick_procs[this->subtype](this); } -void EffectVehicle::UpdateDeltaXY(Direction direction) +void EffectVehicle::UpdateDeltaXY() { this->x_offs = 0; this->y_offs = 0; diff --git a/src/effectvehicle_base.h b/src/effectvehicle_base.h index 27da420017..d809657fab 100644 --- a/src/effectvehicle_base.h +++ b/src/effectvehicle_base.h @@ -32,7 +32,7 @@ struct EffectVehicle FINAL : public SpecializedVehicle. - */ - -/** - * @file endian_check.cpp - * This pretty simple file checks if the system is LITTLE_ENDIAN or BIG_ENDIAN - * it does that by putting a 1 and a 0 in an array, and read it out as one - * number. If it is 1, it is LITTLE_ENDIAN, if it is 256, it is BIG_ENDIAN - * - * After that it outputs the contents of an include files (endian.h) - * that says or TTD_LITTLE_ENDIAN, or TTD_BIG_ENDIAN. Makefile takes - * care of the real writing to the file. - */ - -#include -#include - -/** Supported endian types */ -enum Endian { - ENDIAN_LITTLE, ///< little endian - ENDIAN_BIG, ///< big endian -}; - -/** - * Shortcut to printf("#define TTD_ENDIAN TTD_*_ENDIAN") - * @param endian endian type to define - */ -static inline void printf_endian(Endian endian) -{ - printf("#define TTD_ENDIAN %s\n", endian == ENDIAN_LITTLE ? "TTD_LITTLE_ENDIAN" : "TTD_BIG_ENDIAN"); -} - -/** - * Main call of the endian_check program - * @param argc argument count - * @param argv arguments themselves - * @return exit code - */ -int main (int argc, char *argv[]) -{ - unsigned char endian_test[2] = { 1, 0 }; - int force_BE = 0, force_LE = 0, force_PREPROCESSOR = 0; - - if (argc > 1 && strcmp(argv[1], "BE") == 0) force_BE = 1; - if (argc > 1 && strcmp(argv[1], "LE") == 0) force_LE = 1; - if (argc > 1 && strcmp(argv[1], "PREPROCESSOR") == 0) force_PREPROCESSOR = 1; - - printf("#ifndef ENDIAN_H\n#define ENDIAN_H\n"); - - if (force_LE == 1) { - printf_endian(ENDIAN_LITTLE); - } else if (force_BE == 1) { - printf_endian(ENDIAN_BIG); - } else if (force_PREPROCESSOR == 1) { - /* Support for universal binaries on OSX - * Universal binaries supports both PPC and x86 - * If a compiler for OSX gets this setting, it will always pick the correct endian and no test is needed - */ - printf("#ifdef __BIG_ENDIAN__\n"); - printf_endian(ENDIAN_BIG); - printf("#else\n"); - printf_endian(ENDIAN_LITTLE); - printf("#endif\n"); - } else if (*(short*)endian_test == 1 ) { - printf_endian(ENDIAN_LITTLE); - } else { - printf_endian(ENDIAN_BIG); - } - printf("#endif\n"); - - return 0; -} diff --git a/src/engine.cpp b/src/engine.cpp index b0af3bc4df..ac2e8df0ec 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -752,7 +752,7 @@ static CompanyID GetPreviewCompany(Engine *e) CompanyID best_company = INVALID_COMPANY; /* For trains the cargomask has no useful meaning, since you can attach other wagons */ - uint32 cargomask = e->type != VEH_TRAIN ? GetUnionOfArticulatedRefitMasks(e->index, true) : (uint32)-1; + CargoTypes cargomask = e->type != VEH_TRAIN ? GetUnionOfArticulatedRefitMasks(e->index, true) : ALL_CARGOTYPES; int32 best_hist = -1; const Company *c; @@ -1117,7 +1117,9 @@ bool IsEngineRefittable(EngineID engine) /* Is there any cargo except the default cargo? */ CargoID default_cargo = e->GetDefaultCargoType(); - return default_cargo != CT_INVALID && ei->refit_mask != 1U << default_cargo; + CargoTypes default_cargo_mask = 0; + SetBit(default_cargo_mask, default_cargo); + return default_cargo != CT_INVALID && ei->refit_mask != default_cargo_mask; } /** diff --git a/src/engine_func.h b/src/engine_func.h index 6c3fb14ff2..37fb005092 100644 --- a/src/engine_func.h +++ b/src/engine_func.h @@ -26,7 +26,7 @@ extern const uint8 _engine_offsets[4]; bool IsEngineBuildable(EngineID engine, VehicleType type, CompanyID company); bool IsEngineRefittable(EngineID engine); -void GetArticulatedVehicleCargoesAndRefits(EngineID engine, CargoArray *cargoes, uint32 *refits); +void GetArticulatedVehicleCargoesAndRefits(EngineID engine, CargoArray *cargoes, CargoTypes *refits); void SetYearEngineAgingStops(); void StartupOneEngine(Engine *e, Date aging_date); diff --git a/src/engine_type.h b/src/engine_type.h index 8356fda8f8..82f10d9d87 100644 --- a/src/engine_type.h +++ b/src/engine_type.h @@ -137,7 +137,7 @@ struct EngineInfo { byte load_amount; byte climates; ///< Climates supported by the engine. CargoID cargo_type; - uint32 refit_mask; + CargoTypes refit_mask; byte refit_cost; byte misc_flags; ///< Miscellaneous flags. @see EngineMiscFlags byte callback_mask; ///< Bitmask of vehicle callbacks that have to be called diff --git a/src/fileio.cpp b/src/fileio.cpp index 0590efd3a7..3ad5be711d 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -325,15 +325,7 @@ bool FioCheckFileExists(const char *filename, Subdirectory subdir) */ bool FileExists(const char *filename) { -#if defined(WINCE) - /* There is always one platform that doesn't support basic commands... */ - HANDLE hand = CreateFile(OTTD2FS(filename), 0, 0, NULL, OPEN_EXISTING, 0, NULL); - if (hand == INVALID_HANDLE_VALUE) return 1; - CloseHandle(hand); - return 0; -#else return access(OTTD2FS(filename), 0) == 0; -#endif } /** @@ -540,11 +532,11 @@ FILE *FioFOpenFile(const char *filename, const char *mode, Subdirectory subdir, * Create a directory with the given name * @param name the new name of the directory */ -static void FioCreateDirectory(const char *name) +void FioCreateDirectory(const char *name) { /* Ignore directory creation errors; they'll surface later on, and most * of the time they are 'directory already exists' errors anyhow. */ -#if defined(WIN32) || defined(WINCE) +#if defined(WIN32) CreateDirectory(OTTD2FS(name), NULL); #elif defined(OS2) && !defined(__INNOTEK_LIBC__) mkdir(OTTD2FS(name)); @@ -988,14 +980,14 @@ bool ExtractTar(const char *tar_filename, Subdirectory subdir) return true; } -#if defined(WIN32) || defined(WINCE) +#if defined(WIN32) /** * Determine the base (personal dir and game data dir) paths * @param exe the path from the current path to the executable * @note defined in the OS related files (os2.cpp, win32.cpp, unix.cpp etc) */ extern void DetermineBasePaths(const char *exe); -#else /* defined(WIN32) || defined(WINCE) */ +#else /* defined(WIN32) */ /** * Changes the working directory to the path of the give executable. @@ -1158,7 +1150,7 @@ extern void cocoaSetApplicationBundleDir(); _searchpaths[SP_APPLICATION_BUNDLE_DIR] = NULL; #endif } -#endif /* defined(WIN32) || defined(WINCE) */ +#endif /* defined(WIN32) */ const char *_personal_dir; diff --git a/src/fileio_func.h b/src/fileio_func.h index 443460b2d3..6383180744 100644 --- a/src/fileio_func.h +++ b/src/fileio_func.h @@ -55,6 +55,7 @@ char *FioGetFullPath(char *buf, const char *last, Searchpath sp, Subdirectory su char *FioFindFullPath(char *buf, const char *last, Subdirectory subdir, const char *filename); char *FioAppendDirectory(char *buf, const char *last, Searchpath sp, Subdirectory subdir); char *FioGetDirectory(char *buf, const char *last, Subdirectory subdir); +void FioCreateDirectory(const char *name); const char *FiosGetScreenshotDir(); @@ -149,4 +150,17 @@ static inline DIR *ttd_opendir(const char *path) return opendir(OTTD2FS(path)); } + +/** Auto-close a file upon scope exit. */ +class FileCloser { + FILE *f; + +public: + FileCloser(FILE *_f) : f(_f) {} + ~FileCloser() + { + fclose(f); + } +}; + #endif /* FILEIO_FUNC_H */ diff --git a/src/fios.cpp b/src/fios.cpp index 5e78fb1b4d..f4a25e1ed2 100644 --- a/src/fios.cpp +++ b/src/fios.cpp @@ -153,9 +153,7 @@ const char *FiosBrowseTo(const FiosItem *item) { switch (item->type) { case FIOS_TYPE_DRIVE: -#if defined(WINCE) - seprintf(_fios_path, _fios_path_last, PATHSEP ""); -#elif defined(WIN32) || defined(__OS2__) +#if defined(WIN32) || defined(__OS2__) seprintf(_fios_path, _fios_path_last, "%c:" PATHSEP, item->title[0]); #endif break; diff --git a/src/fontcache.cpp b/src/fontcache.cpp index 72e42ccbb3..3a5dd886c1 100644 --- a/src/fontcache.cpp +++ b/src/fontcache.cpp @@ -86,6 +86,7 @@ public: virtual GlyphID MapCharToGlyph(WChar key) { assert(IsPrintable(key)); return SPRITE_GLYPH | key; } virtual const void *GetFontTable(uint32 tag, size_t &length) { length = 0; return NULL; } virtual const char *GetFontName() { return "sprite"; } + virtual bool IsBuiltInFont() { return true; } }; /** @@ -208,6 +209,7 @@ bool SpriteFontCache::GetDrawGlyphShadow() class FreeTypeFontCache : public FontCache { private: FT_Face face; ///< The font face associated with this font. + int req_size; ///< Requested font size. typedef SmallMap > FontTable; ///< Table with font table cache FontTable font_tables; ///< Cached font tables. @@ -236,6 +238,7 @@ private: GlyphEntry *GetGlyphPtr(GlyphID key); void SetGlyphPtr(GlyphID key, const GlyphEntry *glyph, bool duplicate = false); + void SetFontSize(FontSize fs, FT_Face face, int pixels); public: FreeTypeFontCache(FontSize fs, FT_Face face, int pixels); @@ -250,6 +253,7 @@ public: virtual GlyphID MapCharToGlyph(WChar key); virtual const void *GetFontTable(uint32 tag, size_t &length); virtual const char *GetFontName() { return face->family_name; } + virtual bool IsBuiltInFont() { return false; } }; FT_Library _library = NULL; @@ -265,20 +269,26 @@ static const byte SHADOW_COLOUR = 2; * @param face The font that has to be loaded. * @param pixels The number of pixels this font should be high. */ -FreeTypeFontCache::FreeTypeFontCache(FontSize fs, FT_Face face, int pixels) : FontCache(fs), face(face), glyph_to_sprite(NULL) +FreeTypeFontCache::FreeTypeFontCache(FontSize fs, FT_Face face, int pixels) : FontCache(fs), face(face), req_size(pixels), glyph_to_sprite(NULL) { assert(face != NULL); + this->SetFontSize(fs, face, pixels); +} + +void FreeTypeFontCache::SetFontSize(FontSize fs, FT_Face face, int pixels) +{ if (pixels == 0) { /* Try to determine a good height based on the minimal height recommended by the font. */ - pixels = _default_font_height[this->fs]; + int scaled_height = ScaleGUITrad(_default_font_height[this->fs]); + pixels = scaled_height; TT_Header *head = (TT_Header *)FT_Get_Sfnt_Table(this->face, ft_sfnt_head); if (head != NULL) { /* Font height is minimum height plus the difference between the default * height for this font size and the small size. */ - int diff = _default_font_height[this->fs] - _default_font_height[FS_SMALL]; - pixels = Clamp(min(head->Lowest_Rec_PPEM, 20) + diff, _default_font_height[this->fs], MAX_FONT_SIZE); + int diff = scaled_height - ScaleGUITrad(_default_font_height[FS_SMALL]); + pixels = Clamp(min(head->Lowest_Rec_PPEM, 20) + diff, scaled_height, MAX_FONT_SIZE); } } @@ -393,6 +403,7 @@ found_face: FreeTypeFontCache::~FreeTypeFontCache() { FT_Done_Face(this->face); + this->face = NULL; this->ClearFontCache(); for (FontTable::iterator iter = this->font_tables.Begin(); iter != this->font_tables.End(); iter++) { @@ -422,6 +433,9 @@ void FreeTypeFontCache::ClearFontCache() this->glyph_to_sprite = NULL; Layouter::ResetFontCache(this->fs); + + /* GUI scaling might have changed, determine font size anew if it was automatically selected. */ + if (this->face != NULL && this->req_size == 0) this->SetFontSize(this->fs, this->face, this->req_size); } FreeTypeFontCache::GlyphEntry *FreeTypeFontCache::GetGlyphPtr(GlyphID key) diff --git a/src/fontcache.h b/src/fontcache.h index 8caf4f1bd3..8d66ed3667 100644 --- a/src/fontcache.h +++ b/src/fontcache.h @@ -143,6 +143,11 @@ public: { return this->parent != NULL; } + + /** + * Is this a built-in sprite font? + */ + virtual bool IsBuiltInFont() = 0; }; /** Get the SpriteID mapped to the given font size and key */ diff --git a/src/framerate_gui.cpp b/src/framerate_gui.cpp new file mode 100644 index 0000000000..021958d323 --- /dev/null +++ b/src/framerate_gui.cpp @@ -0,0 +1,823 @@ +/* $Id$ */ + +/* +* This file is part of OpenTTD. +* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. +* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . +*/ + +/** @file framerate_gui.cpp GUI for displaying framerate/game speed information. */ + +#include "framerate_type.h" +#include +#include "gfx_func.h" +#include "window_gui.h" +#include "table/sprites.h" +#include "strings_func.h" +#include "debug.h" +#include "console_func.h" +#include "console_type.h" + +#include "widgets/framerate_widget.h" + + +namespace { + + /** Number of data points to keep in buffer for each performance measurement */ + const int NUM_FRAMERATE_POINTS = 512; + /** Units a second is divided into in performance measurements */ + const TimingMeasurement TIMESTAMP_PRECISION = 1000000; + + struct PerformanceData { + /** Duration value indicating the value is not valid should be considered a gap in measurements */ + static const TimingMeasurement INVALID_DURATION = UINT64_MAX; + + /** Time spent processing each cycle of the performance element, circular buffer */ + TimingMeasurement durations[NUM_FRAMERATE_POINTS]; + /** Start time of each cycle of the performance element, circular buffer */ + TimingMeasurement timestamps[NUM_FRAMERATE_POINTS]; + /** Expected number of cycles per second when the system is running without slowdowns */ + double expected_rate; + /** Next index to write to in \c durations and \c timestamps */ + int next_index; + /** Last index written to in \c durations and \c timestamps */ + int prev_index; + /** Number of data points recorded, clamped to \c NUM_FRAMERATE_POINTS */ + int num_valid; + + /** Current accumulated duration */ + TimingMeasurement acc_duration; + /** Start time for current accumulation cycle */ + TimingMeasurement acc_timestamp; + + explicit PerformanceData(double expected_rate) : expected_rate(expected_rate), next_index(0), prev_index(0), num_valid(0) { } + + void Add(TimingMeasurement start_time, TimingMeasurement end_time) + { + this->durations[this->next_index] = end_time - start_time; + this->timestamps[this->next_index] = start_time; + this->prev_index = this->next_index; + this->next_index += 1; + if (this->next_index >= NUM_FRAMERATE_POINTS) this->next_index = 0; + this->num_valid = min(NUM_FRAMERATE_POINTS, this->num_valid + 1); + } + + void BeginAccumulate(TimingMeasurement start_time) + { + this->timestamps[this->next_index] = this->acc_timestamp; + this->durations[this->next_index] = this->acc_duration; + this->prev_index = this->next_index; + this->next_index += 1; + if (this->next_index >= NUM_FRAMERATE_POINTS) this->next_index = 0; + this->num_valid = min(NUM_FRAMERATE_POINTS, this->num_valid + 1); + + this->acc_duration = 0; + this->acc_timestamp = start_time; + } + + void AddAccumulate(TimingMeasurement duration) + { + this->acc_duration += duration; + } + + void AddPause(TimingMeasurement start_time) + { + if (this->durations[this->prev_index] != INVALID_DURATION) { + this->timestamps[this->next_index] = start_time; + this->durations[this->next_index] = INVALID_DURATION; + this->prev_index = this->next_index; + this->next_index += 1; + if (this->next_index >= NUM_FRAMERATE_POINTS) this->next_index = 0; + this->num_valid += 1; + } + } + + /** Get average cycle processing time over a number of data points */ + double GetAverageDurationMilliseconds(int count) + { + count = min(count, this->num_valid); + + int first_point = this->prev_index - count; + if (first_point < 0) first_point += NUM_FRAMERATE_POINTS; + + /* Sum durations, skipping invalid points */ + double sumtime = 0; + for (int i = first_point; i < first_point + count; i++) { + auto d = this->durations[i % NUM_FRAMERATE_POINTS]; + if (d != INVALID_DURATION) { + sumtime += d; + } else { + /* Don't count the invalid durations */ + count--; + } + } + + if (count == 0) return 0; // avoid div by zero + return sumtime * 1000 / count / TIMESTAMP_PRECISION; + } + + /** Get current rate of a performance element, based on approximately the past one second of data */ + double GetRate() + { + /* Start at last recorded point, end at latest when reaching the earliest recorded point */ + int point = this->prev_index; + int last_point = this->next_index - this->num_valid; + if (last_point < 0) last_point += NUM_FRAMERATE_POINTS; + + /** Number of data points collected */ + int count = 0; + /** Time of previous data point */ + TimingMeasurement last = this->timestamps[point]; + /** Total duration covered by collected points */ + TimingMeasurement total = 0; + + while (point != last_point) { + /* Only record valid data points, but pretend the gaps in measurements aren't there */ + if (this->durations[point] != INVALID_DURATION) { + total += last - this->timestamps[point]; + count++; + } + last = this->timestamps[point]; + if (total >= TIMESTAMP_PRECISION) break; // end after 1 second has been collected + point--; + if (point < 0) point = NUM_FRAMERATE_POINTS - 1; + } + + if (total == 0 || count == 0) return 0; + return (double)count * TIMESTAMP_PRECISION / total; + } + }; + + /** Game loop rate, cycles per second */ + static const double GL_RATE = 1000.0 / MILLISECONDS_PER_TICK; + + PerformanceData _pf_data[PFE_MAX] = { + PerformanceData(GL_RATE), // PFE_GAMELOOP + PerformanceData(1), // PFE_ACC_GL_ECONOMY + PerformanceData(1), // PFE_ACC_GL_TRAINS + PerformanceData(1), // PFE_ACC_GL_ROADVEHS + PerformanceData(1), // PFE_ACC_GL_SHIPS + PerformanceData(1), // PFE_ACC_GL_AIRCRAFT + PerformanceData(1), // PFE_GL_LANDSCAPE + PerformanceData(1), // PFE_GL_LINKGRAPH + PerformanceData(GL_RATE), // PFE_DRAWING + PerformanceData(1), // PFE_ACC_DRAWWORLD + PerformanceData(60.0), // PFE_VIDEO + PerformanceData(1000.0 * 8192 / 44100), // PFE_SOUND + }; + +} + + +/** + * Return a timestamp with \c TIMESTAMP_PRECISION ticks per second precision. + * The basis of the timestamp is implementation defined, but the value should be steady, + * so differences can be taken to reliably measure intervals. + */ +static TimingMeasurement GetPerformanceTimer() +{ + using namespace std::chrono; + return (TimingMeasurement)time_point_cast(high_resolution_clock::now()).time_since_epoch().count(); +} + + +/** Begin a cycle of a measured element. */ +PerformanceMeasurer::PerformanceMeasurer(PerformanceElement elem) +{ + assert(elem < PFE_MAX); + + this->elem = elem; + this->start_time = GetPerformanceTimer(); +} + +/** Finish a cycle of a measured element and store the measurement taken. */ +PerformanceMeasurer::~PerformanceMeasurer() +{ + _pf_data[this->elem].Add(this->start_time, GetPerformanceTimer()); +} + +/** Set the rate of expected cycles per second of a performance element. */ +void PerformanceMeasurer::SetExpectedRate(double rate) +{ + _pf_data[this->elem].expected_rate = rate; +} + +/** Indicate that a cycle of "pause" where no processing occurs. */ +void PerformanceMeasurer::Paused(PerformanceElement elem) +{ + _pf_data[elem].AddPause(GetPerformanceTimer()); +} + + +/** Begin measuring one block of the accumulating value. */ +PerformanceAccumulator::PerformanceAccumulator(PerformanceElement elem) +{ + assert(elem < PFE_MAX); + + this->elem = elem; + this->start_time = GetPerformanceTimer(); +} + +/** Finish and add one block of the accumulating value. */ +PerformanceAccumulator::~PerformanceAccumulator() +{ + _pf_data[this->elem].AddAccumulate(GetPerformanceTimer() - this->start_time); +} + +/** Store the previous accumulator value and reset for a new cycle of accumulating measurements. */ +void PerformanceAccumulator::Reset(PerformanceElement elem) +{ + _pf_data[elem].BeginAccumulate(GetPerformanceTimer()); +} + + +void ShowFrametimeGraphWindow(PerformanceElement elem); + + +static const NWidgetPart _framerate_window_widgets[] = { + NWidget(NWID_HORIZONTAL), + NWidget(WWT_CLOSEBOX, COLOUR_GREY), + NWidget(WWT_CAPTION, COLOUR_GREY, WID_FRW_CAPTION), SetDataTip(STR_FRAMERATE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), + NWidget(WWT_SHADEBOX, COLOUR_GREY), + NWidget(WWT_STICKYBOX, COLOUR_GREY), + EndContainer(), + NWidget(WWT_PANEL, COLOUR_GREY), + NWidget(NWID_VERTICAL), SetPadding(6), SetPIP(0, 3, 0), + NWidget(WWT_TEXT, COLOUR_GREY, WID_FRW_RATE_GAMELOOP), SetDataTip(STR_FRAMERATE_RATE_GAMELOOP, STR_FRAMERATE_RATE_GAMELOOP_TOOLTIP), + NWidget(WWT_TEXT, COLOUR_GREY, WID_FRW_RATE_DRAWING), SetDataTip(STR_FRAMERATE_RATE_BLITTER, STR_FRAMERATE_RATE_BLITTER_TOOLTIP), + NWidget(WWT_TEXT, COLOUR_GREY, WID_FRW_RATE_FACTOR), SetDataTip(STR_FRAMERATE_SPEED_FACTOR, STR_FRAMERATE_SPEED_FACTOR_TOOLTIP), + EndContainer(), + EndContainer(), + NWidget(WWT_PANEL, COLOUR_GREY), + NWidget(NWID_VERTICAL), SetPadding(6), SetPIP(0, 3, 0), + NWidget(NWID_HORIZONTAL), SetPIP(0, 6, 0), + NWidget(WWT_EMPTY, COLOUR_GREY, WID_FRW_TIMES_NAMES), + NWidget(WWT_EMPTY, COLOUR_GREY, WID_FRW_TIMES_CURRENT), + NWidget(WWT_EMPTY, COLOUR_GREY, WID_FRW_TIMES_AVERAGE), + EndContainer(), + NWidget(WWT_TEXT, COLOUR_GREY, WID_FRW_INFO_DATA_POINTS), SetDataTip(STR_FRAMERATE_DATA_POINTS, 0x0), + EndContainer(), + EndContainer(), +}; + +struct FramerateWindow : Window { + bool small; + uint32 next_update; + + struct CachedDecimal { + StringID strid; + uint32 value; + + inline void SetRate(double value, double target) + { + const double threshold_good = target * 0.95; + const double threshold_bad = target * 2 / 3; + value = min(9999.99, value); + this->value = (uint32)(value * 100); + this->strid = (value > threshold_good) ? STR_FRAMERATE_FPS_GOOD : (value < threshold_bad) ? STR_FRAMERATE_FPS_BAD : STR_FRAMERATE_FPS_WARN; + } + + inline void SetTime(double value, double target) + { + const double threshold_good = target / 3; + const double threshold_bad = target; + value = min(9999.99, value); + this->value = (uint32)(value * 100); + this->strid = (value < threshold_good) ? STR_FRAMERATE_MS_GOOD : (value > threshold_bad) ? STR_FRAMERATE_MS_BAD : STR_FRAMERATE_MS_WARN; + } + + inline void InsertDParams(uint n) const + { + SetDParam(n, this->value); + SetDParam(n + 1, 2); + } + }; + + CachedDecimal rate_gameloop; ///< cached game loop tick rate + CachedDecimal rate_drawing; ///< cached drawing frame rate + CachedDecimal speed_gameloop; ///< cached game loop speed factor + CachedDecimal times_shortterm[PFE_MAX]; ///< cached short term average times + CachedDecimal times_longterm[PFE_MAX]; ///< cached long term average times + + static const int VSPACING = 3; ///< space between column heading and values + + FramerateWindow(WindowDesc *desc, WindowNumber number) : Window(desc) + { + this->InitNested(number); + this->small = this->IsShaded(); + this->UpdateData(); + } + + virtual void OnTick() + { + /* Check if the shaded state has changed, switch caption text if it has */ + if (this->small != this->IsShaded()) { + this->small = this->IsShaded(); + this->GetWidget(WID_FRW_CAPTION)->SetDataTip(this->small ? STR_FRAMERATE_CAPTION_SMALL : STR_FRAMERATE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS); + this->next_update = 0; + } + + if (_realtime_tick >= this->next_update) { + this->UpdateData(); + this->SetDirty(); + this->next_update = _realtime_tick + 100; + } + } + + void UpdateData() + { + double gl_rate = _pf_data[PFE_GAMELOOP].GetRate(); + this->rate_gameloop.SetRate(gl_rate, _pf_data[PFE_GAMELOOP].expected_rate); + this->speed_gameloop.SetRate(gl_rate / _pf_data[PFE_GAMELOOP].expected_rate, 1.0); + if (this->small) return; // in small mode, this is everything needed + + this->rate_drawing.SetRate(_pf_data[PFE_DRAWING].GetRate(), _pf_data[PFE_DRAWING].expected_rate); + + for (PerformanceElement e = PFE_FIRST; e < PFE_MAX; e++) { + this->times_shortterm[e].SetTime(_pf_data[e].GetAverageDurationMilliseconds(8), MILLISECONDS_PER_TICK); + this->times_longterm[e].SetTime(_pf_data[e].GetAverageDurationMilliseconds(NUM_FRAMERATE_POINTS), MILLISECONDS_PER_TICK); + } + } + + virtual void SetStringParameters(int widget) const + { + switch (widget) { + case WID_FRW_CAPTION: + /* When the window is shaded, the caption shows game loop rate and speed factor */ + if (!this->small) break; + SetDParam(0, this->rate_gameloop.strid); + this->rate_gameloop.InsertDParams(1); + this->speed_gameloop.InsertDParams(3); + break; + + case WID_FRW_RATE_GAMELOOP: + SetDParam(0, this->rate_gameloop.strid); + this->rate_gameloop.InsertDParams(1); + break; + case WID_FRW_RATE_DRAWING: + SetDParam(0, this->rate_drawing.strid); + this->rate_drawing.InsertDParams(1); + break; + case WID_FRW_RATE_FACTOR: + this->speed_gameloop.InsertDParams(0); + break; + case WID_FRW_INFO_DATA_POINTS: + SetDParam(0, NUM_FRAMERATE_POINTS); + break; + } + } + + virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) + { + switch (widget) { + case WID_FRW_RATE_GAMELOOP: + SetDParam(0, STR_FRAMERATE_FPS_GOOD); + SetDParam(1, 999999); + SetDParam(2, 2); + *size = GetStringBoundingBox(STR_FRAMERATE_RATE_GAMELOOP); + break; + case WID_FRW_RATE_DRAWING: + SetDParam(0, STR_FRAMERATE_FPS_GOOD); + SetDParam(1, 999999); + SetDParam(2, 2); + *size = GetStringBoundingBox(STR_FRAMERATE_RATE_BLITTER); + break; + case WID_FRW_RATE_FACTOR: + SetDParam(0, 999999); + SetDParam(1, 2); + *size = GetStringBoundingBox(STR_FRAMERATE_SPEED_FACTOR); + break; + + case WID_FRW_TIMES_NAMES: { + int linecount = PFE_MAX - PFE_FIRST; + size->width = 0; + size->height = FONT_HEIGHT_NORMAL * (linecount + 1) + VSPACING; + for (int line = 0; line < linecount; line++) { + Dimension line_size = GetStringBoundingBox(STR_FRAMERATE_GAMELOOP + line); + size->width = max(size->width, line_size.width); + } + break; + } + + case WID_FRW_TIMES_CURRENT: + case WID_FRW_TIMES_AVERAGE: { + int linecount = PFE_MAX - PFE_FIRST; + *size = GetStringBoundingBox(STR_FRAMERATE_CURRENT + (widget - WID_FRW_TIMES_CURRENT)); + SetDParam(0, 999999); + SetDParam(1, 2); + Dimension item_size = GetStringBoundingBox(STR_FRAMERATE_MS_GOOD); + size->width = max(size->width, item_size.width); + size->height += FONT_HEIGHT_NORMAL * linecount + VSPACING; + break; + } + } + } + + /** Render a column of formatted average durations */ + void DrawElementTimesColumn(const Rect &r, StringID heading_str, const CachedDecimal *values) const + { + int y = r.top; + DrawString(r.left, r.right, y, heading_str, TC_FROMSTRING, SA_CENTER); + y += FONT_HEIGHT_NORMAL + VSPACING; + + for (PerformanceElement e = PFE_FIRST; e < PFE_MAX; e++) { + values[e].InsertDParams(0); + DrawString(r.left, r.right, y, values[e].strid, TC_FROMSTRING, SA_RIGHT); + y += FONT_HEIGHT_NORMAL; + } + } + + virtual void DrawWidget(const Rect &r, int widget) const + { + switch (widget) { + case WID_FRW_TIMES_NAMES: { + /* Render a column of titles for performance element names */ + int linecount = PFE_MAX - PFE_FIRST; + int y = r.top + FONT_HEIGHT_NORMAL + VSPACING; // first line contains headings in the value columns + for (int i = 0; i < linecount; i++) { + DrawString(r.left, r.right, y, STR_FRAMERATE_GAMELOOP + i, TC_FROMSTRING, SA_LEFT); + y += FONT_HEIGHT_NORMAL; + } + break; + } + case WID_FRW_TIMES_CURRENT: + /* Render short-term average values */ + DrawElementTimesColumn(r, STR_FRAMERATE_CURRENT, this->times_shortterm); + break; + case WID_FRW_TIMES_AVERAGE: + /* Render averages of all recorded values */ + DrawElementTimesColumn(r, STR_FRAMERATE_AVERAGE, this->times_longterm); + break; + } + } + + virtual void OnClick(Point pt, int widget, int click_count) + { + switch (widget) { + case WID_FRW_TIMES_NAMES: + case WID_FRW_TIMES_CURRENT: + case WID_FRW_TIMES_AVERAGE: { + /* Open time graph windows when clicking detail measurement lines */ + int line = this->GetRowFromWidget(pt.y, widget, VSPACING, FONT_HEIGHT_NORMAL); + if (line > 0) { + line -= 1; + ShowFrametimeGraphWindow((PerformanceElement)line); + } + break; + } + } + } +}; + +static WindowDesc _framerate_display_desc( + WDP_AUTO, "framerate_display", 60, 40, + WC_FRAMERATE_DISPLAY, WC_NONE, + 0, + _framerate_window_widgets, lengthof(_framerate_window_widgets) +); + + +static const NWidgetPart _frametime_graph_window_widgets[] = { + NWidget(NWID_HORIZONTAL), + NWidget(WWT_CLOSEBOX, COLOUR_GREY), + NWidget(WWT_CAPTION, COLOUR_GREY, WID_FGW_CAPTION), SetDataTip(STR_WHITE_STRING, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), + NWidget(WWT_STICKYBOX, COLOUR_GREY), + EndContainer(), + NWidget(WWT_PANEL, COLOUR_GREY), + NWidget(NWID_VERTICAL), SetPadding(6), + NWidget(WWT_EMPTY, COLOUR_GREY, WID_FGW_GRAPH), + EndContainer(), + EndContainer(), +}; + +struct FrametimeGraphWindow : Window { + int vertical_scale; ///< number of TIMESTAMP_PRECISION units vertically + int horizontal_scale; ///< number of half-second units horizontally + uint32 next_scale_update; ///< realtime tick for next scale update + + PerformanceElement element; ///< what element this window renders graph for + Dimension graph_size; ///< size of the main graph area (excluding axis labels) + + FrametimeGraphWindow(WindowDesc *desc, WindowNumber number) : Window(desc) + { + this->element = (PerformanceElement)number; + this->horizontal_scale = 4; + this->vertical_scale = TIMESTAMP_PRECISION / 10; + this->next_scale_update = 0; + + this->InitNested(number); + } + + virtual void SetStringParameters(int widget) const + { + switch (widget) { + case WID_FGW_CAPTION: + SetDParam(0, STR_FRAMETIME_CAPTION_GAMELOOP + this->element); + break; + } + } + + virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) + { + if (widget == WID_FGW_GRAPH) { + SetDParam(0, 100); + Dimension size_ms_label = GetStringBoundingBox(STR_FRAMERATE_GRAPH_MILLISECONDS); + SetDParam(0, 100); + Dimension size_s_label = GetStringBoundingBox(STR_FRAMERATE_GRAPH_SECONDS); + + /* Size graph in height to fit at least 10 vertical labels with space between, or at least 100 pixels */ + graph_size.height = max(100, 10 * (size_ms_label.height + 1)); + /* Always 2:1 graph area */ + graph_size.width = 2 * graph_size.height; + *size = graph_size; + + size->width += size_ms_label.width + 2; + size->height += size_s_label.height + 2; + } + } + + void SelectHorizontalScale(TimingMeasurement range) + { + /* Determine horizontal scale based on period covered by 60 points + * (slightly less than 2 seconds at full game speed) */ + struct ScaleDef { TimingMeasurement range; int scale; }; + static const ScaleDef hscales[] = { + { 120, 60 }, + { 10, 20 }, + { 5, 10 }, + { 3, 4 }, + { 1, 2 }, + }; + for (const ScaleDef *sc = hscales; sc < hscales + lengthof(hscales); sc++) { + if (range < sc->range) this->horizontal_scale = sc->scale; + } + } + + void SelectVerticalScale(TimingMeasurement range) + { + /* Determine vertical scale based on peak value (within the horizontal scale + a bit) */ + static const TimingMeasurement vscales[] = { + TIMESTAMP_PRECISION * 100, + TIMESTAMP_PRECISION * 10, + TIMESTAMP_PRECISION * 5, + TIMESTAMP_PRECISION, + TIMESTAMP_PRECISION / 2, + TIMESTAMP_PRECISION / 5, + TIMESTAMP_PRECISION / 10, + TIMESTAMP_PRECISION / 50, + TIMESTAMP_PRECISION / 200, + }; + for (const TimingMeasurement *sc = vscales; sc < vscales + lengthof(vscales); sc++) { + if (range < *sc) this->vertical_scale = (int)*sc; + } + } + + /** Recalculate the graph scaling factors based on current recorded data */ + void UpdateScale() + { + const TimingMeasurement *durations = _pf_data[this->element].durations; + const TimingMeasurement *timestamps = _pf_data[this->element].timestamps; + int num_valid = _pf_data[this->element].num_valid; + int point = _pf_data[this->element].prev_index; + + TimingMeasurement lastts = timestamps[point]; + TimingMeasurement time_sum = 0; + TimingMeasurement peak_value = 0; + int count = 0; + + /* Sensible default for when too few measurements are available */ + this->horizontal_scale = 4; + + for (int i = 1; i < num_valid; i++) { + point--; + if (point < 0) point = NUM_FRAMERATE_POINTS - 1; + + TimingMeasurement value = durations[point]; + if (value == PerformanceData::INVALID_DURATION) { + /* Skip gaps in data by pretending time is continuous across them */ + lastts = timestamps[point]; + continue; + } + if (value > peak_value) peak_value = value; + count++; + + /* Accumulate period of time covered by data */ + time_sum += lastts - timestamps[point]; + lastts = timestamps[point]; + + /* Enough data to select a range and get decent data density */ + if (count == 60) this->SelectHorizontalScale(time_sum / TIMESTAMP_PRECISION); + + /* End when enough points have been collected and the horizontal scale has been exceeded */ + if (count >= 60 && time_sum >= (this->horizontal_scale + 2) * TIMESTAMP_PRECISION / 2) break; + } + + this->SelectVerticalScale(peak_value); + } + + virtual void OnTick() + { + this->SetDirty(); + + if (this->next_scale_update < _realtime_tick) { + this->next_scale_update = _realtime_tick + 500; + this->UpdateScale(); + } + } + + /** Scale and interpolate a value from a source range into a destination range */ + template + static inline T Scinterlate(T dst_min, T dst_max, T src_min, T src_max, T value) + { + T dst_diff = dst_max - dst_min; + T src_diff = src_max - src_min; + return (value - src_min) * dst_diff / src_diff + dst_min; + } + + virtual void DrawWidget(const Rect &r, int widget) const + { + if (widget == WID_FGW_GRAPH) { + const TimingMeasurement *durations = _pf_data[this->element].durations; + const TimingMeasurement *timestamps = _pf_data[this->element].timestamps; + int point = _pf_data[this->element].prev_index; + + const int x_zero = r.right - (int)this->graph_size.width; + const int x_max = r.right; + const int y_zero = r.top + (int)this->graph_size.height; + const int y_max = r.top; + const int c_grid = PC_DARK_GREY; + const int c_lines = PC_BLACK; + const int c_peak = PC_DARK_RED; + + const TimingMeasurement draw_horz_scale = (TimingMeasurement)this->horizontal_scale * TIMESTAMP_PRECISION / 2; + const TimingMeasurement draw_vert_scale = (TimingMeasurement)this->vertical_scale; + + /* Number of \c horizontal_scale units in each horizontal division */ + const uint horz_div_scl = (this->horizontal_scale <= 20) ? 1 : 10; + /* Number of divisions of the horizontal axis */ + const uint horz_divisions = this->horizontal_scale / horz_div_scl; + /* Number of divisions of the vertical axis */ + const uint vert_divisions = 10; + + /* Draw division lines and labels for the vertical axis */ + for (uint division = 0; division < vert_divisions; division++) { + int y = Scinterlate(y_zero, y_max, 0, (int)vert_divisions, (int)division); + GfxDrawLine(x_zero, y, x_max, y, c_grid); + if (division % 2 == 0) { + if ((TimingMeasurement)this->vertical_scale > TIMESTAMP_PRECISION) { + SetDParam(0, this->vertical_scale * division / 10 / TIMESTAMP_PRECISION); + DrawString(r.left, x_zero - 2, y - FONT_HEIGHT_SMALL, STR_FRAMERATE_GRAPH_SECONDS, TC_GREY, SA_RIGHT | SA_FORCE, false, FS_SMALL); + } else { + SetDParam(0, this->vertical_scale * division / 10 * 1000 / TIMESTAMP_PRECISION); + DrawString(r.left, x_zero - 2, y - FONT_HEIGHT_SMALL, STR_FRAMERATE_GRAPH_MILLISECONDS, TC_GREY, SA_RIGHT | SA_FORCE, false, FS_SMALL); + } + } + } + /* Draw divison lines and labels for the horizontal axis */ + for (uint division = horz_divisions; division > 0; division--) { + int x = Scinterlate(x_zero, x_max, 0, (int)horz_divisions, (int)horz_divisions - (int)division); + GfxDrawLine(x, y_max, x, y_zero, c_grid); + if (division % 2 == 0) { + SetDParam(0, division * horz_div_scl / 2); + DrawString(x, x_max, y_zero + 2, STR_FRAMERATE_GRAPH_SECONDS, TC_GREY, SA_LEFT | SA_FORCE, false, FS_SMALL); + } + } + + /* Position of last rendered data point */ + Point lastpoint = { + x_max, + (int)Scinterlate(y_zero, y_max, 0, this->vertical_scale, durations[point]) + }; + /* Timestamp of last rendered data point */ + TimingMeasurement lastts = timestamps[point]; + + TimingMeasurement peak_value = 0; + Point peak_point = { 0, 0 }; + TimingMeasurement value_sum = 0; + TimingMeasurement time_sum = 0; + int points_drawn = 0; + + for (int i = 1; i < NUM_FRAMERATE_POINTS; i++) { + point--; + if (point < 0) point = NUM_FRAMERATE_POINTS - 1; + + TimingMeasurement value = durations[point]; + if (value == PerformanceData::INVALID_DURATION) { + /* Skip gaps in measurements, pretend the data points on each side are continuous */ + lastts = timestamps[point]; + continue; + } + + /* Use total time period covered for value along horizontal axis */ + time_sum += lastts - timestamps[point]; + lastts = timestamps[point]; + /* Stop if past the width of the graph */ + if (time_sum > draw_horz_scale) break; + + /* Draw line from previous point to new point */ + Point newpoint = { + (int)Scinterlate(x_zero, x_max, 0, (int64)draw_horz_scale, (int64)draw_horz_scale - (int64)time_sum), + (int)Scinterlate(y_zero, y_max, 0, (int64)draw_vert_scale, (int64)value) + }; + assert(newpoint.x <= lastpoint.x); + GfxDrawLine(lastpoint.x, lastpoint.y, newpoint.x, newpoint.y, c_lines); + lastpoint = newpoint; + + /* Record peak and average value across graphed data */ + value_sum += value; + points_drawn++; + if (value > peak_value) { + peak_value = value; + peak_point = newpoint; + } + } + + /* If the peak value is significantly larger than the average, mark and label it */ + if (points_drawn > 0 && peak_value > TIMESTAMP_PRECISION / 100 && 2 * peak_value > 3 * value_sum / points_drawn) { + TextColour tc_peak = (TextColour)(TC_IS_PALETTE_COLOUR | c_peak); + GfxFillRect(peak_point.x - 1, peak_point.y - 1, peak_point.x + 1, peak_point.y + 1, c_peak); + SetDParam(0, peak_value * 1000 / TIMESTAMP_PRECISION); + int label_y = max(y_max, peak_point.y - FONT_HEIGHT_SMALL); + if (peak_point.x - x_zero > (int)this->graph_size.width / 2) { + DrawString(x_zero, peak_point.x - 2, label_y, STR_FRAMERATE_GRAPH_MILLISECONDS, tc_peak, SA_RIGHT | SA_FORCE, false, FS_SMALL); + } else { + DrawString(peak_point.x + 2, x_max, label_y, STR_FRAMERATE_GRAPH_MILLISECONDS, tc_peak, SA_LEFT | SA_FORCE, false, FS_SMALL); + } + } + } + } +}; + +static WindowDesc _frametime_graph_window_desc( + WDP_AUTO, "frametime_graph", 140, 90, + WC_FRAMETIME_GRAPH, WC_NONE, + 0, + _frametime_graph_window_widgets, lengthof(_frametime_graph_window_widgets) +); + + + +void ShowFramerateWindow() +{ + AllocateWindowDescFront(&_framerate_display_desc, 0); +} + +void ShowFrametimeGraphWindow(PerformanceElement elem) +{ + if (elem < PFE_FIRST || elem >= PFE_MAX) return; // maybe warn? + AllocateWindowDescFront(&_frametime_graph_window_desc, elem, true); +} + +void ConPrintFramerate() +{ + const int count1 = NUM_FRAMERATE_POINTS / 8; + const int count2 = NUM_FRAMERATE_POINTS / 4; + const int count3 = NUM_FRAMERATE_POINTS / 1; + + IConsolePrintF(TC_SILVER, "Based on num. data points: %d %d %d", count1, count2, count3); + + static const char *MEASUREMENT_NAMES[PFE_MAX] = { + "Game loop", + " GL station ticks", + " GL train ticks", + " GL road vehicle ticks", + " GL ship ticks", + " GL aircraft ticks", + " GL landscape ticks", + " GL link graph delays", + "Drawing", + " Viewport drawing", + "Video output", + "Sound mixing", + }; + + static const PerformanceElement rate_elements[] = { PFE_GAMELOOP, PFE_DRAWING, PFE_VIDEO }; + + bool printed_anything = false; + + for (const PerformanceElement *e = rate_elements; e < rate_elements + lengthof(rate_elements); e++) { + auto &pf = _pf_data[*e]; + if (pf.num_valid == 0) continue; + IConsolePrintF(TC_GREEN, "%s rate: %.2ffps (expected: %.2ffps)", + MEASUREMENT_NAMES[*e], + pf.GetRate(), + pf.expected_rate); + printed_anything = true; + } + + for (PerformanceElement e = PFE_FIRST; e < PFE_MAX; e++) { + auto &pf = _pf_data[e]; + if (pf.num_valid == 0) continue; + IConsolePrintF(TC_LIGHT_BLUE, "%s times: %.2fms %.2fms %.2fms", + MEASUREMENT_NAMES[e], + pf.GetAverageDurationMilliseconds(count1), + pf.GetAverageDurationMilliseconds(count2), + pf.GetAverageDurationMilliseconds(count3)); + printed_anything = true; + } + + if (!printed_anything) { + IConsoleWarning("No performance measurements have been taken yet"); + } +} diff --git a/src/framerate_type.h b/src/framerate_type.h new file mode 100644 index 0000000000..295939efec --- /dev/null +++ b/src/framerate_type.h @@ -0,0 +1,67 @@ +/* $Id$ */ + +/* +* This file is part of OpenTTD. +* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. +* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . +*/ + +#ifndef FRAMERATE_GUI_H +#define FRAMERATE_GUI_H + +#include "stdafx.h" +#include "core/enum_type.hpp" + +enum PerformanceElement { + PFE_FIRST = 0, + PFE_GAMELOOP = 0, ///< Speed of gameloop processing. + PFE_GL_ECONOMY, ///< Time spent processing cargo movement + PFE_GL_TRAINS, ///< Time spent processing trains + PFE_GL_ROADVEHS, ///< Time spend processing road vehicles + PFE_GL_SHIPS, ///< Time spent processing ships + PFE_GL_AIRCRAFT, ///< Time spent processing aircraft + PFE_GL_LANDSCAPE, ///< Time spent processing other world features + PFE_GL_LINKGRAPH, ///< Time spent waiting for link graph background jobs + PFE_DRAWING, ///< Speed of drawing world and GUI. + PFE_DRAWWORLD, ///< Time spent drawing world viewports in GUI + PFE_VIDEO, ///< Speed of painting drawn video buffer. + PFE_SOUND, ///< Speed of mixing audio samples + PFE_MAX, ///< End of enum, must be last. +}; +DECLARE_POSTFIX_INCREMENT(PerformanceElement) + +typedef uint64 TimingMeasurement; + +/** + * RAII class for measuring simple elements of performance. + * Construct an object with the appropriate element parameter when processing begins, + * time is automatically taken when the object goes out of scope again. + */ +class PerformanceMeasurer { + PerformanceElement elem; + TimingMeasurement start_time; +public: + PerformanceMeasurer(PerformanceElement elem); + ~PerformanceMeasurer(); + void SetExpectedRate(double rate); + static void Paused(PerformanceElement elem); +}; + +/** + * RAII class for measuring multi-step elements of performance. + * At the beginning of a frame, call Reset on the element, then construct an object in the scope where + * each processing cycle happens. The measurements are summed between resets. + */ +class PerformanceAccumulator { + PerformanceElement elem; + TimingMeasurement start_time; +public: + PerformanceAccumulator(PerformanceElement elem); + ~PerformanceAccumulator(); + static void Reset(PerformanceElement elem); +}; + +void ShowFramerateWindow(); + +#endif /* FRAMERATE_GUI_H */ diff --git a/src/gamelog.h b/src/gamelog.h index 7f5b6a7765..83694e3ea8 100644 --- a/src/gamelog.h +++ b/src/gamelog.h @@ -38,7 +38,7 @@ void GamelogReset(); * @param s The string to print. */ typedef void GamelogPrintProc(const char *s); -void GamelogPrint(GamelogPrintProc *proc); // needed for WIN32 / WINCE crash.log +void GamelogPrint(GamelogPrintProc *proc); // needed for WIN32 crash.log void GamelogPrintDebug(int level); void GamelogPrintConsole(); diff --git a/src/genworld_gui.cpp b/src/genworld_gui.cpp index 359709e361..04eea8e660 100644 --- a/src/genworld_gui.cpp +++ b/src/genworld_gui.cpp @@ -288,7 +288,7 @@ static DropDownList *BuildMapsizeDropDown() for (uint i = MIN_MAP_SIZE_BITS; i <= MAX_MAP_SIZE_BITS; i++) { DropDownListParamStringItem *item = new DropDownListParamStringItem(STR_JUST_INT, i, false); - item->SetParam(0, 1 << i); + item->SetParam(0, 1LL << i); *list->Append() = item; } @@ -336,8 +336,8 @@ struct GenerateLandscapeWindow : public Window { { switch (widget) { case WID_GL_START_DATE_TEXT: SetDParam(0, ConvertYMDToDate(_settings_newgame.game_creation.starting_year, 0, 1)); break; - case WID_GL_MAPSIZE_X_PULLDOWN: SetDParam(0, 1 << _settings_newgame.game_creation.map_x); break; - case WID_GL_MAPSIZE_Y_PULLDOWN: SetDParam(0, 1 << _settings_newgame.game_creation.map_y); break; + case WID_GL_MAPSIZE_X_PULLDOWN: SetDParam(0, 1LL << _settings_newgame.game_creation.map_x); break; + case WID_GL_MAPSIZE_Y_PULLDOWN: SetDParam(0, 1LL << _settings_newgame.game_creation.map_y); break; case WID_GL_MAX_HEIGHTLEVEL_TEXT: SetDParam(0, _settings_newgame.construction.max_heightlevel); break; case WID_GL_SNOW_LEVEL_TEXT: SetDParam(0, _settings_newgame.game_creation.snow_line_height); break; @@ -896,11 +896,11 @@ struct CreateScenarioWindow : public Window break; case WID_CS_MAPSIZE_X_PULLDOWN: - SetDParam(0, 1 << _settings_newgame.game_creation.map_x); + SetDParam(0, 1LL << _settings_newgame.game_creation.map_x); break; case WID_CS_MAPSIZE_Y_PULLDOWN: - SetDParam(0, 1 << _settings_newgame.game_creation.map_y); + SetDParam(0, 1LL << _settings_newgame.game_creation.map_y); break; case WID_CS_FLAT_LAND_HEIGHT_TEXT: diff --git a/src/gfx.cpp b/src/gfx.cpp index 7195051577..c9c36019ce 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -1111,16 +1111,17 @@ void DoPaletteAnimations() /** * Determine a contrasty text colour for a coloured background. * @param background Background colour. + * @param threshold Background colour brightness threshold below which the background is considered dark and TC_WHITE is returned, range: 0 - 255, default 128. * @return TC_BLACK or TC_WHITE depending on what gives a better contrast. */ -TextColour GetContrastColour(uint8 background) +TextColour GetContrastColour(uint8 background, uint8 threshold) { Colour c = _cur_palette.palette[background]; /* Compute brightness according to http://www.w3.org/TR/AERT#color-contrast. * The following formula computes 1000 * brightness^2, with brightness being in range 0 to 255. */ uint sq1000_brightness = c.r * c.r * 299 + c.g * c.g * 587 + c.b * c.b * 114; - /* Compare with threshold brightness 128 (50%) */ - return sq1000_brightness < 128 * 128 * 1000 ? TC_WHITE : TC_BLACK; + /* Compare with threshold brightness which defaults to 128 (50%) */ + return sq1000_brightness < ((uint) threshold) * ((uint) threshold) * 1000 ? TC_WHITE : TC_BLACK; } /** @@ -1214,11 +1215,6 @@ void UndrawMouseCursor() void DrawMouseCursor() { -#if defined(WINCE) - /* Don't ever draw the mouse for WinCE, as we work with a stylus */ - return; -#endif - /* Don't draw the mouse cursor if the screen is not ready */ if (_screen.dst_ptr == NULL) return; diff --git a/src/gfx_func.h b/src/gfx_func.h index 99461f9079..9f7cb9153d 100644 --- a/src/gfx_func.h +++ b/src/gfx_func.h @@ -187,7 +187,7 @@ int GetCharacterHeight(FontSize size); extern DrawPixelInfo *_cur_dpi; -TextColour GetContrastColour(uint8 background); +TextColour GetContrastColour(uint8 background, uint8 threshold = 128); /** * All 16 colour gradients diff --git a/src/gfx_layout.cpp b/src/gfx_layout.cpp index 3290aea653..bb7efa2d72 100644 --- a/src/gfx_layout.cpp +++ b/src/gfx_layout.cpp @@ -21,6 +21,10 @@ #include #endif /* WITH_ICU_LAYOUT */ +#ifdef WITH_UNISCRIBE +#include "os/windows/string_uniscribe.h" +#endif /* WITH_UNISCRIBE */ + #include "safeguards.h" @@ -113,26 +117,12 @@ le_bool Font::getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &poin return FALSE; } -static size_t AppendToBuffer(UChar *buff, const UChar *buffer_last, WChar c) -{ - /* Transform from UTF-32 to internal ICU format of UTF-16. */ - int32 length = 0; - UErrorCode err = U_ZERO_ERROR; - u_strFromUTF32(buff, buffer_last - buff, &length, (UChar32*)&c, 1, &err); - return length; -} - /** * Wrapper for doing layouts with ICU. */ class ICUParagraphLayout : public AutoDeleteSmallVector, public ParagraphLayouter { ParagraphLayout *p; ///< The actual ICU paragraph layout. public: - /** Helper for GetLayouter, to get the right type. */ - typedef UChar CharType; - /** Helper for GetLayouter, to get whether the layouter supports RTL. */ - static const bool SUPPORTS_RTL = true; - /** Visual run contains data about the bit of text with the same font. */ class ICUVisualRun : public ParagraphLayouter::VisualRun { const ParagraphLayout::VisualRun *vr; ///< The actual ICU vr. @@ -184,35 +174,54 @@ public: } }; -static ParagraphLayouter *GetParagraphLayout(UChar *buff, UChar *buff_end, FontMap &fontMapping) -{ - int32 length = buff_end - buff; +/** + * Helper class to construct a new #ICUParagraphLayout. + */ +class ICUParagraphLayoutFactory { +public: + /** Helper for GetLayouter, to get the right type. */ + typedef UChar CharType; + /** Helper for GetLayouter, to get whether the layouter supports RTL. */ + static const bool SUPPORTS_RTL = true; - if (length == 0) { - /* ICU's ParagraphLayout cannot handle empty strings, so fake one. */ - buff[0] = ' '; - length = 1; - fontMapping.End()[-1].first++; + static ParagraphLayouter *GetParagraphLayout(UChar *buff, UChar *buff_end, FontMap &fontMapping) + { + int32 length = buff_end - buff; + + if (length == 0) { + /* ICU's ParagraphLayout cannot handle empty strings, so fake one. */ + buff[0] = ' '; + length = 1; + fontMapping.End()[-1].first++; + } + + /* Fill ICU's FontRuns with the right data. */ + FontRuns runs(fontMapping.Length()); + for (FontMap::iterator iter = fontMapping.Begin(); iter != fontMapping.End(); iter++) { + runs.add(iter->second, iter->first); + } + + 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. */ + ParagraphLayout *p = new ParagraphLayout(buff, length, &runs, NULL, NULL, NULL, _current_text_dir == TD_RTL ? UBIDI_DEFAULT_RTL : UBIDI_DEFAULT_LTR, false, status); + if (status != LE_NO_ERROR) { + delete p; + return NULL; + } + + return new ICUParagraphLayout(p); } - /* Fill ICU's FontRuns with the right data. */ - FontRuns runs(fontMapping.Length()); - for (FontMap::iterator iter = fontMapping.Begin(); iter != fontMapping.End(); iter++) { - runs.add(iter->second, iter->first); + static size_t AppendToBuffer(UChar *buff, const UChar *buffer_last, WChar c) + { + /* Transform from UTF-32 to internal ICU format of UTF-16. */ + int32 length = 0; + UErrorCode err = U_ZERO_ERROR; + u_strFromUTF32(buff, buffer_last - buff, &length, (UChar32*)&c, 1, &err); + return length; } - - 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. */ - ParagraphLayout *p = new ParagraphLayout(buff, length, &runs, NULL, NULL, NULL, _current_text_dir == TD_RTL ? UBIDI_DEFAULT_RTL : UBIDI_DEFAULT_LTR, false, status); - if (status != LE_NO_ERROR) { - delete p; - return NULL; - } - - return new ICUParagraphLayout(p); -} - +}; #endif /* WITH_ICU_LAYOUT */ /*** Paragraph layout ***/ @@ -236,11 +245,6 @@ static ParagraphLayouter *GetParagraphLayout(UChar *buff, UChar *buff_end, FontM */ class FallbackParagraphLayout : public ParagraphLayouter { public: - /** Helper for GetLayouter, to get the right type. */ - typedef WChar CharType; - /** Helper for GetLayouter, to get whether the layouter supports RTL. */ - static const bool SUPPORTS_RTL = false; - /** Visual run contains data about the bit of text with the same font. */ class FallbackVisualRun : public ParagraphLayouter::VisualRun { Font *font; ///< The font used to layout these. @@ -280,6 +284,42 @@ public: const ParagraphLayouter::Line *NextLine(int max_width); }; +/** + * Helper class to construct a new #FallbackParagraphLayout. + */ +class FallbackParagraphLayoutFactory { +public: + /** Helper for GetLayouter, to get the right type. */ + typedef WChar CharType; + /** Helper for GetLayouter, to get whether the layouter supports RTL. */ + static const bool SUPPORTS_RTL = false; + + /** + * Get the actual ParagraphLayout for the given buffer. + * @param buff The begin of the buffer. + * @param buff_end The location after the last element in the buffer. + * @param fontMapping THe mapping of the fonts. + * @return The ParagraphLayout instance. + */ + static ParagraphLayouter *GetParagraphLayout(WChar *buff, WChar *buff_end, FontMap &fontMapping) + { + return new FallbackParagraphLayout(buff, buff_end - buff, fontMapping); + } + + /** + * Append a wide character to the internal buffer. + * @param buff The buffer to append to. + * @param buffer_last The end of the buffer. + * @param c The character to add. + * @return The number of buffer spaces that were used. + */ + static size_t AppendToBuffer(WChar *buff, const WChar *buffer_last, WChar c) + { + *buff = c; + return 1; + } +}; + /** * Create the visual run. * @param font The font to use for this run. @@ -536,31 +576,6 @@ const ParagraphLayouter::Line *FallbackParagraphLayout::NextLine(int max_width) return l; } -/** - * Appand a wide character to the internal buffer. - * @param buff The buffer to append to. - * @param buffer_last The end of the buffer. - * @param c The character to add. - * @return The number of buffer spaces that were used. - */ -static size_t AppendToBuffer(WChar *buff, const WChar *buffer_last, WChar c) -{ - *buff = c; - return 1; -} - -/** - * Get the actual ParagraphLayout for the given buffer. - * @param buff The begin of the buffer. - * @param buff_end The location after the last element in the buffer. - * @param fontMapping THe mapping of the fonts. - * @return The ParagraphLayout instance. - */ -static FallbackParagraphLayout *GetParagraphLayout(WChar *buff, WChar *buff_end, FontMap &fontMapping) -{ - return new FallbackParagraphLayout(buff, buff_end - buff, fontMapping); -} - /** * Helper for getting a ParagraphLayouter of the given type. * @@ -582,6 +597,7 @@ static inline void GetLayouter(Layouter::LineCacheItem &line, const char *&str, Font *f = Layouter::GetFont(state.fontsize, state.cur_colour); line.buffer = buff_begin; + fontMapping.Clear(); /* * Go through the whole string while adding Font instances to the font map @@ -605,7 +621,7 @@ static inline void GetLayouter(Layouter::LineCacheItem &line, const char *&str, * will not be handled in the fallback non ICU case because they are * mostly needed for RTL languages which need more ICU support. */ if (!T::SUPPORTS_RTL && IsTextDirectionChar(c)) continue; - buff += AppendToBuffer(buff, buffer_last, c); + buff += T::AppendToBuffer(buff, buffer_last, c); continue; } @@ -621,7 +637,7 @@ static inline void GetLayouter(Layouter::LineCacheItem &line, const char *&str, if (!fontMapping.Contains(buff - buff_begin)) { fontMapping.Insert(buff - buff_begin, f); } - line.layout = GetParagraphLayout(buff_begin, buff, fontMapping); + line.layout = T::GetParagraphLayout(buff_begin, buff, fontMapping); line.state_after = state; } @@ -654,11 +670,13 @@ Layouter::Layouter(const char *str, int maxw, TextColour colour, FontSize fontsi line.layout->Reflow(); } else { /* Line is new, layout it */ -#ifdef WITH_ICU_LAYOUT FontState old_state = state; +#if defined(WITH_ICU_LAYOUT) || defined(WITH_UNISCRIBE) const char *old_str = str; +#endif - GetLayouter(line, str, state); +#ifdef WITH_ICU_LAYOUT + GetLayouter(line, str, state); if (line.layout == NULL) { static bool warned = false; if (!warned) { @@ -668,11 +686,22 @@ Layouter::Layouter(const char *str, int maxw, TextColour colour, FontSize fontsi state = old_state; str = old_str; - GetLayouter(line, str, state); } -#else - GetLayouter(line, str, state); #endif + +#ifdef WITH_UNISCRIBE + if (line.layout == NULL) { + GetLayouter(line, str, state); + if (line.layout == NULL) { + state = old_state; + str = old_str; + } + } +#endif + + if (line.layout == NULL) { + GetLayouter(line, str, state); + } } /* Copy all lines into a local cache so we can reuse them later on more easily. */ @@ -809,6 +838,10 @@ void Layouter::ResetFontCache(FontSize size) /* We must reset the linecache since it references the just freed fonts */ ResetLineCache(); + +#if defined(WITH_UNISCRIBE) + UniscribeResetScriptCache(size); +#endif } /** diff --git a/src/gfxinit.cpp b/src/gfxinit.cpp index d5959f5e16..f73027e91e 100644 --- a/src/gfxinit.cpp +++ b/src/gfxinit.cpp @@ -284,6 +284,9 @@ static bool SwitchNewGRFBlitter() #endif { "8bpp-optimized", 2, 8, 8, 8, 8 }, { "32bpp-optimized", 0, 8, 32, 8, 32 }, +#ifdef WITH_SSE + { "32bpp-sse2-anim", 1, 8, 32, 8, 32 }, +#endif { "32bpp-anim", 1, 8, 32, 8, 32 }, }; diff --git a/src/goal.cpp b/src/goal.cpp index 2f6ca242a9..f7aae350e5 100644 --- a/src/goal.cpp +++ b/src/goal.cpp @@ -23,6 +23,8 @@ #include "string_func.h" #include "gui.h" #include "network/network.h" +#include "network/network_base.h" +#include "network/network_func.h" #include "safeguards.h" @@ -234,7 +236,9 @@ 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 for which this question is. + * - 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. * @param text Text of the question. * @return the cost of this operation or an error @@ -243,17 +247,37 @@ CommandCost CmdGoalQuestion(TileIndex tile, DoCommandFlag flags, uint32 p1, uint { uint16 uniqueid = (GoalType)GB(p1, 0, 16); CompanyID company = (CompanyID)GB(p1, 16, 8); - byte type = GB(p1, 24, 8); +#ifdef ENABLE_NETWORK + ClientIndex client = (ClientIndex)GB(p1, 16, 8); +#endif + byte type = GB(p1, 24, 2); + bool is_client = HasBit(p1, 31); if (_current_company != OWNER_DEITY) return CMD_ERROR; if (StrEmpty(text)) return CMD_ERROR; - if (company != INVALID_COMPANY && !Company::IsValidID(company)) return CMD_ERROR; + if (is_client) { +#ifdef ENABLE_NETWORK + if (!NetworkClientInfo::IsValidID(client)) 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 (type >= GOAL_QUESTION_TYPE_COUNT) return CMD_ERROR; if (flags & DC_EXEC) { - if ((company != INVALID_COMPANY && company == _local_company) || (company == INVALID_COMPANY && Company::IsValidID(_local_company))) ShowGoalQuestion(uniqueid, type, p2, text); + if (is_client) { +#ifdef ENABLE_NETWORK + if (NetworkClientInfo::Get(client)->client_id != _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); } return CommandCost(); diff --git a/src/graph_gui.cpp b/src/graph_gui.cpp index c12c6ace4d..f4334429fb 100644 --- a/src/graph_gui.cpp +++ b/src/graph_gui.cpp @@ -33,8 +33,8 @@ #include "safeguards.h" /* Bitmasks of company and cargo indices that shouldn't be drawn. */ -static uint _legend_excluded_companies; -static uint _legend_excluded_cargo; +static CompanyMask _legend_excluded_companies; +static CargoTypes _legend_excluded_cargo; /* Apparently these don't play well with enums. */ static const OverflowSafeInt64 INVALID_DATAPOINT(INT64_MAX); // Value used for a datapoint that shouldn't be drawn. @@ -166,14 +166,14 @@ struct ValuesInterval { struct BaseGraphWindow : Window { protected: - static const int GRAPH_MAX_DATASETS = 32; + static const int GRAPH_MAX_DATASETS = 64; static const int GRAPH_AXIS_LINE_COLOUR = PC_BLACK; static const int GRAPH_NUM_MONTHS = 24; ///< Number of months displayed in the graph. static const int MIN_GRAPH_NUM_LINES_Y = 9; ///< Minimal number of horizontal lines to draw. static const int MIN_GRID_PIXEL_SIZE = 20; ///< Minimum distance between graph lines. - uint excluded_data; ///< bitmask of the datasets that shouldn't be displayed. + uint64 excluded_data; ///< bitmask of the datasets that shouldn't be displayed. byte num_dataset; byte num_on_x_axis; byte num_vert_lines; @@ -561,7 +561,7 @@ public: */ void UpdateStatistics(bool initialize) { - uint excluded_companies = _legend_excluded_companies; + CompanyMask excluded_companies = _legend_excluded_companies; /* Exclude the companies which aren't valid */ for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) { diff --git a/src/ground_vehicle.cpp b/src/ground_vehicle.cpp index fcdab77b03..f8efd8e1aa 100644 --- a/src/ground_vehicle.cpp +++ b/src/ground_vehicle.cpp @@ -58,8 +58,8 @@ void GroundVehicle::PowerChanged() this->gcache.cached_air_drag = air_drag + 3 * air_drag * number_of_parts / 20; - max_te *= 10000; // Tractive effort in (tonnes * 1000 * 10 =) N. - max_te /= 256; // Tractive effort is a [0-255] coefficient. + max_te *= 9800; // Tractive effort in (tonnes * 1000 * 9.8 =) N. + max_te /= 256; // Tractive effort is a [0-255] coefficient. if (this->gcache.cached_power != total_power || this->gcache.cached_max_te != max_te) { /* Stop the vehicle if it has no power. */ if (total_power == 0) this->vehstatus |= VS_STOPPED; diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index 9c98b120c6..7d1a7e2e6a 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -390,7 +390,7 @@ static Foundation GetFoundation_Industry(TileIndex tile, Slope tileh) return FlatteningFoundation(tileh); } -static void AddAcceptedCargo_Industry(TileIndex tile, CargoArray &acceptance, uint32 *always_accepted) +static void AddAcceptedCargo_Industry(TileIndex tile, CargoArray &acceptance, CargoTypes *always_accepted) { IndustryGfx gfx = GetIndustryGfx(tile); const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx); diff --git a/src/landscape.cpp b/src/landscape.cpp index 185e84a80b..18f27807d7 100644 --- a/src/landscape.cpp +++ b/src/landscape.cpp @@ -32,6 +32,7 @@ #include "company_func.h" #include "pathfinder/npf/aystar.h" #include "saveload/saveload.h" +#include "framerate_type.h" #include #include @@ -720,6 +721,8 @@ TileIndex _cur_tileloop_tile; */ void RunTileLoop() { + PerformanceAccumulator framerate(PFE_GL_LANDSCAPE); + /* The pseudorandom sequence of tiles is generated using a Galois linear feedback * shift register (LFSR). This allows a deterministic pseudorandom ordering, but * still with minimal state and fast iteration. */ @@ -1080,8 +1083,7 @@ static uint River_Hash(uint tile, uint dir) */ static void BuildRiver(TileIndex begin, TileIndex end) { - AyStar finder; - MemSetT(&finder, 0); + AyStar finder = {}; finder.CalculateG = River_CalculateG; finder.CalculateH = River_CalculateH; finder.GetNeighbours = River_GetNeighbours; @@ -1304,10 +1306,14 @@ void OnTick_LinkGraph(); void CallLandscapeTick() { - OnTick_Town(); - OnTick_Trees(); - OnTick_Station(); - OnTick_Industry(); + { + PerformanceAccumulator framerate(PFE_GL_LANDSCAPE); + + OnTick_Town(); + OnTick_Trees(); + OnTick_Station(); + OnTick_Industry(); + } OnTick_Companies(); OnTick_LinkGraph(); diff --git a/src/lang/afrikaans.txt b/src/lang/afrikaans.txt index b7fee9ae8b..b888e37992 100644 --- a/src/lang/afrikaans.txt +++ b/src/lang/afrikaans.txt @@ -670,10 +670,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Kies 'Be STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Skakel musiek lys skommel aan/af STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Vertoon musiek snit keuse venster -STR_ERROR_NO_SONGS :{WHITE}'n Musiek stel is gekies wat geen liedere bevat nie. Geen liedere sal gespeel word nie - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Musiek Program Keuse STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Liedjie Indeks STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Program - '{STRING}' @@ -1338,8 +1335,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Kleur van die t STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Groen STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Donkergroen STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Violet -STR_CONFIG_SETTING_REVERSE_SCROLLING :Agteruit rol rigting: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :As dit geaktiveer is, skuif die muis die kaart, andersins skuif die muis die kamera. STR_CONFIG_SETTING_SMOOTH_SCROLLING :Maak kykpoort beweegings glad: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Beheer hoe die hoofvertoonvenster skuif na 'n spesifieke posisie - as dit geaktiveer is, dan skuif die venster glad na die posisie toe, andersins skuif die venster direk na die posisie toe. STR_CONFIG_SETTING_MEASURE_TOOLTIP :Toon 'n meting wanneer jy verskeie bou-gereedskap gebruik: {STRING} @@ -1371,8 +1366,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command-klik STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl-klik STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Af -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Links-klik vir skermrol: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Maak dit moontlik om die kaart te skuif deur met die die linker-muisknoppie te sleep. Hier opsie werk baie goed vir toestelle met raakskerms. STR_CONFIG_SETTING_AUTOSAVE :Outostoor: {STRING} STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :Tyd tussen outomatiese spelstore @@ -2690,6 +2683,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Oorspron STR_ABOUT_VERSION :{BLACK}OpenTTD uitgawe {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 Die OpenTTD span +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Spaar Spel STR_SAVELOAD_LOAD_CAPTION :{WHITE}Laai Spel @@ -2981,8 +2981,6 @@ STR_TOWN_POPULATION :{BLACK}Wêreldb STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (City) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Bevolking: {ORANGE}{COMMA}{BLACK} Huise: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Passasiers verlede maand: {ORANGE}{COMMA}{BLACK} maks: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Pos verlede maand: {ORANGE}{COMMA}{BLACK} maks: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Vrag nodig om dorp te laat groei: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} vereis STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} vereis in winter diff --git a/src/lang/arabic_egypt.txt b/src/lang/arabic_egypt.txt index b026705865..e0a7eb3a0a 100644 --- a/src/lang/arabic_egypt.txt +++ b/src/lang/arabic_egypt.txt @@ -644,10 +644,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}اختي STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}تشغيل / ايقاف العشوائي STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}اظهار اطار اختيار الموسيقى -STR_ERROR_NO_SONGS :{WHITE}لا تحتوى قاعده الموسيقى المُختاره على اى اغانى. لن تُعزَف اى اغانى - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}برنامج اختيار الموسيقى STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}قائمة المعزوفات STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}برنامج - '{STRING}' @@ -1177,7 +1174,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR :لون الار STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :اخضر STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :اخضر غامق STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :بنفسجي -STR_CONFIG_SETTING_REVERSE_SCROLLING :عكس تحريك الشاشة : {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING :تحريك سلس في نوافذ المشاهدة: {STRING} STR_CONFIG_SETTING_MEASURE_TOOLTIP :عرض المقاسات عند استخدام ادوات البناء المختلفة: {STRING} STR_CONFIG_SETTING_LIVERIES :عرض لون و شعار الشركة: {STRING} @@ -1196,7 +1192,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :الأوامر STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :للتحكم STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :عدم استخدام -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :تصفح بالزر الايسر: {STRING} STR_CONFIG_SETTING_AUTOSAVE :حفظ تلقائي : {STRING} STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :اختر الوقت بين كل عملية حفظ اتوماتيكية @@ -2322,6 +2317,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}الحق STR_ABOUT_VERSION :{BLACK}النسخة المفتوحة رقم {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}النسخة المفتوحة {COPYRIGHT}2002-2018 فريق النسخة المفتوحة +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}حفظ اللعبة STR_SAVELOAD_LOAD_CAPTION :{WHITE}فتح @@ -2594,8 +2596,6 @@ STR_TOWN_POPULATION :{BLACK}سكان STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} - مدينة - STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}السكان: {ORANGE}{COMMA}{BLACK} المنازل: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}الركاب الشهر الماضي: {ORANGE}{COMMA}{BLACK} الأقصى: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}طرود البريد الشهر الماضي: {ORANGE}{COMMA}{BLACK} الأقصى: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK} نمو المدينة يتطلب بضائع STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} مطلوب STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK}مطلوب في الشتاء diff --git a/src/lang/basque.txt b/src/lang/basque.txt index 6d80461b68..cd97bf02cf 100644 --- a/src/lang/basque.txt +++ b/src/lang/basque.txt @@ -663,10 +663,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}'Pertson STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Programa zorizko moduan jarri/kendu STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Erakutsi kanten selekzio leihoa -STR_ERROR_NO_SONGS :{WHITE}Kantarik gabeko musika paketea aukeratua. Ez dago kantarik entzuteko - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Musika Programen Selekzioa STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Pistaren Indizea STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Programatu - '{STRING}' @@ -1301,8 +1298,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Mapa txikiaren STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Berdea STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Berde iluna STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Bioleta -STR_CONFIG_SETTING_REVERSE_SCROLLING :Leihoa mapan zehar mugitzeko sagua mugitzeko era aldrebes jarri: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Mapan zehar saguaren eskuineko botoiarekin mugitzerakoan izango duen portaera. Desgaitua badago, saguak kamera mugituko du. Gaitua dagoenean, saguak mapa mugituko du STR_CONFIG_SETTING_SMOOTH_SCROLLING :Mapan zehar mugitzerakoan, abiadura moteltzea: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Kontrolatu nola mugituko den ikuspegia lehio nagusitik zehar, puntu jakin batera joateko mapa txikian sakatzen denean edo objektu zehatz batera joateko agintzen denean STR_CONFIG_SETTING_MEASURE_TOOLTIP :Eraikitze tresna ezberdinak erabiltzerakoan neurtresna erakutsi: {STRING} @@ -1334,8 +1329,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Komandoa+Klik STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+Klik STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Itzalita -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Saguaren ezkerreko botoiarekin mapan zehar mugitzea: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Gaitu mapatik zehar mugitzea saguaren ezkerreko botoia mapan arrastratzerakoan. Oso erabilgarria da ukipen pantailak erabiltzerakoan STR_CONFIG_SETTING_AUTOSAVE :Auto-gordea: {STRING} STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :Partida gordetze automatikoaren bitartea aukeratu @@ -2594,6 +2587,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Original STR_ABOUT_VERSION :{BLACK}OpenTTD bertsioa {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 The OpenTTD team +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Gordetako jokoa STR_SAVELOAD_LOAD_CAPTION :{WHITE}Jokoa kargatu @@ -2870,8 +2870,6 @@ STR_TOWN_POPULATION :{BLACK}Munduko STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Hiria) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Biztanleria: {ORANGE}{COMMA}{BLACK} Etxe kopurua: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Bidaiari kopurua aurreko hilabetean: {ORANGE}{COMMA}{BLACK} gehienez: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Posta kopurua aurreko hilabetean: {ORANGE}{COMMA}{BLACK} gehienez: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Beharrezko zama herri hazkunderako: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} beharrezkoa STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} Neguan beharrezkoa diff --git a/src/lang/belarusian.txt b/src/lang/belarusian.txt index 71efd347ab..52f7821d93 100644 --- a/src/lang/belarusian.txt +++ b/src/lang/belarusian.txt @@ -963,6 +963,7 @@ STR_MUSIC_RULER_MARKER :{TINY_FONT}{BLA STR_MUSIC_TRACK_NONE :{TINY_FONT}{DKGREEN}-- STR_MUSIC_TRACK_DIGIT :{TINY_FONT}{DKGREEN}{ZEROFILL_NUM} STR_MUSIC_TITLE_NONE :{TINY_FONT}{DKGREEN}------ +STR_MUSIC_TITLE_NOMUSIC :{TINY_FONT}{DKGREEN}Музычнае афармленне недаступна STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKGREEN}«{STRING}» STR_MUSIC_TRACK :{TINY_FONT}{BLACK}Трэк STR_MUSIC_XTITLE :{TINY_FONT}{BLACK}Назва @@ -982,15 +983,15 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Выбр STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Уключыць/выключыць выпадковы выбар трэкаў STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Паказаць вакно выбару трэкаў -STR_ERROR_NO_SONGS :{WHITE}У выбранай праґраме адсутнічае музыка - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Выбар музычнай праґрамы +STR_PLAYLIST_MUSIC_SELECTION_SETNAME :{WHITE}Музычная праграма - '{STRING}' STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} «{STRING}» STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Сьпіс трэкаў STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Programme — «{STRING}» STR_PLAYLIST_CLEAR :{TINY_FONT}{BLACK}Ачысьціць +STR_PLAYLIST_CHANGE_SET :{BLACK}Зьмяніць набор STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Ачысьціць сьпіс уласнай праґрамы +STR_PLAYLIST_TOOLTIP_CHANGE_SET :{BLACK}Змяніць выбар музычнага афармлення на іншы ўсталяваны набор STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}Клікніце па назьве трэка, каб дадаць яго ва ўласную праґраму STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}Клікніце па назьве трэка, каб выдаліць яго з уласнай праґрамы @@ -1195,7 +1196,7 @@ STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION :{BIG_FONT}{BLAC STR_EXTRA_VIEW_PORT_TITLE :{WHITE}Вакно прагляду {COMMA} STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Капіяваць у вакно прагляду STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN_TT :{BLACK}Скапіяваць бягучую пазыцыю ў вакно прагляду -STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Уставіць з вакна прагляду +STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}У асноўнае акно STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT :{BLACK}Перайсьці да гэтага месца ў асноўным вакне # Game options window @@ -1650,8 +1651,12 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Колер ля STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :зялёны STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :цёмна-зялёны STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :фіялетавы -STR_CONFIG_SETTING_REVERSE_SCROLLING :Перавярнуць напрамак зрушэньня прагляду мышшу: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Паводзіны пры пракручваньні мапы правай кнопкай мышы. Калі адключана, мыш перамяшчае кропку позірку. Калі ўключана, мыш перамяшчае мапу. +STR_CONFIG_SETTING_SCROLLMODE :Перамяшчэнне агляду: {STRING} +STR_CONFIG_SETTING_SCROLLMODE_HELPTEXT :Спосаб перамяшчэння па гульнёваму полю +STR_CONFIG_SETTING_SCROLLMODE_DEFAULT :Перамяшчаць з дапамогай ПКМ, зафіксаваўшы курсор +STR_CONFIG_SETTING_SCROLLMODE_RMB_LOCKED :Перамяшчаць з дапамогай ПКМ, зафіксаваўшы курсор +STR_CONFIG_SETTING_SCROLLMODE_RMB :Перамяшчаць з дапамогай ПКМ +STR_CONFIG_SETTING_SCROLLMODE_LMB :Перамяшчаць з дапамогай ЛКМ STR_CONFIG_SETTING_SMOOTH_SCROLLING :Павольная пракрутка ў вакне прагляду: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Кантралюе, што адбудзецца ў галоўным вакне, калі пстрыкнуць у малым вакне прагляду па нейкай кропцы. Калі ўключана, позірк будзе павольна перамяшчацца па мапе ў галоўным вакне. Калі выключана — экран адразу прыгне ў вызначанае месца. STR_CONFIG_SETTING_MEASURE_TOOLTIP :Паказваць замеры пры будаўніцтве: {STRING} @@ -1683,8 +1688,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :каманда+ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+клік STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :выключана -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Скролінг па кліку левай кнопкай мышы: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Уключыць пракручваньне мапы цягненьнем з націснутай левай кнопкай мышы. Гэта асабліва зручна пры выкарыстоўваньні сэнсарнага экрана. STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Зачыняць вокны пстрычкай ПКМ: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Зачыняць акно пстрычкай правай кнопкай мышы ў яго межах. Пры гэтым адключаецца з'яўленне падказак па правай кнопцы. @@ -2614,6 +2617,7 @@ STR_LINKGRAPH_LEGEND_CAPTION :{BLACK}Схем STR_LINKGRAPH_LEGEND_ALL :{BLACK}Усе STR_LINKGRAPH_LEGEND_NONE :{BLACK}Няма STR_LINKGRAPH_LEGEND_SELECT_COMPANIES :{BLACK}Выберыце кампаніі для адлюстраваньня +STR_LINKGRAPH_LEGEND_COMPANY_TOOLTIP :{BLACK}{STRING}{}{COMPANY} # Linkgraph legend window and linkgraph legend in smallmap STR_LINKGRAPH_LEGEND_UNUSED :{TINY_FONT}{BLACK}нявыкарыст. @@ -3026,6 +3030,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Арыґ STR_ABOUT_VERSION :{BLACK}OpenTTD вэрсія {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002–2018 Каманда распрацоўнікаў OpenTTD +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Захаваць гульню STR_SAVELOAD_LOAD_CAPTION :{WHITE}Загрузіць гульню @@ -3310,6 +3321,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Увяд STR_TOWN_DIRECTORY_CAPTION :{WHITE}Гарады STR_TOWN_DIRECTORY_NONE :{ORANGE}- Няма - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Мегаполіс){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Сьпіс гарадоў: клiк па назьве паказвае горад у асноўным вакне. Ctrl+клiк паказвае ў дадатковым вакне. STR_TOWN_POPULATION :{BLACK}Насельніцтва: {COMMA} @@ -3317,8 +3329,7 @@ STR_TOWN_POPULATION :{BLACK}Насе STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Мэґаполіс) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Насельніцтва: {ORANGE}{COMMA}{BLACK} Будынкаў: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Пасажыраў за мінулы месяц: {ORANGE}{COMMA}{BLACK} Макс.: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Пошты за мінулы месяц: {ORANGE}{COMMA}{BLACK} Макс.: {ORANGE}{COMMA} +STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX :{BLACK}{CARGO_LIST} у мінулым месяцы: {ORANGE}{COMMA}{BLACK} Макс.: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Груз, неабходны для росту горада: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} патрабу{G 0 е e e ю}цца STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} патрабу{G 0 е e e ю}цца ўзімку @@ -4585,6 +4596,7 @@ 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... @@ -4836,6 +4848,8 @@ STR_BASESOUNDS_DOS_DESCRIPTION :Арыґіна STR_BASESOUNDS_WIN_DESCRIPTION :Арыґінальны набор гукавога афармленьня з гульні Transport Tycoon Deluxe для Windows. STR_BASESOUNDS_NONE_DESCRIPTION :"Пусты" набор гукавога афармленьня, які не зьмяшчае ніякіх гукаў. STR_BASEMUSIC_WIN_DESCRIPTION :Арыґінальны набор музычнага афармленьня з гульні Transport Tycoon Deluxe для Windows. +STR_BASEMUSIC_DOS_DESCRIPTION :Набор музычнага афармленьня з гульні Transport Tycoon Deluxe для DOS. +STR_BASEMUSIC_TTO_DESCRIPTION :Набор музычнага афармлення з гульні Transport Tycoon (Original/World Editor) для DOS. STR_BASEMUSIC_NONE_DESCRIPTION :"Пусты" набор музычнага афармлення, які не зьмяшчае ніякай музыкі. ##id 0x2000 diff --git a/src/lang/brazilian_portuguese.txt b/src/lang/brazilian_portuguese.txt index 859a6c1afa..fd61397862 100644 --- a/src/lang/brazilian_portuguese.txt +++ b/src/lang/brazilian_portuguese.txt @@ -670,10 +670,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Selecion STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Alternar programa misturado em ligado/desligado STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Exibir janela de seleção de faixas de música -STR_ERROR_NO_SONGS :{WHITE}Um conjunto de músicas sem canções foi selecionado. Nenhuma música será tocada - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Seleção de Programa de Música STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} '{STRING}' STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Índice de faixas STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Programa - '{STRING}' @@ -1338,8 +1335,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Cor do terreno STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Verde STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Verde escuro STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Violeta -STR_CONFIG_SETTING_REVERSE_SCROLLING :Rolar a tela no sentido oposto ao movimento do mouse: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Comportamento quando rolar o mapa com o botão direito. Quando desativado, o mouse move a câmera. Ativado, o mouse move o mapa. STR_CONFIG_SETTING_SMOOTH_SCROLLING :Suavizar rolamento da janela: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Controla como a janela principal rola para uma posição específica quando clicado no minimapa ou após localizar um objeto. Ativado torna o rolamento suave. Desativado torna o rolamento instanâneo STR_CONFIG_SETTING_MEASURE_TOOLTIP :Exibe distâncias quando usar ferramentas de construção: {STRING} @@ -1371,8 +1366,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Clique de coman STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Clique de controle STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Desligado -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Mover a tela com o botão esquerdo: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Ativa rolamento do mapa por clique e arraste com o botão esquerdo. Especialmente útil ao usar um touchscreen para o rolamento STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Fechar janela com botão direito do mouse: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Fecha uma janela ao clicar com o botão direito do mouse nela. Desativa o tooltip com o botão direito! @@ -2694,6 +2687,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Copyrigh STR_ABOUT_VERSION :{BLACK}OpenTTD versão {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 A equipe do OpenTTD +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Salvar Jogo STR_SAVELOAD_LOAD_CAPTION :{WHITE}Abrir Jogo @@ -2985,8 +2985,6 @@ STR_TOWN_POPULATION :{BLACK}Populaç STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Cidade) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}População: {ORANGE}{COMMA}{BLACK} Casas: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Passageiros no mês passado: {ORANGE}{COMMA}{BLACK} máx: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Cartas no mês passado: {ORANGE}{COMMA}{BLACK} máx: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Carga necessária para prover o crescimento: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} necessário(a) STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} necessário no inverno diff --git a/src/lang/bulgarian.txt b/src/lang/bulgarian.txt index 40394260d4..818bc8b8e0 100644 --- a/src/lang/bulgarian.txt +++ b/src/lang/bulgarian.txt @@ -667,10 +667,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Избе STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Активирай/деактивирай разместване на парчетата STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Покажи прозореца за избор на музикални парчета -STR_ERROR_NO_SONGS :{WHITE}Музикален пакет без песни е избран. Няма да се пускат песни. - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Избор на музикалната програма STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Номер на песен STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Програма - '{STRING}' @@ -1320,8 +1317,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Цвят на STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Зелен STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Тъмно зелен STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Виолетов -STR_CONFIG_SETTING_REVERSE_SCROLLING :Обърната посока на преместване: {STRING.n} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Когато опцията бъде активирана, когато "скролвате" картата с десния бутон на мишката ще местите картата, когато опцията не е активирана, мишката ще мести камерата STR_CONFIG_SETTING_SMOOTH_SCROLLING :Плавно местене на камера: {STRING.n} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Ако опцията е активирана, когато натиснете на малката карта камерата ще се придвижи до там плавно, ако не е активирана камерата ще отиде там директно STR_CONFIG_SETTING_MEASURE_TOOLTIP :Подсказка за разстояние при строене: {STRING.f} @@ -1353,8 +1348,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Команда- STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Контрол-щракане STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Изключен -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Скролиране с ляв бутон: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Позволява да "скролнете" картата, чрез влачене на левия бутон на мишката. Това и изключително полезно ако ползвате тъч-скрийн STR_CONFIG_SETTING_AUTOSAVE :Автоматично запазване: {STRING} STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :Изберете интервал между автоматично запаметяване на играта @@ -2635,6 +2628,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Авто STR_ABOUT_VERSION :{BLACK}OpenTTD версия {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2018 The OpenTTD team +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Запази играта STR_SAVELOAD_LOAD_CAPTION :{WHITE}Отваряне на игра @@ -2918,8 +2918,6 @@ STR_TOWN_POPULATION :{BLACK}Обща STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Град) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Население: {ORANGE}{COMMA}{BLACK} Жилища: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Пътници през последния месец: {ORANGE}{COMMA}{BLACK} максимум: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Поща през последния месец: {ORANGE}{COMMA}{BLACK} максимум: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Товар нужен за растеж на града: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} необходим STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} необходим през зимата diff --git a/src/lang/catalan.txt b/src/lang/catalan.txt index 28814005c8..54f7aac651 100644 --- a/src/lang/catalan.txt +++ b/src/lang/catalan.txt @@ -476,6 +476,7 @@ STR_ABOUT_MENU_SCREENSHOT :Captura de pant STR_ABOUT_MENU_ZOOMIN_SCREENSHOT :Captura de pantalla amb el zoom màxim STR_ABOUT_MENU_DEFAULTZOOM_SCREENSHOT :Captura de pantalla amb el zoom predeterminat STR_ABOUT_MENU_GIANT_SCREENSHOT :Captura de pantalla de tot el mapa +STR_ABOUT_MENU_SHOW_FRAMERATE :Mostra els fotogrames per segon STR_ABOUT_MENU_ABOUT_OPENTTD :Quant a l'OpenTTD STR_ABOUT_MENU_SPRITE_ALIGNER :Alineador de sprites STR_ABOUT_MENU_TOGGLE_BOUNDING_BOXES :Commuta les caixes delimitadores @@ -651,6 +652,7 @@ STR_MUSIC_RULER_MARKER :{TINY_FONT}{BLA STR_MUSIC_TRACK_NONE :{TINY_FONT}{DKGREEN}-- STR_MUSIC_TRACK_DIGIT :{TINY_FONT}{DKGREEN}{ZEROFILL_NUM} STR_MUSIC_TITLE_NONE :{TINY_FONT}{DKGREEN}------ +STR_MUSIC_TITLE_NOMUSIC :{TINY_FONT}{DKGREEN}No hi ha peces musicals disponibles STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKGREEN}«{STRING}» STR_MUSIC_TRACK :{TINY_FONT}{BLACK}Pista STR_MUSIC_XTITLE :{TINY_FONT}{BLACK}Títol @@ -670,15 +672,15 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Seleccio STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Habilita/deshabilita la reproducció en ordre aleatori STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Mostra la finestra de selecció de pistes -STR_ERROR_NO_SONGS :{WHITE}S'ha seleccionat un conjunt de música sense peces. No es reproduirà res. - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Selecció de les peces de la llista +STR_PLAYLIST_MUSIC_SELECTION_SETNAME :{WHITE}Programació de pistes - «{STRING}» STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} «{STRING}» STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Índex de pistes STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Llista «{STRING}» STR_PLAYLIST_CLEAR :{TINY_FONT}{BLACK}Esborra +STR_PLAYLIST_CHANGE_SET :{BLACK}Canvia conjunt STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Esborra la llista actual (només les llistes personalitzables) +STR_PLAYLIST_TOOLTIP_CHANGE_SET :{BLACK}Canvia la selecció musical a un altre conjunt instal·lat. STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}Clica la pista de música per afegir-la a la llista actual (només en les llistes personalitzables) STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}Clica la pista de música per treure-la de la llista actual (només en llistes personalitzables) @@ -881,10 +883,10 @@ STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION :{BIG_FONT}{BLAC # Extra view window STR_EXTRA_VIEW_PORT_TITLE :{WHITE}Vista {COMMA} -STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Copia a la vista +STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Canvia la vista extra STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN_TT :{BLACK}Mou aquesta vista on està la vista principal -STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Vés a la vista -STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT :{BLACK}Mou la vista principal on està aquesta vista +STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Canvia vista principal +STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT :{BLACK}Copia el lloc d'aquesta vista extra a la vista principal. # Game options window STR_GAME_OPTIONS_CAPTION :{WHITE}Opcions de la partida @@ -1338,8 +1340,12 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Color del terre STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Verd STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Verd fosc STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Violat -STR_CONFIG_SETTING_REVERSE_SCROLLING :En desplaçar la pantalla amb el ratolí mou la vista en la direcció contrària: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Comportament quan es desplaci el mapa amb el botó dret del ratolí. Quan està desactivat, el ratolí mou la càmera. Quan està activat, el ratolí mou el mapa +STR_CONFIG_SETTING_SCROLLMODE :Desplaçament del mapa: {STRING} +STR_CONFIG_SETTING_SCROLLMODE_HELPTEXT :Comportament quan es desplaça el mapa. +STR_CONFIG_SETTING_SCROLLMODE_DEFAULT :Mou la vista amb el botó dret del ratolí amb la posició del ratolí fixada +STR_CONFIG_SETTING_SCROLLMODE_RMB_LOCKED :Mou el mapa amb el botó dret del ratolí amb la posició del ratolí fixada +STR_CONFIG_SETTING_SCROLLMODE_RMB :Mou el mapa amb el botó dret del ratolí +STR_CONFIG_SETTING_SCROLLMODE_LMB :Mou el mapa amb el botó esquerre del ratolí STR_CONFIG_SETTING_SMOOTH_SCROLLING :Desplaçament suau de la vista: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Controla com la vista principal es desplaça a una posició específica quan es clica al mapa petit o quan s'envia una ordre de desplaçar-se a un objecte específic al mapa. Si està activat, la vista es desplaça suaument; si està desactivat, salta directament al punt assenyalat STR_CONFIG_SETTING_MEASURE_TOOLTIP :Mostra un cartell de mesura quan estiguis utilitzant vàries eines de construcció: {STRING} @@ -1371,8 +1377,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command-clic STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Control-clic STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Desactivat -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Desplaçament amb el botó esquerre: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Activa el desplaçament del mapa arrossegant-lo amb el botó esquerre del ratolí. Això és especialment útil quan s'utilitzen pantalles tàctils STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Tanca la finestra amb un clic dret del ratolí: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Tanca una finestra fent-hi un clic amb el botó dret del ratolí. Aquesta opció desactiva els indicadors de funció amb el mateix botó. @@ -2286,6 +2290,7 @@ STR_LINKGRAPH_LEGEND_CAPTION :{BLACK}Llegenda STR_LINKGRAPH_LEGEND_ALL :{BLACK}Tot STR_LINKGRAPH_LEGEND_NONE :{BLACK}Cap STR_LINKGRAPH_LEGEND_SELECT_COMPANIES :{BLACK}Selecciona les companyies que seran mostrades +STR_LINKGRAPH_LEGEND_COMPANY_TOOLTIP :{BLACK}{STRING}{}{COMPANY} # Linkgraph legend window and linkgraph legend in smallmap STR_LINKGRAPH_LEGEND_UNUSED :{G=Masculin}{TINY_FONT}{BLACK}no utilitzat @@ -2694,6 +2699,56 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Copyrigh STR_ABOUT_VERSION :{BLACK}Versió {REV} de l'OpenTTD STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 L'equip de l'OpenTTD +# Framerate display window +STR_FRAMERATE_CAPTION :{WHITE}Fotogrames per segon +STR_FRAMERATE_CAPTION_SMALL :{STRING}{WHITE} (x{DECIMAL}) +STR_FRAMERATE_RATE_GAMELOOP :{WHITE}Velocitat de simulació: {STRING} +STR_FRAMERATE_RATE_GAMELOOP_TOOLTIP :{BLACK}Nombre de tics del joc per segon. +STR_FRAMERATE_RATE_BLITTER :{WHITE}Fotogrames per segon: {STRING} +STR_FRAMERATE_RATE_BLITTER_TOOLTIP :{BLACK}Nombre de fotogrames renderitzats per segon. +STR_FRAMERATE_SPEED_FACTOR :{WHITE}Factor de velocitat actual: x{DECIMAL} +STR_FRAMERATE_SPEED_FACTOR_TOOLTIP :{BLACK}Quant ràpid va la partida actual, comparant-ho amb l'estimació de la velocitat normal. +STR_FRAMERATE_CURRENT :{WHITE}Actual +STR_FRAMERATE_AVERAGE :{WHITE}Mitjana +STR_FRAMERATE_DATA_POINTS :{WHITE}Dades basades en {COMMA} mesures. +STR_FRAMERATE_MS_GOOD :{LTBLUE}{DECIMAL}{WHITE}{NBSP}ms +STR_FRAMERATE_MS_WARN :{YELLOW}{DECIMAL}{WHITE}{NBSP}ms +STR_FRAMERATE_MS_BAD :{RED}{DECIMAL}{WHITE}{NBSP}ms +STR_FRAMERATE_FPS_GOOD :{LTBLUE}{DECIMAL}{WHITE}{NBSP}fps +STR_FRAMERATE_FPS_WARN :{YELLOW}{DECIMAL}{WHITE}{NBSP}fps +STR_FRAMERATE_FPS_BAD :{RED}{DECIMAL}{WHITE}{NBSP}fps +STR_FRAMERATE_GRAPH_MILLISECONDS :{TINY_FONT}{COMMA}{NBSP}ms +STR_FRAMERATE_GRAPH_SECONDS :{TINY_FONT}{COMMA}{NBSP}s +############ Leave those lines in this order!! +STR_FRAMERATE_GAMELOOP :{WHITE}Total del bucle: +STR_FRAMERATE_GL_ECONOMY :{WHITE} Tractament de la càrrega: +STR_FRAMERATE_GL_TRAINS :{WHITE} Tics de tren: +STR_FRAMERATE_GL_ROADVEHS :{WHITE} Tics de vehicles de carretera: +STR_FRAMERATE_GL_SHIPS :{WHITE} Tics de vaixell: +STR_FRAMERATE_GL_AIRCRAFT :{WHITE} Tics d'aeronau: +STR_FRAMERATE_GL_LANDSCAPE :{WHITE} Tics del mapa: +STR_FRAMERATE_GL_LINKGRAPH :{WHITE} Retard del graf de distribució: +STR_FRAMERATE_DRAWING :{WHITE}Renderitzat de gràfics: +STR_FRAMERATE_DRAWING_VIEWPORTS :{WHITE} Vistes del mapa: +STR_FRAMERATE_VIDEO :{WHITE}Sortida de vídeo: +STR_FRAMERATE_SOUND :{WHITE}Mescla de so: +############ End of leave-in-this-order +############ Leave those lines in this order!! +STR_FRAMETIME_CAPTION_GAMELOOP :Bucle +STR_FRAMETIME_CAPTION_GL_ECONOMY :Tractament de la càrrega +STR_FRAMETIME_CAPTION_GL_TRAINS :Tics de tren +STR_FRAMETIME_CAPTION_GL_ROADVEHS :Tics de vehicle de carretera +STR_FRAMETIME_CAPTION_GL_SHIPS :Tics de vaixell +STR_FRAMETIME_CAPTION_GL_AIRCRAFT :Tics d'aeronau +STR_FRAMETIME_CAPTION_GL_LANDSCAPE :Tics del mapa +STR_FRAMETIME_CAPTION_GL_LINKGRAPH :Retard del graf de distribució +STR_FRAMETIME_CAPTION_DRAWING :Renderitzat de gràfics +STR_FRAMETIME_CAPTION_DRAWING_VIEWPORTS :Renderitzat de la vista del mapa +STR_FRAMETIME_CAPTION_VIDEO :Sortida de vídeo +STR_FRAMETIME_CAPTION_SOUND :Mescla de so +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Desa la Partida STR_SAVELOAD_LOAD_CAPTION :{WHITE}Carrega una Partida @@ -2978,6 +3033,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Posa un STR_TOWN_DIRECTORY_CAPTION :{WHITE}Poblacions STR_TOWN_DIRECTORY_NONE :{ORANGE}- Cap - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{BLACK} ({COMMA} -{YELLOW} ciutat{BLACK}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Noms de Població - clica al nom per centrar la vista principal a la població. Ctrl+Clic obre una nova vista al lloc de la població STR_TOWN_POPULATION :{BLACK}Població mundial: {COMMA} @@ -2985,8 +3041,7 @@ STR_TOWN_POPULATION :{BLACK}Poblaci STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Ciutat) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Població: {ORANGE}{COMMA}{BLACK} Cases: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Passatgers el darrer mes: {ORANGE}{COMMA}{BLACK} màx: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Correu el darrer mes: {ORANGE}{COMMA}{BLACK} màx: {ORANGE}{COMMA} +STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX :{BLACK}{CARGO_LIST} l'últim mes: {ORANGE}{COMMA}{BLACK} (màx. {ORANGE}{COMMA}{BLACK}) STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Càrrega requerida per tal que la població creixi: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} requerides STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} requerit a l'hivern @@ -4233,6 +4288,7 @@ 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ó... @@ -4484,6 +4540,8 @@ STR_BASESOUNDS_DOS_DESCRIPTION :Sons originals STR_BASESOUNDS_WIN_DESCRIPTION :Sons originals del Transport Tycoon Deluxe pel Windows. STR_BASESOUNDS_NONE_DESCRIPTION :Una llista de sons buida. STR_BASEMUSIC_WIN_DESCRIPTION :Música original del Transport Tycoon Deluxe pel Windows. +STR_BASEMUSIC_DOS_DESCRIPTION :Música original del Transport Tycoon Deluxe pel DOS. +STR_BASEMUSIC_TTO_DESCRIPTION :Música original del Transport Tycoon Deluxe (original/editor d'escenaris) pel DOS. STR_BASEMUSIC_NONE_DESCRIPTION :Una llista de música sense cap peça. ##id 0x2000 diff --git a/src/lang/croatian.txt b/src/lang/croatian.txt index e7694f1bde..0d6a8a44a3 100644 --- a/src/lang/croatian.txt +++ b/src/lang/croatian.txt @@ -746,6 +746,7 @@ STR_MUSIC_RULER_MARKER :{TINY_FONT}{BLA STR_MUSIC_TRACK_NONE :{TINY_FONT}{DKGREEN}-- STR_MUSIC_TRACK_DIGIT :{TINY_FONT}{DKGREEN}{ZEROFILL_NUM} STR_MUSIC_TITLE_NONE :{TINY_FONT}{DKGREEN}------ +STR_MUSIC_TITLE_NOMUSIC :{TINY_FONT}{DKGREEN}Nema dostupne muzike STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKGREEN}"{STRING}" STR_MUSIC_TRACK :{TINY_FONT}{BLACK}Traka STR_MUSIC_XTITLE :{TINY_FONT}{BLACK}Naslov @@ -765,15 +766,15 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Odaberi STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Uključi/isključi miješanje programa STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Pokaži prozor za izbor glazbenih traka -STR_ERROR_NO_SONGS :{WHITE}Odabran je set glazbe bez pjesama. Ne će se puštati nikakve pjesme - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Izbor glazbenog programa +STR_PLAYLIST_MUSIC_SELECTION_SETNAME :{WHITE}Program muzike - '{STRING}' STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Popis traka STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Program- '{STRING}' STR_PLAYLIST_CLEAR :{TINY_FONT}{BLACK}Obriši +STR_PLAYLIST_CHANGE_SET :{BLACK}Promijeni set STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Obriši aktivni program (samo Proizvoljno 1 ili Proizvoljno 2) +STR_PLAYLIST_TOOLTIP_CHANGE_SET :{BLACK}Promijeni odabir muzike na neki drugi instalirani set STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}Klikni na glazbenu traku za dodavanje u aktivni program (samo Proizvoljno 1 ili Proizvoljno 2) STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}Klikni na glazbenu traku kako bi ju uklonio iz trenutnog programa (samo Proizvoljno 1 ili Proizvoljno 2) @@ -976,10 +977,10 @@ STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION :{BIG_FONT}{BLAC # Extra view window STR_EXTRA_VIEW_PORT_TITLE :{WHITE}Mini pogled {COMMA} -STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Kopiraj u mini pogled +STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Promijeni pogled STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN_TT :{BLACK}Kopiraj lokaciju globalnog pogleda u ovaj mini pogled -STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Zalijepi iz mini pogleda -STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT :{BLACK}Zalijepi lokaciju ovog mini pogleda u globalni pogled +STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Promijeni glavni pogled +STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT :{BLACK}Kopiraj lokaciju ovog mini pogleda u glavni pogled # Game options window STR_GAME_OPTIONS_CAPTION :{WHITE}Postavke igre @@ -1433,8 +1434,12 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Boja terena na STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :{G=female}Zelena STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :{G=female}Tamno zelena STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :{G=female}Ljubičasta -STR_CONFIG_SETTING_REVERSE_SCROLLING :Promijeni smjer klizanja: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Ponašanje kod pomicanja karte desnim gumbom miša. Kada je isključeno, miš pomiče kameru. Kada je uključeno, miš pomiče kartu +STR_CONFIG_SETTING_SCROLLMODE :Ponašanje klizanja kroz mini pogled: {STRING} +STR_CONFIG_SETTING_SCROLLMODE_HELPTEXT :Ponašanje kod klizanja kroz mapu +STR_CONFIG_SETTING_SCROLLMODE_DEFAULT :Pomiči mini pogled sa desnom tipkom miša, pozicija miša zaključana +STR_CONFIG_SETTING_SCROLLMODE_RMB_LOCKED :Pomiči mapu sa desnom tipkom miša, pozicija miša zaključana +STR_CONFIG_SETTING_SCROLLMODE_RMB :Pomiči mapu sa desnom tipkom miša +STR_CONFIG_SETTING_SCROLLMODE_LMB :Pomiči mapu sa lijevom tipkom miša STR_CONFIG_SETTING_SMOOTH_SCROLLING :Glatko klizanje kroz mini pogled: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Odredi kako se glavni prikaz pomiče na određeno mjesto kada se klikne na malu kartu ili kada se izda naredba za pomicanje na određeni objekt na karti. Ako je uključeno, prikaz se pomiče glatko, ako je isključeno, prikaz izravno skače na ciljnu lokaciju STR_CONFIG_SETTING_MEASURE_TOOLTIP :Pokaži mjerni naputak prilikom korištenja raznih alata za izgradnju: {STRING} @@ -1466,8 +1471,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command+klik STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Control+klik STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Isključeno -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Skrolanje lijevim klikom: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Uključi pomicanje karte povlačenjem pomoću lijevog gumba miša. Ovo je posebno korisno kada se koristi zaslon osjetljiv na dodir STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Zatvori prozor nakon desnog klika: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Zatvara prozor nakon desnog klika unutar prozora. S desnim klikom zatvaraju se i upute alata! @@ -2381,6 +2384,7 @@ STR_LINKGRAPH_LEGEND_CAPTION :{BLACK}Kazalo p STR_LINKGRAPH_LEGEND_ALL :{BLACK}Sve STR_LINKGRAPH_LEGEND_NONE :{BLACK}Ništa STR_LINKGRAPH_LEGEND_SELECT_COMPANIES :{BLACK}Odaberi tvrtke koje će se prikazati +STR_LINKGRAPH_LEGEND_COMPANY_TOOLTIP :{BLACK}{STRING}{}{COMPANY} # Linkgraph legend window and linkgraph legend in smallmap STR_LINKGRAPH_LEGEND_UNUSED :{TINY_FONT}{BLACK}nekorišten @@ -2789,6 +2793,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Izvorno STR_ABOUT_VERSION :{BLACK}OpenTTD verzija {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 OpenTTD tim +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Spremi igru STR_SAVELOAD_LOAD_CAPTION :{WHITE}Učitaj igru @@ -3073,6 +3084,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Unesi im STR_TOWN_DIRECTORY_CAPTION :{WHITE}Gradovi STR_TOWN_DIRECTORY_NONE :{ORANGE}- Ništa - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Grad){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Imena gradova - klikni na ime kako bi centrirao pogled na grad. Ctrl+klik otvara novi prozor sa lokacijom grada STR_TOWN_POPULATION :{BLACK}Svjetsko stanovništvo: {COMMA} @@ -3080,8 +3092,7 @@ STR_TOWN_POPULATION :{BLACK}Svjetsko STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Metropola) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Stanovništvo: {ORANGE}{COMMA}{BLACK} Kuće: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Putnika prošli mjesec: {ORANGE}{COMMA}{BLACK} najviše: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Pošte prošli mjesec: {ORANGE}{COMMA}{BLACK} najviše: {ORANGE}{COMMA} +STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX :{BLACK}{CARGO_LIST} prošli mjesec: {ORANGE}{COMMA}{BLACK} maks: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Potrebno tereta za rast grada: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} potrebno STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} potrebno zimi @@ -4328,6 +4339,7 @@ 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... @@ -4579,6 +4591,8 @@ STR_BASESOUNDS_DOS_DESCRIPTION :Originalni zvuk STR_BASESOUNDS_WIN_DESCRIPTION :Originalni zvukovi za Transport Tycoon Deluxe Windows izdanje. STR_BASESOUNDS_NONE_DESCRIPTION :Zvučni paket bez ikakvih zvukova. STR_BASEMUSIC_WIN_DESCRIPTION :Originalna glazba za Transport Tycoon Deluxe Windows izdanje. +STR_BASEMUSIC_DOS_DESCRIPTION :Originalna glazba za Transport Tycoon Deluxe DOS izdanje. +STR_BASEMUSIC_TTO_DESCRIPTION :Originalna glazba za Transport Tycoon (original/editor svijeta) DOS izdanje. STR_BASEMUSIC_NONE_DESCRIPTION :Glazbeni paket bez ikakve glazbe. ##id 0x2000 diff --git a/src/lang/czech.txt b/src/lang/czech.txt index cab72a7c92..6a9372de33 100644 --- a/src/lang/czech.txt +++ b/src/lang/czech.txt @@ -756,10 +756,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Zvolit p STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Zapnout/vypnout náhodné opakování skladeb STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Ukaž skladbu ve výběrovém okně -STR_ERROR_NO_SONGS :{WHITE}Byl vybrán hudební set bez písní. Nebudou přehrány žádné písně - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Volba programu hudby STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Index skladeb STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Program - '{STRING}' @@ -1424,8 +1421,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Barva terénu n STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :zelená STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :tmavě zelená STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :fialová -STR_CONFIG_SETTING_REVERSE_SCROLLING :Posouvat pohled opačným směrem: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Chování při posouvání mapy pomocí stisku pravého tlačítka myši. Pokud vypnuto, myš pohybuje kamerou. Pokud zapnuto, myš pohybuje mapou STR_CONFIG_SETTING_SMOOTH_SCROLLING :Plynulé posouvání po mapě: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Ovládá jak se hlavní pohled posouvá na specifické místo na mapě, kliknutím na minimapu nebo spuštěním příkazu na posun na specifický objekt na mapě. Pokud zapnuto, pohled se posouvá plynule, pokud vypnuto, skáče pohled přímo na cílové místo STR_CONFIG_SETTING_MEASURE_TOOLTIP :Ukázat rozměry při použití stavebních nástrojů: {STRING} @@ -1457,8 +1452,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command + klikn STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Control + kliknutí STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :vypnutá -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Posouvání levým tlačítkem: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Povolit posouvání mapy chycením pomocí levého tlačítka myši. Toto je velmi užitečné hlavně při použití s dotykovou obrazovkou. STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Zavírat okno kliknutím pravým tlačítkem myši: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Zavírat okno kliknutím pravým tlačítkem na něj. Znemožňuje využívat nápovědu zobrazující se při stisknutí pravého tlačítka myši! @@ -2786,6 +2779,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Původn STR_ABOUT_VERSION :{BLACK}OpenTTD verze {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 Tým OpenTTD +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Uložit hru STR_SAVELOAD_LOAD_CAPTION :{WHITE}Otevřít hru @@ -3077,8 +3077,6 @@ STR_TOWN_POPULATION :{BLACK}Populace STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (velkoměsto) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Populace: {ORANGE}{COMMA}{BLACK} Domů: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Cestujících minulý měsíc: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Pošta za minulý měsíc: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Množství doručeného nákladu potřebného pro rozvoj města: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{RED}Je potřeba {ORANGE}{STRING} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} vyžadováno v zimě diff --git a/src/lang/danish.txt b/src/lang/danish.txt index 3119390f3e..4b9ea6bf56 100644 --- a/src/lang/danish.txt +++ b/src/lang/danish.txt @@ -650,6 +650,7 @@ STR_MUSIC_RULER_MARKER :{TINY_FONT}{BLA STR_MUSIC_TRACK_NONE :{TINY_FONT}{DKGREEN}-- STR_MUSIC_TRACK_DIGIT :{TINY_FONT}{DKGREEN}{ZEROFILL_NUM} STR_MUSIC_TITLE_NONE :{TINY_FONT}{DKGREEN}------ +STR_MUSIC_TITLE_NOMUSIC :{TINY_FONT}{DKGREEN}Ingen musik tilgængelig STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKGREEN}"{STRING}" STR_MUSIC_TRACK :{TINY_FONT}{BLACK}Nummer STR_MUSIC_XTITLE :{TINY_FONT}{BLACK}Titel @@ -669,15 +670,13 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Select ' STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Tilfældig afspilning til/fra STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Vis vinduet med musiknummervalg -STR_ERROR_NO_SONGS :{WHITE}Det valgte musik sæt er uden sange. Der kan ikke afspilles musik. - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Musikprogram Valg STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Nummerliste STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Program - '{STRING}' STR_PLAYLIST_CLEAR :{TINY_FONT}{BLACK}Ryd STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Ryd det valgte program (Gælder kun Custom1/Custom2) +STR_PLAYLIST_TOOLTIP_CHANGE_SET :{BLACK}Ændre musik listen til et anden installeret sæt STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}Klik på et musiknummer for at tilføje det til programlisten (kun for Custom1/Custom2) STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}Klik på et musiknummer for at fjerne det fra programlisten (kun for Custom1/Custom2) @@ -1337,8 +1336,10 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Land farve brug STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Grøn STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Mørkegrøn STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Violet -STR_CONFIG_SETTING_REVERSE_SCROLLING :Flyt i modsat retning ved scroll med musen: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Adfærd når kortet rulles med højre museknap. Hvis deaktiveret, bevæger musen kameraet. Når funktionen er aktiveret, flytter musen kortet +STR_CONFIG_SETTING_SCROLLMODE_DEFAULT :Bevæg syns vinduet med højre mussetast, musse position låst +STR_CONFIG_SETTING_SCROLLMODE_RMB_LOCKED :Bevæg kortet med højre mussetast, musse position låst +STR_CONFIG_SETTING_SCROLLMODE_RMB :Bevæg kortet med højre musseknap +STR_CONFIG_SETTING_SCROLLMODE_LMB :Bevæg kortet med venstre musseknap STR_CONFIG_SETTING_SMOOTH_SCROLLING :Jævn scrolling af udsnit: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Kontroller hvordan de vigtigste visning ruller til en bestemt position, når du klikker på det lille kort eller når de udsteder en kommando til at rulle til en bestemt genstand på kortet. Hvis aktiveret, ruller udsigtspunktet jævnt, hvis deaktiveret springer den direkte til det valgte punkt STR_CONFIG_SETTING_MEASURE_TOOLTIP :Vis måleværktøjstip ved brug af div. bygge-værktøjer: {STRING} @@ -1370,8 +1371,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Kommandoklik STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Kontrolklik STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Fra -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Venstreklik-scrolling: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Aktiver rulle kortet ved at trække den med venstre museknap. Dette er især nyttigt, når du bruger en touch-screen til at rulle STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Luk vindue ved højre-klik: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Lukker vinduet ved at højreklikke inde i det. Deaktiverer værktøjstip ved at højreklikke! @@ -2693,6 +2692,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Original STR_ABOUT_VERSION :{BLACK}OpenTTD version {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 OpenTTD teamet +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Gem spil STR_SAVELOAD_LOAD_CAPTION :{WHITE}Hent spil @@ -2984,8 +2990,6 @@ STR_TOWN_POPULATION :{BLACK}Verdens STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (by) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Indbyggere: {ORANGE}{COMMA}{BLACK} Huse: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Passagerer sidste måned: {ORANGE}{COMMA}{BLACK} maks.: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Post sidste måned: {ORANGE}{COMMA}{BLACK} maks.: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Nødvendig godsmængde for at byen kan vokse: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} krævet STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} kræves om vinteren @@ -4232,6 +4236,7 @@ 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... diff --git a/src/lang/dutch.txt b/src/lang/dutch.txt index 383706f727..9b387f2f7c 100644 --- a/src/lang/dutch.txt +++ b/src/lang/dutch.txt @@ -476,7 +476,7 @@ STR_ABOUT_MENU_ZOOMIN_SCREENSHOT :Ingezoomd scree STR_ABOUT_MENU_DEFAULTZOOM_SCREENSHOT :Screenshot met standaard zoom STR_ABOUT_MENU_GIANT_SCREENSHOT :Screenshot van hele kaart STR_ABOUT_MENU_ABOUT_OPENTTD :Over 'OpenTTD' -STR_ABOUT_MENU_SPRITE_ALIGNER :Sprite uitlijner +STR_ABOUT_MENU_SPRITE_ALIGNER :Sprite-uitlijner STR_ABOUT_MENU_TOGGLE_BOUNDING_BOXES :Schakel selectiekaders STR_ABOUT_MENU_TOGGLE_DIRTY_BLOCKS :Schakel kleuren van braakliggende grond aan/uit ############ range ends here @@ -669,10 +669,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Selectee STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Programmashuffle aan/uit STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Toon nummerkeuzescherm -STR_ERROR_NO_SONGS :{WHITE}Er is een muziek set zonder liedjes gekozen. Er zal geen muziek worden gespeeld - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Muziekprogrammakeuze STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Nummerindex STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Programma - '{STRING}' @@ -1147,7 +1144,7 @@ STR_CONFIG_SETTING_RUNNING_COSTS :Onderhoudskoste STR_CONFIG_SETTING_RUNNING_COSTS_HELPTEXT :Het niveau van onderhoud en bedrijfskosten van voertuigen en infrastuctuur STR_CONFIG_SETTING_CONSTRUCTION_SPEED :Bouwsnelheid: {STRING} STR_CONFIG_SETTING_CONSTRUCTION_SPEED_HELPTEXT :Beperk de hoeveelheid bouwactiviteiten voor computerspeler -STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS :Voertuig storingen: {STRING} +STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS :Voertuigstoringen: {STRING} STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS_HELPTEXT :Controle hoe vaak onvoldoende onderhouden voertuigen kapot kunnen gaan STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER :Subsidie indicator: {STRING} STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER_HELPTEXT :Instellen hoeveel wordt betaald voor gesubsidieerde verbindingen @@ -1337,8 +1334,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Kleur van het t STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Groen STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Donker groen STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Violet -STR_CONFIG_SETTING_REVERSE_SCROLLING :Omgekeerde scrollrichting: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Gedrag wanneer gescrolld wordt door de map met de rechter muisknop. Indien uitgeschakeld bestuurd de muis de camera. Indien ingeschakeld bestuurd de muis de kaart. STR_CONFIG_SETTING_SMOOTH_SCROLLING :Vloeiend scrollen kijkvenster: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Bepalen hoe de hoofdweergave schuift naar een specifieke positie bij het klikken op de minikaart of bij de afgifte van een opdracht om naar een specifiek object op de kaart. Indien ingeschakeld, de viewport scrollt soepel, als deze uitgeschakeld gaat u rechtstreeks naar de beoogde plek STR_CONFIG_SETTING_MEASURE_TOOLTIP :Toon dimensie-informatie bij het gebruik van diverse bouwgereedschappen: {STRING} @@ -1370,8 +1365,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command-klik STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+klik STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Uit -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Scrollen met linkermuisknop: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Schakel scrollen met de linkermuisknop in door te slepen. Dit is vooral handig bij het gebruik van een touchscreen voor scrollen STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Sluit window met rechts-klik: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Sluit een venster door met de rechtermuisknop erin te klikken. Schakelt de tooltip uit met de rechtermuisknop! @@ -2693,6 +2686,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Originel STR_ABOUT_VERSION :{BLACK}OpenTTD versie {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 Het OpenTTD-team +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Spel Opslaan STR_SAVELOAD_LOAD_CAPTION :{WHITE}Spel Laden @@ -2984,8 +2984,6 @@ STR_TOWN_POPULATION :{BLACK}Wereldbe STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Groeistad) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Bevolking: {ORANGE}{COMMA}{BLACK} Huizen: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Passagiers afgelopen maand: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Post afgelopen maand: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Vracht nodig voor groei van stad: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} noodzakelijk STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} noodzakelijk in de winter diff --git a/src/lang/english.txt b/src/lang/english.txt index 258c02c6d6..1be1387061 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -475,6 +475,7 @@ STR_ABOUT_MENU_SCREENSHOT :Screenshot STR_ABOUT_MENU_ZOOMIN_SCREENSHOT :Fully zoomed in screenshot STR_ABOUT_MENU_DEFAULTZOOM_SCREENSHOT :Default zoom screenshot STR_ABOUT_MENU_GIANT_SCREENSHOT :Whole map screenshot +STR_ABOUT_MENU_SHOW_FRAMERATE :Show frame rate STR_ABOUT_MENU_ABOUT_OPENTTD :About 'OpenTTD' STR_ABOUT_MENU_SPRITE_ALIGNER :Sprite aligner STR_ABOUT_MENU_TOGGLE_BOUNDING_BOXES :Toggle bounding boxes @@ -650,6 +651,7 @@ STR_MUSIC_RULER_MARKER :{TINY_FONT}{BLA STR_MUSIC_TRACK_NONE :{TINY_FONT}{DKGREEN}-- STR_MUSIC_TRACK_DIGIT :{TINY_FONT}{DKGREEN}{ZEROFILL_NUM} STR_MUSIC_TITLE_NONE :{TINY_FONT}{DKGREEN}------ +STR_MUSIC_TITLE_NOMUSIC :{TINY_FONT}{DKGREEN}No music available STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKGREEN}"{RAW_STRING}" STR_MUSIC_TRACK :{TINY_FONT}{BLACK}Track STR_MUSIC_XTITLE :{TINY_FONT}{BLACK}Title @@ -669,15 +671,15 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Select ' STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Toggle programme shuffle on/off STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Show music track selection window -STR_ERROR_NO_SONGS :{WHITE}A music set without songs has been selected. No songs will be played - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Music Programme Selection +STR_PLAYLIST_MUSIC_SELECTION_SETNAME :{WHITE}Music Programme - '{RAW_STRING}' STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{RAW_STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Track Index STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Programme - '{STRING}' STR_PLAYLIST_CLEAR :{TINY_FONT}{BLACK}Clear +STR_PLAYLIST_CHANGE_SET :{BLACK}Change set STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Clear current programme (Custom1 or Custom2 only) +STR_PLAYLIST_TOOLTIP_CHANGE_SET :{BLACK}Change music selection to another installed set STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}Click on music track to add to current programme (Custom1 or Custom2 only) STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}Click on music track to remove it from current programme (Custom1 or Custom2 only) @@ -880,10 +882,10 @@ STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION :{BIG_FONT}{BLAC # Extra view window STR_EXTRA_VIEW_PORT_TITLE :{WHITE}Viewport {COMMA} -STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Copy to viewport +STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Change viewport STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN_TT :{BLACK}Copy the location of the main view to this viewport -STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Paste from viewport -STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT :{BLACK}Paste the location of this viewport to the main view +STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Change main view +STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT :{BLACK}Copy the location of this viewport to the main view # Game options window STR_GAME_OPTIONS_CAPTION :{WHITE}Game Options @@ -1337,8 +1339,12 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Colour of the t STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Green STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Dark green STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Violet -STR_CONFIG_SETTING_REVERSE_SCROLLING :Reverse scroll direction: {STRING2} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Behaviour when scrolling the map with the right mouse button. When disabled, the mouse moves the camera. When enabled, the mouse moves the map +STR_CONFIG_SETTING_SCROLLMODE :Viewport scroll behaviour: {STRING2} +STR_CONFIG_SETTING_SCROLLMODE_HELPTEXT :Behaviour when scrolling the map +STR_CONFIG_SETTING_SCROLLMODE_DEFAULT :Move viewport with RMB, mouse position locked +STR_CONFIG_SETTING_SCROLLMODE_RMB_LOCKED :Move map with RMB, mouse position locked +STR_CONFIG_SETTING_SCROLLMODE_RMB :Move map with RMB +STR_CONFIG_SETTING_SCROLLMODE_LMB :Move map with LMB STR_CONFIG_SETTING_SMOOTH_SCROLLING :Smooth viewport scrolling: {STRING2} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Control how the main view scrolls to a specific position when clicking on the smallmap or when issuing a command to scroll to a specific object on the map. If enabled, the viewport scrolls smoothly, if disabled it jumps directly to the targeted spot STR_CONFIG_SETTING_MEASURE_TOOLTIP :Show a measurement tooltip when using various build-tools: {STRING2} @@ -1370,8 +1376,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command+Click STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+Click STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Off -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Left-click scrolling: {STRING2} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Enable scrolling the map by dragging it with the left mouse button. This is especially useful when using a touch-screen for scrolling STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Close window on right-click: {STRING2} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Closes a window by right-clicking inside it. Disables the tooltip on right-click! @@ -2285,6 +2289,7 @@ STR_LINKGRAPH_LEGEND_CAPTION :{BLACK}Cargo Fl STR_LINKGRAPH_LEGEND_ALL :{BLACK}All STR_LINKGRAPH_LEGEND_NONE :{BLACK}None STR_LINKGRAPH_LEGEND_SELECT_COMPANIES :{BLACK}Select companies to be displayed +STR_LINKGRAPH_LEGEND_COMPANY_TOOLTIP :{BLACK}{STRING}{}{COMPANY} # Linkgraph legend window and linkgraph legend in smallmap STR_LINKGRAPH_LEGEND_UNUSED :{TINY_FONT}{BLACK}unused @@ -2693,6 +2698,56 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Original STR_ABOUT_VERSION :{BLACK}OpenTTD version {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 The OpenTTD team +# Framerate display window +STR_FRAMERATE_CAPTION :{WHITE}Frame rate +STR_FRAMERATE_CAPTION_SMALL :{STRING2}{WHITE} ({DECIMAL}x) +STR_FRAMERATE_RATE_GAMELOOP :{WHITE}Simulation rate: {STRING2} +STR_FRAMERATE_RATE_GAMELOOP_TOOLTIP :{BLACK}Number of game ticks simulated per second. +STR_FRAMERATE_RATE_BLITTER :{WHITE}Graphics frame rate: {STRING2} +STR_FRAMERATE_RATE_BLITTER_TOOLTIP :{BLACK}Number of video frames rendered per second. +STR_FRAMERATE_SPEED_FACTOR :{WHITE}Current game speed factor: {DECIMAL}x +STR_FRAMERATE_SPEED_FACTOR_TOOLTIP :{BLACK}How fast the game is currently running, compared to the expected speed at normal simulation rate. +STR_FRAMERATE_CURRENT :{WHITE}Current +STR_FRAMERATE_AVERAGE :{WHITE}Average +STR_FRAMERATE_DATA_POINTS :{WHITE}Data based on {COMMA} measurements +STR_FRAMERATE_MS_GOOD :{LTBLUE}{DECIMAL}{WHITE} ms +STR_FRAMERATE_MS_WARN :{YELLOW}{DECIMAL}{WHITE} ms +STR_FRAMERATE_MS_BAD :{RED}{DECIMAL}{WHITE} ms +STR_FRAMERATE_FPS_GOOD :{LTBLUE}{DECIMAL}{WHITE} frames/s +STR_FRAMERATE_FPS_WARN :{YELLOW}{DECIMAL}{WHITE} frames/s +STR_FRAMERATE_FPS_BAD :{RED}{DECIMAL}{WHITE} frames/s +STR_FRAMERATE_GRAPH_MILLISECONDS :{TINY_FONT}{COMMA} ms +STR_FRAMERATE_GRAPH_SECONDS :{TINY_FONT}{COMMA} s +############ Leave those lines in this order!! +STR_FRAMERATE_GAMELOOP :{WHITE}Game loop total: +STR_FRAMERATE_GL_ECONOMY :{WHITE} Cargo handling: +STR_FRAMERATE_GL_TRAINS :{WHITE} Train ticks: +STR_FRAMERATE_GL_ROADVEHS :{WHITE} Road vehicle ticks: +STR_FRAMERATE_GL_SHIPS :{WHITE} Ship ticks: +STR_FRAMERATE_GL_AIRCRAFT :{WHITE} Aircraft ticks: +STR_FRAMERATE_GL_LANDSCAPE :{WHITE} World ticks: +STR_FRAMERATE_GL_LINKGRAPH :{WHITE} Link graph delay: +STR_FRAMERATE_DRAWING :{WHITE}Graphics rendering: +STR_FRAMERATE_DRAWING_VIEWPORTS :{WHITE} World viewports: +STR_FRAMERATE_VIDEO :{WHITE}Video output: +STR_FRAMERATE_SOUND :{WHITE}Sound mixing: +############ End of leave-in-this-order +############ Leave those lines in this order!! +STR_FRAMETIME_CAPTION_GAMELOOP :Game loop +STR_FRAMETIME_CAPTION_GL_ECONOMY :Cargo handling +STR_FRAMETIME_CAPTION_GL_TRAINS :Train ticks +STR_FRAMETIME_CAPTION_GL_ROADVEHS :Road vehicle ticks +STR_FRAMETIME_CAPTION_GL_SHIPS :Ship ticks +STR_FRAMETIME_CAPTION_GL_AIRCRAFT :Aircraft ticks +STR_FRAMETIME_CAPTION_GL_LANDSCAPE :World ticks +STR_FRAMETIME_CAPTION_GL_LINKGRAPH :Link graph delay +STR_FRAMETIME_CAPTION_DRAWING :Graphics rendering +STR_FRAMETIME_CAPTION_DRAWING_VIEWPORTS :World viewport rendering +STR_FRAMETIME_CAPTION_VIDEO :Video output +STR_FRAMETIME_CAPTION_SOUND :Sound mixing +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Save Game STR_SAVELOAD_LOAD_CAPTION :{WHITE}Load Game @@ -2977,6 +3032,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Enter a STR_TOWN_DIRECTORY_CAPTION :{WHITE}Towns STR_TOWN_DIRECTORY_NONE :{ORANGE}- None - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (City){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Town names - click on name to centre main view on town. Ctrl+Click opens a new viewport on town location STR_TOWN_POPULATION :{BLACK}World population: {COMMA} @@ -2984,8 +3040,7 @@ STR_TOWN_POPULATION :{BLACK}World po STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (City) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Population: {ORANGE}{COMMA}{BLACK} Houses: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Passengers last month: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Mail last month: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} +STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX :{BLACK}{CARGO_LIST} last month: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Cargo needed for town growth: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} required STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} required in winter @@ -4232,6 +4287,7 @@ 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... @@ -4483,6 +4539,8 @@ STR_BASESOUNDS_DOS_DESCRIPTION :Original Transp STR_BASESOUNDS_WIN_DESCRIPTION :Original Transport Tycoon Deluxe Windows edition sounds. STR_BASESOUNDS_NONE_DESCRIPTION :A sound pack without any sounds. STR_BASEMUSIC_WIN_DESCRIPTION :Original Transport Tycoon Deluxe Windows edition music. +STR_BASEMUSIC_DOS_DESCRIPTION :Original Transport Tycoon Deluxe DOS edition music. +STR_BASEMUSIC_TTO_DESCRIPTION :Original Transport Tycoon (Original/World Editor) DOS edition music. STR_BASEMUSIC_NONE_DESCRIPTION :A music pack without actual music. ##id 0x2000 diff --git a/src/lang/english_AU.txt b/src/lang/english_AU.txt index 8d51d06660..52ff246da3 100644 --- a/src/lang/english_AU.txt +++ b/src/lang/english_AU.txt @@ -660,10 +660,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Select ' STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Toggle programme shuffle on/off STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Show music track selection window -STR_ERROR_NO_SONGS :{WHITE}A music set without songs has been selected. No songs will be played - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Music Programme Selection STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Track Index STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Programme - '{STRING}' @@ -1316,8 +1313,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Colour of the t STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Green STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Dark green STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Violet -STR_CONFIG_SETTING_REVERSE_SCROLLING :Reverse scroll direction: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Behaviour when scrolling the map with the right mouse button. When disabled, the mouse moves the camera. When enabled, the mouse moves the map STR_CONFIG_SETTING_SMOOTH_SCROLLING :Smooth viewport scrolling: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Control how the main view scrolls to a specific position when clicking on the smallmap or when issuing a command to scroll to a specific object on the map. If enabled, the viewport scrolls smoothly, if disabled it jumps directly to the targeted spot STR_CONFIG_SETTING_MEASURE_TOOLTIP :Show a measurement tooltip when using various build-tools: {STRING} @@ -1349,8 +1344,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command+Click STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+Click STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Off -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Left-click scrolling: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Enable scrolling the map by dragging it with the left mouse button. This is especially useful when using a touch-screen for scrolling STR_CONFIG_SETTING_AUTOSAVE :Autosave: {STRING} STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :Select interval between automatic game saves @@ -2664,6 +2657,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Original STR_ABOUT_VERSION :{BLACK}OpenTTD version {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 The OpenTTD team +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Save Game STR_SAVELOAD_LOAD_CAPTION :{WHITE}Load Game @@ -2947,8 +2947,6 @@ STR_TOWN_POPULATION :{BLACK}World po STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (City) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Population: {ORANGE}{COMMA}{BLACK} Houses: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Passengers last month: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Mail last month: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Cargo needed for town growth: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} required STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} required in winter diff --git a/src/lang/english_US.txt b/src/lang/english_US.txt index 86519ddc61..6126be2e85 100644 --- a/src/lang/english_US.txt +++ b/src/lang/english_US.txt @@ -650,6 +650,7 @@ STR_MUSIC_RULER_MARKER :{TINY_FONT}{BLA STR_MUSIC_TRACK_NONE :{TINY_FONT}{DKGREEN}-- STR_MUSIC_TRACK_DIGIT :{TINY_FONT}{DKGREEN}{ZEROFILL_NUM} STR_MUSIC_TITLE_NONE :{TINY_FONT}{DKGREEN}------ +STR_MUSIC_TITLE_NOMUSIC :{TINY_FONT}{DKGREEN}No music available STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKGREEN}"{STRING}" STR_MUSIC_TRACK :{TINY_FONT}{BLACK}Track STR_MUSIC_XTITLE :{TINY_FONT}{BLACK}Title @@ -669,15 +670,15 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Select ' STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Toggle program shuffle on/off STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Show music track selection window -STR_ERROR_NO_SONGS :{WHITE}A music set without songs has been selected. No songs will be played - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Music Program Selection +STR_PLAYLIST_MUSIC_SELECTION_SETNAME :{WHITE}Music Program - '{STRING}' STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Track Index STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Program - '{STRING}' STR_PLAYLIST_CLEAR :{TINY_FONT}{BLACK}Clear +STR_PLAYLIST_CHANGE_SET :{BLACK}Change set STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Clear current program (Custom1 or Custom2 only) +STR_PLAYLIST_TOOLTIP_CHANGE_SET :{BLACK}Change music selection to another installed set STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}Click on music track to add to current program (Custom1 or Custom2 only) STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}Click on music track to remove it from current program (Custom1 or Custom2 only) @@ -880,10 +881,10 @@ STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION :{BIG_FONT}{BLAC # Extra view window STR_EXTRA_VIEW_PORT_TITLE :{WHITE}Viewport {COMMA} -STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Copy to viewport +STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Change viewport STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN_TT :{BLACK}Copy the location of the main view to this viewport -STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Paste from viewport -STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT :{BLACK}Paste the location of this viewport to the main view +STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Change main view +STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT :{BLACK}Copy the location of this viewport to the main view # Game options window STR_GAME_OPTIONS_CAPTION :{WHITE}Game Options @@ -1337,8 +1338,12 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Color of the te STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Green STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Dark green STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Purple -STR_CONFIG_SETTING_REVERSE_SCROLLING :Reverse scroll direction: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Behavior when scrolling the map with the right mouse button. When disabled, the mouse moves the camera. When enabled, the mouse moves the map +STR_CONFIG_SETTING_SCROLLMODE :Viewport scroll behaviour: {STRING} +STR_CONFIG_SETTING_SCROLLMODE_HELPTEXT :Behavior when scrolling the map +STR_CONFIG_SETTING_SCROLLMODE_DEFAULT :Move viewport with RMB, mouse position locked +STR_CONFIG_SETTING_SCROLLMODE_RMB_LOCKED :Move map with RMB, mouse position locked +STR_CONFIG_SETTING_SCROLLMODE_RMB :Move map with RMB +STR_CONFIG_SETTING_SCROLLMODE_LMB :Move map with LMB STR_CONFIG_SETTING_SMOOTH_SCROLLING :Smooth viewport scrolling: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Control how the main view scrolls to a specific position when clicking on the smallmap or when issuing a command to scroll to a specific object on the map. If enabled, the viewport scrolls smoothly, if disabled it jumps directly to the targeted spot STR_CONFIG_SETTING_MEASURE_TOOLTIP :Show a measurement tooltip when using various build-tools: {STRING} @@ -1370,8 +1375,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command+Click STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+Click STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Off -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Left-click scrolling: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Enable scrolling the map by dragging it with the left mouse button. This is especially useful when using a touch-screen for scrolling STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Close window on right-click: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Closes a window by right-clicking inside it. Disables the tooltip on right-click! @@ -2285,6 +2288,7 @@ STR_LINKGRAPH_LEGEND_CAPTION :{BLACK}Cargo Fl STR_LINKGRAPH_LEGEND_ALL :{BLACK}All STR_LINKGRAPH_LEGEND_NONE :{BLACK}None STR_LINKGRAPH_LEGEND_SELECT_COMPANIES :{BLACK}Select companies to be displayed +STR_LINKGRAPH_LEGEND_COMPANY_TOOLTIP :{BLACK}{STRING}{}{COMPANY} # Linkgraph legend window and linkgraph legend in smallmap STR_LINKGRAPH_LEGEND_UNUSED :{TINY_FONT}{BLACK}unused @@ -2693,6 +2697,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Original STR_ABOUT_VERSION :{BLACK}OpenTTD version {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 The OpenTTD team +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Save Game STR_SAVELOAD_LOAD_CAPTION :{WHITE}Load Game @@ -2977,6 +2988,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Enter a STR_TOWN_DIRECTORY_CAPTION :{WHITE}Towns STR_TOWN_DIRECTORY_NONE :{ORANGE}- None - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (City){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Town names - click on name to center main view on town. Ctrl+Click opens a new viewport on town location STR_TOWN_POPULATION :{BLACK}World population: {COMMA} @@ -2984,8 +2996,7 @@ STR_TOWN_POPULATION :{BLACK}World po STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (City) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Population: {ORANGE}{COMMA}{BLACK} Houses: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Passengers last month: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Mail last month: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} +STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX :{BLACK}{CARGO_LIST} last month: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Cargo needed for town growth: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} required STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} required in winter @@ -4232,6 +4243,7 @@ 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... @@ -4483,6 +4495,8 @@ STR_BASESOUNDS_DOS_DESCRIPTION :Original Transp STR_BASESOUNDS_WIN_DESCRIPTION :Original Transport Tycoon Deluxe Windows edition sounds. STR_BASESOUNDS_NONE_DESCRIPTION :A sound pack without any sounds. STR_BASEMUSIC_WIN_DESCRIPTION :Original Transport Tycoon Deluxe Windows edition music. +STR_BASEMUSIC_DOS_DESCRIPTION :Original Transport Tycoon Deluxe DOS edition music. +STR_BASEMUSIC_TTO_DESCRIPTION :Original Transport Tycoon (Original/World Editor) DOS edition music. STR_BASEMUSIC_NONE_DESCRIPTION :A music pack without actual music. ##id 0x2000 diff --git a/src/lang/esperanto.txt b/src/lang/esperanto.txt index 949fdb0d2c..8b445cb735 100644 --- a/src/lang/esperanto.txt +++ b/src/lang/esperanto.txt @@ -663,10 +663,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Elektu l STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Miksu/ne miksu STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Montru muziker-elektan fenestron -STR_ERROR_NO_SONGS :{WHITE}Senkanta muzikaro estas elektita. Neniu kanto ludos. - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Elekto de Muzikprogramo STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Numera Indekso STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Programo - '{STRING}' @@ -1199,7 +1196,6 @@ STR_CONFIG_SETTING_LINK_TERRAFORM_TOOLBAR :Ligu landaspekt STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Verda STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Malhele verda STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Viola -STR_CONFIG_SETTING_REVERSE_SCROLLING :Inversigu skroldirekton: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING :Glata rulumado de vidujo: {STRING} STR_CONFIG_SETTING_MEASURE_TOOLTIP :Montru mezuran konsilbalonon ĉe uzo de konstruiloj: {STRING} STR_CONFIG_SETTING_LIVERIES :Montru veturiltipe specifajn liverojn: {STRING} @@ -1223,7 +1219,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Komando+Klako STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+Klako STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Ne -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Maldekstr-klak-rulumado: {STRING} STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES :Uzu la {STRING} datformon por nomoj de konservludoj. @@ -2267,6 +2262,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Origina STR_ABOUT_VERSION :{BLACK}OpenTTD-versio {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2018 La teamo de OpenTTD +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Konservu Ludon STR_SAVELOAD_LOAD_CAPTION :{WHITE}Ŝarĝu Ludon @@ -2514,8 +2516,6 @@ STR_TOWN_POPULATION :{BLACK}Monda en STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Urbo) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Enloĝantoj: {ORANGE}{COMMA}{BLACK} Domoj: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Pasaĝeroj lastmonate: {ORANGE}{COMMA}{BLACK} maksimume: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Poŝto lastmonate: {ORANGE}{COMMA}{BLACK} maksimume: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Kargo bezonata por kreskigi urbon: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} bezonatas STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} bezonatas en vintro diff --git a/src/lang/estonian.txt b/src/lang/estonian.txt index 344f099741..80c27eebf6 100644 --- a/src/lang/estonian.txt +++ b/src/lang/estonian.txt @@ -726,10 +726,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Vali 'om STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Lülita lugude segamine sisse ja välja STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Näita muusikalugude valimise akent -STR_ERROR_NO_SONGS :{WHITE}Valitud muusikakomplekt ei sisalda ühtegi lugu. Ühtegi lugu ei esitata - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Muusikaprogrammi valimine STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Loo number STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Programm - '{STRING}' @@ -1394,8 +1391,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Maa värv väik STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Roheline STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Tumeroheline STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Violetne -STR_CONFIG_SETTING_REVERSE_SCROLLING :Vaade liigub vastassuunas: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Vaate liigutamine parema hiireklahviga. Kui see on välja lülitatud, siis hiireosuti juhib vaatepunkti. Kui sisse, siis kaarti STR_CONFIG_SETTING_SMOOTH_SCROLLING :Vaade keskendatakse sujuvalt: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Vaateakna asukohale keskendamise viis, kui vajutatakse väikesele kaardile, või kui vaade keskendatakse mõnele rekvisiidile. Sisse lülitades on liikumine sujuv, välja lülitades läheb vaade kohe sihtpunkti STR_CONFIG_SETTING_MEASURE_TOOLTIP :Ehitamisel mõõtude arvesti näitamine: {STRING} @@ -1427,8 +1422,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command+klõps STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+klõps STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Väljas -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Vaate liigutamine vasaku hiireklahviga: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Lubab kaardi liigutamise vasaku hiireklahvi abil. See lihtsustab mängimist puutetundlikul ekraanil STR_CONFIG_SETTING_AUTOSAVE :Automaatne salvestamine: {STRING} STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :Vali automaatse salvestamise intervall @@ -2747,6 +2740,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Algne au STR_ABOUT_VERSION :{BLACK}OpenTTD osa {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2018 OpenTTD meeskond +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Mängu salvestamine STR_SAVELOAD_LOAD_CAPTION :{WHITE}Mängu jätkamine @@ -3038,8 +3038,6 @@ STR_TOWN_POPULATION :{BLACK}Maailma STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Linn) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Rahvaarv: {ORANGE}{COMMA}{BLACK} Ehitisi: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Reisijaid eelmisel kuul: {ORANGE}{COMMA}{BLACK} Enim: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Posti eelmisel kuul: {ORANGE}{COMMA}{BLACK} Enim: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Veoseid linna kasvamiseks: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} vajalik STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} on talvel vajalik diff --git a/src/lang/faroese.txt b/src/lang/faroese.txt index 4d90facad2..2eb53ca217 100644 --- a/src/lang/faroese.txt +++ b/src/lang/faroese.txt @@ -647,10 +647,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Vel 'Sj STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Tendra/sløkk bland av skránni STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Vís tónleika spor úrvals glugga -STR_ERROR_NO_SONGS :{WHITE}Eitt tónleika sett uttan sangir er valt. Engir sangir vera spældir - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Úrval av tónleika skráðum STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Spor yvirlit STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Skrá - '{STRING}' @@ -1273,8 +1270,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Liturin av lend STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Grønt STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Myrka grønt STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Blákollulitur -STR_CONFIG_SETTING_REVERSE_SCROLLING :Umvend skrull ætt: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Atburður tá tú skrullar korti við høgra músa knøtti. Um ógilda flytir músin kamerai. Um gilda flytir músin korti. STR_CONFIG_SETTING_SMOOTH_SCROLLING :Mjúka sýnisglugga skrulling: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Stýr hvussu høvuðs sýni skrullar til eitt ávíst stað tá tú trýstir á lítlakorti ella tú tú gevur eini boð um at skrulla til ein ávísan lut á kortinum. Um gilda, skrullar sýni mjúgdliga, um ógilda leypur sýni beint til staði STR_CONFIG_SETTING_MEASURE_TOOLTIP :Vís eina mátingar vegleiðing tá tú brúkar ymisku byggji amboðini: {STRING} @@ -1306,8 +1301,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command+trýst STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+trýst STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Sløkt -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Vinstra-trýst skrulling: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Gilda skrulling av kortinum við at toga ta við vinstra músa knøtti. Hetta er serstakliga hent um tú nýtur ein fingraskugga at skrulla vi STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES :Nýt {STRING} dato sniði til nøvnini á goymdum spølum @@ -2429,6 +2422,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Upprunal STR_ABOUT_VERSION :{BLACK}OpenTTD útgáva {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 OpenTTD toymi +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Goym spæl STR_SAVELOAD_LOAD_CAPTION :{WHITE}Heinta spæl @@ -2650,8 +2650,6 @@ STR_TOWN_POPULATION :{BLACK}Heims f STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Býur) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Fólkatal: {ORANGE}{COMMA}{BLACK} Hús: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Ferðafólk síðsta mánað: {ORANGE}{COMMA}{BLACK} maks: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Postur síðsta mánað: {ORANGE}{COMMA}{BLACK} maks: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Farmur ið tørvast fyri bygda menning: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} krevst STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} krevst um veturin diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt index b53a762c9b..65f7e27286 100644 --- a/src/lang/finnish.txt +++ b/src/lang/finnish.txt @@ -475,7 +475,7 @@ STR_ABOUT_MENU_SCREENSHOT :Kuvakaappaus STR_ABOUT_MENU_ZOOMIN_SCREENSHOT :Täysin lähennetty kuvakaappaus STR_ABOUT_MENU_DEFAULTZOOM_SCREENSHOT :Kuvakaappaus oletuslähennystasolla STR_ABOUT_MENU_GIANT_SCREENSHOT :Koko kartan kuvakaappaus -STR_ABOUT_MENU_ABOUT_OPENTTD :Tietoja 'OpenTTD':stä +STR_ABOUT_MENU_ABOUT_OPENTTD :Tietoja OpenTTD:stä STR_ABOUT_MENU_SPRITE_ALIGNER :Sprite-kohdistaja STR_ABOUT_MENU_TOGGLE_BOUNDING_BOXES :Reunat päälle/pois STR_ABOUT_MENU_TOGGLE_DIRTY_BLOCKS :Likaisten ruutujen värjäys päälle/pois @@ -669,10 +669,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Valitse STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Sekoittaminen päälle/pois STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Näytä musiikkiraitojen valintaikkuna -STR_ERROR_NO_SONGS :{WHITE}Musiikkipaketti jossa ei ole kappaleita on valittu. Musiikkia ei soiteta - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Soittolistan valinta STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Raita STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Soittolista - '{STRING}' @@ -780,12 +777,12 @@ STR_NEWS_MESSAGE_CAPTION :{WHITE}Viesti STR_NEWS_CUSTOM_ITEM :{BIG_FONT}{BLACK}{STRING} STR_NEWS_FIRST_TRAIN_ARRIVAL :{BIG_FONT}{BLACK}Kaupunkilaiset juhlivat . . .{}Ensimmäinen juna saapuu asemalle {STATION}! -STR_NEWS_FIRST_BUS_ARRIVAL :{BIG_FONT}{BLACK}Kaupunkilaiset juhlivat . . .{}Ensimmäinen linja-auto saapuu asemalle {STATION}! -STR_NEWS_FIRST_TRUCK_ARRIVAL :{BIG_FONT}{BLACK}Kaupunkilaiset juhlivat . . .{}Ensimmäinen kuorma-auto saapuu asemalle {STATION}! -STR_NEWS_FIRST_PASSENGER_TRAM_ARRIVAL :{BIG_FONT}{BLACK}Kaupunkilaiset juhlivat . . .{}Ensimmäinen raitiovaunu saapuu asemalle {STATION}! -STR_NEWS_FIRST_CARGO_TRAM_ARRIVAL :{BIG_FONT}{BLACK}Kaupunkilaiset juhlivat . . .{}Ensimmäinen rahtiraitiovaunu saapuu asemalle {STATION}! -STR_NEWS_FIRST_SHIP_ARRIVAL :{BIG_FONT}{BLACK}Kaupunkilaiset juhlivat . . .{}Ensimmäinen laiva saapuu asemalle {STATION}! -STR_NEWS_FIRST_AIRCRAFT_ARRIVAL :{BIG_FONT}{BLACK}Kaupunkilaiset juhlivat . . .{}Ensimmäinen lentokone saapuu asemalle {STATION}! +STR_NEWS_FIRST_BUS_ARRIVAL :{BIG_FONT}{BLACK}Kaupunkilaiset juhlivat . . .{}{STATION} vastaanottaa ensimmäisen linja-auton! +STR_NEWS_FIRST_TRUCK_ARRIVAL :{BIG_FONT}{BLACK}Kaupunkilaiset juhlivat . . .{}{STATION} vastaanottaa ensimmäisen kuorma-auton! +STR_NEWS_FIRST_PASSENGER_TRAM_ARRIVAL :{BIG_FONT}{BLACK}Kaupunkilaiset juhlivat . . .{}{STATION} vastaanottaa ensimmäisen raitiovaunun! +STR_NEWS_FIRST_CARGO_TRAM_ARRIVAL :{BIG_FONT}{BLACK}Kaupunkilaiset juhlivat . . .{}{STATION} vastaanottaa ensimmäisen rahtiraitiovaunun! +STR_NEWS_FIRST_SHIP_ARRIVAL :{BIG_FONT}{BLACK}Kaupunkilaiset juhlivat . . .{}{STATION} vastaanottaa ensimmäisen laivan! +STR_NEWS_FIRST_AIRCRAFT_ARRIVAL :{BIG_FONT}{BLACK}Kaupunkilaiset juhlivat . . .{}{STATION} vastaanottaa ensimmäisen lentokoneen! STR_NEWS_TRAIN_CRASH :{BIG_FONT}{BLACK}Junaonnettomuus!{}{COMMA} kuolee törmäyksen jälkeisessä tulipallossa. STR_NEWS_ROAD_VEHICLE_CRASH_DRIVER :{BIG_FONT}{BLACK}Tasoristeysturma!{}Kuljettaja kuolee junan ja auton törmäyksen jälkeisessä tulipallossa @@ -927,10 +924,10 @@ STR_GAME_OPTIONS_CURRENCY_GEL :Georgian lari ( STR_GAME_OPTIONS_CURRENCY_IRR :Iranin rial (IRR) ############ end of currency region -STR_GAME_OPTIONS_ROAD_VEHICLES_FRAME :{BLACK}Ajoneuvot +STR_GAME_OPTIONS_ROAD_VEHICLES_FRAME :{BLACK}Kulkuneuvot STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_TOOLTIP :{BLACK}Valitse kummalla puolella tietä ajetaan. -STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Vasemmalla kaistalla -STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :Oikealla kaistalla +STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Vasemmanpuolinen liikenne +STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :Oikeanpuolinen liikenne STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Kaupunkien nimet STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}Valitse kaupunkien nimien tyyli. @@ -1096,11 +1093,11 @@ STR_CONFIG_SETTING_COLLAPSE_ALL :{BLACK}Sulje ka STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT :(selitystä ei saatavilla) STR_CONFIG_SETTING_DEFAULT_VALUE :{LTBLUE}Oletusarvo: {ORANGE}{STRING} STR_CONFIG_SETTING_TYPE :{LTBLUE}Asetuksen tyyppi: {ORANGE}{STRING} -STR_CONFIG_SETTING_TYPE_CLIENT :Yleinen asetus (ei tallenneta tallenteisiin; vaikuttaa kaikkiin peleihin) +STR_CONFIG_SETTING_TYPE_CLIENT :Yleinen asetus (ei tallenneta tallennuksiin; vaikuttaa kaikkiin peleihin) STR_CONFIG_SETTING_TYPE_GAME_MENU :Pelin asetus (tallennetaan tallenteisiin; vaikuttaa vain uusiin peleihin) STR_CONFIG_SETTING_TYPE_GAME_INGAME :Pelin asetus (tallennetaan tallenteeseen; vaikuttaa vain nykyiseen peliin) STR_CONFIG_SETTING_TYPE_COMPANY_MENU :Yhtiön asetus (tallennetaan tallenteisiin; vaikuttaa vain uusiin peleihin) -STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :Yhtiön asetus (tallennetaan tallenteeseen; vaikuttaa vain nykyiseen yhtiöön) +STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :Yhtiön asetus (tallennetaan tallennukseen; vaikuttaa vain nykyiseen yhtiöön) STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}Kategoria: STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}Tyyppi: @@ -1337,8 +1334,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Maaston väri k STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Vihreä STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Tummanvihreä STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Violetti -STR_CONFIG_SETTING_REVERSE_SCROLLING :Käänteinen vierityssuunta: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Käyttäytyminen siirrettäessä näkymää oikealla hiiren näppäimellä. Mikäli pois käytöstä, hiiri liikuttaa kameraa. Mikäli käytössä, hiiri liikuttaa karttaa STR_CONFIG_SETTING_SMOOTH_SCROLLING :Näkymän tasainen vieritys: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Hallitse miten päänäkymä siirtyy valittuun paikkaan karttaa klikattaessa tai käytettäessä komentoa joka muuttaa näkymän sijaintia. Mikäli käytössä, päänäkymä siirtyy uuteen sijaintiin pehmeäesti, muutoin se hyppää suoraan valittuun sijaintiin STR_CONFIG_SETTING_MEASURE_TOOLTIP :Näytä mittauksen työkaluvihje, kun käytetään rakennustyökaluja: {STRING} @@ -1370,8 +1365,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+Klik STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Pois -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Vasemmalla hiiren painikkeella liikkuminen: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Salli näkymän siirtäminen vetämällä hiiren vasemmalla näppäimellä. Hyödyllinen erityisesti kosketusnäyttöä käytettäessä STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Sulje ikkuna hiiren oikealla painikkeella napsauttamalla: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Ikkunat sulkeutuvat, kun niitä napsautetaan hiiren oikealla painikkeella. Tämä korvaa tavallisesti näkyvän työkaluvihjeen! @@ -2693,6 +2686,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Alkuper STR_ABOUT_VERSION :{BLACK}OpenTTD-versio {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 The OpenTTD team +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Tallenna peli STR_SAVELOAD_LOAD_CAPTION :{WHITE}Lataa peli @@ -2723,9 +2723,9 @@ STR_MAPGEN_WORLD_GENERATION_CAPTION :{WHITE}Maailman STR_MAPGEN_MAPSIZE :{BLACK}Kartan koko: STR_MAPGEN_MAPSIZE_TOOLTIP :{BLACK}Valitse kartan koko ruutuina. Saatavilla olevien ruutujen määrä on hieman alhaisempi STR_MAPGEN_BY :{BLACK}× -STR_MAPGEN_NUMBER_OF_TOWNS :{BLACK}Kaupungit: +STR_MAPGEN_NUMBER_OF_TOWNS :{BLACK}Kaupunkien määrä: STR_MAPGEN_DATE :{BLACK}Päivämäärä: -STR_MAPGEN_NUMBER_OF_INDUSTRIES :{BLACK}Teollisuus: +STR_MAPGEN_NUMBER_OF_INDUSTRIES :{BLACK}Teollisuuden määrä: STR_MAPGEN_MAX_HEIGHTLEVEL :{BLACK}Suurin sallittu kartan korkeus: STR_MAPGEN_MAX_HEIGHTLEVEL_UP :{BLACK}Kasvata suurinta sallittua vuorten korkeutta yhdellä STR_MAPGEN_MAX_HEIGHTLEVEL_DOWN :{BLACK}Vähennä suurinta sallittua vuorten korkeutta yhdellä @@ -2984,8 +2984,6 @@ STR_TOWN_POPULATION :{BLACK}Maailman STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (City) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Asukasluku: {ORANGE}{COMMA}{BLACK} Taloja: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Matkustajia viime kuussa: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Postia viime kuussa: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Kaupungin kasvuun tarvittava rahti: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} vaadittu STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} vaaditaan talvella @@ -3204,8 +3202,8 @@ STR_FINANCES_BANK_BALANCE_TITLE :{WHITE}Tilin sa STR_FINANCES_LOAN_TITLE :{WHITE}Laina STR_FINANCES_MAX_LOAN :{WHITE}Laina enimmillään: {BLACK}{CURRENCY_LONG} STR_FINANCES_TOTAL_CURRENCY :{BLACK}{CURRENCY_LONG} -STR_FINANCES_BORROW_BUTTON :{BLACK}Ota lainaa {CURRENCY_LONG} -STR_FINANCES_BORROW_TOOLTIP :{BLACK}Ota lisää lainaa. Ctrl+Klik lisää lainaa niin paljon kuin mahdollista +STR_FINANCES_BORROW_BUTTON :{BLACK}Nosta lainaa {CURRENCY_LONG} +STR_FINANCES_BORROW_TOOLTIP :{BLACK}Ota lisää lainaa. Ctrl+Klik nostaa lainaa niin paljon kuin mahdollista STR_FINANCES_REPAY_BUTTON :{BLACK}Lyhennä lainaa {CURRENCY_LONG} STR_FINANCES_REPAY_TOOLTIP :{BLACK}Lyhennä lainaa. Ctrl+Klik lyhentää lainaa niin paljon kuin mahdollista STR_FINANCES_INFRASTRUCTURE_BUTTON :{BLACK}Infrastruktuuri @@ -3236,7 +3234,7 @@ STR_COMPANY_VIEW_BUILD_HQ_BUTTON :{BLACK}Rakenna STR_COMPANY_VIEW_BUILD_HQ_TOOLTIP :{BLACK}Rakenna yhtiön päämaja STR_COMPANY_VIEW_VIEW_HQ_BUTTON :{BLACK}Näytä päämaja STR_COMPANY_VIEW_VIEW_HQ_TOOLTIP :{BLACK}Näytä yhtiön päämaja -STR_COMPANY_VIEW_RELOCATE_HQ :{BLACK}Sijoita päämaja +STR_COMPANY_VIEW_RELOCATE_HQ :{BLACK}Siirrä päämaja STR_COMPANY_VIEW_RELOCATE_COMPANY_HEADQUARTERS :{BLACK}Rakenna yhtiön päärakennus muualle, kustannus 1{NBSP}% yhtiön arvosta. Shift+Klik näyttää kustannearvion sijoittamatta päärakennusta uudelleen STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON :{BLACK}Yksityiskohdat STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP :{BLACK}Näytä tarkka infrastruktuurin määrä @@ -3261,7 +3259,7 @@ STR_COMPANY_VIEW_PRESIDENT_S_NAME_QUERY_CAPTION :Pääjohtajan n STR_BUY_COMPANY_MESSAGE :{WHITE}Etsimme kuljetusyhtiötä, joka ottaisi haltuunsa yhtiömme{}{}Haluatko ostaa yhtiön {COMPANY} hintaan {CURRENCY_LONG}? # Company infrastructure window -STR_COMPANY_INFRASTRUCTURE_VIEW_CAPTION :{WHITE}Yhtiön {COMPANY} infrastruktuuri +STR_COMPANY_INFRASTRUCTURE_VIEW_CAPTION :{WHITE}{COMPANY}: Infrastruktuuri STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT :{GOLD}Rautatiepalat: STR_COMPANY_INFRASTRUCTURE_VIEW_SIGNALS :{WHITE}Opastimet STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT :{GOLD}Teiden palat: @@ -4259,7 +4257,7 @@ STR_ERROR_CAN_T_POSITION_BUOY_HERE :{WHITE}Poijua e STR_ERROR_CAN_T_CHANGE_WAYPOINT_NAME :{WHITE}Reittipisteen nimeä ei voi muuttaa... STR_ERROR_CAN_T_REMOVE_TRAIN_WAYPOINT :{WHITE}Junien reittipistettä ei voi poistaa... -STR_ERROR_MUST_REMOVE_RAILWAYPOINT_FIRST :{WHITE}Junaradan reittipiste täytyy poistaa ensin +STR_ERROR_MUST_REMOVE_RAILWAYPOINT_FIRST :{WHITE}Rautatien reittipiste täytyy poistaa ensin STR_ERROR_BUOY_IN_THE_WAY :{WHITE}... poiju on tiellä STR_ERROR_BUOY_IS_IN_USE :{WHITE}... poiju on toisen yhtiön käytössä! @@ -4482,6 +4480,7 @@ STR_BASESOUNDS_DOS_DESCRIPTION :Alkuperäiset T STR_BASESOUNDS_WIN_DESCRIPTION :Alkuperäiset Transport Tycoon Deluxen Windows-version äänet. STR_BASESOUNDS_NONE_DESCRIPTION :Äänipaketti, jossa ei ole ääniä. STR_BASEMUSIC_WIN_DESCRIPTION :Alkuperäinen Transport Tycoon Deluxen Windows-version musiikki. +STR_BASEMUSIC_DOS_DESCRIPTION :Alkuperäinen Transport Tycoon Deluxen DOS-version musiikki. STR_BASEMUSIC_NONE_DESCRIPTION :Musiikkipaketti, jossa ei ole musiikkia. ##id 0x2000 @@ -4855,7 +4854,7 @@ STR_VEHICLE_NAME_AIRCRAFT_PLODDYPHUT_500 :Ploddyphut 500 STR_VEHICLE_NAME_AIRCRAFT_FLASHBANG_X1 :Flashbang X1 STR_VEHICLE_NAME_AIRCRAFT_JUGGERPLANE_M1 :Juggerplane M1 STR_VEHICLE_NAME_AIRCRAFT_FLASHBANG_WIZZER :Flashbang Wizzer -STR_VEHICLE_NAME_AIRCRAFT_TRICARIO_HELICOPTER :Tricario -helikopteri +STR_VEHICLE_NAME_AIRCRAFT_TRICARIO_HELICOPTER :Tricario-helikopteri STR_VEHICLE_NAME_AIRCRAFT_GURU_X2_HELICOPTER :Guru X2 -helikopteri STR_VEHICLE_NAME_AIRCRAFT_POWERNAUT_HELICOPTER :Powernaut-helikopteri diff --git a/src/lang/french.txt b/src/lang/french.txt index 2c57358046..34b3bcd892 100644 --- a/src/lang/french.txt +++ b/src/lang/french.txt @@ -651,6 +651,7 @@ STR_MUSIC_RULER_MARKER :{TINY_FONT}{BLA STR_MUSIC_TRACK_NONE :{TINY_FONT}{DKGREEN}-- STR_MUSIC_TRACK_DIGIT :{TINY_FONT}{DKGREEN}{ZEROFILL_NUM} STR_MUSIC_TITLE_NONE :{TINY_FONT}{DKGREEN}------ +STR_MUSIC_TITLE_NOMUSIC :{TINY_FONT}{DKGREEN}Aucune musique disponible STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKGREEN}"{STRING}" STR_MUSIC_TRACK :{TINY_FONT}{BLACK}Piste STR_MUSIC_XTITLE :{TINY_FONT}{BLACK}Titre @@ -664,21 +665,21 @@ STR_MUSIC_TOOLTIP_DRAG_SLIDERS_TO_SET_MUSIC :{BLACK}Faire gl STR_MUSIC_TOOLTIP_SELECT_ALL_TRACKS_PROGRAM :{BLACK}Choisir le programme «{NBSP}Tout{NBSP}» STR_MUSIC_TOOLTIP_SELECT_OLD_STYLE_MUSIC :{BLACK}Choisir le programme musical «{NBSP}Ancien style{NBSP}» STR_MUSIC_TOOLTIP_SELECT_NEW_STYLE_MUSIC :{BLACK}Choisir le programme musical «{NBSP}Nouveau style{NBSP}» -STR_MUSIC_TOOLTIP_SELECT_EZY_STREET_STYLE :{BLACK}Sélectionner le programme musical «{NBSP}Ezy Street{NBSP}» +STR_MUSIC_TOOLTIP_SELECT_EZY_STREET_STYLE :{BLACK}Choisir le programme musical «{NBSP}Ezy Street{NBSP}» STR_MUSIC_TOOLTIP_SELECT_CUSTOM_1_USER_DEFINED :{BLACK}Choisir le programme personnalisé «{NBSP}Personnalisé 1{NBSP}» STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Choisir le programme personnalisé «{NBSP}Personnalisé 2{NBSP}» STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Activer/Désactiver le mode aléatoire STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Afficher la fenêtre de sélection de pistes -STR_ERROR_NO_SONGS :{WHITE}Un ensemble de musique vide a été choisi. Aucune musique ne sera jouée. - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Sélection du programme musical -STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" +STR_PLAYLIST_MUSIC_SELECTION_SETNAME :{WHITE}Programme musical - «{NBSP}{STRING}{NBSP}» +STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} «{NBSP}{STRING}{NBSP}» STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Index des pistes -STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Programme - '{STRING}' +STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Programme - «{NBSP}{STRING}{NBSP}» STR_PLAYLIST_CLEAR :{TINY_FONT}{BLACK}Effacer +STR_PLAYLIST_CHANGE_SET :{BLACK}Changer d'ensemble STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Effacer le programme actuel (Personnalisé 1 ou Personnalisé 2 seulement) +STR_PLAYLIST_TOOLTIP_CHANGE_SET :{BLACK}Choisir un autre ensemble de musique STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}Cliquer sur une piste pour l'ajouter au programme courant (Personnalisé 1 ou Personnalisé 2 seulement) STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}Cliquer sur une piste pour la retirer du programme courant (Personnalisé 1 ou Personnalisé 2 seulement) @@ -881,10 +882,10 @@ STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION :{BIG_FONT}{BLAC # Extra view window STR_EXTRA_VIEW_PORT_TITLE :{WHITE}Vue {COMMA} -STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Copier vers la vue -STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN_TT :{BLACK}Copier l'emplacement de la vue principale vers cette vue-ci -STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Coller depuis la vue -STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT :{BLACK}Coller l'emplacement de cette vue-ci vers la vue principale +STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Modifier cette vue +STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN_TT :{BLACK}Copier l'emplacement de la vue principale vers cette vue +STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Modifier la vue principale +STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT :{BLACK}Copier l'emplacement de cette vue vers la vue principale # Game options window STR_GAME_OPTIONS_CAPTION :{WHITE}Options @@ -1338,8 +1339,12 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Couleur du terr STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Vert STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Vert foncé STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Violet -STR_CONFIG_SETTING_REVERSE_SCROLLING :Inverser la direction lors du défilement avec la souris{NBSP}: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Comportement lors du défilement de la carte avec le bouton droit de la souris. Quand il est désactivé, la souris déplace la caméra. Quand il est activé, la souris déplace la carte +STR_CONFIG_SETTING_SCROLLMODE :Défilement de la vue{NBSP}: {STRING} +STR_CONFIG_SETTING_SCROLLMODE_HELPTEXT :Comportement lors du défilement de la carte +STR_CONFIG_SETTING_SCROLLMODE_DEFAULT :Défilement de la vue par clic droit, position de la souris verrouillée +STR_CONFIG_SETTING_SCROLLMODE_RMB_LOCKED :Défilement de la carte par clic droit, position de la souris verrouillée +STR_CONFIG_SETTING_SCROLLMODE_RMB :Défilement de la carte par clic droit +STR_CONFIG_SETTING_SCROLLMODE_LMB :Défilement de la carte par clic gauche STR_CONFIG_SETTING_SMOOTH_SCROLLING :Défilement régulier de la vue{NBSP}: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Contrôle comment la vue principale défile jusqu'à une position spécifique lors d'un clic sur la mini-carte ou pour atteindre un objet précis sur la carte. Si activé, la vue défile doucement, si désactivé elle saute directement à la cible STR_CONFIG_SETTING_MEASURE_TOOLTIP :Montrer une infobulle de mesure lors de l'utilisation de divers outils de construction{NBSP}: {STRING} @@ -1371,8 +1376,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Commande-clic STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl-clic STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Désactivé -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Défilement par clic gauche{NBSP}: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Active le défilement de la carte en la glissant avec le bouton gauche de la souris. C'est surtout utile pour les écrans tactiles STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Fermer une fenêtre en cliquant droit{NBSP}: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Fermer une fenêtre en cliquant droit à l’intérieur de celle-ci. Désactive l'infobulle sur clic droit{NBSP}! @@ -2286,6 +2289,7 @@ STR_LINKGRAPH_LEGEND_CAPTION :{BLACK}Légende STR_LINKGRAPH_LEGEND_ALL :{BLACK}Toute STR_LINKGRAPH_LEGEND_NONE :{BLACK}Aucune STR_LINKGRAPH_LEGEND_SELECT_COMPANIES :{BLACK}Choisir les compagnies à afficher +STR_LINKGRAPH_LEGEND_COMPANY_TOOLTIP :{BLACK}{STRING}{}{COMPANY} # Linkgraph legend window and linkgraph legend in smallmap STR_LINKGRAPH_LEGEND_UNUSED :{TINY_FONT}{BLACK}inutilisé @@ -2694,6 +2698,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Copyrigh STR_ABOUT_VERSION :{BLACK}OpenTTD version {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 L'équipe OpenTTD +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Sauvegarder la partie STR_SAVELOAD_LOAD_CAPTION :{WHITE}Charger une partie @@ -2978,6 +2989,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Entrer u STR_TOWN_DIRECTORY_CAPTION :{WHITE}Villes STR_TOWN_DIRECTORY_NONE :{ORANGE}− Aucune − STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Métropole){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Noms des villes - Cliquer sur un nom pour centrer la vue principale sur la ville. Ctrl-clic pour ouvrir une nouvelle vue sur la ville. STR_TOWN_POPULATION :{BLACK}Population mondiale{NBSP}: {COMMA} @@ -2985,8 +2997,7 @@ STR_TOWN_POPULATION :{BLACK}Populati STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Métropole) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Population{NBSP}: {ORANGE}{COMMA}{BLACK} − Maisons{NBSP}: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Passagers le mois dernier{NBSP}: {ORANGE}{COMMA}{BLACK} − max.{NBSP}: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Courrier le mois dernier{NBSP}: {ORANGE}{COMMA}{BLACK} − max.{NBSP}: {ORANGE}{COMMA} +STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX :{BLACK}{CARGO_LIST} le mois dernier{NBSP}: {ORANGE}{COMMA}{BLACK} - max.{NBSP}: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Cargaison nécessaire à la croissance de la ville{NBSP}: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} requis STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} requis en hiver @@ -4233,6 +4244,7 @@ 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... @@ -4484,6 +4496,8 @@ STR_BASESOUNDS_DOS_DESCRIPTION :Sons originaux STR_BASESOUNDS_WIN_DESCRIPTION :Sons originaux de Transport Tycoon Deluxe (version Windows). STR_BASESOUNDS_NONE_DESCRIPTION :Un pack de sons sans sons. STR_BASEMUSIC_WIN_DESCRIPTION :Musiques originales de Transport Tycoon Deluxe (version Windows). +STR_BASEMUSIC_DOS_DESCRIPTION :Musiques originales de Transport Tycoon Deluxe (version DOS). +STR_BASEMUSIC_TTO_DESCRIPTION :Musiques originales de Transport Tycoon (version Originale/World Editor). STR_BASEMUSIC_NONE_DESCRIPTION :Un pack de musiques sans musiques. ##id 0x2000 diff --git a/src/lang/gaelic.txt b/src/lang/gaelic.txt index c06b81ecf7..5264ba8b29 100644 --- a/src/lang/gaelic.txt +++ b/src/lang/gaelic.txt @@ -868,10 +868,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Tagh am STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Toglaich prògram air thuaiream air/dheth STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Seall uinneag taghadh tracaichean ciùil -STR_ERROR_NO_SONGS :{WHITE}Chaidh seata dhe cheòl às aonais òrain a thaghadh. Cha tèid òran sam bith a chluiche - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Taghadh prògram ciùil STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} “{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Clàr-amais nan traca STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Prògram - “{STRING}" @@ -1539,8 +1536,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Dath na crutha- STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Uaine STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Dorch-uaine STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Purpaidh -STR_CONFIG_SETTING_REVERSE_SCROLLING :Comhair sgrolaidh chontrarra: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Giùlan nuair a thèid am mapa a sgroladh le putan deas na luchaige. Nuair a bhios seo air, gluaisidh an luchag am mapa STR_CONFIG_SETTING_SMOOTH_SCROLLING :Sgroladh mìn nam port-seallaidh: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Tagh mar a ghluaiseas am prìomh-shealladh gu ionad sònraichte. Ma tha seo dheth, thèid leum dhan ionad a chaidh a thaghadh sa bhad STR_CONFIG_SETTING_MEASURE_TOOLTIP :Seall gliocasan-sgrìn tomhais le innealan togail: {STRING} @@ -1572,8 +1567,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command+Briogad STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+Briogadh STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Dheth -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Sgroladh le briogadh clì: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Cuir an comas gun tèid am mapa a sgroladh le slaodadh le putan clì na luchaige. Tha seo feumail gu h-àraidh nuair a chleachdas tu sgrìn-shuathaidh airson sgroladh STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Dùin an uinneag le briogadh deas: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Dùinidh seo uinneag le briogadh deas ’na broinn. Cuiridh e à comas an gliocas-sgrìn le briogadh deas! @@ -2934,6 +2927,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Còir-le STR_ABOUT_VERSION :{BLACK}OpenTTD tionndadh {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 An sgioba OpenTTD +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Sàbhail an geama STR_SAVELOAD_LOAD_CAPTION :{WHITE}Luchdaich geama @@ -3225,8 +3225,6 @@ STR_TOWN_POPULATION :{BLACK}Sluagh a STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Mòr-bhaile) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Sluagh: {ORANGE}{COMMA}{BLACK} Taighean: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Taistealaich am mìos mu dheireadh: {ORANGE}{COMMA}{BLACK} as motha: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Post am mìos mu dheireadh: {ORANGE}{COMMA}{BLACK} as motha: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Carago a tha a dhìth ach am fàs am baile: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{RED}Feum air {ORANGE}{STRING} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{BLACK}Feum air {ORANGE}{STRING}{BLACK} sa gheamhradh diff --git a/src/lang/galician.txt b/src/lang/galician.txt index d87aa14abe..fbd6330025 100644 --- a/src/lang/galician.txt +++ b/src/lang/galician.txt @@ -670,10 +670,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Seleccio STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Activar/desactivar programa aleatorio STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Amosar a fiestra de selección de pista musical -STR_ERROR_NO_SONGS :{WHITE}Seleccionouse unha lista de reprodución sen cancións. Non se reproducirá ningunha canción - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Selección do programa de música STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Índice de pistas STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Programa - '{STRING}' @@ -1338,8 +1335,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Cor do terreo n STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Verde STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Verde escuro STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Violeta -STR_CONFIG_SETTING_REVERSE_SCROLLING :Inverti-la dirección de desprazamento: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Acción cando o mapa se despraza co botón dereito do rato. Cando se desactiva, o rato move a cámara. Cando se activa, o rato move o mapa STR_CONFIG_SETTING_SMOOTH_SCROLLING :Desprazamento de vista suave: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Controla como a vista principal se despraza a unah posición específica cando se fai clic no minimapa ou cando se emprega un comando para desprazarse a un obxecto específico sobre o mapa. Se se activa, a vista desprázase suavemente, se se desactiva salta directamente STR_CONFIG_SETTING_MEASURE_TOOLTIP :Mostrar medidas ao usar as ferramentas de construción: {STRING} @@ -1371,8 +1366,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Tecla Command+C STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+Clic STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Apagado -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Desprazamento con click esquerdo: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Habilitar o desprazamento do mapa arrastrándoo co botón esquerdo do rato. Isto é especialmente útil se se emprega unha pantalla táctil para desprazarse STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Pechar a fiestra con click dereito: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Pecha a fiestra facendo botón dereito dentro de ela. Deshabilita a axuda contextual facendo click-dereito! @@ -2694,6 +2687,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Copyrigh STR_ABOUT_VERSION :{BLACK}OpenTTD versión {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2018 O equipo de OpenTTD +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Gravar partida STR_SAVELOAD_LOAD_CAPTION :{WHITE}Cargar partida @@ -2985,8 +2985,6 @@ STR_TOWN_POPULATION :{BLACK}Poboaci STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Cidade) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Poboación: {ORANGE}{COMMA}{BLACK} Casas: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Pasaxeiros último mes: {ORANGE}{COMMA}{BLACK} máx: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Correo último mes: {ORANGE}{COMMA}{BLACK} máx: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Carga necesaria para o crecemento da cidade: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} necesario STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} necesarios en inverno diff --git a/src/lang/german.txt b/src/lang/german.txt index 128c516c62..cd7eb37d8a 100644 --- a/src/lang/german.txt +++ b/src/lang/german.txt @@ -670,10 +670,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Programm STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Zufällige Wiedergabe ein/aus STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Zeige Musiktitelauswahl -STR_ERROR_NO_SONGS :{WHITE}Ein Musikset ohne Musikdateien wurde ausgewählt. Es kann folglich nichts abgespielt werden. - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Musik-Programmauswahl STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Track Inhalt STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Programm - '{STRING}' @@ -1338,8 +1335,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Farbe von Landf STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Grün STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Dunkelgrün STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Lila -STR_CONFIG_SETTING_REVERSE_SCROLLING :Scrollrichtung invertieren: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Legt das Verhalten beim Scrollen der Karte mit der rechten Maustaste fest. Ist diese Option aktiviert, bewegt sich der sichtbare Kartenausschnitt in Mausrichtung. Ist sie deaktiviert, bewegt sich die Karte entgegen der Mausrichtung STR_CONFIG_SETTING_SMOOTH_SCROLLING :Weicher Bildlauf beim Springen zu einer Position: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Lege fest, auf welche Weise die Hauptansicht an eine bestimmte Position wechselt (z.B. wenn ein Punkt auf der Weltkarte angeklickt wird oder der Standort eines Bahnhofs angezeigt werden soll). Ist diese Option eingeschaltet, schwenkt die Ansicht über die Karte, bis sie am gewünschten Punkt angekommen ist. Ist sie ausgeschaltet, springt die Ansicht sofort an die gewünschte Position STR_CONFIG_SETTING_MEASURE_TOOLTIP :Beim Bauen Tooltip mit Abmessungen anzeigen: {STRING} @@ -1371,8 +1366,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Kommando+Klick STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Strg+Klick STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Aus -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Scrollen mit linker Maustaste: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Scrolle die Karte, indem mit der linken Maustaste gezogen wird. Dies ist besonders sinnvoll, wenn ein Touchscreen zum Scrollen genutzt wird STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Fenster mit Rechtsklick schließen: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Schließt ein Fenster mittels Rechts-Klick. Schaltet Tooltip mit Rechts-Klick ab! @@ -2694,6 +2687,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Transpor STR_ABOUT_VERSION :{BLACK}OpenTTD-Version {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 OpenTTD-Team +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Spiel speichern STR_SAVELOAD_LOAD_CAPTION :{WHITE}Spiel laden @@ -2985,8 +2985,6 @@ STR_TOWN_POPULATION :{BLACK}Weltbev STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Großstadt) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Einwohner: {ORANGE}{COMMA}{BLACK} Häuser: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Passagiere im letzten Monat: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Postsäcke im letzten Monat: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Für Stadtwachstum benötigte Fracht: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} benötigt STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} im Winter benötigt diff --git a/src/lang/greek.txt b/src/lang/greek.txt index 11d5755d78..909e180b23 100644 --- a/src/lang/greek.txt +++ b/src/lang/greek.txt @@ -731,7 +731,7 @@ STR_PERFORMANCE_DETAIL_LOAN :{BLACK}Δάνε STR_PERFORMANCE_DETAIL_TOTAL :{BLACK}Σύνολο: ############ End of order list STR_PERFORMANCE_DETAIL_VEHICLES_TOOLTIP :{BLACK}Απαρίθμηση των οχημάτων που απέφεραν κέρδος πέρσι. Περιλαμβανομένων των επιγείων οχημάτων, τρένων, πλοίων και αεροσκαφών. -STR_PERFORMANCE_DETAIL_STATIONS_TOOLTIP :{BLACK}Αριθμός των πρόσφατα επισκευασμένων σταθμών. Σταθμοί τραίνων, στάσεις λεωφορείων, αεροδρόμια, κ.ο.κ. προσμετρώνται ξεχωριστά, ακόμα κι αν ανήκουν στον ίδιο σταθμό. +STR_PERFORMANCE_DETAIL_STATIONS_TOOLTIP :{BLACK}Αριθμός των πρόσφατα επισκευασμένων σταθμών. Σταθμοί τρένων, στάσεις λεωφορείων, αεροδρόμια, κ.ο.κ. προσμετρώνται ξεχωριστά, ακόμα κι αν ανήκουν στον ίδιο σταθμό. STR_PERFORMANCE_DETAIL_MIN_PROFIT_TOOLTIP :{BLACK}Το κέρδος του οχήματος με το μικρότερο εισόδημα (μόνο οχήματα παλιότερα των 2 ετών θα λαμβάνονται υπόψην) STR_PERFORMANCE_DETAIL_MIN_INCOME_TOOLTIP :{BLACK}Το ποσό των χρημάτων που έγιναν σε ένα τρίμηνο με το μικρότερο κέρδος των τελευταίων 12 τριμήνων STR_PERFORMANCE_DETAIL_MAX_INCOME_TOOLTIP :{BLACK}Το ποσό των χρημάτων που έγιναν σε ένα τρίμηνο με το μεγαλύτερο κέρδος των τελευταίων 12 τριμήνων @@ -757,6 +757,7 @@ STR_MUSIC_RULER_MARKER :{TINY_FONT}{BLA STR_MUSIC_TRACK_NONE :{TINY_FONT}{DKGREEN}-- STR_MUSIC_TRACK_DIGIT :{TINY_FONT}{DKGREEN}{ZEROFILL_NUM} STR_MUSIC_TITLE_NONE :{TINY_FONT}{DKGREEN}------ +STR_MUSIC_TITLE_NOMUSIC :{TINY_FONT}{DKGREEN}Δεν υπάρχει διαθέσιμη μουσική STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKGREEN}«{STRING}» STR_MUSIC_TRACK :{TINY_FONT}{BLACK}Κομμάτι STR_MUSIC_XTITLE :{TINY_FONT}{BLACK}Τίτλος @@ -776,15 +777,15 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Επιλ STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Εναλλαγή τυχαίας αναπαραγωγής on/off στο πρόγραμμα STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Εμφάνιση παραθύρου επιλογής μουσικού κομματιού -STR_ERROR_NO_SONGS :{WHITE}Επιλέχτηκε σετ μουσικής χωρίς τραγούδια. Κανένα τραγούδι δεν θα παιχτεί - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Επιλογή Μουσικού Προγράμματος +STR_PLAYLIST_MUSIC_SELECTION_SETNAME :{WHITE}Πρόγραμμα μουσικής - '{STRING}' STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} «{STRING}» STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Λίστα σιδηροτροχιών STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Πρόγραμμα - '{STRING}' STR_PLAYLIST_CLEAR :{TINY_FONT}{BLACK}Καθαρισμός +STR_PLAYLIST_CHANGE_SET :{BLACK}Αλλαγή σετ STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Καθαρισμός τρέχοντος προγράμματος (μόνο Προσαρμοσμένο 1 ή Προσαρμοσμένο 2) +STR_PLAYLIST_TOOLTIP_CHANGE_SET :{BLACK}Αλλαγή μουσικής επιλογής σε άλλο εγκατεστημένο σετ STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}Πατήστε στο μουσικό κομμάτι για προσθήκη στο τρέχον πρόγραμμα (Προσαρμοσμένο1 ή Προσαρμοσμένο2 μόνο) STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}Πατήστε στο τραγούδι για να το αφαιρέσετε από το πρόγραμμα (Προσαρμοσμένο 1 ή 2 μόνο) @@ -987,9 +988,9 @@ STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION :{BIG_FONT}{BLAC # Extra view window STR_EXTRA_VIEW_PORT_TITLE :{WHITE}Εμφάνιση {COMMA} -STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Αντιγραφή στην εμφάνιση +STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Αντιγραφή στο παράθυρο εμφάνισης STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN_TT :{BLACK}Αντιγραφή της τοποθεσίας της κύριας προβολής σε αυτό το παράθυρο εμφάνισης -STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Επικόλληση από εμφάνιση +STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Επικόλληση από παράθυρο εμφάνισης STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT :{BLACK}Επικόλληση της τοποθεσίας αυτού του παραθύρου εμφάνισης στην κύρια προβολή # Game options window @@ -1278,22 +1279,22 @@ STR_CONFIG_SETTING_CATCHMENT :Επιτρέπ STR_CONFIG_SETTING_CATCHMENT_HELPTEXT :Διαφορετικοί σταθμοί και αεροδρόμια έχουν περιοχές κάλυψης διαφορετικού μεγέθους STR_CONFIG_SETTING_EXTRADYNAMITE :Επιτρέπεται η αφαίρεση περισσότερων ιδιοκτησιών των πολέων: {STRING} STR_CONFIG_SETTING_EXTRADYNAMITE_HELPTEXT :Είναι ευκολότερη η αφαίρεση υποδομών και κτιρίων που κατέχονται από την πόλη -STR_CONFIG_SETTING_TRAIN_LENGTH :Μέγιστο μήκος τραίνων: {STRING} -STR_CONFIG_SETTING_TRAIN_LENGTH_HELPTEXT :Ορίστε το μέγιστο μήκος των τραίνων +STR_CONFIG_SETTING_TRAIN_LENGTH :Μέγιστο μήκος τρένων: {STRING} +STR_CONFIG_SETTING_TRAIN_LENGTH_HELPTEXT :Ορίστε το μέγιστο μήκος των τρένων STR_CONFIG_SETTING_TILE_LENGTH :{COMMA} τετραγωνίδι{P 0 ο α} STR_CONFIG_SETTING_SMOKE_AMOUNT :Ποσότητα καπνού/σπινθύρων οχήματος: {STRING} STR_CONFIG_SETTING_SMOKE_AMOUNT_HELPTEXT :Ορίστε τον όγκο του καπνού ή τον αριθμό των σπιθών που παράγονται από τα οχήματα STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL :Μοντέλο επιτάχυνσης τρένων: {STRING} -STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL_HELPTEXT :Επιλέξτε το μοντέλο φυσικής για την επιτάχυνση των τραίνων. Με το «αρχικό» μοντέλο οι κλίσεις επιβαρύνουν το ίδιο όλα τα οχήματα. Με το «ρεαλιστικό» μοντέλο οι κλίσεις και οι στροφές τα επιβαρύνουν ανάλογα με διάφορες ιδιότητες όπως το μήκος και το ελκτικό φορτίο +STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL_HELPTEXT :Επιλέξτε το μοντέλο φυσικής για την επιτάχυνση των τρένων. Με το «αρχικό» μοντέλο οι κλίσεις επιβαρύνουν το ίδιο όλα τα οχήματα. Με το «ρεαλιστικό» μοντέλο οι κλίσεις και οι στροφές τα επιβαρύνουν ανάλογα με διάφορες ιδιότητες όπως το μήκος και το ελκτικό φορτίο STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL :Μοντέλο επιτάχυνσης οχημάτων δρόμου: {STRING} STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL_HELPTEXT :Επιλέξτε το μοντέλο φυσικής για την επιτάχυνση των οχημάτων. Με το «αρχικό» μοντέλο οι κλίσεις επιβαρύνουν το ίδιο όλα τα οχήματα. Με το «ρεαλιστικό» μοντέλο οι κλίσεις και οι στροφές τα επιβαρύνουν ανάλογα με διάφορες ιδιότητες όπως το μήκος και το ελκτικό φορτίο -STR_CONFIG_SETTING_TRAIN_SLOPE_STEEPNESS :Κλίση εδάφους για τα τραίνα: {STRING} -STR_CONFIG_SETTING_TRAIN_SLOPE_STEEPNESS_HELPTEXT :Η κλίση ενός κεκλιμένου τετραγωνίδιου για τα τραίνα. Μεγαλύτερες τιμές καθιστούν δυσκολότερο το ανέβασμα λόφων +STR_CONFIG_SETTING_TRAIN_SLOPE_STEEPNESS :Κλίση εδάφους για τα τρένα: {STRING} +STR_CONFIG_SETTING_TRAIN_SLOPE_STEEPNESS_HELPTEXT :Η κλίση ενός κεκλιμένου τετραγωνίδιου για τα τρένα. Μεγαλύτερες τιμές καθιστούν δυσκολότερο το ανέβασμα λόφων STR_CONFIG_SETTING_PERCENTAGE :{COMMA}% STR_CONFIG_SETTING_ROAD_VEHICLE_SLOPE_STEEPNESS :Κλίση εδάφους για τα οδικά οχήματα: {STRING} STR_CONFIG_SETTING_ROAD_VEHICLE_SLOPE_STEEPNESS_HELPTEXT :Η κλίση ενός κεκλιμένου τετραγωνίδιου για τα οδικά οχήματα. Μεγαλύτερες τιμές καθιστούν δυσκολότερο το ανέβασμα λόφων STR_CONFIG_SETTING_FORBID_90_DEG :Απαγόρευση στα τρένα και πλοία να κάνουν στροφές 90°: {STRING} -STR_CONFIG_SETTING_FORBID_90_DEG_HELPTEXT :Στροφές 90 μοιρών προκύπτουν όταν μια οριζόντια σιδηροτροχιά ακολουθείται από μια κάθετη στο επόμενο τετραγωνίδιο, κάνοντας το τραίνο να στρίψει κατά 90 μοίρες όταν αλλάζει τετραγωνίδιο, αντί για τις συνηθισμένες 45 μοίρες σε άλλους συνδυασμούς σιδηροτροχιών. Αυτό έχει επίσης εφαρμογή στην ακτίνα στροφής των πλοίων +STR_CONFIG_SETTING_FORBID_90_DEG_HELPTEXT :Στροφές 90 μοιρών προκύπτουν όταν μια οριζόντια σιδηροτροχιά ακολουθείται από μια κάθετη στο επόμενο τετραγωνίδιο, κάνοντας το τρένο να στρίψει κατά 90 μοίρες όταν αλλάζει τετραγωνίδιο, αντί για τις συνηθισμένες 45 μοίρες σε άλλους συνδυασμούς σιδηροτροχιών. Αυτό έχει επίσης εφαρμογή στην ακτίνα στροφής των πλοίων STR_CONFIG_SETTING_DISTANT_JOIN_STATIONS :Να επιτρέπεται η συνένωση μη παρακείμενων σταθμών: {STRING} STR_CONFIG_SETTING_DISTANT_JOIN_STATIONS_HELPTEXT :Επιτρέπεται η προσθήκη τμημάτων σε σταθμό χωρίς αυτά να αγγίζουν τα ήδη υπάρχοντα τμήματα. Χρειάζεται Ctrl+Κλικ κατά την τοποθέτηση των νέων τμημάτων STR_CONFIG_SETTING_INFLATION :Πληθωρισμός: {STRING} @@ -1323,7 +1324,7 @@ STR_CONFIG_SETTING_SHOWFINANCES_HELPTEXT :Όταν ενε STR_CONFIG_SETTING_NONSTOP_BY_DEFAULT :Οι νέες οδηγίες είναι «χωρίς στάση» από προεπιλογή: {STRING} STR_CONFIG_SETTING_NONSTOP_BY_DEFAULT_HELPTEXT :Κανονικά, τα οχήματα σταματούν σε κάθε σταθμό που περνούν. Ενεργοποιώντας αυτήν τη ρύθμιση, δεν θα σταματούν σε κανένα σταθμό που θα βρει στη διαδρομή τους προς τον τελικό προορισμό. Σημείωστε πως αυτή η ρύθμιση ορίζει μόνο μια καθορισμένη τιμή για νέες εντολές. Ειδικές εντολές μπορούν να δοθούν για οποιαδήποτε συμπεριφορά, άσχετα από την προκαθορισμένη STR_CONFIG_SETTING_STOP_LOCATION :Οι εντόλες νέων τρένων διορίζουν ότι σταματάνε εξ ορισμού στο {STRING} της πλατφόρμας -STR_CONFIG_SETTING_STOP_LOCATION_HELPTEXT :Το προεπιλεγμένο σημείο όπου θα σταματούν τα τραίνα στην πλατφόρμα . Το «κοντινό άκρο» σημαίνει κοντά στο σημείο εισόδου, «Μέση» σημαίνει στο μέσο της πλατφόρμας και «μακρινό άκρο» σημαίνει στο άλλο άκρο από το σημείο εισόδου. Σημειώστε ότι αυτή η ρύθμιση ορίζει μόνο την προκαθορισμένη τιμή για νέες εντολές. Παρ' όλα αυτά, είναι δυνατό να δοθούν διαφορετικές εντολές για οποιαδήποτε συμπεριφορά. +STR_CONFIG_SETTING_STOP_LOCATION_HELPTEXT :Το προεπιλεγμένο σημείο όπου θα σταματούν τα τρένα στην πλατφόρμα . Το «κοντινό άκρο» σημαίνει κοντά στο σημείο εισόδου, «Μέση» σημαίνει στο μέσο της πλατφόρμας και «μακρινό άκρο» σημαίνει στο άλλο άκρο από το σημείο εισόδου. Σημειώστε ότι αυτή η ρύθμιση ορίζει μόνο την προκαθορισμένη τιμή για νέες εντολές. Παρ' όλα αυτά, είναι δυνατό να δοθούν διαφορετικές εντολές για οποιαδήποτε συμπεριφορά. STR_CONFIG_SETTING_STOP_LOCATION_NEAR_END :κοντινό άκρο STR_CONFIG_SETTING_STOP_LOCATION_MIDDLE :στη μέση STR_CONFIG_SETTING_STOP_LOCATION_FAR_END :μακρινό άκρο @@ -1344,7 +1345,7 @@ STR_CONFIG_SETTING_ALLOW_FUND_ROAD_HELPTEXT :Επιτρέπ STR_CONFIG_SETTING_ALLOW_GIVE_MONEY :Επιτρέπεται η αποστολή χρημάτων σε άλλες εταιρίες: {STRING} STR_CONFIG_SETTING_ALLOW_GIVE_MONEY_HELPTEXT :Επιτρέπεται η μεταφορά χρημάτων μεταξύ των εταιρειών σε παιχνίδια πολλαπλών παικτών STR_CONFIG_SETTING_FREIGHT_TRAINS :Πολλαπλασιαστής βάρους σε φορτία για εξομοίωση βαρέων τρένων: {STRING} -STR_CONFIG_SETTING_FREIGHT_TRAINS_HELPTEXT :Ορίζεται ο αντίκτυπος της μεταφοράς φορτίων στα τραίνα. Υψηλότερη τιμή κάνει τη μεταφορά φορτίων πιο απαιτητική για τραίνα, ιδιαίτερα στους λόφους +STR_CONFIG_SETTING_FREIGHT_TRAINS_HELPTEXT :Ορίζεται ο αντίκτυπος της μεταφοράς φορτίων στα τρένα. Υψηλότερη τιμή κάνει τη μεταφορά φορτίων πιο απαιτητική για τρένα, ιδιαίτερα στους λόφους STR_CONFIG_SETTING_PLANE_SPEED :Παράγοντας ταχύτητας αεροπλάνων: {STRING} STR_CONFIG_SETTING_PLANE_SPEED_HELPTEXT :Ορίζεται η σχετική ταχύτητα των αεροπλάνων συγκριτικά με τους άλλους τύπους οχημάτων, ώστε να μειώνεται το ποσό του εισοδήματος από μεταφορές με αεροσκάφη STR_CONFIG_SETTING_PLANE_SPEED_VALUE :1 / {COMMA} @@ -1444,8 +1445,12 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Χρώμα εδ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Πράσινο STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Σκούρο πράσινο STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Βιολετί -STR_CONFIG_SETTING_REVERSE_SCROLLING :Ανάποδη μετακίνηση οθόνης: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Συμπεριφορά όταν κυλίεται ο χάρτης με το δεξί κουμπί του ποντικιού. Όταν είναι απενεργοποιημένη, το ποντίκι μετακινεί την κάμερα. Όταν είναι ενεργοποιημένη, το ποντίκι μετακινεί τον χάρτη +STR_CONFIG_SETTING_SCROLLMODE :Συμπεριφορά κύλισης του παραθύρου εμφάνισης: {STRING} +STR_CONFIG_SETTING_SCROLLMODE_HELPTEXT :Συμπεριφορά κατά την κύλιση του χάρτη +STR_CONFIG_SETTING_SCROLLMODE_DEFAULT :Μετακίνηση μικρού χάρτη με ΔΠΠ, θέση ποντικιού κλειδωμένη +STR_CONFIG_SETTING_SCROLLMODE_RMB_LOCKED :Μετακίνηση χάρτη με ΔΠΠ, θέση ποντικιού κλειδωμένη +STR_CONFIG_SETTING_SCROLLMODE_RMB :Μετακίνηση χάρτη με ΔΠΠ +STR_CONFIG_SETTING_SCROLLMODE_LMB :Μετακίνηση χάρτη με ΑΠΠ STR_CONFIG_SETTING_SMOOTH_SCROLLING :Ομαλή μετάβαση οθόνης: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Ελέγξτε τον τρόπο με τον οποίο η κύρια προβολή κυλίεται σε μια συγκεκριμένη θέση όταν πατάτε πάνω στον μικρό χάρτη ή όταν δίνετε εντολή για μετάβαση σε ένα συγκεκριμένο αντικείμενο στον χάρτη. Όταν είναι ενεργοποιημένη, η κύλιση γίνεται ομαλά, και όταν είναι απενεργοποιημένη μεταβαίνει απ' ευθείας στο επιλεγμένο σημείο STR_CONFIG_SETTING_MEASURE_TOOLTIP :Εμφάνιση εργαλείου μετρήσεως όταν χρησιμοποιούνται διάφορα εργαλεία: {STRING} @@ -1477,8 +1482,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command+Κλι STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Control+Κλικ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Απενεργοποιημένος -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Μετάβαση με αριστερό κλικ: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Ενεργοποίηση της κύλισης του χάρτη σύροντας τον με το αριστερό κουμπί του ποντικιού. Αυτό είναι ιδιαίτερα χρήσιμο για την κύλιση όταν χρησιμοποιείται οθόνη αφής STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Κλείσιμο παραθύρου με δεξί-κλικ: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Κλείνει το παράθυρο με δεξί πάτημα μέσα του. Απενεργοποιεί την ανάδυση επεξηγήσεων με το δεξί κουμπί! @@ -1504,7 +1507,7 @@ STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS_HELPTEXT :Ενεργοπ STR_CONFIG_SETTING_LOADING_INDICATORS :Χρήση δεικτών φόρτωσης: {STRING} STR_CONFIG_SETTING_LOADING_INDICATORS_HELPTEXT :Επιλέξτε εάν οι δείκτες φόρτωσης εμφανίζονται πάνω από τα οχήματα που φορτώνουν ή ξεφορτώνουν STR_CONFIG_SETTING_TIMETABLE_IN_TICKS :Εμφάνιση δρομολογίων σε στιγμές αντί για ημέρες: {STRING} -STR_CONFIG_SETTING_TIMETABLE_IN_TICKS_HELPTEXT :Εμφάνιση χρόνων ταξιδιού στα χρονοδιαγράμματα σε χρόνο παιχνιδιού αντί σε ημέρες +STR_CONFIG_SETTING_TIMETABLE_IN_TICKS_HELPTEXT :Εμφάνιση χρόνων ταξιδιού στα χρονοδιαγράμματα σε στιγμές αντί σε ημέρες STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE :Εμφάνιση αφίξεων και αναχωρήσεων στα δρομολόγια: {STRING} STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE_HELPTEXT :Εμφάνιση αναμενόμενης ώρας άφιξης και αναχώρησης στα χρονοδιαγράμματα STR_CONFIG_SETTING_QUICKGOTO :Γρήγορη δημιουργία εντολών για τα οχήματα: {STRING} @@ -1514,8 +1517,8 @@ STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_HELPTEXT :Επιλογή STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_FIRST :Πρώτος διαθέσιμος STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_LAST :Τελευταίος διαθέσιμος STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_MOST_USED :Περισσότερο χρησιμοποιούμενος -STR_CONFIG_SETTING_SHOW_TRACK_RESERVATION :Εμφάνιση δεσμέυσεων διαδρομών για γραμμές τραίνου: {STRING} -STR_CONFIG_SETTING_SHOW_TRACK_RESERVATION_HELPTEXT :Δίνεται ένα διαφορετικό χρώμα στις κατειλημμένες ράγες για να σας βοηθήσουν με προβλήματα όταν τα τραίνα αρνούνται να εισέλθουν σε τμήματα με βάση τροχιές +STR_CONFIG_SETTING_SHOW_TRACK_RESERVATION :Εμφάνιση δεσμέυσεων διαδρομών για γραμμές τρένου: {STRING} +STR_CONFIG_SETTING_SHOW_TRACK_RESERVATION_HELPTEXT :Δίνεται ένα διαφορετικό χρώμα στις κατειλημμένες ράγες για να σας βοηθήσουν με προβλήματα όταν τα τρένα αρνούνται να εισέλθουν σε τμήματα με βάση τροχιές STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS :Διατήρηση των οικοδομικών εργαλείων ενεργών μετά από χρήση τους: {STRING} STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS_HELPTEXT :Διατήρηση ανοικτών των εργαλείων για γέφυρες, σήραγγες, κλπ μετά από τη χρήση STR_CONFIG_SETTING_EXPENSES_LAYOUT :Ομαδοποίηση εξόδων στο παράθυρο οικονομικών της εταιρίας: {STRING} @@ -1541,7 +1544,7 @@ STR_CONFIG_SETTING_SOUND_AMBIENT_HELPTEXT :Παίζει τ STR_CONFIG_SETTING_DISABLE_UNSUITABLE_BUILDING :Απενεργοποίηση των υποδομών για τα οχήματα που δεν είναι διαθέσιμα: {STRING} STR_CONFIG_SETTING_DISABLE_UNSUITABLE_BUILDING_HELPTEXT :Όταν είναι ενεργοποιημένο, οι υποδομές είναι διαθέσιμες μόνο όταν υπάρχουν διαθέσιμα οχήματα, αποτρέποντας σπατάλη χρόνου και χρημάτων σε μη χρησιμοποιήσιμες υποδομές STR_CONFIG_SETTING_MAX_TRAINS :Μέγιστος αριθμός τρένων ανά εταιρία: {STRING} -STR_CONFIG_SETTING_MAX_TRAINS_HELPTEXT :Μέγιστος αριθμός τραίνων που μπορεί να έχει μια εταιρεία +STR_CONFIG_SETTING_MAX_TRAINS_HELPTEXT :Μέγιστος αριθμός τρένων που μπορεί να έχει μια εταιρεία STR_CONFIG_SETTING_MAX_ROAD_VEHICLES :Μέγιστος αριθμός οχημάτων δρόμου ανά εταιρία: {STRING} STR_CONFIG_SETTING_MAX_ROAD_VEHICLES_HELPTEXT :Μέγιστος αριθμός οδικών οχημάτων που μπορεί να έχει μια εταιρεία STR_CONFIG_SETTING_MAX_AIRCRAFT :Μέγιστος αριθμός αεροσκαφών ανά εταιρία: {STRING} @@ -1550,7 +1553,7 @@ STR_CONFIG_SETTING_MAX_SHIPS :Μέγιστο STR_CONFIG_SETTING_MAX_SHIPS_HELPTEXT :Μέγιστος αριθμός πλοίων που μπορεί να έχει μια εταιρεία STR_CONFIG_SETTING_AI_BUILDS_TRAINS :Απενεργοποίηση τρένων για τον υπολογιστή: {STRING} -STR_CONFIG_SETTING_AI_BUILDS_TRAINS_HELPTEXT :Ενεργοποιώντας αυτήν τη ρύθμιση κάνει αδύνατη την κατασκευή τραίνων από παίκτη του υπολογιστή +STR_CONFIG_SETTING_AI_BUILDS_TRAINS_HELPTEXT :Ενεργοποιώντας αυτήν τη ρύθμιση κάνει αδύνατη την κατασκευή τρένων από παίκτη του υπολογιστή STR_CONFIG_SETTING_AI_BUILDS_ROAD_VEHICLES :Απενεργοποίηση οχημάτων υπολογιστή: {STRING} STR_CONFIG_SETTING_AI_BUILDS_ROAD_VEHICLES_HELPTEXT :Ενεργοποιώντας αυτήν τη ρύθμιση κάνει αδύνατη την κατασκευή οδικών οχημάτων από παίκτη του υπολογιστή STR_CONFIG_SETTING_AI_BUILDS_AIRCRAFT :Απενεργοποίηση αεροσκαφών υπολογιστή: {STRING} @@ -1571,8 +1574,8 @@ STR_CONFIG_SETTING_SCRIPT_MAX_OPCODES_HELPTEXT :Μέγιστο STR_CONFIG_SETTING_SERVINT_ISPERCENT :Τα διαστήματα μεταξύ συντήρησης είναι σε ποσοστά: {STRING} STR_CONFIG_SETTING_SERVINT_ISPERCENT_HELPTEXT :Επιλέξτε εάν η επισκευή των οχημάτων εξαρτάται από τον χρόνο που πέρασε από την τελευταία επισκευή ή από την μείωση της αξιοπιστίας κατά ένα συγκεκριμένο ποσοστό της μέγιστης αξιοπιστίας -STR_CONFIG_SETTING_SERVINT_TRAINS :Προκαθορισμένο διάστημα μεταξύ επισκευών για τα τραίνα: {STRING} -STR_CONFIG_SETTING_SERVINT_TRAINS_HELPTEXT :Ορίστε το προκαθορισμένο διάστημα μεταξύ συντηρήσεων για τα νέα οχήματα τραίνων, όταν δεν δίνεται άλλο διάστημα για το όχημα +STR_CONFIG_SETTING_SERVINT_TRAINS :Προκαθορισμένο διάστημα μεταξύ επισκευών για τα τρένα: {STRING} +STR_CONFIG_SETTING_SERVINT_TRAINS_HELPTEXT :Ορίστε το προκαθορισμένο διάστημα μεταξύ συντηρήσεων για τα νέα οχήματα τρένων, όταν δεν δίνεται άλλο διάστημα για το όχημα STR_CONFIG_SETTING_SERVINT_VALUE :{COMMA}{NBSP}ημέρ{P 0 α ες}/% STR_CONFIG_SETTING_SERVINT_DISABLED :Απενεργοποιημένο STR_CONFIG_SETTING_SERVINT_ROAD_VEHICLES :Προκαθορισμένο διάστημα μεταξύ συντηρήσεων για οδικά οχήματα: {STRING} @@ -1584,7 +1587,7 @@ STR_CONFIG_SETTING_SERVINT_SHIPS_HELPTEXT :Ορίστε τ STR_CONFIG_SETTING_NOSERVICE :Απενεργοποίηση επισκευών όταν οι καταρρεύσεις είναι απενεργοποιημένες: {STRING} STR_CONFIG_SETTING_NOSERVICE_HELPTEXT :Όταν είναι ενεργοποιημένη, τα οχήματα δεν συντηρούνται όταν δεν είναι δυνατό να χαλάσουν STR_CONFIG_SETTING_WAGONSPEEDLIMITS :Ενεργοποίηση ορίων ταχύτητας βαγονιών: {STRING} -STR_CONFIG_SETTING_WAGONSPEEDLIMITS_HELPTEXT :Όταν είναι ενεργοποιημένο, χρησιμοποιούνται και τα όρια ταχύτητας των βαγονιών όταν αποφασίζεται η μέγιστη ταχύτητα ενός τραίνου +STR_CONFIG_SETTING_WAGONSPEEDLIMITS_HELPTEXT :Όταν είναι ενεργοποιημένο, χρησιμοποιούνται και τα όρια ταχύτητας των βαγονιών όταν αποφασίζεται η μέγιστη ταχύτητα ενός τρένου STR_CONFIG_SETTING_DISABLE_ELRAILS :Απενεργοποίηση ηλεκτρικών σιδηροτροχιών: {STRING} STR_CONFIG_SETTING_DISABLE_ELRAILS_HELPTEXT :Ενεργοποιώντας αυτήν την ρύθμιση απενεργοποιείται η ανάγκη ηλεκτροδότησης των σιδηροτροχιών για να μπορέσουν σε αυτές να λειτουργήσουν οι ηλεκτρικές μηχανές @@ -1802,13 +1805,13 @@ STR_CONFIG_SETTING_PATHFINDER_NPF :NPF STR_CONFIG_SETTING_PATHFINDER_YAPF_RECOMMENDED :YAPF {BLUE}(Συνίσταται) STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS :Μέθοδος δρομολόγησης για τρένα: {STRING} -STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS_HELPTEXT :Μέθοδος διαπίστωσης διαδρομής που χρησιμοποιείται για τα τραίνα +STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS_HELPTEXT :Μέθοδος διαπίστωσης διαδρομής που χρησιμοποιείται για τα τρένα STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES :Μέθοδος δρομολόγησης για οχήματα δρόμου: {STRING} STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES_HELPTEXT :Μέθοδος διαπίστωσης διαδρομής που χρησιμοποιείται για τα οδικά οχήματα STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS :Μέθοδος δρομολόγησης για πλοία: {STRING} STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS_HELPTEXT :Μέθοδος διαπίστωσης διαδρομής που χρησιμοποιείται για τα πλοία STR_CONFIG_SETTING_REVERSE_AT_SIGNALS :Αυτόματη αναστροφή σε σηματοδότες: {STRING} -STR_CONFIG_SETTING_REVERSE_AT_SIGNALS_HELPTEXT :Επιτρέπεται στα τραίνα να αντιστραφούν σε σήμα, εάν περιμένουν εκεί για πολύ ώρα +STR_CONFIG_SETTING_REVERSE_AT_SIGNALS_HELPTEXT :Επιτρέπεται στα τρένα να αντιστραφούν σε σήμα, εάν περιμένουν εκεί για πολύ ώρα STR_CONFIG_SETTING_QUERY_CAPTION :{WHITE}Αλλαγή τιμής ρύθμισης @@ -2392,6 +2395,7 @@ STR_LINKGRAPH_LEGEND_CAPTION :{BLACK}Υπόμ STR_LINKGRAPH_LEGEND_ALL :{BLACK}Όλες STR_LINKGRAPH_LEGEND_NONE :{BLACK}Καμία STR_LINKGRAPH_LEGEND_SELECT_COMPANIES :{BLACK}Επιλογή εταιριών για να εμφανιστούν +STR_LINKGRAPH_LEGEND_COMPANY_TOOLTIP :{BLACK}{STRING}{}{COMPANY} # Linkgraph legend window and linkgraph legend in smallmap STR_LINKGRAPH_LEGEND_UNUSED :{TINY_FONT}{BLACK}μη χρησιμοποιημένο @@ -2800,6 +2804,37 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Αρχι STR_ABOUT_VERSION :{BLACK}Έκδοση OpenTTD{REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 Η ομάδα του OpenTTD +# Framerate display window +STR_FRAMERATE_RATE_GAMELOOP_TOOLTIP :{BLACK}Αριθμός στιγμών παιχνιδιού που προσομοιώνεται ανά δευτερόλεπτο. +STR_FRAMERATE_SPEED_FACTOR :{WHITE}Παράγοντας ταχύτητας τρέχοντος παιχνιδιού: {DECIMAL}x +STR_FRAMERATE_SPEED_FACTOR_TOOLTIP :{BLACK}Πόσο γρήγορα εκτελείται το παιχνίδι αυτήν τη στιγμή, σε σύγκριση με την αναμενόμενη ταχύτητα στον κανονικό ρυθμό εξομοίωσης. +STR_FRAMERATE_CURRENT :{WHITE}Τρέχον +STR_FRAMERATE_AVERAGE :{WHITE}Μέσο +STR_FRAMERATE_DATA_POINTS :{WHITE}Τα δεδομένα βασίζονται σε μετρήσεις {COMMA} +STR_FRAMERATE_MS_GOOD :{LTBLUE}{DECIMAL}{WHITE} ms +############ Leave those lines in this order!! +STR_FRAMERATE_GL_ECONOMY :{WHITE} Διαχείριση φορτίου: +STR_FRAMERATE_GL_TRAINS :Στιγμές τρένων: +STR_FRAMERATE_GL_ROADVEHS :{WHITE} Στιγμές οχημάτων δρόμου: +STR_FRAMERATE_GL_SHIPS :Στιγμές πλοίων: +STR_FRAMERATE_GL_AIRCRAFT :Στιγμές αεροσκαφών: +STR_FRAMERATE_GL_LANDSCAPE :Στιγμές κόσμου: +STR_FRAMERATE_VIDEO :{WHITE}Έξοδος βίντεο: +STR_FRAMERATE_SOUND :{WHITE}Μίξη ήχου: +############ End of leave-in-this-order +############ Leave those lines in this order!! +STR_FRAMETIME_CAPTION_GL_ECONOMY :Διαχείριση φορτίου +STR_FRAMETIME_CAPTION_GL_TRAINS :Στιγμές τρένων +STR_FRAMETIME_CAPTION_GL_ROADVEHS :Στιγμές οχημάτων δρόμου +STR_FRAMETIME_CAPTION_GL_SHIPS :Στιγμές πλοίων +STR_FRAMETIME_CAPTION_GL_AIRCRAFT :Στιγμές αεροσκαφών +STR_FRAMETIME_CAPTION_GL_LANDSCAPE :Στιγμές κόσμου +STR_FRAMETIME_CAPTION_GL_LINKGRAPH :Καθυστέρηση γραφήματος συνδέσμου +STR_FRAMETIME_CAPTION_VIDEO :Έξοδος βίντεο +STR_FRAMETIME_CAPTION_SOUND :Μίξη ήχου +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Αποθήκευση Παιχνιδιού STR_SAVELOAD_LOAD_CAPTION :{WHITE}Φόρτωση Παιχνιδιού @@ -3084,6 +3119,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Δώστ STR_TOWN_DIRECTORY_CAPTION :{WHITE}Πόλεις STR_TOWN_DIRECTORY_NONE :{ORANGE}- Τίποτα - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Πόλη){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Ονόματα πόλεων - πατήστε στο όνομα για να κεντράρετε την εικόνα στην πόλη. Με Ctrl+Κλικ ανοίγει νέο παράθυρο προβολής στην τοποθεσία της πόλης STR_TOWN_POPULATION :{BLACK}Παγκόσμιος πληθυσμός: {COMMA} @@ -3091,8 +3127,7 @@ STR_TOWN_POPULATION :{BLACK}Παγκ STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Πόλη) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Πληθυσμός: {ORANGE}{COMMA}{BLACK} Σπίτια: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Επιβάτες τον προηγούμενο μήνα: {ORANGE}{COMMA}{BLACK} μεγ: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Αλληλογραφία τον προηγούμενο μήνα: {ORANGE}{COMMA}{BLACK} μεγ: {ORANGE}{COMMA} +STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX :{BLACK}{CARGO_LIST} προηγούμενος μήνας: {ORANGE}{COMMA}{BLACK} μέγιστο: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Εμπορεύματα που χρειάζονται για την επέκταση της πόλης: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} απαιτείται STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} απαιτείται τον χειμώνα @@ -3293,7 +3328,7 @@ STR_FINANCES_EXPENDITURE_INCOME_TITLE :{WHITE}Έξοδ STR_FINANCES_YEAR :{WHITE}{NUM} STR_FINANCES_SECTION_CONSTRUCTION :{GOLD}Κατασκευές STR_FINANCES_SECTION_NEW_VEHICLES :{GOLD}Νέα Οχήματα -STR_FINANCES_SECTION_TRAIN_RUNNING_COSTS :{GOLD}Λειτουργικά Έξοδα Τραίνων +STR_FINANCES_SECTION_TRAIN_RUNNING_COSTS :{GOLD}Λειτουργικά Έξοδα Τρένων STR_FINANCES_SECTION_ROAD_VEHICLE_RUNNING_COSTS :{GOLD}Λειτουργικά Έξοδα Οχημάτων STR_FINANCES_SECTION_AIRCRAFT_RUNNING_COSTS :{GOLD}Λειτουργικά Έξοδα Αεροσκαφών STR_FINANCES_SECTION_SHIP_RUNNING_COSTS :{GOLD}Λειτουργικά Έξοδα Πλοίων @@ -3605,7 +3640,7 @@ STR_DEPOT_CLONE_ROAD_VEHICLE :{BLACK}Κλων STR_DEPOT_CLONE_SHIP :{BLACK}Κλωνοποίηση Πλοίου STR_DEPOT_CLONE_AIRCRAFT :{BLACK}Κλωνοποίηση Αεροσκάφους -STR_DEPOT_CLONE_TRAIN_DEPOT_INFO :{BLACK}Αυτό θα αγοράσει ένα αντίγραφο του τρένου μαζί με τα όλα τα βαγόνια. Πατήστε αυτό το κουμπί και μετά σε κάποιο τραίνο μέσα ή έξω από το αμαξοστάσιο. Με Ctrl+Κλικ θα έχει τις ίδιες εντολές. Με Shift+Κλικ εμφανίζεται το εκτιμώμενο κόστος χωρίς να γίνει η αγορά +STR_DEPOT_CLONE_TRAIN_DEPOT_INFO :{BLACK}Αυτό θα αγοράσει ένα αντίγραφο του τρένου μαζί με τα όλα τα βαγόνια. Πατήστε αυτό το κουμπί και μετά σε κάποιο τρένο μέσα ή έξω από το αμαξοστάσιο. Με Ctrl+Κλικ θα έχει τις ίδιες εντολές. Με Shift+Κλικ εμφανίζεται το εκτιμώμενο κόστος χωρίς να γίνει η αγορά STR_DEPOT_CLONE_ROAD_VEHICLE_DEPOT_INFO :{BLACK}Αυτό θα αγοράσει ένα αντίγραφο του οχήματος. Πατήστε αυτό το κουμπί και μετά σε κάποιο όχημα μέσα ή έξω από το αμαξοστάσιο. Με Ctrl+Κλικ θα έχει τις ίδιες εντολές. Με Shift+Κλικ εμφανίζεται το εκτιμώμενο κόστος χωρίς να γίνει η αγορά STR_DEPOT_CLONE_SHIP_DEPOT_INFO :{BLACK}Αυτό θα αγοράσει ένα αντίγραφο του πλοίου. Πατήστε αυτό το κουμπί και μετά σε κάποιο πλοίο μέσα ή έξω από το ναυπηγείο. Με Ctrl+Κλικ θα έχει τις ίδιες εντολές. Με Shift+Κλικ εμφανίζεται το εκτιμώμενο κόστος χωρίς να γίνει η αγορά STR_DEPOT_CLONE_AIRCRAFT_INFO_HANGAR_WINDOW :{BLACK}Αυτό θα αγοράσει ένα αντίγραφο του αεροσκάφους. Πατήστε αυτό το κουμπί και μετά σε κάποιο αεροσκάφος μέσα στο ή έξω από το υπόστεγο. Με Ctrl+Κλικ θα έχει τις ίδιες εντολές. Με Shift+Κλικ εμφανίζεται το εκτιμώμενο κόστος χωρίς να γίνει η αγορά @@ -4345,6 +4380,7 @@ 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}Δεν μπορεί να αφαιρεθεί μέρος του σταθμού... @@ -4549,7 +4585,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Ξεκι # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Δεν μπορεί το τρένο να περάσει σήμα με κίνδυνο... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Δεν αντιστρέφεται η κατεύθυνση του τρένου... -STR_ERROR_TRAIN_START_NO_POWER :Το τραίνο δεν έχει ενέργεια +STR_ERROR_TRAIN_START_NO_POWER :Το τρένο δεν έχει ενέργεια STR_ERROR_CAN_T_MAKE_ROAD_VEHICLE_TURN :{WHITE}Δεν γίνεται να αλλάξει πορεία το όχημα... @@ -4596,6 +4632,8 @@ STR_BASESOUNDS_DOS_DESCRIPTION :Αρχικοί STR_BASESOUNDS_WIN_DESCRIPTION :Αρχικοί ήχοι από το Transport Tycoon Deluxe έκδοση Windows. STR_BASESOUNDS_NONE_DESCRIPTION :Ένα πάκετο ήχων χώρις ήχους. STR_BASEMUSIC_WIN_DESCRIPTION :Αρχική μουσική από το Transport Tycoon Deluxe έκδοση Windows. +STR_BASEMUSIC_DOS_DESCRIPTION :Αρχική μουσική από το Transport Tycoon Deluxe έκδοση DOS. +STR_BASEMUSIC_TTO_DESCRIPTION :Αρχική μουσική από το Transport Tycoon (Αρχικός Επεξεργαστής Κόσμου) έκδοση DOS. STR_BASEMUSIC_NONE_DESCRIPTION :Ένα πάκετο μουσικής χωρίς πραγματική μουσική. ##id 0x2000 diff --git a/src/lang/hebrew.txt b/src/lang/hebrew.txt index 90ed5ccc55..cc36dab80e 100644 --- a/src/lang/hebrew.txt +++ b/src/lang/hebrew.txt @@ -683,10 +683,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}(בחר STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}עירבוב תוכניות פועל/כבוי STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}הצג את חלון בחירת המנגינה -STR_ERROR_NO_SONGS :{WHITE}נבחרה ערכת מוזיקה ללא שירים. לא יושמעו שירים - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}בחירת תכנית מנגינה STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}רשימת רצועות STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}תוכנית- '{STRING}' @@ -1351,8 +1348,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :צבע פני STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :ירוק STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :ירוק כהה STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :סגול -STR_CONFIG_SETTING_REVERSE_SCROLLING :{STRING} :היפוך כיוון הגלילה של התצוגה -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :התנהגות בעת גלילת המפה באמצעות כפתור העכבר האמצעי. כאשר מבוטל, העכבר מזיז את המצלמה. כאשר מאופשר, העכבר מזיז את המפה STR_CONFIG_SETTING_SMOOTH_SCROLLING :{STRING} :גלילה חלקה של התצוגה המשנית STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :שלוט כיצד התצוגה הראשית נגללת למיקום מסוים כאשר מקליקים על המפה הקטנה אן כאשר נותנים הוראה לגלול לעצם מסוים על גבי המפה. אם מאופשר, חלון התצוגה נגלל באופן חלק, אם מבוטל הוא מוקפץ ישירות אל נקודת המטרה STR_CONFIG_SETTING_MEASURE_TOOLTIP :{STRING} :'הצג מידות בעת בניית כבישים/מסילות וכיוב @@ -1384,8 +1379,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command-click STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Control-click STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :כבוי -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :גלילה בלחיצה שמאלית: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :אפשר גלילת המפה באמצעות גרירתה עם כפתור העכבר השמאלי. אפשרות זו שימושית במיוחד בעת שימוש במסך מגע לצורך גלילה STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :סגירת חלון בכפתור ימני: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :סוגר חלון על-ידי לחיצה ימנית בתוכו. מבטל הצגת מידע בלחיצה ימנית! @@ -2707,6 +2700,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}כל ה STR_ABOUT_VERSION :{BLACK}{REV} גירסה , OpenTTD STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2018 The OpenTTD team +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}שמור משחק STR_SAVELOAD_LOAD_CAPTION :{WHITE}טען משחק @@ -2998,8 +2998,6 @@ STR_TOWN_POPULATION :{BLACK}אוכל STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (עיר) STR_TOWN_VIEW_POPULATION_HOUSES :{ORANGE}{1:COMMA}{BLACK} :בתים {ORANGE}{0:COMMA}{BLACK} :אוכלוסיה -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{ORANGE}{1:COMMA}{BLACK} :מספר מירבי {ORANGE}{0:COMMA}{BLACK} :נוסעים בחודש שעבר -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{ORANGE}{1:COMMA}{BLACK} :מספר מירבי {ORANGE}{0:COMMA}{BLACK} :שקי דואר בחודש שעבר STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}המטען שצריך בשביל גידול עיר STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} דרוש STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} דרוש בחורף diff --git a/src/lang/hungarian.txt b/src/lang/hungarian.txt index 99dbfb82c8..886b2def52 100644 --- a/src/lang/hungarian.txt +++ b/src/lang/hungarian.txt @@ -732,10 +732,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}A 'Sajá STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Véletlen sorrendű lejátszás be/ki STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}A számkiválasztó ablak megjelenítése -STR_ERROR_NO_SONGS :{WHITE}Egy zeneszámokat nem tartalmazó zenei alapcsomag lett kiválasztva. A játékban nem lesz zene - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Zenei műsor kiválasztása STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Számlista STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}"{STRING}" Műsora @@ -1401,8 +1398,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Talaj színe a STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Zöld STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Sötétzöld STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Sötétkék -STR_CONFIG_SETTING_REVERSE_SCROLLING :Inverz görgetési irány: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :A térkép jobb gombbal történő görgetésének viselkedése. Kikapcsolva az egér mozgatja a kamerát. Bekapcsolva az egér a térképet mozgatja STR_CONFIG_SETTING_SMOOTH_SCROLLING :Finomított nézőpont-görgetés: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Beállítható, hogy a fő nézet hogyan mozogjon egy adott pozícióra a térképre kattintáskor ha egy adott objektumra történik mozgás. Bekapcsolva a nézet egyenletesen mozog, kikapcsolva közvetlenül a kijelölt helyre ugrik STR_CONFIG_SETTING_MEASURE_TOOLTIP :Területinformációk mutatása építési eszközök használatakor: {STRING} @@ -1434,8 +1429,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Parancs+Kattint STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+kattintás STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Kikapcsolva -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Bal gombos térképmozgatás: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Bal egérgombbal történő térképmozgatás engedélyezése. Különösen hasznos érintőképernyős mozgatás használata esetén STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Ablakok bezárása jobb gombbal: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :A jobb gombbal való kattintás az ablak területén bezárja az ablakot. Ez a beállítás kikapcsolja a segédletek jobb gombbal való megjelenítését! @@ -2757,6 +2750,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Eredeti STR_ABOUT_VERSION :{BLACK}OpenTTD {REV} verzió STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2018 Az OpenTTD csapat +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Játék mentése STR_SAVELOAD_LOAD_CAPTION :{WHITE}Játék betöltése @@ -3048,8 +3048,6 @@ STR_TOWN_POPULATION :{BLACK}Világn STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Város) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Lakosság: {ORANGE}{COMMA}{BLACK} Házak: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Utasok az előző hónapban: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Levélcsomagok az előző hónapban: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}A város növekedéséhez szükséges rakomány: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} szükséges STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} szükséges télen diff --git a/src/lang/icelandic.txt b/src/lang/icelandic.txt index 77e9c09660..6d8a4bae6c 100644 --- a/src/lang/icelandic.txt +++ b/src/lang/icelandic.txt @@ -647,10 +647,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Velja 'S STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Kveikja/slökkva á stokkun STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Sýna lagalista -STR_ERROR_NO_SONGS :{WHITE}Tómur lagalisti hefur verið valinn. Engin lög verða spiluð - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Lagalistar STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Laganúmer STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Listi - '{STRING}' @@ -1273,8 +1270,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Litur á landsl STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Grænn STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Dökkgrænn STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Fjólublátt -STR_CONFIG_SETTING_REVERSE_SCROLLING :Færa sjónarhorn í öfuga átt miðað við mús: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Hegðun þegar sjónarhornið er fært með hægri músartakkanum. Þegar stillingin er óvirk færir músin myndavélina. Þegar stillingin er virk færir músin sjónarhornið STR_CONFIG_SETTING_SMOOTH_SCROLLING :Mjúkt skrun í skjágluggum: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Stýrir hvernig aðalsjónarhornið færist á ákveðna staði þegar smellt er á þá á litla kortinu eða þegar ákveðinn hlutur er valin á kortinu. Ef stillingin er virk færist aðalsjónarhornið rólega, ef stillingin er óvirk fer aðalsjónarhornið beint á ákveðna staðinn STR_CONFIG_SETTING_MEASURE_TOOLTIP :Sýna mælingar þegar verið er að byggja og breyta landslagi: {STRING} @@ -1306,8 +1301,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command+smella STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+smella STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Af -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Skrun með hægri músarhnappi: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Virkja að hægt sé að færa sjónarhornið með því að færa það með vinstri músar takkanum. Þetta er sérstaklega gott þegar notast er við snerti-skjá til að færa sjónarhornið STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES :Nota dagsetningar á {STRING} formi fyrir vistaða leiki. @@ -2538,6 +2531,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Upphafle STR_ABOUT_VERSION :{BLACK}OpenTTD útgáfa {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2018 OpenTTD hópurinn +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Vista leik STR_SAVELOAD_LOAD_CAPTION :{WHITE}Opna leik @@ -2808,8 +2808,6 @@ STR_TOWN_POPULATION :{BLACK}Heildar STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Borg) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Íbúafjöldi: {ORANGE}{COMMA}{BLACK} Hús: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Farþegar síðasta mánaðar: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Póstur síðasta mánaðar: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Nauðsynlegur farmur fyrir stækkun bæjarins: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} nauðsynlegt STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} nauðsynlegt á veturnar diff --git a/src/lang/indonesian.txt b/src/lang/indonesian.txt index 36ead125af..f3300c711f 100644 --- a/src/lang/indonesian.txt +++ b/src/lang/indonesian.txt @@ -669,10 +669,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Pilih 'B STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Acak/Urut program STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Tampilkan jendela pemilihan judul musik -STR_ERROR_NO_SONGS :{WHITE}Set Musik tanpa lagu telah dipilih. Tidak ada lagu yang akan dimainkan. - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Pilihan program Musik STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Daftar rel STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Program - '{STRING}' @@ -1337,8 +1334,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Warna daratan d STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Hijau STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Hijau Gelap STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Violet -STR_CONFIG_SETTING_REVERSE_SCROLLING :Berbalik Arah: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Untuk menggeser peta berlawanan arah dengan klik kanan. Ketika dimatikan, mouse menggeser kamera. Ketika dinyalakan, mouse menggeser peta STR_CONFIG_SETTING_SMOOTH_SCROLLING :Pergeseran pandangan viewport secara halus: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Menyetel bagaimana tampilan utama menggeser posisi di peta kecil. Jika dinyalakan, peta akan bergeser secara halus. Jika dimatikan, peta langsung menuju tempat yang di klik STR_CONFIG_SETTING_MEASURE_TOOLTIP :Tampilkan ukuran ketika menggunakan alat pembangun: {STRING} @@ -1370,8 +1365,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Perintah-klik STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Kontrol-klik STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Non-aktifkan -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Geser dgn klik-kiri: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Aktifkan penggeseran peta dengan menyeret menggunakan tombol kiri mouse. Hal ini sangat berguna apabila menggunakan layar sentuh. STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Tutup jendela dengan klik kanan: {STRING} STR_CONFIG_SETTING_AUTOSAVE :Simpan otomatis: {STRING} @@ -2691,6 +2684,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Hak Cipt STR_ABOUT_VERSION :{BLACK}OpenTTD versi {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 Tim OpenTTD +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Simpan Permainan STR_SAVELOAD_LOAD_CAPTION :{WHITE}Buka Permainan @@ -2978,8 +2978,6 @@ STR_TOWN_POPULATION :{BLACK}Populasi STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (City) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Populasi: {ORANGE}{COMMA}{BLACK} Rumah: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Penumpang bulan lalu: {ORANGE}{COMMA}{BLACK} maks: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Surat bulan lalu: {ORANGE}{COMMA}{BLACK} maks: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Kargo untuk pertumbuhan kota: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{RED} Butuh {ORANGE}{STRING} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} dibutuhkan saat musim dingin diff --git a/src/lang/irish.txt b/src/lang/irish.txt index 6c2cb21375..47f1e7e981 100644 --- a/src/lang/irish.txt +++ b/src/lang/irish.txt @@ -669,10 +669,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Roghnaig STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Scoránaigh ord randamach clár air/as STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Taispeáin an fhuinneogh chun rianta ceoil a roghnú -STR_ERROR_NO_SONGS :{WHITE}Roghnaíodh sraith ceoil gan aon amhrán ann. Ní sheinnfear aon amhrán - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Clár Ceoil a Roghnú STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Innéacs na Rianta STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Clár - '{STRING}' @@ -1337,8 +1334,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Dath an tír-ra STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Uaine STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Ciaruaine STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Corcairghorm -STR_CONFIG_SETTING_REVERSE_SCROLLING :Aisiompaigh an treo scrollaithe: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :An méid a tharlaíonn agus an léarscáil á scrollú leis an gcnaipe luchóige deas. Má bhíonn sé díchumasaithe, bogann an luchóg leis an gceamara. Má bhíonn sé cumasaithe, bogann an luchóg an léarscáil STR_CONFIG_SETTING_SMOOTH_SCROLLING :Scrollú mín do na fuinneoga amhairc: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Roghnaigh an chaoi a scrollóidh an príomhamharc chuig suíomh ar leith má chliceálann tú ar an léarscáil bheag nó má thugann tú ordú scrollú chuig oibiacht ar leith ar an léarscáil. Má tá sé cumasaithe, scrollóidh an fhuinneog amhairc go mín, má tá sé díchumasaithe léimfidh sé go díreach chuig an suíomh sin. STR_CONFIG_SETTING_MEASURE_TOOLTIP :Taispeáin leid uirlise tomhais agu uirlisí tógála áirithe in úsáid: {STRING} @@ -1370,8 +1365,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Ordú+Cliceáil STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+Cliceáil STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :As -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Scrollú le cléchliceáil: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Cumasaigh scrollú an léarscáil trí bheith ag tarraingt le cnaipe clé na luiche. Tá sé seo thar a bheith úsáideach don scrollú nuair atá scáileán tadhaill á úsáid STR_CONFIG_SETTING_AUTOSAVE :Uathshábháil: {STRING} STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :Roghnaigh an t-eatramh idir uathshábhálacha cluichí @@ -2689,6 +2682,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Cóipche STR_ABOUT_VERSION :{BLACK}OpenTTD leagan {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 An fhoireann OpenTTD +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Sábháil an Cluiche STR_SAVELOAD_LOAD_CAPTION :{WHITE}Lódáil Cluiche @@ -2980,8 +2980,6 @@ STR_TOWN_POPULATION :{BLACK}Daonra d STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Cathair) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Daonra: {ORANGE}{COMMA}{BLACK} Tithe: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Paisinéirí an mhí seo caite: {ORANGE}{COMMA}{BLACK} Uasmhéid: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Post an mhí seo caite: {ORANGE}{COMMA}{BLACK} uasmhéid: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Lastas atá ag teastáil le go bhfásfaidh an baile: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} ag teastáil STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} ag teastáil sa Gheimhreadh diff --git a/src/lang/italian.txt b/src/lang/italian.txt index e2d5ffa49a..1ffafdcd76 100644 --- a/src/lang/italian.txt +++ b/src/lang/italian.txt @@ -477,6 +477,7 @@ STR_ABOUT_MENU_SCREENSHOT :Screenshot STR_ABOUT_MENU_ZOOMIN_SCREENSHOT :Screenshot con zoom massimo STR_ABOUT_MENU_DEFAULTZOOM_SCREENSHOT :Screenshot con zoom predefinito STR_ABOUT_MENU_GIANT_SCREENSHOT :Screenshot intera mappa +STR_ABOUT_MENU_SHOW_FRAMERATE :Mostra frame rate STR_ABOUT_MENU_ABOUT_OPENTTD :Informazioni su 'OpenTTD' STR_ABOUT_MENU_SPRITE_ALIGNER :Strumento allineamento sprite STR_ABOUT_MENU_TOGGLE_BOUNDING_BOXES :Attiva/disattiva bounding box @@ -652,6 +653,7 @@ STR_MUSIC_RULER_MARKER :{TINY_FONT}{BLA STR_MUSIC_TRACK_NONE :{TINY_FONT}{DKGREEN}-- STR_MUSIC_TRACK_DIGIT :{TINY_FONT}{DKGREEN}{ZEROFILL_NUM} STR_MUSIC_TITLE_NONE :{TINY_FONT}{DKGREEN}------ +STR_MUSIC_TITLE_NOMUSIC :{TINY_FONT}{DKGREEN}Musica non disponibile STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKGREEN}"{STRING}" STR_MUSIC_TRACK :{TINY_FONT}{BLACK}Brano STR_MUSIC_XTITLE :{TINY_FONT}{BLACK}Titolo @@ -671,15 +673,15 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Selezion STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Attiva/disattiva la riproduzione in ordine casuale STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Mostra la finestra di selezione dei brani musicali -STR_ERROR_NO_SONGS :{WHITE}È stato selezionato un pacchetto musicale senza brani. Non sarà possibile avviare la musica. - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Selezione programma musicale +STR_PLAYLIST_MUSIC_SELECTION_SETNAME :{WHITE}Programma musicale - '{STRING}' STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Indice brani STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Programma - '{STRING}' STR_PLAYLIST_CLEAR :{TINY_FONT}{BLACK}Elimina +STR_PLAYLIST_CHANGE_SET :{BLACK}Cambia pacchetto STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Elimina il programma corrente (solo Personale1 e Personale2) +STR_PLAYLIST_TOOLTIP_CHANGE_SET :{BLACK}Seleziona un altro pacchetto musicale installato STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}Fare clic su un brano per aggiungerlo al programma corrente (solo Personale1 o Personale2) STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}Fare clic su un brano per rimuoverlo dal programma corrente (solo Personale1 o Personale2) @@ -882,9 +884,9 @@ STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION :{BIG_FONT}{BLAC # Extra view window STR_EXTRA_VIEW_PORT_TITLE :{WHITE}Mini visuale {COMMA} -STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Copia nella mini visuale +STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Cambia mini visuale STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN_TT :{BLACK}Copia la posizione della visuale principale in questa mini visuale -STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Copia dalla mini visuale +STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Cambia vis. principale STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT :{BLACK}Copia la posizione di questa mini visuale nella visuale principale # Game options window @@ -1361,8 +1363,12 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Colore del terr STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Verde STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Verde scuro STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Viola -STR_CONFIG_SETTING_REVERSE_SCROLLING :Inverti direzione di scorrimento della mappa: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Comportamento dello scorrimento della mappa con il tasto destro del mouse. Se disabilitata, il mouse muove l'inquadratura. Se abilitata, il mouse muove la mappa +STR_CONFIG_SETTING_SCROLLMODE :Scorrimento delle visuali: {STRING} +STR_CONFIG_SETTING_SCROLLMODE_HELPTEXT :Comportamento dello scorrimento della mappa +STR_CONFIG_SETTING_SCROLLMODE_DEFAULT :Muovi visuale col pulsante destro, puntatore bloccato +STR_CONFIG_SETTING_SCROLLMODE_RMB_LOCKED :Muovi mappa col pulsante destro, puntatore bloccato +STR_CONFIG_SETTING_SCROLLMODE_RMB :Muovi mappa col pulsante destro +STR_CONFIG_SETTING_SCROLLMODE_LMB :Muovi mappa col pulsante sinistro STR_CONFIG_SETTING_SMOOTH_SCROLLING :Scorrimento morbido delle visuali: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Controlla il modo in cui la visuale principale scorre verso una specifica posizione quando si fa clic sulla minimappa o si ordina di visualizzare un oggetto specifico sulla mappa. Se abilitata, la visuale scorre in modo morbido. Se disabilitata, salta direttamente al punto prescelto STR_CONFIG_SETTING_MEASURE_TOOLTIP :Mostra un tooltip di misura durante la costruzione: {STRING} @@ -1394,8 +1400,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :COMANDO+clic STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :CTRL+clic STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Nessuna -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Scorrimento con clic sinistro: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Abilita lo scorrimento della mappa trascinandola con il pulsante sinistro del mouse. Questa impostazione è utile quando si utilizza un touch-screen STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Chiudi finestra con clic destro: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Consente di chiudere una finestra facendo clic col pulsante destro al suo interno. Disabilita i suggerimenti attivati al clic col pulsante destro! @@ -2311,6 +2315,7 @@ STR_LINKGRAPH_LEGEND_NONE :{BLACK}Nessuno STR_LINKGRAPH_LEGEND_NONE.ms :{BLACK}Nessuno STR_LINKGRAPH_LEGEND_NONE.fs :{BLACK}Nessuna STR_LINKGRAPH_LEGEND_SELECT_COMPANIES :{BLACK}Seleziona le compagnie da mostrare +STR_LINKGRAPH_LEGEND_COMPANY_TOOLTIP :{BLACK}{STRING}{}{COMPANY} # Linkgraph legend window and linkgraph legend in smallmap STR_LINKGRAPH_LEGEND_UNUSED :{TINY_FONT}{BLACK}inutilizzata @@ -2723,6 +2728,56 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Copyrigh STR_ABOUT_VERSION :{BLACK}OpenTTD versione {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 Il team OpenTTD +# Framerate display window +STR_FRAMERATE_CAPTION :{WHITE}Frame rate +STR_FRAMERATE_CAPTION_SMALL :{STRING}{WHITE} ({DECIMAL}x) +STR_FRAMERATE_RATE_GAMELOOP :{WHITE}Velocità simulazione: {STRING} +STR_FRAMERATE_RATE_GAMELOOP_TOOLTIP :{BLACK}Numero di cicli di simulazione della partita in un secondo +STR_FRAMERATE_RATE_BLITTER :{WHITE}Frame rate grafica: {STRING} +STR_FRAMERATE_RATE_BLITTER_TOOLTIP :{BLACK}Numero di fotogrammi video renderizzati in un secondo +STR_FRAMERATE_SPEED_FACTOR :{WHITE}Fattore di velocità corrente della partita: {DECIMAL}x +STR_FRAMERATE_SPEED_FACTOR_TOOLTIP :{BLACK}Prestazioni correnti della partita, confrontate con le prestazioni attese alla velocità di giorno normale. +STR_FRAMERATE_CURRENT :{WHITE}Corrente +STR_FRAMERATE_AVERAGE :{WHITE}Media +STR_FRAMERATE_DATA_POINTS :{WHITE}Dati basati su {COMMA} misurazioni +STR_FRAMERATE_MS_GOOD :{LTBLUE}{DECIMAL}{WHITE} ms +STR_FRAMERATE_MS_WARN :{YELLOW}{DECIMAL}{WHITE} ms +STR_FRAMERATE_MS_BAD :{RED}{DECIMAL}{WHITE} ms +STR_FRAMERATE_FPS_GOOD :{LTBLUE}{DECIMAL}{WHITE} frame/s +STR_FRAMERATE_FPS_WARN :{YELLOW}{DECIMAL}{WHITE} frame/s +STR_FRAMERATE_FPS_BAD :{RED}{DECIMAL}{WHITE} frame/s +STR_FRAMERATE_GRAPH_MILLISECONDS :{TINY_FONT}{COMMA} ms +STR_FRAMERATE_GRAPH_SECONDS :{TINY_FONT}{COMMA} s +############ Leave those lines in this order!! +STR_FRAMERATE_GAMELOOP :{WHITE}Totale ciclo simulazione: +STR_FRAMERATE_GL_ECONOMY :{WHITE} Gestione carichi: +STR_FRAMERATE_GL_TRAINS :{WHITE} Aggiornamento treni: +STR_FRAMERATE_GL_ROADVEHS :{WHITE} Aggiornamento automezzi: +STR_FRAMERATE_GL_SHIPS :{WHITE} Aggiornamento navi: +STR_FRAMERATE_GL_AIRCRAFT :{WHITE} Aggiornamento aeromobili: +STR_FRAMERATE_GL_LANDSCAPE :{WHITE} Aggiornamento mondo: +STR_FRAMERATE_GL_LINKGRAPH :{WHITE} Ritardo grafo di distribuzione: +STR_FRAMERATE_DRAWING :{WHITE}Renderizzazione grafica: +STR_FRAMERATE_DRAWING_VIEWPORTS :{WHITE} Visuali mondo: +STR_FRAMERATE_VIDEO :{WHITE}Output video: +STR_FRAMERATE_SOUND :{WHITE}Missaggio suoni: +############ End of leave-in-this-order +############ Leave those lines in this order!! +STR_FRAMETIME_CAPTION_GAMELOOP :Ciclo simulazione +STR_FRAMETIME_CAPTION_GL_ECONOMY :Gestione carichi +STR_FRAMETIME_CAPTION_GL_TRAINS :Aggiornamento treni +STR_FRAMETIME_CAPTION_GL_ROADVEHS :Aggiornamento automezzi +STR_FRAMETIME_CAPTION_GL_SHIPS :Aggiornamento navi +STR_FRAMETIME_CAPTION_GL_AIRCRAFT :Aggiornamento aeromobili +STR_FRAMETIME_CAPTION_GL_LANDSCAPE :Aggiornamento mondo +STR_FRAMETIME_CAPTION_GL_LINKGRAPH :Ritardo grafo di distribuzione +STR_FRAMETIME_CAPTION_DRAWING :Renderizzazione grafica +STR_FRAMETIME_CAPTION_DRAWING_VIEWPORTS :Renderizzazione visuali mondo +STR_FRAMETIME_CAPTION_VIDEO :Output video +STR_FRAMETIME_CAPTION_SOUND :Missaggio suoni +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Salva partita STR_SAVELOAD_LOAD_CAPTION :{WHITE}Carica partita @@ -3007,6 +3062,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Inserire STR_TOWN_DIRECTORY_CAPTION :{WHITE}Città STR_TOWN_DIRECTORY_NONE :{ORANGE}- Nessuna - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Metropoli){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Nomi delle città - fare clic su un nome per centrare la visuale principale sulla città. CTRL+clic la mostra in una mini visuale. STR_TOWN_POPULATION :{BLACK}Popolazione mondiale: {COMMA} @@ -3014,8 +3070,7 @@ STR_TOWN_POPULATION :{BLACK}Popolazi STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Metropoli) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Popolazione: {ORANGE}{COMMA}{BLACK} Case: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Passeggeri il mese scorso: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Posta il mese scorso: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} +STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX :{BLACK}{CARGO_LIST} il mese scorso: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Carichi richiesti per la crescita della città: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} richiest{G 0 o o a} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} richiest{G 0 o o a} in inverno @@ -4262,6 +4317,7 @@ 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... @@ -4513,6 +4569,8 @@ STR_BASESOUNDS_DOS_DESCRIPTION :Suoni originali STR_BASESOUNDS_WIN_DESCRIPTION :Suoni originali di Transport Tycoon Deluxe, edizione Windows. STR_BASESOUNDS_NONE_DESCRIPTION :Un pacchetto sonoro non contenente alcun suono. STR_BASEMUSIC_WIN_DESCRIPTION :Musica originale di Transport Tycoon Deluxe, edizione Windows. +STR_BASEMUSIC_DOS_DESCRIPTION :Musica originale di Transport Tycoon Deluxe, edizione DOS. +STR_BASEMUSIC_TTO_DESCRIPTION :Musica originale di Transport Tycoon (edizione Original/World). STR_BASEMUSIC_NONE_DESCRIPTION :Un pacchetto musicale non contenente alcuna musica. ##id 0x2000 diff --git a/src/lang/japanese.txt b/src/lang/japanese.txt index 8e7f0c486d..8c3af735f4 100644 --- a/src/lang/japanese.txt +++ b/src/lang/japanese.txt @@ -669,10 +669,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}プレ STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}プレイリストのシャッフルの有効/無効を切り替えます STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}曲選択のウィンドウを表示します -STR_ERROR_NO_SONGS :{WHITE}選択した音楽セットに曲がありません - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}プレイリストの選択 STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}楽曲索引 STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}プレイリスト - '{STRING}' @@ -1337,8 +1334,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :ミニマップ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :緑 STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :濃緑 STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :青紫 -STR_CONFIG_SETTING_REVERSE_SCROLLING :スクロール方面を反転: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :マウス右ボタンで地図をスクロールする時の挙動を設定します。無効にした場合はマウスはカメラを動かします(マウスの移動方向に移動します)。有効にした場合は地図を動かします(マウスの移動方向と逆に移動します) STR_CONFIG_SETTING_SMOOTH_SCROLLING :画面のスムーズスクロール: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :ミニマップでの移動や「現在位置に移動」などのコマンドを使用した際にメイン画面がどのように移動するかを設定します。有効にした場合はスムーズにスクロールして移動します。無効の場合は目的地に直接ジャンプします STR_CONFIG_SETTING_MEASURE_TOOLTIP :測定ツールチップ表示: {STRING} @@ -1370,8 +1365,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :コマンド+ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+クリック (Win) STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :切 -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :左ドラッグスクロール: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :有効にすると左ドラッグでマップのスクロールができるようになります。特にタッチスクリーンを利用しているときに便利です STR_CONFIG_SETTING_AUTOSAVE :オートセーブ: {STRING} STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :オートセーブの間隔を設定します @@ -2690,6 +2683,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}オリ STR_ABOUT_VERSION :{BLACK}OpenTTD バージョン {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 The OpenTTD team +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}ゲームを保存 STR_SAVELOAD_LOAD_CAPTION :{WHITE}ゲームを開く @@ -2981,8 +2981,6 @@ STR_TOWN_POPULATION :{BLACK}地域 STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN}(市) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}人口: {ORANGE}{COMMA}人{BLACK} 建物: {ORANGE}{COMMA}戸 -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}旅客数(先月): {ORANGE}{COMMA}人{BLACK} 最大: {ORANGE}{COMMA}人 -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}郵便袋(先月): {ORANGE}{COMMA}袋{BLACK} 最大: {ORANGE}{COMMA}袋 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}街の成長に必要な物資: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}が{RED}必要です STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}が{BLACK}冬に必要です diff --git a/src/lang/korean.txt b/src/lang/korean.txt index b6dc29a099..8eb6dca1de 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -651,6 +651,7 @@ STR_MUSIC_RULER_MARKER :{TINY_FONT}{BLA STR_MUSIC_TRACK_NONE :{TINY_FONT}{DKGREEN}-- STR_MUSIC_TRACK_DIGIT :{TINY_FONT}{DKGREEN}{ZEROFILL_NUM} STR_MUSIC_TITLE_NONE :{TINY_FONT}{DKGREEN}------ +STR_MUSIC_TITLE_NOMUSIC :{TINY_FONT}{DKGREEN}사용 가능한 음악 없음 STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKGREEN}"{STRING}" STR_MUSIC_TRACK :{TINY_FONT}{BLACK}트랙 STR_MUSIC_XTITLE :{TINY_FONT}{BLACK}제목 @@ -670,15 +671,15 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}'사용 STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}프로그램을 무작위 재생합니다. STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}배경 음악 트랙을 선택할 수 있는 창을 엽니다. -STR_ERROR_NO_SONGS :{WHITE}선택된 배경 음악 목록에 노래가 없습니다. 배경 음악이 재생 되지 않을 것입니다. - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}배경 음악 프로그램 선택 +STR_PLAYLIST_MUSIC_SELECTION_SETNAME :{WHITE}음악 프로그램 - '{STRING}' STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}음악 목록 STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}프로그램 - '{STRING}' STR_PLAYLIST_CLEAR :{TINY_FONT}{BLACK}초기화 +STR_PLAYLIST_CHANGE_SET :{BLACK}세트 변경 STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}현재 배경 음악 프로그램을 초기화합니다. (사용자1, 사용자2에서만 선택 가능) +STR_PLAYLIST_TOOLTIP_CHANGE_SET :{BLACK}배경 음악 세트를 이미 설치된 다른 세트로 변경합니다. STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}배경 음악 목록에 음악을 추가하려면 클릭하세요. (사용자1, 사용자2에서만 사용 가능) STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}배경 음악 목록에서 음악을 제거하려면 클릭하세요. (사용자1, 사용자2에서만 사용 가능) @@ -881,7 +882,7 @@ STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION :{BIG_FONT}{BLAC # Extra view window STR_EXTRA_VIEW_PORT_TITLE :{WHITE}외부 화면 {COMMA} -STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}외부 화면에 복사 +STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}외부 화면으로 복사 STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN_TT :{BLACK}현재 장소를 외부 화면에 복사합니다. STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}이 장소로 이동 STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT :{BLACK}외부 화면에 저장된 장소로 이동합니다. @@ -1338,8 +1339,12 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :소형지도 STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :녹색 STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :어두운 녹색 STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :보라색 -STR_CONFIG_SETTING_REVERSE_SCROLLING :스크롤 방향 뒤집기: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :마우스 오른쪽 클릭으로 지도를 스크롤하는 방법을 선택합니다. 이 설정을을 끄면, 마우스 방향과 화면의 스크롤 방향이 같아집니다. 설정을 켜면, 마우스 방향과 화면의 스크롤 방향이 반대가 됩니다. +STR_CONFIG_SETTING_SCROLLMODE :외부 화면 스크롤 행동: {STRING} +STR_CONFIG_SETTING_SCROLLMODE_HELPTEXT :지도를 스크롤 할 때의 행동을 선택합니다. +STR_CONFIG_SETTING_SCROLLMODE_DEFAULT :마우스 오른쪽 클릭으로 외부 화면 이동 (마우스 위치는 고정) +STR_CONFIG_SETTING_SCROLLMODE_RMB_LOCKED :마우스 오른쪽 클릭으로 지도 이동 (마우스 위치는 고정) +STR_CONFIG_SETTING_SCROLLMODE_RMB :마우스 오른쪽 클릭으로 지도 이동 +STR_CONFIG_SETTING_SCROLLMODE_LMB :마우스 왼쪽 클릭으로 지도 이동 STR_CONFIG_SETTING_SMOOTH_SCROLLING :게임 화면을 이동시킬 때 부드럽게 이동: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :소형 지도를 클릭하여 특정 지역으로 스크롤되거나 지도 상의 특정 장소로 이동하는 경우에 주 화면이 어떻게 스크롤 되는지를 설정합니다. 이 설정을 켜면, 화면이 목표 지점까지 부드럽게 이동하고, 설정을 끄면 목표 지점으로 곧바로 넘어가게 됩니다. STR_CONFIG_SETTING_MEASURE_TOOLTIP :건설도구 사용시 거리 도움말 표시: {STRING} @@ -1352,7 +1357,7 @@ STR_CONFIG_SETTING_LIVERIES_ALL :모든 회사 STR_CONFIG_SETTING_PREFER_TEAMCHAT :엔터(ENTER) 키로 같은 팀끼리 채팅: {STRING} STR_CONFIG_SETTING_PREFER_TEAMCHAT_HELPTEXT :이 설정을 켜면, 멀티 플레이시 같은 회사 간의 채팅을 키 대신 키로 할 수 있게 됩니다. STR_CONFIG_SETTING_SCROLLWHEEL_SCROLLING :마우스 휠 동작: {STRING} -STR_CONFIG_SETTING_SCROLLWHEEL_SCROLLING_HELPTEXT :상하좌우로 회전 가능한 마우스 휠(2차원 마우스휠)로 지도를 스크롤할 수 있게 허용합니다. +STR_CONFIG_SETTING_SCROLLWHEEL_SCROLLING_HELPTEXT :상하좌우로 회전 가능한 마우스 휠(2차원 마우스 휠)로 지도를 스크롤할 수 있게 허용합니다. STR_CONFIG_SETTING_SCROLLWHEEL_ZOOM :화면 확대/축소 STR_CONFIG_SETTING_SCROLLWHEEL_SCROLL :지도 스크롤 STR_CONFIG_SETTING_SCROLLWHEEL_OFF :끄기 @@ -1371,8 +1376,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :커맨드 + 클 STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :CTRL + 클릭 STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :끄기 -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :마우스 왼쪽 버튼으로 스크롤: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :왼쪽 마우스 버튼을 드래그하여 지도를 스크롤 할 수 있도록 합니다. 터치 스크린 환경에서 이 설정을 켜면 매우 유용합니다. STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :오른쪽 클릭으로 창 닫기: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :창 내부를 오른쪽 클릭하여 창을 닫습니다. 오른쪽 클릭으로 도움말 표시 설정을 해제해야 합니다! @@ -2286,6 +2289,7 @@ STR_LINKGRAPH_LEGEND_CAPTION :{BLACK}화물 STR_LINKGRAPH_LEGEND_ALL :{BLACK}모두 STR_LINKGRAPH_LEGEND_NONE :{BLACK}없음 STR_LINKGRAPH_LEGEND_SELECT_COMPANIES :{BLACK}표시할 회사를 선택하십시오 +STR_LINKGRAPH_LEGEND_COMPANY_TOOLTIP :{BLACK}{STRING}{}{COMPANY} # Linkgraph legend window and linkgraph legend in smallmap STR_LINKGRAPH_LEGEND_UNUSED :{TINY_FONT}{BLACK}이용 없음 @@ -2694,6 +2698,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Original STR_ABOUT_VERSION :{BLACK}OpenTTD 버전 {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 OpenTTD 개발팀 +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}게임 저장 STR_SAVELOAD_LOAD_CAPTION :{WHITE}게임 불러오기 @@ -2978,6 +2989,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}팻말 STR_TOWN_DIRECTORY_CAPTION :{WHITE}도시 목록 STR_TOWN_DIRECTORY_NONE :{ORANGE}(없음) STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (대도시){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}도시 이름 - 이 도시로 시점을 변경하려면 클릭하세요. CTRL+클릭하면 이 도시 위치를 기준으로 새로운 외부 화면을 엽니다. STR_TOWN_POPULATION :{BLACK}총 인구 수: {COMMA} @@ -2985,8 +2997,7 @@ STR_TOWN_POPULATION :{BLACK}총 인 STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (대도시) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}인구: {ORANGE}{COMMA}{BLACK} 가구수: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}지난 달 승객 수: {ORANGE}{COMMA}{BLACK} 최대: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}지난달 우편수: {ORANGE}{COMMA}{BLACK} 최고: {ORANGE}{COMMA} +STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX :{BLACK}{CARGO_LIST} 지난 달: {ORANGE}{COMMA}{BLACK} 최대: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}도시가 성장하기 위해 필요한 화물: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED}{G 0 "이" "가"} 필요함 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :겨울에는 {ORANGE}{STRING}{BLACK}{G 0 "이" "가"} 필요함 @@ -4233,6 +4244,7 @@ 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}역의 일부를 제거할 수 없습니다... @@ -4480,10 +4492,12 @@ STR_DESKTOP_SHORTCUT_COMMENT :트랜스포트 STR_BASEGRAPHICS_DOS_DESCRIPTION :오리지널 트랜스포트 타이쿤 디럭스 도스 에디션의 그래픽입니다. STR_BASEGRAPHICS_DOS_DE_DESCRIPTION :오리지널 트랜스포트 타이쿤 디럭스 도스 에디션(독일)의 그래픽입니다. STR_BASEGRAPHICS_WIN_DESCRIPTION :오리지널 트랜스포트 타이쿤 디럭스 윈도 에디션의 그래픽입니다. -STR_BASESOUNDS_DOS_DESCRIPTION :오리지널 트랜스포트 타이쿤 도스 에디션의 효과음입니다. +STR_BASESOUNDS_DOS_DESCRIPTION :오리지널 트랜스포트 타이쿤 디럭스 도스 에디션의 효과음입니다. STR_BASESOUNDS_WIN_DESCRIPTION :오리지널 트랜스포트 타이쿤 디럭스 윈도 에디션의 효과음입니다. STR_BASESOUNDS_NONE_DESCRIPTION :아무런 효과음도 없는 효과음 팩입니다. STR_BASEMUSIC_WIN_DESCRIPTION :오리지널 트랜스포트 타이쿤 디럭스 윈도 에디션의 음악입니다. +STR_BASEMUSIC_DOS_DESCRIPTION :오리지널 트랜스포트 타이쿤 디럭스 DOS 에디션의 음악입니다. +STR_BASEMUSIC_TTO_DESCRIPTION :오리지널 트랜스포트 타이쿤 (오리지널/월드 에디터) DOS 에디션의 음악입니다. STR_BASEMUSIC_NONE_DESCRIPTION :실제 음악이 없는 음악 목록입니다. ##id 0x2000 diff --git a/src/lang/latin.txt b/src/lang/latin.txt index 42047a47d6..9c2834da02 100644 --- a/src/lang/latin.txt +++ b/src/lang/latin.txt @@ -838,6 +838,7 @@ STR_MUSIC_RULER_MARKER :{TINY_FONT}{BLA STR_MUSIC_TRACK_NONE :{TINY_FONT}{DKGREEN}-- STR_MUSIC_TRACK_DIGIT :{TINY_FONT}{DKGREEN}{ZEROFILL_NUM} STR_MUSIC_TITLE_NONE :{TINY_FONT}{DKGREEN}------ +STR_MUSIC_TITLE_NOMUSIC :{TINY_FONT}{DKGREEN}Nulla musica parata STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKGREEN}"{STRING}" STR_MUSIC_TRACK :{TINY_FONT}{BLACK}Carmen STR_MUSIC_XTITLE :{TINY_FONT}{BLACK}Titulus @@ -857,15 +858,15 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Eligere STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Incipere desinereve admixtionem carminum STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Monstrare fenestram electionis carminum -STR_ERROR_NO_SONGS :{WHITE}Compositio sine carminibus electa est. Nulla carmina canentur - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Electio Compositionis Musicae +STR_PLAYLIST_MUSIC_SELECTION_SETNAME :{WHITE}Compositio Musicae - '{STRING}' STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Index Carminum STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Compositio - '{STRING}' STR_PLAYLIST_CLEAR :{TINY_FONT}{BLACK}Vacuefacere +STR_PLAYLIST_CHANGE_SET :{BLACK}Mutare gregem STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Vacuefacere compositionem (modo Propriam I aut Propriam II) +STR_PLAYLIST_TOOLTIP_CHANGE_SET :{BLACK}Mutare gregem musicam STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}Preme in carmen ut compositioni addantur (modo Propriae I aut Propriae II) STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}Preme in carmen ut ex compositione removeatur (modo Propria I aut Propria II) @@ -1068,10 +1069,10 @@ STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION :{BIG_FONT}{BLAC # Extra view window STR_EXTRA_VIEW_PORT_TITLE :{WHITE}Fenestra conspectus {COMMA} -STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Transcribere ad fenestram conspectus +STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Mutare conspectum STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN_TT :{BLACK}Transcribere locum primarium ad hanc fenestram conspectus -STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Glutinare ex fenestra conspectus -STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT :{BLACK}Glutinare locum ex hac fenestra ad conspectum primarium +STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Mutare conspectum primum +STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT :{BLACK}Transcribere locum ex hac fenestra ad conspectum primarium # Game options window STR_GAME_OPTIONS_CAPTION :{WHITE}Ludi optiones @@ -1525,9 +1526,13 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Color terrae in STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Viridis STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Viridis Obscurus STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Purpureus -STR_CONFIG_SETTING_REVERSE_SCROLLING :Revertere cursum vagationis: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Quomodo tabula vagatur globulo dextri presso. Neglecta, mus conspectum movet. Electa, mus tabulam movet -STR_CONFIG_SETTING_SMOOTH_SCROLLING :Vagari conspectum leniter: {STRING} +STR_CONFIG_SETTING_SCROLLMODE :Modus conspectum movendi: {STRING} +STR_CONFIG_SETTING_SCROLLMODE_HELPTEXT :Quomodo tabula geographica vagatur +STR_CONFIG_SETTING_SCROLLMODE_DEFAULT :Conspectus movetur globulo dextro, loco muris fixo +STR_CONFIG_SETTING_SCROLLMODE_RMB_LOCKED :Tabula movetur globulo dextro, loco muris fixo +STR_CONFIG_SETTING_SCROLLMODE_RMB :Tabula movetur globulo muris dextro +STR_CONFIG_SETTING_SCROLLMODE_LMB :Tabula movetur globulo muris sinistro +STR_CONFIG_SETTING_SMOOTH_SCROLLING :Movere conspectum leniter: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Quomodo conspectus vagatur ad quemdam locum globulo sinistro in tabula premendi aut cum iubetur vagari ad quamdam rem in tabula. Electa, conspectus leniter vagatur. Neglecta, statim salit ad locum STR_CONFIG_SETTING_MEASURE_TOOLTIP :Ostendere nuntium adiuvans apud varia ferramenta construendi: {STRING} STR_CONFIG_SETTING_MEASURE_TOOLTIP_HELPTEXT :Ostendere spatium atque altitudinem inter tegulas dum mus trahitur in construendo @@ -1558,8 +1563,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Cmd+Premere STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+Premere STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Neglecta -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Vagatio globuli sinistri: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Annuere tabulam vagari trahendo globuli sinistri. Magnopere utilis est cum tangendo navigas in scrinio STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Claudere fenestras globulo muris dextro: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Facit ut globulus muris dexter fenestras claudat. Cave: hac electa, non apparent nuntia adiuvantia globulo dextro. @@ -2483,6 +2486,7 @@ STR_LINKGRAPH_LEGEND_CAPTION :{BLACK}Formula STR_LINKGRAPH_LEGEND_ALL :{BLACK}Omnia STR_LINKGRAPH_LEGEND_NONE :{BLACK}Nulla STR_LINKGRAPH_LEGEND_SELECT_COMPANIES :{BLACK}Eligere societates monstrandas +STR_LINKGRAPH_LEGEND_COMPANY_TOOLTIP :{BLACK}{STRING}{}{COMPANY} # Linkgraph legend window and linkgraph legend in smallmap STR_LINKGRAPH_LEGEND_UNUSED :{TINY_FONT}{BLACK}non usus @@ -2895,6 +2899,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Privileg STR_ABOUT_VERSION :{BLACK}OpenTTD editio {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} MMII-MMXVII Manus OpenTTD +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Servare Ludum STR_SAVELOAD_LOAD_CAPTION :{WHITE}Legere Ludum @@ -3179,6 +3190,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Inscribe STR_TOWN_DIRECTORY_CAPTION :{WHITE}Oppida STR_TOWN_DIRECTORY_NONE :{ORANGE}- Nulla - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Urbs){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Nomina oppidorum - preme in nomen ut conspectus supra oppidum locetur. Ctrl+Preme ut novam fenestram conspectus supra oppidum aperiatur STR_TOWN_POPULATION :{BLACK}Incolae mundi: {COMMA} @@ -3186,8 +3198,6 @@ STR_TOWN_POPULATION :{BLACK}Incolae STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Urbs) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Incolae: {ORANGE}{COMMA}{BLACK} Aedificia: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Vectores mensis prioris: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Epistulae mensis prioris: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Onera mandata ad oppidum crescendum: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} mandatur STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} hieme mandatur @@ -4436,6 +4446,7 @@ 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... @@ -4687,6 +4698,8 @@ STR_BASESOUNDS_DOS_DESCRIPTION :Soni ex edition STR_BASESOUNDS_WIN_DESCRIPTION :Soni ex editione originale Transport Tycoon Deluxe Windows. STR_BASESOUNDS_NONE_DESCRIPTION :Sarcina sonorum sine ullis sonis. STR_BASEMUSIC_WIN_DESCRIPTION :Musica ex editione originale Transport Tycoon Deluxe Windows. +STR_BASEMUSIC_DOS_DESCRIPTION :Musica ex editione originale Transport Tycoon Deluxe DOS. +STR_BASEMUSIC_TTO_DESCRIPTION :Musica ex editione originale Transport Tycoon (Originale/World Editor) DOS. STR_BASEMUSIC_NONE_DESCRIPTION :Sarcina musicae sine ulla musica. ##id 0x2000 diff --git a/src/lang/latvian.txt b/src/lang/latvian.txt index dab5900f75..0408558c5a 100644 --- a/src/lang/latvian.txt +++ b/src/lang/latvian.txt @@ -669,10 +669,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Izvēlē STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Ieslēgt/izslēgt mūzikas saraksta jaukšanu STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Rādīt mūzikas celiņu atlases logu -STR_ERROR_NO_SONGS :{WHITE}Izvēlēts komplekts bez mūzikas. Mūzika netiks atskaņota - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Mūzikas programmas izvēle STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Celiņu rādītājs STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Programma - '{STRING}' @@ -1307,7 +1304,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Apvidus krāsa STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :zaļa STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :{G=f}tumši zaļa STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :{G=f}violeta -STR_CONFIG_SETTING_REVERSE_SCROLLING :Pretējs ritināšanas virziens: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING :Plūdena skatvietas ritināšana: {STRING} STR_CONFIG_SETTING_MEASURE_TOOLTIP :Rādīt mērījumu rīkjoslu, izmantojot dažādus būvniecības rīkus: {STRING} STR_CONFIG_SETTING_MEASURE_TOOLTIP_HELPTEXT :Rāda lauciņu attālumus un augstuma starpības, ar vilkšanu veicot būvniecības darbības @@ -1337,7 +1333,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Komanda+klikš STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+klikšķis STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Izslēgta -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Kreisā klikšķa ritināšana: {STRING} STR_CONFIG_SETTING_AUTOSAVE :Automātiskā saglabāšana: {STRING} STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :Izvēlēties spēles automātiskās saglabāšanas starplaikus @@ -2630,6 +2625,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Oriģin STR_ABOUT_VERSION :{BLACK}OpenTTD versija {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 OpenTTD darba grupa +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Saglabāt spēli STR_SAVELOAD_LOAD_CAPTION :{WHITE}Ielādēt spēli @@ -2913,8 +2915,6 @@ STR_TOWN_POPULATION :{BLACK}Pasaules STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (lielpilsēta) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Iedzīvotāji: {ORANGE}{COMMA}{BLACK} Mājas: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Pasažieri pagājušajā mēnesī: {ORANGE}{COMMA}{BLACK} maksimāli: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Pasts pagājušajā mēnesī: {ORANGE}{COMMA}{BLACK} maksimāli: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Krava nepieciešama pilsētas attīstībai: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} nepieciešams STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} nepieciešams ziemā diff --git a/src/lang/lithuanian.txt b/src/lang/lithuanian.txt index 4d44522671..5b8a103696 100644 --- a/src/lang/lithuanian.txt +++ b/src/lang/lithuanian.txt @@ -864,10 +864,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Parinkti STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Programos „Atsitiktiniai takeliai“ įj./išj. STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Rodyti muzikos takelių pasirinkimo langą -STR_ERROR_NO_SONGS :{WHITE}Pasirinktas muzikos rinkinys be dainų. Dainos nebus grojamos - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Muzikos programos pasirinkimas STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} „{STRING}“ STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Takelio numeris STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Programa - „{STRING}“ @@ -1542,8 +1539,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Reljefo spalva STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Žalia STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Tamsiai žalia STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Violetinė -STR_CONFIG_SETTING_REVERSE_SCROLLING :Priešinga slinkties kryptis: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Vaizdo slinkties elgsena, laikant nuspaudus dešinįjį pelės klavišą: pasirinkus „ne“, judės stebėtojas. Pasirinkus „taip“, judės žemėlapis STR_CONFIG_SETTING_SMOOTH_SCROLLING :Tolydi vaizdo slinktis: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Įjungus šią nuostatą ir pakeitus pagrindinio lango rodomą vietą (pvz., spragtelėjus žemėlapyje), vaizdas slinksis tolydžiai. Priešingu atveju vaizdas pasikeis akimirksniu, šuoliškai. STR_CONFIG_SETTING_MEASURE_TOOLTIP :Rodyti matavimo pastabą, kai naudojami įvairūs statybų įrankiai: {STRING} @@ -1575,8 +1570,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command+Click STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+Click STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Išjungta -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Left-click scrolling: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Slinkti žemėlapį velkant jį nuspaudus kairįjį pelės klavišą. Naudinga, jei žaidžiama kompiuteriuose su lietimui jautriais ekranais STR_CONFIG_SETTING_AUTOSAVE :Automatinis saugojimas: {STRING} STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :Laiko tarpsnis tarp automatinių žaidimo išsaugojimų @@ -2908,6 +2901,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Pradinė STR_ABOUT_VERSION :{BLACK}OpenTTD versija {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2018 OpenTTD komanda +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Išsaugoti žaidimą STR_SAVELOAD_LOAD_CAPTION :{WHITE}Įkelti žaidimą @@ -3199,8 +3199,6 @@ STR_TOWN_POPULATION :{BLACK}Pasaulio STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Miestas) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Populiacija: {ORANGE}{COMMA}{BLACK} Namų skaičius: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Praėjusio mėnesio keleivių sk.: {ORANGE}{COMMA}{BLACK} Daugiausia: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Praėjusio mėnesio pašto siuntų sk.: {ORANGE}{COMMA}{BLACK} Daugiausia: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Kad miestas augtų reikalingi kroviniai: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} reikia STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} reikalingas žiemą diff --git a/src/lang/luxembourgish.txt b/src/lang/luxembourgish.txt index 38dba61000..c4978c0b88 100644 --- a/src/lang/luxembourgish.txt +++ b/src/lang/luxembourgish.txt @@ -669,10 +669,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Wielt de STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Schalt den "shuffle" un/aus STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Weis d'Fënster fir Musik ze wielen -STR_ERROR_NO_SONGS :{WHITE}E Music Set ouni Lidder gouf gewielt. Et wäerten keng Lidder gespillt ginn - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Musiksprogramm Auswiel STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Lidder Index STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Programm - '{STRING}' @@ -1337,8 +1334,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Faarf vum Terra STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Gréng STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Donkelgréng STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Mof -STR_CONFIG_SETTING_REVERSE_SCROLLING :Deen anere Wee scrollen: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Verhalen beim Scrollen vun der Kaart mat der rietser Maustast. Wann ausgeschalt, beweegt d'Maus d'Kamera. Wann ugeschalt, beweegt d'Maus d'Kaart STR_CONFIG_SETTING_SMOOTH_SCROLLING :Feine Scrolling: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Kontrolléiert wéi d'Haptusiicht op eng bestëmmten Positioun scrollt, wann een op déi kléng Kaart klickt oder en Befehl fir ob en spezifescht Objet ze scrollen gëtt. Wann ugeschalt, gëtt bis dohin gescrollt, wann ausgeschalt, spréngt d'Vue op den Zielobjet STR_CONFIG_SETTING_MEASURE_TOOLTIP :Weis en Mooss-Tooltip wann verschidde Bau-Tools benotzt ginn: {STRING} @@ -1370,8 +1365,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :COMM+Klick STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :CTRL+Klick STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Aus -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Lénksklickscroll: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Schalt d'Scrollen vun der Kaart un, wann se mat der lénker Maustast gezunn gëtt STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Fënster mat rietsem Mausklick zouman: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Mécht eng Fenster mat engem Rietsklick zou, wann een an d'Fënster klickt. Schalt Tooltips aus déi per Rietsklick gemet ginn! @@ -2693,6 +2686,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Original STR_ABOUT_VERSION :{BLACK}OpenTTD Versioun {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 D'OpenTTD team +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Spill späicheren STR_SAVELOAD_LOAD_CAPTION :{WHITE}Spill lueden @@ -2984,8 +2984,6 @@ STR_TOWN_POPULATION :{BLACK}Weltbev STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Stad) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Awunner: {ORANGE}{COMMA}{BLACK} Haiser: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Passagéier leschte Mount: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Post leschte Mount: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Gidder gebraucht fir Stadwuesstem: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} gebraucht STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} gebraucht am Wanter diff --git a/src/lang/malay.txt b/src/lang/malay.txt index 4ba83efdaa..1aa657c22c 100644 --- a/src/lang/malay.txt +++ b/src/lang/malay.txt @@ -215,6 +215,7 @@ STR_UNITS_VOLUME_LONG_SI :{COMMA} m³ STR_UNITS_FORCE_SI :{COMMA} kN STR_UNITS_HEIGHT_IMPERIAL :{COMMA} ka +STR_UNITS_HEIGHT_METRIC :{COMMA}{NBSP}m STR_UNITS_HEIGHT_SI :{COMMA} m # Common window strings @@ -241,6 +242,7 @@ STR_TOOLTIP_HSCROLL_BAR_SCROLLS_LIST :{BLACK}Bar Skro STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC :{BLACK}Musnahkan bangunan dll. dari dataran tanah. Ctrl memilih kawasan menyerong. Shift bangunan/tunjukkan anggaran kos. # Show engines button +STR_SHOW_HIDDEN_ENGINES_VEHICLE_AIRCRAFT :{BLACK}Tunjukkan perkara yang tersembunyi STR_SHOW_HIDDEN_ENGINES_VEHICLE_SHIP_TOOLTIP :{BLACK}Dengan membenarkan pilihan ini, kapal tersembunyi turut ditunjukkan @@ -453,7 +455,7 @@ STR_ABOUT_MENU_TOGGLE_CONSOLE :Papar atau pada STR_ABOUT_MENU_AI_DEBUG :Al/Skrip pepijat permainan STR_ABOUT_MENU_SCREENSHOT :Tangkapan skrin (Ctrl+S) STR_ABOUT_MENU_ZOOMIN_SCREENSHOT :Zum sepenuhnya di pembidik skrin -STR_ABOUT_MENU_DEFAULTZOOM_SCREENSHOT :Tangkapan skrin dizoom asal +STR_ABOUT_MENU_DEFAULTZOOM_SCREENSHOT :Tangkapan skrin di zum asal STR_ABOUT_MENU_GIANT_SCREENSHOT :Tangkap gambar skrin besar (Ctrl+G) STR_ABOUT_MENU_ABOUT_OPENTTD :Tentang 'OpenTTD' STR_ABOUT_MENU_SPRITE_ALIGNER :Penjajar peperi @@ -610,7 +612,7 @@ STR_PERFORMANCE_DETAIL_MIN_INCOME_TOOLTIP :{BLACK}Jumlah w STR_PERFORMANCE_DETAIL_MAX_INCOME_TOOLTIP :{BLACK}Jumlah wang keuntungan dalam suku tahun dengan keuntungan tertinggi dalam 12 suku tahun yang lepas STR_PERFORMANCE_DETAIL_DELIVERED_TOOLTIP :{BLACK}Unit-unit kargo yang dihantar dalam 4 suku tahun yang lepas STR_PERFORMANCE_DETAIL_CARGO_TOOLTIP :{BLACK}Jumlah jenis kargo yang dihantar dalam suku tahun yang lepas -STR_PERFORMANCE_DETAIL_MONEY_TOOLTIP :{BLACK}Jumlah wang syarikat ini mempunyai dalam bank +STR_PERFORMANCE_DETAIL_MONEY_TOOLTIP :{BLACK}Jumlah wang syarikat di dalam bank STR_PERFORMANCE_DETAIL_LOAN_TOOLTIP :{BLACK}Jumlah wang syarikat ini yang telah dipinjam STR_PERFORMANCE_DETAIL_TOTAL_TOOLTIP :{BLACK}Jumlah markah daripada markah yang boleh diperolehi @@ -649,10 +651,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Pilih ra STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Mainkan muzik secara rawak atau tidak STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Tunjukkan tetingkap pilihan lagu -STR_ERROR_NO_SONGS :{WHITE}Set muzik yang tidak mengandungi lagu telah dipilih. Tiada lagu yang akan dimainkan - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Pilihan Rancangan Muzik STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Indeks Lagu STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Program - '{STRING}' @@ -737,6 +736,7 @@ STR_SMALLMAP_TOOLTIP_ENABLE_ALL_INDUSTRIES :{BLACK}Paparkan STR_SMALLMAP_TOOLTIP_SHOW_HEIGHT :{BLACK}Papar atau padamkan heightmap STR_SMALLMAP_TOOLTIP_DISABLE_ALL_COMPANIES :{BLACK}Paparkan hartanah tanpa syarikat pada peta STR_SMALLMAP_TOOLTIP_ENABLE_ALL_COMPANIES :{BLACK}Paparkan seluruh maklumat hartanah syarikat pada peta +STR_SMALLMAP_TOOLTIP_ENABLE_ALL_CARGOS :{BLACK}Tunjukkan semua kargo di atas peta # Status bar messages STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS :{BLACK}Tunjukkan mesej atau laporan berita terakhir @@ -853,10 +853,10 @@ STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION :{BIG_FONT} {BLA # Extra view window STR_EXTRA_VIEW_PORT_TITLE :{WHITE}Tetingkap Pemandangan {COMMA} -STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Salin ke tetingkap pemandangan +STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Ubah tetingkap paparan STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN_TT :{BLACK}Salin lokasi pemandangan global kepada tetingkap pemandangan ini -STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Tampal daripada tetingkap pemandangan -STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT :{BLACK}Salin lokasi tetingkap pemandangan ini kepada pemandangan utama +STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Ubah paparan utama +STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT :{BLACK}Salin lokasi tetingkap paparan ini ke paparan utama # Game options window STR_GAME_OPTIONS_CAPTION :{WHITE}Pilihan Permainan @@ -1218,6 +1218,7 @@ STR_CONFIG_SETTING_ORDER_REVIEW_ON :Semua kenderaan STR_CONFIG_SETTING_WARN_INCOME_LESS :Beri amaran jika pendapatan kenderaan adalah negatif: {STRING} STR_CONFIG_SETTING_NEVER_EXPIRE_VEHICLES :Kenderaan tidak akan tamat tempohnya: {STRING} STR_CONFIG_SETTING_AUTORENEW_VEHICLE :Gunakan pembaharuan automatik apabila kenderaan usang : {STRING} +STR_CONFIG_SETTING_AUTORENEW_MONTHS_VALUE_AFTER :{COMMA} bulan{P 0 "" s} selepas STR_CONFIG_SETTING_AUTORENEW_MONEY :Wang minimum yang diperlukan untuk pembaharuan automatik: {STRING} STR_CONFIG_SETTING_ERRMSG_DURATION :Jangkamasa mesej ralat: {STRING} STR_CONFIG_SETTING_POPULATION_IN_LABEL :Tunjukkan jumlah penduduk dalam label nama bandar: {STRING} @@ -1253,7 +1254,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR :Warna tanah yan STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Hijau STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Hijau Gelap STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Ungu -STR_CONFIG_SETTING_REVERSE_SCROLLING :Arah skrol terbalik: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING :Skrol tetingkap pemandangan yang licin: {STRING} STR_CONFIG_SETTING_MEASURE_TOOLTIP :Tunjukkan bantuan ukuran ketika menggunakan alat binaan: {STRING} STR_CONFIG_SETTING_LIVERIES :Tunjukkan seragam syarikat: {STRING} @@ -1266,6 +1266,7 @@ STR_CONFIG_SETTING_SCROLLWHEEL_ZOOM :Membesarkan pet STR_CONFIG_SETTING_SCROLLWHEEL_SCROLL :Skrol peta STR_CONFIG_SETTING_SCROLLWHEEL_OFF :Matikan STR_CONFIG_SETTING_SCROLLWHEEL_MULTIPLIER :Kelajuan roda skrol pada peta: {STRING} +STR_CONFIG_SETTING_SCROLLWHEEL_MULTIPLIER_HELPTEXT :Kawal kesensitifan skrol roda tetikus STR_CONFIG_SETTING_OSK_ACTIVATION :Papan kekunci di skrin: {STRING} STR_CONFIG_SETTING_OSK_ACTIVATION_HELPTEXT :Pilih kaedah untuk membuka papan kekunci pada skrin untuk memasukkan teks ke dalam kotak edit hanya menggunakan petunjuk peranti. Ini bertujuan untuk peranti kecil yang tiada papan kekunci sebenar STR_CONFIG_SETTING_OSK_ACTIVATION_DISABLED :Dinyah-upayakan @@ -1278,7 +1279,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command+Klik STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+Klik STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Matikan -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Skrol klik-kiri: {STRING} STR_CONFIG_SETTING_AUTOSAVE :Simpanan automatik:{STRING} STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :Pilih jarak waktu antara menyimpankan permainan automatik @@ -1298,6 +1298,7 @@ STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS :Gunakan senarai STR_CONFIG_SETTING_LOADING_INDICATORS :Gunakan penunjuk muatan: {STRING} STR_CONFIG_SETTING_TIMETABLE_IN_TICKS :Tunjukkan jadual menggunakan tanda rait dan bukan hari: {STRING} STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE :Tunjukkan ketibaan dan pelepasan dalam jadual: {STRING} +STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE_HELPTEXT :Tunjukkan jangkaan waktu ketibaan dan pelepasan dalam jadual STR_CONFIG_SETTING_QUICKGOTO :Pewujudan pantas arahan kenderaan: {STRING} STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE :Landasan keretapi lazim (apabila memulakan permainan baru/buka permainan: {STRING} STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_FIRST :Yang tersedia terawal @@ -1305,6 +1306,7 @@ STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_LAST :Yang tersedia s STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_MOST_USED :Yang selalu digunakan STR_CONFIG_SETTING_SHOW_TRACK_RESERVATION :Tunjukkan landasan yang ditempah: {STRING} STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS :Alat binaan tetap aktif selepas digunakan: {STRING} +STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS_HELPTEXT :Simpan alat pembinaan untuk jambatan, terowong, dll. buka selepas guna STR_CONFIG_SETTING_EXPENSES_LAYOUT :Perbelanjaan kumpulan dalam tetingkap kewangan syarikat: {STRING} STR_CONFIG_SETTING_SOUND_CONFIRM :Pembinaan: {STRING} @@ -1312,6 +1314,7 @@ STR_CONFIG_SETTING_SOUND_CONFIRM :Pembinaan: {STR STR_CONFIG_SETTING_DISABLE_UNSUITABLE_BUILDING :Nyahaktif infrastruktur bangunan apabila tiada kenderaan yang sesuai: {STRING} STR_CONFIG_SETTING_MAX_TRAINS :Amaun maksimum kereta api setiap syarikat: {STRING} STR_CONFIG_SETTING_MAX_ROAD_VEHICLES :Amaun maksimum kenderaan jalanraya setiap syarikat: {STRING} +STR_CONFIG_SETTING_MAX_ROAD_VEHICLES_HELPTEXT :Jumlah maksimum kenderaan darat sesebuah syarikat STR_CONFIG_SETTING_MAX_AIRCRAFT :Amaun maksimum pesawat setiap syarikat: {STRING} STR_CONFIG_SETTING_MAX_SHIPS :Amaun maksimum kapal setiap syarikat: {STRING} @@ -1332,7 +1335,10 @@ STR_CONFIG_SETTING_SCRIPT_MAX_OPCODES :#opcodes sebelu STR_CONFIG_SETTING_SERVINT_ISPERCENT :Tempoh waktu servis dalam peratusan: {STRING} STR_CONFIG_SETTING_SERVINT_ISPERCENT_HELPTEXT :Pilih sama ada selenggara kenderaan dimulakan sejak tempoh masa dari servis terakhir atau apabila peratusan kebolehupayaan kenderaan berkurang kepada peratusan tertentu. +STR_CONFIG_SETTING_SERVINT_VALUE :{COMMA}{NBSP}hari{P 0 "" s}/% STR_CONFIG_SETTING_SERVINT_DISABLED :Dilumpuhkan +STR_CONFIG_SETTING_SERVINT_AIRCRAFT_HELPTEXT :Tetapkan selang masa servis untuk pesawat baru kepada tetapan asal jika tiada selang masa servis yang jelas ditetapkan untuk pesawat tersebut +STR_CONFIG_SETTING_SERVINT_SHIPS_HELPTEXT :Tetapkan selang masa servis untuk kapal baru kepada tetapan asal jika tiada selang masa servis yang jelas ditetapkan untuk kapal tersebut STR_CONFIG_SETTING_NOSERVICE :Servis tidak diperlukan apabila kerosakan kenderaan ditetapkan kepada tiada: {STRING} STR_CONFIG_SETTING_WAGONSPEEDLIMITS :Benarkan had kelajuan untuk gerabak: {STRING} STR_CONFIG_SETTING_DISABLE_ELRAILS :Tiada landasan elektrik: {STRING} @@ -1344,13 +1350,16 @@ STR_CONFIG_SETTING_NEWS_COMPANY_INFORMATION :Maklumat syarik STR_CONFIG_SETTING_NEWS_COMPANY_INFORMATION_HELPTEXT :Paparkan surat khabar mengenai pembukaan syarikat baru, atau apabila syarikat dalam risiko untuk muflis STR_CONFIG_SETTING_NEWS_INDUSTRY_OPEN :Pembukaan industri: {STRING} STR_CONFIG_SETTING_NEWS_INDUSTRY_CLOSE :Penutupan industri: {STRING} +STR_CONFIG_SETTING_NEWS_INDUSTRY_CLOSE_HELPTEXT :Paparkan keratan akhbar apabila ada industri yang ditutup STR_CONFIG_SETTING_NEWS_ECONOMY_CHANGES :Perubahan ekonomi: {STRING} STR_CONFIG_SETTING_NEWS_INDUSTRY_CHANGES_COMPANY :Perubahan pengeluaran industri-industri yang diservis oleh syarikat: {STRING} STR_CONFIG_SETTING_NEWS_INDUSTRY_CHANGES_OTHER :Perubahan pengeluaran industri-industri yang diservis oleh pesaing: {STRING} +STR_CONFIG_SETTING_NEWS_INDUSTRY_CHANGES_OTHER_HELPTEXT :Paparkan keratan akhbar apabila berlaku perubahan tahap pengeluaran industri yang diservis oleh pesaing STR_CONFIG_SETTING_NEWS_INDUSTRY_CHANGES_UNSERVED :Pengubaran pengeluaran industri lain: {STRING} STR_CONFIG_SETTING_NEWS_ADVICE :Nasihat / maklumat tentang kenderaan syarikat: {STRING} STR_CONFIG_SETTING_NEWS_NEW_VEHICLES :Kenderaan baru: {STRING} STR_CONFIG_SETTING_NEWS_CHANGES_ACCEPTANCE :Penukaran pada penerimaan kargo: {STRING} +STR_CONFIG_SETTING_NEWS_CHANGES_ACCEPTANCE_HELPTEXT :Tunjukkan mesej berkenaan perubahan kebolehterimaan sesetengah kargo di stesen terlibat STR_CONFIG_SETTING_NEWS_SUBSIDIES :Subsidi: {STRING} STR_CONFIG_SETTING_NEWS_GENERAL_INFORMATION :Maklumat umum: {STRING} @@ -1411,17 +1420,25 @@ STR_CONFIG_SETTING_TOWN_GROWTH_NORMAL :Biasa STR_CONFIG_SETTING_TOWN_GROWTH_FAST :Pantas STR_CONFIG_SETTING_TOWN_GROWTH_VERY_FAST :Sangat pantas STR_CONFIG_SETTING_LARGER_TOWNS_VALUE :1 dalam {COMMA} +STR_CONFIG_SETTING_LARGER_TOWNS_DISABLED :Tiada STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER :Pengganda awal saiz bandar: {STRING} +STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER_IMPERIAL :Sistem Imperial (kuasa kuda/hp) +STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER_METRIC :Sistem metrik (kuasa kuda/hp) +STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER_SI :Unit SI (kW) + + +STR_CONFIG_SETTING_LOCALISATION_UNITS_VOLUME_SI :Unit SI (m³) - - +STR_CONFIG_SETTING_SOUND :{ORANGE}Bunyi STR_CONFIG_SETTING_INTERFACE :{ORANGE}Antaramuka (Interface) STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION :{ORANGE}Pembinaan +STR_CONFIG_SETTING_ADVISORS :{ORANGE}Berita / Penasihat +STR_CONFIG_SETTING_COMPANY :{ORANGE}Syarikat STR_CONFIG_SETTING_VEHICLES :{ORANGE}Kenderaan STR_CONFIG_SETTING_VEHICLES_ROUTING :{ORANGE}Laluan STR_CONFIG_SETTING_ACCIDENTS :{ORANGE}Kecelakaan / Kemalangan @@ -1502,7 +1519,7 @@ STR_INTRO_TRANSLATION :{BLACK}Terjemah # Quit window STR_QUIT_CAPTION :{WHITE}Keluar -STR_QUIT_ARE_YOU_SURE_YOU_WANT_TO_EXIT_OPENTTD :{YELLOW}Pastikah anda untuk keluar dari OpenTTD dan kembali ke {STRING}? +STR_QUIT_ARE_YOU_SURE_YOU_WANT_TO_EXIT_OPENTTD :{YELLOW}Adakah anda pasti untuk keluar dari OpenTTD dan kembali ke {STRING}? STR_QUIT_YES :{BLACK}Ya STR_QUIT_NO :{BLACK}Tidak @@ -1520,8 +1537,8 @@ STR_OSNAME_SUNOS :SunOS # Abandon game STR_ABANDON_GAME_CAPTION :{WHITE}Tinggalkan Permainan -STR_ABANDON_GAME_QUERY :{YELLOW}Pastikah anda mahu keluar permainan ini? -STR_ABANDON_SCENARIO_QUERY :{YELLOW}Pastikah anda untuk keluar senario ini? +STR_ABANDON_GAME_QUERY :{YELLOW}Pastikah anda mahu keluar dari permainan ini? +STR_ABANDON_SCENARIO_QUERY :{YELLOW}Pastikah anda untuk keluar dari senario ini? # Cheat window STR_CHEATS :{WHITE}Penipuan (Cheats) @@ -1696,6 +1713,7 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Nama per STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Tetapkan kata laluan STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Lindungi permainan anda dengan kata laluan jika anda tidak mahu ianya diakses awam +STR_NETWORK_START_SERVER_UNADVERTISED :Tidak STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} pelanggan STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Amaun maksimum pemain: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Tentukan bilangan klien maks. Tidak perlu semua slot diisi @@ -1773,7 +1791,7 @@ STR_NETWORK_GAME_LOBBY_NEW_COMPANY_TOOLTIP :{BLACK}Mulakan STR_NETWORK_GAME_LOBBY_SPECTATE_GAME :{BLACK}Saksikan permainan STR_NETWORK_GAME_LOBBY_SPECTATE_GAME_TOOLTIP :{BLACK}Saksikan permainan sebagai seorang penyaksi STR_NETWORK_GAME_LOBBY_JOIN_COMPANY :{BLACK}Sertai syarikat -STR_NETWORK_GAME_LOBBY_JOIN_COMPANY_TOOLTIP :{BLACK}Bantu mengurus syarikat ini +STR_NETWORK_GAME_LOBBY_JOIN_COMPANY_TOOLTIP :{BLACK}Bantu uruskan syarikat ini # Network connecting window STR_NETWORK_CONNECTING_CAPTION :{WHITE}Menyambung... @@ -1934,6 +1952,7 @@ STR_CONTENT_SELECT_UPDATES_CAPTION :{BLACK}Pilih pe STR_CONTENT_SELECT_UPDATES_CAPTION_TOOLTIP :{BLACK}Tandakan semua kandungan sedia ada yang telah ditingkatkan untuk dimuat turun STR_CONTENT_UNSELECT_ALL_CAPTION :{BLACK}Nyahpilihkan semua STR_CONTENT_UNSELECT_ALL_CAPTION_TOOLTIP :{BLACK}Tandakan semua kandungan supaya jangan dimuat turun +STR_CONTENT_SEARCH_EXTERNAL_DISCLAIMER_CAPTION :{WHITE}Anda sedang meninggalkan OpenTTD! STR_CONTENT_FILTER_TITLE :{BLACK}Saringan tag/nama: STR_CONTENT_OPEN_URL :{BLACK}Lawati halaman STR_CONTENT_OPEN_URL_TOOLTIP :{BLACK}Lawati halaman untuk kandungan ini @@ -1986,7 +2005,7 @@ STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD_FILE_NOT_WRITABLE :{WHITE}... fail STR_CONTENT_ERROR_COULD_NOT_EXTRACT :{WHITE}Tidak dapat menyahmampat fail yang dimuat turun STR_MISSING_GRAPHICS_SET_CAPTION :{WHITE}Grafik hilang -STR_MISSING_GRAPHICS_SET_MESSAGE :{BLACK}OpenTTD memerlukan grafik berfungsi tetapi tiada diperolehi. Adakah anda membenarkan OpenTTD untuk memuat turun dan memasang-grafik? +STR_MISSING_GRAPHICS_SET_MESSAGE :{BLACK}OpenTTD memerlukan grafik berfungsi tetapi tiada grafik diperolehi. Adakah anda benarkan OpenTTD untuk memuat turun dan memasang grafik? STR_MISSING_GRAPHICS_YES_DOWNLOAD :{BLACK}Ya, muat turun grafik STR_MISSING_GRAPHICS_NO_QUIT :{BLACK}Tidak, keluar dari OpenTTD @@ -2309,6 +2328,7 @@ STR_LAND_AREA_INFORMATION_AIRPORTTILE_NAME :{BLACK}Nama pet STR_LAND_AREA_INFORMATION_NEWGRF_NAME :{BLACK}NewGRF: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_CARGO_ACCEPTED :{BLACK}Kargo yang diterima: {LTBLUE} STR_LAND_AREA_INFORMATION_CARGO_EIGHTS :({COMMA}/8 {STRING}) +STR_LANG_AREA_INFORMATION_RAIL_TYPE :{BLACK}Jenis landasan: {LTBLUE}{STRING} STR_LANG_AREA_INFORMATION_RAIL_SPEED_LIMIT :{BLACK}Had kelajuan landasan: {LTBLUE}{VELOCITY} # Description of land area of different tiles @@ -2321,28 +2341,28 @@ STR_LAI_CLEAR_DESCRIPTION_SNOW_COVERED_LAND :Tanah diliputi STR_LAI_CLEAR_DESCRIPTION_DESERT :Padang pasir STR_LAI_RAIL_DESCRIPTION_TRACK :Landasan keretapi -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_SIGNALS :Keretapi landasan dengan isyarat sekatan -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRESIGNALS :Keretapi landasan dengan pra-isyarat +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_SIGNALS :Landasan kereta api dengan isyarat sekatan +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRESIGNALS :Landasan kereta api dengan pra-isyarat STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXITSIGNALS :Landasan keretapi dengan isyarat keluar STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBOSIGNALS :Landasan keretapi dengan isyarat kombo -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PBSSIGNALS :Keretapi landasan dengan isyarat laluan +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PBSSIGNALS :Landasan kereta api dengan isyarat laluan STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NOENTRYSIGNALS :Landasan keretapi dengan isyarat satu hala -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_PRESIGNALS :Keretapi landasan dengan isyarat sekatan dan pra-isyarat +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_PRESIGNALS :Landasan kereta api dengan isyarat sekatan dan pra-isyarat STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_EXITSIGNALS :Landasan keretapi dengan isyarat sekatan dan keluar STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_COMBOSIGNALS :Landasan keretapi dengan isyarat sekatan dan kombo -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_PBSSIGNALS :Keretapi landasan dengan isyarat sekatan dan laluan +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_PBSSIGNALS :Landasan kereta api dengan isyarat sekatan dan laluan STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_NOENTRYSIGNALS :Landasan keretapi dengan isyarat sekatan dan satu hala -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_EXITSIGNALS :Keretapi landasan dengan isyarat pra- dan keluar -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_COMBOSIGNALS :Keretapi landasan dengan isyarat pra- dan kombo -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_PBSSIGNALS :Keretapi landasan dengan isyarat pra- dan laluan -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_NOENTRYSIGNALS :Keretapi landasan dengan isyarat pra- dan satu hala +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_EXITSIGNALS :Landasan kereta api dengan pra-isyarat dan isyarat keluar +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_COMBOSIGNALS :Landasan kereta api dengan pra-isyarat dan isyarat kombo +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_PBSSIGNALS :Landasan kereta api dengan pra-isyarat dan isyarat laluan +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_NOENTRYSIGNALS :Landasan kereta api dengan pra-isyarat dan isyarat laluan satu hala STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_COMBOSIGNALS :Landasan keretapi dengan isyarat keluar dan kombo. STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_PBSSIGNALS :Landasan keretapi dengan isyarat keluar dan laluan STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_NOENTRYSIGNALS :Landasan keretapi dengan isyarat keluar dan satu hala STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBO_PBSSIGNALS :Landasan keretapi dengan isyarat kombo dan signal laluan STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBO_NOENTRYSIGNALS :Landasan keretapi dengan isyarat kombo dan satu hala -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PBS_NOENTRYSIGNALS :Keretapi landasan dengan isyarat laluan dan satu hala -STR_LAI_RAIL_DESCRIPTION_TRAIN_DEPOT :Keretapi depoh keretapi +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PBS_NOENTRYSIGNALS :Landasan kereta api dengan isyarat laluan dan isyarat laluan satu hala +STR_LAI_RAIL_DESCRIPTION_TRAIN_DEPOT :Depoh penyelenggaraan kereta api STR_LAI_ROAD_DESCRIPTION_ROAD :Jalanraya STR_LAI_ROAD_DESCRIPTION_ROAD_WITH_STREETLIGHTS :Jalan raya berlampu @@ -2408,6 +2428,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Hakcipta STR_ABOUT_VERSION :{BLACK}OpenTTD versi {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2018 The OpenTTD team +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Simpankan Permainan STR_SAVELOAD_LOAD_CAPTION :{WHITE}Buka Permainan @@ -2555,6 +2582,7 @@ STR_NEWGRF_SETTINGS_INCOMPATIBLE :{RED}Tidak sera # NewGRF save preset window STR_SAVE_PRESET_CAPTION :{WHITE}Simpan pratetapan STR_SAVE_PRESET_TITLE :{BLACK}Masukkan nama untuk pratetapan +STR_SAVE_PRESET_CANCEL :{BLACK}Batal STR_SAVE_PRESET_SAVE :{BLACK}Simpan # NewGRF parameters window @@ -2586,7 +2614,7 @@ STR_SPRITE_ALIGNER_GOTO_TOOLTIP :{BLACK}Pergi ke STR_SPRITE_ALIGNER_PREVIOUS_BUTTON :{BLACK}Peperi sebelumnya STR_SPRITE_ALIGNER_PREVIOUS_TOOLTIP :{BLACK}Teruskan ke peperi dahulu yang biasa, melangkau sebarang peperi pseudo/warna kembali/fon dan memusing balik semula STR_SPRITE_ALIGNER_SPRITE_TOOLTIP :{BLACK}Perwakilan peperi yang terpilih. Penjajaran tidak diendahkan apabila sedang melukiskan peperi. -STR_SPRITE_ALIGNER_MOVE_TOOLTIP :{BLACK}Alih peperi, mengubahkan ofset X dan Y +STR_SPRITE_ALIGNER_MOVE_TOOLTIP :{BLACK}Alihkan "sprite" ke lokasi lain lantas mengubah ofset X dan Y. "Ctrl+Click" untuk ubah lokasi "sprite" lapan unit pada satu-satu masa STR_SPRITE_ALIGNER_PICKER_BUTTON :{BLACK}Pilih peperi STR_SPRITE_ALIGNER_PICKER_TOOLTIP :{BLACK}Pilih peperi di mana-mana sahaja dari skrin @@ -2686,8 +2714,6 @@ STR_TOWN_POPULATION :{BLACK}Jumlah p STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Bandaraya) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Jumlah penduduk: {ORANGE}{COMMA}{BLACK} Rumah: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Penumpang bulan lalu: {ORANGE}{COMMA}{BLACK} maks: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Beg surat bulan lepas: {ORANGE}{COMMA}{BLACK} maks: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Kargi yang diperlukan untuk pembesaran bandar: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} diperlukan STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} diperlukan sewaktu musim sejuk @@ -2782,6 +2808,7 @@ STR_SUBSIDIES_TOOLTIP_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Klik di # Story book window STR_STORY_BOOK_TITLE :{YELLOW}{STRING} +STR_STORY_BOOK_NEXT_PAGE :{BLACK}Seterusnya # Station list window STR_STATION_LIST_TOOLTIP :{BLACK}Nama stesen - klik pada nama untuk memusatkan pemandangan ke stesen. Ctrl+Klik membuka tetingkap pemandangan di lokasi stesen @@ -2808,6 +2835,10 @@ STR_STATION_VIEW_RATINGS_BUTTON :{BLACK}Penarafa STR_STATION_VIEW_RATINGS_TOOLTIP :{BLACK}Tunjukkan penarafan stesen STR_STATION_VIEW_SUPPLY_RATINGS_TITLE :{BLACK}Bekalan bulanan dan penarafan tempatan: +STR_STATION_VIEW_PLANNED_AMOUNT :Jumlah: Telah dirancang +STR_STATION_VIEW_VIA :{YELLOW}{CARGO_SHORT} melalui {STATION} +STR_STATION_VIEW_TO :{YELLOW}{CARGO_SHORT} ke {STATION} +STR_STATION_VIEW_VIA_HERE :{GREEN}{CARGO_SHORT} sedang berhenti di stesen ini ############ range for rating starts @@ -2825,12 +2856,13 @@ STR_STATION_VIEW_CENTER_TOOLTIP :{BLACK}Pusatkan STR_STATION_VIEW_RENAME_TOOLTIP :{BLACK}Tukarkan nama stesen STR_STATION_VIEW_SCHEDULED_TRAINS_TOOLTIP :{BLACK}Tunjukkan semua keretapi yang mengandungi stesen ini dalam jadual mereka -STR_STATION_VIEW_SCHEDULED_ROAD_VEHICLES_TOOLTIP :{BLACK}Tunjukkan semua kenderaan jalanraya yang mengandungi stesen ini dalam jadual mereka +STR_STATION_VIEW_SCHEDULED_ROAD_VEHICLES_TOOLTIP :{BLACK}Tunjukkan semua kenderaan darat yang mempunyai stesen ini di dalam jadual mereka STR_STATION_VIEW_SCHEDULED_AIRCRAFT_TOOLTIP :{BLACK}Tunjukkan semua pesawat yang mengandungi lapangan terbang ini dalam jadual mereka STR_STATION_VIEW_SCHEDULED_SHIPS_TOOLTIP :{BLACK}Tunjukkan semua kapal yang mengandungi stesen ini dalam jadual mereka STR_STATION_VIEW_RENAME_STATION_CAPTION :Namakan semula stesen/ruang punggahan +STR_STATION_VIEW_CLOSE_AIRPORT_TOOLTIP :{BLACK}Halang pesawat daripada mendarat di lapangan terbang ini # Waypoint/buoy view window STR_WAYPOINT_VIEW_CAPTION :{WHITE}{WAYPOINT} @@ -3012,11 +3044,11 @@ STR_GROUP_DEFAULT_ROAD_VEHICLES :Kenderaan jalan STR_GROUP_DEFAULT_SHIPS :Kapal yang belum berkumpulan STR_GROUP_DEFAULT_AIRCRAFTS :Pesawat yang belum berkumpulan -STR_GROUPS_CLICK_ON_GROUP_FOR_TOOLTIP :{BLACK}Kumpulan - klik sebuah kumpulan untuk menaraikan semua kenderaan di dalam kumpulan +STR_GROUPS_CLICK_ON_GROUP_FOR_TOOLTIP :{BLACK}Kumpulan - klik sebuah kumpulan untuk menyenaraikan semua kenderaan di dalam kumpulan tersebut. Tarik dan lepaskan kumpulan untuk menyusun kumpulan mengikut heirarki STR_GROUP_CREATE_TOOLTIP :{BLACK}Klik untuk mewujudkan kumpulan STR_GROUP_DELETE_TOOLTIP :{BLACK}Padamkan kumpulan yang telah dipilih STR_GROUP_RENAME_TOOLTIP :{BLACK}Tukar nama kumpulan yang terpilih -STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Klik untuk menghalang daripada kumpulan ini digantikan secara automatik +STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Klik untuk menghalang kumpulan ini daripada digantikan secara automatik STR_GROUP_ADD_SHARED_VEHICLE :Tambah kenderaan berkongsi @@ -3304,6 +3336,8 @@ STR_VEHICLE_INFO_AGE :{COMMA} tahun ( STR_VEHICLE_INFO_AGE_RED :{RED}{COMMA} tahun ({COMMA}) STR_VEHICLE_INFO_MAX_SPEED :{BLACK}Kelajuan Maks.: {LTBLUE}{VELOCITY} +STR_VEHICLE_INFO_MAX_SPEED_TYPE :{BLACK}Kelajuan maksima: {LTBLUE}{VELOCITY} {BLACK}Jenis pesawat: {LTBLUE}{STRING} +STR_VEHICLE_INFO_MAX_SPEED_TYPE_RANGE :{BLACK}Kelajuan maksima: {LTBLUE}{VELOCITY} {BLACK}Jenis pesawat: {LTBLUE}{STRING} {BLACK}Lingkungan: {LTBLUE}{COMMA} petak STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED :{BLACK}Berat: {LTBLUE}{WEIGHT_SHORT} {BLACK}Kuasa: {LTBLUE}{POWER}{BLACK} Kelajuan Maks.: {LTBLUE}{VELOCITY} STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :{BLACK}Berat: {LTBLUE}{WEIGHT_SHORT} {BLACK}Kuasa: {LTBLUE}{POWER}{BLACK} Max. speed: {LTBLUE}{VELOCITY} {BLACK}T.E. Maks.: {LTBLUE}{FORCE} @@ -3323,6 +3357,7 @@ STR_VEHICLE_DETAILS_SERVICING_INTERVAL_PERCENT :{BLACK}Tempoh P STR_VEHICLE_DETAILS_INCREASE_SERVICING_INTERVAL_TOOLTIP :{BLACK}Tambah 10 tempoh penyenggelaraan. Ctrl+Klik untuk tambah 5 tempoh penyenggelaraan STR_VEHICLE_DETAILS_DECREASE_SERVICING_INTERVAL_TOOLTIP :{BLACK}Kurangkan 10 tempoh penyenggelaraan. Ctrl+Klik untuk kurangkan 5 tempoh penyenggelaraan +STR_VEHICLE_DETAILS_DAYS :Hari STR_VEHICLE_DETAILS_PERCENT :Peratusan STR_QUERY_RENAME_TRAIN_CAPTION :{WHITE}Nama keretapi @@ -3462,7 +3497,7 @@ STR_ORDER_GO_TO_NEAREST_DEPOT :Pergi ke depoh STR_ORDER_GO_TO_NEAREST_HANGAR :Pergi ke hangar paling hampir STR_ORDER_CONDITIONAL :Lompatan arahan bersyarat STR_ORDER_SHARE :Kongsi arahan -STR_ORDERS_GO_TO_TOOLTIP :{BLACK}Masukkan arahan baru ke atas arahan yang terpilih. Ctrl membuatkan arahan stesen 'muatan penuh sebarang kargo', arahan halutuju 'tanpa henti', dan arahn depoh 'penyenggelaraan'. 'Arahan berkongsi' atau Ctrl membenarkan kenderaan ini berkongsi arahan dengan kenderaan terpilih +STR_ORDERS_GO_TO_TOOLTIP :{BLACK}Masukkan arahan baru ke dalam susunan senarai yang terpilih, atau tambah pada penghujung senarai. "Ctrl" mengubah arahan stesen kepada 'muatan penuh untuk apa-apa kargo', arahan halutuju 'tanpa henti', dan arahan depoh 'penyenggelaraan'. 'Arahan berkongsi' atau "Ctrl" membenarkan kenderaan ini berkongsi arahan dengan kenderaan terpilih STR_ORDERS_VEH_WITH_SHARED_ORDERS_LIST_TOOLTIP :{BLACK}Tunjukkan semua kenderaan yang berkongsi jadual yang sama @@ -4079,7 +4114,7 @@ STR_ERROR_AIRCRAFT_NOT_ENOUGH_RANGE :{WHITE}... pesa # Timetable related errors STR_ERROR_CAN_T_TIMETABLE_VEHICLE :{WHITE}Kenderaan tidak boleh dijadualkan... STR_ERROR_TIMETABLE_ONLY_WAIT_AT_STATIONS :{WHITE}Kenderaan hanya boleh menunggu di stesen -STR_ERROR_TIMETABLE_NOT_STOPPING_HERE :{WHITE}Kenderaan ini tidak akan berhenti di stesen ini +STR_ERROR_TIMETABLE_NOT_STOPPING_HERE :{WHITE}Kenderaan ini tidak akan berhenti di stesen berikut # Sign related errors STR_ERROR_TOO_MANY_SIGNS :{WHITE}... papan tanda terlalu banyak @@ -4092,8 +4127,12 @@ STR_DESKTOP_SHORTCUT_COMMENT :Sebuah permaina # Translatable descriptions in media/baseset/*.ob* files STR_BASEGRAPHICS_DOS_DESCRIPTION :Grafik asal Transport Tycoon Deluxe DOS edition. +STR_BASEGRAPHICS_DOS_DE_DESCRIPTION :Grafik asal Transport Tycoon DOS (German) edition STR_BASEGRAPHICS_WIN_DESCRIPTION :Grafik asal Transport Tycoon Deluxe edisi Windows. +STR_BASESOUNDS_WIN_DESCRIPTION :Bunyi asal Transport Tycoon Deluxe edisi Windows +STR_BASESOUNDS_NONE_DESCRIPTION :Sebuah pek suara tanpa apa-apa suara STR_BASEMUSIC_WIN_DESCRIPTION :Muzik asal Transport Tycoon Deluxe edisi Windows. +STR_BASEMUSIC_DOS_DESCRIPTION :Muzik asal Transport Tycoon Deluxe edisi DOS STR_BASEMUSIC_NONE_DESCRIPTION :Pek muzik tanpa muzik sebenar. ##id 0x2000 diff --git a/src/lang/norwegian_bokmal.txt b/src/lang/norwegian_bokmal.txt index dccf73075f..fcb3f7afe9 100644 --- a/src/lang/norwegian_bokmal.txt +++ b/src/lang/norwegian_bokmal.txt @@ -671,10 +671,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Velg pro STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Skru av/på tilfeldig program STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Vis musikkspormeny -STR_ERROR_NO_SONGS :{WHITE}Et musikksett uten sanger er valgt. Ingen sanger vil bli avspilt - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Musikkprogram STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Sporliste STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Program - '{STRING}' @@ -1340,8 +1337,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Farge på terre STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Grønn STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Mørkegrønn STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Fiolett -STR_CONFIG_SETTING_REVERSE_SCROLLING :Snu rulleretningen: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Opptreden ved rulling av kartet med høyre museknapp. Når deaktivert, beveger musen kameraet. Når aktivert, beveger musen kartet STR_CONFIG_SETTING_SMOOTH_SCROLLING :Myk rulling: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Velge hvordan synsfeltet ruller til en bestemt posisjon når du klikker på det lille kartet, eller ved utstedelse av en kommando for å gå til et bestemt objekt på kartet. Hvis aktivert, ruller synsfeltet jevnt, og hvis deaktivert hopper det direkte til det valgte punktet STR_CONFIG_SETTING_MEASURE_TOOLTIP :Vis målingsverktøy ved bruk av byggingsverktøy: {STRING} @@ -1373,8 +1368,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Kommando+klikk STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+klikk STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Av -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Venstre-klikk rulling: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Tillat rulling av kartet ved å dra det med den venstre museknappen. Dette er spesielt nyttig når du bruker en berøringsskjerm STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Lukk vinduet med høyreklikk: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Lukker et vindu ved å høyreklikke i det. Deaktiverer verktøytipset med høyreklikk! @@ -2697,6 +2690,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Opprinne STR_ABOUT_VERSION :{BLACK}OpenTTD versjon {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 OpenTTD-teamet +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Lagre spill STR_SAVELOAD_LOAD_CAPTION :{WHITE}Last inn spill @@ -2988,8 +2988,6 @@ STR_TOWN_POPULATION :{BLACK}Verdensb STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (By) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Innbyggertall: {ORANGE}{COMMA}{BLACK} Antall hus: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Passasjerer forrige måned: {ORANGE}{COMMA}{BLACK} maks: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Post forrige måned: {ORANGE}{COMMA}{BLACK} maks: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Varebehov for byvekst: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} påkrevd STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} nødvendig om vinteren diff --git a/src/lang/norwegian_nynorsk.txt b/src/lang/norwegian_nynorsk.txt index 5e545ce290..aa53408bea 100644 --- a/src/lang/norwegian_nynorsk.txt +++ b/src/lang/norwegian_nynorsk.txt @@ -671,10 +671,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Vel 'Eig STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Skru tilfeldig program av/på STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Syne musikkspormeny -STR_ERROR_NO_SONGS :{WHITE}Eit musikksett utan songar har blitt valt. Ingen songar vil bli spelt - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Musikkprogram STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Sporregister STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Program - '{STRING}' @@ -1311,7 +1308,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Farge på terre STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Grøn STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Mørkegrøn STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Fiolett -STR_CONFIG_SETTING_REVERSE_SCROLLING :Snu rulleretninga: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING :Jamn rulling i tilleggsvindauge: {STRING} STR_CONFIG_SETTING_MEASURE_TOOLTIP :Syne eit målingverktøytips når ymse byggjeverktøy brukast: {STRING} STR_CONFIG_SETTING_LIVERIES :Syne firmaovertakingar: {STRING} @@ -1338,7 +1334,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Kommando+klikk STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :CTRL+klikk STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Av -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Venstreknapps-rulling: {STRING} STR_CONFIG_SETTING_AUTOSAVE :Autolaging: {STRING} STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :Vel intervall for automatisk lagring av spel @@ -2610,6 +2605,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Opphavel STR_ABOUT_VERSION :{BLACK}OpenTTD versjon {REV}. Oversett til nynorsk av Thor Morten Skogrand med fleire. STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 OpenTTD-teamet +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Lagre spel STR_SAVELOAD_LOAD_CAPTION :{WHITE}Last inn spel @@ -2897,8 +2899,6 @@ STR_TOWN_POPULATION :{BLACK}Verdsinn STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (By) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Innbyggjartal: {ORANGE}{COMMA}{BLACK} Antal hus: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Passasjerar førre månad: {ORANGE}{COMMA}{BLACK} maks.: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Post førre månad: {ORANGE}{COMMA}{BLACK} maks.: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Varer naudsynt for folketalsauke: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} naudsynt STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} naudsynt om vinteren diff --git a/src/lang/polish.txt b/src/lang/polish.txt index cc3f06cffe..5825519ef3 100644 --- a/src/lang/polish.txt +++ b/src/lang/polish.txt @@ -1029,6 +1029,7 @@ STR_MUSIC_RULER_MARKER :{TINY_FONT}{BLA STR_MUSIC_TRACK_NONE :{TINY_FONT}{DKGREEN}-- STR_MUSIC_TRACK_DIGIT :{TINY_FONT}{DKGREEN}{ZEROFILL_NUM} STR_MUSIC_TITLE_NONE :{TINY_FONT}{DKGREEN}------ +STR_MUSIC_TITLE_NOMUSIC :{TINY_FONT}{DKGREEN}Brak dostępnej muzyki STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKGREEN}"{STRING}" STR_MUSIC_TRACK :{TINY_FONT}{BLACK}Ścieżka STR_MUSIC_XTITLE :{TINY_FONT}{BLACK}Tytuł @@ -1048,14 +1049,12 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Wybierz STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Losowe odtwarzanie wł./wył. STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Pokaż okno wyboru ścieżek -STR_ERROR_NO_SONGS :{WHITE}Został wybrany zestaw muzyki bez utworów. Żaden utwór nie będzie odtwarzany - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Wybór Programu STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Wykaz ścieżek STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Programuj - '{STRING}' STR_PLAYLIST_CLEAR :{TINY_FONT}{BLACK}Wyczyść +STR_PLAYLIST_CHANGE_SET :{BLACK}Zmień zestaw STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Wyczyść obecny program (tylko Wlasny1 lub Wlasny2) STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}Klik na ścieżce aby dodać do obecnego programu (Wlasny1 i Wlasny2) STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}Kliknij na ścieżce muzycznej aby usunąć ją z wybranego programu (Wlasny1 lub Wlasny2) @@ -1717,8 +1716,9 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Kolor terenu na STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :zielony STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :ciemnozielony STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :fioletowy -STR_CONFIG_SETTING_REVERSE_SCROLLING :Przewijaj obraz myszką w przeciwnym kierunku: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Zachowanie podczas przewijania mapy za pomocą prawego przycisku myszy. W przypadku wyłączenia mysz porusza kamerą. Po włączeniu mysz przesuwa mapę +STR_CONFIG_SETTING_SCROLLMODE_HELPTEXT :Zachowanie podczas przeciągania mapy +STR_CONFIG_SETTING_SCROLLMODE_RMB :Przeciągnij mapę prawym przyciskiem myszy +STR_CONFIG_SETTING_SCROLLMODE_LMB :Przeciągnij mapę lewym przyciskiem myszy STR_CONFIG_SETTING_SMOOTH_SCROLLING :Wygładź przesuwanie widoku: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Zdecyduj, jak główny widok przesuwa się do konkretnej lokacji, gdy klikasz na mini-mapie lub gdy używasz komendy do przesunięcia do danego obiektu na mapie. Kiedy włączone, widok przesuwa się płynnie, kiedy wyłączone, następuje skok bezpośrednio do wybranego miejsca STR_CONFIG_SETTING_MEASURE_TOOLTIP :Pokaż dymek z pomiarem podczas używania różnych narzędzi: {STRING} @@ -1750,8 +1750,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command+klik STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+klik STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Wyłączona -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Przewijanie lewym przyciskiem myszy: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Włącz przewijanie mapy przeciąganiem lewym przyciskiem myszki. Jest to przydatne podczas używania ekranu dotykowego do przewijania STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Zamknij okno prawym przyciskiem: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Zamyka okno poprzez kliknięcie prawym przyciskiem. Wyłącza pomoc kontekstową! @@ -3073,6 +3071,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Prawa Au STR_ABOUT_VERSION :{BLACK}OpenTTD wersja {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2018 Zespół OpenTTD +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Zapisz grę STR_SAVELOAD_LOAD_CAPTION :{WHITE}Wczytaj grę @@ -3364,8 +3369,7 @@ STR_TOWN_POPULATION :{BLACK}Populacj STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Miasto) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Populacja: {ORANGE}{COMMA}{BLACK} Domów: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Pasażerów w zeszłym miesiącu: {ORANGE}{COMMA}{BLACK} maks: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Poczta w zeszłym miesiącu: {ORANGE}{COMMA}{BLACK} maks: {ORANGE}{COMMA} +STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX :{BLACK}{CARGO_LIST} w ostatnim miesiącu: {ORANGE}{COMMA}{BLACK} najwięcej: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Towar potrzebny do rozwoju miasta: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{RED}Wymagana {ORANGE}{STRING} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} wymagane zimą @@ -4618,6 +4622,7 @@ 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... diff --git a/src/lang/portuguese.txt b/src/lang/portuguese.txt index 65ad9c6661..b071b9c185 100644 --- a/src/lang/portuguese.txt +++ b/src/lang/portuguese.txt @@ -670,10 +670,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Seleccio STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Ligar/Desligar programa aleatório STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Mostrar janela de selecção de faixas de música -STR_ERROR_NO_SONGS :{WHITE}Um conjunto de música vazio foi seleccionado. Nenhuma música vai ser tocada. - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Programação Musical STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} '{STRING}' STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Índice de faixas STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Programa - '{STRING}' @@ -1338,8 +1335,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Cor do terreno STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Verde STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Verde Escuro STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Violeta -STR_CONFIG_SETTING_REVERSE_SCROLLING :Ao deslizar com o rato, mover a vista na direcção oposta: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Comportamento ao navegar pelo mapa com o botão direito do rato. Quando desactivado, o rato move a câmara. Quando activo, o rato move o mapa STR_CONFIG_SETTING_SMOOTH_SCROLLING :Suavizar deslocamento da navegação no mapa: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Controla como a vista principal navega para uma posição específica ao clicar no mapa pequeno ou ao dar um comando para navegar para um objecto específico no mapa. Se activo, a vista principal navega suavemente, se inactivo a vista salta directamente para o destino. STR_CONFIG_SETTING_MEASURE_TOOLTIP :Mostrar medidas nas várias ferramentas de construção: {STRING} @@ -1371,8 +1366,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND : + Cli STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL : + clique STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Desligado -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Deslocar com botão esquerdo: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Activar deslocamento do mapa através de arrastamento com o botão esquerdo do rato. Esta opção é particularmente útil quando é usado um ecran de toque para deslocamento STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Fechar janelas ao fazer clique direito: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Fecha uma janela ao fazer clique direito dentro dela. Desactiva os textos de ajuda ao fazer clique direito! @@ -2694,6 +2687,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Direitos STR_ABOUT_VERSION :{BLACK}OpenTTD versão {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 A equipa do OpenTTD +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Guardar Jogo STR_SAVELOAD_LOAD_CAPTION :{WHITE}Abrir Jogo @@ -2985,8 +2985,6 @@ STR_TOWN_POPULATION :{BLACK}Populaç STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Metrópole) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}População: {ORANGE}{COMMA}{BLACK} Casas: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Passageiros no último mês: {ORANGE}{COMMA}{BLACK} máx: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Correio no último mês: {ORANGE}{COMMA}{BLACK} máx: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Mercadoria necessária para o seu desenvolvimento: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{RED}É necessário {ORANGE}{STRING} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{BLACK}No inverno, é necessário {ORANGE}{STRING} diff --git a/src/lang/romanian.txt b/src/lang/romanian.txt index a2aa17927e..2693346136 100644 --- a/src/lang/romanian.txt +++ b/src/lang/romanian.txt @@ -669,10 +669,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Selectea STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Comutator pentru amestecarea melodiilor (pornit/oprit) STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Afişeaza fereastra pentru selecţia melodiilor -STR_ERROR_NO_SONGS :{WHITE}A fost selectat un set de muzică fără melodii. Nici o melodie nu va fi cântată - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Programare piese muzicale STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Lista melodiilor STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Program - '{STRING}' @@ -1322,8 +1319,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Culoarea terenu STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Verde STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Verde închis STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Mov -STR_CONFIG_SETTING_REVERSE_SCROLLING :Inversează direcţia de scroll: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Modul de funcționare in momentul folosirii butonului drept al mouse-ului pentru deplasare pe hartă. Când opțiunea este dezactivată, mouse-ul schimbă poziția camerei. La activare, mouse-ul desplasează harta. STR_CONFIG_SETTING_SMOOTH_SCROLLING :Derulare uşoară ecran: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Controlează modul de deplasare a imaginii din ecranul principal când se face click pe harta mică sau când se execută o comandă de deplasare către un obiect anume de pe hartă. Dacă este activată, imaginea se deplasează în mod fluid, altfel imaginea sare direct la zona dorită STR_CONFIG_SETTING_MEASURE_TOOLTIP :Arată o indicaţie de distanţă la folosirea uneltelor de construcţie: {STRING} @@ -1355,8 +1350,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Comandă+Click STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Control+Click STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Oprit -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Derulare ecran cu click-stânga: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Activează derularea hărții prin tragerea acesteia cu butonul stâng al mouse-ului. Această opțiune este în special utilă când se folosește un ecran tactil pentru deplasare STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES :Foloseşte formatul datei {STRING} pentru numele salvărilor @@ -2654,6 +2647,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Copyrigh STR_ABOUT_VERSION :{BLACK}OpenTTD versiunea {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 Echipa OpenTTD +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Salvează joc STR_SAVELOAD_LOAD_CAPTION :{WHITE}Încarcă joc @@ -2939,8 +2939,6 @@ STR_TOWN_POPULATION :{BLACK}Populaţ STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Metropolă) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Populaţia: {ORANGE}{COMMA}{BLACK} Locuinţe: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Călători luna trecută: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Colete poştale luna trecută: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Transporturi necesare dezvoltării oraşului: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} necesare STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} necesare iarna diff --git a/src/lang/russian.txt b/src/lang/russian.txt index 45b3be2c6d..742639720f 100644 --- a/src/lang/russian.txt +++ b/src/lang/russian.txt @@ -788,8 +788,9 @@ STR_MUSIC_RULER_MARKER :{TINY_FONT}{BLA STR_MUSIC_TRACK_NONE :{TINY_FONT}{DKGREEN}-- STR_MUSIC_TRACK_DIGIT :{TINY_FONT}{DKGREEN}{ZEROFILL_NUM} STR_MUSIC_TITLE_NONE :{TINY_FONT}{DKGREEN}------ +STR_MUSIC_TITLE_NOMUSIC :{TINY_FONT}{DKGREEN}Музыкальное оформление недоступно STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKGREEN}«{STRING}» -STR_MUSIC_TRACK :{TINY_FONT}{BLACK}Дорожка +STR_MUSIC_TRACK :{TINY_FONT}{BLACK}Трек STR_MUSIC_XTITLE :{TINY_FONT}{BLACK}Название STR_MUSIC_SHUFFLE :{TINY_FONT}{BLACK}Случ. выбор STR_MUSIC_PROGRAM :{TINY_FONT}{BLACK}Программа @@ -807,17 +808,17 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Выбо STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Вкл./Выкл. случайный выбор программы STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Показать окно выбора музыкальных треков -STR_ERROR_NO_SONGS :{WHITE}В выбранном музыкальном наборе отсутствует музыка. - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Выбор программы воспроизведения +STR_PLAYLIST_MUSIC_SELECTION_SETNAME :{WHITE}Музыкальная программа - '{STRING}' STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} «{STRING}» STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Номер трека STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Программа - «{STRING}» STR_PLAYLIST_CLEAR :{TINY_FONT}{BLACK}Очистить +STR_PLAYLIST_CHANGE_SET :{BLACK}Изменить набор STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Очистка пользовательской программы +STR_PLAYLIST_TOOLTIP_CHANGE_SET :{BLACK}Сменить выбор музыкального оформления на другой установленный набор STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}Щёлкните по названию трека для добавления в пользовательскую программу -STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}Выберите дорожку для удаления из пользовательского списка +STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}Выберите трек для удаления из пользовательского списка # Highscore window STR_HIGHSCORE_TOP_COMPANIES_WHO_REACHED :{BIG_FONT}{BLACK}Крупнейшие компании, достигшие {NUM} года @@ -1025,9 +1026,9 @@ STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION :{BIG_FONT}{BLAC # Extra view window STR_EXTRA_VIEW_PORT_TITLE :{WHITE}Окно просмотра {COMMA} -STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Скопировать в окно -STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN_TT :{BLACK}Скопировать текущую позицию в окно просмотра -STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Вставить из окна +STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Из основного окна +STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN_TT :{BLACK}Показать то, что отображается в основном окне +STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}В основное окно STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT :{BLACK}Показать в основном окне # Game options window @@ -1072,13 +1073,13 @@ STR_GAME_OPTIONS_CURRENCY_GEL :Грузинс STR_GAME_OPTIONS_CURRENCY_IRR :Иранский риал (IRR) ############ end of currency region -STR_GAME_OPTIONS_ROAD_VEHICLES_FRAME :{BLACK}Направление движения -STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_TOOLTIP :{BLACK}По какой стороне дороги ездит автотранспорт -STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :левостороннее -STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :правостороннее +STR_GAME_OPTIONS_ROAD_VEHICLES_FRAME :{BLACK}Движение автомобилей +STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_TOOLTIP :{BLACK}Сторона дороги, по которой ездит автотранспорт +STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Левостороннее +STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :Правостороннее STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Названия городов -STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}На каком языке будут названы населённые пункты +STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}Язык, который будет использоваться для выбора названий населённых пунктов ############ start of townname region STR_GAME_OPTIONS_TOWN_NAME_ORIGINAL_ENGLISH :Английские @@ -1173,7 +1174,7 @@ STR_CURRENCY_DECREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP :{BLACK}Пере STR_CURRENCY_INCREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP :{BLACK}Перейти на евро позже STR_CURRENCY_PREVIEW :{LTBLUE}Образец: {ORANGE}{CURRENCY_LONG} -STR_CURRENCY_CUSTOM_CURRENCY_PREVIEW_TOOLTIP :{BLACK}10000 англ. фунтов (£) в вашей валюте +STR_CURRENCY_CUSTOM_CURRENCY_PREVIEW_TOOLTIP :{BLACK}10{NBSP}000 фунтов стерлингов (£) в вашей валюте STR_CURRENCY_CHANGE_PARAMETER :{BLACK}Изменить параметр валюты STR_DIFFICULTY_LEVEL_SETTING_MAXIMUM_NO_COMPETITORS :{LTBLUE}Максимальное количество конкурентов: {ORANGE}{COMMA} @@ -1257,7 +1258,7 @@ STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}Тип: STR_CONFIG_SETTING_RESTRICT_DROPDOWN_HELPTEXT :{BLACK}Отображать в списке только настройки, соответствующие выбранной категории STR_CONFIG_SETTING_RESTRICT_BASIC :Основные настройки (только самые важные) STR_CONFIG_SETTING_RESTRICT_ADVANCED :Расширенные настройки (практически все) -STR_CONFIG_SETTING_RESTRICT_ALL :Специальные настройки (все, включая самые непонятные) +STR_CONFIG_SETTING_RESTRICT_ALL :Все настройки (включая самые непонятные) STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_DEFAULT :Настройки со значениями, отличающимися от значений по умолчанию STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_NEW :Настройки со значениями, отличающимися от настроек новой игры @@ -1489,9 +1490,13 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Цвет лан STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :зелёный STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :тёмно-зелёный STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :фиолетовый -STR_CONFIG_SETTING_REVERSE_SCROLLING :Обратить направление перемещения обзора мышью: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Настройка смещения обзора правой кнопкой мыши.{}Если отключено, мышь двигает камеру.{}Если включено, мышь двигает карту. -STR_CONFIG_SETTING_SMOOTH_SCROLLING :Плавное смещение обзора: {STRING} +STR_CONFIG_SETTING_SCROLLMODE :Перемещение обзора: {STRING} +STR_CONFIG_SETTING_SCROLLMODE_HELPTEXT :Способ перемещения по игровому полю +STR_CONFIG_SETTING_SCROLLMODE_DEFAULT :Перемещать с помощью ПКМ, зафиксировав курсор +STR_CONFIG_SETTING_SCROLLMODE_RMB_LOCKED :Перемещать с помощью ПКМ, зафиксировав курсор +STR_CONFIG_SETTING_SCROLLMODE_RMB :Перемещать с помощью ПКМ +STR_CONFIG_SETTING_SCROLLMODE_LMB :Перемещать с помощью ЛКМ +STR_CONFIG_SETTING_SMOOTH_SCROLLING :Плавное перемещение: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Настройка перемещения обзора в основном окне при щелчке по миникарте или по команде обзора какого-нибудь объекта. Если включено, то обзор смещается плавно; если отключено - то мгновенно. STR_CONFIG_SETTING_MEASURE_TOOLTIP :Показывать замеры при строительстве: {STRING} STR_CONFIG_SETTING_MEASURE_TOOLTIP_HELPTEXT :Показывать расстояния и разницу высот при строительстве @@ -1500,8 +1505,8 @@ STR_CONFIG_SETTING_LIVERIES_HELPTEXT :Включит STR_CONFIG_SETTING_LIVERIES_NONE :нет STR_CONFIG_SETTING_LIVERIES_OWN :только для своей компании STR_CONFIG_SETTING_LIVERIES_ALL :для всех компаний -STR_CONFIG_SETTING_PREFER_TEAMCHAT :Открывать командный чат при нажатии Enter: {STRING} -STR_CONFIG_SETTING_PREFER_TEAMCHAT_HELPTEXT :Настроить внутрикорпоративный чат на клавишу «Enter», а общий - на «Ctrl+Enter» +STR_CONFIG_SETTING_PREFER_TEAMCHAT :Использовать Enter для командного чата: {STRING} +STR_CONFIG_SETTING_PREFER_TEAMCHAT_HELPTEXT :Использовать «Enter» для командного чата, а «Ctrl+Enter» - для общего STR_CONFIG_SETTING_SCROLLWHEEL_SCROLLING :Использовать колесо прокрутки: {STRING} STR_CONFIG_SETTING_SCROLLWHEEL_SCROLLING_HELPTEXT :Можно настроить смещение обзора с помощью качающегося колеса прокрутки STR_CONFIG_SETTING_SCROLLWHEEL_ZOOM :для масштабирования @@ -1522,8 +1527,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Команд. STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Контрол. STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Выкл. -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Смещение обзора по нажатию левой кнопки мыши: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Смещение обзора левой кнопкой мыши. Это удобно при использовании сенсорного экрана. STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Закрывать окна щелчком ПКМ: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Закрывать окно щелчком правой кнопкой мыши в его пределах. При этом отключается появление подсказок по правой кнопке. @@ -1778,7 +1781,7 @@ STR_CONFIG_SETTING_LINKGRAPH_ACCURACY_HELPTEXT :Чем выше STR_CONFIG_SETTING_DEMAND_DISTANCE :Зависимость спроса от расстояния: {STRING} STR_CONFIG_SETTING_DEMAND_DISTANCE_HELPTEXT :Если это значение больше 0, то количество груза, отправляемого с одной станции на другую, будет зависеть от расстояния между станциями. Чем выше это значение, тем больше груза будет отправляться к ближним станциям и меньше{NBSP}- к дальним. STR_CONFIG_SETTING_DEMAND_SIZE :Количество возвращаемого груза при симметричном распределении: {STRING} -STR_CONFIG_SETTING_DEMAND_SIZE_HELPTEXT :Установка этого значения ниже 100% заставит распределение быть менее «симметричным»: количество возвращаемого груза сможет быть меньше, чем количество отправленного. Установка в 0% сделает распределение полностью несимметричным. +STR_CONFIG_SETTING_DEMAND_SIZE_HELPTEXT :Установка этого значения ниже 100% заставит распределение быть менее «симметричным»: количество возвращаемого груза сможет быть меньше, чем количество отправленного. Установка в 0% сделает распределение полностью асимметричным. STR_CONFIG_SETTING_SHORT_PATH_SATURATION :Предел загрузки коротких маршрутов перед использованием вместительных: {STRING} STR_CONFIG_SETTING_SHORT_PATH_SATURATION_HELPTEXT :При наличии нескольких маршрутов между станциями алгоритм распределения грузов будет использовать кратчайший маршрут до его загрузки, потом следующий по длине и т.{NBSP}д. При избытке груза маршруты будут перегружаться начиная с самых производительных. Загрузка рассчитывается исходя из оценки пропускной способности (которая может быть неточной) и интенсивности использования. Эта настройка определяет, насколько загружать маршрут перед тем, как начать использовать следующий. Установите значение ниже 100% для того, чтобы избежать задержки груза, если пропускная способность маршрута будет переоценена алгоритмом. @@ -2453,6 +2456,7 @@ STR_LINKGRAPH_LEGEND_CAPTION :{BLACK}Схем STR_LINKGRAPH_LEGEND_ALL :{BLACK}Все STR_LINKGRAPH_LEGEND_NONE :{BLACK}Нет STR_LINKGRAPH_LEGEND_SELECT_COMPANIES :{BLACK}Выберите компании для отображения +STR_LINKGRAPH_LEGEND_COMPANY_TOOLTIP :{BLACK}{STRING}{}{COMPANY} # Linkgraph legend window and linkgraph legend in smallmap STR_LINKGRAPH_LEGEND_UNUSED :{TINY_FONT}{BLACK}неиспольз. @@ -2873,6 +2877,22 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Ориг STR_ABOUT_VERSION :{BLACK}OpenTTD версия {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 Команда разработчиков OpenTTD +# Framerate display window +STR_FRAMERATE_CAPTION_SMALL :{STRING}{WHITE} ({DECIMAL}x) +STR_FRAMERATE_MS_GOOD :{LTBLUE}{DECIMAL}{WHITE} мс +STR_FRAMERATE_MS_WARN :{YELLOW}{DECIMAL}{WHITE} мс +STR_FRAMERATE_MS_BAD :{RED}{DECIMAL}{WHITE} мс +STR_FRAMERATE_FPS_GOOD :{LTBLUE}{DECIMAL}{WHITE} кадр{P "" а ов}/с +STR_FRAMERATE_FPS_WARN :{YELLOW}{DECIMAL}{WHITE} кадр{P "" а ов}/с +STR_FRAMERATE_FPS_BAD :{RED}{DECIMAL}{WHITE} кадр{P "" а ов}/с +STR_FRAMERATE_GRAPH_MILLISECONDS :{TINY_FONT}{COMMA} мс +STR_FRAMERATE_GRAPH_SECONDS :{TINY_FONT}{COMMA} с +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Сохранить игру STR_SAVELOAD_LOAD_CAPTION :{WHITE}Загрузить игру @@ -3157,15 +3177,15 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Введ STR_TOWN_DIRECTORY_CAPTION :{WHITE}Города STR_TOWN_DIRECTORY_NONE :{ORANGE}- Нет - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Список городов - щелчок по названию показывает город в основном окне. Ctrl+щелчок показывает в дополнительном окне. +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Мегаполис){BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Список городов. Щелчок по названию показывает город в основном окне. Ctrl+щелчок показывает в дополнительном окне. STR_TOWN_POPULATION :{BLACK}Население: {COMMA} # Town view window STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Мегаполис) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Население: {ORANGE}{COMMA}{BLACK} Зданий: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Пассажиров в прошлом месяце: {ORANGE}{COMMA}{BLACK}; макс.: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Почты в прошлом месяце: {ORANGE}{COMMA}{BLACK}; макс.: {ORANGE}{COMMA} +STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX :{BLACK}{CARGO_LIST} в прошлом месяце: {ORANGE}{COMMA}{BLACK} Макс.: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Груз, необходимый для роста города: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} требу{G 0 е е е ю}тся STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} требу{G 0 е е е ю}тся зимой @@ -4422,6 +4442,7 @@ 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}Невозможно удалить часть станции... @@ -4490,7 +4511,7 @@ STR_ERROR_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}Недо STR_ERROR_MUST_REMOVE_SIGNALS_FIRST :{WHITE}Сначала удалите сигналы STR_ERROR_NO_SUITABLE_RAILROAD_TRACK :{WHITE}Нет подходящих рельсов STR_ERROR_MUST_REMOVE_RAILROAD_TRACK :{WHITE}Сначала удалите рельсы -STR_ERROR_CROSSING_ON_ONEWAY_ROAD :{WHITE}Дорога односторонняя или блокирована +STR_ERROR_CROSSING_ON_ONEWAY_ROAD :{WHITE}Дорога односторонняя или заблокирована STR_ERROR_CROSSING_DISALLOWED :{WHITE}Через этот вид рельсов запрещено строить переезды STR_ERROR_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Здесь невозможно поставить сигнал... STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Здесь невозможно проложить рельсы... @@ -4666,13 +4687,15 @@ STR_ERROR_CAN_T_DELETE_SIGN :{WHITE}Не у STR_DESKTOP_SHORTCUT_COMMENT :Экономический симулятор на основе игры «Transport Tycoon Deluxe» # Translatable descriptions in media/baseset/*.ob* files -STR_BASEGRAPHICS_DOS_DESCRIPTION :Оригинальная графика из Transport Tycoon Deluxe для DOS. -STR_BASEGRAPHICS_DOS_DE_DESCRIPTION :Оригинальная графика из немецкой версии Transport Tycoon Deluxe для DOS. -STR_BASEGRAPHICS_WIN_DESCRIPTION :Оригинальная графика из Transport Tycoon Deluxe для Windows. -STR_BASESOUNDS_DOS_DESCRIPTION :Оригинальный набор звукового оформления из игры Transport Tycoon Deluxe для DOS. -STR_BASESOUNDS_WIN_DESCRIPTION :Оригинальный набор звукового оформления из игры Transport Tycoon Deluxe для Windows. +STR_BASEGRAPHICS_DOS_DESCRIPTION :Графика из Transport Tycoon Deluxe для DOS. +STR_BASEGRAPHICS_DOS_DE_DESCRIPTION :Графика из немецкой версии Transport Tycoon Deluxe для DOS. +STR_BASEGRAPHICS_WIN_DESCRIPTION :Графика из Transport Tycoon Deluxe для Windows. +STR_BASESOUNDS_DOS_DESCRIPTION :Набор звукового оформления из игры Transport Tycoon Deluxe для DOS. +STR_BASESOUNDS_WIN_DESCRIPTION :Набор звукового оформления из игры Transport Tycoon Deluxe для Windows. STR_BASESOUNDS_NONE_DESCRIPTION :"Пустой" набор звукового оформления, не содержащий никаких звуков. -STR_BASEMUSIC_WIN_DESCRIPTION :Оригинальный набор музыкального оформления из игры Transport Tycoon Deluxe для Windows. +STR_BASEMUSIC_WIN_DESCRIPTION :Набор музыкального оформления из игры Transport Tycoon Deluxe для Windows. +STR_BASEMUSIC_DOS_DESCRIPTION :Набор музыкального оформления из игры Transport Tycoon Deluxe для DOS. +STR_BASEMUSIC_TTO_DESCRIPTION :Набор музыкального оформления из игры Transport Tycoon Deluxe для DOS. STR_BASEMUSIC_NONE_DESCRIPTION :"Пустой" набор музыкального оформления, не содержащий никакой музыки. ##id 0x2000 diff --git a/src/lang/serbian.txt b/src/lang/serbian.txt index 155772ce5d..eeaa8a4141 100644 --- a/src/lang/serbian.txt +++ b/src/lang/serbian.txt @@ -838,6 +838,7 @@ STR_MUSIC_RULER_MARKER :{TINY_FONT}{BLA STR_MUSIC_TRACK_NONE :{TINY_FONT}{DKGREEN}-- STR_MUSIC_TRACK_DIGIT :{TINY_FONT}{DKGREEN}{ZEROFILL_NUM} STR_MUSIC_TITLE_NONE :{TINY_FONT}{DKGREEN}------ +STR_MUSIC_TITLE_NOMUSIC :{TINY_FONT} {DKGREEN} Nije dostupna muzika STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKGREEN}"{STRING}" STR_MUSIC_TRACK :{TINY_FONT}{BLACK}Numera STR_MUSIC_XTITLE :{TINY_FONT}{BLACK}Naziv @@ -857,15 +858,15 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Izaberi STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Uključi/isključi nasumičan izbor pri puštanju STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Prikaži prozor za izbor muzičkih numera -STR_ERROR_NO_SONGS :{WHITE}Izabran je skup muzike bez ijedne numere. Neće biti puštena nikakva muzika - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Izbor muzičkog programa +STR_PLAYLIST_MUSIC_SELECTION_SETNAME :{WHITE} Muzički program - '{STRING}' STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Indeks numera STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Program - '{STRING}' STR_PLAYLIST_CLEAR :{TINY_FONT}{BLACK}Obriši +STR_PLAYLIST_CHANGE_SET :{BLACK}Promeni set STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Obriši tekući program (samo korisnički-definisani programi) +STR_PLAYLIST_TOOLTIP_CHANGE_SET :{BLACK}Promenite izbor muzike na drugi instalirani skup STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}Klik na numeru je dodaje u tekući program (samo za korisnički-definisane programe) STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}Pritisnite na muzičku numeru kako biste je uklonili sa trenutnog rasporeda (samo za Custom1 ili Custom2) @@ -1075,10 +1076,10 @@ STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION :{BIG_FONT}{BLAC # Extra view window STR_EXTRA_VIEW_PORT_TITLE :{WHITE}Pogled{COMMA} -STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Premesti u pogled +STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK} Kopiraj u prozor za pogled STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN_TT :{BLACK}Premešta pogled na trenutnu poziciju glavnog pogleda -STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Prebaci se -STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT :{BLACK}Premešta glavni pogled na lokaciju na kojoj je ovaj pogled +STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Promenite glavni prikaz +STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT :{BLACK}Kopirajte lokaciju prozora za prikaz u glavnom prikazu # Game options window STR_GAME_OPTIONS_CAPTION :{WHITE}Opcije @@ -1532,8 +1533,12 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Boja terena na STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Zelena STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Tamno zelena STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Ljubičasta -STR_CONFIG_SETTING_REVERSE_SCROLLING :Suprotan smer pomeranja prozora: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Ponašanje kod skrolovanja karte desnim dugmetom miša. Kada je isključeno, miš pomiče kameru. Kada je uključeno, miš pomiče kartu +STR_CONFIG_SETTING_SCROLLMODE :Ponašanje listanja pogleda: {STRING} +STR_CONFIG_SETTING_SCROLLMODE_HELPTEXT :Ponašanje prilikom skrolovanje mape +STR_CONFIG_SETTING_SCROLLMODE_DEFAULT :Pomerite pogled sa desnim tasterom miša, položaj miša zaključan +STR_CONFIG_SETTING_SCROLLMODE_RMB_LOCKED :Pomerite mapu sa desnim tasterom miša, zaključajte položaj miša +STR_CONFIG_SETTING_SCROLLMODE_RMB :Pomerite mapu pomoću desne tipke miša +STR_CONFIG_SETTING_SCROLLMODE_LMB :Pomerite mapu pomoću levog miša STR_CONFIG_SETTING_SMOOTH_SCROLLING :Ravnomeran prelaz prozora: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Odredi kako se glavni prikaz pomiče na određeno mesto kada se klikne na malu kartu ili kada se daje naredba za pomicanje na određeni objekat na karti. Ako je omogućeno, prikaz se pomiče glatko, ako je onemogućeno, prikaz izravno skače na ciljano mesto STR_CONFIG_SETTING_MEASURE_TOOLTIP :Prikazivati mere dok se koriste alati za gradnju: {STRING} @@ -1565,8 +1570,8 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command+Klik STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+Klik STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Nikakvo -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Pomeranje sa levim klikom: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Omogući skrolovanje po mapi povlačenjem mape sa levim dugmetom miša. Ovo je posebno korisno kod skrolovanja na ekranima na dodir +STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Zatvori prozor pomoću desnog klika: {STRING} +STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Zatvara prozor tako što klikne desnim klikom unutar nje. Onemogućava dodir sa desnim tasterom miša! STR_CONFIG_SETTING_AUTOSAVE :Autočuvanje: {STRING} STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :Izbor vremenskog intervala između dve automatski sačuvane pozicije @@ -2477,6 +2482,7 @@ STR_LINKGRAPH_LEGEND_CAPTION :{BLACK}Legenda STR_LINKGRAPH_LEGEND_ALL :{BLACK}Sve STR_LINKGRAPH_LEGEND_NONE :{BLACK}Nema STR_LINKGRAPH_LEGEND_SELECT_COMPANIES :{BLACK}Odaberite preduzeća koja želite da se prikažu +STR_LINKGRAPH_LEGEND_COMPANY_TOOLTIP :{BLACK}{STRING}{}{COMPANY} # Linkgraph legend window and linkgraph legend in smallmap STR_LINKGRAPH_LEGEND_UNUSED :{TINY_FONT}{BLACK}neiskorišćen @@ -2784,6 +2790,7 @@ STR_LAND_AREA_INFORMATION_AIRPORTTILE_NAME :{BLACK}Naziv de STR_LAND_AREA_INFORMATION_NEWGRF_NAME :{BLACK}NewGRF: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_CARGO_ACCEPTED :{BLACK}Tovar prihvaćen: {LTBLUE} STR_LAND_AREA_INFORMATION_CARGO_EIGHTS :({COMMA}/8 {STRING}) +STR_LANG_AREA_INFORMATION_RAIL_TYPE :{BLACK}Tip šine: {LTBLUE}{STRING} STR_LANG_AREA_INFORMATION_RAIL_SPEED_LIMIT :{BLACK}Najveća brzina na pruzi: {LTBLUE}{VELOCITY} STR_LANG_AREA_INFORMATION_ROAD_SPEED_LIMIT :{BLACK}Ograničenje brzine: {LTBLUE}{VELOCITY} @@ -2796,29 +2803,29 @@ STR_LAI_CLEAR_DESCRIPTION_FIELDS :Polja STR_LAI_CLEAR_DESCRIPTION_SNOW_COVERED_LAND :Snegom prekrivena zemlja STR_LAI_CLEAR_DESCRIPTION_DESERT :Pustinja -STR_LAI_RAIL_DESCRIPTION_TRACK :Železnica kolosek -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_SIGNALS :Železnica kolosek sa blok signalizacijom -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRESIGNALS :Železnica kolosek sa predsignalizacijom -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXITSIGNALS :Železnica kolosek sa izlaznom signalizacijom -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBOSIGNALS :Železnica kolosek sa kombinovanom signalizacijom -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PBSSIGNALS :Železnica kolosek sa putnom signalizacijom -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NOENTRYSIGNALS :Železnica kolosek sa jednosmernom putnom signalizacijom -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_PRESIGNALS :Železnica kolosek sa blok i predsignalizacijom -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_EXITSIGNALS :Železnica kolosek sa blok i izlaznom signalizacijom -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_COMBOSIGNALS :Železnica kolosek sa blok i kombinovanom signalizacijom -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_PBSSIGNALS :Železnica kolosek sa blok i putnom signalizacijom -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_NOENTRYSIGNALS :Železnica kolosek sa blok i jednosmernom putnom signalizacijom -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_EXITSIGNALS :Železnica kolosek sa pred i izlaznom signalizacijom -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_COMBOSIGNALS :Železnica kolosek sa pred i kombinovanom signalizacijom -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_PBSSIGNALS :Železnica kolosek sa pred i putnom signalizacijom -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_NOENTRYSIGNALS :Železnica kolosek sa pred i jednosmernom putnom signalizacijom -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_COMBOSIGNALS :Železnica kolosek sa izlaznom i kombinovanom signalizacijom -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_PBSSIGNALS :Železnica kolosek sa izlaznom i putnom signalizacijom -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_NOENTRYSIGNALS :Železnica kolosek sa izlaznom i jednosmernom putnom signalizacijom -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBO_PBSSIGNALS :Železnica kolosek sa kombinovanom i putnom signalizacijom -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBO_NOENTRYSIGNALS :Železnica kolosek sa kombinovanom i jednosmernom putnom signalizacijom -STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PBS_NOENTRYSIGNALS :Železnica kolosek sa putnom i jednosmernom putnom signalizacijom -STR_LAI_RAIL_DESCRIPTION_TRAIN_DEPOT :Železnica železnički depo +STR_LAI_RAIL_DESCRIPTION_TRACK :Željeznički put +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_SIGNALS :Željeznički put sa blok signalima +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRESIGNALS :Željeznički put sa pred-signalima +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXITSIGNALS :Železnički put sa izlaznom signalizacijom +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBOSIGNALS :Željeznički put sa kombinovanim signalima +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PBSSIGNALS :Železnički put sa putnom signalizacijom +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NOENTRYSIGNALS :Železnički put sa jednosmernim signalima +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_PRESIGNALS :Železnički put sa blokom i pred-signalima +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_EXITSIGNALS :Željeznički put sa blokovnim i izlaznim signalima +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_COMBOSIGNALS :Željeznički put sa blokovnim i kombinovanim signalima +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_PBSSIGNALS :Železnički put sa signalizacijom izlaza i puta +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_NOENTRYSIGNALS :Železnički put sa blokom i pred-signalima +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_EXITSIGNALS :Željeznički put sa pred-i izlaznim signalima +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_COMBOSIGNALS :Željeznički put sa pred- i kombo-signalima +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_PBSSIGNALS :Željeznički put sa pre- i putnom signalizacijom +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_NOENTRYSIGNALS :Željeznički put sa signalima pre i jednosmernog puta +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_COMBOSIGNALS :Železnički put sa izlaznim i kombo-signalima +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_PBSSIGNALS :Železnički put sa signalizacijom izlaza i puta +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_NOENTRYSIGNALS :Železnički put sa izlaznim i jednosmernim signalima +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBO_PBSSIGNALS :Željeznički put sa kombinovanim i putnim signalima +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBO_NOENTRYSIGNALS :Željeznički put sa kombinovanim i jednosmernim signalima +STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PBS_NOENTRYSIGNALS :Železnički put sa putnim i jednosmernim signalima +STR_LAI_RAIL_DESCRIPTION_TRAIN_DEPOT :Vozni park željeznice STR_LAI_ROAD_DESCRIPTION_ROAD :Put STR_LAI_ROAD_DESCRIPTION_ROAD_WITH_STREETLIGHTS :Kolovoz sa uličnom rasvetom @@ -2884,6 +2891,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Original STR_ABOUT_VERSION :{BLACK}OpenTTD verzija {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 OpenTTD tim +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Sačuvaj poziciju STR_SAVELOAD_LOAD_CAPTION :{WHITE}Učitavanje Partije @@ -3168,6 +3182,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Unos naz STR_TOWN_DIRECTORY_CAPTION :{WHITE}Naselja STR_TOWN_DIRECTORY_NONE :{ORANGE}- Prazno - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (City){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Imena naselja - klikom na ime se centrira glavni pogled na to naselje. Ctrl+Klik otvara novi pogled na lokaciju naselja STR_TOWN_POPULATION :{BLACK}Svetska populacija: {COMMA} @@ -3175,8 +3190,7 @@ STR_TOWN_POPULATION :{BLACK}Svetska STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Grad) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Populacija: {ORANGE}{COMMA}{BLACK} Zgrada: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Broj putnika tokom meseca: {ORANGE}{COMMA}{BLACK} najviše: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Količina pošte tokom meseca: {ORANGE}{COMMA}{BLACK} najviše: {ORANGE}{COMMA} +STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX :{BLACK}{CARGO_LIST} u poslednjem mesecu: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Tovar potreban za razvoj naselja: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} potrebno STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} potrebno zimi @@ -3487,6 +3501,9 @@ STR_INDUSTRY_VIEW_REQUIRES_CARGO_CARGO :{BLACK}Potražu STR_INDUSTRY_VIEW_REQUIRES_CARGO_CARGO_CARGO :{BLACK}Potražuje: {YELLOW}{STRING.aku}{STRING}, {STRING.aku}{STRING}, {STRING.aku}{STRING} ############ range for requires ends +STR_INDUSTRY_VIEW_REQUIRES :{BLACK} Zahteva: +STR_INDUSTRY_VIEW_ACCEPT_CARGO :{YELLOW}{STRING}{BLACK}{3:STRING} +STR_INDUSTRY_VIEW_ACCEPT_CARGO_AMOUNT :{YELLOW}{STRING}{BLACK}: {CARGO_SHORT} čekaje {STRING} ############ range for produces starts STR_INDUSTRY_VIEW_PRODUCES_CARGO :{BLACK}Proizvodi: {YELLOW}{STRING}{STRING} @@ -3555,6 +3572,10 @@ STR_GROUP_REMOVE_ALL_VEHICLES :Ukloni sva vozi STR_GROUP_RENAME_CAPTION :{BLACK}Preimenuj grupu +STR_GROUP_PROFIT_THIS_YEAR :Dobit ove godine: +STR_GROUP_PROFIT_LAST_YEAR :Dobit prošle godine: +STR_GROUP_OCCUPANCY :Trenutna upotreba: +STR_GROUP_OCCUPANCY_VALUE :{NUM}% # Build vehicle window STR_BUY_VEHICLE_TRAIN_RAIL_CAPTION :Nova Železnička Vozila @@ -3587,6 +3608,7 @@ STR_PURCHASE_INFO_ALL_TYPES :Sve vrste teret STR_PURCHASE_INFO_ALL_BUT :Sve sem {CARGO_LIST} STR_PURCHASE_INFO_MAX_TE :{BLACK}Najveća vučna snaga: {GOLD}{FORCE} STR_PURCHASE_INFO_AIRCRAFT_RANGE :{BLACK}Domet: {GOLD}{COMMA} pločica +STR_PURCHASE_INFO_AIRCRAFT_TYPE :{BLACK} Tip aviona: {GOLD} {STRING} STR_BUY_VEHICLE_TRAIN_LIST_TOOLTIP :{BLACK}Spisak probranih šinskih vozila - kliknite na vozilo za više podataka STR_BUY_VEHICLE_ROAD_VEHICLE_LIST_TOOLTIP :{BLACK}Spisak probranih drumskih vozila - kliknite na vozilo za više podataka @@ -3727,6 +3749,10 @@ STR_ENGINE_PREVIEW_MAGLEV_LOCOMOTIVE.aku :magnetnog žel. STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER :{BLACK}Cena: {CURRENCY_LONG} Težina: {WEIGHT_SHORT}{}Brzina: {VELOCITY} Snaga: {POWER}{}Cena Održavanja: {CURRENCY_LONG}/god.{}Nosivost: {CARGO_LONG} STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER_MAX_TE :{BLACK}Cena: {CURRENCY_LONG} Težina: {WEIGHT_SHORT}{}Brzina: {VELOCITY} Snaga: {POWER} Najveća vučna snaga: {6:FORCE}{}Cena Održavanja: {4:CURRENCY_LONG}/god{}Nosivost: {5:CARGO_LONG} STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAP_RUNCOST :{BLACK}Cena: {CURRENCY_LONG} Najveća Brzina: {VELOCITY}{}Nosivost: {CARGO_LONG}{}Cena Održavanja: {CURRENCY_LONG}/god. +STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_CAP_CAP_RUNCOST :BLACK} Cena: {CURRENCY_LONG} Maks. Brzina: {VELOCITY}{} Tip aviona: {STRING}{} Kapacitet: {CARGO_LONG}, {CARGO_LONG}{}Pokretna cena: {CURRENCY_LONG}/godine. +STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_CAP_RUNCOST :{BLACK} Cena: {CURRENCY_LONG} Maks. Brzina: {VELOCITY}{}Tip aviona: {STRING}{}Kapacitet: {CARGO_LONG}{}Pokretna cena: {CURRENCY_LONG}/god. +STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_CAP_RUNCOST :{BLACK} Cena: {CURRENCY_LONG} Maks. Brzina: {VELOCITY}{} Tip aviona: {STRING} Domet: {COMMA} pločice{}Kapacitet: {CARGO_LONG}, {CARGO_LONG}{} Pokretni trošak: {CURRENCY_LONG} /god. +STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_RUNCOST :BLACK}Cena: {CURRENCY_LONG} Maks. Brzina: {VELOCITY}{}Tip aviona: {STRING} Opseg: {COMMA} pločice{}Kapacitet: {CARGO_LONG}{}Pokretni trošak: {CURRENCY_LONG}/god. # Autoreplace window STR_REPLACE_VEHICLES_WHITE :{WHITE}Zameni {STRING} - {STRING} @@ -3766,6 +3792,7 @@ STR_REPLACE_HELP_STOP_BUTTON :{BLACK}Pritisni STR_REPLACE_ENGINE_WAGON_SELECT_HELP :{BLACK}Prebacuje između prikaza zamene lokomotiva i zamene vagona STR_REPLACE_ENGINES :Lokomotive STR_REPLACE_WAGONS :Vagoni +STR_REPLACE_ALL_RAILTYPE :Sve šinskih vozila STR_REPLACE_HELP_RAILTYPE :{BLACK}Izaberite vrstu pruge za koju želite zamenu kompozicije STR_REPLACE_HELP_REPLACE_INFO_TAB :{BLACK}Prikazuje koja lokomotiva će se zameniti označenom sa leve strane, ako ih ima @@ -3858,6 +3885,8 @@ STR_VEHICLE_INFO_AGE :{COMMA} godin{P STR_VEHICLE_INFO_AGE_RED :{RED}{COMMA} godin{P a e a} ({COMMA}) STR_VEHICLE_INFO_MAX_SPEED :{BLACK}Najveća brzina: {LTBLUE}{VELOCITY} +STR_VEHICLE_INFO_MAX_SPEED_TYPE :{BLACK}Maks. brzina: {LTBLUE}{VELOCITY} {BLACK}Tip aviona: {LTBLUE}{STRING} +STR_VEHICLE_INFO_MAX_SPEED_TYPE_RANGE :BLACK} Maks. brzina: {LTBLUE} {VELOCITY} {BLACK} Tip aviona: {LTBLUE} {STRING} {BLACK} Opseg: {LTBLUE} {COMMA} pločice STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED :{BLACK}Težina: {LTBLUE}{WEIGHT_SHORT} {BLACK}Snaga: {LTBLUE}{POWER}{BLACK} Najveća brzina: {LTBLUE}{VELOCITY} STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :{BLACK}Težina: {LTBLUE}{WEIGHT_SHORT} {BLACK}Snaga: {LTBLUE}{POWER}{BLACK} Najveća brzina: {LTBLUE}{VELOCITY} {BLACK} Najveća vučna snaga: {LTBLUE}{FORCE} @@ -4424,6 +4453,7 @@ 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... @@ -4675,6 +4705,8 @@ STR_BASESOUNDS_DOS_DESCRIPTION :Originalni skup STR_BASESOUNDS_WIN_DESCRIPTION :Originalni skup zvukova Transport Tycoon Deluxe Windows izdanja. STR_BASESOUNDS_NONE_DESCRIPTION :Prazan skup zvukova. STR_BASEMUSIC_WIN_DESCRIPTION :Originalni skup muzičkih numera Transport Tycoon Deluxe Windows izdanja. +STR_BASEMUSIC_DOS_DESCRIPTION :Originalna muzika za TTD za DOS izdanje. +STR_BASEMUSIC_TTO_DESCRIPTION :Originalna muzika TTD (Original / World Editor) DOS izdanja. STR_BASEMUSIC_NONE_DESCRIPTION :Prazan skup muzičkih numera. ##id 0x2000 diff --git a/src/lang/simplified_chinese.txt b/src/lang/simplified_chinese.txt index d8e9f0c8c6..7675bed2b6 100644 --- a/src/lang/simplified_chinese.txt +++ b/src/lang/simplified_chinese.txt @@ -669,15 +669,14 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}选择 STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}开启/关闭 随机播放列表中的曲目 STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}打开音乐选单窗口 -STR_ERROR_NO_SONGS :{WHITE}选择了没有歌曲的音乐组。不会播放歌曲。 - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}音乐选单 STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}全部音轨列表 STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}当前选用'{STRING}'列表 STR_PLAYLIST_CLEAR :{TINY_FONT}{BLACK}清除 +STR_PLAYLIST_CHANGE_SET :更改设置 STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}清除当前列表中曲目{}(仅限自定义1或自定义2) +STR_PLAYLIST_TOOLTIP_CHANGE_SET :{BLACK}选择另一种已安装的音乐 STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}点击音乐曲目以加入当前播放列表{}(仅限自定义1或自定义2) STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}点击音乐曲目以从当前播放列表中删除{}(仅限自定义1或自定义2) @@ -1337,8 +1336,7 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :设置缩略地 STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :绿色 STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :深绿色 STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :紫色 -STR_CONFIG_SETTING_REVERSE_SCROLLING :拖动方向与屏幕移动方向相反:{STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :设置按下鼠标右键拖动时地图移动的方向,“关闭”鼠标拖动摄像机,“打开”时鼠标拖动地图。 +STR_CONFIG_SETTING_SCROLLMODE_RMB :鼠标右键移动地图 STR_CONFIG_SETTING_SMOOTH_SCROLLING :平滑视角滚动: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :设置在缩略图上点击或者发出转到特定目标的命令时主视角的转换方式,如果“打开”本选项,视角平缓滚动,“关闭”时直接跳转到目标位置 STR_CONFIG_SETTING_MEASURE_TOOLTIP :建设时显示测量数据:{STRING} @@ -1370,8 +1368,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :按住Command STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :按住Ctrl键 点击 STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :关闭 -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :左击滚动: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :可用按住鼠标左键再拖拉的方法来进行屏幕滚动. 这对于触摸屏设备特别有用 STR_CONFIG_SETTING_AUTOSAVE :自动保存: {STRING} STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :选择自动存档时间间隔 @@ -2690,6 +2686,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}原始 STR_ABOUT_VERSION :{BLACK}OpenTTD 版本 {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 OpenTTD 团队 +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}保存游戏 STR_SAVELOAD_LOAD_CAPTION :{WHITE}读取存档 @@ -2981,8 +2984,6 @@ STR_TOWN_POPULATION :{BLACK}所有 STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (都市) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}人口:{ORANGE}{COMMA}{BLACK} 房屋:{ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}上月旅客数量:{ORANGE}{COMMA}{BLACK} 最大值:{ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}上月邮包数量:{ORANGE}{COMMA}{BLACK} 最大值:{ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}城镇发展所必需的货物: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{RED} 需要: {ORANGE}{STRING} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} 冬季的需求 @@ -3656,6 +3657,7 @@ STR_VEHICLE_INFO_AGE :{COMMA} 年 ({C STR_VEHICLE_INFO_AGE_RED :{RED}{COMMA} 年 ({COMMA}) STR_VEHICLE_INFO_MAX_SPEED :{BLACK}最大速度:{LTBLUE}{VELOCITY} +STR_VEHICLE_INFO_MAX_SPEED_TYPE :{BLACK}最高速度: {LTBLUE}{VELOCITY} {BLACK}飞机种类: {LTBLUE}{STRING} STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED :{BLACK}重量:{LTBLUE}{WEIGHT_SHORT} {BLACK}功率:{LTBLUE}{POWER}{BLACK} 最大速度:{LTBLUE}{VELOCITY} STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :{BLACK}重量:{LTBLUE}{WEIGHT_SHORT} {BLACK}功率:{LTBLUE}{POWER}{BLACK} 最大速度:{LTBLUE}{VELOCITY} {BLACK}最大牵引力:{LTBLUE}{FORCE} @@ -4473,6 +4475,7 @@ STR_BASESOUNDS_DOS_DESCRIPTION :运输大亨DOS STR_BASESOUNDS_WIN_DESCRIPTION :Transport Tycoon Deluxe Windows (运输大亨Windows豪华版)的原版音效包. STR_BASESOUNDS_NONE_DESCRIPTION :一个空的音效包. STR_BASEMUSIC_WIN_DESCRIPTION :Transport Tycoon Deluxe(运输大亨Windows豪华版)的原版音乐包 +STR_BASEMUSIC_DOS_DESCRIPTION :运输大亨DOS豪华版原版音乐。 STR_BASEMUSIC_NONE_DESCRIPTION :一个没有实际内容的音乐包. ##id 0x2000 diff --git a/src/lang/slovak.txt b/src/lang/slovak.txt index 4e28c45c02..c313e497a6 100644 --- a/src/lang/slovak.txt +++ b/src/lang/slovak.txt @@ -733,10 +733,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Zvoliť STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Prepnúť náhodný výber STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Zobraziť okno pre výber hudobných stôp -STR_ERROR_NO_SONGS :{WHITE}Bola zvolená sada hudby bez skladieb. Žiadne skladby nebudú hrať - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Výber hudobného programu STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Zoznam skladieb STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Program - '{STRING}' @@ -1405,8 +1402,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Farby terénu n STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Zelená STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Tmavozelená STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Fialová -STR_CONFIG_SETTING_REVERSE_SCROLLING :Posúvať mapu opačným smerom: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Chovanie sa mapy keď je posúvaná pravým tlačítkom myši. Ak je vypnuté posúva sa kamera, ak je zapnuté posúva sa mapa. STR_CONFIG_SETTING_SMOOTH_SCROLLING :Plynulé posúvanie pohľadu: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Nastaví ako bude reagovať posúvanie na špecifickú pozíciu po kliknutí na minimapu, alebo po zadaní príkazu na presun na zadaný objekt. Ak je zapnuté, pohľad sa presúva plynulo. Ak je vypnuté, pohľad skočí priamo na zadané miesto/objekt. STR_CONFIG_SETTING_MEASURE_TOOLTIP :Zobraziť údaje o rozmeroch pri výstavbe: {STRING} @@ -1438,8 +1433,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Príkaz + klik STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :CTRL + klik STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Žiadna -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Posúvať pohľad ľavým tlačidlom myši: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Povolí posúvanie mapy ĽAVÝM tlačítkom myši. Toto je obzvlášť užitočné pri použití dotykového displeja. STR_CONFIG_SETTING_AUTOSAVE :Automatické ukladanie: {STRING} STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :Vyberte interval pre automatické ukladanie hry @@ -2757,6 +2750,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Pôvodn STR_ABOUT_VERSION :{BLACK}OpenTTD verzia {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 team OpenTTD +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Uložiť hru STR_SAVELOAD_LOAD_CAPTION :{WHITE}Nahrať hru @@ -3048,8 +3048,6 @@ STR_TOWN_POPULATION :{BLACK}Svetová STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Mesto) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Obyvateľstvo: {ORANGE}{COMMA}{BLACK} Domov: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Cestujúci posledný mesiac: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Pošta posledný mesiac: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Tovar potrebný k rozrastu mesta: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} potrebný STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} potrebné v zime diff --git a/src/lang/slovenian.txt b/src/lang/slovenian.txt index 5fd44b4d36..122dd10ff1 100644 --- a/src/lang/slovenian.txt +++ b/src/lang/slovenian.txt @@ -822,10 +822,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Izberi g STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Preklapljaj mešan program vključeno/izključeno STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Prikaži okno z izborom glasbe -STR_ERROR_NO_SONGS :{WHITE}Izbran je bil komplet glasbe brez skladb. Nobena skladba ne bo predvajana - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Izbor glasbenega programa STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Kazalo skladb STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Program - '{STRING}' @@ -1490,8 +1487,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Barva ozemlja n STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Zelena STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Temno zelena STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Vijolična -STR_CONFIG_SETTING_REVERSE_SCROLLING :Obrni smer premika okna: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Sistem delovanja avtomatskega pomika z miško na robu. Onemogočeno - miška premika pogled, omogočeno - miška premika zemljevid. STR_CONFIG_SETTING_SMOOTH_SCROLLING :Gladek premik pogleda: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Način pomika pogleda na določen objekt majhnega zemljevida (centriranje pogleda). Omogočeno - pogled drsi, onemogočeno - pogled preskoči. STR_CONFIG_SETTING_MEASURE_TOOLTIP :Prikaz merilnega nasveta med uporabo gradbenih orodij: {STRING} @@ -1523,8 +1518,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Ukaz-klik STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Kontrola-klik STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Izklop -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Premik slike z levim klikom: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Omogoči pomik pogleda z levim klikom miške in vlečenjem. Primerno za dotične zaslone. STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Zapri okno z desnim klikom: {STRING} STR_CONFIG_SETTING_AUTOSAVE :Samodejno shrani: {STRING} @@ -2843,6 +2836,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Prvotne STR_ABOUT_VERSION :{BLACK}OpenTTD različica {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2018 ekipa OpenTTD +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Shrani igro STR_SAVELOAD_LOAD_CAPTION :{WHITE}Naloži igro @@ -3134,8 +3134,6 @@ STR_TOWN_POPULATION :{BLACK}Svetovno STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Mesto) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Prebivalstvo: {ORANGE}{COMMA}{BLACK} Število stavb: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Potnikov prejšnji mesec: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Pošte prejšnji mesec: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Količina potrebnega tovora za rast mesta: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} potrebno STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} je potreben pozimi diff --git a/src/lang/spanish.txt b/src/lang/spanish.txt index 6993b7b04b..d0deb739eb 100644 --- a/src/lang/spanish.txt +++ b/src/lang/spanish.txt @@ -670,10 +670,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Seleccio STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Encender/apagar mezclador STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Mostrar ventana de selección de pistas musicales -STR_ERROR_NO_SONGS :{WHITE}Se ha seleccionado un conjunto de música sin canciones. No se reproducirá música - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Selección del programa de música STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Índice de pistas STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Programa - '{STRING}' @@ -1338,8 +1335,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Color a usar pa STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Verde STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Verde oscuro STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Violeta -STR_CONFIG_SETTING_REVERSE_SCROLLING :Desplazamiento de vista invertido: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Comportamiento del juego al arrastrar el mapa con el botón derecho. Si se desactiva, el ratón mueve la cámara. Si se activa, el ratón mueve el mapa STR_CONFIG_SETTING_SMOOTH_SCROLLING :Desplazamiento de vista suavizado: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Controla la forma en la que la vista principal se mueve a una posición específica como resultado de hacer click en el mapa o al enviar la orden de moverse a un objeto determinado del mapa. Si se activa, la vista se mueve de forma suave. Si se desactiva, la vista se mueve directamente al destino STR_CONFIG_SETTING_MEASURE_TOOLTIP :Mostrar medidas usando las herramientas de construcción: {STRING} @@ -1371,8 +1366,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command+Click STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+Click STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Desactivado -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Desplazamiento con botón izquierdo: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Activa el deslizamiento del mapa al arrastrarlo con el botón izquierdo. Esto es especialmente útil al usar pantallas táctiles STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Cerrar ventana con click derecho: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Cierra una ventana al hacer click derecho dentro. ¡Quita la información al hacer click derecho! @@ -2694,6 +2687,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Copyrigh STR_ABOUT_VERSION :{BLACK}OpenTTD versión {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 El equipo OpenTTD +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Guardar Juego STR_SAVELOAD_LOAD_CAPTION :{WHITE}Cargar Juego @@ -2985,8 +2985,6 @@ STR_TOWN_POPULATION :{BLACK}Poblaci STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Ciudad) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Habitantes: {ORANGE}{COMMA}{BLACK} Casas: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Pasajeros último mes: {ORANGE}{COMMA}{BLACK} Máx.: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Correo último mes: {ORANGE}{COMMA}{BLACK} Máx.: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Carga necesaria para crecimiento del municipio: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} requeridos STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} requerido en invierno diff --git a/src/lang/spanish_MX.txt b/src/lang/spanish_MX.txt index afca51643c..c658780710 100644 --- a/src/lang/spanish_MX.txt +++ b/src/lang/spanish_MX.txt @@ -476,6 +476,7 @@ STR_ABOUT_MENU_SCREENSHOT :Captura de pant STR_ABOUT_MENU_ZOOMIN_SCREENSHOT :Captura con acercamiento completo STR_ABOUT_MENU_DEFAULTZOOM_SCREENSHOT :Captura con acercamiento predeterminado STR_ABOUT_MENU_GIANT_SCREENSHOT :Captura de mapa completo +STR_ABOUT_MENU_SHOW_FRAMERATE :Mostrar FPS STR_ABOUT_MENU_ABOUT_OPENTTD :Acerca de 'OpenTTD' STR_ABOUT_MENU_SPRITE_ALIGNER :Alineador de sprites STR_ABOUT_MENU_TOGGLE_BOUNDING_BOXES :Activar cajas delimitadoras @@ -651,6 +652,7 @@ STR_MUSIC_RULER_MARKER :{TINY_FONT}{BLA STR_MUSIC_TRACK_NONE :{TINY_FONT}{DKGREEN}-- STR_MUSIC_TRACK_DIGIT :{TINY_FONT}{DKGREEN}{ZEROFILL_NUM} STR_MUSIC_TITLE_NONE :{TINY_FONT}{DKGREEN}------ +STR_MUSIC_TITLE_NOMUSIC :{TINY_FONT}{DKGREEN}No hay música disponible STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKGREEN}"{STRING}" STR_MUSIC_TRACK :{TINY_FONT}{BLACK}Pista STR_MUSIC_XTITLE :{TINY_FONT}{BLACK}Título @@ -670,15 +672,15 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Elegir p STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Encender o apagar mezclador STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Mostrar ventana de selección de pistas musicales -STR_ERROR_NO_SONGS :{WHITE}Se eligió una colección vacía. No se reproducirá música - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Selección del programa musical +STR_PLAYLIST_MUSIC_SELECTION_SETNAME :{WHITE}Programa musical - "{STRING}" STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Lista de reproducción STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Programa: '{STRING}' STR_PLAYLIST_CLEAR :{TINY_FONT}{BLACK}Eliminar +STR_PLAYLIST_CHANGE_SET :{BLACK}Cambiar lista musical STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Eliminar programa actual (solo Personal 1 y Personal 2) +STR_PLAYLIST_TOOLTIP_CHANGE_SET :{BLACK}Cambiar la selección musical a otra lista instalada STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}Clic en la pista de música para añadirla al programa actual (solo Personal 1 y 2) STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}Clic en la pista de música para quitarla del programa actual (solo Personal 1 y 2) @@ -881,10 +883,10 @@ STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION :{BIG_FONT}{BLAC # Extra view window STR_EXTRA_VIEW_PORT_TITLE :{WHITE}Vista {COMMA} -STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Copiar ventana de vista +STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Cambiar ventana de vista STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN_TT :{BLACK}Copiar la vista principal a esta ventana de vista -STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Pegar ventana de vista -STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT :{BLACK}Pegar esta ventana de vista en la principal +STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Cambiar vista principal +STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT :{BLACK}Copiar ubicación en esta vista a la principal # Game options window STR_GAME_OPTIONS_CAPTION :{WHITE}Opciones de juego @@ -1338,8 +1340,12 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Color para el t STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Verde STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Verde oscuro STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Violeta -STR_CONFIG_SETTING_REVERSE_SCROLLING :Desplazamiento de vista invertido: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Efecto al arrastrar el mapa con el botón derecho. Si se desactiva, el ratón mueve la cámara. Si se activa, el ratón mueve el mapa +STR_CONFIG_SETTING_SCROLLMODE :Desplazamiento de vista: {STRING} +STR_CONFIG_SETTING_SCROLLMODE_HELPTEXT :Modo de recorrer la vista sobre el mapa +STR_CONFIG_SETTING_SCROLLMODE_DEFAULT :Desplazar la vista con clic derecho, ratón en posición fija +STR_CONFIG_SETTING_SCROLLMODE_RMB_LOCKED :Recorrer mapa con clic derecho, ratón en posición fija +STR_CONFIG_SETTING_SCROLLMODE_RMB :Recorrer mapa con clic derecho +STR_CONFIG_SETTING_SCROLLMODE_LMB :Recorrer mapa con clic izquierdo STR_CONFIG_SETTING_SMOOTH_SCROLLING :Desplazamiento de vista suavizado: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Forma en la que la vista principal se mueve a una ubicación específica al hacer clic en el minimapa o tras una orden de moverse a un objeto determinado del mapa. Si se activa, la vista se mueve de forma suave. Si se desactiva, la vista se mueve instantáneamente al sitio indicado STR_CONFIG_SETTING_MEASURE_TOOLTIP :Mostrar información de medidas al usar las herramientas de construcción: {STRING} @@ -1371,8 +1377,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command+Clic STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+Clic STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Ninguno -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Desplazamiento con botón izquierdo: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Activar el desplazamiento del mapa al arrastrar con el botón izquierdo. Esto es especialmente útil al usar pantallas táctiles STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Cerrar ventana con clic derecho: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Cerrar la ventana haciendo clic derecho sobre ella. ¡Desactiva los mensajes de ayuda con clic derecho! @@ -2286,6 +2290,7 @@ STR_LINKGRAPH_LEGEND_CAPTION :{BLACK}Leyenda STR_LINKGRAPH_LEGEND_ALL :{BLACK}Todas STR_LINKGRAPH_LEGEND_NONE :{BLACK}Ninguna STR_LINKGRAPH_LEGEND_SELECT_COMPANIES :{BLACK}Elegir las empresas a mostrar +STR_LINKGRAPH_LEGEND_COMPANY_TOOLTIP :{BLACK}{STRING}{}{COMPANY} # Linkgraph legend window and linkgraph legend in smallmap STR_LINKGRAPH_LEGEND_UNUSED :{TINY_FONT}{BLACK}sin uso @@ -2694,6 +2699,56 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Copyrigh STR_ABOUT_VERSION :{BLACK}OpenTTD versión {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018, el equipo de OpenTTD +# Framerate display window +STR_FRAMERATE_CAPTION :{WHITE}FPS +STR_FRAMERATE_CAPTION_SMALL :{STRING}{WHITE} ({DECIMAL}x) +STR_FRAMERATE_RATE_GAMELOOP :{WHITE}Simulación: {STRING} +STR_FRAMERATE_RATE_GAMELOOP_TOOLTIP :{BLACK}Número de ticks simulados por segundo. +STR_FRAMERATE_RATE_BLITTER :{WHITE}FPS de gráficos: {STRING} +STR_FRAMERATE_RATE_BLITTER_TOOLTIP :{BLACK}Número de cuadros por segundo. +STR_FRAMERATE_SPEED_FACTOR :{WHITE}Factor de velocidad de juego actual: {DECIMAL}x +STR_FRAMERATE_SPEED_FACTOR_TOOLTIP :{BLACK}Rapidez actual del juego comparada con la esperada durante una simulación normal. +STR_FRAMERATE_CURRENT :{WHITE}Actual +STR_FRAMERATE_AVERAGE :{WHITE}Promedio +STR_FRAMERATE_DATA_POINTS :{WHITE}Información de {COMMA} mediciones +STR_FRAMERATE_MS_GOOD :{LTBLUE}{DECIMAL}{WHITE} ms +STR_FRAMERATE_MS_WARN :{YELLOW}{DECIMAL}{WHITE} ms +STR_FRAMERATE_MS_BAD :{RED}{DECIMAL}{WHITE} ms +STR_FRAMERATE_FPS_GOOD :{LTBLUE}{DECIMAL}{WHITE} cuadros/s +STR_FRAMERATE_FPS_WARN :{YELLOW}{DECIMAL}{WHITE} cuadros/s +STR_FRAMERATE_FPS_BAD :{RED}{DECIMAL}{WHITE} cuadros/s +STR_FRAMERATE_GRAPH_MILLISECONDS :{TINY_FONT}{COMMA} ms +STR_FRAMERATE_GRAPH_SECONDS :{TINY_FONT}{COMMA} s +############ Leave those lines in this order!! +STR_FRAMERATE_GAMELOOP :{WHITE}Bucles de juego totales: +STR_FRAMERATE_GL_ECONOMY :{WHITE} Manejo de cargamento: +STR_FRAMERATE_GL_TRAINS :{WHITE} Ticks de trenes: +STR_FRAMERATE_GL_ROADVEHS :{WHITE} Ticks de vehículos de carretera: +STR_FRAMERATE_GL_SHIPS :{WHITE} Ticks de barcos: +STR_FRAMERATE_GL_AIRCRAFT :{WHITE} Ticks de aeronaves: +STR_FRAMERATE_GL_LANDSCAPE :{WHITE} Ticks de mapa: +STR_FRAMERATE_GL_LINKGRAPH :{WHITE} Retraro en gráfica de distribución: +STR_FRAMERATE_DRAWING :{WHITE}Presentación de gráficos: +STR_FRAMERATE_DRAWING_VIEWPORTS :{WHITE} Ventanas de vista generales: +STR_FRAMERATE_VIDEO :{WHITE}Salida de video: +STR_FRAMERATE_SOUND :{WHITE}Mezcla de sonido: +############ End of leave-in-this-order +############ Leave those lines in this order!! +STR_FRAMETIME_CAPTION_GAMELOOP :Bucle de juego +STR_FRAMETIME_CAPTION_GL_ECONOMY :Manejo de cargamento +STR_FRAMETIME_CAPTION_GL_TRAINS :Ticks de trenes +STR_FRAMETIME_CAPTION_GL_ROADVEHS :Ticks de vehículos de carretera +STR_FRAMETIME_CAPTION_GL_SHIPS :Ticks de barcos +STR_FRAMETIME_CAPTION_GL_AIRCRAFT :Ticks de areonaves +STR_FRAMETIME_CAPTION_GL_LANDSCAPE :Ticks de mapa +STR_FRAMETIME_CAPTION_GL_LINKGRAPH :Retraro en gráfica de distribución +STR_FRAMETIME_CAPTION_DRAWING :Presentación de gráficos +STR_FRAMETIME_CAPTION_DRAWING_VIEWPORTS :Presentación de ventanas de vista generales +STR_FRAMETIME_CAPTION_VIDEO :Salida de video +STR_FRAMETIME_CAPTION_SOUND :Mezcla de sonido +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Guardar partida STR_SAVELOAD_LOAD_CAPTION :{WHITE}Cargar partida @@ -2978,6 +3033,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Indicar STR_TOWN_DIRECTORY_CAPTION :{WHITE}Pueblos STR_TOWN_DIRECTORY_NONE :{ORANGE}- Ninguno - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (ciudad){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Nombres de pueblos. Clic en un nombre para centrar la vista principal en el pueblo. Ctrl+Clic abre una ventana de vista en dicha ubicación STR_TOWN_POPULATION :{BLACK}Población mundial: {COMMA} @@ -2985,8 +3041,7 @@ STR_TOWN_POPULATION :{BLACK}Poblaci STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (ciudad) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Habitantes: {ORANGE}{COMMA}{BLACK} Casas: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Pasajeros mes pasado: {ORANGE}{COMMA}{BLACK} Máx.: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Correo mes pasado: {ORANGE}{COMMA}{BLACK} Máx.: {ORANGE}{COMMA} +STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX :{BLACK}{CARGO_LIST} mes pasado: {ORANGE}{COMMA}{BLACK} máx.: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Cargamento necesario para crecimiento: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} requeridos STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} requerido en invierno @@ -4233,6 +4288,7 @@ 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... @@ -4484,6 +4540,8 @@ STR_BASESOUNDS_DOS_DESCRIPTION :Sonidos origina STR_BASESOUNDS_WIN_DESCRIPTION :Sonidos originales de Transport Tycoon Deluxe para Windows. STR_BASESOUNDS_NONE_DESCRIPTION :Paquete de sonidos vacío STR_BASEMUSIC_WIN_DESCRIPTION :Música original de Transport Tycoon Deluxe para Windows. +STR_BASEMUSIC_DOS_DESCRIPTION :Música original de Transport Tycoon Deluxe para DOS. +STR_BASEMUSIC_TTO_DESCRIPTION :Música original de Transport Tycoon versión World Editor para DOS. STR_BASEMUSIC_NONE_DESCRIPTION :Paquete de música vacío ##id 0x2000 diff --git a/src/lang/swedish.txt b/src/lang/swedish.txt index 255967c9d7..051b13271c 100644 --- a/src/lang/swedish.txt +++ b/src/lang/swedish.txt @@ -669,10 +669,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Välj sp STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Växla slumpning av/på STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Visa fönstret för val av musikspår -STR_ERROR_NO_SONGS :{WHITE}Ett musikpaket utan låtar har valts. Ingen musik kommer att spelas - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Konstruera spellista STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Spårindex STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Spellista - '{STRING}' @@ -1337,8 +1334,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Terrängens fä STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Grön STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Mörkgrön STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Violett -STR_CONFIG_SETTING_REVERSE_SCROLLING :Omvänd scrollriktning: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Beteende för skrollning av kartan med den högra musknappen. När det är inaktiverat rör musen kameran. När det är aktiverat rör musen kartan STR_CONFIG_SETTING_SMOOTH_SCROLLING :Mjuk scrollning av vy: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Kontrollera hur huvudvyn skrollar till en specifik position vid klick på minikartan eller när ett kommando används för att skrolla till ett specifikt objekt på kartan. Om det är aktiverat skrollar vyn mjukt, om det är inaktiverat hoppar den direkt till målet STR_CONFIG_SETTING_MEASURE_TOOLTIP :Visa måtthjälptext vid användning av byggverktyg: {STRING} @@ -1370,8 +1365,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command-klick STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Control-klick STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Av -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Scrolla med vänster musknappsklick: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Aktivera skrollning av kartan genom att dra den med den vänstra musknappen. Detta är särskilt användbart för skrollning vid användning av en pekskärm STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Stäng fönster med högerklick: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Stänger fönster när man högerklickar inuti dem. Denna inställning inaktiverar tooltips vid högerklick! @@ -2693,6 +2686,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Ursprung STR_ABOUT_VERSION :{BLACK}OpenTTD-version {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 OpenTTD-teamet +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Spara spel STR_SAVELOAD_LOAD_CAPTION :{WHITE}Ladda spel @@ -2984,8 +2984,6 @@ STR_TOWN_POPULATION :{BLACK}Global f STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Stad) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Invånare: {ORANGE}{COMMA}{BLACK} Hus: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Passagerare förra månaden: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Post förra månaden: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Fraktgods behövs för ortens tillväxt: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} krävs STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} krävs under vintern diff --git a/src/lang/tamil.txt b/src/lang/tamil.txt index ec3ef56fff..9c623a3619 100644 --- a/src/lang/tamil.txt +++ b/src/lang/tamil.txt @@ -659,10 +659,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_1_USER_DEFINED :{BLACK}'பய STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}'பயனரால் மாற்றியமைக்கப்பட்ட 2' பிரோகிராமினைத் தேர்ந்தெடுக்கவும் STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}இசைத் த்டத்தினைத் தேர்ந்தெடுக்கும் திரையினைக் காட்டு -STR_ERROR_NO_SONGS :{WHITE}இசைத்தடமே இல்லாதப் பட்டியல் தேர்ந்தெடுக்கப்பட்டுள்ளது. எந்த பாட்டும் ஒலிக்காது - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}இசை பிரோகிராம் தேர்ந்தெடுத்தல் STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}இசைத்தடம் வரிசை STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}பிரோகிராம் - '{STRING}' @@ -1231,7 +1228,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :சிறுப STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :பச்சை STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :கரும் பச்சை STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :ஊதா -STR_CONFIG_SETTING_REVERSE_SCROLLING :திருப்பப்பட்ட பக்கமுருட்டி திசை : {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING :பார்படத்தின் இலகுவான பக்கமுருட்டல்: {STRING} STR_CONFIG_SETTING_LIVERIES :நிறுவன livery களைக் காட்டு: {STRING} STR_CONFIG_SETTING_LIVERIES_NONE :ஒன்றுமில்லை @@ -2380,6 +2376,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}அச STR_ABOUT_VERSION :{BLACK}OpenTTD பதிப்பு {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 OpenTTD குழுமம் +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}ஆட்டத்தை பதிவு செய் STR_SAVELOAD_LOAD_CAPTION :{WHITE}பதிவு செய்த ஆட்டத்தை தொடரு @@ -2624,8 +2627,6 @@ STR_TOWN_POPULATION :{BLACK}உல STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (மாநகரம்) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}மக்கள்தொகை: {ORANGE}{COMMA}{BLACK} வீடுகள்: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}சென்ற மாத பயணிகள்: {ORANGE}{COMMA}{BLACK} அதிகம்: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}சென்ற மாத அஞ்சல்கள்: {ORANGE}{COMMA}{BLACK} அதிகம்: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}நகரத்தின் வளர்ச்சியிற்கு தேவையான சரக்குகள்: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} தேவை STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} குளிர்காலத்தில் தேவை diff --git a/src/lang/thai.txt b/src/lang/thai.txt index d939eeeeac..7bb1e09c72 100644 --- a/src/lang/thai.txt +++ b/src/lang/thai.txt @@ -661,10 +661,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}เล STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}เปิด/ปิด Toggle programme shuffle on/off STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}แสดงหน้าต่างเลือกรายการเพลง -STR_ERROR_NO_SONGS :{WHITE}ชุดเพลงประกอบนี้ไม่มีการเลือกเพลงไว้ - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}รายการเลือกโปรแกรมเพลง STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}รายการเพลง STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}โปรแกรม - '{STRING}' @@ -1300,8 +1297,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :สีของ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :สีเขียว STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :สีเขียวแก่ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :สีม่วง -STR_CONFIG_SETTING_REVERSE_SCROLLING :กลับทิศการเลื่อนหน้าจอ: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :เลือกลักษณะการเลื่อนแผนที่ เมื่อใช้ปุ่มคลิ๊กเมาส์ขวา หากเปิดการใช้งาน หน้าจอจะเคลื่อนที่ไปในทิศตรงกันข้ามกับการคลิ๊กเมาส์ค้างแล้วลากเมาส์ไป STR_CONFIG_SETTING_SMOOTH_SCROLLING :เลื่อนอย่างนิ่มนวลบนจอภาพ: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :ควบคุมการเคลื่อนที่ของจอภาพ เวลาคลิ๊กเลือกตำแหน่งในแผนที่ย่อ หากไม่เปิดใช้งาน ตำแหน่งของจอจะย้ายไปที่ตำแหน่งที่เลือกทันที แต่หากเปิดใช้งาน จะเคลื่อนที่ไปยังตำแหน่งอย่างนุ่มนวล STR_CONFIG_SETTING_MEASURE_TOOLTIP :แสดงบอลลูนข้อความแสดงระยะทางหรือข้อมูลอื่นๆ เมื่อใช่เครื่องมือสร้าง: {STRING} @@ -1333,8 +1328,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command+คล STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+Click STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :ปิด -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :เลื่อนหน้าจอด้วยการคลิ๊กเมาส์ซ้าย: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :เปิดใช้งานเพื่อให้สามารถใช้การคลิ๊กเมาส์ซ้ายในการเลื่อนภาพหน้าจอได้ STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES :ใช้รูปแบบวันที่ {STRING} เป็นชื่อเซฟของเกม @@ -2637,6 +2630,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}ลิ STR_ABOUT_VERSION :{BLACK}OpenTTD รุ่นที่ {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}ลิขสิทธิ์ OpenTTD {COPYRIGHT}2002-2018 ของ The OpenTTD team +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}บันทึกเกม STR_SAVELOAD_LOAD_CAPTION :{WHITE}โหลดเกม @@ -2912,8 +2912,6 @@ STR_TOWN_POPULATION :{BLACK}ปร STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}นคร {TOWN} STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}จำนวนประชากร: {ORANGE}{COMMA}{BLACK} จำนวนอาคาร: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}ผู้โดยสารเมื่อเดือนที่แล้ว: {ORANGE}{COMMA}{BLACK} จำนวนสูงสุด: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}ไปรษณีย์ภัณฑ์เมื่อเดือนที่แล้ว: {ORANGE}{COMMA}{BLACK} จำนวนสูงสุด: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}ความต้องการสินค้าสำหรับการขยายตัวของเมือง: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} required STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} ต้องการหิมะ diff --git a/src/lang/traditional_chinese.txt b/src/lang/traditional_chinese.txt index 7ce922edc1..f72e44e5fe 100644 --- a/src/lang/traditional_chinese.txt +++ b/src/lang/traditional_chinese.txt @@ -669,10 +669,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}選擇 STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}開關播放清單亂序播放 STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}於選擇視窗顯示樂軌 -STR_ERROR_NO_SONGS :{WHITE}已選擇不含音樂的音樂集,不會播放任何音樂 - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}背景音樂播放清單選擇 STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM}「{STRING}」 STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}音軌索引 STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}播放清單 - 「{STRING}」 @@ -1337,8 +1334,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :設定在小地 STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :綠 STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :暗綠 STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :紫 -STR_CONFIG_SETTING_REVERSE_SCROLLING :反轉捲軸方向:{STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :設定在右撳拖曳滑鼠時的系統反應。如停用此選項,移動滑鼠時會移動顯示範圍 (即影像的移動方向與滑鼠的移動方向相反)。如啟用此選項,移動滑鼠時會移動顯示地圖 (即影像的移動方向與滑鼠的移動方向相同) STR_CONFIG_SETTING_SMOOTH_SCROLLING :視野平滑移動:{STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :設定在小地圖中點選一個位置時,主視野的顯示反應。如啟用此選項,影像會移動直至到達點選的位置;否則影像會直接跳到點選的位置 STR_CONFIG_SETTING_MEASURE_TOOLTIP :使用某些建設工具時顯示度量提示:{STRING} @@ -1370,8 +1365,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command 鍵 STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Control 鍵 STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :無 -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :滑鼠左鍵捲動:{STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :容許以左撳並拖曳滑鼠捲動地圖。此選項對使用觸控螢幕進行捲動動作很有幫助 STR_CONFIG_SETTING_AUTOSAVE :自動儲存: {STRING} STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :選擇自動存檔的週期 @@ -2689,6 +2682,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}原著 STR_ABOUT_VERSION :{BLACK}OpenTTD 版本 {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 OpenTTD 開發小組 +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}儲存遊戲 STR_SAVELOAD_LOAD_CAPTION :{WHITE}載入遊戲 @@ -2980,8 +2980,6 @@ STR_TOWN_POPULATION :{BLACK}世界 STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (城市) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}人口:{ORANGE}{COMMA}{BLACK} 房屋:{ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}上月乘客數字:{ORANGE}{COMMA}{BLACK} 紀錄最高:{ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}上月郵件數量:{ORANGE}{COMMA}{BLACK} 紀錄最高:{ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}市鎮成長所需貨物: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{RED}需要 {ORANGE}{STRING} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} 必須是冬天 diff --git a/src/lang/turkish.txt b/src/lang/turkish.txt index 763fb2a65a..b820385ef9 100644 --- a/src/lang/turkish.txt +++ b/src/lang/turkish.txt @@ -670,10 +670,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}'Özel 2 STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Rastgele programı aç/kapa STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Şarkı seçim penceresini göster -STR_ERROR_NO_SONGS :{WHITE}Şarkısız bir müzik kümesi seçildi. Hiçbir şarkı çalınmayacak - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Müzik Program Seçimi STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Parça Listesi STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Program - '{STRING}' @@ -1338,8 +1335,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Küçük harita STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Yeşil STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Koyu yeşil STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Mor -STR_CONFIG_SETTING_REVERSE_SCROLLING :Fareyle kaydırma hareketini ters çevir: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Haritayı sağ fare tuşuyla kaydırırken davranış biçimi. Etkisiz kılındığında, fare kamerayı hareket ettirir. Etkinleştirildiğinde ise fare haritayı hareket ettirir. STR_CONFIG_SETTING_SMOOTH_SCROLLING :Düzgün viewport kaydırması: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Küçük haritaya tıklandığında veya harita üzerindeki belli bir nesneye gidilmesi için komut verildiğinde ana görüntünün nasıl kaydırılacağını kontrol eder. Etkinleştirildiğinde harita kayarak ilerler, kapatıldığında ise doğrudan hedeflenen noktaya atlama yapar. STR_CONFIG_SETTING_MEASURE_TOOLTIP :İnşa araçları kullanılırken ölçüm ipucu göster: {STRING} @@ -1371,8 +1366,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Komut-tıklama STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Kontrol-tıklama STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Kapalı -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Sol tık ile ekran kaydır: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Sol fare tuşuyla sürükleyerek harita kaydırma özelliğini etkinleştir. Özellikle dokunmatik-ekran kullanırken kaydırma yapmak için kullanılabilir. STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Sağ tıklama ile pencereyi kapat: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :İçerisinde sağ tıklandığında pencereyi kapatır. Sağ tıklandığında ipuçları gösterimini devre dışı bırakır! @@ -2694,6 +2687,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Telif ha STR_ABOUT_VERSION :{BLACK}OpenTTD sürüm {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 OpenTTD ekibi +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Oyunu Kaydet STR_SAVELOAD_LOAD_CAPTION :{WHITE}Yükle @@ -2985,8 +2985,6 @@ STR_TOWN_POPULATION :{BLACK}Dünya n STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Şehir) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Nüfus: {ORANGE}{COMMA}{BLACK} Ev: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Geçen ayki yolcu: {ORANGE}{COMMA}{BLACK} azami: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Geçen ayki posta: {ORANGE}{COMMA}{BLACK} azami: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Kasaba büyümesi için gerekli kargo: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} gerekli STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} kışın gerekir diff --git a/src/lang/ukrainian.txt b/src/lang/ukrainian.txt index dbb815d2dc..ac77f0cead 100644 --- a/src/lang/ukrainian.txt +++ b/src/lang/ukrainian.txt @@ -797,10 +797,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Вибр STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Вкл./відкл. випадкову програму STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Показує вікно вибору музичної програми -STR_ERROR_NO_SONGS :{WHITE}Був обраний музичний набір без пісень. Пісні не будуть програватись - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Вибір музичної програми STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Назва доріжки STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Програма - '{STRING}' @@ -1465,8 +1462,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Колір по STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :зелений STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :темнозелений STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :фіолетовий -STR_CONFIG_SETTING_REVERSE_SCROLLING :Змінити напрямок прокрутки: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Налаштування переміщення по карті правою кнопкою миші. При включенні переміщується карта. При виключенні - камера. STR_CONFIG_SETTING_SMOOTH_SCROLLING :Плавна прокрутка у вікні: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Налаштування способу прокрутки основного екрану при клацанні мишою по зменшенній карті, або інших діях, що призводять до переміщення по карті (кнопки "Оглянути", тощо). При включенні опції переміщення карти відбувається плавно. При виключенні - відбувається моментальне переміщення в необхідну точку STR_CONFIG_SETTING_MEASURE_TOOLTIP :Показувати підказки про розміри під час будівництва: {STRING} @@ -1498,8 +1493,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Команда+ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+клац мишою STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :не емулювати -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Прокрутка по лівому клацу миші: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Дозволяє "тягати" карту утримуючи ліву кнопку миші, що дає можливість використовувати сенсорні екрани природнім способом.. STR_CONFIG_SETTING_AUTOSAVE :Автозбереження: {STRING} STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :Оберіть проміжок між автоматичними збереженнями гри @@ -2820,6 +2813,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Авто STR_ABOUT_VERSION :{BLACK}OpenTTD версія {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 команда OpenTTD +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Зберегти гру STR_SAVELOAD_LOAD_CAPTION :{WHITE}Завантажити гру @@ -3111,8 +3111,6 @@ STR_TOWN_POPULATION :{BLACK}Насе STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (місто) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Населення: {ORANGE}{COMMA}{BLACK} Будинки: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Пасажирів за місяць: {ORANGE}{COMMA}{BLACK} найбільше: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Пошти за місяць: {ORANGE}{COMMA}{BLACK} найбільше: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Вантаж, потрібний для зростання міста: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} потрібно STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} потрібно взимку diff --git a/src/lang/unfinished/chuvash.txt b/src/lang/unfinished/chuvash.txt index a9f98fe138..474c328f96 100644 --- a/src/lang/unfinished/chuvash.txt +++ b/src/lang/unfinished/chuvash.txt @@ -403,7 +403,6 @@ STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKG STR_MUSIC_TRACK :{TINY_FONT}{BLACK}Кӗвӗ STR_MUSIC_XTITLE :{TINY_FONT}{BLACK}Ят - # Playlist window STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_CLEAR :{TINY_FONT}{BLACK}Тасат @@ -971,6 +970,13 @@ STR_LAI_OBJECT_DESCRIPTION_LIGHTHOUSE :Маяк # About OpenTTD window STR_ABOUT_VERSION :{BLACK}OpenTTD верси {REV} +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario diff --git a/src/lang/unfinished/frisian.txt b/src/lang/unfinished/frisian.txt index 051b62c843..0a9968ddf4 100644 --- a/src/lang/unfinished/frisian.txt +++ b/src/lang/unfinished/frisian.txt @@ -669,10 +669,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Selektea STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Set musyk mjokselje oan/út STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Lit musykseleksjeskerm sjen. -STR_ERROR_NO_SONGS :{WHITE}In musykset sûnder nûmers is selektearre. Gjin nûmers sille spile wurden - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Musykprogramseleksje STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Nûmeryndeks STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Program - '{STRING}' @@ -1329,8 +1326,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Kleur fan it l STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Grien STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Donker grien STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Fiolet -STR_CONFIG_SETTING_REVERSE_SCROLLING :Draai scrollrjochtig om: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :By útskeakeljen beweecht de mûs de kamera. By ynskeakeljen beweecht de mûs de kaart STR_CONFIG_SETTING_SMOOTH_SCROLLING :Loaitsfinster floeiend scrolle : {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Bepaalt hoe it haadfinster scrollt. By ynskeakeljen sil dit floeiend wêze. By útskeakeljen ljept it byld direktst nei de selektearre lokaasje STR_CONFIG_SETTING_MEASURE_TOOLTIP :Under it gebrûk fan de ferskate bou-arken diminsjes sjen litte: {STRING} @@ -1362,8 +1357,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Kommando+Klik STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+Klik STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Ut -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Scrolle mei lofter mûsknop: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Skeakel scrollen mei de lofter mûsknop oan. Dit is brûksum foar scollen op oanreitsskermen STR_CONFIG_SETTING_AUTOSAVE :Automatysk bewarje: {STRING} STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :Selektearje de tiid tusken automatysk bewarje fan it spul @@ -2477,6 +2470,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Orizjine STR_ABOUT_VERSION :{BLACK}OpenTTD-ferzje {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2018 It OpenTTD team +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Spul Opslaan STR_SAVELOAD_LOAD_CAPTION :{WHITE}Spul Lade @@ -2754,8 +2754,6 @@ STR_TOWN_POPULATION :{BLACK}Wrâldpo STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (City) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Ynwenners: {ORANGE}{COMMA}{BLACK} Hûzen: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Passazjiers lêste moanne: {ORANGE}{COMMA}{BLACK} maks: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Post lêste moanne: {ORANGE}{COMMA}{BLACK} maks: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Guod nedich foar stêdsgroei: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} ferplichte STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} ferplichte yn de winter diff --git a/src/lang/unfinished/ido.txt b/src/lang/unfinished/ido.txt index 4f4d4846ff..114c434f36 100644 --- a/src/lang/unfinished/ido.txt +++ b/src/lang/unfinished/ido.txt @@ -377,7 +377,6 @@ STR_MUSIC_TRACK_DIGIT :{TINY_FONT}{DKG STR_MUSIC_TITLE_NONE :{TINY_FONT}{DKGREEN}------ STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKGREEN}"{STRING}" - # Playlist window # Highscore window @@ -778,6 +777,13 @@ STR_LAI_OBJECT_DESCRIPTION_COMPANY_HEADQUARTERS :Stabeyo di komp STR_ABOUT_VERSION :{BLACK}OpenTTD versiono {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2018 La kruo OpenTTD +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_DETAIL_CAPTION :{BLACK}Ludo Detali STR_SAVELOAD_DETAIL_COMPANY_INDEX :{SILVER}{COMMA}: {WHITE}{STRING} diff --git a/src/lang/unfinished/macedonian.txt b/src/lang/unfinished/macedonian.txt index 6a0157c5a8..30a0f142b1 100644 --- a/src/lang/unfinished/macedonian.txt +++ b/src/lang/unfinished/macedonian.txt @@ -641,10 +641,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Избе STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Вклучи/исклучи мешање за програм STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Прикажи диалог за избор на песна -STR_ERROR_NO_SONGS :{WHITE}Музички сет без песни е избран. Не песни ќе се одигра - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Избор на музички програм STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Индекс на песната STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Програм - '{STRING}' @@ -1204,6 +1201,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Ориг STR_ABOUT_VERSION :{BLACK}OpenTTD верзија {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2018 OpenTTD тимот +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_LOAD_BUTTON :{BLACK}Оптоварување STR_SAVELOAD_LOAD_TOOLTIP :{BLACK}Оптоварување на избраната игра diff --git a/src/lang/unfinished/maltese.txt b/src/lang/unfinished/maltese.txt index 628fe94cfc..4fc0e8cb10 100644 --- a/src/lang/unfinished/maltese.txt +++ b/src/lang/unfinished/maltese.txt @@ -346,7 +346,6 @@ STR_MUSIC_TRACK_DIGIT :{TINY_FONT}{DKG STR_MUSIC_TITLE_NONE :{TINY_FONT}{DKGREEN}------ STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKGREEN}"{STRING}" - # Playlist window # Highscore window @@ -683,6 +682,13 @@ STR_OBJECT_BUILD_CLASS_TOOLTIP :{BLACK}Aghzel i # About OpenTTD window +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario diff --git a/src/lang/unfinished/marathi.txt b/src/lang/unfinished/marathi.txt index 2437182361..4576bccbae 100644 --- a/src/lang/unfinished/marathi.txt +++ b/src/lang/unfinished/marathi.txt @@ -628,10 +628,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}'कस STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}कार्यक्रम चुळबूळ - प्रारंभ / बंद STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}संगीत ट्रॅक निवड दाखवा -STR_ERROR_NO_SONGS :{WHITE}संगीत न संगीत संच निवडले गेले आहे. एकही गाणी खेळला जाईल. - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}संगीत कार्यक्रम निवड. STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}गाणे क्रमांक STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}कार्यक्रम - '{STRING}' @@ -1110,6 +1107,13 @@ STR_LAI_WATER_DESCRIPTION_RIVER :नदी # About OpenTTD window STR_ABOUT_OPENTTD :{WHITE}ओपेन टीटीडी बद्दल +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_BYTES_FREE :{BLACK}{BYTES} मोकळ STR_SAVELOAD_DETAIL_COMPANY_INDEX :{SILVER}{COMMA}: {WHITE}{STRING} diff --git a/src/lang/unfinished/persian.txt b/src/lang/unfinished/persian.txt index 9701899630..30ad05666c 100644 --- a/src/lang/unfinished/persian.txt +++ b/src/lang/unfinished/persian.txt @@ -658,10 +658,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}انتخ STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}پخش به صورت لیست برهم ریخته STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}نمایش پنجره لیست آهنگهای انتخابی -STR_ERROR_NO_SONGS :{WHITE}در مجموعه موسیقی آهنگی انتخاب نشده است. هیچ آهنگی پخش نخواهد شد - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}انتخاب برنامه پخش موسیقی STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}شماره ی آهنگ STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}برنامه - '{STRING}' @@ -1227,7 +1224,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR :رنگ استف STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :سبز STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :سبز تیره STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :بنفش -STR_CONFIG_SETTING_REVERSE_SCROLLING :برعکس کردن جهت حرکت کردن صفحه: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING :تصویر صاف در نمای اضافه: {STRING} STR_CONFIG_SETTING_MEASURE_TOOLTIP :نمایش متن کمکی وقتی از چندین ابزار استفاده می شود: {STRING} STR_CONFIG_SETTING_LIVERIES :نمایش طراحی مخصوص وسیله نقلیه : {STRING} @@ -1247,7 +1243,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :دستور+کل STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :کنترل+کلیک STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :خاموش -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :حرکت در نقشه با کلیک چپ:: {STRING} STR_CONFIG_SETTING_AUTOSAVE :ذخیره خودکار: {STRING} STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :انتخاب فاصله زمانی بین ذخیره کردن های خودکار @@ -2391,6 +2386,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Original STR_ABOUT_VERSION :{BLACK}OpenTTD ویرایش {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2018 The OpenTTD team +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}ذخیره ی بازی STR_SAVELOAD_LOAD_CAPTION :{WHITE}ادامه ی بازی @@ -2663,8 +2665,6 @@ STR_TOWN_POPULATION :{BLACK}جمعی STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (شهر) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}جمعیت: {ORANGE}{COMMA}{BLACK} خانه ها: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}مسافران در ماه گذشته: {ORANGE}{COMMA}{BLACK} حداکثر: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}نامه ها در ماه گذشته: {ORANGE}{COMMA}{BLACK} حداکثر: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}نوع بار برای رشد شهر: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} ضروری STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} در زمستان ضروری است diff --git a/src/lang/unfinished/urdu.txt b/src/lang/unfinished/urdu.txt index 324e073aa4..b5fd180e01 100644 --- a/src/lang/unfinished/urdu.txt +++ b/src/lang/unfinished/urdu.txt @@ -649,10 +649,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}'اپن STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}پروگرام ہلانے کی تدویم کیجئیے STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}گانا چننے کا اختیار دینے والی ونڈو دکھائیں -STR_ERROR_NO_SONGS :{WHITE}کوئی گانا دستیاب نہیں ہے - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}موسیقی کے پروگرام کا انتخاب کریں STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}گانوں کی فہرست STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}پروگرام - '{STRING}' @@ -2129,6 +2126,13 @@ STR_FOUND_TOWN_SELECT_LAYOUT_RANDOM :{G=f}{BLACK}ک STR_ABOUT_OPENTTD :{WHITE}اوپن ٹی ٹی ڈی کے متعلق STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} ٢٠٠٢ - ٢٠١٦ OpenTTD ٹیم +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario diff --git a/src/lang/vietnamese.txt b/src/lang/vietnamese.txt index 19fbce1cfd..c1643d0731 100644 --- a/src/lang/vietnamese.txt +++ b/src/lang/vietnamese.txt @@ -669,10 +669,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Chọn k STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Bật/tắt chơi nhạc ngẫu nhiên STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Hiện cửa số chọn bài nhạc -STR_ERROR_NO_SONGS :{WHITE}Đã chọn gói nhạc chuẩn nhưng không có bài nào. Không có bài nào để chơi - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Chọn Kiểu Chơi Nhạc STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Bảng Bài Nhạc STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Chương Trình - '{STRING}' @@ -1337,8 +1334,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Màu sắc củ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Lục STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Lục tối STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Tím -STR_CONFIG_SETTING_REVERSE_SCROLLING :Đảo ngược hướng cuộn: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Phản ứng khi cuộn bản đồ bằng nút chuột phải. Nếu tắt, thì chuột di chuyển theo vùng nhìn. Nếu bật thì chuột di chuyển theo bản đồ STR_CONFIG_SETTING_SMOOTH_SCROLLING :Cuộn uyển chuyển cửa sổ: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Điều khiển cách màn hình chính cuộn tới vị trí cụ thể khi nháy chuột vào bản đồ nhỏ hoặc khi gõ lệnh cuộn tới đối tượng trên bản đồ. Nếu bật, thì sẽ cuộn trượt, nếu tắt thì nhảy thẳng tới vị trí đó. STR_CONFIG_SETTING_MEASURE_TOOLTIP :Hiện bảng chú giải đo lường khi dùng các công cụ xây dựng: {STRING} @@ -1370,8 +1365,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command+Click STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+Click STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Tắt -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Cuộn chuột trái: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Cho phép cuộn bản đồ bằng cách kéo với nút trái chuột. Tùy chọn này sẽ hữu ích khi dùng màn hình cảm ứng STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Đóng cửa số khi click chuột phải: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Đóng cửa sổ bằng cách bấm chuột phải vào đó. Ngăn tooltip bằng cách bấm phải! @@ -2693,6 +2686,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Nguyên STR_ABOUT_VERSION :{BLACK}OpenTTD phiên bản {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2018 Nhóm OpenTTD +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Lưu Ván Chơi STR_SAVELOAD_LOAD_CAPTION :{WHITE}Nạp Ván Chơi @@ -2984,8 +2984,6 @@ STR_TOWN_POPULATION :{BLACK}Dân s STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Thành Phố) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Dân số: {ORANGE}{COMMA}{BLACK} Toà nhà: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Du khách tháng trước: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Bưu kiện tháng trước: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Hàng hoá cần để đô thị tăng trưởng: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} được yêu cầu STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} Yêu cầu trong mùa đông diff --git a/src/lang/welsh.txt b/src/lang/welsh.txt index 6e77712da4..c5652db878 100644 --- a/src/lang/welsh.txt +++ b/src/lang/welsh.txt @@ -669,10 +669,7 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Dewis y STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Toglu cymysgu trefn rhaglen ymlaen neu i ffwrdd STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Dangos y ffenestr dewis traciau cerddoriaeth -STR_ERROR_NO_SONGS :{WHITE}Dewiswyd set caneuon heb ganeuon ynddo. Ni chwaraeir unrhyw ganeuon - # Playlist window -STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Dewisiadau Rhaglen Gerddoriaeth STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Indecs Traciau STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Rhaglen - '{STRING}' @@ -1337,8 +1334,6 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Lliw y tirwedd STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Gwyrdd STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Gwyrdd tywyll STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Fioled -STR_CONFIG_SETTING_REVERSE_SCROLLING :Gwrthdroi'r cyfeiriad sgrolio: {STRING} -STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT :Ymddygiad pan yn sgrolio gyda botwm dde y llygoden. Pan yr analluogir, bydd y llygoden yn symyd y camera. Pan y galluogir, bydd y llygoden yn symyd y map STR_CONFIG_SETTING_SMOOTH_SCROLLING :Sgrolio prif ffenestr llyfn: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Rheoli syt y mae'r prif olygfa'n sgrolio at leoliad penodol pan yn clicio ar y map bychan neu yn rhoi gorchymyn i sgrolio at wrthrych penodol STR_CONFIG_SETTING_MEASURE_TOOLTIP :Dangos cymorth mesur wrth ddefnyddio'r offer adeiladu amrywiol: {STRING} @@ -1370,8 +1365,6 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command-clic STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+Clic STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :I ffwrdd -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING :Sgrolio Clic-chwith: {STRING} -STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT :Galluogi sgrolio ar y map drwy ei lusgo gyda botwm chwith y llygoden. Mae hyn yn arbennig o ddefnyddiol pan yn defnyddio sgrin-gyffwrdd ar gyfer sgrolio STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Cau ffenest wrth dde-glicio: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Cau ffenest wrth dde-glicio tu fewn iddo. Mae hyn yn analluogi dangos gwybodaeth ar dde-clicio! @@ -2693,6 +2686,13 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Hawlfrai STR_ABOUT_VERSION :{BLACK}fersiwn OpenTTD {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2018 Y tîm OpenTTD +# Framerate display window +############ Leave those lines in this order!! +############ End of leave-in-this-order +############ Leave those lines in this order!! +############ End of leave-in-this-order + + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Cadw Gêm STR_SAVELOAD_LOAD_CAPTION :{WHITE}Llwytho Gêm @@ -2984,8 +2984,6 @@ STR_TOWN_POPULATION :{BLACK}Poblogae STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Dinas) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Poblogaeth: {ORANGE}{COMMA}{BLACK} Tai: {ORANGE}{COMMA} -STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX :{BLACK}Teithwyr mis diwethaf: {ORANGE}{COMMA}{BLACK} uchafswm: {ORANGE}{COMMA} -STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX :{BLACK}Post mis diwethaf: {ORANGE}{COMMA}{BLACK} uchafswm: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Nwyddau angenrheidiol ar gyfer tyfiant y dref: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{RED}Angen {ORANGE}{STRING} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} ei angen yn y gaeaf diff --git a/src/linkgraph/linkgraph_gui.cpp b/src/linkgraph/linkgraph_gui.cpp index 1fe34fe79c..c91fa20588 100644 --- a/src/linkgraph/linkgraph_gui.cpp +++ b/src/linkgraph/linkgraph_gui.cpp @@ -298,7 +298,7 @@ Point LinkGraphOverlay::GetStationMiddle(const Station *st) const * Set a new cargo mask and rebuild the cache. * @param cargo_mask New cargo mask. */ -void LinkGraphOverlay::SetCargoMask(uint32 cargo_mask) +void LinkGraphOverlay::SetCargoMask(CargoTypes cargo_mask) { this->cargo_mask = cargo_mask; this->RebuildCache(); @@ -319,7 +319,7 @@ void LinkGraphOverlay::SetCompanyMask(uint32 company_mask) /** Make a number of rows with buttons for each company for the linkgraph legend window. */ NWidgetBase *MakeCompanyButtonRowsLinkGraphGUI(int *biggest_index) { - return MakeCompanyButtonRows(biggest_index, WID_LGL_COMPANY_FIRST, WID_LGL_COMPANY_LAST, 3, STR_LINKGRAPH_LEGEND_SELECT_COMPANIES); + return MakeCompanyButtonRows(biggest_index, WID_LGL_COMPANY_FIRST, WID_LGL_COMPANY_LAST, 3, STR_NULL); } NWidgetBase *MakeSaturationLegendLinkGraphGUI(int *biggest_index) @@ -435,7 +435,7 @@ void LinkGraphLegendWindow::SetOverlay(LinkGraphOverlay *overlay) { this->SetWidgetLoweredState(WID_LGL_COMPANY_FIRST + c, HasBit(companies, c)); } } - uint32 cargoes = this->overlay->GetCargoMask(); + CargoTypes cargoes = this->overlay->GetCargoMask(); for (uint c = 0; c < NUM_CARGO; c++) { if (!this->IsWidgetDisabled(WID_LGL_CARGO_FIRST + c)) { this->SetWidgetLoweredState(WID_LGL_CARGO_FIRST + c, HasBit(cargoes, c)); @@ -496,10 +496,48 @@ void LinkGraphLegendWindow::DrawWidget(const Rect &r, int widget) const if (this->IsWidgetDisabled(widget)) return; CargoSpec *cargo = CargoSpec::Get(widget - WID_LGL_CARGO_FIRST); GfxFillRect(r.left + 2, r.top + 2, r.right - 2, r.bottom - 2, cargo->legend_colour); - DrawString(r.left, r.right, (r.top + r.bottom + 1 - FONT_HEIGHT_SMALL) / 2, cargo->abbrev, TC_BLACK, SA_HOR_CENTER); + DrawString(r.left, r.right, (r.top + r.bottom + 1 - FONT_HEIGHT_SMALL) / 2, cargo->abbrev, GetContrastColour(cargo->legend_colour, 73), SA_HOR_CENTER); } } +bool LinkGraphLegendWindow::OnHoverCommon(Point pt, int widget, TooltipCloseCondition close_cond) +{ + if (IsInsideMM(widget, WID_LGL_COMPANY_FIRST, WID_LGL_COMPANY_LAST + 1)) { + if (this->IsWidgetDisabled(widget)) { + GuiShowTooltips(this, STR_LINKGRAPH_LEGEND_SELECT_COMPANIES, 0, NULL, close_cond); + } else { + uint64 params[2]; + CompanyID cid = (CompanyID)(widget - WID_LGL_COMPANY_FIRST); + params[0] = STR_LINKGRAPH_LEGEND_SELECT_COMPANIES; + params[1] = cid; + GuiShowTooltips(this, STR_LINKGRAPH_LEGEND_COMPANY_TOOLTIP, 2, params, close_cond); + } + return true; + } + if (IsInsideMM(widget, WID_LGL_CARGO_FIRST, WID_LGL_CARGO_LAST + 1)) { + if (this->IsWidgetDisabled(widget)) return false; + CargoSpec *cargo = CargoSpec::Get(widget - WID_LGL_CARGO_FIRST); + uint64 params[1]; + params[0] = cargo->name; + GuiShowTooltips(this, STR_BLACK_STRING, 1, params, close_cond); + return true; + } + return false; +} + +void LinkGraphLegendWindow::OnHover(Point pt, int widget) +{ + this->OnHoverCommon(pt, widget, TCC_HOVER); +} + +bool LinkGraphLegendWindow::OnRightClick(Point pt, int widget) +{ + if (_settings_client.gui.hover_delay_ms == 0) { + return this->OnHoverCommon(pt, widget, TCC_RIGHT_CLICK); + } + return false; +} + /** * Update the overlay with the new company selection. */ @@ -519,7 +557,7 @@ void LinkGraphLegendWindow::UpdateOverlayCompanies() */ void LinkGraphLegendWindow::UpdateOverlayCargoes() { - uint32 mask = 0; + CargoTypes mask = 0; for (uint c = 0; c < NUM_CARGO; c++) { if (this->IsWidgetDisabled(c + WID_LGL_CARGO_FIRST)) continue; if (!this->IsWidgetLowered(c + WID_LGL_CARGO_FIRST)) continue; diff --git a/src/linkgraph/linkgraph_gui.h b/src/linkgraph/linkgraph_gui.h index a9be8254d4..a933bfc683 100644 --- a/src/linkgraph/linkgraph_gui.h +++ b/src/linkgraph/linkgraph_gui.h @@ -15,6 +15,7 @@ #include "../company_func.h" #include "../station_base.h" #include "../widget_type.h" +#include "../window_gui.h" #include "linkgraph_base.h" #include #include @@ -51,17 +52,17 @@ public: * @param company_mask Bitmask of companies to be shown. * @param scale Desired thickness of lines and size of station dots. */ - LinkGraphOverlay(const Window *w, uint wid, uint32 cargo_mask, uint32 company_mask, uint scale) : + LinkGraphOverlay(const Window *w, uint wid, CargoTypes cargo_mask, uint32 company_mask, uint scale) : window(w), widget_id(wid), cargo_mask(cargo_mask), company_mask(company_mask), scale(scale) {} void RebuildCache(); void Draw(const DrawPixelInfo *dpi) const; - void SetCargoMask(uint32 cargo_mask); + void SetCargoMask(CargoTypes cargo_mask); void SetCompanyMask(uint32 company_mask); /** Get a bitmask of the currently shown cargoes. */ - uint32 GetCargoMask() { return this->cargo_mask; } + CargoTypes GetCargoMask() { return this->cargo_mask; } /** Get a bitmask of the currently shown companies. */ uint32 GetCompanyMask() { return this->company_mask; } @@ -69,7 +70,7 @@ public: protected: const Window *window; ///< Window to be drawn into. const uint widget_id; ///< ID of Widget in Window to be drawn to. - uint32 cargo_mask; ///< Bitmask of cargos to be displayed. + CargoTypes cargo_mask; ///< Bitmask of cargos to be displayed. uint32 company_mask; ///< Bitmask of companies to be displayed. LinkMap cached_links; ///< Cache for links to reduce recalculation. StationSupplyList cached_stations; ///< Cache for stations to be drawn. @@ -101,6 +102,8 @@ public: virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize); virtual void DrawWidget(const Rect &r, int widget) const; + virtual void OnHover(Point pt, int widget); + virtual bool OnRightClick(Point pt, int widget); virtual void OnClick(Point pt, int widget, int click_count); virtual void OnInvalidateData(int data = 0, bool gui_scope = true); @@ -109,6 +112,7 @@ private: void UpdateOverlayCompanies(); void UpdateOverlayCargoes(); + bool OnHoverCommon(Point pt, int widget, TooltipCloseCondition close_cond); }; #endif /* LINKGRAPH_GUI_H */ diff --git a/src/linkgraph/linkgraphschedule.cpp b/src/linkgraph/linkgraphschedule.cpp index a65783a5e7..8c508d8173 100644 --- a/src/linkgraph/linkgraphschedule.cpp +++ b/src/linkgraph/linkgraphschedule.cpp @@ -15,6 +15,7 @@ #include "demands.h" #include "mcf.h" #include "flowmapper.h" +#include "../framerate_type.h" #include "../safeguards.h" @@ -151,6 +152,7 @@ void OnTick_LinkGraph() if (offset == 0) { LinkGraphSchedule::instance.SpawnNext(); } else if (offset == _settings_game.linkgraph.recalc_interval / 2) { + PerformanceMeasurer framerate(PFE_GL_LINKGRAPH); LinkGraphSchedule::instance.JoinNext(); } } diff --git a/src/main_gui.cpp b/src/main_gui.cpp index b13920a648..199546d439 100644 --- a/src/main_gui.cpp +++ b/src/main_gui.cpp @@ -439,7 +439,7 @@ struct MainWindow : Window virtual void OnMouseWheel(int wheel) { - if (_settings_client.gui.scrollwheel_scrolling == 0) { + if (_settings_client.gui.scrollwheel_scrolling != 2) { ZoomInOrOutToCursorWindow(wheel < 0, this); } } diff --git a/src/map.cpp b/src/map.cpp index 3bee6ab97e..2995d8ca5e 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -87,7 +87,7 @@ TileIndex TileAdd(TileIndex tile, TileIndexDiff add, seprintf(buf, lastof(buf), "TILE_ADD(%s) when adding 0x%.4X and 0x%.4X failed", exp, tile, add); -#if !defined(_MSC_VER) || defined(WINCE) +#if !defined(_MSC_VER) fprintf(stderr, "%s:%d %s\n", file, line, buf); #else _assert(buf, (char*)file, line); @@ -269,7 +269,7 @@ bool CircularTileSearch(TileIndex *tile, uint size, TestTileOnSearchProc proc, v /* If tile test is not successful, get one tile up, * ready for a test in first circle around center tile */ - *tile = TILE_ADD(*tile, TileOffsByDir(DIR_N)); + *tile = TileAddByDir(*tile, DIR_N); return CircularTileSearch(tile, size / 2, 1, 1, proc, user_data); } else { return CircularTileSearch(tile, size / 2, 0, 0, proc, user_data); diff --git a/src/map_func.h b/src/map_func.h index 8c2752d95b..e737505a32 100644 --- a/src/map_func.h +++ b/src/map_func.h @@ -147,7 +147,7 @@ static inline uint ScaleByMapSize1D(uint n) * An offset value between to tiles. * * This value is used for the difference between - * to tiles. It can be added to a tileindex to get + * two tiles. It can be added to a tileindex to get * the resulting tileindex of the start tile applied * with this saved difference. * @@ -362,6 +362,18 @@ static inline TileIndexDiff TileOffsByDir(Direction dir) return ToTileIndexDiff(_tileoffs_by_dir[dir]); } +/** + * Adds a Direction to a tile. + * + * @param tile The current tile + * @param dir The direction in which we want to step + * @return the moved tile + */ +static inline TileIndex TileAddByDir(TileIndex tile, Direction dir) +{ + return TILE_ADD(tile, TileOffsByDir(dir)); +} + /** * Adds a DiagDir to a tile. * diff --git a/src/map_type.h b/src/map_type.h index 620885e5da..7af391b46c 100644 --- a/src/map_type.h +++ b/src/map_type.h @@ -33,8 +33,9 @@ assert_compile(sizeof(Tile) == 8); * Look at docs/landscape.html for the exact meaning of the members. */ struct TileExtended { - byte m6; ///< General purpose - byte m7; ///< Primarily used for newgrf support + byte m6; ///< General purpose + byte m7; ///< Primarily used for newgrf support + uint16 m8; ///< General purpose }; /** diff --git a/src/misc/hashtable.hpp b/src/misc/hashtable.hpp index 1afe58cac7..1078f1861d 100644 --- a/src/misc/hashtable.hpp +++ b/src/misc/hashtable.hpp @@ -161,12 +161,10 @@ protected: /** static helper - return hash for the given key modulo number of slots */ inline static int CalcHash(const Tkey &key) { - int32 hash = key.CalcHash(); - if ((8 * Thash_bits) < 32) hash ^= hash >> (min(8 * Thash_bits, 31)); - if ((4 * Thash_bits) < 32) hash ^= hash >> (min(4 * Thash_bits, 31)); - if ((2 * Thash_bits) < 32) hash ^= hash >> (min(2 * Thash_bits, 31)); - if ((1 * Thash_bits) < 32) hash ^= hash >> (min(1 * Thash_bits, 31)); - hash &= (1 << Thash_bits) - 1; + uint32 hash = key.CalcHash(); + hash -= (hash >> 17); // hash * 131071 / 131072 + hash -= (hash >> 5); // * 31 / 32 + hash &= (1 << Thash_bits) - 1; // modulo slots return hash; } diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index 01e8d2c45d..dd75410628 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -313,10 +313,7 @@ public: for (CargoID i = 0; i < NUM_CARGO; ++i) { if (acceptance[i] > 0) { /* Add a comma between each item. */ - if (found) { - *strp++ = ','; - *strp++ = ' '; - } + if (found) strp = strecpy(strp, ", ", lastof(this->landinfo_data[LAND_INFO_MULTICENTER_LINE])); found = true; /* If the accepted value is less than 8, show it in 1/8:ths */ @@ -659,7 +656,7 @@ struct TooltipsWindow : public Window this->string_id = str; assert_compile(sizeof(this->params[0]) == sizeof(params[0])); assert(paramcount <= lengthof(this->params)); - memcpy(this->params, params, sizeof(this->params[0]) * paramcount); + if (paramcount > 0) memcpy(this->params, params, sizeof(this->params[0]) * paramcount); this->paramcount = paramcount; this->close_cond = close_tooltip; diff --git a/src/mixer.cpp b/src/mixer.cpp index 5945bd235a..6aaa8204d4 100644 --- a/src/mixer.cpp +++ b/src/mixer.cpp @@ -12,6 +12,7 @@ #include "stdafx.h" #include #include "core/math_func.hpp" +#include "framerate_type.h" #include "safeguards.h" @@ -138,6 +139,13 @@ static void MxCloseChannel(MixerChannel *mc) void MxMixSamples(void *buffer, uint samples) { + PerformanceMeasurer framerate(PFE_SOUND); + static uint last_samples = 0; + if (samples != last_samples) { + framerate.SetExpectedRate((double)_play_rate / samples); + last_samples = samples; + } + MixerChannel *mc; /* Clear the buffer */ diff --git a/src/music.cpp b/src/music.cpp index 4001e621e1..3d0e40bf9b 100644 --- a/src/music.cpp +++ b/src/music.cpp @@ -11,11 +11,69 @@ #include "stdafx.h" + /** The type of set we're replacing */ #define SET_TYPE "music" #include "base_media_func.h" #include "safeguards.h" +#include "fios.h" + + +/** + * Read the name of a music CAT file entry. + * @param filename Name of CAT file to read from + * @param entrynum Index of entry whose name to read + * @return Pointer to string, caller is responsible for freeing memory, + * NULL if entrynum does not exist. + */ +char *GetMusicCatEntryName(const char *filename, size_t entrynum) +{ + if (!FioCheckFileExists(filename, BASESET_DIR)) return NULL; + + FioOpenFile(CONFIG_SLOT, filename, BASESET_DIR); + uint32 ofs = FioReadDword(); + size_t entry_count = ofs / 8; + if (entrynum < entry_count) { + FioSeekTo(entrynum * 8, SEEK_SET); + FioSeekTo(FioReadDword(), SEEK_SET); + byte namelen = FioReadByte(); + char *name = MallocT(namelen + 1); + FioReadBlock(name, namelen); + name[namelen] = '\0'; + return name; + } + return NULL; +} + +/** + * Read the full data of a music CAT file entry. + * @param filename Name of CAT file to read from. + * @param entrynum Index of entry to read + * @param[out] entrylen Receives length of data read + * @return Pointer to buffer with data read, caller is responsible for freeind memory, + * NULL if entrynum does not exist. + */ +byte *GetMusicCatEntryData(const char *filename, size_t entrynum, size_t &entrylen) +{ + entrylen = 0; + if (!FioCheckFileExists(filename, BASESET_DIR)) return NULL; + + FioOpenFile(CONFIG_SLOT, filename, BASESET_DIR); + uint32 ofs = FioReadDword(); + size_t entry_count = ofs / 8; + if (entrynum < entry_count) { + FioSeekTo(entrynum * 8, SEEK_SET); + size_t entrypos = FioReadDword(); + entrylen = FioReadDword(); + FioSeekTo(entrypos, SEEK_SET); + FioSkipBytes(FioReadByte()); + byte *data = MallocT(entrylen); + FioReadBlock(data, entrylen); + return data; + } + return NULL; +} INSTANTIATE_BASE_MEDIA_METHODS(BaseMedia, MusicSet) @@ -66,34 +124,73 @@ bool MusicSet::FillSetDetails(IniFile *ini, const char *path, const char *full_f if (ret) { this->num_available = 0; IniGroup *names = ini->GetGroup("names"); - for (uint i = 0, j = 1; i < lengthof(this->song_name); i++) { + IniGroup *catindex = ini->GetGroup("catindex"); + IniGroup *timingtrim = ini->GetGroup("timingtrim"); + uint tracknr = 1; + for (uint i = 0; i < lengthof(this->songinfo); i++) { const char *filename = this->files[i].filename; - if (names == NULL || StrEmpty(filename)) { - this->song_name[i][0] = '\0'; + if (names == NULL || StrEmpty(filename) || this->files[i].check_result == MD5File::CR_NO_FILE) { + this->songinfo[i].songname[0] = '\0'; continue; } - IniItem *item = NULL; + this->songinfo[i].filename = filename; // non-owned pointer + + IniItem *item = catindex->GetItem(_music_file_names[i], false); + if (item != NULL && !StrEmpty(item->value)) { + /* Song has a CAT file index, assume it's MPS MIDI format */ + this->songinfo[i].filetype = MTT_MPSMIDI; + this->songinfo[i].cat_index = atoi(item->value); + char *songname = GetMusicCatEntryName(filename, this->songinfo[i].cat_index); + if (songname == NULL) { + DEBUG(grf, 0, "Base music set song missing from CAT file: %s/%d", filename, this->songinfo[i].cat_index); + this->songinfo[i].songname[0] = '\0'; + continue; + } + strecpy(this->songinfo[i].songname, songname, lastof(this->songinfo[i].songname)); + free(songname); + } else { + this->songinfo[i].filetype = MTT_STANDARDMIDI; + } + + const char *trimmed_filename = filename; /* As we possibly add a path to the filename and we compare * on the filename with the path as in the .obm, we need to * keep stripping path elements until we find a match. */ - for (const char *p = filename; p != NULL; p = strchr(p, PATHSEPCHAR)) { + for (; trimmed_filename != NULL; trimmed_filename = strchr(trimmed_filename, PATHSEPCHAR)) { /* Remove possible double path separator characters from * the beginning, so we don't start reading e.g. root. */ - while (*p == PATHSEPCHAR) p++; + while (*trimmed_filename == PATHSEPCHAR) trimmed_filename++; - item = names->GetItem(p, false); + item = names->GetItem(trimmed_filename, false); if (item != NULL && !StrEmpty(item->value)) break; } - if (item == NULL || StrEmpty(item->value)) { - DEBUG(grf, 0, "Base music set song name missing: %s", filename); - return false; + if (this->songinfo[i].filetype == MTT_STANDARDMIDI) { + if (item != NULL && !StrEmpty(item->value)) { + strecpy(this->songinfo[i].songname, item->value, lastof(this->songinfo[i].songname)); + } else { + DEBUG(grf, 0, "Base music set song name missing: %s", filename); + return false; + } + } + this->num_available++; + + /* Number the theme song (if any) track 0, rest are normal */ + if (i == 0) { + this->songinfo[i].tracknr = 0; + } else { + this->songinfo[i].tracknr = tracknr++; } - strecpy(this->song_name[i], item->value, lastof(this->song_name[i])); - this->track_nr[i] = j++; - this->num_available++; + item = timingtrim->GetItem(trimmed_filename, false); + if (item != NULL && !StrEmpty(item->value)) { + const char *endpos = strchr(item->value, ':'); + if (endpos != NULL) { + this->songinfo[i].override_start = atoi(item->value); + this->songinfo[i].override_end = atoi(endpos + 1); + } + } } } return ret; diff --git a/src/music/allegro_m.cpp b/src/music/allegro_m.cpp index 77b488186a..906aec84fc 100644 --- a/src/music/allegro_m.cpp +++ b/src/music/allegro_m.cpp @@ -14,6 +14,7 @@ #include "../stdafx.h" #include "../debug.h" #include "allegro_m.h" +#include "midifile.hpp" #include #include "../safeguards.h" @@ -58,11 +59,17 @@ void MusicDriver_Allegro::Stop() if (--_allegro_instance_count == 0) allegro_exit(); } -void MusicDriver_Allegro::PlaySong(const char *filename) +void MusicDriver_Allegro::PlaySong(const MusicSongInfo &song) { + std::string filename = MidiFile::GetSMFFile(song); + if (_midi != NULL) destroy_midi(_midi); - _midi = load_midi(filename); - play_midi(_midi, false); + if (!filename.empty()) { + _midi = load_midi(filename.c_str()); + play_midi(_midi, false); + } else { + _midi = NULL; + } } void MusicDriver_Allegro::StopSong() diff --git a/src/music/allegro_m.h b/src/music/allegro_m.h index 69cf59569a..65d8ab811d 100644 --- a/src/music/allegro_m.h +++ b/src/music/allegro_m.h @@ -21,7 +21,7 @@ public: /* virtual */ void Stop(); - /* virtual */ void PlaySong(const char *filename); + /* virtual */ void PlaySong(const MusicSongInfo &song); /* virtual */ void StopSong(); diff --git a/src/music/bemidi.cpp b/src/music/bemidi.cpp index 2bc2074763..ff56d787f1 100644 --- a/src/music/bemidi.cpp +++ b/src/music/bemidi.cpp @@ -12,6 +12,8 @@ #include "../stdafx.h" #include "../openttd.h" #include "bemidi.h" +#include "../base_media_base.h" +#include "midifile.hpp" /* BeOS System Includes */ #include @@ -34,13 +36,17 @@ void MusicDriver_BeMidi::Stop() midiSynthFile.UnloadFile(); } -void MusicDriver_BeMidi::PlaySong(const char *filename) +void MusicDriver_BeMidi::PlaySong(const MusicSongInfo &song) { + std::string filename = MidiFile::GetSMFFile(song); + this->Stop(); - entry_ref midiRef; - get_ref_for_path(filename, &midiRef); - midiSynthFile.LoadFile(&midiRef); - midiSynthFile.Start(); + if (!filename.empty()) { + entry_ref midiRef; + get_ref_for_path(filename.c_str(), &midiRef); + midiSynthFile.LoadFile(&midiRef); + midiSynthFile.Start(); + } } void MusicDriver_BeMidi::StopSong() diff --git a/src/music/bemidi.h b/src/music/bemidi.h index 23c6249d59..7c546525d2 100644 --- a/src/music/bemidi.h +++ b/src/music/bemidi.h @@ -21,7 +21,7 @@ public: /* virtual */ void Stop(); - /* virtual */ void PlaySong(const char *filename); + /* virtual */ void PlaySong(const MusicSongInfo &song); /* virtual */ void StopSong(); diff --git a/src/music/cocoa_m.cpp b/src/music/cocoa_m.cpp index 925dc21ab5..8d97aedf06 100644 --- a/src/music/cocoa_m.cpp +++ b/src/music/cocoa_m.cpp @@ -18,7 +18,9 @@ #include "../stdafx.h" #include "../os/macosx/macos.h" #include "cocoa_m.h" +#include "midifile.hpp" #include "../debug.h" +#include "../base_media_base.h" #define Rect OTTDRect #define Point OTTDPoint @@ -141,11 +143,13 @@ void MusicDriver_Cocoa::Stop() /** * Starts playing a new song. * - * @param filename Path to a MIDI file. + * @param song Description of music to load and play */ -void MusicDriver_Cocoa::PlaySong(const char *filename) +void MusicDriver_Cocoa::PlaySong(const MusicSongInfo &song) { - DEBUG(driver, 2, "cocoa_m: trying to play '%s'", filename); + std::string filename = MidiFile::GetSMFFile(song); + + DEBUG(driver, 2, "cocoa_m: trying to play '%s'", filename.c_str()); this->StopSong(); if (_sequence != NULL) { @@ -153,12 +157,14 @@ void MusicDriver_Cocoa::PlaySong(const char *filename) _sequence = NULL; } + if (filename.empty()) return; + if (NewMusicSequence(&_sequence) != noErr) { DEBUG(driver, 0, "cocoa_m: Failed to create music sequence"); return; } - const char *os_file = OTTD2FS(filename); + const char *os_file = OTTD2FS(filename.c_str()); CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8*)os_file, strlen(os_file), false); #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) @@ -218,7 +224,7 @@ void MusicDriver_Cocoa::PlaySong(const char *filename) if (MusicPlayerStart(_player) != noErr) return; _playing = true; - DEBUG(driver, 3, "cocoa_m: playing '%s'", filename); + DEBUG(driver, 3, "cocoa_m: playing '%s'", filename.c_str()); } diff --git a/src/music/cocoa_m.h b/src/music/cocoa_m.h index 1963bef5b7..fdb10b84e6 100644 --- a/src/music/cocoa_m.h +++ b/src/music/cocoa_m.h @@ -20,7 +20,7 @@ public: /* virtual */ void Stop(); - /* virtual */ void PlaySong(const char *filename); + /* virtual */ void PlaySong(const MusicSongInfo &song); /* virtual */ void StopSong(); diff --git a/src/music/dmusic.cpp b/src/music/dmusic.cpp index 471fb3f366..fece709fda 100644 --- a/src/music/dmusic.cpp +++ b/src/music/dmusic.cpp @@ -19,86 +19,1099 @@ #include "../debug.h" #include "../os/windows/win32.h" #include "../core/mem_func.hpp" +#include "../thread/thread.h" +#include "../fileio_func.h" +#include "../base_media_base.h" #include "dmusic.h" +#include "midifile.hpp" +#include "midi.h" #include -#undef FACILITY_DIRECTMUSIC // Needed for newer Windows SDK version. #include -#include #include -#include +#include #include "../safeguards.h" -static FMusicDriver_DMusic iFMusicDriver_DMusic; +#if defined(_MSC_VER) +# pragma comment(lib, "ole32.lib") +#endif /* defined(_MSC_VER) */ -/** the direct music object manages buffers and ports */ -static IDirectMusic *music = NULL; - -/** the performance object controls manipulation of the segments */ -static IDirectMusicPerformance *performance = NULL; - -/** the loader object can load many types of DMusic related files */ -static IDirectMusicLoader *loader = NULL; - -/** the segment object is where the MIDI data is stored for playback */ -static IDirectMusicSegment *segment = NULL; - -static bool seeking = false; +static const int MS_TO_REFTIME = 1000 * 10; ///< DirectMusic time base is 100 ns. +static const int MIDITIME_TO_REFTIME = 10; ///< Time base of the midi file reader is 1 us. -#define M(x) x "\0" -static const char ole_files[] = - M("ole32.dll") - M("CoCreateInstance") - M("CoInitialize") - M("CoUninitialize") - M("") -; -#undef M +#define FOURCC_INFO mmioFOURCC('I','N','F','O') +#define FOURCC_fmt mmioFOURCC('f','m','t',' ') +#define FOURCC_data mmioFOURCC('d','a','t','a') -struct ProcPtrs { - unsigned long (WINAPI * CoCreateInstance)(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID *ppv); - HRESULT (WINAPI * CoInitialize)(LPVOID pvReserved); - void (WINAPI * CoUninitialize)(); +/** A DLS file. */ +struct DLSFile { + /** An instrument region maps a note range to wave data. */ + struct DLSRegion { + RGNHEADER hdr; + WAVELINK wave; + WSMPL wave_sample; + + std::vector wave_loops; + std::vector articulators; + }; + + /** Instrument definition read from a DLS file. */ + struct DLSInstrument { + INSTHEADER hdr; + + std::vector articulators; + std::vector regions; + }; + + /** Wave data definition from a DLS file. */ + struct DLSWave { + long file_offset; + + PCMWAVEFORMAT fmt; + std::vector data; + + WSMPL wave_sample; + std::vector wave_loops; + + bool operator ==(long offset) const { + return this->file_offset == offset; + } + }; + + std::vector instruments; + std::vector pool_cues; + std::vector waves; + + /** Try loading a DLS file into memory. */ + bool LoadFile(const TCHAR *file); + +private: + /** Load an articulation structure from a DLS file. */ + bool ReadDLSArticulation(FILE *f, DWORD list_length, std::vector &out); + /** Load a list of regions from a DLS file. */ + bool ReadDLSRegionList(FILE *f, DWORD list_length, DLSInstrument &instrument); + /** Load a single region from a DLS file. */ + bool ReadDLSRegion(FILE *f, DWORD list_length, std::vector &out); + /** Load a list of instruments from a DLS file. */ + bool ReadDLSInstrumentList(FILE *f, DWORD list_length); + /** Load a single instrument from a DLS file. */ + bool ReadDLSInstrument(FILE *f, DWORD list_length); + /** Load a list of waves from a DLS file. */ + bool ReadDLSWaveList(FILE *f, DWORD list_length); + /** Load a single wave from a DLS file. */ + bool ReadDLSWave(FILE *f, DWORD list_length, long offset); }; -static ProcPtrs proc; +/** A RIFF chunk header. */ +PACK_N(struct ChunkHeader { + FOURCC type; ///< Chunk type. + DWORD length; ///< Length of the chunk, not including the chunk header itself. +}, 2); + +/** Buffer format for a DLS wave download. */ +PACK_N(struct WAVE_DOWNLOAD { + DMUS_DOWNLOADINFO dlInfo; + ULONG ulOffsetTable[2]; + DMUS_WAVE dmWave; + DMUS_WAVEDATA dmWaveData; +}, 2); + +struct PlaybackSegment { + uint32 start, end; + size_t start_block; + bool loop; +}; + +static struct { + bool shutdown; ///< flag to indicate playback thread shutdown + bool playing; ///< flag indicating that playback is active + bool do_start; ///< flag for starting playback of next_file at next opportunity + bool do_stop; ///< flag for stopping playback at next opportunity + + int preload_time; ///< preload time for music blocks. + byte new_volume; ///< volume setting to change to + + MidiFile next_file; ///< upcoming file to play + PlaybackSegment next_segment; ///< segment info for upcoming file +} _playback; + +/** Handle to our worker thread. */ +static ThreadObject *_dmusic_thread = NULL; +/** Event to signal the thread that it should look at a state change. */ +static HANDLE _thread_event = NULL; +/** Lock access to playback data that is not thread-safe. */ +static ThreadMutex *_thread_mutex = NULL; + +/** The direct music object manages buffers and ports. */ +static IDirectMusic *_music = NULL; +/** The port object lets us send MIDI data to the synthesizer. */ +static IDirectMusicPort *_port = NULL; +/** The buffer object collects the data to sent. */ +static IDirectMusicBuffer *_buffer = NULL; +/** List of downloaded DLS instruments. */ +static std::vector _dls_downloads; + + +static FMusicDriver_DMusic iFMusicDriver_DMusic; + + +bool DLSFile::ReadDLSArticulation(FILE *f, DWORD list_length, std::vector &out) +{ + while (list_length > 0) { + ChunkHeader chunk; + if (fread(&chunk, sizeof(chunk), 1, f) != 1) return false; + list_length -= chunk.length + sizeof(chunk); + + if (chunk.type == FOURCC_ART1) { + CONNECTIONLIST conns; + if (fread(&conns, sizeof(conns), 1, f) != 1) return false; + fseek(f, conns.cbSize - sizeof(conns), SEEK_CUR); + + /* Read all defined articulations. */ + for (ULONG i = 0; i < conns.cConnections; i++) { + CONNECTION con; + if (fread(&con, sizeof(con), 1, f) != 1) return false; + out.push_back(con); + } + } else { + fseek(f, chunk.length, SEEK_CUR); + } + } + + return true; +} + +bool DLSFile::ReadDLSRegion(FILE *f, DWORD list_length, std::vector &out) +{ + out.push_back(DLSRegion()); + DLSRegion ®ion = out.back(); + + /* Set default values. */ + region.wave_sample.cbSize = 0; + + while (list_length > 0) { + ChunkHeader chunk; + if (fread(&chunk, sizeof(chunk), 1, f) != 1) return false; + list_length -= chunk.length + sizeof(chunk); + + if (chunk.type == FOURCC_LIST) { + /* Unwrap list header. */ + if (fread(&chunk.type, sizeof(chunk.type), 1, f) != 1) return false; + chunk.length -= sizeof(chunk.type); + } + + switch (chunk.type) { + case FOURCC_RGNH: + if (fread(®ion.hdr, sizeof(region.hdr), 1, f) != 1) return false; + break; + + case FOURCC_WSMP: + if (fread(®ion.wave_sample, sizeof(region.wave_sample), 1, f) != 1) return false; + fseek(f, region.wave_sample.cbSize - sizeof(region.wave_sample), SEEK_CUR); + + /* Read all defined sample loops. */ + for (ULONG i = 0; i < region.wave_sample.cSampleLoops; i++) { + WLOOP loop; + if (fread(&loop, sizeof(loop), 1, f) != 1) return false; + region.wave_loops.push_back(loop); + } + break; + + case FOURCC_WLNK: + if (fread(®ion.wave, sizeof(region.wave), 1, f) != 1) return false; + break; + + case FOURCC_LART: // List chunk + if (!this->ReadDLSArticulation(f, chunk.length, region.articulators)) return false; + break; + + case FOURCC_INFO: + /* We don't care about info stuff. */ + fseek(f, chunk.length, SEEK_CUR); + break; + + default: + DEBUG(driver, 7, "DLS: Ignoring unkown chunk %c%c%c%c", (char)(chunk.type & 0xFF), (char)((chunk.type >> 8) & 0xFF), (char)((chunk.type >> 16) & 0xFF), (char)((chunk.type >> 24) & 0xFF)); + fseek(f, chunk.length, SEEK_CUR); + break; + } + } + + return true; +} + +bool DLSFile::ReadDLSRegionList(FILE *f, DWORD list_length, DLSInstrument &instrument) +{ + while (list_length > 0) { + ChunkHeader chunk; + if (fread(&chunk, sizeof(chunk), 1, f) != 1) return false; + list_length -= chunk.length + sizeof(chunk); + + if (chunk.type == FOURCC_LIST) { + FOURCC list_type; + if (fread(&list_type, sizeof(list_type), 1, f) != 1) return false; + + if (list_type == FOURCC_RGN) { + this->ReadDLSRegion(f, chunk.length - sizeof(list_type), instrument.regions); + } else { + DEBUG(driver, 7, "DLS: Ignoring unkown list chunk of type %c%c%c%c", (char)(list_type & 0xFF), (char)((list_type >> 8) & 0xFF), (char)((list_type >> 16) & 0xFF), (char)((list_type >> 24) & 0xFF)); + fseek(f, chunk.length - sizeof(list_type), SEEK_CUR); + } + } else { + DEBUG(driver, 7, "DLS: Ignoring chunk %c%c%c%c", (char)(chunk.type & 0xFF), (char)((chunk.type >> 8) & 0xFF), (char)((chunk.type >> 16) & 0xFF), (char)((chunk.type >> 24) & 0xFF)); + fseek(f, chunk.length, SEEK_CUR); + } + } + + return true; +} + +bool DLSFile::ReadDLSInstrument(FILE *f, DWORD list_length) +{ + this->instruments.push_back(DLSInstrument()); + DLSInstrument &instrument = this->instruments.back(); + + while (list_length > 0) { + ChunkHeader chunk; + if (fread(&chunk, sizeof(chunk), 1, f) != 1) return false; + list_length -= chunk.length + sizeof(chunk); + + if (chunk.type == FOURCC_LIST) { + /* Unwrap list header. */ + if (fread(&chunk.type, sizeof(chunk.type), 1, f) != 1) return false; + chunk.length -= sizeof(chunk.type); + } + + switch (chunk.type) { + case FOURCC_INSH: + if (fread(&instrument.hdr, sizeof(instrument.hdr), 1, f) != 1) return false; + break; + + case FOURCC_LART: // List chunk + if (!this->ReadDLSArticulation(f, chunk.length, instrument.articulators)) return false; + break; + + case FOURCC_LRGN: // List chunk + if (!this->ReadDLSRegionList(f, chunk.length, instrument)) return false; + break; + + case FOURCC_INFO: + /* We don't care about info stuff. */ + fseek(f, chunk.length, SEEK_CUR); + break; + + default: + DEBUG(driver, 7, "DLS: Ignoring unkown chunk %c%c%c%c", (char)(chunk.type & 0xFF), (char)((chunk.type >> 8) & 0xFF), (char)((chunk.type >> 16) & 0xFF), (char)((chunk.type >> 24) & 0xFF)); + fseek(f, chunk.length, SEEK_CUR); + break; + } + } + + return true; +} + +bool DLSFile::ReadDLSInstrumentList(FILE *f, DWORD list_length) +{ + while (list_length > 0) { + ChunkHeader chunk; + if (fread(&chunk, sizeof(chunk), 1, f) != 1) return false; + list_length -= chunk.length + sizeof(chunk); + + if (chunk.type == FOURCC_LIST) { + FOURCC list_type; + if (fread(&list_type, sizeof(list_type), 1, f) != 1) return false; + + if (list_type == FOURCC_INS) { + DEBUG(driver, 6, "DLS: Reading instrument %d", (int)instruments.size()); + + if (!this->ReadDLSInstrument(f, chunk.length - sizeof(list_type))) return false; + } else { + DEBUG(driver, 7, "DLS: Ignoring unkown list chunk of type %c%c%c%c", (char)(list_type & 0xFF), (char)((list_type >> 8) & 0xFF), (char)((list_type >> 16) & 0xFF), (char)((list_type >> 24) & 0xFF)); + fseek(f, chunk.length - sizeof(list_type), SEEK_CUR); + } + } else { + DEBUG(driver, 7, "DLS: Ignoring chunk %c%c%c%c", (char)(chunk.type & 0xFF), (char)((chunk.type >> 8) & 0xFF), (char)((chunk.type >> 16) & 0xFF), (char)((chunk.type >> 24) & 0xFF)); + fseek(f, chunk.length, SEEK_CUR); + } + } + + return true; +} + +bool DLSFile::ReadDLSWave(FILE *f, DWORD list_length, long offset) +{ + this->waves.push_back(DLSWave()); + DLSWave &wave = this->waves.back(); + + /* Set default values. */ + MemSetT(&wave.wave_sample, 0); + wave.wave_sample.cbSize = sizeof(WSMPL); + wave.wave_sample.usUnityNote = 60; + wave.file_offset = offset; // Store file offset so we can resolve the wave pool table later on. + + while (list_length > 0) { + ChunkHeader chunk; + if (fread(&chunk, sizeof(chunk), 1, f) != 1) return false; + list_length -= chunk.length + sizeof(chunk); + + if (chunk.type == FOURCC_LIST) { + /* Unwrap list header. */ + if (fread(&chunk.type, sizeof(chunk.type), 1, f) != 1) return false; + chunk.length -= sizeof(chunk.type); + } + + switch (chunk.type) { + case FOURCC_fmt: + if (fread(&wave.fmt, sizeof(wave.fmt), 1, f) != 1) return false; + if (chunk.length > sizeof(wave.fmt)) fseek(f, chunk.length - sizeof(wave.fmt), SEEK_CUR); + break; + + case FOURCC_WSMP: + if (fread(&wave.wave_sample, sizeof(wave.wave_sample), 1, f) != 1) return false; + fseek(f, wave.wave_sample.cbSize - sizeof(wave.wave_sample), SEEK_CUR); + + /* Read all defined sample loops. */ + for (ULONG i = 0; i < wave.wave_sample.cSampleLoops; i++) { + WLOOP loop; + if (fread(&loop, sizeof(loop), 1, f) != 1) return false; + wave.wave_loops.push_back(loop); + } + break; + + case FOURCC_data: + wave.data.resize(chunk.length); + if (fread(&wave.data[0], sizeof(BYTE), wave.data.size(), f) != wave.data.size()) return false; + break; + + case FOURCC_INFO: + /* We don't care about info stuff. */ + fseek(f, chunk.length, SEEK_CUR); + break; + + default: + DEBUG(driver, 7, "DLS: Ignoring unkown chunk %c%c%c%c", (char)(chunk.type & 0xFF), (char)((chunk.type >> 8) & 0xFF), (char)((chunk.type >> 16) & 0xFF), (char)((chunk.type >> 24) & 0xFF)); + fseek(f, chunk.length, SEEK_CUR); + break; + } + } + + return true; +} + +bool DLSFile::ReadDLSWaveList(FILE *f, DWORD list_length) +{ + long base_offset = ftell(f); + + while (list_length > 0) { + long chunk_offset = ftell(f); + + ChunkHeader chunk; + if (fread(&chunk, sizeof(chunk), 1, f) != 1) return false; + list_length -= chunk.length + sizeof(chunk); + + if (chunk.type == FOURCC_LIST) { + FOURCC list_type; + if (fread(&list_type, sizeof(list_type), 1, f) != 1) return false; + + if (list_type == FOURCC_wave) { + DEBUG(driver, 6, "DLS: Reading wave %d", (int)waves.size()); + + if (!this->ReadDLSWave(f, chunk.length - sizeof(list_type), chunk_offset - base_offset)) return false; + } else { + DEBUG(driver, 7, "DLS: Ignoring unkown list chunk of type %c%c%c%c", (char)(list_type & 0xFF), (char)((list_type >> 8) & 0xFF), (char)((list_type >> 16) & 0xFF), (char)((list_type >> 24) & 0xFF)); + fseek(f, chunk.length - sizeof(list_type), SEEK_CUR); + } + } else { + DEBUG(driver, 7, "DLS: Ignoring chunk %c%c%c%c", (char)(chunk.type & 0xFF), (char)((chunk.type >> 8) & 0xFF), (char)((chunk.type >> 16) & 0xFF), (char)((chunk.type >> 24) & 0xFF)); + fseek(f, chunk.length, SEEK_CUR); + } + } + + return true; +} + +bool DLSFile::LoadFile(const TCHAR *file) +{ + DEBUG(driver, 2, "DMusic: Try to load DLS file %s", FS2OTTD(file)); + + FILE *f = _tfopen(file, _T("rb")); + if (f == NULL) return false; + + FileCloser f_scope(f); + + /* Check DLS file header. */ + ChunkHeader hdr; + FOURCC dls_type; + if (fread(&hdr, sizeof(hdr), 1, f) != 1) return false; + if (fread(&dls_type, sizeof(dls_type), 1, f) != 1) return false; + if (hdr.type != FOURCC_RIFF || dls_type != FOURCC_DLS) return false; + + hdr.length -= sizeof(FOURCC); + + DEBUG(driver, 2, "DMusic: Parsing DLS file"); + + DLSHEADER header; + MemSetT(&header, 0); + + /* Iterate over all chunks in the file. */ + while (hdr.length > 0) { + ChunkHeader chunk; + if (fread(&chunk, sizeof(chunk), 1, f) != 1) return false; + hdr.length -= chunk.length + sizeof(chunk); + + if (chunk.type == FOURCC_LIST) { + /* Unwrap list header. */ + if (fread(&chunk.type, sizeof(chunk.type), 1, f) != 1) return false; + chunk.length -= sizeof(chunk.type); + } + + switch (chunk.type) { + case FOURCC_COLH: + if (fread(&header, sizeof(header), 1, f) != 1) return false; + break; + + case FOURCC_LINS: // List chunk + if (!this->ReadDLSInstrumentList(f, chunk.length)) return false; + break; + + case FOURCC_WVPL: // List chunk + if (!this->ReadDLSWaveList(f, chunk.length)) return false; + break; + + case FOURCC_PTBL: + POOLTABLE ptbl; + if (fread(&ptbl, sizeof(ptbl), 1, f) != 1) return false; + fseek(f, ptbl.cbSize - sizeof(ptbl), SEEK_CUR); + + /* Read all defined cues. */ + for (ULONG i = 0; i < ptbl.cCues; i++) { + POOLCUE cue; + if (fread(&cue, sizeof(cue), 1, f) != 1) return false; + this->pool_cues.push_back(cue); + } + break; + + case FOURCC_INFO: + /* We don't care about info stuff. */ + fseek(f, chunk.length, SEEK_CUR); + break; + + default: + DEBUG(driver, 7, "DLS: Ignoring unkown chunk %c%c%c%c", (char)(chunk.type & 0xFF), (char)((chunk.type >> 8) & 0xFF), (char)((chunk.type >> 16) & 0xFF), (char)((chunk.type >> 24) & 0xFF)); + fseek(f, chunk.length, SEEK_CUR); + break; + } + } + + /* Have we read as many instruments as indicated? */ + if (header.cInstruments != this->instruments.size()) return false; + + /* Resolve wave pool table. */ + for (std::vector::iterator cue = this->pool_cues.begin(); cue != this->pool_cues.end(); cue++) { + std::vector::iterator w = std::find(this->waves.begin(), this->waves.end(), cue->ulOffset); + if (w != this->waves.end()) { + cue->ulOffset = (ULONG)(w - this->waves.begin()); + } else { + cue->ulOffset = 0; + } + } + + return true; +} + + +static byte ScaleVolume(byte original, byte scale) +{ + return original * scale / 127; +} + +static void TransmitChannelMsg(IDirectMusicBuffer *buffer, REFERENCE_TIME rt, byte status, byte p1, byte p2 = 0) +{ + if (buffer->PackStructured(rt, 0, status | (p1 << 8) | (p2 << 16)) == E_OUTOFMEMORY) { + /* Buffer is full, clear it and try again. */ + _port->PlayBuffer(buffer); + buffer->Flush(); + + buffer->PackStructured(rt, 0, status | (p1 << 8) | (p2 << 16)); + } +} + +static void TransmitSysex(IDirectMusicBuffer *buffer, REFERENCE_TIME rt, byte *&msg_start, size_t &remaining) +{ + /* Find end of message. */ + 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) { + /* Buffer is full, clear it and try again. */ + _port->PlayBuffer(buffer); + buffer->Flush(); + + buffer->PackUnstructured(rt, 0, msg_end - msg_start, msg_start); + } + + /* Update position in buffer. */ + remaining -= msg_end - msg_start; + msg_start = msg_end; +} + +static void TransmitSysexConst(IDirectMusicBuffer *buffer, REFERENCE_TIME rt, byte *msg_start, size_t length) +{ + TransmitSysex(buffer, rt, msg_start, length); +} + +/** Transmit 'Note off' messages to all MIDI channels. */ +static void TransmitNotesOff(IDirectMusicBuffer *buffer, REFERENCE_TIME block_time, REFERENCE_TIME cur_time) +{ + for (int ch = 0; ch < 16; ch++) { + TransmitChannelMsg(_buffer, block_time + 10, MIDIST_CONTROLLER | ch, MIDICT_MODE_ALLNOTESOFF, 0); + 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. */ + _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)); +} + +static void MidiThreadProc(void *) +{ + DEBUG(driver, 2, "DMusic: Entering playback thread"); + + REFERENCE_TIME last_volume_time = 0; // timestamp of the last volume change + REFERENCE_TIME block_time = 0; // timestamp of the last block sent to the port + REFERENCE_TIME playback_start_time; // timestamp current file began playback + MidiFile current_file; // file currently being played from + PlaybackSegment current_segment; // segment info for current playback + size_t current_block = 0; // next block index to send + byte current_volume = 0; // current effective volume setting + byte channel_volumes[16]; // last seen volume controller values in raw data + + /* Get pointer to the reference clock of our output port. */ + IReferenceClock *clock; + _port->GetLatencyClock(&clock); + + 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(); + + DWORD next_timeout = 1000; + while (true) { + /* Wait for a signal from the GUI thread or until the time for the next event has come. */ + DWORD wfso = WaitForSingleObject(_thread_event, next_timeout); + + if (_playback.shutdown) { + _playback.playing = false; + break; + } + + if (_playback.do_stop) { + DEBUG(driver, 2, "DMusic thread: Stopping playback"); + + /* Turn all notes off and wait a bit to allow the messages to be handled. */ + clock->GetTime(&cur_time); + TransmitNotesOff(_buffer, block_time, cur_time); + + _playback.playing = false; + _playback.do_stop = false; + block_time = 0; + next_timeout = 1000; + continue; + } + + if (wfso == WAIT_OBJECT_0) { + if (_playback.do_start) { + DEBUG(driver, 2, "DMusic thread: Starting playback"); + { + /* New scope to limit the time the mutex is locked. */ + ThreadMutexLocker lock(_thread_mutex); + + current_file.MoveFrom(_playback.next_file); + std::swap(_playback.next_segment, current_segment); + current_segment.start_block = 0; + current_block = 0; + _playback.playing = true; + _playback.do_start = false; + } + + /* Turn all notes off in case we are seeking between music titles. */ + clock->GetTime(&cur_time); + TransmitNotesOff(_buffer, block_time, cur_time); + + MemSetT(channel_volumes, 127, lengthof(channel_volumes)); + + /* Take the current time plus the preload time as the music start time. */ + clock->GetTime(&playback_start_time); + playback_start_time += _playback.preload_time * MS_TO_REFTIME; + } + } + + if (_playback.playing) { + /* skip beginning of file? */ + if (current_segment.start > 0 && current_block == 0 && 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 */ + size_t preload_bytes = 0; + for (size_t bl = 0; bl < current_file.blocks.size(); bl++) { + MidiFile::DataBlock &block = current_file.blocks[bl]; + preload_bytes += block.data.Length(); + if (block.ticktime >= current_segment.start) { + if (current_segment.loop) { + DEBUG(driver, 2, "DMusic: timer: loop from block %d (ticktime %d, realtime %.3f, bytes %d)", (int)bl, (int)block.ticktime, ((int)block.realtime) / 1000.0, (int)preload_bytes); + current_segment.start_block = bl; + break; + } else { + /* Skip the transmission delay compensation performed in the Win32 MIDI driver. + * The DMusic driver will most likely be used with the MS softsynth, which is not subject to transmission delays. + */ + DEBUG(driver, 2, "DMusic: timer: start from block %d (ticktime %d, realtime %.3f, bytes %d)", (int)bl, (int)block.ticktime, ((int)block.realtime) / 1000.0, (int)preload_bytes); + playback_start_time -= block.realtime * MIDITIME_TO_REFTIME; + break; + } + } + } + } + + /* Get current playback timestamp. */ + REFERENCE_TIME current_time; + clock->GetTime(¤t_time); + + /* Check for volume change. */ + if (current_volume != _playback.new_volume) { + if (current_time - last_volume_time > 10 * MS_TO_REFTIME) { + DEBUG(driver, 2, "DMusic thread: volume change"); + current_volume = _playback.new_volume; + last_volume_time = current_time; + for (int ch = 0; ch < 16; ch++) { + int vol = ScaleVolume(channel_volumes[ch], current_volume); + TransmitChannelMsg(_buffer, block_time + 1, MIDIST_CONTROLLER | ch, MIDICT_CHANVOLUME, vol); + } + _port->PlayBuffer(_buffer); + _buffer->Flush(); + } + } + + while (current_block < current_file.blocks.size()) { + MidiFile::DataBlock &block = current_file.blocks[current_block]; + + /* check that block isn't at end-of-song override */ + if (current_segment.end > 0 && block.ticktime >= current_segment.end) { + if (current_segment.loop) { + DEBUG(driver, 2, "DMusic thread: Looping song"); + current_block = current_segment.start_block; + playback_start_time = current_time - current_file.blocks[current_block].realtime * MIDITIME_TO_REFTIME; + } else { + _playback.do_stop = true; + } + next_timeout = 0; + break; + } + /* check that block is not in the future */ + REFERENCE_TIME playback_time = current_time - playback_start_time; + if (block.realtime * MIDITIME_TO_REFTIME > playback_time + 3 *_playback.preload_time * MS_TO_REFTIME) { + /* Stop the thread loop until we are at the preload time of the next block. */ + next_timeout = Clamp(((int64)block.realtime * MIDITIME_TO_REFTIME - playback_time) / MS_TO_REFTIME - _playback.preload_time, 0, 1000); + DEBUG(driver, 9, "DMusic thread: Next event in %lu ms (music %u, ref " OTTD_PRINTF64 ")", next_timeout, block.realtime * MIDITIME_TO_REFTIME, playback_time); + break; + } + + /* Timestamp of the current block. */ + 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(); + size_t remaining = block.data.Length(); + byte last_status = 0; + while (remaining > 0) { + /* MidiFile ought to have converted everything out of running status, + * but handle it anyway just to be safe */ + byte status = data[0]; + if (status & 0x80) { + last_status = status; + data++; + remaining--; + } else { + status = last_status; + } + switch (status & 0xF0) { + case MIDIST_PROGCHG: + case MIDIST_CHANPRESS: + /* 2 byte channel messages */ + TransmitChannelMsg(_buffer, block_time, status, data[0]); + data++; + remaining--; + break; + case MIDIST_NOTEOFF: + case MIDIST_NOTEON: + case MIDIST_POLYPRESS: + case MIDIST_PITCHBEND: + /* 3 byte channel messages */ + TransmitChannelMsg(_buffer, block_time, status, data[0], data[1]); + data += 2; + remaining -= 2; + break; + case MIDIST_CONTROLLER: + /* controller change */ + if (data[0] == MIDICT_CHANVOLUME) { + /* volume controller, adjust for user volume */ + channel_volumes[status & 0x0F] = data[1]; + int vol = ScaleVolume(data[1], current_volume); + TransmitChannelMsg(_buffer, block_time, status, data[0], vol); + } else { + /* handle other controllers normally */ + TransmitChannelMsg(_buffer, block_time, status, data[0], data[1]); + } + data += 2; + remaining -= 2; + break; + case 0xF0: + /* system messages */ + switch (status) { + case MIDIST_SYSEX: /* system exclusive */ + TransmitSysex(_buffer, block_time, data, remaining); + break; + case MIDIST_TC_QFRAME: /* time code quarter frame */ + case MIDIST_SONGSEL: /* song select */ + data++; + remaining--; + break; + case MIDIST_SONGPOSPTR: /* song position pointer */ + data += 2; + remaining -= 2; + break; + default: /* remaining have no data bytes */ + break; + } + break; + } + } + + current_block++; + } + + /* Anything in the playback buffer? Send it down the port. */ + DWORD used_buffer = 0; + _buffer->GetUsedBytes(&used_buffer); + if (used_buffer > 0) { + _port->PlayBuffer(_buffer); + _buffer->Flush(); + } + + /* end? */ + if (current_block == current_file.blocks.size()) { + if (current_segment.loop) { + current_block = current_segment.start_block; + playback_start_time = block_time - current_file.blocks[current_block].realtime * MIDITIME_TO_REFTIME; + } else { + _playback.do_stop = true; + } + next_timeout = 0; + } + } + } + + DEBUG(driver, 2, "DMusic: Exiting playback thread"); + + /* Turn all notes off and wait a bit to allow the messages to be handled by real hardware. */ + clock->GetTime(&cur_time); + TransmitNotesOff(_buffer, block_time, cur_time); + Sleep(_playback.preload_time * 4); + + clock->Release(); +} + +static void * DownloadArticulationData(int base_offset, void *data, const std::vector &artic) +{ + DMUS_ARTICULATION2 *art = (DMUS_ARTICULATION2 *)data; + art->ulArtIdx = base_offset + 1; + art->ulFirstExtCkIdx = 0; + art->ulNextArtIdx = 0; + + CONNECTIONLIST *con_list = (CONNECTIONLIST *)(art + 1); + con_list->cbSize = sizeof(CONNECTIONLIST); + con_list->cConnections = (ULONG)artic.size(); + MemCpyT((CONNECTION *)(con_list + 1), &artic.front(), artic.size()); + + return (CONNECTION *)(con_list + 1) + artic.size(); +} + +static const char *LoadDefaultDLSFile(const char *user_dls) +{ + DMUS_PORTCAPS caps; + MemSetT(&caps, 0); + caps.dwSize = sizeof(DMUS_PORTCAPS); + _port->GetCaps(&caps); + + /* Nothing to unless it is a synth with instrument download that doesn't come with GM voices by default. */ + if ((caps.dwFlags & (DMUS_PC_DLS | DMUS_PC_DLS2)) != 0 && (caps.dwFlags & DMUS_PC_GMINHARDWARE) == 0) { + DLSFile dls_file; + + if (user_dls == NULL) { + /* Try loading the default GM DLS file stored in the registry. */ + HKEY hkDM; + if (SUCCEEDED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\Microsoft\\DirectMusic"), 0, KEY_READ, &hkDM))) { + TCHAR dls_path[MAX_PATH]; + DWORD buf_size = sizeof(dls_path); // Buffer size as to be given in bytes! + if (SUCCEEDED(RegQueryValueEx(hkDM, _T("GMFilePath"), NULL, NULL, (LPBYTE)dls_path, &buf_size))) { + TCHAR expand_path[MAX_PATH * 2]; + ExpandEnvironmentStrings(dls_path, expand_path, lengthof(expand_path)); + if (!dls_file.LoadFile(expand_path)) DEBUG(driver, 1, "Failed to load default GM DLS file from registry"); + } + RegCloseKey(hkDM); + } + + /* If we couldn't load the file from the registry, try again at the default install path of the GM DLS file. */ + if (dls_file.instruments.size() == 0) { + static const TCHAR *DLS_GM_FILE = _T("%windir%\\System32\\drivers\\gm.dls"); + TCHAR path[MAX_PATH]; + ExpandEnvironmentStrings(DLS_GM_FILE, path, lengthof(path)); + + if (!dls_file.LoadFile(path)) return "Can't load GM DLS collection"; + } + } else { + if (!dls_file.LoadFile(OTTD2FS(user_dls))) return "Can't load GM DLS collection"; + } + + /* Get download port and allocate download IDs. */ + IDirectMusicPortDownload *download_port = NULL; + if (FAILED(_port->QueryInterface(IID_IDirectMusicPortDownload, (LPVOID *)&download_port))) return "Can't get download port"; + + DWORD dlid_wave = 0, dlid_inst = 0; + if (FAILED(download_port->GetDLId(&dlid_wave, (DWORD)dls_file.waves.size())) || FAILED(download_port->GetDLId(&dlid_inst, (DWORD)dls_file.instruments.size()))) { + download_port->Release(); + return "Can't get enough DLS ids"; + } + + DWORD dwAppend = 0; + download_port->GetAppend(&dwAppend); + + /* Download wave data. */ + for (DWORD i = 0; i < dls_file.waves.size(); i++) { + IDirectMusicDownload *dl_wave = NULL; + if (FAILED(download_port->AllocateBuffer((DWORD)(sizeof(WAVE_DOWNLOAD) + dwAppend * dls_file.waves[i].fmt.wf.nBlockAlign + dls_file.waves[i].data.size()), &dl_wave))) { + download_port->Release(); + return "Can't allocate wave download buffer"; + } + + WAVE_DOWNLOAD *wave; + DWORD wave_size = 0; + if (FAILED(dl_wave->GetBuffer((LPVOID *)&wave, &wave_size))) { + dl_wave->Release(); + download_port->Release(); + return "Can't get wave download buffer"; + } + + /* Fill download data. */ + MemSetT(wave, 0); + wave->dlInfo.dwDLType = DMUS_DOWNLOADINFO_WAVE; + wave->dlInfo.cbSize = wave_size; + wave->dlInfo.dwDLId = dlid_wave + i; + wave->dlInfo.dwNumOffsetTableEntries = 2; + wave->ulOffsetTable[0] = offsetof(WAVE_DOWNLOAD, dmWave); + wave->ulOffsetTable[1] = offsetof(WAVE_DOWNLOAD, dmWaveData); + wave->dmWave.ulWaveDataIdx = 1; + MemCpyT((PCMWAVEFORMAT *)&wave->dmWave.WaveformatEx, &dls_file.waves[i].fmt, 1); + wave->dmWaveData.cbSize = (DWORD)dls_file.waves[i].data.size(); + MemCpyT(wave->dmWaveData.byData, &dls_file.waves[i].data[0], dls_file.waves[i].data.size()); + + _dls_downloads.push_back(dl_wave); + if (FAILED(download_port->Download(dl_wave))) { + download_port->Release(); + return "Downloading DLS wave failed"; + } + } + + /* Download instrument data. */ + for (DWORD i = 0; i < dls_file.instruments.size(); i++) { + DWORD offsets = 1 + (DWORD)dls_file.instruments[i].regions.size(); + + /* Calculate download size for the instrument. */ + size_t i_size = sizeof(DMUS_DOWNLOADINFO) + sizeof(DMUS_INSTRUMENT); + if (dls_file.instruments[i].articulators.size() > 0) { + /* Articulations are stored as two chunks, one containing meta data and one with the actual articulation data. */ + offsets += 2; + i_size += sizeof(DMUS_ARTICULATION2) + sizeof(CONNECTIONLIST) + sizeof(CONNECTION) * dls_file.instruments[i].articulators.size(); + } + + for (std::vector::iterator rgn = dls_file.instruments[i].regions.begin(); rgn != dls_file.instruments[i].regions.end(); rgn++) { + if (rgn->articulators.size() > 0) { + offsets += 2; + i_size += sizeof(DMUS_ARTICULATION2) + sizeof(CONNECTIONLIST) + sizeof(CONNECTION) * rgn->articulators.size(); + } + + /* Region size depends on the number of wave loops. The size of the + * declared structure already accounts for one loop. */ + if (rgn->wave_sample.cbSize != 0) { + i_size += sizeof(DMUS_REGION) - sizeof(DMUS_REGION::WLOOP) + sizeof(WLOOP) * rgn->wave_loops.size(); + } else { + i_size += sizeof(DMUS_REGION) - sizeof(DMUS_REGION::WLOOP) + sizeof(WLOOP) * dls_file.waves[dls_file.pool_cues[rgn->wave.ulTableIndex].ulOffset].wave_loops.size(); + } + } + + i_size += offsets * sizeof(ULONG); + + /* Allocate download buffer. */ + IDirectMusicDownload *dl_inst = NULL; + if (FAILED(download_port->AllocateBuffer((DWORD)i_size, &dl_inst))) { + download_port->Release(); + return "Can't allocate instrument download buffer"; + } + + void *instrument; + DWORD inst_size = 0; + if (FAILED(dl_inst->GetBuffer((LPVOID *)&instrument, &inst_size))) { + dl_inst->Release(); + download_port->Release(); + return "Can't get instrument download buffer"; + } + char *inst_base = (char *)instrument; + + /* Fill download header. */ + DMUS_DOWNLOADINFO *d_info = (DMUS_DOWNLOADINFO *)instrument; + d_info->dwDLType = DMUS_DOWNLOADINFO_INSTRUMENT2; + d_info->cbSize = inst_size; + d_info->dwDLId = dlid_inst + i; + d_info->dwNumOffsetTableEntries = offsets; + instrument = d_info + 1; + + /* Download offset table; contains the offsets of all chunks relative to the buffer start. */ + ULONG *offset_table = (ULONG *)instrument; + instrument = offset_table + offsets; + int last_offset = 0; + + /* Instrument header. */ + DMUS_INSTRUMENT *inst_data = (DMUS_INSTRUMENT *)instrument; + MemSetT(inst_data, 0); + offset_table[last_offset++] = (char *)inst_data - inst_base; + inst_data->ulPatch = (dls_file.instruments[i].hdr.Locale.ulBank & F_INSTRUMENT_DRUMS) | ((dls_file.instruments[i].hdr.Locale.ulBank & 0x7F7F) << 8) | (dls_file.instruments[i].hdr.Locale.ulInstrument & 0x7F); + instrument = inst_data + 1; + + /* Write global articulations. */ + if (dls_file.instruments[i].articulators.size() > 0) { + inst_data->ulGlobalArtIdx = last_offset; + offset_table[last_offset++] = (char *)instrument - inst_base; + offset_table[last_offset++] = (char *)instrument + sizeof(DMUS_ARTICULATION2) - inst_base; + + instrument = DownloadArticulationData(inst_data->ulGlobalArtIdx, instrument, dls_file.instruments[i].articulators); + assert((char *)instrument - inst_base <= (ptrdiff_t)inst_size); + } + + /* Write out regions. */ + inst_data->ulFirstRegionIdx = last_offset; + for (uint j = 0; j < dls_file.instruments[i].regions.size(); j++) { + DLSFile::DLSRegion &rgn = dls_file.instruments[i].regions[j]; + + DMUS_REGION *inst_region = (DMUS_REGION *)instrument; + offset_table[last_offset++] = (char *)inst_region - inst_base; + inst_region->RangeKey = rgn.hdr.RangeKey; + inst_region->RangeVelocity = rgn.hdr.RangeVelocity; + inst_region->fusOptions = rgn.hdr.fusOptions; + inst_region->usKeyGroup = rgn.hdr.usKeyGroup; + inst_region->ulFirstExtCkIdx = 0; + + ULONG wave_id = dls_file.pool_cues[rgn.wave.ulTableIndex].ulOffset; + inst_region->WaveLink = rgn.wave; + inst_region->WaveLink.ulTableIndex = wave_id + dlid_wave; + + /* The wave sample data will be taken from the region, if defined, otherwise from the wave itself. */ + if (rgn.wave_sample.cbSize != 0) { + inst_region->WSMP = rgn.wave_sample; + if (rgn.wave_loops.size() > 0) MemCpyT(inst_region->WLOOP, &rgn.wave_loops.front(), rgn.wave_loops.size()); + + instrument = (char *)(inst_region + 1) - sizeof(DMUS_REGION::WLOOP) + sizeof(WLOOP) * rgn.wave_loops.size(); + } else { + inst_region->WSMP = rgn.wave_sample; + if (dls_file.waves[wave_id].wave_loops.size() > 0) MemCpyT(inst_region->WLOOP, &dls_file.waves[wave_id].wave_loops.front(), dls_file.waves[wave_id].wave_loops.size()); + + instrument = (char *)(inst_region + 1) - sizeof(DMUS_REGION::WLOOP) + sizeof(WLOOP) * dls_file.waves[wave_id].wave_loops.size(); + } + + /* Write local articulator data. */ + if (rgn.articulators.size() > 0) { + inst_region->ulRegionArtIdx = last_offset; + offset_table[last_offset++] = (char *)instrument - inst_base; + offset_table[last_offset++] = (char *)instrument + sizeof(DMUS_ARTICULATION2) - inst_base; + + instrument = DownloadArticulationData(inst_region->ulRegionArtIdx, instrument, rgn.articulators); + } else { + inst_region->ulRegionArtIdx = 0; + } + assert((char *)instrument - inst_base <= (ptrdiff_t)inst_size); + + /* Link to the next region unless this was the last one.*/ + inst_region->ulNextRegionIdx = j < dls_file.instruments[i].regions.size() - 1 ? last_offset : 0; + } + + _dls_downloads.push_back(dl_inst); + if (FAILED(download_port->Download(dl_inst))) { + download_port->Release(); + return "Downloading DLS instrument failed"; + } + } + + download_port->Release(); + } + + return NULL; +} const char *MusicDriver_DMusic::Start(const char * const *parm) { - if (performance != NULL) return NULL; - - if (proc.CoCreateInstance == NULL) { - if (!LoadLibraryList((Function*)&proc, ole_files)) { - return "ole32.dll load failed"; - } - } - /* Initialize COM */ - if (FAILED(proc.CoInitialize(NULL))) { - return "COM initialization failed"; - } + if (FAILED(CoInitializeEx(NULL, COINITBASE_MULTITHREADED))) return "COM initialization failed"; - /* create the performance object */ - if (FAILED(proc.CoCreateInstance( - CLSID_DirectMusicPerformance, + /* Create the DirectMusic object */ + if (FAILED(CoCreateInstance( + CLSID_DirectMusic, NULL, CLSCTX_INPROC, - IID_IDirectMusicPerformance, - (LPVOID*)&performance + IID_IDirectMusic, + (LPVOID*)&_music ))) { - return "Failed to create the performance object"; + return "Failed to create the music object"; } - /* initialize it */ - if (FAILED(performance->Init(&music, NULL, NULL))) { - return "Failed to initialize performance object"; - } + /* Assign sound output device. */ + if (FAILED(_music->SetDirectSound(NULL, NULL))) return "Can't set DirectSound interface"; - int port = GetDriverParamInt(parm, "port", -1); + /* MIDI events need to be send to the synth in time before their playback time + * has come. By default, we try send any events at least 50 ms before playback. */ + _playback.preload_time = GetDriverParamInt(parm, "preload", 50); + int pIdx = GetDriverParamInt(parm, "port", -1); if (_debug_driver_level > 0) { /* Print all valid output ports. */ char desc[DMUS_MAX_DESCRIPTION]; @@ -108,69 +1121,56 @@ const char *MusicDriver_DMusic::Start(const char * const *parm) caps.dwSize = sizeof(DMUS_PORTCAPS); DEBUG(driver, 1, "Detected DirectMusic ports:"); - for (int i = 0; music->EnumPort(i, &caps) == S_OK; i++) { + for (int i = 0; _music->EnumPort(i, &caps) == S_OK; i++) { if (caps.dwClass == DMUS_PC_OUTPUTCLASS) { /* Description is UNICODE even for ANSI build. */ - DEBUG(driver, 1, " %d: %s%s", i, convert_from_fs(caps.wszDescription, desc, lengthof(desc)), i == port ? " (selected)" : ""); + DEBUG(driver, 1, " %d: %s%s", i, convert_from_fs(caps.wszDescription, desc, lengthof(desc)), i == pIdx ? " (selected)" : ""); } } } - IDirectMusicPort *music_port = NULL; // NULL means 'use default port'. - - if (port >= 0) { + GUID guidPort; + if (pIdx >= 0) { /* Check if the passed port is a valid port. */ DMUS_PORTCAPS caps; MemSetT(&caps, 0); caps.dwSize = sizeof(DMUS_PORTCAPS); - if (FAILED(music->EnumPort(port, &caps))) return "Supplied port parameter is not a valid port"; + if (FAILED(_music->EnumPort(pIdx, &caps))) return "Supplied port parameter is not a valid port"; if (caps.dwClass != DMUS_PC_OUTPUTCLASS) return "Supplied port parameter is not an output port"; - - /* Create new port. */ - DMUS_PORTPARAMS params; - MemSetT(¶ms, 0); - params.dwSize = sizeof(DMUS_PORTPARAMS); - params.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS; - params.dwChannelGroups = 1; - - if (FAILED(music->CreatePort(caps.guidPort, ¶ms, &music_port, NULL))) { - return "Failed to create port"; - } - - /* Activate port. */ - if (FAILED(music_port->Activate(TRUE))) { - music_port->Release(); - return "Failed to activate port"; - } + guidPort = caps.guidPort; + } else { + if (FAILED(_music->GetDefaultPort(&guidPort))) return "Can't query default music port"; } - /* Add port to performance. */ - if (FAILED(performance->AddPort(music_port))) { - if (music_port != NULL) music_port->Release(); - return "AddPort failed"; - } + /* Create new port. */ + DMUS_PORTPARAMS params; + MemSetT(¶ms, 0); + params.dwSize = sizeof(DMUS_PORTPARAMS); + params.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS; + params.dwChannelGroups = 1; + if (FAILED(_music->CreatePort(guidPort, ¶ms, &_port, NULL))) return "Failed to create port"; + /* Activate port. */ + if (FAILED(_port->Activate(TRUE))) return "Failed to activate port"; - /* Assign a performance channel block to the performance if we added - * a custom port to the performance. */ - if (music_port != NULL) { - if (FAILED(performance->AssignPChannelBlock(0, music_port, 1))) { - music_port->Release(); - return "Failed to assign PChannel block"; - } - /* We don't need the port anymore. */ - music_port->Release(); - } + /* Create playback buffer. */ + DMUS_BUFFERDESC desc; + MemSetT(&desc, 0); + desc.dwSize = sizeof(DMUS_BUFFERDESC); + desc.guidBufferFormat = KSDATAFORMAT_SUBTYPE_DIRECTMUSIC; + desc.cbBuffer = 1024; + if (FAILED(_music->CreateMusicBuffer(&desc, &_buffer, NULL))) return "Failed to create music buffer"; - /* create the loader object; this will be used to load the MIDI file */ - if (FAILED(proc.CoCreateInstance( - CLSID_DirectMusicLoader, - NULL, - CLSCTX_INPROC, - IID_IDirectMusicLoader, - (LPVOID*)&loader - ))) { - return "Failed to create loader object"; - } + /* On soft-synths (e.g. the default DirectMusic one), we might need to load a wavetable set to get music. */ + const char *dls = LoadDefaultDLSFile(GetDriverParam(parm, "dls")); + if (dls != NULL) return dls; + + /* Create playback thread and synchronization primitives. */ + _thread_event = CreateEvent(NULL, FALSE, FALSE, NULL); + if (_thread_event == NULL) return "Can't create thread shutdown event"; + _thread_mutex = ThreadMutex::New(); + if (_thread_mutex == NULL) return "Can't create thread mutex"; + + if (!ThreadObject::New(&MidiThreadProc, this, &_dmusic_thread, "ottd:dmusic")) return "Can't create MIDI output thread"; return NULL; } @@ -184,114 +1184,82 @@ MusicDriver_DMusic::~MusicDriver_DMusic() void MusicDriver_DMusic::Stop() { - seeking = false; - - if (performance != NULL) performance->Stop(NULL, NULL, 0, 0); - - if (segment != NULL) { - segment->SetParam(GUID_Unload, 0xFFFFFFFF, 0, 0, performance); - segment->Release(); - segment = NULL; + if (_dmusic_thread != NULL) { + _playback.shutdown = true; + SetEvent(_thread_event); + _dmusic_thread->Join(); } - if (music != NULL) { - music->Release(); - music = NULL; + /* Unloaded any instruments we loaded. */ + if (_dls_downloads.size() > 0) { + IDirectMusicPortDownload *download_port = NULL; + _port->QueryInterface(IID_IDirectMusicPortDownload, (LPVOID *)&download_port); + + /* Instruments refer to waves. As the waves are at the beginning of the download list, + * do the unload from the back so that references are cleared properly. */ + for (std::vector::reverse_iterator i = _dls_downloads.rbegin(); download_port != NULL && i != _dls_downloads.rend(); i++) { + download_port->Unload(*i); + (*i)->Release(); + } + _dls_downloads.clear(); + + if (download_port != NULL) download_port->Release(); } - if (performance != NULL) { - performance->CloseDown(); - performance->Release(); - performance = NULL; + if (_buffer != NULL) { + _buffer->Release(); + _buffer = NULL; } - if (loader != NULL) { - loader->Release(); - loader = NULL; + if (_port != NULL) { + _port->Activate(FALSE); + _port->Release(); + _port = NULL; } - proc.CoUninitialize(); + if (_music != NULL) { + _music->Release(); + _music = NULL; + } + + CloseHandle(_thread_event); + delete _thread_mutex; + + CoUninitialize(); } -void MusicDriver_DMusic::PlaySong(const char *filename) +void MusicDriver_DMusic::PlaySong(const MusicSongInfo &song) { - /* set up the loader object info */ - DMUS_OBJECTDESC obj_desc; - ZeroMemory(&obj_desc, sizeof(obj_desc)); - obj_desc.dwSize = sizeof(obj_desc); - obj_desc.guidClass = CLSID_DirectMusicSegment; - obj_desc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH; - MultiByteToWideChar( - CP_ACP, MB_PRECOMPOSED, - filename, -1, - obj_desc.wszFileName, lengthof(obj_desc.wszFileName) - ); + ThreadMutexLocker lock(_thread_mutex); - /* release the existing segment if we have any */ - if (segment != NULL) { - segment->Release(); - segment = NULL; - } + if (!_playback.next_file.LoadSong(song)) return; - /* make a new segment */ - if (FAILED(loader->GetObject( - &obj_desc, IID_IDirectMusicSegment, (LPVOID*)&segment - ))) { - DEBUG(driver, 0, "DirectMusic: GetObject failed"); - return; - } + _playback.next_segment.start = song.override_start; + _playback.next_segment.end = song.override_end; + _playback.next_segment.loop = song.loop; - /* tell the segment what kind of data it contains */ - if (FAILED(segment->SetParam( - GUID_StandardMIDIFile, 0xFFFFFFFF, 0, 0, performance - ))) { - DEBUG(driver, 0, "DirectMusic: SetParam (MIDI file) failed"); - return; - } - - /* tell the segment to 'download' the instruments */ - if (FAILED(segment->SetParam(GUID_Download, 0xFFFFFFFF, 0, 0, performance))) { - DEBUG(driver, 0, "DirectMusic: failed to download instruments"); - return; - } - - /* start playing the MIDI file */ - if (FAILED(performance->PlaySegment(segment, 0, 0, NULL))) { - DEBUG(driver, 0, "DirectMusic: PlaySegment failed"); - return; - } - - seeking = true; + _playback.do_start = true; + SetEvent(_thread_event); } void MusicDriver_DMusic::StopSong() { - if (FAILED(performance->Stop(segment, NULL, 0, 0))) { - DEBUG(driver, 0, "DirectMusic: StopSegment failed"); - } - seeking = false; + _playback.do_stop = true; + SetEvent(_thread_event); } bool MusicDriver_DMusic::IsSongPlaying() { - /* Not the nicest code, but there is a short delay before playing actually - * starts. OpenTTD makes no provision for this. */ - if (performance->IsPlaying(segment, NULL) == S_OK) { - seeking = false; - return true; - } else { - return seeking; - } + return _playback.playing || _playback.do_start; } void MusicDriver_DMusic::SetVolume(byte vol) { - long db = vol * 2000 / 127 - 2000; ///< 0 - 127 -> -2000 - 0 - performance->SetGlobalParam(GUID_PerfMasterVolume, &db, sizeof(db)); + _playback.new_volume = vol; } diff --git a/src/music/dmusic.h b/src/music/dmusic.h index 7287623e48..527e064e49 100644 --- a/src/music/dmusic.h +++ b/src/music/dmusic.h @@ -23,7 +23,7 @@ public: /* virtual */ void Stop(); - /* virtual */ void PlaySong(const char *filename); + /* virtual */ void PlaySong(const MusicSongInfo &song); /* virtual */ void StopSong(); diff --git a/src/music/extmidi.cpp b/src/music/extmidi.cpp index d39a050f6c..9d07761b73 100644 --- a/src/music/extmidi.cpp +++ b/src/music/extmidi.cpp @@ -17,6 +17,8 @@ #include "../video/video_driver.hpp" #include "../gfx_func.h" #include "extmidi.h" +#include "../base_media_base.h" +#include "midifile.hpp" #include #include #include @@ -83,10 +85,13 @@ void MusicDriver_ExtMidi::Stop() this->DoStop(); } -void MusicDriver_ExtMidi::PlaySong(const char *filename) +void MusicDriver_ExtMidi::PlaySong(const MusicSongInfo &song) { - strecpy(this->song, filename, lastof(this->song)); - this->DoStop(); + std::string filename = MidiFile::GetSMFFile(song); + if (!filename.empty()) { + strecpy(this->song, filename.c_str(), lastof(this->song)); + this->DoStop(); + } } void MusicDriver_ExtMidi::StopSong() diff --git a/src/music/extmidi.h b/src/music/extmidi.h index cfbd894596..e174dc9b08 100644 --- a/src/music/extmidi.h +++ b/src/music/extmidi.h @@ -28,7 +28,7 @@ public: /* virtual */ void Stop(); - /* virtual */ void PlaySong(const char *filename); + /* virtual */ void PlaySong(const MusicSongInfo &song); /* virtual */ void StopSong(); diff --git a/src/music/libtimidity.cpp b/src/music/libtimidity.cpp index 1cb2adc0f9..42c1e3c155 100644 --- a/src/music/libtimidity.cpp +++ b/src/music/libtimidity.cpp @@ -14,6 +14,8 @@ #include "../sound_type.h" #include "../debug.h" #include "libtimidity.h" +#include "midifile.hpp" +#include "../base_media_base.h" #include #include #include @@ -22,9 +24,6 @@ #include #include #include -#if defined(PSP) -#include -#endif /* PSP */ #include "../safeguards.h" @@ -44,16 +43,6 @@ static struct { uint32 song_position; } _midi; ///< Metadata about the midi we're playing. -#if defined(PSP) -static void AudioOutCallback(void *buf, unsigned int _reqn, void *userdata) -{ - memset(buf, 0, _reqn * PSP_NUM_AUDIO_CHANNELS); - if (_midi.status == MIDI_PLAYING) { - mid_song_read_wave(_midi.song, buf, _reqn * PSP_NUM_AUDIO_CHANNELS); - } -} -#endif /* PSP */ - /** Factory for the libtimidity driver. */ static FMusicDriver_LibTimidity iFMusicDriver_LibTimidity; @@ -75,17 +64,7 @@ const char *MusicDriver_LibTimidity::Start(const char * const *param) _midi.options.rate = 44100; _midi.options.format = MID_AUDIO_S16LSB; _midi.options.channels = 2; -#if defined(PSP) - _midi.options.buffer_size = PSP_NUM_AUDIO_SAMPLES; -#else _midi.options.buffer_size = _midi.options.rate; -#endif - -#if defined(PSP) - pspAudioInit(); - pspAudioSetChannelCallback(_midi.options.channels, &AudioOutCallback, NULL); - pspAudioSetVolume(_midi.options.channels, PSP_VOLUME_MAX, PSP_VOLUME_MAX); -#endif /* PSP */ return NULL; } @@ -96,11 +75,14 @@ void MusicDriver_LibTimidity::Stop() mid_exit(); } -void MusicDriver_LibTimidity::PlaySong(const char *filename) +void MusicDriver_LibTimidity::PlaySong(const MusicSongInfo &song) { - this->StopSong(); + std::string filename = MidiFile::GetSMFFile(song); - _midi.stream = mid_istream_open_file(filename); + this->StopSong(); + if (filename.empty()) return; + + _midi.stream = mid_istream_open_file(filename.c_str()); if (_midi.stream == NULL) { DEBUG(driver, 0, "Could not open music file"); return; diff --git a/src/music/libtimidity.h b/src/music/libtimidity.h index abe17e7703..badb05bab2 100644 --- a/src/music/libtimidity.h +++ b/src/music/libtimidity.h @@ -21,7 +21,7 @@ public: /* virtual */ void Stop(); - /* virtual */ void PlaySong(const char *filename); + /* virtual */ void PlaySong(const MusicSongInfo &song); /* virtual */ void StopSong(); diff --git a/src/music/midi.h b/src/music/midi.h new file mode 100644 index 0000000000..473f7f18bb --- /dev/null +++ b/src/music/midi.h @@ -0,0 +1,144 @@ +/* $Id$ */ + +/* +* This file is part of OpenTTD. +* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. +* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . +*/ + +/* @file midi.h Declarations for MIDI data */ + +#ifndef MUSIC_MIDI_H +#define MUSIC_MIDI_H + +#include "../stdafx.h" + +/** Header of a Stanard MIDI File */ +struct SMFHeader { + uint16 format; + uint16 tracks; + uint16 tickdiv; +}; + +/** MIDI status byte codes */ +enum MidiStatus { + /* Bytes with top bit unset are data bytes i.e. not status bytes */ + /* Channel status messages, require channel number in lower nibble */ + MIDIST_NOTEOFF = 0x80, + MIDIST_NOTEON = 0x90, + MIDIST_POLYPRESS = 0xA0, + MIDIST_CONTROLLER = 0xB0, + MIDIST_PROGCHG = 0xC0, + MIDIST_CHANPRESS = 0xD0, + MIDIST_PITCHBEND = 0xE0, + /* Full byte status messages */ + MIDIST_SYSEX = 0xF0, + MIDIST_TC_QFRAME = 0xF1, + MIDIST_SONGPOSPTR = 0xF2, + MIDIST_SONGSEL = 0xF3, + /* not defined: 0xF4, */ + /* not defined: 0xF5, */ + MIDIST_TUNEREQ = 0xF6, + MIDIST_ENDSYSEX = 0xF7, ///< only occurs in realtime data + MIDIST_SMF_ESCAPE = 0xF7, ///< only occurs in SMF data + MIDIST_RT_CLOCK = 0xF8, + /* not defined: 0xF9, */ + MIDIST_RT_START = 0xFA, + MIDIST_RT_CONTINUE = 0xFB, + MIDIST_RT_STOP = 0xFC, + /* not defined: 0xFD, */ + MIDIST_RT_ACTSENS = 0xFE, + MIDIST_SYSRESET = 0xFF, ///< only occurs in realtime data + MIDIST_SMF_META = 0xFF, ///< only occurs in SMF data +}; + +/** + * MIDI controller numbers. + * Complete list per General MIDI, missing values are not defined. + */ +enum MidiController { + /* Standard continuous controllers (MSB control) */ + MIDICT_BANKSELECT = 0, + MIDICT_MODWHEEL = 1, + MIDICT_BREATH = 2, + MIDICT_FOOT = 4, + MIDICT_PORTAMENTO = 5, + MIDICT_DATAENTRY = 6, + MIDICT_CHANVOLUME = 7, + MIDICT_BALANCE = 8, + MIDICT_PAN = 10, + MIDICT_EXPRESSION = 11, + MIDICT_EFFECT1 = 12, + MIDICT_EFFECT2 = 13, + MIDICT_GENERAL1 = 16, + MIDICT_GENERAL2 = 17, + MIDICT_GENERAL3 = 18, + MIDICT_GENERAL4 = 19, + /* Offset from MSB to LSB of continuous controllers */ + MIDICTOFS_HIGHRES = 32, + /* Stanard continuous controllers (LSB control) */ + MIDICT_BANKSELECT_LO = MIDICTOFS_HIGHRES + MIDICT_BANKSELECT, + MIDICT_MODWHEEL_LO = MIDICTOFS_HIGHRES + MIDICT_MODWHEEL, + MIDICT_BREATH_LO = MIDICTOFS_HIGHRES + MIDICT_BREATH, + MIDICT_FOOT_LO = MIDICTOFS_HIGHRES + MIDICT_FOOT, + MIDICT_PORTAMENTO_LO = MIDICTOFS_HIGHRES + MIDICT_PORTAMENTO, + MIDICT_DATAENTRY_LO = MIDICTOFS_HIGHRES + MIDICT_DATAENTRY, + MIDICT_CHANVOLUME_LO = MIDICTOFS_HIGHRES + MIDICT_CHANVOLUME, + MIDICT_BALANCE_LO = MIDICTOFS_HIGHRES + MIDICT_BALANCE, + MIDICT_PAN_LO = MIDICTOFS_HIGHRES + MIDICT_PAN, + MIDICT_EXPRESSION_LO = MIDICTOFS_HIGHRES + MIDICT_EXPRESSION, + MIDICT_EFFECT1_LO = MIDICTOFS_HIGHRES + MIDICT_EFFECT1, + MIDICT_EFFECT2_LO = MIDICTOFS_HIGHRES + MIDICT_EFFECT2, + MIDICT_GENERAL1_LO = MIDICTOFS_HIGHRES + MIDICT_GENERAL1, + MIDICT_GENERAL2_LO = MIDICTOFS_HIGHRES + MIDICT_GENERAL2, + MIDICT_GENERAL3_LO = MIDICTOFS_HIGHRES + MIDICT_GENERAL3, + MIDICT_GENERAL4_LO = MIDICTOFS_HIGHRES + MIDICT_GENERAL4, + /* Switch controllers */ + MIDICT_SUSTAINSW = 64, + MIDICT_PORTAMENTOSW = 65, + MIDICT_SOSTENUTOSW = 66, + MIDICT_SOFTPEDALSW = 67, + MIDICT_LEGATOSW = 68, + MIDICT_HOLD2SW = 69, + /* Standard low-resolution controllers */ + MIDICT_SOUND1 = 70, + MIDICT_SOUND2 = 71, + MIDICT_SOUND3 = 72, + MIDICT_SOUND4 = 73, + MIDICT_SOUND5 = 74, + MIDICT_SOUND6 = 75, + MIDICT_SOUND7 = 76, + MIDICT_SOUND8 = 77, + MIDICT_SOUND9 = 78, + MIDICT_SOUND10 = 79, + MIDICT_GENERAL5 = 80, + MIDICT_GENERAL6 = 81, + MIDICT_GENERAL7 = 82, + MIDICT_GENERAL8 = 83, + MIDICT_PORTAMENTOCTL = 84, + MIDICT_PRF_HIGHRESVEL = 88, + MIDICT_EFFECTS1 = 91, + MIDICT_EFFECTS2 = 92, + MIDICT_EFFECTS3 = 93, + MIDICT_EFFECTS4 = 94, + MIDICT_EFFECTS5 = 95, + /* Registered/unregistered parameters control */ + MIDICT_DATA_INCREMENT = 96, + MIDICT_DATA_DECREMENT = 97, + MIDICT_NRPN_SELECT_LO = 98, + MIDICT_NRPN_SELECT_HI = 99, + MIDICT_RPN_SELECT_LO = 100, + MIDICT_RPN_SELECT_HI = 101, + /* Channel mode messages */ + MIDICT_MODE_ALLSOUNDOFF = 120, + MIDICT_MODE_RESETALLCTRL = 121, + MIDICT_MODE_LOCALCTL = 122, + MIDICT_MODE_ALLNOTESOFF = 123, + MIDICT_MODE_OMNI_OFF = 124, + MIDICT_MODE_OMNI_ON = 125, + MIDICT_MODE_MONO = 126, + MIDICT_MODE_POLY = 127, +}; + +#endif /* MUSIC_MIDI_H */ diff --git a/src/music/midifile.cpp b/src/music/midifile.cpp new file mode 100644 index 0000000000..688538db9b --- /dev/null +++ b/src/music/midifile.cpp @@ -0,0 +1,1118 @@ +/* $Id$ */ + +/* +* This file is part of OpenTTD. +* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. +* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . +*/ + +/* @file midifile.cpp Parser for standard MIDI files */ + +#include "midifile.hpp" +#include "../fileio_func.h" +#include "../fileio_type.h" +#include "../string_func.h" +#include "../core/endian_func.hpp" +#include "../base_media_base.h" +#include "midi.h" +#include + +#include "../console_func.h" +#include "../console_internal.h" + + +/* SMF reader based on description at: http://www.somascape.org/midi/tech/mfile.html */ + + +static MidiFile *_midifile_instance = NULL; + +/** + * Owning byte buffer readable as a stream. + * RAII-compliant to make teardown in error situations easier. + */ +class ByteBuffer { + byte *buf; + size_t buflen; + size_t pos; +public: + /** + * Construct buffer from data in a file. + * If file does not have sufficient bytes available, the object is constructed + * in an error state, that causes all further function calls to fail. + * @param file file to read from at current position + * @param len number of bytes to read + */ + ByteBuffer(FILE *file, size_t len) + { + this->buf = MallocT(len); + if (fread(this->buf, 1, len, file) == len) { + this->buflen = len; + this->pos = 0; + } else { + /* invalid state */ + this->buflen = 0; + } + } + + /** + * Destructor, frees the buffer. + */ + ~ByteBuffer() + { + free(this->buf); + } + + /** + * Return whether the buffer was constructed successfully. + * @return true is the buffer contains data + */ + bool IsValid() const + { + return this->buflen > 0; + } + + /** + * Return whether reading has reached the end of the buffer. + * @return true if there are no more bytes available to read + */ + bool IsEnd() const + { + return this->pos >= this->buflen; + } + + /** + * Read a single byte from the buffer. + * @param[out] b returns the read value + * @return true if a byte was available for reading + */ + bool ReadByte(byte &b) + { + if (this->IsEnd()) return false; + b = this->buf[this->pos++]; + return true; + } + + /** + * Read a MIDI file variable length value. + * Each byte encodes 7 bits of the value, most-significant bits are encoded first. + * If the most significant bit in a byte is set, there are further bytes encoding the value. + * @param[out] res returns the read value + * @return true if there was data available + */ + bool ReadVariableLength(uint32 &res) + { + res = 0; + byte b = 0; + do { + if (this->IsEnd()) return false; + b = this->buf[this->pos++]; + res = (res << 7) | (b & 0x7F); + } while (b & 0x80); + return true; + } + + /** + * Read bytes into a buffer. + * @param[out] dest buffer to copy info + * @param length number of bytes to read + * @return true if the requested number of bytes were available + */ + bool ReadBuffer(byte *dest, size_t length) + { + if (this->IsEnd()) return false; + if (this->buflen - this->pos < length) return false; + memcpy(dest, this->buf + this->pos, length); + this->pos += length; + return true; + } + + /** + * Skip over a number of bytes in the buffer. + * @param count number of bytes to skip over + * @return true if there were enough bytes available + */ + bool Skip(size_t count) + { + if (this->IsEnd()) return false; + if (this->buflen - this->pos < count) return false; + this->pos += count; + return true; + } + + /** + * Go a number of bytes back to re-read. + * @param count number of bytes to go back + * @return true if at least count bytes had been read previously + */ + bool Rewind(size_t count) + { + if (count > this->pos) return false; + this->pos -= count; + return true; + } +}; + +static bool ReadTrackChunk(FILE *file, MidiFile &target) +{ + byte buf[4]; + + const byte magic[] = { 'M', 'T', 'r', 'k' }; + if (fread(buf, sizeof(magic), 1, file) != 1) { + return false; + } + if (memcmp(magic, buf, sizeof(magic)) != 0) { + return false; + } + + /* Read chunk length and then the whole chunk */ + uint32 chunk_length; + if (fread(&chunk_length, 1, 4, file) != 4) { + return false; + } + chunk_length = FROM_BE32(chunk_length); + + ByteBuffer chunk(file, chunk_length); + if (!chunk.IsValid()) { + return false; + } + + target.blocks.push_back(MidiFile::DataBlock()); + MidiFile::DataBlock *block = &target.blocks.back(); + + byte last_status = 0; + bool running_sysex = false; + while (!chunk.IsEnd()) { + /* Read deltatime for event, start new block */ + uint32 deltatime = 0; + if (!chunk.ReadVariableLength(deltatime)) { + return false; + } + if (deltatime > 0) { + target.blocks.push_back(MidiFile::DataBlock(block->ticktime + deltatime)); + block = &target.blocks.back(); + } + + /* Read status byte */ + byte status; + if (!chunk.ReadByte(status)) { + return false; + } + + if ((status & 0x80) == 0) { + /* High bit not set means running status message, status is same as last + * convert to explicit status */ + chunk.Rewind(1); + status = last_status; + goto running_status; + } else if ((status & 0xF0) != 0xF0) { + /* Regular channel message */ + last_status = status; + running_status: + byte *data; + switch (status & 0xF0) { + case MIDIST_NOTEOFF: + case MIDIST_NOTEON: + case MIDIST_POLYPRESS: + case MIDIST_CONTROLLER: + case MIDIST_PITCHBEND: + /* 3 byte messages */ + data = block->data.Append(3); + data[0] = status; + if (!chunk.ReadBuffer(&data[1], 2)) { + return false; + } + break; + case MIDIST_PROGCHG: + case MIDIST_CHANPRESS: + /* 2 byte messages */ + data = block->data.Append(2); + data[0] = status; + if (!chunk.ReadByte(data[1])) { + return false; + } + break; + default: + NOT_REACHED(); + } + } else if (status == MIDIST_SMF_META) { + /* Meta event, read event type byte and data length */ + if (!chunk.ReadByte(buf[0])) { + return false; + } + uint32 length = 0; + if (!chunk.ReadVariableLength(length)) { + return false; + } + switch (buf[0]) { + case 0x2F: + /* end of track, no more data (length != 0 is illegal) */ + return (length == 0); + case 0x51: + /* tempo change */ + if (length != 3) return false; + if (!chunk.ReadBuffer(buf, 3)) return false; + target.tempos.push_back(MidiFile::TempoChange(block->ticktime, buf[0] << 16 | buf[1] << 8 | buf[2])); + break; + default: + /* unimportant meta event, skip over it */ + if (!chunk.Skip(length)) { + return false; + } + break; + } + } else if (status == MIDIST_SYSEX || (status == MIDIST_SMF_ESCAPE && running_sysex)) { + /* System exclusive message */ + uint32 length = 0; + if (!chunk.ReadVariableLength(length)) { + return false; + } + byte *data = block->data.Append(length + 1); + data[0] = 0xF0; + if (!chunk.ReadBuffer(data + 1, length)) { + return false; + } + if (data[length] != 0xF7) { + /* Engage Casio weirdo mode - convert to normal sysex */ + running_sysex = true; + *block->data.Append() = 0xF7; + } else { + running_sysex = false; + } + } else if (status == MIDIST_SMF_ESCAPE) { + /* Escape sequence */ + uint32 length = 0; + if (!chunk.ReadVariableLength(length)) { + return false; + } + byte *data = block->data.Append(length); + if (!chunk.ReadBuffer(data, length)) { + return false; + } + } else { + /* Messages undefined in standard midi files: + * 0xF1 - MIDI time code quarter frame + * 0xF2 - Song position pointer + * 0xF3 - Song select + * 0xF4 - undefined/reserved + * 0xF5 - undefined/reserved + * 0xF6 - Tune request for analog synths + * 0xF8..0xFE - System real-time messages + */ + return false; + } + } + + NOT_REACHED(); +} + +template +bool TicktimeAscending(const T &a, const T &b) +{ + return a.ticktime < b.ticktime; +} + +static bool FixupMidiData(MidiFile &target) +{ + /* Sort all tempo changes and events */ + std::sort(target.tempos.begin(), target.tempos.end(), TicktimeAscending); + std::sort(target.blocks.begin(), target.blocks.end(), TicktimeAscending); + + if (target.tempos.size() == 0) { + /* No tempo information, assume 120 bpm (500,000 microseconds per beat */ + target.tempos.push_back(MidiFile::TempoChange(0, 500000)); + } + /* Add sentinel tempo at end */ + target.tempos.push_back(MidiFile::TempoChange(UINT32_MAX, 0)); + + /* Merge blocks with identical tick times */ + std::vector merged_blocks; + uint32 last_ticktime = 0; + for (size_t i = 0; i < target.blocks.size(); i++) { + MidiFile::DataBlock &block = target.blocks[i]; + if (block.data.Length() == 0) { + continue; + } else if (block.ticktime > last_ticktime || merged_blocks.size() == 0) { + merged_blocks.push_back(block); + last_ticktime = block.ticktime; + } else { + byte *datadest = merged_blocks.back().data.Append(block.data.Length()); + memcpy(datadest, block.data.Begin(), block.data.Length()); + } + } + std::swap(merged_blocks, target.blocks); + + /* Annotate blocks with real time */ + last_ticktime = 0; + uint32 last_realtime = 0; + size_t cur_tempo = 0, cur_block = 0; + while (cur_block < target.blocks.size()) { + MidiFile::DataBlock &block = target.blocks[cur_block]; + MidiFile::TempoChange &tempo = target.tempos[cur_tempo]; + MidiFile::TempoChange &next_tempo = target.tempos[cur_tempo+1]; + if (block.ticktime <= next_tempo.ticktime) { + /* block is within the current tempo */ + int64 tickdiff = block.ticktime - last_ticktime; + last_ticktime = block.ticktime; + last_realtime += uint32(tickdiff * tempo.tempo / target.tickdiv); + block.realtime = last_realtime; + cur_block++; + } else { + /* tempo change occurs before this block */ + int64 tickdiff = next_tempo.ticktime - last_ticktime; + last_ticktime = next_tempo.ticktime; + last_realtime += uint32(tickdiff * tempo.tempo / target.tickdiv); // current tempo until the tempo change + cur_tempo++; + } + } + + return true; +} + +/** + * Read the header of a standard MIDI file. + * @param[in] filename name of file to read from + * @param[out] header filled with data read + * @return true if the file could be opened and contained a header with correct format + */ +bool MidiFile::ReadSMFHeader(const char *filename, SMFHeader &header) +{ + FILE *file = FioFOpenFile(filename, "rb", Subdirectory::BASESET_DIR); + if (!file) return false; + bool result = ReadSMFHeader(file, header); + FioFCloseFile(file); + return result; +} + +/** + * Read the header of a standard MIDI file. + * The function will consume 14 bytes from the current file pointer position. + * @param[in] file open file to read from (should be in binary mode) + * @param[out] header filled with data read + * @return true if a header in correct format could be read from the file + */ +bool MidiFile::ReadSMFHeader(FILE *file, SMFHeader &header) +{ + /* Try to read header, fixed size */ + byte buffer[14]; + if (fread(buffer, sizeof(buffer), 1, file) != 1) { + return false; + } + + /* Check magic, 'MThd' followed by 4 byte length indicator (always = 6 in SMF) */ + const byte magic[] = { 'M', 'T', 'h', 'd', 0x00, 0x00, 0x00, 0x06 }; + if (MemCmpT(buffer, magic, sizeof(magic)) != 0) { + return false; + } + + /* Read the parameters of the file */ + header.format = (buffer[8] << 8) | buffer[9]; + header.tracks = (buffer[10] << 8) | buffer[11]; + header.tickdiv = (buffer[12] << 8) | buffer[13]; + return true; +} + +/** + * Load a standard MIDI file. + * @param filename name of the file to load + * @returns true if loaded was successful + */ +bool MidiFile::LoadFile(const char *filename) +{ + _midifile_instance = this; + + this->blocks.clear(); + this->tempos.clear(); + this->tickdiv = 0; + + bool success = false; + FILE *file = FioFOpenFile(filename, "rb", Subdirectory::BASESET_DIR); + if (file == NULL) return false; + + SMFHeader header; + if (!ReadSMFHeader(file, header)) goto cleanup; + + /* Only format 0 (single-track) and format 1 (multi-track single-song) are accepted for now */ + if (header.format != 0 && header.format != 1) goto cleanup; + /* Doesn't support SMPTE timecode files */ + if ((header.tickdiv & 0x8000) != 0) goto cleanup; + + this->tickdiv = header.tickdiv; + + for (; header.tracks > 0; header.tracks--) { + if (!ReadTrackChunk(file, *this)) { + goto cleanup; + } + } + + success = FixupMidiData(*this); + +cleanup: + FioFCloseFile(file); + return success; +} + + +/** + * Decoder for "MPS MIDI" format data. + * This format for MIDI music is also used in a few other Microprose games contemporary with Transport Tycoon. + * + * The song data are usually packed inside a CAT file, with one CAT chunk per song. The song titles are used as names for the CAT chunks. + * + * Unlike the Standard MIDI File format, which is based on the IFF structure, the MPS MIDI format is best described as two linked lists of sub-tracks, + * the first list contains a number of reusable "segments", and the second list contains the "master tracks". Each list is prefixed with a byte + * giving the number of elements in the list, and the actual list is just a byte count (BE16 format) for the segment/track followed by the actual data, + * there is no index as such, so the entire data must be seeked through to build an index. + * + * The actual MIDI data inside each track is almost standard MIDI, prefixing every event with a delay, encoded using the same variable-length format + * used in SMF. A few status codes have changed meaning in MPS MIDI: 0xFE changes control from master track to a segment, 0xFD returns from a segment + * to the master track, and 0xFF is used to end the song. (In Standard MIDI all those values must only occur in real-time data.) + * + * As implemented in the original decoder, there is no support for recursively calling segments from segments, i.e. code 0xFE must only occur in + * a master track, and code 0xFD must only occur in a segment. There are no checks made for this, it's assumed that the only input data will ever + * be the original game music, not music from other games, or new productions. + * + * Additionally, some program change and controller events are given special meaning, see comments in the code. + */ +struct MpsMachine { + /** Starting parameter and playback status for one channel/track */ + struct Channel { + byte cur_program; ///< program selected, used for velocity scaling (lookup into programvelocities array) + byte running_status; ///< last midi status code seen + uint16 delay; ///< frames until next command + uint32 playpos; ///< next byte to play this channel from + uint32 startpos; ///< start position of master track + uint32 returnpos; ///< next return position after playing a segment + Channel() : cur_program(0xFF), running_status(0), delay(0), playpos(0), startpos(0), returnpos(0) { } + }; + Channel channels[16]; ///< playback status for each MIDI channel + std::vector segments; ///< pointers into songdata to repeatable data segments + int16 tempo_ticks; ///< ticker that increments when playing a frame, decrements before playing a frame + int16 current_tempo; ///< threshold for actually playing a frame + int16 initial_tempo; ///< starting tempo of song + bool shouldplayflag; ///< not-end-of-song flag + + static const int TEMPO_RATE; + static const byte programvelocities[128]; + + const byte *songdata; ///< raw data array + size_t songdatalen; ///< length of song data + MidiFile ⌖ ///< recipient of data + + /** Overridden MIDI status codes used in the data format */ + enum MpsMidiStatus { + MPSMIDIST_SEGMENT_RETURN = 0xFD, ///< resume playing master track from stored position + MPSMIDIST_SEGMENT_CALL = 0xFE, ///< store current position of master track playback, and begin playback of a segment + MPSMIDIST_ENDSONG = 0xFF, ///< immediately end the song + }; + + static void AddMidiData(MidiFile::DataBlock &block, byte b1, byte b2) + { + *block.data.Append() = b1; + *block.data.Append() = b2; + } + static void AddMidiData(MidiFile::DataBlock &block, byte b1, byte b2, byte b3) + { + *block.data.Append() = b1; + *block.data.Append() = b2; + *block.data.Append() = b3; + } + + /** + * Construct a TTD DOS music format decoder. + * @param songdata Buffer of song data from CAT file, ownership remains with caller + * @param songdatalen Length of the data buffer in bytes + * @param target MidiFile object to add decoded data to + */ + MpsMachine(const byte *data, size_t length, MidiFile &target) + : songdata(data), songdatalen(length), target(target) + { + uint32 pos = 0; + int loopmax; + int loopidx; + + /* First byte is the initial "tempo" */ + this->initial_tempo = this->songdata[pos++]; + + /* Next byte is a count of callable segments */ + loopmax = this->songdata[pos++]; + for (loopidx = 0; loopidx < loopmax; loopidx++) { + /* Segments form a linked list in the stream, + * first two bytes in each is an offset to the next. + * Two bytes between offset to next and start of data + * are unaccounted for. */ + this->segments.push_back(pos + 4); + pos += FROM_LE16(*(const int16 *)(this->songdata + pos)); + } + + /* After segments follows list of master tracks for each channel, + * also prefixed with a byte counting actual tracks. */ + loopmax = this->songdata[pos++]; + for (loopidx = 0; loopidx < loopmax; loopidx++) { + /* Similar structure to segments list, but also has + * the MIDI channel number as a byte before the offset + * to next track. */ + byte ch = this->songdata[pos++]; + this->channels[ch].startpos = pos + 4; + pos += FROM_LE16(*(const int16 *)(this->songdata + pos)); + } + } + + /** + * Read an SMF-style variable length value (note duration) from songdata. + * @param pos Position to read from, updated to point to next byte after the value read + * @return Value read from data stream + */ + uint16 ReadVariableLength(uint32 &pos) + { + byte b = 0; + uint16 res = 0; + do { + b = this->songdata[pos++]; + res = (res << 7) + (b & 0x7F); + } while (b & 0x80); + return res; + } + + /** + * Prepare for playback from the beginning. Resets the song pointer for every track to the beginning. + */ + void RestartSong() + { + for (int ch = 0; ch < 16; ch++) { + Channel &chandata = this->channels[ch]; + if (chandata.startpos != 0) { + /* Active track, set position to beginning */ + chandata.playpos = chandata.startpos; + chandata.delay = this->ReadVariableLength(chandata.playpos); + } else { + /* Inactive track, mark as such */ + chandata.playpos = 0; + chandata.delay = 0; + } + } + } + + /** + * Play one frame of data from one channel + */ + uint16 PlayChannelFrame(MidiFile::DataBlock &outblock, int channel) + { + uint16 newdelay = 0; + byte b1, b2; + Channel &chandata = this->channels[channel]; + + do { + /* Read command/status byte */ + b1 = this->songdata[chandata.playpos++]; + + /* Command 0xFE, call segment from master track */ + if (b1 == MPSMIDIST_SEGMENT_CALL) { + b1 = this->songdata[chandata.playpos++]; + chandata.returnpos = chandata.playpos; + chandata.playpos = this->segments[b1]; + newdelay = this->ReadVariableLength(chandata.playpos); + if (newdelay == 0) { + continue; + } + return newdelay; + } + + /* Command 0xFD, return from segment to master track */ + if (b1 == MPSMIDIST_SEGMENT_RETURN) { + chandata.playpos = chandata.returnpos; + chandata.returnpos = 0; + newdelay = this->ReadVariableLength(chandata.playpos); + if (newdelay == 0) { + continue; + } + return newdelay; + } + + /* Command 0xFF, end of song */ + if (b1 == MPSMIDIST_ENDSONG) { + this->shouldplayflag = false; + return 0; + } + + /* Regular MIDI channel message status byte */ + if (b1 >= 0x80) { + /* Save the status byte as running status for the channel + * and read another byte for first parameter to command */ + chandata.running_status = b1; + b1 = this->songdata[chandata.playpos++]; + } + + switch (chandata.running_status & 0xF0) { + case MIDIST_NOTEOFF: + case MIDIST_NOTEON: + b2 = this->songdata[chandata.playpos++]; + if (b2 != 0) { + /* Note on, read velocity and scale according to rules */ + int16 velocity; + if (channel == 9) { + /* Percussion channel, fixed velocity scaling not in the table */ + velocity = (int16)b2 * 0x50; + } else { + /* Regular channel, use scaling from table */ + velocity = b2 * programvelocities[chandata.cur_program]; + } + b2 = (velocity / 128) & 0x00FF; + AddMidiData(outblock, MIDIST_NOTEON + channel, b1, b2); + } else { + /* Note off */ + AddMidiData(outblock, MIDIST_NOTEON + channel, b1, 0); + } + break; + case MIDIST_CONTROLLER: + b2 = this->songdata[chandata.playpos++]; + if (b1 == MIDICT_MODE_MONO) { + /* Unknown what the purpose of this is. + * Occurs in "Can't get There from Here" and in "Aliens Ate my Railway" a few times each. + * Possibly intended to give hints to other (non-GM) music drivers decoding the song. + */ + break; + } else if (b1 == 0) { + /* Standard MIDI controller 0 is "bank select", override meaning to change tempo. + * This is not actually used in any of the original songs. */ + if (b2 != 0) { + this->current_tempo = ((int)b2) * 48 / 60; + } + break; + } else if (b1 == MIDICT_EFFECTS1) { + /* Override value of this controller, default mapping is Reverb Send Level according to MMA RP-023. + * Unknown what the purpose of this particular value is. */ + b2 = 30; + } + AddMidiData(outblock, MIDIST_CONTROLLER + channel, b1, b2); + break; + case MIDIST_PROGCHG: + if (b1 == 0x7E) { + /* Program change to "Applause" is originally used + * to cause the song to loop, but that gets handled + * separately in the output driver here. + * Just end the song. */ + this->shouldplayflag = false; + break; + } + /* Used for note velocity scaling lookup */ + chandata.cur_program = b1; + /* Two programs translated to a third, this is likely to + * provide three different velocity scalings of "brass". */ + if (b1 == 0x57 || b1 == 0x3F) { + b1 = 0x3E; + } + AddMidiData(outblock, MIDIST_PROGCHG + channel, b1); + break; + case MIDIST_PITCHBEND: + b2 = this->songdata[chandata.playpos++]; + AddMidiData(outblock, MIDIST_PITCHBEND + channel, b1, b2); + break; + default: + break; + } + + newdelay = this->ReadVariableLength(chandata.playpos); + } while (newdelay == 0); + + return newdelay; + } + + /** + * Play one frame of data into a block. + */ + bool PlayFrame(MidiFile::DataBlock &block) + { + /* Update tempo/ticks counter */ + this->tempo_ticks -= this->current_tempo; + if (this->tempo_ticks > 0) { + return true; + } + this->tempo_ticks += TEMPO_RATE; + + /* Look over all channels, play those active */ + for (int ch = 0; ch < 16; ch++) { + Channel &chandata = this->channels[ch]; + if (chandata.playpos != 0) { + if (chandata.delay == 0) { + chandata.delay = this->PlayChannelFrame(block, ch); + } + chandata.delay--; + } + } + + return this->shouldplayflag; + } + + /** + * Perform playback of whole song. + */ + bool PlayInto() + { + /* Tempo seems to be handled as TEMPO_RATE = 148 ticks per second. + * Use this as the tickdiv, and define the tempo to be one second (1M microseconds) per tickdiv. + * MIDI software loading exported files will show a bogus tempo, but playback will be correct. */ + this->target.tickdiv = TEMPO_RATE; + this->target.tempos.push_back(MidiFile::TempoChange(0, 1000000)); + + /* Initialize playback simulation */ + this->RestartSong(); + this->shouldplayflag = true; + this->current_tempo = (int32)this->initial_tempo * 24 / 60; + this->tempo_ticks = this->current_tempo; + + /* Always reset percussion channel to program 0 */ + this->target.blocks.push_back(MidiFile::DataBlock()); + AddMidiData(this->target.blocks.back(), MIDIST_PROGCHG+9, 0x00); + + /* Technically should be an endless loop, but having + * a maximum (about 10 minutes) avoids getting stuck, + * in case of corrupted data. */ + for (uint32 tick = 0; tick < 100000; tick+=1) { + this->target.blocks.push_back(MidiFile::DataBlock()); + auto &block = this->target.blocks.back(); + block.ticktime = tick; + if (!this->PlayFrame(block)) { + break; + } + } + return true; + } +}; +/** Frames/ticks per second for music playback */ +const int MpsMachine::TEMPO_RATE = 148; +/** Base note velocities for various GM programs */ +const byte MpsMachine::programvelocities[128] = { + 100, 100, 100, 100, 100, 90, 100, 100, 100, 100, 100, 90, 100, 100, 100, 100, + 100, 100, 85, 100, 100, 100, 100, 100, 100, 100, 100, 100, 90, 90, 110, 80, + 100, 100, 100, 90, 70, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 90, 100, 100, 100, 100, 100, 100, 120, 100, 100, 100, 120, 100, 127, + 100, 100, 90, 100, 100, 100, 100, 100, 100, 95, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 115, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, +}; + +/** + * Create MIDI data from song data for the original Microprose music drivers. + * @param data pointer to block of data + * @param length size of data in bytes + * @return true if the data could be loaded + */ +bool MidiFile::LoadMpsData(const byte *data, size_t length) +{ + _midifile_instance = this; + + MpsMachine machine(data, length, *this); + return machine.PlayInto() && FixupMidiData(*this); +} + +bool MidiFile::LoadSong(const MusicSongInfo &song) +{ + switch (song.filetype) { + case MTT_STANDARDMIDI: + return this->LoadFile(song.filename); + case MTT_MPSMIDI: + { + size_t songdatalen = 0; + byte *songdata = GetMusicCatEntryData(song.filename, song.cat_index, songdatalen); + if (songdata != NULL) { + bool result = this->LoadMpsData(songdata, songdatalen); + free(songdata); + return result; + } else { + return false; + } + } + default: + NOT_REACHED(); + } +} + +/** + * Move data from other to this, and clears other. + * @param other object containing loaded data to take over + */ +void MidiFile::MoveFrom(MidiFile &other) +{ + std::swap(this->blocks, other.blocks); + std::swap(this->tempos, other.tempos); + this->tickdiv = other.tickdiv; + + _midifile_instance = this; + + other.blocks.clear(); + other.tempos.clear(); + other.tickdiv = 0; +} + +static void WriteVariableLen(FILE *f, uint32 value) +{ + if (value < 0x7F) { + byte tb = value; + fwrite(&tb, 1, 1, f); + } else if (value < 0x3FFF) { + byte tb[2]; + tb[1] = value & 0x7F; value >>= 7; + tb[0] = (value & 0x7F) | 0x80; value >>= 7; + fwrite(tb, 1, sizeof(tb), f); + } else if (value < 0x1FFFFF) { + byte tb[3]; + tb[2] = value & 0x7F; value >>= 7; + tb[1] = (value & 0x7F) | 0x80; value >>= 7; + tb[0] = (value & 0x7F) | 0x80; value >>= 7; + fwrite(tb, 1, sizeof(tb), f); + } else if (value < 0x0FFFFFFF) { + byte tb[4]; + tb[3] = value & 0x7F; value >>= 7; + tb[2] = (value & 0x7F) | 0x80; value >>= 7; + tb[1] = (value & 0x7F) | 0x80; value >>= 7; + tb[0] = (value & 0x7F) | 0x80; value >>= 7; + fwrite(tb, 1, sizeof(tb), f); + } +} + +/** + * Write a Standard MIDI File containing the decoded music. + * @param filename Name of file to write to + * @return True if the file was written to completion + */ +bool MidiFile::WriteSMF(const char *filename) +{ + FILE *f = FioFOpenFile(filename, "wb", Subdirectory::NO_DIRECTORY); + if (!f) { + return false; + } + + /* SMF header */ + const byte fileheader[] = { + 'M', 'T', 'h', 'd', // block name + 0x00, 0x00, 0x00, 0x06, // BE32 block length, always 6 bytes + 0x00, 0x00, // writing format 0 (all in one track) + 0x00, 0x01, // containing 1 track (BE16) + (byte)(this->tickdiv >> 8), (byte)this->tickdiv, // tickdiv in BE16 + }; + fwrite(fileheader, sizeof(fileheader), 1, f); + + /* Track header */ + const byte trackheader[] = { + 'M', 'T', 'r', 'k', // block name + 0, 0, 0, 0, // BE32 block length, unknown at this time + }; + fwrite(trackheader, sizeof(trackheader), 1, f); + /* Determine position to write the actual track block length at */ + size_t tracksizepos = ftell(f) - 4; + + /* Write blocks in sequence */ + uint32 lasttime = 0; + size_t nexttempoindex = 0; + for (size_t bi = 0; bi < this->blocks.size(); bi++) { + DataBlock &block = this->blocks[bi]; + TempoChange &nexttempo = this->tempos[nexttempoindex]; + + uint32 timediff = block.ticktime - lasttime; + + /* Check if there is a tempo change before this block */ + if (nexttempo.ticktime < block.ticktime) { + timediff = nexttempo.ticktime - lasttime; + } + + /* Write delta time for block */ + lasttime += timediff; + bool needtime = false; + WriteVariableLen(f, timediff); + + /* Write tempo change if there is one */ + if (nexttempo.ticktime <= block.ticktime) { + byte tempobuf[6] = { MIDIST_SMF_META, 0x51, 0x03, 0, 0, 0 }; + tempobuf[3] = (nexttempo.tempo & 0x00FF0000) >> 16; + tempobuf[4] = (nexttempo.tempo & 0x0000FF00) >> 8; + tempobuf[5] = (nexttempo.tempo & 0x000000FF); + fwrite(tempobuf, sizeof(tempobuf), 1, f); + nexttempoindex++; + needtime = true; + } + /* If a tempo change occurred between two blocks, rather than + * at start of this one, start over with delta time for the block. */ + if (nexttempo.ticktime < block.ticktime) { + /* Start loop over at same index */ + bi--; + continue; + } + + /* Write each block data command */ + byte *dp = block.data.Begin(); + while (dp < block.data.End()) { + /* Always zero delta time inside blocks */ + if (needtime) { + fputc(0, f); + } + needtime = true; + + /* Check message type and write appropriate number of bytes */ + switch (*dp & 0xF0) { + case MIDIST_NOTEOFF: + case MIDIST_NOTEON: + case MIDIST_POLYPRESS: + case MIDIST_CONTROLLER: + case MIDIST_PITCHBEND: + fwrite(dp, 1, 3, f); + dp += 3; + continue; + case MIDIST_PROGCHG: + case MIDIST_CHANPRESS: + fwrite(dp, 1, 2, f); + dp += 2; + continue; + } + + /* Sysex needs to measure length and write that as well */ + if (*dp == MIDIST_SYSEX) { + fwrite(dp, 1, 1, f); + dp++; + byte *sysexend = dp; + while (*sysexend != MIDIST_ENDSYSEX) sysexend++; + ptrdiff_t sysexlen = sysexend - dp; + WriteVariableLen(f, sysexlen); + fwrite(dp, 1, sysexend - dp, f); + dp = sysexend; + continue; + } + + /* Fail for any other commands */ + fclose(f); + return false; + } + } + + /* End of track marker */ + static const byte track_end_marker[] = { 0x00, MIDIST_SMF_META, 0x2F, 0x00 }; + fwrite(&track_end_marker, sizeof(track_end_marker), 1, f); + + /* Fill out the RIFF block length */ + size_t trackendpos = ftell(f); + fseek(f, tracksizepos, SEEK_SET); + uint32 tracksize = (uint32)(trackendpos - tracksizepos - 4); // blindly assume we never produce files larger than 2 GB + tracksize = TO_BE32(tracksize); + fwrite(&tracksize, 4, 1, f); + + fclose(f); + return true; +} + +/** + * Get the name of a Standard MIDI File for a given song. + * For songs already in SMF format, just returns the original. + * Otherwise the song is converted, written to a temporary-ish file, and the written filename is returned. + * @param song Song definition to query + * @return Full filename string, empty string if failed + */ +std::string MidiFile::GetSMFFile(const MusicSongInfo &song) +{ + if (song.filetype == MTT_STANDARDMIDI) { + return std::string(song.filename); + } + + if (song.filetype != MTT_MPSMIDI) return std::string(); + + const char *lastpathsep = strrchr(song.filename, PATHSEPCHAR); + if (lastpathsep == NULL) { + lastpathsep = song.filename; + } + + char basename[MAX_PATH]; + { + /* Remove all '.' characters from filename */ + char *wp = basename; + for (const char *rp = lastpathsep + 1; *rp != '\0'; rp++) { + if (*rp != '.') *wp++ = *rp; + } + *wp++ = '\0'; + } + + char tempdirname[MAX_PATH]; + FioGetFullPath(tempdirname, lastof(tempdirname), Searchpath::SP_AUTODOWNLOAD_DIR, Subdirectory::BASESET_DIR, basename); + if (!AppendPathSeparator(tempdirname, lastof(tempdirname))) return std::string(); + FioCreateDirectory(tempdirname); + + char output_filename[MAX_PATH]; + seprintf(output_filename, lastof(output_filename), "%s%d.mid", tempdirname, song.cat_index); + + if (FileExists(output_filename)) { + /* If the file already exists, assume it's the correct decoded data */ + return std::string(output_filename); + } + + byte *data; + size_t datalen; + data = GetMusicCatEntryData(song.filename, song.cat_index, datalen); + if (data == NULL) return std::string(); + + MidiFile midifile; + if (!midifile.LoadMpsData(data, datalen)) { + free(data); + return std::string(); + } + free(data); + + if (midifile.WriteSMF(output_filename)) { + return std::string(output_filename); + } else { + return std::string(); + } +} + + +static bool CmdDumpSMF(byte argc, char *argv[]) +{ + if (argc == 0) { + IConsolePrint(CC_WARNING, "Write the current song to a Standard MIDI File. Usage: 'dumpsmf '"); + return true; + } + if (argc != 2) { + IConsolePrint(CC_WARNING, "You must specify a filename to write MIDI data to."); + return false; + } + + if (_midifile_instance == NULL) { + IConsolePrint(CC_ERROR, "There is no MIDI file loaded currently, make sure music is playing, and you're using a driver that works with raw MIDI."); + return false; + } + + char fnbuf[MAX_PATH] = { 0 }; + if (seprintf(fnbuf, lastof(fnbuf), "%s%s", FiosGetScreenshotDir(), argv[1]) >= (int)lengthof(fnbuf)) { + IConsolePrint(CC_ERROR, "Filename too long."); + return false; + } + IConsolePrintF(CC_INFO, "Dumping MIDI to: %s", fnbuf); + + if (_midifile_instance->WriteSMF(fnbuf)) { + IConsolePrint(CC_INFO, "File written successfully."); + return true; + } else { + IConsolePrint(CC_ERROR, "An error occurred writing MIDI file."); + return false; + } +} + +static void RegisterConsoleMidiCommands() +{ + static bool registered = false; + if (!registered) { + IConsoleCmdRegister("dumpsmf", CmdDumpSMF); + registered = true; + } +} + +MidiFile::MidiFile() +{ + RegisterConsoleMidiCommands(); +} + +MidiFile::~MidiFile() +{ + if (_midifile_instance == this) { + _midifile_instance = NULL; + } +} + diff --git a/src/music/midifile.hpp b/src/music/midifile.hpp new file mode 100644 index 0000000000..0016be86ca --- /dev/null +++ b/src/music/midifile.hpp @@ -0,0 +1,55 @@ +/* $Id$ */ + +/* +* This file is part of OpenTTD. +* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. +* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . +*/ + +/* @file midifile.hpp Parser for standard MIDI files */ + +#ifndef MUSIC_MIDIFILE_HPP +#define MUSIC_MIDIFILE_HPP + +#include "../stdafx.h" +#include "../core/smallvec_type.hpp" +#include "midi.h" +#include +#include + +struct MusicSongInfo; + +struct MidiFile { + struct DataBlock { + uint32 ticktime; ///< tick number since start of file this block should be triggered at + uint32 realtime; ///< real-time (microseconds) since start of file this block should be triggered at + SmallVector data; ///< raw midi data contained in block + DataBlock(uint32 _ticktime = 0) : ticktime(_ticktime) { } + }; + struct TempoChange { + uint32 ticktime; ///< tick number since start of file this tempo change occurs at + uint32 tempo; ///< new tempo in microseconds per tick + TempoChange(uint32 _ticktime, uint32 _tempo) : ticktime(_ticktime), tempo(_tempo) { } + }; + + std::vector blocks; ///< sequential time-annotated data of file, merged to a single track + std::vector tempos; ///< list of tempo changes in file + uint16 tickdiv; ///< ticks per quarter note + + MidiFile(); + ~MidiFile(); + + bool LoadFile(const char *filename); + bool LoadMpsData(const byte *data, size_t length); + bool LoadSong(const MusicSongInfo &song); + void MoveFrom(MidiFile &other); + + bool WriteSMF(const char *filename); + + static std::string GetSMFFile(const MusicSongInfo &song); + static bool ReadSMFHeader(const char *filename, SMFHeader &header); + static bool ReadSMFHeader(FILE *file, SMFHeader &header); +}; + +#endif /* MUSIC_MIDIFILE_HPP */ diff --git a/src/music/music_driver.hpp b/src/music/music_driver.hpp index be09d3ea2b..10a99d2750 100644 --- a/src/music/music_driver.hpp +++ b/src/music/music_driver.hpp @@ -14,6 +14,8 @@ #include "../driver.h" +struct MusicSongInfo; + /** Driver for all music playback. */ class MusicDriver : public Driver { public: @@ -21,7 +23,7 @@ public: * Play a particular song. * @param filename The name of file with the song to play. */ - virtual void PlaySong(const char *filename) = 0; + virtual void PlaySong(const MusicSongInfo &song) = 0; /** * Stop playing the current song. diff --git a/src/music/null_m.h b/src/music/null_m.h index df9f7d80d5..51e1a06656 100644 --- a/src/music/null_m.h +++ b/src/music/null_m.h @@ -21,7 +21,7 @@ public: /* virtual */ void Stop() { } - /* virtual */ void PlaySong(const char *filename) { } + /* virtual */ void PlaySong(const MusicSongInfo &song) { } /* virtual */ void StopSong() { } diff --git a/src/music/os2_m.cpp b/src/music/os2_m.cpp index d7fb97d2d3..1689f00a64 100644 --- a/src/music/os2_m.cpp +++ b/src/music/os2_m.cpp @@ -12,6 +12,8 @@ #include "../stdafx.h" #include "../openttd.h" #include "os2_m.h" +#include "midifile.hpp" +#include "../base_media_base.h" #define INCL_DOS #define INCL_OS2MM @@ -49,11 +51,14 @@ static long CDECL MidiSendCommand(const char *cmd, ...) /** OS/2's music player's factory. */ static FMusicDriver_OS2 iFMusicDriver_OS2; -void MusicDriver_OS2::PlaySong(const char *filename) +void MusicDriver_OS2::PlaySong(const MusicSongInfo &song) { - MidiSendCommand("close all"); + std::string filename = MidiFile::GetSMFFile(song); - if (MidiSendCommand("open %s type sequencer alias song", filename) != 0) { + MidiSendCommand("close all"); + if (filename.empty()) return; + + if (MidiSendCommand("open %s type sequencer alias song", filename.c_str()) != 0) { return; } diff --git a/src/music/os2_m.h b/src/music/os2_m.h index f35e2fdcf6..ac7cd03197 100644 --- a/src/music/os2_m.h +++ b/src/music/os2_m.h @@ -21,7 +21,7 @@ public: /* virtual */ void Stop(); - /* virtual */ void PlaySong(const char *filename); + /* virtual */ void PlaySong(const MusicSongInfo &song); /* virtual */ void StopSong(); diff --git a/src/music/qtmidi.cpp b/src/music/qtmidi.cpp index 9bc6a61740..f8ab150e79 100644 --- a/src/music/qtmidi.cpp +++ b/src/music/qtmidi.cpp @@ -30,7 +30,9 @@ #include "../stdafx.h" #include "qtmidi.h" +#include "midifile.hpp" #include "../debug.h" +#include "../base_media_base.h" #define Rect OTTDRect #define Point OTTDPoint @@ -258,11 +260,14 @@ void MusicDriver_QtMidi::Stop() * * @param filename Path to a MIDI file. */ -void MusicDriver_QtMidi::PlaySong(const char *filename) +void MusicDriver_QtMidi::PlaySong(const MusicSongInfo &song) { if (!_quicktime_started) return; - DEBUG(driver, 2, "qtmidi: trying to play '%s'", filename); + std::string filename = MidiFile::GetSMFFile(song); + if (filename.empty()) return; + + DEBUG(driver, 2, "qtmidi: trying to play '%s'", filename.c_str()); switch (_quicktime_state) { case QT_STATE_PLAY: StopSong(); @@ -276,12 +281,12 @@ void MusicDriver_QtMidi::PlaySong(const char *filename) FALLTHROUGH; case QT_STATE_IDLE: - LoadMovieForMIDIFile(filename, &_quicktime_movie); + LoadMovieForMIDIFile(filename.c_str(), &_quicktime_movie); SetMovieVolume(_quicktime_movie, VOLUME); StartMovie(_quicktime_movie); _quicktime_state = QT_STATE_PLAY; } - DEBUG(driver, 3, "qtmidi: playing '%s'", filename); + DEBUG(driver, 3, "qtmidi: playing '%s'", filename.c_str()); } diff --git a/src/music/qtmidi.h b/src/music/qtmidi.h index f0e17086e4..32163db939 100644 --- a/src/music/qtmidi.h +++ b/src/music/qtmidi.h @@ -20,7 +20,7 @@ public: /* virtual */ void Stop(); - /* virtual */ void PlaySong(const char *filename); + /* virtual */ void PlaySong(const MusicSongInfo &song); /* virtual */ void StopSong(); diff --git a/src/music/win32_m.cpp b/src/music/win32_m.cpp index fff0376a09..a32318db12 100644 --- a/src/music/win32_m.cpp +++ b/src/music/win32_m.cpp @@ -15,170 +15,407 @@ #include #include #include "../os/windows/win32.h" +#include "../debug.h" +#include "midifile.hpp" +#include "midi.h" +#include "../base_media_base.h" #include "../safeguards.h" +struct PlaybackSegment { + uint32 start, end; + size_t start_block; + bool loop; +}; + static struct { - bool stop_song; - bool terminate; - bool playing; - int new_vol; - HANDLE wait_obj; - HANDLE thread; - UINT_PTR devid; - char start_song[MAX_PATH]; + UINT time_period; ///< obtained timer precision value + HMIDIOUT midi_out; ///< handle to open midiOut + UINT timer_id; ///< ID of active multimedia timer + 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 + 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 + + MidiFile current_file; ///< file currently being played from + PlaybackSegment current_segment; ///< segment info for current playback + DWORD playback_start_time; ///< timestamp current file began playback + size_t current_block; ///< next block index to send + MidiFile next_file; ///< upcoming file to play + PlaybackSegment next_segment; ///< segment info for upcoming file + + byte channel_volumes[16]; ///< last seen volume controller values in raw data } _midi; static FMusicDriver_Win32 iFMusicDriver_Win32; -void MusicDriver_Win32::PlaySong(const char *filename) + +static byte ScaleVolume(byte original, byte scale) { - assert(filename != NULL); - strecpy(_midi.start_song, filename, lastof(_midi.start_song)); - _midi.playing = true; - _midi.stop_song = false; - SetEvent(_midi.wait_obj); + return original * scale / 127; +} + + +void CALLBACK MidiOutProc(HMIDIOUT hmo, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) +{ + if (wMsg == MOM_DONE) { + MIDIHDR *hdr = (LPMIDIHDR)dwParam1; + midiOutUnprepareHeader(hmo, hdr, sizeof(*hdr)); + free(hdr); + } +} + +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) +{ + /* find end of message */ + byte *msg_end = msg_start; + while (*msg_end != MIDIST_ENDSYSEX) msg_end++; + msg_end++; /* also include sysex end byte */ + + /* prepare header */ + MIDIHDR *hdr = CallocT(1); + hdr->lpData = (LPSTR)msg_start; + hdr->dwBufferLength = msg_end - msg_start; + if (midiOutPrepareHeader(_midi.midi_out, hdr, sizeof(*hdr)) == MMSYSERR_NOERROR) { + /* transmit - just point directly into the data buffer */ + hdr->dwBytesRecorded = hdr->dwBufferLength; + midiOutLongMsg(_midi.midi_out, hdr, sizeof(*hdr)); + } else { + free(hdr); + } + + /* update position in buffer */ + remaining -= msg_end - msg_start; + msg_start = msg_end; +} + +static void TransmitSysexConst(byte *msg_start, size_t length) +{ + TransmitSysex(msg_start, length); +} + +/** + * Realtime MIDI playback service routine. + * This is called by the multimedia timer. + */ +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; + LeaveCriticalSection(&_midi.lock); + return; + } + + /* 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); + } + } + _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.current_block = 0; + + MemSetT(_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--; + } + } + + LeaveCriticalSection(&_midi.lock); + } + + /* 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 */ + uint preload_bytes = 0; + for (size_t bl = 0; bl < _midi.current_file.blocks.size(); bl++) { + MidiFile::DataBlock &block = _midi.current_file.blocks[bl]; + preload_bytes += block.data.Length(); + if (block.ticktime >= _midi.current_segment.start) { + if (_midi.current_segment.loop) { + DEBUG(driver, 2, "Win32-MIDI: timer: loop from block %d (ticktime %d, realtime %.3f, bytes %d)", (int)bl, (int)block.ticktime, ((int)block.realtime)/1000.0, (int)preload_bytes); + _midi.current_segment.start_block = bl; + break; + } else { + /* Calculate offset start time for playback. + * The preload_bytes are used to compensate for delay in transmission over traditional serial MIDI interfaces, + * which have a bitrate of 31,250 bits/sec, and transmit 1+8+1 start/data/stop bits per byte. + * 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; + break; + } + } + } + } + + + /* play pending blocks */ + DWORD current_time = timeGetTime(); + DWORD playback_time = current_time - _midi.playback_start_time; + while (_midi.current_block < _midi.current_file.blocks.size()) { + MidiFile::DataBlock &block = _midi.current_file.blocks[_midi.current_block]; + + /* check that block isn't at end-of-song override */ + if (_midi.current_segment.end > 0 && block.ticktime >= _midi.current_segment.end) { + if (_midi.current_segment.loop) { + _midi.current_block = _midi.current_segment.start_block; + _midi.playback_start_time = timeGetTime() - _midi.current_file.blocks[_midi.current_block].realtime / 1000; + } else { + _midi.do_stop = true; + } + break; + } + /* check that block is not in the future */ + if (block.realtime / 1000 > playback_time) { + break; + } + + byte *data = block.data.Begin(); + size_t remaining = block.data.Length(); + byte last_status = 0; + while (remaining > 0) { + /* MidiFile ought to have converted everything out of running status, + * but handle it anyway just to be safe */ + byte status = data[0]; + if (status & 0x80) { + last_status = status; + data++; + remaining--; + } else { + status = last_status; + } + switch (status & 0xF0) { + case MIDIST_PROGCHG: + case MIDIST_CHANPRESS: + /* 2 byte channel messages */ + TransmitChannelMsg(status, data[0]); + data++; + remaining--; + break; + case MIDIST_NOTEOFF: + case MIDIST_NOTEON: + case MIDIST_POLYPRESS: + case MIDIST_PITCHBEND: + /* 3 byte channel messages */ + TransmitChannelMsg(status, data[0], data[1]); + data += 2; + remaining -= 2; + break; + case MIDIST_CONTROLLER: + /* controller change */ + if (data[0] == MIDICT_CHANVOLUME) { + /* volume controller, adjust for user volume */ + _midi.channel_volumes[status & 0x0F] = data[1]; + int vol = ScaleVolume(data[1], _midi.current_volume); + TransmitChannelMsg(status, data[0], vol); + } else { + /* handle other controllers normally */ + TransmitChannelMsg(status, data[0], data[1]); + } + data += 2; + remaining -= 2; + break; + case 0xF0: + /* system messages */ + switch (status) { + case MIDIST_SYSEX: /* system exclusive */ + TransmitSysex(data, remaining); + break; + case MIDIST_TC_QFRAME: /* time code quarter frame */ + case MIDIST_SONGSEL: /* song select */ + data++; + remaining--; + break; + case MIDIST_SONGPOSPTR: /* song position pointer */ + data += 2; + remaining -= 2; + break; + default: /* remaining have no data bytes */ + break; + } + break; + } + } + + _midi.current_block++; + } + + /* end? */ + if (_midi.current_block == _midi.current_file.blocks.size()) { + if (_midi.current_segment.loop) { + _midi.current_block = _midi.current_segment.start_block; + _midi.playback_start_time = timeGetTime() - _midi.current_file.blocks[_midi.current_block].realtime / 1000; + } else { + _midi.do_stop = true; + } + } +} + +void MusicDriver_Win32::PlaySong(const MusicSongInfo &song) +{ + DEBUG(driver, 2, "Win32-MIDI: PlaySong: entry"); + EnterCriticalSection(&_midi.lock); + + if (!_midi.next_file.LoadSong(song)) { + LeaveCriticalSection(&_midi.lock); + return; + } + + _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; + + if (_midi.timer_id == 0) { + DEBUG(driver, 2, "Win32-MIDI: PlaySong: starting timer"); + _midi.timer_id = timeSetEvent(_midi.time_period, _midi.time_period, TimerCallback, (DWORD_PTR)this, TIME_PERIODIC | TIME_CALLBACK_FUNCTION); + } + + LeaveCriticalSection(&_midi.lock); } void MusicDriver_Win32::StopSong() { - if (_midi.playing) { - _midi.stop_song = true; - _midi.start_song[0] = '\0'; - SetEvent(_midi.wait_obj); - } + DEBUG(driver, 2, "Win32-MIDI: StopSong: entry"); + EnterCriticalSection(&_midi.lock); + DEBUG(driver, 2, "Win32-MIDI: StopSong: setting flag"); + _midi.do_stop = true; + LeaveCriticalSection(&_midi.lock); } bool MusicDriver_Win32::IsSongPlaying() { - return _midi.playing; + return _midi.playing || _midi.do_start; } void MusicDriver_Win32::SetVolume(byte vol) { - _midi.new_vol = vol; - SetEvent(_midi.wait_obj); -} - -static MCIERROR CDECL MidiSendCommand(const TCHAR *cmd, ...) -{ - va_list va; - TCHAR buf[512]; - - va_start(va, cmd); - _vsntprintf(buf, lengthof(buf), cmd, va); - va_end(va); - return mciSendString(buf, NULL, 0, 0); -} - -static bool MidiIntPlaySong(const char *filename) -{ - MidiSendCommand(_T("close all")); - - if (MidiSendCommand(_T("open \"%s\" type sequencer alias song"), OTTD2FS(filename)) != 0) { - /* Let's try the "short name" */ - TCHAR buf[MAX_PATH]; - if (GetShortPathName(OTTD2FS(filename), buf, MAX_PATH) == 0) return false; - if (MidiSendCommand(_T("open \"%s\" type sequencer alias song"), buf) != 0) return false; - } - - MidiSendCommand(_T("seek song to start wait")); - return MidiSendCommand(_T("play song")) == 0; -} - -static void MidiIntStopSong() -{ - MidiSendCommand(_T("close all")); -} - -static void MidiIntSetVolume(int vol) -{ - DWORD v = (vol * 65535 / 127); - midiOutSetVolume((HMIDIOUT)_midi.devid, v + (v << 16)); -} - -static bool MidiIntIsSongPlaying() -{ - char buf[16]; - mciSendStringA("status song mode", buf, sizeof(buf), 0); - return strcmp(buf, "playing") == 0 || strcmp(buf, "seeking") == 0; -} - -static DWORD WINAPI MidiThread(LPVOID arg) -{ - SetWin32ThreadName(-1, "ottd:win-midi"); - - do { - char *s; - int vol; - - vol = _midi.new_vol; - if (vol != -1) { - _midi.new_vol = -1; - MidiIntSetVolume(vol); - } - - s = _midi.start_song; - if (s[0] != '\0') { - _midi.playing = MidiIntPlaySong(s); - s[0] = '\0'; - - /* Delay somewhat in case we don't manage to play. */ - if (!_midi.playing) WaitForMultipleObjects(1, &_midi.wait_obj, FALSE, 5000); - } - - if (_midi.stop_song && _midi.playing) { - _midi.stop_song = false; - _midi.playing = false; - MidiIntStopSong(); - } - - if (_midi.playing && !MidiIntIsSongPlaying()) _midi.playing = false; - - WaitForMultipleObjects(1, &_midi.wait_obj, FALSE, 1000); - } while (!_midi.terminate); - - MidiIntStopSong(); - return 0; + EnterCriticalSection(&_midi.lock); + _midi.new_volume = vol; + LeaveCriticalSection(&_midi.lock); } const char *MusicDriver_Win32::Start(const char * const *parm) { - MIDIOUTCAPS midicaps; - UINT nbdev; - UINT_PTR dev; - char buf[16]; + DEBUG(driver, 2, "Win32-MIDI: Start: initializing"); - mciSendStringA("capability sequencer has audio", buf, lengthof(buf), 0); - if (strcmp(buf, "true") != 0) return "MCI sequencer can't play audio"; + InitializeCriticalSection(&_midi.lock); - memset(&_midi, 0, sizeof(_midi)); - _midi.new_vol = -1; + int resolution = GetDriverParamInt(parm, "resolution", 5); + int port = GetDriverParamInt(parm, "port", -1); - /* Get midi device */ - _midi.devid = MIDI_MAPPER; - for (dev = 0, nbdev = midiOutGetNumDevs(); dev < nbdev; dev++) { - if (midiOutGetDevCaps(dev, &midicaps, sizeof(midicaps)) == 0 && (midicaps.dwSupport & MIDICAPS_VOLUME)) { - _midi.devid = dev; - break; - } + UINT devid; + if (port < 0) { + devid = MIDI_MAPPER; + } else { + devid = (UINT)port; } - if (NULL == (_midi.wait_obj = CreateEvent(NULL, FALSE, FALSE, NULL))) return "Failed to create event"; + resolution = Clamp(resolution, 1, 20); - /* The lpThreadId parameter of CreateThread (the last parameter) - * may NOT be NULL on Windows 95, 98 and ME. */ - DWORD threadId; - if (NULL == (_midi.thread = CreateThread(NULL, 8192, MidiThread, 0, 0, &threadId))) return "Failed to create thread"; + if (midiOutOpen(&_midi.midi_out, devid, (DWORD_PTR)&MidiOutProc, (DWORD_PTR)this, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) { + return "could not open midi device"; + } - return NULL; + 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) { + _midi.time_period = min(max((UINT)resolution, timecaps.wPeriodMin), timecaps.wPeriodMax); + if (timeBeginPeriod(_midi.time_period) == MMSYSERR_NOERROR) { + /* success */ + DEBUG(driver, 2, "Win32-MIDI: Start: timer resolution is %d", (int)_midi.time_period); + return NULL; + } + } + midiOutClose(_midi.midi_out); + return "could not set timer resolution"; } void MusicDriver_Win32::Stop() { - _midi.terminate = true; - SetEvent(_midi.wait_obj); - WaitForMultipleObjects(1, &_midi.thread, true, INFINITE); - CloseHandle(_midi.wait_obj); - CloseHandle(_midi.thread); + EnterCriticalSection(&_midi.lock); + + if (_midi.timer_id) { + timeKillEvent(_midi.timer_id); + _midi.timer_id = 0; + } + + timeEndPeriod(_midi.time_period); + midiOutReset(_midi.midi_out); + midiOutClose(_midi.midi_out); + + LeaveCriticalSection(&_midi.lock); + DeleteCriticalSection(&_midi.lock); } diff --git a/src/music/win32_m.h b/src/music/win32_m.h index 3efee3243a..1ac8ae69e4 100644 --- a/src/music/win32_m.h +++ b/src/music/win32_m.h @@ -21,7 +21,7 @@ public: /* virtual */ void Stop(); - /* virtual */ void PlaySong(const char *filename); + /* virtual */ void PlaySong(const MusicSongInfo &song); /* virtual */ void StopSong(); diff --git a/src/music_gui.cpp b/src/music_gui.cpp index 279f376525..e7552fe02f 100644 --- a/src/music_gui.cpp +++ b/src/music_gui.cpp @@ -10,6 +10,7 @@ /** @file music_gui.cpp GUI for the music playback. */ #include "stdafx.h" +#include #include "openttd.h" #include "base_media_base.h" #include "music/music_driver.hpp" @@ -18,11 +19,15 @@ #include "window_func.h" #include "sound_func.h" #include "gfx_func.h" +#include "zoom_func.h" #include "core/random_func.hpp" #include "error.h" #include "core/geometry_func.hpp" #include "string_func.h" #include "settings_type.h" +#include "settings_gui.h" +#include "widgets/dropdown_func.h" +#include "widgets/dropdown_type.h" #include "widgets/music_widget.h" @@ -31,271 +36,416 @@ #include "safeguards.h" -/** - * Get the name of the song. - * @param index of the song. - * @return the name of the song. - */ -static const char *GetSongName(int index) -{ - return BaseMusic::GetUsedSet()->song_name[index]; -} -/** - * Get the track number of the song. - * @param index of the song. - * @return the track number of the song. - */ -static int GetTrackNumber(int index) -{ - return BaseMusic::GetUsedSet()->track_nr[index]; -} +struct MusicSystem { + struct PlaylistEntry : MusicSongInfo { + const MusicSet *set; ///< music set the song comes from + uint set_index; ///< index of song in set -/** The currently played song */ -static byte _music_wnd_cursong = 1; -/** Whether a song is currently played */ -static bool _song_is_active = false; + PlaylistEntry(const MusicSet *set, uint set_index) : MusicSongInfo(set->songinfo[set_index]), set(set), set_index(set_index) { } + bool IsValid() const { return !StrEmpty(this->songname); } + }; + typedef std::vector Playlist; -/** Indices of the songs in the current playlist */ -static byte _cur_playlist[NUM_SONGS_PLAYLIST + 1]; + enum PlaylistChoices { + PLCH_ALLMUSIC, + PLCH_OLDSTYLE, + PLCH_NEWSTYLE, + PLCH_EZYSTREET, + PLCH_CUSTOM1, + PLCH_CUSTOM2, + PLCH_THEMEONLY, + PLCH_MAX, + }; -/** Indices of all songs */ -static byte _playlist_all[NUM_SONGS_AVAILABLE + 1]; -/** Indices of all old style songs */ -static byte _playlist_old_style[NUM_SONGS_CLASS + 1]; -/** Indices of all new style songs */ -static byte _playlist_new_style[NUM_SONGS_CLASS + 1]; -/** Indices of all ezy street songs */ -static byte _playlist_ezy_street[NUM_SONGS_CLASS + 1]; + Playlist active_playlist; ///< current play order of songs, including any shuffle + Playlist displayed_playlist; ///< current playlist as displayed in GUI, never in shuffled order + Playlist music_set; ///< all songs in current music set, in set order -assert_compile(lengthof(_settings_client.music.custom_1) == NUM_SONGS_PLAYLIST + 1); -assert_compile(lengthof(_settings_client.music.custom_2) == NUM_SONGS_PLAYLIST + 1); + PlaylistChoices selected_playlist; -/** The different playlists that can be played. */ -static byte * const _playlists[] = { - _playlist_all, - _playlist_old_style, - _playlist_new_style, - _playlist_ezy_street, - _settings_client.music.custom_1, - _settings_client.music.custom_2, + void BuildPlaylists(); + + void ChangePlaylist(PlaylistChoices pl); + void ChangeMusicSet(const char *set_name); + void Shuffle(); + void Unshuffle(); + + void Play(); + void Stop(); + void Next(); + void Prev(); + void CheckStatus(); + + bool IsPlaying() const; + bool IsShuffle() const; + PlaylistEntry GetCurrentSong() const; + + bool IsCustomPlaylist() const; + void PlaylistAdd(size_t song_index); + void PlaylistRemove(size_t song_index); + void PlaylistClear(); + +private: + void ChangePlaylistPosition(int ofs); + int playlist_position; + + void SaveCustomPlaylist(PlaylistChoices pl); + + Playlist standard_playlists[PLCH_MAX]; }; -/** - * Validate a playlist. - * @param playlist The playlist to validate. - * @param last The last location in the list. - */ -void ValidatePlaylist(byte *playlist, byte *last) -{ - while (*playlist != 0 && playlist <= last) { - /* Song indices are saved off-by-one so 0 is "nothing". */ - if (*playlist <= NUM_SONGS_AVAILABLE && !StrEmpty(GetSongName(*playlist - 1))) { - playlist++; - continue; - } - for (byte *p = playlist; *p != 0 && p <= last; p++) { - p[0] = p[1]; - } - } +MusicSystem _music; - /* Make sure the list is null terminated. */ - *last = 0; -} -/** Initialize the playlists */ -void InitializeMusic() +/** Rebuild all playlists for the current music set */ +void MusicSystem::BuildPlaylists() { - uint j = 0; + const MusicSet *set = BaseMusic::GetUsedSet(); + + /* Clear current playlists */ + for (size_t i = 0; i < lengthof(this->standard_playlists); ++i) this->standard_playlists[i].clear(); + this->music_set.clear(); + + /* Build standard playlists, and a list of available music */ for (uint i = 0; i < NUM_SONGS_AVAILABLE; i++) { - if (StrEmpty(GetSongName(i))) continue; - _playlist_all[j++] = i + 1; - } - /* Terminate the list */ - _playlist_all[j] = 0; + PlaylistEntry entry(set, i); + if (!entry.IsValid()) continue; - /* Now make the 'styled' playlists */ - for (uint k = 0; k < NUM_SONG_CLASSES; k++) { - j = 0; - for (uint i = 0; i < NUM_SONGS_CLASS; i++) { - int id = k * NUM_SONGS_CLASS + i + 1; - if (StrEmpty(GetSongName(id))) continue; - _playlists[k + 1][j++] = id + 1; - } - /* Terminate the list */ - _playlists[k + 1][j] = 0; - } + this->music_set.push_back(entry); - ValidatePlaylist(_settings_client.music.custom_1, lastof(_settings_client.music.custom_1)); - ValidatePlaylist(_settings_client.music.custom_2, lastof(_settings_client.music.custom_2)); + /* Add theme song to theme-only playlist */ + if (i == 0) this->standard_playlists[PLCH_THEMEONLY].push_back(entry); - if (BaseMusic::GetUsedSet()->num_available < _music_wnd_cursong) { - /* If there are less songs than the currently played song, - * just pause and reset to no song. */ - _music_wnd_cursong = 0; - _song_is_active = false; - } -} - -static void SkipToPrevSong() -{ - byte *b = _cur_playlist; - byte *p = b; - byte t; - - if (b[0] == 0) return; // empty playlist - - do p++; while (p[0] != 0); // find the end - - t = *--p; // and copy the bytes - while (p != b) { - p--; - p[1] = p[0]; - } - *b = t; - - _song_is_active = false; -} - -static void SkipToNextSong() -{ - byte *b = _cur_playlist; - byte t; - - t = b[0]; - if (t != 0) { - while (b[1] != 0) { - b[0] = b[1]; - b++; - } - b[0] = t; - } - - _song_is_active = false; -} - -static void MusicVolumeChanged(byte new_vol) -{ - MusicDriver::GetInstance()->SetVolume(new_vol); -} - -static void DoPlaySong() -{ - char filename[MAX_PATH]; - if (FioFindFullPath(filename, lastof(filename), BASESET_DIR, BaseMusic::GetUsedSet()->files[_music_wnd_cursong - 1].filename) == NULL) { - FioFindFullPath(filename, lastof(filename), OLD_GM_DIR, BaseMusic::GetUsedSet()->files[_music_wnd_cursong - 1].filename); - } - MusicDriver::GetInstance()->PlaySong(filename); - SetWindowDirty(WC_MUSIC_WINDOW, 0); -} - -static void DoStopMusic() -{ - MusicDriver::GetInstance()->StopSong(); - SetWindowDirty(WC_MUSIC_WINDOW, 0); -} - -static void SelectSongToPlay() -{ - uint i = 0; - uint j = 0; - - memset(_cur_playlist, 0, sizeof(_cur_playlist)); - do { - /* File is the index into the file table of the music set. The play list uses 0 as 'no entry', - * so we need to subtract 1. In case of 'no entry' (file = -1), just skip adding it outright. */ - int file = _playlists[_settings_client.music.playlist][i] - 1; - if (file >= 0) { - const char *filename = BaseMusic::GetUsedSet()->files[file].filename; - /* We are now checking for the existence of that file prior - * to add it to the list of available songs */ - if (!StrEmpty(filename) && FioCheckFileExists(filename, BASESET_DIR)) { - _cur_playlist[j] = _playlists[_settings_client.music.playlist][i]; - j++; - } - } - } while (_playlists[_settings_client.music.playlist][++i] != 0 && j < lengthof(_cur_playlist) - 1); - - /* Do not shuffle when on the intro-start window, as the song to play has to be the original TTD Theme*/ - if (_settings_client.music.shuffle && _game_mode != GM_MENU) { - i = 500; - do { - uint32 r = InteractiveRandom(); - byte *a = &_cur_playlist[GB(r, 0, 5)]; - byte *b = &_cur_playlist[GB(r, 8, 5)]; - - if (*a != 0 && *b != 0) { - byte t = *a; - *a = *b; - *b = t; - } - } while (--i); - } -} - -static void StopMusic() -{ - _music_wnd_cursong = 0; - DoStopMusic(); - _song_is_active = false; - SetWindowWidgetDirty(WC_MUSIC_WINDOW, 0, 9); -} - -static void PlayPlaylistSong() -{ - if (_cur_playlist[0] == 0) { - SelectSongToPlay(); - /* if there is not songs in the playlist, it may indicate - * no file on the gm folder, or even no gm folder. - * Stop the playback, then */ - if (_cur_playlist[0] == 0) { - _song_is_active = false; - _music_wnd_cursong = 0; - _settings_client.music.playing = false; - return; + /* Don't add the theme song to standard playlists */ + if (i > 0) { + this->standard_playlists[PLCH_ALLMUSIC].push_back(entry); + uint theme = (i - 1) / NUM_SONGS_CLASS; + this->standard_playlists[PLCH_OLDSTYLE + theme].push_back(entry); } } - _music_wnd_cursong = _cur_playlist[0]; - DoPlaySong(); - _song_is_active = true; - SetWindowWidgetDirty(WC_MUSIC_WINDOW, 0, 9); -} - -void ResetMusic() -{ - _music_wnd_cursong = 1; - DoPlaySong(); -} - -void MusicLoop() -{ - if (!_settings_client.music.playing && _song_is_active) { - StopMusic(); - } else if (_settings_client.music.playing && !_song_is_active) { - PlayPlaylistSong(); - } - - if (!_song_is_active) return; - - if (!MusicDriver::GetInstance()->IsSongPlaying()) { - if (_game_mode != GM_MENU) { - StopMusic(); - SkipToNextSong(); - PlayPlaylistSong(); - } else { - ResetMusic(); + /* Load custom playlists + * Song index offsets are 1-based, zero indicates invalid/end-of-list value */ + for (uint i = 0; i < NUM_SONGS_PLAYLIST; i++) { + if (_settings_client.music.custom_1[i] > 0) { + PlaylistEntry entry(set, _settings_client.music.custom_1[i] - 1); + if (entry.IsValid()) this->standard_playlists[PLCH_CUSTOM1].push_back(entry); + } + if (_settings_client.music.custom_2[i] > 0) { + PlaylistEntry entry(set, _settings_client.music.custom_2[i] - 1); + if (entry.IsValid()) this->standard_playlists[PLCH_CUSTOM2].push_back(entry); } } } -static void SelectPlaylist(byte list) +/** + * Switch to another playlist, or reload the current one. + * @param pl Playlist to select + */ +void MusicSystem::ChangePlaylist(PlaylistChoices pl) { - _settings_client.music.playlist = list; + assert(pl < PLCH_MAX && pl >= PLCH_ALLMUSIC); + + this->displayed_playlist = this->standard_playlists[pl]; + this->active_playlist = this->displayed_playlist; + this->selected_playlist = pl; + this->playlist_position = 0; + + if (this->selected_playlist != PLCH_THEMEONLY) _settings_client.music.playlist = this->selected_playlist; + + if (_settings_client.music.shuffle) { + this->Shuffle(); + /* Shuffle() will also Play() if necessary, only start once */ + } else if (_settings_client.music.playing) { + this->Play(); + } + InvalidateWindowData(WC_MUSIC_TRACK_SELECTION, 0); InvalidateWindowData(WC_MUSIC_WINDOW, 0); } +/** + * Change to named music set, and reset playback. + * @param set_name Name of music set to select + */ +void MusicSystem::ChangeMusicSet(const char *set_name) +{ + BaseMusic::SetSet(set_name); + + this->BuildPlaylists(); + this->ChangePlaylist(this->selected_playlist); + + InvalidateWindowData(WC_GAME_OPTIONS, WN_GAME_OPTIONS_GAME_OPTIONS, 0, true); +} + +/** Enable shuffle mode and restart playback */ +void MusicSystem::Shuffle() +{ + _settings_client.music.shuffle = true; + + this->active_playlist = this->displayed_playlist; + for (size_t i = 0; i < this->active_playlist.size(); i++) { + size_t shuffle_index = InteractiveRandom() % (this->active_playlist.size() - i); + std::swap(this->active_playlist[i], this->active_playlist[i + shuffle_index]); + } + + if (_settings_client.music.playing) this->Play(); + + InvalidateWindowData(WC_MUSIC_WINDOW, 0); +} + +/** Disable shuffle and restart playback */ +void MusicSystem::Unshuffle() +{ + _settings_client.music.shuffle = false; + this->active_playlist = this->displayed_playlist; + + if (_settings_client.music.playing) this->Play(); + + InvalidateWindowData(WC_MUSIC_WINDOW, 0); +} + +/** Start/restart playback at current song */ +void MusicSystem::Play() +{ + /* Always set the playing flag, even if there is no music */ + _settings_client.music.playing = true; + MusicDriver::GetInstance()->StopSong(); + /* Make sure playlist_position is a valid index, if playlist has changed etc. */ + this->ChangePlaylistPosition(0); + + /* If there is no music, don't try to play it */ + if (this->active_playlist.empty()) return; + + MusicSongInfo song = this->active_playlist[this->playlist_position]; + if (_game_mode == GM_MENU && this->selected_playlist == PLCH_THEMEONLY) song.loop = true; + MusicDriver::GetInstance()->PlaySong(song); + + InvalidateWindowData(WC_MUSIC_WINDOW, 0); +} + +/** Stop playback and set flag that we don't intend to play music */ +void MusicSystem::Stop() +{ + MusicDriver::GetInstance()->StopSong(); + _settings_client.music.playing = false; + + InvalidateWindowData(WC_MUSIC_WINDOW, 0); +} + +/** Skip to next track */ +void MusicSystem::Next() +{ + this->ChangePlaylistPosition(+1); + if (_settings_client.music.playing) this->Play(); + + InvalidateWindowData(WC_MUSIC_WINDOW, 0); +} + +/** Skip to previous track */ +void MusicSystem::Prev() +{ + this->ChangePlaylistPosition(-1); + if (_settings_client.music.playing) this->Play(); + + InvalidateWindowData(WC_MUSIC_WINDOW, 0); +} + +/** Check that music is playing if it should, and that appropriate playlist is active for game/main menu */ +void MusicSystem::CheckStatus() +{ + if ((_game_mode == GM_MENU) != (this->selected_playlist == PLCH_THEMEONLY)) { + /* Make sure the theme-only playlist is active when on the title screen, and not during gameplay */ + this->ChangePlaylist((_game_mode == GM_MENU) ? PLCH_THEMEONLY : (PlaylistChoices)_settings_client.music.playlist); + } + if (this->active_playlist.empty()) return; + /* If we were supposed to be playing, but music has stopped, move to next song */ + if (this->IsPlaying() && !MusicDriver::GetInstance()->IsSongPlaying()) this->Next(); +} + +/** Is the player getting music right now? */ +bool MusicSystem::IsPlaying() const +{ + return _settings_client.music.playing && !this->active_playlist.empty(); +} + +/** Is shuffle mode enabled? */ +bool MusicSystem::IsShuffle() const +{ + return _settings_client.music.shuffle; +} + +/** Return the current song, or a dummy if none */ +MusicSystem::PlaylistEntry MusicSystem::GetCurrentSong() const +{ + if (!this->IsPlaying()) return PlaylistEntry(BaseMusic::GetUsedSet(), 0); + return this->active_playlist[this->playlist_position]; +} + +/** Is one of the custom playlists selected? */ +bool MusicSystem::IsCustomPlaylist() const +{ + return (this->selected_playlist == PLCH_CUSTOM1) || (this->selected_playlist == PLCH_CUSTOM2); +} + +/** + * Append a song to a custom playlist. + * Always adds to the currently active playlist. + * @param song_index Index of song in the current music set to add + */ +void MusicSystem::PlaylistAdd(size_t song_index) +{ + if (!this->IsCustomPlaylist()) return; + + /* Pick out song from the music set */ + if (song_index >= this->music_set.size()) return; + PlaylistEntry entry = this->music_set[song_index]; + + /* Check for maximum length */ + if (this->standard_playlists[this->selected_playlist].size() >= NUM_SONGS_PLAYLIST) return; + + /* Add it to the appropriate playlist, and the display */ + this->standard_playlists[this->selected_playlist].push_back(entry); + this->displayed_playlist.push_back(entry); + + /* Add it to the active playlist, if playback is shuffled select a random position to add at */ + if (this->active_playlist.empty()) { + this->active_playlist.push_back(entry); + if (this->IsPlaying()) this->Play(); + } else if (this->IsShuffle()) { + /* Generate a random position between 0 and n (inclusive, new length) to insert at */ + size_t maxpos = this->displayed_playlist.size(); + size_t newpos = InteractiveRandom() % maxpos; + this->active_playlist.insert(this->active_playlist.begin() + newpos, entry); + /* Make sure to shift up the current playback position if the song was inserted before it */ + if ((int)newpos <= this->playlist_position) this->playlist_position++; + } else { + this->active_playlist.push_back(entry); + } + + this->SaveCustomPlaylist(this->selected_playlist); + + InvalidateWindowData(WC_MUSIC_TRACK_SELECTION, 0); +} + +/** + * Remove a song from a custom playlist. + * @param song_index Index in the custom playlist to remove. + */ +void MusicSystem::PlaylistRemove(size_t song_index) +{ + if (!this->IsCustomPlaylist()) return; + + Playlist &pl = this->standard_playlists[this->selected_playlist]; + if (song_index >= pl.size()) return; + + /* Remove from "simple" playlists */ + PlaylistEntry song = pl[song_index]; + pl.erase(pl.begin() + song_index); + this->displayed_playlist.erase(this->displayed_playlist.begin() + song_index); + + /* Find in actual active playlist (may be shuffled) and remove, + * if it's the current song restart playback */ + for (size_t i = 0; i < this->active_playlist.size(); i++) { + Playlist::iterator s2 = this->active_playlist.begin() + i; + if (s2->filename == song.filename && s2->cat_index == song.cat_index) { + this->active_playlist.erase(s2); + if ((int)i == this->playlist_position && this->IsPlaying()) this->Play(); + break; + } + } + + this->SaveCustomPlaylist(this->selected_playlist); + + InvalidateWindowData(WC_MUSIC_TRACK_SELECTION, 0); +} + +/** + * Remove all songs from the current custom playlist. + * Effectively stops playback too. + */ +void MusicSystem::PlaylistClear() +{ + if (!this->IsCustomPlaylist()) return; + + this->standard_playlists[this->selected_playlist].clear(); + this->ChangePlaylist(this->selected_playlist); + + this->SaveCustomPlaylist(this->selected_playlist); +} + +/** + * Change playlist position pointer by the given offset, making sure to keep it within valid range. + * If the playlist is empty, position is always set to 0. + * @param ofs Amount to move playlist position by. + */ +void MusicSystem::ChangePlaylistPosition(int ofs) +{ + if (this->active_playlist.empty()) { + this->playlist_position = 0; + } else { + this->playlist_position += ofs; + while (this->playlist_position >= (int)this->active_playlist.size()) this->playlist_position -= (int)this->active_playlist.size(); + while (this->playlist_position < 0) this->playlist_position += (int)this->active_playlist.size(); + } +} + +/** + * Save a custom playlist to settings after modification. + * @param pl Playlist to store back + */ +void MusicSystem::SaveCustomPlaylist(PlaylistChoices pl) +{ + byte *settings_pl; + if (pl == PLCH_CUSTOM1) { + settings_pl = _settings_client.music.custom_1; + } else if (pl == PLCH_CUSTOM2) { + settings_pl = _settings_client.music.custom_2; + } else { + return; + } + + size_t num = 0; + MemSetT(settings_pl, 0, NUM_SONGS_PLAYLIST); + + for (Playlist::const_iterator song = this->standard_playlists[pl].begin(); song != this->standard_playlists[pl].end(); ++song) { + /* Music set indices in the settings playlist are 1-based, 0 means unused slot */ + settings_pl[num++] = (byte)song->set_index + 1; + } +} + + +/** + * Check music playback status and start/stop/song-finished. + * Called from main loop. + */ +void MusicLoop() +{ + _music.CheckStatus(); +} + +/** + * Change the configured music set and reset playback + * @param index Index of music set to switch to + */ +void ChangeMusicSet(int index) +{ + if (BaseMusic::GetIndexOfUsedSet() == index) return; + const char *name = BaseMusic::GetSet(index)->name; + _music.ChangeMusicSet(name); +} + +/** + * Prepare the music system for use. + * Called from \c InitializeGame + */ +void InitializeMusic() +{ + _music.BuildPlaylists(); +} + + struct MusicTrackSelectionWindow : public Window { MusicTrackSelectionWindow(WindowDesc *desc, WindowNumber number) : Window(desc) { @@ -312,6 +462,9 @@ struct MusicTrackSelectionWindow : public Window { case WID_MTS_PLAYLIST: SetDParam(0, STR_MUSIC_PLAYLIST_ALL + _settings_client.music.playlist); break; + case WID_MTS_CAPTION: + SetDParamStr(0, BaseMusic::GetUsedSet()->name); + break; } } @@ -349,13 +502,10 @@ struct MusicTrackSelectionWindow : public Window { case WID_MTS_LIST_LEFT: case WID_MTS_LIST_RIGHT: { Dimension d = {0, 0}; - for (uint i = 0; i < NUM_SONGS_AVAILABLE; i++) { - const char *song_name = GetSongName(i); - if (StrEmpty(song_name)) continue; - - SetDParam(0, GetTrackNumber(i)); + for (MusicSystem::Playlist::const_iterator song = _music.music_set.begin(); song != _music.music_set.end(); ++song) { + SetDParam(0, song->tracknr); SetDParam(1, 2); - SetDParamStr(2, GetSongName(i)); + SetDParamStr(2, song->songname); Dimension d2 = GetStringBoundingBox(STR_PLAYLIST_TRACK_NAME); d.width = max(d.width, d2.width); d.height += d2.height; @@ -375,13 +525,10 @@ struct MusicTrackSelectionWindow : public Window { GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, PC_BLACK); int y = r.top + WD_FRAMERECT_TOP; - for (uint i = 0; i < NUM_SONGS_AVAILABLE; i++) { - const char *song_name = GetSongName(i); - if (StrEmpty(song_name)) continue; - - SetDParam(0, GetTrackNumber(i)); + for (MusicSystem::Playlist::const_iterator song = _music.music_set.begin(); song != _music.music_set.end(); ++song) { + SetDParam(0, song->tracknr); SetDParam(1, 2); - SetDParamStr(2, song_name); + SetDParamStr(2, song->songname); DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_PLAYLIST_TRACK_NAME); y += FONT_HEIGHT_SMALL; } @@ -392,11 +539,10 @@ struct MusicTrackSelectionWindow : public Window { GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, PC_BLACK); int y = r.top + WD_FRAMERECT_TOP; - for (const byte *p = _playlists[_settings_client.music.playlist]; *p != 0; p++) { - uint i = *p - 1; - SetDParam(0, GetTrackNumber(i)); + for (MusicSystem::Playlist::const_iterator song = _music.active_playlist.begin(); song != _music.active_playlist.end(); ++song) { + SetDParam(0, song->tracknr); SetDParam(1, 2); - SetDParamStr(2, GetSongName(i)); + SetDParamStr(2, song->songname); DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_PLAYLIST_TRACK_NAME); y += FONT_HEIGHT_SMALL; } @@ -410,57 +556,42 @@ struct MusicTrackSelectionWindow : public Window { switch (widget) { case WID_MTS_LIST_LEFT: { // add to playlist int y = this->GetRowFromWidget(pt.y, widget, 0, FONT_HEIGHT_SMALL); - - if (_settings_client.music.playlist < 4) return; - if (!IsInsideMM(y, 0, BaseMusic::GetUsedSet()->num_available)) return; - - byte *p = _playlists[_settings_client.music.playlist]; - for (uint i = 0; i != NUM_SONGS_PLAYLIST - 1; i++) { - if (p[i] == 0) { - /* Find the actual song number */ - for (uint j = 0; j < NUM_SONGS_AVAILABLE; j++) { - if (GetTrackNumber(j) == y + 1) { - p[i] = j + 1; - break; - } - } - p[i + 1] = 0; - this->SetDirty(); - SelectSongToPlay(); - break; - } - } + _music.PlaylistAdd(y); break; } case WID_MTS_LIST_RIGHT: { // remove from playlist int y = this->GetRowFromWidget(pt.y, widget, 0, FONT_HEIGHT_SMALL); + _music.PlaylistRemove(y); + break; + } - if (_settings_client.music.playlist < 4) return; - if (!IsInsideMM(y, 0, NUM_SONGS_PLAYLIST)) return; - - byte *p = _playlists[_settings_client.music.playlist]; - for (uint i = y; i != NUM_SONGS_PLAYLIST - 1; i++) { - p[i] = p[i + 1]; - } - - this->SetDirty(); - SelectSongToPlay(); + case WID_MTS_MUSICSET: { + int selected = 0; + DropDownList *dropdown = BuildMusicSetDropDownList(&selected); + ShowDropDownList(this, dropdown, selected, widget, 0, true, false); break; } case WID_MTS_CLEAR: // clear - for (uint i = 0; _playlists[_settings_client.music.playlist][i] != 0; i++) _playlists[_settings_client.music.playlist][i] = 0; - this->SetDirty(); - StopMusic(); - SelectSongToPlay(); + _music.PlaylistClear(); break; case WID_MTS_ALL: case WID_MTS_OLD: case WID_MTS_NEW: case WID_MTS_EZY: case WID_MTS_CUSTOM1: case WID_MTS_CUSTOM2: // set playlist - SelectPlaylist(widget - WID_MTS_ALL); - StopMusic(); - SelectSongToPlay(); + _music.ChangePlaylist((MusicSystem::PlaylistChoices)(widget - WID_MTS_ALL)); + break; + } + } + + virtual void OnDropdownSelect(int widget, int index) + { + switch (widget) { + case WID_MTS_MUSICSET: + ChangeMusicSet(index); + break; + default: + NOT_REACHED(); break; } } @@ -469,7 +600,8 @@ struct MusicTrackSelectionWindow : public Window { static const NWidgetPart _nested_music_track_selection_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), - NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_PLAYLIST_MUSIC_PROGRAM_SELECTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), + NWidget(WWT_CAPTION, COLOUR_GREY, WID_MTS_CAPTION), SetDataTip(STR_PLAYLIST_MUSIC_SELECTION_SETNAME, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), + NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_MTS_MUSICSET), SetDataTip(STR_PLAYLIST_CHANGE_SET, STR_PLAYLIST_TOOLTIP_CHANGE_SET), EndContainer(), NWidget(WWT_PANEL, COLOUR_GREY), NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2), @@ -522,6 +654,20 @@ struct MusicWindow : public Window { this->InitNested(number); this->LowerWidget(_settings_client.music.playlist + WID_M_ALL); this->SetWidgetLoweredState(WID_M_SHUFFLE, _settings_client.music.shuffle); + + UpdateDisabledButtons(); + } + + void UpdateDisabledButtons() + { + /* Disable music control widgets if there is no music + * -- except Programme button! So you can still select a music set. */ + this->SetWidgetsDisabledState( + BaseMusic::GetUsedSet()->num_available == 0, + WID_M_PREV, WID_M_NEXT, WID_M_STOP, WID_M_PLAY, WID_M_SHUFFLE, + WID_M_ALL, WID_M_OLD, WID_M_NEW, WID_M_EZY, WID_M_CUSTOM1, WID_M_CUSTOM2, + WIDGET_LIST_END + ); } virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) @@ -548,8 +694,8 @@ struct MusicWindow : public Window { case WID_M_TRACK_NAME: { Dimension d = GetStringBoundingBox(STR_MUSIC_TITLE_NONE); - for (uint i = 0; i < NUM_SONGS_AVAILABLE; i++) { - SetDParamStr(0, GetSongName(i)); + for (MusicSystem::Playlist::const_iterator song = _music.music_set.begin(); song != _music.music_set.end(); ++song) { + SetDParamStr(0, song->songname); d = maxdim(d, GetStringBoundingBox(STR_MUSIC_TITLE_NAME)); } d.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT; @@ -571,9 +717,12 @@ struct MusicWindow : public Window { switch (widget) { case WID_M_TRACK_NR: { GfxFillRect(r.left + 1, r.top + 1, r.right, r.bottom, PC_BLACK); + if (BaseMusic::GetUsedSet()->num_available == 0) { + break; + } StringID str = STR_MUSIC_TRACK_NONE; - if (_song_is_active != 0 && _music_wnd_cursong != 0) { - SetDParam(0, GetTrackNumber(_music_wnd_cursong - 1)); + if (_music.IsPlaying()) { + SetDParam(0, _music.GetCurrentSong().tracknr); SetDParam(1, 2); str = STR_MUSIC_TRACK_DIGIT; } @@ -584,24 +733,24 @@ struct MusicWindow : public Window { case WID_M_TRACK_NAME: { GfxFillRect(r.left, r.top + 1, r.right - 1, r.bottom, PC_BLACK); StringID str = STR_MUSIC_TITLE_NONE; - if (_song_is_active != 0 && _music_wnd_cursong != 0) { + if (BaseMusic::GetUsedSet()->num_available == 0) { + str = STR_MUSIC_TITLE_NOMUSIC; + } else if (_music.IsPlaying()) { str = STR_MUSIC_TITLE_NAME; - SetDParamStr(0, GetSongName(_music_wnd_cursong - 1)); + SetDParamStr(0, _music.GetCurrentSong().songname); } DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, str, TC_FROMSTRING, SA_HOR_CENTER); break; } case WID_M_MUSIC_VOL: case WID_M_EFFECT_VOL: { - DrawFrameRect(r.left, r.top + 2, r.right, r.bottom - 2, COLOUR_GREY, FR_LOWERED); + int sw = ScaleGUITrad(slider_width); + int hsw = sw / 2; + DrawFrameRect(r.left + hsw, r.top + 2, r.right - hsw, r.bottom - 2, COLOUR_GREY, FR_LOWERED); byte volume = (widget == WID_M_MUSIC_VOL) ? _settings_client.music.music_vol : _settings_client.music.effect_vol; - int x = (volume * (r.right - r.left) / 127); - if (_current_text_dir == TD_RTL) { - x = r.right - x; - } else { - x += r.left; - } - DrawFrameRect(x, r.top, x + slider_width, r.bottom, COLOUR_GREY, FR_NONE); + if (_current_text_dir == TD_RTL) volume = 127 - volume; + int x = r.left + (volume * (r.right - r.left - sw) / 127); + DrawFrameRect(x, r.top, x + sw, r.bottom, COLOUR_GREY, FR_NONE); break; } } @@ -618,6 +767,9 @@ struct MusicWindow : public Window { for (int i = 0; i < 6; i++) { this->SetWidgetLoweredState(WID_M_ALL + i, i == _settings_client.music.playlist); } + + UpdateDisabledButtons(); + this->SetDirty(); } @@ -625,23 +777,19 @@ struct MusicWindow : public Window { { switch (widget) { case WID_M_PREV: // skip to prev - if (!_song_is_active) return; - SkipToPrevSong(); - this->SetDirty(); + _music.Prev(); break; case WID_M_NEXT: // skip to next - if (!_song_is_active) return; - SkipToNextSong(); - this->SetDirty(); + _music.Next(); break; case WID_M_STOP: // stop playing - _settings_client.music.playing = false; + _music.Stop(); break; case WID_M_PLAY: // start playing - _settings_client.music.playing = true; + _music.Play(); break; case WID_M_MUSIC_VOL: case WID_M_EFFECT_VOL: { // volume sliders @@ -651,9 +799,12 @@ struct MusicWindow : public Window { byte new_vol = x * 127 / this->GetWidget(widget)->current_x; if (_current_text_dir == TD_RTL) new_vol = 127 - new_vol; + /* Clamp to make sure min and max are properly settable */ + if (new_vol > 124) new_vol = 127; + if (new_vol < 3) new_vol = 0; if (new_vol != *vol) { *vol = new_vol; - if (widget == WID_M_MUSIC_VOL) MusicVolumeChanged(new_vol); + if (widget == WID_M_MUSIC_VOL) MusicDriver::GetInstance()->SetVolume(new_vol); this->SetDirty(); } @@ -662,12 +813,13 @@ struct MusicWindow : public Window { } case WID_M_SHUFFLE: // toggle shuffle - _settings_client.music.shuffle ^= 1; - this->SetWidgetLoweredState(WID_M_SHUFFLE, _settings_client.music.shuffle); + if (_music.IsShuffle()) { + _music.Unshuffle(); + } else { + _music.Shuffle(); + } + this->SetWidgetLoweredState(WID_M_SHUFFLE, _music.IsShuffle()); this->SetWidgetDirty(WID_M_SHUFFLE); - StopMusic(); - SelectSongToPlay(); - this->SetDirty(); break; case WID_M_PROGRAMME: // show track selection @@ -676,10 +828,7 @@ struct MusicWindow : public Window { case WID_M_ALL: case WID_M_OLD: case WID_M_NEW: case WID_M_EZY: case WID_M_CUSTOM1: case WID_M_CUSTOM2: // playlist - SelectPlaylist(widget - WID_M_ALL); - StopMusic(); - SelectSongToPlay(); - this->SetDirty(); + _music.ChangePlaylist((MusicSystem::PlaylistChoices)(widget - WID_M_ALL)); break; } } @@ -776,6 +925,5 @@ static WindowDesc _music_window_desc( void ShowMusicWindow() { - if (BaseMusic::GetUsedSet()->num_available == 0) ShowErrorMessage(STR_ERROR_NO_SONGS, INVALID_STRING_ID, WL_WARNING); AllocateWindowDescFront(&_music_window_desc, 0); } diff --git a/src/network/core/host.cpp b/src/network/core/host.cpp index cf98239f86..e431dde9fc 100644 --- a/src/network/core/host.cpp +++ b/src/network/core/host.cpp @@ -24,12 +24,7 @@ */ static void NetworkFindBroadcastIPsInternal(NetworkAddressList *broadcast); -#if defined(PSP) -static void NetworkFindBroadcastIPsInternal(NetworkAddressList *broadcast) // PSP implementation -{ -} - -#elif defined(BEOS_NET_SERVER) || defined(__HAIKU__) /* doesn't have neither getifaddrs or net/if.h */ +#if defined(BEOS_NET_SERVER) || defined(__HAIKU__) /* doesn't have neither getifaddrs or net/if.h */ /* Based on Andrew Bachmann's netstat+.c. Big thanks to him! */ extern "C" int _netstat(int fd, char **output, int verbose); diff --git a/src/network/core/os_abstraction.h b/src/network/core/os_abstraction.h index 9608f08fa7..c24cc9f8fe 100644 --- a/src/network/core/os_abstraction.h +++ b/src/network/core/os_abstraction.h @@ -194,29 +194,6 @@ static inline void OTTDfreeaddrinfo(struct addrinfo *ai) #define IPV6_V6ONLY 27 #endif -#if defined(PSP) -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include - -# define TCP_NODELAY 1 -# define SO_NONBLOCK 0x1009 -# define SOCKET int -# define INVALID_SOCKET -1 -# define INADDR_NONE 0xffffffff -# define closesocket close -# define GET_LAST_ERROR() sceNetInetGetErrno() -#endif /* PSP */ - /* OS/2 stuff */ #if defined(__OS2__) # define SOCKET int @@ -318,7 +295,7 @@ static inline bool SetNonBlocking(SOCKET d) #else int nonblocking = 1; #endif -#if (defined(__BEOS__) && defined(BEOS_NET_SERVER)) || defined(PSP) +#if (defined(__BEOS__) && defined(BEOS_NET_SERVER)) return setsockopt(d, SOL_SOCKET, SO_NONBLOCK, &nonblocking, sizeof(nonblocking)) == 0; #else return ioctlsocket(d, FIONBIO, &nonblocking) == 0; diff --git a/src/network/core/tcp_game.cpp b/src/network/core/tcp_game.cpp index 9b3f7b5ef3..caa378fc4c 100644 --- a/src/network/core/tcp_game.cpp +++ b/src/network/core/tcp_game.cpp @@ -45,6 +45,8 @@ NetworkRecvStatus NetworkGameSocketHandler::CloseConnection(bool error) { /* Clients drop back to the main menu */ if (!_network_server && _networking) { + extern void ClientNetworkEmergencySave(); // from network_client.cpp + ClientNetworkEmergencySave(); _switch_mode = SM_MENU; _networking = false; ShowErrorMessage(STR_NETWORK_ERROR_LOSTCONNECTION, INVALID_STRING_ID, WL_CRITICAL); diff --git a/src/network/core/udp.cpp b/src/network/core/udp.cpp index 20b1ce1196..d2dc15d427 100644 --- a/src/network/core/udp.cpp +++ b/src/network/core/udp.cpp @@ -252,8 +252,8 @@ void NetworkUDPSocketHandler::ReceiveNetworkGameInfo(Packet *p, NetworkGameInfo *dst = c; dst = &c->next; } + FALLTHROUGH; } - FALLTHROUGH; case 3: info->game_date = Clamp(p->Recv_uint32(), 0, MAX_DATE); diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index e3bcbb2d87..4b066681d7 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -119,6 +119,19 @@ struct PacketReader : LoadFilter { }; +/** + * Create an emergency savegame when the network connection is lost. + */ +void ClientNetworkEmergencySave() +{ + if (!_settings_client.gui.autosave_on_network_disconnect) return; + + const char *filename = "netsave.sav"; + DEBUG(net, 0, "Client: Performing emergency save (%s)", filename); + SaveOrLoad(filename, SLO_SAVE, DFT_GAME_FILE, AUTOSAVE_DIR, false); +} + + /** * Create a new socket for the client side of the game connection. * @param s The socket to connect with. @@ -670,6 +683,9 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ERROR(Packet *p ShowErrorMessage(err, INVALID_STRING_ID, WL_CRITICAL); + /* Perform an emergency save if we had already entered the game */ + if (this->status == STATUS_ACTIVE) ClientNetworkEmergencySave(); + DeleteWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN); return NETWORK_RECV_STATUS_SERVER_ERROR; @@ -1051,6 +1067,8 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_SHUTDOWN(Packet ShowErrorMessage(STR_NETWORK_MESSAGE_SERVER_SHUTDOWN, INVALID_STRING_ID, WL_CRITICAL); } + if (this->status == STATUS_ACTIVE) ClientNetworkEmergencySave(); + return NETWORK_RECV_STATUS_SERVER_ERROR; } @@ -1066,6 +1084,8 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_NEWGAME(Packet ShowErrorMessage(STR_NETWORK_MESSAGE_SERVER_REBOOT, INVALID_STRING_ID, WL_CRITICAL); } + if (this->status == STATUS_ACTIVE) ClientNetworkEmergencySave(); + return NETWORK_RECV_STATUS_SERVER_ERROR; } @@ -1153,6 +1173,7 @@ void ClientNetworkGameSocketHandler::CheckConnection() if (lag > 20) { this->NetworkGameSocketHandler::CloseConnection(); ShowErrorMessage(STR_NETWORK_ERROR_LOSTCONNECTION, INVALID_STRING_ID, WL_CRITICAL); + ClientNetworkEmergencySave(); return; } diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index bcee408528..c406b454d9 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -1115,7 +1115,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMMAND(Packet } if ((GetCommandFlags(cp.cmd) & CMD_SPECTATOR) == 0 && !Company::IsValidID(cp.company) && ci->client_id != CLIENT_ID_SERVER) { - IConsolePrintF(CC_ERROR, "WARNING: spectator issueing command from client %d (IP: %s), kicking...", ci->client_id, this->GetClientIP()); + IConsolePrintF(CC_ERROR, "WARNING: spectator issuing command from client %d (IP: %s), kicking...", ci->client_id, this->GetClientIP()); return this->SendError(NETWORK_ERROR_KICKED); } diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 5b1713709d..4cd61b95cf 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -313,8 +313,8 @@ struct GRFTempEngineData { Refittability refittability; ///< Did the newgrf set any refittability property? If not, default refittability will be applied. bool prop27_set; ///< Did the NewGRF set property 27 (misc flags)? uint8 rv_max_speed; ///< Temporary storage of RV prop 15, maximum speed in mph/0.8 - uint32 ctt_include_mask; ///< Cargo types always included in the refit mask. - uint32 ctt_exclude_mask; ///< Cargo types always excluded from the refit mask. + CargoTypes ctt_include_mask; ///< Cargo types always included in the refit mask. + CargoTypes ctt_exclude_mask; ///< Cargo types always excluded from the refit mask. /** * Update the summary refittability on setting a refittability property. @@ -943,11 +943,11 @@ static bool ReadSpriteLayout(ByteReader *buf, uint num_building_sprites, bool us } /** - * Translate the refit mask. + * Translate the refit mask. refit_mask is uint32 as it has not been mapped to CargoTypes. */ -static uint32 TranslateRefitMask(uint32 refit_mask) +static CargoTypes TranslateRefitMask(uint32 refit_mask) { - uint32 result = 0; + CargoTypes result = 0; uint8 bit; FOR_EACH_SET_BIT(bit, refit_mask) { CargoID cargo = GetCargoTranslation(bit, _cur.grffile, true); @@ -1310,7 +1310,7 @@ static ChangeInfoResult RailVehicleChangeInfo(uint engine, int numinfo, int prop uint8 count = buf->ReadByte(); _gted[e->index].UpdateRefittability(prop == 0x2C && count != 0); if (prop == 0x2C) _gted[e->index].defaultcargo_grf = _cur.grffile; - uint32 &ctt = prop == 0x2C ? _gted[e->index].ctt_include_mask : _gted[e->index].ctt_exclude_mask; + CargoTypes &ctt = prop == 0x2C ? _gted[e->index].ctt_include_mask : _gted[e->index].ctt_exclude_mask; ctt = 0; while (count--) { CargoID ctype = GetCargoTranslation(buf->ReadByte(), _cur.grffile); @@ -1498,7 +1498,7 @@ static ChangeInfoResult RoadVehicleChangeInfo(uint engine, int numinfo, int prop uint8 count = buf->ReadByte(); _gted[e->index].UpdateRefittability(prop == 0x24 && count != 0); if (prop == 0x24) _gted[e->index].defaultcargo_grf = _cur.grffile; - uint32 &ctt = prop == 0x24 ? _gted[e->index].ctt_include_mask : _gted[e->index].ctt_exclude_mask; + CargoTypes &ctt = prop == 0x24 ? _gted[e->index].ctt_include_mask : _gted[e->index].ctt_exclude_mask; ctt = 0; while (count--) { CargoID ctype = GetCargoTranslation(buf->ReadByte(), _cur.grffile); @@ -1670,7 +1670,7 @@ static ChangeInfoResult ShipVehicleChangeInfo(uint engine, int numinfo, int prop uint8 count = buf->ReadByte(); _gted[e->index].UpdateRefittability(prop == 0x1E && count != 0); if (prop == 0x1E) _gted[e->index].defaultcargo_grf = _cur.grffile; - uint32 &ctt = prop == 0x1E ? _gted[e->index].ctt_include_mask : _gted[e->index].ctt_exclude_mask; + CargoTypes &ctt = prop == 0x1E ? _gted[e->index].ctt_include_mask : _gted[e->index].ctt_exclude_mask; ctt = 0; while (count--) { CargoID ctype = GetCargoTranslation(buf->ReadByte(), _cur.grffile); @@ -1820,7 +1820,7 @@ static ChangeInfoResult AircraftVehicleChangeInfo(uint engine, int numinfo, int uint8 count = buf->ReadByte(); _gted[e->index].UpdateRefittability(prop == 0x1D && count != 0); if (prop == 0x1D) _gted[e->index].defaultcargo_grf = _cur.grffile; - uint32 &ctt = prop == 0x1D ? _gted[e->index].ctt_include_mask : _gted[e->index].ctt_exclude_mask; + CargoTypes &ctt = prop == 0x1D ? _gted[e->index].ctt_include_mask : _gted[e->index].ctt_exclude_mask; ctt = 0; while (count--) { CargoID ctype = GetCargoTranslation(buf->ReadByte(), _cur.grffile); @@ -2036,9 +2036,10 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, Byte break; case 0x12: // Cargo types for random triggers - statspec->cargo_triggers = buf->ReadDWord(); if (_cur.grffile->grf_version >= 7) { - statspec->cargo_triggers = TranslateRefitMask(statspec->cargo_triggers); + statspec->cargo_triggers = TranslateRefitMask(buf->ReadDWord()); + } else { + statspec->cargo_triggers = (CargoTypes)buf->ReadDWord(); } break; @@ -4740,7 +4741,7 @@ static void NewSpriteGroup(ByteReader *buf) } } - group->num_ranges = optimised.size(); + group->num_ranges = (uint)optimised.size(); // cast is safe, there should never be 2**31 elements here if (group->num_ranges > 0) { group->ranges = MallocT(group->num_ranges); MemCpyT(group->ranges, &optimised.front(), group->num_ranges); @@ -8305,9 +8306,9 @@ static void CalculateRefitMasks() /* Did the newgrf specify any refitting? If not, use defaults. */ if (_gted[engine].refittability != GRFTempEngineData::UNSET) { - uint32 mask = 0; - uint32 not_mask = 0; - uint32 xor_mask = ei->refit_mask; + CargoTypes mask = 0; + CargoTypes not_mask = 0; + CargoTypes xor_mask = ei->refit_mask; /* If the original masks set by the grf are zero, the vehicle shall only carry the default cargo. * Note: After applying the translations, the vehicle may end up carrying no defined cargo. It becomes unavailable in that case. */ @@ -8328,7 +8329,7 @@ static void CalculateRefitMasks() ei->refit_mask |= _gted[engine].ctt_include_mask; ei->refit_mask &= ~_gted[engine].ctt_exclude_mask; } else { - uint32 xor_mask = 0; + CargoTypes xor_mask = 0; /* Don't apply default refit mask to wagons nor engines with no capacity */ if (e->type != VEH_TRAIN || (e->u.rail.capacity != 0 && e->u.rail.railveh_type != RAILVEH_WAGON)) { diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp index c0aa160c25..d71e052da1 100644 --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -1033,8 +1033,8 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { break; } /* With double click, continue */ + FALLTHROUGH; } - FALLTHROUGH; case WID_NS_REMOVE: { // Remove GRF if (this->active_sel == NULL || !this->editable) break; @@ -1089,8 +1089,8 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { break; } /* With double click, continue */ + FALLTHROUGH; } - FALLTHROUGH; case WID_NS_ADD: if (this->avail_sel == NULL || !this->editable || HasBit(this->avail_sel->flags, GCF_INVALID)) break; diff --git a/src/newgrf_house.cpp b/src/newgrf_house.cpp index ebdd858a4d..314f02b3dc 100644 --- a/src/newgrf_house.cpp +++ b/src/newgrf_house.cpp @@ -56,7 +56,7 @@ static const GRFFile *GetHouseSpecGrf(HouseID house_id) */ HouseResolverObject::HouseResolverObject(HouseID house_id, TileIndex tile, Town *town, CallbackID callback, uint32 param1, uint32 param2, - bool not_yet_constructed, uint8 initial_random_bits, uint32 watched_cargo_triggers) + bool not_yet_constructed, uint8 initial_random_bits, CargoTypes watched_cargo_triggers) : ResolverObject(GetHouseSpecGrf(house_id), callback, param1, param2), house_scope(*this, house_id, tile, town, not_yet_constructed, initial_random_bits, watched_cargo_triggers), town_scope(*this, town, not_yet_constructed) // Don't access StorePSA if house is not yet constructed. @@ -409,7 +409,7 @@ static uint32 GetDistanceFromNearbyHouse(uint8 parameter, TileIndex tile, HouseI } uint16 GetHouseCallback(CallbackID callback, uint32 param1, uint32 param2, HouseID house_id, Town *town, TileIndex tile, - bool not_yet_constructed, uint8 initial_random_bits, uint32 watched_cargo_triggers) + bool not_yet_constructed, uint8 initial_random_bits, CargoTypes watched_cargo_triggers) { assert(IsValidTile(tile) && (not_yet_constructed || IsTileType(tile, MP_HOUSE))); @@ -472,13 +472,13 @@ void DrawNewHouseTile(TileInfo *ti, HouseID house_id) } /* Simple wrapper for GetHouseCallback to keep the animation unified. */ -uint16 GetSimpleHouseCallback(CallbackID callback, uint32 param1, uint32 param2, const HouseSpec *spec, Town *town, TileIndex tile, uint32 extra_data) +uint16 GetSimpleHouseCallback(CallbackID callback, uint32 param1, uint32 param2, const HouseSpec *spec, Town *town, TileIndex tile, CargoTypes extra_data) { return GetHouseCallback(callback, param1, param2, spec - HouseSpec::Get(0), town, tile, false, 0, extra_data); } /** Helper class for animation control. */ -struct HouseAnimationBase : public AnimationBase { +struct HouseAnimationBase : public AnimationBase { static const CallbackID cb_animation_speed = CBID_HOUSE_ANIMATION_SPEED; static const CallbackID cb_animation_next_frame = CBID_HOUSE_ANIMATION_NEXT_FRAME; @@ -633,7 +633,7 @@ void TriggerHouse(TileIndex t, HouseTrigger trigger) * @param trigger_cargoes Cargo types that triggered the callback. * @param random Random bits. */ -void DoWatchedCargoCallback(TileIndex tile, TileIndex origin, uint32 trigger_cargoes, uint16 random) +void DoWatchedCargoCallback(TileIndex tile, TileIndex origin, CargoTypes trigger_cargoes, uint16 random) { TileIndexDiffC diff = TileIndexToTileIndexDiffC(origin, tile); uint32 cb_info = random << 16 | (uint8)diff.y << 8 | (uint8)diff.x; @@ -646,7 +646,7 @@ void DoWatchedCargoCallback(TileIndex tile, TileIndex origin, uint32 trigger_car * @param trigger_cargoes Triggering cargo types. * @pre IsTileType(t, MP_HOUSE) */ -void WatchedCargoCallback(TileIndex tile, uint32 trigger_cargoes) +void WatchedCargoCallback(TileIndex tile, CargoTypes trigger_cargoes) { assert(IsTileType(tile, MP_HOUSE)); HouseID id = GetHouseType(tile); diff --git a/src/newgrf_house.h b/src/newgrf_house.h index 0ac868d1e7..bb364f6fc6 100644 --- a/src/newgrf_house.h +++ b/src/newgrf_house.h @@ -25,7 +25,7 @@ struct HouseScopeResolver : public ScopeResolver { Town *town; ///< Town of this house. bool not_yet_constructed; ///< True for construction check. uint16 initial_random_bits; ///< Random bits during construction checks. - uint32 watched_cargo_triggers; ///< Cargo types that triggered the watched cargo callback. + CargoTypes watched_cargo_triggers; ///< Cargo types that triggered the watched cargo callback. /** * Constructor of a house scope resolver. @@ -38,7 +38,7 @@ struct HouseScopeResolver : public ScopeResolver { * @param watched_cargo_triggers Cargo types that triggered the watched cargo callback. */ HouseScopeResolver(ResolverObject &ro, HouseID house_id, TileIndex tile, Town *town, - bool not_yet_constructed, uint8 initial_random_bits, uint32 watched_cargo_triggers) + bool not_yet_constructed, uint8 initial_random_bits, CargoTypes watched_cargo_triggers) : ScopeResolver(ro), house_id(house_id), tile(tile), town(town), not_yet_constructed(not_yet_constructed), initial_random_bits(initial_random_bits), watched_cargo_triggers(watched_cargo_triggers) { @@ -56,7 +56,7 @@ struct HouseResolverObject : public ResolverObject { HouseResolverObject(HouseID house_id, TileIndex tile, Town *town, CallbackID callback = CBID_NO_CALLBACK, uint32 param1 = 0, uint32 param2 = 0, - bool not_yet_constructed = false, uint8 initial_random_bits = 0, uint32 watched_cargo_triggers = 0); + bool not_yet_constructed = false, uint8 initial_random_bits = 0, CargoTypes watched_cargo_triggers = 0); /* virtual */ ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, byte relative = 0) { @@ -97,8 +97,8 @@ void AnimateNewHouseTile(TileIndex tile); void AnimateNewHouseConstruction(TileIndex tile); uint16 GetHouseCallback(CallbackID callback, uint32 param1, uint32 param2, HouseID house_id, Town *town, TileIndex tile, - bool not_yet_constructed = false, uint8 initial_random_bits = 0, uint32 watched_cargo_triggers = 0); -void WatchedCargoCallback(TileIndex tile, uint32 trigger_cargoes); + bool not_yet_constructed = false, uint8 initial_random_bits = 0, CargoTypes watched_cargo_triggers = 0); +void WatchedCargoCallback(TileIndex tile, CargoTypes trigger_cargoes); bool CanDeleteHouse(TileIndex tile); diff --git a/src/newgrf_object.cpp b/src/newgrf_object.cpp index 78bbc52443..40a966a166 100644 --- a/src/newgrf_object.cpp +++ b/src/newgrf_object.cpp @@ -96,7 +96,9 @@ uint ObjectSpec::Index() const void ResetObjects() { /* Clean the pool. */ - MemSetT(_object_specs, 0, lengthof(_object_specs)); + for (uint16 i = 0; i < NUM_OBJECTS; i++) { + _object_specs[i] = {}; + } /* And add our originals. */ MemCpyT(_object_specs, _original_objects, lengthof(_original_objects)); diff --git a/src/newgrf_object.h b/src/newgrf_object.h index 69e1a3299c..43c8de031c 100644 --- a/src/newgrf_object.h +++ b/src/newgrf_object.h @@ -138,8 +138,8 @@ struct ObjectResolverObject : public ResolverObject { case VSG_SCOPE_PARENT: { TownScopeResolver *tsr = this->GetTown(); if (tsr != NULL) return tsr; + FALLTHROUGH; } - FALLTHROUGH; default: return ResolverObject::GetScope(scope, relative); diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp index 41ef7af75c..5271b2bfc9 100644 --- a/src/newgrf_station.cpp +++ b/src/newgrf_station.cpp @@ -963,7 +963,7 @@ void TriggerStationRandomisation(Station *st, TileIndex tile, StationRandomTrigg uint32 whole_reseed = 0; ETileArea area = ETileArea(st, tile, tas[trigger]); - uint32 empty_mask = 0; + CargoTypes empty_mask = 0; if (trigger == SRT_CARGO_TAKEN) { /* Create a bitmask of completely empty cargo types to be matched */ for (CargoID i = 0; i < NUM_CARGO; i++) { diff --git a/src/newgrf_station.h b/src/newgrf_station.h index 5413a4c08f..123330d0ad 100644 --- a/src/newgrf_station.h +++ b/src/newgrf_station.h @@ -68,8 +68,8 @@ struct StationResolverObject : public ResolverObject { case VSG_SCOPE_PARENT: { TownScopeResolver *tsr = this->GetTown(); if (tsr != NULL) return tsr; + FALLTHROUGH; } - FALLTHROUGH; default: return ResolverObject::GetScope(scope, relative); @@ -153,7 +153,7 @@ struct StationSpec { */ uint16 cargo_threshold; - uint32 cargo_triggers; ///< Bitmask of cargo types which cause trigger re-randomizing + CargoTypes cargo_triggers; ///< Bitmask of cargo types which cause trigger re-randomizing byte callback_mask; ///< Bitmask of station callbacks that have to be called diff --git a/src/newgrf_town.cpp b/src/newgrf_town.cpp index 820e2be689..00fcf76b63 100644 --- a/src/newgrf_town.cpp +++ b/src/newgrf_town.cpp @@ -50,7 +50,7 @@ case 0x81: return GB(this->t->xy, 8, 8); case 0x82: return ClampToU16(this->t->cache.population); case 0x83: return GB(ClampToU16(this->t->cache.population), 8, 8); - case 0x8A: return this->t->grow_counter; + case 0x8A: return this->t->grow_counter / TOWN_GROWTH_TICKS; case 0x92: return this->t->flags; // In original game, 0x92 and 0x93 are really one word. Since flags is a byte, this is to adjust case 0x93: return 0; case 0x94: return ClampToU16(this->t->cache.squared_town_zone_radius[0]); @@ -82,7 +82,7 @@ case 0xAE: return this->t->have_ratings; case 0xB2: return this->t->statues; case 0xB6: return ClampToU16(this->t->cache.num_houses); - case 0xB9: return this->t->growth_rate & (~TOWN_GROW_RATE_CUSTOM); + case 0xB9: return this->t->growth_rate / TOWN_GROWTH_TICKS; case 0xBA: return ClampToU16(this->t->supplied[CT_PASSENGERS].new_max); case 0xBB: return GB(ClampToU16(this->t->supplied[CT_PASSENGERS].new_max), 8, 8); case 0xBC: return ClampToU16(this->t->supplied[CT_MAIL].new_max); diff --git a/src/object_cmd.cpp b/src/object_cmd.cpp index f7ba0d995b..9f03813dfb 100644 --- a/src/object_cmd.cpp +++ b/src/object_cmd.cpp @@ -540,7 +540,7 @@ static CommandCost ClearTile_Object(TileIndex tile, DoCommandFlag flags) return cost; } -static void AddAcceptedCargo_Object(TileIndex tile, CargoArray &acceptance, uint32 *always_accepted) +static void AddAcceptedCargo_Object(TileIndex tile, CargoArray &acceptance, CargoTypes *always_accepted) { if (!IsObjectType(tile, OBJECT_HQ)) return; diff --git a/src/openttd.cpp b/src/openttd.cpp index e9a52d0f81..43c22fdffa 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -63,6 +63,7 @@ #include "subsidy_func.h" #include "gfx_layout.h" #include "viewport_sprite_sorter.h" +#include "framerate_type.h" #include "thread/thread.h" #include "linkgraph/linkgraphschedule.h" @@ -373,8 +374,7 @@ static void LoadIntroGame(bool load_newgrfs = true) CheckForMissingGlyphs(); - /* Play main theme */ - if (MusicDriver::GetInstance()->IsSongPlaying()) ResetMusic(); + MusicLoop(); // ensure music is correct } void MakeNewgameSettingsLive() @@ -725,11 +725,6 @@ int openttd_main(int argc, char *argv[]) goto exit_noshutdown; } -#if defined(WINCE) && defined(_DEBUG) - /* Switch on debug lvl 4 for WinCE if Debug release, as you can't give params, and you most likely do want this information */ - SetDebugString("4"); -#endif - DeterminePaths(argv[0]); TarScanner::DoScan(TarScanner::BASESET); @@ -1375,6 +1370,14 @@ void StateGameLoop() { /* don't execute the state loop during pause */ if (_pause_mode != PM_UNPAUSED) { + PerformanceMeasurer::Paused(PFE_GAMELOOP); + PerformanceMeasurer::Paused(PFE_GL_ECONOMY); + PerformanceMeasurer::Paused(PFE_GL_TRAINS); + PerformanceMeasurer::Paused(PFE_GL_ROADVEHS); + PerformanceMeasurer::Paused(PFE_GL_SHIPS); + PerformanceMeasurer::Paused(PFE_GL_AIRCRAFT); + PerformanceMeasurer::Paused(PFE_GL_LANDSCAPE); + UpdateLandscapingLimits(); #ifndef DEBUG_DUMP_COMMANDS Game::GameLoop(); @@ -1382,6 +1385,9 @@ void StateGameLoop() CallWindowTickEvent(); return; } + + PerformanceMeasurer framerate(PFE_GAMELOOP); + PerformanceAccumulator::Reset(PFE_GL_LANDSCAPE); if (HasModalProgress()) return; Layouter::ReduceLineCache(); @@ -1440,11 +1446,6 @@ static void DoAutosave() { char buf[MAX_PATH]; -#if defined(PSP) - /* Autosaving in networking is too time expensive for the PSP */ - if (_networking) return; -#endif /* PSP */ - if (_settings_client.gui.keep_all_autosave) { GenerateDefaultSaveName(buf, lastof(buf)); strecat(buf, ".sav", lastof(buf)); diff --git a/src/os/unix/unix.cpp b/src/os/unix/unix.cpp index d7c2304ce5..bea69ec931 100644 --- a/src/os/unix/unix.cpp +++ b/src/os/unix/unix.cpp @@ -308,9 +308,7 @@ bool GetClipboardContents(char *buffer, const char *last) void CSleep(int milliseconds) { - #if defined(PSP) - sceKernelDelayThread(milliseconds * 1000); - #elif defined(__BEOS__) + #if defined(__BEOS__) snooze(milliseconds * 1000); #elif defined(__AMIGA__) { diff --git a/src/os/windows/string_uniscribe.cpp b/src/os/windows/string_uniscribe.cpp new file mode 100644 index 0000000000..ea8b8c0224 --- /dev/null +++ b/src/os/windows/string_uniscribe.cpp @@ -0,0 +1,610 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file string_uniscribe.cpp Functions related to laying out text on Win32. */ + +#if defined(WITH_UNISCRIBE) + +#include "../../stdafx.h" +#include "../../debug.h" +#include "string_uniscribe.h" +#include "../../language.h" +#include "../../strings_func.h" +#include "../../string_func.h" +#include "../../table/control_codes.h" +#include "win32.h" +#include + +#include +#include + +#include "../../safeguards.h" + +#ifdef _MSC_VER +# pragma comment(lib, "usp10") +#endif + + +/** Uniscribe cache for internal font information, cleared when OTTD changes fonts. */ +static SCRIPT_CACHE _script_cache[FS_END]; + +/** + * Contains all information about a run of characters. A run are consecutive + * characters that share a single font and language. + */ +struct UniscribeRun { + int pos; + int len; + Font *font; + + std::vector ft_glyphs; + + SCRIPT_ANALYSIS sa; + std::vector char_to_glyph; + + std::vector vis_attribs; + std::vector glyphs; + std::vector advances; + std::vector offsets; + int total_advance; + + UniscribeRun(int pos, int len, Font *font, SCRIPT_ANALYSIS &sa) : pos(pos), len(len), font(font), sa(sa) {} +}; + +/** Break a string into language formatting ranges. */ +static std::vector UniscribeItemizeString(UniscribeParagraphLayoutFactory::CharType *buff, int32 length); +/** Generate and place glyphs for a run of characters. */ +static bool UniscribeShapeRun(const UniscribeParagraphLayoutFactory::CharType *buff, UniscribeRun &range); + +/** + * Wrapper for doing layouts with Uniscribe. + */ +class UniscribeParagraphLayout : public ParagraphLayouter { +private: + const UniscribeParagraphLayoutFactory::CharType *text_buffer; + + std::vector ranges; ///< All runs of the text. + std::vector::iterator cur_range; ///< The next run to be output. + int cur_range_offset = 0; ///< Offset from the start of the current run from where to output. + +public: + /** Visual run contains data about the bit of text with the same font. */ + class UniscribeVisualRun : public ParagraphLayouter::VisualRun { + private: + std::vector glyphs; + std::vector positions; + std::vector char_to_glyph; + + int start_pos; + int total_advance; + int num_glyphs; + Font *font; + + mutable int *glyph_to_char = NULL; + + public: + UniscribeVisualRun(const UniscribeRun &range, int x); + virtual ~UniscribeVisualRun() + { + free(this->glyph_to_char); + } + + virtual const GlyphID *GetGlyphs() const { return &this->glyphs[0]; } + virtual const float *GetPositions() const { return &this->positions[0]; } + virtual const int *GetGlyphToCharMap() const; + + virtual const Font *GetFont() const { return this->font; } + virtual int GetLeading() const { return this->font->fc->GetHeight(); } + virtual int GetGlyphCount() const { return this->num_glyphs; } + int GetAdvance() const { return this->total_advance; } + }; + + /** A single line worth of VisualRuns. */ + class UniscribeLine : public AutoDeleteSmallVector, public ParagraphLayouter::Line { + public: + virtual int GetLeading() const; + virtual int GetWidth() const; + virtual int CountRuns() const { return this->Length(); } + virtual const VisualRun *GetVisualRun(int run) const { return *this->Get(run); } + + int GetInternalCharLength(WChar c) const + { + /* Uniscribe uses UTF-16 internally which means we need to account for surrogate pairs. */ + return c >= 0x010000U ? 2 : 1; + } + }; + + UniscribeParagraphLayout(std::vector &ranges, const UniscribeParagraphLayoutFactory::CharType *buffer) : text_buffer(buffer), ranges(ranges) + { + this->Reflow(); + } + + virtual ~UniscribeParagraphLayout() {} + + virtual void Reflow() + { + this->cur_range = this->ranges.begin(); + this->cur_range_offset = 0; + } + + virtual const Line *NextLine(int max_width); +}; + +void UniscribeResetScriptCache(FontSize size) +{ + if (_script_cache[size] != NULL) { + ScriptFreeCache(&_script_cache[size]); + _script_cache[size] = NULL; + } +} + +/** Load the matching native Windows font. */ +static HFONT HFontFromFont(Font *font) +{ + LOGFONT logfont; + ZeroMemory(&logfont, sizeof(LOGFONT)); + logfont.lfHeight = font->fc->GetHeight(); + logfont.lfWeight = FW_NORMAL; + logfont.lfCharSet = DEFAULT_CHARSET; + convert_to_fs(font->fc->GetFontName(), logfont.lfFaceName, lengthof(logfont.lfFaceName)); + + return CreateFontIndirect(&logfont); +} + +/** Determine the glyph positions for a run. */ +static bool UniscribeShapeRun(const UniscribeParagraphLayoutFactory::CharType *buff, UniscribeRun &range) +{ + /* Initial size guess for the number of glyphs recommended by Uniscribe. */ + range.glyphs.resize(range.len * 3 / 2 + 16); + range.vis_attribs.resize(range.glyphs.size()); + + /* The char-to-glyph array is the same size as the input. */ + range.char_to_glyph.resize(range.len); + + HDC temp_dc = NULL; + HFONT old_font = NULL; + HFONT cur_font = NULL; + + while (true) { + /* Shape the text run by determining the glyphs needed for display. */ + int glyphs_used = 0; + HRESULT hr = ScriptShape(temp_dc, &_script_cache[range.font->fc->GetSize()], buff + range.pos, range.len, (int)range.glyphs.size(), &range.sa, &range.glyphs[0], &range.char_to_glyph[0], &range.vis_attribs[0], &glyphs_used); + + if (SUCCEEDED(hr)) { + range.glyphs.resize(glyphs_used); + range.vis_attribs.resize(glyphs_used); + + /* Calculate the glyph positions. */ + ABC abc; + range.advances.resize(range.glyphs.size()); + range.offsets.resize(range.glyphs.size()); + hr = ScriptPlace(temp_dc, &_script_cache[range.font->fc->GetSize()], &range.glyphs[0], (int)range.glyphs.size(), &range.vis_attribs[0], &range.sa, &range.advances[0], &range.offsets[0], &abc); + if (SUCCEEDED(hr)) { + /* We map our special sprite chars to values that don't fit into a WORD. Copy the glyphs + * into a new vector and query the real glyph to use for these special chars. */ + range.ft_glyphs.resize(range.glyphs.size()); + for (size_t g_id = 0; g_id < range.glyphs.size(); g_id++) { + range.ft_glyphs[g_id] = range.glyphs[g_id]; + } + for (int i = 0; i < range.len; i++) { + if (buff[range.pos + i] >= SCC_SPRITE_START && buff[range.pos + i] <= SCC_SPRITE_END) { + range.ft_glyphs[range.char_to_glyph[i]] = range.font->fc->MapCharToGlyph(buff[range.pos + i]); + } + } + + /* FreeType and GDI/Uniscribe seems to occasionally disagree over the width of a glyph. */ + range.total_advance = 0; + for (size_t i = 0; i < range.advances.size(); i++) { + if (range.advances[i] > 0 && range.ft_glyphs[i] != 0xFFFF) range.advances[i] = range.font->fc->GetGlyphWidth(range.ft_glyphs[i]); + range.total_advance += range.advances[i]; + } + break; + } + } + + if (hr == E_OUTOFMEMORY) { + /* The glyph buffer needs to be larger. Just double it every time. */ + range.glyphs.resize(range.glyphs.size() * 2); + range.vis_attribs.resize(range.vis_attribs.size() * 2); + } else if (hr == E_PENDING) { + /* Glyph data is not in cache, load native font. */ + cur_font = HFontFromFont(range.font); + if (cur_font == NULL) return false; // Sorry, no dice. + + temp_dc = CreateCompatibleDC(NULL); + SetMapMode(temp_dc, MM_TEXT); + old_font = (HFONT)SelectObject(temp_dc, cur_font); + } else if (hr == USP_E_SCRIPT_NOT_IN_FONT && range.sa.eScript != SCRIPT_UNDEFINED) { + /* Try again with the generic shaping engine. */ + range.sa.eScript = SCRIPT_UNDEFINED; + } else { + /* Some unknown other error. */ + if (temp_dc != NULL) { + SelectObject(temp_dc, old_font); + DeleteObject(cur_font); + ReleaseDC(NULL, temp_dc); + } + return false; + } + } + + if (temp_dc != NULL) { + SelectObject(temp_dc, old_font); + DeleteObject(cur_font); + ReleaseDC(NULL, temp_dc); + } + + return true; +} + +static std::vector UniscribeItemizeString(UniscribeParagraphLayoutFactory::CharType *buff, int32 length) +{ + /* Itemize text. */ + SCRIPT_CONTROL control; + ZeroMemory(&control, sizeof(SCRIPT_CONTROL)); + control.uDefaultLanguage = _current_language->winlangid; + + SCRIPT_STATE state; + ZeroMemory(&state, sizeof(SCRIPT_STATE)); + state.uBidiLevel = _current_text_dir == TD_RTL ? 1 : 0; + + std::vector items(16); + while (true) { + /* We subtract one from max_items to work around a buffer overflow on some older versions of Windows. */ + int generated = 0; + HRESULT hr = ScriptItemize(buff, length, (int)items.size() - 1, &control, &state, &items[0], &generated); + + if (SUCCEEDED(hr)) { + /* Resize the item buffer. Note that Uniscribe will always add an additional end sentinel item. */ + items.resize(generated + 1); + break; + } + /* Some kind of error except item buffer too small. */ + if (hr != E_OUTOFMEMORY) return std::vector(); + + items.resize(items.size() * 2); + } + + return items; +} + +/* static */ ParagraphLayouter *UniscribeParagraphLayoutFactory::GetParagraphLayout(CharType *buff, CharType *buff_end, FontMap &fontMapping) +{ + int32 length = buff_end - buff; + /* Can't layout an empty string. */ + if (length == 0) return NULL; + + /* Can't layout our in-built sprite fonts. */ + for (FontMap::const_iterator i = fontMapping.Begin(); i != fontMapping.End(); i++) { + if (i->second->fc->IsBuiltInFont()) return NULL; + } + + /* Itemize text. */ + std::vector items = UniscribeItemizeString(buff, length); + if (items.size() == 0) return NULL; + + /* Build ranges from the items and the font map. A range is a run of text + * that is part of a single item and formatted using a single font style. */ + std::vector ranges; + + int cur_pos = 0; + std::vector::iterator cur_item = items.begin(); + for (FontMap::const_iterator i = fontMapping.Begin(); i != fontMapping.End(); i++) { + while (cur_pos < i->first && cur_item != items.end() - 1) { + /* Add a range that spans the intersection of the remaining item and font run. */ + int stop_pos = min(i->first, (cur_item + 1)->iCharPos); + assert(stop_pos - cur_pos > 0); + ranges.push_back(UniscribeRun(cur_pos, stop_pos - cur_pos, i->second, cur_item->a)); + + /* Shape the range. */ + if (!UniscribeShapeRun(buff, ranges.back())) { + return NULL; + } + + /* If we are at the end of the current item, advance to the next item. */ + if (stop_pos == (cur_item + 1)->iCharPos) cur_item++; + cur_pos = stop_pos; + } + } + + return new UniscribeParagraphLayout(ranges, buff); +} + +/* virtual */ const ParagraphLayouter::Line *UniscribeParagraphLayout::NextLine(int max_width) +{ + std::vector::iterator start_run = this->cur_range; + std::vector::iterator last_run = this->cur_range; + + if (start_run == this->ranges.end()) return NULL; + + /* Add remaining width of the first run if it is a broken run. */ + int cur_width = 0; + if (this->cur_range_offset != 0) { + std::vector dx(start_run->len); + ScriptGetLogicalWidths(&start_run->sa, start_run->len, (int)start_run->glyphs.size(), &start_run->advances[0], &start_run->char_to_glyph[0], &start_run->vis_attribs[0], &dx[0]); + + for (std::vector::const_iterator c = dx.begin() + this->cur_range_offset; c != dx.end(); c++) { + cur_width += *c; + } + ++last_run; + } + + /* Gather runs until the line is full. */ + while (last_run != this->ranges.end() && cur_width < max_width) { + cur_width += last_run->total_advance; + ++last_run; + } + + /* If the text does not fit into the available width, find a suitable breaking point. */ + int remaing_offset = (last_run - 1)->len; + if (cur_width > max_width) { + std::vector log_attribs; + + /* Get word break information. */ + int width_avail = max_width; + int num_chars = this->cur_range_offset; + int start_offs = this->cur_range_offset; + int last_cluster = this->cur_range_offset + 1; + for (std::vector::iterator r = start_run; r != last_run; r++) { + log_attribs.resize(r->pos - start_run->pos + r->len); + if (FAILED(ScriptBreak(this->text_buffer + r->pos + start_offs, r->len - start_offs, &r->sa, &log_attribs[r->pos - start_run->pos + start_offs]))) return NULL; + + std::vector dx(r->len); + ScriptGetLogicalWidths(&r->sa, r->len, (int)r->glyphs.size(), &r->advances[0], &r->char_to_glyph[0], &r->vis_attribs[0], &dx[0]); + + /* Count absolute max character count on the line. */ + for (int c = start_offs; c < r->len && width_avail > 0; c++, num_chars++) { + if (c > start_offs && log_attribs[num_chars].fCharStop) last_cluster = num_chars; + width_avail -= dx[c]; + } + + start_offs = 0; + } + + /* Walk backwards to find the last suitable breaking point. */ + while (--num_chars > this->cur_range_offset && !log_attribs[num_chars].fSoftBreak && !log_attribs[num_chars].fWhiteSpace) {} + + if (num_chars == this->cur_range_offset) { + /* Didn't find any suitable word break point, just break on the last cluster boundary. */ + num_chars = last_cluster; + } + + /* Include whitespace characters after the breaking point. */ + while (num_chars < (int)log_attribs.size() && log_attribs[num_chars].fWhiteSpace) { + num_chars++; + } + + /* Get last run that corresponds to the number of characters to show. */ + for (std::vector::iterator run = start_run; run != last_run; run++) { + num_chars -= run->len; + + if (num_chars <= 0) { + remaing_offset = num_chars + run->len + 1; + last_run = run + 1; + assert(remaing_offset - 1 > 0); + break; + } + } + } + + /* Build display order from the runs. */ + std::vector bidi_level; + for (std::vector::iterator r = start_run; r != last_run; r++) { + bidi_level.push_back(r->sa.s.uBidiLevel); + } + std::vector vis_to_log(bidi_level.size()); + if (FAILED(ScriptLayout((int)bidi_level.size(), &bidi_level[0], &vis_to_log[0], NULL))) return NULL; + + /* Create line. */ + UniscribeLine *line = new UniscribeLine(); + + int cur_pos = 0; + for (std::vector::iterator l = vis_to_log.begin(); l != vis_to_log.end(); l++) { + std::vector::iterator i_run = start_run + *l; + UniscribeRun run = *i_run; + + /* Partial run after line break (either start or end)? Reshape run to get the first/last glyphs right. */ + if (i_run == last_run - 1 && remaing_offset < (last_run - 1)->len) { + run.len = remaing_offset - 1; + + if (!UniscribeShapeRun(this->text_buffer, run)) return NULL; + } + if (i_run == start_run && this->cur_range_offset > 0) { + assert(run.len - this->cur_range_offset > 0); + run.pos += this->cur_range_offset; + run.len -= this->cur_range_offset; + + if (!UniscribeShapeRun(this->text_buffer, run)) return NULL; + } + + *line->Append() = new UniscribeVisualRun(run, cur_pos); + cur_pos += run.total_advance; + } + + if (remaing_offset < (last_run - 1)->len) { + /* We didn't use up all of the last run, store remainder for the next line. */ + this->cur_range_offset = remaing_offset - 1; + this->cur_range = last_run - 1; + assert(this->cur_range->len > this->cur_range_offset); + } else { + this->cur_range_offset = 0; + this->cur_range = last_run; + } + + return line; +} + +/** + * Get the height of the line. + * @return The maximum height of the line. + */ +int UniscribeParagraphLayout::UniscribeLine::GetLeading() const +{ + int leading = 0; + for (const UniscribeVisualRun * const *run = this->Begin(); run != this->End(); run++) { + leading = max(leading, (*run)->GetLeading()); + } + + return leading; +} + +/** + * Get the width of this line. + * @return The width of the line. + */ +int UniscribeParagraphLayout::UniscribeLine::GetWidth() const +{ + int length = 0; + for (const UniscribeVisualRun * const *run = this->Begin(); run != this->End(); run++) { + length += (*run)->GetAdvance(); + } + + return length; +} + +UniscribeParagraphLayout::UniscribeVisualRun::UniscribeVisualRun(const UniscribeRun &range, int x) : glyphs(range.ft_glyphs), char_to_glyph(range.char_to_glyph), start_pos(range.pos), total_advance(range.total_advance), font(range.font) +{ + this->num_glyphs = (int)glyphs.size(); + this->positions.resize(this->num_glyphs * 2 + 2); + + int advance = 0; + for (int i = 0; i < this->num_glyphs; i++) { + this->positions[i * 2 + 0] = range.offsets[i].du + advance + x; + this->positions[i * 2 + 1] = range.offsets[i].dv; + + advance += range.advances[i]; + } + this->positions[this->num_glyphs * 2] = advance + x; +} + +const int *UniscribeParagraphLayout::UniscribeVisualRun::GetGlyphToCharMap() const +{ + if (this->glyph_to_char == NULL) { + this->glyph_to_char = CallocT(this->GetGlyphCount()); + + /* The char to glyph array contains the first glyph index of the cluster that is associated + * with each character. It is possible for a cluster to be formed of several chars. */ + for (int c = 0; c < (int)this->char_to_glyph.size(); c++) { + /* If multiple chars map to one glyph, only refer back to the first character. */ + if (this->glyph_to_char[this->char_to_glyph[c]] == 0) this->glyph_to_char[this->char_to_glyph[c]] = c + this->start_pos; + } + + /* We only marked the first glyph of each cluster in the loop above. Fill the gaps. */ + int last_char = this->glyph_to_char[0]; + for (int g = 0; g < this->GetGlyphCount(); g++) { + if (this->glyph_to_char[g] != 0) last_char = this->glyph_to_char[g]; + this->glyph_to_char[g] = last_char; + } + } + + return this->glyph_to_char; +} + + +/* virtual */ void UniscribeStringIterator::SetString(const char *s) +{ + const char *string_base = s; + + this->utf16_to_utf8.clear(); + this->str_info.clear(); + this->cur_pos = 0; + + /* Uniscribe operates on UTF-16, thus we have to convert the input string. + * To be able to return proper offsets, we have to create a mapping at the same time. */ + std::vector utf16_str; ///< UTF-16 copy of the string. + while (*s != '\0') { + size_t idx = s - string_base; + + WChar c = Utf8Consume(&s); + if (c < 0x10000) { + utf16_str.push_back((wchar_t)c); + } else { + /* Make a surrogate pair. */ + utf16_str.push_back((wchar_t)(0xD800 + ((c - 0x10000) >> 10))); + utf16_str.push_back((wchar_t)(0xDC00 + ((c - 0x10000) & 0x3FF))); + this->utf16_to_utf8.push_back(idx); + } + this->utf16_to_utf8.push_back(idx); + } + this->utf16_to_utf8.push_back(s - string_base); + + /* Query Uniscribe for word and cluster break information. */ + this->str_info.resize(utf16_to_utf8.size()); + + if (utf16_str.size() > 0) { + /* Itemize string into language runs. */ + std::vector runs = UniscribeItemizeString(&utf16_str[0], (int32)utf16_str.size()); + + for (std::vector::const_iterator run = runs.begin(); runs.size() > 0 && run != runs.end() - 1; run++) { + /* Get information on valid word and character break.s */ + int len = (run + 1)->iCharPos - run->iCharPos; + std::vector attr(len); + ScriptBreak(&utf16_str[run->iCharPos], len, &run->a, &attr[0]); + + /* Extract the information we're interested in. */ + for (size_t c = 0; c < attr.size(); c++) { + /* First character of a run is always a valid word break. */ + this->str_info[c + run->iCharPos].word_stop = attr[c].fWordStop || c == 0; + this->str_info[c + run->iCharPos].char_stop = attr[c].fCharStop; + } + } + } + + /* End-of-string is always a valid stopping point. */ + this->str_info.back().char_stop = true; + this->str_info.back().word_stop = true; +} + +/* virtual */ size_t UniscribeStringIterator::SetCurPosition(size_t pos) +{ + /* Convert incoming position to an UTF-16 string index. */ + size_t utf16_pos = 0; + for (size_t i = 0; i < this->utf16_to_utf8.size(); i++) { + if (this->utf16_to_utf8[i] == pos) { + utf16_pos = i; + break; + } + } + + /* Sanitize in case we get a position inside a grapheme cluster. */ + while (utf16_pos > 0 && !this->str_info[utf16_pos].char_stop) utf16_pos--; + this->cur_pos = utf16_pos; + + return this->utf16_to_utf8[this->cur_pos]; +} + +/* virtual */ size_t UniscribeStringIterator::Next(IterType what) +{ + assert(this->cur_pos <= this->utf16_to_utf8.size()); + assert(what == StringIterator::ITER_CHARACTER || what == StringIterator::ITER_WORD); + + if (this->cur_pos == this->utf16_to_utf8.size()) return END; + + do { + this->cur_pos++; + } while (this->cur_pos < this->utf16_to_utf8.size() && (what == ITER_WORD ? !this->str_info[this->cur_pos].word_stop : !this->str_info[this->cur_pos].char_stop)); + + return this->cur_pos == this->utf16_to_utf8.size() ? END : this->utf16_to_utf8[this->cur_pos]; +} + +/*virtual */ size_t UniscribeStringIterator::Prev(IterType what) +{ + assert(this->cur_pos <= this->utf16_to_utf8.size()); + assert(what == StringIterator::ITER_CHARACTER || what == StringIterator::ITER_WORD); + + if (this->cur_pos == 0) return END; + + do { + this->cur_pos--; + } while (this->cur_pos > 0 && (what == ITER_WORD ? !this->str_info[this->cur_pos].word_stop : !this->str_info[this->cur_pos].char_stop)); + + return this->utf16_to_utf8[this->cur_pos]; +} + +#endif /* defined(WITH_UNISCRIBE) */ diff --git a/src/os/windows/string_uniscribe.h b/src/os/windows/string_uniscribe.h new file mode 100644 index 0000000000..6af858a88f --- /dev/null +++ b/src/os/windows/string_uniscribe.h @@ -0,0 +1,92 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file string_uniscribe.h Functions related to laying out text on Win32. */ + +#ifndef STRING_UNISCRIBE_H +#define STRING_UNISCRIBE_H + +#if defined(WITH_UNISCRIBE) + +#include "../../gfx_layout.h" +#include "../../string_base.h" +#include + + +void UniscribeResetScriptCache(FontSize size); + + +/** + * Helper class to construct a new #UniscribeParagraphLayout. + */ +class UniscribeParagraphLayoutFactory { +public: + /** Helper for GetLayouter, to get the right type. */ + typedef wchar_t CharType; + /** Helper for GetLayouter, to get whether the layouter supports RTL. */ + static const bool SUPPORTS_RTL = true; + + /** + * Get the actual ParagraphLayout for the given buffer. + * @param buff The begin of the buffer. + * @param buff_end The location after the last element in the buffer. + * @param fontMapping THe mapping of the fonts. + * @return The ParagraphLayout instance. + */ + static ParagraphLayouter *GetParagraphLayout(CharType *buff, CharType *buff_end, FontMap &fontMapping); + + /** + * Append a wide character to the internal buffer. + * @param buff The buffer to append to. + * @param buffer_last The end of the buffer. + * @param c The character to add. + * @return The number of buffer spaces that were used. + */ + static size_t AppendToBuffer(CharType *buff, const CharType *buffer_last, WChar c) + { + if (c >= 0x010000U) { + /* Character is encoded using surrogates in UTF-16. */ + if (buff + 1 <= buffer_last) { + buff[0] = (CharType)(((c - 0x010000U) >> 10) + 0xD800); + buff[1] = (CharType)(((c - 0x010000U) & 0x3FF) + 0xDC00); + } else { + /* Not enough space in buffer. */ + *buff = 0; + } + return 2; + } else { + *buff = (CharType)(c & 0xFFFF); + return 1; + } + } +}; + +/** String iterator using Uniscribe as a backend. */ +class UniscribeStringIterator : public StringIterator { + /** */ + struct CharInfo { + bool word_stop : 1; ///< Code point is suitable as a word break. + bool char_stop : 1; ///< Code point is the start of a grapheme cluster, i.e. a "character". + }; + + std::vector str_info; ///< Break information for each code point. + std::vector utf16_to_utf8; ///< Mapping from UTF-16 code point position to index in the UTF-8 source string. + + size_t cur_pos; ///< Current iteration position. + +public: + virtual void SetString(const char *s); + virtual size_t SetCurPosition(size_t pos); + virtual size_t Next(IterType what); + virtual size_t Prev(IterType what); +}; + +#endif /* defined(WITH_UNISCRIBE) */ + +#endif /* STRING_UNISCRIBE_H */ diff --git a/src/os/windows/win32.cpp b/src/os/windows/win32.cpp index e57cc1ef04..ef921a28d5 100644 --- a/src/os/windows/win32.cpp +++ b/src/os/windows/win32.cpp @@ -28,6 +28,7 @@ #include "../../crashlog.h" #include #include +#include "../../language.h" /* Due to TCHAR, strncat and strncpy have to remain (for a while). */ #include "../../safeguards.h" @@ -69,11 +70,7 @@ bool LoadLibraryList(Function proc[], const char *dll) while (*dll++ != '\0') { /* Nothing */ } if (*dll == '\0') break; -#if defined(WINCE) - p = GetProcAddress(lib, MB_TO_WIDE(dll)); -#else p = GetProcAddress(lib, dll); -#endif if (p == NULL) return false; *proc++ = (Function)p; } @@ -213,14 +210,6 @@ bool FiosIsRoot(const char *file) void FiosGetDrives(FileList &file_list) { -#if defined(WINCE) - /* WinCE only knows one drive: / */ - FiosItem *fios = file_list.Append(); - fios->type = FIOS_TYPE_DRIVE; - fios->mtime = 0; - seprintf(fios->name, lastof(fios->name), PATHSEP ""); - strecpy(fios->title, fios->name, lastof(fios->title)); -#else TCHAR drives[256]; const TCHAR *s; @@ -233,7 +222,6 @@ void FiosGetDrives(FileList &file_list) strecpy(fios->title, fios->name, lastof(fios->title)); while (*s++ != '\0') { /* Nothing */ } } -#endif } bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb) @@ -309,9 +297,6 @@ static int ParseCommandLine(char *line, char **argv, int max_argc) void CreateConsole() { -#if defined(WINCE) - /* WinCE doesn't support console stuff */ -#else HANDLE hand; CONSOLE_SCREEN_BUFFER_INFO coninfo; @@ -361,7 +346,6 @@ void CreateConsole() setvbuf(stdin, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); -#endif } /** Temporary pointer to get the help message to the window */ @@ -429,18 +413,14 @@ void ShowInfo(const char *str) } } -#if defined(WINCE) -int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) -#else int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) -#endif { int argc; char *argv[64]; // max 64 command line arguments CrashLog::InitialiseCrashLog(); -#if defined(UNICODE) && !defined(WINCE) +#if defined(UNICODE) /* Check if a win9x user started the win32 version */ if (HasBit(GetVersion(), 31)) usererror("This version of OpenTTD doesn't run on windows 95/98/ME.\nPlease download the win9x binary and try again."); #endif @@ -454,9 +434,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi CreateConsole(); #endif -#if !defined(WINCE) _set_error_mode(_OUT_TO_MSGBOX); // force assertion output to messagebox -#endif /* setup random seed to something quite random */ SetRandomSeed(GetTickCount()); @@ -471,35 +449,11 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi return 0; } -#if defined(WINCE) -void GetCurrentDirectoryW(int length, wchar_t *path) -{ - /* Get the name of this module */ - GetModuleFileName(NULL, path, length); - - /* Remove the executable name, this we call CurrentDir */ - wchar_t *pDest = wcsrchr(path, '\\'); - if (pDest != NULL) { - int result = pDest - path + 1; - path[result] = '\0'; - } -} -#endif - char *getcwd(char *buf, size_t size) { -#if defined(WINCE) - TCHAR path[MAX_PATH]; - GetModuleFileName(NULL, path, MAX_PATH); - convert_from_fs(path, buf, size); - /* GetModuleFileName returns dir with file, so remove everything behind latest '\\' */ - char *p = strrchr(buf, '\\'); - if (p != NULL) *p = '\0'; -#else TCHAR path[MAX_PATH]; GetCurrentDirectory(MAX_PATH - 1, path); convert_from_fs(path, buf, size); -#endif return buf; } @@ -789,17 +743,80 @@ uint GetCPUCoreCount() return info.dwNumberOfProcessors; } + +static WCHAR _cur_iso_locale[16] = L""; + +void Win32SetCurrentLocaleName(const char *iso_code) +{ + /* Convert the iso code into the format that windows expects. */ + char iso[16]; + if (strcmp(iso_code, "zh_TW") == 0) { + strecpy(iso, "zh-Hant", lastof(iso)); + } else if (strcmp(iso_code, "zh_CN") == 0) { + strecpy(iso, "zh-Hans", lastof(iso)); + } else { + /* Windows expects a '-' between language and country code, but we use a '_'. */ + strecpy(iso, iso_code, lastof(iso)); + for (char *c = iso; *c != '\0'; c++) { + if (*c == '_') *c = '-'; + } + } + + MultiByteToWideChar(CP_UTF8, 0, iso, -1, _cur_iso_locale, lengthof(_cur_iso_locale)); +} + +int OTTDStringCompare(const char *s1, const char *s2) +{ + typedef int (WINAPI *PFNCOMPARESTRINGEX)(LPCWSTR, DWORD, LPCWCH, int, LPCWCH, int, LPVOID, LPVOID, LPARAM); + static PFNCOMPARESTRINGEX _CompareStringEx = NULL; + static bool first_time = true; + +#ifndef SORT_DIGITSASNUMBERS +# define SORT_DIGITSASNUMBERS 0x00000008 // use digits as numbers sort method +#endif +#ifndef LINGUISTIC_IGNORECASE +# define LINGUISTIC_IGNORECASE 0x00000010 // linguistically appropriate 'ignore case' +#endif + + if (first_time) { + _CompareStringEx = (PFNCOMPARESTRINGEX)GetProcAddress(GetModuleHandle(_T("Kernel32")), "CompareStringEx"); + first_time = false; + } + + if (_CompareStringEx != NULL) { + /* CompareStringEx takes UTF-16 strings, even in ANSI-builds. */ + int len_s1 = MultiByteToWideChar(CP_UTF8, 0, s1, -1, NULL, 0); + int len_s2 = MultiByteToWideChar(CP_UTF8, 0, s2, -1, NULL, 0); + + if (len_s1 != 0 && len_s2 != 0) { + LPWSTR str_s1 = AllocaM(WCHAR, len_s1); + LPWSTR str_s2 = AllocaM(WCHAR, len_s2); + + MultiByteToWideChar(CP_UTF8, 0, s1, -1, str_s1, len_s1); + MultiByteToWideChar(CP_UTF8, 0, s2, -1, str_s2, len_s2); + + int result = _CompareStringEx(_cur_iso_locale, LINGUISTIC_IGNORECASE | SORT_DIGITSASNUMBERS, str_s1, -1, str_s2, -1, NULL, NULL, 0); + if (result != 0) return result; + } + } + + TCHAR s1_buf[512], s2_buf[512]; + convert_to_fs(s1, s1_buf, lengthof(s1_buf)); + convert_to_fs(s2, s2_buf, lengthof(s2_buf)); + + return CompareString(MAKELCID(_current_language->winlangid, SORT_DEFAULT), NORM_IGNORECASE, s1_buf, -1, s2_buf, -1); +} + #ifdef _MSC_VER -/* Code from MSDN: https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx */ +/* Based on code from MSDN: https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx */ const DWORD MS_VC_EXCEPTION = 0x406D1388; -#pragma pack(push,8) -typedef struct { + +PACK_N(struct THREADNAME_INFO { DWORD dwType; ///< Must be 0x1000. LPCSTR szName; ///< Pointer to name (in user addr space). DWORD dwThreadID; ///< Thread ID (-1=caller thread). DWORD dwFlags; ///< Reserved for future use, must be zero. -} THREADNAME_INFO; -#pragma pack(pop) +}, 8); /** * Signal thread name to any attached debuggers. diff --git a/src/os/windows/win32.h b/src/os/windows/win32.h index 16632f6e9a..4f813c4a6f 100644 --- a/src/os/windows/win32.h +++ b/src/os/windows/win32.h @@ -45,4 +45,7 @@ void SetWin32ThreadName(DWORD dwThreadID, const char* threadName); static inline void SetWin32ThreadName(DWORD dwThreadID, const char* threadName) {} #endif +void Win32SetCurrentLocaleName(const char *iso_code); +int OTTDStringCompare(const char *s1, const char *s2); + #endif /* WIN32_H */ diff --git a/src/pathfinder/follow_track.hpp b/src/pathfinder/follow_track.hpp index 9f19b029c0..70f148de38 100644 --- a/src/pathfinder/follow_track.hpp +++ b/src/pathfinder/follow_track.hpp @@ -73,7 +73,8 @@ struct CFollowTrackT inline void Init(Owner o, RailTypes railtype_override, CPerformanceTimer *pPerf) { - assert((!IsRoadTT() || m_veh != NULL) && (!IsRailTT() || railtype_override != INVALID_RAILTYPES)); + assert(!IsRoadTT() || m_veh != NULL); + assert(!IsRailTT() || railtype_override != INVALID_RAILTYPES); m_veh_owner = o; m_pPerf = pPerf; /* don't worry, all is inlined so compiler should remove unnecessary initializations */ @@ -219,16 +220,13 @@ protected: } /* normal or station tile, do one step */ - TileIndexDiff diff = TileOffsByDiagDir(m_exitdir); - m_new_tile = TILE_ADD(m_old_tile, diff); + m_new_tile = TileAddByDiagDir(m_old_tile, m_exitdir); /* special handling for stations */ if (IsRailTT() && HasStationTileRail(m_new_tile)) { m_is_station = true; } else if (IsRoadTT() && IsRoadStopTile(m_new_tile)) { m_is_station = true; - } else { - m_is_station = false; } } @@ -241,7 +239,7 @@ protected: } else { m_new_td_bits = TrackStatusToTrackdirBits(GetTileTrackStatus(m_new_tile, TT(), IsRoadTT() ? RoadVehicle::From(m_veh)->compatible_roadtypes : 0)); - if (IsTram() && m_new_td_bits == 0) { + if (IsTram() && m_new_td_bits == TRACKDIR_BIT_NONE) { /* GetTileTrackStatus() returns 0 for single tram bits. * As we cannot change it there (easily) without breaking something, change it here */ switch (GetSingleTramBit(m_new_tile)) { diff --git a/src/pathfinder/npf/npf.cpp b/src/pathfinder/npf/npf.cpp index f989ff2c34..3218d8314f 100644 --- a/src/pathfinder/npf/npf.cpp +++ b/src/pathfinder/npf/npf.cpp @@ -807,7 +807,7 @@ static TrackdirBits GetDriveableTrackdirBits(TileIndex dst_tile, Trackdir src_tr { TrackdirBits trackdirbits = TrackStatusToTrackdirBits(GetTileTrackStatus(dst_tile, type, subtype)); - if (trackdirbits == 0 && type == TRANSPORT_ROAD && HasBit(subtype, ROADTYPE_TRAM)) { + if (trackdirbits == TRACKDIR_BIT_NONE && type == TRANSPORT_ROAD && HasBit(subtype, ROADTYPE_TRAM)) { /* GetTileTrackStatus() returns 0 for single tram bits. * As we cannot change it there (easily) without breaking something, change it here */ switch (GetSingleTramBit(dst_tile)) { @@ -900,7 +900,7 @@ static void NPFFollowTrack(AyStar *aystar, OpenListNode *current) trackdirbits = GetDriveableTrackdirBits(dst_tile, src_trackdir, type, subtype); - if (trackdirbits == 0) { + if (trackdirbits == TRACKDIR_BIT_NONE) { /* We cannot enter the next tile. Road vehicles can reverse, others reach dead end */ if (type != TRANSPORT_ROAD || HasBit(subtype, ROADTYPE_TRAM)) return; @@ -924,7 +924,7 @@ static void NPFFollowTrack(AyStar *aystar, OpenListNode *current) /* Enumerate possible track */ uint i = 0; - while (trackdirbits != 0) { + while (trackdirbits != TRACKDIR_BIT_NONE) { Trackdir dst_trackdir = RemoveFirstTrackdir(&trackdirbits); DEBUG(npf, 5, "Expanded into trackdir: %d, remaining trackdirs: 0x%X", dst_trackdir, trackdirbits); diff --git a/src/pathfinder/opf/opf_ship.cpp b/src/pathfinder/opf/opf_ship.cpp index 023c6a4a09..1a866337c7 100644 --- a/src/pathfinder/opf/opf_ship.cpp +++ b/src/pathfinder/opf/opf_ship.cpp @@ -183,9 +183,14 @@ bad:; } /** - * returns the track to choose on the next tile, or -1 when it's better to - * reverse. The tile given is the tile we are about to enter, enterdir is the - * direction in which we are entering the tile + * Finds the best track to choose on the next tile and + * returns INVALID_TRACK when it is better to reverse. + * @param v The ship. + * @param tile The tile we are about to enter. + * @param enterdir The direction entering the tile. + * @param tracks The tracks available on new tile. + * @param[out] path_found Whether a path has been found. + * @return Best track on next tile or INVALID_TRACK when better to reverse. */ Track OPFShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found) { @@ -195,13 +200,15 @@ Track OPFShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, Track track; /* Let's find out how far it would be if we would reverse first */ - Trackdir trackdir = v->GetVehicleTrackdir(); - TrackBits b = TrackStatusToTrackBits(GetTileTrackStatus(tile2, TRANSPORT_WATER, 0)) & DiagdirReachesTracks(ReverseDiagDir(enterdir)) & TrackdirBitsToTrackBits(TrackdirToTrackdirBits(trackdir)); + uint rev_dist = UINT_MAX; // distance if we reverse + Track cur_track = TrackdirToTrack(v->GetVehicleTrackdir()); // track on the current tile + DiagDirection rev_enterdir = ReverseDiagDir(enterdir); + TrackBits rev_tracks = TrackStatusToTrackBits(GetTileTrackStatus(tile2, TRANSPORT_WATER, 0)) & + DiagdirReachesTracks(rev_enterdir); - uint distr = UINT_MAX; // distance if we reversed - if (b != 0) { - distr = FindShipTrack(v, tile2, ReverseDiagDir(enterdir), b, tile, &track); - if (distr != UINT_MAX) distr++; // penalty for reversing + if (HasTrack(rev_tracks, cur_track)) { + rev_dist = FindShipTrack(v, tile2, rev_enterdir, TrackToTrackBits(cur_track), tile, &track); + if (rev_dist != UINT_MAX) rev_dist++; // penalty for reversing } /* And if we would not reverse? */ @@ -209,6 +216,6 @@ Track OPFShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, /* Due to the way this pathfinder works we cannot determine whether we're lost or not. */ path_found = true; - if (dist <= distr) return track; + if (dist <= rev_dist) return track; return INVALID_TRACK; // We could better reverse } diff --git a/src/pathfinder/yapf/yapf_common.hpp b/src/pathfinder/yapf/yapf_common.hpp index 660c231161..8ff69b3f6b 100644 --- a/src/pathfinder/yapf/yapf_common.hpp +++ b/src/pathfinder/yapf/yapf_common.hpp @@ -142,8 +142,7 @@ public: /** Called by YAPF to detect if node ends in the desired destination */ inline bool PfDetectDestination(Node &n) { - bool bDest = (n.m_key.m_tile == m_destTile) && ((m_destTrackdirs & TrackdirToTrackdirBits(n.GetTrackdir())) != TRACKDIR_BIT_NONE); - return bDest; + return (n.m_key.m_tile == m_destTile) && HasTrackdir(m_destTrackdirs, n.GetTrackdir()); } /** diff --git a/src/pathfinder/yapf/yapf_costrail.hpp b/src/pathfinder/yapf/yapf_costrail.hpp index ca317f09a7..022b9a1678 100644 --- a/src/pathfinder/yapf/yapf_costrail.hpp +++ b/src/pathfinder/yapf/yapf_costrail.hpp @@ -104,7 +104,7 @@ public: assert(IsValidTrackdir(td2)); int cost = 0; if (TrackFollower::Allow90degTurns() - && ((TrackdirToTrackdirBits(td2) & (TrackdirBits)TrackdirCrossesTrackdirs(td1)) != 0)) { + && HasTrackdir(TrackdirCrossesTrackdirs(td1), td2)) { /* 90-deg curve penalty */ cost += Yapf().PfGetSettings().rail_curve90_penalty; } else if (td2 != NextTrackdir(td1)) { @@ -280,7 +280,7 @@ public: { assert(!n.flags_u.flags_s.m_targed_seen); assert(tf->m_new_tile == n.m_key.m_tile); - assert((TrackdirToTrackdirBits(n.m_key.m_td) & tf->m_new_td_bits) != TRACKDIR_BIT_NONE); + assert((HasTrackdir(tf->m_new_td_bits, n.m_key.m_td))); CPerfStart perf_cost(Yapf().m_perf_cost); diff --git a/src/pathfinder/yapf/yapf_destrail.hpp b/src/pathfinder/yapf/yapf_destrail.hpp index 03519b059f..1d1833fbfd 100644 --- a/src/pathfinder/yapf/yapf_destrail.hpp +++ b/src/pathfinder/yapf/yapf_destrail.hpp @@ -166,16 +166,13 @@ public: /** Called by YAPF to detect if node ends in the desired destination */ inline bool PfDetectDestination(TileIndex tile, Trackdir td) { - bool bDest; if (m_dest_station_id != INVALID_STATION) { - bDest = HasStationTileRail(tile) + return HasStationTileRail(tile) && (GetStationIndex(tile) == m_dest_station_id) && (GetRailStationTrack(tile) == TrackdirToTrack(td)); - } else { - bDest = (tile == m_destTile) - && ((m_destTrackdirs & TrackdirToTrackdirBits(td)) != TRACKDIR_BIT_NONE); } - return bDest; + + return (tile == m_destTile) && HasTrackdir(m_destTrackdirs, td); } /** diff --git a/src/pathfinder/yapf/yapf_road.cpp b/src/pathfinder/yapf/yapf_road.cpp index 380b641da7..edc8d2a3a3 100644 --- a/src/pathfinder/yapf/yapf_road.cpp +++ b/src/pathfinder/yapf/yapf_road.cpp @@ -185,8 +185,7 @@ public: /** Called by YAPF to detect if node ends in the desired destination */ inline bool PfDetectDestination(Node &n) { - bool bDest = IsRoadDepotTile(n.m_segment_last_tile); - return bDest; + return IsRoadDepotTile(n.m_segment_last_tile); } inline bool PfDetectDestinationTile(TileIndex tile, Trackdir trackdir) @@ -261,7 +260,7 @@ public: (m_non_artic || IsDriveThroughStopTile(tile)); } - return tile == m_destTile && ((m_destTrackdirs & TrackdirToTrackdirBits(trackdir)) != TRACKDIR_BIT_NONE); + return tile == m_destTile && HasTrackdir(m_destTrackdirs, trackdir); } /** @@ -421,7 +420,7 @@ public: /* set origin (tile, trackdir) */ TileIndex src_tile = v->tile; Trackdir src_td = v->GetVehicleTrackdir(); - if ((TrackStatusToTrackdirBits(GetTileTrackStatus(src_tile, TRANSPORT_ROAD, v->compatible_roadtypes)) & TrackdirToTrackdirBits(src_td)) == 0) { + if (!HasTrackdir(TrackStatusToTrackdirBits(GetTileTrackStatus(src_tile, TRANSPORT_ROAD, v->compatible_roadtypes)), src_td)) { /* sometimes the roadveh is not on the road (it resides on non-existing track) * how should we handle that situation? */ return false; @@ -504,7 +503,7 @@ FindDepotData YapfRoadVehicleFindNearestDepot(const RoadVehicle *v, int max_dist { TileIndex tile = v->tile; Trackdir trackdir = v->GetVehicleTrackdir(); - if ((TrackStatusToTrackdirBits(GetTileTrackStatus(tile, TRANSPORT_ROAD, v->compatible_roadtypes)) & TrackdirToTrackdirBits(trackdir)) == 0) { + if (!HasTrackdir(TrackStatusToTrackdirBits(GetTileTrackStatus(tile, TRANSPORT_ROAD, v->compatible_roadtypes)), trackdir)) { return FindDepotData(); } diff --git a/src/pathfinder/yapf/yapf_ship.cpp b/src/pathfinder/yapf/yapf_ship.cpp index e4b99462d2..44a5c0cfa7 100644 --- a/src/pathfinder/yapf/yapf_ship.cpp +++ b/src/pathfinder/yapf/yapf_ship.cpp @@ -65,11 +65,11 @@ public: /* use vehicle's current direction if that's possible, otherwise use first usable one. */ Trackdir veh_dir = v->GetVehicleTrackdir(); - return ((trackdirs & TrackdirToTrackdirBits(veh_dir)) != 0) ? veh_dir : (Trackdir)FindFirstBit2x64(trackdirs); + return (HasTrackdir(trackdirs, veh_dir)) ? veh_dir : (Trackdir)FindFirstBit2x64(trackdirs); } /* move back to the old tile/trackdir (where ship is coming from) */ - TileIndex src_tile = TILE_ADD(tile, TileOffsByDiagDir(ReverseDiagDir(enterdir))); + TileIndex src_tile = TileAddByDiagDir(tile, ReverseDiagDir(enterdir)); Trackdir trackdir = v->GetVehicleTrackdir(); assert(IsValidTrackdir(trackdir)); diff --git a/src/pbs.cpp b/src/pbs.cpp index 133293909f..6bb35a6964 100644 --- a/src/pbs.cpp +++ b/src/pbs.cpp @@ -81,7 +81,7 @@ void SetRailStationPlatformReservation(TileIndex start, DiagDirection dir, bool */ bool TryReserveRailTrack(TileIndex tile, Track t, bool trigger_stations) { - assert((GetTileTrackStatus(tile, TRANSPORT_RAIL, 0) & TrackToTrackBits(t)) != 0); + assert(HasTrack(TrackStatusToTrackBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, 0)), t)); if (_settings_client.gui.show_track_reservation) { /* show the reserved rail if needed */ @@ -142,7 +142,7 @@ bool TryReserveRailTrack(TileIndex tile, Track t, bool trigger_stations) */ void UnreserveRailTrack(TileIndex tile, Track t) { - assert((GetTileTrackStatus(tile, TRANSPORT_RAIL, 0) & TrackToTrackBits(t)) != 0); + assert(HasTrack(TrackStatusToTrackBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, 0)), t)); if (_settings_client.gui.show_track_reservation) { if (IsBridgeTile(tile)) { diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 9f284fc305..d21c1468ca 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -166,11 +166,11 @@ RailType AllocateRailType(RailTypeLabel label) rti->alternate_labels.Clear(); /* Make us compatible with ourself. */ - rti->powered_railtypes = (RailTypes)(1 << rt); - rti->compatible_railtypes = (RailTypes)(1 << rt); + rti->powered_railtypes = (RailTypes)(1LL << rt); + rti->compatible_railtypes = (RailTypes)(1LL << rt); /* We also introduce ourself. */ - rti->introduces_railtypes = (RailTypes)(1 << rt); + rti->introduces_railtypes = (RailTypes)(1LL << rt); /* Default sort order; order of allocation, but with some * offsets so it's easier for NewGRF to pick a spot without @@ -441,7 +441,7 @@ static inline bool ValParamTrackOrientation(Track track) */ CommandCost CmdBuildSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - RailType railtype = Extract(p1); + RailType railtype = Extract(p1); Track track = Extract(p2); CommandCost cost(EXPENSES_CONSTRUCTION); @@ -554,8 +554,8 @@ CommandCost CmdBuildSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, u if (IsLevelCrossing(tile) && GetCrossingRailBits(tile) == trackbit) { return_cmd_error(STR_ERROR_ALREADY_BUILT); } + FALLTHROUGH; } - FALLTHROUGH; default: { /* Will there be flat water on the lower halftile? */ @@ -854,19 +854,19 @@ static CommandCost ValidateAutoDrag(Trackdir *trackdir, TileIndex start, TileInd * @param flags operation to perform * @param p1 end tile of drag * @param p2 various bitstuffed elements - * - p2 = (bit 0-3) - railroad type normal/maglev (0 = normal, 1 = mono, 2 = maglev), only used for building - * - p2 = (bit 4-6) - track-orientation, valid values: 0-5 (Track enum) - * - p2 = (bit 7) - 0 = build, 1 = remove tracks - * - p2 = (bit 8) - 0 = build up to an obstacle, 1 = fail if an obstacle is found (used for AIs). + * - p2 = (bit 0-5) - railroad type normal/maglev (0 = normal, 1 = mono, 2 = maglev), only used for building + * - p2 = (bit 6-8) - track-orientation, valid values: 0-5 (Track enum) + * - p2 = (bit 9) - 0 = build, 1 = remove tracks + * - p2 = (bit 10) - 0 = build up to an obstacle, 1 = fail if an obstacle is found (used for AIs). * @param text unused * @return the cost of this operation or an error */ static CommandCost CmdRailTrackHelper(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { CommandCost total_cost(EXPENSES_CONSTRUCTION); - Track track = Extract(p2); - bool remove = HasBit(p2, 7); - RailType railtype = Extract(p2); + Track track = Extract(p2); + bool remove = HasBit(p2, 9); + RailType railtype = Extract(p2); if ((!remove && !ValParamRailtype(railtype)) || !ValParamTrackOrientation(track)) return CMD_ERROR; if (p1 >= MapSize()) return CMD_ERROR; @@ -884,7 +884,7 @@ static CommandCost CmdRailTrackHelper(TileIndex tile, DoCommandFlag flags, uint3 if (ret.Failed()) { last_error = ret; if (last_error.GetErrorMessage() != STR_ERROR_ALREADY_BUILT && !remove) { - if (HasBit(p2, 8)) return last_error; + if (HasBit(p2, 10)) return last_error; break; } @@ -914,16 +914,16 @@ static CommandCost CmdRailTrackHelper(TileIndex tile, DoCommandFlag flags, uint3 * @param flags operation to perform * @param p1 end tile of drag * @param p2 various bitstuffed elements - * - p2 = (bit 0-3) - railroad type normal/maglev (0 = normal, 1 = mono, 2 = maglev) - * - p2 = (bit 4-6) - track-orientation, valid values: 0-5 (Track enum) - * - p2 = (bit 7) - 0 = build, 1 = remove tracks + * - p2 = (bit 0-5) - railroad type normal/maglev (0 = normal, 1 = mono, 2 = maglev) + * - p2 = (bit 6-8) - track-orientation, valid values: 0-5 (Track enum) + * - p2 = (bit 9) - 0 = build, 1 = remove tracks * @param text unused * @return the cost of this operation or an error * @see CmdRailTrackHelper */ CommandCost CmdBuildRailroadTrack(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - return CmdRailTrackHelper(tile, flags, p1, ClrBit(p2, 7), text); + return CmdRailTrackHelper(tile, flags, p1, ClrBit(p2, 9), text); } /** @@ -933,16 +933,16 @@ CommandCost CmdBuildRailroadTrack(TileIndex tile, DoCommandFlag flags, uint32 p1 * @param flags operation to perform * @param p1 end tile of drag * @param p2 various bitstuffed elements - * - p2 = (bit 0-3) - railroad type normal/maglev (0 = normal, 1 = mono, 2 = maglev), only used for building - * - p2 = (bit 4-6) - track-orientation, valid values: 0-5 (Track enum) - * - p2 = (bit 7) - 0 = build, 1 = remove tracks + * - p2 = (bit 0-5) - railroad type normal/maglev (0 = normal, 1 = mono, 2 = maglev), only used for building + * - p2 = (bit 6-8) - track-orientation, valid values: 0-5 (Track enum) + * - p2 = (bit 9) - 0 = build, 1 = remove tracks * @param text unused * @return the cost of this operation or an error * @see CmdRailTrackHelper */ CommandCost CmdRemoveRailroadTrack(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - return CmdRailTrackHelper(tile, flags, p1, SetBit(p2, 7), text); + return CmdRailTrackHelper(tile, flags, p1, SetBit(p2, 9), text); } /** @@ -960,7 +960,7 @@ CommandCost CmdRemoveRailroadTrack(TileIndex tile, DoCommandFlag flags, uint32 p CommandCost CmdBuildTrainDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { /* check railtype and valid direction for depot (0 through 3), 4 in total */ - RailType railtype = Extract(p1); + RailType railtype = Extract(p1); if (!ValParamRailtype(railtype)) return CMD_ERROR; Slope tileh = GetTileSlope(tile); @@ -1540,17 +1540,17 @@ static Vehicle *UpdateTrainPowerProc(Vehicle *v, void *data) * @param flags operation to perform * @param p1 start tile of drag * @param p2 various bitstuffed elements: - * - p2 = (bit 0- 3) new railtype to convert to. - * - p2 = (bit 4) build diagonally or not. + * - p2 = (bit 0- 5) new railtype to convert to. + * - p2 = (bit 6) build diagonally or not. * @param text unused * @return the cost of this operation or an error */ CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - RailType totype = Extract(p2); + RailType totype = Extract(p2); TileIndex area_start = p1; TileIndex area_end = tile; - bool diagonal = HasBit(p2, 4); + bool diagonal = HasBit(p2, 6); if (!ValParamRailtype(totype)) return CMD_ERROR; if (area_start >= MapSize()) return CMD_ERROR; diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index 73fe29da0d..5a533e5c55 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -192,7 +192,7 @@ static void PlaceRail_Station(TileIndex tile) VpStartPlaceSizing(tile, VPM_X_AND_Y_LIMITED, DDSP_BUILD_STATION); VpSetPlaceSizingLimit(_settings_game.station.station_spread); } else { - uint32 p1 = _cur_railtype | _railstation.orientation << 4 | _settings_client.gui.station_numtracks << 8 | _settings_client.gui.station_platlength << 16 | _ctrl_pressed << 24; + uint32 p1 = _cur_railtype | _railstation.orientation << 6 | _settings_client.gui.station_numtracks << 8 | _settings_client.gui.station_platlength << 16 | _ctrl_pressed << 24; uint32 p2 = _railstation.station_class | _railstation.station_type << 8 | INVALID_STATION << 16; int w = _settings_client.gui.station_numtracks; @@ -352,7 +352,7 @@ static void BuildRailClick_Remove(Window *w) static void DoRailroadTrack(int mode) { - DoCommandP(TileVirtXY(_thd.selstart.x, _thd.selstart.y), TileVirtXY(_thd.selend.x, _thd.selend.y), _cur_railtype | (mode << 4), + DoCommandP(TileVirtXY(_thd.selstart.x, _thd.selstart.y), TileVirtXY(_thd.selend.x, _thd.selend.y), _cur_railtype | (mode << 6), _remove_button_clicked ? CMD_REMOVE_RAILROAD_TRACK | CMD_MSG(STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK) : CMD_BUILD_RAILROAD_TRACK | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK), @@ -711,7 +711,7 @@ struct BuildRailToolbarWindow : Window { break; case DDSP_CONVERT_RAIL: - DoCommandP(end_tile, start_tile, _cur_railtype | (_ctrl_pressed ? 0x10 : 0), CMD_CONVERT_RAIL | CMD_MSG(STR_ERROR_CAN_T_CONVERT_RAIL), CcPlaySound_SPLAT_RAIL); + DoCommandP(end_tile, start_tile, _cur_railtype | (_ctrl_pressed ? 1 << 6 : 0), CMD_CONVERT_RAIL | CMD_MSG(STR_ERROR_CAN_T_CONVERT_RAIL), CcPlaySound_SPLAT_RAIL); break; case DDSP_REMOVE_STATION: @@ -729,7 +729,7 @@ struct BuildRailToolbarWindow : Window { DoCommandP(end_tile, start_tile, _ctrl_pressed ? 0 : 1, CMD_REMOVE_FROM_RAIL_WAYPOINT | CMD_MSG(STR_ERROR_CAN_T_REMOVE_TRAIN_WAYPOINT), CcPlaySound_SPLAT_RAIL); } else { TileArea ta(start_tile, end_tile); - uint32 p1 = _cur_railtype | (select_method == VPM_X_LIMITED ? AXIS_X : AXIS_Y) << 4 | ta.w << 8 | ta.h << 16 | _ctrl_pressed << 24; + uint32 p1 = _cur_railtype | (select_method == VPM_X_LIMITED ? AXIS_X : AXIS_Y) << 6 | ta.w << 8 | ta.h << 16 | _ctrl_pressed << 24; uint32 p2 = STAT_CLASS_WAYP | _cur_waypoint_type << 8 | INVALID_STATION << 16; CommandContainer cmdcont = { ta.tile, p1, p2, CMD_BUILD_RAIL_WAYPOINT | CMD_MSG(STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT), CcPlaySound_SPLAT_RAIL, "" }; @@ -886,7 +886,7 @@ static void HandleStationPlacement(TileIndex start, TileIndex end) if (_railstation.orientation == AXIS_X) Swap(numtracks, platlength); - uint32 p1 = _cur_railtype | _railstation.orientation << 4 | numtracks << 8 | platlength << 16 | _ctrl_pressed << 24; + uint32 p1 = _cur_railtype | _railstation.orientation << 6 | numtracks << 8 | platlength << 16 | _ctrl_pressed << 24; uint32 p2 = _railstation.station_class | _railstation.station_type << 8 | INVALID_STATION << 16; CommandContainer cmdcont = { ta.tile, p1, p2, CMD_BUILD_RAIL_STATION | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_STATION), CcStation, "" }; @@ -1908,7 +1908,7 @@ static void SetDefaultRailGui() RailType rt = (RailType)(_settings_client.gui.default_rail_type + RAILTYPE_END); if (rt == DEF_RAILTYPE_MOST_USED) { /* Find the most used rail type */ - RailType count[RAILTYPE_END]; + uint count[RAILTYPE_END]; memset(count, 0, sizeof(count)); for (TileIndex t = 0; t < MapSize(); t++) { if (IsTileType(t, MP_RAILWAY) || IsLevelCrossingTile(t) || HasStationTileRail(t) || diff --git a/src/rail_map.h b/src/rail_map.h index 2431a79202..74afe5ace5 100644 --- a/src/rail_map.h +++ b/src/rail_map.h @@ -115,7 +115,7 @@ static inline bool IsRailDepotTile(TileIndex t) */ static inline RailType GetRailType(TileIndex t) { - return (RailType)GB(_m[t].m3, 0, 4); + return (RailType)GB(_me[t].m8, 0, 6); } /** @@ -125,7 +125,7 @@ static inline RailType GetRailType(TileIndex t) */ static inline void SetRailType(TileIndex t, RailType r) { - SB(_m[t].m3, 0, 4, r); + SB(_me[t].m8, 0, 6, r); } @@ -522,11 +522,12 @@ static inline void MakeRailNormal(TileIndex t, Owner o, TrackBits b, RailType r) SetTileType(t, MP_RAILWAY); SetTileOwner(t, o); _m[t].m2 = 0; - _m[t].m3 = r; + _m[t].m3 = 0; _m[t].m4 = 0; _m[t].m5 = RAIL_TILE_NORMAL << 6 | b; SB(_me[t].m6, 2, 4, 0); _me[t].m7 = 0; + _me[t].m8 = r; } @@ -535,11 +536,12 @@ static inline void MakeRailDepot(TileIndex t, Owner o, DepotID did, DiagDirectio SetTileType(t, MP_RAILWAY); SetTileOwner(t, o); _m[t].m2 = did; - _m[t].m3 = r; + _m[t].m3 = 0; _m[t].m4 = 0; _m[t].m5 = RAIL_TILE_DEPOT << 6 | d; SB(_me[t].m6, 2, 4, 0); _me[t].m7 = 0; + _me[t].m8 = r; } #endif /* RAIL_MAP_H */ diff --git a/src/rail_type.h b/src/rail_type.h index ee589898b8..ebca7ec35d 100644 --- a/src/rail_type.h +++ b/src/rail_type.h @@ -32,7 +32,7 @@ enum RailType { RAILTYPE_ELECTRIC = 1, ///< Electric rails RAILTYPE_MONO = 2, ///< Monorail RAILTYPE_MAGLEV = 3, ///< Maglev - RAILTYPE_END = 16, ///< Used for iterations + RAILTYPE_END = 64, ///< Used for iterations INVALID_RAILTYPE = 0xFF, ///< Flag for invalid railtype DEF_RAILTYPE_FIRST = RAILTYPE_END, ///< Default railtype: first available @@ -43,7 +43,7 @@ enum RailType { /** Allow incrementing of Track variables */ DECLARE_POSTFIX_INCREMENT(RailType) /** Define basic enum properties */ -template <> struct EnumPropsT : MakeEnumPropsT {}; +template <> struct EnumPropsT : MakeEnumPropsT {}; typedef TinyEnumT RailTypeByte; /** @@ -55,7 +55,7 @@ enum RailTypes { RAILTYPES_ELECTRIC = 1 << RAILTYPE_ELECTRIC, ///< Electrified rails RAILTYPES_MONO = 1 << RAILTYPE_MONO, ///< Monorail! RAILTYPES_MAGLEV = 1 << RAILTYPE_MAGLEV, ///< Ever fast maglev - INVALID_RAILTYPES = UINT_MAX, ///< Invalid railtypes + INVALID_RAILTYPES = UINT64_MAX, ///< Invalid railtypes }; DECLARE_ENUM_AS_BIT_SET(RailTypes) diff --git a/src/rev.cpp.in b/src/rev.cpp.in index cb34b04295..89c95e2b49 100644 --- a/src/rev.cpp.in +++ b/src/rev.cpp.in @@ -70,13 +70,13 @@ const byte _openttd_revision_modified = !!MODIFIED!!; * 24-27 minor version * 20-23 build * 19 1 if it is a release, 0 if it is not. - * 0-18 used to be the SVN revision, currently unused + * 0-18 used to be the SVN revision, now just last revision before switch to git * * The 19th bit is there so the development/betas/alpha, etc. leading to a * 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 | 0 << 20 | 0 << 19; +const uint32 _openttd_newgrf_version = 1 << 28 | 9 << 24 | 0 << 20 | 0 << 19 | 28004; #ifdef __MORPHOS__ /** diff --git a/src/road_gui.cpp b/src/road_gui.cpp index 801d334351..6faa422627 100644 --- a/src/road_gui.cpp +++ b/src/road_gui.cpp @@ -633,24 +633,28 @@ struct BuildRoadToolbarWindow : Window { break; case DDSP_BUILD_BUSSTOP: - PlaceRoadStop(start_tile, end_tile, (_ctrl_pressed << 5) | RoadTypeToRoadTypes(_cur_roadtype) << 2 | ROADSTOP_BUS, CMD_BUILD_ROAD_STOP | CMD_MSG(_road_type_infos[_cur_roadtype].err_build_station[ROADSTOP_BUS])); + case DDSP_REMOVE_BUSSTOP: + if (this->IsWidgetLowered(WID_ROT_BUS_STATION)) { + if (_remove_button_clicked) { + TileArea ta(start_tile, end_tile); + DoCommandP(ta.tile, ta.w | ta.h << 8, (_ctrl_pressed << 1) | ROADSTOP_BUS, CMD_REMOVE_ROAD_STOP | CMD_MSG(_road_type_infos[_cur_roadtype].err_remove_station[ROADSTOP_BUS]), CcPlaySound_SPLAT_OTHER); + } else { + PlaceRoadStop(start_tile, end_tile, (_ctrl_pressed << 5) | RoadTypeToRoadTypes(_cur_roadtype) << 2 | ROADSTOP_BUS, CMD_BUILD_ROAD_STOP | CMD_MSG(_road_type_infos[_cur_roadtype].err_build_station[ROADSTOP_BUS])); + } + } break; case DDSP_BUILD_TRUCKSTOP: - PlaceRoadStop(start_tile, end_tile, (_ctrl_pressed << 5) | RoadTypeToRoadTypes(_cur_roadtype) << 2 | ROADSTOP_TRUCK, CMD_BUILD_ROAD_STOP | CMD_MSG(_road_type_infos[_cur_roadtype].err_build_station[ROADSTOP_TRUCK])); + case DDSP_REMOVE_TRUCKSTOP: + if (this->IsWidgetLowered(WID_ROT_TRUCK_STATION)) { + if (_remove_button_clicked) { + TileArea ta(start_tile, end_tile); + DoCommandP(ta.tile, ta.w | ta.h << 8, (_ctrl_pressed << 1) | ROADSTOP_TRUCK, CMD_REMOVE_ROAD_STOP | CMD_MSG(_road_type_infos[_cur_roadtype].err_remove_station[ROADSTOP_TRUCK]), CcPlaySound_SPLAT_OTHER); + } else { + PlaceRoadStop(start_tile, end_tile, (_ctrl_pressed << 5) | RoadTypeToRoadTypes(_cur_roadtype) << 2 | ROADSTOP_TRUCK, CMD_BUILD_ROAD_STOP | CMD_MSG(_road_type_infos[_cur_roadtype].err_build_station[ROADSTOP_TRUCK])); + } + } break; - - case DDSP_REMOVE_BUSSTOP: { - TileArea ta(start_tile, end_tile); - DoCommandP(ta.tile, ta.w | ta.h << 8, (_ctrl_pressed << 1) | ROADSTOP_BUS, CMD_REMOVE_ROAD_STOP | CMD_MSG(_road_type_infos[_cur_roadtype].err_remove_station[ROADSTOP_BUS]), CcPlaySound_SPLAT_OTHER); - break; - } - - case DDSP_REMOVE_TRUCKSTOP: { - TileArea ta(start_tile, end_tile); - DoCommandP(ta.tile, ta.w | ta.h << 8, (_ctrl_pressed << 1) | ROADSTOP_TRUCK, CMD_REMOVE_ROAD_STOP | CMD_MSG(_road_type_infos[_cur_roadtype].err_remove_station[ROADSTOP_TRUCK]), CcPlaySound_SPLAT_OTHER); - break; - } } } } diff --git a/src/road_map.h b/src/road_map.h index 693730294e..5b3e6b0900 100644 --- a/src/road_map.h +++ b/src/road_map.h @@ -579,11 +579,12 @@ static inline void MakeRoadCrossing(TileIndex t, Owner road, Owner tram, Owner r SetTileType(t, MP_ROAD); SetTileOwner(t, rail); _m[t].m2 = town; - _m[t].m3 = rat; + _m[t].m3 = 0; _m[t].m4 = 0; _m[t].m5 = ROAD_TILE_CROSSING << 6 | roaddir; SB(_me[t].m6, 2, 4, 0); _me[t].m7 = rot << 6 | road; + _me[t].m8 = rat; SetRoadOwner(t, ROADTYPE_TRAM, tram); } diff --git a/src/roadveh.h b/src/roadveh.h index b1865fc22e..ca069b7acf 100644 --- a/src/roadveh.h +++ b/src/roadveh.h @@ -105,7 +105,7 @@ struct RoadVehicle FINAL : public GroundVehicle { friend struct GroundVehicle; // GroundVehicle needs to use the acceleration functions defined at RoadVehicle. void MarkDirty(); - void UpdateDeltaXY(Direction direction); + void UpdateDeltaXY(); ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_ROADVEH_INC : EXPENSES_ROADVEH_RUN; } bool IsPrimaryVehicle() const { return this->IsFrontEngine(); } void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const; diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index 7adc532b6b..ed67a52211 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -35,6 +35,7 @@ #include "core/backup_type.hpp" #include "newgrf.h" #include "zoom_func.h" +#include "framerate_type.h" #include "table/strings.h" @@ -403,7 +404,7 @@ void RoadVehicle::MarkDirty() this->CargoChanged(); } -void RoadVehicle::UpdateDeltaXY(Direction direction) +void RoadVehicle::UpdateDeltaXY() { static const int8 _delta_xy_table[8][10] = { /* y_extent, x_extent, y_offs, x_offs, y_bb_offs, x_bb_offs, y_extent_shorten, x_extent_shorten, y_bb_offs_shorten, x_bb_offs_shorten */ @@ -418,9 +419,9 @@ void RoadVehicle::UpdateDeltaXY(Direction direction) }; int shorten = VEHICLE_LENGTH - this->gcache.cached_veh_length; - if (!IsDiagonalDirection(direction)) shorten >>= 1; + if (!IsDiagonalDirection(this->direction)) shorten >>= 1; - const int8 *bb = _delta_xy_table[direction]; + const int8 *bb = _delta_xy_table[this->direction]; this->x_bb_offs = bb[5] + bb[9] * shorten; this->y_bb_offs = bb[4] + bb[8] * shorten;; this->x_offs = bb[3]; @@ -1449,7 +1450,7 @@ again: /* Vehicle has arrived at a bay in a road stop */ if (IsDriveThroughStopTile(v->tile)) { - TileIndex next_tile = TILE_ADD(v->tile, TileOffsByDir(v->direction)); + TileIndex next_tile = TileAddByDir(v->tile, v->direction); /* Check if next inline bay is free and has compatible road. */ if (RoadStop::IsDriveThroughRoadStopContinuation(v->tile, next_tile) && (GetRoadTypes(next_tile) & v->compatible_roadtypes) != 0) { @@ -1587,6 +1588,8 @@ Money RoadVehicle::GetRunningCost() const bool RoadVehicle::Tick() { + PerformanceAccumulator framerate(PFE_GL_ROADVEHS); + this->tick_counter++; if (this->IsFrontEngine()) { diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 35e2767024..6f708ba0f2 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -1256,6 +1256,38 @@ bool AfterLoadGame() } } + /* Railtype moved from m3 to m8 in version 200. */ + if (IsSavegameVersionBefore(200)) { + 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(24)) { RailType min_rail = RAILTYPE_ELECTRIC; @@ -3011,6 +3043,19 @@ bool AfterLoadGame() #endif } + if (IsSavegameVersionBefore(198)) { + /* Convert towns growth_rate and grow_counter to ticks */ + Town *t; + FOR_ALL_TOWNS(t) { + /* 0x8000 = TOWN_GROWTH_RATE_CUSTOM previously */ + if (t->growth_rate & 0x8000) SetBit(t->flags, TOWN_CUSTOM_GROWTH); + if (t->growth_rate != TOWN_GROWTH_RATE_NONE) { + t->growth_rate = TownTicksToGameTicks(t->growth_rate & ~0x8000); + } + /* Add t->index % TOWN_GROWTH_TICKS to spread growth across ticks. */ + t->grow_counter = TownTicksToGameTicks(t->grow_counter) + t->index % TOWN_GROWTH_TICKS; + } + } /* Station acceptance is some kind of cache */ if (IsSavegameVersionBefore(127)) { diff --git a/src/saveload/company_sl.cpp b/src/saveload/company_sl.cpp index d7c3130271..ce388e2141 100644 --- a/src/saveload/company_sl.cpp +++ b/src/saveload/company_sl.cpp @@ -259,7 +259,7 @@ static const SaveLoad _company_desc[] = { SLE_VAR(CompanyProperties, colour, SLE_UINT8), SLE_VAR(CompanyProperties, money_fraction, SLE_UINT8), - SLE_CONDVAR(CompanyProperties, avail_railtypes, SLE_VAR_I32 | SLE_FILE_I8, 0, 57), + SLE_CONDNULL(1, 0, 57), ///< avail_railtypes SLE_VAR(CompanyProperties, block_preview, SLE_UINT8), SLE_CONDNULL(2, 0, 93), ///< cargo_types @@ -350,7 +350,8 @@ static const SaveLoad _company_economy_desc[] = { SLE_CONDVAR(CompanyEconomyEntry, company_value, SLE_INT64, 2, SL_MAX_VERSION), SLE_CONDVAR(CompanyEconomyEntry, delivered_cargo[NUM_CARGO - 1], SLE_INT32, 0, 169), - SLE_CONDARR(CompanyEconomyEntry, delivered_cargo, SLE_UINT32, NUM_CARGO, 170, SL_MAX_VERSION), + SLE_CONDARR(CompanyEconomyEntry, delivered_cargo, SLE_UINT32, 32, 170, 198), + SLE_CONDARR(CompanyEconomyEntry, delivered_cargo, SLE_UINT32, NUM_CARGO, 199, SL_MAX_VERSION), SLE_VAR(CompanyEconomyEntry, performance_history, SLE_INT32), SLE_END() @@ -497,7 +498,6 @@ static void Check_PLYR() int index; while ((index = SlIterateArray()) != -1) { CompanyProperties *cprops = new CompanyProperties(); - memset(cprops, 0, sizeof(*cprops)); SaveLoad_PLYR_common(NULL, cprops); /* We do not load old custom names */ diff --git a/src/saveload/economy_sl.cpp b/src/saveload/economy_sl.cpp index dabf120fca..0effb5b2ff 100644 --- a/src/saveload/economy_sl.cpp +++ b/src/saveload/economy_sl.cpp @@ -29,7 +29,7 @@ static void Load_PRIC() /** Cargo payment rates in pre 126 savegames */ static void Load_CAPR() { - uint num_cargo = IsSavegameVersionBefore(55) ? 12 : NUM_CARGO; + uint num_cargo = IsSavegameVersionBefore(55) ? 12 : IsSavegameVersionBefore(199) ? 32 : NUM_CARGO; int vt = IsSavegameVersionBefore(65) ? SLE_FILE_I32 : SLE_FILE_I64; SlArray(NULL, num_cargo, vt | SLE_VAR_NULL); SlArray(NULL, num_cargo, SLE_FILE_U16 | SLE_VAR_NULL); diff --git a/src/saveload/map_sl.cpp b/src/saveload/map_sl.cpp index 86a185ca42..693ddb7ce3 100644 --- a/src/saveload/map_sl.cpp +++ b/src/saveload/map_sl.cpp @@ -272,6 +272,30 @@ static void Save_MAP7() } } +static void Load_MAP8() +{ + SmallStackSafeStackAlloc buf; + TileIndex size = MapSize(); + + for (TileIndex i = 0; i != size;) { + SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT16); + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m8 = buf[j]; + } +} + +static void Save_MAP8() +{ + SmallStackSafeStackAlloc buf; + TileIndex size = MapSize(); + + SlSetLength(size * sizeof(uint16)); + for (TileIndex i = 0; i != size;) { + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m8; + SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT16); + } +} + + extern const ChunkHandler _map_chunk_handlers[] = { { 'MAPS', Save_MAPS, Load_MAPS, NULL, Check_MAPS, CH_RIFF }, { 'MAPT', Save_MAPT, Load_MAPT, NULL, NULL, CH_RIFF }, @@ -282,5 +306,6 @@ extern const ChunkHandler _map_chunk_handlers[] = { { 'M3HI', Save_MAP4, Load_MAP4, NULL, NULL, CH_RIFF }, { 'MAP5', Save_MAP5, Load_MAP5, NULL, NULL, CH_RIFF }, { 'MAPE', Save_MAP6, Load_MAP6, NULL, NULL, CH_RIFF }, - { 'MAP7', Save_MAP7, Load_MAP7, NULL, NULL, CH_RIFF | CH_LAST }, + { 'MAP7', Save_MAP7, Load_MAP7, NULL, NULL, CH_RIFF }, + { 'MAP8', Save_MAP8, Load_MAP8, NULL, NULL, CH_RIFF | CH_LAST }, }; diff --git a/src/saveload/oldloader_sl.cpp b/src/saveload/oldloader_sl.cpp index 61a5aa5c6d..1974bb31fa 100644 --- a/src/saveload/oldloader_sl.cpp +++ b/src/saveload/oldloader_sl.cpp @@ -946,7 +946,7 @@ static const OldChunks _company_chunk[] = { OCL_SVAR( OC_UINT8, Company, block_preview ), OCL_CNULL( OC_TTD, 1 ), // Old AI - OCL_SVAR( OC_TTD | OC_UINT8, Company, avail_railtypes ), + OCL_CNULL( OC_TTD, 1 ), // avail_railtypes OCL_SVAR( OC_TILE, Company, location_of_HQ ), OCL_SVAR( OC_TTD | OC_UINT8, Company, share_owners[0] ), OCL_SVAR( OC_TTD | OC_UINT8, Company, share_owners[1] ), diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index cea80b59df..e065237693 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -265,8 +265,11 @@ * 195 27572 1.6.x * 196 27778 1.7.x * 197 27978 1.8.x + * 198 + * 199 + * 200 #6805 Extend railtypes to 64, adding uint16 to map array. */ -extern const uint16 SAVEGAME_VERSION = 197; ///< Current savegame version of OpenTTD. +extern const uint16 SAVEGAME_VERSION = 200; ///< Current savegame version of OpenTTD. SavegameType _savegame_type; ///< type of savegame we are loading FileToSaveLoad _file_to_saveload; ///< File to save or load in the openttd loop. diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index d492558c5a..3405f3351c 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -436,7 +436,7 @@ typedef SaveLoad SaveLoadGlobVarList; * @param variable Name of the global variable. * @param type Storage of the data in memory and in the savegame. */ -#define SLEG_STR(variable, type) SLEG_CONDSTR(variable, type, lengthof(variable), 0, SL_MAX_VERSION) +#define SLEG_STR(variable, type) SLEG_CONDSTR(variable, type, sizeof(variable), 0, SL_MAX_VERSION) /** * Storage of a global list in every savegame version. diff --git a/src/saveload/station_sl.cpp b/src/saveload/station_sl.cpp index 391ba30a8e..f01123da0a 100644 --- a/src/saveload/station_sl.cpp +++ b/src/saveload/station_sl.cpp @@ -329,6 +329,7 @@ static void Load_STNS() _cargo_days = 0; _cargo_feeder_share = 0; + uint num_cargo = IsSavegameVersionBefore(55) ? 12 : IsSavegameVersionBefore(199) ? 32 : NUM_CARGO; int index; while ((index = SlIterateArray()) != -1) { Station *st = new (index) Station(); @@ -337,7 +338,6 @@ static void Load_STNS() _waiting_acceptance = 0; - uint num_cargo = IsSavegameVersionBefore(55) ? 12 : NUM_CARGO; for (CargoID i = 0; i < num_cargo; i++) { GoodsEntry *ge = &st->goods[i]; SlObject(ge, GetGoodsDesc()); @@ -377,10 +377,11 @@ static void Ptrs_STNS() /* Don't run when savegame version is higher than or equal to 123. */ if (!IsSavegameVersionBefore(123)) return; + uint num_cargo = IsSavegameVersionBefore(199) ? 32 : NUM_CARGO; Station *st; FOR_ALL_STATIONS(st) { if (!IsSavegameVersionBefore(68)) { - for (CargoID i = 0; i < NUM_CARGO; i++) { + for (CargoID i = 0; i < num_cargo; i++) { GoodsEntry *ge = &st->goods[i]; SwapPackets(ge); SlObject(ge, GetGoodsDesc()); @@ -440,7 +441,8 @@ static const SaveLoad _station_desc[] = { SLE_VAR(Station, last_vehicle_type, SLE_UINT8), SLE_VAR(Station, had_vehicle_of_type, SLE_UINT8), SLE_LST(Station, loading_vehicles, REF_VEHICLE), - SLE_CONDVAR(Station, always_accepted, SLE_UINT32, 127, SL_MAX_VERSION), + SLE_CONDVAR(Station, always_accepted, SLE_FILE_U32 | SLE_VAR_U64, 127, 198), + SLE_CONDVAR(Station, always_accepted, SLE_UINT64, 199, SL_MAX_VERSION), SLE_END() }; @@ -520,6 +522,7 @@ static void Load_STNN() { _num_flows = 0; + uint num_cargo = IsSavegameVersionBefore(199) ? 32 : NUM_CARGO; int index; while ((index = SlIterateArray()) != -1) { bool waypoint = (SlReadByte() & FACIL_WAYPOINT) != 0; @@ -538,7 +541,7 @@ static void Load_STNN() memcpy(st->airport.psa->storage, _old_st_persistent_storage.storage, sizeof(st->airport.psa->storage)); } - for (CargoID i = 0; i < NUM_CARGO; i++) { + for (CargoID i = 0; i < num_cargo; i++) { SlObject(&st->goods[i], GetGoodsDesc()); FlowSaveLoad flow; FlowStat *fs = NULL; @@ -580,9 +583,10 @@ static void Ptrs_STNN() /* Don't run when savegame version lower than 123. */ if (IsSavegameVersionBefore(123)) return; + uint num_cargo = IsSavegameVersionBefore(199) ? 32 : NUM_CARGO; Station *st; FOR_ALL_STATIONS(st) { - for (CargoID i = 0; i < NUM_CARGO; i++) { + for (CargoID i = 0; i < num_cargo; i++) { GoodsEntry *ge = &st->goods[i]; if (IsSavegameVersionBefore(183)) { SwapPackets(ge); diff --git a/src/saveload/town_sl.cpp b/src/saveload/town_sl.cpp index 3af5171b87..13438d85bf 100644 --- a/src/saveload/town_sl.cpp +++ b/src/saveload/town_sl.cpp @@ -192,7 +192,8 @@ static const SaveLoad _town_desc[] = { SLE_CONDLST(Town, psa_list, REF_STORAGE, 161, SL_MAX_VERSION), - SLE_CONDVAR(Town, cargo_produced, SLE_UINT32, 166, SL_MAX_VERSION), + SLE_CONDVAR(Town, cargo_produced, SLE_FILE_U32 | SLE_VAR_U64, 166, 198), + SLE_CONDVAR(Town, cargo_produced, SLE_UINT64, 199, SL_MAX_VERSION), /* reserve extra space in savegame here. (currently 30 bytes) */ SLE_CONDNULL(30, 2, SL_MAX_VERSION), @@ -274,12 +275,13 @@ static void Save_TOWN() static void Load_TOWN() { int index; + uint num_cargo = IsSavegameVersionBefore(199) ? 32 : NUM_CARGO; while ((index = SlIterateArray()) != -1) { Town *t = new (index) Town(); SlObject(t, _town_desc); - for (CargoID i = 0; i < NUM_CARGO; i++) { + for (CargoID i = 0; i < num_cargo; i++) { SlObject(&t->supplied[i], _town_supplied_desc); } for (int i = TE_BEGIN; i < TE_END; i++) { @@ -295,7 +297,7 @@ static void Load_TOWN() SlObject(&t->cargo_accepted, GetTileMatrixDesc()); if (t->cargo_accepted.area.w != 0) { uint arr_len = t->cargo_accepted.area.w / AcceptanceMatrix::GRID * t->cargo_accepted.area.h / AcceptanceMatrix::GRID; - t->cargo_accepted.data = MallocT(arr_len); + t->cargo_accepted.data = MallocT(arr_len); SlArray(t->cargo_accepted.data, arr_len, SLE_UINT32); /* Rebuild total cargo acceptance. */ diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp index 2234659aba..bb3db3fe3e 100644 --- a/src/saveload/vehicle_sl.cpp +++ b/src/saveload/vehicle_sl.cpp @@ -433,8 +433,8 @@ void AfterLoadVehicles(bool part_of_load) RoadVehicle *rv = RoadVehicle::From(v); rv->roadtype = HasBit(EngInfo(v->First()->engine_type)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD; rv->compatible_roadtypes = RoadTypeToRoadTypes(rv->roadtype); + FALLTHROUGH; } - FALLTHROUGH; case VEH_TRAIN: case VEH_SHIP: @@ -461,7 +461,7 @@ void AfterLoadVehicles(bool part_of_load) default: break; } - v->UpdateDeltaXY(v->direction); + v->UpdateDeltaXY(); v->coord.left = INVALID_COORD; v->UpdatePosition(); v->UpdateViewport(false); diff --git a/src/screenshot.cpp b/src/screenshot.cpp index a24cc6b211..1e7a45645c 100644 --- a/src/screenshot.cpp +++ b/src/screenshot.cpp @@ -71,23 +71,16 @@ struct ScreenshotFormat { /************************************************* **** SCREENSHOT CODE FOR WINDOWS BITMAP (.BMP) *************************************************/ -#if defined(_MSC_VER) || defined(__WATCOMC__) -#pragma pack(push, 1) -#endif /** BMP File Header (stored in little endian) */ -struct BitmapFileHeader { +PACK(struct BitmapFileHeader { uint16 type; uint32 size; uint32 reserved; uint32 off_bits; -} GCC_PACK; +}); assert_compile(sizeof(BitmapFileHeader) == 14); -#if defined(_MSC_VER) || defined(__WATCOMC__) -#pragma pack(pop) -#endif - /** BMP Info Header (stored in little endian) */ struct BitmapInfoHeader { uint32 size; diff --git a/src/script/api/game/game_goal.hpp.sq b/src/script/api/game/game_goal.hpp.sq index 7d8a3bf5e7..4cf15b3fc4 100644 --- a/src/script/api/game/game_goal.hpp.sq +++ b/src/script/api/game/game_goal.hpp.sq @@ -51,15 +51,16 @@ void SQGSGoal_Register(Squirrel *engine) SQGSGoal.DefSQConst(engine, ScriptGoal::BUTTON_SURRENDER, "BUTTON_SURRENDER"); SQGSGoal.DefSQConst(engine, ScriptGoal::BUTTON_CLOSE, "BUTTON_CLOSE"); - SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::IsValidGoal, "IsValidGoal", 2, ".i"); - SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::New, "New", 5, ".i.ii"); - SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::Remove, "Remove", 2, ".i"); - SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::SetText, "SetText", 3, ".i."); - SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::SetProgress, "SetProgress", 3, ".i."); - SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::SetCompleted, "SetCompleted", 3, ".ib"); - SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::IsCompleted, "IsCompleted", 2, ".i"); - SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::Question, "Question", 6, ".ii.ii"); - SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::CloseQuestion, "CloseQuestion", 2, ".i"); + SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::IsValidGoal, "IsValidGoal", 2, ".i"); + SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::New, "New", 5, ".i.ii"); + SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::Remove, "Remove", 2, ".i"); + SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::SetText, "SetText", 3, ".i."); + SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::SetProgress, "SetProgress", 3, ".i."); + SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::SetCompleted, "SetCompleted", 3, ".ib"); + SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::IsCompleted, "IsCompleted", 2, ".i"); + SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::Question, "Question", 6, ".ii.ii"); + SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::QuestionClient, "QuestionClient", 6, ".ii.ii"); + SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::CloseQuestion, "CloseQuestion", 2, ".i"); SQGSGoal.PostRegister(engine); } diff --git a/src/script/api/game/game_window.hpp.sq b/src/script/api/game/game_window.hpp.sq index f52de827d9..7ce2c70292 100644 --- a/src/script/api/game/game_window.hpp.sq +++ b/src/script/api/game/game_window.hpp.sq @@ -138,6 +138,8 @@ void SQGSWindow_Register(Squirrel *engine) SQGSWindow.DefSQConst(engine, ScriptWindow::WC_SPRITE_ALIGNER, "WC_SPRITE_ALIGNER"); SQGSWindow.DefSQConst(engine, ScriptWindow::WC_LINKGRAPH_LEGEND, "WC_LINKGRAPH_LEGEND"); SQGSWindow.DefSQConst(engine, ScriptWindow::WC_SAVE_PRESET, "WC_SAVE_PRESET"); + SQGSWindow.DefSQConst(engine, ScriptWindow::WC_FRAMERATE_DISPLAY, "WC_FRAMERATE_DISPLAY"); + SQGSWindow.DefSQConst(engine, ScriptWindow::WC_FRAMETIME_GRAPH, "WC_FRAMETIME_GRAPH"); SQGSWindow.DefSQConst(engine, ScriptWindow::WC_INVALID, "WC_INVALID"); SQGSWindow.DefSQConst(engine, ScriptWindow::TC_BLUE, "TC_BLUE"); SQGSWindow.DefSQConst(engine, ScriptWindow::TC_SILVER, "TC_SILVER"); @@ -450,6 +452,16 @@ void SQGSWindow_Register(Squirrel *engine) SQGSWindow.DefSQConst(engine, ScriptWindow::WID_SL_NEWGRF_INFO, "WID_SL_NEWGRF_INFO"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_SL_LOAD_BUTTON, "WID_SL_LOAD_BUTTON"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_SL_MISSING_NEWGRFS, "WID_SL_MISSING_NEWGRFS"); + SQGSWindow.DefSQConst(engine, ScriptWindow::WID_FRW_CAPTION, "WID_FRW_CAPTION"); + SQGSWindow.DefSQConst(engine, ScriptWindow::WID_FRW_RATE_GAMELOOP, "WID_FRW_RATE_GAMELOOP"); + SQGSWindow.DefSQConst(engine, ScriptWindow::WID_FRW_RATE_DRAWING, "WID_FRW_RATE_DRAWING"); + SQGSWindow.DefSQConst(engine, ScriptWindow::WID_FRW_RATE_FACTOR, "WID_FRW_RATE_FACTOR"); + SQGSWindow.DefSQConst(engine, ScriptWindow::WID_FRW_INFO_DATA_POINTS, "WID_FRW_INFO_DATA_POINTS"); + SQGSWindow.DefSQConst(engine, ScriptWindow::WID_FRW_TIMES_NAMES, "WID_FRW_TIMES_NAMES"); + SQGSWindow.DefSQConst(engine, ScriptWindow::WID_FRW_TIMES_CURRENT, "WID_FRW_TIMES_CURRENT"); + SQGSWindow.DefSQConst(engine, ScriptWindow::WID_FRW_TIMES_AVERAGE, "WID_FRW_TIMES_AVERAGE"); + SQGSWindow.DefSQConst(engine, ScriptWindow::WID_FGW_CAPTION, "WID_FGW_CAPTION"); + SQGSWindow.DefSQConst(engine, ScriptWindow::WID_FGW_GRAPH, "WID_FGW_GRAPH"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_GL_TEMPERATE, "WID_GL_TEMPERATE"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_GL_ARCTIC, "WID_GL_ARCTIC"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_GL_TROPICAL, "WID_GL_TROPICAL"); @@ -551,6 +563,7 @@ void SQGSWindow_Register(Squirrel *engine) SQGSWindow.DefSQConst(engine, ScriptWindow::WID_GL_DELETE_GROUP, "WID_GL_DELETE_GROUP"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_GL_RENAME_GROUP, "WID_GL_RENAME_GROUP"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_GL_REPLACE_PROTECTION, "WID_GL_REPLACE_PROTECTION"); + SQGSWindow.DefSQConst(engine, ScriptWindow::WID_GL_INFO, "WID_GL_INFO"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_H_BACKGROUND, "WID_H_BACKGROUND"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_DPI_MATRIX_WIDGET, "WID_DPI_MATRIX_WIDGET"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_DPI_SCROLLBAR, "WID_DPI_SCROLLBAR"); @@ -626,9 +639,11 @@ void SQGSWindow_Register(Squirrel *engine) SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TF_BACKGROUND, "WID_TF_BACKGROUND"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TF_VSCROLLBAR, "WID_TF_VSCROLLBAR"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TF_HSCROLLBAR, "WID_TF_HSCROLLBAR"); + SQGSWindow.DefSQConst(engine, ScriptWindow::WID_MTS_CAPTION, "WID_MTS_CAPTION"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_MTS_LIST_LEFT, "WID_MTS_LIST_LEFT"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_MTS_PLAYLIST, "WID_MTS_PLAYLIST"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_MTS_LIST_RIGHT, "WID_MTS_LIST_RIGHT"); + SQGSWindow.DefSQConst(engine, ScriptWindow::WID_MTS_MUSICSET, "WID_MTS_MUSICSET"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_MTS_ALL, "WID_MTS_ALL"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_MTS_OLD, "WID_MTS_OLD"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_MTS_NEW, "WID_MTS_NEW"); @@ -1180,7 +1195,7 @@ void SQGSWindow_Register(Squirrel *engine) SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TN_TRAINS, "WID_TN_TRAINS"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TN_ROADVEHS, "WID_TN_ROADVEHS"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TN_SHIPS, "WID_TN_SHIPS"); - SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TN_AIRCRAFTS, "WID_TN_AIRCRAFTS"); + SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TN_AIRCRAFT, "WID_TN_AIRCRAFT"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TN_ZOOM_IN, "WID_TN_ZOOM_IN"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TN_ZOOM_OUT, "WID_TN_ZOOM_OUT"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TN_BUILDING_TOOLS_START, "WID_TN_BUILDING_TOOLS_START"); diff --git a/src/script/api/game_changelog.hpp b/src/script/api/game_changelog.hpp index 5f278e4f08..390c1f31ff 100644 --- a/src/script/api/game_changelog.hpp +++ b/src/script/api/game_changelog.hpp @@ -25,6 +25,7 @@ * \li GSViewport::ScrollEveryoneTo * \li GSViewport::ScrollCompanyClientsTo * \li GSViewport::ScrollClientTo + * \li GSGoal::QuestionClient * * \b 1.8.0 * diff --git a/src/script/api/script_company.hpp b/src/script/api/script_company.hpp index 4bfe0d02e6..dc917500b7 100644 --- a/src/script/api/script_company.hpp +++ b/src/script/api/script_company.hpp @@ -55,12 +55,12 @@ public: EXPENSES_NEW_VEHICLES = ::EXPENSES_NEW_VEHICLES, ///< New vehicles. EXPENSES_TRAIN_RUN = ::EXPENSES_TRAIN_RUN, ///< Running costs trains. EXPENSES_ROADVEH_RUN = ::EXPENSES_ROADVEH_RUN, ///< Running costs road vehicles. - EXPENSES_AIRCRAFT_RUN = ::EXPENSES_AIRCRAFT_RUN, ///< Running costs aircrafts. + EXPENSES_AIRCRAFT_RUN = ::EXPENSES_AIRCRAFT_RUN, ///< Running costs aircraft. EXPENSES_SHIP_RUN = ::EXPENSES_SHIP_RUN, ///< Running costs ships. EXPENSES_PROPERTY = ::EXPENSES_PROPERTY, ///< Property costs. EXPENSES_TRAIN_INC = ::EXPENSES_TRAIN_INC, ///< Income from trains. EXPENSES_ROADVEH_INC = ::EXPENSES_ROADVEH_INC, ///< Income from road vehicles. - EXPENSES_AIRCRAFT_INC = ::EXPENSES_AIRCRAFT_INC, ///< Income from aircrafts. + EXPENSES_AIRCRAFT_INC = ::EXPENSES_AIRCRAFT_INC, ///< Income from aircraft. EXPENSES_SHIP_INC = ::EXPENSES_SHIP_INC, ///< Income from ships. EXPENSES_LOAN_INT = ::EXPENSES_LOAN_INT, ///< Interest payments over the loan. EXPENSES_OTHER = ::EXPENSES_OTHER, ///< Other expenses. diff --git a/src/script/api/script_goal.cpp b/src/script/api/script_goal.cpp index 5153e0ef0e..c183b75834 100644 --- a/src/script/api/script_goal.cpp +++ b/src/script/api/script_goal.cpp @@ -10,6 +10,7 @@ /** @file script_goal.cpp Implementation of ScriptGoal. */ #include "../../stdafx.h" +#include "script_game.hpp" #include "script_goal.hpp" #include "script_error.hpp" #include "script_industry.hpp" @@ -19,6 +20,7 @@ #include "../script_instance.hpp" #include "../../goal_base.h" #include "../../string_func.h" +#include "../../network/network_base.h" #include "../../safeguards.h" @@ -107,7 +109,7 @@ return g != NULL && g->completed; } -/* static */ bool ScriptGoal::Question(uint16 uniqueid, ScriptCompany::CompanyID company, Text *question, QuestionType type, int buttons) +/* static */ bool ScriptGoal::DoQuestion(uint16 uniqueid, uint8 target, bool is_client, Text *question, QuestionType type, int buttons) { CCountedPtr counter(question); @@ -115,15 +117,32 @@ EnforcePrecondition(false, question != NULL); const char *text = question->GetEncodedText(); EnforcePreconditionEncodedText(false, text); - EnforcePrecondition(false, company == ScriptCompany::COMPANY_INVALID || ScriptCompany::ResolveCompanyID(company) != ScriptCompany::COMPANY_INVALID); EnforcePrecondition(false, CountBits(buttons) >= 1 && CountBits(buttons) <= 3); 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); +} + +/* static */ bool ScriptGoal::Question(uint16 uniqueid, ScriptCompany::CompanyID company, Text *question, QuestionType type, int buttons) +{ + EnforcePrecondition(false, company == ScriptCompany::COMPANY_INVALID || ScriptCompany::ResolveCompanyID(company) != ScriptCompany::COMPANY_INVALID); uint8 c = company; if (company == ScriptCompany::COMPANY_INVALID) c = INVALID_COMPANY; - return ScriptObject::DoCommand(0, uniqueid | (c << 16) | (type << 24), buttons, CMD_GOAL_QUESTION, text); + return DoQuestion(uniqueid, c, false, question, type, buttons); +} + +/* static */ bool ScriptGoal::QuestionClient(uint16 uniqueid, ScriptClient::ClientID client, Text *question, QuestionType type, int buttons) +{ + 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); +#else + return false; +#endif } /* static */ bool ScriptGoal::CloseQuestion(uint16 uniqueid) diff --git a/src/script/api/script_goal.hpp b/src/script/api/script_goal.hpp index a9c7b239d5..f5dfba095f 100644 --- a/src/script/api/script_goal.hpp +++ b/src/script/api/script_goal.hpp @@ -12,6 +12,7 @@ #ifndef SCRIPT_GOAL_HPP #define SCRIPT_GOAL_HPP +#include "script_client.hpp" #include "script_company.hpp" #include "../../goal_type.h" @@ -160,7 +161,7 @@ public: static bool IsCompleted(GoalID goal_id); /** - * Ask a question. + * Ask a question of all players in a company. * @param uniqueid Your unique id to distinguish results of multiple questions in the returning event. * @param company The company to ask the question, or ScriptCompany::COMPANY_INVALID for all. * @param question The question to ask (can be either a raw string, or a ScriptText object). @@ -176,6 +177,24 @@ public: */ static bool Question(uint16 uniqueid, ScriptCompany::CompanyID company, Text *question, QuestionType type, int buttons); + /** + * Ask client a question. + * @param uniqueid Your unique id to distinguish results of multiple questions in the returning event. + * @param client The client to ask the question. + * @param question The question to ask (can be either a raw string, or a ScriptText object). + * @param type The type of question that is being asked. + * @param buttons Any combinations (at least 1, up to 3) of buttons defined in QuestionButton. Like BUTTON_YES + BUTTON_NO. + * @return True if the action succeeded. + * @pre No ScriptCompanyMode may be in scope. + * @pre ScriptGame::IsMultiplayer() + * @pre question != NULL && len(question) != 0. + * @pre ResolveClientID(client) != CLIENT_INVALID. + * @pre CountBits(buttons) >= 1 && CountBits(buttons) <= 3. + * @note Replies to the question are given by you via the event ScriptEvent_GoalQuestionAnswer. + * @note There is no guarantee you ever get a reply on your question. + */ + static bool QuestionClient(uint16 uniqueid, ScriptClient::ClientID client, Text *question, QuestionType type, int buttons); + /** * Close the question on all clients. * @param uniqueid The uniqueid of the question you want to close. @@ -187,6 +206,12 @@ public: * companies, but you are only interested in the reply of the first. */ static bool CloseQuestion(uint16 uniqueid); + +protected: + /** + * Does common checks and asks the question. + */ + static bool DoQuestion(uint16 uniqueid, uint8 target, bool is_client, Text *question, QuestionType type, int buttons); }; #endif /* SCRIPT_GOAL_HPP */ diff --git a/src/script/api/script_rail.cpp b/src/script/api/script_rail.cpp index af68a3edc8..25ad2ec131 100644 --- a/src/script/api/script_rail.cpp +++ b/src/script/api/script_rail.cpp @@ -157,7 +157,7 @@ EnforcePrecondition(false, station_id == ScriptStation::STATION_NEW || station_id == ScriptStation::STATION_JOIN_ADJACENT || ScriptStation::IsValidStation(station_id)); uint32 p1 = GetCurrentRailType() | (platform_length << 16) | (num_platforms << 8); - if (direction == RAILTRACK_NW_SE) p1 |= (1 << 4); + if (direction == RAILTRACK_NW_SE) p1 |= (1 << 6); if (station_id != ScriptStation::STATION_JOIN_ADJACENT) p1 |= (1 << 24); return ScriptObject::DoCommand(tile, p1, (ScriptStation::IsValidStation(station_id) ? station_id : INVALID_STATION) << 16, CMD_BUILD_RAIL_STATION); } @@ -176,7 +176,7 @@ EnforcePrecondition(false, goal_industry == ScriptIndustryType::INDUSTRYTYPE_UNKNOWN || goal_industry == ScriptIndustryType::INDUSTRYTYPE_TOWN || ScriptIndustryType::IsValidIndustryType(goal_industry)); uint32 p1 = GetCurrentRailType() | (platform_length << 16) | (num_platforms << 8); - if (direction == RAILTRACK_NW_SE) p1 |= 1 << 4; + if (direction == RAILTRACK_NW_SE) p1 |= 1 << 6; if (station_id != ScriptStation::STATION_JOIN_ADJACENT) p1 |= (1 << 24); const GRFFile *file; @@ -244,7 +244,7 @@ EnforcePrecondition(false, KillFirstBit((uint)rail_track) == 0); EnforcePrecondition(false, IsRailTypeAvailable(GetCurrentRailType())); - return ScriptObject::DoCommand(tile, tile, GetCurrentRailType() | (FindFirstTrack((::TrackBits)rail_track) << 4), CMD_BUILD_RAILROAD_TRACK); + return ScriptObject::DoCommand(tile, tile, GetCurrentRailType() | (FindFirstTrack((::TrackBits)rail_track) << 6), CMD_BUILD_RAILROAD_TRACK); } /* static */ bool ScriptRail::RemoveRailTrack(TileIndex tile, RailTrack rail_track) @@ -255,7 +255,7 @@ EnforcePrecondition(false, GetRailTracks(tile) & rail_track); EnforcePrecondition(false, KillFirstBit((uint)rail_track) == 0); - return ScriptObject::DoCommand(tile, tile, FindFirstTrack((::TrackBits)rail_track) << 4, CMD_REMOVE_RAILROAD_TRACK); + return ScriptObject::DoCommand(tile, tile, FindFirstTrack((::TrackBits)rail_track) << 6, CMD_REMOVE_RAILROAD_TRACK); } /* static */ bool ScriptRail::AreTilesConnected(TileIndex from, TileIndex tile, TileIndex to) @@ -355,7 +355,7 @@ static uint32 SimulateDrag(TileIndex from, TileIndex tile, TileIndex *to) (::TileX(from) == ::TileX(tile) && ::TileX(tile) == ::TileX(to)) || (::TileY(from) == ::TileY(tile) && ::TileY(tile) == ::TileY(to))); - uint32 p2 = SimulateDrag(from, tile, &to) | 1 << 8 | ScriptRail::GetCurrentRailType();; + uint32 p2 = SimulateDrag(from, tile, &to) | 1 << 10 | ScriptRail::GetCurrentRailType();; return ScriptObject::DoCommand(tile, to, p2, CMD_BUILD_RAILROAD_TRACK); } diff --git a/src/script/api/script_stationlist.cpp b/src/script/api/script_stationlist.cpp index ab9503a1b5..51a06b5a74 100644 --- a/src/script/api/script_stationlist.cpp +++ b/src/script/api/script_stationlist.cpp @@ -151,13 +151,13 @@ void CargoCollector::Update(StationID from, StationID via, uint amount) switch (Tselector) { case ScriptStationList_Cargo::CS_VIA_BY_FROM: if (via != this->other_station) return; - /* fall through */ + FALLTHROUGH; case ScriptStationList_Cargo::CS_BY_FROM: key = from; break; case ScriptStationList_Cargo::CS_FROM_BY_VIA: if (from != this->other_station) return; - /* fall through */ + FALLTHROUGH; case ScriptStationList_Cargo::CS_BY_VIA: key = via; break; diff --git a/src/script/api/script_town.cpp b/src/script/api/script_town.cpp index d81704ae38..4cdd6a9d0e 100644 --- a/src/script/api/script_town.cpp +++ b/src/script/api/script_town.cpp @@ -159,24 +159,24 @@ /* static */ bool ScriptTown::SetGrowthRate(TownID town_id, uint32 days_between_town_growth) { EnforcePrecondition(false, IsValidTown(town_id)); - + uint16 growth_rate; switch (days_between_town_growth) { case TOWN_GROWTH_NORMAL: - days_between_town_growth = 0; + growth_rate = 0; break; case TOWN_GROWTH_NONE: - days_between_town_growth = TOWN_GROW_RATE_CUSTOM_NONE; + growth_rate = TOWN_GROWTH_RATE_NONE; break; default: - days_between_town_growth = days_between_town_growth * DAY_TICKS / TOWN_GROWTH_TICKS; - EnforcePrecondition(false, days_between_town_growth < TOWN_GROW_RATE_CUSTOM); - if (days_between_town_growth == 0) days_between_town_growth = 1; // as fast as possible + EnforcePrecondition(false, days_between_town_growth <= MAX_TOWN_GROWTH_TICKS); + /* Don't use growth_rate 0 as it means GROWTH_NORMAL */ + growth_rate = max(days_between_town_growth * DAY_TICKS, 2u) - 1; break; } - return ScriptObject::DoCommand(::Town::Get(town_id)->xy, town_id, days_between_town_growth, CMD_TOWN_GROWTH_RATE); + return ScriptObject::DoCommand(::Town::Get(town_id)->xy, town_id, growth_rate, CMD_TOWN_GROWTH_RATE); } /* static */ int32 ScriptTown::GetGrowthRate(TownID town_id) @@ -185,9 +185,9 @@ const Town *t = ::Town::Get(town_id); - if (t->growth_rate == TOWN_GROW_RATE_CUSTOM_NONE) return TOWN_GROWTH_NONE; + if (t->growth_rate == TOWN_GROWTH_RATE_NONE) return TOWN_GROWTH_NONE; - return ((t->growth_rate & ~TOWN_GROW_RATE_CUSTOM) * TOWN_GROWTH_TICKS + DAY_TICKS) / DAY_TICKS; + return RoundDivSU(t->growth_rate + 1, DAY_TICKS); } /* static */ int32 ScriptTown::GetDistanceManhattanToTile(TownID town_id, TileIndex tile) diff --git a/src/script/api/script_town.hpp b/src/script/api/script_town.hpp index 03868e67a4..7fdf8a6b39 100644 --- a/src/script/api/script_town.hpp +++ b/src/script/api/script_town.hpp @@ -259,7 +259,7 @@ public: * @param town_id The index of the town. * @param days_between_town_growth The amount of days between town growth, TOWN_GROWTH_NONE or TOWN_GROWTH_NORMAL. * @pre IsValidTown(town_id). - * @pre days_between_town_growth <= 30000 || days_between_town_growth == TOWN_GROWTH_NONE || days_between_town_growth == TOWN_GROWTH_NORMAL. + * @pre days_between_town_growth <= 880 || days_between_town_growth == TOWN_GROWTH_NONE || days_between_town_growth == TOWN_GROWTH_NORMAL. * @return True if the action succeeded. * @note Even when setting a growth rate, towns only grow when the conditions for growth (SetCargoCoal) are met, * and the game settings (economy.town_growth_rate) allow town growth at all. diff --git a/src/script/api/script_window.hpp b/src/script/api/script_window.hpp index fbdffb54b7..9dcf58e05b 100644 --- a/src/script/api/script_window.hpp +++ b/src/script/api/script_window.hpp @@ -32,6 +32,7 @@ #include "../../widgets/engine_widget.h" #include "../../widgets/error_widget.h" #include "../../widgets/fios_widget.h" +#include "../../widgets/framerate_widget.h" #include "../../widgets/genworld_widget.h" #include "../../widgets/goal_widget.h" #include "../../widgets/graph_widget.h" @@ -764,6 +765,18 @@ public: */ WC_SAVE_PRESET = ::WC_SAVE_PRESET, + /** + * Framerate display; %Window numbers: + * - 0 = #FramerateDisplayWidgets + */ + WC_FRAMERATE_DISPLAY = ::WC_FRAMERATE_DISPLAY, + + /** + * Frame time graph; %Window numbers: + * - 0 = #FrametimeGraphWindowWidgets + */ + WC_FRAMETIME_GRAPH = ::WC_FRAMETIME_GRAPH, + WC_INVALID = ::WC_INVALID, ///< Invalid window. }; @@ -1275,6 +1288,25 @@ public: WID_SL_MISSING_NEWGRFS = ::WID_SL_MISSING_NEWGRFS, ///< Button to find missing NewGRFs online. }; + /* automatically generated from ../../widgets/framerate_widget.h */ + /** Widgets of the #FramerateWindow class. */ + enum FramerateWindowWidgets { + WID_FRW_CAPTION = ::WID_FRW_CAPTION, + WID_FRW_RATE_GAMELOOP = ::WID_FRW_RATE_GAMELOOP, + WID_FRW_RATE_DRAWING = ::WID_FRW_RATE_DRAWING, + WID_FRW_RATE_FACTOR = ::WID_FRW_RATE_FACTOR, + WID_FRW_INFO_DATA_POINTS = ::WID_FRW_INFO_DATA_POINTS, + WID_FRW_TIMES_NAMES = ::WID_FRW_TIMES_NAMES, + WID_FRW_TIMES_CURRENT = ::WID_FRW_TIMES_CURRENT, + WID_FRW_TIMES_AVERAGE = ::WID_FRW_TIMES_AVERAGE, + }; + + /** Widgets of the #FrametimeGraphWindow class. */ + enum FrametimeGraphWindowWidgets { + WID_FGW_CAPTION = ::WID_FGW_CAPTION, + WID_FGW_GRAPH = ::WID_FGW_GRAPH, + }; + /* automatically generated from ../../widgets/genworld_widget.h */ /** Widgets of the #GenerateLandscapeWindow class. */ enum GenerateLandscapeWidgets { @@ -1439,6 +1471,7 @@ public: WID_GL_DELETE_GROUP = ::WID_GL_DELETE_GROUP, ///< Delete group button. WID_GL_RENAME_GROUP = ::WID_GL_RENAME_GROUP, ///< Rename group button. WID_GL_REPLACE_PROTECTION = ::WID_GL_REPLACE_PROTECTION, ///< Replace protection button. + WID_GL_INFO = ::WID_GL_INFO, ///< Group info. }; /* automatically generated from ../../widgets/highscore_widget.h */ @@ -1581,9 +1614,11 @@ public: /* automatically generated from ../../widgets/music_widget.h */ /** Widgets of the #MusicTrackSelectionWindow class. */ enum MusicTrackSelectionWidgets { + WID_MTS_CAPTION = ::WID_MTS_CAPTION, ///< Window caption. WID_MTS_LIST_LEFT = ::WID_MTS_LIST_LEFT, ///< Left button. WID_MTS_PLAYLIST = ::WID_MTS_PLAYLIST, ///< Playlist. WID_MTS_LIST_RIGHT = ::WID_MTS_LIST_RIGHT, ///< Right button. + WID_MTS_MUSICSET = ::WID_MTS_MUSICSET, ///< Music set selection. WID_MTS_ALL = ::WID_MTS_ALL, ///< All button. WID_MTS_OLD = ::WID_MTS_OLD, ///< Old button. WID_MTS_NEW = ::WID_MTS_NEW, ///< New button. @@ -2381,7 +2416,7 @@ public: WID_TN_TRAINS = ::WID_TN_TRAINS, ///< Train menu. WID_TN_ROADVEHS = ::WID_TN_ROADVEHS, ///< Road vehicle menu. WID_TN_SHIPS = ::WID_TN_SHIPS, ///< Ship menu. - WID_TN_AIRCRAFTS = ::WID_TN_AIRCRAFTS, ///< Aircraft menu. + WID_TN_AIRCRAFT = ::WID_TN_AIRCRAFT, ///< Aircraft menu. WID_TN_ZOOM_IN = ::WID_TN_ZOOM_IN, ///< Zoom in the main viewport. WID_TN_ZOOM_OUT = ::WID_TN_ZOOM_OUT, ///< Zoom out the main viewport. WID_TN_BUILDING_TOOLS_START = ::WID_TN_BUILDING_TOOLS_START, ///< Helper for the offset of the building tools diff --git a/src/script/api/template/template_window.hpp.sq b/src/script/api/template/template_window.hpp.sq index a21a75ab89..3077215ec2 100644 --- a/src/script/api/template/template_window.hpp.sq +++ b/src/script/api/template/template_window.hpp.sq @@ -77,6 +77,10 @@ namespace SQConvert { template <> inline int Return(HSQUIRRELVM vm, ScriptWindow::ErrorMessageWidgets res) { sq_pushinteger(vm, (int32)res); return 1; } template <> inline ScriptWindow::SaveLoadWidgets GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::SaveLoadWidgets)tmp; } template <> inline int Return(HSQUIRRELVM vm, ScriptWindow::SaveLoadWidgets res) { sq_pushinteger(vm, (int32)res); return 1; } + template <> inline ScriptWindow::FramerateWindowWidgets GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::FramerateWindowWidgets)tmp; } + template <> inline int Return(HSQUIRRELVM vm, ScriptWindow::FramerateWindowWidgets res) { sq_pushinteger(vm, (int32)res); return 1; } + template <> inline ScriptWindow::FrametimeGraphWindowWidgets GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::FrametimeGraphWindowWidgets)tmp; } + template <> inline int Return(HSQUIRRELVM vm, ScriptWindow::FrametimeGraphWindowWidgets res) { sq_pushinteger(vm, (int32)res); return 1; } template <> inline ScriptWindow::GenerateLandscapeWidgets GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::GenerateLandscapeWidgets)tmp; } template <> inline int Return(HSQUIRRELVM vm, ScriptWindow::GenerateLandscapeWidgets res) { sq_pushinteger(vm, (int32)res); return 1; } template <> inline ScriptWindow::CreateScenarioWidgets GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::CreateScenarioWidgets)tmp; } diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 0420ba15b3..5ebac02807 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -114,19 +114,24 @@ static int GetCurRes() static void ShowCustCurrency(); template -static DropDownList *BuiltSetDropDownList(int *selected_index) +static DropDownList *BuildSetDropDownList(int *selected_index, bool allow_selection) { int n = T::GetNumSets(); *selected_index = T::GetIndexOfUsedSet(); DropDownList *list = new DropDownList(); for (int i = 0; i < n; i++) { - *list->Append() = new DropDownListCharStringItem(T::GetSet(i)->name, i, (_game_mode == GM_MENU) ? false : (*selected_index != i)); + *list->Append() = new DropDownListCharStringItem(T::GetSet(i)->name, i, !allow_selection && (*selected_index != i)); } return list; } +DropDownList *BuildMusicSetDropDownList(int *selected_index) +{ + return BuildSetDropDownList(selected_index, true); +} + /** Window for displaying the textfile of a BaseSet. */ template struct BaseSetTextfileWindow : public TextfileWindow { @@ -297,15 +302,15 @@ struct GameOptionsWindow : Window { } case WID_GO_BASE_GRF_DROPDOWN: - list = BuiltSetDropDownList(selected_index); + list = BuildSetDropDownList(selected_index, (_game_mode == GM_MENU)); break; case WID_GO_BASE_SFX_DROPDOWN: - list = BuiltSetDropDownList(selected_index); + list = BuildSetDropDownList(selected_index, (_game_mode == GM_MENU)); break; case WID_GO_BASE_MUSIC_DROPDOWN: - list = BuiltSetDropDownList(selected_index); + list = BuildMusicSetDropDownList(selected_index); break; default: @@ -544,7 +549,7 @@ struct GameOptionsWindow : Window { break; case WID_GO_BASE_MUSIC_DROPDOWN: - this->SetMediaSet(index); + ChangeMusicSet(index); break; } } @@ -1508,9 +1513,8 @@ static SettingsContainer &GetSettingsTree() SettingsPage *viewports = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_VIEWPORTS)); { viewports->Add(new SettingEntry("gui.auto_scrolling")); - viewports->Add(new SettingEntry("gui.reverse_scroll")); + viewports->Add(new SettingEntry("gui.scroll_mode")); viewports->Add(new SettingEntry("gui.smooth_scroll")); - viewports->Add(new SettingEntry("gui.left_mouse_btn_scrolling")); /* While the horizontal scrollwheel scrolling is written as general code, only * the cocoa (OSX) driver generates input for it. * Since it's also able to completely disable the scrollwheel will we display it on all platforms anyway */ diff --git a/src/settings_gui.h b/src/settings_gui.h index 05955aa557..23a343219f 100644 --- a/src/settings_gui.h +++ b/src/settings_gui.h @@ -13,6 +13,7 @@ #define SETTING_GUI_H #include "gfx_type.h" +#include "widgets/dropdown_type.h" /** Width of setting buttons */ #define SETTING_BUTTON_WIDTH ((int)NWidgetScrollbar::GetHorizontalDimension().width * 2) @@ -23,5 +24,10 @@ void DrawArrowButtons(int x, int y, Colours button_colour, byte state, bool clic void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable); void DrawBoolButton(int x, int y, bool state, bool clickable); +DropDownList *BuildMusicSetDropDownList(int *selected_index); + +/* Actually implemented in music_gui.cpp */ +void ChangeMusicSet(int index); + #endif /* SETTING_GUI_H */ diff --git a/src/settings_type.h b/src/settings_type.h index 2dc9ec92ec..f9cc00f3a3 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -71,6 +71,15 @@ struct DifficultySettings { byte town_council_tolerance; ///< minimum required town ratings to be allowed to demolish stuff }; +/** Settings relating to viewport/smallmap scrolling. */ +enum ViewportScrollMode { + VSM_VIEWPORT_RMB_FIXED, ///< Viewport moves with mouse movement on holding right mouse button, cursor position is fixed. + VSM_MAP_RMB_FIXED, ///< Map moves with mouse movement on holding right mouse button, cursor position is fixed. + VSM_MAP_RMB, ///< Map moves with mouse movement on holding right mouse button, cursor moves. + VSM_MAP_LMB, ///< Map moves with mouse movement on holding left mouse button, cursor moves. + VSM_END, ///< Number of scroll mode settings. +}; + /** Settings related to the GUI and other stuff that is not saved in the savegame. */ struct GUISettings { bool sg_full_load_any; ///< new full load calculation, any cargo must be full read from pre v93 savegames @@ -86,7 +95,7 @@ struct GUISettings { uint16 hover_delay_ms; ///< time required to activate a hover event, in milliseconds bool link_terraform_toolbar; ///< display terraform toolbar when displaying rail, road, water and airport toolbars uint8 smallmap_land_colour; ///< colour used for land and heightmap at the smallmap - bool reverse_scroll; ///< right-Click-Scrolling scrolls in the opposite direction + uint8 scroll_mode; ///< viewport scroll mode bool smooth_scroll; ///< smooth scroll viewports bool measure_tooltip; ///< show a permanent tooltip when dragging tools byte liveries; ///< options for displaying company liveries, 0=none, 1=self, 2=all @@ -105,6 +114,7 @@ struct GUISettings { bool threaded_saves; ///< should we do threaded saves? bool keep_all_autosave; ///< name the autosave in a different way bool autosave_on_exit; ///< save an autosave when you quit the game, but do not ask "Do you really want to quit?" + bool autosave_on_network_disconnect; ///< save an autosave when you get disconnected from a network game with an error? uint8 date_format_in_default_names; ///< should the default savegame/screenshot name use long dates (31th Dec 2008), short dates (31-12-2008) or ISO dates (2008-12-31) byte max_num_autosaves; ///< controls how many autosavegames are made before the game starts to overwrite (names them 0 to max_num_autosaves - 1) bool population_in_label; ///< show the population of a town in his label? @@ -112,7 +122,6 @@ struct GUISettings { uint8 scrollwheel_scrolling; ///< scrolling using the scroll wheel? uint8 scrollwheel_multiplier; ///< how much 'wheel' per incoming event from the OS? bool timetable_arrival_departure; ///< show arrivals and departures in vehicle timetables - bool left_mouse_btn_scrolling; ///< left mouse button scroll bool right_mouse_wnd_close; ///< close window with right click bool pause_on_newgame; ///< whether to start new games paused or not bool enable_signal_gui; ///< show the signal GUI when the signal button is pressed diff --git a/src/ship.h b/src/ship.h index c94cbcddb7..0f396a237d 100644 --- a/src/ship.h +++ b/src/ship.h @@ -30,7 +30,7 @@ struct Ship FINAL : public SpecializedVehicle { virtual ~Ship() { this->PreDestructor(); } void MarkDirty(); - void UpdateDeltaXY(Direction direction); + void UpdateDeltaXY(); ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_SHIP_INC : EXPENSES_SHIP_RUN; } void PlayLeaveStationSound() const; bool IsPrimaryVehicle() const { return true; } diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index 771863a24d..ca8bdfc8e7 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -34,6 +34,7 @@ #include "company_base.h" #include "tunnelbridge_map.h" #include "zoom_func.h" +#include "framerate_type.h" #include "table/strings.h" @@ -296,7 +297,7 @@ TileIndex Ship::GetOrderStationLocation(StationID station) } } -void Ship::UpdateDeltaXY(Direction direction) +void Ship::UpdateDeltaXY() { static const int8 _delta_xy_table[8][4] = { /* y_extent, x_extent, y_offs, x_offs */ @@ -310,7 +311,7 @@ void Ship::UpdateDeltaXY(Direction direction) {32, 6, -16, -3}, // NW }; - const int8 *bb = _delta_xy_table[direction]; + const int8 *bb = _delta_xy_table[this->direction]; this->x_offs = bb[3]; this->y_offs = bb[2]; this->x_extent = bb[1]; @@ -537,6 +538,10 @@ static void ShipController(Ship *v) if (v->current_order.IsType(OT_LEAVESTATION)) { v->current_order.Free(); SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP); + /* Test if continuing forward would lead to a dead-end, moving into the dock. */ + DiagDirection exitdir = VehicleExitDir(v->direction, v->state); + TileIndex tile = TileAddByDiagDir(v->tile, exitdir); + if (TrackStatusToTrackBits(GetTileTrackStatus(tile, TRANSPORT_WATER, 0, exitdir)) == TRACK_BIT_NONE) goto reverse_direction; } else if (v->dest_tile != 0) { /* We have a target, let's see if we reached it... */ if (v->current_order.IsType(OT_GOTO_WAYPOINT) && @@ -634,6 +639,8 @@ reverse_direction: bool Ship::Tick() { + PerformanceAccumulator framerate(PFE_GL_SHIPS); + if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++; ShipController(this); @@ -670,7 +677,7 @@ CommandCost CmdBuildShip(TileIndex tile, DoCommandFlag flags, const Engine *e, u v->y_pos = y; v->z_pos = GetSlopePixelZ(x, y); - v->UpdateDeltaXY(v->direction); + v->UpdateDeltaXY(); v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL; v->spritenum = svi->image_index; diff --git a/src/smallmap_gui.cpp b/src/smallmap_gui.cpp index 4ea887c066..7e3e759531 100644 --- a/src/smallmap_gui.cpp +++ b/src/smallmap_gui.cpp @@ -1351,7 +1351,7 @@ void SmallMapWindow::SelectLegendItem(int click_pos, LegendAndColour *legend, in */ void SmallMapWindow::SetOverlayCargoMask() { - uint32 cargo_mask = 0; + CargoTypes cargo_mask = 0; for (int i = 0; i != _smallmap_cargo_count; ++i) { if (_legend_linkstats[i].show_on_map) SetBit(cargo_mask, _legend_linkstats[i].type); } @@ -1559,7 +1559,7 @@ int SmallMapWindow::GetPositionOnLegend(Point pt) /* virtual */ void SmallMapWindow::OnMouseWheel(int wheel) { - if (_settings_client.gui.scrollwheel_scrolling == 0) { + if (_settings_client.gui.scrollwheel_scrolling != 2) { const NWidgetBase *wid = this->GetWidget(WID_SM_MAP); int cursor_x = _cursor.pos.x - this->left - wid->pos_x; int cursor_y = _cursor.pos.y - this->top - wid->pos_y; @@ -1628,7 +1628,7 @@ void SmallMapWindow::SetNewScroll(int sx, int sy, int sub) /* virtual */ void SmallMapWindow::OnScroll(Point delta) { - _cursor.fix_at = true; + if (_settings_client.gui.scroll_mode == VSM_VIEWPORT_RMB_FIXED || _settings_client.gui.scroll_mode == VSM_MAP_RMB_FIXED) _cursor.fix_at = true; /* While tile is at (delta.x, delta.y)? */ int sub; diff --git a/src/sound/win32_s.h b/src/sound/win32_s.h index 77906c88a3..c6c8e8d149 100644 --- a/src/sound/win32_s.h +++ b/src/sound/win32_s.h @@ -26,7 +26,7 @@ public: /** Factory for the sound driver for Windows. */ class FSoundDriver_Win32 : public DriverFactoryBase { public: - FSoundDriver_Win32() : DriverFactoryBase(Driver::DT_SOUND, 10, "win32", "Win32 WaveOut Sound Driver") {} + FSoundDriver_Win32() : DriverFactoryBase(Driver::DT_SOUND, 9, "win32", "Win32 WaveOut Sound Driver") {} /* virtual */ Driver *CreateInstance() const { return new SoundDriver_Win32(); } }; diff --git a/src/sound/xaudio2_s.cpp b/src/sound/xaudio2_s.cpp new file mode 100644 index 0000000000..60311ced20 --- /dev/null +++ b/src/sound/xaudio2_s.cpp @@ -0,0 +1,273 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file xaudio2_s.cpp XAudio2 sound driver. */ + +#ifdef WITH_XAUDIO2 + +#include "../stdafx.h" +#include "../openttd.h" +#include "../driver.h" +#include "../mixer.h" +#include "../debug.h" +#include "../core/alloc_func.hpp" +#include "../core/bitmath_func.hpp" +#include "../core/math_func.hpp" + +// Windows 8 SDK required for XAudio2 +#undef NTDDI_VERSION +#undef _WIN32_WINNT + +#define NTDDI_VERSION NTDDI_WIN8 +#define _WIN32_WINNT _WIN32_WINNT_WIN8 + +#include "xaudio2_s.h" + +#include +#include +#include +#include + +using Microsoft::WRL::ComPtr; + +#include "../os/windows/win32.h" +#include "../safeguards.h" + +// Definition of the "XAudio2Create" call used to initialise XAudio2 +typedef HRESULT(__stdcall *API_XAudio2Create)(_Outptr_ IXAudio2** ppXAudio2, UINT32 Flags, XAUDIO2_PROCESSOR XAudio2Processor); + +static FSoundDriver_XAudio2 iFSoundDriver_XAudio2; + +/** +* Implementation of the IXAudio2VoiceCallback interface. +* Provides buffered audio to XAudio2 from the OpenTTD mixer. +*/ +class StreamingVoiceContext : public IXAudio2VoiceCallback +{ +private: + int bufferLength; + char *buffer; + +public: + IXAudio2SourceVoice* SourceVoice; + + StreamingVoiceContext(int bufferLength) + { + this->bufferLength = bufferLength; + this->buffer = MallocT(bufferLength); + } + + virtual ~StreamingVoiceContext() + { + free(this->buffer); + } + + HRESULT SubmitBuffer() + { + // Ensure we do have a valid voice + if (this->SourceVoice == nullptr) + { + return E_FAIL; + } + + MxMixSamples(this->buffer, this->bufferLength / 4); + + XAUDIO2_BUFFER buf = { 0 }; + buf.AudioBytes = this->bufferLength; + buf.pAudioData = (const BYTE *) this->buffer; + + return SourceVoice->SubmitSourceBuffer(&buf); + } + + STDMETHOD_(void, OnVoiceProcessingPassStart)(UINT32) override + { + } + + STDMETHOD_(void, OnVoiceProcessingPassEnd)() override + { + } + + STDMETHOD_(void, OnStreamEnd)() override + { + } + + STDMETHOD_(void, OnBufferStart)(void*) override + { + } + + STDMETHOD_(void, OnBufferEnd)(void*) override + { + SubmitBuffer(); + } + + STDMETHOD_(void, OnLoopEnd)(void*) override + { + } + + STDMETHOD_(void, OnVoiceError)(void*, HRESULT) override + { + } +}; + +static HMODULE _xaudio_dll_handle; +static IXAudio2SourceVoice* _source_voice = nullptr; +static IXAudio2MasteringVoice* _mastering_voice = nullptr; +static ComPtr _xaudio2; +static StreamingVoiceContext* _voice_context = nullptr; + +/** +* Initialises the XAudio2 driver. +* +* @param parm Driver parameters. +* @return An error message if unsuccessful, or NULL otherwise. +* +*/ +const char *SoundDriver_XAudio2::Start(const char * const *parm) +{ + HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); + + if (FAILED(hr)) + { + DEBUG(driver, 0, "xaudio2_s: CoInitializeEx failed (%08x)", hr); + return "Failed to initialise COM"; + } + + _xaudio_dll_handle = LoadLibraryA(XAUDIO2_DLL_A); + + if (_xaudio_dll_handle == NULL) + { + CoUninitialize(); + + DEBUG(driver, 0, "xaudio2_s: Unable to load " XAUDIO2_DLL_A); + return "Failed to load XAudio2 DLL"; + } + + API_XAudio2Create xAudio2Create = (API_XAudio2Create) GetProcAddress(_xaudio_dll_handle, "XAudio2Create"); + + if (xAudio2Create == NULL) + { + FreeLibrary(_xaudio_dll_handle); + CoUninitialize(); + + DEBUG(driver, 0, "xaudio2_s: Unable to find XAudio2Create function in DLL"); + return "Failed to load XAudio2 DLL"; + } + + // Create the XAudio engine + UINT32 flags = 0; + hr = xAudio2Create(_xaudio2.GetAddressOf(), flags, XAUDIO2_DEFAULT_PROCESSOR); + + if (FAILED(hr)) + { + FreeLibrary(_xaudio_dll_handle); + CoUninitialize(); + + DEBUG(driver, 0, "xaudio2_s: XAudio2Create failed (%08x)", hr); + return "Failed to inititialise the XAudio2 engine"; + } + + // Create a mastering voice + hr = _xaudio2->CreateMasteringVoice(&_mastering_voice); + + if (FAILED(hr)) + { + _xaudio2.Reset(); + FreeLibrary(_xaudio_dll_handle); + CoUninitialize(); + + DEBUG(driver, 0, "xaudio2_s: CreateMasteringVoice failed (%08x)", hr); + return "Failed to create a mastering voice"; + } + + // Create a source voice to stream our audio + WAVEFORMATEX wfex; + + wfex.wFormatTag = WAVE_FORMAT_PCM; + wfex.nChannels = 2; + wfex.wBitsPerSample = 16; + wfex.nSamplesPerSec = GetDriverParamInt(parm, "hz", 44100); + wfex.nBlockAlign = (wfex.nChannels * wfex.wBitsPerSample) / 8; + wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign; + + // Limit buffer size to prevent overflows + int bufsize = GetDriverParamInt(parm, "bufsize", 8192); + bufsize = min(bufsize, UINT16_MAX); + + _voice_context = new StreamingVoiceContext(bufsize * 4); + + if (_voice_context == nullptr) + { + _mastering_voice->DestroyVoice(); + _xaudio2.Reset(); + FreeLibrary(_xaudio_dll_handle); + CoUninitialize(); + + return "Failed to create streaming voice context"; + } + + hr = _xaudio2->CreateSourceVoice(&_source_voice, &wfex, 0, 1.0f, _voice_context); + + if (FAILED(hr)) + { + _mastering_voice->DestroyVoice(); + _xaudio2.Reset(); + FreeLibrary(_xaudio_dll_handle); + CoUninitialize(); + + DEBUG(driver, 0, "xaudio2_s: CreateSourceVoice failed (%08x)", hr); + return "Failed to create a source voice"; + } + + _voice_context->SourceVoice = _source_voice; + hr = _source_voice->Start(0, 0); + + if (FAILED(hr)) + { + DEBUG(driver, 0, "xaudio2_s: _source_voice->Start failed (%08x)", hr); + + Stop(); + return "Failed to start the source voice"; + } + + MxInitialize(wfex.nSamplesPerSec); + + // Submit the first buffer + hr = _voice_context->SubmitBuffer(); + + if (FAILED(hr)) + { + DEBUG(driver, 0, "xaudio2_s: _voice_context->SubmitBuffer failed (%08x)", hr); + + Stop(); + return "Failed to submit the first audio buffer"; + } + + return NULL; +} + +/** +* Terminates the XAudio2 driver. +*/ +void SoundDriver_XAudio2::Stop() +{ + // Clean up XAudio2 + _source_voice->DestroyVoice(); + + delete _voice_context; + _voice_context = nullptr; + + _mastering_voice->DestroyVoice(); + + _xaudio2.Reset(); + + FreeLibrary(_xaudio_dll_handle); + CoUninitialize(); +} + +#endif diff --git a/src/sound/xaudio2_s.h b/src/sound/xaudio2_s.h new file mode 100644 index 0000000000..2385f49ee2 --- /dev/null +++ b/src/sound/xaudio2_s.h @@ -0,0 +1,33 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file xaudio2_s.h Base for XAudio2 sound handling. */ + +#ifndef SOUND_XAUDIO2_H +#define SOUND_XAUDIO2_H + +#include "sound_driver.hpp" + +/** Implementation of the XAudio2 sound driver. */ +class SoundDriver_XAudio2 : public SoundDriver { +public: + /* virtual */ const char *Start(const char * const *param); + + /* virtual */ void Stop(); + /* virtual */ const char *GetName() const { return "xaudio2"; } +}; + +/** Factory for the XAudio2 sound driver. */ +class FSoundDriver_XAudio2 : public DriverFactoryBase { +public: + FSoundDriver_XAudio2() : DriverFactoryBase(Driver::DT_SOUND, 10, "xaudio2", "XAudio2 Sound Driver") {} + /* virtual */ Driver *CreateInstance() const { return new SoundDriver_XAudio2(); } +}; + +#endif /* SOUND_XAUDIO2_H */ diff --git a/src/station_base.h b/src/station_base.h index af4d206ba0..5e16b0d548 100644 --- a/src/station_base.h +++ b/src/station_base.h @@ -470,7 +470,7 @@ public: byte last_vehicle_type; std::list loading_vehicles; GoodsEntry goods[NUM_CARGO]; ///< Goods at this station - uint32 always_accepted; ///< Bitmask of always accepted cargo types (by houses, HQs, industry tiles when industry doesn't accept cargo) + CargoTypes always_accepted; ///< Bitmask of always accepted cargo types (by houses, HQs, industry tiles when industry doesn't accept cargo) IndustryVector industries_near; ///< Cached list of industries near the station that can accept cargo, @see DeliverGoodsToIndustry() diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 5fd865a0db..6dd7bb2fd9 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -440,12 +440,12 @@ void UpdateAllStationVirtCoords() * @param st Station to query * @return the expected mask */ -static uint GetAcceptanceMask(const Station *st) +static CargoTypes GetAcceptanceMask(const Station *st) { - uint mask = 0; + CargoTypes mask = 0; for (CargoID i = 0; i < NUM_CARGO; i++) { - if (HasBit(st->goods[i].status, GoodsEntry::GES_ACCEPTANCE)) mask |= 1 << i; + if (HasBit(st->goods[i].status, GoodsEntry::GES_ACCEPTANCE)) SetBit(mask, i); } return mask; } @@ -524,7 +524,7 @@ CargoArray GetProductionAroundTiles(TileIndex tile, int w, int h, int rad) * @param rad Search radius in addition to given area * @param always_accepted bitmask of cargo accepted by houses and headquarters; can be NULL */ -CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad, uint32 *always_accepted) +CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad, CargoTypes *always_accepted) { CargoArray acceptance; if (always_accepted != NULL) *always_accepted = 0; @@ -562,7 +562,7 @@ CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad, uint3 void UpdateStationAcceptance(Station *st, bool show_msg) { /* old accepted goods types */ - uint old_acc = GetAcceptanceMask(st); + CargoTypes old_acc = GetAcceptanceMask(st); /* And retrieve the acceptance. */ CargoArray acceptance; @@ -595,7 +595,7 @@ void UpdateStationAcceptance(Station *st, bool show_msg) } /* Only show a message in case the acceptance was actually changed. */ - uint new_acc = GetAcceptanceMask(st); + CargoTypes new_acc = GetAcceptanceMask(st); if (old_acc == new_acc) return; /* show a message to report that the acceptance was changed? */ @@ -960,6 +960,8 @@ static CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags num_roadbits += CountBits(GetRoadBits(cur_tile, ROADTYPE_ROAD)); } + if (GetDisallowedRoadDirections(cur_tile) != DRD_NONE) return_cmd_error(STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD); + /* There is a tram, check if we can build road+tram stop over it. */ if (HasBit(cur_rts, ROADTYPE_TRAM)) { Owner tram_owner = GetRoadOwner(cur_tile, ROADTYPE_TRAM); @@ -1171,8 +1173,8 @@ static void RestoreTrainReservation(Train *v) * @param tile_org northern most position of station dragging/placement * @param flags operation to perform * @param p1 various bitstuffed elements - * - p1 = (bit 0- 3) - railtype - * - p1 = (bit 4) - orientation (Axis) + * - p1 = (bit 0- 5) - railtype + * - p1 = (bit 6) - orientation (Axis) * - p1 = (bit 8-15) - number of tracks * - p1 = (bit 16-23) - platform length * - p1 = (bit 24) - allow stations directly adjacent to other stations. @@ -1186,8 +1188,8 @@ static void RestoreTrainReservation(Train *v) CommandCost CmdBuildRailStation(TileIndex tile_org, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { /* Unpack parameters */ - RailType rt = Extract(p1); - Axis axis = Extract(p1); + RailType rt = Extract(p1); + Axis axis = Extract(p1); byte numtracks = GB(p1, 8, 8); byte plat_len = GB(p1, 16, 8); bool adjacent = HasBit(p1, 24); @@ -3186,7 +3188,7 @@ static VehicleEnterTileStatus VehicleEnter_Station(Vehicle *v, TileIndex tile, i void TriggerWatchedCargoCallbacks(Station *st) { /* Collect cargoes accepted since the last big tick. */ - uint cargoes = 0; + CargoTypes cargoes = 0; for (CargoID cid = 0; cid < NUM_CARGO; cid++) { if (HasBit(st->goods[cid].status, GoodsEntry::GES_ACCEPTED_BIGTICK)) SetBit(cargoes, cid); } diff --git a/src/station_func.h b/src/station_func.h index f33dbd21fb..9748297f21 100644 --- a/src/station_func.h +++ b/src/station_func.h @@ -28,7 +28,7 @@ void ShowStationViewWindow(StationID station); void UpdateAllStationVirtCoords(); CargoArray GetProductionAroundTiles(TileIndex tile, int w, int h, int rad); -CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad, uint32 *always_accepted = NULL); +CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad, CargoTypes *always_accepted = NULL); void UpdateStationAcceptance(Station *st, bool show_msg); diff --git a/src/station_gui.cpp b/src/station_gui.cpp index aa20170180..52738ab13f 100644 --- a/src/station_gui.cpp +++ b/src/station_gui.cpp @@ -56,7 +56,7 @@ int DrawStationCoverageAreaText(int left, int right, int top, StationCoverageType sct, int rad, bool supplies) { TileIndex tile = TileVirtXY(_thd.pos.x, _thd.pos.y); - uint32 cargo_mask = 0; + CargoTypes cargo_mask = 0; if (_thd.drawstyle == HT_RECT && tile < MapSize()) { CargoArray cargoes; if (supplies) { @@ -156,8 +156,8 @@ protected: static Listing last_sorting; static byte facilities; // types of stations of interest static bool include_empty; // whether we should include stations without waiting cargo - static const uint32 cargo_filter_max; - static uint32 cargo_filter; // bitmap of cargo types to include + static const CargoTypes cargo_filter_max; + static CargoTypes cargo_filter; // bitmap of cargo types to include static const Station *last_station; /* Constants for sorting stations */ @@ -654,8 +654,8 @@ public: Listing CompanyStationsWindow::last_sorting = {false, 0}; byte CompanyStationsWindow::facilities = FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK; bool CompanyStationsWindow::include_empty = true; -const uint32 CompanyStationsWindow::cargo_filter_max = UINT32_MAX; -uint32 CompanyStationsWindow::cargo_filter = UINT32_MAX; +const CargoTypes CompanyStationsWindow::cargo_filter_max = ALL_CARGOTYPES; +CargoTypes CompanyStationsWindow::cargo_filter = ALL_CARGOTYPES; const Station *CompanyStationsWindow::last_station = NULL; /* Availible station sorting functions */ @@ -1799,7 +1799,7 @@ struct StationViewWindow : public Window { { const Station *st = Station::Get(this->window_number); - uint32 cargo_mask = 0; + CargoTypes cargo_mask = 0; for (CargoID i = 0; i < NUM_CARGO; i++) { if (HasBit(st->goods[i].status, GoodsEntry::GES_ACCEPTANCE)) SetBit(cargo_mask, i); } @@ -2208,7 +2208,7 @@ static const T *FindStationsNearby(TileArea ta, bool distant_join) if (distant_join && min(ta.w, ta.h) >= _settings_game.station.station_spread) return NULL; uint max_dist = distant_join ? _settings_game.station.station_spread - min(ta.w, ta.h) : 1; - TileIndex tile = TILE_ADD(ctx.tile, TileOffsByDir(DIR_N)); + TileIndex tile = TileAddByDir(ctx.tile, DIR_N); CircularTileSearch(&tile, max_dist, ta.w, ta.h, AddNearbyStation, &ctx); return NULL; diff --git a/src/stdafx.h b/src/stdafx.h index 8c33b5e9cc..46028d7a70 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -100,12 +100,6 @@ #define strcasecmp stricmp #endif -#if defined(PSP) - #include - #include - #include -#endif - #if defined(SUNOS) || defined(HPUX) #include #endif @@ -134,20 +128,11 @@ #define CLIB_USERGROUP_PROTOS_H #endif /* __MORPHOS__ */ -#if defined(PSP) - /* PSP can only have 10 file-descriptors open at any given time, but this - * switch only limits reads via the Fio system. So keep 2 fds free for things - * like saving a game. */ - #define LIMITED_FDS 8 - #define printf pspDebugScreenPrintf -#endif /* PSP */ - /* Stuff for GCC */ #if defined(__GNUC__) || defined(__clang__) #define NORETURN __attribute__ ((noreturn)) #define CDECL #define __int64 long long - #define GCC_PACK __attribute__((packed)) /* Warn about functions using 'printf' format syntax. First argument determines which parameter * is the format string, second argument is start of values passed to printf. */ #define WARN_FORMAT(string, args) __attribute__ ((format (printf, string, args))) @@ -168,7 +153,6 @@ #if defined(__WATCOMC__) #define NORETURN #define CDECL - #define GCC_PACK #define WARN_FORMAT(string, args) #define FINAL #define FALLTHROUGH @@ -199,9 +183,7 @@ #define NTDDI_VERSION NTDDI_WIN2K // Windows 2000 #define _WIN32_WINNT 0x0500 // Windows 2000 #define _WIN32_WINDOWS 0x400 // Windows 95 - #if !defined(WINCE) - #define WINVER 0x0400 // Windows NT 4.0 / Windows 95 - #endif + #define WINVER 0x0400 // Windows NT 4.0 / Windows 95 #define _WIN32_IE_ 0x0401 // 4.01 (win98 and NT4SP5+) #endif #define NOMINMAX // Disable min/max macros in windows.h. @@ -235,11 +217,7 @@ #define inline __forceinline #endif - #if !defined(WINCE) - #define CDECL _cdecl - #endif - - #define GCC_PACK + #define CDECL _cdecl #define WARN_FORMAT(string, args) #define FINAL sealed @@ -250,10 +228,6 @@ #define FALLTHROUGH #endif - #if defined(WINCE) - int CDECL vsnprintf(char *str, size_t size, const char *format, va_list ap); - #endif - #if defined(WIN32) && !defined(_WIN64) && !defined(WIN64) #if !defined(_W64) #define _W64 @@ -274,15 +248,8 @@ #endif #endif - #if defined(WINCE) - #define strcasecmp _stricmp - #define strncasecmp _strnicmp - #undef DEBUG - #else - #define strcasecmp stricmp - #define strncasecmp strnicmp - #endif - + #define strcasecmp stricmp + #define strncasecmp strnicmp #define strtoull _strtoui64 /* MSVC doesn't have these :( */ @@ -300,10 +267,6 @@ #define SIGBUS SIGNOFP #endif -#if defined(WINCE) - #define stredup _stredup -#endif /* WINCE */ - /* NOTE: the string returned by these functions is only valid until the next * call to the same function and is not thread- or reentrancy-safe */ #if !defined(STRGEN) && !defined(SETTINGSGEN) @@ -312,12 +275,9 @@ #include #include - /* XXX - WinCE without MSVCRT doesn't support wfopen, so it seems */ - #if !defined(WINCE) - namespace std { using ::_tfopen; } - #define fopen(file, mode) _tfopen(OTTD2FS(file), _T(mode)) - #define unlink(file) _tunlink(OTTD2FS(file)) - #endif /* WINCE */ + namespace std { using ::_tfopen; } + #define fopen(file, mode) _tfopen(OTTD2FS(file), _T(mode)) + #define unlink(file) _tunlink(OTTD2FS(file)) const char *FS2OTTD(const TCHAR *name); const TCHAR *OTTD2FS(const char *name, bool console_cp = false); @@ -336,6 +296,16 @@ #define PATHSEPCHAR '/' #endif +#if defined(_MSC_VER) || defined(__WATCOMC__) +# define PACK_N(type_dec, n) __pragma(pack(push, n)) type_dec; __pragma(pack(pop)) +#elif defined(__MINGW32__) +# define PRAGMA(x) _Pragma(#x) +# define PACK_N(type_dec, n) PRAGMA(pack(push, n)) type_dec; PRAGMA(pack(pop)) +#else +# define PACK_N(type_dec, n) type_dec __attribute__((__packed__, aligned(n))) +#endif +#define PACK(type_dec) PACK_N(type_dec, 1) + /* MSVCRT of course has to have a different syntax for long long *sigh* */ #if defined(_MSC_VER) || defined(__MINGW32__) #define OTTD_PRINTF64 "%I64d" diff --git a/src/string.cpp b/src/string.cpp index 6306e6f75e..4c714a2e02 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -25,6 +25,14 @@ #include // required by vsnprintf implementation for MSVC #endif +#ifdef WIN32 +#include "os/windows/win32.h" +#endif + +#ifdef WITH_UNISCRIBE +#include "os/windows/string_uniscribe.h" +#endif + #ifdef WITH_ICU_SORT /* Required by strnatcmp. */ #include @@ -572,20 +580,32 @@ int strnatcmp(const char *s1, const char *s2, bool ignore_garbage_at_front) s1 = SkipGarbage(s1); s2 = SkipGarbage(s2); } + #ifdef WITH_ICU_SORT if (_current_collator != NULL) { UErrorCode status = U_ZERO_ERROR; int result = _current_collator->compareUTF8(s1, s2, status); if (U_SUCCESS(status)) return result; } - #endif /* WITH_ICU_SORT */ +#if defined(WIN32) && !defined(STRGEN) && !defined(SETTINGSGEN) + int res = OTTDStringCompare(s1, s2); + if (res != 0) return res - 2; // Convert to normal C return values. +#endif + /* Do a normal comparison if ICU is missing or if we cannot create a collator. */ return strcasecmp(s1, s2); } -#ifdef WITH_ICU_SORT +#ifdef WITH_UNISCRIBE + +/* static */ StringIterator *StringIterator::Create() +{ + return new UniscribeStringIterator(); +} + +#elif defined(WITH_ICU_SORT) #include #include diff --git a/src/strings.cpp b/src/strings.cpp index e1e352f5df..b793503187 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -1147,7 +1147,7 @@ static char *FormatString(char *buff, const char *str_arg, StringParameters *arg } case SCC_CARGO_LIST: { // {CARGO_LIST} - uint32 cmask = args->GetInt32(SCC_CARGO_LIST); + CargoTypes cmask = args->GetInt64(SCC_CARGO_LIST); bool first = true; const CargoSpec *cs; @@ -1788,6 +1788,11 @@ bool ReadLanguagePack(const LanguageMetadata *lang) strecpy(_config_language_file, c_file, lastof(_config_language_file)); SetCurrentGrfLangID(_current_language->newgrflangid); +#ifdef WIN32 + extern void Win32SetCurrentLocaleName(const char *iso_code); + Win32SetCurrentLocaleName(_current_language->isocode); +#endif + #ifdef WITH_ICU_SORT /* Delete previous collator. */ if (_current_collator != NULL) { @@ -2130,7 +2135,7 @@ void CheckForMissingGlyphs(bool base_font, MissingGlyphSearcher *searcher) /* Update the font with cache */ LoadStringWidthTable(searcher->Monospace()); -#if !defined(WITH_ICU_LAYOUT) +#if !defined(WITH_ICU_LAYOUT) && !defined(WITH_UNISCRIBE) /* * For right-to-left languages we need the ICU library. If * we do not have support for that library we warn the user diff --git a/src/subsidy.cpp b/src/subsidy.cpp index 62b463ced3..bd2ed07be5 100644 --- a/src/subsidy.cpp +++ b/src/subsidy.cpp @@ -334,7 +334,7 @@ bool FindSubsidyTownCargoRoute() /* Select a random town. */ const Town *src_town = Town::GetRandom(); - uint32 town_cargo_produced = src_town->cargo_produced; + CargoTypes town_cargo_produced = src_town->cargo_produced; /* Passenger subsidies are not handled here. */ ClrBit(town_cargo_produced, CT_PASSENGERS); diff --git a/src/table/settings.h.preamble b/src/table/settings.h.preamble index 33345bb713..f475e305bc 100644 --- a/src/table/settings.h.preamble +++ b/src/table/settings.h.preamble @@ -74,7 +74,7 @@ static size_t ConvertLandscape(const char *value); SDTG_GENERAL(name, SDT_INTLIST, SL_ARR, type, flags, guiflags, var, length, def, 0, 0, 0, NULL, str, strhelp, strval, proc, from, to, cat) #define SDTG_STR(name, type, flags, guiflags, var, def, str, strhelp, strval, proc, from, to, cat)\ - SDTG_GENERAL(name, SDT_STRING, SL_STR, type, flags, guiflags, var, lengthof(var), def, 0, 0, 0, NULL, str, strhelp, strval, proc, from, to, cat) + SDTG_GENERAL(name, SDT_STRING, SL_STR, type, flags, guiflags, var, sizeof(var), def, 0, 0, 0, NULL, str, strhelp, strval, proc, from, to, cat) #define SDTG_OMANY(name, type, flags, guiflags, var, def, max, full, str, strhelp, strval, proc, from, to, cat)\ SDTG_GENERAL(name, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, var, 0, def, 0, max, 0, full, str, strhelp, strval, proc, from, to, cat) @@ -102,7 +102,7 @@ static size_t ConvertLandscape(const char *value); SDT_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, base, var, lengthof(((base*)8)->var), def, 0, 0, 0, NULL, str, strhelp, strval, proc, NULL, from, to, cat) #define SDT_STR(base, var, type, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat)\ - SDT_GENERAL(#var, SDT_STRING, SL_STR, type, flags, guiflags, base, var, lengthof(((base*)8)->var), def, 0, 0, 0, NULL, str, strhelp, strval, proc, NULL, from, to, cat) + SDT_GENERAL(#var, SDT_STRING, SL_STR, type, flags, guiflags, base, var, sizeof(((base*)8)->var), def, 0, 0, 0, NULL, str, strhelp, strval, proc, NULL, from, to, cat) #define SDT_CHR(base, var, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat)\ SDT_GENERAL(#var, SDT_STRING, SL_VAR, SLE_CHAR, flags, guiflags, base, var, 1, def, 0, 0, 0, NULL, str, strhelp, strval, proc, NULL, from, to, cat) @@ -127,7 +127,7 @@ static size_t ConvertLandscape(const char *value); SDTG_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, _settings_client.var, lengthof(_settings_client.var), def, 0, 0, 0, NULL, str, strhelp, strval, proc, from, to, cat) #define SDTC_STR(var, type, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat)\ - SDTG_GENERAL(#var, SDT_STRING, SL_STR, type, flags, guiflags, _settings_client.var, lengthof(_settings_client.var), def, 0, 0, 0, NULL, str, strhelp, strval, proc, from, to, cat) + SDTG_GENERAL(#var, SDT_STRING, SL_STR, type, flags, guiflags, _settings_client.var, sizeof(_settings_client.var), def, 0, 0, 0, NULL, str, strhelp, strval, proc, from, to, cat) #define SDTC_OMANY(var, type, flags, guiflags, def, max, full, str, strhelp, strval, proc, from, to, cat)\ SDTG_GENERAL(#var, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, _settings_client.var, 1, def, 0, max, 0, full, str, strhelp, strval, proc, from, to, cat) diff --git a/src/table/settings.ini b/src/table/settings.ini index 2554a2ece5..c061c394f0 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -2560,13 +2560,17 @@ strhelp = STR_CONFIG_SETTING_AUTOSCROLL_HELPTEXT strval = STR_CONFIG_SETTING_AUTOSCROLL_DISABLED cat = SC_BASIC -[SDTC_BOOL] -var = gui.reverse_scroll +[SDTC_VAR] +var = gui.scroll_mode +type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -def = false -str = STR_CONFIG_SETTING_REVERSE_SCROLLING -strhelp = STR_CONFIG_SETTING_REVERSE_SCROLLING_HELPTEXT -cat = SC_BASIC +guiflags = SGF_MULTISTRING +def = 0 +min = 0 +max = 3 +str = STR_CONFIG_SETTING_SCROLLMODE +strhelp = STR_CONFIG_SETTING_SCROLLMODE_HELPTEXT +strval = STR_CONFIG_SETTING_SCROLLMODE_DEFAULT [SDTC_BOOL] var = gui.smooth_scroll @@ -2575,14 +2579,6 @@ def = false str = STR_CONFIG_SETTING_SMOOTH_SCROLLING strhelp = STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT -[SDTC_BOOL] -var = gui.left_mouse_btn_scrolling -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -def = false -str = STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING -strhelp = STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING_HELPTEXT -cat = SC_BASIC - [SDTC_BOOL] var = gui.right_mouse_wnd_close flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC @@ -2991,6 +2987,12 @@ flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC def = false cat = SC_BASIC +[SDTC_BOOL] +var = gui.autosave_on_network_disconnect +flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +def = true +cat = SC_EXPERT + [SDTC_VAR] var = gui.max_num_autosaves type = SLE_UINT8 diff --git a/src/tile_cmd.h b/src/tile_cmd.h index 6b8d6c69f4..ce70232a02 100644 --- a/src/tile_cmd.h +++ b/src/tile_cmd.h @@ -81,7 +81,7 @@ typedef CommandCost ClearTileProc(TileIndex tile, DoCommandFlag flags); * @param acceptance Storage destination of the cargo acceptance in 1/8 * @param always_accepted Bitmask of always accepted cargo types */ -typedef void AddAcceptedCargoProc(TileIndex tile, CargoArray &acceptance, uint32 *always_accepted); +typedef void AddAcceptedCargoProc(TileIndex tile, CargoArray &acceptance, CargoTypes *always_accepted); /** * Tile callback function signature for obtaining a tile description @@ -165,11 +165,11 @@ VehicleEnterTileStatus VehicleEnterTile(Vehicle *v, TileIndex tile, int x, int y void ChangeTileOwner(TileIndex tile, Owner old_owner, Owner new_owner); void GetTileDesc(TileIndex tile, TileDesc *td); -static inline void AddAcceptedCargo(TileIndex tile, CargoArray &acceptance, uint32 *always_accepted) +static inline void AddAcceptedCargo(TileIndex tile, CargoArray &acceptance, CargoTypes *always_accepted) { AddAcceptedCargoProc *proc = _tile_type_procs[GetTileType(tile)]->add_accepted_cargo_proc; if (proc == NULL) return; - uint32 dummy = 0; // use dummy bitmask so there don't need to be several 'always_accepted != NULL' checks + CargoTypes dummy = 0; // use dummy bitmask so there don't need to be several 'always_accepted != NULL' checks proc(tile, acceptance, always_accepted == NULL ? &dummy : always_accepted); } diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp index f253be8b3a..40ac3634f1 100644 --- a/src/toolbar_gui.cpp +++ b/src/toolbar_gui.cpp @@ -47,6 +47,7 @@ #include "goal_base.h" #include "story_base.h" #include "toolbar_gui.h" +#include "framerate_type.h" #include "widgets/toolbar_widget.h" @@ -1045,7 +1046,7 @@ static CallBackFunction PlaceLandBlockInfo() static CallBackFunction ToolbarHelpClick(Window *w) { - PopupMainToolbMenu(w, WID_TN_HELP, STR_ABOUT_MENU_LAND_BLOCK_INFO, _settings_client.gui.newgrf_developer_tools ? 12 : 9); + PopupMainToolbMenu(w, WID_TN_HELP, STR_ABOUT_MENU_LAND_BLOCK_INFO, _settings_client.gui.newgrf_developer_tools ? 13 : 10); return CBF_NONE; } @@ -1147,10 +1148,11 @@ static CallBackFunction MenuClickHelp(int index) case 5: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN); break; case 6: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM); break; case 7: MenuClickLargeWorldScreenshot(SC_WORLD); break; - case 8: ShowAboutWindow(); break; - case 9: ShowSpriteAlignerWindow(); break; - case 10: ToggleBoundingBoxes(); break; - case 11: ToggleDirtyBlocks(); break; + case 8: ShowFramerateWindow(); break; + case 9: ShowAboutWindow(); break; + case 10: ShowSpriteAlignerWindow(); break; + case 11: ToggleBoundingBoxes(); break; + case 12: ToggleDirtyBlocks(); break; } return CBF_NONE; } @@ -1482,7 +1484,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer { WID_TN_TRAINS, WID_TN_ROADVEHS, WID_TN_SHIPS, - WID_TN_AIRCRAFTS, + WID_TN_AIRCRAFT, WID_TN_ZOOM_IN, WID_TN_ZOOM_OUT, WID_TN_RAILS, @@ -1514,7 +1516,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer { WID_TN_TRAINS, WID_TN_ROADVEHS, WID_TN_SHIPS, - WID_TN_AIRCRAFTS, + WID_TN_AIRCRAFT, WID_TN_RAILS, WID_TN_ROADS, WID_TN_WATER, @@ -1548,7 +1550,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer { WID_TN_TRAINS, WID_TN_ROADVEHS, WID_TN_SHIPS, - WID_TN_AIRCRAFTS, + WID_TN_AIRCRAFT, WID_TN_RAILS, WID_TN_ROADS, WID_TN_WATER, @@ -1584,7 +1586,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer { WID_TN_TRAINS, WID_TN_ROADVEHS, WID_TN_SHIPS, - WID_TN_AIRCRAFTS, + WID_TN_AIRCRAFT, WID_TN_RAILS, WID_TN_ROADS, WID_TN_WATER, @@ -1643,7 +1645,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer { WID_TN_TRAINS, WID_TN_ROADVEHS, WID_TN_SHIPS, - WID_TN_AIRCRAFTS, + WID_TN_AIRCRAFT, WID_TN_MUSIC_SOUND, WID_TN_MESSAGES, WID_TN_HELP, @@ -1661,7 +1663,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer { WID_TN_TRAINS, WID_TN_ROADVEHS, WID_TN_SHIPS, - WID_TN_AIRCRAFTS, + WID_TN_AIRCRAFT, WID_TN_RAILS, WID_TN_ROADS, WID_TN_WATER, @@ -1702,7 +1704,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer { WID_TN_TRAINS, WID_TN_ROADVEHS, WID_TN_SHIPS, - WID_TN_AIRCRAFTS, + WID_TN_AIRCRAFT, WID_TN_RAILS, WID_TN_ROADS, WID_TN_WATER, @@ -1754,7 +1756,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer { WID_TN_TRAINS, WID_TN_ROADVEHS, WID_TN_SHIPS, - WID_TN_AIRCRAFTS, + WID_TN_AIRCRAFT, WID_TN_ZOOM_IN, WID_TN_ZOOM_OUT, WID_TN_RAILS, @@ -2000,7 +2002,7 @@ struct MainToolbarWindow : Window { * Since enabled state is the default, just disable when needed */ this->SetWidgetsDisabledState(_local_company == COMPANY_SPECTATOR, WID_TN_RAILS, WID_TN_ROADS, WID_TN_WATER, WID_TN_AIR, WID_TN_LANDSCAPE, WIDGET_LIST_END); /* disable company list drop downs, if there are no companies */ - this->SetWidgetsDisabledState(Company::GetNumItems() == 0, WID_TN_STATIONS, WID_TN_FINANCES, WID_TN_TRAINS, WID_TN_ROADVEHS, WID_TN_SHIPS, WID_TN_AIRCRAFTS, WIDGET_LIST_END); + this->SetWidgetsDisabledState(Company::GetNumItems() == 0, WID_TN_STATIONS, WID_TN_FINANCES, WID_TN_TRAINS, WID_TN_ROADVEHS, WID_TN_SHIPS, WID_TN_AIRCRAFT, WIDGET_LIST_END); this->SetWidgetDisabledState(WID_TN_GOAL, Goal::GetNumItems() == 0); this->SetWidgetDisabledState(WID_TN_STORY, StoryPage::GetNumItems() == 0); diff --git a/src/town.h b/src/town.h index 010c7c2168..19a4118bad 100644 --- a/src/town.h +++ b/src/town.h @@ -26,7 +26,7 @@ struct BuildingCounts { T class_count[HOUSE_CLASS_MAX]; }; -typedef TileMatrix AcceptanceMatrix; +typedef TileMatrix AcceptanceMatrix; static const uint CUSTOM_TOWN_NUMBER_DIFFICULTY = 4; ///< value for custom town number in difficulty settings static const uint CUSTOM_TOWN_MAX_NUMBER = 5000; ///< this is the maximum number of towns a user can specify in customisation @@ -35,8 +35,8 @@ static const uint INVALID_TOWN = 0xFFFF; static const uint TOWN_GROWTH_WINTER = 0xFFFFFFFE; ///< The town only needs this cargo in the winter (any amount) static const uint TOWN_GROWTH_DESERT = 0xFFFFFFFF; ///< The town needs the cargo for growth when on desert (any amount) -static const uint16 TOWN_GROW_RATE_CUSTOM = 0x8000; ///< If this mask is applied to Town::growth_rate, the grow_counter will not be calculated by the system (but assumed to be set by scripts) -static const uint16 TOWN_GROW_RATE_CUSTOM_NONE = 0xFFFF; ///< Special value for Town::growth_rate to disable town growth. +static const uint16 TOWN_GROWTH_RATE_NONE = 0xFFFF; ///< Special value for Town::growth_rate to disable town growth. +static const uint16 MAX_TOWN_GROWTH_TICKS = 930; ///< Max amount of original town ticks that still fit into uint16, about equal to UINT16_MAX / TOWN_GROWTH_TICKS but sligtly less to simplify calculations typedef Pool TownPool; extern TownPool _town_pool; @@ -85,9 +85,9 @@ struct Town : TownPool::PoolItem<&_town_pool> { inline byte GetPercentTransported(CargoID cid) const { return this->supplied[cid].old_act * 256 / (this->supplied[cid].old_max + 1); } /* Cargo production and acceptance stats. */ - uint32 cargo_produced; ///< Bitmap of all cargoes produced by houses in this town. + CargoTypes cargo_produced; ///< Bitmap of all cargoes produced by houses in this town. AcceptanceMatrix cargo_accepted; ///< Bitmap of cargoes accepted by houses for each 4*4 map square of the town. - uint32 cargo_accepted_total; ///< NOSAVE: Bitmap of all cargoes accepted by houses in this town. + CargoTypes cargo_accepted_total; ///< NOSAVE: Bitmap of all cargoes accepted by houses in this town. uint16 time_until_rebuild; ///< time until we rebuild a house @@ -165,6 +165,7 @@ enum TownFlags { TOWN_IS_GROWING = 0, ///< Conditions for town growth are met. Grow according to Town::growth_rate. TOWN_HAS_CHURCH = 1, ///< There can be only one church by town. TOWN_HAS_STADIUM = 2, ///< There can be only one stadium by town. + TOWN_CUSTOM_GROWTH = 3, ///< Growth rate is controlled by GS. }; CommandCost CheckforTownRating(DoCommandFlag flags, Town *t, TownRatingCheckType type); @@ -194,7 +195,6 @@ uint GetMaskOfTownActions(int *nump, CompanyID cid, const Town *t); bool GenerateTowns(TownLayout layout); const CargoSpec *FindFirstCargoWithTownEffect(TownEffect effect); - /** Town actions of a company. */ enum TownActions { TACT_NONE = 0x00, ///< Empty action set. @@ -284,6 +284,15 @@ void MakeDefaultName(T *obj) obj->town_cn = (uint16)next; // set index... } -extern uint32 _town_cargoes_accepted; +/* + * Converts original town ticks counters to plain game ticks. Note that + * tick 0 is a valid tick so actual amount is one more than the counter value. + */ +static inline uint16 TownTicksToGameTicks(uint16 ticks) { + return (min(ticks, MAX_TOWN_GROWTH_TICKS) + 1) * TOWN_GROWTH_TICKS - 1; +} + + +extern CargoTypes _town_cargoes_accepted; #endif /* TOWN_H */ diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index daaad7e8d0..92a3991ba9 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -53,7 +53,7 @@ #include "safeguards.h" TownID _new_town_id; -uint32 _town_cargoes_accepted; ///< Bitmap of all cargoes accepted by houses. +CargoTypes _town_cargoes_accepted; ///< Bitmap of all cargoes accepted by houses. /* Initialize the town-pool */ TownPool _town_pool("Town"); @@ -601,14 +601,14 @@ static void AddProducedCargo_Town(TileIndex tile, CargoArray &produced) } } -static inline void AddAcceptedCargoSetMask(CargoID cargo, uint amount, CargoArray &acceptance, uint32 *always_accepted) +static inline void AddAcceptedCargoSetMask(CargoID cargo, uint amount, CargoArray &acceptance, CargoTypes *always_accepted) { if (cargo == CT_INVALID || amount == 0) return; acceptance[cargo] += amount; SetBit(*always_accepted, cargo); } -static void AddAcceptedCargo_Town(TileIndex tile, CargoArray &acceptance, uint32 *always_accepted) +static void AddAcceptedCargo_Town(TileIndex tile, CargoArray &acceptance, CargoTypes *always_accepted) { const HouseSpec *hs = HouseSpec::Get(GetHouseType(tile)); CargoID accepts[3]; @@ -719,7 +719,7 @@ void UpdateTownCargoTotal(Town *t) static void UpdateTownCargoes(Town *t, TileIndex start, bool update_total = true) { CargoArray accepted, produced; - uint32 dummy; + CargoTypes dummy; /* Gather acceptance for all houses in an area around the start tile. * The area is composed of the square the tile is in, extended one square in all @@ -733,7 +733,7 @@ static void UpdateTownCargoes(Town *t, TileIndex start, bool update_total = true } /* Create bitmap of produced and accepted cargoes. */ - uint32 acc = 0; + CargoTypes acc = 0; for (uint cid = 0; cid < NUM_CARGO; cid++) { if (accepted[cid] >= 8) SetBit(acc, cid); if (produced[cid] > 0) SetBit(t->cargo_produced, cid); @@ -780,12 +780,13 @@ static bool GrowTown(Town *t); static void TownTickHandler(Town *t) { if (HasBit(t->flags, TOWN_IS_GROWING)) { - int i = t->grow_counter - 1; + int i = (int)t->grow_counter - 1; if (i < 0) { if (GrowTown(t)) { - i = t->growth_rate & (~TOWN_GROW_RATE_CUSTOM); + i = t->growth_rate; } else { - i = 0; + /* If growth failed wait a bit before retrying */ + i = min(t->growth_rate, TOWN_GROWTH_TICKS - 1); } } t->grow_counter = i; @@ -798,10 +799,7 @@ void OnTick_Town() Town *t; FOR_ALL_TOWNS(t) { - /* Run town tick at regular intervals, but not all at once. */ - if ((_tick_counter + t->index) % TOWN_GROWTH_TICKS == 0) { - TownTickHandler(t); - } + TownTickHandler(t); } } @@ -1228,17 +1226,48 @@ static void GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, DiagDirection t /* Possibly extend the road in a direction. * Randomize a direction and if it has a road, bail out. */ target_dir = RandomDiagDir(); - if (cur_rb & DiagDirToRoadBits(target_dir)) return; + RoadBits target_rb = DiagDirToRoadBits(target_dir); + TileIndex house_tile; // position of a possible house - /* This is the tile we will reach if we extend to this direction. */ - TileIndex house_tile = TileAddByDiagDir(tile, target_dir); // position of a possible house + if (cur_rb & target_rb) { + /* If it's a road turn possibly build a house in a corner. + * Use intersection with straight road as an indicator + * that we randomed corner house position. + * A turn (and we check for that later) always has only + * one common bit with a straight road so it has the same + * chance to be chosen as the house on the side of a road. + */ + if ((cur_rb & ROAD_X) != target_rb) return; + + /* Check whether it is a turn and if so determine + * position of the corner tile */ + switch (cur_rb) { + case ROAD_N: + house_tile = TileAddByDir(tile, DIR_S); + break; + case ROAD_S: + house_tile = TileAddByDir(tile, DIR_N); + break; + case ROAD_E: + house_tile = TileAddByDir(tile, DIR_W); + break; + case ROAD_W: + house_tile = TileAddByDir(tile, DIR_E); + break; + default: + return; // not a turn + } + target_dir = DIAGDIR_END; + } else { + house_tile = TileAddByDiagDir(tile, target_dir); + } /* Don't walk into water. */ if (HasTileWaterGround(house_tile)) return; if (!IsValidTile(house_tile)) return; - if (_settings_game.economy.allow_town_roads || _generating_world) { + if (target_dir != DIAGDIR_END && (_settings_game.economy.allow_town_roads || _generating_world)) { switch (t1->layout) { default: NOT_REACHED(); @@ -1248,7 +1277,7 @@ static void GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, DiagDirection t case TL_2X2_GRID: rcmd = GetTownRoadGridElement(t1, tile, target_dir); - allow_house = (rcmd & DiagDirToRoadBits(target_dir)) == ROAD_NONE; + allow_house = (rcmd & target_rb) == ROAD_NONE; break; case TL_BETTER_ROADS: // Use original afterwards! @@ -1258,7 +1287,7 @@ static void GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, DiagDirection t case TL_ORIGINAL: /* Allow a house at the edge. 60% chance or * always ok if no road allowed. */ - rcmd = DiagDirToRoadBits(target_dir); + rcmd = target_rb; allow_house = (!IsRoadAllowedHere(t1, house_tile, target_dir) || Chance16(6, 10)); break; } @@ -1546,6 +1575,9 @@ void UpdateTownMaxPass(Town *t) t->supplied[CT_MAIL].old_max = t->cache.population >> 4; } +static void UpdateTownGrowthRate(Town *t); +static void UpdateTownGrowth(Town *t); + /** * Does the actual town creation. * @@ -1565,8 +1597,10 @@ static void DoCreateTown(Town *t, TileIndex tile, uint32 townnameparts, TownSize UpdateTownRadius(t); t->flags = 0; t->cache.population = 0; - t->grow_counter = 0; - t->growth_rate = 250; + /* Spread growth across ticks so even if there are many + * similar towns they're unlikely to grow all in one tick */ + t->grow_counter = t->index % TOWN_GROWTH_TICKS; + t->growth_rate = TownTicksToGameTicks(250); /* Set the default cargo requirement for town growth */ switch (_settings_game.game_creation.landscape) { @@ -1623,6 +1657,7 @@ static void DoCreateTown(Town *t, TileIndex tile, uint32 townnameparts, TownSize t->cache.num_houses -= x; UpdateTownRadius(t); + UpdateTownGrowthRate(t); UpdateTownMaxPass(t); UpdateAirportsNoise(); } @@ -2381,6 +2416,7 @@ static bool BuildTownHouse(Town *t, TileIndex tile) MakeTownHouse(tile, t, construction_counter, construction_stage, house, random_bits); UpdateTownRadius(t); + UpdateTownGrowthRate(t); UpdateTownCargoes(t, tile); return true; @@ -2516,8 +2552,6 @@ const CargoSpec *FindFirstCargoWithTownEffect(TownEffect effect) return NULL; } -static void UpdateTownGrowRate(Town *t); - /** * Change the cargo goal of a town. * @param tile Unused. @@ -2546,7 +2580,7 @@ CommandCost CmdTownCargoGoal(TileIndex tile, DoCommandFlag flags, uint32 p1, uin if (flags & DC_EXEC) { t->goal[te] = p2; - UpdateTownGrowRate(t); + UpdateTownGrowth(t); InvalidateWindowData(WC_TOWN_VIEW, index); } @@ -2582,14 +2616,13 @@ CommandCost CmdTownSetText(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 * @param tile Unused. * @param flags Type of operation. * @param p1 Town ID to cargo game of. - * @param p2 Amount of days between growth, or TOWN_GROW_RATE_CUSTOM_NONE, or 0 to reset custom growth rate. + * @param p2 Amount of days between growth, or TOWN_GROWTH_RATE_NONE, or 0 to reset custom growth rate. * @param text Unused. * @return Empty cost or an error. */ CommandCost CmdTownGrowthRate(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { if (_current_company != OWNER_DEITY) return CMD_ERROR; - if ((p2 & TOWN_GROW_RATE_CUSTOM) != 0 && p2 != TOWN_GROW_RATE_CUSTOM_NONE) return CMD_ERROR; if (GB(p2, 16, 16) != 0) return CMD_ERROR; Town *t = Town::GetIfValid(p1); @@ -2597,10 +2630,10 @@ CommandCost CmdTownGrowthRate(TileIndex tile, DoCommandFlag flags, uint32 p1, ui if (flags & DC_EXEC) { if (p2 == 0) { - /* Clear TOWN_GROW_RATE_CUSTOM, UpdateTownGrowRate will determine a proper value */ - t->growth_rate = 0; + /* Just clear the flag, UpdateTownGrowth will determine a proper growth rate */ + ClrBit(t->flags, TOWN_CUSTOM_GROWTH); } else { - uint old_rate = t->growth_rate & ~TOWN_GROW_RATE_CUSTOM; + uint old_rate = t->growth_rate; if (t->grow_counter >= old_rate) { /* This also catches old_rate == 0 */ t->grow_counter = p2; @@ -2608,9 +2641,10 @@ CommandCost CmdTownGrowthRate(TileIndex tile, DoCommandFlag flags, uint32 p1, ui /* Scale grow_counter, so half finished houses stay half finished */ t->grow_counter = t->grow_counter * p2 / old_rate; } - t->growth_rate = p2 | TOWN_GROW_RATE_CUSTOM; + t->growth_rate = p2; + SetBit(t->flags, TOWN_CUSTOM_GROWTH); } - UpdateTownGrowRate(t); + UpdateTownGrowth(t); InvalidateWindowData(WC_TOWN_VIEW, p1); } @@ -2893,13 +2927,21 @@ static CommandCost TownActionFundBuildings(Town *t, DoCommandFlag flags) if (!_settings_game.economy.fund_buildings) return CMD_ERROR; if (flags & DC_EXEC) { - /* Build next tick */ - t->grow_counter = 1; /* And grow for 3 months */ t->fund_buildings_months = 3; /* Enable growth (also checking GameScript's opinion) */ - UpdateTownGrowRate(t); + UpdateTownGrowth(t); + + /* Build a new house, but add a small delay to make sure + * that spamming funding doesn't let town grow any faster + * than 1 house per 2 * TOWN_GROWTH_TICKS ticks. + * Also emulate original behaviour when town was only growing in + * TOWN_GROWTH_TICKS intervals, to make sure that it's not too + * tick-perfect and gives player some time window where he can + * spam funding with the exact same effeciency. + */ + t->grow_counter = min(t->grow_counter, 2 * TOWN_GROWTH_TICKS - (t->growth_rate - t->grow_counter) % TOWN_GROWTH_TICKS); SetWindowDirty(WC_TOWN_VIEW, t->index); } @@ -3093,8 +3135,87 @@ static void UpdateTownRating(Town *t) SetWindowDirty(WC_TOWN_AUTHORITY, t->index); } -static void UpdateTownGrowRate(Town *t) + +/** + * Updates town grow counter after growth rate change. + * Preserves relative house builting progress whenever it can. + * @param town The town to calculate grow counter for + * @param prev_growth_rate Town growth rate before it changed (one that was used with grow counter to be updated) + */ +static void UpdateTownGrowCounter(Town *t, uint16 prev_growth_rate) { + if (t->growth_rate == TOWN_GROWTH_RATE_NONE) return; + if (prev_growth_rate == TOWN_GROWTH_RATE_NONE) { + t->grow_counter = min(t->growth_rate, t->grow_counter); + return; + } + t->grow_counter = RoundDivSU((uint32)t->grow_counter * (t->growth_rate + 1), prev_growth_rate + 1); +} + +/** + * Calculates amount of active stations in the range of town (HZB_TOWN_EDGE). + * @param town The town to calculate stations for + * @returns Amount of active stations + */ +static int CountActiveStations(Town *t) +{ + int n = 0; + const Station *st; + FOR_ALL_STATIONS(st) { + if (DistanceSquare(st->xy, t->xy) <= t->cache.squared_town_zone_radius[0]) { + if (st->time_since_load <= 20 || st->time_since_unload <= 20) { + n++; + } + } + } + return n; +} + +/** + * Calculates town growth rate in normal conditions (custom growth rate not set). + * If town growth speed is set to None(0) returns the same rate as if it was Normal(2). + * @param town The town to calculate growth rate for + * @returns Calculated growth rate + */ +static uint GetNormalGrowthRate(Town *t) +{ + static const uint16 _grow_count_values[2][6] = { + { 120, 120, 120, 100, 80, 60 }, // Fund new buildings has been activated + { 320, 420, 300, 220, 160, 100 } // Normal values + }; + + int n = CountActiveStations(t); + uint16 m = _grow_count_values[t->fund_buildings_months != 0 ? 0 : 1][min(n, 5)]; + + uint growth_multiplier = _settings_game.economy.town_growth_rate != 0 ? _settings_game.economy.town_growth_rate - 1 : 1; + + m >>= growth_multiplier; + if (t->larger_town) m /= 2; + + return TownTicksToGameTicks(m / (t->cache.num_houses / 50 + 1)); +} + +/** + * Updates town growth rate. + * @param town The town to update growth rate for + */ +static void UpdateTownGrowthRate(Town *t) +{ + if (HasBit(t->flags, TOWN_CUSTOM_GROWTH)) return; + uint old_rate = t->growth_rate; + t->growth_rate = GetNormalGrowthRate(t); + UpdateTownGrowCounter(t, old_rate); + SetWindowDirty(WC_TOWN_VIEW, t->index); +} + +/** + * Updates town growth state (whether it is growing or not). + * @param town The town to update growth for + */ +static void UpdateTownGrowth(Town *t) +{ + UpdateTownGrowthRate(t); + ClrBit(t->flags, TOWN_IS_GROWING); SetWindowDirty(WC_TOWN_VIEW, t->index); @@ -3117,50 +3238,13 @@ static void UpdateTownGrowRate(Town *t) } } - if ((t->growth_rate & TOWN_GROW_RATE_CUSTOM) != 0) { - if (t->growth_rate != TOWN_GROW_RATE_CUSTOM_NONE) SetBit(t->flags, TOWN_IS_GROWING); + if (HasBit(t->flags, TOWN_CUSTOM_GROWTH)) { + if (t->growth_rate != TOWN_GROWTH_RATE_NONE) SetBit(t->flags, TOWN_IS_GROWING); SetWindowDirty(WC_TOWN_VIEW, t->index); return; } - /** - * Towns are processed every TOWN_GROWTH_TICKS ticks, and this is the - * number of times towns are processed before a new building is built. - */ - static const uint16 _grow_count_values[2][6] = { - { 120, 120, 120, 100, 80, 60 }, // Fund new buildings has been activated - { 320, 420, 300, 220, 160, 100 } // Normal values - }; - - int n = 0; - - const Station *st; - FOR_ALL_STATIONS(st) { - if (DistanceSquare(st->xy, t->xy) <= t->cache.squared_town_zone_radius[0]) { - if (st->time_since_load <= 20 || st->time_since_unload <= 20) { - n++; - } - } - } - - uint16 m; - - if (t->fund_buildings_months != 0) { - m = _grow_count_values[0][min(n, 5)]; - } else { - m = _grow_count_values[1][min(n, 5)]; - if (n == 0 && !Chance16(1, 12)) return; - } - - /* Use the normal growth rate values if new buildings have been funded in - * this town and the growth rate is set to none. */ - uint growth_multiplier = _settings_game.economy.town_growth_rate != 0 ? _settings_game.economy.town_growth_rate - 1 : 1; - - m >>= growth_multiplier; - if (t->larger_town) m /= 2; - - t->growth_rate = m / (t->cache.num_houses / 50 + 1); - t->grow_counter = min(t->growth_rate, t->grow_counter); + if (t->fund_buildings_months == 0 && CountActiveStations(t) == 0 && !Chance16(1, 12)) return; SetBit(t->flags, TOWN_IS_GROWING); SetWindowDirty(WC_TOWN_VIEW, t->index); @@ -3394,8 +3478,8 @@ void TownsMonthlyLoop() } UpdateTownAmounts(t); + UpdateTownGrowth(t); UpdateTownRating(t); - UpdateTownGrowRate(t); UpdateTownUnwanted(t); UpdateTownCargoes(t); } diff --git a/src/town_gui.cpp b/src/town_gui.cpp index 696b71afd2..17449854d6 100644 --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -269,8 +269,8 @@ public: } /* When double-clicking, continue */ if (click_count == 1 || y < 0) break; + FALLTHROUGH; } - FALLTHROUGH; case WID_TA_EXECUTE: DoCommandP(this->town->xy, this->window_number, this->sel_index, CMD_DO_TOWN_ACTION | CMD_MSG(STR_ERROR_CAN_T_DO_THIS)); @@ -337,13 +337,15 @@ public: SetDParam(1, this->town->cache.num_houses); DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y, STR_TOWN_VIEW_POPULATION_HOUSES); - SetDParam(0, this->town->supplied[CT_PASSENGERS].old_act); - SetDParam(1, this->town->supplied[CT_PASSENGERS].old_max); - DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX); + SetDParam(0, 1 << CT_PASSENGERS); + SetDParam(1, this->town->supplied[CT_PASSENGERS].old_act); + SetDParam(2, this->town->supplied[CT_PASSENGERS].old_max); + DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX); - SetDParam(0, this->town->supplied[CT_MAIL].old_act); - SetDParam(1, this->town->supplied[CT_MAIL].old_max); - DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX); + SetDParam(0, 1 << CT_MAIL); + SetDParam(1, this->town->supplied[CT_MAIL].old_act); + SetDParam(2, this->town->supplied[CT_MAIL].old_max); + DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX); bool first = true; for (int i = TE_BEGIN; i < TE_END; i++) { @@ -392,7 +394,7 @@ public: } if (HasBit(this->town->flags, TOWN_IS_GROWING)) { - SetDParam(0, ((this->town->growth_rate & (~TOWN_GROW_RATE_CUSTOM)) * TOWN_GROWTH_TICKS + DAY_TICKS) / DAY_TICKS); + SetDParam(0, RoundDivSU(this->town->growth_rate + 1, DAY_TICKS)); DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, this->town->fund_buildings_months == 0 ? STR_TOWN_VIEW_TOWN_GROWS_EVERY : STR_TOWN_VIEW_TOWN_GROWS_EVERY_FUNDED); } else { DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, STR_TOWN_VIEW_TOWN_GROW_STOPPED); @@ -745,6 +747,16 @@ public: } } + /** + * Get the string to draw the town name. + * @param t Town to draw. + * @return The string to use. + */ + static StringID GetTownString(const Town *t) + { + return t->larger_town ? STR_TOWN_DIRECTORY_CITY : STR_TOWN_DIRECTORY_TOWN; + } + virtual void DrawWidget(const Rect &r, int widget) const { switch (widget) { @@ -783,7 +795,7 @@ public: SetDParam(0, t->index); SetDParam(1, t->cache.population); - DrawString(text_left, text_right, y + (this->resize.step_height - FONT_HEIGHT_NORMAL) / 2, STR_TOWN_DIRECTORY_TOWN); + DrawString(text_left, text_right, y + (this->resize.step_height - FONT_HEIGHT_NORMAL) / 2, GetTownString(t)); y += this->resize.step_height; if (++n == this->vscroll->GetCapacity()) break; // max number of towns in 1 window @@ -822,7 +834,7 @@ public: SetDParam(0, t->index); SetDParamMaxDigits(1, 8); - d = maxdim(d, GetStringBoundingBox(STR_TOWN_DIRECTORY_TOWN)); + d = maxdim(d, GetStringBoundingBox(GetTownString(t))); } Dimension icon_size = GetSpriteSize(SPR_TOWN_RATING_GOOD); d.width += icon_size.width + 2; diff --git a/src/track_func.h b/src/track_func.h index 68de827ef1..8e2056265e 100644 --- a/src/track_func.h +++ b/src/track_func.h @@ -61,7 +61,7 @@ static inline bool IsValidTrackdirForRoadVehicle(Trackdir trackdir) */ static inline bool IsValidTrackdir(Trackdir trackdir) { - return (1 << trackdir & TRACKDIR_BIT_MASK) != 0; + return (1 << trackdir & TRACKDIR_BIT_MASK) != TRACKDIR_BIT_NONE; } /** @@ -331,6 +331,28 @@ static inline TrackdirBits TrackBitsToTrackdirBits(TrackBits bits) return (TrackdirBits)(bits * 0x101); } +/** + * Checks whether a TrackBits has a given Track. + * @param tracks The track bits. + * @param track The track to check. + */ +static inline bool HasTrack(TrackBits tracks, Track track) +{ + assert(IsValidTrack(track)); + return HasBit(tracks, track); +} + +/** + * Checks whether a TrackdirBits has a given Trackdir. + * @param trackdirs The trackdir bits. + * @param trackdir The trackdir to check. + */ +static inline bool HasTrackdir(TrackdirBits trackdirs, Trackdir trackdir) +{ + assert(IsValidTrackdir(trackdir)); + return HasBit(trackdirs, trackdir); +} + /** * Returns the present-trackdir-information of a TrackStatus. * @@ -692,4 +714,25 @@ static inline bool IsUphillTrackdir(Slope slope, Trackdir dir) return HasBit(_uphill_trackdirs[RemoveHalftileSlope(slope)], dir); } +/** + * Determine the side in which the vehicle will leave the tile + * + * @param direction vehicle direction + * @param track vehicle track bits + * @return side of tile the vehicle will leave + */ +static inline DiagDirection VehicleExitDir(Direction direction, TrackBits track) +{ + static const TrackBits state_dir_table[DIAGDIR_END] = { TRACK_BIT_RIGHT, TRACK_BIT_LOWER, TRACK_BIT_LEFT, TRACK_BIT_UPPER }; + + DiagDirection diagdir = DirToDiagDir(direction); + + /* Determine the diagonal direction in which we will exit this tile */ + if (!HasBit(direction, 0) && track != state_dir_table[diagdir]) { + diagdir = ChangeDiagDir(diagdir, DIAGDIRDIFF_90LEFT); + } + + return diagdir; +} + #endif /* TRACK_FUNC_H */ diff --git a/src/train.h b/src/train.h index c40ab75560..5958cde1a0 100644 --- a/src/train.h +++ b/src/train.h @@ -110,7 +110,7 @@ struct Train FINAL : public GroundVehicle { friend struct GroundVehicle; // GroundVehicle needs to use the acceleration functions defined at Train. void MarkDirty(); - void UpdateDeltaXY(Direction direction); + void UpdateDeltaXY(); ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_TRAIN_INC : EXPENSES_TRAIN_RUN; } void PlayLeaveStationSound() const; bool IsPrimaryVehicle() const { return this->IsFrontEngine(); } diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index fb1d2b1ee4..60a7b2ca92 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -35,6 +35,7 @@ #include "order_backup.h" #include "zoom_func.h" #include "newgrf_debug.h" +#include "framerate_type.h" #include "table/strings.h" #include "table/train_cmd.h" @@ -57,27 +58,6 @@ bool IsValidImageIndex(uint8 image_index) return image_index < lengthof(_engine_sprite_base); } -/** - * Determine the side in which the train will leave the tile - * - * @param direction vehicle direction - * @param track vehicle track bits - * @return side of tile the train will leave - */ -static inline DiagDirection TrainExitDir(Direction direction, TrackBits track) -{ - static const TrackBits state_dir_table[DIAGDIR_END] = { TRACK_BIT_RIGHT, TRACK_BIT_LOWER, TRACK_BIT_LEFT, TRACK_BIT_UPPER }; - - DiagDirection diagdir = DirToDiagDir(direction); - - /* Determine the diagonal direction in which we will exit this tile */ - if (!HasBit(direction, 0) && track != state_dir_table[diagdir]) { - diagdir = ChangeDiagDir(diagdir, DIAGDIRDIFF_90LEFT); - } - - return diagdir; -} - /** * Return the cargo weight multiplier to use for a rail vehicle @@ -1442,7 +1422,7 @@ CommandCost CmdSellRailWagon(DoCommandFlag flags, Vehicle *t, uint16 data, uint3 return cost; } -void Train::UpdateDeltaXY(Direction direction) +void Train::UpdateDeltaXY() { /* Set common defaults. */ this->x_offs = -1; @@ -1453,7 +1433,7 @@ void Train::UpdateDeltaXY(Direction direction) this->x_bb_offs = 0; this->y_bb_offs = 0; - if (!IsDiagonalDirection(direction)) { + if (!IsDiagonalDirection(this->direction)) { static const int _sign_table[] = { /* x, y */ @@ -1466,12 +1446,12 @@ void Train::UpdateDeltaXY(Direction direction) int half_shorten = (VEHICLE_LENGTH - this->gcache.cached_veh_length) / 2; /* For all straight directions, move the bound box to the centre of the vehicle, but keep the size. */ - this->x_offs -= half_shorten * _sign_table[direction]; - this->y_offs -= half_shorten * _sign_table[direction + 1]; + this->x_offs -= half_shorten * _sign_table[this->direction]; + this->y_offs -= half_shorten * _sign_table[this->direction + 1]; this->x_extent += this->x_bb_offs = half_shorten * _sign_table[direction]; this->y_extent += this->y_bb_offs = half_shorten * _sign_table[direction + 1]; } else { - switch (direction) { + switch (this->direction) { /* Shorten southern corner of the bounding box according the vehicle length * and center the bounding box on the vehicle. */ case DIR_NE: @@ -1872,9 +1852,9 @@ void ReverseTrainDirection(Train *v) return; } - /* TrainExitDir does not always produce the desired dir for depots and + /* VehicleExitDir does not always produce the desired dir for depots and * tunnels/bridges that is needed for UpdateSignalsOnSegment. */ - DiagDirection dir = TrainExitDir(v->direction, v->track); + DiagDirection dir = VehicleExitDir(v->direction, v->track); if (IsRailDepotTile(v->tile) || IsTileType(v->tile, MP_TUNNELBRIDGE)) dir = INVALID_DIAGDIR; if (UpdateSignalsOnSegment(v->tile, dir, v->owner) == SIGSEG_PBS || _settings_game.pf.reserve_paths) { @@ -3098,7 +3078,7 @@ static Vehicle *CheckTrainAtSignal(Vehicle *v, void *data) /* not front engine of a train, inside wormhole or depot, crashed */ if (!t->IsFrontEngine() || !(t->track & TRACK_BIT_MASK)) return NULL; - if (t->cur_speed > 5 || TrainExitDir(t->direction, t->track) != exitdir) return NULL; + if (t->cur_speed > 5 || VehicleExitDir(t->direction, t->track) != exitdir) return NULL; return t; } @@ -3361,7 +3341,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) } /* update image of train, as well as delta XY */ - v->UpdateDeltaXY(v->direction); + v->UpdateDeltaXY(); v->x_pos = gp.x; v->y_pos = gp.y; @@ -3681,7 +3661,7 @@ static TileIndex TrainApproachingCrossingTile(const Train *v) if (!TrainCanLeaveTile(v)) return INVALID_TILE; - DiagDirection dir = TrainExitDir(v->direction, v->track); + DiagDirection dir = VehicleExitDir(v->direction, v->track); TileIndex tile = v->tile + TileOffsByDiagDir(dir); /* not a crossing || wrong axis || unusable rail (wrong type or owner) */ @@ -3718,7 +3698,7 @@ static bool TrainCheckIfLineEnds(Train *v, bool reverse) if (!TrainCanLeaveTile(v)) return true; /* Determine the non-diagonal direction in which we will exit this tile */ - DiagDirection dir = TrainExitDir(v->direction, v->track); + DiagDirection dir = VehicleExitDir(v->direction, v->track); /* Calculate next tile */ TileIndex tile = v->tile + TileOffsByDiagDir(dir); @@ -3786,7 +3766,7 @@ static bool TrainLocoHandler(Train *v, bool mode) /* Try to reserve a path when leaving the station as we * might not be marked as wanting a reservation, e.g. * when an overlength train gets turned around in a station. */ - DiagDirection dir = TrainExitDir(v->direction, v->track); + DiagDirection dir = VehicleExitDir(v->direction, v->track); if (IsRailDepotTile(v->tile) || IsTileType(v->tile, MP_TUNNELBRIDGE)) dir = INVALID_DIAGDIR; if (UpdateSignalsOnSegment(v->tile, dir, v->owner) == SIGSEG_PBS || _settings_game.pf.reserve_paths) { @@ -3923,6 +3903,8 @@ Money Train::GetRunningCost() const */ bool Train::Tick() { + PerformanceAccumulator framerate(PFE_GL_TRAINS); + this->tick_counter++; if (this->IsFrontEngine()) { diff --git a/src/tunnel_map.h b/src/tunnel_map.h index e200a1275e..d6f475d05c 100644 --- a/src/tunnel_map.h +++ b/src/tunnel_map.h @@ -58,6 +58,7 @@ static inline void MakeRoadTunnel(TileIndex t, Owner o, DiagDirection d, RoadTyp _m[t].m5 = TRANSPORT_ROAD << 2 | d; SB(_me[t].m6, 2, 4, 0); _me[t].m7 = 0; + _me[t].m8 = 0; SetRoadOwner(t, ROADTYPE_ROAD, o); if (o != OWNER_TOWN) SetRoadOwner(t, ROADTYPE_TRAM, o); SetRoadTypes(t, r); @@ -75,11 +76,12 @@ static inline void MakeRailTunnel(TileIndex t, Owner o, DiagDirection d, RailTyp SetTileType(t, MP_TUNNELBRIDGE); SetTileOwner(t, o); _m[t].m2 = 0; - _m[t].m3 = r; + _m[t].m3 = 0; _m[t].m4 = 0; _m[t].m5 = TRANSPORT_RAIL << 2 | d; SB(_me[t].m6, 2, 4, 0); _me[t].m7 = 0; + _me[t].m8 = r; } #endif /* TUNNEL_MAP_H */ diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 9ba9b26e31..ce14188fd0 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -232,7 +232,7 @@ CommandCost CheckBridgeAvailability(BridgeType bridge_type, uint bridge_len, DoC * @param p1 packed start tile coords (~ dx) * @param p2 various bitstuffed elements * - p2 = (bit 0- 7) - bridge type (hi bh) - * - p2 = (bit 8-11) - rail type or road types. + * - p2 = (bit 8-13) - rail type or road types. * - p2 = (bit 15-16) - transport type. * @param text unused * @return the cost of this operation or an error @@ -259,7 +259,7 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u break; case TRANSPORT_RAIL: - railtype = Extract(p2); + railtype = Extract(p2); if (!ValParamRailtype(railtype)) return CMD_ERROR; break; @@ -574,7 +574,7 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u * Build Tunnel. * @param start_tile start tile of tunnel * @param flags type of operation - * @param p1 bit 0-3 railtype or roadtypes + * @param p1 bit 0-5 railtype or roadtypes * bit 8-9 transport type * @param p2 unused * @param text unused @@ -591,7 +591,7 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, _build_tunnel_endtile = 0; switch (transport_type) { case TRANSPORT_RAIL: - railtype = Extract(p1); + railtype = Extract(p1); if (!ValParamRailtype(railtype)) return CMD_ERROR; break; @@ -701,8 +701,22 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, /* Hide the tile from the terraforming command */ TileIndex old_first_tile = coa->first_tile; coa->first_tile = INVALID_TILE; + + /* CMD_TERRAFORM_LAND may append further items to _cleared_object_areas, + * however it will never erase or re-order existing items. + * _cleared_object_areas is a value-type SmallVector, therefore appending items + * may result in a backing-store re-allocation, which would invalidate the coa pointer. + * The index of the coa pointer into the _cleared_object_areas vector remains valid, + * and can be used safely after the CMD_TERRAFORM_LAND operation. + * Deliberately clear the coa pointer to avoid leaving dangling pointers which could + * inadvertently be dereferenced. + */ + assert(coa >= _cleared_object_areas.Begin() && coa < _cleared_object_areas.End()); + size_t coa_index = coa - _cleared_object_areas.Begin(); + coa = NULL; + ret = DoCommand(end_tile, end_tileh & start_tileh, 0, flags, CMD_TERRAFORM_LAND); - coa->first_tile = old_first_tile; + _cleared_object_areas[coa_index].first_tile = old_first_tile; if (ret.Failed()) return_cmd_error(STR_ERROR_UNABLE_TO_EXCAVATE_LAND); cost.AddCost(ret); } diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 0644add6dc..d4cad73e7f 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -52,6 +52,7 @@ #include "gamelog.h" #include "linkgraph/linkgraph.h" #include "linkgraph/refresh.h" +#include "framerate_type.h" #include "string_func.h" #include "scope_info.h" @@ -221,7 +222,7 @@ bool Vehicle::NeedsServicing() const if (replace_when_old && !v->NeedsAutorenewing(c, false)) continue; /* Check refittability */ - uint32 available_cargo_types, union_mask; + CargoTypes available_cargo_types, union_mask; GetArticulatedRefitMasks(new_engine, true, &union_mask, &available_cargo_types); /* Is there anything to refit? */ if (union_mask != 0) { @@ -952,10 +953,15 @@ void CallVehicleTicks() RunVehicleDayProc(); { + PerformanceMeasurer framerate(PFE_GL_ECONOMY); Station *st = nullptr; SCOPE_INFO_FMT([&st], "CallVehicleTicks: LoadUnloadStation: %s", scope_dumper().StationInfo(st)); FOR_ALL_STATIONS(st) LoadUnloadStation(st); } + PerformanceAccumulator::Reset(PFE_GL_TRAINS); + PerformanceAccumulator::Reset(PFE_GL_ROADVEHS); + PerformanceAccumulator::Reset(PFE_GL_SHIPS); + PerformanceAccumulator::Reset(PFE_GL_AIRCRAFT); Vehicle *v = NULL; SCOPE_INFO_FMT([&v], "CallVehicleTicks: %s", scope_dumper().VehicleInfo(v)); diff --git a/src/vehicle_base.h b/src/vehicle_base.h index fc40f22a62..73f499c483 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -366,9 +366,8 @@ public: /** * Updates the x and y offsets and the size of the sprite used * for this vehicle. - * @param direction the direction the vehicle is facing */ - virtual void UpdateDeltaXY(Direction direction) {} + virtual void UpdateDeltaXY() {} /** * Determines the effective direction-specific vehicle movement speed. @@ -1139,7 +1138,7 @@ struct SpecializedVehicle : public Vehicle { /* Explicitly choose method to call to prevent vtable dereference - * it gives ~3% runtime improvements in games with many vehicles */ - if (update_delta) ((T *)this)->T::UpdateDeltaXY(this->direction); + if (update_delta) ((T *)this)->T::UpdateDeltaXY(); VehicleSpriteSeq seq; ((T *)this)->T::GetImage(this->direction, EIT_ON_MAP, &seq); if (force_update || this->sprite_seq != seq) { diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index 9670fa05d0..339365f780 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -464,7 +464,7 @@ CommandCost CmdRefitVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint byte new_subtype = GB(p2, 8, 8); if (new_cid >= NUM_CARGO) return CMD_ERROR; - /* For ships and aircrafts there is always only one. */ + /* For ships and aircraft there is always only one. */ bool only_this = HasBit(p2, 7) || front->type == VEH_SHIP || front->type == VEH_AIRCRAFT; uint8 num_vehicles = GB(p2, 16, 8); diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index 8ebd73a8af..667836f566 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -416,7 +416,7 @@ struct RefitWindow : public Window { do { if (v->type == VEH_TRAIN && !vehicles_to_refit.Contains(v->index)) continue; const Engine *e = v->GetEngine(); - uint32 cmask = e->info.refit_mask; + CargoTypes cmask = e->info.refit_mask; byte callback_mask = e->info.callback_mask; /* Skip this engine if it does not carry anything */ @@ -817,8 +817,8 @@ struct RefitWindow : public Window { Vehicle *v = Vehicle::Get(this->window_number); this->selected_vehicle = v->index; this->num_vehicles = UINT8_MAX; + FALLTHROUGH; } - FALLTHROUGH; case 2: { // The vehicle selection has changed; rebuild the entire list. if (!gui_scope) break; @@ -843,8 +843,8 @@ struct RefitWindow : public Window { this->information_width = max_width; this->ReInit(); } + FALLTHROUGH; } - FALLTHROUGH; case 1: // A new cargo has been selected. if (!gui_scope) break; @@ -905,8 +905,8 @@ struct RefitWindow : public Window { if (_ctrl_pressed) this->num_vehicles = UINT8_MAX; break; } + FALLTHROUGH; } - FALLTHROUGH; default: /* Clear the selection. */ @@ -940,8 +940,8 @@ struct RefitWindow : public Window { this->InvalidateData(1); if (click_count == 1) break; + FALLTHROUGH; } - FALLTHROUGH; case WID_VR_REFIT: // refit button if (this->cargo != NULL) { @@ -1043,9 +1043,9 @@ void ShowVehicleRefitWindow(const Vehicle *v, VehicleOrderID order, Window *pare uint ShowRefitOptionsList(int left, int right, int y, EngineID engine) { /* List of cargo types of this engine */ - uint32 cmask = GetUnionOfArticulatedRefitMasks(engine, false); + CargoTypes cmask = GetUnionOfArticulatedRefitMasks(engine, false); /* List of cargo types available in this climate */ - uint32 lmask = _cargo_mask; + CargoTypes lmask = _cargo_mask; /* Draw nothing if the engine is not refittable */ if (HasAtMostOneBit(cmask)) return y; @@ -2370,7 +2370,7 @@ static const uint32 _vehicle_command_translation_table[][4] = { CMD_REVERSE_TRAIN_DIRECTION | CMD_MSG(STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN), CMD_TURN_ROADVEH | CMD_MSG(STR_ERROR_CAN_T_MAKE_ROAD_VEHICLE_TURN), 0xffffffff, // invalid for ships - 0xffffffff // invalid for aircrafts + 0xffffffff // invalid for aircraft }, }; diff --git a/src/video/allegro_v.cpp b/src/video/allegro_v.cpp index 01628f99cd..960d7fb7c8 100644 --- a/src/video/allegro_v.cpp +++ b/src/video/allegro_v.cpp @@ -24,6 +24,7 @@ #include "../network/network.h" #include "../core/random_func.hpp" #include "../core/math_func.hpp" +#include "../framerate_type.h" #include "allegro_v.h" #include @@ -56,6 +57,8 @@ void VideoDriver_Allegro::MakeDirty(int left, int top, int width, int height) static void DrawSurfaceToScreen() { + PerformanceMeasurer framerate(PFE_VIDEO); + int n = _num_dirty_rects; if (n == 0) return; @@ -458,7 +461,7 @@ void VideoDriver_Allegro::Stop() if (--_allegro_instance_count == 0) allegro_exit(); } -#if defined(UNIX) || defined(__OS2__) || defined(PSP) || defined(DOS) +#if defined(UNIX) || defined(__OS2__) || defined(DOS) # include /* gettimeofday */ static uint32 GetTime() diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index f8412e3877..d165610245 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -214,6 +214,12 @@ static void setupApplication() } #endif + /* Disable the system-wide tab feature as we only have one window. */ + if ([ NSWindow respondsToSelector:@selector(setAllowsAutomaticWindowTabbing:) ]) { + /* We use nil instead of NO as withObject requires an id. */ + [ NSWindow performSelector:@selector(setAllowsAutomaticWindowTabbing:) withObject:nil]; + } + /* Become the front process, important when start from the command line. */ [ [ NSApplication sharedApplication ] activateIgnoringOtherApps:YES ]; diff --git a/src/video/cocoa/event.mm b/src/video/cocoa/event.mm index f4a7c2b421..30b6563b68 100644 --- a/src/video/cocoa/event.mm +++ b/src/video/cocoa/event.mm @@ -587,12 +587,12 @@ static bool QZ_PollEvent() while (_current_magnification >= 1.0f) { _current_magnification -= 1.0f; - _cursor.wheel++; + _cursor.wheel--; HandleMouseEvents(); } while (_current_magnification <= -1.0f) { _current_magnification += 1.0f; - _cursor.wheel--; + _cursor.wheel++; HandleMouseEvents(); } break; diff --git a/src/video/cocoa/wnd_quartz.mm b/src/video/cocoa/wnd_quartz.mm index d42749bac5..4245a3c183 100644 --- a/src/video/cocoa/wnd_quartz.mm +++ b/src/video/cocoa/wnd_quartz.mm @@ -33,6 +33,7 @@ #include "cocoa_v.h" #include "../../core/math_func.hpp" #include "../../gfx_func.h" +#include "../../framerate_type.h" /* On some old versions of MAC OS this may not be defined. * Those versions generally only produce code for PPC. So it should be safe to @@ -431,6 +432,8 @@ WindowQuartzSubdriver::~WindowQuartzSubdriver() void WindowQuartzSubdriver::Draw(bool force_update) { + PerformanceMeasurer framerate(PFE_VIDEO); + /* Check if we need to do anything */ if (this->num_dirty_rects == 0 || [ this->window isMiniaturized ]) return; @@ -544,7 +547,7 @@ NSPoint WindowQuartzSubdriver::GetMouseLocation(NSEvent *event) if ( [ event window ] == nil) { #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - if ([ this->cocoaview respondsToSelector:@selector(convertRectFromScreen:) ]) { + if ([ [ this->cocoaview window ] respondsToSelector:@selector(convertRectFromScreen:) ]) { pt = [ this->cocoaview convertPoint:[ [ this->cocoaview window ] convertRectFromScreen:NSMakeRect([ event locationInWindow ].x, [ event locationInWindow ].y, 0, 0) ].origin fromView:nil ]; } else diff --git a/src/video/cocoa/wnd_quickdraw.mm b/src/video/cocoa/wnd_quickdraw.mm index df10d87739..8475efb0fd 100644 --- a/src/video/cocoa/wnd_quickdraw.mm +++ b/src/video/cocoa/wnd_quickdraw.mm @@ -32,6 +32,7 @@ #include "cocoa_v.h" #include "../../core/math_func.hpp" #include "../../gfx_func.h" +#include "../../framerate_type.h" /** * Important notice regarding all modifications!!!!!!! @@ -361,6 +362,8 @@ WindowQuickdrawSubdriver::~WindowQuickdrawSubdriver() void WindowQuickdrawSubdriver::Draw(bool force_update) { + PerformanceMeasurer framerate(PFE_VIDEO); + /* Check if we need to do anything */ if (this->num_dirty_rects == 0 || [ this->window isMiniaturized ]) return; diff --git a/src/video/dedicated_v.cpp b/src/video/dedicated_v.cpp index 5e2be481c9..aaadd94614 100644 --- a/src/video/dedicated_v.cpp +++ b/src/video/dedicated_v.cpp @@ -57,16 +57,12 @@ static void OS2_SwitchToConsoleMode() } #endif -#if defined(UNIX) || defined(PSP) +#if defined(UNIX) # include /* gettimeofday */ # include # include # include # define STDIN 0 /* file descriptor for standard input */ -# if defined(PSP) -# include -# include -# endif /* PSP */ /* Signal handlers */ static void DedicatedSignalHandler(int sig) @@ -79,9 +75,7 @@ static void DedicatedSignalHandler(int sig) #if defined(WIN32) # include /* GetTickCount */ -# if !defined(WINCE) -# include -# endif +# include # include # include # include "../os/windows/win32.h" @@ -92,10 +86,6 @@ static char _win_console_thread_buffer[200]; /* Windows Console thread. Just loop and signal when input has been received */ static void WINAPI CheckForConsoleInput() { -#if defined(WINCE) - /* WinCE doesn't support console stuff */ - return; -#else SetWin32ThreadName(-1, "ottd:win-console"); DWORD nb; @@ -110,7 +100,6 @@ static void WINAPI CheckForConsoleInput() SetEvent(_hInputReady); WaitForSingleObject(_hWaitForInputHandling, INFINITE); } -#endif } static void CreateWindowsConsoleThread() @@ -161,9 +150,7 @@ const char *VideoDriver_Dedicated::Start(const char * const *parm) ScreenSizeChanged(); BlitterFactory::GetCurrentBlitter()->PostResize(); -#if defined(WINCE) - /* WinCE doesn't support console stuff */ -#elif defined(WIN32) +#if defined(WIN32) /* For win32 we need to allocate a console (debug mode does the same) */ CreateConsole(); CreateWindowsConsoleThread(); @@ -196,7 +183,7 @@ void VideoDriver_Dedicated::MakeDirty(int left, int top, int width, int height) bool VideoDriver_Dedicated::ChangeResolution(int w, int h) { return false; } bool VideoDriver_Dedicated::ToggleFullscreen(bool fs) { return false; } -#if defined(UNIX) || defined(__OS2__) || defined(PSP) +#if defined(UNIX) || defined(__OS2__) static bool InputWaiting() { struct timeval tv; @@ -242,7 +229,7 @@ static void DedicatedHandleKeyInput() if (_exit_game) return; -#if defined(UNIX) || defined(__OS2__) || defined(PSP) +#if defined(UNIX) || defined(__OS2__) if (fgets(input_line, lengthof(input_line), stdin) == NULL) return; #else /* Handle console input, and signal console thread, it can accept input again */ @@ -269,7 +256,7 @@ void VideoDriver_Dedicated::MainLoop() uint32 next_tick = cur_ticks + MILLISECONDS_PER_TICK; /* Signal handlers */ -#if defined(UNIX) || defined(PSP) +#if defined(UNIX) signal(SIGTERM, DedicatedSignalHandler); signal(SIGINT, DedicatedSignalHandler); signal(SIGQUIT, DedicatedSignalHandler); diff --git a/src/video/sdl_v.cpp b/src/video/sdl_v.cpp index 3668f86020..f40c4b6461 100644 --- a/src/video/sdl_v.cpp +++ b/src/video/sdl_v.cpp @@ -23,6 +23,7 @@ #include "../core/random_func.hpp" #include "../core/math_func.hpp" #include "../fileio_func.h" +#include "../framerate_type.h" #include "sdl_v.h" #include @@ -148,6 +149,8 @@ static void CheckPaletteAnim() static void DrawSurfaceToScreen() { + PerformanceMeasurer framerate(PFE_VIDEO); + int n = _num_dirty_rects; if (n == 0) return; @@ -323,7 +326,7 @@ bool VideoDriver_SDL::CreateMainSurface(uint w, uint h) want_hwpalette = _use_hwpalette; } - if (want_hwpalette) DEBUG(driver, 1, "SDL: requesting hardware palete"); + if (want_hwpalette) DEBUG(driver, 1, "SDL: requesting hardware palette"); /* Free any previously allocated shadow surface */ if (_sdl_screen != NULL && _sdl_screen != _sdl_realscreen) SDL_CALL SDL_FreeSurface(_sdl_screen); diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp index 4534b87bec..0655065a6c 100644 --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -23,6 +23,7 @@ #include "../progress.h" #include "../window_gui.h" #include "../window_func.h" +#include "../framerate_type.h" #include "win32_v.h" #include #include @@ -60,9 +61,7 @@ bool _force_full_redraw; bool _window_maximize; uint _display_hz; static Dimension _bck_resolution; -#if !defined(WINCE) || _WIN32_WCE >= 0x400 DWORD _imm_props; -#endif /** Whether the drawing is/may be done in a separate thread. */ static bool _draw_threaded; @@ -272,9 +271,6 @@ bool VideoDriver_Win32::MakeWindow(bool full_screen) _wnd.main_wnd = 0; } -#if defined(WINCE) - /* WinCE is always fullscreen */ -#else if (full_screen) { DEVMODE settings; @@ -318,7 +314,6 @@ bool VideoDriver_Win32::MakeWindow(bool full_screen) _wnd.width = _bck_resolution.width; _wnd.height = _bck_resolution.height; } -#endif { RECT r; @@ -337,22 +332,20 @@ bool VideoDriver_Win32::MakeWindow(bool full_screen) SetRect(&r, 0, 0, _wnd.width, _wnd.height); } -#if !defined(WINCE) AdjustWindowRect(&r, style, FALSE); -#endif w = r.right - r.left; h = r.bottom - r.top; if (_wnd.main_wnd != NULL) { if (!_window_maximize) SetWindowPos(_wnd.main_wnd, 0, 0, 0, w, h, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE); } else { - TCHAR Windowtitle[50]; int x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2; int y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2; - _sntprintf(Windowtitle, lengthof(Windowtitle), _T("OpenTTD %s"), MB_TO_WIDE(_openttd_revision)); + char window_title[64]; + seprintf(window_title, lastof(window_title), "OpenTTD %s", _openttd_revision); - _wnd.main_wnd = CreateWindow(_T("OTTD"), Windowtitle, style, x, y, w, h, 0, 0, GetModuleHandle(NULL), 0); + _wnd.main_wnd = CreateWindow(_T("OTTD"), MB_TO_WIDE(window_title), style, x, y, w, h, 0, 0, GetModuleHandle(NULL), 0); if (_wnd.main_wnd == NULL) usererror("CreateWindow failed"); ShowWindow(_wnd.main_wnd, showstyle); } @@ -367,6 +360,8 @@ bool VideoDriver_Win32::MakeWindow(bool full_screen) /** Do palette animation and blit to the window. */ static void PaintWindow(HDC dc) { + PerformanceMeasurer framerate(PFE_VIDEO); + HDC dc2 = CreateCompatibleDC(dc); HBITMAP old_bmp = (HBITMAP)SelectObject(dc2, _wnd.dib_sect); HPALETTE old_palette = SelectPalette(dc, _wnd.gdi_palette, FALSE); @@ -497,7 +492,6 @@ static LRESULT HandleCharMsg(uint keycode, WChar charcode) return 0; } -#if !defined(WINCE) || _WIN32_WCE >= 0x400 /** Should we draw the composition string ourself, i.e is this a normal IME? */ static bool DrawIMECompositionString() { @@ -634,15 +628,6 @@ static void CancelIMEComposition(HWND hwnd) HandleTextInput(NULL, true); } -#else - -static bool DrawIMECompositionString() { return false; } -static void SetCompositionPos(HWND hwnd) {} -static void SetCandidatePos(HWND hwnd) {} -static void CancelIMEComposition(HWND hwnd) {} - -#endif /* !defined(WINCE) || _WIN32_WCE >= 0x400 */ - static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { static uint32 keycode = 0; @@ -653,9 +638,7 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP case WM_CREATE: SetTimer(hwnd, TID_POLLMOUSE, MOUSE_POLL_DELAY, (TIMERPROC)TrackMouseTimerProc); SetCompositionPos(hwnd); -#if !defined(WINCE) || _WIN32_WCE >= 0x400 _imm_props = ImmGetProperty(GetKeyboardLayout(0), IGP_PROPERTY); -#endif break; case WM_ENTERSIZEMOVE: @@ -784,7 +767,6 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP return 0; } -#if !defined(WINCE) || _WIN32_WCE >= 0x400 case WM_INPUTLANGCHANGE: _imm_props = ImmGetProperty(GetKeyboardLayout(0), IGP_PROPERTY); break; @@ -820,7 +802,6 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP } HandleCharMsg(0, GB(wParam, 0, 8)); return 0; -#endif #endif case WM_DEADCHAR: @@ -914,7 +895,6 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP } return 0; -#if !defined(WINCE) case WM_SIZING: { RECT *r = (RECT*)lParam; RECT r2; @@ -972,7 +952,6 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP } return TRUE; } -#endif /* needed for wheel */ #if !defined(WM_MOUSEWHEEL) @@ -1003,7 +982,6 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP _wnd.has_focus = false; break; -#if !defined(WINCE) case WM_ACTIVATE: { /* Don't do anything if we are closing openttd */ if (_exit_game) break; @@ -1023,7 +1001,6 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP } break; } -#endif } return DefWindowProc(hwnd, msg, wParam, lParam); @@ -1112,10 +1089,6 @@ static const Dimension default_resolutions[] = { static void FindResolutions() { uint n = 0; -#if defined(WINCE) - /* EnumDisplaySettingsW is only supported in CE 4.2+ - * XXX -- One might argue that we assume 4.2+ on every system. Then we can use this function safely */ -#else uint i; DEVMODEA dm; @@ -1145,7 +1118,6 @@ static void FindResolutions() } } } -#endif /* We have found no resolutions, show the default list */ if (n == 0) { @@ -1191,9 +1163,7 @@ void VideoDriver_Win32::Stop() DeleteObject(_wnd.dib_sect); DestroyWindow(_wnd.main_wnd); -#if !defined(WINCE) if (_wnd.fullscreen) ChangeDisplaySettings(NULL, 0); -#endif MyShowCursor(true); } @@ -1295,10 +1265,8 @@ void VideoDriver_Win32::MainLoop() if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged(); -#if !defined(WINCE) /* Flush GDI buffer to ensure we don't conflict with the drawing thread. */ GdiFlush(); -#endif /* The game loop is the part that can run asynchronously. * The rest except sleeping can't. */ @@ -1311,10 +1279,8 @@ void VideoDriver_Win32::MainLoop() UpdateWindows(); CheckPaletteAnim(); } else { -#if !defined(WINCE) /* Flush GDI buffer to ensure we don't conflict with the drawing thread. */ GdiFlush(); -#endif /* Release the thread while sleeping */ if (_draw_threaded) _draw_mutex->EndCritical(); diff --git a/src/viewport.cpp b/src/viewport.cpp index 6de827b4ee..cb0b36f40f 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -87,6 +87,7 @@ #include "company_base.h" #include "command_func.h" #include "network/network_func.h" +#include "framerate_type.h" #include @@ -1654,6 +1655,8 @@ static inline void ViewportDraw(const ViewPort *vp, int left, int top, int right */ void Window::DrawViewport() const { + PerformanceAccumulator framerate(PFE_DRAWWORLD); + DrawPixelInfo *dpi = _cur_dpi; dpi->left += this->left; @@ -2636,8 +2639,8 @@ static int CalcHeightdiff(HighLightStyle style, uint distance, TileIndex start_t byte style_t = (byte)(TileX(end_tile) > TileX(start_tile)); start_tile = TILE_ADD(start_tile, ToTileIndexDiff(heightdiff_area_by_dir[style_t])); end_tile = TILE_ADD(end_tile, ToTileIndexDiff(heightdiff_area_by_dir[2 + style_t])); + FALLTHROUGH; } - FALLTHROUGH; case HT_POINT: h0 = TileHeight(start_tile); diff --git a/src/viewport_gui.cpp b/src/viewport_gui.cpp index cbd300dec7..9c89a85f84 100644 --- a/src/viewport_gui.cpp +++ b/src/viewport_gui.cpp @@ -138,7 +138,7 @@ public: virtual void OnMouseWheel(int wheel) { - if (_settings_client.gui.scrollwheel_scrolling == 0) { + if (_settings_client.gui.scrollwheel_scrolling != 2) { ZoomInOrOutToCursorWindow(wheel < 0, this); } } diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp index 07b6a95507..737257a823 100644 --- a/src/water_cmd.cpp +++ b/src/water_cmd.cpp @@ -1218,7 +1218,7 @@ void ConvertGroundTilesIntoWaterTiles() default: uint dir; FOR_EACH_SET_BIT(dir, _flood_from_dirs[slope & ~SLOPE_STEEP]) { - TileIndex dest = TILE_ADD(tile, TileOffsByDir((Direction)dir)); + TileIndex dest = TileAddByDir(tile, (Direction)dir); Slope slope_dest = GetTileSlope(dest) & ~SLOPE_STEEP; if (slope_dest == SLOPE_FLAT || IsSlopeWithOneCornerRaised(slope_dest)) { MakeShore(tile); diff --git a/src/widgets/framerate_widget.h b/src/widgets/framerate_widget.h new file mode 100644 index 0000000000..388599537c --- /dev/null +++ b/src/widgets/framerate_widget.h @@ -0,0 +1,33 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file framerate_widget.h Types related to the framerate windows widgets. */ + +#ifndef WIDGETS_FRAMERATE_WIDGET_H +#define WIDGETS_FRAMERATE_WIDGET_H + +/** Widgets of the #FramerateWindow class. */ +enum FramerateWindowWidgets { + WID_FRW_CAPTION, + WID_FRW_RATE_GAMELOOP, + WID_FRW_RATE_DRAWING, + WID_FRW_RATE_FACTOR, + WID_FRW_INFO_DATA_POINTS, + WID_FRW_TIMES_NAMES, + WID_FRW_TIMES_CURRENT, + WID_FRW_TIMES_AVERAGE, +}; + +/** Widgets of the #FrametimeGraphWindow class. */ +enum FrametimeGraphWindowWidgets { + WID_FGW_CAPTION, + WID_FGW_GRAPH, +}; + +#endif /* WIDGETS_FRAMERATE_WIDGET_H */ diff --git a/src/widgets/music_widget.h b/src/widgets/music_widget.h index 3a99bc6150..c8e6a98186 100644 --- a/src/widgets/music_widget.h +++ b/src/widgets/music_widget.h @@ -14,9 +14,11 @@ /** Widgets of the #MusicTrackSelectionWindow class. */ enum MusicTrackSelectionWidgets { + WID_MTS_CAPTION, ///< Window caption. WID_MTS_LIST_LEFT, ///< Left button. WID_MTS_PLAYLIST, ///< Playlist. WID_MTS_LIST_RIGHT, ///< Right button. + WID_MTS_MUSICSET, ///< Music set selection. WID_MTS_ALL, ///< All button. WID_MTS_OLD, ///< Old button. WID_MTS_NEW, ///< New button. diff --git a/src/widgets/toolbar_widget.h b/src/widgets/toolbar_widget.h index 434a238acc..c317fc9574 100644 --- a/src/widgets/toolbar_widget.h +++ b/src/widgets/toolbar_widget.h @@ -33,7 +33,7 @@ enum ToolbarNormalWidgets { WID_TN_TRAINS = WID_TN_VEHICLE_START, ///< Train menu. WID_TN_ROADVEHS, ///< Road vehicle menu. WID_TN_SHIPS, ///< Ship menu. - WID_TN_AIRCRAFTS, ///< Aircraft menu. + WID_TN_AIRCRAFT, ///< Aircraft menu. WID_TN_ZOOM_IN, ///< Zoom in the main viewport. WID_TN_ZOOM_OUT, ///< Zoom out the main viewport. WID_TN_BUILDING_TOOLS_START, ///< Helper for the offset of the building tools diff --git a/src/window.cpp b/src/window.cpp index e47415343d..8dc4c18c23 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -36,6 +36,7 @@ #include "error.h" #include "game/game.hpp" #include "video/video_driver.hpp" +#include "framerate_type.h" #include "safeguards.h" @@ -2442,7 +2443,7 @@ static EventState HandleViewportScroll() * outside of the window and should not left-mouse scroll anymore. */ if (_last_scroll_window == NULL) _last_scroll_window = FindWindowFromPt(_cursor.pos.x, _cursor.pos.y); - if (_last_scroll_window == NULL || !(_right_button_down || scrollwheel_scrolling || (_settings_client.gui.left_mouse_btn_scrolling && _left_button_down))) { + if (_last_scroll_window == NULL || !((_settings_client.gui.scroll_mode != VSM_MAP_LMB && _right_button_down) || scrollwheel_scrolling || (_settings_client.gui.scroll_mode == VSM_MAP_LMB && _left_button_down))) { _cursor.fix_at = false; _scrolling_viewport = false; _last_scroll_window = NULL; @@ -2457,20 +2458,20 @@ static EventState HandleViewportScroll() } Point delta; - if (_settings_client.gui.reverse_scroll || (_settings_client.gui.left_mouse_btn_scrolling && _left_button_down)) { - delta.x = -_cursor.delta.x; - delta.y = -_cursor.delta.y; - } else { - delta.x = _cursor.delta.x; - delta.y = _cursor.delta.y; - } - if (scrollwheel_scrolling) { /* We are using scrollwheels for scrolling */ delta.x = _cursor.h_wheel; delta.y = _cursor.v_wheel; _cursor.v_wheel = 0; _cursor.h_wheel = 0; + } else { + if (_settings_client.gui.scroll_mode != VSM_VIEWPORT_RMB_FIXED) { + delta.x = -_cursor.delta.x; + delta.y = -_cursor.delta.y; + } else { + delta.x = _cursor.delta.x; + delta.y = _cursor.delta.y; + } } /* Create a scroll-event and send it to the window */ @@ -2862,21 +2863,26 @@ static void MouseLoop(MouseClick click, int mousewheel) if (vp != NULL && (_game_mode == GM_MENU || HasModalProgress())) return; if (mousewheel != 0) { - /* Send mousewheel event to window */ - w->OnMouseWheel(mousewheel); + /* Send mousewheel event to window, unless we're scrolling a viewport or the map */ + if (!scrollwheel_scrolling || (vp == NULL && w->window_class != WC_SMALLMAP)) w->OnMouseWheel(mousewheel); /* Dispatch a MouseWheelEvent for widgets if it is not a viewport */ if (vp == NULL) DispatchMouseWheelEvent(w, w->nested_root->GetWidgetFromPos(x - w->left, y - w->top), mousewheel); } if (vp != NULL) { - if (scrollwheel_scrolling) click = MC_RIGHT; // we are using the scrollwheel in a viewport, so we emulate right mouse button + if (scrollwheel_scrolling && !(w->flags & WF_DISABLE_VP_SCROLL)) { + _scrolling_viewport = true; + _cursor.fix_at = true; + return; + } + switch (click) { case MC_DOUBLE_LEFT: case MC_LEFT: if (HandleViewportClicked(vp, x, y)) return; if (!(w->flags & WF_DISABLE_VP_SCROLL) && - _settings_client.gui.left_mouse_btn_scrolling) { + _settings_client.gui.scroll_mode == VSM_MAP_LMB) { _scrolling_viewport = true; _cursor.fix_at = false; return; @@ -2884,13 +2890,11 @@ static void MouseLoop(MouseClick click, int mousewheel) break; case MC_RIGHT: - if (!(w->flags & WF_DISABLE_VP_SCROLL)) { + if (!(w->flags & WF_DISABLE_VP_SCROLL) && + _settings_client.gui.scroll_mode != VSM_MAP_LMB) { _scrolling_viewport = true; - _cursor.fix_at = true; - - /* clear 2D scrolling caches before we start a 2D scroll */ - _cursor.h_wheel = 0; - _cursor.v_wheel = 0; + _cursor.fix_at = (_settings_client.gui.scroll_mode == VSM_VIEWPORT_RMB_FIXED || + _settings_client.gui.scroll_mode == VSM_MAP_RMB_FIXED); return; } break; @@ -2905,7 +2909,7 @@ static void MouseLoop(MouseClick click, int mousewheel) case MC_LEFT: case MC_DOUBLE_LEFT: DispatchLeftClickEvent(w, x - w->left, y - w->top, click == MC_DOUBLE_LEFT ? 2 : 1); - break; + return; default: if (!scrollwheel_scrolling || w == NULL || w->window_class != WC_SMALLMAP) break; @@ -2913,11 +2917,19 @@ static void MouseLoop(MouseClick click, int mousewheel) * Simulate a right button click so we can get started. */ FALLTHROUGH; - case MC_RIGHT: DispatchRightClickEvent(w, x - w->left, y - w->top); break; + case MC_RIGHT: + DispatchRightClickEvent(w, x - w->left, y - w->top); + return; - case MC_HOVER: DispatchHoverEvent(w, x - w->left, y - w->top); break; + case MC_HOVER: + DispatchHoverEvent(w, x - w->left, y - w->top); + break; } } + + /* We're not doing anything with 2D scrolling, so reset the value. */ + _cursor.h_wheel = 0; + _cursor.v_wheel = 0; } /** @@ -3074,6 +3086,9 @@ void InputLoop() */ void UpdateWindows() { + PerformanceMeasurer framerate(PFE_DRAWING); + PerformanceAccumulator::Reset(PFE_DRAWWORLD); + Window *w; static int highlight_timer = 1; diff --git a/src/window_type.h b/src/window_type.h index 809e81d485..7185bfcb4f 100644 --- a/src/window_type.h +++ b/src/window_type.h @@ -681,6 +681,18 @@ enum WindowClass { */ WC_SAVE_PRESET, + /** + * Framerate display; %Window numbers: + * - 0 = #FramerateDisplayWidgets + */ + WC_FRAMERATE_DISPLAY, + + /** + * Frame time graph; %Window numbers: + * - 0 = #FrametimeGraphWindowWidgets + */ + WC_FRAMETIME_GRAPH, + WC_INVALID = 0xFFFF, ///< Invalid window. };