Merge pull request #277 from Laupetin/refactor/sound-bank-loading-dumping

refactor: sound bank loading dumping
This commit is contained in:
Jan 2024-10-06 19:34:26 +02:00 committed by GitHub
commit 1fc31b8c44
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 1671 additions and 919 deletions

View File

@ -6228,9 +6228,9 @@ namespace T6
unsigned int distanceLpf : 1; // 2
unsigned int doppler : 1; // 3
unsigned int isBig : 1; // 4
unsigned int pauseable : 1; // 5
unsigned int pausable : 1; // 5
unsigned int isMusic : 1; // 6
unsigned int stopOnDeath : 1; // 7
unsigned int stopOnEntDeath : 1; // 7
unsigned int timescale : 1; // 8
unsigned int voiceLimit : 1; // 9
unsigned int ignoreMaxDist : 1; // 10
@ -6249,7 +6249,9 @@ namespace T6
unsigned int reverbFalloffCurve : 6; // 8-13
unsigned int volumeMinFalloffCurve : 6; // 14-19
unsigned int reverbMinFalloffCurve : 6; // 20-25
unsigned int unknown1_1 : 6; // 26-31
unsigned int unknown1_1 : 1; // 26
unsigned int isCinematic : 1; // 27
unsigned int unknown1_2 : 4; // 28-31
};
struct SndAlias
@ -6257,7 +6259,7 @@ namespace T6
const char* name;
unsigned int id;
const char* subtitle;
const char* secondaryname;
const char* secondaryName;
unsigned int assetId;
const char* assetFileName;
SndAliasFlags flags;

View File

@ -0,0 +1,34 @@
#include "Csv/CsvHeaderRow.h"
CsvHeaderRow::CsvHeaderRow() = default;
bool CsvHeaderRow::Read(const CsvInputStream& inputStream)
{
if (!m_header_row.empty())
return false;
return inputStream.NextRow(m_header_row);
}
const std::string& CsvHeaderRow::HeaderNameForColumn(const unsigned columnIndex) const
{
return m_header_row[columnIndex];
}
bool CsvHeaderRow::RequireIndexForHeader(const std::string& headerName, unsigned& out) const
{
const auto existingHeader = std::ranges::find(m_header_row, headerName);
if (existingHeader == m_header_row.end())
return false;
out = std::distance(m_header_row.begin(), existingHeader);
return true;
}
std::optional<unsigned> CsvHeaderRow::GetIndexForHeader(const std::string& headerName) const
{
unsigned result;
if (!RequireIndexForHeader(headerName, result))
return std::nullopt;
return result;
}

View File

@ -0,0 +1,22 @@
#pragma once
#include "Csv/CsvStream.h"
#include <optional>
#include <string>
#include <vector>
class CsvHeaderRow
{
public:
CsvHeaderRow();
bool Read(const CsvInputStream& inputStream);
const std::string& HeaderNameForColumn(unsigned columnIndex) const;
bool RequireIndexForHeader(const std::string& headerName, unsigned& out) const;
[[nodiscard]] std::optional<unsigned> GetIndexForHeader(const std::string& headerName) const;
private:
std::vector<std::string> m_header_row;
};

View File

@ -1,14 +1,88 @@
#include "CsvStream.h"
#include "Utils/StringUtils.h"
#include <cstdlib>
#include <sstream>
constexpr char CSV_SEPARATOR = ',';
CsvCell::CsvCell(std::string value)
: m_value(std::move(value))
{
}
bool CsvCell::AsFloat(float& out) const
{
const char* startPtr = m_value.c_str();
char* endPtr;
out = std::strtof(startPtr, &endPtr);
if (endPtr == startPtr)
return false;
for (const auto* c = endPtr; *c; c++)
{
if (!isspace(*c))
return false;
}
return true;
}
bool CsvCell::AsInt32(int32_t& out) const
{
const char* startPtr = m_value.c_str();
char* endPtr;
out = std::strtol(startPtr, &endPtr, 0);
if (endPtr == startPtr)
return false;
for (const auto* c = endPtr; *c; c++)
{
if (!isspace(*c))
return false;
}
return true;
}
bool CsvCell::AsUInt32(uint32_t& out) const
{
const char* startPtr = m_value.c_str();
char* endPtr;
out = std::strtoul(startPtr, &endPtr, 0);
if (endPtr == startPtr)
return false;
for (const auto* c = endPtr; *c; c++)
{
if (!isspace(*c))
return false;
}
return true;
}
CsvInputStream::CsvInputStream(std::istream& stream)
: m_stream(stream)
{
}
bool CsvInputStream::NextRow(std::vector<CsvCell>& out) const
{
if (!out.empty())
out.clear();
return EmitNextRow(
[&out](std::string value)
{
out.emplace_back(std::move(value));
});
}
bool CsvInputStream::NextRow(std::vector<std::string>& out) const
{
if (!out.empty())
@ -38,13 +112,17 @@ bool CsvInputStream::EmitNextRow(const std::function<void(std::string)>& cb) con
auto c = m_stream.get();
const auto isEof = c == EOF;
std::ostringstream col;
auto content = false;
while (c != EOF)
{
if (c == CSV_SEPARATOR)
{
cb(col.str());
auto value = col.str();
utils::StringTrimR(value);
cb(std::move(value));
col.clear();
col.str(std::string());
content = false;
}
else if (c == '\r')
{
@ -57,8 +135,14 @@ bool CsvInputStream::EmitNextRow(const std::function<void(std::string)>& cb) con
{
break;
}
else if (isspace(c))
{
if (content)
col << static_cast<char>(c);
}
else
{
content = true;
col << static_cast<char>(c);
}
@ -67,7 +151,9 @@ bool CsvInputStream::EmitNextRow(const std::function<void(std::string)>& cb) con
if (!isEof)
{
cb(col.str());
auto value = col.str();
utils::StringTrimR(value);
cb(std::move(value));
}
return !isEof;

View File

@ -1,16 +1,30 @@
#pragma once
#include "Utils/MemoryManager.h"
#include <cstdint>
#include <functional>
#include <iostream>
#include <string>
#include <vector>
class CsvCell
{
public:
explicit CsvCell(std::string value);
bool AsFloat(float& out) const;
bool AsInt32(int32_t& out) const;
bool AsUInt32(uint32_t& out) const;
std::string m_value;
};
class CsvInputStream
{
public:
explicit CsvInputStream(std::istream& stream);
bool NextRow(std::vector<CsvCell>& out) const;
bool NextRow(std::vector<std::string>& out) const;
bool NextRow(std::vector<const char*>& out, MemoryManager& memory) const;

View File

@ -1,80 +0,0 @@
#include "Csv/ParsedCsv.h"
ParsedCsvRow::ParsedCsvRow(std::unordered_map<std::string, size_t>& headers, std::vector<std::string> row)
: headers(headers),
values(std::move(row))
{
}
std::string ParsedCsvRow::GetValue(const std::string& header, const bool required) const
{
if (this->headers.find(header) == this->headers.end())
{
if (required)
std::cerr << "ERROR: Required column \"" << header << "\" was not found\n";
else
std::cerr << "WARNING: Expected column \"" << header << "\" was not found\n";
return {};
}
auto& value = this->values.at(this->headers[header]);
if (required && value.empty())
{
std::cerr << "ERROR: Required column \"" << header << "\" does not have a value\n";
return {};
}
return value;
}
float ParsedCsvRow::GetValueFloat(const std::string& header, const bool required) const
{
const auto& value = this->GetValue(header, required);
if (!value.empty())
{
std::istringstream ss(value);
float out;
ss >> out;
return out;
}
return {};
}
ParsedCsv::ParsedCsv(const CsvInputStream& inputStream, const bool hasHeaders)
{
std::vector<std::vector<std::string>> csvLines;
std::vector<std::string> currentLine;
while (inputStream.NextRow(currentLine))
{
csvLines.emplace_back(std::move(currentLine));
currentLine = std::vector<std::string>();
}
if (hasHeaders)
{
const auto& headersRow = csvLines[0];
for (auto i = 0u; i < headersRow.size(); i++)
{
this->headers[headersRow[i]] = i;
}
}
for (auto i = hasHeaders ? 1u : 0u; i < csvLines.size(); i++)
{
auto& rowValues = csvLines[i];
this->rows.emplace_back(this->headers, std::move(rowValues));
}
}
size_t ParsedCsv::Size() const
{
return this->rows.size();
}
ParsedCsvRow ParsedCsv::operator[](const size_t index) const
{
return this->rows.at(index);
}

View File

@ -1,45 +0,0 @@
#pragma once
#include "Csv/CsvStream.h"
#include "Utils/ClassUtils.h"
#include <sstream>
#include <unordered_map>
class ParsedCsvRow
{
std::unordered_map<std::string, size_t>& headers;
std::vector<std::string> values;
public:
explicit ParsedCsvRow(std::unordered_map<std::string, size_t>& headers, std::vector<std::string> row);
_NODISCARD std::string GetValue(const std::string& header, bool required = false) const;
_NODISCARD float GetValueFloat(const std::string& header, bool required = false) const;
template<typename T> T GetValueInt(const std::string& header, const bool required = false) const
{
const auto& value = this->GetValue(header, required);
if (!value.empty())
{
std::istringstream ss(value);
long long out;
ss >> out;
return static_cast<T>(out);
}
return {};
}
};
class ParsedCsv
{
std::unordered_map<std::string, size_t> headers;
std::vector<ParsedCsvRow> rows;
public:
explicit ParsedCsv(const CsvInputStream& inputStream, bool hasHeaders = true);
_NODISCARD size_t Size() const;
ParsedCsvRow operator[](size_t index) const;
};

View File

@ -95,6 +95,43 @@ namespace T6
"snp_x3",
};
// From SndDriverGlobals
inline constexpr const char* SOUND_PANS[]{
"default",
"music",
"wpn_all",
"wpn_fnt",
"wpn_rear",
"wpn_left",
"wpn_right",
"music_all",
"fly_foot_all",
"front",
"back",
"front_mostly",
"back_mostly",
"all",
"center",
"front_and_center",
"lfe",
"quad",
"front_mostly_some_center",
"front_halfback",
"halffront_back",
"test",
"brass_right",
"brass_left",
"veh_back",
"tst_left",
"tst_center",
"tst_right",
"tst_surround_left",
"tst_surround_right",
"tst_lfe",
"pip",
"movie_vo",
};
inline constexpr const char* SOUND_LIMIT_TYPES[]{
"none",
"oldest",
@ -138,9 +175,23 @@ namespace T6
// From executable
inline constexpr const char* SOUND_RANDOMIZE_TYPES[]{
"",
"volume",
"pitch",
"variant",
};
inline constexpr const char* SOUND_NO_YES[]{
"no",
"yes",
};
inline constexpr const char* SOUND_LOOP_TYPES[]{
"nonlooping",
"looping",
};
inline constexpr const char* SOUND_PAN_TYPES[]{
"2d",
"3d",
};
} // namespace T6

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
#include "StringUtils.h"
#include <iostream>
#include <algorithm>
#include <cctype>
#include <sstream>
namespace utils
@ -102,13 +103,41 @@ namespace utils
c = static_cast<char>(toupper(static_cast<unsigned char>(c)));
}
std::vector<std::string> StringSplit(const std::string& str, const char delim)
void StringTrimL(std::string& str)
{
str.erase(str.begin(),
std::ranges::find_if(str,
[](const unsigned char ch)
{
return !std::isspace(ch);
}));
}
void StringTrimR(std::string& str)
{
str.erase(std::find_if(str.rbegin(),
str.rend(),
[](const unsigned char ch)
{
return !std::isspace(ch);
})
.base(),
str.end());
}
void StringTrim(std::string& str)
{
StringTrimR(str);
StringTrimL(str);
}
std::vector<std::string> StringSplit(const std::string& str, const char delimiter)
{
std::vector<std::string> strings;
std::istringstream stream(str);
std::string s;
while (std::getline(stream, s, delim))
while (std::getline(stream, s, delimiter))
{
strings.emplace_back(std::move(s));
}

View File

@ -16,5 +16,9 @@ namespace utils
void MakeStringLowerCase(std::string& str);
void MakeStringUpperCase(std::string& str);
std::vector<std::string> StringSplit(const std::string& str, const char delim);
void StringTrimL(std::string& str);
void StringTrimR(std::string& str);
void StringTrim(std::string& str);
std::vector<std::string> StringSplit(const std::string& str, char delimiter);
} // namespace utils

View File

@ -21,7 +21,7 @@ set count head count;
use SndAlias;
set string name;
set string subtitle;
set string secondaryname;
set string secondaryName;
set string assetFileName;
// SndDuck