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/>.
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
18 #include "fileio_func.h"
19 #include "core/pointer.h"
20 #include "core/string_compare_type.hpp"
24 /* Forward declare these; can't do 'struct X' in functions as older GCCs barf on that */
28 /** Structure holding filename and MD5 information about a single file */
30 /** The result of a checksum check */
32 CR_MATCH
, ///< The file did exist and the md5 checksum did match
33 CR_MISMATCH
, ///< The file did exist, just the md5 checksum did not match
34 CR_NO_FILE
, ///< The file did not exist
37 const char *filename
; ///< filename
38 uint8 hash
[16]; ///< md5 sum of the file
39 const char *missing_warning
; ///< warning when this file is missing
41 ChecksumResult
CheckMD5(Subdirectory subdir
, size_t max_size
) const;
44 /** Description of a single base set. */
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
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
);
90 * Information about a single base set.
91 * @tparam T the real class we're going to be
92 * @tparam Tnum_files the number of files in the set
94 template <class T
, size_t Tnum_files
>
95 struct BaseSet
: BaseSetDesc
{
96 /** Number of files in this set */
97 static const size_t NUM_FILES
= Tnum_files
;
99 MD5File files
[NUM_FILES
]; ///< All files part of this set
100 uint found_files
; ///< Number of the files that could be found
101 uint valid_files
; ///< Number of the files that could be found and are valid
103 T
*next
; ///< The next base set in this list
105 /** Construct an instance. */
106 BaseSet() : next(NULL
) { }
108 /** Free everything we allocated */
111 for (uint i
= 0; i
< NUM_FILES
; i
++) {
112 free(this->files
[i
].filename
);
113 free(this->files
[i
].missing_warning
);
120 * Get the number of missing files.
123 int GetNumMissing() const
125 return Tnum_files
- this->found_files
;
129 * Get the number of invalid files.
130 * @note a missing file is invalid too!
133 int GetNumInvalid() const
135 return Tnum_files
- this->valid_files
;
138 bool FillSetDetails(IniFile
*ini
, const char *path
, const char *full_filename
, bool allow_empty_filename
= true);
141 * Check if this set is preferred to another one.
142 * (Used in derived classes.)
144 static bool IsPreferredTo (const BaseSet
&other
)
150 * Calculate and check the MD5 hash of the supplied file.
151 * @param file The file get the hash of.
152 * @param subdir The sub directory to get the files from.
154 * - #CR_MATCH if the MD5 hash matches
155 * - #CR_MISMATCH if the MD5 does not match
156 * - #CR_NO_FILE if the file misses
158 static MD5File::ChecksumResult
CheckMD5(const MD5File
*file
, Subdirectory subdir
)
160 return file
->CheckMD5(subdir
, SIZE_MAX
);
164 * Search a textfile file next to this base media.
165 * @param type The type of the textfile to search for.
166 * @return A description for the textfile.
168 TextfileDesc
GetTextfile (TextfileType type
) const
170 for (uint i
= 0; i
< NUM_FILES
; i
++) {
171 TextfileDesc
txt (type
, BASESET_DIR
, this->files
[i
].filename
);
172 if (txt
.valid()) return txt
;
174 return TextfileDesc();
179 * Base for all base media (graphics, sounds)
180 * @tparam Tbase_set the real set we're going to be
182 template <class Tbase_set
>
185 static Tbase_set
*available_sets
; ///< All available sets
186 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.
187 static const Tbase_set
*used_set
; ///< The currently used set
189 struct Scanner
: FileScanner
{
190 bool AddFile (const char *filename
, size_t basepath_length
, const char *tar_filename
) OVERRIDE
;
194 /** The set as saved in the config file. */
195 static const char *ini_set
;
198 * Determine the graphics pack that has to be used.
199 * The one with the most correct files wins.
200 * @return true if a best set has been found.
202 static bool DetermineBestSet();
204 /** Do the scan for files. */
205 static uint
FindSets (const char *extension
,
206 Subdirectory dir1
, Subdirectory dir2
, bool search_in_tars
)
209 uint num
= fs
.Scan (extension
, dir1
, search_in_tars
);
210 return num
+ fs
.Scan (extension
, dir2
, search_in_tars
);
213 static Tbase_set
*GetAvailableSets();
215 static bool SetSet(const char *name
);
216 static void GetSetsList (stringb
*buf
);
217 static int GetNumSets();
218 static int GetIndexOfUsedSet();
219 static const Tbase_set
*GetSet(int index
);
220 static const Tbase_set
*GetUsedSet();
223 * Check whether we have an set with the exact characteristics as ci.
224 * @param ci the characteristics to search on (shortname and md5sum)
225 * @param md5sum whether to check the MD5 checksum
226 * @return true iff we have an set matching.
228 static bool HasSet(const ContentInfo
*ci
, bool md5sum
);
232 * Helper class that adds a suitable scanner to a base media class.
233 * @tparam Tbase_set the real set we're going to be
234 * @tparam Tsearch_in_tars whether to search in the tars or not
236 template <class Tbase_set
, bool Tsearch_in_tars
>
237 struct BaseMediaS
: BaseMedia
<Tbase_set
> {
238 /** Whether to search in the tars or not. */
239 static const bool SEARCH_IN_TARS
= Tsearch_in_tars
;
241 /** Do the scan for files. */
242 static uint
FindSets()
244 /* Searching in tars is only done in the old "data" directories basesets. */
245 return BaseMedia
<Tbase_set
>::FindSets (Tbase_set::extension
,
246 SEARCH_IN_TARS
? OLD_DATA_DIR
: OLD_GM_DIR
,
247 BASESET_DIR
, SEARCH_IN_TARS
);
252 * Check whether there's a base set matching some information.
253 * @param ci The content info to compare it to.
254 * @param md5sum Should the MD5 checksum be tested as well?
255 * @param s The list with sets.
256 * @return The filename of the first file of the base set, or \c NULL if there is no match.
258 template <class Tbase_set
>
259 const char *TryGetBaseSetFile(const ContentInfo
*ci
, bool md5sum
, const Tbase_set
*s
);
261 /** Types of graphics in the base graphics set */
262 enum GraphicsFileType
{
263 GFT_BASE
, ///< Base sprites for all climates
264 GFT_LOGOS
, ///< Logos, landscape icons and original terrain generator sprites
265 GFT_ARCTIC
, ///< Landscape replacement sprites for arctic
266 GFT_TROPICAL
, ///< Landscape replacement sprites for tropical
267 GFT_TOYLAND
, ///< Landscape replacement sprites for toyland
268 GFT_EXTRA
, ///< Extra sprites that were not part of the original sprites
269 MAX_GFT
, ///< We are looking for this amount of GRFs
272 /** Blitter type for base graphics sets. */
274 BLT_8BPP
, ///< Base set has 8 bpp sprites only.
275 BLT_32BPP
, ///< Base set has both 8 bpp and 32 bpp sprites.
278 /** All data of a graphics set. */
279 struct GraphicsSet
: BaseSet
<GraphicsSet
, MAX_GFT
> {
280 static const char set_type
[]; ///< Description of the set type
281 static const char extension
[]; ///< File extension
283 /** Internal names of the files in this set. */
284 static const char * const file_names
[MAX_GFT
];
286 PaletteType palette
; ///< Palette of this graphics set
287 BlitterType blitter
; ///< Blitter of this graphics set
289 bool FillSetDetails(struct IniFile
*ini
, const char *path
, const char *full_filename
);
291 /** Check if this set is preferred to another one. */
292 bool IsPreferredTo (const GraphicsSet
&other
) const
294 return (this->palette
== PAL_DOS
) && (other
.palette
!= PAL_DOS
);
297 static MD5File::ChecksumResult
CheckMD5(const MD5File
*file
, Subdirectory subdir
);
300 /** All data/functions related with replacing the base graphics. */
301 class BaseGraphics
: public BaseMediaS
<GraphicsSet
, true> {
305 /** All data of a sounds set. */
306 struct SoundsSet
: BaseSet
<SoundsSet
, 1> {
307 static const char set_type
[]; ///< Description of the set type
308 static const char extension
[]; ///< File extension
310 /** Internal names of the files in this set. */
311 static const char * const file_names
[1];
314 /** All data/functions related with replacing the base sounds */
315 class BaseSounds
: public BaseMediaS
<SoundsSet
, true> {
319 /** Maximum number of songs in the 'class' playlists. */
320 static const uint NUM_SONGS_CLASS
= 10;
321 /** Number of classes for songs */
322 static const uint NUM_SONG_CLASSES
= 3;
323 /** Maximum number of songs in the full playlist; theme song + the classes */
324 static const uint NUM_SONGS_AVAILABLE
= 1 + NUM_SONG_CLASSES
* NUM_SONGS_CLASS
;
326 /** Maximum number of songs in the (custom) playlist */
327 static const uint NUM_SONGS_PLAYLIST
= 32;
329 /** All data of a music set. */
330 struct MusicSet
: BaseSet
<MusicSet
, NUM_SONGS_AVAILABLE
> {
331 static const char set_type
[]; ///< Description of the set type
332 static const char extension
[]; ///< File extension
334 /** Internal names of the files in this set. */
335 static const char * const file_names
[NUM_SONGS_AVAILABLE
];
337 /** The name of the different songs. */
338 char song_name
[NUM_SONGS_AVAILABLE
][32];
339 byte track_nr
[NUM_SONGS_AVAILABLE
];
342 bool FillSetDetails(struct IniFile
*ini
, const char *path
, const char *full_filename
);
345 /** All data/functions related with replacing the base music */
346 class BaseMusic
: public BaseMediaS
<MusicSet
, false> {
350 #endif /* BASE_MEDIA_BASE_H */