#ifndef GUARD_GBA_M4A_INTERNAL_H #define GUARD_GBA_M4A_INTERNAL_H #include "gba/gba.h" // ASCII encoding of 'Smsh' in reverse // This is presumably short for SMASH, the developer of MKS4AGB. #define ID_NUMBER 0x68736D53 #define C_V 0x40 // center value for PAN, BEND, and TUNE #define SOUND_MODE_REVERB_VAL 0x0000007F #define SOUND_MODE_REVERB_SET 0x00000080 #define SOUND_MODE_MAXCHN 0x00000F00 #define SOUND_MODE_MAXCHN_SHIFT 8 #define SOUND_MODE_MASVOL 0x0000F000 #define SOUND_MODE_MASVOL_SHIFT 12 #define SOUND_MODE_FREQ_05734 0x00010000 #define SOUND_MODE_FREQ_07884 0x00020000 #define SOUND_MODE_FREQ_10512 0x00030000 #define SOUND_MODE_FREQ_13379 0x00040000 #define SOUND_MODE_FREQ_15768 0x00050000 #define SOUND_MODE_FREQ_18157 0x00060000 #define SOUND_MODE_FREQ_21024 0x00070000 #define SOUND_MODE_FREQ_26758 0x00080000 #define SOUND_MODE_FREQ_31536 0x00090000 #define SOUND_MODE_FREQ_36314 0x000A0000 #define SOUND_MODE_FREQ_40137 0x000B0000 #define SOUND_MODE_FREQ_42048 0x000C0000 #define SOUND_MODE_FREQ 0x000F0000 #define SOUND_MODE_FREQ_SHIFT 16 #define SOUND_MODE_DA_BIT_9 0x00800000 #define SOUND_MODE_DA_BIT_8 0x00900000 #define SOUND_MODE_DA_BIT_7 0x00A00000 #define SOUND_MODE_DA_BIT_6 0x00B00000 #define SOUND_MODE_DA_BIT 0x00B00000 #define SOUND_MODE_DA_BIT_SHIFT 20 struct WaveData { u16 type; u16 status; u32 freq; u32 loopStart; u32 size; // number of samples s8 data[1]; // samples }; #define TONEDATA_TYPE_CGB 0x07 #define TONEDATA_TYPE_FIX 0x08 #define TONEDATA_TYPE_SPL 0x40 // key split #define TONEDATA_TYPE_RHY 0x80 // rhythm #define TONEDATA_P_S_PAN 0xc0 #define TONEDATA_P_S_PAM TONEDATA_P_S_PAN struct ToneData { u8 type; u8 key; u8 length; // sound length (compatible sound) u8 pan_sweep; // pan or sweep (compatible sound ch. 1) struct WaveData *wav; u8 attack; u8 decay; u8 sustain; u8 release; }; #define SOUND_CHANNEL_SF_START 0x80 #define SOUND_CHANNEL_SF_STOP 0x40 #define SOUND_CHANNEL_SF_LOOP 0x10 #define SOUND_CHANNEL_SF_IEC 0x04 #define SOUND_CHANNEL_SF_ENV 0x03 #define SOUND_CHANNEL_SF_ENV_ATTACK 0x03 #define SOUND_CHANNEL_SF_ENV_DECAY 0x02 #define SOUND_CHANNEL_SF_ENV_SUSTAIN 0x01 #define SOUND_CHANNEL_SF_ENV_RELEASE 0x00 #define SOUND_CHANNEL_SF_ON (SOUND_CHANNEL_SF_START | SOUND_CHANNEL_SF_STOP | SOUND_CHANNEL_SF_IEC | SOUND_CHANNEL_SF_ENV) #define CGB_CHANNEL_MO_PIT 0x02 #define CGB_CHANNEL_MO_VOL 0x01 #define CGB_NRx2_ENV_DIR_DEC 0x00 #define CGB_NRx2_ENV_DIR_INC 0x08 struct CgbChannel { u8 statusFlags; u8 type; u8 rightVolume; u8 leftVolume; u8 attack; u8 decay; u8 sustain; u8 release; u8 key; u8 envelopeVolume; u8 envelopeGoal; u8 envelopeCounter; u8 pseudoEchoVolume; u8 pseudoEchoLength; u8 dummy1; u8 dummy2; u8 gateTime; u8 midiKey; u8 velocity; u8 priority; u8 rhythmPan; u8 dummy3[3]; u8 dummy5; u8 sustainGoal; u8 n4; // NR[1-4]4 register (initial, length bit) u8 pan; u8 panMask; u8 modify; u8 length; u8 sweep; u32 frequency; u32 *wavePointer; // instructs CgbMain to load targeted wave u32 *currentPointer; // stores the currently loaded wave struct MusicPlayerTrack *track; void *prevChannelPointer; void *nextChannelPointer; u8 dummy4[8]; }; struct MusicPlayerTrack; struct SoundChannel { u8 statusFlags; u8 type; u8 rightVolume; u8 leftVolume; u8 attack; u8 decay; u8 sustain; u8 release; u8 key; // midi key as it was translated into final pitch u8 envelopeVolume; u8 envelopeVolumeRight; u8 envelopeVolumeLeft; u8 pseudoEchoVolume; u8 pseudoEchoLength; u8 dummy1; u8 dummy2; u8 gateTime; u8 midiKey; // midi key as it was used in the track data u8 velocity; u8 priority; u8 rhythmPan; u8 dummy3[3]; u32 count; u32 fw; u32 frequency; struct WaveData *wav; s8 *currentPointer; struct MusicPlayerTrack *track; void *prevChannelPointer; void *nextChannelPointer; u32 dummy4; u16 xpi; u16 xpc; }; #define MAX_DIRECTSOUND_CHANNELS 12 #define PCM_DMA_BUF_SIZE 1584 // size of Direct Sound buffer struct MusicPlayerInfo; typedef void (*MPlayFunc)(); typedef void (*PlyNoteFunc)(u32, struct MusicPlayerInfo *, struct MusicPlayerTrack *); typedef void (*CgbSoundFunc)(void); typedef void (*CgbOscOffFunc)(u8); typedef u32 (*MidiKeyToCgbFreqFunc)(u8, u8, u8); typedef void (*ExtVolPitFunc)(void); typedef void (*MPlayMainFunc)(struct MusicPlayerInfo *); struct SoundInfo { // This field is normally equal to ID_NUMBER but it is set to other // values during sensitive operations for locking purposes. // This field should be volatile but isn't. This could potentially cause // race conditions. u32 ident; vu8 pcmDmaCounter; // Direct Sound u8 reverb; u8 maxChans; u8 masterVolume; u8 freq; u8 mode; u8 c15; // periodically counts from 14 down to 0 (15 states) u8 pcmDmaPeriod; // number of V-blanks per PCM DMA u8 maxLines; u8 gap[3]; s32 pcmSamplesPerVBlank; s32 pcmFreq; s32 divFreq; struct CgbChannel *cgbChans; MPlayMainFunc MPlayMainHead; struct MusicPlayerInfo *musicPlayerHead; CgbSoundFunc CgbSound; CgbOscOffFunc CgbOscOff; MidiKeyToCgbFreqFunc MidiKeyToCgbFreq; MPlayFunc *MPlayJumpTable; PlyNoteFunc plynote; ExtVolPitFunc ExtVolPit; u8 gap2[16]; struct SoundChannel chans[MAX_DIRECTSOUND_CHANNELS]; s8 ALIGNED(4) pcmBuffer[PCM_DMA_BUF_SIZE * 2]; }; struct SongHeader { u8 trackCount; u8 blockCount; u8 priority; u8 reverb; struct ToneData *tone; u8 *part[1]; }; struct PokemonCrySong { u8 trackCount; u8 blockCount; u8 priority; u8 reverb; struct ToneData *tone; u8 *part[2]; u8 gap; u8 part0; // 0x11 u8 tuneValue; // 0x12 u8 gotoCmd; // 0x13 u32 gotoTarget; // 0x14 u8 part1; // 0x18 u8 tuneValue2; // 0x19 u8 cont[2]; // 0x1A u8 volCmd; // 0x1C u8 volumeValue; // 0x1D u8 unkCmd0D[2]; // 0x1E u32 unkCmd0DParam; // 0x20 u8 xreleCmd[2]; // 0x24 u8 releaseValue; // 0x26 u8 panCmd; u8 panValue; // 0x28 u8 tieCmd; // 0x29 u8 tieKeyValue; // 0x2A u8 tieVelocityValue; // 0x2B u8 unkCmd0C[2]; // 0x2C u16 unkCmd0CParam; // 0x2E u8 end[2]; // 0x30 }; #define MPT_FLG_VOLSET 0x01 #define MPT_FLG_VOLCHG 0x03 #define MPT_FLG_PITSET 0x04 #define MPT_FLG_PITCHG 0x0C #define MPT_FLG_START 0x40 #define MPT_FLG_EXIST 0x80 struct MusicPlayerTrack { u8 flags; u8 wait; u8 patternLevel; u8 repN; u8 gateTime; u8 key; u8 velocity; u8 runningStatus; u8 keyM; u8 pitM; s8 keyShift; s8 keyShiftX; s8 tune; u8 pitX; s8 bend; u8 bendRange; u8 volMR; u8 volML; u8 vol; u8 volX; s8 pan; s8 panX; s8 modM; u8 mod; u8 modT; u8 lfoSpeed; u8 lfoSpeedC; u8 lfoDelay; u8 lfoDelayC; u8 priority; u8 pseudoEchoVolume; u8 pseudoEchoLength; struct SoundChannel *chan; struct ToneData tone; u8 gap[10]; u16 unk_3A; u32 unk_3C; u8 *cmdPtr; u8 *patternStack[3]; }; #define MUSICPLAYER_STATUS_TRACK 0x0000ffff #define MUSICPLAYER_STATUS_PAUSE 0x80000000 #define MAX_MUSICPLAYER_TRACKS 16 #define TRACKS_ALL 0xFFFF #define TEMPORARY_FADE 0x0001 #define FADE_IN 0x0002 #define FADE_VOL_MAX 64 #define FADE_VOL_SHIFT 2 struct MusicPlayerInfo { struct SongHeader *songHeader; u32 status; u8 trackCount; u8 priority; u8 cmd; u8 unk_B; u32 clock; u8 gap[8]; u8 *memAccArea; u16 tempoD; u16 tempoU; u16 tempoI; u16 tempoC; u16 fadeOI; u16 fadeOC; u16 fadeOV; struct MusicPlayerTrack *tracks; struct ToneData *tone; u32 ident; MPlayMainFunc MPlayMainNext; struct MusicPlayerInfo *musicPlayerNext; }; struct MusicPlayer { struct MusicPlayerInfo *info; struct MusicPlayerTrack *track; u8 numTracks; u16 unk_A; }; struct Song { struct SongHeader *header; u16 ms; u16 me; }; extern const struct MusicPlayer gMPlayTable[]; extern const struct Song gSongTable[]; extern u8 gMPlayMemAccArea[]; //u8 gPokemonCrySong[52]; //u8 gPokemonCrySongs[52 * MAX_POKEMON_CRIES]; #define MAX_POKEMON_CRIES 2 extern struct PokemonCrySong gPokemonCrySong; extern struct PokemonCrySong gPokemonCrySongs[]; extern struct MusicPlayerInfo gPokemonCryMusicPlayers[]; extern struct MusicPlayerTrack gPokemonCryTracks[]; extern char SoundMainRAM[]; extern MPlayFunc gMPlayJumpTable[]; typedef void (*XcmdFunc)(struct MusicPlayerInfo *, struct MusicPlayerTrack *); extern const XcmdFunc gXcmdTable[]; extern struct CgbChannel gCgbChans[]; extern const u8 gScaleTable[]; extern const u32 gFreqTable[]; extern const u16 gPcmSamplesPerVBlankTable[]; extern const u8 gCgbScaleTable[]; extern const s16 gCgbFreqTable[]; extern const u8 gNoiseTable[]; extern const struct PokemonCrySong gPokemonCrySongTemplate; extern const struct ToneData voicegroup000; extern char gNumMusicPlayers[]; extern char gMaxLines[]; #define NUM_MUSIC_PLAYERS ((u16)gNumMusicPlayers) #define MAX_LINES ((u32)gMaxLines) u32 umul3232H32(u32 multiplier, u32 multiplicand); void SoundMain(void); void SoundMainBTM(void); void TrackStop(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track); void MPlayMain(struct MusicPlayerInfo *); void RealClearChain(void *x); void MPlayContinue(struct MusicPlayerInfo *mplayInfo); void MPlayStart(struct MusicPlayerInfo *mplayInfo, struct SongHeader *songHeader); void m4aMPlayStop(struct MusicPlayerInfo *mplayInfo); void FadeOutBody(struct MusicPlayerInfo *mplayInfo); void TrkVolPitSet(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track); void MPlayFadeOut(struct MusicPlayerInfo *mplayInfo, u16 speed); void ClearChain(void *x); void Clear64byte(void *addr); void SoundInit(struct SoundInfo *soundInfo); void MPlayExtender(struct CgbChannel *cgbChans); void m4aSoundMode(u32 mode); void MPlayOpen(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *tracks, u8 trackCount); void CgbSound(void); void CgbOscOff(u8); void CgbModVol(struct CgbChannel *chan); u32 MidiKeyToCgbFreq(u8, u8, u8); void DummyFunc(void); void MPlayJumpTableCopy(MPlayFunc *mplayJumpTable); void SampleFreqSet(u32 freq); void m4aSoundVSyncOn(void); void m4aSoundVSyncOff(void); void m4aMPlayTempoControl(struct MusicPlayerInfo *mplayInfo, u16 tempo); void m4aMPlayVolumeControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u16 volume); void m4aMPlayPitchControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, s16 pitch); void m4aMPlayPanpotControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, s8 pan); void ClearModM(struct MusicPlayerTrack *track); void m4aMPlayModDepthSet(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u8 modDepth); void m4aMPlayLFOSpeedSet(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u8 lfoSpeed); struct MusicPlayerInfo *SetPokemonCryTone(struct ToneData *tone); void SetPokemonCryVolume(u8 val); void SetPokemonCryPanpot(s8 val); void SetPokemonCryPitch(s16 val); void SetPokemonCryLength(u16 val); void SetPokemonCryRelease(u8 val); void SetPokemonCryProgress(u32 val); bool32 IsPokemonCryPlaying(struct MusicPlayerInfo *mplayInfo); void SetPokemonCryChorus(s8 val); void SetPokemonCryStereo(u32 val); void SetPokemonCryPriority(u8 val); // sound command handler functions void ply_fine(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_goto(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_patt(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_pend(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_rept(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_memacc(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_prio(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_tempo(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_keysh(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_voice(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_vol(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_pan(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_bend(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_bendr(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_lfos(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_lfodl(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_mod(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_modt(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_tune(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_port(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_xcmd(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_endtie(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_note(u32 note_cmd, struct MusicPlayerInfo *, struct MusicPlayerTrack *); // extended sound command handler functions void ply_xxx(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_xwave(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_xtype(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_xatta(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_xdeca(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_xsust(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_xrele(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_xiecv(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_xiecl(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_xleng(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_xswee(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_xcmd_0C(struct MusicPlayerInfo *, struct MusicPlayerTrack *); void ply_xcmd_0D(struct MusicPlayerInfo *, struct MusicPlayerTrack *); #endif // GUARD_GBA_M4A_INTERNAL_H