activity_cinematic_incident_codec.cpp 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. #include <bit>
  2. #include "../../encoding/bit_reader.h"
  3. #include "cinematic_incident.h"
  4. namespace sunrise::middleware::bap::activity_message::cinematic_incident {
  5. namespace {
  6. namespace bits = encoding::bits;
  7. /** Bit offset of the client reference inside the incident body. */
  8. constexpr std::size_t kClientReferenceOffset = 335;
  9. /** Field widths of the client reference and the event tail, in bits. */
  10. constexpr std::uint8_t kRegistryKeyBits = 32;
  11. constexpr std::uint8_t kSlotTypeBits = 7;
  12. constexpr std::uint8_t kSlotIndexBits = 16;
  13. constexpr std::uint8_t kRuntimeObjectBits = 64;
  14. constexpr std::uint8_t kEventValueBits = 32;
  15. constexpr std::uint8_t kPaddingBits = 2;
  16. /** The slot type and index are sent unsigned, biased so their absent value is zero. */
  17. constexpr std::int32_t kSlotTypeBias = 1;
  18. constexpr std::int32_t kSlotIndexBias = 32'768;
  19. } // namespace
  20. /**
  21. * Maps one global SObject row to its cinematic signal.
  22. * @param target Global SObject row from the incident header.
  23. * @param output Set only when the row is one of the three cinematic rows.
  24. * @return True when the row names a cinematic signal.
  25. */
  26. bool signal_for_target(std::uint32_t target, Signal& output) noexcept {
  27. if (target == kStartedTarget) {
  28. output = Signal::started;
  29. return true;
  30. }
  31. if (target == kTerminatedTarget) {
  32. output = Signal::terminated;
  33. return true;
  34. }
  35. if (target == kSkipTarget) {
  36. output = Signal::skipRequested;
  37. return true;
  38. }
  39. return false;
  40. }
  41. /**
  42. * Decodes the fixed 486-bit payload; the two trailing padding bits must be zero.
  43. * @param input Exact payload bytes.
  44. * @param output Cleared first. Receives the ClientRef and runtime values.
  45. * @return True when the whole payload decoded.
  46. */
  47. bool decode(std::span<const std::byte> input, Payload& output) noexcept {
  48. output = {};
  49. if (input.size() != kPayloadBytes) {
  50. return false;
  51. }
  52. bits::Reader reader(input);
  53. std::uint64_t registryKey = 0;
  54. std::uint64_t slotType = 0;
  55. std::uint64_t slotIndex = 0;
  56. std::uint64_t runtimeObjectId = 0;
  57. std::uint64_t eventValue = 0;
  58. std::uint64_t padding = 0;
  59. if (!reader.skip(kClientReferenceOffset) || !reader.read(kRegistryKeyBits, registryKey)
  60. || !reader.read(kSlotTypeBits, slotType) || !reader.read(kSlotIndexBits, slotIndex)
  61. || !reader.read(kRuntimeObjectBits, runtimeObjectId)
  62. || !reader.read(kEventValueBits, eventValue) || !reader.read(kPaddingBits, padding)
  63. || padding != 0 || reader.remaining_bits() != 0) {
  64. return false;
  65. }
  66. Payload parsed{};
  67. parsed.registryKey = static_cast<std::uint32_t>(registryKey);
  68. parsed.slotType = static_cast<std::int8_t>(static_cast<std::int32_t>(slotType) - kSlotTypeBias);
  69. parsed.slotIndex =
  70. static_cast<std::int16_t>(static_cast<std::int32_t>(slotIndex) - kSlotIndexBias);
  71. parsed.runtimeObjectId = runtimeObjectId;
  72. parsed.eventValue = std::bit_cast<float>(static_cast<std::uint32_t>(eventValue));
  73. output = parsed;
  74. return true;
  75. }
  76. } // namespace sunrise::middleware::bap::activity_message::cinematic_incident