mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-08-20 13:24:40 -04:00
FlowService & MessageService (#2313)
This commit is contained in:
+14
-12
@@ -27,18 +27,20 @@ public:
|
||||
|
||||
// Attributes
|
||||
/* 0x04 */ BE(u16) message_id;
|
||||
/* 0x06 */ BE(u16) event_label_id;
|
||||
/* 0x08 */ u8 se_speaker;
|
||||
/* 0x09 */ u8 fuki_kind;
|
||||
/* 0x0A */ u8 output_type;
|
||||
/* 0x0B */ u8 fuki_pos_type;
|
||||
/* 0x0C */ u8 unk_0xc;
|
||||
/* 0x0D */ u8 unk_0xd;
|
||||
/* 0x0E */ u8 se_mood;
|
||||
/* 0x0F */ u8 camera_id;
|
||||
/* 0x10 */ u8 base_anm_id;
|
||||
/* 0x11 */ u8 face_anm_id;
|
||||
/* 0x12 */ BE(u16) unk_0x12;
|
||||
/* 0x06 */ BE(u16) event_label_id; // saveBitLabels index set when the message displays
|
||||
/* 0x08 */ u8 speaker; // Z2SpeechMgr2 voice bank ID
|
||||
/* 0x09 */ u8 box_kind; // screen class, see dMsgObject_c::talkStartInit
|
||||
/* 0x0A */ u8 draw_type; // text pacing, see jmessage_tSequenceProcessor::do_begin
|
||||
/* 0x0B */ u8 box_position; // see dMsgObject_c::fukiPosCalc
|
||||
/* 0x0C */ u8 item_no; // unused; legacy dItemNo, 0xFF = none
|
||||
/* 0x0D */ u8 line_alignment; // 0 centered (JP only), 1 left; also copied to
|
||||
// jmessage_tReference::mForm
|
||||
/* 0x0E */ u8 speaker_mood; // grunt emotion index for the voice bank
|
||||
/* 0x0F */ u8 camera_attr; // 1-10 talk-actor slot, >=11 talk-camera style
|
||||
/* 0x10 */ u8 talk_anim; // NPC talk motion attribute
|
||||
/* 0x11 */ u8 face_anim; // NPC talk face attribute
|
||||
/* 0x12 */ u8 lines_per_page; // unused; runtime uses getLineMax()
|
||||
/* 0x13 */ u8 _pad;
|
||||
};
|
||||
|
||||
class JMSMesgInfo_c {
|
||||
|
||||
@@ -22,7 +22,7 @@ struct msg_class;
|
||||
// all mesg_flow_node structs members might be wrong
|
||||
struct mesg_flow_node {
|
||||
/* 0x00 */ u8 type;
|
||||
/* 0x01 */ u8 field_0x1;
|
||||
/* 0x01 */ u8 subtype;
|
||||
/* 0x02 */ BE(u16) msg_index;
|
||||
/* 0x04 */ BE(u16) next_node_idx;
|
||||
/* 0x06 */ BE(u16) unk_0x6;
|
||||
@@ -30,7 +30,7 @@ struct mesg_flow_node {
|
||||
|
||||
struct mesg_flow_node_branch {
|
||||
/* 0x00 */ u8 type;
|
||||
/* 0x01 */ u8 field_0x1;
|
||||
/* 0x01 */ u8 result_count;
|
||||
/* 0x02 */ BE(u16) query_idx;
|
||||
/* 0x04 */ BE(u16) param;
|
||||
/* 0x06 */ BE(u16) next_node_idx;
|
||||
|
||||
@@ -280,13 +280,13 @@ public:
|
||||
/* 0x150 */ f32 field_0x150;
|
||||
/* 0x154 */ u32 mMessageID;
|
||||
/* 0x158 */ u32 field_0x158;
|
||||
/* 0x15C */ u32 field_0x15c;
|
||||
/* 0x15C */ u32 mSelectMessageID; // message ID of the selection options message; 1000 = none
|
||||
/* 0x160 */ int mIdx;
|
||||
/* 0x164 */ u16 mNodeIdx;
|
||||
/* 0x166 */ u16 field_0x166;
|
||||
/* 0x168 */ u16 field_0x168;
|
||||
/* 0x16A */ s16 field_0x16a;
|
||||
/* 0x16C */ s16 field_0x16c;
|
||||
/* 0x16C */ s16 mCurrentGroupID; // group whose BMG is parsed; -1 none, 0 common, 1-8 stage
|
||||
/* 0x16E */ s16 field_0x16e;
|
||||
/* 0x170 */ s16 mNowTalkFlowNo;
|
||||
/* 0x172 */ s16 field_0x172;
|
||||
|
||||
@@ -30,7 +30,7 @@ struct msg_class {
|
||||
/* 0xDC */ fopAc_ac_c* talk_actor;
|
||||
/* 0xE0 */ cXyz pos;
|
||||
/* 0xEC */ u32 msg_idx;
|
||||
/* 0xF0 */ u32 field_0xf0;
|
||||
/* 0xF0 */ u32 select_msg_idx; // selection options message ID; 1000 = none
|
||||
/* 0xF4 */ u32 field_0xf4;
|
||||
/* 0xF8 */ u16 mode;
|
||||
/* 0xFA */ u8 select_idx;
|
||||
|
||||
@@ -19,7 +19,7 @@ struct fopMsg_prm_class {
|
||||
/* 0x00 */ fopAc_ac_c* talk_actor;
|
||||
/* 0x04 */ cXyz pos;
|
||||
/* 0x10 */ u32 msg_idx;
|
||||
/* 0x14 */ u32 field_0x14;
|
||||
/* 0x14 */ u32 select_msg_idx; // selection options message ID; 1000 = none
|
||||
/* 0x18 */ fpc_ProcID field_0x18;
|
||||
}; // Size: 0x1C
|
||||
|
||||
@@ -46,8 +46,8 @@ void fopMsgM_setMessageID(fpc_ProcID msg_id);
|
||||
void fopMsgM_destroyExpHeap(JKRExpHeap* i_heap);
|
||||
f32 fopMsgM_valueIncrease(int param_0, int param_1, u8 i_type);
|
||||
s32 fopMsgM_setStageLayer(void* i_process);
|
||||
fpc_ProcID fopMsgM_messageSet(u32 i_msgIdx, fopAc_ac_c* i_talkActor, u32 param_2);
|
||||
fpc_ProcID fopMsgM_messageSet(u32 i_msgIdx, u32 param_1);
|
||||
fpc_ProcID fopMsgM_messageSet(u32 i_msgIdx, fopAc_ac_c* i_talkActor, u32 i_selectMsgIdx);
|
||||
fpc_ProcID fopMsgM_messageSet(u32 i_msgIdx, u32 i_selectMsgIdx);
|
||||
fpc_ProcID fopMsgM_messageSetDemo(u32 i_msgidx);
|
||||
msg_class* fopMsgM_SearchByID(fpc_ProcID i_id);
|
||||
TEXT_SPAN fopMsgM_messageGet(TEXT_SPAN i_stringBuf, u32 i_msgId);
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
#pragma once
|
||||
|
||||
#include <bit>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
|
||||
namespace dusk {
|
||||
namespace detail {
|
||||
|
||||
template <size_t Size>
|
||||
struct uint_of_size;
|
||||
|
||||
template <>
|
||||
struct uint_of_size<1> {
|
||||
using type = uint8_t;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct uint_of_size<2> {
|
||||
using type = uint16_t;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct uint_of_size<4> {
|
||||
using type = uint32_t;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct uint_of_size<8> {
|
||||
using type = uint64_t;
|
||||
};
|
||||
|
||||
template <size_t Size>
|
||||
using uint_of_size_t = uint_of_size<Size>::type;
|
||||
|
||||
template <typename T>
|
||||
requires(std::is_trivially_copyable_v<T>)
|
||||
T unaligned_load(const void* source) noexcept {
|
||||
T value;
|
||||
std::memcpy(&value, source, sizeof(value));
|
||||
return value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires(std::is_trivially_copyable_v<T>)
|
||||
void unaligned_store(void* destination, T value) noexcept {
|
||||
std::memcpy(destination, &value, sizeof(value));
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T>
|
||||
requires(std::is_unsigned_v<T>)
|
||||
constexpr T bswap(T value) noexcept {
|
||||
if constexpr (sizeof(T) == 1) {
|
||||
return value;
|
||||
} else if constexpr (sizeof(T) == 2) {
|
||||
return static_cast<T>((value << 8) | (value >> 8));
|
||||
} else if constexpr (sizeof(T) == 4) {
|
||||
return static_cast<T>(((value & 0x000000ffU) << 24) | ((value & 0x0000ff00U) << 8) |
|
||||
((value & 0x00ff0000U) >> 8) | ((value & 0xff000000U) >> 24));
|
||||
} else {
|
||||
static_assert(sizeof(T) == 8);
|
||||
return static_cast<T>(
|
||||
((value & 0x00000000000000ffULL) << 56) | ((value & 0x000000000000ff00ULL) << 40) |
|
||||
((value & 0x0000000000ff0000ULL) << 24) | ((value & 0x00000000ff000000ULL) << 8) |
|
||||
((value & 0x000000ff00000000ULL) >> 8) | ((value & 0x0000ff0000000000ULL) >> 24) |
|
||||
((value & 0x00ff000000000000ULL) >> 40) | ((value & 0xff00000000000000ULL) >> 56));
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads an unaligned integral value in the specified byte order.
|
||||
template <typename T>
|
||||
requires(std::is_integral_v<T> && !std::is_same_v<T, bool>)
|
||||
T read_bits(const void* source, std::endian endian = std::endian::big) noexcept {
|
||||
using Bits = std::make_unsigned_t<T>;
|
||||
Bits value = detail::unaligned_load<Bits>(source);
|
||||
if constexpr (sizeof(Bits) > 1) {
|
||||
if (endian != std::endian::native) {
|
||||
value = bswap(value);
|
||||
}
|
||||
}
|
||||
return std::bit_cast<T>(value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires(std::is_integral_v<T> && !std::is_same_v<T, bool>)
|
||||
constexpr T read_bits(const uint8_t* source, std::endian endian = std::endian::big) noexcept {
|
||||
if (!std::is_constant_evaluated()) {
|
||||
return read_bits<T>(static_cast<const void*>(source), endian);
|
||||
}
|
||||
using Bits = std::make_unsigned_t<T>;
|
||||
Bits value{};
|
||||
if (endian == std::endian::big) {
|
||||
for (size_t i = 0; i < sizeof(Bits); ++i) {
|
||||
value = static_cast<Bits>((value << 8) | source[i]);
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < sizeof(Bits); ++i) {
|
||||
value |= static_cast<Bits>(source[i]) << (i * 8);
|
||||
}
|
||||
}
|
||||
return std::bit_cast<T>(value);
|
||||
}
|
||||
|
||||
/// Reads an unaligned floating-point value in the specified byte order.
|
||||
template <typename T>
|
||||
requires(
|
||||
std::is_floating_point_v<T> && requires { typename detail::uint_of_size_t<sizeof(T)>; })
|
||||
T read_bits(const void* source, std::endian endian = std::endian::big) noexcept {
|
||||
using Bits = detail::uint_of_size_t<sizeof(T)>;
|
||||
return std::bit_cast<T>(read_bits<Bits>(source, endian));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires(
|
||||
std::is_floating_point_v<T> && requires { typename detail::uint_of_size_t<sizeof(T)>; })
|
||||
constexpr T read_bits(const uint8_t* source, std::endian endian = std::endian::big) noexcept {
|
||||
using Bits = detail::uint_of_size_t<sizeof(T)>;
|
||||
return std::bit_cast<T>(read_bits<Bits>(source, endian));
|
||||
}
|
||||
|
||||
/// Writes an unaligned integral value in the specified byte order.
|
||||
template <typename T>
|
||||
requires(std::is_integral_v<T> && !std::is_same_v<T, bool>)
|
||||
void write_bits(void* destination, T value, std::endian endian = std::endian::big) noexcept {
|
||||
using Bits = std::make_unsigned_t<T>;
|
||||
Bits bits = std::bit_cast<Bits>(value);
|
||||
if constexpr (sizeof(Bits) > 1) {
|
||||
if (endian != std::endian::native) {
|
||||
bits = bswap(bits);
|
||||
}
|
||||
}
|
||||
detail::unaligned_store(destination, bits);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires(std::is_integral_v<T> && !std::is_same_v<T, bool>)
|
||||
constexpr void write_bits(
|
||||
uint8_t* destination, T value, std::endian endian = std::endian::big) noexcept {
|
||||
if (!std::is_constant_evaluated()) {
|
||||
write_bits(static_cast<void*>(destination), value, endian);
|
||||
return;
|
||||
}
|
||||
using Bits = std::make_unsigned_t<T>;
|
||||
const Bits bits = std::bit_cast<Bits>(value);
|
||||
if (endian == std::endian::big) {
|
||||
for (size_t i = 0; i < sizeof(Bits); ++i) {
|
||||
destination[sizeof(Bits) - i - 1] = static_cast<uint8_t>(bits >> (i * 8));
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < sizeof(Bits); ++i) {
|
||||
destination[i] = static_cast<uint8_t>(bits >> (i * 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Writes an unaligned floating-point value in the specified byte order.
|
||||
template <typename T>
|
||||
requires(
|
||||
std::is_floating_point_v<T> && requires { typename detail::uint_of_size_t<sizeof(T)>; })
|
||||
void write_bits(void* destination, T value, std::endian endian = std::endian::big) noexcept {
|
||||
using Bits = detail::uint_of_size_t<sizeof(T)>;
|
||||
write_bits(destination, std::bit_cast<Bits>(value), endian);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires(
|
||||
std::is_floating_point_v<T> && requires { typename detail::uint_of_size_t<sizeof(T)>; })
|
||||
constexpr void write_bits(
|
||||
uint8_t* destination, T value, std::endian endian = std::endian::big) noexcept {
|
||||
using Bits = detail::uint_of_size_t<sizeof(T)>;
|
||||
write_bits(destination, std::bit_cast<Bits>(value), endian);
|
||||
}
|
||||
|
||||
} // namespace dusk
|
||||
Reference in New Issue
Block a user