summaryrefslogtreecommitdiff
path: root/src/m4a_2.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/m4a_2.c')
-rw-r--r--src/m4a_2.c834
1 files changed, 834 insertions, 0 deletions
diff --git a/src/m4a_2.c b/src/m4a_2.c
new file mode 100644
index 0000000..176910e
--- /dev/null
+++ b/src/m4a_2.c
@@ -0,0 +1,834 @@
+#include "gba/m4a_internal.h"
+
+extern char SoundMainRAM_Buffer[0x400];
+
+extern struct SoundInfo gSoundInfo;
+
+
+u32 MidiKeyToFreq(struct WaveData *wav, u8 key, u8 fineAdjust)
+{
+ u32 val1;
+ u32 val2;
+ u32 fineAdjustShifted = fineAdjust << 24;
+
+ if (key > 178)
+ {
+ key = 178;
+ fineAdjustShifted = 255 << 24;
+ }
+
+ val1 = gScaleTable[key];
+ val1 = gFreqTable[val1 & 0xF] >> (val1 >> 4);
+
+ val2 = gScaleTable[key + 1];
+ val2 = gFreqTable[val2 & 0xF] >> (val2 >> 4);
+
+ return umul3232H32(wav->freq, val1 + umul3232H32(val2 - val1, fineAdjustShifted));
+}
+
+void UnusedDummyFunc()
+{
+}
+
+void MPlayContinue(struct MusicPlayerInfo *mplayInfo)
+{
+ if (mplayInfo->ident == ID_NUMBER)
+ {
+ mplayInfo->ident++;
+ mplayInfo->status &= ~MUSICPLAYER_STATUS_PAUSE;
+ mplayInfo->ident = ID_NUMBER;
+ }
+}
+
+void MPlayFadeOut(struct MusicPlayerInfo *mplayInfo, u16 speed)
+{
+ if (mplayInfo->ident == ID_NUMBER)
+ {
+ mplayInfo->ident++;
+ mplayInfo->fadeOC = speed;
+ mplayInfo->fadeOI = speed;
+ mplayInfo->fadeOV = (64 << FADE_VOL_SHIFT);
+ mplayInfo->ident = ID_NUMBER;
+ }
+}
+
+void m4aSoundInit(void)
+{
+ s32 i;
+
+ CpuCopy32((void *)((s32)SoundMainRAM & ~1), SoundMainRAM_Buffer, sizeof(SoundMainRAM_Buffer));
+
+ SoundInit(&gSoundInfo);
+ MPlayExtender(gCgbChans);
+ m4aSoundMode(SOUND_MODE_DA_BIT_8
+ | SOUND_MODE_FREQ_18157
+ | (14 << SOUND_MODE_MASVOL_SHIFT)
+ | (5 << SOUND_MODE_MAXCHN_SHIFT));
+
+ for (i = 0; i < NUM_MUSIC_PLAYERS; i++)
+ {
+ struct MusicPlayerInfo *mplayInfo = gMPlayTable[i].info;
+ MPlayOpen(mplayInfo, gMPlayTable[i].track, gMPlayTable[i].unk_8);
+ mplayInfo->unk_B = gMPlayTable[i].unk_A;
+ mplayInfo->memAccArea = gMPlayMemAccArea;
+ }
+}
+
+void m4aSoundMain(void)
+{
+ SoundMain();
+}
+
+void m4aSongNumStart(u16 n)
+{
+ const struct MusicPlayer *mplayTable = gMPlayTable;
+ const struct Song *songTable = gSongTable;
+ const struct Song *song = &songTable[n];
+ const struct MusicPlayer *mplay = &mplayTable[song->ms];
+
+ MPlayStart(mplay->info, song->header);
+}
+
+void m4aSongNumStartOrChange(u16 n)
+{
+ const struct MusicPlayer *mplayTable = gMPlayTable;
+ const struct Song *songTable = gSongTable;
+ const struct Song *song = &songTable[n];
+ const struct MusicPlayer *mplay = &mplayTable[song->ms];
+
+ if (mplay->info->songHeader != song->header)
+ {
+ MPlayStart(mplay->info, song->header);
+ }
+ else
+ {
+ if ((mplay->info->status & MUSICPLAYER_STATUS_TRACK) == 0
+ || (mplay->info->status & MUSICPLAYER_STATUS_PAUSE))
+ {
+ MPlayStart(mplay->info, song->header);
+ }
+ }
+}
+
+void m4aSongNumStartOrContinue(u16 n)
+{
+ const struct MusicPlayer *mplayTable = gMPlayTable;
+ const struct Song *songTable = gSongTable;
+ const struct Song *song = &songTable[n];
+ const struct MusicPlayer *mplay = &mplayTable[song->ms];
+
+ if (mplay->info->songHeader != song->header)
+ MPlayStart(mplay->info, song->header);
+ else if ((mplay->info->status & MUSICPLAYER_STATUS_TRACK) == 0)
+ MPlayStart(mplay->info, song->header);
+ else if (mplay->info->status & MUSICPLAYER_STATUS_PAUSE)
+ MPlayContinue(mplay->info);
+}
+
+
+void m4aSongNumStop(u16 n)
+{
+ const struct MusicPlayer *mplayTable = gMPlayTable;
+ const struct Song *songTable = gSongTable;
+ const struct Song *song = &songTable[n];
+ const struct MusicPlayer *mplay = &mplayTable[song->ms];
+
+ if (mplay->info->songHeader == song->header)
+ m4aMPlayStop(mplay->info);
+}
+
+void m4aSongNumContinue(u16 n)
+{
+ const struct MusicPlayer *mplayTable = gMPlayTable;
+ const struct Song *songTable = gSongTable;
+ const struct Song *song = &songTable[n];
+ const struct MusicPlayer *mplay = &mplayTable[song->ms];
+
+ if (mplay->info->songHeader == song->header)
+ MPlayContinue(mplay->info);
+}
+
+void m4aMPlayAllStop(void)
+{
+ s32 i;
+
+ for (i = 0; i < NUM_MUSIC_PLAYERS; i++)
+ m4aMPlayStop(gMPlayTable[i].info);
+}
+
+void m4aMPlayContinue(struct MusicPlayerInfo *mplayInfo)
+{
+ MPlayContinue(mplayInfo);
+}
+
+void m4aMPlayAllContinue(void)
+{
+ s32 i;
+
+ for (i = 0; i < NUM_MUSIC_PLAYERS; i++)
+ MPlayContinue(gMPlayTable[i].info);
+}
+
+void m4aMPlayFadeOut(struct MusicPlayerInfo *mplayInfo, u16 speed)
+{
+ MPlayFadeOut(mplayInfo, speed);
+}
+
+void m4aMPlayFadeOutTemporarily(struct MusicPlayerInfo *mplayInfo, u16 speed)
+{
+ if (mplayInfo->ident == ID_NUMBER)
+ {
+ mplayInfo->ident++;
+ mplayInfo->fadeOC = speed;
+ mplayInfo->fadeOI = speed;
+ mplayInfo->fadeOV = (64 << FADE_VOL_SHIFT) | TEMPORARY_FADE;
+ mplayInfo->ident = ID_NUMBER;
+ }
+}
+void m4aMPlayFadeIn(struct MusicPlayerInfo *mplayInfo, u16 speed)
+{
+ if (mplayInfo->ident == ID_NUMBER)
+ {
+ mplayInfo->ident++;
+ mplayInfo->fadeOC = speed;
+ mplayInfo->fadeOI = speed;
+ mplayInfo->fadeOV = (0 << FADE_VOL_SHIFT) | FADE_IN;
+ mplayInfo->status &= ~MUSICPLAYER_STATUS_PAUSE;
+ mplayInfo->ident = ID_NUMBER;
+ }
+}
+
+void m4aMPlayImmInit(struct MusicPlayerInfo *mplayInfo)
+{
+ s32 trackCount = mplayInfo->trackCount;
+ struct MusicPlayerTrack *track = mplayInfo->tracks;
+
+ while (trackCount > 0)
+ {
+ if (track->flags & MPT_FLG_EXIST)
+ {
+ if (track->flags & MPT_FLG_START)
+ {
+ Clear64byte(track);
+ track->flags = MPT_FLG_EXIST;
+ track->bendRange = 2;
+ track->volX = 64;
+ track->lfoSpeed = 22;
+ track->tone.type = 1;
+ }
+ }
+
+ trackCount--;
+ track++;
+ }
+}
+
+void MPlayExtender(struct CgbChannel *cgbChans)
+{
+ struct SoundInfo *soundInfo;
+ u32 ident;
+
+ REG_SOUNDCNT_X = SOUND_MASTER_ENABLE
+ | SOUND_4_ON
+ | SOUND_3_ON
+ | SOUND_2_ON
+ | SOUND_1_ON;
+ REG_SOUNDCNT_L = 0; // set master volume to zero
+ REG_NR12 = 0x8;
+ REG_NR22 = 0x8;
+ REG_NR42 = 0x8;
+ REG_NR14 = 0x80;
+ REG_NR24 = 0x80;
+ REG_NR44 = 0x80;
+ REG_NR30 = 0;
+ REG_NR50 = 0x77;
+
+ soundInfo = SOUND_INFO_PTR;
+
+ ident = soundInfo->ident;
+
+ if (ident != ID_NUMBER)
+ return;
+
+ soundInfo->ident++;
+
+ gMPlayJumpTable[8] = ply_memacc;
+ gMPlayJumpTable[17] = ply_lfos;
+ gMPlayJumpTable[19] = ply_mod;
+ gMPlayJumpTable[28] = ply_xcmd;
+ gMPlayJumpTable[29] = ply_endtie;
+ gMPlayJumpTable[30] = SampleFreqSet;
+ gMPlayJumpTable[31] = TrackStop;
+ gMPlayJumpTable[32] = FadeOutBody;
+ gMPlayJumpTable[33] = TrkVolPitSet;
+
+ soundInfo->cgbChans = (struct CgbChannel *)cgbChans;
+ soundInfo->CgbSound = CgbSound;
+ soundInfo->CgbOscOff = CgbOscOff;
+ soundInfo->MidiKeyToCgbFreq = MidiKeyToCgbFreq;
+ soundInfo->maxLines = MAX_LINES;
+
+ CpuFill32(0, cgbChans, sizeof(struct CgbChannel) * 4);
+
+ cgbChans[0].ty = 1;
+ cgbChans[0].panMask = 0x11;
+ cgbChans[1].ty = 2;
+ cgbChans[1].panMask = 0x22;
+ cgbChans[2].ty = 3;
+ cgbChans[2].panMask = 0x44;
+ cgbChans[3].ty = 4;
+ cgbChans[3].panMask = 0x88;
+
+ soundInfo->ident = ident;
+}
+
+void MusicPlayerJumpTableCopy(void)
+{
+ asm("swi 0x2A");
+}
+
+void ClearChain(void *x)
+{
+ void (*func)(void *) = *(&gMPlayJumpTable[34]);
+ func(x);
+}
+
+void Clear64byte(void *x)
+{
+ void (*func)(void *) = *(&gMPlayJumpTable[35]);
+ func(x);
+}
+
+void SoundInit(struct SoundInfo *soundInfo)
+{
+ soundInfo->ident = 0;
+
+ if (REG_DMA1CNT & (DMA_REPEAT << 16))
+ REG_DMA1CNT = ((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4;
+
+ if (REG_DMA2CNT & (DMA_REPEAT << 16))
+ REG_DMA2CNT = ((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4;
+
+ REG_DMA1CNT_H = DMA_32BIT;
+ REG_DMA2CNT_H = DMA_32BIT;
+ REG_SOUNDCNT_X = SOUND_MASTER_ENABLE
+ | SOUND_4_ON
+ | SOUND_3_ON
+ | SOUND_2_ON
+ | SOUND_1_ON;
+ REG_SOUNDCNT_H = SOUND_B_FIFO_RESET | SOUND_B_TIMER_0 | SOUND_B_LEFT_OUTPUT
+ | SOUND_A_FIFO_RESET | SOUND_A_TIMER_0 | SOUND_A_RIGHT_OUTPUT
+ | SOUND_ALL_MIX_FULL;
+ REG_SOUNDBIAS_H = (REG_SOUNDBIAS_H & 0x3F) | 0x40;
+
+ REG_DMA1SAD = (s32)soundInfo->pcmBuffer;
+ REG_DMA1DAD = (s32)&REG_FIFO_A;
+ REG_DMA2SAD = (s32)soundInfo->pcmBuffer + PCM_DMA_BUF_SIZE;
+ REG_DMA2DAD = (s32)&REG_FIFO_B;
+
+ SOUND_INFO_PTR = soundInfo;
+ CpuFill32(0, soundInfo, sizeof(struct SoundInfo));
+
+ soundInfo->maxChans = 8;
+ soundInfo->masterVolume = 15;
+ soundInfo->plynote = (u32)ply_note;
+ soundInfo->CgbSound = DummyFunc;
+ soundInfo->CgbOscOff = (void (*)(u8))DummyFunc;
+ soundInfo->MidiKeyToCgbFreq = (u32 (*)(u8, u8, u8))DummyFunc;
+ soundInfo->ExtVolPit = (u32)DummyFunc;
+
+ MPlayJumpTableCopy(gMPlayJumpTable);
+
+ soundInfo->MPlayJumpTable = (u32)gMPlayJumpTable;
+
+ SampleFreqSet(SOUND_MODE_FREQ_13379);
+
+ soundInfo->ident = ID_NUMBER;
+}
+
+void SampleFreqSet(u32 freq)
+{
+ struct SoundInfo *soundInfo = SOUND_INFO_PTR;
+
+ freq = (freq & 0xF0000) >> 16;
+ soundInfo->freq = freq;
+ soundInfo->pcmSamplesPerVBlank = gPcmSamplesPerVBlankTable[freq - 1];
+ soundInfo->pcmDmaPeriod = PCM_DMA_BUF_SIZE / soundInfo->pcmSamplesPerVBlank;
+
+ // LCD refresh rate 59.7275Hz
+ soundInfo->pcmFreq = (597275 * soundInfo->pcmSamplesPerVBlank + 5000) / 10000;
+
+ // CPU frequency 16.78Mhz
+ soundInfo->divFreq = (16777216 / soundInfo->pcmFreq + 1) >> 1;
+
+ // Turn off timer 0.
+ REG_TM0CNT_H = 0;
+
+ // cycles per LCD fresh 280896
+ REG_TM0CNT_L = -(280896 / soundInfo->pcmSamplesPerVBlank);
+
+ m4aSoundVSyncOn();
+
+ while (*(vu8 *)REG_ADDR_VCOUNT == 159)
+ ;
+
+ while (*(vu8 *)REG_ADDR_VCOUNT != 159)
+ ;
+
+ REG_TM0CNT_H = TIMER_ENABLE | TIMER_1CLK;
+}
+
+void m4aSoundMode(u32 mode)
+{
+ struct SoundInfo *soundInfo = SOUND_INFO_PTR;
+ u32 temp;
+
+ if (soundInfo->ident != ID_NUMBER)
+ return;
+
+ soundInfo->ident++;
+
+ temp = mode & (SOUND_MODE_REVERB_SET | SOUND_MODE_REVERB_VAL);
+
+ if (temp)
+ soundInfo->reverb = temp & SOUND_MODE_REVERB_VAL;
+
+ temp = mode & SOUND_MODE_MAXCHN;
+
+ if (temp)
+ {
+ struct SoundChannel *chan;
+
+ soundInfo->maxChans = temp >> SOUND_MODE_MAXCHN_SHIFT;
+
+ temp = MAX_DIRECTSOUND_CHANNELS;
+ chan = &soundInfo->chans[0];
+
+ while (temp != 0)
+ {
+ chan->status = 0;
+ temp--;
+ chan++;
+ }
+ }
+
+ temp = mode & SOUND_MODE_MASVOL;
+
+ if (temp)
+ soundInfo->masterVolume = temp >> SOUND_MODE_MASVOL_SHIFT;
+
+ temp = mode & SOUND_MODE_DA_BIT;
+
+ if (temp)
+ {
+ temp = (temp & 0x300000) >> 14;
+ REG_SOUNDBIAS_H = (REG_SOUNDBIAS_H & 0x3F) | temp;
+ }
+
+ temp = mode & SOUND_MODE_FREQ;
+
+ if (temp)
+ {
+ m4aSoundVSyncOff();
+ SampleFreqSet(temp);
+ }
+
+ soundInfo->ident = ID_NUMBER;
+}
+
+void SoundClear(void)
+{
+ struct SoundInfo *soundInfo = SOUND_INFO_PTR;
+ s32 i;
+ void *chan;
+
+ if (soundInfo->ident != ID_NUMBER)
+ return;
+
+ soundInfo->ident++;
+
+ i = MAX_DIRECTSOUND_CHANNELS;
+ chan = &soundInfo->chans[0];
+
+ while (i > 0)
+ {
+ ((struct SoundChannel *)chan)->status = 0;
+ i--;
+ chan = (void *)((s32)chan + sizeof(struct SoundChannel));
+ }
+
+ chan = soundInfo->cgbChans;
+
+ if (chan)
+ {
+ i = 1;
+
+ while (i <= 4)
+ {
+ soundInfo->CgbOscOff(i);
+ ((struct CgbChannel *)chan)->sf = 0;
+ i++;
+ chan = (void *)((s32)chan + sizeof(struct CgbChannel));
+ }
+ }
+
+ soundInfo->ident = ID_NUMBER;
+}
+
+void m4aSoundVSyncOff(void)
+{
+ struct SoundInfo *soundInfo = SOUND_INFO_PTR;
+
+ if (soundInfo->ident >= ID_NUMBER && soundInfo->ident <= ID_NUMBER + 1)
+ {
+ soundInfo->ident += 10;
+
+ if (REG_DMA1CNT & (DMA_REPEAT << 16))
+ REG_DMA1CNT = ((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4;
+
+ if (REG_DMA2CNT & (DMA_REPEAT << 16))
+ REG_DMA2CNT = ((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4;
+
+ REG_DMA1CNT_H = DMA_32BIT;
+ REG_DMA2CNT_H = DMA_32BIT;
+
+ CpuFill32(0, soundInfo->pcmBuffer, sizeof(soundInfo->pcmBuffer));
+ }
+}
+
+void m4aSoundVSyncOn(void)
+{
+ struct SoundInfo *soundInfo = SOUND_INFO_PTR;
+ u32 ident = soundInfo->ident;
+
+ if (ident == ID_NUMBER)
+ return;
+
+ REG_DMA1CNT_H = DMA_ENABLE | DMA_START_SPECIAL | DMA_32BIT | DMA_REPEAT;
+ REG_DMA2CNT_H = DMA_ENABLE | DMA_START_SPECIAL | DMA_32BIT | DMA_REPEAT;
+
+ soundInfo->pcmDmaCounter = 0;
+ soundInfo->ident = ident - 10;
+}
+
+void MPlayOpen(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *tracks, u8 trackCount)
+{
+ struct SoundInfo *soundInfo;
+
+ if (trackCount == 0)
+ return;
+
+ if (trackCount > MAX_MUSICPLAYER_TRACKS)
+ trackCount = MAX_MUSICPLAYER_TRACKS;
+
+ soundInfo = SOUND_INFO_PTR;
+
+ if (soundInfo->ident != ID_NUMBER)
+ return;
+
+ soundInfo->ident++;
+
+ Clear64byte(mplayInfo);
+
+ mplayInfo->tracks = tracks;
+ mplayInfo->trackCount = trackCount;
+ mplayInfo->status = MUSICPLAYER_STATUS_PAUSE;
+
+ while (trackCount != 0)
+ {
+ tracks->flags = 0;
+ trackCount--;
+ tracks++;
+ }
+
+ if (soundInfo->func != 0)
+ {
+ mplayInfo->func = soundInfo->func;
+ mplayInfo->intp = soundInfo->intp;
+ soundInfo->func = 0;
+ }
+
+ soundInfo->intp = (u32)mplayInfo;
+ soundInfo->func = (u32)MPlayMain;
+ soundInfo->ident = ID_NUMBER;
+ mplayInfo->ident = ID_NUMBER;
+}
+
+void MPlayStart(struct MusicPlayerInfo *mplayInfo, struct SongHeader *songHeader)
+{
+ s32 i;
+ u8 unk_B;
+ struct MusicPlayerTrack *track;
+
+ if (mplayInfo->ident != ID_NUMBER)
+ return;
+
+ unk_B = mplayInfo->unk_B;
+
+ if (!unk_B
+ || ((!mplayInfo->songHeader || !(mplayInfo->tracks[0].flags & MPT_FLG_START))
+ && ((mplayInfo->status & MUSICPLAYER_STATUS_TRACK) == 0
+ || (mplayInfo->status & MUSICPLAYER_STATUS_PAUSE)))
+ || (mplayInfo->priority <= songHeader->priority))
+ {
+ mplayInfo->ident++;
+ mplayInfo->status = 0;
+ mplayInfo->songHeader = songHeader;
+ mplayInfo->tone = songHeader->tone;
+ mplayInfo->priority = songHeader->priority;
+ mplayInfo->clock = 0;
+ mplayInfo->tempoD = 150;
+ mplayInfo->tempoI = 150;
+ mplayInfo->tempoU = 0x100;
+ mplayInfo->tempoC = 0;
+ mplayInfo->fadeOI = 0;
+
+ i = 0;
+ track = mplayInfo->tracks;
+
+ while (i < songHeader->trackCount && i < mplayInfo->trackCount)
+ {
+ TrackStop(mplayInfo, track);
+ track->flags = MPT_FLG_EXIST | MPT_FLG_START;
+ track->chan = 0;
+ track->cmdPtr = songHeader->part[i];
+ i++;
+ track++;
+ }
+
+ while (i < mplayInfo->trackCount)
+ {
+ TrackStop(mplayInfo, track);
+ track->flags = 0;
+ i++;
+ track++;
+ }
+
+ if (songHeader->reverb & 0x80)
+ m4aSoundMode(songHeader->reverb);
+
+ mplayInfo->ident = ID_NUMBER;
+ }
+}
+
+void m4aMPlayStop(struct MusicPlayerInfo *mplayInfo)
+{
+ s32 i;
+ struct MusicPlayerTrack *track;
+
+ if (mplayInfo->ident != ID_NUMBER)
+ return;
+
+ mplayInfo->ident++;
+ mplayInfo->status |= MUSICPLAYER_STATUS_PAUSE;
+
+ i = mplayInfo->trackCount;
+ track = mplayInfo->tracks;
+
+ while (i > 0)
+ {
+ TrackStop(mplayInfo, track);
+ i--;
+ track++;
+ }
+
+ mplayInfo->ident = ID_NUMBER;
+}
+
+void FadeOutBody(struct MusicPlayerInfo *mplayInfo)
+{
+ s32 i;
+ struct MusicPlayerTrack *track;
+ u16 fadeOI = mplayInfo->fadeOI;
+ register u32 temp asm("r3");
+ register u16 mask asm("r2");
+
+ if (fadeOI == 0)
+ return;
+
+ mplayInfo->fadeOC--;
+
+ temp = 0xFFFF;
+ mask = temp;
+
+ if (mplayInfo->fadeOC != 0)
+ return;
+
+ mplayInfo->fadeOC = fadeOI;
+
+ if (mplayInfo->fadeOV & FADE_IN)
+ {
+ mplayInfo->fadeOV += (4 << FADE_VOL_SHIFT);
+
+ if ((u16)(mplayInfo->fadeOV & mask) >= (64 << FADE_VOL_SHIFT))
+ {
+ mplayInfo->fadeOV = (64 << FADE_VOL_SHIFT);
+ mplayInfo->fadeOI = 0;
+ }
+ }
+ else
+ {
+ mplayInfo->fadeOV -= (4 << FADE_VOL_SHIFT);
+
+ if ((s16)(mplayInfo->fadeOV & mask) <= 0)
+ {
+ i = mplayInfo->trackCount;
+ track = mplayInfo->tracks;
+
+ while (i > 0)
+ {
+ register u32 fadeOV asm("r7");
+ u32 val;
+
+ TrackStop(mplayInfo, track);
+
+ val = TEMPORARY_FADE;
+ fadeOV = mplayInfo->fadeOV;
+ val &= fadeOV;
+
+ if (!val)
+ track->flags = 0;
+
+ i--;
+ track++;
+ }
+
+ if (mplayInfo->fadeOV & TEMPORARY_FADE)
+ mplayInfo->status |= MUSICPLAYER_STATUS_PAUSE;
+ else
+ mplayInfo->status = MUSICPLAYER_STATUS_PAUSE;
+
+ mplayInfo->fadeOI = 0;
+ return;
+ }
+ }
+
+ i = mplayInfo->trackCount;
+ track = mplayInfo->tracks;
+
+ while (i > 0)
+ {
+ if (track->flags & MPT_FLG_EXIST)
+ {
+ track->volX = (mplayInfo->fadeOV >> FADE_VOL_SHIFT);
+ track->flags |= MPT_FLG_VOLCHG;
+ }
+
+ i--;
+ track++;
+ }
+}
+
+void TrkVolPitSet(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ if (track->flags & MPT_FLG_VOLSET)
+ {
+ s32 x;
+ s32 y;
+
+ x = (u32)(track->vol * track->volX) >> 5;
+
+ if (track->modT == 1)
+ x = (u32)(x * (track->modM + 128)) >> 7;
+
+ y = 2 * track->pan + track->panX;
+
+ if (track->modT == 2)
+ y += track->modM;
+
+ if (y < -128)
+ y = -128;
+ else if (y > 127)
+ y = 127;
+
+ track->volMR = (u32)((y + 128) * x) >> 8;
+ track->volML = (u32)((127 - y) * x) >> 8;
+ }
+
+ if (track->flags & MPT_FLG_PITSET)
+ {
+ s32 bend = track->bend * track->bendRange;
+ register s32 x asm("r1") = track->tune;
+ x += bend;
+ x *= 4;
+ x += (track->keyShift << 8);
+ x += (track->keyShiftX << 8);
+ x += track->pitX;
+
+ if (track->modT == 0)
+ x += 16 * track->modM;
+
+ track->keyM = x >> 8;
+ track->pitM = x;
+ }
+
+ track->flags &= ~(MPT_FLG_PITSET | MPT_FLG_VOLSET);
+}
+
+u32 MidiKeyToCgbFreq(u8 chanNum, u8 key, u8 fineAdjust)
+{
+ if (chanNum == 4)
+ {
+ if (key <= 20)
+ {
+ key = 0;
+ }
+ else
+ {
+ key -= 21;
+ if (key > 59)
+ key = 59;
+ }
+
+ return gNoiseTable[key];
+ }
+ else
+ {
+ s32 val1;
+ s32 val2;
+
+ if (key <= 35)
+ {
+ fineAdjust = 0;
+ key = 0;
+ }
+ else
+ {
+ key -= 36;
+ if (key > 130)
+ {
+ key = 130;
+ fineAdjust = 255;
+ }
+ }
+
+ val1 = gCgbScaleTable[key];
+ val1 = gCgbFreqTable[val1 & 0xF] >> (val1 >> 4);
+
+ val2 = gCgbScaleTable[key + 1];
+ val2 = gCgbFreqTable[val2 & 0xF] >> (val2 >> 4);
+
+ return val1 + ((fineAdjust * (val2 - val1)) >> 8) + 2048;
+ }
+}
+
+void CgbOscOff(u8 chanNum)
+{
+ switch (chanNum)
+ {
+ case 1:
+ REG_NR12 = 8;
+ REG_NR14 = 0x80;
+ break;
+ case 2:
+ REG_NR22 = 8;
+ REG_NR24 = 0x80;
+ break;
+ case 3:
+ REG_NR30 = 0;
+ break;
+ default:
+ REG_NR42 = 8;
+ REG_NR44 = 0x80;
+ }
+}