Translations update
[openttd/fttd.git] / src / base_media_base.h
blobdbb8acfe6bdbb4df898fe53f583b69b85e7ca880
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 <map>
17 #include "string.h"
18 #include "fileio_func.h"
19 #include "core/pointer.h"
20 #include "core/string_compare_type.hpp"
21 #include "gfx_type.h"
22 #include "textfile.h"
23 #include "ini_type.h"
25 /* Forward declare these; can't do 'struct X' in functions as older GCCs barf on that */
26 struct ContentInfo;
28 /** Description of a single base set. */
29 struct BaseSetDesc {
30 public:
31 /** Structure holding filename and MD5 information about a single file */
32 struct FileDesc {
33 /** Actual status of this file. */
34 enum Status {
35 MATCH, ///< The file did exist and the md5 checksum did match
36 MISMATCH, ///< The file did exist, just the md5 checksum did not match
37 MISSING, ///< The file did not exist
40 const char *filename; ///< filename
41 uint8 hash[16]; ///< md5 sum of the file
42 const char *missing_warning; ///< warning when this file is missing
43 Status status; ///< status of this file
46 private:
47 typedef std::map <const char *, ttd_unique_free_ptr<char>, StringCompare> StringMap;
49 ttd_unique_free_ptr<char> name; ///< The name of the set
50 ttd_unique_free_ptr<char> def; ///< Default description of the set
51 StringMap description; ///< Descriptions of the set
53 public:
54 uint32 shortname; ///< Four letter short variant of the name
55 uint32 version; ///< The version of this set
56 bool fallback; ///< This set is a fallback set, i.e. it should be used only as last resort
58 /** Get the name of this set. */
59 const char *get_name (void) const
61 return this->name.get();
64 /** Set the name of this set. */
65 void set_name (const char *s)
67 this->name.reset (xstrdup (s));
70 /** Get the default description of this set. */
71 const char *get_default_desc (void) const
73 return this->def.get();
76 /** Add the default description of this set. */
77 void add_default_desc (const char *desc)
79 this->def.reset (xstrdup (desc));
82 /* Get the description of this set for the given ISO code. */
83 const char *get_desc (const char *isocode) const;
85 /* Add a description of this set for a given language. */
86 void add_desc (const char *lang, const char *desc);
88 /* Try to read a single piece of metadata from an ini file. */
89 static const IniItem *fetch_metadata (const IniGroup *metadata,
90 const char *name, const char *type, const char *filename);
92 /* Calculate and check the MD5 hash of the supplied file. */
93 static FileDesc::Status CheckMD5 (const FileDesc *file);
96 /**
97 * Information about a single base set.
98 * @tparam T the real class we're going to be
99 * @tparam Tnum_files the number of files in the set
101 template <class T, size_t Tnum_files>
102 struct BaseSet : BaseSetDesc {
103 /** Number of files in this set */
104 static const size_t NUM_FILES = Tnum_files;
106 FileDesc files[NUM_FILES]; ///< All files part of this set
107 uint found_files; ///< Number of the files that could be found
108 uint valid_files; ///< Number of the files that could be found and are valid
110 T *next; ///< The next base set in this list
112 /** Construct an instance. */
113 BaseSet() : next(NULL) { }
115 /** Free everything we allocated */
116 ~BaseSet()
118 for (uint i = 0; i < NUM_FILES; i++) {
119 free(this->files[i].filename);
120 free(this->files[i].missing_warning);
123 delete this->next;
127 * Get the number of missing files.
128 * @return the number
130 int GetNumMissing() const
132 return Tnum_files - this->found_files;
136 * Get the number of invalid files.
137 * @note a missing file is invalid too!
138 * @return the number
140 int GetNumInvalid() const
142 return Tnum_files - this->valid_files;
145 bool FillSetDetails(IniFile *ini, const char *path, const char *full_filename, bool allow_empty_filename = true);
148 * Check if this set is preferred to another one.
149 * (Used in derived classes.)
151 static bool IsPreferredTo (const BaseSet &other)
153 return false;
157 * Search a textfile file next to this base media.
158 * @param type The type of the textfile to search for.
159 * @return A description for the textfile.
161 TextfileDesc GetTextfile (TextfileType type) const
163 for (uint i = 0; i < NUM_FILES; i++) {
164 TextfileDesc txt (type, BASESET_DIR, this->files[i].filename);
165 if (txt.valid()) return txt;
167 return TextfileDesc();
171 * Try to read a single piece of metadata from an ini file.
172 * @param metadata The metadata group to search in.
173 * @param name The name of the item to fetch.
174 * @param filename The name of the filename for debugging output.
175 * @return The associated item, or NULL if it doesn't exist.
177 static const IniItem *fetch_metadata (const IniGroup *metadata,
178 const char *name, const char *filename)
180 return BaseSetDesc::fetch_metadata (metadata, name, T::set_type, filename);
185 * Base for all base media (graphics, sounds)
186 * @tparam Tbase_set the real set we're going to be
188 template <class Tbase_set>
189 class BaseMedia {
190 protected:
191 static Tbase_set *available_sets; ///< All available sets
192 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.
193 static const Tbase_set *used_set; ///< The currently used set
195 struct Scanner : FileScanner {
196 bool AddFile (const char *filename, size_t basepath_length, const char *tar_filename) OVERRIDE;
199 public:
200 /** The set as saved in the config file. */
201 static const char *ini_set;
204 * Determine the graphics pack that has to be used.
205 * The one with the most correct files wins.
206 * @return true if a best set has been found.
208 static bool DetermineBestSet();
210 /** Do the scan for files. */
211 static uint FindSets (const char *extension,
212 Subdirectory dir1, Subdirectory dir2, bool search_in_tars)
214 Scanner fs;
215 uint num = fs.Scan (extension, dir1, search_in_tars);
216 return num + fs.Scan (extension, dir2, search_in_tars);
219 static Tbase_set *GetAvailableSets();
221 static bool SetSet(const char *name);
222 static void GetSetsList (stringb *buf);
223 static int GetNumSets();
224 static int GetIndexOfUsedSet();
225 static const Tbase_set *GetSet(int index);
226 static const Tbase_set *GetUsedSet();
229 * Check whether we have an set with the exact characteristics as ci.
230 * @param ci the characteristics to search on (shortname and md5sum)
231 * @param md5sum whether to check the MD5 checksum
232 * @return true iff we have an set matching.
234 static bool HasSet(const ContentInfo *ci, bool md5sum);
238 * Helper class that adds a suitable scanner to a base media class.
239 * @tparam Tbase_set the real set we're going to be
240 * @tparam Tsearch_in_tars whether to search in the tars or not
242 template <class Tbase_set, bool Tsearch_in_tars>
243 struct BaseMediaS : BaseMedia<Tbase_set> {
244 /** Whether to search in the tars or not. */
245 static const bool SEARCH_IN_TARS = Tsearch_in_tars;
247 /** Do the scan for files. */
248 static uint FindSets()
250 /* Searching in tars is only done in the old "data" directories basesets. */
251 return BaseMedia<Tbase_set>::FindSets (Tbase_set::extension,
252 SEARCH_IN_TARS ? OLD_DATA_DIR : OLD_GM_DIR,
253 BASESET_DIR, SEARCH_IN_TARS);
258 * Check whether there's a base set matching some information.
259 * @param ci The content info to compare it to.
260 * @param md5sum Should the MD5 checksum be tested as well?
261 * @param s The list with sets.
262 * @return The filename of the first file of the base set, or \c NULL if there is no match.
264 template <class Tbase_set>
265 const char *TryGetBaseSetFile(const ContentInfo *ci, bool md5sum, const Tbase_set *s);
267 /** Types of graphics in the base graphics set */
268 enum GraphicsFileType {
269 GFT_BASE, ///< Base sprites for all climates
270 GFT_LOGOS, ///< Logos, landscape icons and original terrain generator sprites
271 GFT_ARCTIC, ///< Landscape replacement sprites for arctic
272 GFT_TROPICAL, ///< Landscape replacement sprites for tropical
273 GFT_TOYLAND, ///< Landscape replacement sprites for toyland
274 GFT_EXTRA, ///< Extra sprites that were not part of the original sprites
275 MAX_GFT, ///< We are looking for this amount of GRFs
278 /** Blitter type for base graphics sets. */
279 enum BlitterType {
280 BLT_8BPP, ///< Base set has 8 bpp sprites only.
281 BLT_32BPP, ///< Base set has both 8 bpp and 32 bpp sprites.
284 /** All data of a graphics set. */
285 struct GraphicsSet : BaseSet<GraphicsSet, MAX_GFT> {
286 static const char set_type[]; ///< Description of the set type
287 static const char extension[]; ///< File extension
289 /** Internal names of the files in this set. */
290 static const char * const file_names [MAX_GFT];
292 PaletteType palette; ///< Palette of this graphics set
293 BlitterType blitter; ///< Blitter of this graphics set
295 bool FillSetDetails (IniFile *ini, const char *path, const char *full_filename);
297 /** Check if this set is preferred to another one. */
298 bool IsPreferredTo (const GraphicsSet &other) const
300 return (this->palette == PAL_DOS) && (other.palette != PAL_DOS);
303 static FileDesc::Status CheckMD5 (const FileDesc *file);
306 /** All data/functions related with replacing the base graphics. */
307 class BaseGraphics : public BaseMediaS <GraphicsSet, true> {
308 public:
309 static bool SetSet (const char *name);
312 /** All data of a sounds set. */
313 struct SoundsSet : BaseSet<SoundsSet, 1> {
314 static const char set_type[]; ///< Description of the set type
315 static const char extension[]; ///< File extension
317 /** Internal names of the files in this set. */
318 static const char * const file_names [1];
321 /** All data/functions related with replacing the base sounds */
322 class BaseSounds : public BaseMediaS <SoundsSet, true> {
323 public:
324 static bool SetSet (const char *name);
327 /** Maximum number of songs in the 'class' playlists. */
328 static const uint NUM_SONGS_CLASS = 10;
329 /** Number of classes for songs */
330 static const uint NUM_SONG_CLASSES = 3;
331 /** Maximum number of songs in the full playlist; theme song + the classes */
332 static const uint NUM_SONGS_AVAILABLE = 1 + NUM_SONG_CLASSES * NUM_SONGS_CLASS;
334 /** Maximum number of songs in the (custom) playlist */
335 static const uint NUM_SONGS_PLAYLIST = 32;
337 /** All data of a music set. */
338 struct MusicSet : BaseSet<MusicSet, NUM_SONGS_AVAILABLE> {
339 static const char set_type[]; ///< Description of the set type
340 static const char extension[]; ///< File extension
342 /** Internal names of the files in this set. */
343 static const char * const file_names [NUM_SONGS_AVAILABLE];
345 /** The name of the different songs. */
346 char song_name[NUM_SONGS_AVAILABLE][32];
347 byte track_nr[NUM_SONGS_AVAILABLE];
348 byte num_available;
350 bool FillSetDetails (IniFile *ini, const char *path, const char *full_filename);
353 /** All data/functions related with replacing the base music */
354 class BaseMusic : public BaseMediaS <MusicSet, false> {
355 public:
358 #endif /* BASE_MEDIA_BASE_H */