BST SE/STREAM replacement support

No SEQ yet since idk how I wanna handle it.
This commit is contained in:
PJB3005
2026-08-24 21:04:16 +02:00
parent 2fca463139
commit 2bc53dddcc
37 changed files with 832 additions and 128 deletions
@@ -3,6 +3,10 @@
#include "JSystem/JGeometry.h"
namespace dusk::mods::svc::audio_res::bst {
struct SoundTableReplacementSlot;
}
class JAIAudible;
class JAISoundID;
struct JASSoundParams;
@@ -14,7 +18,8 @@ struct JASSoundParams;
struct JAIAudience {
virtual ~JAIAudience();
virtual JAIAudible* newAudible(JGeometry::TVec3<f32> const&, JAISoundID,
JGeometry::TVec3<f32> const*, u32) = 0;
JGeometry::TVec3<f32> const*, u32
IF_DUSK_ARG(dusk::mods::svc::audio_res::bst::SoundTableReplacementSlot const*)) = 0;
virtual int getMaxChannels() = 0;
virtual void deleteAudible(JAIAudible*) = 0;
virtual u32 calcPriority(JAIAudible*) = 0;
+1 -1
View File
@@ -43,7 +43,7 @@ public:
void startTrack_(const JASSoundParams& params);
void JAISeCategoryMgr_mixOut_(bool, const JASSoundParams& params, JAISoundActivity activity);
void JAISeCategoryMgr_calc_();
void JAISeMgr_startID_(JAISoundID id, const JGeometry::TVec3<f32>* posPtr, JAIAudience* audience);
void JAISeMgr_startID_(JAISoundID id, const JGeometry::TVec3<f32>* posPtr, JAIAudience* audience IF_DUSK_ARG(std::shared_ptr<SoundEffectReplacementSlot> replacement));
bool prepare_getSeqData_();
void prepare_();
@@ -104,7 +104,7 @@ public:
JAISe* newSe_(int category, u32 priority);
void calc();
void mixOut();
bool startSound(JAISoundID id, JAISoundHandle* handle, const JGeometry::TVec3<f32>* posPtr);
bool startSound(JAISoundID id, JAISoundHandle* handle, const JGeometry::TVec3<f32>* posPtr IF_DUSK_ARG(std::shared_ptr<dusk::mods::svc::audio_res::bst::SoundEffectReplacementSlot> replacement));
int getNumActiveSe() const;
/* 0x004 */ JAISoundActivity mSoundActivity;
@@ -6,7 +6,16 @@
#include "JSystem/JUtility/JUTAssert.h"
#include "global.h"
#include "helpers/endian.h"
#include <cstdint>
#if TARGET_PC
#include <memory>
namespace dusk::mods::svc::audio_res::bst {
struct SoundTableReplacementSlot;
struct SoundEffectReplacementSlot;
struct StreamReplacementSlot;
}
#endif
class JAISound;
@@ -271,10 +280,16 @@ class JAITempoMgr;
*/
class JAISound {
public:
#if TARGET_PC
using SoundTableReplacementSlot = dusk::mods::svc::audio_res::bst::SoundTableReplacementSlot;
using SoundEffectReplacementSlot = dusk::mods::svc::audio_res::bst::SoundEffectReplacementSlot;
using StreamReplacementSlot = dusk::mods::svc::audio_res::bst::StreamReplacementSlot;
#endif
void releaseHandle();
void attachHandle(JAISoundHandle* handle);
JAISound();
void start_JAISound_(JAISoundID id, const JGeometry::TVec3<f32>* posPtr, JAIAudience* audience);
void start_JAISound_(JAISoundID id, const JGeometry::TVec3<f32>* posPtr, JAIAudience* audience IF_DUSK_ARG(std::shared_ptr<SoundTableReplacementSlot> replacement));
bool acceptsNewAudible() const;
void newAudible(const JGeometry::TVec3<f32>&, JGeometry::TVec3<f32> const*, u32,
JAIAudience*);
@@ -297,6 +312,11 @@ public:
virtual bool JAISound_tryDie_() = 0;
JAISoundID getID() const { return soundID_; }
#if TARGET_PC
SoundTableReplacementSlot* getReplacement() const {
return replacement.get();
}
#endif
u32 getAnimationState() const { return status_.state.flags.animationState; }
bool isAnimated() const { return getAnimationState() != 0; }
void setAnimationState(u32 state) {
@@ -380,6 +400,9 @@ public:
/* 0x34 */ u32 priority_;
/* 0x38 */ s32 count_;
/* 0x3C */ JAISoundParams params_;
#if TARGET_PC
std::shared_ptr<SoundTableReplacementSlot> replacement;
#endif
}; // Size: 0x98
STATIC_ASSERT(sizeof(JAISound) == 0x98);
@@ -9,13 +9,17 @@
*
*/
struct JAISoundInfo : public JASGlobalInstance<JAISoundInfo> {
IF_DUSK(using SoundTableReplacementSlot = dusk::mods::svc::audio_res::bst::SoundTableReplacementSlot);
IF_DUSK(using SoundEffectReplacementSlot = dusk::mods::svc::audio_res::bst::SoundEffectReplacementSlot);
IF_DUSK(using StreamReplacementSlot = dusk::mods::svc::audio_res::bst::StreamReplacementSlot);
JAISoundInfo(bool);
virtual int getSoundType(JAISoundID) const = 0;
virtual int getCategory(JAISoundID) const = 0;
virtual u32 getPriority(JAISoundID) const = 0;
virtual void getSeInfo(JAISoundID, JAISe*) const = 0;
virtual u32 getPriority(JAISoundID IF_DUSK_ARG(SoundTableReplacementSlot const* replacement)) const = 0;
virtual void getSeInfo(JAISoundID, JAISe* IF_DUSK_ARG(SoundEffectReplacementSlot const* replacement)) const = 0;
virtual void getSeqInfo(JAISoundID, JAISeq*) const = 0;
virtual void getStreamInfo(JAISoundID, JAIStream*) const = 0;
virtual void getStreamInfo(JAISoundID, JAIStream* IF_DUSK_ARG(StreamReplacementSlot const* replacement)) const = 0;
virtual ~JAISoundInfo();
};
@@ -20,7 +20,7 @@ public:
JAIStream(JAIStreamMgr* streamMgr, JAISoundStrategyMgr<JAIStream>* soundStrategyMgr);
void JAIStreamMgr_startID_(JAISoundID id, s32 streamFileEntry,
const JGeometry::TVec3<f32>* posPtr, JAIAudience* audience,
int category);
int category IF_DUSK_ARG(std::shared_ptr<StreamReplacementSlot> replacement));
bool prepare_prepareStream_();
void prepare_();
void prepare_startStream_();
@@ -8,7 +8,9 @@
*
*/
struct JAIStreamDataMgr {
virtual s32 getStreamFileEntry(JAISoundID) = 0;
IF_DUSK(using StreamReplacementSlot2 = dusk::mods::svc::audio_res::bst::StreamReplacementSlot);
virtual s32 getStreamFileEntry(JAISoundID IF_DUSK_ARG(StreamReplacementSlot2 const*)) = 0;
virtual ~JAIStreamDataMgr();
};
@@ -15,7 +15,7 @@ struct JAIStreamDataMgr;
class JAIStreamMgr : public JASGlobalInstance<JAIStreamMgr> {
public:
JAIStreamMgr(bool setInstance);
bool startSound(JAISoundID id, JAISoundHandle* handle, const JGeometry::TVec3<f32>* posPtr);
bool startSound(JAISoundID id, JAISoundHandle* handle, const JGeometry::TVec3<f32>* posPtr IF_DUSK_ARG(std::shared_ptr<dusk::mods::svc::audio_res::bst::StreamReplacementSlot> replacement));
void freeDeadStream_();
void calc();
void stop();
@@ -10,8 +10,10 @@
*/
class JAUSoundInfo : public JASGlobalInstance<JAUSoundInfo> {
public:
IF_DUSK(using SoundTableReplacementSlot2 = dusk::mods::svc::audio_res::bst::SoundTableReplacementSlot);
JAUSoundInfo(bool param_0) : JASGlobalInstance<JAUSoundInfo>(param_0) {}
virtual u16 getAudibleSw(JAISoundID) const = 0;
virtual u16 getAudibleSw(JAISoundID IF_DUSK_ARG(SoundTableReplacementSlot2 const*)) const = 0;
virtual u16 getBgmSeqResourceID(JAISoundID) const = 0;
};
@@ -51,6 +51,11 @@
*/
#define SOUND_SW_IGNORE_FX_MIX 0x0000'0004
/**
* Mute all BGM sequences while this sound is playing.
*/
#define SOUND_SW_MUTE_BGM 0x0000'0008
/**
* Offset to shift to access @see SOUND_SW_RANDOM_PITCH_MASK
*/
@@ -82,10 +87,21 @@
*/
#define SOUND_SW_IGNORE_DOLBY 0x0000'2000
/**
* Unsure. Relates to Z2 pooling of sound handles.
*/
#define SOUND_SW_POOL_FLAG_1 0x0000'4000
/**
* Unsure. Relates to Z2 pooling of sound handles.
*/
#define SOUND_SW_POOL_FLAG_2 0x0000'8000
/**
* 3-bit mask used to select a volume distance/falloff class for this sound.
*/
#define SOUND_SW_VOL_DIST_BIT_MASK 0x0007'0000
#define SOUND_SW_VOL_DIST_BIT_OFFSET 16
/**
* Limit minimum volume of this sound (after distance falloff) to 0.2.
@@ -97,6 +113,7 @@
* @see SOUND_SW_VOL_DIST_BIT_MASK must be zero for this to work.
*/
#define SOUND_SW_VOL_DIST_BIT_2_MASK 0x0070'0000
#define SOUND_SW_VOL_DIST_BIT_2_OFFSET 20
/**
* Mark sound as "far away" or "culled" when at max distance (selected by distance class).
@@ -290,13 +307,17 @@ struct JAUSoundTableGroup {
*
*/
struct JAUSoundTable : public JASGlobalInstance<JAUSoundTable> {
#if TARGET_PC
using SoundTableReplacementSlot = dusk::mods::svc::audio_res::bst::SoundTableReplacementSlot;
#endif
JAUSoundTable(bool setInstance) : JASGlobalInstance<JAUSoundTable>(setInstance) {
}
~JAUSoundTable() {}
void init(void const*);
u8 getTypeID(JAISoundID) const;
JAUSoundTableItem* getData(JAISoundID) const;
u8 getTypeID(JAISoundID IF_DUSK_ARG(SoundTableReplacementSlot const*)) const;
JAUSoundTableItem DUSK_CONST* getData(JAISoundID IF_DUSK_ARG(SoundTableReplacementSlot const*)) const;
int getNumGroups_inSection(u8) const;
int getNumItems_inGroup(u8, u8) const;
@@ -29,7 +29,7 @@ struct JAUStreamFileTable {
*
*/
struct JAUStreamDataMgr_StreamFileTable : public JAIStreamDataMgr, JAUStreamFileTable {
virtual s32 getStreamFileEntry(JAISoundID);
virtual s32 getStreamFileEntry(JAISoundID IF_DUSK_ARG(StreamReplacementSlot2 const*));
virtual ~JAUStreamDataMgr_StreamFileTable() {}
};
+3 -2
View File
@@ -3,6 +3,7 @@
#include "JSystem/JAudio2/JAISe.h"
#include "JSystem/JAudio2/JAIAudience.h"
#include "JSystem/JAudio2/JAISeMgr.h"
#include "dusk/mods/svc/audio_res/bst.hpp"
JAISe::JAISe(JAISeMgr* seMgr, JAISoundStrategyMgr<JAISe>* soundStrategyMgr, u32 priority) : JSULink<JAISe>(this) {
inner_.mSoundStrategyMgr = soundStrategyMgr;
@@ -129,10 +130,10 @@ bool JAISe::JAISound_tryDie_() {
return false;
}
void JAISe::JAISeMgr_startID_(JAISoundID id, const JGeometry::TVec3<f32>* posPtr, JAIAudience* audience) {
void JAISe::JAISeMgr_startID_(JAISoundID id, const JGeometry::TVec3<f32>* posPtr, JAIAudience* audience IF_DUSK_ARG(std::shared_ptr<SoundEffectReplacementSlot> replacement)) {
JUT_ASSERT(221, inner_.track.getStatus() == JASTrack::STATUS_FREE);
start_JAISound_(id, posPtr, audience);
start_JAISound_(id, posPtr, audience IF_DUSK_ARG(std::static_pointer_cast<SoundTableReplacementSlot>(replacement)));
inner_.field_0x26c = 0;
if (inner_.mSoundStrategyMgr) {
inner_.field_0x278 = inner_.mSoundStrategyMgr->calc(id);
+5 -4
View File
@@ -4,6 +4,7 @@
#include "JSystem/JAudio2/JAISoundHandles.h"
#include "JSystem/JAudio2/JAISoundInfo.h"
#include "JSystem/JAudio2/JASReport.h"
#include "dusk/mods/svc/audio_res/bst.hpp"
bool JAISeCategoryMgr::isUsingSeqData(const JAISeqDataRegion& seqDataRegion) {
{
@@ -284,7 +285,7 @@ void JAISeMgr::mixOut() {
}
}
bool JAISeMgr::startSound(JAISoundID id, JAISoundHandle* handle, const JGeometry::TVec3<f32>* posPtr) {
bool JAISeMgr::startSound(JAISoundID id, JAISoundHandle* handle, const JGeometry::TVec3<f32>* posPtr IF_DUSK_ARG(std::shared_ptr<dusk::mods::svc::audio_res::bst::SoundEffectReplacementSlot> replacement)) {
if (handle && *handle) {
(*handle)->stop();
}
@@ -294,7 +295,7 @@ bool JAISeMgr::startSound(JAISoundID id, JAISoundHandle* handle, const JGeometry
u32 category;
if (soundInfoPtr != NULL) {
category = soundInfoPtr->getCategory(id);
priority = soundInfoPtr->getPriority(id);
priority = soundInfoPtr->getPriority(id IF_DUSK_ARG(replacement.get()));
} else {
category = id.id_.info.type.parts.groupID;
priority = 0;
@@ -309,10 +310,10 @@ bool JAISeMgr::startSound(JAISoundID id, JAISoundHandle* handle, const JGeometry
}
JAIAudience* audiencePtr = getAudience(category);
se->JAISeMgr_startID_(id, posPtr, audiencePtr);
se->JAISeMgr_startID_(id, posPtr, audiencePtr IF_DUSK_ARG(replacement));
if (soundInfoPtr != NULL) {
soundInfoPtr->getSeInfo(id, se);
soundInfoPtr->getSeInfo(id, se IF_DUSK_ARG(replacement.get()));
}
if (handle != NULL) {
+1 -1
View File
@@ -28,7 +28,7 @@ void JAISeq::JAISeqMgr_startID_(JAISoundID id, const JGeometry::TVec3<f32>* posP
JAIAudience* audience, int category, int param_4) {
inner_.field_0x39c = category;
reserveChildTracks_(param_4);
start_JAISound_(id, posPtr, audience);
start_JAISound_(id, posPtr, audience IF_DUSK_ARG(nullptr));
if (inner_.strategyMgr) {
field_0x3a8 = inner_.strategyMgr->calc(id);
+4 -3
View File
@@ -63,7 +63,7 @@ void JAISoundParams::mixOutAll(const JASSoundParams& inParams, JASSoundParams* o
JAISound::JAISound() : params_() {}
void JAISound::start_JAISound_(JAISoundID id, const JGeometry::TVec3<f32>* posPtr, JAIAudience* audience) {
void JAISound::start_JAISound_(JAISoundID id, const JGeometry::TVec3<f32>* posPtr, JAIAudience* audience IF_DUSK_ARG(std::shared_ptr<SoundTableReplacementSlot> replacement)) {
handle_ = NULL;
soundID_ = id;
status_.init();
@@ -72,9 +72,10 @@ void JAISound::start_JAISound_(JAISoundID id, const JGeometry::TVec3<f32>* posPt
audience_ = audience;
prepareCount_ = 0;
count_ = 0;
IF_DUSK(this->replacement = std::move(replacement));
if (posPtr != NULL && audience_ != NULL) {
audible_ = audience_->newAudible(*posPtr, soundID_, NULL, 0);
audible_ = audience_->newAudible(*posPtr, soundID_, NULL, 0 IF_DUSK_ARG(getReplacement()));
} else {
audible_ = NULL;
}
@@ -98,7 +99,7 @@ void JAISound::newAudible(const JGeometry::TVec3<f32>& pos,
}
JUT_ASSERT(157, audience_);
audible_ = audience_->newAudible(pos, soundID_, param_1, param_2);
audible_ = audience_->newAudible(pos, soundID_, param_1, param_2 IF_DUSK_ARG(getReplacement()));
}
void JAISound::stop(u32 fadeTime) {
+3 -2
View File
@@ -5,6 +5,7 @@
#include "JSystem/JAudio2/JAISoundChild.h"
#include "JSystem/JAudio2/JAIStreamDataMgr.h"
#include "JSystem/JAudio2/JAIAudience.h"
#include "dusk/mods/svc/audio_res/bst.hpp"
static void JAIStream_JASAramStreamCallback_(u32 type, JASAramStream* aramStream, void* userData) {
JAIStream* stream = (JAIStream*)userData;
@@ -34,10 +35,10 @@ JAIStream::JAIStream(JAIStreamMgr* streamMgr, JAISoundStrategyMgr<JAIStream>* so
void JAIStream::JAIStreamMgr_startID_(JAISoundID id, s32 streamFileEntry,
const JGeometry::TVec3<f32>* posPtr, JAIAudience* audience,
int category) {
int category IF_DUSK_ARG(std::shared_ptr<dusk::mods::svc::audio_res::bst::StreamReplacementSlot> replacement)) {
field_0x298 = category;
field_0x294 = streamFileEntry;
start_JAISound_(id, posPtr, audience);
start_JAISound_(id, posPtr, audience IF_DUSK_ARG(std::static_pointer_cast<SoundTableReplacementSlot>(replacement)));
field_0x290 = 0;
if (field_0x2c0 != NULL) {
+4 -4
View File
@@ -14,13 +14,13 @@ JAIStreamMgr::JAIStreamMgr(bool setInstance) : JASGlobalInstance<JAIStreamMgr>(s
mActivity.init();
}
bool JAIStreamMgr::startSound(JAISoundID id, JAISoundHandle* handle, const JGeometry::TVec3<f32>* posPtr) {
bool JAIStreamMgr::startSound(JAISoundID id, JAISoundHandle* handle, const JGeometry::TVec3<f32>* posPtr IF_DUSK_ARG(std::shared_ptr<dusk::mods::svc::audio_res::bst::StreamReplacementSlot> replacement)) {
JUT_ASSERT(37, streamDataMgr_);
if (handle != NULL && *handle) {
(*handle)->stop();
}
s32 streamFileEntry = streamDataMgr_->getStreamFileEntry(id);
s32 streamFileEntry = streamDataMgr_->getStreamFileEntry(id IF_DUSK_ARG(replacement.get()));
if (streamFileEntry < 0) {
JUT_WARN(46, "Cannot find the stream file entry for ID:%08x\n", id.id_.composite_)
return false;
@@ -38,9 +38,9 @@ bool JAIStreamMgr::startSound(JAISoundID id, JAISoundHandle* handle, const JGeom
return false;
}
stream->JAIStreamMgr_startID_(id, streamFileEntry, posPtr, mAudience, category);
stream->JAIStreamMgr_startID_(id, streamFileEntry, posPtr, mAudience, category IF_DUSK_ARG(replacement));
if (soundInfo != NULL) {
soundInfo->getStreamInfo(id, stream);
soundInfo->getStreamInfo(id, stream IF_DUSK_ARG(replacement.get()));
}
if (handle != NULL) {
+6 -1
View File
@@ -47,7 +47,12 @@ namespace {
mStreamFileDVDEntryNums[i] = DVDConvertPathToEntrynum(stack_14.getFilePath(i));
}
}
virtual s32 getStreamFileEntry(JAISoundID id) {
virtual s32 getStreamFileEntry(JAISoundID id IF_DUSK_ARG(StreamReplacementSlot2 const* replacement)) {
#if TARGET_PC
if (replacement) {
CRASH("TStreamDataMgr::getStreamFileEntry not implemented for replacements");
}
#endif
u32 short_id = id.id_.info.waveID;
if (short_id >= mNumStreamFiles) {
return -1;
+14 -2
View File
@@ -6,6 +6,8 @@
#include "JSystem/JAudio2/JAUSoundTable.h"
#include "dusk/mods/svc/audio_res/bst.hpp"
void JAUSoundTable::init(void const* param_0) {
if (param_0 != NULL) {
field_0x0.init(param_0);
@@ -14,11 +16,16 @@ void JAUSoundTable::init(void const* param_0) {
}
}
u8 JAUSoundTable::getTypeID(JAISoundID param_0) const {
u8 JAUSoundTable::getTypeID(JAISoundID param_0 IF_DUSK_ARG(SoundTableReplacementSlot const* replacement)) const {
#if DUSK_AUDIO_DISABLED
if (this == NULL) {
return 0xff;
}
#endif
#if TARGET_PC
if (replacement) {
return replacement->get_type_id();
}
#endif
if (param_0.isAnonymous()) {
return 0xff;
@@ -34,11 +41,16 @@ u8 JAUSoundTable::getTypeID(JAISoundID param_0) const {
return group->getTypeID(param_0.id_.info.waveID);
}
JAUSoundTableItem* JAUSoundTable::getData(JAISoundID param_0) const {
JAUSoundTableItem DUSK_CONST* JAUSoundTable::getData(JAISoundID param_0 IF_DUSK_ARG(SoundTableReplacementSlot const* replacement)) const {
#if DUSK_AUDIO_DISABLED
if (this == NULL) {
return NULL;
}
#endif
#if TARGET_PC
if (replacement) {
return &replacement->item;
}
#endif
if (param_0.isAnonymous()) {
return NULL;
@@ -31,7 +31,12 @@ const char* JAUStreamFileTable::getFilePath(int index) const {
return (char*)(data + *(int*)(data + 8 + (index * sizeof(s32))));
}
s32 JAUStreamDataMgr_StreamFileTable::getStreamFileEntry(JAISoundID soundId) {
s32 JAUStreamDataMgr_StreamFileTable::getStreamFileEntry(JAISoundID soundId IF_DUSK_ARG(StreamReplacementSlot2 const* replacement)) {
#if TARGET_PC
if (replacement) {
CRASH("JAUStreamDataMgr_StreamFileTable::getStreamFileEntry not implemented for replacements");
}
#endif
const char* filePath = getFilePath(soundId.id_.info.waveID);
if (filePath == NULL) {
return -1;