definition_index_table.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. #pragma once
  2. #include <cstddef>
  3. #include <cstdint>
  4. #include <span>
  5. namespace sunrise::middleware::content::packages::tables {
  6. /** Definition tags sit in this closed range. */
  7. inline constexpr std::uint32_t kTagLowerBound = 0x80800000;
  8. /** Values above this are not definition tags. */
  9. inline constexpr std::uint32_t kTagUpperBound = 0x82000000;
  10. /** A tag holds its entry index in the low bits and its package id above them. */
  11. inline constexpr std::uint32_t kTagPackageShift = 13;
  12. /** The package id no tag names, reported for a value outside the tag range. */
  13. inline constexpr std::uint16_t kAbsentPackageId = 0xFFFFU;
  14. /**
  15. * Reads the package id one tag names.
  16. * It is the same number the package file carries in its name.
  17. * @param tag Definition tag.
  18. * @return The package id, or `kAbsentPackageId` when the value is not a tag.
  19. */
  20. [[nodiscard]] constexpr std::uint16_t package_of(std::uint32_t tag) noexcept {
  21. if (tag < kTagLowerBound || tag >= kTagUpperBound) {
  22. return kAbsentPackageId;
  23. }
  24. return static_cast<std::uint16_t>((tag - kTagLowerBound) >> kTagPackageShift);
  25. }
  26. /** Element class of the item index table inside the investment container. */
  27. inline constexpr std::uint32_t kItemIndexTableClass = 0x80807BE8U;
  28. /** The investment root holds the installed collectible definition table at this slot. */
  29. inline constexpr std::size_t kCollectibleTableSlot = 19;
  30. /** Definition class recorded for the installed investment root tag. */
  31. inline constexpr std::uint32_t kInvestmentRootClass = 0x80807D84U;
  32. /** Definition class recorded for the installed collectible table tag. */
  33. inline constexpr std::uint32_t kCollectibleTableClass = 0x8080306DU;
  34. /** Element class recorded by the collectible table's inline array header. */
  35. inline constexpr std::uint32_t kCollectibleRowClass = 0x80803475U;
  36. /** One collectible row in this installed build occupies 184 bytes. */
  37. inline constexpr std::size_t kCollectibleRowStride = 0xB8;
  38. /** Authored DestinyCollectibleDefinition hash inside one collectible row. */
  39. inline constexpr std::size_t kCollectibleHashOffset = 0x28;
  40. /** Native item-definition index granted by one collectible row. */
  41. inline constexpr std::size_t kCollectibleItemIndexOffset = 0x2C;
  42. /** Native material-requirement-set ordinal carried by one collectible row. */
  43. inline constexpr std::size_t kCollectibleMaterialRequirementIndexOffset = 0x9A;
  44. /** The investment root holds the material-requirement-set table at this slot. */
  45. inline constexpr std::size_t kMaterialRequirementTableSlot = 96;
  46. /** Installed material-requirement-set table and row classes. */
  47. inline constexpr std::uint32_t kMaterialRequirementTableClass = 0x80807ACEU;
  48. inline constexpr std::uint32_t kMaterialRequirementSetRowClass = 0x80807AD4U;
  49. inline constexpr std::uint32_t kMaterialRequirementRowClass = 0x80807AD7U;
  50. /** One set row is a hash followed by a self-relative pointer to an array descriptor. */
  51. inline constexpr std::size_t kMaterialRequirementSetRowStride = 0x10;
  52. inline constexpr std::size_t kMaterialRequirementSetHashOffset = 0;
  53. inline constexpr std::size_t kMaterialRequirementSetArrayPointerOffset = 8;
  54. /** One requirement row is item index, quantity, two flags, then a native sentinel. */
  55. inline constexpr std::size_t kMaterialRequirementRowStride = 0x0C;
  56. inline constexpr std::size_t kMaterialRequirementItemIndexOffset = 0;
  57. inline constexpr std::size_t kMaterialRequirementQuantityOffset = 4;
  58. inline constexpr std::size_t kMaterialRequirementDeleteOffset = 8;
  59. inline constexpr std::size_t kMaterialRequirementOmitOffset = 9;
  60. inline constexpr std::size_t kMaterialRequirementSentinelOffset = 10;
  61. /** Plug item definitions name insertion/enabled requirement-set ordinals at fixed offsets. */
  62. inline constexpr std::size_t kInsertionMaterialRequirementSetIndexOffset = 0x1E8;
  63. inline constexpr std::size_t kEnabledMaterialRequirementSetIndexOffset = 0x200;
  64. inline constexpr std::uint16_t kUnavailableMaterialRequirementSetIndex = 0xFFFFU;
  65. /** Element class of an item's ordinary socket array. */
  66. inline constexpr std::uint32_t kOrdinarySocketClass = 0x808077C4U;
  67. /** One ordinary socket entry is 80 bytes. */
  68. inline constexpr std::size_t kSocketEntryStride = 80;
  69. /** An item definition holds its socket block self-relative at this offset. */
  70. inline constexpr std::size_t kSocketBlockOffset = 104;
  71. /** An item definition holds its inventory bucket id at this offset. */
  72. inline constexpr std::size_t kBucketIdOffset = 184;
  73. /** An item definition holds its art block self-relative at this offset, zero when absent. */
  74. inline constexpr std::size_t kArtBlockOffset = 136;
  75. /** Element class of an item's art row array. */
  76. inline constexpr std::uint32_t kArtRowClass = 0x808077B5U;
  77. /** Element class of an item's material override array. */
  78. inline constexpr std::uint32_t kMaterialOverrideClass = 0x808077B3U;
  79. /** Element class of an item's sandbox perk array. */
  80. inline constexpr std::uint32_t kSandboxPerkClass = 0x808077BCU;
  81. /** An item definition holds its stat block self-relative at this offset, zero when absent. */
  82. inline constexpr std::size_t kStatBlockOffset = 112;
  83. /** The investment root holds the constants blob at this slot. */
  84. inline constexpr std::size_t kInvestmentConstantsSlot = 11;
  85. /** The investment root holds the progression definition table at this slot. */
  86. inline constexpr std::size_t kProgressionTableSlot = 68;
  87. /** Element class of the progression definition table. */
  88. inline constexpr std::uint32_t kProgressionTableClass = 0x80807CDDU;
  89. /** One progression definition is 88 inline bytes. */
  90. inline constexpr std::size_t kProgressionRowStride = 88;
  91. /** A progression definition names the object array holding its record here. */
  92. inline constexpr std::size_t kProgressionScopeOffset = 4;
  93. /** One array found inside a definition blob. */
  94. struct Array {
  95. std::uint64_t count{};
  96. std::size_t dataOffset{};
  97. std::uint32_t elementClass{};
  98. };
  99. /** One row of a definition index table. */
  100. struct IndexRow {
  101. std::uint32_t definitionHash{};
  102. std::uint32_t targetTag{};
  103. };
  104. /** Visitor called once per index-table row. */
  105. using RowVisitor = bool (*)(void* context, std::uint32_t index, const IndexRow& row) noexcept;
  106. /**
  107. * Reads the array descriptor at one known offset.
  108. * @param blob Whole definition bytes.
  109. * @param descriptorOffset Offset of the count and self-relative offset pair.
  110. * @param output Receives the array that was found.
  111. * @return True when the descriptor points at a valid array header.
  112. */
  113. [[nodiscard]] bool find_array_at(std::span<const std::byte> blob,
  114. std::size_t descriptorOffset,
  115. Array& output) noexcept;
  116. /**
  117. * Finds the first array whose header names one element class.
  118. * @param blob Whole definition bytes.
  119. * @param elementClass Element class the header must carry.
  120. * @param output Cleared before the search and filled only on a match.
  121. * @return True when one descriptor points at a header of that class.
  122. */
  123. [[nodiscard]] bool
  124. find_array(std::span<const std::byte> blob, std::uint32_t elementClass, Array& output) noexcept;
  125. /**
  126. * Reads every row of one index table in order and hands each to a visitor.
  127. * @param blob Whole definition bytes.
  128. * @param array Index-table array that was found.
  129. * @param visitor Called once per row. Returning false ends the walk.
  130. * @param context Opaque pointer handed back to the visitor.
  131. * @return True when every row read back and the visitor accepted all of them.
  132. */
  133. [[nodiscard]] bool visit_index_rows(std::span<const std::byte> blob,
  134. const Array& array,
  135. RowVisitor visitor,
  136. void* context) noexcept;
  137. /**
  138. * Walks the child tags of one container blob.
  139. * @param blob Whole container bytes.
  140. * @param index Child ordinal.
  141. * @param tag Receives the child tag.
  142. * @return True when the ordinal is inside the container.
  143. */
  144. [[nodiscard]] bool
  145. child_tag(std::span<const std::byte> blob, std::size_t index, std::uint32_t& tag) noexcept;
  146. /**
  147. * Reads one investment-root slot.
  148. * @param blob Whole root bytes.
  149. * @param index Slot ordinal.
  150. * @param tag Receives the slot tag.
  151. * @return True when the slot is inside the root.
  152. */
  153. [[nodiscard]] bool
  154. slot_tag(std::span<const std::byte> blob, std::size_t index, std::uint32_t& tag) noexcept;
  155. /** The investment root holds the item index table at this slot. */
  156. inline constexpr std::size_t kItemTableSlot = 48;
  157. /** The investment root holds the shared reusable/randomized plug-set table at this slot. */
  158. inline constexpr std::size_t kPlugSetTableSlot = 51;
  159. /** The investment root holds the socket entry list table at this slot. */
  160. inline constexpr std::size_t kSocketEntryListTableSlot = 97;
  161. /** The globals container names the investment root as its first child. */
  162. inline constexpr std::size_t kInvestmentRootChild = 0;
  163. /** The investment root holds the inventory bucket table at this slot. */
  164. inline constexpr std::size_t kBucketTableSlot = 17;
  165. /** Installed bucket-definition table pairing inventory buckets with native equipment slots. */
  166. inline constexpr std::uint32_t kBucketDefinitionTableTag = 0x81327D66U;
  167. /** Package class of the bucket-definition index table. */
  168. inline constexpr std::uint32_t kBucketDefinitionTableClass = 0x80805936U;
  169. /** The installed table contains one row for each item-bearing bucket definition. */
  170. inline constexpr std::size_t kBucketDefinitionCount = 34;
  171. /** One resolved bucket definition occupies 72 bytes. */
  172. inline constexpr std::size_t kBucketDefinitionSize = 72;
  173. /** The native equipment-slot byte sits here in each resolved bucket definition. */
  174. inline constexpr std::size_t kBucketDefinitionEquipmentSlotOffset = 64;
  175. /** Non-equippable bucket definitions carry the all-one slot sentinel. */
  176. inline constexpr std::uint8_t kBucketDefinitionUnavailableEquipmentSlot = 0xFF;
  177. /** Element class of the socket entry list table. */
  178. inline constexpr std::uint32_t kSocketEntryListTableClass = 0x80807A7EU;
  179. /** A socket entry list definition holds its entry array descriptor here. */
  180. inline constexpr std::size_t kSocketEntryArrayDescriptor = 16;
  181. /** One socket entry is 64 bytes. */
  182. inline constexpr std::size_t kSocketEntrySize = 64;
  183. /** A socket entry holds its plug source hash here. */
  184. inline constexpr std::size_t kSocketEntryPlugSource = 8;
  185. /** Bucket group this socket entry competes in. `0xFF` marks an entry with no group. */
  186. inline constexpr std::size_t kSocketEntryGroup = 12;
  187. /** Entry kind. Kind 34 is the super lane, which is active despite carrying no plug source. */
  188. inline constexpr std::size_t kSocketEntryKind = 13;
  189. /** The absent plug source. */
  190. inline constexpr std::uint32_t kNoPlugSource = 0x811C9DC5U;
  191. /** The bucket table declares its descriptor count here. */
  192. inline constexpr std::size_t kBucketCountOffset = 140;
  193. /** Bucket descriptors follow the count. */
  194. inline constexpr std::size_t kBucketFirstDescriptor = 144;
  195. /** One bucket descriptor is 36 bytes. */
  196. inline constexpr std::size_t kBucketDescriptorSize = 36;
  197. /** Bucket descriptor field offsets. */
  198. inline constexpr std::size_t kBucketFirstSlotOffset = 4;
  199. inline constexpr std::size_t kBucketSlotCountOffset = 8;
  200. inline constexpr std::size_t kBucketArraySelectorOffset = 24;
  201. /** Every definition table holds its array descriptor at this fixed offset. */
  202. inline constexpr std::size_t kTableArrayDescriptor = 8;
  203. /** @param blob Whole container bytes. @return Its child count. */
  204. [[nodiscard]] std::size_t child_count(std::span<const std::byte> blob) noexcept;
  205. /**
  206. * Reads one row of an index table that was found.
  207. * @param blob Whole definition bytes owning the array.
  208. * @param array Array with a 24-byte stride.
  209. * @param index Row ordinal.
  210. * @param row Receives the row fields.
  211. * @return True when the row is inside the blob.
  212. */
  213. [[nodiscard]] bool index_row(std::span<const std::byte> blob,
  214. const Array& array,
  215. std::uint64_t index,
  216. IndexRow& row) noexcept;
  217. } // namespace sunrise::middleware::content::packages::tables