neptools

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

header.cpp (4364B)


      1 #include "header.hpp"
      2 
      3 #include "instruction.hpp"
      4 #include "../context.hpp"
      5 #include "../raw_item.hpp"
      6 #include "../../sink.hpp"
      7 
      8 #include <libshit/string_utils.hpp>
      9 
     10 namespace Neptools::Stsc
     11 {
     12 
     13   void HeaderItem::Header::Validate(FilePosition size) const
     14   {
     15 #define VALIDATE(x) LIBSHIT_VALIDATE_FIELD("Stsc::HeaderItem::Header", x)
     16     VALIDATE(memcmp(magic, "STSC", 4) == 0);
     17     VALIDATE(entry_point < size - 1);
     18     VALIDATE((flags & ~0x07) == 0);
     19 
     20     FilePosition hdr_len = sizeof(Header);
     21     if (flags & 1) hdr_len += 32;
     22     if (flags & 2) hdr_len += sizeof(ExtraHeader2Ser);
     23     if (flags & 4) hdr_len += 2; // uint16_t
     24     VALIDATE(entry_point >= hdr_len);
     25 #undef VALIDATE
     26   }
     27 
     28   HeaderItem::HeaderItem(Key k, Context& ctx, Source src)
     29     : Item{k, ctx}, entry_point{Libshit::EmptyNotNull{}}
     30   {
     31     ADD_SOURCE(Parse_(ctx, src), src);
     32   }
     33 
     34   HeaderItem::HeaderItem(
     35       Key k, Context& ctx, Libshit::NotNull<LabelPtr> entry_point,
     36       std::optional<Libshit::StringView> extra_headers_1,
     37       std::optional<ExtraHeaders2> extra_headers_2,
     38       std::optional<uint16_t> extra_headers_4)
     39     : Item{k, ctx}, entry_point{entry_point},
     40       extra_headers_2{extra_headers_2}, extra_headers_4{extra_headers_4}
     41   {
     42     if (extra_headers_1)
     43     {
     44       LIBSHIT_VALIDATE_FIELD("Ststc::HeaderItem", extra_headers_1->size() <= 32);
     45       this->extra_headers_1.emplace();
     46 
     47       auto s = extra_headers_1->size();
     48       memcpy(this->extra_headers_1->data(), extra_headers_1->data(), s);
     49       memset(this->extra_headers_1->data() + s, 0, 32 - s);
     50     }
     51   }
     52 
     53   FilePosition HeaderItem::GetSize() const noexcept
     54   {
     55     FilePosition size = sizeof(Header);
     56     if (extra_headers_1) size += 32;
     57     if (extra_headers_2) size += sizeof(ExtraHeader2Ser);
     58     if (extra_headers_4) size += 2;
     59     return size;
     60   }
     61 
     62   HeaderItem& HeaderItem::CreateAndInsert(ItemPointer ptr, Flavor flavor)
     63   {
     64     auto x = RawItem::GetSource(ptr, -1);
     65     auto& ret = x.ritem.SplitCreate<HeaderItem>(ptr.offset, x.src);
     66 
     67     InstructionBase::CreateAndInsert(ret.entry_point->GetPtr(), flavor);
     68     return ret;
     69   }
     70 
     71   void HeaderItem::Parse_(Context& ctx, Source& src)
     72   {
     73     src.CheckRemainingSize(sizeof(Header));
     74     auto hdr = src.ReadGen<Header>();
     75     hdr.Validate(src.GetSize());
     76 
     77     entry_point = ctx.CreateLabelFallback("entry_point", hdr.entry_point);
     78 
     79     if (hdr.flags & 1)
     80     {
     81       extra_headers_1.emplace();
     82       src.ReadGen(*extra_headers_1);
     83     }
     84     if (hdr.flags & 2)
     85     {
     86       auto eh2 = src.ReadGen<ExtraHeader2Ser>();
     87       extra_headers_2.emplace(
     88         eh2.field_0, eh2.field_2, eh2.field_4, eh2.field_6, eh2.field_8,
     89         eh2.field_a, eh2.field_c);
     90     }
     91     if (hdr.flags & 4)
     92       extra_headers_4 = src.ReadLittleUint16();
     93   }
     94 
     95   void HeaderItem::Dump_(Sink& sink) const
     96   {
     97     Header hdr;
     98     memcpy(hdr.magic, "STSC", 4);
     99     hdr.entry_point = ToFilePos(entry_point->GetPtr());
    100     uint32_t flags = 0;
    101     if (extra_headers_1) flags |= 1;
    102     if (extra_headers_2) flags |= 2;
    103     if (extra_headers_4) flags |= 4;
    104     hdr.flags = flags;
    105     sink.WriteGen(hdr);
    106 
    107     if (extra_headers_1) sink.WriteGen(*extra_headers_1);
    108     if (extra_headers_2)
    109     {
    110       ExtraHeader2Ser eh{
    111         extra_headers_2->field_0, extra_headers_2->field_2,
    112         extra_headers_2->field_4, extra_headers_2->field_6,
    113         extra_headers_2->field_8, extra_headers_2->field_a,
    114         extra_headers_2->field_c,
    115       };
    116       sink.WriteGen(eh);
    117     }
    118     if (extra_headers_4)
    119       sink.WriteLittleUint16(*extra_headers_4);
    120   }
    121 
    122   void HeaderItem::Inspect_(std::ostream& os, unsigned indent) const
    123   {
    124     Item::Inspect_(os, indent);
    125 
    126     os << "header(" << PrintLabel(entry_point) << ", ";
    127     if (extra_headers_1)
    128       Libshit::DumpBytes(os, {extra_headers_1->data(), extra_headers_1->size()});
    129     else os << "nil";
    130 
    131     if (extra_headers_2)
    132       os << ", neptools.stsc.header_item.extra_headers_2(" <<extra_headers_2->field_0
    133          << ", " << extra_headers_2->field_2
    134          << ", " << extra_headers_2->field_4
    135          << ", " << extra_headers_2->field_6
    136          << ", " << extra_headers_2->field_8
    137          << ", " << extra_headers_2->field_a
    138          << ", " << extra_headers_2->field_c << "), ";
    139     else os << ", nil, ";
    140     if (extra_headers_4) os << *extra_headers_4;
    141     else os << "nil";
    142     os << ")";
    143   }
    144 
    145 }
    146 
    147 #include "header.binding.hpp"