diff --git a/py/py_byml.cpp b/py/py_byml.cpp index 488d227..8035321 100644 --- a/py/py_byml.cpp +++ b/py/py_byml.cpp @@ -118,14 +118,14 @@ void BindByml(py::module& parent) { BindMap(m, "Hash32"); BindMap(m, "Hash64"); - py::class_ clas(m, "File"); + py::class_ clas(m, "BinaryWithAlignment"); clas .def(py::init<>()) .def(py::init, U32>()) .def(py::self == py::self) - .def_readwrite("data", &Byml::File::data) - .def_readwrite("alignment", &Byml::File::align) - .def("__copy__", [](const Byml::File& f) { return Byml::File(f); }) - .def("__deepcopy__", [](const Byml::File& f, py::dict) { return Byml::File(f); }); + .def_readwrite("data", &Byml::BinaryWithAlignment::data) + .def_readwrite("alignment", &Byml::BinaryWithAlignment::align) + .def("__copy__", [](const Byml::BinaryWithAlignment& f) { return Byml::BinaryWithAlignment(f); }) + .def("__deepcopy__", [](const Byml::BinaryWithAlignment& f, py::dict) { return Byml::BinaryWithAlignment(f); }); } } // namespace oead::bind diff --git a/readme.rst b/readme.rst index e1fe62b..95c30ac 100644 --- a/readme.rst +++ b/readme.rst @@ -12,7 +12,7 @@ Features Currently, oead only handles very common formats that are extensively used in recent games such as *Breath of the Wild* and *Super Mario Odyssey*. * `AAMP `_ (binary parameter archive): Only version 2 is supported. -* `BYML `_ (binary YAML): Versions 1-4 are fully supported, version 5-10 have partial support. +* `BYML `_ (binary YAL): Versions 1-10 are supported (only 32-bit and 64-bit hash nodes), remapped container nodes, monotyped arrays, and non-container root nodes are not supported. * `SARC `_ (archive) * `Yaz0 `_ (compression algorithm) diff --git a/src/byml.cpp b/src/byml.cpp index 34ba44e..3181e9e 100644 --- a/src/byml.cpp +++ b/src/byml.cpp @@ -60,7 +60,7 @@ enum class NodeType : u8 { // 0x30 to 0x3f are also hash nodes but with index remapping (unsupported) String = 0xa0, Binary = 0xa1, - File = 0xa2, + BinaryWithAlignment = 0xa2, Array = 0xc0, Dictionary = 0xc1, StringTable = 0xc2, @@ -81,7 +81,7 @@ enum class NodeType : u8 { constexpr NodeType GetNodeType(Byml::Type type) { constexpr std::array map{ NodeType::Null, NodeType::Hash32, NodeType::Hash64, NodeType::String, NodeType::Binary, - NodeType::File, NodeType::Array, NodeType::Dictionary, NodeType::Bool, NodeType::Int, + NodeType::BinaryWithAlignment, NodeType::Array, NodeType::Dictionary, NodeType::Bool, NodeType::Int, NodeType::Float, NodeType::UInt, NodeType::Int64, NodeType::UInt64, NodeType::Double, }; return map[u8(type)]; @@ -99,7 +99,7 @@ constexpr bool IsLongType(T type) { template constexpr bool IsNonInlineType(T type) { - return IsContainerType(type) || IsLongType(type) || type == T::Binary || type == T::File; + return IsContainerType(type) || IsLongType(type) || type == T::Binary || type == T::BinaryWithAlignment; } constexpr bool IsValidVersion(int version) { @@ -211,11 +211,11 @@ class Parser { return Byml{std::vector(m_reader.span().begin() + data_offset + 4, m_reader.span().begin() + data_offset + 4 + size)}; } - case NodeType::File: { + case NodeType::BinaryWithAlignment: { const u32 data_offset = *raw; const u32 size = m_reader.Read(data_offset).value(); const u32 align = m_reader.Read().value(); - return Byml{Byml::File{{m_reader.span().begin() + data_offset + 8, + return Byml{Byml::BinaryWithAlignment{{m_reader.span().begin() + data_offset + 8, m_reader.span().begin() + data_offset + 8 + size}, align}}; } case NodeType::Bool: @@ -250,8 +250,8 @@ class Parser { const u32 types_offset = offset + 4 + 8 * size; for (u32 i = 0; i< size; ++i) { const auto type = m_reader.Read(types_offset + i); - const auto hash = m_reader.Read(offset + 4 + 8 * i); - result.emplace(*hash, ParseContainerChildNode(offset + 8 + 8 * i, type.value())); + const auto hash = m_reader.Read(offset + 4 + 8 * i).value(); + result.emplace(hash, ParseContainerChildNode(offset + 8 + 8 * i, type.value())); } return Byml{std::move(result)}; } @@ -377,11 +377,11 @@ struct WriteContext { writer.Write(static_cast(data.GetBinary().size())); writer.WriteBytes(data.GetBinary()); return; - case Byml::Type::File: - writer.Seek(util::AlignUp(data.GetFile().align, writer.Tell() + 8) - 8); - writer.Write(static_cast(data.GetFile().data.size())); - writer.Write(data.GetFile().align); - writer.WriteBytes(data.GetFile().data); + case Byml::Type::BinaryWithAlignment: + writer.Seek(util::AlignUp(data.GetBinaryWithAlignment().align, writer.Tell() + 8) - 8); + writer.Write(static_cast(data.GetBinaryWithAlignment().data.size())); + writer.Write(data.GetBinaryWithAlignment().align); + writer.WriteBytes(data.GetBinaryWithAlignment().data); return; case Byml::Type::Bool: return writer.Write(data.GetBool()); @@ -485,8 +485,8 @@ struct WriteContext { if (IsContainerType(type)) { writer.AlignUp(4); // unsure if necessary but a lot of other tools will break from unaligned reads so compatiblity I guess } - const size_t offset = type != Byml::Type::File ? writer.Tell() - : util::AlignUp(node.data->GetFile().align, writer.Tell() + 8) - 8; + const size_t offset = type != Byml::Type::BinaryWithAlignment ? writer.Tell() + : util::AlignUp(node.data->GetBinaryWithAlignment().align, writer.Tell() + 8) - 8; writer.RunAt(node.offset_in_container, [&](size_t) { writer.Write(offset); }); non_inline_node_data.emplace(*node.data, offset); if (IsContainerType(type)) @@ -604,8 +604,8 @@ std::vector& Byml::GetBinary() { return Get(); } -Byml::File& Byml::GetFile() { - return Get(); +Byml::BinaryWithAlignment& Byml::GetBinaryWithAlignment() { + return Get(); } const Byml::Hash32& Byml::GetHash32() const { @@ -632,8 +632,8 @@ const std::vector& Byml::GetBinary() const { return Get(); } -const Byml::File& Byml::GetFile() const { - return Get(); +const Byml::BinaryWithAlignment& Byml::GetBinaryWithAlignment() const { + return Get(); } bool Byml::GetBool() const { diff --git a/src/byml_text.cpp b/src/byml_text.cpp index f03b682..55aa1ed 100644 --- a/src/byml_text.cpp +++ b/src/byml_text.cpp @@ -123,7 +123,7 @@ Byml ParseYamlNode(const c4::yml::NodeRef& node) { } else if (yml::RymlGetValTag(node) == "!h32") { auto hash = Byml::Hash32{}; for (const auto& child : node) { - u32 key = std::stoul(child.key().data(), nullptr, 16); + u32 key = std::stoul(std::string(child.key().data(), child.key().size()), nullptr, 16); Byml value = ParseYamlNode(child); hash.emplace(key, std::move(value)); } @@ -131,7 +131,7 @@ Byml ParseYamlNode(const c4::yml::NodeRef& node) { } else if (yml::RymlGetValTag(node) == "!h64") { auto hash = Byml::Hash64{}; for (const auto& child : node) { - u64 key = std::stoull(child.key().data(), nullptr, 16); + u64 key = std::stoull(std::string(child.key().data(), child.key().size()), nullptr, 16); Byml value = ParseYamlNode(child); hash.emplace(key, std::move(value)); } @@ -139,7 +139,7 @@ Byml ParseYamlNode(const c4::yml::NodeRef& node) { } else if (yml::RymlGetValTag(node) == "!file") { const auto& align = node["Alignment"]; const auto& data = node["Data"]; - return Byml::File{ + return Byml::BinaryWithAlignment{ byml::ScalarToValue(yml::RymlGetValTag(data), yml::ParseScalar(data, byml::RecognizeTag)).GetBinary(), byml::ScalarToValue(yml::RymlGetValTag(align), @@ -181,13 +181,13 @@ std::string Byml::ToText() const { [&](const String& v) { emitter.EmitString(v); }, [&](const std::vector& v) { const std::string encoded = - absl::Base64Escape(absl::string_view((const char*)v.data(), v.size())); + absl::Base64Escape(absl::string_view(reinterpret_cast(v.data()), v.size())); emitter.EmitString(encoded, "tag:yaml.org,2002:binary"); }, - [&](const File& v) { + [&](const BinaryWithAlignment& v) { yml::LibyamlEmitter::MappingScope scope{emitter, "!file", YAML_BLOCK_MAPPING_STYLE}; const std::string encoded = - absl::Base64Escape(absl::string_view((const char*)v.data.data(), v.data.size())); + absl::Base64Escape(absl::string_view(reinterpret_cast(v.data.data()), v.data.size())); emitter.EmitString("Alignment"); emitter.EmitScalar(absl::StrFormat("0x%08x", v.align), false, false, "!u"); emitter.EmitString("Data"); diff --git a/src/include/oead/byml.h b/src/include/oead/byml.h index e7ef821..8df81bb 100644 --- a/src/include/oead/byml.h +++ b/src/include/oead/byml.h @@ -53,7 +53,7 @@ class Byml { Hash64, String, Binary, - File, + BinaryWithAlignment, Array, Dictionary, Bool, @@ -72,10 +72,10 @@ class Byml { using Array = std::vector; using Dictionary = absl::btree_map; - using File = BinaryAligned; + using BinaryWithAlignment = BinaryAligned; using Value = util::Variant, std::unique_ptr, std::unique_ptr, - std::unique_ptr>, std::unique_ptr, std::unique_ptr, + std::unique_ptr>, std::unique_ptr, std::unique_ptr, std::unique_ptr, bool, S32, F32, U32, S64, U64, F64>; Byml() = default; @@ -184,14 +184,14 @@ class Byml { Array& GetArray(); String& GetString(); std::vector& GetBinary(); - File& GetFile(); + BinaryWithAlignment& GetBinaryWithAlignment(); const Hash32& GetHash32() const; const Hash64& GetHash64() const; const Dictionary& GetDictionary() const; const Array& GetArray() const; const String& GetString() const; const std::vector& GetBinary() const; - const File& GetFile() const; + const BinaryWithAlignment& GetBinaryWithAlignment() const; bool GetBool() const; s32 GetInt() const; u32 GetUInt() const;