summaryrefslogtreecommitdiff
path: root/src/libs/m4a_4.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/m4a_4.c')
-rw-r--r--src/libs/m4a_4.c545
1 files changed, 545 insertions, 0 deletions
diff --git a/src/libs/m4a_4.c b/src/libs/m4a_4.c
new file mode 100644
index 000000000..2e1d140b4
--- /dev/null
+++ b/src/libs/m4a_4.c
@@ -0,0 +1,545 @@
+#include "gba/m4a_internal.h"
+
+void m4aMPlayTempoControl(struct MusicPlayerInfo *mplayInfo, u16 tempo)
+{
+ if (mplayInfo->ident == ID_NUMBER)
+ {
+ mplayInfo->ident++;
+ mplayInfo->tempoU = tempo;
+ mplayInfo->tempoI = (mplayInfo->tempoD * mplayInfo->tempoU) >> 8;
+ mplayInfo->ident = ID_NUMBER;
+ }
+}
+
+void m4aMPlayVolumeControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u16 volume)
+{
+ s32 i;
+ u32 bit;
+ struct MusicPlayerTrack *track;
+
+ if (mplayInfo->ident != ID_NUMBER)
+ return;
+
+ mplayInfo->ident++;
+
+ i = mplayInfo->trackCount;
+ track = mplayInfo->tracks;
+ bit = 1;
+
+ while (i > 0)
+ {
+ if (trackBits & bit)
+ {
+ if (track->flags & MPT_FLG_EXIST)
+ {
+ track->volX = volume / 4;
+ track->flags |= MPT_FLG_VOLCHG;
+ }
+ }
+
+ i--;
+ track++;
+ bit <<= 1;
+ }
+
+ mplayInfo->ident = ID_NUMBER;
+}
+
+void m4aMPlayPitchControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, s16 pitch)
+{
+ s32 i;
+ u32 bit;
+ struct MusicPlayerTrack *track;
+
+ if (mplayInfo->ident != ID_NUMBER)
+ return;
+
+ mplayInfo->ident++;
+
+ i = mplayInfo->trackCount;
+ track = mplayInfo->tracks;
+ bit = 1;
+
+ while (i > 0)
+ {
+ if (trackBits & bit)
+ {
+ if (track->flags & MPT_FLG_EXIST)
+ {
+ track->keyShiftX = (s16)pitch >> 8;
+ track->pitX = pitch;
+ track->flags |= MPT_FLG_PITCHG;
+ }
+ }
+
+ i--;
+ track++;
+ bit <<= 1;
+ }
+
+ mplayInfo->ident = ID_NUMBER;
+}
+
+void m4aMPlayPanpotControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, s8 pan)
+{
+ s32 i;
+ u32 bit;
+ struct MusicPlayerTrack *track;
+
+ if (mplayInfo->ident != ID_NUMBER)
+ return;
+
+ mplayInfo->ident++;
+
+ i = mplayInfo->trackCount;
+ track = mplayInfo->tracks;
+ bit = 1;
+
+ while (i > 0)
+ {
+ if (trackBits & bit)
+ {
+ if (track->flags & MPT_FLG_EXIST)
+ {
+ track->panX = pan;
+ track->flags |= MPT_FLG_VOLCHG;
+ }
+ }
+
+ i--;
+ track++;
+ bit <<= 1;
+ }
+
+ mplayInfo->ident = ID_NUMBER;
+}
+
+void ClearModM(struct MusicPlayerTrack *track)
+{
+ track->lfoSpeedC = 0;
+ track->modM = 0;
+
+ if (track->modT == 0)
+ track->flags |= MPT_FLG_PITCHG;
+ else
+ track->flags |= MPT_FLG_VOLCHG;
+}
+
+void m4aMPlayModDepthSet(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u8 modDepth)
+{
+ s32 i;
+ u32 bit;
+ struct MusicPlayerTrack *track;
+
+ if (mplayInfo->ident != ID_NUMBER)
+ return;
+
+ mplayInfo->ident++;
+
+ i = mplayInfo->trackCount;
+ track = mplayInfo->tracks;
+ bit = 1;
+
+ while (i > 0)
+ {
+ if (trackBits & bit)
+ {
+ if (track->flags & MPT_FLG_EXIST)
+ {
+ track->mod = modDepth;
+
+ if (!track->mod)
+ ClearModM(track);
+ }
+ }
+
+ i--;
+ track++;
+ bit <<= 1;
+ }
+
+ mplayInfo->ident = ID_NUMBER;
+}
+
+void m4aMPlayLFOSpeedSet(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u8 lfoSpeed)
+{
+ s32 i;
+ u32 bit;
+ struct MusicPlayerTrack *track;
+
+ if (mplayInfo->ident != ID_NUMBER)
+ return;
+
+ mplayInfo->ident++;
+
+ i = mplayInfo->trackCount;
+ track = mplayInfo->tracks;
+ bit = 1;
+
+ while (i > 0)
+ {
+ if (trackBits & bit)
+ {
+ if (track->flags & MPT_FLG_EXIST)
+ {
+ track->lfoSpeed = lfoSpeed;
+
+ if (!track->lfoSpeed)
+ ClearModM(track);
+ }
+ }
+
+ i--;
+ track++;
+ bit <<= 1;
+ }
+
+ mplayInfo->ident = ID_NUMBER;
+}
+
+#define MEMACC_COND_JUMP(cond) \
+if (cond) \
+ goto cond_true; \
+else \
+ goto cond_false; \
+
+void ply_memacc(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ u32 op;
+ u8 *addr;
+ u8 data;
+
+ op = *track->cmdPtr;
+ track->cmdPtr++;
+
+ addr = mplayInfo->memAccArea + *track->cmdPtr;
+ track->cmdPtr++;
+
+ data = *track->cmdPtr;
+ track->cmdPtr++;
+
+ switch (op)
+ {
+ case 0:
+ *addr = data;
+ return;
+ case 1:
+ *addr += data;
+ return;
+ case 2:
+ *addr -= data;
+ return;
+ case 3:
+ *addr = mplayInfo->memAccArea[data];
+ return;
+ case 4:
+ *addr += mplayInfo->memAccArea[data];
+ return;
+ case 5:
+ *addr -= mplayInfo->memAccArea[data];
+ return;
+ case 6:
+ MEMACC_COND_JUMP(*addr == data)
+ return;
+ case 7:
+ MEMACC_COND_JUMP(*addr != data)
+ return;
+ case 8:
+ MEMACC_COND_JUMP(*addr > data)
+ return;
+ case 9:
+ MEMACC_COND_JUMP(*addr >= data)
+ return;
+ case 10:
+ MEMACC_COND_JUMP(*addr <= data)
+ return;
+ case 11:
+ MEMACC_COND_JUMP(*addr < data)
+ return;
+ case 12:
+ MEMACC_COND_JUMP(*addr == mplayInfo->memAccArea[data])
+ return;
+ case 13:
+ MEMACC_COND_JUMP(*addr != mplayInfo->memAccArea[data])
+ return;
+ case 14:
+ MEMACC_COND_JUMP(*addr > mplayInfo->memAccArea[data])
+ return;
+ case 15:
+ MEMACC_COND_JUMP(*addr >= mplayInfo->memAccArea[data])
+ return;
+ case 16:
+ MEMACC_COND_JUMP(*addr <= mplayInfo->memAccArea[data])
+ return;
+ case 17:
+ MEMACC_COND_JUMP(*addr < mplayInfo->memAccArea[data])
+ return;
+ default:
+ return;
+ }
+
+cond_true:
+ {
+ void (*func)(struct MusicPlayerInfo *, struct MusicPlayerTrack *) = *(&gMPlayJumpTable[1]);
+ func(mplayInfo, track);
+ return;
+ }
+
+cond_false:
+ track->cmdPtr += 4;
+}
+
+void ply_xcmd(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ u32 n = *track->cmdPtr;
+ track->cmdPtr++;
+
+ gXcmdTable[n](mplayInfo, track);
+}
+
+void ply_xxx(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ void (*func)(struct MusicPlayerInfo *, struct MusicPlayerTrack *) = *(&gMPlayJumpTable[0]);
+ func(mplayInfo, track);
+}
+
+#define READ_XCMD_BYTE(var, n) \
+{ \
+ u32 byte = track->cmdPtr[(n)]; \
+ byte <<= n * 8; \
+ (var) &= ~(0xFF << (n * 8)); \
+ (var) |= byte; \
+}
+
+void ply_xwave(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ u32 wav;
+
+ READ_XCMD_BYTE(wav, 0) // UB: uninitialized variable
+ READ_XCMD_BYTE(wav, 1)
+ READ_XCMD_BYTE(wav, 2)
+ READ_XCMD_BYTE(wav, 3)
+
+ track->tone.wav = (struct WaveData *)wav;
+ track->cmdPtr += 4;
+}
+
+void ply_xtype(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->tone.type = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xatta(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->tone.attack = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xdeca(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->tone.decay = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xsust(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->tone.sustain = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xrele(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->tone.release = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xiecv(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->echoVolume = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xiecl(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->echoLength = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xleng(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->tone.length = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xswee(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->tone.pan_sweep = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xcmd_0C(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ u32 unk;
+
+ READ_XCMD_BYTE(unk, 0) // UB: uninitialized variable
+ READ_XCMD_BYTE(unk, 1)
+
+ if (track->unk_3A < (u16)unk)
+ {
+ track->unk_3A++;
+ track->cmdPtr -= 2;
+ track->wait = 1;
+ }
+ else
+ {
+ track->unk_3A = 0;
+ track->cmdPtr += 2;
+ }
+}
+
+void ply_xcmd_0D(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ u32 unk;
+
+ READ_XCMD_BYTE(unk, 0) // UB: uninitialized variable
+ READ_XCMD_BYTE(unk, 1)
+ READ_XCMD_BYTE(unk, 2)
+ READ_XCMD_BYTE(unk, 3)
+
+ track->unk_3C = unk;
+ track->cmdPtr += 4;
+}
+
+void DummyFunc(void)
+{
+}
+
+struct MusicPlayerInfo *SetPokemonCryTone(struct ToneData *tone)
+{
+ u32 maxClock = 0;
+ s32 maxClockIndex = 0;
+ s32 i;
+ struct MusicPlayerInfo *mplayInfo;
+
+ for (i = 0; i < MAX_POKEMON_CRIES; i++)
+ {
+ struct MusicPlayerTrack *track = &gPokemonCryTracks[i * 2];
+
+ if (!track->flags && (!track->chan || track->chan->track != track))
+ goto start_song;
+
+ if (maxClock < gPokemonCryMusicPlayers[i].clock)
+ {
+ maxClock = gPokemonCryMusicPlayers[i].clock;
+ maxClockIndex = i;
+ }
+ }
+
+ i = maxClockIndex;
+
+start_song:
+ mplayInfo = &gPokemonCryMusicPlayers[i];
+ mplayInfo->ident++;
+
+#define CRY ((s32)&gPokemonCrySongs + i * sizeof(struct PokemonCrySong))
+#define CRY_OFS(field) offsetof(struct PokemonCrySong, field)
+
+ memcpy((void *)CRY, &gPokemonCrySong, sizeof(struct PokemonCrySong));
+
+ *(u32 *)(CRY + CRY_OFS(tone)) = (u32)tone;
+ *(u32 *)(CRY + CRY_OFS(part)) = CRY + CRY_OFS(part0);
+ *(u32 *)(CRY + CRY_OFS(part) + 4) = CRY + CRY_OFS(part1);
+ *(u32 *)(CRY + CRY_OFS(gotoTarget)) = CRY + CRY_OFS(cont);
+
+#undef CRY_OFS
+#undef CRY
+
+ mplayInfo->ident = ID_NUMBER;
+
+ MPlayStart(mplayInfo, (struct SongHeader *)(&gPokemonCrySongs[i]));
+
+ return mplayInfo;
+}
+
+void SetPokemonCryVolume(u8 val)
+{
+ gPokemonCrySong.volumeValue = val & 0x7F;
+}
+
+void SetPokemonCryPanpot(s8 val)
+{
+ gPokemonCrySong.panValue = (val + C_V) & 0x7F;
+}
+
+void SetPokemonCryPitch(s16 val)
+{
+ s16 b = val + 0x80;
+ u8 a = gPokemonCrySong.tuneValue2 - gPokemonCrySong.tuneValue;
+ gPokemonCrySong.tieKeyValue = (b >> 8) & 0x7F;
+ gPokemonCrySong.tuneValue = (b >> 1) & 0x7F;
+ gPokemonCrySong.tuneValue2 = (a + ((b >> 1) & 0x7F)) & 0x7F;
+}
+
+void SetPokemonCryLength(u16 val)
+{
+ gPokemonCrySong.unkCmd0CParam = val;
+}
+
+void SetPokemonCryRelease(u8 val)
+{
+ gPokemonCrySong.releaseValue = val;
+}
+
+void SetPokemonCryProgress(u32 val)
+{
+ gPokemonCrySong.unkCmd0DParam = val;
+}
+
+int IsPokemonCryPlaying(struct MusicPlayerInfo *mplayInfo)
+{
+ struct MusicPlayerTrack *track = mplayInfo->tracks;
+
+ if (track->chan && track->chan->track == track)
+ return 1;
+ else
+ return 0;
+}
+
+void SetPokemonCryChorus(s8 val)
+{
+ if (val)
+ {
+ gPokemonCrySong.trackCount = 2;
+ gPokemonCrySong.tuneValue2 = (val + gPokemonCrySong.tuneValue) & 0x7F;
+ }
+ else
+ {
+ gPokemonCrySong.trackCount = 1;
+ }
+}
+
+void SetPokemonCryStereo(u32 val)
+{
+ struct SoundInfo *soundInfo = SOUND_INFO_PTR;
+
+ if (val)
+ {
+ REG_SOUNDCNT_H = SOUND_B_TIMER_0 | SOUND_B_LEFT_OUTPUT
+ | SOUND_A_TIMER_0 | SOUND_A_RIGHT_OUTPUT
+ | SOUND_ALL_MIX_FULL;
+ soundInfo->mode &= ~1;
+ }
+ else
+ {
+ REG_SOUNDCNT_H = SOUND_B_TIMER_0 | SOUND_B_LEFT_OUTPUT | SOUND_B_RIGHT_OUTPUT
+ | SOUND_A_TIMER_0 | SOUND_A_LEFT_OUTPUT | SOUND_A_RIGHT_OUTPUT
+ | SOUND_B_MIX_HALF | SOUND_A_MIX_HALF | SOUND_CGB_MIX_FULL;
+ soundInfo->mode |= 1;
+ }
+}
+
+void SetPokemonCryPriority(u8 val)
+{
+ gPokemonCrySong.priority = val;
+}