mirror of
https://github.com/SAT-R/sa2.git
synced 2026-10-28 09:43:38 +00:00
- Update software renderer to the gpsp renderer (fast enough to render on slow hardware) - Convert audio emulation to fixed point (since float is slower on these systems) - Add PSP as a target for SDL - Add PS2 as its own target, though it's still using software rendering Thanks to @kikugrave for adding the initial psp boilerplate and inspiring me to finally finish the ps2 port!
483 lines
15 KiB
C
483 lines
15 KiB
C
#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
|
|
|
|
#if COLLECT_RINGS_ROM
|
|
#define DEFAULT_SOUND_MODE (SOUND_MODE_DA_BIT_8 | SOUND_MODE_FREQ_07884 | (15 << SOUND_MODE_MASVOL_SHIFT) | (4 << SOUND_MODE_MAXCHN_SHIFT))
|
|
#else
|
|
#if (ENGINE == ENGINE_3)
|
|
#define DEFAULT_SOUND_MODE (SOUND_MODE_DA_BIT_8 | SOUND_MODE_FREQ_10512 | (10 << SOUND_MODE_MASVOL_SHIFT) | (6 << SOUND_MODE_MAXCHN_SHIFT))
|
|
#else
|
|
#define DEFAULT_SOUND_MODE (SOUND_MODE_DA_BIT_8 | SOUND_MODE_FREQ_10512 | (15 << SOUND_MODE_MASVOL_SHIFT) | (5 << SOUND_MODE_MAXCHN_SHIFT))
|
|
#endif
|
|
#endif
|
|
|
|
#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
|
|
|
|
#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
|
|
|
|
#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
|
|
|
|
#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
|
|
|
|
#define MAX_DIRECTSOUND_CHANNELS 12
|
|
|
|
#if PLATFORM_GBA
|
|
#define PCM_DMA_BUF_SIZE 1584 // size of Direct Sound buffer
|
|
#else
|
|
#define PCM_DMA_BUF_SIZE 4907 // size of Direct Sound buffer
|
|
#endif
|
|
|
|
#if PLATFORM_GBA
|
|
#define NUM_MUSIC_PLAYERS ((u16)gNumMusicPlayers)
|
|
#define MAX_LINES ((u32)gMaxLines)
|
|
#else
|
|
#define NUM_MUSIC_PLAYERS 4
|
|
#define MAX_LINES 0
|
|
#endif
|
|
|
|
typedef s32 fixed8_24;
|
|
#define float_to_fp8_24(value) (fixed8_24)((value)*16777216.0f)
|
|
#define u32_to_fp8_24(value) ((value) << 24)
|
|
#define fp8_24_to_u32(value) ((value) >> 24)
|
|
#define fp8_24_to_float(value) (float)((value) / 16777216.0f)
|
|
#define fp8_24_fractional_part(value) ((value)&0xFFFFFF)
|
|
|
|
struct MP2KTrack;
|
|
struct MP2KPlayerState;
|
|
|
|
typedef void (*MP2KEventNoteFunc)(u8, struct MP2KPlayerState *, struct MP2KTrack *);
|
|
typedef void (*MP2KEventFunc)(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
typedef void (*CgbSoundFunc)(void);
|
|
typedef void (*CgbOscOffFunc)(u8);
|
|
typedef u32 (*MidiKeyToCgbFreqFunc)(u8, u8, u8);
|
|
typedef void (*ExtVolPitFunc)(void);
|
|
typedef void (*MPlayMainFunc)(struct MP2KPlayerState *);
|
|
|
|
struct MixerSource {
|
|
u8 status;
|
|
u8 type;
|
|
u8 rightVol;
|
|
u8 leftVol;
|
|
|
|
union {
|
|
struct {
|
|
u8 attack;
|
|
u8 decay;
|
|
u8 sustain;
|
|
u8 release;
|
|
u8 key;
|
|
u8 envelopeVol;
|
|
|
|
u8 envelopeGoal;
|
|
u8 envelopeCtr;
|
|
|
|
u8 echoVol;
|
|
u8 echoLen;
|
|
u8 padding1;
|
|
u8 padding2;
|
|
u8 gateTime;
|
|
u8 untransposedKey;
|
|
u8 velocity;
|
|
u8 priority;
|
|
u8 rhythmPan;
|
|
u8 padding3;
|
|
u8 padding4;
|
|
u8 padding5;
|
|
|
|
u8 padding6;
|
|
u8 sustainGoal;
|
|
u8 nrx4;
|
|
u8 pan;
|
|
|
|
u8 panMask;
|
|
u8 cgbStatus;
|
|
u8 length;
|
|
u8 sweep;
|
|
|
|
u32 freq;
|
|
} cgb;
|
|
struct {
|
|
u8 attack;
|
|
u8 decay;
|
|
u8 sustain;
|
|
u8 release;
|
|
u8 key;
|
|
u8 envelopeVol;
|
|
|
|
u8 envelopeVolR;
|
|
u8 envelopeVolL;
|
|
|
|
u8 echoVol;
|
|
u8 echoLen;
|
|
u8 padding1;
|
|
u8 padding2;
|
|
u8 gateTime;
|
|
u8 untransposedKey;
|
|
u8 velocity;
|
|
u8 priority;
|
|
u8 rhythmPan;
|
|
u8 padding3;
|
|
u8 padding4;
|
|
u8 padding5;
|
|
|
|
u32 ct;
|
|
fixed8_24 fw;
|
|
|
|
u32 freq;
|
|
} sound;
|
|
} data;
|
|
|
|
void *wav; // The next piece of data to be loading
|
|
void *current; // The working pointer from wav
|
|
|
|
struct MP2KTrack *track;
|
|
struct MixerSource *prev;
|
|
struct MixerSource *next;
|
|
u32 padding7; // d4
|
|
u32 blockCount; // bdpcm block count
|
|
};
|
|
|
|
struct SoundMixerState {
|
|
// This field is normally equal to ID_NUMBER but it is set to other
|
|
// values during sensitive operations for locking purposes.
|
|
u32 lockStatus;
|
|
|
|
vu8 dmaCounter;
|
|
|
|
// Direct Sound
|
|
u8 reverb;
|
|
u8 numChans;
|
|
u8 masterVol;
|
|
u8 freqOption;
|
|
|
|
u8 extensionFlags;
|
|
u8 cgbCounter15; // periodically counts from 14 down to 0 (15 states)
|
|
u8 framesPerDmaCycle; // number of V-blanks per PCM DMA
|
|
u8 maxScanlines;
|
|
u8 gap[3];
|
|
s32 samplesPerFrame;
|
|
s32 sampleRate;
|
|
#if PLATFORM_GBA
|
|
s32 sampleRateReciprocal;
|
|
#else
|
|
float sampleRateReciprocal;
|
|
#endif
|
|
struct MixerSource *cgbChans;
|
|
MPlayMainFunc MPlayMainHead;
|
|
struct MP2KPlayerState *musicPlayerHead;
|
|
CgbSoundFunc CgbSound;
|
|
CgbOscOffFunc CgbOscOff;
|
|
MidiKeyToCgbFreqFunc MidiKeyToCgbFreq;
|
|
void **MPlayJumpTable;
|
|
MP2KEventNoteFunc plynote;
|
|
ExtVolPitFunc ExtVolPit;
|
|
void *reserved2;
|
|
void *reserved3;
|
|
void *reversed4;
|
|
void *reserved5;
|
|
struct MixerSource chans[MAX_DIRECTSOUND_CHANNELS];
|
|
#if PLATFORM_GBA
|
|
s8 pcmBuffer[PCM_DMA_BUF_SIZE * 2];
|
|
#else
|
|
fixed8_24 pcmBuffer[PCM_DMA_BUF_SIZE * 2];
|
|
#endif
|
|
};
|
|
|
|
struct MP2KVoiceGroup {
|
|
u8 type;
|
|
u8 drumKey;
|
|
u8 cgbLength;
|
|
u8 pan_sweep; // pan or sweep (compatible sound ch. 1)
|
|
union {
|
|
struct {
|
|
struct WaveData *wav;
|
|
u8 attack;
|
|
u8 decay;
|
|
u8 sustain;
|
|
u8 release;
|
|
} sound;
|
|
struct {
|
|
struct MP2KVoiceGroup *group;
|
|
u8 *keySplitTable;
|
|
} keySplit;
|
|
} data;
|
|
};
|
|
|
|
struct WaveData {
|
|
u16 type;
|
|
u16 status;
|
|
|
|
u32 freq;
|
|
u32 loopStart;
|
|
u32 size; // number of samples
|
|
s8 data[1]; // samples
|
|
};
|
|
|
|
struct MP2KSongHeader {
|
|
u8 trackCount;
|
|
u8 blockCount;
|
|
u8 priority;
|
|
u8 reverb;
|
|
struct MP2KVoiceGroup *voicegroup;
|
|
u8 *part[1];
|
|
};
|
|
|
|
struct MP2KTrack {
|
|
u8 status;
|
|
u8 wait;
|
|
u8 patternLevel;
|
|
u8 repeatCount;
|
|
u8 gateTime; // 0 if TIE
|
|
u8 key;
|
|
u8 velocity;
|
|
u8 runningStatus;
|
|
s8 keyShiftCalculated; // Calculated by TrkVolPitSet using fields below. Units: semitones
|
|
u8 pitchCalculated; // Calculated by TrkVolPitSet using fields below. Units: 256ths of a semitone
|
|
s8 keyShift; // Units: semitones
|
|
s8 keyShiftPublic; // Units: semitones
|
|
s8 tune; // Units: 64ths of a semitone
|
|
u8 pitchPublic; // Units: 256ths of a semitone
|
|
s8 bend; // Units: (bendRange / 64)ths of a semitone
|
|
u8 bendRange;
|
|
u8 volRightCalculated;
|
|
u8 volLeftCalculated;
|
|
u8 vol;
|
|
u8 volPublic; // Used both for fades and MPlayVolumeControl
|
|
s8 pan;
|
|
s8 panPublic;
|
|
s8 modCalculated; // Pitch units: 16ths of a semitone
|
|
u8 modDepth;
|
|
u8 modType;
|
|
u8 lfoSpeed;
|
|
u8 lfoSpeedCounter;
|
|
u8 lfoDelay;
|
|
u8 lfoDelayCounter;
|
|
u8 priority;
|
|
u8 echoVolume;
|
|
u8 echoLength;
|
|
|
|
struct MixerSource *chan;
|
|
struct MP2KVoiceGroup voicegroup;
|
|
|
|
u8 gap[10];
|
|
u16 unk_3A;
|
|
u32 unk_3C;
|
|
u8 *cmdPtr;
|
|
u8 *patternStack[3];
|
|
};
|
|
|
|
struct MP2KPlayerState {
|
|
struct MP2KSongHeader *songHeader;
|
|
u32 status;
|
|
u8 trackCount;
|
|
u8 priority;
|
|
u8 cmd;
|
|
bool8 checkSongPriority;
|
|
u32 clock;
|
|
u8 padding[8];
|
|
u8 *memAccArea;
|
|
u16 tempoRawBPM; // 150 initially... this doesn't seem right but whatever
|
|
u16 tempoScale; // 0x100 initially
|
|
u16 tempoInterval; // 150 initially
|
|
u16 tempoCounter;
|
|
u16 fadeInterval;
|
|
u16 fadeCounter;
|
|
u16 fadeOV;
|
|
struct MP2KTrack *tracks;
|
|
struct MP2KVoiceGroup *voicegroup;
|
|
u32 lockStatus;
|
|
MPlayMainFunc nextPlayerFunc;
|
|
struct MP2KPlayerState *nextPlayer;
|
|
};
|
|
|
|
struct MusicPlayer {
|
|
struct MP2KPlayerState *info;
|
|
struct MP2KTrack *track;
|
|
u8 numTracks;
|
|
u16 unk_A;
|
|
};
|
|
|
|
struct Song {
|
|
struct MP2KSongHeader *header;
|
|
u16 ms;
|
|
u16 me;
|
|
};
|
|
|
|
typedef void (*XcmdFunc)(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
|
|
extern char SoundMainRAM[];
|
|
extern u8 gMPlayMemAccArea[];
|
|
extern void *gMPlayJumpTable[];
|
|
extern struct MixerSource gCgbChans[];
|
|
|
|
extern const struct MusicPlayer gMPlayTable[];
|
|
extern const struct Song gSongTable[];
|
|
extern const XcmdFunc gXcmdTable[];
|
|
|
|
extern const u8 gClockTable[];
|
|
extern const u8 gScaleTable[];
|
|
extern const u32 gFreqTable[];
|
|
extern const u16 gPcmSamplesPerVBlankTable[];
|
|
extern void *const gMPlayJumpTableTemplate[];
|
|
|
|
extern const u8 gCgbScaleTable[];
|
|
extern const s16 gCgbFreqTable[];
|
|
extern const u8 gNoiseTable[];
|
|
extern const u8 gCgb3Vol[];
|
|
|
|
#if PLATFORM_GBA
|
|
extern char gNumMusicPlayers[];
|
|
extern char gMaxLines[];
|
|
#endif
|
|
|
|
u32 MidiKeyToFreq(struct WaveData *wav, u8 key, u8 fineAdjust);
|
|
u32 umul3232H32(u32 multiplier, u32 multiplicand);
|
|
void SoundMain(void);
|
|
void SoundMainBTM(void *ptr);
|
|
void TrackStop(struct MP2KPlayerState *player, struct MP2KTrack *track);
|
|
void MP2KPlayerMain(struct MP2KPlayerState *);
|
|
|
|
void ClearChain(struct MixerSource *chan);
|
|
void MP2KClearChain(struct MixerSource *chan);
|
|
|
|
void MPlayContinue(struct MP2KPlayerState *mplayInfo);
|
|
void MPlayStart(struct MP2KPlayerState *mplayInfo, struct MP2KSongHeader *songHeader);
|
|
void MPlayStop(struct MP2KPlayerState *mplayInfo);
|
|
void FadeOutBody(struct MP2KPlayerState *mplayInfo);
|
|
void TrkVolPitSet(struct MP2KPlayerState *mplayInfo, struct MP2KTrack *track);
|
|
void MPlayFadeOut(struct MP2KPlayerState *mplayInfo, u16 speed);
|
|
void Clear64byte(void *addr);
|
|
void SoundInit(struct SoundMixerState *soundInfo);
|
|
void MPlayExtender(struct MixerSource *cgbChans);
|
|
void m4aSoundMode(u32 mode);
|
|
void MPlayOpen(struct MP2KPlayerState *mplayInfo, struct MP2KTrack *tracks, u8 trackCount);
|
|
void CgbSound(void);
|
|
void CgbOscOff(u8);
|
|
void CgbModVol(struct MixerSource *chan);
|
|
u32 MidiKeyToCgbFreq(u8, u8, u8);
|
|
void MPlayJumpTableCopy(void **mplayJumpTable);
|
|
void SampleFreqSet(u32 freq);
|
|
void m4aSoundVSyncOn(void);
|
|
void m4aSoundVSyncOff(void);
|
|
|
|
void m4aMPlayTempoControl(struct MP2KPlayerState *mplayInfo, u16 tempo);
|
|
void m4aMPlayVolumeControl(struct MP2KPlayerState *mplayInfo, u16 trackBits, u16 volume);
|
|
void m4aMPlayPitchControl(struct MP2KPlayerState *mplayInfo, u16 trackBits, s16 pitch);
|
|
void m4aMPlayPanpotControl(struct MP2KPlayerState *mplayInfo, u16 trackBits, s8 pan);
|
|
void ClearModM(struct MP2KTrack *track);
|
|
void m4aMPlayModDepthSet(struct MP2KPlayerState *mplayInfo, u16 trackBits, u8 modDepth);
|
|
void m4aMPlayLFOSpeedSet(struct MP2KPlayerState *mplayInfo, u16 trackBits, u8 lfoSpeed);
|
|
|
|
// sound command handler functions
|
|
void MP2K_event_fine(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_goto(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_patt(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_pend(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_rept(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_memacc(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_prio(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_tempo(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_keysh(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_voice(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_vol(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_pan(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_bend(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_bendr(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_lfos(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_lfodl(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_mod(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_modt(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_tune(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_port(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_xcmd(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_endtie(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_nxx(u8 clock, struct MP2KPlayerState *, struct MP2KTrack *);
|
|
|
|
// extended sound command handler functions
|
|
void MP2K_event_xxx(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_xwave(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_xtype(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_xatta(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_xdeca(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_xsust(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_xrele(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_xiecv(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_xiecl(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_xleng(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_xswee(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_xcmd_0C(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
void MP2K_event_xcmd_0D(struct MP2KPlayerState *, struct MP2KTrack *);
|
|
|
|
#endif // GUARD_GBA_M4A_INTERNAL_H
|