32 size_t entry_count = ofs / 8;
33 if (entrynum >= entry_count)
return std::nullopt;
35 file.
SeekTo(entrynum * 8, SEEK_SET);
39 std::string name(namelen,
'\0');
56 size_t entry_count = ofs / 8;
57 if (entrynum >= entry_count)
return std::nullopt;
59 file.
SeekTo(entrynum * 8, SEEK_SET);
62 file.
SeekTo(entrypos, SEEK_SET);
65 std::vector<uint8_t> data(entrylen);
73 "old_0",
"old_1",
"old_2",
"old_3",
"old_4",
"old_5",
"old_6",
"old_7",
"old_8",
"old_9",
74 "new_0",
"new_1",
"new_2",
"new_3",
"new_4",
"new_5",
"new_6",
"new_7",
"new_8",
"new_9",
75 "ezy_0",
"ezy_1",
"ezy_2",
"ezy_3",
"ezy_4",
"ezy_5",
"ezy_6",
"ezy_7",
"ezy_8",
"ezy_9",
99 if (c->GetNumMissing() != 0)
continue;
101 if (best ==
nullptr ||
116bool MusicSet::FillSetDetails(
const IniFile &ini,
const std::string &path,
const std::string &full_filename)
121 const IniGroup *names = ini.
GetGroup(
"names");
122 const IniGroup *catindex = ini.
GetGroup(
"catindex");
123 const IniGroup *timingtrim = ini.
GetGroup(
"timingtrim");
126 const std::string &filename = this->
files[i].filename;
131 this->
songinfo[i].filename = filename;
134 if (item !=
nullptr && item->
value.has_value() && !item->
value->empty()) {
138 if (!value.has_value()) {
139 Debug(grf, 0,
"Invalid base music set song index: {}/{}", filename, *item->
value);
142 this->
songinfo[i].cat_index = *value;
144 if (!songname.has_value()) {
145 Debug(grf, 0,
"Base music set song missing from CAT file: {}/{}", filename, this->
songinfo[i].cat_index);
148 this->
songinfo[i].songname = *songname;
153 std::string_view trimmed_filename{filename};
157 while (!trimmed_filename.empty()) {
160 while (trimmed_filename.starts_with(PATHSEPCHAR)) trimmed_filename.remove_prefix(1);
162 item = names !=
nullptr ? names->
GetItem(trimmed_filename) :
nullptr;
163 if (item !=
nullptr && item->
value.has_value() && !item->
value->empty())
break;
165 auto next = trimmed_filename.find(PATHSEPCHAR);
166 if (next == std::string_view::npos) {
167 trimmed_filename = {};
169 trimmed_filename.remove_prefix(next);
174 if (item !=
nullptr && item->
value.has_value() && !item->
value->empty()) {
177 Debug(grf, 0,
"Base music set song name missing: {}", filename);
187 this->
songinfo[i].tracknr = tracknr++;
190 item = !trimmed_filename.empty() && timingtrim !=
nullptr ? timingtrim->
GetItem(trimmed_filename) :
nullptr;
191 if (item !=
nullptr && item->
value.has_value() && !item->
value->empty()) {
192 StringConsumer consumer{*item->
value};
194 auto valid = consumer.
ReadIf(
":");
196 if (start.has_value() && valid && end.has_value() && !consumer.
AnyBytesLeft()) {
197 this->
songinfo[i].override_start = *start;
198 this->
songinfo[i].override_end = *end;
A file from which bytes, words and double words are read in (potentially) a random order.
void ReadBlock(void *ptr, size_t size)
Read a block.
void SeekTo(size_t pos, int mode)
Seek in the current file.
uint8_t ReadByte()
Read a byte from the file.
uint32_t ReadDword()
Read a double word (32 bits) from the file (in low endian format).
void SkipBytes(size_t n)
Skip n bytes ahead in the file.
std::optional< T > TryReadIntegerBase(int base, bool clamp=false)
Try to read and parse an integer in number 'base', and then advance the reader.
bool AnyBytesLeft() const noexcept
Check whether any bytes left to read.
bool ReadIf(std::string_view str)
Check whether the next data matches 'str', and skip it.
#define Debug(category, level, format_string,...)
Output a line of debugging information.
bool FioCheckFileExists(std::string_view filename, Subdirectory subdir)
Check whether the given file exists.
@ BASESET_DIR
Subdirectory for all base data (base sets, intro game).
std::optional< std::string > GetMusicCatEntryName(const std::string &filename, size_t entrynum)
Read the name of a music CAT file entry.
static const std::string_view _music_file_names[]
Names corresponding to the music set's files.
std::optional< std::vector< uint8_t > > GetMusicCatEntryData(const std::string &filename, size_t entrynum)
Read the full data of a music CAT file entry.
Class related to random access to files.
A number of safeguards to prevent using unsafe methods.
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
static void StrMakeValid(Builder &builder, StringConsumer &consumer, StringValidationSettings settings)
Copies the valid (UTF-8) characters from consumer to the builder.
static std::optional< T > ParseInteger(std::string_view arg, int base=10, bool clamp=false)
Change a string into its number representation.
Functions related to low-level strings.
std::array< MD5File, BaseSet< MusicSet >::NUM_FILES > files
uint valid_files
Number of the files that could be found and are valid.
static std::span< const std::string_view > GetFilenames()
Get the internal names of the files in this set.
bool fallback
This set is a fallback set, i.e. it should be used only as last resort.
bool FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename, bool allow_empty_filename=true)
Read the set information from a loaded ini.
std::vector< uint32_t > version
The version of this base set.
uint32_t shortname
Four letter short variant of the name.
Ini file that supports both loading and saving.
const IniItem * GetItem(std::string_view name) const
Get the item with the given name.
std::optional< std::string > value
The value of this item.
const IniGroup * GetGroup(std::string_view name) const
Get the group with the given name.
@ CR_NO_FILE
The file did not exist.
MusicSongInfo songinfo[NUM_SONGS_AVAILABLE]
Data about individual songs in set.
uint8_t num_available
Number of valid songs in set.