Merge branch 'main' of ssh://github.com/TwilitRealm/dusklight into rando-mod

This commit is contained in:
TakaRikka
2026-08-18 23:39:05 -07:00
28 changed files with 3555 additions and 86 deletions
+14 -12
View File
@@ -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 {
+2 -2
View File
@@ -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;
+2 -2
View File
@@ -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;
+1 -1
View File
@@ -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;
+3 -3
View File
@@ -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);
+178
View File
@@ -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