d_snd_bgm_harp_data OK

This commit is contained in:
robojumper
2025-06-29 22:48:44 +02:00
parent d36d8ac2ac
commit 69cdf95057
6 changed files with 325 additions and 20 deletions
+5 -2
View File
@@ -2698,11 +2698,14 @@ d/snd/d_snd_bgm_sound.cpp:
.text start:0x80379D20 end:0x8037BA68 align:16
.sbss start:0x80575D88 end:0x80575D90
d/snd/d_snd_bgm_data_mgr.cpp:
.text start:0x8037BA70 end:0x8037C518 align:16
d/snd/d_snd_bgm_battle_data_mgr.cpp:
.text start:0x8037BA70 end:0x8037BEA8 align:16
.data start:0x80549148 end:0x80549158
.sdata start:0x805742F0 end:0x805742F8
d/snd/d_snd_bgm_harp_data.cpp:
.text start:0x8037BEB0 end:0x8037C518 align:16
d/snd/d_snd_bgm_mml_parser_base.cpp:
.text start:0x8037C520 end:0x8037D014 align:16
.data start:0x80549158 end:0x80549168
+17 -17
View File
@@ -20781,23 +20781,23 @@ fn_8037BD80 = .text:0x8037BD80; // type:function size:0x4
fn_8037BD90 = .text:0x8037BD90; // type:function size:0x4C
fn_8037BDE0 = .text:0x8037BDE0; // type:function size:0x5C
fn_8037BE40 = .text:0x8037BE40; // type:function size:0x68
fn_8037BEB0 = .text:0x8037BEB0; // type:function size:0x7C
fn_8037BF30 = .text:0x8037BF30; // type:function size:0x10
fn_8037BF40 = .text:0x8037BF40; // type:function size:0x64
fn_8037BFB0 = .text:0x8037BFB0; // type:function size:0x48
fn_8037C000 = .text:0x8037C000; // type:function size:0x30
fn_8037C030 = .text:0x8037C030; // type:function size:0x14
fn_8037C050 = .text:0x8037C050; // type:function size:0x70
fn_8037C0C0 = .text:0x8037C0C0; // type:function size:0x64
fn_8037C130 = .text:0x8037C130; // type:function size:0x124
fn_8037C260 = .text:0x8037C260; // type:function size:0x14
fn_8037C280 = .text:0x8037C280; // type:function size:0x34
fn_8037C2C0 = .text:0x8037C2C0; // type:function size:0x34
fn_8037C300 = .text:0x8037C300; // type:function size:0x68
fn_8037C370 = .text:0x8037C370; // type:function size:0x34
fn_8037C3B0 = .text:0x8037C3B0; // type:function size:0x58
fn_8037C410 = .text:0x8037C410; // type:function size:0x60
setHarpPitchSeqVars = .text:0x8037C470; // type:function size:0xA8
__ct__27dSndBgmDataHarpVarSetBase_cFl = .text:0x8037BEB0; // type:function size:0x7C
__ct__20dSndBgmDataHarpVar_cFv = .text:0x8037BF30; // type:function size:0x10 scope:weak
__dt__27dSndBgmDataHarpVarSetBase_cFv = .text:0x8037BF40; // type:function size:0x64
resetVars__27dSndBgmDataHarpVarSetBase_cFv = .text:0x8037BFB0; // type:function size:0x48
addVar__27dSndBgmDataHarpVarSetBase_cFUc = .text:0x8037C000; // type:function size:0x30
__ct__21dSndBgmHarpDataBase_cFv = .text:0x8037C030; // type:function size:0x14
resetVars__21dSndBgmHarpDataBase_cFv = .text:0x8037C050; // type:function size:0x70
getIdxForPosition__21dSndBgmHarpDataBase_cFl = .text:0x8037C0C0; // type:function size:0x64
addVar__21dSndBgmHarpDataBase_cFlll = .text:0x8037C130; // type:function size:0x124
setField_0x08__21dSndBgmHarpDataBase_cFl = .text:0x8037C260; // type:function size:0x14
getUsableVarSet__21dSndBgmHarpDataBase_cFl = .text:0x8037C280; // type:function size:0x34
getVarSet__21dSndBgmHarpDataBase_cFl = .text:0x8037C2C0; // type:function size:0x34
__ct__17dSndBgmHarpData_cFv = .text:0x8037C300; // type:function size:0x68
__ct__23dSndBgmDataHarpVarSet_cFv = .text:0x8037C370; // type:function size:0x34 scope:weak
__dt__23dSndBgmDataHarpVarSet_cFv = .text:0x8037C3B0; // type:function size:0x58 scope:weak
__dt__17dSndBgmHarpData_cFv = .text:0x8037C410; // type:function size:0x60
writeSeqVars__17dSndBgmHarpData_cFl = .text:0x8037C470; // type:function size:0xA8
__ct__18dSndBgmMmlParser_cFPQ34nw4r3snd18SoundArchivePlayerPQ34nw4r3snd12SoundArchive = .text:0x8037C520; // type:function size:0x20
initTrack__18dSndBgmMmlParser_cFlUl = .text:0x8037C540; // type:function size:0x34
loadAndParse__18dSndBgmMmlParser_cFUlUlb = .text:0x8037C580; // type:function size:0x98
+2 -1
View File
@@ -757,7 +757,8 @@ config.libs = [
Object(NonMatching, "d/snd/d_snd_bgm_sound_callbacks.cpp"),
Object(NonMatching, "d/snd/d_snd_bgm_sound_battle_callbacks.cpp"),
Object(NonMatching, "d/snd/d_snd_bgm_sound.cpp"),
Object(NonMatching, "d/snd/d_snd_bgm_data_mgr.cpp"),
Object(NonMatching, "d/snd/d_snd_bgm_battle_data_mgr.cpp"),
Object(Matching, "d/snd/d_snd_bgm_harp_data.cpp"),
Object(Matching, "d/snd/d_snd_bgm_mml_parser_base.cpp"),
Object(NonMatching, "d/snd/d_snd_bgm_mml_parsers.cpp"),
Object(NonMatching, "d/snd/d_snd_small_effect_mgr.cpp"),
+132
View File
@@ -0,0 +1,132 @@
#ifndef D_SND_BGM_HARP_DATA_H
#define D_SND_BGM_HARP_DATA_H
#include "common.h"
/**
* This file deals with the pitch of the Goddess' Harp when Link
* is freely strumming. In this case the pitch of the strings
* is adjusted to match the key of background music through sequence variables.
* When Link strums the harp, 12 strings can be heard, but it's actually only four
* notes of the same chord spanning three octaves.
*
* I haven't yet investigated all the data, but a typical chord Link might play
* is Cmaj^7, consisting of C-E-G-B. Link actually plays:
* G3-C4-E4-G4-B4-C5-E5-G5-B5-C6-E6-G6
* B3 is missing, possibly to prevent dissonance at the ends of the scale.
* (Sealed Grounds, before Demise fight, no actual BGM)
*/
/**
* Contains a single Seq sound var controlling the pitch of a subset of harp strings
* Size: 0x02
*/
struct dSndBgmDataHarpVar_c {
dSndBgmDataHarpVar_c() : field_0x00(0), field_0x01(0) {}
void reset() {
field_0x00 = 0;
field_0x01 = 0;
}
void onFlag() {
field_0x00 |= 1;
}
/* 0x00 */ u8 field_0x00; // flags
/* 0x01 */ s8 field_0x01; // var
};
/**
* Contains Seq sound vars for all harp strings, represents a "key" in the bgm music
* Size: 0x0C
*/
class dSndBgmDataHarpVarSetBase_c {
public:
dSndBgmDataHarpVarSetBase_c(s32 count);
~dSndBgmDataHarpVarSetBase_c();
void resetVars();
void addVar(u8 value);
s32 getPosition() const {
return mPosition;
}
void setPosition(s32 position) {
mPosition = position;
}
s32 getCount() const {
return mCount;
}
s32 getMax() const {
return mMax;
}
dSndBgmDataHarpVar_c *getVar(s32 idx) {
if (idx >= getCount()) {
return nullptr;
}
return &mpVars[idx];
}
dSndBgmDataHarpVar_c *getUnusedVar() {
if (mCount >= mMax) {
return nullptr;
}
return &mpVars[mCount];
}
private:
/* 0x00 */ dSndBgmDataHarpVar_c *mpVars;
/* 0x04 */ s32 mPosition;
/* 0x08 */ s16 mMax;
/* 0x0A */ s16 mCount;
};
class dSndBgmDataHarpVarSet_c : public dSndBgmDataHarpVarSetBase_c {
public:
dSndBgmDataHarpVarSet_c() : dSndBgmDataHarpVarSetBase_c(4) {}
private:
};
/**
* Contains parsed seq data for harp strings for a single bgm sound
*/
class dSndBgmHarpDataBase_c {
public:
dSndBgmHarpDataBase_c();
void resetVars();
s32 getIdxForPosition(s32 position);
dSndBgmDataHarpVarSetBase_c *getUsableVarSet(s32 idx);
void addVar(s32 position, s32 value, s32 unk);
void setField_0x08(s32 value);
protected:
dSndBgmDataHarpVarSetBase_c *getVarSet(s32 idx);
/* 0x00 */ dSndBgmDataHarpVarSetBase_c *mpVarSets;
/* 0x04 */ s16 mMax;
/* 0x06 */ s16 mCount;
/* 0x08 */ s32 field_0x08;
};
class dSndBgmHarpData_c : public dSndBgmHarpDataBase_c {
public:
dSndBgmHarpData_c();
~dSndBgmHarpData_c();
/**
* Writes the Seq sound variables that control the pitch
* of the individual harp strings.
*/
void writeSeqVars(s32 idx);
private:
static const u32 NUM_SETS = 300;
};
#endif
+4
View File
@@ -52,6 +52,10 @@ namespace nw4r { namespace snd
mSound->ReadVariable(varNo, value);
}
static bool WriteGlobalVariable(int varNo, s16 value) {
return detail::SeqSound::WriteGlobalVariable(varNo, value);
}
void SetTrackMute(u32 trackFlags, SeqMute mute) {
if (IsAttachedSound())
mSound->SetTrackMute(trackFlags, mute);
+165
View File
@@ -0,0 +1,165 @@
#include "d/snd/d_snd_bgm_harp_data.h"
#include "common.h"
#include "nw4r/snd/snd_SeqSoundHandle.h"
dSndBgmDataHarpVarSetBase_c::dSndBgmDataHarpVarSetBase_c(s32 count) {
mPosition = -1;
mMax = count;
mCount = 0;
mpVars = new dSndBgmDataHarpVar_c[count];
resetVars();
}
dSndBgmDataHarpVarSetBase_c::~dSndBgmDataHarpVarSetBase_c() {
delete[] mpVars;
}
void dSndBgmDataHarpVarSetBase_c::resetVars() {
mCount = 0;
mPosition = -1;
for (int i = 0; i < mMax; i++) {
mpVars[i].reset();
}
}
void dSndBgmDataHarpVarSetBase_c::addVar(u8 value) {
if (mCount < mMax) {
mpVars[mCount].field_0x01 = value;
mCount++;
}
}
dSndBgmHarpDataBase_c::dSndBgmHarpDataBase_c() : mMax(0), mCount(0), field_0x08(0) {}
void dSndBgmHarpDataBase_c::resetVars() {
mCount = 0;
field_0x08 = 0;
for (int i = 0; i < mMax; i++) {
mpVarSets[i].resetVars();
}
}
s32 dSndBgmHarpDataBase_c::getIdxForPosition(s32 position) {
if (position < 0) {
return 0;
}
if (mpVarSets[0].getPosition() > position) {
return 0;
}
for (int i = mCount - 1; i > 0; i--) {
if (mpVarSets[i].getPosition() <= position) {
return i;
}
}
return 0;
}
void dSndBgmHarpDataBase_c::addVar(s32 position, s32 value, s32 unk) {
if (position < 0) {
return;
}
if (value <= 0) {
return;
}
if (field_0x08 > 0) {
return;
}
if (mCount > mMax) {
return;
}
// Look at the set that might not be full yet
dSndBgmDataHarpVarSetBase_c *set = getVarSet(mCount);
if (set->getPosition() >= 0 && set->getPosition() < position) {
// If it's not full but it doesn't match the position,
// advance either way
set++;
mCount++;
}
// Set position for new set
if (set->getPosition() < 0) {
// Make sure set positions are strictly monotonically increasing (1),
// do not record e.g. a fifth value for the same set
if (mCount > 0 && set[-1].getPosition() >= position) {
return;
}
set->setPosition(position);
}
dSndBgmDataHarpVar_c *var = set->getUnusedVar();
if (var != nullptr) {
if (unk == 0x7F) {
var->onFlag();
}
set->addVar(value);
if (set->getCount() >= set->getMax()) {
// If the set is full, continue with the next set.
// Condition (1) above will make sure that the next
// set gets a strictly higher position, so there are
// no sets with the same position.
mCount++;
}
}
}
void dSndBgmHarpDataBase_c::setField_0x08(s32 value) {
if (value < 0) {
value = 0;
}
field_0x08 = value;
}
dSndBgmDataHarpVarSetBase_c *dSndBgmHarpDataBase_c::getUsableVarSet(s32 idx) {
if (idx < 0) {
return nullptr;
}
if (idx >= mCount) {
return nullptr;
}
return &mpVarSets[idx];
}
dSndBgmDataHarpVarSetBase_c *dSndBgmHarpDataBase_c::getVarSet(s32 idx) {
if (idx < 0) {
return nullptr;
}
if (idx >= mMax) {
return nullptr;
}
return &mpVarSets[idx];
}
dSndBgmHarpData_c::dSndBgmHarpData_c() {
mpVarSets = new dSndBgmDataHarpVarSet_c[NUM_SETS];
mMax = NUM_SETS;
resetVars();
}
dSndBgmHarpData_c::~dSndBgmHarpData_c() {
delete[] mpVarSets;
}
void dSndBgmHarpData_c::writeSeqVars(s32 idx) {
if (idx < 0) {
return;
}
if (idx >= mCount) {
return;
}
for (int i = 0; i < mpVarSets[idx].getCount(); i++) {
nw4r::snd::SeqSoundHandle::WriteGlobalVariable(10 + i, mpVarSets[idx].getVar(i)->field_0x01);
}
}