definition_index_table.h 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. #pragma once
  2. #include <cstddef>
  3. #include <cstdint>
  4. #include <span>
  5. #include "unlock_opcode.h"
  6. namespace sunrise::middleware::content::packages::tables {
  7. /** Definition tags sit in this closed range. */
  8. inline constexpr std::uint32_t kTagLowerBound = 0x80800000;
  9. /** Values above this are not definition tags. */
  10. inline constexpr std::uint32_t kTagUpperBound = 0x82000000;
  11. /** A tag holds its entry index in the low bits and its package id above them. */
  12. inline constexpr std::uint32_t kTagPackageShift = 13;
  13. /** The package id no tag names, reported for a value outside the tag range. */
  14. inline constexpr std::uint16_t kAbsentPackageId = 0xFFFFU;
  15. /**
  16. * Reads the package id one tag names.
  17. * It is the same number the package file carries in its name.
  18. * @param tag Definition tag.
  19. * @return The package id, or `kAbsentPackageId` when the value is not a tag.
  20. */
  21. [[nodiscard]] constexpr std::uint16_t package_of(std::uint32_t tag) noexcept {
  22. if (tag < kTagLowerBound || tag >= kTagUpperBound) {
  23. return kAbsentPackageId;
  24. }
  25. return static_cast<std::uint16_t>((tag - kTagLowerBound) >> kTagPackageShift);
  26. }
  27. /** Element class of the item index table inside the investment container. */
  28. inline constexpr std::uint32_t kItemIndexTableClass = 0x80807BE8U;
  29. /** Serialized item definition class, distinct from the item index table class. */
  30. inline constexpr std::uint32_t kItemDefinitionClass = 0x80807BEAU;
  31. /** Investment root slot of the records and lore table. */
  32. inline constexpr std::size_t kRecordTableSlot = 72;
  33. /** One record row, wider than any field this pass reads. */
  34. inline constexpr std::size_t kRecordRowStride = 216;
  35. /** Unlock slot of the record's completion flag, or a non-positive value when it has none. */
  36. inline constexpr std::size_t kRecordCompletionFlagOffset = 100;
  37. /** Authored record definition hash inside one record row. */
  38. inline constexpr std::size_t kRecordHashOffset = 0x28;
  39. /**
  40. * Lore row a record names, or 0xFFFF when it names none.
  41. * A collectible row carries the same field at the same offset, which joins the two.
  42. */
  43. inline constexpr std::size_t kLoreRowOffset = 0x2C;
  44. // TODO: read the lore table so incident grants stop authoring their lore ordinal ranges.
  45. /** Investment root slot of the lore table. */
  46. inline constexpr std::size_t kLoreTableSlot = 52;
  47. /** One lore row, and the definition hash inside it. */
  48. inline constexpr std::size_t kLoreRowStride = 16;
  49. inline constexpr std::size_t kLoreHashOffset = 8;
  50. /** Points the record is worth. Zero for lore and for the interval records that score per step. */
  51. inline constexpr std::size_t kRecordScoreOffset = 92;
  52. /** A record names its category's value slot here. The record's own bar reads the next slot up. */
  53. inline constexpr std::size_t kRecordCategoryExpressionField = 120;
  54. /** A record's other expression field. A presentation gate sits in either of the two. */
  55. inline constexpr std::size_t kRecordAlternateExpressionField = 136;
  56. /** Objective rows a record names, two bytes each. */
  57. inline constexpr std::size_t kRecordObjectiveField = 48;
  58. inline constexpr std::uint32_t kRecordObjectiveRowClass = 0x80807455U;
  59. inline constexpr std::size_t kRecordObjectiveStride = 2;
  60. /** Interval rows a record names: objective row, score, then the item index the step grants. */
  61. inline constexpr std::size_t kRecordIntervalField = 64;
  62. inline constexpr std::uint32_t kRecordIntervalRowClass = 0x80802C0FU;
  63. inline constexpr std::size_t kRecordIntervalStride = 12;
  64. inline constexpr std::size_t kRecordIntervalObjectiveRowOffset = 0;
  65. inline constexpr std::size_t kRecordIntervalScoreOffset = 4;
  66. inline constexpr std::size_t kRecordIntervalItemIndexOffset = 8;
  67. /** Unlock value slot counting a record's redeemed intervals, or 0xFFFF when it has none. */
  68. inline constexpr std::size_t kRecordRedeemedCountSlotOffset = 82;
  69. /** An objective holds the expression naming its progress source at this field. */
  70. inline constexpr std::size_t kObjectiveSourceExpressionField = 8;
  71. /** Installed tag of the record display table. Its rows sit in record order. */
  72. inline constexpr std::uint32_t kRecordDisplayTableTag = 0x81613CFFU;
  73. inline constexpr std::size_t kRecordDisplayRowStride = 128;
  74. inline constexpr std::uint32_t kRecordDisplayRowClass = 0x80805A99U;
  75. /** Reward rows a record grants, held on its display row: item index then quantity. */
  76. inline constexpr std::size_t kRecordRewardField = 72;
  77. inline constexpr std::uint32_t kRecordRewardRowClass = 0x80805A9BU;
  78. inline constexpr std::size_t kRecordRewardStride = 24;
  79. inline constexpr std::size_t kRecordRewardItemIndexOffset = 0;
  80. inline constexpr std::size_t kRecordRewardQuantityOffset = 4;
  81. /** Nonzero when the record's completion grants a character-equippable title. */
  82. inline constexpr std::size_t kRecordHasTitleOffset = 0xB8;
  83. /** Investment root slot of the four unlock value mapping tables. */
  84. inline constexpr std::size_t kUnlockValueMapTableSlot = 113;
  85. /** Array descriptor of the account object's value mapping table. */
  86. inline constexpr std::size_t kAccountValueMapDescriptor = 8;
  87. /** One unlock expression instruction: an opcode then its operand. */
  88. inline constexpr std::size_t kUnlockInstructionStride = 8;
  89. /** The operand within one unlock expression instruction. */
  90. inline constexpr std::size_t kUnlockInstructionOperandOffset = 4;
  91. /** An expression field is a 64-bit count then a 64-bit self-relative offset. */
  92. inline constexpr std::size_t kUnlockExpressionFieldSize = 16;
  93. inline constexpr std::size_t kUnlockExpressionPointerOffset = 8;
  94. /** The opcode that reads a value slot. */
  95. inline constexpr std::uint32_t kUnlockReadValueOpcode =
  96. static_cast<std::uint32_t>(UnlockOpcode::loadValue);
  97. /** The opcode that tests a flag. */
  98. inline constexpr std::uint32_t kUnlockReadFlagOpcode =
  99. static_cast<std::uint32_t>(UnlockOpcode::flag);
  100. /** The opcode that pushes a literal. */
  101. inline constexpr std::uint32_t kUnlockLiteralOpcode =
  102. static_cast<std::uint32_t>(UnlockOpcode::constant);
  103. /** The opcode that tests greater than or equal. */
  104. inline constexpr std::uint32_t kUnlockGreaterEqualOpcode =
  105. static_cast<std::uint32_t>(UnlockOpcode::greaterOrEqual);
  106. /** The opcode that inverts the value on top of the stack. Its operand is unused. */
  107. inline constexpr std::uint32_t kUnlockNotOpcode =
  108. static_cast<std::uint32_t>(UnlockOpcode::logicalNot);
  109. /** The opcode that folds the top two values with logical and. */
  110. inline constexpr std::uint32_t kUnlockAndOpcode =
  111. static_cast<std::uint32_t>(UnlockOpcode::logicalAnd);
  112. /** The opcode that tests the top two values for equality. */
  113. inline constexpr std::uint32_t kUnlockEqualOpcode = static_cast<std::uint32_t>(UnlockOpcode::equal);
  114. /** High half every installed array marker and element class carries. */
  115. inline constexpr std::uint32_t kDefinitionClassHigh = 0x8080U;
  116. /** Shift that leaves `kDefinitionClassHigh` from a marker or element class. */
  117. inline constexpr std::uint32_t kDefinitionClassShift = 16;
  118. /** Array payloads begin after a sixteen byte header. */
  119. inline constexpr std::size_t kHeaderSkip = 16;
  120. /** Stops a wild count being walked as an expression. One shipped book carries 59 instructions. */
  121. inline constexpr std::int64_t kNodeExpressionCapacity = 128;
  122. /** Investment root slot of the presentation node table. */
  123. inline constexpr std::size_t kPresentationNodeTableSlot = 63;
  124. /** One node row. */
  125. inline constexpr std::size_t kNodeRowStride = 168;
  126. /** A node's expression sits at one of these two fields, never both. */
  127. inline constexpr std::size_t kNodeExpressionFieldPrimary = 64;
  128. inline constexpr std::size_t kNodeExpressionFieldAlternate = 48;
  129. /** Records a node owns, four bytes each as a row then a gate. */
  130. inline constexpr std::size_t kNodeChildRecordField = 136;
  131. inline constexpr std::size_t kNodeChildRecordStride = 4;
  132. /** Array descriptor of the account object's profile unlock flag mapping table. */
  133. inline constexpr std::size_t kProfileFlagMapDescriptor = 24;
  134. /** Array descriptor of the character object's flag mapping table, sized to that bank. */
  135. inline constexpr std::size_t kCharacterFlagMapDescriptor = 40;
  136. /** Array descriptor of the character object's value mapping table, sized to that bank. */
  137. inline constexpr std::size_t kCharacterValueMapDescriptor = 24;
  138. /** Investment root slot of the unlock flag mapping tables. */
  139. inline constexpr std::size_t kUnlockFlagMapTableSlot = 111;
  140. /** Array descriptor of the account object's flag mapping table. */
  141. inline constexpr std::size_t kAccountFlagMapDescriptor = 8;
  142. /** One mapping row: a source and the slot it feeds. */
  143. inline constexpr std::size_t kUnlockMapRowStride = 8;
  144. /** The destination slot within one mapping row. */
  145. inline constexpr std::size_t kUnlockMapDestinationSlotOffset = 4;
  146. /** The investment root holds the installed collectible definition table at this slot. */
  147. inline constexpr std::size_t kCollectibleTableSlot = 19;
  148. /** Definition class recorded for the installed investment root tag. */
  149. inline constexpr std::uint32_t kInvestmentRootClass = 0x80807D84U;
  150. /** Definition class recorded for the installed collectible table tag. */
  151. inline constexpr std::uint32_t kCollectibleTableClass = 0x8080306DU;
  152. /** Element class recorded by the collectible table's inline array header. */
  153. inline constexpr std::uint32_t kCollectibleRowClass = 0x80803475U;
  154. /** One collectible row in this installed build occupies 184 bytes. */
  155. inline constexpr std::size_t kCollectibleRowStride = 0xB8;
  156. /** Authored DestinyCollectibleDefinition hash inside one collectible row. */
  157. inline constexpr std::size_t kCollectibleHashOffset = 0x28;
  158. /** Native item-definition index granted by one collectible row. */
  159. inline constexpr std::size_t kCollectibleItemIndexOffset = 0x2C;
  160. /** Native material-requirement-set ordinal carried by one collectible row. */
  161. inline constexpr std::size_t kCollectibleMaterialRequirementIndexOffset = 0x9A;
  162. /** The investment root holds the material-requirement-set table at this slot. */
  163. inline constexpr std::size_t kMaterialRequirementTableSlot = 96;
  164. /** Installed material-requirement-set table and row classes. */
  165. inline constexpr std::uint32_t kMaterialRequirementTableClass = 0x80807ACEU;
  166. inline constexpr std::uint32_t kMaterialRequirementSetRowClass = 0x80807AD4U;
  167. inline constexpr std::uint32_t kMaterialRequirementRowClass = 0x80807AD7U;
  168. /** One set row is a hash followed by a self-relative pointer to an array descriptor. */
  169. inline constexpr std::size_t kMaterialRequirementSetRowStride = 0x10;
  170. inline constexpr std::size_t kMaterialRequirementSetHashOffset = 0;
  171. inline constexpr std::size_t kMaterialRequirementSetArrayPointerOffset = 8;
  172. /** One requirement row is item index, quantity, two flags, then a native sentinel. */
  173. inline constexpr std::size_t kMaterialRequirementRowStride = 0x0C;
  174. inline constexpr std::size_t kMaterialRequirementItemIndexOffset = 0;
  175. inline constexpr std::size_t kMaterialRequirementQuantityOffset = 4;
  176. inline constexpr std::size_t kMaterialRequirementDeleteOffset = 8;
  177. inline constexpr std::size_t kMaterialRequirementOmitOffset = 9;
  178. inline constexpr std::size_t kMaterialRequirementSentinelOffset = 10;
  179. /** Plug item definitions name insertion/enabled requirement-set ordinals at fixed offsets. */
  180. inline constexpr std::size_t kInsertionMaterialRequirementSetIndexOffset = 0x1E8;
  181. inline constexpr std::size_t kEnabledMaterialRequirementSetIndexOffset = 0x200;
  182. inline constexpr std::uint16_t kUnavailableMaterialRequirementSetIndex = 0xFFFFU;
  183. /** Element class of an item's ordinary socket array. */
  184. inline constexpr std::uint32_t kOrdinarySocketClass = 0x808077C4U;
  185. /** One ordinary socket entry is 80 bytes. */
  186. inline constexpr std::size_t kSocketEntryStride = 80;
  187. /** An item definition holds its socket block self-relative at this offset. */
  188. inline constexpr std::size_t kSocketBlockOffset = 104;
  189. /** An item definition holds its inventory bucket id at this offset. */
  190. inline constexpr std::size_t kBucketIdOffset = 184;
  191. /** An item definition holds its art block self-relative at this offset, zero when absent. */
  192. inline constexpr std::size_t kArtBlockOffset = 136;
  193. /** Element class of an item's art row array. */
  194. inline constexpr std::uint32_t kArtRowClass = 0x808077B5U;
  195. /** Element class of an item's material override array. */
  196. inline constexpr std::uint32_t kMaterialOverrideClass = 0x808077B3U;
  197. /** Element class of an item's sandbox perk array. */
  198. inline constexpr std::uint32_t kSandboxPerkClass = 0x808077BCU;
  199. /** An item definition holds its stat block self-relative at this offset, zero when absent. */
  200. inline constexpr std::size_t kStatBlockOffset = 112;
  201. /** The investment root holds the constants blob at this slot. */
  202. inline constexpr std::size_t kInvestmentConstantsSlot = 11;
  203. /** The investment root holds the progression definition table at this slot. */
  204. inline constexpr std::size_t kProgressionTableSlot = 68;
  205. /** Element class of the progression definition table. */
  206. inline constexpr std::uint32_t kProgressionTableClass = 0x80807CDDU;
  207. /** One progression definition is 88 inline bytes. */
  208. inline constexpr std::size_t kProgressionRowStride = 88;
  209. /** A progression definition names the object array holding its record here. */
  210. inline constexpr std::size_t kProgressionScopeOffset = 4;
  211. /** Rank steps a progression declares: the experience each rank costs, in rank order. */
  212. inline constexpr std::size_t kProgressionStepField = 24;
  213. inline constexpr std::uint32_t kProgressionStepRowClass = 0x80807CEDU;
  214. inline constexpr std::size_t kProgressionStepStride = 8;
  215. /** Reward rows a progression grants, held on the progression definition. */
  216. inline constexpr std::size_t kProgressionRewardField = 72;
  217. inline constexpr std::uint32_t kProgressionRewardRowClass = 0x80802FF7U;
  218. inline constexpr std::size_t kProgressionRewardStride = 56;
  219. /** Reward row fields: the rank it needs, the item it grants, and how many. */
  220. inline constexpr std::size_t kProgressionRewardRankOffset = 0;
  221. inline constexpr std::size_t kProgressionRewardItemIndexOffset = 4;
  222. inline constexpr std::size_t kProgressionRewardQuantityOffset = 8;
  223. /** Unlock flag slot a reward's claim sets. The slots run dense in reward order. */
  224. inline constexpr std::size_t kProgressionRewardClaimSlotOffset = 20;
  225. /** Eligibility expressions and socket overrides carried by one progression reward. */
  226. inline constexpr std::size_t kProgressionRewardConditionsOffset = 24;
  227. inline constexpr std::size_t kProgressionRewardSocketsOffset = 40;
  228. /** Items a wrapper item opens into, two bytes each as an item-definition index. */
  229. inline constexpr std::size_t kGearsetItemField = 392;
  230. inline constexpr std::uint32_t kGearsetItemRowClass = 0x808087DBU;
  231. inline constexpr std::size_t kGearsetItemStride = 2;
  232. /** Expression that makes one collectible acquired, which a purchase or a grant sets. */
  233. inline constexpr std::size_t kCollectibleAcquiredExpressionField = 112;
  234. /** Investment root slot of the unlock flag slot table, which is keyed by slot. */
  235. inline constexpr std::size_t kUnlockFlagSlotTableSlot = 112;
  236. /** One flag slot row, and the bank row it feeds inside the object its kind names. */
  237. inline constexpr std::size_t kUnlockSlotRowStride = 8;
  238. inline constexpr std::size_t kUnlockSlotBankIndexOffset = 6;
  239. /** Installed tag of the per-item strings index table. Its rows sit in item index order. */
  240. inline constexpr std::uint32_t kItemStringsIndexTag = 0x81613CF1U;
  241. inline constexpr std::uint32_t kItemStringsIndexRowClass = 0x80805CDFU;
  242. /** Item-type pair on one item's strings blob: the bank, then the name hash inside it. */
  243. inline constexpr std::size_t kItemStringsTypePairOffset = 144;
  244. inline constexpr std::size_t kItemStringsTypeHashOffset = 148;
  245. /** One array found inside a definition blob. */
  246. struct Array {
  247. std::uint64_t count{};
  248. std::size_t dataOffset{};
  249. std::uint32_t elementClass{};
  250. };
  251. /** One row of a definition index table. */
  252. struct IndexRow {
  253. std::uint32_t definitionHash{};
  254. std::uint32_t targetTag{};
  255. };
  256. // TODO: visit_index_rows has no caller yet; the open runtime extraction sources need it.
  257. /** Visitor called once per index-table row. */
  258. using RowVisitor = bool (*)(void* context, std::uint32_t index, const IndexRow& row) noexcept;
  259. /**
  260. * Reads the array descriptor at one known offset.
  261. * @param blob Whole definition bytes.
  262. * @param descriptorOffset Offset of the count and self-relative offset pair.
  263. * @param output Receives the array that was found.
  264. * @return True when the descriptor points at a valid array header.
  265. */
  266. [[nodiscard]] bool find_array_at(std::span<const std::byte> blob,
  267. std::size_t descriptorOffset,
  268. Array& output) noexcept;
  269. /**
  270. * Reads the array descriptor at one known offset and accepts an array with no entries.
  271. * A zero count is authored either with no header at all or with a header repeating that count.
  272. * Use this where an empty list is ordinary data rather than an unreadable one.
  273. * @param blob Whole definition bytes.
  274. * @param descriptorOffset Offset of the count and self-relative offset pair.
  275. * @param output Receives the array, with count zero when the list is empty.
  276. * @return True when the descriptor is a valid array or a valid empty one.
  277. */
  278. [[nodiscard]] bool find_optional_array_at(std::span<const std::byte> blob,
  279. std::size_t descriptorOffset,
  280. Array& output) noexcept;
  281. /** Reads an optional typed array and checks every fixed-stride row lies in its blob. */
  282. [[nodiscard]] bool read_array(std::span<const std::byte> blob,
  283. std::size_t at,
  284. std::uint32_t elementClass,
  285. std::size_t stride,
  286. Array& rows) noexcept;
  287. /**
  288. * Finds the first array whose header names one element class.
  289. * @param blob Whole definition bytes.
  290. * @param elementClass Element class the header must carry.
  291. * @param output Cleared before the search and filled only on a match.
  292. * @return True when one descriptor points at a header of that class.
  293. */
  294. [[nodiscard]] bool
  295. find_array(std::span<const std::byte> blob, std::uint32_t elementClass, Array& output) noexcept;
  296. /**
  297. * Reads every row of one index table in order and hands each to a visitor.
  298. * @param blob Whole definition bytes.
  299. * @param array Index-table array that was found.
  300. * @param visitor Called once per row. Returning false ends the walk.
  301. * @param context Opaque pointer handed back to the visitor.
  302. * @return True when every row read back and the visitor accepted all of them.
  303. */
  304. [[nodiscard]] bool visit_index_rows(std::span<const std::byte> blob,
  305. const Array& array,
  306. RowVisitor visitor,
  307. void* context) noexcept;
  308. /**
  309. * Walks the child tags of one container blob.
  310. * @param blob Whole container bytes.
  311. * @param index Child ordinal.
  312. * @param tag Receives the child tag.
  313. * @return True when the ordinal is inside the container.
  314. */
  315. [[nodiscard]] bool
  316. child_tag(std::span<const std::byte> blob, std::size_t index, std::uint32_t& tag) noexcept;
  317. /**
  318. * Reads one investment-root slot.
  319. * @param blob Whole root bytes.
  320. * @param index Slot ordinal.
  321. * @param tag Receives the slot tag.
  322. * @return True when the slot is inside the root.
  323. */
  324. [[nodiscard]] bool
  325. slot_tag(std::span<const std::byte> blob, std::size_t index, std::uint32_t& tag) noexcept;
  326. /** The investment root holds the item index table at this slot. */
  327. inline constexpr std::size_t kItemTableSlot = 48;
  328. /** The investment root holds the shared reusable/randomized plug-set table at this slot. */
  329. inline constexpr std::size_t kPlugSetTableSlot = 51;
  330. /** The investment root holds the dense ordinary socket-type table at this slot. */
  331. inline constexpr std::size_t kSocketTypeTableSlot = 94;
  332. /** Element class and row size of the installed ordinary socket-type table. */
  333. inline constexpr std::uint32_t kSocketTypeTableClass = 0x80807ABBU;
  334. inline constexpr std::size_t kSocketTypeRowStride = 96;
  335. /** One socket type points to its acquired-state rule array from this row offset. */
  336. inline constexpr std::size_t kSocketTypeAcquisitionDescriptor = 16;
  337. /** Acquired-state and item-completion arrays carry this postfix expression-row class. */
  338. inline constexpr std::uint32_t kInvestmentExpressionRowClass = 0x80807D31U;
  339. /** Catalyst progress items reference objective rows through this one-row array. */
  340. inline constexpr std::uint32_t kObjectiveReferenceArrayClass = 0x808087B1U;
  341. inline constexpr std::uint32_t kObjectiveReferenceRowClass = 0x808077E3U;
  342. /** The investment root holds the dense objective definition table at this slot. */
  343. inline constexpr std::size_t kObjectiveTableSlot = 58;
  344. /** Installed objective table and row layout. */
  345. inline constexpr std::uint32_t kObjectiveTableClass = 0x8080775BU;
  346. inline constexpr std::uint32_t kObjectiveRowClass = 0x8080775FU;
  347. inline constexpr std::size_t kObjectiveRowStride = 0xA0;
  348. inline constexpr std::size_t kObjectiveCompletionValueOffset = 0x30;
  349. /** The investment root holds the socket entry list table at this slot. */
  350. inline constexpr std::size_t kSocketEntryListTableSlot = 97;
  351. /** The globals container names the investment root as its first child. */
  352. inline constexpr std::size_t kInvestmentRootChild = 0;
  353. /** The investment root holds the inventory bucket table at this slot. */
  354. inline constexpr std::size_t kBucketTableSlot = 17;
  355. /**
  356. * Package class of the bucket-definition table pairing inventory buckets with native equipment
  357. * slots. Exactly one installed entry carries it, so a class sweep locates the table without
  358. * naming the tag it happens to hold in one install.
  359. */
  360. inline constexpr std::uint32_t kBucketDefinitionTableClass = 0x80805936U;
  361. /** The installed table contains one row for each item-bearing bucket definition. */
  362. inline constexpr std::size_t kBucketDefinitionCount = 34;
  363. /** One resolved bucket definition occupies 72 bytes. */
  364. inline constexpr std::size_t kBucketDefinitionSize = 72;
  365. /** The native equipment-slot byte sits here in each resolved bucket definition. */
  366. inline constexpr std::size_t kBucketDefinitionEquipmentSlotOffset = 64;
  367. /** Non-equippable bucket definitions carry the all-one slot sentinel. */
  368. inline constexpr std::uint8_t kBucketDefinitionUnavailableEquipmentSlot = 0xFF;
  369. /** Element class of the socket entry list table. */
  370. inline constexpr std::uint32_t kSocketEntryListTableClass = 0x80807A7EU;
  371. /** A socket entry list definition holds its entry array descriptor here. */
  372. inline constexpr std::size_t kSocketEntryArrayDescriptor = 16;
  373. /** One socket entry is 64 bytes. */
  374. inline constexpr std::size_t kSocketEntrySize = 64;
  375. /** A socket entry holds its plug source hash here. */
  376. inline constexpr std::size_t kSocketEntryPlugSource = 8;
  377. /** Bucket group this socket entry competes in. `0xFF` marks an entry with no group. */
  378. inline constexpr std::size_t kSocketEntryGroup = 12;
  379. /** Entry kind. Kind 34 is the super lane, which is active despite carrying no plug source. */
  380. inline constexpr std::size_t kSocketEntryKind = 13;
  381. /** The absent plug source. */
  382. inline constexpr std::uint32_t kNoPlugSource = 0x811C9DC5U;
  383. /** The bucket table declares its descriptor count here. */
  384. inline constexpr std::size_t kBucketCountOffset = 140;
  385. /** Bucket descriptors follow the count. */
  386. inline constexpr std::size_t kBucketFirstDescriptor = 144;
  387. /** One bucket descriptor is 36 bytes. */
  388. inline constexpr std::size_t kBucketDescriptorSize = 36;
  389. /** Bucket descriptor field offsets. */
  390. inline constexpr std::size_t kBucketFirstSlotOffset = 4;
  391. inline constexpr std::size_t kBucketSlotCountOffset = 8;
  392. inline constexpr std::size_t kBucketArraySelectorOffset = 24;
  393. /** Every definition table holds its array descriptor at this fixed offset. */
  394. inline constexpr std::size_t kTableArrayDescriptor = 8;
  395. /** Installed tags carrying the sobject definition table. The first one that reads is used. */
  396. inline constexpr std::uint32_t kSobjectTablePrimaryTag = 0x81327CD4U;
  397. inline constexpr std::uint32_t kSobjectTableAlternateTag = 0x80B9E5BFU;
  398. /** The sobject table declares its row count here, and its rows begin after it. */
  399. inline constexpr std::size_t kSobjectCountOffset = 112;
  400. inline constexpr std::size_t kSobjectFirstRow = 128;
  401. /** One sobject row, and the three fields an incident target needs from it. */
  402. inline constexpr std::size_t kSobjectRowStride = 40;
  403. inline constexpr std::size_t kSobjectNameHashOffset = 0;
  404. inline constexpr std::size_t kSobjectLaneOffset = 16;
  405. inline constexpr std::size_t kSobjectTypeCodeOffset = 36;
  406. /** @param blob Whole container bytes. @return Its child count. */
  407. [[nodiscard]] std::size_t child_count(std::span<const std::byte> blob) noexcept;
  408. /**
  409. * Reads one row of an index table that was found.
  410. * @param blob Whole definition bytes owning the array.
  411. * @param array Array with a 24-byte stride.
  412. * @param index Row ordinal.
  413. * @param row Receives the row fields.
  414. * @return True when the row is inside the blob.
  415. */
  416. [[nodiscard]] bool index_row(std::span<const std::byte> blob,
  417. const Array& array,
  418. std::uint64_t index,
  419. IndexRow& row) noexcept;
  420. } // namespace sunrise::middleware::content::packages::tables