2012-11-15 00:39:56 +01:00
|
|
|
#pragma once
|
|
|
|
|
|
2020-12-22 09:42:57 +01:00
|
|
|
#include "util/types.hpp"
|
2016-02-01 22:47:09 +01:00
|
|
|
#include <map>
|
2020-12-22 09:42:57 +01:00
|
|
|
#include <string>
|
2020-08-22 00:55:17 +02:00
|
|
|
#include <string_view>
|
2016-02-01 22:47:09 +01:00
|
|
|
|
2020-12-22 09:42:57 +01:00
|
|
|
namespace fs
|
|
|
|
|
{
|
|
|
|
|
class file;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-07 23:12:33 +01:00
|
|
|
namespace psf
|
2016-01-07 20:22:36 +01:00
|
|
|
{
|
2022-06-01 20:19:45 +02:00
|
|
|
enum sound_format_flag : s32
|
|
|
|
|
{
|
|
|
|
|
lpcm_2 = 1 << 0, // Linear PCM 2 Ch.
|
|
|
|
|
lpcm_5_1 = 1 << 2, // Linear PCM 5.1 Ch.
|
|
|
|
|
lpcm_7_1 = 1 << 4, // Linear PCM 7.1 Ch.
|
|
|
|
|
ac3 = 1 << 8, // Dolby Digital 5.1 Ch.
|
|
|
|
|
dts = 1 << 9, // DTS 5.1 Ch.
|
|
|
|
|
};
|
|
|
|
|
|
2022-06-01 20:20:08 +02:00
|
|
|
enum resolution_flag : s32
|
|
|
|
|
{
|
|
|
|
|
_480p = 1 << 0,
|
|
|
|
|
_576p = 1 << 1,
|
|
|
|
|
_720p = 1 << 2,
|
|
|
|
|
_1080p = 1 << 3,
|
|
|
|
|
_480p_16_9 = 1 << 4,
|
|
|
|
|
_576p_16_9 = 1 << 5,
|
|
|
|
|
};
|
|
|
|
|
|
2016-01-26 19:13:36 +01:00
|
|
|
enum class format : u16
|
2015-04-16 01:17:42 +02:00
|
|
|
{
|
2016-01-26 19:13:36 +01:00
|
|
|
array = 0x0004, // claimed to be a non-NTS string (char array)
|
|
|
|
|
string = 0x0204,
|
2016-01-07 23:12:33 +01:00
|
|
|
integer = 0x0404,
|
|
|
|
|
};
|
2015-04-16 01:17:42 +02:00
|
|
|
|
2021-03-30 23:44:58 +02:00
|
|
|
enum class error
|
|
|
|
|
{
|
|
|
|
|
ok,
|
|
|
|
|
stream,
|
|
|
|
|
not_psf,
|
|
|
|
|
corrupt,
|
|
|
|
|
};
|
|
|
|
|
|
2016-01-26 19:13:36 +01:00
|
|
|
class entry final
|
2016-01-07 20:22:36 +01:00
|
|
|
{
|
2021-04-03 18:38:02 +02:00
|
|
|
format m_type{};
|
|
|
|
|
u32 m_max_size{}; // Entry max size (supplementary info, stored in PSF format)
|
|
|
|
|
u32 m_value_integer{}; // TODO: is it really unsigned?
|
|
|
|
|
std::string m_value_string{};
|
2016-01-07 23:12:33 +01:00
|
|
|
|
|
|
|
|
public:
|
2016-01-26 19:13:36 +01:00
|
|
|
// Construct string entry, assign the value
|
2023-02-04 10:46:34 +01:00
|
|
|
entry(format type, u32 max_size, std::string_view value, bool allow_truncate = false) noexcept;
|
2016-01-07 23:12:33 +01:00
|
|
|
|
2016-01-26 19:13:36 +01:00
|
|
|
// Construct integer entry, assign the value
|
2023-02-04 10:46:34 +01:00
|
|
|
entry(u32 value) noexcept;
|
2016-05-13 16:01:48 +02:00
|
|
|
|
2022-04-09 12:13:08 +02:00
|
|
|
~entry() = default;
|
2016-01-07 23:12:33 +01:00
|
|
|
|
2016-01-26 19:13:36 +01:00
|
|
|
const std::string& as_string() const;
|
|
|
|
|
u32 as_integer() const;
|
2016-01-07 23:12:33 +01:00
|
|
|
|
2021-03-31 07:20:38 +02:00
|
|
|
entry& operator =(std::string_view value);
|
2016-01-26 19:13:36 +01:00
|
|
|
entry& operator =(u32 value);
|
2016-01-08 00:07:55 +01:00
|
|
|
|
2016-01-26 19:13:36 +01:00
|
|
|
format type() const { return m_type; }
|
2023-02-04 10:46:34 +01:00
|
|
|
u32 max(bool with_nts) const { return m_max_size - (!with_nts && m_type == format::string ? 1 : 0); }
|
2016-01-26 19:13:36 +01:00
|
|
|
u32 size() const;
|
2023-02-04 10:46:34 +01:00
|
|
|
bool is_valid() const;
|
2016-01-26 19:13:36 +01:00
|
|
|
};
|
2016-01-08 00:53:03 +01:00
|
|
|
|
2016-01-26 19:13:36 +01:00
|
|
|
// Define PSF registry as a sorted map of entries:
|
2022-04-09 12:13:08 +02:00
|
|
|
using registry = std::map<std::string, entry, std::less<>>;
|
2016-01-07 23:12:33 +01:00
|
|
|
|
2021-03-30 23:44:58 +02:00
|
|
|
struct load_result_t
|
|
|
|
|
{
|
|
|
|
|
registry sfo;
|
|
|
|
|
error errc;
|
|
|
|
|
|
|
|
|
|
explicit operator bool() const
|
|
|
|
|
{
|
|
|
|
|
return !sfo.empty();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2016-05-13 16:01:48 +02:00
|
|
|
// Load PSF registry from SFO binary format
|
2022-11-27 08:59:57 +01:00
|
|
|
load_result_t load(const fs::file&, std::string_view filename);
|
2021-03-30 23:44:58 +02:00
|
|
|
load_result_t load(const std::string& filename);
|
2022-11-27 08:59:57 +01:00
|
|
|
inline registry load_object(const fs::file& f, std::string_view filename) { return load(f, filename).sfo; }
|
|
|
|
|
inline registry load_object(const std::string& filename) { return load(filename).sfo; }
|
2016-01-07 23:12:33 +01:00
|
|
|
|
2016-02-01 22:47:09 +01:00
|
|
|
// Convert PSF registry to SFO binary format
|
2021-02-21 20:55:07 +01:00
|
|
|
std::vector<u8> save_object(const registry&, std::vector<u8>&& init = std::vector<u8>{});
|
2016-01-07 23:12:33 +01:00
|
|
|
|
2016-01-26 19:13:36 +01:00
|
|
|
// Get string value or default value
|
2022-04-09 12:13:08 +02:00
|
|
|
std::string_view get_string(const registry& psf, std::string_view key, std::string_view def = ""sv);
|
2016-01-07 23:12:33 +01:00
|
|
|
|
2016-01-26 19:13:36 +01:00
|
|
|
// Get integer value or default value
|
2022-04-09 12:13:08 +02:00
|
|
|
u32 get_integer(const registry& psf, std::string_view key, u32 def = 0);
|
2016-01-07 23:12:33 +01:00
|
|
|
|
2023-02-04 10:46:34 +01:00
|
|
|
bool check_registry(const registry& psf, std::function<bool(bool ok, const std::string& key, const entry& value)> validate = {},
|
|
|
|
|
u32 line = __builtin_LINE(),
|
|
|
|
|
u32 col = __builtin_COLUMN(),
|
|
|
|
|
const char* file = __builtin_FILE(),
|
|
|
|
|
const char* func = __builtin_FUNCTION());
|
|
|
|
|
|
2017-12-29 00:54:12 +01:00
|
|
|
// Assign new entry
|
2022-04-09 12:13:08 +02:00
|
|
|
inline void assign(registry& psf, std::string_view key, entry&& _entry)
|
2017-12-29 00:54:12 +01:00
|
|
|
{
|
|
|
|
|
const auto found = psf.find(key);
|
|
|
|
|
|
|
|
|
|
if (found == psf.end())
|
|
|
|
|
{
|
|
|
|
|
psf.emplace(key, std::move(_entry));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
found->second = std::move(_entry);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-26 19:13:36 +01:00
|
|
|
// Make string entry
|
2023-02-04 10:46:34 +01:00
|
|
|
inline entry string(u32 max_size, std::string_view value, bool allow_truncate = false)
|
|
|
|
|
{
|
|
|
|
|
return {format::string, max_size, value, allow_truncate};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Make string entry (from char[N])
|
|
|
|
|
template <usz CharN>
|
|
|
|
|
inline entry string(u32 max_size, char (&value_array)[CharN], bool allow_truncate = false)
|
2016-01-26 19:13:36 +01:00
|
|
|
{
|
2023-02-04 10:46:34 +01:00
|
|
|
std::string_view value{value_array, CharN};
|
|
|
|
|
value = value.substr(0, std::min<usz>(value.find_first_of('\0'), value.size()));
|
2023-03-11 20:08:27 +01:00
|
|
|
return string(max_size, value, allow_truncate);
|
2016-01-26 19:13:36 +01:00
|
|
|
}
|
2016-01-07 23:12:33 +01:00
|
|
|
|
2016-01-26 19:13:36 +01:00
|
|
|
// Make array entry
|
2020-08-22 00:55:17 +02:00
|
|
|
inline entry array(u32 max_size, std::string_view value)
|
2016-01-26 19:13:36 +01:00
|
|
|
{
|
2021-03-31 07:20:38 +02:00
|
|
|
return {format::array, max_size, value};
|
2016-01-26 19:13:36 +01:00
|
|
|
}
|
2022-04-09 12:13:08 +02:00
|
|
|
|
|
|
|
|
// Checks if of HDD catgeory (assumes a valid category is being passed)
|
|
|
|
|
constexpr bool is_cat_hdd(std::string_view cat)
|
|
|
|
|
{
|
|
|
|
|
return cat.size() == 2u && cat[1] != 'D' && cat != "DG"sv && cat != "MS"sv;
|
|
|
|
|
}
|
2016-01-07 23:12:33 +01:00
|
|
|
}
|