#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); }