Skip to content

Commit

Permalink
tr2/music_main: refactor music track handling
Browse files Browse the repository at this point in the history
This refactors the way music is checked when requested to play tracks.
Some tracks require to be enforced such as from flip effects, while
others are tracked, such as from regular triggers. Tracked tracks will
not play in succession, provided the mode is the same when requesting
to play them.

Resolves #1899.
  • Loading branch information
lahm86 committed Nov 16, 2024
1 parent f4162df commit 36eec3d
Show file tree
Hide file tree
Showing 13 changed files with 96 additions and 43 deletions.
2 changes: 2 additions & 0 deletions docs/tr2/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
- fixed being unable to go from surface swimming to underwater swimming without first stopping (#1863, regression from 0.6)
- fixed pistols appearing in Lara's hands when entering the fly cheat during certain animations (#1874)
- fixed Lara continuing to walk after being killed if in that animation (#1880, regression from 0.1)
- fixed some music tracks looping while Lara remained on the same trigger tile (#1899, regression from 0.2)
- fixed some music tracks not playing if they were the last played track and the level had no ambience (#1899, regression from 0.2)

## [0.6](https://github.com/LostArtefacts/TRX/compare/tr2-0.5...tr2-0.6) - 2024-11-06
- added a fly cheat key (#1642)
Expand Down
4 changes: 2 additions & 2 deletions docs/tr2/progress.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions docs/tr2/progress.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4131,7 +4131,7 @@ typedef enum {
0x004553C0 0x001F + BOOL __cdecl S_Audio_Sample_OutIsTrackPlaying(int32_t track_id);
0x004553E0 0x0077 + bool __cdecl Music_Init(void);
0x00455460 0x0051 + void __cdecl Music_Shutdown(void);
0x00455500 0x006F + void __cdecl Music_Play(int16_t track_id, bool is_looped);
0x00455500 0x006F + void __cdecl Music_Legacy_Play(int16_t track_id, bool is_looped);
0x00455570 0x0039 + void __cdecl Music_Stop(void);
0x004555B0 0x0084 + bool __cdecl Music_PlaySynced(int32_t track_id);
0x00455640 0x0061 + int32_t __cdecl Music_GetFrames(void);
Expand Down Expand Up @@ -4249,7 +4249,7 @@ typedef enum {
0x0046408C - float g_RhwFactor = 335544320.0f; // 10*2**25
0x004640B0 - int32_t g_CineTrackID = 1;
0x004640B8 - int32_t g_CineTickRate = 0x8000; // 0x8000 = PHD_ONE/TICKS_PER_FRAME
0x004640BC - int16_t g_CD_TrackID = -1;
0x004640BC + int16_t g_CD_TrackID = -1;
0x004640C4 - int32_t g_FlipEffect = -1;
0x004641F0 - int32_t g_AssaultBestTime = -1;
0x004641F8 - void (*__cdecl g_EffectRoutines[32])(ITEM *item);
Expand Down
6 changes: 3 additions & 3 deletions src/tr2/decomp/decomp.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ int16_t __cdecl TitleSequence(void)

S_DisplayPicture("data/title.pcx", true);
if (g_GameFlow.title_track) {
Music_Play(g_GameFlow.title_track, true);
Music_Play(g_GameFlow.title_track, MPM_LOOPED);
}

GAME_FLOW_DIR dir = Inv_Display(INV_TITLE_MODE);
Expand Down Expand Up @@ -1127,7 +1127,7 @@ int32_t __cdecl Level_Initialise(
if (level_type == GFL_NORMAL || level_type == GFL_SAVED
|| level_type == GFL_DEMO) {
if (g_GF_MusicTracks[0]) {
Music_Play(g_GF_MusicTracks[0], 1);
Music_Play(g_GF_MusicTracks[0], MPM_LOOPED);
}
}
g_IsAssaultTimerActive = 0;
Expand Down Expand Up @@ -2876,7 +2876,7 @@ void __cdecl DisplayCredits(void)
memcpy(old_palette, g_GamePalette8, sizeof(old_palette));
memset(g_GamePalette8, 0, sizeof(g_GamePalette8));

Music_Play(MX_SKIDOO_THEME, false);
Music_Play(MX_SKIDOO_THEME, MPM_ALWAYS);

for (int32_t i = 0; i < 9; i++) {
char file_name[60];
Expand Down
2 changes: 1 addition & 1 deletion src/tr2/decomp/skidoo.c
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,7 @@ void __cdecl Skidoo_Animation(
const int32_t music_track =
M_IsArmed(skidoo_data) ? MX_BATTLE_THEME : MX_SKIDOO_THEME;
if (!(g_MusicTrackFlags[music_track] & IF_ONE_SHOT)) {
Music_Play(music_track, false);
Music_Play(music_track, MPM_ALWAYS);
g_LaraItem = g_LaraItem;
g_MusicTrackFlags[music_track] |= IF_ONE_SHOT;
}
Expand Down
2 changes: 1 addition & 1 deletion src/tr2/decomp/stats.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ int32_t __cdecl LevelStats(const int32_t level_num)
char buffer[100];
sprintf(buffer, "%02d:%02d:%02d", sec / 3600, (sec / 60) % 60, sec % 60);

Music_Play(g_GameFlow.level_complete_track, false);
Music_Play(g_GameFlow.level_complete_track, MPM_ALWAYS);

TempVideoAdjust(g_HiRes, 1.0);
FadeToPal(30, g_GamePalette8);
Expand Down
15 changes: 14 additions & 1 deletion src/tr2/game/music.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,25 @@

#include "global/types.h"

typedef enum {
MPM_ALWAYS,
MPM_LOOPED,
MPM_DELAYED,
MPM_TRACKED,
} MUSIC_PLAY_MODE;

bool __cdecl Music_Init(void);
void __cdecl Music_Shutdown(void);
void __cdecl Music_Play(int16_t track_id, bool is_looped);
void Music_Play(MUSIC_TRACK_ID track_id, MUSIC_PLAY_MODE mode);
void __cdecl Music_Stop(void);
bool __cdecl Music_PlaySynced(int16_t track_id);
double __cdecl Music_GetTimestamp(void);
void __cdecl Music_SetVolume(int32_t volume);
MUSIC_TRACK_ID Music_GetCurrentTrack(void);
MUSIC_TRACK_ID Music_GetLastPlayedTrack(void);
MUSIC_TRACK_ID Music_GetDelayedTrack(void);
void Music_Pause(void);
void Music_Unpause(void);

// TODO: eliminate
void __cdecl Music_Legacy_Play(int16_t track_id, bool is_looped);
55 changes: 46 additions & 9 deletions src/tr2/game/music/music_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#include <assert.h>

static MUSIC_TRACK_ID m_TrackCurrent = MX_INACTIVE;
static MUSIC_TRACK_ID m_TrackLastPlayed = MX_INACTIVE;
static MUSIC_TRACK_ID m_TrackDelayed = MX_INACTIVE;
static MUSIC_TRACK_ID m_TrackLooped = MX_INACTIVE;

static float m_MusicVolume = 0.0f;
Expand Down Expand Up @@ -65,9 +67,10 @@ static void M_StreamFinished(const int32_t stream_id, void *const user_data)
{
// When a stream finishes, play the remembered background BGM.
if (stream_id == m_AudioStreamID) {
m_TrackCurrent = MX_INACTIVE;
m_AudioStreamID = -1;
if (m_TrackLooped >= 0) {
Music_Play(m_TrackLooped, true);
Music_Play(m_TrackLooped, MPM_LOOPED);
}
}
}
Expand All @@ -88,6 +91,8 @@ bool __cdecl Music_Init(void)

finish:
m_TrackCurrent = MX_INACTIVE;
m_TrackLastPlayed = MX_INACTIVE;
m_TrackDelayed = MX_INACTIVE;
m_TrackLooped = MX_INACTIVE;
return result;
}
Expand All @@ -106,9 +111,23 @@ void __cdecl Music_Shutdown(void)
Audio_Stream_Close(m_AudioStreamID);
}

void __cdecl Music_Play(int16_t track_id, bool is_looped)
void __cdecl Music_Legacy_Play(int16_t track_id, bool is_looped)
{
if (track_id == m_TrackCurrent) {
Music_Play(track_id, is_looped ? MPM_LOOPED : MPM_ALWAYS);
}

void Music_Play(const MUSIC_TRACK_ID track_id, const MUSIC_PLAY_MODE mode)
{
if (track_id == m_TrackCurrent && mode != MPM_ALWAYS) {
return;
}

if (mode == MPM_TRACKED && track_id == m_TrackLastPlayed) {
return;
}

if (mode == MPM_DELAYED) {
m_TrackDelayed = track_id;
return;
}

Expand All @@ -127,24 +146,25 @@ void __cdecl Music_Play(int16_t track_id, bool is_looped)

const int32_t real_track_id = Music_GetRealTrack(track_id);
LOG_DEBUG(
"Playing track %d (real: %d), looped: %d", track_id, real_track_id,
is_looped);
"Playing track %d (real: %d), mode: %d", track_id, real_track_id, mode);

m_AudioStreamID = m_Backend->play(m_Backend, real_track_id);
if (m_AudioStreamID < 0) {
LOG_ERROR("Failed to create music stream for track %d", track_id);
goto finish;
}

Audio_Stream_SetIsLooped(m_AudioStreamID, is_looped);
Audio_Stream_SetIsLooped(m_AudioStreamID, mode == MPM_LOOPED);
Audio_Stream_SetVolume(m_AudioStreamID, m_MusicVolume);
Audio_Stream_SetFinishCallback(m_AudioStreamID, M_StreamFinished, NULL);

finish:
g_CD_TrackID = track_id;
m_TrackCurrent = track_id;
if (is_looped) {
m_TrackDelayed = MX_INACTIVE;
if (mode == MPM_LOOPED) {
m_TrackLooped = track_id;
} else {
m_TrackCurrent = track_id;
m_TrackLastPlayed = track_id;
}
}

Expand All @@ -154,6 +174,8 @@ void __cdecl Music_Stop(void)
return;
}
m_TrackCurrent = MX_INACTIVE;
m_TrackLastPlayed = MX_INACTIVE;
m_TrackDelayed = MX_INACTIVE;
m_TrackLooped = MX_INACTIVE;
M_StopActiveStream();
}
Expand All @@ -180,6 +202,21 @@ void __cdecl Music_SetVolume(int32_t volume)
}
}

MUSIC_TRACK_ID Music_GetCurrentTrack(void)
{
return m_TrackCurrent != MX_INACTIVE ? m_TrackCurrent : m_TrackLooped;
}

MUSIC_TRACK_ID Music_GetLastPlayedTrack(void)
{
return m_TrackLastPlayed;
}

MUSIC_TRACK_ID Music_GetDelayedTrack(void)
{
return m_TrackDelayed;
}

void Music_Pause(void)
{
if (m_AudioStreamID < 0) {
Expand Down
2 changes: 1 addition & 1 deletion src/tr2/game/objects/general/gong_bonger.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ void __cdecl GongBonger_Control(const int16_t item_num)

Item_Animate(item);
if (item->frame_num - g_Anims[item->anim_num].frame_base == 41) {
Music_Play(MX_REVEAL_1, 0);
Music_Play(MX_REVEAL_1, MPM_ALWAYS);
g_Camera.bounce -= 50;
}

Expand Down
2 changes: 1 addition & 1 deletion src/tr2/game/overlay.c
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ void __cdecl Overlay_AddDisplayPickup(const int16_t object_id)
{
if (object_id == O_SECRET_1 || object_id == O_SECRET_2
|| object_id == O_SECRET_3) {
Music_Play(g_GameFlow.secret_track, false);
Music_Play(g_GameFlow.secret_track, MPM_ALWAYS);
}

int32_t grid_x = -1;
Expand Down
42 changes: 22 additions & 20 deletions src/tr2/game/room.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,27 +115,29 @@ static void M_TriggerMusicTrack(
}
}

if (track != g_CD_TrackID) {
const int32_t timer = trigger->timer;
if (timer) {
g_CD_TrackID = track;
g_MusicTrackFlags[track] =
(g_MusicTrackFlags[track] & 0xFF00) | ((30 * timer) & 0xFF);
} else {
Music_Play(track, false);
}
} else {
int32_t timer = g_MusicTrackFlags[track] & 0xFF;
if (timer) {
timer--;
if (timer == 0) {
g_CD_TrackID = -1;
Music_Play(track, false);
}
g_MusicTrackFlags[track] =
(g_MusicTrackFlags[track] & 0xFF00) | (timer & 0xFF);
}
if (trigger->timer == 0) {
Music_Play(track, MPM_TRACKED);
return;
}

if (track != Music_GetDelayedTrack()) {
Music_Play(track, MPM_DELAYED);
g_MusicTrackFlags[track] = (g_MusicTrackFlags[track] & 0xFF00)
| ((FRAMES_PER_SECOND * trigger->timer) & 0xFF);
return;
}

int32_t timer = g_MusicTrackFlags[track] & 0xFF;
if (timer == 0) {
return;
}

timer--;
if (timer == 0) {
Music_Play(track, MPM_TRACKED);
}
g_MusicTrackFlags[track] =
(g_MusicTrackFlags[track] & 0xFF00) | (timer & 0xFF);
}

static bool M_TestLava(const ITEM *const item)
Expand Down
1 change: 0 additions & 1 deletion src/tr2/global/vars_decomp.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
#define g_RhwFactor (*(float*)0x0046408C) // = 335544320.0f
#define g_CineTrackID (*(int32_t*)0x004640B0) // = 1
#define g_CineTickRate (*(int32_t*)0x004640B8) // = 0x8000
#define g_CD_TrackID (*(int16_t*)0x004640BC) // = -1
#define g_FlipEffect (*(int32_t*)0x004640C4) // = -1
#define g_BoxLines (*(int32_t(*)[12][2])0x00464180)
#define g_AssaultBestTime (*(int32_t*)0x004641F0) // = -1
Expand Down
2 changes: 1 addition & 1 deletion src/tr2/inject_exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ static void M_Music(const bool enable)
{
INJECT(enable, 0x004553E0, Music_Init);
INJECT(enable, 0x00455460, Music_Shutdown);
INJECT(enable, 0x00455500, Music_Play);
INJECT(enable, 0x00455500, Music_Legacy_Play);
INJECT(enable, 0x00455570, Music_Stop);
INJECT(enable, 0x004555B0, Music_PlaySynced);
INJECT(enable, 0x004556B0, Music_SetVolume);
Expand Down

0 comments on commit 36eec3d

Please sign in to comment.