Add CScriptMidi

This commit is contained in:
Henrique Gemignani Passos Lima 2022-10-22 00:40:29 +03:00
parent 890d2bb2d1
commit 1b5ee3bee8
No known key found for this signature in database
GPG Key ID: E224F951761145F8
10 changed files with 149 additions and 8 deletions

View File

@ -3,8 +3,8 @@
.section .data
.balign 8
.global lbl_803E7048
lbl_803E7048:
.global __vt__11CScriptMidi
__vt__11CScriptMidi:
# ROM: 0x3E4048
.4byte 0
.4byte 0
@ -202,9 +202,9 @@ __dt__11CScriptMidiFv:
/* 8020BBDC 00208B3C 93 C1 00 08 */ stw r30, 8(r1)
/* 8020BBE0 00208B40 7C 7E 1B 79 */ or. r30, r3, r3
/* 8020BBE4 00208B44 41 82 00 48 */ beq lbl_8020BC2C
/* 8020BBE8 00208B48 3C 80 80 3E */ lis r4, lbl_803E7048@ha
/* 8020BBE8 00208B48 3C 80 80 3E */ lis r4, __vt__11CScriptMidi@ha
/* 8020BBEC 00208B4C C0 22 B1 B0 */ lfs f1, lbl_805ACED0@sda21(r2)
/* 8020BBF0 00208B50 38 04 70 48 */ addi r0, r4, lbl_803E7048@l
/* 8020BBF0 00208B50 38 04 70 48 */ addi r0, r4, __vt__11CScriptMidi@l
/* 8020BBF4 00208B54 90 1E 00 00 */ stw r0, 0(r30)
/* 8020BBF8 00208B58 4B FF FD 45 */ bl StopInternal__11CScriptMidiFf
/* 8020BBFC 00208B5C 34 1E 00 34 */ addic. r0, r30, 0x34
@ -324,9 +324,9 @@ Accept__11CScriptMidiFR8IVisitor:
/* 8020BD84 00208CE4 7C 87 23 78 */ mr r7, r4
/* 8020BD88 00208CE8 38 81 00 08 */ addi r4, r1, 8
/* 8020BD8C 00208CEC 4B E4 55 99 */ bl "__ct__7CEntityF9TUniqueIdRC11CEntityInfobRCQ24rstl66basic_string<c,Q24rstl14char_traits<c>,Q24rstl17rmemory_allocator>"
/* 8020BD90 00208CF0 3C 60 80 3E */ lis r3, lbl_803E7048@ha
/* 8020BD90 00208CF0 3C 60 80 3E */ lis r3, __vt__11CScriptMidi@ha
/* 8020BD94 00208CF4 3C 80 43 53 */ lis r4, 0x43534E47@ha
/* 8020BD98 00208CF8 38 03 70 48 */ addi r0, r3, lbl_803E7048@l
/* 8020BD98 00208CF8 38 03 70 48 */ addi r0, r3, __vt__11CScriptMidi@l
/* 8020BD9C 00208CFC 38 61 00 0C */ addi r3, r1, 0xc
/* 8020BDA0 00208D00 90 1D 00 00 */ stw r0, 0(r29)
/* 8020BDA4 00208D04 38 04 4E 47 */ addi r0, r4, 0x43534E47@l

View File

@ -312,7 +312,7 @@ LIBS = [
"MetroidPrime/CVisorFlare",
"MetroidPrime/Enemies/CFlaahgraPlants",
"MetroidPrime/CWorldTransManager",
"MetroidPrime/ScriptObjects/CScriptMidi",
["MetroidPrime/ScriptObjects/CScriptMidi", False],
"MetroidPrime/ScriptObjects/CScriptStreamedAudio",
"MetroidPrime/CRagDoll",
"MetroidPrime/Player/CGameOptions",

View File

@ -0,0 +1,15 @@
#ifndef _CMIDIMANAGER
#define _CMIDIMANAGER
#include "Kyoto/Audio/CSfxHandle.hpp"
class CMidiManager {
public:
class CMidiWrapper {};
class CMidiData {};
static CSfxHandle Play(const CMidiData&, unsigned short fadeTime, bool stopExisting, short volume);
static void Stop(const CSfxHandle&, unsigned short);
};
#endif // _CMIDIMANAGER

View File

@ -36,10 +36,22 @@ inline short FtoS(register float in) {
}
return *ptr;
}
inline ushort FtoUS(register float in) {
ushort a;
register ushort* ptr = &a;
asm {
psq_st in, 0(ptr), 1, OS_FASTCAST_U16
}
return *ptr;
}
#else
inline uchar ToUint8(float in) { return static_cast< uchar >(in); }
inline float ToReal32(uchar in) { return static_cast< float >(in); }
inline short FtoS(float in) { return static_cast< short >(in); }
inline ushort FtoUS(float in) { return static_cast< ushort >(in); }
#endif
inline int ToInt32(float in) { return static_cast< int >(in); }

View File

@ -99,6 +99,7 @@ public:
EOcclusionState x10dc_occlusionState;
};
CAssetId GetAreaAssetId() const { return x84_mrea; }
const CAreaFog* GetAreaFog() const { return x12c_postConstructed->x10c4_areaFog.get(); }
CAreaFog* AreaFog() { return x12c_postConstructed->x10c4_areaFog.get(); }
EOcclusionState GetOcclusionState() const { return x12c_postConstructed->x10dc_occlusionState; }

View File

@ -58,8 +58,12 @@ class CInGameTweakManager {
public:
CInGameTweakManager();
bool HasTweakValue(const rstl::string& name) const;
const CTweakValue* GetTweakValue(const rstl::string& name) const;
bool ReadFromMemoryCard(const rstl::string&);
static rstl::string GetIdentifierForMidiEvent(CAssetId world, CAssetId area, const rstl::string& midiObj);
private:
rstl::vector< CTweakValue > x0_values;
};

View File

@ -0,0 +1,29 @@
#ifndef _CSCRIPTMIDI
#define _CSCRIPTMIDI
#include "MetroidPrime/CEntity.hpp"
#include "Kyoto/Audio/CMidiManager.hpp"
class CScriptMidi : public CEntity {
public:
CScriptMidi(TUniqueId id, const CEntityInfo& info, const rstl::string& name, bool active,
CAssetId csng, float, float, int);
~CScriptMidi() override;
void Stop(CStateManager& mgr, float fadeTime);
void Play(CStateManager& mgr, float fadeTime);
void Accept(IVisitor& visitor) override;
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) override;
private:
TToken< CMidiManager::CMidiData > x34_song;
CSfxHandle x3c_handle;
float x40_fadeInTime;
float x44_fadeOutTime;
ushort x48_volume;
void StopInternal(float fadeTime);
};
#endif // _CSCRIPTMIDI

View File

@ -6,6 +6,7 @@ extern "C" {
#endif
#define OS_FASTCAST_U8 2
#define OS_FASTCAST_U16 3
#define OS_FASTCAST_S16 5
#ifdef __cplusplus

View File

@ -30,7 +30,7 @@ TUniqueId CScriptCameraWaypoint::GetRandomNextWaypointId(const CStateManager& mg
rstl::vector< TUniqueId > candidateIds;
rstl::vector< SConnection >::const_iterator conn = x20_conns.begin();
for (; conn != x20_conns.end(); ++conn) {
if (conn->x0_state == kSS_Arrived && conn->x4_msg == kSM_Next) {
TUniqueId uid = mgr.GetIdForScript(conn->x8_objId);

View File

@ -0,0 +1,79 @@
#include "MetroidPrime/ScriptObjects/CScriptMidi.hpp"
#include "MetroidPrime/CGameArea.hpp"
#include "MetroidPrime/CInGameTweakManager.hpp"
#include "MetroidPrime/CWorld.hpp"
CScriptMidi::CScriptMidi(TUniqueId id, const CEntityInfo& info, const rstl::string& name,
bool active, CAssetId csng, float fadeIn, float fadeOut, int volume)
: CEntity(id, info, active, name)
, x34_song(gpSimplePool->GetObj(SObjectTag('CSNG', csng)))
, x3c_handle()
, x40_fadeInTime(fadeIn)
, x44_fadeOutTime(fadeOut)
, x48_volume(volume) {}
void CScriptMidi::Accept(IVisitor& visitor) { visitor.Visit(*this); }
void CScriptMidi::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId,
CStateManager& stateMgr) {
CEntity::AcceptScriptMsg(msg, objId, stateMgr);
switch (msg) {
case kSM_Play:
if (GetActive()) {
Play(stateMgr, x40_fadeInTime);
}
break;
case kSM_Stop:
if (GetActive()) {
Stop(stateMgr, x44_fadeOutTime);
}
break;
case kSM_Deactivate:
StopInternal(0.f);
break;
default:
break;
}
}
CScriptMidi::~CScriptMidi() { StopInternal(0.f); }
void CScriptMidi::Play(CStateManager& mgr, float fadeTime) {
short volume = x48_volume;
const CWorld* wld = mgr.GetWorld();
const CGameArea& area = wld->GetAreaAlways(GetAreaIdAlways());
rstl::string twkName = CInGameTweakManager::GetIdentifierForMidiEvent(
wld->GetWorldAssetId(), area.GetAreaAssetId(), x10_name);
if (gpTweakManager->HasTweakValue(twkName)) {
const CTweakValue::Audio& audio = gpTweakManager->GetTweakValue(twkName)->GetAudio();
x34_song = gpSimplePool->GetObj(SObjectTag('CSNG', audio.GetResId()));
fadeTime = audio.GetFadeIn();
volume = static_cast< short >(audio.GetVolume() * 127.f);
}
x3c_handle = CMidiManager::Play(**x34_song, CCast::FtoUS(fadeTime * 1000.f), false, volume);
}
void CScriptMidi::Stop(CStateManager& mgr, float fadeTime) {
const CWorld* wld = mgr.GetWorld();
const CGameArea& area = wld->GetAreaAlways(GetAreaIdAlways());
const rstl::string twkName = CInGameTweakManager::GetIdentifierForMidiEvent(
wld->GetWorldAssetId(), area.GetAreaAssetId(), x10_name);
if (gpTweakManager->HasTweakValue(twkName)) {
const CTweakValue::Audio& audio = gpTweakManager->GetTweakValue(twkName)->GetAudio();
fadeTime = audio.GetFadeOut();
}
StopInternal(fadeTime);
}
void CScriptMidi::StopInternal(float fadeTime) {
if (x3c_handle != CSfxHandle::NullHandle()) {
CMidiManager::Stop(x3c_handle, CCast::FtoUS(fadeTime * 1000.f));
}
x3c_handle.Clear();
}