mirror of
https://github.com/pret/pokefirered.git
synced 2024-11-26 23:00:28 +00:00
port cgbsound documentation and fakematch fixes
This commit is contained in:
parent
feb5428937
commit
dbc41d1d14
@ -1,5 +1,5 @@
|
|||||||
#ifndef GUARD_M4A_INTERNAL_H
|
#ifndef GUARD_GBA_M4A_INTERNAL_H
|
||||||
#define GUARD_M4A_INTERNAL_H
|
#define GUARD_GBA_M4A_INTERNAL_H
|
||||||
|
|
||||||
#include "gba/gba.h"
|
#include "gba/gba.h"
|
||||||
|
|
||||||
@ -67,52 +67,26 @@ struct ToneData
|
|||||||
u8 release;
|
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
|
struct CgbChannel
|
||||||
{
|
{
|
||||||
u8 sf;
|
u8 statusFlags;
|
||||||
u8 ty;
|
|
||||||
u8 rightVolume;
|
|
||||||
u8 leftVolume;
|
|
||||||
u8 at;
|
|
||||||
u8 de;
|
|
||||||
u8 su;
|
|
||||||
u8 re;
|
|
||||||
u8 ky;
|
|
||||||
u8 ev;
|
|
||||||
u8 eg;
|
|
||||||
u8 ec;
|
|
||||||
u8 echoVolume;
|
|
||||||
u8 echoLength;
|
|
||||||
u8 d1;
|
|
||||||
u8 d2;
|
|
||||||
u8 gt;
|
|
||||||
u8 mk;
|
|
||||||
u8 ve;
|
|
||||||
u8 pr;
|
|
||||||
u8 rp;
|
|
||||||
u8 d3[3];
|
|
||||||
u8 d5;
|
|
||||||
u8 sg;
|
|
||||||
u8 n4;
|
|
||||||
u8 pan;
|
|
||||||
u8 panMask;
|
|
||||||
u8 mo;
|
|
||||||
u8 le;
|
|
||||||
u8 sw;
|
|
||||||
u32 fr;
|
|
||||||
u32 * wp;
|
|
||||||
u32 cp;
|
|
||||||
u32 tp;
|
|
||||||
u32 pp;
|
|
||||||
u32 np;
|
|
||||||
u8 d4[8];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MusicPlayerTrack;
|
|
||||||
|
|
||||||
struct SoundChannel
|
|
||||||
{
|
|
||||||
u8 status;
|
|
||||||
u8 type;
|
u8 type;
|
||||||
u8 rightVolume;
|
u8 rightVolume;
|
||||||
u8 leftVolume;
|
u8 leftVolume;
|
||||||
@ -120,29 +94,72 @@ struct SoundChannel
|
|||||||
u8 decay;
|
u8 decay;
|
||||||
u8 sustain;
|
u8 sustain;
|
||||||
u8 release;
|
u8 release;
|
||||||
u8 ky;
|
u8 key;
|
||||||
u8 ev;
|
u8 envelopeVolume;
|
||||||
u8 er;
|
u8 envelopeGoal;
|
||||||
u8 el;
|
u8 envelopeCounter;
|
||||||
u8 echoVolume;
|
u8 pseudoEchoVolume;
|
||||||
u8 echoLength;
|
u8 pseudoEchoLength;
|
||||||
u8 d1;
|
u8 dummy1;
|
||||||
u8 d2;
|
u8 dummy2;
|
||||||
u8 gt;
|
u8 gateTime;
|
||||||
u8 mk;
|
u8 midiKey;
|
||||||
u8 ve;
|
u8 velocity;
|
||||||
u8 pr;
|
u8 priority;
|
||||||
u8 rp;
|
u8 rhythmPan;
|
||||||
u8 d3[3];
|
u8 dummy3[3];
|
||||||
u32 ct;
|
u8 dummy5;
|
||||||
u32 fw;
|
u8 sustainGoal;
|
||||||
u32 freq;
|
u8 n4; // NR[1-4]4 register (initial, length bit)
|
||||||
struct WaveData *wav;
|
u8 pan;
|
||||||
u32 cp;
|
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;
|
struct MusicPlayerTrack *track;
|
||||||
u32 pp;
|
void *prevChannelPointer;
|
||||||
u32 np;
|
void *nextChannelPointer;
|
||||||
u32 d4;
|
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 xpi;
|
||||||
u16 xpc;
|
u16 xpc;
|
||||||
};
|
};
|
||||||
@ -151,6 +168,16 @@ struct SoundChannel
|
|||||||
|
|
||||||
#define PCM_DMA_BUF_SIZE 1584 // size of Direct Sound buffer
|
#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
|
struct SoundInfo
|
||||||
{
|
{
|
||||||
// This field is normally equal to ID_NUMBER but it is set to other
|
// This field is normally equal to ID_NUMBER but it is set to other
|
||||||
@ -168,7 +195,7 @@ struct SoundInfo
|
|||||||
u8 freq;
|
u8 freq;
|
||||||
|
|
||||||
u8 mode;
|
u8 mode;
|
||||||
u8 c15;
|
u8 c15; // periodically counts from 14 down to 0 (15 states)
|
||||||
u8 pcmDmaPeriod; // number of V-blanks per PCM DMA
|
u8 pcmDmaPeriod; // number of V-blanks per PCM DMA
|
||||||
u8 maxLines;
|
u8 maxLines;
|
||||||
u8 gap[3];
|
u8 gap[3];
|
||||||
@ -176,14 +203,14 @@ struct SoundInfo
|
|||||||
s32 pcmFreq;
|
s32 pcmFreq;
|
||||||
s32 divFreq;
|
s32 divFreq;
|
||||||
struct CgbChannel *cgbChans;
|
struct CgbChannel *cgbChans;
|
||||||
u32 func;
|
MPlayMainFunc MPlayMainHead;
|
||||||
u32 intp;
|
struct MusicPlayerInfo *musicPlayerHead;
|
||||||
void (*CgbSound)(void);
|
CgbSoundFunc CgbSound;
|
||||||
void (*CgbOscOff)(u8);
|
CgbOscOffFunc CgbOscOff;
|
||||||
u32 (*MidiKeyToCgbFreq)(u8, u8, u8);
|
MidiKeyToCgbFreqFunc MidiKeyToCgbFreq;
|
||||||
u32 MPlayJumpTable;
|
MPlayFunc *MPlayJumpTable;
|
||||||
u32 plynote;
|
PlyNoteFunc plynote;
|
||||||
u32 ExtVolPit;
|
ExtVolPitFunc ExtVolPit;
|
||||||
u8 gap2[16];
|
u8 gap2[16];
|
||||||
struct SoundChannel chans[MAX_DIRECTSOUND_CHANNELS];
|
struct SoundChannel chans[MAX_DIRECTSOUND_CHANNELS];
|
||||||
s8 pcmBuffer[PCM_DMA_BUF_SIZE * 2];
|
s8 pcmBuffer[PCM_DMA_BUF_SIZE * 2];
|
||||||
@ -270,8 +297,8 @@ struct MusicPlayerTrack
|
|||||||
u8 lfoDelay;
|
u8 lfoDelay;
|
||||||
u8 lfoDelayC;
|
u8 lfoDelayC;
|
||||||
u8 priority;
|
u8 priority;
|
||||||
u8 echoVolume;
|
u8 pseudoEchoVolume;
|
||||||
u8 echoLength;
|
u8 pseudoEchoLength;
|
||||||
struct SoundChannel *chan;
|
struct SoundChannel *chan;
|
||||||
struct ToneData tone;
|
struct ToneData tone;
|
||||||
u8 gap[10];
|
u8 gap[10];
|
||||||
@ -312,8 +339,8 @@ struct MusicPlayerInfo
|
|||||||
struct MusicPlayerTrack *tracks;
|
struct MusicPlayerTrack *tracks;
|
||||||
struct ToneData *tone;
|
struct ToneData *tone;
|
||||||
u32 ident;
|
u32 ident;
|
||||||
u32 func;
|
MPlayMainFunc MPlayMainNext;
|
||||||
u32 intp;
|
struct MusicPlayerInfo *musicPlayerNext;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MusicPlayer
|
struct MusicPlayer
|
||||||
@ -351,7 +378,7 @@ extern struct MusicPlayerTrack gPokemonCryTracks[];
|
|||||||
|
|
||||||
extern char SoundMainRAM[];
|
extern char SoundMainRAM[];
|
||||||
|
|
||||||
extern void *gMPlayJumpTable[];
|
extern MPlayFunc gMPlayJumpTable[];
|
||||||
|
|
||||||
typedef void (*XcmdFunc)(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
|
typedef void (*XcmdFunc)(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
|
||||||
extern const XcmdFunc gXcmdTable[];
|
extern const XcmdFunc gXcmdTable[];
|
||||||
@ -380,7 +407,7 @@ u32 umul3232H32(u32 multiplier, u32 multiplicand);
|
|||||||
void SoundMain(void);
|
void SoundMain(void);
|
||||||
void SoundMainBTM(void);
|
void SoundMainBTM(void);
|
||||||
void TrackStop(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track);
|
void TrackStop(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track);
|
||||||
void MPlayMain(void);
|
void MPlayMain(struct MusicPlayerInfo *);
|
||||||
void RealClearChain(void *x);
|
void RealClearChain(void *x);
|
||||||
|
|
||||||
void MPlayContinue(struct MusicPlayerInfo *mplayInfo);
|
void MPlayContinue(struct MusicPlayerInfo *mplayInfo);
|
||||||
@ -397,9 +424,10 @@ void m4aSoundMode(u32 mode);
|
|||||||
void MPlayOpen(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track, u8 a3);
|
void MPlayOpen(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track, u8 a3);
|
||||||
void CgbSound(void);
|
void CgbSound(void);
|
||||||
void CgbOscOff(u8);
|
void CgbOscOff(u8);
|
||||||
|
void CgbModVol(struct CgbChannel *chan);
|
||||||
u32 MidiKeyToCgbFreq(u8, u8, u8);
|
u32 MidiKeyToCgbFreq(u8, u8, u8);
|
||||||
void DummyFunc(void);
|
void DummyFunc(void);
|
||||||
void MPlayJumpTableCopy(void **mplayJumpTable);
|
void MPlayJumpTableCopy(MPlayFunc *mplayJumpTable);
|
||||||
void SampleFreqSet(u32 freq);
|
void SampleFreqSet(u32 freq);
|
||||||
void m4aSoundVSyncOn(void);
|
void m4aSoundVSyncOn(void);
|
||||||
void m4aSoundVSyncOff(void);
|
void m4aSoundVSyncOff(void);
|
||||||
@ -419,7 +447,7 @@ void SetPokemonCryPitch(s16 val);
|
|||||||
void SetPokemonCryLength(u16 val);
|
void SetPokemonCryLength(u16 val);
|
||||||
void SetPokemonCryRelease(u8 val);
|
void SetPokemonCryRelease(u8 val);
|
||||||
void SetPokemonCryProgress(u32 val);
|
void SetPokemonCryProgress(u32 val);
|
||||||
int IsPokemonCryPlaying(struct MusicPlayerInfo *mplayInfo);
|
bool32 IsPokemonCryPlaying(struct MusicPlayerInfo *mplayInfo);
|
||||||
void SetPokemonCryChorus(s8 val);
|
void SetPokemonCryChorus(s8 val);
|
||||||
void SetPokemonCryStereo(u32 val);
|
void SetPokemonCryStereo(u32 val);
|
||||||
void SetPokemonCryPriority(u8 val);
|
void SetPokemonCryPriority(u8 val);
|
||||||
@ -447,7 +475,7 @@ void ply_tune(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
|
|||||||
void ply_port(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
|
void ply_port(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
|
||||||
void ply_xcmd(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
|
void ply_xcmd(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
|
||||||
void ply_endtie(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
|
void ply_endtie(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
|
||||||
void ply_note(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
|
void ply_note(u32 note_cmd, struct MusicPlayerInfo *, struct MusicPlayerTrack *);
|
||||||
|
|
||||||
// extended sound command handler functions
|
// extended sound command handler functions
|
||||||
void ply_xxx(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
|
void ply_xxx(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
|
||||||
@ -464,4 +492,4 @@ void ply_xswee(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
|
|||||||
void ply_xcmd_0C(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
|
void ply_xcmd_0C(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
|
||||||
void ply_xcmd_0D(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
|
void ply_xcmd_0D(struct MusicPlayerInfo *, struct MusicPlayerTrack *);
|
||||||
|
|
||||||
#endif // GUARD_M4A_INTERNAL_H
|
#endif // GUARD_GBA_M4A_INTERNAL_H
|
||||||
|
@ -1,22 +1,15 @@
|
|||||||
#ifndef GUARD_M4A_H
|
#ifndef GUARD_M4A_H
|
||||||
#define GUARD_M4A_H
|
#define GUARD_M4A_H
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
#include "gba/m4a_internal.h"
|
#include "gba/m4a_internal.h"
|
||||||
|
|
||||||
extern struct MusicPlayerInfo gMPlayInfo_BGM;
|
|
||||||
extern struct MusicPlayerInfo gMPlayInfo_SE1;
|
|
||||||
extern struct MusicPlayerInfo gMPlayInfo_SE2;
|
|
||||||
extern struct MusicPlayerInfo gMPlayInfo_SE3;
|
|
||||||
extern struct SoundInfo gSoundInfo;
|
|
||||||
|
|
||||||
void m4aSoundVSync(void);
|
void m4aSoundVSync(void);
|
||||||
void m4aSoundVSyncOn(void);
|
void m4aSoundVSyncOn(void);
|
||||||
|
|
||||||
void m4aSoundInit(void);
|
void m4aSoundInit(void);
|
||||||
void m4aSoundMain(void);
|
void m4aSoundMain(void);
|
||||||
void m4aSongNumStart(u16);
|
void m4aSongNumStart(u16 n);
|
||||||
|
void m4aSongNumStartOrChange(u16 n);
|
||||||
void m4aSongNumStop(u16 n);
|
void m4aSongNumStop(u16 n);
|
||||||
void m4aMPlayAllStop(void);
|
void m4aMPlayAllStop(void);
|
||||||
void m4aMPlayContinue(struct MusicPlayerInfo *mplayInfo);
|
void m4aMPlayContinue(struct MusicPlayerInfo *mplayInfo);
|
||||||
@ -25,6 +18,12 @@ void m4aMPlayFadeOutTemporarily(struct MusicPlayerInfo *mplayInfo, u16 speed);
|
|||||||
void m4aMPlayFadeIn(struct MusicPlayerInfo *mplayInfo, u16 speed);
|
void m4aMPlayFadeIn(struct MusicPlayerInfo *mplayInfo, u16 speed);
|
||||||
void m4aMPlayImmInit(struct MusicPlayerInfo *mplayInfo);
|
void m4aMPlayImmInit(struct MusicPlayerInfo *mplayInfo);
|
||||||
|
|
||||||
|
extern struct MusicPlayerInfo gMPlayInfo_BGM;
|
||||||
|
extern struct MusicPlayerInfo gMPlayInfo_SE1;
|
||||||
|
extern struct MusicPlayerInfo gMPlayInfo_SE2;
|
||||||
|
extern struct MusicPlayerInfo gMPlayInfo_SE3;
|
||||||
|
extern struct SoundInfo gSoundInfo;
|
||||||
|
|
||||||
extern const struct SongHeader mus_victory_gym_leader;
|
extern const struct SongHeader mus_victory_gym_leader;
|
||||||
|
|
||||||
#endif //GUARD_M4A_H
|
#endif //GUARD_M4A_H
|
||||||
|
414
src/m4a.c
414
src/m4a.c
@ -1,3 +1,4 @@
|
|||||||
|
#include <string.h>
|
||||||
#include "gba/m4a_internal.h"
|
#include "gba/m4a_internal.h"
|
||||||
|
|
||||||
extern const u8 gCgb3Vol[];
|
extern const u8 gCgb3Vol[];
|
||||||
@ -9,7 +10,7 @@ BSS_CODE ALIGNED(4) char SoundMainRAM_Buffer[0x800] = {0};
|
|||||||
struct SoundInfo gSoundInfo;
|
struct SoundInfo gSoundInfo;
|
||||||
struct PokemonCrySong gPokemonCrySongs[MAX_POKEMON_CRIES];
|
struct PokemonCrySong gPokemonCrySongs[MAX_POKEMON_CRIES];
|
||||||
struct MusicPlayerInfo gPokemonCryMusicPlayers[MAX_POKEMON_CRIES];
|
struct MusicPlayerInfo gPokemonCryMusicPlayers[MAX_POKEMON_CRIES];
|
||||||
void *gMPlayJumpTable[36];
|
MPlayFunc gMPlayJumpTable[36];
|
||||||
struct CgbChannel gCgbChans[4];
|
struct CgbChannel gCgbChans[4];
|
||||||
struct MusicPlayerTrack gPokemonCryTracks[MAX_POKEMON_CRIES * 2];
|
struct MusicPlayerTrack gPokemonCryTracks[MAX_POKEMON_CRIES * 2];
|
||||||
struct PokemonCrySong gPokemonCrySong;
|
struct PokemonCrySong gPokemonCrySong;
|
||||||
@ -292,7 +293,7 @@ void MPlayExtender(struct CgbChannel *cgbChans)
|
|||||||
gMPlayJumpTable[32] = FadeOutBody;
|
gMPlayJumpTable[32] = FadeOutBody;
|
||||||
gMPlayJumpTable[33] = TrkVolPitSet;
|
gMPlayJumpTable[33] = TrkVolPitSet;
|
||||||
|
|
||||||
soundInfo->cgbChans = (struct CgbChannel *)cgbChans;
|
soundInfo->cgbChans = cgbChans;
|
||||||
soundInfo->CgbSound = CgbSound;
|
soundInfo->CgbSound = CgbSound;
|
||||||
soundInfo->CgbOscOff = CgbOscOff;
|
soundInfo->CgbOscOff = CgbOscOff;
|
||||||
soundInfo->MidiKeyToCgbFreq = MidiKeyToCgbFreq;
|
soundInfo->MidiKeyToCgbFreq = MidiKeyToCgbFreq;
|
||||||
@ -300,13 +301,13 @@ void MPlayExtender(struct CgbChannel *cgbChans)
|
|||||||
|
|
||||||
CpuFill32(0, cgbChans, sizeof(struct CgbChannel) * 4);
|
CpuFill32(0, cgbChans, sizeof(struct CgbChannel) * 4);
|
||||||
|
|
||||||
cgbChans[0].ty = 1;
|
cgbChans[0].type = 1;
|
||||||
cgbChans[0].panMask = 0x11;
|
cgbChans[0].panMask = 0x11;
|
||||||
cgbChans[1].ty = 2;
|
cgbChans[1].type = 2;
|
||||||
cgbChans[1].panMask = 0x22;
|
cgbChans[1].panMask = 0x22;
|
||||||
cgbChans[2].ty = 3;
|
cgbChans[2].type = 3;
|
||||||
cgbChans[2].panMask = 0x44;
|
cgbChans[2].panMask = 0x44;
|
||||||
cgbChans[3].ty = 4;
|
cgbChans[3].type = 4;
|
||||||
cgbChans[3].panMask = 0x88;
|
cgbChans[3].panMask = 0x88;
|
||||||
|
|
||||||
soundInfo->ident = ident;
|
soundInfo->ident = ident;
|
||||||
@ -314,7 +315,7 @@ void MPlayExtender(struct CgbChannel *cgbChans)
|
|||||||
|
|
||||||
void MusicPlayerJumpTableCopy(void)
|
void MusicPlayerJumpTableCopy(void)
|
||||||
{
|
{
|
||||||
asm("svc 0x2A");
|
asm("swi 0x2A");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClearChain(void *x)
|
void ClearChain(void *x)
|
||||||
@ -361,15 +362,15 @@ void SoundInit(struct SoundInfo *soundInfo)
|
|||||||
|
|
||||||
soundInfo->maxChans = 8;
|
soundInfo->maxChans = 8;
|
||||||
soundInfo->masterVolume = 15;
|
soundInfo->masterVolume = 15;
|
||||||
soundInfo->plynote = (u32)ply_note;
|
soundInfo->plynote = ply_note;
|
||||||
soundInfo->CgbSound = DummyFunc;
|
soundInfo->CgbSound = DummyFunc;
|
||||||
soundInfo->CgbOscOff = (void (*)(u8))DummyFunc;
|
soundInfo->CgbOscOff = (CgbOscOffFunc)DummyFunc;
|
||||||
soundInfo->MidiKeyToCgbFreq = (u32 (*)(u8, u8, u8))DummyFunc;
|
soundInfo->MidiKeyToCgbFreq = (MidiKeyToCgbFreqFunc)DummyFunc;
|
||||||
soundInfo->ExtVolPit = (u32)DummyFunc;
|
soundInfo->ExtVolPit = (ExtVolPitFunc)DummyFunc;
|
||||||
|
|
||||||
MPlayJumpTableCopy(gMPlayJumpTable);
|
MPlayJumpTableCopy(gMPlayJumpTable);
|
||||||
|
|
||||||
soundInfo->MPlayJumpTable = (u32)gMPlayJumpTable;
|
soundInfo->MPlayJumpTable = gMPlayJumpTable;
|
||||||
|
|
||||||
SampleFreqSet(SOUND_MODE_FREQ_13379);
|
SampleFreqSet(SOUND_MODE_FREQ_13379);
|
||||||
|
|
||||||
@ -436,7 +437,7 @@ void m4aSoundMode(u32 mode)
|
|||||||
|
|
||||||
while (temp != 0)
|
while (temp != 0)
|
||||||
{
|
{
|
||||||
chan->status = 0;
|
chan->statusFlags = 0;
|
||||||
temp--;
|
temp--;
|
||||||
chan++;
|
chan++;
|
||||||
}
|
}
|
||||||
@ -482,7 +483,7 @@ void SoundClear(void)
|
|||||||
|
|
||||||
while (i > 0)
|
while (i > 0)
|
||||||
{
|
{
|
||||||
((struct SoundChannel *)chan)->status = 0;
|
((struct SoundChannel *)chan)->statusFlags = 0;
|
||||||
i--;
|
i--;
|
||||||
chan = (void *)((s32)chan + sizeof(struct SoundChannel));
|
chan = (void *)((s32)chan + sizeof(struct SoundChannel));
|
||||||
}
|
}
|
||||||
@ -496,7 +497,7 @@ void SoundClear(void)
|
|||||||
while (i <= 4)
|
while (i <= 4)
|
||||||
{
|
{
|
||||||
soundInfo->CgbOscOff(i);
|
soundInfo->CgbOscOff(i);
|
||||||
((struct CgbChannel *)chan)->sf = 0;
|
((struct CgbChannel *)chan)->statusFlags = 0;
|
||||||
i++;
|
i++;
|
||||||
chan = (void *)((s32)chan + sizeof(struct CgbChannel));
|
chan = (void *)((s32)chan + sizeof(struct CgbChannel));
|
||||||
}
|
}
|
||||||
@ -571,15 +572,18 @@ void MPlayOpen(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track
|
|||||||
tracks++;
|
tracks++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (soundInfo->func != 0)
|
// append music player and MPlayMain to linked list
|
||||||
|
|
||||||
|
if (soundInfo->MPlayMainHead != NULL)
|
||||||
{
|
{
|
||||||
mplayInfo->func = soundInfo->func;
|
mplayInfo->MPlayMainNext = soundInfo->MPlayMainHead;
|
||||||
mplayInfo->intp = soundInfo->intp;
|
mplayInfo->musicPlayerNext = soundInfo->musicPlayerHead;
|
||||||
soundInfo->func = 0;
|
// NULL assignment semantically useless, but required for match
|
||||||
|
soundInfo->MPlayMainHead = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
soundInfo->intp = (u32)mplayInfo;
|
soundInfo->musicPlayerHead = mplayInfo;
|
||||||
soundInfo->func = (u32)MPlayMain;
|
soundInfo->MPlayMainHead = MPlayMain;
|
||||||
soundInfo->ident = ID_NUMBER;
|
soundInfo->ident = ID_NUMBER;
|
||||||
mplayInfo->ident = ID_NUMBER;
|
mplayInfo->ident = ID_NUMBER;
|
||||||
}
|
}
|
||||||
@ -634,7 +638,7 @@ void MPlayStart(struct MusicPlayerInfo *mplayInfo, struct SongHeader *songHeader
|
|||||||
track++;
|
track++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (songHeader->reverb & 0x80)
|
if (songHeader->reverb & SOUND_MODE_REVERB_SET)
|
||||||
m4aSoundMode(songHeader->reverb);
|
m4aSoundMode(songHeader->reverb);
|
||||||
|
|
||||||
mplayInfo->ident = ID_NUMBER;
|
mplayInfo->ident = ID_NUMBER;
|
||||||
@ -690,7 +694,10 @@ void FadeOutBody(struct MusicPlayerInfo *mplayInfo)
|
|||||||
{
|
{
|
||||||
if ((s16)(mplayInfo->fadeOV -= (4 << FADE_VOL_SHIFT)) <= 0)
|
if ((s16)(mplayInfo->fadeOV -= (4 << FADE_VOL_SHIFT)) <= 0)
|
||||||
{
|
{
|
||||||
for (i = mplayInfo->trackCount, track = mplayInfo->tracks; i > 0; i--, track++)
|
i = mplayInfo->trackCount;
|
||||||
|
track = mplayInfo->tracks;
|
||||||
|
|
||||||
|
while (i > 0)
|
||||||
{
|
{
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
@ -702,6 +709,9 @@ void FadeOutBody(struct MusicPlayerInfo *mplayInfo)
|
|||||||
|
|
||||||
if (!val)
|
if (!val)
|
||||||
track->flags = 0;
|
track->flags = 0;
|
||||||
|
|
||||||
|
i--;
|
||||||
|
track++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mplayInfo->fadeOV & TEMPORARY_FADE)
|
if (mplayInfo->fadeOV & TEMPORARY_FADE)
|
||||||
@ -714,7 +724,10 @@ void FadeOutBody(struct MusicPlayerInfo *mplayInfo)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = mplayInfo->trackCount, track = mplayInfo->tracks; i > 0; i--, track++)
|
i = mplayInfo->trackCount;
|
||||||
|
track = mplayInfo->tracks;
|
||||||
|
|
||||||
|
while (i > 0)
|
||||||
{
|
{
|
||||||
if (track->flags & MPT_FLG_EXIST)
|
if (track->flags & MPT_FLG_EXIST)
|
||||||
{
|
{
|
||||||
@ -723,6 +736,9 @@ void FadeOutBody(struct MusicPlayerInfo *mplayInfo)
|
|||||||
track->volX = (fadeOV >> FADE_VOL_SHIFT);
|
track->volX = (fadeOV >> FADE_VOL_SHIFT);
|
||||||
track->flags |= MPT_FLG_VOLCHG;
|
track->flags |= MPT_FLG_VOLCHG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i--;
|
||||||
|
track++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -871,18 +887,18 @@ void CgbModVol(struct CgbChannel *chan)
|
|||||||
if ((soundInfo->mode & 1) || !CgbPan(chan))
|
if ((soundInfo->mode & 1) || !CgbPan(chan))
|
||||||
{
|
{
|
||||||
chan->pan = 0xFF;
|
chan->pan = 0xFF;
|
||||||
chan->eg = (u32)(chan->leftVolume + chan->rightVolume);
|
chan->envelopeGoal = (u32)(chan->leftVolume + chan->rightVolume);
|
||||||
chan->eg /= 16;
|
chan->envelopeGoal /= 16;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
chan->eg = (u32)(chan->leftVolume + chan->rightVolume);
|
chan->envelopeGoal = (u32)(chan->leftVolume + chan->rightVolume);
|
||||||
chan->eg /= 16;
|
chan->envelopeGoal /= 16;
|
||||||
if (chan->eg > 15)
|
if (chan->envelopeGoal > 15)
|
||||||
chan->eg = 15;
|
chan->envelopeGoal = 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
chan->sg = (chan->eg * chan->su + 15) >> 4;
|
chan->sustainGoal = (chan->envelopeGoal * chan->sustain + 15) >> 4;
|
||||||
chan->pan &= chan->panMask;
|
chan->pan &= chan->panMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -890,7 +906,6 @@ void CgbSound(void)
|
|||||||
{
|
{
|
||||||
s32 ch;
|
s32 ch;
|
||||||
struct CgbChannel *channels;
|
struct CgbChannel *channels;
|
||||||
s32 evAdd;
|
|
||||||
s32 prevC15;
|
s32 prevC15;
|
||||||
struct SoundInfo *soundInfo = SOUND_INFO_PTR;
|
struct SoundInfo *soundInfo = SOUND_INFO_PTR;
|
||||||
vu8 *nrx0ptr;
|
vu8 *nrx0ptr;
|
||||||
@ -898,6 +913,7 @@ void CgbSound(void)
|
|||||||
vu8 *nrx2ptr;
|
vu8 *nrx2ptr;
|
||||||
vu8 *nrx3ptr;
|
vu8 *nrx3ptr;
|
||||||
vu8 *nrx4ptr;
|
vu8 *nrx4ptr;
|
||||||
|
s32 envelopeStepTimeAndDir;
|
||||||
|
|
||||||
// Most comparision operations that cast to s8 perform 'and' by 0xFF.
|
// Most comparision operations that cast to s8 perform 'and' by 0xFF.
|
||||||
int mask = 0xff;
|
int mask = 0xff;
|
||||||
@ -909,9 +925,10 @@ void CgbSound(void)
|
|||||||
|
|
||||||
for (ch = 1, channels = soundInfo->cgbChans; ch <= 4; ch++, channels++)
|
for (ch = 1, channels = soundInfo->cgbChans; ch <= 4; ch++, channels++)
|
||||||
{
|
{
|
||||||
if (!(channels->sf & 0xc7))
|
if (!(channels->statusFlags & SOUND_CHANNEL_SF_ON))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* 1. determine hardware channel registers */
|
||||||
switch (ch)
|
switch (ch)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
@ -945,243 +962,233 @@ void CgbSound(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
prevC15 = soundInfo->c15;
|
prevC15 = soundInfo->c15;
|
||||||
evAdd = *nrx2ptr;
|
envelopeStepTimeAndDir = *nrx2ptr;
|
||||||
|
|
||||||
if (channels->sf & 0x80)
|
/* 2. calculate envelope volume */
|
||||||
|
if (channels->statusFlags & SOUND_CHANNEL_SF_START)
|
||||||
{
|
{
|
||||||
if (!(channels->sf & 0x40))
|
if (!(channels->statusFlags & SOUND_CHANNEL_SF_STOP))
|
||||||
{
|
{
|
||||||
channels->sf = 3;
|
channels->statusFlags = SOUND_CHANNEL_SF_ENV_ATTACK;
|
||||||
channels->mo = 3;
|
channels->modify = CGB_CHANNEL_MO_PIT | CGB_CHANNEL_MO_VOL;
|
||||||
CgbModVol(channels);
|
CgbModVol(channels);
|
||||||
switch (ch)
|
switch (ch)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
*nrx0ptr = channels->sw;
|
*nrx0ptr = channels->sweep;
|
||||||
// fallthrough
|
// fallthrough
|
||||||
case 2:
|
case 2:
|
||||||
*nrx1ptr = ((u32)channels->wp << 6) + channels->le;
|
*nrx1ptr = ((u32)channels->wavePointer << 6) + channels->length;
|
||||||
goto loc_82E0E30;
|
goto init_env_step_time_dir;
|
||||||
case 3:
|
case 3:
|
||||||
if ((u32)channels->wp != channels->cp)
|
if (channels->wavePointer != channels->currentPointer)
|
||||||
{
|
{
|
||||||
*nrx0ptr = 0x40;
|
*nrx0ptr = 0x40;
|
||||||
REG_WAVE_RAM0 = channels->wp[0];
|
REG_WAVE_RAM0 = channels->wavePointer[0];
|
||||||
REG_WAVE_RAM1 = channels->wp[1];
|
REG_WAVE_RAM1 = channels->wavePointer[1];
|
||||||
REG_WAVE_RAM2 = channels->wp[2];
|
REG_WAVE_RAM2 = channels->wavePointer[2];
|
||||||
REG_WAVE_RAM3 = channels->wp[3];
|
REG_WAVE_RAM3 = channels->wavePointer[3];
|
||||||
channels->cp = (u32)channels->wp;
|
channels->currentPointer = channels->wavePointer;
|
||||||
}
|
}
|
||||||
*nrx0ptr = 0;
|
*nrx0ptr = 0;
|
||||||
*nrx1ptr = channels->le;
|
*nrx1ptr = channels->length;
|
||||||
if (channels->le)
|
if (channels->length)
|
||||||
channels->n4 = -64;
|
channels->n4 = 0xC0;
|
||||||
else
|
else
|
||||||
channels->n4 = -128;
|
channels->n4 = 0x80;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
*nrx1ptr = channels->le;
|
*nrx1ptr = channels->length;
|
||||||
*nrx3ptr = (u32)channels->wp << 3;
|
*nrx3ptr = (u32)channels->wavePointer << 3;
|
||||||
loc_82E0E30:
|
init_env_step_time_dir:
|
||||||
evAdd = channels->at + 8;
|
envelopeStepTimeAndDir = channels->attack + CGB_NRx2_ENV_DIR_INC;
|
||||||
if (channels->le)
|
if (channels->length)
|
||||||
channels->n4 = 64;
|
channels->n4 = 0x40;
|
||||||
else
|
else
|
||||||
channels->n4 = 0;
|
channels->n4 = 0x00;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
channels->ec = channels->at;
|
channels->envelopeCounter = channels->attack;
|
||||||
if ((s8)(channels->at & mask))
|
if ((s8)(channels->attack & mask))
|
||||||
{
|
{
|
||||||
channels->ev = 0;
|
channels->envelopeVolume = 0;
|
||||||
goto EC_MINUS;
|
goto envelope_step_complete;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
goto loc_82E0F96;
|
// skip attack phase if attack is instantaneous (=0)
|
||||||
|
goto envelope_decay_start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
goto loc_82E0E82;
|
goto oscillator_off;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (channels->sf & 0x04)
|
else if (channels->statusFlags & SOUND_CHANNEL_SF_IEC)
|
||||||
{
|
{
|
||||||
channels->echoLength--;
|
channels->pseudoEchoLength--;
|
||||||
if ((s8)(channels->echoLength & mask) <= 0)
|
if ((s8)(channels->pseudoEchoLength & mask) <= 0)
|
||||||
{
|
{
|
||||||
loc_82E0E82:
|
oscillator_off:
|
||||||
CgbOscOff(ch);
|
CgbOscOff(ch);
|
||||||
channels->sf = 0;
|
channels->statusFlags = 0;
|
||||||
goto LAST_LABEL;
|
goto channel_complete;
|
||||||
}
|
}
|
||||||
goto loc_82E0FD6;
|
goto envelope_complete;
|
||||||
}
|
}
|
||||||
else if ((channels->sf & 0x40) && (channels->sf & 0x03))
|
else if ((channels->statusFlags & SOUND_CHANNEL_SF_STOP) && (channels->statusFlags & SOUND_CHANNEL_SF_ENV))
|
||||||
{
|
{
|
||||||
channels->sf &= 0xfc;
|
channels->statusFlags &= ~SOUND_CHANNEL_SF_ENV;
|
||||||
channels->ec = channels->re;
|
channels->envelopeCounter = channels->release;
|
||||||
if ((s8)(channels->re & mask))
|
if ((s8)(channels->release & mask))
|
||||||
{
|
{
|
||||||
channels->mo |= 1;
|
channels->modify |= CGB_CHANNEL_MO_VOL;
|
||||||
if (ch != 3)
|
if (ch != 3)
|
||||||
{
|
envelopeStepTimeAndDir = channels->release | CGB_NRx2_ENV_DIR_DEC;
|
||||||
evAdd = channels->re;
|
goto envelope_step_complete;
|
||||||
}
|
|
||||||
goto EC_MINUS;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
goto loc_82E0F02;
|
goto envelope_pseudoecho_start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
loc_82E0ED0:
|
envelope_step_repeat:
|
||||||
if (channels->ec == 0)
|
if (channels->envelopeCounter == 0)
|
||||||
{
|
{
|
||||||
if (ch == 3)
|
if (ch == 3)
|
||||||
{
|
channels->modify |= CGB_CHANNEL_MO_VOL;
|
||||||
channels->mo |= 1;
|
|
||||||
}
|
|
||||||
CgbModVol(channels);
|
|
||||||
if ((channels->sf & 0x3) == 0)
|
|
||||||
{
|
|
||||||
channels->ev--;
|
|
||||||
if ((s8)(channels->ev & mask) <= 0)
|
|
||||||
{
|
|
||||||
loc_82E0F02:
|
|
||||||
channels->ev = ((channels->eg * channels->echoVolume) + 0xFF) >> 8;
|
|
||||||
if (channels->ev)
|
|
||||||
{
|
|
||||||
channels->sf |= 0x4;
|
|
||||||
channels->mo |= 1;
|
|
||||||
if (ch != 3)
|
|
||||||
{
|
|
||||||
evAdd = 8;
|
|
||||||
}
|
|
||||||
goto loc_82E0FD6;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
goto loc_82E0E82;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
channels->ec = channels->re;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ((channels->sf & 0x3) == 1)
|
|
||||||
{
|
|
||||||
loc_82E0F3A:
|
|
||||||
channels->ev = channels->sg;
|
|
||||||
channels->ec = 7;
|
|
||||||
}
|
|
||||||
else if ((channels->sf & 0x3) == 2)
|
|
||||||
{
|
|
||||||
int ev, sg;
|
|
||||||
|
|
||||||
channels->ev--;
|
CgbModVol(channels);
|
||||||
ev = (s8)(channels->ev & mask);
|
if ((channels->statusFlags & SOUND_CHANNEL_SF_ENV) == SOUND_CHANNEL_SF_ENV_RELEASE)
|
||||||
sg = (s8)(channels->sg);
|
{
|
||||||
if (ev <= sg)
|
channels->envelopeVolume--;
|
||||||
|
if ((s8)(channels->envelopeVolume & mask) <= 0)
|
||||||
{
|
{
|
||||||
loc_82E0F5A:
|
envelope_pseudoecho_start:
|
||||||
if (channels->su == 0)
|
channels->envelopeVolume = ((channels->envelopeGoal * channels->pseudoEchoVolume) + 0xFF) >> 8;
|
||||||
|
if (channels->envelopeVolume)
|
||||||
{
|
{
|
||||||
channels->sf &= 0xfc;
|
channels->statusFlags |= SOUND_CHANNEL_SF_IEC;
|
||||||
goto loc_82E0F02;
|
channels->modify |= CGB_CHANNEL_MO_VOL;
|
||||||
|
if (ch != 3)
|
||||||
|
envelopeStepTimeAndDir = 0 | CGB_NRx2_ENV_DIR_INC;
|
||||||
|
goto envelope_complete;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
channels->sf--;
|
goto oscillator_off;
|
||||||
channels->mo |= 1;
|
|
||||||
if (ch != 3)
|
|
||||||
{
|
|
||||||
evAdd = 8;
|
|
||||||
}
|
|
||||||
goto loc_82E0F3A;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
channels->ec = channels->de;
|
channels->envelopeCounter = channels->release;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((channels->statusFlags & SOUND_CHANNEL_SF_ENV) == SOUND_CHANNEL_SF_ENV_SUSTAIN)
|
||||||
|
{
|
||||||
|
envelope_sustain:
|
||||||
|
channels->envelopeVolume = channels->sustainGoal;
|
||||||
|
channels->envelopeCounter = 7;
|
||||||
|
}
|
||||||
|
else if ((channels->statusFlags & SOUND_CHANNEL_SF_ENV) == SOUND_CHANNEL_SF_ENV_DECAY)
|
||||||
|
{
|
||||||
|
int envelopeVolume, sustainGoal;
|
||||||
|
|
||||||
|
channels->envelopeVolume--;
|
||||||
|
envelopeVolume = (s8)(channels->envelopeVolume & mask);
|
||||||
|
sustainGoal = (s8)(channels->sustainGoal);
|
||||||
|
if (envelopeVolume <= sustainGoal)
|
||||||
|
{
|
||||||
|
envelope_sustain_start:
|
||||||
|
if (channels->sustain == 0)
|
||||||
|
{
|
||||||
|
channels->statusFlags &= ~SOUND_CHANNEL_SF_ENV;
|
||||||
|
goto envelope_pseudoecho_start;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
channels->statusFlags--;
|
||||||
|
channels->modify |= CGB_CHANNEL_MO_VOL;
|
||||||
|
if (ch != 3)
|
||||||
|
envelopeStepTimeAndDir = 0 | CGB_NRx2_ENV_DIR_INC;
|
||||||
|
goto envelope_sustain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
channels->envelopeCounter = channels->decay;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
channels->ev++;
|
channels->envelopeVolume++;
|
||||||
if ((u8)(channels->ev & mask) >= channels->eg)
|
if ((u8)(channels->envelopeVolume & mask) >= channels->envelopeGoal)
|
||||||
{
|
{
|
||||||
loc_82E0F96:
|
envelope_decay_start:
|
||||||
channels->sf--;
|
channels->statusFlags--;
|
||||||
channels->ec = channels->de;
|
channels->envelopeCounter = channels->decay;
|
||||||
if ((u8)(channels->ec & mask))
|
if ((u8)(channels->envelopeCounter & mask))
|
||||||
{
|
{
|
||||||
channels->mo |= 1;
|
channels->modify |= CGB_CHANNEL_MO_VOL;
|
||||||
channels->ev = channels->eg;
|
channels->envelopeVolume = channels->envelopeGoal;
|
||||||
if (ch != 3)
|
if (ch != 3)
|
||||||
{
|
envelopeStepTimeAndDir = channels->decay | CGB_NRx2_ENV_DIR_DEC;
|
||||||
evAdd = channels->de;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
goto loc_82E0F5A;
|
goto envelope_sustain_start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
channels->ec = channels->at;
|
channels->envelopeCounter = channels->attack;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EC_MINUS:
|
envelope_step_complete:
|
||||||
channels->ec--;
|
// every 15 frames, envelope calculation has to be done twice
|
||||||
|
// to keep up with the hardware envelope rate (1/64 s)
|
||||||
|
channels->envelopeCounter--;
|
||||||
if (prevC15 == 0)
|
if (prevC15 == 0)
|
||||||
{
|
{
|
||||||
prevC15--;
|
prevC15--;
|
||||||
goto loc_82E0ED0;
|
goto envelope_step_repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
loc_82E0FD6:
|
envelope_complete:
|
||||||
if (channels->mo & 0x2)
|
/* 3. apply pitch to HW registers */
|
||||||
|
if (channels->modify & CGB_CHANNEL_MO_PIT)
|
||||||
{
|
{
|
||||||
if (ch < 4 && (channels->ty & 0x08))
|
if (ch < 4 && (channels->type & TONEDATA_TYPE_FIX))
|
||||||
{
|
{
|
||||||
int biasH = REG_SOUNDBIAS_H;
|
int dac_pwm_rate = REG_SOUNDBIAS_H;
|
||||||
|
|
||||||
if (biasH < 64)
|
if (dac_pwm_rate < 0x40) // if PWM rate = 32768 Hz
|
||||||
{
|
channels->frequency = (channels->frequency + 2) & 0x7fc;
|
||||||
channels->fr = (channels->fr + 2) & 0x7fc;
|
else if (dac_pwm_rate < 0x80) // if PWM rate = 65536 Hz
|
||||||
}
|
channels->frequency = (channels->frequency + 1) & 0x7fe;
|
||||||
else if (biasH < 128)
|
|
||||||
{
|
|
||||||
channels->fr = (channels->fr + 1) & 0x7fe;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ch != 4)
|
if (ch != 4)
|
||||||
{
|
*nrx3ptr = channels->frequency;
|
||||||
*nrx3ptr = channels->fr;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
*nrx3ptr = (*nrx3ptr & 0x08) | channels->frequency;
|
||||||
*nrx3ptr = (*nrx3ptr & 0x08) | channels->fr;
|
channels->n4 = (channels->n4 & 0xC0) + (*((u8*)(&channels->frequency) + 1));
|
||||||
}
|
|
||||||
channels->n4 = (channels->n4 & 0xC0) + (*((u8*)(&channels->fr) + 1));
|
|
||||||
*nrx4ptr = (s8)(channels->n4 & mask);
|
*nrx4ptr = (s8)(channels->n4 & mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channels->mo & 1)
|
/* 4. apply envelope & volume to HW registers */
|
||||||
|
if (channels->modify & CGB_CHANNEL_MO_VOL)
|
||||||
{
|
{
|
||||||
REG_NR51 = (REG_NR51 & ~channels->panMask) | channels->pan;
|
REG_NR51 = (REG_NR51 & ~channels->panMask) | channels->pan;
|
||||||
if (ch == 3)
|
if (ch == 3)
|
||||||
{
|
{
|
||||||
*nrx2ptr = gCgb3Vol[channels->ev];
|
*nrx2ptr = gCgb3Vol[channels->envelopeVolume];
|
||||||
if (channels->n4 & 0x80)
|
if (channels->n4 & 0x80)
|
||||||
{
|
{
|
||||||
*nrx0ptr = 0x80;
|
*nrx0ptr = 0x80;
|
||||||
@ -1191,18 +1198,16 @@ void CgbSound(void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
evAdd &= 0xf;
|
unsigned int envMask = 0xF;
|
||||||
*nrx2ptr = (channels->ev << 4) + evAdd;
|
*nrx2ptr = (envelopeStepTimeAndDir & envMask) + (channels->envelopeVolume << 4);
|
||||||
*nrx4ptr = channels->n4 | 0x80;
|
*nrx4ptr = channels->n4 | 0x80;
|
||||||
if (ch == 1 && !(*nrx0ptr & 0x08))
|
if (ch == 1 && !(*nrx0ptr & 0x08))
|
||||||
{
|
|
||||||
*nrx4ptr = channels->n4 | 0x80;
|
*nrx4ptr = channels->n4 | 0x80;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LAST_LABEL:
|
channel_complete:
|
||||||
channels->mo = 0;
|
channels->modify = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1486,8 +1491,8 @@ void ply_memacc(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *trac
|
|||||||
|
|
||||||
cond_true:
|
cond_true:
|
||||||
{
|
{
|
||||||
void (*func)(struct MusicPlayerInfo *, struct MusicPlayerTrack *) = *(&gMPlayJumpTable[1]);
|
// *& is required for matching
|
||||||
func(mplayInfo, track);
|
(*&gMPlayJumpTable[1])(mplayInfo, track);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1505,8 +1510,7 @@ void ply_xcmd(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
|
|||||||
|
|
||||||
void ply_xxx(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
|
void ply_xxx(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
|
||||||
{
|
{
|
||||||
void (*func)(struct MusicPlayerInfo *, struct MusicPlayerTrack *) = *(&gMPlayJumpTable[0]);
|
gMPlayJumpTable[0](mplayInfo, track);
|
||||||
func(mplayInfo, track);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define READ_XCMD_BYTE(var, n) \
|
#define READ_XCMD_BYTE(var, n) \
|
||||||
@ -1521,6 +1525,10 @@ void ply_xwave(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track
|
|||||||
{
|
{
|
||||||
u32 wav;
|
u32 wav;
|
||||||
|
|
||||||
|
#ifdef UBFIX
|
||||||
|
wav = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
READ_XCMD_BYTE(wav, 0) // UB: uninitialized variable
|
READ_XCMD_BYTE(wav, 0) // UB: uninitialized variable
|
||||||
READ_XCMD_BYTE(wav, 1)
|
READ_XCMD_BYTE(wav, 1)
|
||||||
READ_XCMD_BYTE(wav, 2)
|
READ_XCMD_BYTE(wav, 2)
|
||||||
@ -1562,13 +1570,13 @@ void ply_xrele(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track
|
|||||||
|
|
||||||
void ply_xiecv(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
|
void ply_xiecv(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
|
||||||
{
|
{
|
||||||
track->echoVolume = *track->cmdPtr;
|
track->pseudoEchoVolume = *track->cmdPtr;
|
||||||
track->cmdPtr++;
|
track->cmdPtr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ply_xiecl(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
|
void ply_xiecl(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
|
||||||
{
|
{
|
||||||
track->echoLength = *track->cmdPtr;
|
track->pseudoEchoLength = *track->cmdPtr;
|
||||||
track->cmdPtr++;
|
track->cmdPtr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1588,6 +1596,10 @@ void ply_xcmd_0C(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *tra
|
|||||||
{
|
{
|
||||||
u32 unk;
|
u32 unk;
|
||||||
|
|
||||||
|
#ifdef UBFIX
|
||||||
|
unk = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
READ_XCMD_BYTE(unk, 0) // UB: uninitialized variable
|
READ_XCMD_BYTE(unk, 0) // UB: uninitialized variable
|
||||||
READ_XCMD_BYTE(unk, 1)
|
READ_XCMD_BYTE(unk, 1)
|
||||||
|
|
||||||
@ -1608,6 +1620,10 @@ void ply_xcmd_0D(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *tra
|
|||||||
{
|
{
|
||||||
u32 unk;
|
u32 unk;
|
||||||
|
|
||||||
|
#ifdef UBFIX
|
||||||
|
unk = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
READ_XCMD_BYTE(unk, 0) // UB: uninitialized variable
|
READ_XCMD_BYTE(unk, 0) // UB: uninitialized variable
|
||||||
READ_XCMD_BYTE(unk, 1)
|
READ_XCMD_BYTE(unk, 1)
|
||||||
READ_XCMD_BYTE(unk, 2)
|
READ_XCMD_BYTE(unk, 2)
|
||||||
@ -1648,18 +1664,12 @@ start_song:
|
|||||||
mplayInfo = &gPokemonCryMusicPlayers[i];
|
mplayInfo = &gPokemonCryMusicPlayers[i];
|
||||||
mplayInfo->ident++;
|
mplayInfo->ident++;
|
||||||
|
|
||||||
#define CRY ((s32)&gPokemonCrySongs + i * sizeof(struct PokemonCrySong))
|
gPokemonCrySongs[i] = gPokemonCrySong;
|
||||||
#define CRY_OFS(field) offsetof(struct PokemonCrySong, field)
|
|
||||||
|
|
||||||
memcpy((void *)CRY, &gPokemonCrySong, sizeof(struct PokemonCrySong));
|
gPokemonCrySongs[i].tone = tone;
|
||||||
|
gPokemonCrySongs[i].part[0] = &gPokemonCrySongs[i].part0;
|
||||||
*(u32 *)(CRY + CRY_OFS(tone)) = (u32)tone;
|
gPokemonCrySongs[i].part[1] = &gPokemonCrySongs[i].part1;
|
||||||
*(u32 *)(CRY + CRY_OFS(part)) = CRY + CRY_OFS(part0);
|
gPokemonCrySongs[i].gotoTarget = (u32)&gPokemonCrySongs[i].cont;
|
||||||
*(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;
|
mplayInfo->ident = ID_NUMBER;
|
||||||
|
|
||||||
@ -1702,14 +1712,14 @@ void SetPokemonCryProgress(u32 val)
|
|||||||
gPokemonCrySong.unkCmd0DParam = val;
|
gPokemonCrySong.unkCmd0DParam = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IsPokemonCryPlaying(struct MusicPlayerInfo *mplayInfo)
|
bool32 IsPokemonCryPlaying(struct MusicPlayerInfo *mplayInfo)
|
||||||
{
|
{
|
||||||
struct MusicPlayerTrack *track = mplayInfo->tracks;
|
struct MusicPlayerTrack *track = mplayInfo->tracks;
|
||||||
|
|
||||||
if (track->chan && track->chan->track == track)
|
if (track->chan && track->chan->track == track)
|
||||||
return 1;
|
return TRUE;
|
||||||
else
|
else
|
||||||
return 0;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetPokemonCryChorus(s8 val)
|
void SetPokemonCryChorus(s8 val)
|
||||||
|
Loading…
Reference in New Issue
Block a user