(svn r18608) -Change: add the concept of music sets

pull/155/head
rubidium 15 years ago
parent 8e802135d8
commit 42d7f30dcc

@ -0,0 +1,48 @@
; $Id$
;
; This represents more or less nothingness
;
[metadata]
name = NoMusic
shortname = NOMU
version = 0
description = A music pack without actual music
[files]
theme =
old_0 =
old_1 =
old_2 =
old_3 =
old_4 =
old_5 =
old_6 =
old_7 =
old_8 =
old_9 =
new_0 =
new_1 =
new_2 =
new_3 =
new_4 =
new_5 =
new_6 =
new_7 =
new_8 =
new_9 =
ezy_0 =
ezy_1 =
ezy_2 =
ezy_3 =
ezy_4 =
ezy_5 =
ezy_6 =
ezy_7 =
ezy_8 =
ezy_9 =
[md5s]
[names]
[origin]

@ -0,0 +1,94 @@
; $Id$
;
; This represents the original music as on the Transport
; Tycoon Deluxe for Windows CD.
;
[metadata]
name = original_windows
shortname = TTDW
version = 1
description = Original Transport Tycoon Deluxe Windows edition music
[files]
theme = GM_TT00.GM
old_0 = GM_TT02.GM
old_1 = GM_TT06.GM
old_2 = GM_TT03.GM
old_3 = GM_TT12.GM
old_4 = GM_TT08.GM
old_5 = GM_TT13.GM
old_6 = GM_TT14.GM
old_7 = GM_TT19.GM
old_8 =
old_9 =
new_0 = GM_TT04.GM
new_1 = GM_TT01.GM
new_2 = GM_TT05.GM
new_3 = GM_TT15.GM
new_4 = GM_TT11.GM
new_5 = GM_TT16.GM
new_6 = GM_TT09.GM
new_7 =
new_8 =
new_9 =
ezy_0 = GM_TT18.GM
ezy_1 = GM_TT19.GM
ezy_2 = GM_TT21.GM
ezy_3 = GM_TT17.GM
ezy_4 = GM_TT20.GM
ezy_5 = GM_TT07.GM
ezy_6 =
ezy_7 =
ezy_8 =
ezy_9 =
[md5s]
GM_TT00.GM = 45cfec1b9d8c7a0ad45e755833cbf221
GM_TT01.GM = ab14ed3392d848abd2a2e90a9d75d121
GM_TT02.GM = dd4f696e4be5987ce738257b08b50171
GM_TT03.GM = a1bfde23343df9e4063419bf29c166b8
GM_TT04.GM = 4e6943aa0c455203d76c79389054747d
GM_TT05.GM = cee281cb85a2e2343552d97640545a47
GM_TT06.GM = 26d1de5efa8675f94065784e9d539e49
GM_TT07.GM = 6f2691e17558f552ec4c565e4ab7139c
GM_TT08.GM = a42bf2cb3340a822f1a69646fc7a487d
GM_TT09.GM = eb35761a58a8df3c59ed8929cce13916
GM_TT10.GM = 42fecd686720a785d20a78590c466a82
GM_TT11.GM = 50ef1ef02e49d2112786dd45e69dc3ee
GM_TT12.GM = 4ce707a0e0e72419f0681dd9bd95271b
GM_TT13.GM = e765753be29d889ec818f38009103619
GM_TT14.GM = 270e2d63bd32b95a4d007ce15a6ce45f
GM_TT15.GM = 89e116a1c0c69f1845cc903a9bfbe460
GM_TT16.GM = f824e2371b3bedfe61aad4b9c62dd6be
GM_TT17.GM = 1b23eebb0796c1ab99cd97fa7082cf7b
GM_TT18.GM = 15650de3bad645d0e88c4f5c7a2df92a
GM_TT19.GM = 7aec079e15bd09588660b85545ac4dfc
GM_TT20.GM = 1509097889dee617aa1e9a1738a5a930
GM_TT21.GM = a8d0aaad02e1a762d8d54cf81da56bab
[names]
GM_TT00.GM = Tycoon DELUXE Theme
GM_TT01.GM = Snarl Up
GM_TT02.GM = Easy Driver
GM_TT03.GM = Little Red Diesel
GM_TT04.GM = City Groove
GM_TT05.GM = Aliens Ate My Railway
GM_TT06.GM = Stoke It
GM_TT07.GM = Don't Walk!
GM_TT08.GM = Sawyer's Tune
GM_TT09.GM = Fell Apart On Me
GM_TT10.GM = Can't Get There From Here
GM_TT11.GM = Hard Drivin'
GM_TT12.GM = Road Hog
GM_TT13.GM = Hold That Train!
GM_TT14.GM = Broomer's Oil Rag
GM_TT15.GM = Goss Groove
GM_TT16.GM = Small Town
GM_TT17.GM = Cruise Control
GM_TT18.GM = Stroll On
GM_TT19.GM = Funk Central
GM_TT20.GM = Jammit
GM_TT21.GM = Movin' On
[origin]
default = You can find it on your Transport Tycoon Deluxe CD-ROM.

@ -0,0 +1,106 @@
;
; Example file for the OpenTTD Base Music replacement sets.
; This file consists of basically two different parts:
; * metadata
; * information about the files/songs
;
; Metadata contains information about the name and version
; of the music set.
;
; == Getting started ==
; - you can't add comments after values
; - you have to fill the MD5 checksum for each file
; - you may not miss any of the metadata or files items
; - `openttd -h` lists all music replacement sets it found to be correct
; - `openttd -d grf=1` shows warnings/errors when parsing an .obm file
; - `openttd -M <name>` starts OpenTTD with the given set (case sensitive)
; - adding `musicset = <name>` to the misc section of openttd.cfg makes
; OpenTTD start with that sound set by default
; - there is a command line tool for all platforms called md5sum that can
; create the MD5 checksum you need.
; - all files specified in this file are search relatively to the path where
; this file is found, i.e. if the sound files are in a subdir you have
; to add that subdir to the names in this file to! It will NOT search for
; a file named like specified in here.
[metadata]
; the name of the pack, preferably less than 16 characters
name = example
; the short name (4 characters), used to identify this set
shortname = XMPL
; the version of this sound set (read as single integer)
version = 0
; a fairly short description of the set
; By adding '.<iso code>' you can translate the description.
; Note that OpenTTD first tries the full ISO code, then the first
; two characters and then uses the fallback (no '.<iso code>').
; The ISO code matching is case sensitive!
; So en_US will be used for en_GB if no en_GB translation is added.
; As a result the below example has 'howdie' for en_US and en_GB but
; 'foo' for all other languages.
description = foo
description.en_US = howdie
; The files section lists the files that replace songs.
; The file names are case sensitive.
; You can have empty file names; in that case no song will be loaded
; for that 'entry'.
[files]
; The theme song for OpenTTD
theme = THEME_SONG.GM
; The songs in the 'old style' category
old_0 =
old_1 =
old_2 =
old_3 =
old_4 =
old_5 =
old_6 =
old_7 =
old_8 =
old_9 =
; The songs in the 'new style' category
new_0 =
new_1 =
new_2 =
new_3 =
new_4 =
new_5 =
new_6 =
new_7 =
new_8 =
new_9 =
; The songs in the 'ezy street' category
ezy_0 =
ezy_1 =
ezy_2 =
ezy_3 =
ezy_4 =
ezy_5 =
ezy_6 =
ezy_7 =
ezy_8 =
ezy_9 =
; The names section lists the song names for the given file name.
; Note that the list of files is case sensitive. Each file listed in the
; files section must be listed here with it's song name, otherwise you
; will get a lot of warnings when starting OpenTTD.
[names]
THEME_SONG.GM = Tycoon DELUXE Theme
; The md5s section lists the MD5 checksum for the files that replace them.
; Note that the list of files is case sensitive. Each file listed in the
; files section must be listed here with it's MD5 checksum, otherwise you
; will get a lot of warnings when starting OpenTTD.
[md5s]
THEME_SONG.GM = 45cfec1b9d8c7a0ad45e755833cbf221
; The origin section provides the possibility to put and extra line into
; the warning that a file is missing/corrupt. This can be used to tell
; them where to find it. It works on the filename specified in the
; files section and if that is not found it will fall back to the default
; as shown below here.
[origin]
default = You can find it on your Transport Tycoon Deluxe CD-ROM.
THEME_SONG.GM = You can find it also on your Transport Tycoon Deluxe CD-ROM.

@ -123,6 +123,10 @@ Section "!OpenTTD" Section1
File ${PATH_ROOT}bin\data\*.obs
File ${PATH_ROOT}bin\data\opntitle.dat
; Copy the music base metadata files
SetOutPath "$INSTDIR\gm\"
File ${PATH_ROOT}bin\gm\*.obm
; Copy the scripts
SetOutPath "$INSTDIR\scripts\"
File ${PATH_ROOT}bin\scripts\*.*
@ -397,6 +401,10 @@ Section "Uninstall"
; Scripts
Delete "$INSTDIR\scripts\*.*"
; Base sets for music
Delete "$INSTDIR\gm\orig_mus.obm"
Delete "$INSTDIR\gm\no_sound.obm"
; Remove remaining directories
RMDir "$SMPROGRAMS\$SHORTCUTS\Extras\"
RMDir "$SMPROGRAMS\$SHORTCUTS"

@ -1099,10 +1099,6 @@
RelativePath=".\..\src\mixer.h"
>
</File>
<File
RelativePath=".\..\src\music.h"
>
</File>
<File
RelativePath=".\..\src\network\network.h"
>

@ -1096,10 +1096,6 @@
RelativePath=".\..\src\mixer.h"
>
</File>
<File
RelativePath=".\..\src\music.h"
>
</File>
<File
RelativePath=".\..\src\network\network.h"
>

@ -184,7 +184,6 @@ livery.h
map_func.h
map_type.h
mixer.h
music.h
network/network.h
network/network_base.h
network/network_client.h

@ -14,6 +14,7 @@
#include "fileio_func.h"
#include "core/smallmap_type.hpp"
#include "gfx_type.h"
/* Forward declare these; can't do 'struct X' in functions as older GCCs barf on that */
struct IniFile;
@ -32,21 +33,25 @@ struct MD5File {
uint8 hash[16]; ///< md5 sum of the file
const char *missing_warning; ///< warning when this file is missing
ChecksumResult CheckMD5() const;
ChecksumResult CheckMD5(Subdirectory subdir) 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
* @tparam Tsubdir the subdirectory where to find the files
*/
template <class T, size_t Tnum_files>
template <class T, size_t Tnum_files, Subdirectory Tsubdir>
struct BaseSet {
typedef SmallMap<const char *, const char *> TranslatedStrings;
/** Number of files in this set */
static const size_t NUM_FILES = Tnum_files;
/** The sub directory to search for the files */
static const Subdirectory SUBDIR = Tsubdir;
/** Internal names of the files in this set. */
static const char * const *file_names;
@ -163,7 +168,7 @@ public:
static uint FindSets()
{
BaseMedia<Tbase_set> fs;
return fs.Scan(GetExtension(), DATA_DIR);
return fs.Scan(GetExtension(), Tbase_set::SUBDIR);
}
/**
@ -226,7 +231,7 @@ enum GraphicsFileType {
};
/** All data of a graphics set. */
struct GraphicsSet : BaseSet<GraphicsSet, MAX_GFT> {
struct GraphicsSet : BaseSet<GraphicsSet, MAX_GFT, DATA_DIR> {
PaletteType palette; ///< Palette of this graphics set
bool FillSetDetails(struct IniFile *ini, const char *path);
@ -242,7 +247,7 @@ public:
};
/** All data of a sounds set. */
struct SoundsSet : BaseSet<SoundsSet, 1> {
struct SoundsSet : BaseSet<SoundsSet, 1, DATA_DIR> {
};
/** All data/functions related with replacing the base sounds */
@ -250,4 +255,29 @@ class BaseSounds : public BaseMedia<SoundsSet> {
public:
};
/** 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;
/** All data of a music set. */
struct MusicSet : BaseSet<MusicSet, NUM_SONGS_AVAILABLE, GM_DIR> {
/** The name of the different songs. */
char song_name[NUM_SONGS_AVAILABLE][32];
byte track_nr[NUM_SONGS_AVAILABLE];
byte num_available;
bool FillSetDetails(struct IniFile *ini, const char *path);
};
/** All data/functions related with replacing the base music */
class BaseMusic : public BaseMedia<MusicSet> {
public:
};
#endif /* BASE_MEDIA_BASE_H */

@ -28,8 +28,8 @@ template <class Tbase_set> /* static */ Tbase_set *BaseMedia<Tbase_set>::availab
return false; \
}
template <class T, size_t Tnum_files>
bool BaseSet<T, Tnum_files>::FillSetDetails(IniFile *ini, const char *path)
template <class T, size_t Tnum_files, Subdirectory Tsubdir>
bool BaseSet<T, Tnum_files, Tsubdir>::FillSetDetails(IniFile *ini, const char *path)
{
memset(this, 0, sizeof(*this));
@ -64,13 +64,21 @@ bool BaseSet<T, Tnum_files>::FillSetDetails(IniFile *ini, const char *path)
for (uint i = 0; i < Tnum_files; i++) {
MD5File *file = &this->files[i];
/* Find the filename first. */
item = files->GetItem(BaseSet<T, Tnum_files>::file_names[i], false);
item = files->GetItem(BaseSet<T, Tnum_files, Tsubdir>::file_names[i], false);
if (item == NULL) {
DEBUG(grf, 0, "No " SET_TYPE " file for: %s", BaseSet<T, Tnum_files>::file_names[i]);
DEBUG(grf, 0, "No " SET_TYPE " file for: %s", BaseSet<T, Tnum_files, Tsubdir>::file_names[i]);
return false;
}
const char *filename = item->value;
if (filename == NULL) {
file->filename = NULL;
/* If we list no file, that file must be valid */
this->valid_files++;
this->found_files++;
continue;
}
file->filename = str_fmt("%s%s", path, filename);
/* Then find the MD5 checksum */
@ -100,7 +108,7 @@ bool BaseSet<T, Tnum_files>::FillSetDetails(IniFile *ini, const char *path)
}
/* Then find the warning message when the file's missing */
item = origin->GetItem(filename, false);
item = filename == NULL ? NULL : origin->GetItem(filename, false);
if (item == NULL) item = origin->GetItem("default", false);
if (item == NULL) {
DEBUG(grf, 1, "No origin warning message specified for: %s", filename);
@ -109,7 +117,7 @@ bool BaseSet<T, Tnum_files>::FillSetDetails(IniFile *ini, const char *path)
file->missing_warning = strdup(item->value);
}
switch (file->CheckMD5()) {
switch (file->CheckMD5(Tsubdir)) {
case MD5File::CR_MATCH:
this->valid_files++;
/* FALL THROUGH */

@ -1669,7 +1669,7 @@ DEF_CONSOLE_CMD(ConContent)
if (strcasecmp(argv[1], "state") == 0) {
IConsolePrintF(CC_WHITE, "id, type, state, name");
for (ConstContentIterator iter = _network_content_client.Begin(); iter != _network_content_client.End(); iter++) {
static const char * const types[] = { "Base graphics", "NewGRF", "AI", "AI library", "Scenario", "Heightmap", "Base sound" };
static const char * const types[] = { "Base graphics", "NewGRF", "AI", "AI library", "Scenario", "Heightmap", "Base sound", "Base music" };
assert_compile(lengthof(types) == CONTENT_TYPE_END - CONTENT_TYPE_BEGIN);
static const char * const states[] = { "Not selected", "Selected", "Dep Selected", "Installed", "Unknown" };
static const ConsoleColour state_to_colour[] = { CC_COMMAND, CC_INFO, CC_INFO, CC_WHITE, CC_ERROR };

@ -118,7 +118,7 @@ void CheckExternalFiles()
/* Not all files were loaded succesfully, see which ones */
add_pos += seprintf(add_pos, last, "Trying to load graphics set '%s', but it is incomplete. The game will probably not run correctly until you properly install this set or select another one. See section 4.1 of readme.txt.\n\nThe following files are corrupted or missing:\n", used_set->name);
for (uint i = 0; i < GraphicsSet::NUM_FILES; i++) {
MD5File::ChecksumResult res = used_set->files[i].CheckMD5();
MD5File::ChecksumResult res = used_set->files[i].CheckMD5(DATA_DIR);
if (res != MD5File::CR_MATCH) add_pos += seprintf(add_pos, last, "\t%s is %s (%s)\n", used_set->files[i].filename, res == MD5File::CR_MISMATCH ? "corrupt" : "missing", used_set->files[i].missing_warning);
}
add_pos += seprintf(add_pos, last, "\n");
@ -131,7 +131,7 @@ void CheckExternalFiles()
assert_compile(SoundsSet::NUM_FILES == 1);
/* No need to loop each file, as long as there is only a single
* sound file. */
add_pos += seprintf(add_pos, last, "\t%s is %s (%s)\n", sounds_set->files->filename, sounds_set->files->CheckMD5() == MD5File::CR_MISMATCH ? "corrupt" : "missing", sounds_set->files->missing_warning);
add_pos += seprintf(add_pos, last, "\t%s is %s (%s)\n", sounds_set->files->filename, sounds_set->files->CheckMD5(DATA_DIR) == MD5File::CR_MISMATCH ? "corrupt" : "missing", sounds_set->files->missing_warning);
}
if (add_pos != error_msg) ShowInfoF("%s", error_msg);
@ -206,7 +206,7 @@ void GfxLoadSprites()
bool GraphicsSet::FillSetDetails(IniFile *ini, const char *path)
{
bool ret = this->BaseSet<GraphicsSet, MAX_GFT>::FillSetDetails(ini, path);
bool ret = this->BaseSet<GraphicsSet, MAX_GFT, DATA_DIR>::FillSetDetails(ini, path);
if (ret) {
IniGroup *metadata = ini->GetGroup("metadata");
IniItem *item;
@ -220,15 +220,16 @@ bool GraphicsSet::FillSetDetails(IniFile *ini, const char *path)
/**
* Calculate and check the MD5 hash of the supplied filename.
* @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
*/
MD5File::ChecksumResult MD5File::CheckMD5() const
MD5File::ChecksumResult MD5File::CheckMD5(Subdirectory subdir) const
{
size_t size;
FILE *f = FioFOpenFile(this->filename, "rb", DATA_DIR, &size);
FILE *f = FioFOpenFile(this->filename, "rb", subdir, &size);
if (f == NULL) return CR_NO_FILE;
@ -252,8 +253,8 @@ MD5File::ChecksumResult MD5File::CheckMD5() const
static const char * const _graphics_file_names[] = { "base", "logos", "arctic", "tropical", "toyland", "extra" };
/** Implementation */
template <class T, size_t Tnum_files>
/* static */ const char * const *BaseSet<T, Tnum_files>::file_names = _graphics_file_names;
template <class T, size_t Tnum_files, Subdirectory Tsubdir>
/* static */ const char * const *BaseSet<T, Tnum_files, Tsubdir>::file_names = _graphics_file_names;
extern void UpdateNewGRFConfigPalette();

@ -607,6 +607,8 @@ STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Select '
STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Toggle programme shuffle on/off
STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Show music track selection window
STR_ERROR_NO_SONGS :{WHITE}A music set without songs has been selected. No songs will be played
# Playlist window
STR_PLAYLIST_MUSIC_PROGRAM_SELECTION :{WHITE}Music Programme Selection
STR_PLAYLIST_TRACK_NAME :{TINYFONT}{LTBLUE}{ZEROFILL_NUM} "{RAW_STRING}"
@ -942,6 +944,11 @@ STR_GAME_OPTIONS_BASE_SFX :{BLACK}Base sou
STR_GAME_OPTIONS_BASE_SFX_TOOLTIP :{BLACK}Select the base sounds set to use
STR_GAME_OPTIONS_BASE_SFX_DESCRIPTION_TOOLTIP :{BLACK}Additional information about the base sounds set
STR_GAME_OPTIONS_BASE_MUSIC :{BLACK}Base music set
STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP :{BLACK}Select the base music set to use
STR_GAME_OPTIONS_BASE_MUSIC_STATUS :{RED}{NUM} corrupted file{P "" s}
STR_GAME_OPTIONS_BASE_MUSIC_DESCRIPTION_TOOLTIP :{BLACK}Additional information about the base music set
STR_ERROR_FULLSCREEN_FAILED :{WHITE}Fullscreen mode failed
# Custom currency window
@ -1812,6 +1819,7 @@ STR_CONTENT_TYPE_AI_LIBRARY :AI library
STR_CONTENT_TYPE_SCENARIO :Scenario
STR_CONTENT_TYPE_HEIGHTMAP :Heightmap
STR_CONTENT_TYPE_BASE_SOUNDS :Base sounds
STR_CONTENT_TYPE_BASE_MUSIC :Base music
# Content downloading progress window
STR_CONTENT_DOWNLOAD_TITLE :{WHITE}Downloading content...

@ -31,6 +31,7 @@ extern TileIndex _cur_tileloop_tile;
extern void MakeNewgameSettingsLive();
void InitializeSound();
void InitializeMusic();
void InitializeVehicles();
void InitializeDepots();
void InitializeEngineRenews();
@ -71,6 +72,7 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin
if (reset_settings) MakeNewgameSettingsLive();
InitializeSound();
InitializeMusic();
if (reset_date) {
SetDate(ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1));

@ -10,31 +10,85 @@
/** @file music.cpp The songs that OpenTTD knows. */
#include "stdafx.h"
#include "music.h"
const SongSpecs _origin_songs_specs[] = {
{"gm_tt00.gm", "Tycoon DELUXE Theme"},
{"gm_tt02.gm", "Easy Driver"},
{"gm_tt03.gm", "Little Red Diesel"},
{"gm_tt17.gm", "Cruise Control"},
{"gm_tt07.gm", "Don't Walk!"},
{"gm_tt09.gm", "Fell Apart On Me"},
{"gm_tt04.gm", "City Groove"},
{"gm_tt19.gm", "Funk Central"},
{"gm_tt06.gm", "Stoke It"},
{"gm_tt12.gm", "Road Hog"},
{"gm_tt05.gm", "Aliens Ate My Railway"},
{"gm_tt01.gm", "Snarl Up"},
{"gm_tt18.gm", "Stroll On"},
{"gm_tt10.gm", "Can't Get There From Here"},
{"gm_tt08.gm", "Sawyer's Tune"},
{"gm_tt13.gm", "Hold That Train!"},
{"gm_tt21.gm", "Movin' On"},
{"gm_tt15.gm", "Goss Groove"},
{"gm_tt16.gm", "Small Town"},
{"gm_tt14.gm", "Broomer's Oil Rag"},
{"gm_tt20.gm", "Jammit"},
{"gm_tt11.gm", "Hard Drivin'"},
#include "debug.h"
/* The type of set we're replacing */
#define SET_TYPE "music"
#include "base_media_func.h"
INSTANTIATE_BASE_MEDIA_METHODS(BaseMedia<MusicSet>, MusicSet)
/** Names corresponding to the music set's files */
static const char * const _music_file_names[] = {
"theme",
"old_0", "old_1", "old_2", "old_3", "old_4", "old_5", "old_6", "old_7", "old_8", "old_9",
"new_0", "new_1", "new_2", "new_3", "new_4", "new_5", "new_6", "new_7", "new_8", "new_9",
"ezy_0", "ezy_1", "ezy_2", "ezy_3", "ezy_4", "ezy_5", "ezy_6", "ezy_7", "ezy_8", "ezy_9",
};
assert_compile(lengthof(_music_file_names) == NUM_SONGS_AVAILABLE);
template <class T, size_t Tnum_files, Subdirectory Tsubdir>
/* static */ const char * const *BaseSet<T, Tnum_files, Tsubdir>::file_names = _music_file_names;
template <class Tbase_set>
/* static */ const char *BaseMedia<Tbase_set>::GetExtension()
{
return ".obm"; // OpenTTD Base Music
}
template <class Tbase_set>
/* static */ bool BaseMedia<Tbase_set>::DetermineBestSet()
{
if (BaseMedia<Tbase_set>::used_set != NULL) return true;
const Tbase_set *best = NULL;
for (const Tbase_set *c = BaseMedia<Tbase_set>::available_sets; c != NULL; c = c->next) {
if (best == NULL ||
best->valid_files < c->valid_files ||
(best->valid_files == c->valid_files &&
(best->shortname == c->shortname && best->version < c->version))) {
best = c;
}
}
BaseMedia<Tbase_set>::used_set = best;
return BaseMedia<Tbase_set>::used_set != NULL;
}
/**
* Try to read a single piece of metadata and return false if it doesn't exist.
* @param name the name of the item to fetch.
*/
#define fetch_name(name) \
item = metadata->GetItem(name, false); \
if (item == NULL || strlen(item->value) == 0) { \
DEBUG(grf, 0, "Base " SET_TYPE "set detail loading: %s field missing", name); \
return false; \
}
bool MusicSet::FillSetDetails(IniFile *ini, const char *path)
{
bool ret = this->BaseSet<MusicSet, NUM_SONGS_AVAILABLE, GM_DIR>::FillSetDetails(ini, path);
if (ret) {
this->num_available = 0;
IniGroup *names = ini->GetGroup("names");
for (uint i = 0, j = 1; i < lengthof(this->song_name); i++) {
const char *filename = this->files[i].filename;
if (names == NULL || StrEmpty(filename)) {
this->song_name[i][0] = '\0';
continue;
}
IniItem *item = names->GetItem(filename, false);
if (item == NULL || strlen(item->value) == 0) {
DEBUG(grf, 0, "Base music set song name missing: %s", filename);
return false;
}
assert_compile(NUM_SONGS_AVAILABLE == lengthof(_origin_songs_specs));
strecpy(this->song_name[i], item->value, lastof(this->song_name[i]));
this->track_nr[i] = j++;
this->num_available++;
}
}
return true;
}

@ -1,25 +0,0 @@
/* $Id$ */
/*
* 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/>.
*/
/** @file music.h Base for the music handling. */
#ifndef MUSIC_H
#define MUSIC_H
#define NUM_SONGS_PLAYLIST 33
#define NUM_SONGS_AVAILABLE 22
struct SongSpecs {
char filename[MAX_PATH];
char song_name[64];
};
extern const SongSpecs _origin_songs_specs[];
#endif /* MUSIC_H */

@ -12,7 +12,7 @@
#include "stdafx.h"
#include "openttd.h"
#include "fileio_func.h"
#include "music.h"
#include "base_media_base.h"
#include "music/music_driver.hpp"
#include "window_gui.h"
#include "strings_func.h"
@ -20,6 +20,7 @@
#include "sound_func.h"
#include "gfx_func.h"
#include "core/random_func.hpp"
#include "gui.h"
#include "table/strings.h"
#include "table/sprites.h"
@ -31,32 +32,40 @@
*/
static const char *GetSongName(int index)
{
return _origin_songs_specs[index].song_name;
return BaseMusic::GetUsedSet()->song_name[index];
}
/**
* Get the track number of the song.
* @param index of the song.
* @return the track number of the song.
*/
static int GetTrackNumber(int index)
{
return BaseMusic::GetUsedSet()->track_nr[index];
}
static byte _music_wnd_cursong;
static bool _song_is_active;
static byte _cur_playlist[NUM_SONGS_PLAYLIST];
/** The currently played song */
static byte _music_wnd_cursong = 1;
/** Whether a song is currently played */
static bool _song_is_active = false;
/** Indices of the songs in the current playlist */
static byte _cur_playlist[NUM_SONGS_PLAYLIST + 1];
static byte _playlist_all[] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0
};
/** Indices of all songs */
static byte _playlist_all[NUM_SONGS_AVAILABLE + 1];
/** Indices of all old style songs */
static byte _playlist_old_style[NUM_SONGS_CLASS + 1];
/** Indices of all new style songs */
static byte _playlist_new_style[NUM_SONGS_CLASS + 1];
/** Indices of all ezy street songs */
static byte _playlist_ezy_street[NUM_SONGS_CLASS + 1];
static byte _playlist_old_style[] = {
2, 9, 3, 10, 15, 16, 20, 14, 0
};
static byte _playlist_new_style[] = {
7, 12, 11, 18, 22, 19, 6, 0
};
static byte _playlist_ezy_street[] = {
13, 8, 17, 4, 21, 5, 0
};
assert_compile(lengthof(msf.custom_1) == NUM_SONGS_PLAYLIST + 1);
assert_compile(lengthof(msf.custom_2) == NUM_SONGS_PLAYLIST + 1);
/** The different playlists that can be played. */
static byte * const _playlists[] = {
_playlist_all,
_playlist_old_style,
@ -66,6 +75,57 @@ static byte * const _playlists[] = {
msf.custom_2,
};
/**
* Validate a playlist.
* @param playlist the playlist to validate
*/
void ValidatePlaylist(byte *playlist)
{
while (*playlist != 0) {
if (*playlist <= BaseMusic::GetUsedSet()->num_available) {
playlist++;
continue;
}
for (byte *p = playlist; *p != 0; p++) {
p[0] = p[1];
}
}
}
/** Initialize the playlists */
void InitializeMusic()
{
uint j = 0;
for (uint i = 0; i < NUM_SONGS_AVAILABLE; i++) {
if (StrEmpty(GetSongName(i))) continue;
_playlist_all[j++] = i + 1;
}
/* Terminate the list */
_playlist_all[j] = 0;
/* Now make the 'styled' playlists */
for (uint k = 0; k < NUM_SONG_CLASSES; k++) {
j = 0;
for (uint i = 0; i < NUM_SONGS_CLASS; i++) {
int id = k * NUM_SONGS_CLASS + i + 1;
if (StrEmpty(GetSongName(id))) continue;
_playlists[k + 1][j++] = id + 1;
}
/* Terminate the list */
_playlists[k + 1][j] = 0;
}
ValidatePlaylist(msf.custom_1);
ValidatePlaylist(msf.custom_2);
if (BaseMusic::GetUsedSet()->num_available < _music_wnd_cursong) {
/* If there are less songs than the currently played song,
* just pause and reset to no song. */
_music_wnd_cursong = 0;
_song_is_active = false;
}
}
static void SkipToPrevSong()
{
byte *b = _cur_playlist;
@ -112,13 +172,15 @@ static void DoPlaySong()
{
char filename[MAX_PATH];
FioFindFullPath(filename, lengthof(filename), GM_DIR,
_origin_songs_specs[_music_wnd_cursong - 1].filename);
BaseMusic::GetUsedSet()->files[_music_wnd_cursong - 1].filename);
_music_driver->PlaySong(filename);
SetWindowDirty(WC_MUSIC_WINDOW, 0);
}
static void DoStopMusic()
{
_music_driver->StopSong();
SetWindowDirty(WC_MUSIC_WINDOW, 0);
}
static void SelectSongToPlay()
@ -128,9 +190,10 @@ static void SelectSongToPlay()
memset(_cur_playlist, 0, sizeof(_cur_playlist));
do {
const char *filename = BaseMusic::GetUsedSet()->files[_playlists[msf.playlist][i] - 1].filename;
/* We are now checking for the existence of that file prior
* to add it to the list of available songs */
if (FioCheckFileExists(_origin_songs_specs[_playlists[msf.playlist][i] - 1].filename, GM_DIR)) {
if (!StrEmpty(filename) && FioCheckFileExists(filename, GM_DIR)) {
_cur_playlist[j] = _playlists[msf.playlist][i];
j++;
}
@ -275,10 +338,13 @@ struct MusicTrackSelectionWindow : public Window {
case MTSW_LIST_LEFT: case MTSW_LIST_RIGHT: {
Dimension d = {0, 0};
for (uint i = 1; i <= NUM_SONGS_AVAILABLE; i++) {
SetDParam(0, i);
for (uint i = 0; i < NUM_SONGS_AVAILABLE; i++) {
const char *song_name = GetSongName(i);
if (StrEmpty(song_name)) continue;
SetDParam(0, GetTrackNumber(i));
SetDParam(1, 2);
SetDParamStr(2, GetSongName(i - 1));
SetDParamStr(2, GetSongName(i));
Dimension d2 = GetStringBoundingBox(STR_PLAYLIST_TRACK_NAME);
d.width = max(d.width, d2.width);
d.height += d2.height;
@ -297,10 +363,13 @@ struct MusicTrackSelectionWindow : public Window {
GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, 0);
int y = r.top + WD_FRAMERECT_TOP;
for (uint i = 1; i <= NUM_SONGS_AVAILABLE; i++) {
SetDParam(0, i);
for (uint i = 0; i < NUM_SONGS_AVAILABLE; i++) {
const char *song_name = GetSongName(i);
if (StrEmpty(song_name)) continue;
SetDParam(0, GetTrackNumber(i));
SetDParam(1, 2);
SetDParamStr(2, GetSongName(i - 1));
SetDParamStr(2, song_name);
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_PLAYLIST_TRACK_NAME);
y += FONT_HEIGHT_SMALL;
}
@ -311,10 +380,10 @@ struct MusicTrackSelectionWindow : public Window {
int y = r.top + WD_FRAMERECT_TOP;
for (const byte *p = _playlists[msf.playlist]; *p != 0; p++) {
uint i = *p;
SetDParam(0, i);
uint i = *p - 1;
SetDParam(0, GetTrackNumber(i));
SetDParam(1, 2);
SetDParamStr(2, GetSongName(i - 1));
SetDParamStr(2, GetSongName(i));
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_PLAYLIST_TRACK_NAME);
y += FONT_HEIGHT_SMALL;
}
@ -334,12 +403,18 @@ struct MusicTrackSelectionWindow : public Window {
int y = (pt.y - this->GetWidget<NWidgetBase>(widget)->pos_y) / FONT_HEIGHT_SMALL;
if (msf.playlist < 4) return;
if (!IsInsideMM(y, 0, NUM_SONGS_AVAILABLE)) return;
if (!IsInsideMM(y, 0, BaseMusic::GetUsedSet()->num_available)) return;
byte *p = _playlists[msf.playlist];
for (uint i = 0; i != NUM_SONGS_PLAYLIST - 1; i++) {
if (p[i] == 0) {
p[i] = y + 1;
/* Find the actual song number */
for (uint j = 0; j < NUM_SONGS_AVAILABLE; j++) {
if (GetTrackNumber(j) == y + 1) {
p[i] = j + 1;
break;
}
}
p[i + 1] = 0;
this->SetDirty();
SelectSongToPlay();
@ -352,7 +427,7 @@ struct MusicTrackSelectionWindow : public Window {
int y = (pt.y - this->GetWidget<NWidgetBase>(widget)->pos_y) / FONT_HEIGHT_SMALL;
if (msf.playlist < 4) return;
if (!IsInsideMM(y, 0, NUM_SONGS_AVAILABLE)) return;
if (!IsInsideMM(y, 0, NUM_SONGS_PLAYLIST)) return;
byte *p = _playlists[msf.playlist];
for (uint i = y; i != NUM_SONGS_PLAYLIST - 1; i++) {
@ -364,7 +439,7 @@ struct MusicTrackSelectionWindow : public Window {
} break;
case MTSW_CLEAR: // clear
_playlists[msf.playlist][0] = 0;
for (uint i = 0; _playlists[msf.playlist][i] != 0; i++) _playlists[msf.playlist][i] = 0;
this->SetDirty();
StopMusic();
SelectSongToPlay();
@ -484,7 +559,7 @@ struct MusicWindow : public Window {
case MW_TRACK_NAME: {
Dimension d = GetStringBoundingBox(STR_MUSIC_TITLE_NONE);
for (int i = 0; i < NUM_SONGS_AVAILABLE; i++) {
for (uint i = 0; i < NUM_SONGS_AVAILABLE; i++) {
SetDParamStr(0, GetSongName(i));
d = maxdim(d, GetStringBoundingBox(STR_MUSIC_TITLE_NAME));
}
@ -523,7 +598,7 @@ struct MusicWindow : public Window {
GfxFillRect(r.left + 1, r.top + 1, r.right, r.bottom, 0);
StringID str = STR_MUSIC_TRACK_NONE;
if (_song_is_active != 0 && _music_wnd_cursong != 0) {
SetDParam(0, _music_wnd_cursong);
SetDParam(0, GetTrackNumber(_music_wnd_cursong - 1));
SetDParam(1, 2);
str = STR_MUSIC_TRACK_DIGIT;
}
@ -727,5 +802,6 @@ static const WindowDesc _music_window_desc(
void ShowMusicWindow()
{
if (BaseMusic::GetUsedSet()->num_available == 0) ShowErrorMessage(STR_ERROR_NO_SONGS, INVALID_STRING_ID, 0, 0);
AllocateWindowDescFront<MusicWindow>(&_music_window_desc, 0);
}

@ -31,6 +31,7 @@ enum ContentType {
CONTENT_TYPE_SCENARIO = 5, ///< The content consists of a scenario
CONTENT_TYPE_HEIGHTMAP = 6, ///< The content consists of a heightmap
CONTENT_TYPE_BASE_SOUNDS = 7, ///< The content consists of base sounds
CONTENT_TYPE_BASE_MUSIC = 8, ///< The content consists of base music
CONTENT_TYPE_END, ///< Helper to mark the end of the types
};

@ -181,6 +181,7 @@ static void ShowHelp()
" specified in graphics set file (see below)\n"
" -I graphics_set = Force the graphics set (see below)\n"
" -S sounds_set = Force the sounds set (see below)\n"
" -M music_set = Force the music set (see below)\n"
" -c config_file = Use 'config_file' instead of 'openttd.cfg'\n"
" -x = Do not automatically save to config file on exit\n"
"\n",
@ -193,6 +194,9 @@ static void ShowHelp()
/* List the sounds packs */
p = BaseSounds::GetSetsList(p, lastof(buf));
/* List the music packs */
p = BaseMusic::GetSetsList(p, lastof(buf));
/* List the drivers */
p = VideoDriverFactoryBase::GetDriversInfo(p, lastof(buf));
@ -409,6 +413,7 @@ int ttd_main(int argc, char *argv[])
char *blitter = NULL;
char *graphics_set = NULL;
char *sounds_set = NULL;
char *music_set = NULL;
Dimension resolution = {0, 0};
Year startyear = INVALID_YEAR;
uint generation_seed = GENERATE_NEW_SEED;
@ -446,6 +451,7 @@ int ttd_main(int argc, char *argv[])
switch (i) {
case 'I': free(graphics_set); graphics_set = strdup(mgo.opt); break;
case 'S': free(sounds_set); sounds_set = strdup(mgo.opt); break;
case 'M': free(music_set); music_set = strdup(mgo.opt); break;
case 'm': free(musicdriver); musicdriver = strdup(mgo.opt); break;
case 's': free(sounddriver); sounddriver = strdup(mgo.opt); break;
case 'v': free(videodriver); videodriver = strdup(mgo.opt); break;
@ -536,6 +542,7 @@ int ttd_main(int argc, char *argv[])
DeterminePaths(argv[0]);
BaseGraphics::FindSets();
BaseSounds::FindSets();
BaseMusic::FindSets();
ShowHelp();
return 0;
}
@ -549,6 +556,7 @@ int ttd_main(int argc, char *argv[])
DeterminePaths(argv[0]);
BaseGraphics::FindSets();
BaseSounds::FindSets();
BaseMusic::FindSets();
#if defined(UNIX) && !defined(__MORPHOS__)
/* We must fork here, or we'll end up without some resources we need (like sockets) */
@ -620,6 +628,14 @@ int ttd_main(int argc, char *argv[])
}
free(graphics_set);
if (music_set == NULL && BaseMusic::ini_set != NULL) music_set = strdup(BaseMusic::ini_set);
if (!BaseMusic::SetSet(music_set)) {
StrEmpty(music_set) ?
usererror("Failed to find a music set. Please acquire a music set for OpenTTD. See section 4.1 of readme.txt.") :
usererror("Failed to select requested music set '%s'", music_set);
}
free(music_set);
/* Initialize game palette */
GfxInitPalettes();
@ -748,6 +764,7 @@ int ttd_main(int argc, char *argv[])
free(const_cast<char *>(BaseGraphics::ini_set));
free(const_cast<char *>(BaseSounds::ini_set));
free(const_cast<char *>(BaseMusic::ini_set));
free(_ini_musicdriver);
free(_ini_sounddriver);
free(_ini_videodriver);

@ -104,21 +104,24 @@ static int GetCurRes()
/** Widgets of the game options menu */
enum GameOptionsWidgets {
GOW_BACKGROUND, ///< Background of the window
GOW_CURRENCY_DROPDOWN, ///< Currency dropdown
GOW_DISTANCE_DROPDOWN, ///< Measuring unit dropdown
GOW_ROADSIDE_DROPDOWN, ///< Dropdown to select the road side (to set the right side ;))
GOW_TOWNNAME_DROPDOWN, ///< Town name dropdown
GOW_AUTOSAVE_DROPDOWN, ///< Dropdown to say how often to autosave
GOW_LANG_DROPDOWN, ///< Language dropdown
GOW_RESOLUTION_DROPDOWN, ///< Dropdown for the resolution
GOW_FULLSCREEN_BUTTON, ///< Toggle fullscreen
GOW_SCREENSHOT_DROPDOWN, ///< Select the screenshot type... please use PNG!
GOW_BASE_GRF_DROPDOWN, ///< Use to select a base GRF
GOW_BASE_GRF_STATUS, ///< Info about missing files etc.
GOW_BASE_GRF_DESCRIPTION,///< Description of selected base GRF
GOW_BASE_SFX_DROPDOWN, ///< Use to select a base SFX
GOW_BASE_SFX_DESCRIPTION,///< Description of selected base SFX
GOW_BACKGROUND, ///< Background of the window
GOW_CURRENCY_DROPDOWN, ///< Currency dropdown
GOW_DISTANCE_DROPDOWN, ///< Measuring unit dropdown
GOW_ROADSIDE_DROPDOWN, ///< Dropdown to select the road side (to set the right side ;))
GOW_TOWNNAME_DROPDOWN, ///< Town name dropdown
GOW_AUTOSAVE_DROPDOWN, ///< Dropdown to say how often to autosave
GOW_LANG_DROPDOWN, ///< Language dropdown
GOW_RESOLUTION_DROPDOWN, ///< Dropdown for the resolution
GOW_FULLSCREEN_BUTTON, ///< Toggle fullscreen
GOW_SCREENSHOT_DROPDOWN, ///< Select the screenshot type... please use PNG!
GOW_BASE_GRF_DROPDOWN, ///< Use to select a base GRF
GOW_BASE_GRF_STATUS, ///< Info about missing files etc.
GOW_BASE_GRF_DESCRIPTION, ///< Description of selected base GRF
GOW_BASE_SFX_DROPDOWN, ///< Use to select a base SFX
GOW_BASE_SFX_DESCRIPTION, ///< Description of selected base SFX
GOW_BASE_MUSIC_DROPDOWN, ///< Use to select a base music set
GOW_BASE_MUSIC_STATUS, ///< Info about corrupted files etc.
GOW_BASE_MUSIC_DESCRIPTION, ///< Description of selected base music set
};
/**
@ -194,6 +197,8 @@ struct GameOptionsWindow : Window {
case GOW_BASE_GRF_DROPDOWN: SetDParamStr(0, BaseGraphics::GetUsedSet()->name); break;
case GOW_BASE_GRF_STATUS: SetDParam(0, BaseGraphics::GetUsedSet()->GetNumInvalid()); break;
case GOW_BASE_SFX_DROPDOWN: SetDParamStr(0, BaseSounds::GetUsedSet()->name); break;
case GOW_BASE_MUSIC_DROPDOWN: SetDParamStr(0, BaseMusic::GetUsedSet()->name); break;
case GOW_BASE_MUSIC_STATUS: SetDParam(0, BaseMusic::GetUsedSet()->GetNumInvalid()); break;
}
}
@ -214,6 +219,11 @@ struct GameOptionsWindow : Window {
SetDParamStr(0, BaseSounds::GetUsedSet()->GetDescription(GetCurrentLanguageIsoCode()));
DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_BLACK_RAW_STRING);
break;
case GOW_BASE_MUSIC_DESCRIPTION:
SetDParamStr(0, BaseMusic::GetUsedSet()->GetDescription(GetCurrentLanguageIsoCode()));
DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_BLACK_RAW_STRING);
break;
}
}
@ -246,6 +256,25 @@ struct GameOptionsWindow : Window {
size->height = max(size->height, (uint)GetStringHeight(STR_BLACK_RAW_STRING, size->width));
}
break;
case GOW_BASE_MUSIC_DESCRIPTION:
/* Find the biggest description for the default size. */
for (int i = 0; i < BaseMusic::GetNumSets(); i++) {
SetDParamStr(0, BaseMusic::GetSet(i)->GetDescription(GetCurrentLanguageIsoCode()));
size->height = max(size->height, (uint)GetStringHeight(STR_BLACK_RAW_STRING, size->width));
}
break;
case GOW_BASE_MUSIC_STATUS:
/* Find the biggest description for the default size. */
for (int i = 0; i < BaseMusic::GetNumSets(); i++) {
uint invalid_files = BaseMusic::GetSet(i)->GetNumInvalid();
if (invalid_files == 0) continue;
SetDParam(0, invalid_files);
*size = maxdim(*size, GetStringBoundingBox(STR_GAME_OPTIONS_BASE_MUSIC_STATUS));
}
break;
}
}
@ -320,6 +349,10 @@ struct GameOptionsWindow : Window {
case GOW_BASE_SFX_DROPDOWN:
ShowSetMenu<BaseSounds>(this, GOW_BASE_SFX_DROPDOWN);
break;
case GOW_BASE_MUSIC_DROPDOWN:
ShowSetMenu<BaseMusic>(this, GOW_BASE_MUSIC_DROPDOWN);
break;
}
}
@ -403,6 +436,10 @@ struct GameOptionsWindow : Window {
case GOW_BASE_SFX_DROPDOWN:
this->SetMediaSet<BaseSounds>(index);
break;
case GOW_BASE_MUSIC_DROPDOWN:
this->SetMediaSet<BaseMusic>(index);
break;
}
}
@ -412,6 +449,9 @@ struct GameOptionsWindow : Window {
bool missing_files = BaseGraphics::GetUsedSet()->GetNumMissing() == 0;
this->GetWidget<NWidgetCore>(GOW_BASE_GRF_STATUS)->SetDataTip(missing_files ? STR_EMPTY : STR_GAME_OPTIONS_BASE_GRF_STATUS, STR_NULL);
missing_files = BaseMusic::GetUsedSet()->GetNumInvalid() == 0;
this->GetWidget<NWidgetCore>(GOW_BASE_MUSIC_STATUS)->SetDataTip(missing_files ? STR_EMPTY : STR_GAME_OPTIONS_BASE_MUSIC_STATUS, STR_NULL);
}
};
@ -459,7 +499,7 @@ static const NWidgetPart _nested_game_options_widgets[] = {
EndContainer(),
NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_GRF, STR_NULL), SetPadding(0, 10, 0, 10),
NWidget(NWID_HORIZONTAL), SetPIP(00, 30, 0),
NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
NWidget(WWT_DROPDOWN, COLOUR_GREY, GOW_BASE_GRF_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_GRF_TOOLTIP),
NWidget(WWT_TEXT, COLOUR_GREY, GOW_BASE_GRF_STATUS), SetMinimalSize(150, 12), SetDataTip(STR_EMPTY, STR_NULL), SetFill(1, 0),
EndContainer(),
@ -473,6 +513,14 @@ static const NWidgetPart _nested_game_options_widgets[] = {
EndContainer(),
NWidget(WWT_TEXT, COLOUR_GREY, GOW_BASE_SFX_DESCRIPTION), SetMinimalSize(330, 0), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_BASE_SFX_DESCRIPTION_TOOLTIP), SetFill(1, 0), SetPadding(6, 0, 0, 0),
EndContainer(),
NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_MUSIC, STR_NULL), SetPadding(0, 10, 0, 10),
NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
NWidget(WWT_DROPDOWN, COLOUR_GREY, GOW_BASE_MUSIC_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP),
NWidget(WWT_TEXT, COLOUR_GREY, GOW_BASE_MUSIC_STATUS), SetMinimalSize(150, 12), SetDataTip(STR_EMPTY, STR_NULL), SetFill(1, 0),
EndContainer(),
NWidget(WWT_TEXT, COLOUR_GREY, GOW_BASE_MUSIC_DESCRIPTION), SetMinimalSize(330, 0), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_BASE_MUSIC_DESCRIPTION_TOOLTIP), SetFill(1, 0), SetPadding(6, 0, 0, 0),
EndContainer(),
EndContainer(),
};

@ -282,8 +282,8 @@ INSTANTIATE_BASE_MEDIA_METHODS(BaseMedia<SoundsSet>, SoundsSet)
static const char * const _sound_file_names[] = { "samples" };
template <class T, size_t Tnum_files>
/* static */ const char * const *BaseSet<T, Tnum_files>::file_names = _sound_file_names;
template <class T, size_t Tnum_files, Subdirectory Tsubdir>
/* static */ const char * const *BaseSet<T, Tnum_files, Tsubdir>::file_names = _sound_file_names;
template <class Tbase_set>
/* static */ const char *BaseMedia<Tbase_set>::GetExtension()

@ -249,6 +249,7 @@ static const SettingDescGlobVarList _misc_settings[] = {
SDTG_BOOL("fullscreen", S, 0, _fullscreen, false, STR_NULL, NULL),
SDTG_STR("graphicsset", SLE_STRQ, S, 0, BaseGraphics::ini_set, NULL, STR_NULL, NULL),
SDTG_STR("soundsset", SLE_STRQ, S, 0, BaseSounds::ini_set, NULL, STR_NULL, NULL),
SDTG_STR("musicset", SLE_STRQ, S, 0, BaseMusic::ini_set, NULL, STR_NULL, NULL),
SDTG_STR("videodriver", SLE_STRQ, S, 0, _ini_videodriver, NULL, STR_NULL, NULL),
SDTG_STR("musicdriver", SLE_STRQ, S, 0, _ini_musicdriver, NULL, STR_NULL, NULL),
SDTG_STR("sounddriver", SLE_STRQ, S, 0, _ini_sounddriver, NULL, STR_NULL, NULL),

Loading…
Cancel
Save