Fix crash when setting separation mode for vehicles with no orders list.
[openttd-joker.git] / src / base_media_base.h
blob6631e9268bda2f43fefaa09d62f5a4e50ed912f3
1 /* $Id$ */
3 /*
4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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 <http://www.gnu.org/licenses/>.
8 */
10 /** @file base_media_base.h Generic functions for replacing base data (graphics, sounds). */
12 #ifndef BASE_MEDIA_BASE_H
13 #define BASE_MEDIA_BASE_H
15 #include "fileio_func.h"
16 #include "core/smallmap_type.hpp"
17 #include "gfx_type.h"
18 #include "textfile_type.h"
19 #include "textfile_gui.h"
21 /* Forward declare these; can't do 'struct X' in functions as older GCCs barf on that */
22 struct IniFile;
23 struct ContentInfo;
25 /** Structure holding filename and MD5 information about a single file */
26 struct MD5File {
27 /** The result of a checksum check */
28 enum ChecksumResult {
29 CR_MATCH, ///< The file did exist and the md5 checksum did match
30 CR_MISMATCH, ///< The file did exist, just the md5 checksum did not match
31 CR_NO_FILE, ///< The file did not exist
34 const char *filename; ///< filename
35 uint8 hash[16]; ///< md5 sum of the file
36 const char *missing_warning; ///< warning when this file is missing
38 ChecksumResult CheckMD5(Subdirectory subdir, size_t max_size) const;
41 /**
42 * Information about a single base set.
43 * @tparam T the real class we're going to be
44 * @tparam Tnum_files the number of files in the set
45 * @tparam Tsearch_in_tars whether to search in the tars or not
47 template <class T, size_t Tnum_files, bool Tsearch_in_tars>
48 struct BaseSet {
49 typedef SmallMap<const char *, const char *> TranslatedStrings;
51 /** Number of files in this set */
52 static const size_t NUM_FILES = Tnum_files;
54 /** Whether to search in the tars or not. */
55 static const bool SEARCH_IN_TARS = Tsearch_in_tars;
57 /** Internal names of the files in this set. */
58 static const char * const *file_names;
60 const char *name; ///< The name of the base set
61 TranslatedStrings description; ///< Description of the base set
62 uint32 shortname; ///< Four letter short variant of the name
63 uint32 version; ///< The version of this base set
64 bool fallback; ///< This set is a fallback set, i.e. it should be used only as last resort
66 MD5File files[NUM_FILES]; ///< All files part of this set
67 uint found_files; ///< Number of the files that could be found
68 uint valid_files; ///< Number of the files that could be found and are valid
70 T *next; ///< The next base set in this list
72 /** Free everything we allocated */
73 ~BaseSet()
75 free(this->name);
77 for (TranslatedStrings::iterator iter = this->description.Begin(); iter != this->description.End(); iter++) {
78 free(iter->first);
79 free(iter->second);
82 for (uint i = 0; i < NUM_FILES; i++) {
83 free(this->files[i].filename);
84 free(this->files[i].missing_warning);
87 delete this->next;
90 /**
91 * Get the number of missing files.
92 * @return the number
94 int GetNumMissing() const
96 return Tnum_files - this->found_files;
99 /**
100 * Get the number of invalid files.
101 * @note a missing file is invalid too!
102 * @return the number
104 int GetNumInvalid() const
106 return Tnum_files - this->valid_files;
109 bool FillSetDetails(IniFile *ini, const char *path, const char *full_filename, bool allow_empty_filename = true);
112 * Get the description for the given ISO code.
113 * It falls back to the first two characters of the ISO code in case
114 * no match could be made with the full ISO code. If even then the
115 * matching fails the default is returned.
116 * @param isocode the isocode to search for
117 * @return the description
119 const char *GetDescription(const char *isocode = nullptr) const
121 if (isocode != nullptr) {
122 /* First the full ISO code */
123 for (TranslatedStrings::const_iterator iter = this->description.Begin(); iter != this->description.End(); iter++) {
124 if (strcmp(iter->first, isocode) == 0) return iter->second;
126 /* Then the first two characters */
127 for (TranslatedStrings::const_iterator iter = this->description.Begin(); iter != this->description.End(); iter++) {
128 if (strncmp(iter->first, isocode, 2) == 0) return iter->second;
131 /* Then fall back */
132 return this->description.Begin()->second;
136 * Calculate and check the MD5 hash of the supplied file.
137 * @param file The file get the hash of.
138 * @param subdir The sub directory to get the files from.
139 * @return
140 * - #CR_MATCH if the MD5 hash matches
141 * - #CR_MISMATCH if the MD5 does not match
142 * - #CR_NO_FILE if the file misses
144 static MD5File::ChecksumResult CheckMD5(const MD5File *file, Subdirectory subdir)
146 return file->CheckMD5(subdir, SIZE_MAX);
150 * Search a textfile file next to this base media.
151 * @param type The type of the textfile to search for.
152 * @return The filename for the textfile, \c nullptr otherwise.
154 const char *GetTextfile(TextfileType type) const
156 for (uint i = 0; i < NUM_FILES; i++) {
157 const char *textfile = ::GetTextfile(type, BASESET_DIR, this->files[i].filename);
158 if (textfile != nullptr) {
159 return textfile;
162 return nullptr;
167 * Base for all base media (graphics, sounds)
168 * @tparam Tbase_set the real set we're going to be
170 template <class Tbase_set>
171 class BaseMedia : FileScanner {
172 protected:
173 static Tbase_set *available_sets; ///< All available sets
174 static Tbase_set *duplicate_sets; ///< All sets that aren't available, but needed for not downloading base sets when a newer version than the one on BaNaNaS is loaded.
175 static const Tbase_set *used_set; ///< The currently used set
177 /* virtual */ bool AddFile(const char *filename, size_t basepath_length, const char *tar_filename);
180 * Get the extension that is used to identify this set.
181 * @return the extension
183 static const char *GetExtension();
184 public:
185 /** The set as saved in the config file. */
186 static const char *ini_set;
189 * Determine the graphics pack that has to be used.
190 * The one with the most correct files wins.
191 * @return true if a best set has been found.
193 static bool DetermineBestSet();
195 /** Do the scan for files. */
196 static uint FindSets()
198 BaseMedia<Tbase_set> fs;
199 /* Searching in tars is only done in the old "data" directories basesets. */
200 uint num = fs.Scan(GetExtension(), Tbase_set::SEARCH_IN_TARS ? OLD_DATA_DIR : OLD_GM_DIR, Tbase_set::SEARCH_IN_TARS);
201 return num + fs.Scan(GetExtension(), BASESET_DIR, Tbase_set::SEARCH_IN_TARS);
204 static Tbase_set *GetAvailableSets();
206 static bool SetSet(const char *name);
207 static char *GetSetsList(char *p, const char *last);
208 static int GetNumSets();
209 static int GetIndexOfUsedSet();
210 static const Tbase_set *GetSet(int index);
211 static const Tbase_set *GetUsedSet();
214 * Check whether we have an set with the exact characteristics as ci.
215 * @param ci the characteristics to search on (shortname and md5sum)
216 * @param md5sum whether to check the MD5 checksum
217 * @return true iff we have an set matching.
219 static bool HasSet(const ContentInfo *ci, bool md5sum);
223 * Check whether there's a base set matching some information.
224 * @param ci The content info to compare it to.
225 * @param md5sum Should the MD5 checksum be tested as well?
226 * @param s The list with sets.
227 * @return The filename of the first file of the base set, or \c nullptr if there is no match.
229 template <class Tbase_set>
230 const char *TryGetBaseSetFile(const ContentInfo *ci, bool md5sum, const Tbase_set *s);
232 /** Types of graphics in the base graphics set */
233 enum GraphicsFileType {
234 GFT_BASE, ///< Base sprites for all climates
235 GFT_LOGOS, ///< Logos, landscape icons and original terrain generator sprites
236 GFT_ARCTIC, ///< Landscape replacement sprites for arctic
237 GFT_TROPICAL, ///< Landscape replacement sprites for tropical
238 GFT_TOYLAND, ///< Landscape replacement sprites for toyland
239 GFT_EXTRA, ///< Extra sprites that were not part of the original sprites
240 MAX_GFT, ///< We are looking for this amount of GRFs
243 /** Blitter type for base graphics sets. */
244 enum BlitterType {
245 BLT_8BPP, ///< Base set has 8 bpp sprites only.
246 BLT_32BPP, ///< Base set has both 8 bpp and 32 bpp sprites.
249 /** All data of a graphics set. */
250 struct GraphicsSet : BaseSet<GraphicsSet, MAX_GFT, true> {
251 PaletteType palette; ///< Palette of this graphics set
252 BlitterType blitter; ///< Blitter of this graphics set
254 bool FillSetDetails(struct IniFile *ini, const char *path, const char *full_filename);
256 static MD5File::ChecksumResult CheckMD5(const MD5File *file, Subdirectory subdir);
259 /** All data/functions related with replacing the base graphics. */
260 class BaseGraphics : public BaseMedia<GraphicsSet> {
261 public:
264 /** All data of a sounds set. */
265 struct SoundsSet : BaseSet<SoundsSet, 1, true> {
268 /** All data/functions related with replacing the base sounds */
269 class BaseSounds : public BaseMedia<SoundsSet> {
270 public:
273 /** Maximum number of songs in the 'class' playlists. */
274 static const uint NUM_SONGS_CLASS = 10;
275 /** Number of classes for songs */
276 static const uint NUM_SONG_CLASSES = 3;
277 /** Maximum number of songs in the full playlist; theme song + the classes */
278 static const uint NUM_SONGS_AVAILABLE = 1 + NUM_SONG_CLASSES * NUM_SONGS_CLASS;
280 /** Maximum number of songs in the (custom) playlist */
281 static const uint NUM_SONGS_PLAYLIST = 32;
283 /** All data of a music set. */
284 struct MusicSet : BaseSet<MusicSet, NUM_SONGS_AVAILABLE, false> {
285 /** The name of the different songs. */
286 char song_name[NUM_SONGS_AVAILABLE][32];
287 byte track_nr[NUM_SONGS_AVAILABLE];
288 byte num_available;
290 bool FillSetDetails(struct IniFile *ini, const char *path, const char *full_filename);
293 /** All data/functions related with replacing the base music */
294 class BaseMusic : public BaseMedia<MusicSet> {
295 public:
298 #endif /* BASE_MEDIA_BASE_H */