neptools

Modding tools to Neptunia games
git clone https://git.neptards.moe/neptards/neptools.git
Log | Files | Refs | Submodules | README | LICENSE

string_data.cpp (2041B)


      1 #include "string_data.hpp"
      2 
      3 #include "data.hpp"
      4 #include "../raw_item.hpp"
      5 #include "../../sink.hpp"
      6 
      7 #include <libshit/string_utils.hpp>
      8 
      9 namespace Neptools::Stcm
     10 {
     11 
     12   Libshit::RefCountedPtr<StringDataItem>
     13   StringDataItem::MaybeCreateAndReplace(DataItem& it)
     14   {
     15     // string: data(0, x, 1), where x = size/4, size is strlen+1 rounded to 4 bytes
     16     // ignore x == 1: it's probably an int32
     17     if (it.type != 0 || it.offset_unit <= 1 || it.field_8 != 1 ||
     18         it.GetChildren().empty() || // only one child
     19         &it.GetChildren().front() != &it.GetChildren().back()) return nullptr;
     20     auto child = dynamic_cast<RawItem*>(&it.GetChildren().front());
     21     if (!child || child->GetSize() != it.offset_unit * 4) return nullptr;
     22 
     23     auto src = child->GetSource();
     24     auto s = src.ReadCString();
     25     auto padlen = it.offset_unit * 4 - s.size() - 1;
     26     if (padlen > 4) return nullptr;
     27     char pad[4];
     28     src.Read(pad, padlen);
     29     // check padding all zero. I don't think it's required, but in the game
     30     // files they're zero filled, + dump will generate zeros, so do not lose
     31     // information by discarding a non-null padding...
     32     for (size_t i = 0; i < padlen; ++i)
     33       if (pad[i] != 0) return nullptr;
     34 
     35     auto sit = it.GetContext()->Create<StringDataItem>(Libshit::Move(s));
     36     it.Replace(sit);
     37     return Libshit::Move(sit);
     38   }
     39 
     40   FilePosition StringDataItem::GetSize() const noexcept
     41   {
     42     return sizeof(DataItem::Header) + (string.length() + 1 + 3) / 4 * 4;
     43   }
     44 
     45   void StringDataItem::Dump_(Sink& sink) const
     46   {
     47     auto len = (string.length() + 1 + 3) / 4 * 4;
     48     sink.WriteGen(DataItem::Header{0, len/4, 1, len});
     49     sink.Write(string);
     50     sink.Pad(len - string.length());
     51   }
     52 
     53   void StringDataItem::Inspect_(std::ostream& os, unsigned indent) const
     54   {
     55     Item::Inspect_(os, indent);
     56     os << "string_data(" << Libshit::Quoted(string) << ')';
     57   }
     58 
     59   static Stcm::DataFactory reg{[](DataItem& it) {
     60       return !!StringDataItem::MaybeCreateAndReplace(it); }};
     61 
     62 }
     63 
     64 #include "string_data.binding.hpp"