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"