2009-08-09 16:54:03 +00:00
/* $Id$ */
2009-08-21 20:21:05 +00:00
/*
* 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 < http : //www.gnu.org/licenses/>.
*/
2009-08-09 16:54:03 +00:00
/** @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"
2009-10-17 20:34:09 +00:00
# include "core/smallmap_type.hpp"
2009-12-22 21:40:29 +00:00
# include "gfx_type.h"
2012-03-17 15:45:37 +00:00
# include "textfile_type.h"
# include "textfile_gui.h"
2009-08-09 16:54:03 +00:00
2009-08-09 18:44:35 +00:00
/* Forward declare these; can't do 'struct X' in functions as older GCCs barf on that */
struct IniFile ;
struct ContentInfo ;
2009-08-09 16:54:03 +00:00
/** Structure holding filename and MD5 information about a single file */
struct MD5File {
2009-08-20 17:02:44 +00:00
/** The result of a checksum check */
enum ChecksumResult {
2018-06-07 19:34:24 +00:00
CR_UNKNOWN , ///< The file has not been checked yet
2009-08-20 17:02:44 +00:00
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
} ;
2009-08-09 16:54:03 +00:00
const char * filename ; ///< filename
uint8 hash [ 16 ] ; ///< md5 sum of the file
const char * missing_warning ; ///< warning when this file is missing
2018-06-07 19:34:24 +00:00
ChecksumResult check_result ; ///< cached result of md5 check
2009-08-09 16:54:03 +00:00
2012-02-04 13:29:00 +00:00
ChecksumResult CheckMD5 ( Subdirectory subdir , size_t max_size ) const ;
2009-08-09 16:54:03 +00:00
} ;
/**
* 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
2011-11-14 19:24:22 +00:00
* @ tparam Tsearch_in_tars whether to search in the tars or not
2009-08-09 16:54:03 +00:00
*/
2011-11-14 19:24:22 +00:00
template < class T , size_t Tnum_files , bool Tsearch_in_tars >
2009-08-09 16:54:03 +00:00
struct BaseSet {
2009-10-17 20:34:09 +00:00
typedef SmallMap < const char * , const char * > TranslatedStrings ;
2009-08-09 16:54:03 +00:00
/** Number of files in this set */
static const size_t NUM_FILES = Tnum_files ;
2011-11-14 19:24:22 +00:00
/** Whether to search in the tars or not. */
static const bool SEARCH_IN_TARS = Tsearch_in_tars ;
2009-12-22 21:40:29 +00:00
2009-08-09 16:54:03 +00:00
/** Internal names of the files in this set. */
2009-09-20 23:11:01 +00:00
static const char * const * file_names ;
2009-08-09 16:54:03 +00:00
2009-10-17 20:34:09 +00:00
const char * name ; ///< The name of the base set
TranslatedStrings description ; ///< Description of the base set
uint32 shortname ; ///< Four letter short variant of the name
uint32 version ; ///< The version of this base set
2010-02-22 16:24:23 +00:00
bool fallback ; ///< This set is a fallback set, i.e. it should be used only as last resort
2009-08-09 16:54:03 +00:00
2009-10-17 20:34:09 +00:00
MD5File files [ NUM_FILES ] ; ///< All files part of this set
uint found_files ; ///< Number of the files that could be found
uint valid_files ; ///< Number of the files that could be found and are valid
2009-08-09 16:54:03 +00:00
2009-10-17 20:34:09 +00:00
T * next ; ///< The next base set in this list
2009-08-09 16:54:03 +00:00
/** Free everything we allocated */
~ BaseSet ( )
{
2011-11-12 13:00:29 +00:00
free ( this - > name ) ;
2009-10-17 20:34:09 +00:00
2019-02-17 11:20:52 +00:00
for ( auto & pair : this - > description ) {
free ( pair . first ) ;
free ( pair . second ) ;
2009-10-17 20:34:09 +00:00
}
2009-08-09 16:54:03 +00:00
for ( uint i = 0 ; i < NUM_FILES ; i + + ) {
2011-11-12 13:00:29 +00:00
free ( this - > files [ i ] . filename ) ;
free ( this - > files [ i ] . missing_warning ) ;
2009-08-09 16:54:03 +00:00
}
delete this - > next ;
}
/**
* Get the number of missing files .
* @ return the number
*/
int GetNumMissing ( ) const
{
return Tnum_files - this - > found_files ;
}
2009-08-20 17:02:44 +00:00
/**
* Get the number of invalid files .
* @ note a missing file is invalid too !
* @ return the number
*/
int GetNumInvalid ( ) const
{
return Tnum_files - this - > valid_files ;
}
2010-04-19 09:34:56 +00:00
bool FillSetDetails ( IniFile * ini , const char * path , const char * full_filename , bool allow_empty_filename = true ) ;
2009-10-17 20:34:09 +00:00
/**
* Get the description for the given ISO code .
* It falls back to the first two characters of the ISO code in case
* no match could be made with the full ISO code . If even then the
* matching fails the default is returned .
* @ param isocode the isocode to search for
* @ return the description
*/
2019-04-10 21:07:06 +00:00
const char * GetDescription ( const char * isocode = nullptr ) const
2009-10-17 20:34:09 +00:00
{
2019-04-10 21:07:06 +00:00
if ( isocode ! = nullptr ) {
2009-10-17 20:34:09 +00:00
/* First the full ISO code */
2019-02-17 11:20:52 +00:00
for ( const auto & pair : this - > description ) {
if ( strcmp ( pair . first , isocode ) = = 0 ) return pair . second ;
2009-10-17 20:34:09 +00:00
}
/* Then the first two characters */
2019-02-17 11:20:52 +00:00
for ( const auto & pair : this - > description ) {
if ( strncmp ( pair . first , isocode , 2 ) = = 0 ) return pair . second ;
2009-10-17 20:34:09 +00:00
}
}
/* Then fall back */
2019-02-17 11:20:52 +00:00
return this - > description . front ( ) . second ;
2009-10-17 20:34:09 +00:00
}
2012-02-04 13:29:00 +00:00
/**
* Calculate and check the MD5 hash of the supplied file .
* @ param file The file get the hash of .
* @ param subdir The sub directory to get the files from .
* @ return
* - # CR_MATCH if the MD5 hash matches
* - # CR_MISMATCH if the MD5 does not match
* - # CR_NO_FILE if the file misses
*/
static MD5File : : ChecksumResult CheckMD5 ( const MD5File * file , Subdirectory subdir )
{
return file - > CheckMD5 ( subdir , SIZE_MAX ) ;
}
2012-03-17 15:45:37 +00:00
/**
* Search a textfile file next to this base media .
* @ param type The type of the textfile to search for .
2019-04-10 21:07:06 +00:00
* @ return The filename for the textfile , \ c nullptr otherwise .
2012-03-17 15:45:37 +00:00
*/
const char * GetTextfile ( TextfileType type ) const
{
for ( uint i = 0 ; i < NUM_FILES ; i + + ) {
const char * textfile = : : GetTextfile ( type , BASESET_DIR , this - > files [ i ] . filename ) ;
2019-04-10 21:07:06 +00:00
if ( textfile ! = nullptr ) {
2012-03-17 15:45:37 +00:00
return textfile ;
}
}
2019-04-10 21:07:06 +00:00
return nullptr ;
2012-03-17 15:45:37 +00:00
}
2009-08-09 16:54:03 +00:00
} ;
/**
2009-08-09 19:50:44 +00:00
* Base for all base media ( graphics , sounds )
2009-08-09 16:54:03 +00:00
* @ 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
2010-08-23 23:49:14 +00:00
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.
2009-08-09 16:54:03 +00:00
static const Tbase_set * used_set ; ///< The currently used set
2019-03-03 22:25:13 +00:00
bool AddFile ( const char * filename , size_t basepath_length , const char * tar_filename ) override ;
2009-08-09 16:54:03 +00:00
/**
* 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 ;
2011-11-14 21:34:27 +00:00
/* Searching in tars is only done in the old "data" directories basesets. */
uint num = fs . Scan ( GetExtension ( ) , Tbase_set : : SEARCH_IN_TARS ? OLD_DATA_DIR : OLD_GM_DIR , Tbase_set : : SEARCH_IN_TARS ) ;
return num + fs . Scan ( GetExtension ( ) , BASESET_DIR , Tbase_set : : SEARCH_IN_TARS ) ;
2009-08-09 16:54:03 +00:00
}
2012-08-20 21:01:40 +00:00
static Tbase_set * GetAvailableSets ( ) ;
2009-08-09 16:54:03 +00:00
static bool SetSet ( const char * name ) ;
static char * GetSetsList ( char * p , const char * last ) ;
static int GetNumSets ( ) ;
static int GetIndexOfUsedSet ( ) ;
static const Tbase_set * GetSet ( int index ) ;
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 .
*/
2009-08-09 18:44:35 +00:00
static bool HasSet ( const ContentInfo * ci , bool md5sum ) ;
2009-08-09 16:54:03 +00:00
} ;
2018-04-21 13:54:46 +00:00
template < class Tbase_set > /* static */ const char * BaseMedia < Tbase_set > : : ini_set ;
template < class Tbase_set > /* static */ const Tbase_set * BaseMedia < Tbase_set > : : used_set ;
template < class Tbase_set > /* static */ Tbase_set * BaseMedia < Tbase_set > : : available_sets ;
template < class Tbase_set > /* static */ Tbase_set * BaseMedia < Tbase_set > : : duplicate_sets ;
2012-08-20 21:01:40 +00:00
/**
* Check whether there ' s a base set matching some information .
* @ param ci The content info to compare it to .
* @ param md5sum Should the MD5 checksum be tested as well ?
* @ param s The list with sets .
2019-04-10 21:07:06 +00:00
* @ return The filename of the first file of the base set , or \ c nullptr if there is no match .
2012-08-20 21:01:40 +00:00
*/
template < class Tbase_set >
const char * TryGetBaseSetFile ( const ContentInfo * ci , bool md5sum , const Tbase_set * s ) ;
2009-08-09 16:54:03 +00:00
/** 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
2011-12-19 17:48:04 +00:00
MAX_GFT , ///< We are looking for this amount of GRFs
2009-08-09 16:54:03 +00:00
} ;
2011-10-04 21:35:47 +00:00
/** Blitter type for base graphics sets. */
enum BlitterType {
BLT_8BPP , ///< Base set has 8 bpp sprites only.
BLT_32BPP , ///< Base set has both 8 bpp and 32 bpp sprites.
} ;
2009-08-09 16:54:03 +00:00
/** All data of a graphics set. */
2011-11-14 19:24:22 +00:00
struct GraphicsSet : BaseSet < GraphicsSet , MAX_GFT , true > {
2009-08-09 16:54:03 +00:00
PaletteType palette ; ///< Palette of this graphics set
2011-10-04 21:35:47 +00:00
BlitterType blitter ; ///< Blitter of this graphics set
2009-08-09 16:54:03 +00:00
2010-04-19 09:34:56 +00:00
bool FillSetDetails ( struct IniFile * ini , const char * path , const char * full_filename ) ;
2012-02-04 13:29:04 +00:00
static MD5File : : ChecksumResult CheckMD5 ( const MD5File * file , Subdirectory subdir ) ;
2009-08-09 16:54:03 +00:00
} ;
/** All data/functions related with replacing the base graphics. */
class BaseGraphics : public BaseMedia < GraphicsSet > {
public :
} ;
2009-08-09 19:50:44 +00:00
/** All data of a sounds set. */
2011-11-14 19:24:22 +00:00
struct SoundsSet : BaseSet < SoundsSet , 1 , true > {
2009-08-09 19:50:44 +00:00
} ;
/** All data/functions related with replacing the base sounds */
class BaseSounds : public BaseMedia < SoundsSet > {
public :
} ;
2009-12-22 21:40:29 +00:00
/** Maximum number of songs in the 'class' playlists. */
static const uint NUM_SONGS_CLASS = 10 ;
/** Number of classes for songs */
static const uint NUM_SONG_CLASSES = 3 ;
/** Maximum number of songs in the full playlist; theme song + the classes */
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 ;
2018-03-14 14:55:40 +00:00
/* 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 ) ;
2018-03-17 13:51:30 +00:00
enum MusicTrackType {
MTT_STANDARDMIDI , ///< Standard MIDI file
2018-03-14 14:55:40 +00:00
MTT_MPSMIDI , ///< MPS GM driver MIDI format (contained in a CAT file)
2018-03-17 13:51:30 +00:00
} ;
/** 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
2018-03-14 14:55:40 +00:00
int cat_index ; ///< entry index in CAT file, for filetype==MTT_MPSMIDI
2018-06-06 18:58:06 +00:00
bool loop ; ///< song should play in a tight loop if possible, never ending
2018-03-04 22:34:02 +00:00
int override_start ; ///< MIDI ticks to skip over in beginning
int override_end ; ///< MIDI tick to end the song at (0 if no override)
2018-03-17 13:51:30 +00:00
} ;
2009-12-22 21:40:29 +00:00
/** All data of a music set. */
2011-11-14 19:24:22 +00:00
struct MusicSet : BaseSet < MusicSet , NUM_SONGS_AVAILABLE , false > {
2018-03-17 13:51:30 +00:00
/** Data about individual songs in set. */
MusicSongInfo songinfo [ NUM_SONGS_AVAILABLE ] ;
/** Number of valid songs in set. */
2009-12-22 21:40:29 +00:00
byte num_available ;
2010-04-19 09:34:56 +00:00
bool FillSetDetails ( struct IniFile * ini , const char * path , const char * full_filename ) ;
2009-12-22 21:40:29 +00:00
} ;
/** All data/functions related with replacing the base music */
class BaseMusic : public BaseMedia < MusicSet > {
public :
} ;
2009-08-09 16:54:03 +00:00
# endif /* BASE_MEDIA_BASE_H */