From 996c43b8e327a2d63f99c4f5a2d820dbaf1be8f3 Mon Sep 17 00:00:00 2001 From: Treeki Date: Thu, 22 Nov 2012 23:12:30 +0100 Subject: new map music system --- src/koopatlas/core.cpp | 50 ++------------- src/koopatlas/core.h | 7 +- src/koopatlas/mapmusic.cpp | 146 ++++++++++++++++++++++++++++++++++++++++++ src/koopatlas/mapmusic.h | 11 ++++ src/koopatlas/pathmanager.cpp | 22 +++---- 5 files changed, 174 insertions(+), 62 deletions(-) create mode 100644 src/koopatlas/mapmusic.cpp create mode 100644 src/koopatlas/mapmusic.h (limited to 'src/koopatlas') diff --git a/src/koopatlas/core.cpp b/src/koopatlas/core.cpp index 5734300..89f315a 100644 --- a/src/koopatlas/core.cpp +++ b/src/koopatlas/core.cpp @@ -194,7 +194,7 @@ bool WMInit_LoadResources2(void *ptr) { } if (wm->mapData.load(wm->mapPath)) { - wm->playBGM(); + dKPMusic::play(GetSaveFile()->GetBlock(-1)->currentMapMusic); return true; } else return false; @@ -421,52 +421,9 @@ int dScKoopatlas_c::onCreate() { extern "C" void PlaySoundWithFunctionB4(void *spc, nw4r::snd::SoundHandle *handle, int id, int unk); -void dScKoopatlas_c::playBGM() { - char cleanName[40]; - // find the end - const char *mapPathEnd = mapPath; - while (*mapPathEnd) - mapPathEnd++; - - // it now points to the zero - const char *findSlash = mapPathEnd; - while (findSlash > mapPath && *findSlash != '/') - findSlash--; - - // it now points to the slash - strcpy(cleanName, "Map_"); - strncpy(&cleanName[4], findSlash+1, 36); - - // nuke everything up to the point - for (int i = 4; i < 40; i++) - if (cleanName[i] == '.') - cleanName[i] = 0; - - int realStreamID; - OSReport("I'm going to play %s!\n", cleanName); - hijackMusicWithSongName(cleanName, -1, false, 16, 8, &realStreamID); - OSReport("Real Stream ID: %d\n", realStreamID); - PlaySoundWithFunctionB4(SoundRelatedClass, &bgm, realStreamID, 1); - - currentBGMTrack = GetSaveFile()->GetBlock(-1)->currentMapMusic; - OSReport("Enabling track %d by setting bitfield 0x%x to volume 1.0f and bitfield 0x%x to volume 0.0f; both over 0 frames\n", currentBGMTrack, 1 << currentBGMTrack, 0xFF ^ (1 << currentBGMTrack)); - bgm.SetTrackVolume(0xFF ^ (1 << currentBGMTrack), 0, 0.0f); - bgm.SetTrackVolume(1 << currentBGMTrack, 0, 1.0f); -} - -void dScKoopatlas_c::setBGMTrack(int trackID) { - if (currentBGMTrack == trackID) - return; - - OSReport("Enabling track %d and disabling track %d by setting bitfield 0x%x to volume 1.0f and bitfield 0x%x to volume 0.0f; both over 30 frames\n", trackID, currentBGMTrack, 1 << trackID, 1 << currentBGMTrack); - bgm.SetTrackVolume(1 << currentBGMTrack, 30, 0.0f); - bgm.SetTrackVolume(1 << trackID, 30, 1.0f); - currentBGMTrack = trackID; -} - int dScKoopatlas_c::onDelete() { - if (bgm.Exists()) - bgm.Stop(0); + if (!keepMusicPlaying) + dKPMusic::stop(); FreeScene(0); FreeScene(1); @@ -506,6 +463,7 @@ bool dScKoopatlas_c::mapIsRunning() { int dScKoopatlas_c::onExecute() { + dKPMusic::execute(); if (!canDoStuff()) return true; //SpammyReport("Executing state: %s\n", state.getCurrentState()->getName()); diff --git a/src/koopatlas/core.h b/src/koopatlas/core.h index 3f795cc..2333c1a 100644 --- a/src/koopatlas/core.h +++ b/src/koopatlas/core.h @@ -16,6 +16,7 @@ #include "koopatlas/starcoin.h" #include "koopatlas/hud.h" #include "koopatlas/pathmanager.h" +#include "koopatlas/mapmusic.h" #define WM_DEBUGGING //#define WM_SPAMMY_DEBUGGING @@ -117,8 +118,6 @@ class dScKoopatlas_c : public dScene_c { const char *getMapNameForIndex(int index); int getIndexForMapName(const char *name); - nw4r::snd::StrmSoundHandle bgm; - void startLevel(dLevelInfo_c::entry_s *level); bool canDoStuff(); @@ -126,9 +125,7 @@ class dScKoopatlas_c : public dScene_c { void showSaveWindow(); - void playBGM(); - void setBGMTrack(int trackID); - int currentBGMTrack; + bool keepMusicPlaying; }; extern void *_8042A788; diff --git a/src/koopatlas/mapmusic.cpp b/src/koopatlas/mapmusic.cpp new file mode 100644 index 0000000..1ccd775 --- /dev/null +++ b/src/koopatlas/mapmusic.cpp @@ -0,0 +1,146 @@ +#include +#include "koopatlas/mapmusic.h" +#include "music.h" + +extern "C" void PlaySoundWithFunctionB4(void *spc, nw4r::snd::SoundHandle *handle, int id, int unk); + +static nw4r::snd::StrmSoundHandle s_handle; +static bool s_playing = false; +static int s_song = -1; +static int s_nextSong = -1; + +static int s_countdownToSwitch = -1; +static int s_countdownToFadeIn = -1; + +static dDvdLoader_c s_adpcmInfoLoader; +static bool s_adpcmInfoLoaded = false; + +#define FADE_OUT_LEN 30 +#define FADE_IN_LEN 30 +#define BUFFER_CLEAR_DELAY 60 + +u8 hijackMusicWithSongName(const char *songName, int themeID, bool hasFast, int channelCount, int trackCount, int *wantRealStreamID); + +void dKPMusic::play(int id) { + if (s_playing) { + // Switch track + OSReport("Trying to switch to song %d (Current one is %d)...\n", id, s_song); + if (s_song == id || s_nextSong == id) + return; + if (s_countdownToSwitch >= 0 || s_countdownToFadeIn >= 0) + return; + OSReport("Will switch; Fading out current track 2 over %d frames\n", FADE_OUT_LEN); + + s_handle.SetTrackVolume(1<<1, FADE_OUT_LEN, 0.0f); + s_nextSong = id; + s_countdownToSwitch = FADE_OUT_LEN; + + } else { + // New track + OSReport("Playing song %d from the start.\n", id); + + int realStreamID; + char brstmName[8]; + sprintf(brstmName, "map%d", id); + hijackMusicWithSongName(brstmName, -1, false, 4, 2, &realStreamID); + + PlaySoundWithFunctionB4(SoundRelatedClass, &s_handle, realStreamID, 1); + + s_playing = true; + s_song = id; + } +} + +// crap. +#include "fileload.h" + +extern "C" void DVDCancel(void *crap); + +extern "C" void AxVoice_SetADPCM(void *axVoice, void *adpcm); +extern "C" void Voice_SetADPCMLoop(void *voice, int channel, void *adpcmLoop); + +void dKPMusic::execute() { + if (!s_adpcmInfoLoaded) { + if (s_adpcmInfoLoader.load("/NewerRes/MapADPCMInfo.bin")) + s_adpcmInfoLoaded = true; + } + + if (!s_playing) + return; + + if (s_countdownToSwitch >= 0) { + s_countdownToSwitch--; + if (s_countdownToSwitch == 0) { + OSReport("Switching brstm files to song %d.\n", s_nextSong); + + s_countdownToFadeIn = BUFFER_CLEAR_DELAY; + + char brstmPath[48]; + sprintf(brstmPath, "/Sound/new/map%d.er", s_nextSong); + + u8 *sound = (u8*)(s_handle.GetSound()); + u8 *player = sound+0x110; + u8 **fileStreamPointer = (u8**)(player+0x808); + u8 *fileStream = *fileStreamPointer; + DVDHandle *fileInfo = (DVDHandle*)(fileStream+0x28); + DVDCancel(fileInfo); + bool result = DVDFastOpen(DVDConvertPathToEntrynum(brstmPath), fileInfo); + + OSReport("StrmSound is at %p, StrmPlayer is at %p, FileStream pointer is at %p, FileStream is at %p, FileInfo is at %p\n", sound, player, fileStreamPointer, fileStream, fileInfo); + OSReport("Changed to name %s. FastOpen returned: %d\n", brstmPath, result); + + u8 *trackArray = player+0xB58; + u8 *track = (trackArray + (0x38 * 1)); + u8 **voicePointer = (u8**)(track+4); + u8 *voice = *voicePointer; + OSReport("Track Array: %p; Track: %p; Voice Pointer: %p; Voice: %p\n", trackArray, track, voicePointer, voice); + + for (int i = 0; i < 2; i++) { + int sourceBlockID = (s_nextSong*2)+i; + u8 *sourceData = ((u8*)(s_adpcmInfoLoader.buffer)) + (0x30*sourceBlockID); + OSReport("Using ADPCM data for channel %d from block %d, data at %p\n", i, sourceBlockID, sourceData); + + Voice_SetADPCMLoop(voice, i, sourceData+0x28); + + // loop through all axVoices + for (int j = 0; j < 4; j++) { + int axVoiceID = (i*4) + j; + u8 **axVoicePointer = (u8**)(voice + 0xC + (axVoiceID*4)); + u8 *axVoice = *axVoicePointer; + OSReport("Setting AxVoice ID %d, with pointer at %p, located at %p\n", axVoiceID, axVoicePointer, axVoice); + + if (axVoice) + AxVoice_SetADPCM(axVoice, sourceData); + } + } + + OSReport("All done\n"); + + s_song = s_nextSong; + s_nextSong = -1; + } + + } else if (s_countdownToFadeIn >= 0) { + s_countdownToFadeIn--; + if (s_countdownToFadeIn == 0) { + OSReport("Going to fade in the second track now!\n"); + s_handle.SetTrackVolume(1<<1, FADE_IN_LEN, 1.0f); + } + } +} + +void dKPMusic::stop() { + if (!s_playing) + return; + + OSReport("Stopping song\n"); + + s_playing = false; + s_song = -1; + s_nextSong = -1; + s_countdownToSwitch = -1; + s_countdownToFadeIn = -1; + + if (s_handle.Exists()) + s_handle.Stop(30); +} diff --git a/src/koopatlas/mapmusic.h b/src/koopatlas/mapmusic.h new file mode 100644 index 0000000..785f870 --- /dev/null +++ b/src/koopatlas/mapmusic.h @@ -0,0 +1,11 @@ +#ifndef MAPMUSIC_H +#define MAPMUSIC_H + +class dKPMusic { + public: + static void play(int id); + static void execute(); + static void stop(); +}; + +#endif /* MAPMUSIC_H */ diff --git a/src/koopatlas/pathmanager.cpp b/src/koopatlas/pathmanager.cpp index 002b400..cf0bd05 100644 --- a/src/koopatlas/pathmanager.cpp +++ b/src/koopatlas/pathmanager.cpp @@ -29,11 +29,6 @@ void dWMPathManager_c::setup() { levelStartWait = -1; unlockPaths(); - if (!countdownToFadeIn) - waitAtStart = 50; - else - waitAtStart = -1; - waitForAfterDeathAnim = -1; mustPlayAfterDeathAnim = false; if (LastPowerupStoreType == LOSE_LEVEL) { @@ -112,7 +107,13 @@ void dWMPathManager_c::setup() { mustComplainToMapCreator = true; } + waitAtStart = -1; } else { + if (!countdownToFadeIn) + waitAtStart = 50; + else + waitAtStart = -1; + SpammyReport("saved path node: %d\n", save->current_path_node); if (save->current_path_node >= pathLayer->nodeCount) { SpammyReport("out of bounds (%d), using node 0\n", pathLayer->nodeCount); @@ -232,7 +233,6 @@ void dWMPathManager_c::unlockPaths() { if (node->type == node->LEVEL && node->isUnlocked() && node->levelNumber[1] != 99) { save->completions[node->levelNumber[0]-1][node->levelNumber[1]-1] |= COND_UNLOCKED; - OSReport("beets: %d-%d\n", node->levelNumber[0], node->levelNumber[1]); } } @@ -735,10 +735,12 @@ void dWMPathManager_c::moveThroughPath() { if (visiblyChange && dWMHud_c::instance) dWMHud_c::instance->showFooter(); - dScKoopatlas_c::instance->setBGMTrack(world->trackID); + dKPMusic::play(world->trackID); } else if (to->worldID == 0) { OSReport("No world\n"); + save->currentMapMusic = 0; + dKPMusic::play(0); save->newerWorldName[0] = 0; if (dWMHud_c::instance) dWMHud_c::instance->hideFooter(); @@ -765,6 +767,7 @@ void dWMPathManager_c::moveThroughPath() { SpammyReport("Change to map ID %d (%s), entrance ID %d\n", save->current_world, to->destMap, to->foreignID); + dScKoopatlas_c::instance->keepMusicPlaying = true; ActivateWipe(to->transition); DoSceneChange(WORLD_MAP, 0x10000000 | (to->foreignID << 20), 0); @@ -828,10 +831,7 @@ void dWMPathManager_c::activatePoint() { levelStartWait = 40; enteredLevel = dLevelInfo_c::s_info.searchBySlot(w, l); - if (dScKoopatlas_c::instance->bgm.Exists()) { - dScKoopatlas_c::instance->bgm.Stop(50); - dScKoopatlas_c::instance->bgm.DetachSound(); - } + dKPMusic::stop(); } } -- cgit v1.2.3