summaryrefslogtreecommitdiff
path: root/src/base_media_base.h
blob: 74185c72b2143031a18d60b513311fdfd770f762 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
/* $Id$ */

/** @file base_media_base.h Generic functions for replacing base data (graphics, sounds). */

#ifndef BASE_MEDIA_BASE_H
#define BASE_MEDIA_BASE_H

#include "fileio_func.h"

/* Forward declare these; can't do 'struct X' in functions as older GCCs barf on that */
struct IniFile;
struct ContentInfo;

/** Structure holding filename and MD5 information about a single file */
struct MD5File {
	const char *filename;        ///< filename
	uint8 hash[16];              ///< md5 sum of the file
	const char *missing_warning; ///< warning when this file is missing

	bool CheckMD5() const;
};

/**
 * Information about a single base set.
 * @tparam T the real class we're going to be
 * @tparam Tnum_files the number of files in the set
 */
template <class T, size_t Tnum_files>
struct BaseSet {
	/** Number of files in this set */
	static const size_t NUM_FILES = Tnum_files;

	/** Internal names of the files in this set. */
	static const char *file_names[Tnum_files];

	const char *name;          ///< The name of the base set
	const char *description;   ///< Description of the base set
	uint32 shortname;          ///< Four letter short variant of the name
	uint32 version;            ///< The version of this base set

	MD5File files[NUM_FILES];  ///< All files part of this set
	uint found_files;          ///< Number of the files that could be found

	T *next;                   ///< The next base set in this list

	/** Free everything we allocated */
	~BaseSet()
	{
		free((void*)this->name);
		free((void*)this->description);
		for (uint i = 0; i < NUM_FILES; i++) {
			free((void*)this->files[i].filename);
			free((void*)this->files[i].missing_warning);
		}

		delete this->next;
	}

	/**
	 * Get the number of missing files.
	 * @return the number
	 */
	int GetNumMissing() const
	{
		return Tnum_files - this->found_files;
	}

	/**
	 * Read the set information from a loaded ini.
	 * @param ini      the ini to read from
	 * @param path     the path to this ini file (for filenames)
	 * @return true if loading was successful.
	 */
	bool FillSetDetails(IniFile *ini, const char *path);
};

/**
 * Base for all base media (graphics, sound)
 * @tparam Tbase_set the real set we're going to be
 */
template <class Tbase_set>
class BaseMedia : FileScanner {
protected:
	static Tbase_set *available_sets; ///< All available sets
	static const Tbase_set *used_set; ///< The currently used set

	/* virtual */ bool AddFile(const char *filename, size_t basepath_length);

	/**
	 * Get the extension that is used to identify this set.
	 * @return the extension
	 */
	static const char *GetExtension();
public:
	/** The set as saved in the config file. */
	static const char *ini_set;

	/**
	 * Determine the graphics pack that has to be used.
	 * The one with the most correct files wins.
	 * @return true if a best set has been found.
	 */
	static bool DetermineBestSet();

	/** Do the scan for files. */
	static uint FindSets()
	{
		BaseMedia<Tbase_set> fs;
		return fs.Scan(GetExtension(), DATA_DIR);
	}

	/**
	 * Set the set to be used.
	 * @param name of the set to use
	 * @return true if it could be loaded
	 */
	static bool SetSet(const char *name);

	/**
	 * Returns a list with the sets.
	 * @param p    where to print to
	 * @param last the last character to print to
	 * @return the last printed character
	 */
	static char *GetSetsList(char *p, const char *last);

	/**
	 * Count the number of available graphics sets.
	 * @return the number of sets
	 */
	static int GetNumSets();

	/**
	 * Get the index of the currently active graphics set
	 * @return the current set's index
	 */
	static int GetIndexOfUsedSet();

	/**
	 * Get the name of the graphics set at the specified index
	 * @return the name of the set
	 */
	static const Tbase_set *GetSet(int index);
	/**
	 * Return the used set.
	 * @return the used set.
	 */
	static const Tbase_set *GetUsedSet();

	/**
	 * Check whether we have an set with the exact characteristics as ci.
	 * @param ci the characteristics to search on (shortname and md5sum)
	 * @param md5sum whether to check the MD5 checksum
	 * @return true iff we have an set matching.
	 */
	static bool HasSet(const ContentInfo *ci, bool md5sum);
};


/** Types of graphics in the base graphics set */
enum GraphicsFileType {
	GFT_BASE,     ///< Base sprites for all climates
	GFT_LOGOS,    ///< Logos, landscape icons and original terrain generator sprites
	GFT_ARCTIC,   ///< Landscape replacement sprites for arctic
	GFT_TROPICAL, ///< Landscape replacement sprites for tropical
	GFT_TOYLAND,  ///< Landscape replacement sprites for toyland
	GFT_EXTRA,    ///< Extra sprites that were not part of the original sprites
	MAX_GFT       ///< We are looking for this amount of GRFs
};

/** All data of a graphics set. */
struct GraphicsSet : BaseSet<GraphicsSet, MAX_GFT> {
	PaletteType palette;       ///< Palette of this graphics set

	/**
	 * Is this set useable? Are enough files found to think it exists.
	 * @return true if it's useable.
	 */
	bool IsUseable() const
	{
		/* Do not find 'only' openttd[dw].grf */
		return this->found_files > 1;
	}

	bool FillSetDetails(struct IniFile *ini, const char *path);
};

/** All data/functions related with replacing the base graphics. */
class BaseGraphics : public BaseMedia<GraphicsSet> {
public:
	/**
	 * Determine the palette of the current graphics set.
	 */
	static void DeterminePalette();
};

#endif /* BASE_MEDIA_BASE_H */