diff --git a/include/ffcc/RedSound/RedCommand.h b/include/ffcc/RedSound/RedCommand.h index d46cbac8ae..9d06390599 100644 --- a/include/ffcc/RedSound/RedCommand.h +++ b/include/ffcc/RedSound/RedCommand.h @@ -1,6 +1,8 @@ #ifndef _FFCC_REDSOUND_REDCOMMAND_H #define _FFCC_REDSOUND_REDCOMMAND_H +#include "ffcc/RedSound/RedExecute.h" + struct RedMusicHEAD; struct RedSeINFO; struct RedTrackDATA; @@ -8,6 +10,15 @@ struct RedWaveHeadWD; enum RedReverbModeLayout { REDSOUND_REVERB_MODE_PARAM_COUNT = 6, + REDSOUND_REVERB_MODE_COUNT = 8, + REDSOUND_REVERB_MODE_INDEX_MASK = REDSOUND_REVERB_MODE_COUNT - 1, + REDSOUND_REVERB_MODE_KIND_OFFSET = 0x00, + REDSOUND_REVERB_MODE_PARAMS_OFFSET = 0x04, + REDSOUND_REVERB_MODE_PARAMS_SIZE = sizeof(int) * REDSOUND_REVERB_MODE_PARAM_COUNT, + REDSOUND_REVERB_MODE_PARAMS_ALLOC_SIZE = 0x18, + REDSOUND_REVERB_MODE_SIZE = 0x1C, + REDSOUND_REVERB_MODE_TABLE_SIZE = REDSOUND_REVERB_MODE_SIZE * REDSOUND_REVERB_MODE_COUNT, + REDSOUND_REVERB_MODE_TABLE_ALLOC_SIZE = 0xE0, }; enum RedReverbParamIndex { @@ -25,13 +36,24 @@ enum RedReverbParamIndex { REDSOUND_REVERB_PARAM_CHORUS_PERIOD = 2, }; +enum RedMusicVolumeMode { + REDSOUND_MUSIC_VOLUME_MODE_NORMAL = 0, + REDSOUND_MUSIC_VOLUME_MODE_FADE_OUT = 1, +}; + +enum RedSeVolumeMode { + REDSOUND_SE_VOLUME_MODE_NORMAL = 0, + REDSOUND_SE_VOLUME_MODE_FADE_OUT = 1, +}; + struct RedReverbModeData { - int m_kind; + RedReverbKind m_kind; int m_params[REDSOUND_REVERB_MODE_PARAM_COUNT]; }; RedTrackDATA* SearchSeEmptyTrack(int trackCount, int eraseTrack, int attrMask); int SeStopID(int seId); +int SeStopG(int group); int SeStopMG(int bank, int sep, int group, int kind); int SeBlockPlay(int seId, int bank, int no, int pan, int volume); int SeSepPlay(int seId, int sepId, int pan, int volume); @@ -42,7 +64,10 @@ void SePause(int seId, int pause); int MusicStop(int musicId); int MusicPlay(int musicId, int volume, int mode); void SetMusicVolume(int musicId, int volume, int frameCount, int mode); +void SetMusicTempo(int tempo, int frameCount); +void SetMusicPitch(int pitch, int frameCount); +void MusicPause(int musicId, int pause); -extern RedReverbModeData t_ReverbModeData[]; +extern RedReverbModeData t_ReverbModeData[REDSOUND_REVERB_MODE_COUNT]; #endif // _FFCC_REDSOUND_REDCOMMAND_H diff --git a/include/ffcc/RedSound/RedDriver.h b/include/ffcc/RedSound/RedDriver.h index e9117d4d43..145f64445d 100644 --- a/include/ffcc/RedSound/RedDriver.h +++ b/include/ffcc/RedSound/RedDriver.h @@ -1,6 +1,19 @@ #ifndef _FFCC_REDSOUND_REDDRIVER_H #define _FFCC_REDSOUND_REDDRIVER_H +#ifndef FFCC_REDSOUND_DMA_CALLBACK_TYPEDEF +#define FFCC_REDSOUND_DMA_CALLBACK_TYPEDEF +typedef void (*RedDmaCallback)(void* callbackData); +#endif + +struct RedReverbDepth; +struct RedReverbModeData; +struct RedReverbSize; +struct RedAdsrDATA; +struct RedStreamDATA; +struct RedTrackDATA; +struct RedWaveHeadWD; + enum RedDmaEntryFlag { REDSOUND_DMA_FLAG_MAIN_QUEUE = 1, REDSOUND_DMA_FLAG_CHUNKED_TRANSFER = 0x8000, @@ -9,11 +22,14 @@ enum RedDmaEntryFlag { REDSOUND_DMA_FLAGS_STREAM_LOAD = REDSOUND_DMA_FLAG_CHUNKED_TRANSFER | REDSOUND_DMA_FLAG_MAIN_QUEUE, }; -unsigned int DeltaTimeSumup(unsigned char**); +unsigned int DeltaTimeSumup(unsigned char** buffer); unsigned int GetMyEntryID(); void RedSleep(int microseconds); -int RedDmaEntry(int flags, int direction, int mainMemory, int aramMemory, int size, void (*callback)(void*), void* callbackData); +int RedDmaEntry(int flags, int direction, int mainMemory, int aramMemory, int size, + RedDmaCallback callback, void* callbackData); int RedDmaSearchID(int id); +void RedDmaClearID(int id); +void RedSetDMAMode(int mode); class CRedDriver { @@ -24,29 +40,45 @@ class CRedDriver void Init(); void End(); int GetProgramTime(); + int GetMasterTime(); void SetSoundMode(int soundMode); int GetSoundMode(); int SetMusicData(void* musicData); int ReentryMusicData(int musicId); + int CheckMusicEntry(int musicId); + void ClearMusicData(int musicId); + int MusicPlayState(int musicId); void MusicStop(int musicId); int MusicPlay(int musicId, int volume, int mode); + int MusicPlay(void* musicData, int volume, int mode); int MusicCrossPlay(int musicId, int volume, int mode); + int MusicCrossPlay(void* musicData, int volume, int mode); int MusicNextPlay(int musicId, int volume, int mode); + int MusicNextPlay(void* musicData, int volume, int mode); void MusicMasterVolume(int volume); void MusicFadeOut(int musicId, int frameCount); void MusicVolume(int musicId, int volume, int frameCount); + void MusicTempo(int tempo, int frameCount); + void MusicPitch(int pitch, int frameCount); + void MusicPause(int musicId, int pause); + void DisplayMusicInfo(); void SetMusicPhraseStop(int enable); + void SetMusicFastSpeed(int speed); + int CheckMusicPhraseStop(); - void* SetSeBlockData(int bank, void* data); - int SetSeSepData(void* data); + void* SetSeBlockData(int bank, void* blockData); + int SetSeSepData(void* seSepData); void ClearSeSepData(int sepId); void ClearSeSepDataMG(int bank, int sep, int group, int kind); int ReentrySeSepData(int sepId); + int CheckSeSepEntry(int sepId); int SePlayState(int seId); void SeStop(int seId); + void SeStopG(int group); void SeStopMG(int bank, int sep, int group, int kind); int SePlay(int bank, int sep, int autoId, int pan, int volume, int pitch); + int SePlay(void* seSepData, int autoId, int pan, int volume, int pitch); void SeMasterVolume(int volume); void SeFadeOut(int seId, int frameCount); void SeVolume(int seId, int volume, int frameCount); @@ -56,24 +88,42 @@ class CRedDriver int GetSeVolume(int seId, int mode); int ReportSeLoop(int seId); void DisplaySePlayInfo(); + void ClearSePlayLine(); + RedTrackDATA* GetSePlayTrack(); int StreamPlayState(int streamId); - int GetStreamPlayPoint(int streamId, int* current, int* total); + int GetStreamPlayPoint(int streamId, int* playPoint, int* readPoint); + RedStreamDATA* GetStreamPlayBlock(int streamId); void StreamStop(int streamId); int StreamPlay(int streamId, void* streamHeader, int fileSize, int pan, int volume); void StreamVolume(int streamId, int volume, int frameCount); + void StreamPan(int streamId, int pan, int frameCount); void StreamPause(int streamId, int pause); void ClearWaveData(int waveNo); void ClearWaveDataM(int waveNo0, int waveNo1, int waveNo2, int waveNo3); void ClearWaveBank(int bank); - void SetWaveData(int bank, int waveNo, void* data, int size); + void SetWaveData(int slot, int waveID, void* waveData, int waveSize); int ReentryWaveData(int waveNo); + RedWaveHeadWD* GetWaveInfo(int waveNo); + int CheckWaveEntry(int waveNo); void DisplayWaveInfo(); + void DisplayMMemoryInfo(); void SetReverb(int kind, int mode); - void SetReverbDepth(int type, int depth, int frameCount); + void SetReverb(int kind, int mode, int* params); + RedReverbSize* GetReverbInfo(); + RedReverbDepth* GetReverbDepth(); + void SetReverbDepth(int bank, int depth, int frameCount); + void SetMute(unsigned int voiceNo, unsigned int mute); + int PlayWaveItem(int waveNo, int itemNo, int key, int pan, int volume); + void StopWaveItem(); + int WavePitchCompute(int key, int pitch); + void SetWaveTune(int key, int fineTune); + void SetWavePitch(int pitch); + void SetWaveAdsr(int attack, RedAdsrDATA* adsr); + RedReverbModeData* GetReverbModeTable(int mode); void TestProcess(int mode); }; diff --git a/include/ffcc/RedSound/RedEntry.h b/include/ffcc/RedSound/RedEntry.h index d13faa4b53..82762bde5e 100644 --- a/include/ffcc/RedSound/RedEntry.h +++ b/include/ffcc/RedSound/RedEntry.h @@ -1,38 +1,81 @@ #ifndef _FFCC_REDSOUND_REDENTRY_H #define _FFCC_REDSOUND_REDENTRY_H +struct RedMusicHEAD; +struct RedSeSepHEAD; +struct RedWaveHeadWD; + struct RedHistoryBANK { int m_id; int m_historyNo; - int m_data; + union { + int m_data; + int m_address; + void* m_pointer; + RedWaveHeadWD* m_waveHead; + RedSeSepHEAD* m_seSepHead; + RedMusicHEAD* m_musicHead; + }; int m_size; }; enum RedEntryBankLayoutSize { REDSOUND_HISTORY_BANK_EMPTY_ID = -1, + REDSOUND_HISTORY_BANK_NOT_FOUND = -1, + REDSOUND_WAVE_NO_NONE = -1, + REDSOUND_WAVE_ADD_FAILED = -1, + REDSOUND_WAVE_SIZE_AUTO = -1, + REDSOUND_WAVE_CLEAR_ALL = -1, + REDSOUND_WAVE_CLEAR_UNBANKED = -2, + REDSOUND_WAVE_CLEAR_UNBANKED_USED = -3, + REDSOUND_SESEP_SEARCH_FIRST = -1, + REDSOUND_SESEP_CLEAR_ALL = -1, + REDSOUND_MUSIC_CLEAR_ALL = -1, REDSOUND_HISTORY_BANK_ENTRY_SIZE = sizeof(RedHistoryBANK), + REDSOUND_HISTORY_BANK_ID_OFFSET = 0x00, + REDSOUND_HISTORY_BANK_HISTORY_NO_OFFSET = 0x04, + REDSOUND_HISTORY_BANK_DATA_OFFSET = 0x08, + REDSOUND_HISTORY_BANK_SIZE_OFFSET = 0x0C, REDSOUND_WAVE_BANK_ENTRY_COUNT = 0x40, REDSOUND_WAVE_PRIMARY_BANK_ENTRY_COUNT = 0x10, REDSOUND_WAVE_PRIMARY_BANK_MASK = REDSOUND_WAVE_PRIMARY_BANK_ENTRY_COUNT - 1, REDSOUND_WAVE_RELEASE_HISTORY_NO = REDSOUND_WAVE_PRIMARY_BANK_ENTRY_COUNT + 4, REDSOUND_SESEP_BANK_ENTRY_COUNT = 0x100, REDSOUND_MUSIC_BANK_ENTRY_COUNT = 0x04, + REDSOUND_WAVE_PRIMARY_BANK_SIZE = REDSOUND_HISTORY_BANK_ENTRY_SIZE * REDSOUND_WAVE_PRIMARY_BANK_ENTRY_COUNT, + REDSOUND_WAVE_HISTORY_BANK_SIZE = + REDSOUND_HISTORY_BANK_ENTRY_SIZE * (REDSOUND_WAVE_BANK_ENTRY_COUNT - REDSOUND_WAVE_PRIMARY_BANK_ENTRY_COUNT), REDSOUND_WAVE_BANK_SIZE = REDSOUND_HISTORY_BANK_ENTRY_SIZE * REDSOUND_WAVE_BANK_ENTRY_COUNT, REDSOUND_WAVE_HISTORY_BANK_OFFSET = REDSOUND_HISTORY_BANK_ENTRY_SIZE * REDSOUND_WAVE_PRIMARY_BANK_ENTRY_COUNT, REDSOUND_SESEP_BANK_SIZE = REDSOUND_HISTORY_BANK_ENTRY_SIZE * REDSOUND_SESEP_BANK_ENTRY_COUNT, REDSOUND_MUSIC_BANK_SIZE = REDSOUND_HISTORY_BANK_ENTRY_SIZE * REDSOUND_MUSIC_BANK_ENTRY_COUNT, + REDSOUND_WAVE_PRIMARY_BANK_ALLOC_SIZE = 0x100, + REDSOUND_WAVE_HISTORY_BANK_ALLOC_SIZE = 0x300, + REDSOUND_WAVE_BANK_ALLOC_SIZE = 0x400, + REDSOUND_SESEP_BANK_ALLOC_SIZE = 0x1000, + REDSOUND_MUSIC_BANK_ALLOC_SIZE = 0x40, + REDSOUND_ENTRY_BANK_ARENA_SIZE = REDSOUND_WAVE_BANK_SIZE + REDSOUND_SESEP_BANK_SIZE + REDSOUND_MUSIC_BANK_SIZE, + REDSOUND_ENTRY_BANK_ARENA_ALLOC_SIZE = 0x1440, +}; + +enum RedHistoryMode { + REDSOUND_HISTORY_MODE_RELEASE = 0, + REDSOUND_HISTORY_MODE_USE = 1, }; enum RedEntryFileLayoutSize { REDSOUND_MUSIC_SIGNATURE_SIZE = 4, REDSOUND_SESEP_SIGNATURE_SIZE = 8, + REDSOUND_SESEP_RESERVED13_SIZE = 0x01, REDSOUND_SE_INFO_SEQUENCE_MIN_COUNT = 1, REDSOUND_SE_BLOCK_SIGNATURE_SIZE = 8, + REDSOUND_SE_BLOCK_RESERVED08_SIZE = 0x02, REDSOUND_SE_BLOCK_ENTRY_MIN_COUNT = 1, REDSOUND_WAVE_SIGNATURE_SIZE = 2, REDSOUND_WAVE_SIGNATURE_MAGIC0 = 'W', REDSOUND_WAVE_SIGNATURE_MAGIC1 = 'D', + REDSOUND_WAVE_HEAD_RESERVED18_SIZE = 0x08, REDSOUND_WAVE_OFFSET_MIN_COUNT = 1, }; @@ -61,6 +104,30 @@ enum RedEntryWaveAramLayout { REDSOUND_WAVE_LARGE_REGION_SIZE = 0x400000, }; +enum RedMusicSignature { + REDSOUND_MUSIC_SIGNATURE_0 = 'B', + REDSOUND_MUSIC_SIGNATURE_1 = 'G', + REDSOUND_MUSIC_SIGNATURE_2 = 'M', +}; + +enum RedSeSepSignature { + REDSOUND_SESEP_SIGNATURE_0 = 'S', + REDSOUND_SESEP_SIGNATURE_1 = 'e', + REDSOUND_SESEP_SIGNATURE_2 = 'S', + REDSOUND_SESEP_SIGNATURE_3 = 'e', + REDSOUND_SESEP_SIGNATURE_4 = 'p', +}; + +enum RedSeBlockSignature { + REDSOUND_SE_BLOCK_SIGNATURE_0 = 'S', + REDSOUND_SE_BLOCK_SIGNATURE_1 = 'e', + REDSOUND_SE_BLOCK_SIGNATURE_2 = 'B', + REDSOUND_SE_BLOCK_SIGNATURE_3 = 'l', + REDSOUND_SE_BLOCK_SIGNATURE_4 = 'o', + REDSOUND_SE_BLOCK_SIGNATURE_5 = 'c', + REDSOUND_SE_BLOCK_SIGNATURE_6 = 'k', +}; + struct RedMusicHEAD { char m_signature[REDSOUND_MUSIC_SIGNATURE_SIZE]; @@ -69,7 +136,7 @@ struct RedMusicHEAD char m_trackCount; char m_reverbKind; short m_reverbDepth; - unsigned short m_flags; + short m_flags; unsigned short m_reserved0E; int m_size; unsigned int m_playFlags; @@ -77,8 +144,43 @@ struct RedMusicHEAD int m_reserved1C; }; +struct RedMusicTrackBlock +{ + unsigned char m_sizeLo; + unsigned char m_sizeHi0; + unsigned char m_sizeHi1; + unsigned char m_sizeHi2; + unsigned char m_command[1]; +}; + +enum RedMusicTrackBlockLayout { + REDSOUND_MUSIC_TRACK_BLOCK_SIZE_LO_OFFSET = 0, + REDSOUND_MUSIC_TRACK_BLOCK_SIZE_HI0_OFFSET = 1, + REDSOUND_MUSIC_TRACK_BLOCK_SIZE_HI1_OFFSET = 2, + REDSOUND_MUSIC_TRACK_BLOCK_SIZE_HI2_OFFSET = 3, + REDSOUND_MUSIC_TRACK_BLOCK_COMMAND_OFFSET = 4, + REDSOUND_MUSIC_TRACK_BLOCK_MIN_SIZE = 5, +}; + enum RedMusicHeaderFlag { REDSOUND_MUSIC_HEADER_SIZE = sizeof(RedMusicHEAD), + REDSOUND_MUSIC_HEADER_SIGNATURE_OFFSET = 0x00, + REDSOUND_MUSIC_HEADER_MUSIC_NO_OFFSET = 0x04, + REDSOUND_MUSIC_HEADER_WAVE_NO_OFFSET = 0x06, + REDSOUND_MUSIC_HEADER_TRACK_COUNT_OFFSET = 0x08, + REDSOUND_MUSIC_HEADER_REVERB_KIND_OFFSET = 0x09, + REDSOUND_MUSIC_HEADER_REVERB_DEPTH_OFFSET = 0x0A, + REDSOUND_MUSIC_HEADER_FLAGS_OFFSET = 0x0C, + REDSOUND_MUSIC_HEADER_RESERVED0E_OFFSET = 0x0E, + REDSOUND_MUSIC_HEADER_DATA_SIZE_OFFSET = 0x10, + REDSOUND_MUSIC_HEADER_PLAY_FLAGS_OFFSET = 0x14, + REDSOUND_MUSIC_HEADER_RESERVED18_OFFSET = 0x18, + REDSOUND_MUSIC_HEADER_RESERVED1C_OFFSET = 0x1C, + REDSOUND_MUSIC_HEADER_RESERVED0E_SIZE = + REDSOUND_MUSIC_HEADER_DATA_SIZE_OFFSET - REDSOUND_MUSIC_HEADER_RESERVED0E_OFFSET, + REDSOUND_MUSIC_HEADER_RESERVED18_SIZE = + REDSOUND_MUSIC_HEADER_RESERVED1C_OFFSET - REDSOUND_MUSIC_HEADER_RESERVED18_OFFSET, + REDSOUND_MUSIC_HEADER_RESERVED1C_SIZE = REDSOUND_MUSIC_HEADER_SIZE - REDSOUND_MUSIC_HEADER_RESERVED1C_OFFSET, REDSOUND_MUSIC_HEADER_VOLUME_SCALE_MASK = 0x7F, REDSOUND_MUSIC_PLAY_FLAG_RELEASE_NOTES = 0x40000, }; @@ -98,11 +200,32 @@ struct RedSeSepHEAD enum RedSeSepHeadLayout { REDSOUND_SESEP_HEADER_SIZE = 0x10, + REDSOUND_SESEP_STRUCT_SIZE = 0x14, + REDSOUND_SESEP_SIGNATURE_OFFSET = 0x00, + REDSOUND_SESEP_SE_NO_OFFSET = 0x08, + REDSOUND_SESEP_SIZE_AND_FLAGS_OFFSET = 0x0C, + REDSOUND_SESEP_INFO_OFFSET = 0x10, + REDSOUND_SESEP_WAVE_NO_LO_OFFSET = 0x11, + REDSOUND_SESEP_WAVE_NO_HI_OFFSET = 0x12, + REDSOUND_SESEP_RESERVED13_OFFSET = 0x13, REDSOUND_SESEP_WAVE_NO_HIGH_SCALE = 0x100, REDSOUND_SESEP_SIZE_MASK = 0x7FFFFFFF, REDSOUND_SESEP_FLAGS_MASK = 0x80000000, }; +#define RedSeSepGetInfo(seSepHead) reinterpret_cast(&(seSepHead)->m_seInfoFlags) + +struct RedSeInfoSequence +{ + unsigned char m_offsetLo; + unsigned char m_offsetHiAndFlags; +}; + +enum RedSeInfoSequenceLayout { + REDSOUND_SE_INFO_SEQUENCE_OFFSET_LO_OFFSET = 0, + REDSOUND_SE_INFO_SEQUENCE_OFFSET_HI_AND_FLAGS_OFFSET = 1, +}; + struct RedSeINFO { unsigned char m_flagsAndCount; @@ -110,22 +233,29 @@ struct RedSeINFO unsigned char m_waveNoHi; unsigned char m_eraseTrack; unsigned char m_attrMask; - unsigned char m_sequence[REDSOUND_SE_INFO_SEQUENCE_MIN_COUNT]; + RedSeInfoSequence m_sequence[REDSOUND_SE_INFO_SEQUENCE_MIN_COUNT]; }; enum RedSeInfoLayout { + REDSOUND_SE_INFO_FLAGS_AND_COUNT_OFFSET = 0, + REDSOUND_SE_INFO_WAVE_NO_LO_OFFSET = 1, + REDSOUND_SE_INFO_WAVE_NO_HI_OFFSET = 2, + REDSOUND_SE_INFO_ERASE_TRACK_OFFSET = 3, + REDSOUND_SE_INFO_ATTR_MASK_OFFSET = 4, + REDSOUND_SE_INFO_SEQUENCE_OFFSET = 5, + REDSOUND_SE_INFO_MIN_SIZE = 7, REDSOUND_SE_INFO_U16_HIGH_SCALE = 0x100, REDSOUND_SE_INFO_MULTI_FLAG = 0x80, REDSOUND_SE_INFO_COUNT_MASK = 0x7F, REDSOUND_SE_INFO_SEQUENCE_CONTINUE_FLAG = 0x80, REDSOUND_SE_INFO_SEQUENCE_OFFSET_MASK = 0x7FFF, - REDSOUND_SE_INFO_SEQUENCE_ENTRY_SIZE = 2, + REDSOUND_SE_INFO_SEQUENCE_ENTRY_SIZE = sizeof(RedSeInfoSequence), }; struct RedSeBlockHEAD { char m_signature[REDSOUND_SE_BLOCK_SIGNATURE_SIZE]; - unsigned char m_reserved08[0x0A - 0x08]; + unsigned char m_reserved08[REDSOUND_SE_BLOCK_RESERVED08_SIZE]; short m_seCount; int m_size; int m_entries[REDSOUND_SE_BLOCK_ENTRY_MIN_COUNT]; @@ -133,6 +263,12 @@ struct RedSeBlockHEAD enum RedSeBlockEntryLayout { REDSOUND_SE_BLOCK_HEADER_SIZE = 0x10, + REDSOUND_SE_BLOCK_STRUCT_SIZE = 0x14, + REDSOUND_SE_BLOCK_SIGNATURE_OFFSET = 0x00, + REDSOUND_SE_BLOCK_RESERVED08_OFFSET = 0x08, + REDSOUND_SE_BLOCK_SE_COUNT_OFFSET = 0x0A, + REDSOUND_SE_BLOCK_SIZE_OFFSET = 0x0C, + REDSOUND_SE_BLOCK_ENTRIES_OFFSET = 0x10, REDSOUND_SE_BLOCK_DATA_FLAG = 0x80000000, REDSOUND_SE_BLOCK_ENTRY_MASK = 0x7FFFFFFF, REDSOUND_SE_BLOCK_ENTRY_EMPTY = -1, @@ -144,6 +280,19 @@ enum RedSeBlockEntryLayout { REDSOUND_SE_BLOCK_SEQUENCE_COUNT = REDSOUND_SE_BLOCK_SEQUENCE_MASK + 1, }; +#define RedSeBlockGetInfo(seBlock, seIndex) \ + reinterpret_cast(reinterpret_cast((seBlock)->m_entries) + \ + (seBlock)->m_seCount * REDSOUND_SE_BLOCK_ENTRY_SIZE + \ + ((seBlock)->m_entries[(seIndex)] & REDSOUND_SE_BLOCK_ENTRY_MASK)) + +#define RedSeBlockGetInfoFromEntries(seBlock, entries, seIndex) \ + reinterpret_cast(reinterpret_cast(entries) + \ + (seBlock)->m_seCount * REDSOUND_SE_BLOCK_ENTRY_SIZE + \ + ((entries)[(seIndex)] & REDSOUND_SE_BLOCK_ENTRY_MASK)) + +#define RedSeBlockGetInfoFromOffset(entries, infoOffset) \ + reinterpret_cast(reinterpret_cast(entries) + (infoOffset)) + struct RedWaveHeadWD { char m_signature[REDSOUND_WAVE_SIGNATURE_SIZE]; @@ -153,10 +302,33 @@ struct RedWaveHeadWD int m_toneCount; int m_aramAddress; int m_loadSize; - unsigned char m_reserved18[0x20 - 0x18]; + unsigned char m_reserved18[REDSOUND_WAVE_HEAD_RESERVED18_SIZE]; int m_waveOffsets[REDSOUND_WAVE_OFFSET_MIN_COUNT]; }; +enum RedWaveHeadLayout { + REDSOUND_WAVE_HEAD_MIN_SIZE = 0x24, + REDSOUND_WAVE_HEAD_SIGNATURE_OFFSET = 0x00, + REDSOUND_WAVE_HEAD_WAVE_NO_OFFSET = 0x02, + REDSOUND_WAVE_HEAD_WAVE_SIZE_OFFSET = 0x04, + REDSOUND_WAVE_HEAD_TABLE_COUNT_OFFSET = 0x08, + REDSOUND_WAVE_HEAD_TONE_COUNT_OFFSET = 0x0C, + REDSOUND_WAVE_HEAD_ARAM_ADDRESS_OFFSET = 0x10, + REDSOUND_WAVE_HEAD_LOAD_SIZE_OFFSET = 0x14, + REDSOUND_WAVE_HEAD_RESERVED18_OFFSET = 0x18, + REDSOUND_WAVE_HEAD_OFFSETS_OFFSET = 0x20, +}; + +enum RedEntryLayout { + REDSOUND_ENTRY_WAVE_BANK_BASE_OFFSET = 0x00, + REDSOUND_ENTRY_SESEP_BANK_BASE_OFFSET = 0x04, + REDSOUND_ENTRY_MUSIC_BANK_BASE_OFFSET = 0x08, + REDSOUND_ENTRY_WAVE_LOAD_NO_OFFSET = 0x0C, + REDSOUND_ENTRY_WAVE_LOAD_SIZE_OFFSET = 0x10, + REDSOUND_ENTRY_WAVE_LOAD_ADDRESS_OFFSET = 0x14, + REDSOUND_ENTRY_SIZE = 0x18, +}; + class CRedEntry { public: @@ -165,51 +337,53 @@ class CRedEntry void Init(); - void WaveHistoryAdd(int); - void WaveHistoryDelete(int); - void WaveHistoryChoice(RedHistoryBANK*); - int SearchWaveSequence(int); - int SearchUseWave(int); - int WaveDelete(RedHistoryBANK*); - int WaveOldClear(int, int); - int WaveHeadAdd(int, RedWaveHeadWD*, int); - int SetWaveData(int, void*, int); - void ClearWaveData(int); - void ClearWaveDataM(int, int, int, int); - void ClearWaveBank(int); - int GetWaveBank(int); - RedWaveHeadWD* SearchWaveBase(int); - int ReentryWaveData(int); - void WaveHistoryManager(int, int); + void WaveHistoryAdd(int waveNo); + void WaveHistoryDelete(int historyNo); + void WaveHistoryChoice(RedHistoryBANK* bank); + int SearchWaveSequence(int waveNo); + int SearchUseWave(int waveNo); + int WaveDelete(RedHistoryBANK* bank); + int WaveOldClear(int waveNo, int aramOffset); + int WaveHeadAdd(int waveBankNo, RedWaveHeadWD* waveHead, int waveNo); + int SetWaveData(int waveBankNo, void* waveData, int waveDataSize); + void ClearWaveData(int waveNo); + void ClearWaveDataM(int waveNo0, int waveNo1, int waveNo2, int waveNo3); + void ClearWaveBank(int waveBankNo); + RedHistoryBANK* GetWaveBank(int waveNo); + RedWaveHeadWD* SearchWaveBase(int waveNo); + int ReentryWaveData(int waveNo); + void WaveHistoryManager(int mode, int waveNo); void DisplayWaveInfo(); void SeSepHistoryAdd(); - void SeSepHistoryDelete(int); - void SeSepHistoryChoice(RedHistoryBANK*); - int SearchSeSepSequence(int); - int SeSepMemoryFree(RedHistoryBANK*); + void SeSepHistoryDelete(int historyNo); + void SeSepHistoryChoice(RedHistoryBANK* bank); + int SearchSeSepSequence(int seNo); + int SeSepMemoryFree(RedHistoryBANK* bank); RedHistoryBANK* SeSepOldDelete(); - RedSeSepHEAD* SeSepHeadAdd(RedSeSepHEAD*); - RedSeSepHEAD* SetSeSepData(RedSeSepHEAD*); - int ClearSeSepData(int); - int ClearSeSepDataMG(int, int, int, int); - RedHistoryBANK* SearchSeSepBank(int); - int ReentrySeSepData(int); - void SeSepHistoryManager(int, int); + RedSeSepHEAD* SeSepHeadAdd(RedSeSepHEAD* seSepHead); + RedSeSepHEAD* SetSeSepData(RedSeSepHEAD* seSepHead); + int ClearSeSepData(int seNo); + int ClearSeSepDataMG(int bank, int sep, int group, int kind); + RedHistoryBANK* SearchSeSepBank(int seNo); + int ReentrySeSepData(int seNo); + void SeSepHistoryManager(int mode, int seNo); void DisplaySePlayInfo(); void MusicHistoryAdd(); - void MusicHistoryDelete(int); - void MusicHistoryChoice(RedHistoryBANK*); - int SearchMusicSequence(int); - int MusicMemoryFree(RedHistoryBANK*); + void MusicHistoryDelete(int historyNo); + void MusicHistoryChoice(RedHistoryBANK* bank); + int SearchMusicSequence(int musicNo); + int MusicMemoryFree(RedHistoryBANK* bank); int MusicOldClear(); RedHistoryBANK* MusicOldChoice(); - RedHistoryBANK* SearchMusicBank(int); - int ReentryMusicData(int); - void MusicHistoryManager(int, int); - RedMusicHEAD* MusicHeadAdd(RedMusicHEAD*); - RedMusicHEAD* SetMusicData(RedMusicHEAD*); + RedHistoryBANK* SearchMusicBank(int musicNo); + int ReentryMusicData(int musicNo); + void MusicHistoryManager(int mode, int musicNo); + RedMusicHEAD* MusicHeadAdd(RedMusicHEAD* musicHead); + RedMusicHEAD* SetMusicData(RedMusicHEAD* musicHead); + int ClearMusicData(int musicNo); + void DisplayMusicInfo(); void DisplayMMemoryInfo(); RedHistoryBANK* m_waveBankBase; diff --git a/include/ffcc/RedSound/RedExecute.h b/include/ffcc/RedSound/RedExecute.h index 15871a79f4..acf71a6801 100644 --- a/include/ffcc/RedSound/RedExecute.h +++ b/include/ffcc/RedSound/RedExecute.h @@ -9,12 +9,6 @@ struct RedTrackDATA; struct RedSoundCONTROL; struct RedKeyOnDATA; -struct RedReverbDATA { - int m_callback; - void* m_context; - int m_kind; -}; - enum RedReverbKind { REDSOUND_REVERB_KIND_NONE = 0, REDSOUND_REVERB_KIND_STD = 1, @@ -24,11 +18,30 @@ enum RedReverbKind { REDSOUND_REVERB_KIND_HI_DPL2 = 5, }; +struct RedReverbDATA { + int m_callback; + void* m_context; + RedReverbKind m_kind; +}; + +enum RedReverbLayoutOffset { + REDSOUND_REVERB_CALLBACK_OFFSET = 0x00, + REDSOUND_REVERB_CONTEXT_OFFSET = 0x04, + REDSOUND_REVERB_KIND_OFFSET = 0x08, + REDSOUND_REVERB_SIZE = 0x0C, +}; + struct RedReverbSize { u32 m_requested; u32 m_aligned; }; +enum RedReverbSizeLayoutOffset { + REDSOUND_REVERB_SIZE_REQUESTED_OFFSET = 0x00, + REDSOUND_REVERB_SIZE_ALIGNED_OFFSET = 0x04, + REDSOUND_REVERB_SIZE_SIZE = 0x08, +}; + struct RedNoteDATA { signed char m_key; signed char m_velocity; @@ -36,6 +49,23 @@ struct RedNoteDATA { unsigned char m_reserved03; }; +inline void RedNoteCopy(RedNoteDATA* dst, const RedNoteDATA* src) +{ + *(int*)&dst->m_key = *(int*)&src->m_key; +} + +enum RedNoteLayoutOffset { + REDSOUND_NOTE_KEY_OFFSET = 0x00, + REDSOUND_NOTE_VELOCITY_OFFSET = 0x01, + REDSOUND_NOTE_ALLOC_FLAGS_OFFSET = 0x02, + REDSOUND_NOTE_RESERVED03_OFFSET = 0x03, + REDSOUND_NOTE_SIZE = 0x04, +}; + +enum RedNoteLayoutSize { + REDSOUND_NOTE_RESERVED03_SIZE = REDSOUND_NOTE_SIZE - REDSOUND_NOTE_RESERVED03_OFFSET, +}; + enum RedNoteAllocFlag { REDSOUND_NOTE_ALLOC_DIRECT = 1, REDSOUND_NOTE_ALLOC_STREAM = 2, @@ -49,22 +79,37 @@ struct RedWaveADPCMInfo { AXPBADPCMLOOP m_loop; }; +enum RedWaveAdpcmLayoutOffset { + REDSOUND_WAVE_ADPCM_DATA_OFFSET = 0x00, + REDSOUND_WAVE_ADPCM_LOOP_OFFSET = 0x28, + REDSOUND_WAVE_ADPCM_INFO_SIZE = 0x2E, + REDSOUND_WAVE_ADPCM_DATA_SIZE = REDSOUND_WAVE_ADPCM_LOOP_OFFSET - REDSOUND_WAVE_ADPCM_DATA_OFFSET, + REDSOUND_WAVE_ADPCM_LOOP_SIZE = REDSOUND_WAVE_ADPCM_INFO_SIZE - REDSOUND_WAVE_ADPCM_LOOP_OFFSET, +}; + +enum RedWaveReservedLayoutSize { + REDSOUND_WAVE_RESERVED10_SIZE = 0x04, + REDSOUND_WAVE_RESERVED1D_SIZE = 0x05, + REDSOUND_WAVE_ADSR_SIZE = 0x0C, + REDSOUND_WAVE_RESERVED5C_SIZE = 0x04, +}; + struct RedWaveDATA { unsigned int m_flags; int m_sampleStart; int m_loopStart; int m_loopEnd; - unsigned char m_reserved10[0x14 - 0x10]; + unsigned char m_reserved10[REDSOUND_WAVE_RESERVED10_SIZE]; int m_pitch; signed char m_splitKey; unsigned char m_splitVelocity; unsigned char m_volume; unsigned char m_pan; signed char m_reverbMix; - unsigned char m_reserved1D[0x22 - 0x1D]; + unsigned char m_reserved1D[REDSOUND_WAVE_RESERVED1D_SIZE]; RedWaveADPCMInfo m_adpcm; - unsigned char m_adsr[0x5C - 0x50]; - unsigned char m_reserved5C[0x60 - 0x5C]; + unsigned char m_adsr[REDSOUND_WAVE_ADSR_SIZE]; + unsigned char m_reserved5C[REDSOUND_WAVE_RESERVED5C_SIZE]; }; enum RedWaveLayoutSize { @@ -79,14 +124,21 @@ enum RedWaveFlag { }; enum RedWaveLayoutOffset { + REDSOUND_WAVE_FLAGS_OFFSET = 0x00, REDSOUND_WAVE_SAMPLE_START_OFFSET = 0x04, REDSOUND_WAVE_LOOP_START_OFFSET = 0x08, REDSOUND_WAVE_LOOP_END_OFFSET = 0x0C, + REDSOUND_WAVE_RESERVED10_OFFSET = 0x10, REDSOUND_WAVE_PITCH_OFFSET = 0x14, REDSOUND_WAVE_SPLIT_KEY_OFFSET = 0x18, + REDSOUND_WAVE_SPLIT_VELOCITY_OFFSET = 0x19, REDSOUND_WAVE_VOLUME_OFFSET = 0x1A, REDSOUND_WAVE_PAN_OFFSET = 0x1B, REDSOUND_WAVE_REVERB_MIX_OFFSET = 0x1C, + REDSOUND_WAVE_RESERVED1D_OFFSET = 0x1D, + REDSOUND_WAVE_ADPCM_OFFSET = 0x22, + REDSOUND_WAVE_ADSR_OFFSET = 0x50, + REDSOUND_WAVE_RESERVED5C_OFFSET = 0x5C, }; enum RedWaveLayoutWord { @@ -96,9 +148,28 @@ enum RedWaveLayoutWord { enum RedVoiceLayoutCount { REDSOUND_VOICE_ADSR_TIME_COUNT = 4, REDSOUND_VOICE_ADSR_LEVEL_COUNT = 4, + REDSOUND_VOICE_ADSR_TIME_BYTE_STRIDE = sizeof(u16), + REDSOUND_VOICE_RESERVED1B_SIZE = 0x01, + REDSOUND_VOICE_RESERVED2A_SIZE = 0x02, + REDSOUND_VOICE_RESERVED3A_SIZE = 0x02, + REDSOUND_VOICE_RESERVED48_SIZE = 0x08, + REDSOUND_VOICE_RESERVEDA4_SIZE = 0x04, + REDSOUND_VOICE_RESERVEDB4_SIZE = 0x04, + REDSOUND_VOICE_RESERVEDBC_SIZE = 0x04, REDSOUND_TERMINATE_NOTE_WORD_COUNT = 1, }; +enum RedAdsrDataLayout { + REDSOUND_ADSR_TIME_OFFSET = 0x00, + REDSOUND_ADSR_LEVEL_OFFSET = REDSOUND_VOICE_ADSR_TIME_COUNT * sizeof(unsigned short), + REDSOUND_ADSR_DATA_SIZE = REDSOUND_ADSR_LEVEL_OFFSET + REDSOUND_VOICE_ADSR_LEVEL_COUNT, +}; + +struct RedAdsrDATA { + unsigned short m_time[REDSOUND_VOICE_ADSR_TIME_COUNT]; + unsigned char m_level[REDSOUND_VOICE_ADSR_LEVEL_COUNT]; +}; + struct RedVoiceDATA { RedTrackDATA* m_track; RedWaveDATA* m_waveData; @@ -114,18 +185,17 @@ struct RedVoiceDATA { int m_pitchModFrames; int m_pitchModFrame; short m_pitchModDelay; - unsigned char m_reserved2A[0x2C - 0x2A]; + unsigned char m_reserved2A[REDSOUND_VOICE_RESERVED2A_SIZE]; int m_volumeModPhase; int m_volumeModFrames; int m_volumeModFrame; short m_volumeModDelay; - unsigned char m_reserved3A[0x3C - 0x3A]; + unsigned char m_reserved3A[REDSOUND_VOICE_RESERVED3A_SIZE]; int m_randomPitch; int m_randomVolume; int m_randomPan; - unsigned char m_reserved48[0x50 - 0x48]; - unsigned short m_adsrTime[REDSOUND_VOICE_ADSR_TIME_COUNT]; - unsigned char m_adsrLevel[REDSOUND_VOICE_ADSR_LEVEL_COUNT]; + unsigned char m_reserved48[REDSOUND_VOICE_RESERVED48_SIZE]; + RedAdsrDATA m_adsr; int m_adsrStage; int m_adsrStepFrames; int m_adsrStepAdd; @@ -136,13 +206,13 @@ struct RedVoiceDATA { int m_pitch; int m_targetPitch; int m_basePitch; - unsigned char m_reservedA4[0xA8 - 0xA4]; + unsigned char m_reservedA4[REDSOUND_VOICE_RESERVEDA4_SIZE]; int m_voiceIndex; int m_adsrCurrentLevel; int m_envelopeLevel; - unsigned char m_reservedB4[0xB8 - 0xB4]; + unsigned char m_reservedB4[REDSOUND_VOICE_RESERVEDB4_SIZE]; unsigned int m_updateFlags; - unsigned char m_reservedBC[0xC0 - 0xBC]; + unsigned char m_reservedBC[REDSOUND_VOICE_RESERVEDBC_SIZE]; }; enum RedVoiceAdsrIndex { @@ -157,7 +227,6 @@ enum RedVoiceAdsrLayout { REDSOUND_VOICE_ADSR_TIME_OFFSET = 0x50, REDSOUND_VOICE_ADSR_LEVEL_OFFSET = 0x58, REDSOUND_VOICE_ADSR_STAGE_OFFSET = 0x5C, - REDSOUND_WAVE_ADSR_OFFSET = 0x50, REDSOUND_VOICE_ADSR_TIME_HALFWORD = REDSOUND_VOICE_ADSR_TIME_OFFSET / sizeof(u16), REDSOUND_VOICE_ADSR_LEVEL_ATTACK_OFFSET = REDSOUND_VOICE_ADSR_LEVEL_OFFSET, REDSOUND_VOICE_ADSR_LEVEL_DECAY_OFFSET = REDSOUND_VOICE_ADSR_LEVEL_OFFSET + 1, @@ -167,18 +236,34 @@ enum RedVoiceAdsrLayout { REDSOUND_VOICE_ADSR_TIME_DECAY_HALFWORD = REDSOUND_VOICE_ADSR_TIME_ATTACK_HALFWORD + 1, REDSOUND_VOICE_ADSR_TIME_SUSTAIN_HALFWORD = REDSOUND_VOICE_ADSR_TIME_ATTACK_HALFWORD + 2, REDSOUND_VOICE_ADSR_TIME_RELEASE_HALFWORD = REDSOUND_VOICE_ADSR_TIME_ATTACK_HALFWORD + 3, + REDSOUND_VOICE_ADSR_TIME_RELEASE_BYTE = + REDSOUND_VOICE_ADSR_RELEASE * REDSOUND_VOICE_ADSR_TIME_BYTE_STRIDE, REDSOUND_VOICE_ADSR_TIME_RELEASE_BYTE_OFFSET = REDSOUND_VOICE_ADSR_TIME_RELEASE_HALFWORD * sizeof(u16), REDSOUND_VOICE_ADSR_LEVEL_BASE = 9, REDSOUND_VOICE_ADSR_STAGE_COUNT = 3, }; +#define RedAdsrGetStageLevel(adsrData, stage) \ + (*reinterpret_cast(reinterpret_cast(adsrData) + (stage) + \ + REDSOUND_VOICE_ADSR_LEVEL_BASE)) + enum RedVoiceLayoutOffset { REDSOUND_VOICE_TRACK_OFFSET = 0x00, + REDSOUND_VOICE_KEY_OFFSET = 0x18, + REDSOUND_VOICE_VELOCITY_OFFSET = 0x19, REDSOUND_VOICE_STATE_FLAGS_OFFSET = 0x1A, + REDSOUND_VOICE_RESERVED1B_OFFSET = 0x1B, + REDSOUND_VOICE_RESERVED2A_OFFSET = 0x2A, + REDSOUND_VOICE_RESERVED3A_OFFSET = 0x3A, + REDSOUND_VOICE_RESERVED48_OFFSET = 0x48, REDSOUND_VOICE_ACTIVE_OFFSET = 0x8C, REDSOUND_VOICE_FLAGS_OFFSET = 0x90, REDSOUND_VOICE_SWITCH_OFFSET = 0x94, + REDSOUND_VOICE_RESERVEDA4_OFFSET = 0xA4, REDSOUND_VOICE_INDEX_OFFSET = 0xA8, + REDSOUND_VOICE_RESERVEDB4_OFFSET = 0xB4, + REDSOUND_VOICE_UPDATE_FLAGS_OFFSET = 0xB8, + REDSOUND_VOICE_RESERVEDBC_OFFSET = 0xBC, }; enum RedVoiceLayoutWord { @@ -192,11 +277,11 @@ enum RedVoiceLayoutWord { REDSOUND_VOICE_PITCH_MOD_PHASE_WORD = 7, REDSOUND_VOICE_PITCH_MOD_FRAMES_WORD = 8, REDSOUND_VOICE_PITCH_MOD_FRAME_WORD = 9, - REDSOUND_VOICE_PITCH_MOD_DELAY_HALFWORD = 0x0A, + REDSOUND_VOICE_PITCH_MOD_DELAY_HALFWORD = 0x14, REDSOUND_VOICE_VOLUME_MOD_PHASE_WORD = 0x0B, REDSOUND_VOICE_VOLUME_MOD_FRAMES_WORD = 0x0C, REDSOUND_VOICE_VOLUME_MOD_FRAME_WORD = 0x0D, - REDSOUND_VOICE_VOLUME_MOD_DELAY_HALFWORD = 0x0E, + REDSOUND_VOICE_VOLUME_MOD_DELAY_HALFWORD = 0x1C, REDSOUND_VOICE_RANDOM_PITCH_WORD = 0x0F, REDSOUND_VOICE_RANDOM_VOLUME_WORD = 0x10, REDSOUND_VOICE_RANDOM_PAN_WORD = 0x11, @@ -217,12 +302,18 @@ enum RedVoiceLayoutWord { REDSOUND_VOICE_UPDATE_FLAGS_WORD = 0x2E, }; +enum RedVoiceActiveState { + REDSOUND_VOICE_ACTIVE_OFF = 0, + REDSOUND_VOICE_ACTIVE_ON = 1, +}; + enum RedVoiceBufferWordOffset { REDSOUND_VOICE_SECOND_MASK_WORD_OFFSET = 0x600, }; enum RedRandomByteLayout { REDSOUND_RANDOM_BYTE_MASK = 0xFF, + REDSOUND_RANDOM_DATA_COUNT = REDSOUND_RANDOM_BYTE_MASK + 1, REDSOUND_RANDOM_BYTE_SIGN_BIT = 0x80, REDSOUND_RANDOM_FUZZY_DEPTH_SHIFT = 8, REDSOUND_RANDOM_FUZZY_PITCH_SHIFT = 15, @@ -253,6 +344,8 @@ enum RedVoiceCleanupMask { REDSOUND_VOICE_SWITCH_REVERB_RIGHT = 0x2000, REDSOUND_VOICE_SWITCH_REVERB_STEREO = REDSOUND_VOICE_SWITCH_REVERB_LEFT | REDSOUND_VOICE_SWITCH_REVERB_RIGHT, REDSOUND_VOICE_SWITCH_MIX_ALL = REDSOUND_VOICE_SWITCH_DRY_STEREO | REDSOUND_VOICE_SWITCH_REVERB_STEREO, + REDSOUND_VOICE_SWITCH_MUSIC_DEFAULT = REDSOUND_VOICE_SWITCH_DRY_STEREO | REDSOUND_VOICE_SWITCH_REVERB_AUX_A, + REDSOUND_VOICE_SWITCH_STREAM_DEFAULT = REDSOUND_VOICE_SWITCH_DRY_STEREO | REDSOUND_VOICE_SWITCH_LOOP, REDSOUND_VOICE_SWITCH_FUZZY_PITCH = 0x4000, REDSOUND_VOICE_SWITCH_FUZZY_VOLUME = 0x8000, REDSOUND_VOICE_SWITCH_FUZZY_PAN = 0x10000, @@ -285,21 +378,23 @@ enum RedVoiceUpdateFlag { }; u8 GetRandomData(); -int PitchCompute(int, int, int, int); -void* ReverbAreaAlloc(unsigned long); -void ReverbAreaFree(void*); +int PitchCompute(int basePitch, int pitchOffset, int wavePitch, int fineTune); +void* ReverbAreaAlloc(unsigned long size); +void ReverbAreaFree(void* area); void InitReverb(); -RedReverbSize* SetReverb(int, int, int*); +RedReverbSize* GetReverbInfo(); +RedReverbSize* SetReverb(int bank, int kind, int* params); -RedVoiceDATA* EntryVoiceSearch(RedTrackDATA*); -void SetVoiceVolumeMix(RedVoiceDATA*, int, int); -void SetVoiceAccess(RedTrackDATA*, int); -void SetVoiceSwitch(RedTrackDATA*, int); +RedVoiceDATA* EntryVoiceSearch(RedTrackDATA* track); +void SetVoiceVolumeMix(RedVoiceDATA* voice, int pan, int volume); +void SetVoiceAccess(RedTrackDATA* track, int mask); +void SetAllVoiceAccess(RedSoundCONTROL* control, int mask); +void SetVoiceSwitch(RedTrackDATA* track, int voiceSwitch); void EnvelopeKeyExecute(); void MusicSkipFunction(); -void MainControl(int); +void MainControl(int frames); #endif // _FFCC_REDSOUND_REDEXECUTE_H diff --git a/include/ffcc/RedSound/RedGlobals.h b/include/ffcc/RedSound/RedGlobals.h index 860bb645a4..bfa7f0c174 100644 --- a/include/ffcc/RedSound/RedGlobals.h +++ b/include/ffcc/RedSound/RedGlobals.h @@ -3,6 +3,7 @@ #include "PowerPC_EABI_Support/Msl/MSL_C/MSL_Common/file_io.h" #include "dolphin/os.h" +#include "ffcc/RedSound/RedEntry.h" #include "ffcc/RedSound/RedMidiCtrl.h" #include "ffcc/RedSound/RedStream.h" #include "types.h" @@ -17,12 +18,32 @@ struct RedControlRamp { int m_count; }; +enum RedControlRampLayout { + REDSOUND_CONTROL_RAMP_VALUE_OFFSET = 0x00, + REDSOUND_CONTROL_RAMP_STEP_OFFSET = 0x04, + REDSOUND_CONTROL_RAMP_COUNT_OFFSET = 0x08, + REDSOUND_CONTROL_RAMP_SIZE = 0x0C, +}; + struct RedReverbDepth { int m_depth; int m_step; int m_count; }; +enum RedReverbDepthLayout { + REDSOUND_REVERB_DEPTH_DEPTH_OFFSET = 0x00, + REDSOUND_REVERB_DEPTH_STEP_OFFSET = 0x04, + REDSOUND_REVERB_DEPTH_COUNT_OFFSET = 0x08, + REDSOUND_REVERB_DEPTH_SIZE = 0x0C, +}; + +enum RedSoundMode { + REDSOUND_SOUND_MODE_STEREO = 0, + REDSOUND_SOUND_MODE_MONO = 1, + REDSOUND_SOUND_MODE_SURROUND = 2, +}; + enum RedSoundControlIndex { REDSOUND_CONTROL_MUSIC_PRIMARY = 0, REDSOUND_CONTROL_MUSIC_SECONDARY = 1, @@ -32,7 +53,7 @@ enum RedSoundControlIndex { enum RedSoundLayoutSize { REDSOUND_TRACK_SIZE = sizeof(RedTrackDATA), - REDSOUND_CONTROL_SIZE = 0x494, + REDSOUND_CONTROL_SIZE = sizeof(RedSoundCONTROL), REDSOUND_CONTROL_COUNT = 4, REDSOUND_CONTROL_BUFFER_SIZE = REDSOUND_CONTROL_SIZE * REDSOUND_CONTROL_COUNT, REDSOUND_CONTROL_SECONDARY_OFFSET = REDSOUND_CONTROL_SIZE * REDSOUND_CONTROL_MUSIC_SECONDARY, @@ -50,9 +71,8 @@ enum RedSoundLayoutSize { REDSOUND_VOICE_SIZE = sizeof(RedVoiceDATA), REDSOUND_VOICE_BUFFER_SIZE = REDSOUND_VOICE_SIZE * REDSOUND_VOICE_COUNT, REDSOUND_KEY_ON_BUFFER_SIZE = sizeof(RedKeyOnDATA), - REDSOUND_CONTROL_RAMP_SIZE = sizeof(RedControlRamp), REDSOUND_REVERB_DEPTH_COUNT = 2, - REDSOUND_REVERB_DEPTH_BUFFER_SIZE = sizeof(RedReverbDepth) * REDSOUND_REVERB_DEPTH_COUNT, + REDSOUND_REVERB_DEPTH_BUFFER_SIZE = REDSOUND_REVERB_DEPTH_SIZE * REDSOUND_REVERB_DEPTH_COUNT, REDSOUND_MUTE_WORD_COUNT = 2, REDSOUND_MUTE_WORD_SHIFT = 5, REDSOUND_MUTE_BITS_PER_WORD = 1 << REDSOUND_MUTE_WORD_SHIFT, @@ -88,13 +108,27 @@ enum RedSoundFixedPoint { REDSOUND_FRAMES_PER_SECOND = 60, REDSOUND_SE_FADE_TICKS_PER_SECOND = 0x60, REDSOUND_MUSIC_FADE_TICKS_PER_SECOND = 200, + REDSOUND_STREAM_FADE_TICKS_PER_SECOND = REDSOUND_MUSIC_FADE_TICKS_PER_SECOND, + REDSOUND_MUSIC_ID_MIN = 0, + REDSOUND_MUSIC_ID_NONE = -1, + REDSOUND_MUSIC_PLAY_FAILED = -1, + REDSOUND_SE_ID_MIN = 0, + REDSOUND_SE_ID_NONE = 0, + REDSOUND_SE_ID_ALL = -1, + REDSOUND_SE_PLAY_FAILED = -1, + REDSOUND_SE_BANK_SESEP = -1, + REDSOUND_SESEP_ID_NONE = -1, + REDSOUND_SE_MG_ID_DIVISOR = 1000, REDSOUND_TEMPO_SCALE_MASK = 0xFFFF, + REDSOUND_TEMPO_SCALE_SHIFT = 0x10, + REDSOUND_TEMPO_SCALE_POSITIVE_SHIFT = 0x0F, REDSOUND_PITCH_NOTE_SHIFT = 8, REDSOUND_PITCH_NOTE_UNIT = 0x100, REDSOUND_PITCH_BASE_NOTE_SHIFT = 0x14, REDSOUND_PITCH_KEY_SIGNATURE_UNIT = 0x100000, REDSOUND_PITCH_NOTE_MASK = 0x7F, REDSOUND_PITCH_FINE_MASK = 0xFF, + REDSOUND_PITCH_FINE_COUNT = REDSOUND_PITCH_FINE_MASK + 1, REDSOUND_PITCH_FINE_TUNE_POSITIVE_SHIFT = 7, REDSOUND_PITCH_FINE_TUNE_NEGATIVE_SHIFT = 8, REDSOUND_PITCH_OCTAVE_UNITS = 0xC00, @@ -105,6 +139,7 @@ enum RedSoundFixedPoint { REDSOUND_PAN_BYTE_MASK = 0x7F, REDSOUND_PAN_BYTE_SIGN_BIT = 0x80, REDSOUND_PAN_BYTE_WRAP = 0x100, + REDSOUND_PAN_TABLE_COUNT = REDSOUND_PAN_BYTE_WRAP, REDSOUND_MASTER_VOLUME_SCALE = 4, REDSOUND_MASTER_VOLUME_FULL = (REDSOUND_COMMAND_VALUE_MASK + 1) * REDSOUND_MASTER_VOLUME_SCALE - 1, REDSOUND_MASTER_VOLUME_FULL_FIXED = REDSOUND_MASTER_VOLUME_FULL * REDSOUND_FIXED_ONE, @@ -113,22 +148,75 @@ enum RedSoundFixedPoint { }; enum RedSoundPauseState { + REDSOUND_PAUSE_OFF = 0, REDSOUND_PAUSE_ON = 1, }; +enum RedSoundReportPrintState { + REDSOUND_REPORT_PRINT_OFF = 0, + REDSOUND_REPORT_PRINT_ON = 1, +}; + +enum RedMusicSkipCompleteState { + REDSOUND_MUSIC_SKIP_NOT_COMPLETE = 0, + REDSOUND_MUSIC_SKIP_COMPLETE = 1, +}; + +enum RedMusicPhraseStopState { + REDSOUND_MUSIC_PHRASE_STOP_OFF = 0, + REDSOUND_MUSIC_PHRASE_STOP_ON = 1, +}; + +enum RedSeVolumeQueryMode { + REDSOUND_SE_VOLUME_QUERY_VALUE = 0, + REDSOUND_SE_VOLUME_QUERY_DELTA = 1, +}; + +enum RedSoundTableLayout { + REDSOUND_TONE_PITCH_TABLE_OFFSET = 0x00, + REDSOUND_TONE_PITCH_TABLE_SIZE = sizeof(u32) * REDSOUND_NOTES_PER_OCTAVE, + REDSOUND_TONE_PITCH_TABLE_ALLOC_SIZE = 0x30, + REDSOUND_FINE_PITCH_TABLE_OFFSET = REDSOUND_TONE_PITCH_TABLE_OFFSET + REDSOUND_TONE_PITCH_TABLE_SIZE, + REDSOUND_FINE_PITCH_TABLE_SIZE = sizeof(int) * REDSOUND_PITCH_FINE_COUNT, + REDSOUND_FINE_PITCH_TABLE_ALLOC_SIZE = 0x400, + REDSOUND_KEY_SIGNATURE_INDEX_TABLE_OFFSET = REDSOUND_FINE_PITCH_TABLE_OFFSET + REDSOUND_FINE_PITCH_TABLE_SIZE, + REDSOUND_KEY_SIGNATURE_INDEX_TABLE_SIZE = sizeof(int) * REDSOUND_KEY_SIGNATURE_INDEX_COUNT, + REDSOUND_KEY_SIGNATURE_INDEX_TABLE_ALLOC_SIZE = 0x80, + REDSOUND_KEY_SIGNATURE_DATA_TABLE_OFFSET = + REDSOUND_KEY_SIGNATURE_INDEX_TABLE_OFFSET + REDSOUND_KEY_SIGNATURE_INDEX_TABLE_SIZE, + REDSOUND_KEY_SIGNATURE_DATA_TABLE_SIZE = sizeof(signed char) * REDSOUND_KEY_SIGNATURE_DATA_COUNT, + REDSOUND_KEY_SIGNATURE_DATA_TABLE_ALLOC_SIZE = 0x2E, + REDSOUND_RANDOM_DATA_TABLE_OFFSET = + REDSOUND_KEY_SIGNATURE_DATA_TABLE_OFFSET + REDSOUND_KEY_SIGNATURE_DATA_TABLE_SIZE, + REDSOUND_RANDOM_DATA_TABLE_SIZE = sizeof(signed char) * REDSOUND_RANDOM_DATA_COUNT, + REDSOUND_RANDOM_DATA_TABLE_ALLOC_SIZE = 0x100, + REDSOUND_PAN_TABLE_OFFSET = REDSOUND_RANDOM_DATA_TABLE_OFFSET + REDSOUND_RANDOM_DATA_TABLE_SIZE, + REDSOUND_PAN_TABLE_SIZE = sizeof(s16) * REDSOUND_PAN_TABLE_COUNT, + REDSOUND_PAN_TABLE_ALLOC_SIZE = 0x200, + REDSOUND_PAN_TABLE_R_OFFSET = REDSOUND_PAN_TABLE_OFFSET + REDSOUND_PAN_TABLE_SIZE, + REDSOUND_PAN_TABLE_PAIR_SIZE = REDSOUND_PAN_TABLE_SIZE * 2, + REDSOUND_PAN_TABLE_PAIR_ALLOC_SIZE = 0x400, + REDSOUND_EXECUTE_DATA_TABLE_END_OFFSET = REDSOUND_PAN_TABLE_R_OFFSET + REDSOUND_PAN_TABLE_SIZE, + REDSOUND_EXECUTE_DATA_TABLE_SIZE = + REDSOUND_TONE_PITCH_TABLE_SIZE + REDSOUND_FINE_PITCH_TABLE_SIZE + + REDSOUND_KEY_SIGNATURE_INDEX_TABLE_SIZE + REDSOUND_KEY_SIGNATURE_DATA_TABLE_SIZE + + REDSOUND_RANDOM_DATA_TABLE_SIZE + REDSOUND_PAN_TABLE_PAIR_SIZE, + REDSOUND_EXECUTE_DATA_TABLE_ALLOC_SIZE = 0x9DE, +}; + struct RedSeBlockHEAD; -extern RedMidiControlFunc p_MidiControl_Function[]; -extern u32 t_TonePitch[]; -extern int t_FinePitch[]; -extern int t_KeySignatureIndex[]; -extern signed char t_KeySignatureData[]; -extern signed char t_RandomData[]; -extern s16 t_PanningData[]; -extern s16 t_PanningDataR[]; +extern RedMidiControlFunc p_MidiControl_Function[REDSOUND_MIDI_CONTROL_FUNCTION_COUNT]; +extern u32 t_TonePitch[REDSOUND_NOTES_PER_OCTAVE]; +extern int t_FinePitch[REDSOUND_PITCH_FINE_COUNT]; +extern int t_KeySignatureIndex[REDSOUND_KEY_SIGNATURE_INDEX_COUNT]; +extern signed char t_KeySignatureData[REDSOUND_KEY_SIGNATURE_DATA_COUNT]; +extern signed char t_RandomData[REDSOUND_RANDOM_DATA_COUNT]; +extern s16 t_PanningData[REDSOUND_PAN_TABLE_COUNT]; +extern s16 t_PanningDataR[REDSOUND_PAN_TABLE_COUNT]; extern CRedEntry c_RedEntry; extern OSSemaphore m_MusicSkipSemaphore; -extern RedSeBlockHEAD* volatile p_SeBlockData[]; +extern RedSeBlockHEAD* volatile p_SeBlockData[REDSOUND_SE_BLOCK_BANK_COUNT]; extern u8* volatile p_ZeroData; extern RedSoundCONTROL* volatile p_SoundControlBuffer; extern RedSoundCONTROL* volatile p_SoundControl; @@ -155,7 +243,7 @@ extern RedTrackDATA* p_EditorTrack; extern u8* volatile p_MusicSkipThreadStack; extern volatile int m_MusicSkipComplete; extern RedReverbDepth* volatile p_ReverbDepth; -extern int m_Mute[REDSOUND_MUTE_WORD_COUNT]; +extern unsigned int m_Mute[REDSOUND_MUTE_WORD_COUNT]; extern CRedMemory c_RedMemory; extern volatile u32 m_ChangeStatus; extern CRedDriver c_Driver; diff --git a/include/ffcc/RedSound/RedMemory.h b/include/ffcc/RedSound/RedMemory.h index f14c6e0e52..5e7017543e 100644 --- a/include/ffcc/RedSound/RedMemory.h +++ b/include/ffcc/RedSound/RedMemory.h @@ -1,12 +1,16 @@ #ifndef _FFCC_REDSOUND_REDMEMORY_H #define _FFCC_REDSOUND_REDMEMORY_H -int RedNew(int); -void RedDelete(int); -void RedDelete(void*); -int RedNewA(int, int, int); -void RedDeleteA(int); -void RedDeleteA(void*); +int RedNew(int size); +void RedDelete(int address); +void RedDelete(void* address); +int RedResize(int address, int size); +void* RedResize(void* address, int size); +int RedNewA(int size, int offset, int maxSize); +void RedDeleteA(int address); +void RedDeleteA(void* address); +int RedResizeA(int address, int size); +void* RedResizeA(void* address, int size); struct RedMemoryBlock { int m_address; @@ -14,6 +18,8 @@ struct RedMemoryBlock { }; enum RedMemoryLayoutSize { + REDSOUND_MEMORY_BLOCK_ADDRESS_OFFSET = 0x00, + REDSOUND_MEMORY_BLOCK_SIZE_OFFSET = 0x04, REDSOUND_MEMORY_BANK_BLOCK_COUNT = 0x400, REDSOUND_MEMORY_NEXT_BLOCK_INDEX = 1, REDSOUND_MEMORY_BANK_LAST_INDEX = REDSOUND_MEMORY_BANK_BLOCK_COUNT - 1, @@ -21,8 +27,14 @@ enum RedMemoryLayoutSize { REDSOUND_MEMORY_BANK_ALIGN_MASK = REDSOUND_MEMORY_BANK_ALIGN - 1, REDSOUND_MEMORY_BLOCK_SIZE = sizeof(RedMemoryBlock), REDSOUND_MEMORY_BLOCK_INDEX_SHIFT = 3, + REDSOUND_MEMORY_MAIN_BANK_OFFSET = 0x00, REDSOUND_MEMORY_BANK_SIZE = sizeof(RedMemoryBlock) * REDSOUND_MEMORY_BANK_BLOCK_COUNT, + REDSOUND_MEMORY_BANK_ALLOC_SIZE = 0x2000, + REDSOUND_MEMORY_AUX_BANK_OFFSET = REDSOUND_MEMORY_MAIN_BANK_OFFSET + REDSOUND_MEMORY_BANK_SIZE, REDSOUND_MEMORY_BANK_TABLE_COUNT = 2, + REDSOUND_MEMORY_BANK_TABLE_SIZE = REDSOUND_MEMORY_BANK_SIZE * REDSOUND_MEMORY_BANK_TABLE_COUNT, + REDSOUND_MEMORY_BANK_TABLE_ALLOC_SIZE = 0x4000, + REDSOUND_MEMORY_DATA_BUFFER_OFFSET = REDSOUND_MEMORY_MAIN_BANK_OFFSET + REDSOUND_MEMORY_BANK_TABLE_SIZE, REDSOUND_MEMORY_ALLOC_FAILED = -1, }; diff --git a/include/ffcc/RedSound/RedMidiCtrl.h b/include/ffcc/RedSound/RedMidiCtrl.h index a1c41f6632..c846759a8c 100644 --- a/include/ffcc/RedSound/RedMidiCtrl.h +++ b/include/ffcc/RedSound/RedMidiCtrl.h @@ -10,13 +10,24 @@ enum RedMidiLayoutSize { REDSOUND_KEY_ON_SLOT_COUNT = 0x40, REDSOUND_MUSIC_TRACK_SAVE_COUNT = 0x40, REDSOUND_TRACK_LOOP_STACK_COUNT = 4, + REDSOUND_SWING_FUNCTION_COUNT = 0x10, + REDSOUND_MIDI_CONTROL_FUNCTION_COUNT = 0x80, + REDSOUND_TRACK_RESERVED04_SIZE = 0x04, + REDSOUND_TRACK_RESERVED88_SIZE = 0x04, + REDSOUND_TRACK_RESERVEDA8_SIZE = 0x04, + REDSOUND_TRACK_RESERVED149_SIZE = 0x02, + REDSOUND_TRACK_RESERVED14C_SIZE = 0x01, + REDSOUND_TRACK_RESERVED151_SIZE = 0x03, + REDSOUND_CONTROL_RESERVED04_SIZE = 0x04, + REDSOUND_CONTROL_RESERVED460_SIZE = 0x0C, + REDSOUND_CONTROL_RESERVED493_SIZE = 0x01, }; -typedef int (*RedSwingFunc)(int); +typedef int (*RedSwingFunc)(int phase); struct RedTrackDATA { unsigned char* m_command; - unsigned char m_reserved04[0x08 - 0x04]; + unsigned char m_reserved04[REDSOUND_TRACK_RESERVED04_SIZE]; unsigned char* m_loopCommand[REDSOUND_TRACK_LOOP_STACK_COUNT]; RedWaveHeadWD* m_waveBankData; RedWaveDATA* m_waveData; @@ -46,7 +57,7 @@ struct RedTrackDATA { int m_vibrateRateAdd; int m_vibrateDepth; int m_vibrateDepthAdd; - unsigned char m_reserved88[0x8C - 0x88]; + unsigned char m_reserved88[REDSOUND_TRACK_RESERVED88_SIZE]; short m_vibrateRateDelta; short m_vibrateDepthDelta; short m_vibrateDelay; @@ -56,7 +67,7 @@ struct RedTrackDATA { int m_tremoloRateAdd; int m_tremoloDepth; int m_tremoloDepthAdd; - unsigned char m_reservedA8[0xAC - 0xA8]; + unsigned char m_reservedA8[REDSOUND_TRACK_RESERVEDA8_SIZE]; short m_tremoloRateDelta; short m_tremoloDepthDelta; short m_tremoloDelay; @@ -70,14 +81,7 @@ struct RedTrackDATA { int m_shakePan; short m_shakeRateDelta; short m_shakeDepthDelta; - unsigned short m_adsrAR; - unsigned short m_adsrDR; - unsigned short m_adsrSR; - unsigned short m_adsrRR; - unsigned char m_adsrAL; - unsigned char m_adsrDL; - unsigned char m_adsrSL; - unsigned char m_adsrRL; + RedAdsrDATA m_adsr; int m_fuzzyPitchDepth; int m_fuzzyVolumeDepth; int m_fuzzyPanDepth; @@ -107,20 +111,20 @@ struct RedTrackDATA { short m_loopStepCurrent; short m_seTickCounter; signed char m_fineTune; - unsigned char m_reserved149[0x14B - 0x149]; + unsigned char m_reserved149[REDSOUND_TRACK_RESERVED149_SIZE]; signed char m_pitchBendRange; - unsigned char m_reserved14C[0x14D - 0x14C]; + unsigned char m_reserved14C[REDSOUND_TRACK_RESERVED14C_SIZE]; unsigned char m_waveBankNo; signed char m_trackNo; unsigned char m_eraseTrack; unsigned char m_attrMask; - unsigned char m_reserved151[0x154 - 0x151]; + unsigned char m_reserved151[REDSOUND_TRACK_RESERVED151_SIZE]; }; enum RedTrackAdsrLayout { REDSOUND_TRACK_ADSR_DEFAULT_BYTE = 0xFF, REDSOUND_TRACK_ADSR_DEFAULT_WORD = -1, - REDSOUND_TRACK_ADSR_SIZE = 0x0C, + REDSOUND_TRACK_ADSR_SIZE = REDSOUND_ADSR_DATA_SIZE, REDSOUND_TRACK_ADSR_TIME_ATTACK_HALFWORD = 0x6A, REDSOUND_TRACK_ADSR_TIME_DECAY_HALFWORD = REDSOUND_TRACK_ADSR_TIME_ATTACK_HALFWORD + 1, REDSOUND_TRACK_ADSR_TIME_SUSTAIN_HALFWORD = REDSOUND_TRACK_ADSR_TIME_ATTACK_HALFWORD + 2, @@ -132,6 +136,10 @@ enum RedTrackAdsrLayout { }; enum RedTrackLayoutWord { + REDSOUND_TRACK_COMMAND_WORD_OFFSET = 0x00, + REDSOUND_TRACK_LOOP_COMMAND_WORD_OFFSET = 0x02, + REDSOUND_TRACK_WAVE_BANK_DATA_WORD_OFFSET = 0x06, + REDSOUND_TRACK_KEY_SIGNATURE_DATA_WORD_OFFSET = 0x08, REDSOUND_TRACK_VOLUME_WORD_OFFSET = 0x0A, REDSOUND_TRACK_VOLUME_ADD_WORD_OFFSET = 0x0B, REDSOUND_TRACK_VOLUME_DELTA_WORD_OFFSET = 0x0C, @@ -181,20 +189,48 @@ enum RedTrackLayoutWord { REDSOUND_TRACK_FUZZY_PITCH_DEPTH_WORD_OFFSET = 0x38, REDSOUND_TRACK_FUZZY_VOLUME_DEPTH_WORD_OFFSET = 0x39, REDSOUND_TRACK_FUZZY_PAN_DEPTH_WORD_OFFSET = 0x3A, + REDSOUND_TRACK_FUZZY_DELTA_TIME_DEPTH_WORD_OFFSET = 0x3B, REDSOUND_TRACK_FUZZY_ADSR_DEPTH_WORD_OFFSET = 0x3C, + REDSOUND_TRACK_SE_SEP_ID_WORD_OFFSET = 0x3D, + REDSOUND_TRACK_SE_ID_WORD_OFFSET = 0x3E, REDSOUND_TRACK_FLAGS_WORD_OFFSET = 0x41, + REDSOUND_TRACK_DELTA_TIME_WORD_OFFSET = 0x42, + REDSOUND_TRACK_PLAY_TIME_WORD_OFFSET = 0x43, REDSOUND_TRACK_SWEEP_DELTA_WORD_OFFSET = 0x44, + REDSOUND_TRACK_SWEEP_ADD_WORD_OFFSET = 0x45, REDSOUND_TRACK_PORTAMENT_TIME_WORD_OFFSET = 0x46, + REDSOUND_TRACK_WAVE_BASE_WORD_OFFSET = 0x47, REDSOUND_TRACK_PORTAMENT_PITCH_WORD_OFFSET = 0x48, + REDSOUND_TRACK_PORTAMENT_PITCH_NONE = -1, + REDSOUND_TRACK_WAVE_NO_WORD_OFFSET = 0x49, }; enum RedTrackLayoutHalfword { + REDSOUND_TRACK_LOOP_COUNT_HALFWORD = 0x94, + REDSOUND_TRACK_LOOP_STEP_HALFWORD = 0x98, + REDSOUND_TRACK_STEP_HALFWORD = 0x9C, + REDSOUND_TRACK_STEP2_HALFWORD = 0x9D, + REDSOUND_TRACK_LOOP_DEPTH_HALFWORD = 0x9E, REDSOUND_TRACK_PITCH_BEND_HALFWORD = 0x9F, + REDSOUND_TRACK_PITCH_BEND_RAW_HALFWORD = 0xA0, REDSOUND_TRACK_KEY_TRANSPOSE_HALFWORD = 0xA1, + REDSOUND_TRACK_LOOP_STEP_CURRENT_HALFWORD = 0xA2, + REDSOUND_TRACK_SE_TICK_COUNTER_HALFWORD = 0xA3, }; enum RedTrackLayoutByte { + REDSOUND_TRACK_RESERVED04_BYTE = 0x04, + REDSOUND_TRACK_RESERVED88_BYTE = 0x88, + REDSOUND_TRACK_RESERVEDA8_BYTE = 0xA8, REDSOUND_TRACK_FINE_TUNE_BYTE = 0x148, + REDSOUND_TRACK_RESERVED149_BYTE = 0x149, + REDSOUND_TRACK_PITCH_BEND_RANGE_BYTE = 0x14B, + REDSOUND_TRACK_RESERVED14C_BYTE = 0x14C, + REDSOUND_TRACK_WAVE_BANK_NO_BYTE = 0x14D, + REDSOUND_TRACK_TRACK_NO_BYTE = 0x14E, + REDSOUND_TRACK_ERASE_TRACK_BYTE = 0x14F, + REDSOUND_TRACK_ATTR_MASK_BYTE = 0x150, + REDSOUND_TRACK_RESERVED151_BYTE = 0x151, }; enum RedTrackWordLayout { @@ -212,6 +248,8 @@ enum RedTrackWordLayout { enum RedKeySignatureLayout { REDSOUND_KEY_SIGNATURE_INDEX_MASK = 0x1F, + REDSOUND_KEY_SIGNATURE_INDEX_COUNT = REDSOUND_KEY_SIGNATURE_INDEX_MASK + 1, + REDSOUND_KEY_SIGNATURE_DATA_COUNT = 0x2E, REDSOUND_KEY_SIGNATURE_DEFAULT_OFFSET = 0x0B, }; @@ -226,6 +264,13 @@ struct RedKeyOnSlot { RedNoteDATA m_note; }; +enum RedKeyOnSlotLayout { + REDSOUND_KEY_ON_SLOT_TRACK_OFFSET = 0x00, + REDSOUND_KEY_ON_SLOT_NOTE_OFFSET = 0x04, + REDSOUND_KEY_ON_SLOT_SIZE = 0x08, + REDSOUND_KEY_ON_SLOT_WORD_COUNT = REDSOUND_KEY_ON_SLOT_SIZE / sizeof(int), +}; + struct RedKeyOnDATA { RedKeyOnSlot m_fixed[REDSOUND_KEY_ON_SLOT_COUNT]; RedKeyOnSlot m_priority[REDSOUND_KEY_ON_SLOT_COUNT]; @@ -244,9 +289,30 @@ enum RedKeyOnByteOffset { REDSOUND_KEY_ON_END_BYTE_OFFSET = REDSOUND_KEY_ON_TOTAL_WORD_COUNT * sizeof(int), }; +struct RedSoundControlPosition { + int m_measure; + int m_tick; + int m_ticksPerMeasure; + short m_timeNumerator; + short m_timeDenominator; +}; + +struct RedSoundControlTempo { + int m_tempo; + int m_tempoAdd; + int m_tempoDelta; +}; + +struct RedSavedTrackDATA { + unsigned char* m_command[REDSOUND_MUSIC_TRACK_SAVE_COUNT]; + int m_delta[REDSOUND_MUSIC_TRACK_SAVE_COUNT]; + unsigned int m_flags[REDSOUND_MUSIC_TRACK_SAVE_COUNT]; + RedNoteDATA m_note[REDSOUND_MUSIC_TRACK_SAVE_COUNT]; +}; + struct RedSoundCONTROL { RedTrackDATA* m_tracks; - unsigned char m_reserved04[0x08 - 0x04]; + unsigned char m_reserved04[REDSOUND_CONTROL_RESERVED04_SIZE]; signed char* m_keySignatureData; int m_measure; int m_tick; @@ -256,25 +322,17 @@ struct RedSoundCONTROL { int m_volume; int m_volumeAdd; int m_volumeDelta; - unsigned char* m_savedCommand[REDSOUND_MUSIC_TRACK_SAVE_COUNT]; - int m_savedDelta[REDSOUND_MUSIC_TRACK_SAVE_COUNT]; - unsigned int m_savedFlags[REDSOUND_MUSIC_TRACK_SAVE_COUNT]; - RedNoteDATA m_savedNote[REDSOUND_MUSIC_TRACK_SAVE_COUNT]; - int m_savedTempo; - int m_savedTempoAdd; - int m_savedTempoDelta; + RedSavedTrackDATA m_savedTracks; + RedSoundControlTempo m_savedTempo; int m_savedActiveTrackCount; - int m_savedMeasure; - int m_savedTick; - int m_savedTicksPerMeasure; - int m_savedTimeSignature; + RedSoundControlPosition m_savedPosition; int m_tempo; int m_tempoAdd; int m_tempoDelta; int m_masterVolume; int m_masterVolumeAdd; int m_masterVolumeDelta; - unsigned char m_reserved460[0x46C - 0x460]; + unsigned char m_reserved460[REDSOUND_CONTROL_RESERVED460_SIZE]; unsigned int m_flags; int m_musicId; int m_skipFrames; @@ -299,6 +357,13 @@ enum RedSoundControlFlag { REDSOUND_CONTROL_FLAG_CLEAR_STOP_ON_VOLUME_ZERO_MASK = ~REDSOUND_CONTROL_FLAG_STOP_ON_VOLUME_ZERO, }; +enum RedSoundControlDefault { + REDSOUND_CONTROL_INITIAL_TICK_COUNTER = 1, + REDSOUND_CONTROL_DEFAULT_TICKS_PER_MEASURE = 10000, + REDSOUND_CONTROL_INITIAL_TICK = -1, + REDSOUND_CONTROL_INITIAL_MEASURE = 1, +}; + enum RedSoundControlWordOffset { REDSOUND_CONTROL_MEASURE_WORD_OFFSET = 0x03, REDSOUND_CONTROL_SAVED_COMMAND_WORD_OFFSET = 0x0A, @@ -313,6 +378,31 @@ enum RedSoundControlWordOffset { REDSOUND_CONTROL_TEMPO_WORD_OFFSET = 0x112, }; +enum RedSoundControlByteOffset { + REDSOUND_CONTROL_TRACKS_OFFSET = 0x00, + REDSOUND_CONTROL_RESERVED04_OFFSET = 0x04, + REDSOUND_CONTROL_KEY_SIGNATURE_DATA_OFFSET = 0x08, + REDSOUND_CONTROL_TICK_OFFSET = 0x10, + REDSOUND_CONTROL_TICKS_PER_MEASURE_OFFSET = 0x14, + REDSOUND_CONTROL_TIME_NUMERATOR_OFFSET = 0x18, + REDSOUND_CONTROL_TIME_DENOMINATOR_OFFSET = 0x1A, + REDSOUND_CONTROL_VOLUME_OFFSET = 0x1C, + REDSOUND_CONTROL_RESERVED460_OFFSET = 0x460, + REDSOUND_CONTROL_FLAGS_OFFSET = 0x46C, + REDSOUND_CONTROL_SKIP_FRAMES_OFFSET = 0x474, + REDSOUND_CONTROL_ELAPSED_TIME_OFFSET = 0x478, + REDSOUND_CONTROL_WAVE_NO_OFFSET = 0x47C, + REDSOUND_CONTROL_KEY_SIGNATURE_OFFSET = 0x480, + REDSOUND_CONTROL_LOOP_BASE_OFFSET = 0x484, + REDSOUND_CONTROL_UPDATE_FLAGS_OFFSET = 0x488, + REDSOUND_CONTROL_TICK_COUNTER_OFFSET = 0x48C, + REDSOUND_CONTROL_ACTIVE_TRACK_COUNT_OFFSET = 0x48E, + REDSOUND_CONTROL_CHANNEL_ALLOC_OFFSET = 0x490, + REDSOUND_CONTROL_TRACK_COUNT_OFFSET = 0x491, + REDSOUND_CONTROL_VOLUME_SCALE_OFFSET = 0x492, + REDSOUND_CONTROL_RESERVED493_OFFSET = 0x493, +}; + enum RedSoundControlBufferOffset { REDSOUND_CONTROL_WORD_COUNT = 0x125, REDSOUND_CONTROL_SECONDARY_TRACKS_WORD_OFFSET = 0x125, @@ -324,17 +414,34 @@ enum RedSoundControlBufferOffset { }; enum RedSoundControlSaveSize { - REDSOUND_CONTROL_SAVED_POSITION_SIZE = sizeof(int) * 4, - REDSOUND_CONTROL_SAVED_TEMPO_SIZE = sizeof(int) * 3, + REDSOUND_CONTROL_SAVED_POSITION_WORD_COUNT = 4, + REDSOUND_CONTROL_SAVED_POSITION_ALLOC_SIZE = 0x10, + REDSOUND_CONTROL_SAVED_POSITION_SIZE = sizeof(RedSoundControlPosition), + REDSOUND_CONTROL_SAVED_TEMPO_WORD_COUNT = 3, + REDSOUND_CONTROL_SAVED_TEMPO_ALLOC_SIZE = 0x0C, + REDSOUND_CONTROL_SAVED_TEMPO_SIZE = sizeof(RedSoundControlTempo), +}; + +typedef void (*RedMidiControlFunc)(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); + +class CRedMidiCtrl +{ +public: + CRedMidiCtrl(); + ~CRedMidiCtrl(); + + void Init(); + +private: + int m_status[3]; }; -typedef void (*RedMidiControlFunc)(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -int DataAddCompute(int*, int, int*); -void KeyOnReserveClear(RedKeyOnDATA*, RedTrackDATA*); -void KeyOnReserve(RedKeyOnDATA*, RedTrackDATA*); -void KeyOffSet(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); +int DataAddCompute(int* current, int target, int* delta); +void KeyOnReserveClear(RedKeyOnDATA* keyOnData, RedTrackDATA* track); +void KeyOnReserve(RedKeyOnDATA* keyOnData, RedTrackDATA* track); +void KeyOffSet(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); -extern RedMidiControlFunc p_MidiControl_Function[]; -extern RedSwingFunc SwingEntryFunction[]; +extern RedMidiControlFunc p_MidiControl_Function[REDSOUND_MIDI_CONTROL_FUNCTION_COUNT]; +extern RedSwingFunc SwingEntryFunction[REDSOUND_SWING_FUNCTION_COUNT]; #endif // _FFCC_REDSOUND_REDMIDICTRL_H diff --git a/include/ffcc/RedSound/RedSound.h b/include/ffcc/RedSound/RedSound.h index e63453dff7..9776f3f479 100644 --- a/include/ffcc/RedSound/RedSound.h +++ b/include/ffcc/RedSound/RedSound.h @@ -1,6 +1,22 @@ #ifndef _FFCC_REDSOUND_REDSOUND_H #define _FFCC_REDSOUND_REDSOUND_H +#ifndef FFCC_REDSOUND_DMA_CALLBACK_TYPEDEF +#define FFCC_REDSOUND_DMA_CALLBACK_TYPEDEF +typedef void (*RedDmaCallback)(void* callbackData); +#endif + +struct RedAdsrDATA; +struct RedMemoryBlock; +struct RedSoundCONTROL; +struct RedWaveHeadWD; +struct RedReverbDepth; +struct RedReverbModeData; +struct RedReverbSize; +struct RedStreamDATA; +struct RedTrackDATA; +struct RedVoiceDATA; + class CRedSound { public: @@ -13,39 +29,65 @@ class CRedSound void Start(); void End(); int GetProgramTime(); + int GetMasterTime(); + void Sleep(int microseconds); void ReportPrint(int enable); int ReportStandby(int entryId); - int DMAEntry(int flags, int direction, int mainMemory, int aramMemory, int size, void (*callback)(void*), void* callbackData); + int DMAEntry(int flags, int direction, int mainMemory, int aramMemory, int size, + RedDmaCallback callback, void* callbackData); int DMACheck(int id); + void SetDMAMode(int mode); void SetSoundMode(int soundMode); int GetSoundMode(); void SetReverb(int kind, int mode); - void SetReverbDepth(int type, int depth, int frameCount); + void SetReverb(int kind, int mode, int* params); + RedReverbSize* GetReverbInfo(); + RedReverbDepth* GetReverbDepth(); + void SetReverbDepth(int bank, int depth, int frameCount); + void SetMute(unsigned int voiceNo, unsigned int mute); + RedReverbModeData* GetReverbModeTable(int mode); void SetMusicData(void* musicData); int ReentryMusicData(int musicId); + void ClearMusicData(int musicId); + int MusicPlayState(int musicId); + int CheckMusicEntry(int musicId); void MusicStop(int musicId); void MusicPlay(int musicId, int volume, int mode); + void MusicPlay(void* musicData, int volume, int mode); void MusicCrossPlay(int musicId, int volume, int mode); + void MusicCrossPlay(void* musicData, int volume, int mode); void MusicNextPlay(int musicId, int volume, int mode); + void MusicNextPlay(void* musicData, int volume, int mode); void MusicMasterVolume(int volume); void MusicFadeOut(int musicId, int frameCount); void MusicVolume(int musicId, int volume, int frameCount); + void MusicTempo(int tempo, int frameCount); + void MusicPitch(int pitch, int frameCount); + void MusicPause(int musicId, int pause); void SetMusicPhraseStop(int enable); + void SetMusicFastSpeed(int speed); + int CheckMusicPhraseStop(); + void DisplayMusicInfo(); - void SetSeBlockData(int bank, void* data); - void SetSeSepData(void* data); + void SetSeBlockData(int bank, void* blockData); + void SetSeSepData(void* seSepData); void ClearSeSepData(int sepId); void ClearSeSepDataMG(int bank, int sep, int group, int kind); int ReentrySeSepData(int sepId); int SePlayState(int seId); void SeStop(int seId); + void SeStopG(int group); void SeStopMG(int bank, int sep, int group, int kind); int SePlay(int bank, int sep, int pan, int volume, int pitch); + int SePlay(void* seSepData, int pan, int volume, int pitch); + int CheckSeSepEntry(int sepId); + int GetSeUsedWave(int bank, int seNo); + int GetSeUsedWave(void* seSepData); void SeMasterVolume(int volume); void SeFadeOut(int seId, int frameCount); void SeVolume(int seId, int volume, int frameCount); @@ -55,20 +97,45 @@ class CRedSound int GetSeVolume(int seId, int mode); int ReportSeLoop(int seId); void DisplaySePlayInfo(); + void ClearSePlayLine(); + RedTrackDATA* GetSePlayTrack(); int StreamPlayState(int streamId); - void GetStreamPlayPoint(int streamId, int* current, int* total); + void GetStreamPlayPoint(int streamId, int* playPoint, int* readPoint); + RedStreamDATA* GetStreamPlayBlock(int streamId); + int StreamStandby(void* streamHeader, int fileSize); + void GetStreamReadPoint(int streamId, int* readPoint); void StreamStop(int streamId); int StreamPlay(void* streamHeader, int fileSize, int pan, int volume); + int StreamPlay(int streamId, int pan, int volume); void StreamVolume(int streamId, int volume, int frameCount); + void StreamPan(int streamId, int pan, int frameCount); void StreamPause(int streamId, int pause); - unsigned int SetWaveData(int bank, void* data, int size); + unsigned int SetWaveData(int waveID, void* waveData, int waveSize); void ClearWaveData(int waveNo); void ClearWaveDataM(int waveNo0, int waveNo1, int waveNo2, int waveNo3); void ClearWaveBank(int bank); int ReentryWaveData(int waveNo); + RedWaveHeadWD* GetWaveInfo(int waveNo); + int CheckWaveEntry(int waveNo); void DisplayWaveInfo(); + int SearchWaveSequence(int waveNo); + void DisplayMMemoryInfo(); + void GetMakeTime(char** date, char** time); + int GetMainBufferAddress(); + int GetMainBufferSize(); + RedMemoryBlock* GetMainBankAddress(); + int GetABufferAddress(); + RedMemoryBlock* GetABankAddress(); + RedSoundCONTROL* GetControlAddress(); + RedVoiceDATA* GetVoiceAddress(); + int PlayWaveItem(int waveNo, int itemNo, int key, int pan, int volume); + void StopWaveItem(); + int WavePitchCompute(int key, int pitch); + void SetWaveTune(int key, int fineTune); + void SetWavePitch(int pitch); + void SetWaveAdsr(int attack, RedAdsrDATA* adsr); void TestProcess(int mode); }; diff --git a/include/ffcc/RedSound/RedStream.h b/include/ffcc/RedSound/RedStream.h index 0c91992b66..2235fab903 100644 --- a/include/ffcc/RedSound/RedStream.h +++ b/include/ffcc/RedSound/RedStream.h @@ -9,13 +9,40 @@ struct RedVoiceDATA; enum RedStreamFileLayoutSize { REDSOUND_STREAM_SIGNATURE_SIZE = 4, - REDSOUND_STREAM_HEADER_PAD_SIZE = 0x0C - 0x04, + REDSOUND_STREAM_PAGE_SIZE = 0x1000, REDSOUND_STREAM_TRACK_DATA_COUNT = 2, }; +enum RedStreamSignature { + REDSOUND_STREAM_SIGNATURE_0 = 'S', + REDSOUND_STREAM_SIGNATURE_1 = 'T', + REDSOUND_STREAM_SIGNATURE_2 = 'R', +}; + +enum RedStreamHeadLayoutOffset { + REDSOUND_STREAM_HEAD_SIGNATURE_OFFSET = 0x00, + REDSOUND_STREAM_HEAD_RESERVED04_OFFSET = 0x04, + REDSOUND_STREAM_HEAD_LOOP_END_OFFSET = 0x0C, + REDSOUND_STREAM_HEAD_LOOP_START_OFFSET = 0x10, + REDSOUND_STREAM_HEAD_PITCH_OFFSET = 0x14, + REDSOUND_STREAM_HEAD_RESERVED18_OFFSET = 0x18, + REDSOUND_STREAM_HEAD_CHANNEL_COUNT_OFFSET = 0x1A, + REDSOUND_STREAM_HEAD_FLAGS_OFFSET = 0x1C, + REDSOUND_STREAM_HEAD_RESERVED1E_OFFSET = 0x1E, + REDSOUND_STREAM_HEAD_SIZE = 0x20, +}; + +enum RedStreamHeadLayoutSize { + REDSOUND_STREAM_HEAD_RESERVED04_SIZE = + REDSOUND_STREAM_HEAD_LOOP_END_OFFSET - REDSOUND_STREAM_HEAD_RESERVED04_OFFSET, + REDSOUND_STREAM_HEAD_RESERVED18_SIZE = + REDSOUND_STREAM_HEAD_CHANNEL_COUNT_OFFSET - REDSOUND_STREAM_HEAD_RESERVED18_OFFSET, + REDSOUND_STREAM_HEAD_RESERVED1E_SIZE = REDSOUND_STREAM_HEAD_SIZE - REDSOUND_STREAM_HEAD_RESERVED1E_OFFSET, +}; + struct RedStreamHEAD { char m_signature[REDSOUND_STREAM_SIGNATURE_SIZE]; - u8 m_reserved04[REDSOUND_STREAM_HEADER_PAD_SIZE]; + u8 m_reserved04[REDSOUND_STREAM_HEAD_RESERVED04_SIZE]; int m_loopEnd; int m_loopStart; int m_pitch; @@ -25,12 +52,64 @@ struct RedStreamHEAD { s16 m_reserved1E; }; +struct RedStreamADPCMHeader { + AXPBADPCM m_data; + AXPBADPCMLOOP m_loop; +}; + +enum RedStreamAdpcmHeaderLayoutOffset { + REDSOUND_STREAM_ADPCM_DATA_OFFSET = 0x00, + REDSOUND_STREAM_ADPCM_LOOP_OFFSET = 0x28, + REDSOUND_STREAM_ADPCM_HEADER_SIZE = 0x2E, + REDSOUND_STREAM_ADPCM_DATA_SIZE = REDSOUND_STREAM_ADPCM_LOOP_OFFSET - REDSOUND_STREAM_ADPCM_DATA_OFFSET, + REDSOUND_STREAM_ADPCM_LOOP_SIZE = REDSOUND_STREAM_ADPCM_HEADER_SIZE - REDSOUND_STREAM_ADPCM_LOOP_OFFSET, +}; + +enum RedStreamFileLayoutOffset { + REDSOUND_STREAM_FILE_HEAD_OFFSET = 0x00, + REDSOUND_STREAM_FILE_ADPCM_OFFSET = 0x20, + REDSOUND_STREAM_FILE_ADPCM_COUNT = REDSOUND_STREAM_TRACK_DATA_COUNT, + REDSOUND_STREAM_FILE_ADPCM_END = + REDSOUND_STREAM_FILE_ADPCM_OFFSET + REDSOUND_STREAM_ADPCM_HEADER_SIZE * REDSOUND_STREAM_FILE_ADPCM_COUNT, + REDSOUND_STREAM_FILE_TRAILING_PAD_OFFSET = REDSOUND_STREAM_FILE_ADPCM_END, + REDSOUND_STREAM_FILE_AUDIO_OFFSET = REDSOUND_STREAM_PAGE_SIZE, + REDSOUND_STREAM_FILE_TRAILING_PAD_SIZE = REDSOUND_STREAM_FILE_AUDIO_OFFSET - REDSOUND_STREAM_FILE_TRAILING_PAD_OFFSET, + REDSOUND_STREAM_FILE_SIZE = REDSOUND_STREAM_FILE_ADPCM_END + REDSOUND_STREAM_FILE_TRAILING_PAD_SIZE, +}; + +struct RedStreamFile { + RedStreamHEAD m_header; + RedStreamADPCMHeader m_adpcm[REDSOUND_STREAM_FILE_ADPCM_COUNT]; + u8 m_trailingPadding[REDSOUND_STREAM_FILE_TRAILING_PAD_SIZE]; +}; + +struct RedStreamStepData { + int m_value; + int m_step; + int m_stepCount; +}; + +enum RedStreamStepDataLayoutOffset { + REDSOUND_STREAM_STEP_VALUE_OFFSET = 0x00, + REDSOUND_STREAM_STEP_STEP_OFFSET = 0x04, + REDSOUND_STREAM_STEP_COUNT_OFFSET = 0x08, +}; + +enum RedStreamStepDataLayoutSize { + REDSOUND_STREAM_STEP_DATA_SIZE = 0x0C, +}; + enum RedStreamState { REDSOUND_STREAM_STATE_STOPPED = 0, REDSOUND_STREAM_STATE_PLAYING = 1, REDSOUND_STREAM_STATE_LOADING = 3, }; +enum RedStreamId { + REDSOUND_STREAM_ID_NONE = 0, + REDSOUND_STREAM_ID_ALL = -1, +}; + enum RedStreamHeaderFlag { REDSOUND_STREAM_HEADER_REVERB_NONE = 0, }; @@ -42,13 +121,9 @@ struct RedStreamDATA { u8* m_buffer; RedStreamHEAD m_header; RedWaveDATA m_trackData[REDSOUND_STREAM_TRACK_DATA_COUNT]; - int m_volume; - int m_volumeStep; - int m_volumeStepCount; + RedStreamStepData m_volume; int m_reservedFC; - int m_pan; - int m_panStep; - int m_panStepCount; + RedStreamStepData m_pan; int m_streamId; int m_state; int m_dmaId; @@ -68,11 +143,17 @@ enum RedStreamDataLayoutOffset { REDSOUND_STREAM_HEADER_OFFSET = 0x10, REDSOUND_STREAM_TRACK_DATA_OFFSET = 0x30, REDSOUND_STREAM_VOLUME_OFFSET = 0xF0, + REDSOUND_STREAM_VOLUME_STEP_OFFSET = 0xF4, + REDSOUND_STREAM_VOLUME_STEP_COUNT_OFFSET = 0xF8, + REDSOUND_STREAM_RESERVED_FC_OFFSET = 0xFC, REDSOUND_STREAM_PAN_OFFSET = 0x100, + REDSOUND_STREAM_PAN_STEP_OFFSET = 0x104, + REDSOUND_STREAM_PAN_STEP_COUNT_OFFSET = 0x108, REDSOUND_STREAM_ID_OFFSET = 0x10C, REDSOUND_STREAM_STATE_OFFSET = 0x110, REDSOUND_STREAM_DMA_ID_OFFSET = 0x114, REDSOUND_STREAM_FILE_SIZE_OFFSET = 0x118, + REDSOUND_STREAM_FILE_CURSOR_OFFSET = 0x11C, REDSOUND_STREAM_READ_OFFSET = 0x120, REDSOUND_STREAM_CURSOR_OFFSET = 0x124, REDSOUND_STREAM_CURSOR_BASE_OFFSET = 0x128, @@ -80,13 +161,15 @@ enum RedStreamDataLayoutOffset { }; enum RedStreamDataLayoutSize { - REDSOUND_STREAM_DATA_SIZE = 0x130, + REDSOUND_STREAM_RESERVED_FC_SIZE = REDSOUND_STREAM_PAN_OFFSET - REDSOUND_STREAM_RESERVED_FC_OFFSET, + REDSOUND_STREAM_DATA_SIZE = sizeof(RedStreamDATA), }; -void StreamStop(int); -int StreamPlay(int, void*, int, int, int); -void SetStreamVolume(int, int, int); -void StreamPause(int, int); +void StreamStop(int streamId); +int StreamPlay(int streamId, void* streamHeader, int fileSize, int pan, int volume); +void SetStreamVolume(int streamId, int volume, int frameCount); +void SetStreamPan(int streamId, int pan, int frameCount); +void StreamPause(int streamId, int pause); void StreamControl(); #endif // _FFCC_REDSOUND_REDSTREAM_H diff --git a/src/MenuUtil.cpp b/src/MenuUtil.cpp index f95945a96b..06e97500df 100644 --- a/src/MenuUtil.cpp +++ b/src/MenuUtil.cpp @@ -3,6 +3,7 @@ #include "ffcc/game.h" #include "ffcc/pad.h" #include "ffcc/sound.h" +#include "ffcc/RedSound/RedSound.h" #include #include "ffcc/fontman.h" #include @@ -10,7 +11,6 @@ extern CMenuPcs MenuPcs; extern "C" void pppDeletePart__8CPartMngFi(void*, int); extern "C" short BindEffect__8CMenuPcsFiii(CMenuPcs*, int, int, int); -extern "C" unsigned int GetSoundMode__9CRedSoundFv(void*); extern "C" void* __nwa__FUlPQ27CMemory6CStagePci(unsigned long, void*, char*, int); extern "C" void __dla__FPv(void*); extern "C" char* strcat(char*, const char*); @@ -194,6 +194,11 @@ static inline int* GetMenuHelpMsgTable() { return reinterpret_cast(reinterpret_cast(&Game.m_cFlatDataArr[1])->table[6].index); } + +static inline CRedSound* GetRedSoundGlobal() +{ + return reinterpret_cast(reinterpret_cast(&Sound) + 8); +} } static inline unsigned short GetMenuPress() @@ -702,7 +707,7 @@ void CMenuPcs::GetOptionData() gameInitMode = static_cast(static_cast(__cntlzw(static_cast(Game.m_gameWork.m_gameInitFlag))) >> 5); - unsigned int soundMode = GetSoundMode__9CRedSoundFv(reinterpret_cast(&Sound) + 8); + unsigned int soundMode = GetRedSoundGlobal()->GetSoundMode(); unsigned int soundModeClz = static_cast(__cntlzw(soundMode)); stereoMode = static_cast(static_cast(__cntlzw(soundModeClz >> 5)) >> 5); diff --git a/src/RedSound/RedCommand.cpp b/src/RedSound/RedCommand.cpp index 30c15fe0f2..9f64ba1755 100644 --- a/src/RedSound/RedCommand.cpp +++ b/src/RedSound/RedCommand.cpp @@ -4,6 +4,7 @@ #include "ffcc/RedSound/RedGlobals.h" #include "ffcc/RedSound/RedMemory.h" #include "ffcc/RedSound/RedMidiCtrl.h" +#include "global.h" #include #include @@ -19,6 +20,27 @@ static const char sRedCommandMusicNeedMemoryFmt[] = "%s%s : music%3.3 static const char sRedCommandMusicPauseOnFmt[] = "%sPause : Music : ON %d\n"; static const char sRedCommandMusicPauseOffFmt[] = "%sPause : Music : OFF %d\n"; +enum RedCommandStringLayout { + REDSOUND_COMMAND_WARN_COLOR_SIZE = 0x08, + REDSOUND_COMMAND_RESET_SIZE = 0x05, + REDSOUND_COMMAND_ERROR_COLOR_SIZE = 0x08, + REDSOUND_COMMAND_WAVE_NOT_ENTRY_FMT_SIZE = 0x26, + REDSOUND_COMMAND_LOG_PREFIX_SIZE = 0x12, + REDSOUND_COMMAND_SE_PAUSE_ON_FMT_SIZE = 0x1B, + REDSOUND_COMMAND_SE_PAUSE_OFF_FMT_SIZE = 0x1B, + REDSOUND_COMMAND_MUSIC_TRACK_CREATE_ERROR_FMT_SIZE = 0x2C, + REDSOUND_COMMAND_MUSIC_NEED_MEMORY_FMT_SIZE = 0x33, + REDSOUND_COMMAND_MUSIC_PAUSE_ON_FMT_SIZE = 0x1B, + REDSOUND_COMMAND_MUSIC_PAUSE_OFF_FMT_SIZE = 0x1B, + REDSOUND_COMMAND_RODATA_STRING_SIZE = 0x103, + REDSOUND_COMMAND_SDATA2_STRING_SIZE = 0x15, +}; + +enum RedCommandDataLayout { + REDSOUND_COMMAND_REVERB_MODE_TABLE_OFFSET = 0x00, + REDSOUND_COMMAND_DATA_TABLE_SIZE = 0xE0, +}; + enum RedCommandEraseTrack { REDSOUND_ERASE_TRACK_SENTINEL = 0x100, REDSOUND_SEP_DIRECT_PLAY_ID = 1000000, @@ -42,7 +64,45 @@ enum RedSeInfoSequenceByte { REDSOUND_SE_INFO_SEQUENCE_OFFSET_HI = 1, }; -RedReverbModeData t_ReverbModeData[] = { +STATIC_ASSERT(offsetof(RedReverbModeData, m_kind) == REDSOUND_REVERB_MODE_KIND_OFFSET); +STATIC_ASSERT(offsetof(RedReverbModeData, m_params) == REDSOUND_REVERB_MODE_PARAMS_OFFSET); +STATIC_ASSERT(sizeof(t_ReverbModeData[0].m_params) == REDSOUND_REVERB_MODE_PARAMS_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_REVERB_MODE_PARAMS_SIZE == REDSOUND_REVERB_MODE_PARAMS_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_REVERB_MODE_PARAMS_OFFSET + REDSOUND_REVERB_MODE_PARAMS_SIZE == REDSOUND_REVERB_MODE_SIZE); +STATIC_ASSERT(sizeof(RedReverbModeData) == REDSOUND_REVERB_MODE_SIZE); +STATIC_ASSERT(REDSOUND_REVERB_MODE_TABLE_SIZE == REDSOUND_REVERB_MODE_TABLE_ALLOC_SIZE); +STATIC_ASSERT(sizeof(t_ReverbModeData) == REDSOUND_REVERB_MODE_TABLE_SIZE); +STATIC_ASSERT(REDSOUND_COMMAND_REVERB_MODE_TABLE_OFFSET + sizeof(t_ReverbModeData) == + REDSOUND_COMMAND_DATA_TABLE_SIZE); +STATIC_ASSERT(REDSOUND_COMMAND_DATA_TABLE_SIZE == REDSOUND_REVERB_MODE_TABLE_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_MUSIC_TRACK_BLOCK_SIZE_BYTE0 == REDSOUND_MUSIC_TRACK_BLOCK_SIZE_LO_OFFSET); +STATIC_ASSERT(REDSOUND_MUSIC_TRACK_BLOCK_SIZE_BYTE1 == REDSOUND_MUSIC_TRACK_BLOCK_SIZE_HI0_OFFSET); +STATIC_ASSERT(REDSOUND_MUSIC_TRACK_BLOCK_SIZE_BYTE2 == REDSOUND_MUSIC_TRACK_BLOCK_SIZE_HI1_OFFSET); +STATIC_ASSERT(REDSOUND_MUSIC_TRACK_BLOCK_SIZE_BYTE3 == REDSOUND_MUSIC_TRACK_BLOCK_SIZE_HI2_OFFSET); +STATIC_ASSERT(REDSOUND_MUSIC_TRACK_BLOCK_SIZE_FIELD_SIZE == REDSOUND_MUSIC_TRACK_BLOCK_COMMAND_OFFSET); +STATIC_ASSERT(REDSOUND_SE_INFO_SEQUENCE_OFFSET_LO == REDSOUND_SE_INFO_SEQUENCE_OFFSET_LO_OFFSET); +STATIC_ASSERT(REDSOUND_SE_INFO_SEQUENCE_OFFSET_HI == REDSOUND_SE_INFO_SEQUENCE_OFFSET_HI_AND_FLAGS_OFFSET); +STATIC_ASSERT(sizeof(sRedCommandLogWarnColor) == REDSOUND_COMMAND_WARN_COLOR_SIZE); +STATIC_ASSERT(sizeof(sRedCommandLogReset) == REDSOUND_COMMAND_RESET_SIZE); +STATIC_ASSERT(sizeof(sRedCommandLogErrorColor) == REDSOUND_COMMAND_ERROR_COLOR_SIZE); +STATIC_ASSERT(sizeof(sRedCommandWaveNotEntryFmt) == REDSOUND_COMMAND_WAVE_NOT_ENTRY_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedCommandLogPrefix) == REDSOUND_COMMAND_LOG_PREFIX_SIZE); +STATIC_ASSERT(sizeof(sRedCommandSePauseOnFmt) == REDSOUND_COMMAND_SE_PAUSE_ON_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedCommandSePauseOffFmt) == REDSOUND_COMMAND_SE_PAUSE_OFF_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedCommandMusicTrackCreateErrorFmt) == REDSOUND_COMMAND_MUSIC_TRACK_CREATE_ERROR_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedCommandMusicNeedMemoryFmt) == REDSOUND_COMMAND_MUSIC_NEED_MEMORY_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedCommandMusicPauseOnFmt) == REDSOUND_COMMAND_MUSIC_PAUSE_ON_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedCommandMusicPauseOffFmt) == REDSOUND_COMMAND_MUSIC_PAUSE_OFF_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedCommandWaveNotEntryFmt) + sizeof(sRedCommandLogPrefix) + + sizeof(sRedCommandSePauseOnFmt) + sizeof(sRedCommandSePauseOffFmt) + + sizeof(sRedCommandMusicTrackCreateErrorFmt) + sizeof(sRedCommandMusicNeedMemoryFmt) + + sizeof(sRedCommandMusicPauseOnFmt) + sizeof(sRedCommandMusicPauseOffFmt) == + REDSOUND_COMMAND_RODATA_STRING_SIZE); +STATIC_ASSERT(sizeof(sRedCommandLogWarnColor) + sizeof(sRedCommandLogReset) + + sizeof(sRedCommandLogErrorColor) == + REDSOUND_COMMAND_SDATA2_STRING_SIZE); + +RedReverbModeData t_ReverbModeData[REDSOUND_REVERB_MODE_COUNT] = { {REDSOUND_REVERB_KIND_HI, {0xA, 0x578, 0x1E, 0x46, 0x64, 0x0}}, {REDSOUND_REVERB_KIND_HI, {0x14, 0x708, 0x1E, 0x50, 0x64, 0x0}}, {REDSOUND_REVERB_KIND_HI, {0x1E, 0x960, 0x1E, 0x50, 0x64, 0x0}}, @@ -53,10 +113,11 @@ RedReverbModeData t_ReverbModeData[] = { {REDSOUND_REVERB_KIND_HI, {0x28, 0x9C4, 0x32, 0x50, 0x64, 0x0}}, }; -static void _EraseAttribute(int, int); -static int _EraseTime(int); -static int _SePlayStart(RedSeINFO*, int, int, int, int); -static RedTrackDATA* _MusicPlayStart(RedMusicHEAD*, RedWaveHeadWD*, int, int, int); +static void _EraseAttribute(int eraseTrack, int attrMask); +static int _EraseTime(int eraseTrack); +static int _SePlayStart(RedSeINFO* info, int seId, int sepId, int pan, int volume); +static RedTrackDATA* _MusicPlayStart(RedMusicHEAD* musicHead, RedWaveHeadWD* waveHead, int musicId, int volume, + int mode); /* * --INFO-- @@ -78,22 +139,21 @@ static void _EraseAttribute(int eraseTrack, int attrMask) int trackNo; KeyOnReserveClear(p_KeyOnData, track); - track->m_seId = 0; + track->m_seId = REDSOUND_SE_ID_NONE; track->m_flags = 0; track->m_command = 0; - track->m_mixVolumeMode = 0; + track->m_mixVolumeMode = REDSOUND_SE_VOLUME_MODE_NORMAL; trackNo = track->m_trackNo; (p_VoiceData + trackNo)->m_stateFlags &= REDSOUND_VOICE_STATE_CLEAR_PLAYING_MASK; (p_VoiceData + trackNo)->m_voiceSwitch &= REDSOUND_VOICE_SWITCH_CLEAR_SE_MASK; (p_VoiceData + trackNo)->m_flags &= REDSOUND_VOICE_FLAGS_CLEAR_ACTIVE_MASK; (p_VoiceData + trackNo)->m_flags |= REDSOUND_VOICE_FLAGS_RELEASED; - (p_VoiceData + trackNo)->m_active = 0; + (p_VoiceData + trackNo)->m_active = REDSOUND_VOICE_ACTIVE_OFF; - c_RedEntry.SeSepHistoryManager(0, track->m_seSepId); + c_RedEntry.SeSepHistoryManager(REDSOUND_HISTORY_MODE_RELEASE, track->m_seSepId); if (track->m_waveBankData != 0) { - c_RedEntry.WaveHistoryManager( - 0, track->m_waveBankData->m_waveNo); + c_RedEntry.WaveHistoryManager(REDSOUND_HISTORY_MODE_RELEASE, track->m_waveBankData->m_waveNo); } } track++; @@ -111,55 +171,58 @@ static void _EraseAttribute(int eraseTrack, int attrMask) */ static int _EraseTime(int eraseTrack) { - int minTrack = REDSOUND_ERASE_TRACK_SENTINEL; + int minEraseTrack = REDSOUND_ERASE_TRACK_SENTINEL; + int maxPlayTime; RedTrackDATA** trackBasePtr = &p_SoundControlBuffer[REDSOUND_CONTROL_SE].m_tracks; RedTrackDATA* track = *trackBasePtr; + int sepId; + int erasedCount; do { - if ((track->m_command != 0) && (track->m_attrMask == 0) && (track->m_eraseTrack < minTrack)) { - minTrack = track->m_eraseTrack; + if ((track->m_command != 0) && (track->m_attrMask == 0) && (track->m_eraseTrack < minEraseTrack)) { + minEraseTrack = track->m_eraseTrack; } track++; } while (track < *trackBasePtr + REDSOUND_SE_TRACK_COUNT); - if (eraseTrack > minTrack) { - eraseTrack = minTrack; + if (eraseTrack > minEraseTrack) { + eraseTrack = minEraseTrack; } track = *trackBasePtr; - minTrack = 0; - int sepId = 0; + maxPlayTime = 0; + sepId = 0; do { if ((track->m_command != 0) && (track->m_attrMask == 0) && (track->m_eraseTrack <= eraseTrack) && - (track->m_playTime > minTrack)) { - minTrack = track->m_playTime; + (track->m_playTime > maxPlayTime)) { + maxPlayTime = track->m_playTime; sepId = track->m_seSepId; } track++; } while (track < *trackBasePtr + REDSOUND_SE_TRACK_COUNT); track = *trackBasePtr; - int erasedCount = 0; + erasedCount = 0; do { if ((track->m_command != 0) && (track->m_attrMask == 0) && (track->m_eraseTrack <= eraseTrack) && - (track->m_playTime == minTrack)) { + (track->m_playTime == maxPlayTime)) { int trackNo; KeyOnReserveClear(p_KeyOnData, track); - track->m_seId = 0; + track->m_seId = REDSOUND_SE_ID_NONE; track->m_flags = 0; track->m_command = 0; - track->m_mixVolumeMode = 0; + track->m_mixVolumeMode = REDSOUND_SE_VOLUME_MODE_NORMAL; trackNo = track->m_trackNo; (p_VoiceData + trackNo)->m_stateFlags &= REDSOUND_VOICE_STATE_CLEAR_PLAYING_MASK; (p_VoiceData + trackNo)->m_voiceSwitch &= REDSOUND_VOICE_SWITCH_CLEAR_SE_MASK; (p_VoiceData + trackNo)->m_flags &= REDSOUND_VOICE_FLAGS_CLEAR_ACTIVE_MASK; (p_VoiceData + trackNo)->m_flags |= REDSOUND_VOICE_FLAGS_RELEASED; - (p_VoiceData + trackNo)->m_active = 0; + (p_VoiceData + trackNo)->m_active = REDSOUND_VOICE_ACTIVE_OFF; if (track->m_waveBankData != 0) { - c_RedEntry.WaveHistoryManager(0, track->m_waveBankData->m_waveNo); + c_RedEntry.WaveHistoryManager(REDSOUND_HISTORY_MODE_RELEASE, track->m_waveBankData->m_waveNo); } erasedCount++; } @@ -167,7 +230,7 @@ static int _EraseTime(int eraseTrack) } while (track < *trackBasePtr + REDSOUND_SE_TRACK_COUNT); if (erasedCount != 0) { - c_RedEntry.SeSepHistoryManager(0, sepId); + c_RedEntry.SeSepHistoryManager(REDSOUND_HISTORY_MODE_RELEASE, sepId); } return erasedCount; @@ -193,9 +256,10 @@ RedTrackDATA* SearchSeEmptyTrack(int trackCount, int eraseTrack, int attrMask) if (attrMask != 0) { _EraseAttribute(eraseTrack, attrMask); } + volatile int unused = 0; erasedCount = 0; - for (;;) { + do { scan = *trackBasePtr + REDSOUND_SE_TRACK_LAST_INDEX; do { track = scan; @@ -214,15 +278,7 @@ RedTrackDATA* SearchSeEmptyTrack(int trackCount, int eraseTrack, int attrMask) } scan--; } while ((remaining != 0) && (track >= *trackBasePtr)); - - if (track >= *trackBasePtr) { - break; - } - erasedCount = _EraseTime(eraseTrack); - if (erasedCount == 0) { - break; - } - } + } while ((track < *trackBasePtr) && ((erasedCount = _EraseTime(eraseTrack)) != 0)); if (track >= *trackBasePtr) { return track; @@ -249,14 +305,60 @@ int SeStopID(int seId) soundControl->m_updateFlags = 0; track = soundControl->m_tracks; do { - if ((track->m_command != 0) && ((seId == -1) || (track->m_seId == seId))) { + if ((track->m_command != 0) && ((seId == REDSOUND_SE_ID_ALL) || (track->m_seId == seId))) { + int trackNo; + + KeyOnReserveClear(p_KeyOnData, track); + track->m_seId = REDSOUND_SE_ID_NONE; + track->m_flags = 0; + track->m_command = 0; + track->m_mixVolumeMode = REDSOUND_SE_VOLUME_MODE_NORMAL; + + trackNo = track->m_trackNo; + (p_VoiceData + trackNo)->m_stateFlags &= REDSOUND_VOICE_STATE_CLEAR_PLAYING_MASK; + (p_VoiceData + trackNo)->m_voiceSwitch &= REDSOUND_VOICE_SWITCH_CLEAR_SE_MASK; + (p_VoiceData + trackNo)->m_flags &= REDSOUND_VOICE_FLAGS_CLEAR_ACTIVE_MASK; + (p_VoiceData + trackNo)->m_flags |= REDSOUND_VOICE_FLAGS_RELEASED; + (p_VoiceData + trackNo)->m_track = 0; + (p_VoiceData + trackNo)->m_active = REDSOUND_VOICE_ACTIVE_OFF; + + if (track->m_waveBankData != 0) { + c_RedEntry.WaveHistoryManager(REDSOUND_HISTORY_MODE_RELEASE, track->m_waveBankData->m_waveNo); + } + c_RedEntry.SeSepHistoryManager(REDSOUND_HISTORY_MODE_RELEASE, track->m_seSepId); + } + track++; + } while (track < soundControl->m_tracks + REDSOUND_SE_TRACK_COUNT); + + return 0; +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 408b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +int SeStopG(int group) +{ + RedSoundCONTROL* soundControl; + RedTrackDATA* track; + + soundControl = &p_SoundControlBuffer[REDSOUND_CONTROL_SE]; + soundControl->m_updateFlags = 0; + track = soundControl->m_tracks; + do { + if ((track->m_command != 0) && ((track->m_seSepId & REDSOUND_SE_BLOCK_DATA_FLAG) == 0) && + (track->m_seSepId / REDSOUND_SE_MG_ID_DIVISOR == group)) { int trackNo; KeyOnReserveClear(p_KeyOnData, track); - track->m_seId = 0; + track->m_seId = REDSOUND_SE_ID_NONE; track->m_flags = 0; track->m_command = 0; - track->m_mixVolumeMode = 0; + track->m_mixVolumeMode = REDSOUND_SE_VOLUME_MODE_NORMAL; trackNo = track->m_trackNo; (p_VoiceData + trackNo)->m_stateFlags &= REDSOUND_VOICE_STATE_CLEAR_PLAYING_MASK; @@ -264,12 +366,12 @@ int SeStopID(int seId) (p_VoiceData + trackNo)->m_flags &= REDSOUND_VOICE_FLAGS_CLEAR_ACTIVE_MASK; (p_VoiceData + trackNo)->m_flags |= REDSOUND_VOICE_FLAGS_RELEASED; (p_VoiceData + trackNo)->m_track = 0; - (p_VoiceData + trackNo)->m_active = 0; + (p_VoiceData + trackNo)->m_active = REDSOUND_VOICE_ACTIVE_OFF; if (track->m_waveBankData != 0) { - c_RedEntry.WaveHistoryManager(0, track->m_waveBankData->m_waveNo); + c_RedEntry.WaveHistoryManager(REDSOUND_HISTORY_MODE_RELEASE, track->m_waveBankData->m_waveNo); } - c_RedEntry.SeSepHistoryManager(0, track->m_seSepId); + c_RedEntry.SeSepHistoryManager(REDSOUND_HISTORY_MODE_RELEASE, track->m_seSepId); } track++; } while (track < soundControl->m_tracks + REDSOUND_SE_TRACK_COUNT); @@ -296,15 +398,15 @@ int SeStopMG(int bank, int sep, int group, int kind) track = soundControl->m_tracks; do { if ((track->m_command != 0) && ((track->m_seSepId & REDSOUND_SE_BLOCK_DATA_FLAG) == 0)) { - int id = track->m_seSepId / 1000; + int id = track->m_seSepId / REDSOUND_SE_MG_ID_DIVISOR; if ((bank != id) && (sep != id) && (group != id) && (kind != id)) { int trackNo; KeyOnReserveClear(p_KeyOnData, track); - track->m_seId = 0; + track->m_seId = REDSOUND_SE_ID_NONE; track->m_flags = 0; track->m_command = 0; - track->m_mixVolumeMode = 0; + track->m_mixVolumeMode = REDSOUND_SE_VOLUME_MODE_NORMAL; trackNo = track->m_trackNo; (p_VoiceData + trackNo)->m_stateFlags &= REDSOUND_VOICE_STATE_CLEAR_PLAYING_MASK; @@ -312,12 +414,12 @@ int SeStopMG(int bank, int sep, int group, int kind) (p_VoiceData + trackNo)->m_flags &= REDSOUND_VOICE_FLAGS_CLEAR_ACTIVE_MASK; (p_VoiceData + trackNo)->m_flags |= REDSOUND_VOICE_FLAGS_RELEASED; (p_VoiceData + trackNo)->m_track = 0; - (p_VoiceData + trackNo)->m_active = 0; + (p_VoiceData + trackNo)->m_active = REDSOUND_VOICE_ACTIVE_OFF; if (track->m_waveBankData != 0) { - c_RedEntry.WaveHistoryManager(0, track->m_waveBankData->m_waveNo); + c_RedEntry.WaveHistoryManager(REDSOUND_HISTORY_MODE_RELEASE, track->m_waveBankData->m_waveNo); } - c_RedEntry.SeSepHistoryManager(0, track->m_seSepId); + c_RedEntry.SeSepHistoryManager(REDSOUND_HISTORY_MODE_RELEASE, track->m_seSepId); } } track++; @@ -342,7 +444,7 @@ static int _SePlayStart(RedSeINFO* info, int seId, int sepId, int pan, int volum RedTrackDATA* track; unsigned int state; unsigned char attrMask; - unsigned char* seq; + RedSeInfoSequence* seq; int deltaTime; unsigned int count; unsigned char* current; @@ -351,13 +453,13 @@ static int _SePlayStart(RedSeINFO* info, int seId, int sepId, int pan, int volum int isMulti; p_SoundControlBuffer[REDSOUND_CONTROL_SE].m_updateFlags = 0; - deltaTime = (unsigned int)info->m_waveNoHi * REDSOUND_SE_INFO_U16_HIGH_SCALE + - (unsigned int)info->m_waveNoLo; + deltaTime = (unsigned int)info->m_waveNoLo + + (unsigned int)info->m_waveNoHi * REDSOUND_SE_INFO_U16_HIGH_SCALE; waveBase = c_RedEntry.SearchWaveBase(deltaTime); if (waveBase != 0) { - c_RedEntry.WaveHistoryManager(1, waveBase->m_waveNo); + c_RedEntry.WaveHistoryManager(REDSOUND_HISTORY_MODE_USE, waveBase->m_waveNo); } else { - if (m_ReportPrint != 0) { + if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { OSReport(sRedCommandWaveNotEntryFmt, sRedCommandLogPrefix, sRedCommandLogWarnColor, deltaTime, sRedCommandLogReset); fflush(__files + 1); @@ -373,14 +475,14 @@ static int _SePlayStart(RedSeINFO* info, int seId, int sepId, int pan, int volum seq = info->m_sequence; attrMask = info->m_attrMask; count = info->m_flagsAndCount & REDSOUND_SE_INFO_COUNT_MASK; - current = seq + count * REDSOUND_SE_INFO_SEQUENCE_ENTRY_SIZE; + current = reinterpret_cast(seq + count); do { remaining = count; if (sepId != REDSOUND_SEP_DIRECT_PLAY_ID) { remaining = 0; do { remaining = remaining + 1; - if ((seq[remaining * REDSOUND_SE_INFO_SEQUENCE_ENTRY_SIZE + 1] & REDSOUND_SE_INFO_SEQUENCE_CONTINUE_FLAG) == 0) { + if ((seq[remaining].m_offsetHiAndFlags & REDSOUND_SE_INFO_SEQUENCE_CONTINUE_FLAG) == 0) { break; } } while ((int)remaining < (int)count); @@ -397,8 +499,8 @@ static int _SePlayStart(RedSeINFO* info, int seId, int sepId, int pan, int volum track->m_waveBankData = waveBase; track->m_command = current; current = current + - (((unsigned int)seq[REDSOUND_SE_INFO_SEQUENCE_OFFSET_HI] * REDSOUND_SE_INFO_U16_HIGH_SCALE + - (unsigned int)seq[REDSOUND_SE_INFO_SEQUENCE_OFFSET_LO]) & + (((unsigned int)seq->m_offsetLo + + (unsigned int)seq->m_offsetHiAndFlags * REDSOUND_SE_INFO_U16_HIGH_SCALE) & REDSOUND_SE_INFO_SEQUENCE_OFFSET_MASK); deltaTime = (int)DeltaTimeSumup((unsigned char**)&track->m_command); track->m_deltaTime = deltaTime + 1; @@ -421,10 +523,10 @@ static int _SePlayStart(RedSeINFO* info, int seId, int sepId, int pan, int volum track->m_attrMask = info->m_attrMask; track->m_mixVolume = volume << REDSOUND_FIXED_SHIFT; track->m_mixVolumeDelta = 0; - track->m_mixVolumeMode = 0; + track->m_mixVolumeMode = REDSOUND_SE_VOLUME_MODE_NORMAL; track->m_pitchDelta = 0; track->m_pitch = 0; - track->m_voiceSwitch = isMulti; + track->m_loopReport = isMulti; track->m_volume = REDSOUND_VOLUME_FULL; track->m_expression = REDSOUND_VOLUME_DEFAULT; track->m_pan = pan << REDSOUND_FIXED_SHIFT; @@ -459,9 +561,9 @@ static int _SePlayStart(RedSeINFO* info, int seId, int sepId, int pan, int volum track->m_fuzzyPanDepth = 0; track->m_fuzzyVolumeDepth = 0; track->m_fuzzyPitchDepth = 0; - track->m_portamentPitch = -1; + track->m_portamentPitch = REDSOUND_TRACK_PORTAMENT_PITCH_NONE; track->m_voiceSwitch = REDSOUND_VOICE_SWITCH_DRY_STEREO; - memset(&track->m_adsrAR, REDSOUND_TRACK_ADSR_DEFAULT_BYTE, REDSOUND_TRACK_ADSR_SIZE); + memset(&track->m_adsr, REDSOUND_TRACK_ADSR_DEFAULT_BYTE, REDSOUND_TRACK_ADSR_SIZE); track->m_note.m_allocFlags = REDSOUND_NOTE_ALLOC_DIRECT_MASK; track->m_seTickCounter = 1; voiceData->m_track = track; @@ -473,7 +575,7 @@ static int _SePlayStart(RedSeINFO* info, int seId, int sepId, int pan, int volum } remaining = remaining - 1; - seq = seq + REDSOUND_SE_INFO_SEQUENCE_ENTRY_SIZE; + seq++; count = count - 1; if (remaining == 0) { break; @@ -515,9 +617,7 @@ int SeBlockPlay(int seId, int bank, int no, int pan, int volume) int* entries = bankData->m_entries; if (entries[seNo] != REDSOUND_SE_BLOCK_ENTRY_EMPTY) { - RedSeINFO* seInfo = reinterpret_cast( - reinterpret_cast(entries + bankData->m_seCount) + - ((unsigned int)entries[seNo] & REDSOUND_SE_BLOCK_ENTRY_MASK)); + RedSeINFO* seInfo = RedSeBlockGetInfoFromEntries(bankData, entries, seNo); RedSeINFO* playInfo = seInfo; if (((unsigned int)entries[seNo] & REDSOUND_SE_BLOCK_DATA_FLAG) != 0) { @@ -530,7 +630,7 @@ int SeBlockPlay(int seId, int bank, int no, int pan, int volume) } } - return -1; + return REDSOUND_SE_PLAY_FAILED; } /* @@ -550,17 +650,17 @@ int SeSepPlay(int seId, int sepId, int pan, int volume) sepBank = c_RedEntry.SearchSeSepBank(sepId); if (sepBank != 0) { - sepHead = reinterpret_cast(sepBank->m_data); - sepInfo = reinterpret_cast(&sepHead->m_seInfoFlags); + sepHead = sepBank->m_seSepHead; + sepInfo = RedSeSepGetInfo(sepHead); if ((sepHead->m_sizeAndFlags & REDSOUND_SESEP_FLAGS_MASK) != 0) { sepInfo->m_flagsAndCount |= REDSOUND_SE_INFO_MULTI_FLAG; } if (_SePlayStart(sepInfo, seId, sepId, pan, volume) != 0) { - c_RedEntry.SeSepHistoryManager(1, sepId); + c_RedEntry.SeSepHistoryManager(REDSOUND_HISTORY_MODE_USE, sepId); return sepId; } } - return -1; + return REDSOUND_SE_PLAY_FAILED; } /* @@ -587,7 +687,7 @@ void SetSeVolume(int seId, int volume, int frameCount, int mode) track = p_SoundControlBuffer[REDSOUND_CONTROL_SE].m_tracks; do { - if ((track->m_command != 0) && ((seId < 0) || (track->m_seId == seId))) { + if ((track->m_command != 0) && ((seId < REDSOUND_SE_ID_MIN) || (track->m_seId == seId))) { int delta = volume - track->m_mixVolume; delta /= frameCount; track->m_mixVolumeAdd = delta; @@ -622,7 +722,7 @@ void SetSePan(int seId, int pan, int frameCount) track = p_SoundControlBuffer[REDSOUND_CONTROL_SE].m_tracks; do { - if ((track->m_command != 0) && ((seId < 0) || (track->m_seId == seId))) { + if ((track->m_command != 0) && ((seId < REDSOUND_SE_ID_MIN) || (track->m_seId == seId))) { int delta = pan - track->m_pan; delta /= frameCount; track->m_panAdd = delta; @@ -656,7 +756,7 @@ void SetSePitch(int seId, int pitch, int frameCount) track = p_SoundControlBuffer[REDSOUND_CONTROL_SE].m_tracks; do { - if ((track->m_command != 0) && ((seId < 0) || (track->m_seId == seId))) { + if ((track->m_command != 0) && ((seId < REDSOUND_SE_ID_MIN) || (track->m_seId == seId))) { int delta = pitch - track->m_pitch; track->m_pitchAdd = delta / frameCount; track->m_pitchDelta = frameCount; @@ -680,7 +780,7 @@ void SePause(int seId, int pause) RedTrackDATA* track; RedVoiceDATA* voice; - if (m_ReportPrint != 0) { + if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { if (pause == REDSOUND_PAUSE_ON) { OSReport(sRedCommandSePauseOnFmt, sRedCommandLogPrefix, seId); } else { @@ -693,7 +793,7 @@ void SePause(int seId, int pause) track = *trackBasePtr; voice = p_VoiceData + REDSOUND_SE_VOICE_BASE_INDEX; do { - if ((track->m_seId != 0) && ((seId == -1) || (seId == track->m_seId))) { + if ((track->m_seId != REDSOUND_SE_ID_NONE) && ((seId == REDSOUND_SE_ID_ALL) || (seId == track->m_seId))) { if (pause == REDSOUND_PAUSE_ON) { if (voice->m_axVoice != 0) { voice->m_targetPitch = 0; @@ -728,9 +828,11 @@ static RedTrackDATA* _MusicPlayStart(RedMusicHEAD* musicHead, RedWaveHeadWD* wav } m_MusicSkipLine = mode; - RedSoundCONTROL* music = p_SoundControlBuffer; + RedSoundCONTROL* music; if (m_MusicSkipLine != 0) { - music += REDSOUND_CONTROL_MUSIC_SKIP; + music = p_SoundControlBuffer + REDSOUND_CONTROL_MUSIC_SKIP; + } else { + music = p_SoundControlBuffer; } music->m_musicId = musicId; @@ -748,9 +850,9 @@ static RedTrackDATA* _MusicPlayStart(RedMusicHEAD* musicHead, RedWaveHeadWD* wav music->m_masterVolumeDelta = 0; } - RedTrackDATA* trackBase = (RedTrackDATA*)RedNew(musicHead->m_trackCount * REDSOUND_TRACK_SIZE); - if (trackBase == 0) { - if (m_ReportPrint != 0) { + RedTrackDATA* track = (RedTrackDATA*)RedNew(musicHead->m_trackCount * REDSOUND_TRACK_SIZE); + if (track == 0) { + if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { OSReport(sRedCommandMusicTrackCreateErrorFmt, sRedCommandLogPrefix, sRedCommandLogErrorColor, sRedCommandLogReset); fflush(__files + 1); @@ -763,10 +865,10 @@ static RedTrackDATA* _MusicPlayStart(RedMusicHEAD* musicHead, RedWaveHeadWD* wav return (RedTrackDATA*)-1; } - music->m_tracks = trackBase; + music->m_tracks = track; if (musicHead->m_reverbKind != 0) { - unsigned int reverbKind = ((int)musicHead->m_reverbKind - 1U) & 7; + unsigned int reverbKind = ((int)musicHead->m_reverbKind - 1U) & REDSOUND_REVERB_MODE_INDEX_MASK; SetReverb(0, t_ReverbModeData[reverbKind].m_kind, t_ReverbModeData[reverbKind].m_params); } @@ -779,23 +881,26 @@ static RedTrackDATA* _MusicPlayStart(RedMusicHEAD* musicHead, RedWaveHeadWD* wav p_ReverbDepth[REDSOUND_REVERB_DEPTH_MUSIC].m_count = 0; music->m_waveNo = musicHead->m_waveNo; - unsigned char* current = (unsigned char*)musicHead + REDSOUND_MUSIC_HEADER_SIZE; - RedTrackDATA* track = music->m_tracks; + RedMusicTrackBlock* current = reinterpret_cast(musicHead + 1); int count = musicHead->m_trackCount; char trackNo = 0; while (count != 0) { - unsigned int blockSize = ((unsigned int)current[REDSOUND_MUSIC_TRACK_BLOCK_SIZE_BYTE3] << 24) | - ((unsigned int)current[REDSOUND_MUSIC_TRACK_BLOCK_SIZE_BYTE2] << 16) | - ((unsigned int)current[REDSOUND_MUSIC_TRACK_BLOCK_SIZE_BYTE1] << 8) | - (unsigned int)current[REDSOUND_MUSIC_TRACK_BLOCK_SIZE_BYTE0]; + unsigned int blockSize = ((unsigned int)current->m_sizeHi2 << 24) | + ((unsigned int)current->m_sizeHi1 << 16) | + ((unsigned int)current->m_sizeHi0 << 8) | + (unsigned int)current->m_sizeLo; track->m_trackNo = trackNo - 1; track->m_waveBankData = waveHead; - track->m_command = current + REDSOUND_MUSIC_TRACK_BLOCK_SIZE_FIELD_SIZE; - current = current + REDSOUND_MUSIC_TRACK_BLOCK_SIZE_FIELD_SIZE + blockSize; + current = (RedMusicTrackBlock*)current->m_command; + track->m_command = (unsigned char*)current; + current = (RedMusicTrackBlock*)((unsigned char*)current + blockSize); track->m_deltaTime = DeltaTimeSumup((unsigned char**)&track->m_command) + 1; track->m_seSepId = 0; - track->m_keySignatureData = - (m_MusicKeySignature == 0) ? 0 : t_KeySignatureData + REDSOUND_KEY_SIGNATURE_DEFAULT_OFFSET; + if (m_MusicKeySignature != 0) { + track->m_keySignatureData = t_KeySignatureData + REDSOUND_KEY_SIGNATURE_DEFAULT_OFFSET; + } else { + track->m_keySignatureData = 0; + } track->m_mixVolume = REDSOUND_VOLUME_DEFAULT; track->m_mixVolumeDelta = 0; track->m_volume = REDSOUND_VOLUME_FULL; @@ -832,10 +937,10 @@ static RedTrackDATA* _MusicPlayStart(RedMusicHEAD* musicHead, RedWaveHeadWD* wav track->m_fuzzyPanDepth = 0; track->m_fuzzyVolumeDepth = 0; track->m_fuzzyPitchDepth = 0; - track->m_portamentPitch = -1; + track->m_portamentPitch = REDSOUND_TRACK_PORTAMENT_PITCH_NONE; track->m_note.m_allocFlags = 0; - track->m_voiceSwitch = REDSOUND_VOICE_SWITCH_DRY_STEREO | REDSOUND_VOICE_SWITCH_REVERB_AUX_A; - memset(&track->m_adsrAR, REDSOUND_TRACK_ADSR_DEFAULT_BYTE, REDSOUND_TRACK_ADSR_SIZE); + track->m_voiceSwitch = REDSOUND_VOICE_SWITCH_MUSIC_DEFAULT; + memset(&track->m_adsr, REDSOUND_TRACK_ADSR_DEFAULT_BYTE, REDSOUND_TRACK_ADSR_SIZE); count--; trackNo++; @@ -851,11 +956,11 @@ static RedTrackDATA* _MusicPlayStart(RedMusicHEAD* musicHead, RedWaveHeadWD* wav music->m_trackCount = musicHead->m_trackCount; music->m_activeTrackCount = (short)musicHead->m_trackCount; music->m_volumeScale = (unsigned char)(musicHead->m_flags & REDSOUND_MUSIC_HEADER_VOLUME_SCALE_MASK); - music->m_tickCounter = 1; + music->m_tickCounter = REDSOUND_CONTROL_INITIAL_TICK_COUNTER; music->m_tempo = REDSOUND_FIXED_ONE; - music->m_ticksPerMeasure = 10000; - music->m_tick = -1; - music->m_measure = 1; + music->m_ticksPerMeasure = REDSOUND_CONTROL_DEFAULT_TICKS_PER_MEASURE; + music->m_tick = REDSOUND_CONTROL_INITIAL_TICK; + music->m_measure = REDSOUND_CONTROL_INITIAL_MEASURE; music->m_elapsedTime = 0; if (volume != 0) { volume = (((volume + 1) * REDSOUND_MASTER_VOLUME_SCALE) - 1) * REDSOUND_FIXED_ONE; @@ -868,8 +973,8 @@ static RedTrackDATA* _MusicPlayStart(RedMusicHEAD* musicHead, RedWaveHeadWD* wav music->m_flags |= REDSOUND_MUSIC_PLAY_FLAG_RELEASE_NOTES; } - c_RedEntry.WaveHistoryManager(1, music->m_waveNo); - c_RedEntry.MusicHistoryManager(1, musicId); + c_RedEntry.WaveHistoryManager(REDSOUND_HISTORY_MODE_USE, music->m_waveNo); + c_RedEntry.MusicHistoryManager(REDSOUND_HISTORY_MODE_USE, musicId); if (m_MusicSkipLine != 0) { OSSignalSemaphore(&m_MusicSkipSemaphore); } @@ -890,10 +995,11 @@ int MusicStop(int musicId) RedSoundCONTROL* music = p_SoundControlBuffer; do { - if ((musicId == -1) || ((music->m_musicId >= 0) && (music->m_musicId == musicId))) { - unsigned int stoppedMusicId = music->m_musicId; + if ((musicId == REDSOUND_MUSIC_ID_NONE) || + ((music->m_musicId >= REDSOUND_MUSIC_ID_MIN) && (music->m_musicId == musicId))) { + int stoppedMusicId = music->m_musicId; music->m_updateFlags = 0; - music->m_musicId = -1; + music->m_musicId = REDSOUND_MUSIC_ID_NONE; if (music->m_activeTrackCount != 0) { RedVoiceDATA* voiceData = p_VoiceData; do { @@ -904,7 +1010,7 @@ int MusicStop(int musicId) voiceData->m_flags |= REDSOUND_VOICE_FLAGS_RELEASED; voiceData->m_stateFlags &= ~REDSOUND_VOICE_STATE_SE; voiceData->m_track = 0; - voiceData->m_active = 0; + voiceData->m_active = REDSOUND_VOICE_ACTIVE_OFF; } voiceData++; } while (voiceData < p_VoiceData + REDSOUND_VOICE_COUNT); @@ -922,19 +1028,20 @@ int MusicStop(int musicId) music->m_trackCount = 0; RedDelete(music->m_tracks); music->m_tracks = 0; - c_RedEntry.WaveHistoryManager(0, music->m_waveNo); - c_RedEntry.MusicHistoryManager(0, stoppedMusicId); + c_RedEntry.WaveHistoryManager(REDSOUND_HISTORY_MODE_RELEASE, music->m_waveNo); + c_RedEntry.MusicHistoryManager(REDSOUND_HISTORY_MODE_RELEASE, stoppedMusicId); } } music++; } while (music < p_SoundControlBuffer + REDSOUND_CONTROL_MUSIC_SKIP); music = p_SoundControlBuffer; - if ((music->m_musicId < 0) && (music[REDSOUND_CONTROL_MUSIC_SECONDARY].m_musicId >= 0)) { + if ((music->m_musicId < REDSOUND_MUSIC_ID_MIN) && + (music[REDSOUND_CONTROL_MUSIC_SECONDARY].m_musicId >= REDSOUND_MUSIC_ID_MIN)) { memcpy(p_SoundControlBuffer, p_SoundControlBuffer + REDSOUND_CONTROL_MUSIC_SECONDARY, REDSOUND_CONTROL_SIZE); music[REDSOUND_CONTROL_MUSIC_SECONDARY].m_activeTrackCount = 0; music[REDSOUND_CONTROL_MUSIC_SECONDARY].m_trackCount = 0; - music[REDSOUND_CONTROL_MUSIC_SECONDARY].m_musicId = -1; + music[REDSOUND_CONTROL_MUSIC_SECONDARY].m_musicId = REDSOUND_MUSIC_ID_NONE; music[REDSOUND_CONTROL_MUSIC_SECONDARY].m_tracks = 0; } @@ -956,11 +1063,11 @@ int MusicPlay(int musicId, int volume, int mode) RedHistoryBANK* musicBank = c_RedEntry.SearchMusicBank(musicId); if (musicBank != 0) { - musicHead = (RedMusicHEAD*)musicBank->m_data; + musicHead = musicBank->m_musicHead; RedWaveHeadWD* waveHead = c_RedEntry.SearchWaveBase(musicHead->m_waveNo); if (waveHead == 0) { - return -1; + return REDSOUND_MUSIC_PLAY_FAILED; } _MusicPlayStart(musicHead, waveHead, musicId, volume, mode); @@ -978,7 +1085,7 @@ int MusicPlay(int musicId, int volume, int mode) * JP Address: TODO * JP Size: TODO */ -void SetMusicVolume(int seId, int volume, int duration, int mode) +void SetMusicVolume(int musicId, int volume, int duration, int mode) { RedSoundCONTROL* music; @@ -999,8 +1106,9 @@ void SetMusicVolume(int seId, int volume, int duration, int mode) music = p_SoundControlBuffer; do { - if ((seId == -1) || (seId == music->m_musicId) || (music->m_musicId < 0)) { - if (mode == 1) { + if ((musicId == REDSOUND_MUSIC_ID_NONE) || (musicId == music->m_musicId) || + (music->m_musicId < REDSOUND_MUSIC_ID_MIN)) { + if (mode == REDSOUND_MUSIC_VOLUME_MODE_FADE_OUT) { music->m_masterVolumeAdd = -music->m_masterVolume / duration; music->m_masterVolumeDelta = duration; } else { @@ -1011,3 +1119,113 @@ void SetMusicVolume(int seId, int volume, int duration, int mode) music++; } while (music < p_SoundControlBuffer + REDSOUND_CONTROL_SE); } + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 104b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +void SetMusicTempo(int tempo, int frameCount) +{ + tempo <<= REDSOUND_FIXED_SHIFT; + tempo |= REDSOUND_FIXED_HALF; + + if (frameCount < 1) { + frameCount = 1; + } else { + frameCount *= REDSOUND_MUSIC_FADE_TICKS_PER_SECOND; + frameCount /= REDSOUND_FRAMES_PER_SECOND; + } + + RedControlRamp* tempoControl = p_MusicTempoControl; + tempoControl->m_step = (tempo - tempoControl->m_value) / frameCount; + p_MusicTempoControl->m_count = frameCount; +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 92b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +void SetMusicPitch(int pitch, int frameCount) +{ + pitch <<= REDSOUND_FIXED_SHIFT; + pitch |= REDSOUND_FIXED_HALF; + + if (frameCount < 1) { + frameCount = 1; + } else { + frameCount *= REDSOUND_MUSIC_FADE_TICKS_PER_SECOND; + frameCount /= REDSOUND_FRAMES_PER_SECOND; + } + + p_MusicPitchControl->m_step = (pitch - p_MusicPitchControl->m_value) / frameCount; + p_MusicPitchControl->m_count = frameCount; +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 476b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +void MusicPause(int musicId, int pause) +{ + RedSoundCONTROL* music; + RedVoiceDATA* voice; + + if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { + if (pause == REDSOUND_PAUSE_ON) { + OSReport(sRedCommandMusicPauseOnFmt, sRedCommandLogPrefix, musicId); + } else { + OSReport(sRedCommandMusicPauseOffFmt, sRedCommandLogPrefix, musicId); + } + fflush(__files + 1); + } + + music = p_SoundControlBuffer; + do { + if ((musicId == REDSOUND_MUSIC_ID_NONE) || + ((music->m_musicId >= REDSOUND_MUSIC_ID_MIN) && (music->m_musicId == musicId))) { + if (pause == REDSOUND_PAUSE_ON) { + if (music->m_activeTrackCount != 0) { + voice = p_VoiceData; + do { + if ((voice->m_track >= music->m_tracks) && + (voice->m_track < music->m_tracks + music->m_trackCount)) { + if (voice->m_axVoice != 0) { + voice->m_targetPitch = 0; + voice->m_flags |= REDSOUND_VOICE_FLAGS_PAUSE_DIRTY; + } + voice->m_track->m_voiceSwitch |= REDSOUND_VOICE_SWITCH_PAUSE; + voice->m_voiceSwitch |= REDSOUND_VOICE_SWITCH_PAUSE; + } + voice++; + } while (voice < p_VoiceData + REDSOUND_VOICE_COUNT); + } + music->m_flags |= REDSOUND_CONTROL_FLAG_PAUSE; + } else { + voice = p_VoiceData; + do { + if ((voice->m_track >= music->m_tracks) && + (voice->m_track < music->m_tracks + music->m_trackCount)) { + voice->m_updateFlags |= REDSOUND_VOICE_UPDATE_ALL; + voice->m_track->m_voiceSwitch &= REDSOUND_VOICE_SWITCH_CLEAR_PAUSE_MASK; + voice->m_voiceSwitch &= REDSOUND_VOICE_SWITCH_CLEAR_PAUSE_MASK; + } + voice++; + } while (voice < p_VoiceData + REDSOUND_VOICE_COUNT); + music->m_flags &= ~REDSOUND_CONTROL_FLAG_PAUSE; + } + } + music++; + } while (music < p_SoundControlBuffer + REDSOUND_CONTROL_SE); +} diff --git a/src/RedSound/RedDriver.cpp b/src/RedSound/RedDriver.cpp index da8d96a11e..e52f6c7df0 100644 --- a/src/RedSound/RedDriver.cpp +++ b/src/RedSound/RedDriver.cpp @@ -6,6 +6,7 @@ #include "ffcc/RedSound/RedExecute.h" #include "ffcc/RedSound/RedMidiCtrl.h" #include "ffcc/RedSound/RedGlobals.h" +#include "global.h" #include "PowerPC_EABI_Support/Msl/MSL_C/MSL_Common/file_io.h" #include "PowerPC_EABI_Support/Msl/MSL_C/MSL_Common/string.h" #include "dolphin/ar.h" @@ -26,14 +27,32 @@ struct RedWaveSettingState { int m_waveSize; }; +enum RedWaveSettingLayoutOffset { + REDSOUND_WAVE_SETTING_SLOT_OFFSET = 0x00, + REDSOUND_WAVE_SETTING_WAVE_ID_OFFSET = 0x04, + REDSOUND_WAVE_SETTING_WAVE_DATA_OFFSET = 0x08, + REDSOUND_WAVE_SETTING_WAVE_SIZE_OFFSET = 0x0C, + REDSOUND_WAVE_SETTING_SIZE = 0x10, +}; + enum RedDriverDmaLayoutSize { + REDSOUND_DMA_REQUEST_ID_OFFSET = 0x00, + REDSOUND_DMA_REQUEST_DIRECTION_OFFSET = 0x04, + REDSOUND_DMA_REQUEST_MAIN_MEMORY_OFFSET = 0x08, + REDSOUND_DMA_REQUEST_ARAM_MEMORY_OFFSET = 0x0C, + REDSOUND_DMA_REQUEST_SIZE_OFFSET = 0x10, + REDSOUND_DMA_REQUEST_CALLBACK_OFFSET = 0x14, + REDSOUND_DMA_REQUEST_CALLBACK_DATA_OFFSET = 0x18, REDSOUND_DMA_MAIN_QUEUE_INDEX = 0, REDSOUND_DMA_STREAM_QUEUE_INDEX = 1, REDSOUND_DMA_QUEUE_COUNT = 2, + REDSOUND_DMA_REQUEST_SIZE = 0x1C, REDSOUND_DMA_QUEUE_WORD_COUNT = 0x380, REDSOUND_DMA_CONTROL_WORD_COUNT = REDSOUND_DMA_QUEUE_WORD_COUNT * 2, REDSOUND_DMA_QUEUE_ENTRY_COUNT = 0x80, REDSOUND_DMA_CONTROL_ENTRY_COUNT = REDSOUND_DMA_QUEUE_ENTRY_COUNT * 2, + REDSOUND_DMA_QUEUE_SIZE = REDSOUND_DMA_REQUEST_SIZE * REDSOUND_DMA_QUEUE_ENTRY_COUNT, + REDSOUND_DMA_CONTROL_SIZE = REDSOUND_DMA_QUEUE_SIZE * REDSOUND_DMA_QUEUE_COUNT, REDSOUND_DMA_TRANSFER_ALIGN = 0x20, REDSOUND_DMA_TRANSFER_ALIGN_MASK = ~(REDSOUND_DMA_TRANSFER_ALIGN - 1), REDSOUND_DMA_MAX_CHUNK_SIZE = 0x40000, @@ -43,6 +62,67 @@ enum RedDriverDmaLayoutSize { REDSOUND_DMA_ARQ_PRIORITY = 1, }; +enum RedDriverSyncLayoutOffset { + REDSOUND_DRIVER_SYNC_MAIN_THREAD_OFFSET = 0x1C00, + REDSOUND_DRIVER_SYNC_MAIN_SEMAPHORE_OFFSET = 0x1F18, + REDSOUND_DRIVER_SYNC_MAIN_THREAD_PAD_OFFSET = 0x1F24, + REDSOUND_DRIVER_SYNC_WAVE_THREAD_OFFSET = 0x1F28, + REDSOUND_DRIVER_SYNC_WAVE_SEMAPHORE_OFFSET = 0x2240, + REDSOUND_DRIVER_SYNC_WAVE_DATA_OFFSET = 0x224C, + REDSOUND_DRIVER_SYNC_WAVE_THREAD_PAD_OFFSET = 0x225C, + REDSOUND_DRIVER_SYNC_DMA_THREAD_OFFSET = 0x2260, + REDSOUND_DRIVER_SYNC_DMA_SEMAPHORE_OFFSET = 0x2578, + REDSOUND_DRIVER_SYNC_DMA_REQUEST_OFFSET = 0x2584, + REDSOUND_DRIVER_SYNC_DMA_THREAD_PAD_OFFSET = 0x25A4, + REDSOUND_DRIVER_SYNC_MUSIC_THREAD_OFFSET = 0x25A8, + REDSOUND_DRIVER_SYNC_MUSIC_SEMAPHORE_OFFSET = 0x28C0, + REDSOUND_DRIVER_SYNC_SIZE = 0x28CC, + REDSOUND_DRIVER_BSS_SE_BLOCK_DATA_OFFSET = 0x28CC, + REDSOUND_DRIVER_BSS_ENTRY_WORK0_OFFSET = 0x28DC, + REDSOUND_DRIVER_BSS_ENTRY_WORK1_OFFSET = 0x28E8, + REDSOUND_DRIVER_BSS_ENTRY_WORK_SIZE = 0x0C, + REDSOUND_DRIVER_BSS_ENTRY_OFFSET = 0x28F4, + REDSOUND_DRIVER_BSS_SIZE = 0x290C, +}; + +enum RedDriverGlobalObjectSize { + REDSOUND_SE_BLOCK_DATA_TABLE_SIZE = 0x10, + REDSOUND_RED_MEMORY_SIZE = 0x01, + REDSOUND_RED_ENTRY_SIZE = 0x18, +}; + +enum RedDriverSmallDataLayout { + REDSOUND_DRIVER_SBSS_SIZE = 0xD8, + REDSOUND_DRIVER_SBSS_MASTER_TIME_OFFSET = 0x00, + REDSOUND_DRIVER_SBSS_DMA_NOW_OFFSET = 0x28, + REDSOUND_DRIVER_SBSS_SOUND_CONTROL_BUFFER_OFFSET = 0x38, + REDSOUND_DRIVER_SBSS_MUSIC_REPLAY_POINT_OFFSET = 0x60, + REDSOUND_DRIVER_SBSS_STREAM_OFFSET = 0x80, + REDSOUND_DRIVER_SBSS_VOICE_DATA_OFFSET = 0x8C, + REDSOUND_DRIVER_SBSS_EDITOR_VOICE_OFFSET = 0x90, + REDSOUND_DRIVER_SBSS_MUTE_OFFSET = 0xC0, + REDSOUND_DRIVER_SBSS_BEFORE_RED_MEMORY_SIZE = 0xC8, + REDSOUND_DRIVER_SBSS_RED_MEMORY_OFFSET = 0xC8, + REDSOUND_DRIVER_SBSS_RED_MEMORY_PAD_OFFSET = 0xC9, + REDSOUND_DRIVER_SBSS_RED_MEMORY_PAD_SIZE = 0x03, + REDSOUND_DRIVER_SBSS_DMA_EXECUTE_OFFSET = 0xCC, + REDSOUND_DRIVER_SBSS_DMA_IN_THREAD_OFFSET = 0xD0, + REDSOUND_DRIVER_SBSS_TRAILING_PAD_SIZE = 0x04, +}; + +enum RedDriverStringLayout { + REDSOUND_DRIVER_DMA_CHECK_HEADER_SIZE = 0x20, + REDSOUND_DRIVER_LOG_PREFIX_SIZE = 0x12, + REDSOUND_DRIVER_DMA_STATUS_FMT_SIZE = 0x3E, + REDSOUND_DRIVER_DMA_ENTRY_FMT_SIZE = 0x48, + REDSOUND_DRIVER_MUSIC_HEADER_ERROR_FMT_SIZE = 0x22, + REDSOUND_DRIVER_SE_SEP_HEADER_ERROR_FMT_SIZE = 0x23, + REDSOUND_DRIVER_LOG_WARN_COLOR_SIZE = 0x08, + REDSOUND_DRIVER_LOG_RESET_SIZE = 0x05, + REDSOUND_DRIVER_RODATA_SIZE = 0xFD, + REDSOUND_DRIVER_SDATA2_SIZE = 0x0D, +}; + enum RedDriverDmaThreadStage { REDSOUND_DMA_THREAD_IDLE = 0, REDSOUND_DMA_THREAD_SELECT_QUEUE = 1, @@ -56,13 +136,28 @@ enum RedDriverDmaThreadStage { REDSOUND_DMA_THREAD_FINISH_ENTRY = 9, }; +enum RedDriverThreadControlState { + REDSOUND_THREAD_CONTROL_STOP = 0, + REDSOUND_THREAD_CONTROL_RUN = 1, +}; + +enum RedDriverDmaStatus { + REDSOUND_DMA_STATUS_IDLE = 0, + REDSOUND_DMA_STATUS_BUSY = 1, +}; + +enum RedDriverWorkerState { + REDSOUND_WORKER_IDLE = 0, + REDSOUND_WORKER_BUSY = 1, +}; + struct RedDmaRequest { int m_id; int m_direction; int m_mainMemory; int m_aramMemory; int m_size; - void (*m_callback)(void*); + RedDmaCallback m_callback; void* m_callbackData; }; @@ -71,28 +166,127 @@ struct RedDriverSyncState { RedDmaRequest m_streamDmaQueue[REDSOUND_DMA_QUEUE_ENTRY_COUNT]; OSThread m_mainThread; OSSemaphore m_mainSemaphore; - u8 m_reserved1F24[0x1F28 - 0x1F18 - sizeof(OSSemaphore)]; + u8 m_mainThreadAlignPadding[REDSOUND_DRIVER_SYNC_WAVE_THREAD_OFFSET - + REDSOUND_DRIVER_SYNC_MAIN_THREAD_PAD_OFFSET]; OSThread m_waveThread; OSSemaphore m_waveSemaphore; RedWaveSettingState m_waveSettingData; - u8 m_reserved225C[0x2260 - 0x2240 - sizeof(OSSemaphore) - sizeof(RedWaveSettingState)]; + u8 m_waveThreadAlignPadding[REDSOUND_DRIVER_SYNC_DMA_THREAD_OFFSET - + REDSOUND_DRIVER_SYNC_WAVE_THREAD_PAD_OFFSET]; OSThread m_dmaThread; OSSemaphore m_dmaSemaphore; ARQRequest m_dmaRequest; - u8 m_reserved25A4[0x25A8 - 0x2578 - sizeof(OSSemaphore) - sizeof(ARQRequest)]; + u8 m_dmaThreadAlignPadding[REDSOUND_DRIVER_SYNC_MUSIC_THREAD_OFFSET - + REDSOUND_DRIVER_SYNC_DMA_THREAD_PAD_OFFSET]; OSThread m_musicThread; OSSemaphore m_musicSemaphore; }; +struct RedDriverBssState { + RedDriverSyncState m_sync; + RedSeBlockHEAD* volatile m_seBlockData[REDSOUND_SE_BLOCK_BANK_COUNT]; + u8 m_entryWork0[REDSOUND_DRIVER_BSS_ENTRY_WORK_SIZE]; + u8 m_entryWork1[REDSOUND_DRIVER_BSS_ENTRY_WORK_SIZE]; + CRedEntry m_entry; +}; + +struct RedDriverSmallDataTailState { + u8 m_beforeRedMemory[REDSOUND_DRIVER_SBSS_BEFORE_RED_MEMORY_SIZE]; + CRedMemory m_redMemory; + u8 m_redMemoryAlignPadding[REDSOUND_DRIVER_SBSS_RED_MEMORY_PAD_SIZE]; + volatile int m_dmaExecute; + volatile int m_dmaInThread; + u8 m_trailingPadding[REDSOUND_DRIVER_SBSS_TRAILING_PAD_SIZE]; +}; + +STATIC_ASSERT(offsetof(RedDmaRequest, m_id) == REDSOUND_DMA_REQUEST_ID_OFFSET); +STATIC_ASSERT(offsetof(RedDmaRequest, m_direction) == REDSOUND_DMA_REQUEST_DIRECTION_OFFSET); +STATIC_ASSERT(offsetof(RedDmaRequest, m_mainMemory) == REDSOUND_DMA_REQUEST_MAIN_MEMORY_OFFSET); +STATIC_ASSERT(offsetof(RedDmaRequest, m_aramMemory) == REDSOUND_DMA_REQUEST_ARAM_MEMORY_OFFSET); +STATIC_ASSERT(offsetof(RedDmaRequest, m_size) == REDSOUND_DMA_REQUEST_SIZE_OFFSET); +STATIC_ASSERT(offsetof(RedDmaRequest, m_callback) == REDSOUND_DMA_REQUEST_CALLBACK_OFFSET); +STATIC_ASSERT(offsetof(RedDmaRequest, m_callbackData) == REDSOUND_DMA_REQUEST_CALLBACK_DATA_OFFSET); +STATIC_ASSERT(sizeof(RedDmaRequest) == REDSOUND_DMA_REQUEST_SIZE); +STATIC_ASSERT(sizeof(((RedDriverSyncState*)0)->m_dmaQueue) == REDSOUND_DMA_QUEUE_SIZE); +STATIC_ASSERT(sizeof(((RedDriverSyncState*)0)->m_streamDmaQueue) == REDSOUND_DMA_QUEUE_SIZE); +STATIC_ASSERT(REDSOUND_DMA_QUEUE_SIZE == REDSOUND_DMA_QUEUE_WORD_COUNT * sizeof(int)); +STATIC_ASSERT(REDSOUND_DMA_CONTROL_SIZE == REDSOUND_DMA_CONTROL_WORD_COUNT * sizeof(int)); +STATIC_ASSERT(sizeof(RedDmaRequest) * REDSOUND_DMA_CONTROL_ENTRY_COUNT == REDSOUND_DMA_CONTROL_SIZE); +STATIC_ASSERT(REDSOUND_DMA_CONTROL_SIZE == REDSOUND_DRIVER_SYNC_MAIN_THREAD_OFFSET); +STATIC_ASSERT(offsetof(RedWaveSettingState, m_slot) == REDSOUND_WAVE_SETTING_SLOT_OFFSET); +STATIC_ASSERT(offsetof(RedWaveSettingState, m_waveId) == REDSOUND_WAVE_SETTING_WAVE_ID_OFFSET); +STATIC_ASSERT(offsetof(RedWaveSettingState, m_waveData) == REDSOUND_WAVE_SETTING_WAVE_DATA_OFFSET); +STATIC_ASSERT(offsetof(RedWaveSettingState, m_waveSize) == REDSOUND_WAVE_SETTING_WAVE_SIZE_OFFSET); +STATIC_ASSERT(sizeof(RedWaveSettingState) == REDSOUND_WAVE_SETTING_SIZE); +STATIC_ASSERT(offsetof(RedDriverSyncState, m_mainThread) == REDSOUND_DRIVER_SYNC_MAIN_THREAD_OFFSET); +STATIC_ASSERT(offsetof(RedDriverSyncState, m_mainSemaphore) == REDSOUND_DRIVER_SYNC_MAIN_SEMAPHORE_OFFSET); +STATIC_ASSERT(offsetof(RedDriverSyncState, m_mainThreadAlignPadding) == + REDSOUND_DRIVER_SYNC_MAIN_THREAD_PAD_OFFSET); +STATIC_ASSERT(sizeof(((RedDriverSyncState*)0)->m_mainThreadAlignPadding) == + REDSOUND_DRIVER_SYNC_WAVE_THREAD_OFFSET - REDSOUND_DRIVER_SYNC_MAIN_THREAD_PAD_OFFSET); +STATIC_ASSERT(offsetof(RedDriverSyncState, m_waveThread) == REDSOUND_DRIVER_SYNC_WAVE_THREAD_OFFSET); +STATIC_ASSERT(offsetof(RedDriverSyncState, m_waveSemaphore) == REDSOUND_DRIVER_SYNC_WAVE_SEMAPHORE_OFFSET); +STATIC_ASSERT(offsetof(RedDriverSyncState, m_waveSettingData) == REDSOUND_DRIVER_SYNC_WAVE_DATA_OFFSET); +STATIC_ASSERT(offsetof(RedDriverSyncState, m_waveThreadAlignPadding) == + REDSOUND_DRIVER_SYNC_WAVE_THREAD_PAD_OFFSET); +STATIC_ASSERT(sizeof(((RedDriverSyncState*)0)->m_waveThreadAlignPadding) == + REDSOUND_DRIVER_SYNC_DMA_THREAD_OFFSET - REDSOUND_DRIVER_SYNC_WAVE_THREAD_PAD_OFFSET); +STATIC_ASSERT(offsetof(RedDriverSyncState, m_dmaThread) == REDSOUND_DRIVER_SYNC_DMA_THREAD_OFFSET); +STATIC_ASSERT(offsetof(RedDriverSyncState, m_dmaSemaphore) == REDSOUND_DRIVER_SYNC_DMA_SEMAPHORE_OFFSET); +STATIC_ASSERT(offsetof(RedDriverSyncState, m_dmaRequest) == REDSOUND_DRIVER_SYNC_DMA_REQUEST_OFFSET); +STATIC_ASSERT(offsetof(RedDriverSyncState, m_dmaThreadAlignPadding) == + REDSOUND_DRIVER_SYNC_DMA_THREAD_PAD_OFFSET); +STATIC_ASSERT(sizeof(((RedDriverSyncState*)0)->m_dmaThreadAlignPadding) == + REDSOUND_DRIVER_SYNC_MUSIC_THREAD_OFFSET - REDSOUND_DRIVER_SYNC_DMA_THREAD_PAD_OFFSET); +STATIC_ASSERT(offsetof(RedDriverSyncState, m_musicThread) == REDSOUND_DRIVER_SYNC_MUSIC_THREAD_OFFSET); +STATIC_ASSERT(offsetof(RedDriverSyncState, m_musicSemaphore) == REDSOUND_DRIVER_SYNC_MUSIC_SEMAPHORE_OFFSET); +STATIC_ASSERT(offsetof(RedDriverSyncState, m_musicSemaphore) + sizeof(OSSemaphore) == REDSOUND_DRIVER_SYNC_SIZE); +STATIC_ASSERT(REDSOUND_DRIVER_SYNC_SIZE == REDSOUND_DRIVER_BSS_SE_BLOCK_DATA_OFFSET); +STATIC_ASSERT(sizeof(((RedDriverBssState*)0)->m_seBlockData) == REDSOUND_SE_BLOCK_DATA_TABLE_SIZE); +STATIC_ASSERT(REDSOUND_DRIVER_BSS_SE_BLOCK_DATA_OFFSET + REDSOUND_SE_BLOCK_DATA_TABLE_SIZE == + REDSOUND_DRIVER_BSS_ENTRY_WORK0_OFFSET); +STATIC_ASSERT(sizeof(((RedDriverBssState*)0)->m_entryWork0) == REDSOUND_DRIVER_BSS_ENTRY_WORK_SIZE); +STATIC_ASSERT(REDSOUND_DRIVER_BSS_ENTRY_WORK0_OFFSET + REDSOUND_DRIVER_BSS_ENTRY_WORK_SIZE == + REDSOUND_DRIVER_BSS_ENTRY_WORK1_OFFSET); +STATIC_ASSERT(sizeof(((RedDriverBssState*)0)->m_entryWork1) == REDSOUND_DRIVER_BSS_ENTRY_WORK_SIZE); +STATIC_ASSERT(REDSOUND_DRIVER_BSS_ENTRY_WORK1_OFFSET + REDSOUND_DRIVER_BSS_ENTRY_WORK_SIZE == + REDSOUND_DRIVER_BSS_ENTRY_OFFSET); +STATIC_ASSERT(REDSOUND_DRIVER_BSS_ENTRY_OFFSET + sizeof(CRedEntry) == REDSOUND_DRIVER_BSS_SIZE); + enum RedExecCommandLayout { + REDSOUND_EXEC_COMMAND_FUNC_OFFSET = 0x00, + REDSOUND_EXEC_COMMAND_ARGS_OFFSET = 0x04, REDSOUND_EXEC_COMMAND_ARG_COUNT = 7, + REDSOUND_EXEC_COMMAND_SIZE = 0x20, +}; + +enum RedExecCommandArgIndex { + REDSOUND_EXEC_COMMAND_ARG0 = 0, + REDSOUND_EXEC_COMMAND_ARG1 = 1, + REDSOUND_EXEC_COMMAND_ARG2 = 2, + REDSOUND_EXEC_COMMAND_ARG3 = 3, + REDSOUND_EXEC_COMMAND_ARG4 = 4, + REDSOUND_EXEC_COMMAND_ARG5 = 5, + REDSOUND_EXEC_COMMAND_ARG6 = 6, }; +typedef void (*RedExecCommandFunc)(int* command); + struct RedExecCommand { - void (*m_func)(int*); + RedExecCommandFunc m_func; int m_args[REDSOUND_EXEC_COMMAND_ARG_COUNT]; }; +enum RedMusicPlayCommandLayout { + REDSOUND_MUSIC_PLAY_COMMAND_ID_OFFSET = 0x00, + REDSOUND_MUSIC_PLAY_COMMAND_VOLUME_OFFSET = 0x04, + REDSOUND_MUSIC_PLAY_COMMAND_MODE_OFFSET = 0x08, + REDSOUND_MUSIC_PLAY_COMMAND_RESERVED_OFFSET = 0x0C, + REDSOUND_MUSIC_PLAY_COMMAND_SIZE = 0x10, + REDSOUND_MUSIC_PLAY_COMMAND_RESERVED_SIZE = + REDSOUND_MUSIC_PLAY_COMMAND_SIZE - REDSOUND_MUSIC_PLAY_COMMAND_RESERVED_OFFSET, +}; + struct RedMusicPlayCommand { int m_musicId; int m_volume; @@ -167,6 +361,7 @@ enum RedSeBlockDataCommandWord { enum RedDriverTickHistoryLayout { REDSOUND_TICK_HISTORY_LATEST = 0, REDSOUND_TICK_HISTORY_COUNT = 100, + REDSOUND_TICK_HISTORY_SIZE = sizeof(int) * REDSOUND_TICK_HISTORY_COUNT, REDSOUND_TICK_HISTORY_SHIFT_SIZE = sizeof(int) * (REDSOUND_TICK_HISTORY_COUNT - 1), }; @@ -174,6 +369,107 @@ struct RedTickHistory { int m_ticks[REDSOUND_TICK_HISTORY_COUNT]; }; +struct RedDriverSmallDataPrefixState { + int m_redMasterTime; + volatile int m_sequencialID; + volatile int m_threadControl; + volatile int m_threadExecute; + int m_soundMode; + RedTickHistory* volatile m_tick; + u8* volatile m_zeroData; + RedExecCommand* volatile m_execCommand; + RedExecCommand* volatile m_execCommandNow; + RedExecCommand* volatile m_execCommandOld; + RedDmaRequest* volatile m_dmaControlNow[REDSOUND_DMA_QUEUE_COUNT]; + RedDmaRequest* volatile m_dmaControlOld[REDSOUND_DMA_QUEUE_COUNT]; + RedSoundCONTROL* volatile m_soundControlBuffer; + RedSoundCONTROL* volatile m_soundControl; + volatile int m_keyOnEntry; + RedKeyOnDATA* volatile m_keyOnData; + int m_soundPlayMode; + int m_soundMasterControl; + volatile int m_reportPrint; + int m_musicFastSpeed; + volatile int m_musicSkipLine; + int m_musicKeySignature; + int* volatile m_musicReplayPoint; + RedControlRamp* volatile m_musicTempoControl; + RedControlRamp* volatile m_musicPitchControl; + int m_musicPhraseStop; + RedMusicPlayCommand* volatile m_musicNextPlay; + int m_crossTime; + volatile int m_masterMusicVolume; + volatile int m_masterSEVolume; + RedStreamDATA* volatile m_stream; + int m_dmaMode; + volatile int m_seSkipStep; + RedVoiceDATA* volatile m_voiceData; + int m_editorVoice[REDSOUND_EDITOR_VOICE_COUNT]; + RedTrackDATA* m_editorTrack; + u8* volatile m_mainThreadStack; + int m_mainThreadTime; + u8* volatile m_waveSettingThreadStack; + int m_waveSettingStatus; + u8* volatile m_dmaExecuteThreadStack; + volatile int m_dmaStatus; + u8* volatile m_musicSkipThreadStack; + volatile int m_musicSkipComplete; + RedReverbDepth* volatile m_reverbDepth; + int m_mute[REDSOUND_MUTE_WORD_COUNT]; +}; + +STATIC_ASSERT(offsetof(RedExecCommand, m_func) == REDSOUND_EXEC_COMMAND_FUNC_OFFSET); +STATIC_ASSERT(offsetof(RedExecCommand, m_args) == REDSOUND_EXEC_COMMAND_ARGS_OFFSET); +STATIC_ASSERT(sizeof(((RedExecCommand*)0)->m_args) == sizeof(int) * REDSOUND_EXEC_COMMAND_ARG_COUNT); +STATIC_ASSERT(sizeof(RedExecCommand) == REDSOUND_EXEC_COMMAND_SIZE); +STATIC_ASSERT(offsetof(RedMusicPlayCommand, m_musicId) == REDSOUND_MUSIC_PLAY_COMMAND_ID_OFFSET); +STATIC_ASSERT(offsetof(RedMusicPlayCommand, m_volume) == REDSOUND_MUSIC_PLAY_COMMAND_VOLUME_OFFSET); +STATIC_ASSERT(offsetof(RedMusicPlayCommand, m_mode) == REDSOUND_MUSIC_PLAY_COMMAND_MODE_OFFSET); +STATIC_ASSERT(offsetof(RedMusicPlayCommand, m_reserved) == REDSOUND_MUSIC_PLAY_COMMAND_RESERVED_OFFSET); +STATIC_ASSERT(sizeof(((RedMusicPlayCommand*)0)->m_reserved) == REDSOUND_MUSIC_PLAY_COMMAND_RESERVED_SIZE); +STATIC_ASSERT(sizeof(RedMusicPlayCommand) == REDSOUND_MUSIC_PLAY_COMMAND_SIZE); +STATIC_ASSERT(sizeof(RedTickHistory) == REDSOUND_TICK_HISTORY_SIZE); +STATIC_ASSERT(sizeof(((RedTickHistory*)0)->m_ticks) == REDSOUND_TICK_HISTORY_SIZE); +STATIC_ASSERT(offsetof(RedControlRamp, m_value) == REDSOUND_CONTROL_RAMP_VALUE_OFFSET); +STATIC_ASSERT(offsetof(RedControlRamp, m_step) == REDSOUND_CONTROL_RAMP_STEP_OFFSET); +STATIC_ASSERT(offsetof(RedControlRamp, m_count) == REDSOUND_CONTROL_RAMP_COUNT_OFFSET); +STATIC_ASSERT(sizeof(RedControlRamp) == REDSOUND_CONTROL_RAMP_SIZE); +STATIC_ASSERT(offsetof(RedReverbDepth, m_depth) == REDSOUND_REVERB_DEPTH_DEPTH_OFFSET); +STATIC_ASSERT(offsetof(RedReverbDepth, m_step) == REDSOUND_REVERB_DEPTH_STEP_OFFSET); +STATIC_ASSERT(offsetof(RedReverbDepth, m_count) == REDSOUND_REVERB_DEPTH_COUNT_OFFSET); +STATIC_ASSERT(sizeof(RedReverbDepth) == REDSOUND_REVERB_DEPTH_SIZE); +STATIC_ASSERT(offsetof(RedDriverSmallDataPrefixState, m_redMasterTime) == REDSOUND_DRIVER_SBSS_MASTER_TIME_OFFSET); +STATIC_ASSERT(offsetof(RedDriverSmallDataPrefixState, m_dmaControlNow) == REDSOUND_DRIVER_SBSS_DMA_NOW_OFFSET); +STATIC_ASSERT(sizeof(((RedDriverSmallDataPrefixState*)0)->m_dmaControlNow) == + REDSOUND_DMA_QUEUE_COUNT * sizeof(RedDmaRequest*)); +STATIC_ASSERT(sizeof(((RedDriverSmallDataPrefixState*)0)->m_dmaControlOld) == + REDSOUND_DMA_QUEUE_COUNT * sizeof(RedDmaRequest*)); +STATIC_ASSERT(offsetof(RedDriverSmallDataPrefixState, m_soundControlBuffer) == + REDSOUND_DRIVER_SBSS_SOUND_CONTROL_BUFFER_OFFSET); +STATIC_ASSERT(offsetof(RedDriverSmallDataPrefixState, m_musicReplayPoint) == + REDSOUND_DRIVER_SBSS_MUSIC_REPLAY_POINT_OFFSET); +STATIC_ASSERT(offsetof(RedDriverSmallDataPrefixState, m_stream) == REDSOUND_DRIVER_SBSS_STREAM_OFFSET); +STATIC_ASSERT(offsetof(RedDriverSmallDataPrefixState, m_voiceData) == REDSOUND_DRIVER_SBSS_VOICE_DATA_OFFSET); +STATIC_ASSERT(offsetof(RedDriverSmallDataPrefixState, m_editorVoice) == REDSOUND_DRIVER_SBSS_EDITOR_VOICE_OFFSET); +STATIC_ASSERT(sizeof(((RedDriverSmallDataPrefixState*)0)->m_editorVoice) == + REDSOUND_EDITOR_VOICE_COUNT * sizeof(int)); +STATIC_ASSERT(offsetof(RedDriverSmallDataPrefixState, m_mute) == REDSOUND_DRIVER_SBSS_MUTE_OFFSET); +STATIC_ASSERT(sizeof(((RedDriverSmallDataPrefixState*)0)->m_mute) == REDSOUND_MUTE_WORD_COUNT * sizeof(int)); +STATIC_ASSERT(sizeof(RedDriverSmallDataPrefixState) == REDSOUND_DRIVER_SBSS_BEFORE_RED_MEMORY_SIZE); +STATIC_ASSERT(sizeof(CRedMemory) == REDSOUND_RED_MEMORY_SIZE); +STATIC_ASSERT(sizeof(CRedEntry) == REDSOUND_RED_ENTRY_SIZE); +STATIC_ASSERT(sizeof(p_SeBlockData) == REDSOUND_SE_BLOCK_DATA_TABLE_SIZE); +STATIC_ASSERT(offsetof(RedDriverSmallDataTailState, m_redMemory) == REDSOUND_DRIVER_SBSS_RED_MEMORY_OFFSET); +STATIC_ASSERT(offsetof(RedDriverSmallDataTailState, m_redMemoryAlignPadding) == + REDSOUND_DRIVER_SBSS_RED_MEMORY_PAD_OFFSET); +STATIC_ASSERT(sizeof(((RedDriverSmallDataTailState*)0)->m_redMemoryAlignPadding) == + REDSOUND_DRIVER_SBSS_RED_MEMORY_PAD_SIZE); +STATIC_ASSERT(offsetof(RedDriverSmallDataTailState, m_dmaExecute) == REDSOUND_DRIVER_SBSS_DMA_EXECUTE_OFFSET); +STATIC_ASSERT(offsetof(RedDriverSmallDataTailState, m_dmaInThread) == REDSOUND_DRIVER_SBSS_DMA_IN_THREAD_OFFSET); +STATIC_ASSERT(sizeof(((RedDriverSmallDataTailState*)0)->m_trailingPadding) == + REDSOUND_DRIVER_SBSS_TRAILING_PAD_SIZE); +STATIC_ASSERT(sizeof(RedDriverSmallDataTailState) == REDSOUND_DRIVER_SBSS_SIZE); + enum RedDriverBufferSize { REDSOUND_ZERO_BUFFER_SIZE = 0x1000, REDSOUND_THREAD_STACK_SIZE = 0x1000, @@ -181,18 +477,38 @@ enum RedDriverBufferSize { REDSOUND_WAVE_SETTING_TABLE_ALIGN_MASK = ~(REDSOUND_WAVE_SETTING_TABLE_ALIGN - 1), REDSOUND_MUSIC_REPLAY_POINT_COUNT = 0x100, REDSOUND_MUSIC_REPLAY_POINT_SIZE = sizeof(int) * REDSOUND_MUSIC_REPLAY_POINT_COUNT, + REDSOUND_MUSIC_REPLAY_POINT_ALLOC_SIZE = 0x400, REDSOUND_EXEC_COMMAND_COUNT = 0x100, REDSOUND_EXEC_COMMAND_BUFFER_SIZE = sizeof(RedExecCommand) * REDSOUND_EXEC_COMMAND_COUNT, + REDSOUND_EXEC_COMMAND_ALLOC_SIZE = 0x2000, REDSOUND_EXEC_COMMAND_WORD_COUNT = REDSOUND_EXEC_COMMAND_BUFFER_SIZE / sizeof(int), REDSOUND_MUSIC_NEXT_PLAY_BUFFER_SIZE = sizeof(RedMusicPlayCommand), + REDSOUND_SOUND_CONTROL_ALLOC_SIZE = 0x1250, + REDSOUND_KEY_ON_ALLOC_SIZE = 0x600, + REDSOUND_VOICE_ALLOC_SIZE = 0x3000, + REDSOUND_SE_TRACK_ARENA_ALLOC_SIZE = 0x2A80, + REDSOUND_REVERB_DEPTH_ALLOC_SIZE = 0x18, + REDSOUND_MUSIC_NEXT_PLAY_ALLOC_SIZE = 0x10, + REDSOUND_STREAM_ALLOC_SIZE = 0x4C0, }; +STATIC_ASSERT(sizeof(int) * REDSOUND_MUSIC_REPLAY_POINT_COUNT == REDSOUND_MUSIC_REPLAY_POINT_ALLOC_SIZE); +STATIC_ASSERT(sizeof(RedExecCommand) * REDSOUND_EXEC_COMMAND_COUNT == REDSOUND_EXEC_COMMAND_ALLOC_SIZE); +STATIC_ASSERT(sizeof(RedSoundCONTROL) * REDSOUND_CONTROL_COUNT == REDSOUND_SOUND_CONTROL_ALLOC_SIZE); +STATIC_ASSERT(sizeof(RedKeyOnDATA) == REDSOUND_KEY_ON_ALLOC_SIZE); +STATIC_ASSERT(sizeof(RedVoiceDATA) * REDSOUND_VOICE_COUNT == REDSOUND_VOICE_ALLOC_SIZE); +STATIC_ASSERT(sizeof(RedTrackDATA) * REDSOUND_SE_TRACK_COUNT == REDSOUND_SE_TRACK_ARENA_ALLOC_SIZE); +STATIC_ASSERT(sizeof(RedReverbDepth) * REDSOUND_REVERB_DEPTH_COUNT == REDSOUND_REVERB_DEPTH_ALLOC_SIZE); +STATIC_ASSERT(sizeof(RedMusicPlayCommand) == REDSOUND_MUSIC_NEXT_PLAY_ALLOC_SIZE); +STATIC_ASSERT(sizeof(RedStreamDATA) * REDSOUND_STREAM_COUNT == REDSOUND_STREAM_ALLOC_SIZE); + enum RedDriverEditorVoiceIndex { REDSOUND_EDITOR_VOICE_LEFT = 0, REDSOUND_EDITOR_VOICE_RIGHT = 1, }; enum RedDriverThreadFlag { + REDSOUND_THREAD_FLAG_NONE = 0, REDSOUND_THREAD_FLAG_MAIN = 1, REDSOUND_THREAD_FLAG_DMA = 2, REDSOUND_THREAD_FLAG_WAVE_SETTING = 4, @@ -203,26 +519,12 @@ enum RedDriverThreadConfig { REDSOUND_DMA_THREAD_PRIORITY = 3, REDSOUND_WORKER_THREAD_PRIORITY = 4, REDSOUND_THREAD_DETACHED = 1, + REDSOUND_THREAD_YIELD_SLEEP_US = 0, }; -enum RedDriverHeaderSignature { - REDSOUND_MUSIC_SIGNATURE_0 = 'B', - REDSOUND_MUSIC_SIGNATURE_1 = 'G', - REDSOUND_MUSIC_SIGNATURE_2 = 'M', - REDSOUND_SE_BLOCK_SIGNATURE_0 = 'S', - REDSOUND_SE_BLOCK_SIGNATURE_1 = 'e', - REDSOUND_SE_BLOCK_SIGNATURE_2 = 'B', - REDSOUND_SE_BLOCK_SIGNATURE_3 = 'l', - REDSOUND_SE_BLOCK_SIGNATURE_4 = 'o', - REDSOUND_SE_BLOCK_SIGNATURE_5 = 'c', - REDSOUND_SE_BLOCK_SIGNATURE_6 = 'k', - REDSOUND_SESEP_SIGNATURE_0 = 'S', - REDSOUND_SESEP_SIGNATURE_1 = 'e', - REDSOUND_SESEP_SIGNATURE_2 = 'S', - REDSOUND_SESEP_SIGNATURE_3 = 'e', - REDSOUND_SESEP_SIGNATURE_4 = 'p', - REDSOUND_WAVE_SIGNATURE_0 = 'W', - REDSOUND_WAVE_SIGNATURE_1 = 'D', +enum RedDriverSleepTimer { + REDSOUND_SLEEP_TIMER_DIVISOR = 125000, + REDSOUND_SLEEP_TIMER_SHIFT = 3, }; enum RedDriverCommandParse { @@ -278,7 +580,8 @@ static volatile int m_DMAStatus; u8* volatile p_MusicSkipThreadStack; volatile int m_MusicSkipComplete; RedReverbDepth* volatile p_ReverbDepth; -int m_Mute[REDSOUND_MUTE_WORD_COUNT]; +unsigned int m_Mute[REDSOUND_MUTE_WORD_COUNT]; +static int m_SilentWave; static RedDmaRequest m_DmaControl[REDSOUND_DMA_CONTROL_ENTRY_COUNT]; static OSThread m_MainThread; static OSSemaphore m_MainSemaphore; @@ -296,6 +599,29 @@ static volatile int m_DMAExecute; static volatile int m_DMAInThread; CRedEntry c_RedEntry; +STATIC_ASSERT(sizeof(m_RedMasterTime) + sizeof(m_SequencialID) + sizeof(m_ThreadControl) + + sizeof(m_ThreadExecute) + sizeof(m_SoundMode) + sizeof(p_Tick) + + sizeof(p_ZeroData) + sizeof(p_ExecCommand) + sizeof(p_ExecCommandNow) + + sizeof(p_ExecCommandOld) + sizeof(p_DmaControlNow) + sizeof(p_DmaControlOld) + + sizeof(p_SoundControlBuffer) + sizeof(p_SoundControl) + sizeof(m_KeyOnEntry) + + sizeof(p_KeyOnData) + sizeof(m_SoundPlayMode) + sizeof(m_SoundMasterControl) + + sizeof(m_ReportPrint) + sizeof(m_MusicFastSpeed) + sizeof(m_MusicSkipLine) + + sizeof(m_MusicKeySignature) + sizeof(p_MusicReplayPoint) + + sizeof(p_MusicTempoControl) + sizeof(p_MusicPitchControl) + + sizeof(m_MusicPhraseStop) + sizeof(p_MusicNextPlay) + sizeof(m_CrossTime) + + sizeof(m_MasterMusicVolume) + sizeof(m_MasterSEVolume) + sizeof(p_Stream) + + sizeof(m_DMAMode) + sizeof(m_SeSkipStep) + sizeof(p_VoiceData) + + sizeof(p_EditorVoice) + sizeof(p_EditorTrack) + sizeof(p_MainThreadStack) + + sizeof(m_MainThreadTime) + sizeof(p_WaveSettingThreadStack) + + sizeof(m_WaveSettingStatus) + sizeof(p_DmaExecuteThreadStack) + + sizeof(m_DMAStatus) + sizeof(p_MusicSkipThreadStack) + + sizeof(m_MusicSkipComplete) + sizeof(p_ReverbDepth) + sizeof(m_Mute) == + REDSOUND_DRIVER_SBSS_BEFORE_RED_MEMORY_SIZE); +STATIC_ASSERT(REDSOUND_DRIVER_SBSS_BEFORE_RED_MEMORY_SIZE + sizeof(c_RedMemory) + + REDSOUND_DRIVER_SBSS_RED_MEMORY_PAD_SIZE + sizeof(m_DMAExecute) + + sizeof(m_DMAInThread) + REDSOUND_DRIVER_SBSS_TRAILING_PAD_SIZE == + REDSOUND_DRIVER_SBSS_SIZE); + static inline RedDriverSyncState& RedDriverSync() { return *reinterpret_cast(m_DmaControl); @@ -330,6 +656,20 @@ static const char sRedDriverSeSepHeaderErrorFmt[] = "%s%sSE-Sep-Header was broke static const char sRedDriverLogWarnColor[] = "\x1B[4;31m"; static const char sRedDriverLogReset[] = "\x1B[0m"; +STATIC_ASSERT(sizeof(s_redDriverDmaCheckHeaderFmt) == REDSOUND_DRIVER_DMA_CHECK_HEADER_SIZE); +STATIC_ASSERT(sizeof(sRedDriverLogPrefix) == REDSOUND_DRIVER_LOG_PREFIX_SIZE); +STATIC_ASSERT(sizeof(sRedDriverDmaStatusFmt) == REDSOUND_DRIVER_DMA_STATUS_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedDriverDmaEntryFmt) == REDSOUND_DRIVER_DMA_ENTRY_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedDriverMusicHeaderErrorFmt) == REDSOUND_DRIVER_MUSIC_HEADER_ERROR_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedDriverSeSepHeaderErrorFmt) == REDSOUND_DRIVER_SE_SEP_HEADER_ERROR_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedDriverLogWarnColor) == REDSOUND_DRIVER_LOG_WARN_COLOR_SIZE); +STATIC_ASSERT(sizeof(sRedDriverLogReset) == REDSOUND_DRIVER_LOG_RESET_SIZE); +STATIC_ASSERT(sizeof(s_redDriverDmaCheckHeaderFmt) + sizeof(sRedDriverLogPrefix) + + sizeof(sRedDriverDmaStatusFmt) + sizeof(sRedDriverDmaEntryFmt) + + sizeof(sRedDriverMusicHeaderErrorFmt) + sizeof(sRedDriverSeSepHeaderErrorFmt) == + REDSOUND_DRIVER_RODATA_SIZE); +STATIC_ASSERT(sizeof(sRedDriverLogWarnColor) + sizeof(sRedDriverLogReset) == REDSOUND_DRIVER_SDATA2_SIZE); + /* * --INFO-- * PAL Address: 0x801bcf0c @@ -342,18 +682,18 @@ static const char sRedDriverLogReset[] = "\x1B[0m"; static void _SetSoundMode(int* command) { m_SoundMode = command[REDSOUND_SOUND_MODE_COMMAND_MODE]; - if (command[REDSOUND_SOUND_MODE_COMMAND_MODE] == 1) { - OSGetSoundMode(0); + if (command[REDSOUND_SOUND_MODE_COMMAND_MODE] == REDSOUND_SOUND_MODE_MONO) { + OSGetSoundMode(OS_SOUND_MODE_MONO); } else { - OSGetSoundMode(1); + OSGetSoundMode(OS_SOUND_MODE_STEREO); } m_SoundPlayMode = m_SoundMode; switch (m_SoundPlayMode) { - case 2: - AXSetMode(2); + case REDSOUND_SOUND_MODE_SURROUND: + AXSetMode(REDSOUND_SOUND_MODE_SURROUND); break; default: - AXSetMode(0); + AXSetMode(REDSOUND_SOUND_MODE_STEREO); break; } } @@ -419,6 +759,24 @@ static void _SetMusicData(int* command) c_RedEntry.SetMusicData((RedMusicHEAD*)command[REDSOUND_DATA_COMMAND_BUFFER]); } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 56b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +static void _ClearMusicData(int* command) +{ + c_RedEntry.ClearMusicData(command[REDSOUND_MUSIC_COMMAND_ID]); +} + +static void _MusicPlaySequence(int* command); +static void _MusicCrossPlaySequence(int* command); +static void _MusicNextPlaySequence(int* command); + /* * --INFO-- * PAL Address: 0x801bd080 @@ -431,12 +789,12 @@ static void _SetMusicData(int* command) static void _MusicStop(int* command) { MusicStop(command[REDSOUND_MUSIC_COMMAND_ID]); - if ((command[REDSOUND_MUSIC_COMMAND_ID] == -1) || + if ((command[REDSOUND_MUSIC_COMMAND_ID] == REDSOUND_MUSIC_ID_NONE) || (p_MusicNextPlay->m_musicId == command[REDSOUND_MUSIC_COMMAND_ID])) { - p_MusicNextPlay->m_musicId = -1; + p_MusicNextPlay->m_musicId = REDSOUND_MUSIC_ID_NONE; } - if (p_MusicNextPlay->m_musicId < 0) { - m_MusicPhraseStop = 0; + if (p_MusicNextPlay->m_musicId < REDSOUND_MUSIC_ID_MIN) { + m_MusicPhraseStop = REDSOUND_MUSIC_PHRASE_STOP_OFF; } } @@ -462,8 +820,8 @@ static void _MusicPlaySequence(int* command) } if (c_RedEntry.SearchMusicSequence(command[REDSOUND_MUSIC_COMMAND_ID]) >= 0) { replayPoint = command[REDSOUND_MUSIC_COMMAND_MODE]; - if (soundControl[REDSOUND_CONTROL_MUSIC_PRIMARY].m_musicId != -1) { - if (soundControl[REDSOUND_CONTROL_MUSIC_SECONDARY].m_musicId != -1) { + if (soundControl[REDSOUND_CONTROL_MUSIC_PRIMARY].m_musicId != REDSOUND_MUSIC_ID_NONE) { + if (soundControl[REDSOUND_CONTROL_MUSIC_SECONDARY].m_musicId != REDSOUND_MUSIC_ID_NONE) { MusicStop(soundControl[REDSOUND_CONTROL_MUSIC_SECONDARY].m_musicId); } if (replayPoint == 0) { @@ -472,7 +830,7 @@ static void _MusicPlaySequence(int* command) } if (replayPoint == 0) { memcpy(&soundControl[REDSOUND_CONTROL_MUSIC_SECONDARY], soundControl, REDSOUND_CONTROL_SIZE); - soundControl[REDSOUND_CONTROL_MUSIC_PRIMARY].m_musicId = -1; + soundControl[REDSOUND_CONTROL_MUSIC_PRIMARY].m_musicId = REDSOUND_MUSIC_ID_NONE; } } MusicPlay(command[REDSOUND_MUSIC_COMMAND_ID], command[REDSOUND_MUSIC_COMMAND_VOLUME], replayPoint); @@ -490,9 +848,9 @@ static void _MusicPlaySequence(int* command) */ static void _MusicCrossPlaySequence(int* command) { - int replayPoint; RedSoundCONTROL* control; RedSoundCONTROL* swapControl; + int replayPoint; command[REDSOUND_MUSIC_COMMAND_FADE_TIME] = command[REDSOUND_MUSIC_COMMAND_FADE_TIME] * REDSOUND_MUSIC_FADE_TICKS_PER_SECOND; @@ -502,45 +860,47 @@ static void _MusicCrossPlaySequence(int* command) command[REDSOUND_MUSIC_COMMAND_FADE_TIME] = command[REDSOUND_MUSIC_COMMAND_FADE_TIME] + 1; } control = p_SoundControlBuffer; - if ((command[REDSOUND_MUSIC_COMMAND_ID] != control[REDSOUND_CONTROL_MUSIC_PRIMARY].m_musicId) && - (command[REDSOUND_MUSIC_COMMAND_ID] != control[REDSOUND_CONTROL_MUSIC_SKIP].m_musicId)) { - if (command[REDSOUND_MUSIC_COMMAND_ID] == control[REDSOUND_CONTROL_MUSIC_SECONDARY].m_musicId) { - control[REDSOUND_CONTROL_MUSIC_PRIMARY].m_masterVolumeAdd = - -control[REDSOUND_CONTROL_MUSIC_PRIMARY].m_masterVolume / command[REDSOUND_MUSIC_COMMAND_FADE_TIME]; - control[REDSOUND_CONTROL_MUSIC_PRIMARY].m_masterVolumeDelta = command[REDSOUND_MUSIC_COMMAND_FADE_TIME]; - control = p_SoundControlBuffer; - control[REDSOUND_CONTROL_MUSIC_SECONDARY].m_masterVolumeAdd = - (REDSOUND_MASTER_VOLUME_FULL_FIXED_HALF - - control[REDSOUND_CONTROL_MUSIC_SECONDARY].m_masterVolume) / - command[REDSOUND_MUSIC_COMMAND_FADE_TIME]; - control[REDSOUND_CONTROL_MUSIC_SECONDARY].m_masterVolumeDelta = command[REDSOUND_MUSIC_COMMAND_FADE_TIME]; - swapControl = (RedSoundCONTROL*)RedNew(REDSOUND_CONTROL_SIZE); - memcpy(swapControl, &p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_SECONDARY], REDSOUND_CONTROL_SIZE); - memcpy(&p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_SECONDARY], p_SoundControlBuffer, - REDSOUND_CONTROL_SIZE); - memcpy(p_SoundControlBuffer, swapControl, REDSOUND_CONTROL_SIZE); - RedDelete(swapControl); - } else { - if (c_RedEntry.SearchMusicSequence(command[REDSOUND_MUSIC_COMMAND_ID]) >= 0) { - m_CrossTime = command[REDSOUND_MUSIC_COMMAND_FADE_TIME]; - replayPoint = 0; - if (control[REDSOUND_CONTROL_MUSIC_PRIMARY].m_musicId != -1) { - if (control[REDSOUND_CONTROL_MUSIC_SECONDARY].m_musicId != -1) { - MusicStop(control[REDSOUND_CONTROL_MUSIC_SECONDARY].m_musicId); - } - control[REDSOUND_CONTROL_MUSIC_PRIMARY].m_masterVolumeAdd = - -control[REDSOUND_CONTROL_MUSIC_PRIMARY].m_masterVolume / - command[REDSOUND_MUSIC_COMMAND_FADE_TIME]; - control[REDSOUND_CONTROL_MUSIC_PRIMARY].m_masterVolumeDelta = command[REDSOUND_MUSIC_COMMAND_FADE_TIME]; - replayPoint = p_MusicReplayPoint[command[REDSOUND_MUSIC_COMMAND_ID]]; - p_MusicReplayPoint[command[REDSOUND_MUSIC_COMMAND_ID]] = 0; - if (replayPoint == 0) { - memcpy(&control[REDSOUND_CONTROL_MUSIC_SECONDARY], control, REDSOUND_CONTROL_SIZE); - control[REDSOUND_CONTROL_MUSIC_PRIMARY].m_musicId = -1; - } + if ((command[REDSOUND_MUSIC_COMMAND_ID] == control[REDSOUND_CONTROL_MUSIC_PRIMARY].m_musicId) || + (command[REDSOUND_MUSIC_COMMAND_ID] == control[REDSOUND_CONTROL_MUSIC_SKIP].m_musicId)) { + return; + } + + if (command[REDSOUND_MUSIC_COMMAND_ID] == control[REDSOUND_CONTROL_MUSIC_SECONDARY].m_musicId) { + control[REDSOUND_CONTROL_MUSIC_PRIMARY].m_masterVolumeAdd = + -control[REDSOUND_CONTROL_MUSIC_PRIMARY].m_masterVolume / command[REDSOUND_MUSIC_COMMAND_FADE_TIME]; + control[REDSOUND_CONTROL_MUSIC_PRIMARY].m_masterVolumeDelta = command[REDSOUND_MUSIC_COMMAND_FADE_TIME]; + control = p_SoundControlBuffer + REDSOUND_CONTROL_MUSIC_SECONDARY; + control->m_masterVolumeAdd = + (REDSOUND_MASTER_VOLUME_FULL_FIXED_HALF - + control->m_masterVolume) / + command[REDSOUND_MUSIC_COMMAND_FADE_TIME]; + control->m_masterVolumeDelta = command[REDSOUND_MUSIC_COMMAND_FADE_TIME]; + swapControl = (RedSoundCONTROL*)RedNew(REDSOUND_CONTROL_SIZE); + memcpy(swapControl, &p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_SECONDARY], REDSOUND_CONTROL_SIZE); + memcpy(&p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_SECONDARY], p_SoundControlBuffer, + REDSOUND_CONTROL_SIZE); + memcpy(p_SoundControlBuffer, swapControl, REDSOUND_CONTROL_SIZE); + RedDelete(swapControl); + } else { + if (c_RedEntry.SearchMusicSequence(command[REDSOUND_MUSIC_COMMAND_ID]) >= 0) { + m_CrossTime = command[REDSOUND_MUSIC_COMMAND_FADE_TIME]; + replayPoint = 0; + if (control[REDSOUND_CONTROL_MUSIC_PRIMARY].m_musicId != REDSOUND_MUSIC_ID_NONE) { + if (control[REDSOUND_CONTROL_MUSIC_SECONDARY].m_musicId != REDSOUND_MUSIC_ID_NONE) { + MusicStop(control[REDSOUND_CONTROL_MUSIC_SECONDARY].m_musicId); + } + control[REDSOUND_CONTROL_MUSIC_PRIMARY].m_masterVolumeAdd = + -control[REDSOUND_CONTROL_MUSIC_PRIMARY].m_masterVolume / + command[REDSOUND_MUSIC_COMMAND_FADE_TIME]; + control[REDSOUND_CONTROL_MUSIC_PRIMARY].m_masterVolumeDelta = command[REDSOUND_MUSIC_COMMAND_FADE_TIME]; + replayPoint = p_MusicReplayPoint[command[REDSOUND_MUSIC_COMMAND_ID]]; + p_MusicReplayPoint[command[REDSOUND_MUSIC_COMMAND_ID]] = 0; + if (replayPoint == 0) { + memcpy(&control[REDSOUND_CONTROL_MUSIC_SECONDARY], control, REDSOUND_CONTROL_SIZE); + control[REDSOUND_CONTROL_MUSIC_PRIMARY].m_musicId = REDSOUND_MUSIC_ID_NONE; } - MusicPlay(command[REDSOUND_MUSIC_COMMAND_ID], command[REDSOUND_MUSIC_COMMAND_VOLUME], replayPoint); } + MusicPlay(command[REDSOUND_MUSIC_COMMAND_ID], command[REDSOUND_MUSIC_COMMAND_VOLUME], replayPoint); } } } @@ -608,14 +968,53 @@ static void _MusicMasterVolume(int* command) */ static void _MusicVolume(int* command) { - if (command[REDSOUND_MUSIC_COMMAND_STOP_NEXT] == 1) { - p_MusicNextPlay->m_musicId = -1; - m_MusicPhraseStop = 0; + if (command[REDSOUND_MUSIC_COMMAND_STOP_NEXT] == REDSOUND_MUSIC_VOLUME_MODE_FADE_OUT) { + p_MusicNextPlay->m_musicId = REDSOUND_MUSIC_ID_NONE; + m_MusicPhraseStop = REDSOUND_MUSIC_PHRASE_STOP_OFF; } SetMusicVolume(command[REDSOUND_MUSIC_COMMAND_ID], command[REDSOUND_MUSIC_COMMAND_VOLUME], command[REDSOUND_MUSIC_COMMAND_FADE_TIME], command[REDSOUND_MUSIC_COMMAND_STOP_NEXT]); } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 52b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +static void _MusicTempo(int* command) +{ + SetMusicTempo(command[REDSOUND_MUSIC_COMMAND_VOLUME], command[REDSOUND_MUSIC_COMMAND_FADE_TIME]); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 52b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +static void _MusicPitch(int* command) +{ + SetMusicPitch(command[REDSOUND_MUSIC_COMMAND_VOLUME], command[REDSOUND_MUSIC_COMMAND_FADE_TIME]); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 52b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +static void _MusicPause(int* command) +{ + MusicPause(command[REDSOUND_MUSIC_COMMAND_ID], command[REDSOUND_MUSIC_COMMAND_VOLUME]); +} + /* * --INFO-- * PAL Address: 0x801bd578 @@ -641,7 +1040,7 @@ static void _SetMusicPhraseStop(int* command) */ static void _SetSeBlockData(int* command) { - u32 index = (u32)command[REDSOUND_SE_BLOCK_DATA_COMMAND_BANK] & 3; + u32 index = (u32)command[REDSOUND_SE_BLOCK_DATA_COMMAND_BANK] & REDSOUND_SE_BLOCK_BANK_MASK; char* seBlockData; if (p_SeBlockData[index] != 0) { @@ -719,6 +1118,19 @@ static void _SeStop(int* command) SeStopID(command[REDSOUND_SE_COMMAND_ID]); } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 48b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +static void _SeStopG(int* command) +{ + SeStopG(command[REDSOUND_SE_COMMAND_ID]); +} + /* * --INFO-- * PAL Address: 0x801bd794 @@ -921,6 +1333,20 @@ static void _StreamVolume(int* command) command[REDSOUND_STREAM_COMMAND_FADE_TIME]); } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 56b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +static void _StreamPan(int* command) +{ + SetStreamPan(command[REDSOUND_STREAM_COMMAND_ID], command[REDSOUND_STREAM_COMMAND_PAN], + command[REDSOUND_STREAM_COMMAND_FADE_TIME]); +} + /* * --INFO-- * PAL Address: 0x801bdadc @@ -944,8 +1370,8 @@ static void _StreamPause(int* command) * JP Address: TODO * JP Size: TODO */ -static RedExecCommand* _EntryExecCommand(void (*func)(int*), int arg1, int arg2, int arg3, int arg4, - int arg5, int arg6, int arg7) +static RedExecCommand* _EntryExecCommand(RedExecCommandFunc func, int arg1, int arg2, int arg3, int arg4, + int arg5, int arg6, int arg7) { unsigned int interruptLevel; RedExecCommand* writePos; @@ -953,13 +1379,13 @@ static RedExecCommand* _EntryExecCommand(void (*func)(int*), int arg1, int arg2, interruptLevel = OSDisableInterrupts(); writePos = p_ExecCommandNow; writePos->m_func = func; - writePos->m_args[0] = arg1; - writePos->m_args[1] = arg2; - writePos->m_args[2] = arg3; - writePos->m_args[3] = arg4; - writePos->m_args[4] = arg5; - writePos->m_args[5] = arg6; - writePos->m_args[6] = arg7; + writePos->m_args[REDSOUND_EXEC_COMMAND_ARG0] = arg1; + writePos->m_args[REDSOUND_EXEC_COMMAND_ARG1] = arg2; + writePos->m_args[REDSOUND_EXEC_COMMAND_ARG2] = arg3; + writePos->m_args[REDSOUND_EXEC_COMMAND_ARG3] = arg4; + writePos->m_args[REDSOUND_EXEC_COMMAND_ARG4] = arg5; + writePos->m_args[REDSOUND_EXEC_COMMAND_ARG5] = arg6; + writePos->m_args[REDSOUND_EXEC_COMMAND_ARG6] = arg7; writePos++; if (writePos == p_ExecCommand + REDSOUND_EXEC_COMMAND_COUNT) { writePos = p_ExecCommand; @@ -1083,7 +1509,9 @@ void RedSleep(int microseconds) interruptLevel = OSDisableInterrupts(); alarm.m_thread = OSGetCurrentThread(); OSCreateAlarm(&alarm.m_alarm); - OSSetAlarm(&alarm.m_alarm, (microseconds * (OS_TIMER_CLOCK / 125000)) >> 3, _MyAlarmHandler); + OSSetAlarm(&alarm.m_alarm, + (microseconds * (OS_TIMER_CLOCK / REDSOUND_SLEEP_TIMER_DIVISOR)) >> REDSOUND_SLEEP_TIMER_SHIFT, + _MyAlarmHandler); OSSuspendThread(alarm.m_thread); OSRestoreInterrupts(interruptLevel); } @@ -1106,9 +1534,9 @@ static int _MainThread(void*) unsigned int elapsed; m_ThreadExecute = m_ThreadExecute | REDSOUND_THREAD_FLAG_MAIN; - while (m_ThreadControl != 0) { + while (m_ThreadControl != REDSOUND_THREAD_CONTROL_STOP) { OSWaitSemaphore(&m_MainSemaphore); - if (m_ThreadControl != 0) { + if (m_ThreadControl != REDSOUND_THREAD_CONTROL_STOP) { startTick = OSGetTick(); control = p_SoundControlBuffer; masterTime = m_RedMasterTime; @@ -1123,10 +1551,11 @@ static int _MainThread(void*) MainControl(elapsed); StreamControl(); _ExecuteCommand(); - if ((p_MusicNextPlay->m_musicId >= 0) && (control->m_musicId < 0)) { + if ((p_MusicNextPlay->m_musicId >= REDSOUND_MUSIC_ID_MIN) && + (control->m_musicId < REDSOUND_MUSIC_ID_MIN)) { _MusicPlaySequence((int*)p_MusicNextPlay); - p_MusicNextPlay->m_musicId = -1; - m_MusicPhraseStop = 0; + p_MusicNextPlay->m_musicId = REDSOUND_MUSIC_ID_NONE; + m_MusicPhraseStop = REDSOUND_MUSIC_PHRASE_STOP_OFF; } while (OSTryWaitSemaphore(&m_MainSemaphore) > 0) { } @@ -1151,17 +1580,17 @@ static int _MainThread(void*) static int _WaveSettingThread(void* threadArg) { m_ThreadExecute = m_ThreadExecute | REDSOUND_THREAD_FLAG_WAVE_SETTING; - m_WaveSettingStatus = 0; - while (m_ThreadControl != 0) { + m_WaveSettingStatus = REDSOUND_WORKER_IDLE; + while (m_ThreadControl != REDSOUND_THREAD_CONTROL_STOP) { OSWaitSemaphore(&m_WaveSettingSemaphore); - if (m_ThreadControl != 0) { + if (m_ThreadControl != REDSOUND_THREAD_CONTROL_STOP) { RedWaveSettingState* waveSetting = (RedWaveSettingState*)threadArg; m_WaveSettingStatus = m_WaveSettingStatus + 1; c_RedEntry.SetWaveData(waveSetting->m_waveId, waveSetting->m_waveData, waveSetting->m_waveSize); *waveSetting->m_slot = 0; do { } while (OSTryWaitSemaphore(&m_WaveSettingSemaphore) > 0); - m_WaveSettingStatus = 0; + m_WaveSettingStatus = REDSOUND_WORKER_IDLE; } } m_ThreadExecute = m_ThreadExecute & ~REDSOUND_THREAD_FLAG_WAVE_SETTING; @@ -1181,7 +1610,7 @@ static void _DMACheckProcess() { RedDmaRequest* dmaInfo; - if (m_ReportPrint != 0) { + if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { OSReport(s_redDriverDmaCheckHeaderFmt, sRedDriverLogPrefix); fflush(__files + 1); @@ -1192,7 +1621,7 @@ static void _DMACheckProcess() dmaInfo = RedDriverMainDmaQueue(); do { - if ((dmaInfo->m_id != 0) && (m_ReportPrint != 0)) { + if ((dmaInfo->m_id != 0) && (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF)) { OSReport(sRedDriverDmaEntryFmt, sRedDriverLogPrefix, dmaInfo->m_id, dmaInfo->m_mainMemory, dmaInfo->m_aramMemory, dmaInfo->m_size, dmaInfo->m_callback); @@ -1215,7 +1644,7 @@ static void _DMACheckProcess() */ static void _DmaCallback(unsigned long) { - m_DMAStatus = 0; + m_DMAStatus = REDSOUND_DMA_STATUS_IDLE; } /* @@ -1227,7 +1656,7 @@ static void _DmaCallback(unsigned long) * JP Address: TODO * JP Size: TODO */ -int RedDmaEntry(int flags, int direction, int mainMemory, int aramMemory, int sizeBytes, void (*callback)(void*), +int RedDmaEntry(int flags, int direction, int mainMemory, int aramMemory, int sizeBytes, RedDmaCallback callback, void* callbackData) { unsigned int interrupt; @@ -1235,8 +1664,8 @@ int RedDmaEntry(int flags, int direction, int mainMemory, int aramMemory, int si RedDmaRequest* volatile* queuePtr; unsigned int entryID; int chunkSize; + int transferSize; RedDmaRequest* queueEntry; - RedDmaRequest* queueEnd; interrupt = OSDisableInterrupts(); if ((flags & REDSOUND_DMA_FLAG_QUEUE_MASK) != 0) { @@ -1248,22 +1677,24 @@ int RedDmaEntry(int flags, int direction, int mainMemory, int aramMemory, int si } queueEntry = *queuePtr; entryID = GetMyEntryID(); - sizeBytes = (sizeBytes + REDSOUND_DMA_TRANSFER_ALIGN - 1) & REDSOUND_DMA_TRANSFER_ALIGN_MASK; + sizeBytes += REDSOUND_DMA_TRANSFER_ALIGN - 1; + sizeBytes &= REDSOUND_DMA_TRANSFER_ALIGN_MASK; if ((m_DMAMode != 0) || ((flags & REDSOUND_DMA_FLAG_CHUNKED_TRANSFER) != 0)) { - queueEnd = queueBase + REDSOUND_DMA_QUEUE_ENTRY_COUNT; do { - chunkSize = sizeBytes; if (sizeBytes > REDSOUND_DMA_MAX_CHUNK_SIZE) { chunkSize = REDSOUND_DMA_MAX_CHUNK_SIZE; + } else { + chunkSize = sizeBytes; } queueEntry->m_id = entryID; - sizeBytes -= chunkSize; + transferSize = chunkSize; + sizeBytes -= transferSize; queueEntry->m_direction = direction; queueEntry->m_mainMemory = mainMemory; - mainMemory += chunkSize; + mainMemory += transferSize; queueEntry->m_aramMemory = aramMemory; - aramMemory += chunkSize; - queueEntry->m_size = chunkSize; + aramMemory += transferSize; + queueEntry->m_size = transferSize; queueEntry->m_callbackData = callbackData; if (sizeBytes < 1) { queueEntry->m_callback = callback; @@ -1271,13 +1702,12 @@ int RedDmaEntry(int flags, int direction, int mainMemory, int aramMemory, int si queueEntry->m_callback = 0; } queueEntry++; - if (!(queueEntry < queueEnd)) { + if (!(queueEntry < queueBase + REDSOUND_DMA_QUEUE_ENTRY_COUNT)) { queueEntry = queueBase; } } while (sizeBytes > 0); *queuePtr = queueEntry; } else { - queueEnd = queueBase + REDSOUND_DMA_QUEUE_ENTRY_COUNT; queueEntry->m_id = entryID; queueEntry->m_direction = direction; queueEntry->m_mainMemory = mainMemory; @@ -1286,7 +1716,7 @@ int RedDmaEntry(int flags, int direction, int mainMemory, int aramMemory, int si queueEntry->m_callback = callback; queueEntry->m_callbackData = callbackData; queueEntry++; - if (!(queueEntry < queueEnd)) { + if (!(queueEntry < queueBase + REDSOUND_DMA_QUEUE_ENTRY_COUNT)) { queueEntry = queueBase; } *queuePtr = queueEntry; @@ -1327,6 +1757,45 @@ int RedDmaSearchID(int id) return found; } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 96b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void RedDmaClearID(int id) +{ + unsigned int interruptLevel; + RedDmaRequest* queueEntry; + + interruptLevel = OSDisableInterrupts(); + queueEntry = RedDriverMainDmaQueue(); + do { + if ((id == 0) || (queueEntry->m_id == id)) { + queueEntry->m_id = 0; + } + queueEntry++; + } while (queueEntry < RedDriverStreamDmaQueueEnd()); + OSRestoreInterrupts(interruptLevel); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 8b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void RedSetDMAMode(int mode) +{ + m_DMAMode = mode; +} + /* * --INFO-- * PAL Address: 0x801be2dc @@ -1360,7 +1829,7 @@ static void _DmaExecute() queueEntry = *oldQueuePtr; m_DMAInThread = REDSOUND_DMA_THREAD_LOAD_ENTRY; if (queueEntry->m_id != 0) { - m_DMAStatus = 1; + m_DMAStatus = REDSOUND_DMA_STATUS_BUSY; if (queueEntry->m_direction == REDSOUND_DMA_DIRECTION_TO_ARAM) { DCFlushRange((void*)queueEntry->m_mainMemory, (u32)queueEntry->m_size); srcAddress = queueEntry->m_mainMemory; @@ -1391,7 +1860,7 @@ static void _DmaExecute() while (activeRequest != 0) { m_DMAInThread = REDSOUND_DMA_THREAD_POLL_STATUS; - if (m_DMAStatus == 0) { + if (m_DMAStatus == REDSOUND_DMA_STATUS_IDLE) { m_DMAInThread = REDSOUND_DMA_THREAD_RUN_CALLBACK; if ((u32)activeRequest->m_callback != 0) { interrupt = OSDisableInterrupts(); @@ -1405,7 +1874,7 @@ static void _DmaExecute() activeRequest->m_id = 0; break; } - RedSleep(0); + RedSleep(REDSOUND_THREAD_YIELD_SLEEP_US); } } m_DMAInThread = REDSOUND_DMA_THREAD_IDLE; @@ -1423,15 +1892,15 @@ static void _DmaExecute() static int _DmaExecuteThread(void*) { m_ThreadExecute |= REDSOUND_THREAD_FLAG_DMA; - m_DMAExecute = 0; - m_DMAInThread = 0; - while (m_ThreadControl != 0) { + m_DMAExecute = REDSOUND_WORKER_IDLE; + m_DMAInThread = REDSOUND_DMA_THREAD_IDLE; + while (m_ThreadControl != REDSOUND_THREAD_CONTROL_STOP) { OSWaitSemaphore(&m_DmaExecuteSemaphore); - m_DMAExecute = 1; - if (m_ThreadControl != 0) { + m_DMAExecute = REDSOUND_WORKER_BUSY; + if (m_ThreadControl != REDSOUND_THREAD_CONTROL_STOP) { _DmaExecute(); } - m_DMAExecute = 0; + m_DMAExecute = REDSOUND_WORKER_IDLE; } m_ThreadExecute &= ~REDSOUND_THREAD_FLAG_DMA; return 0; @@ -1449,10 +1918,10 @@ static int _DmaExecuteThread(void*) static int _MusicSkipThread(void*) { m_ThreadExecute |= REDSOUND_THREAD_FLAG_MUSIC_SKIP; - m_MusicSkipComplete = 0; - while (m_ThreadControl != 0) { + m_MusicSkipComplete = REDSOUND_MUSIC_SKIP_NOT_COMPLETE; + while (m_ThreadControl != REDSOUND_THREAD_CONTROL_STOP) { OSWaitSemaphore(&m_MusicSkipSemaphore); - if (m_ThreadControl != 0) { + if (m_ThreadControl != REDSOUND_THREAD_CONTROL_STOP) { MusicSkipFunction(); } while (OSTryWaitSemaphore(&m_MusicSkipSemaphore) > 0) { @@ -1522,24 +1991,24 @@ void CRedDriver::Init() int fullVolume; int noMusicId; - m_ThreadExecute = 0; - m_ThreadControl = 1; - m_ReportPrint = 1; - m_SoundMode = 0; + m_ThreadExecute = REDSOUND_THREAD_FLAG_NONE; + m_ThreadControl = REDSOUND_THREAD_CONTROL_RUN; + m_ReportPrint = REDSOUND_REPORT_PRINT_ON; + m_SoundMode = REDSOUND_SOUND_MODE_STEREO; GetSoundMode(); - if (m_SoundPlayMode == 2) { - AXSetMode(2); + if (m_SoundPlayMode != REDSOUND_SOUND_MODE_SURROUND) { + AXSetMode(REDSOUND_SOUND_MODE_STEREO); } else { - AXSetMode(0); + AXSetMode(REDSOUND_SOUND_MODE_SURROUND); } - p_Tick = (RedTickHistory*)RedNew(sizeof(RedTickHistory)); - memset(p_Tick, 0, sizeof(RedTickHistory)); + p_Tick = (RedTickHistory*)RedNew(REDSOUND_TICK_HISTORY_SIZE); + memset(p_Tick, 0, REDSOUND_TICK_HISTORY_SIZE); AXSetCompressor(0); m_MusicKeySignature = 0; m_SoundMasterControl = 0; m_MusicSkipLine = 0; m_MusicFastSpeed = 0; - m_DMAStatus = 0; + m_DMAStatus = REDSOUND_DMA_STATUS_IDLE; m_CrossTime = 0; m_MasterSEVolume = REDSOUND_MASTER_VOLUME_FULL; m_MasterMusicVolume = REDSOUND_MASTER_VOLUME_FULL; @@ -1561,11 +2030,11 @@ void CRedDriver::Init() p_ExecCommandNow = p_ExecCommand; p_ExecCommandOld = p_ExecCommand; memset(p_ExecCommand, 0, REDSOUND_EXEC_COMMAND_BUFFER_SIZE); - p_SoundControlBuffer = (RedSoundCONTROL*)RedNew(REDSOUND_CONTROL_BUFFER_SIZE); + p_SoundControlBuffer = (RedSoundCONTROL*)RedNew(REDSOUND_SOUND_CONTROL_ALLOC_SIZE); p_SoundControl = p_SoundControlBuffer; - memset(p_SoundControlBuffer, 0, REDSOUND_CONTROL_BUFFER_SIZE); + memset(p_SoundControlBuffer, 0, REDSOUND_SOUND_CONTROL_ALLOC_SIZE); fullVolume = REDSOUND_MASTER_VOLUME_FULL_FIXED; - noMusicId = -1; + noMusicId = REDSOUND_MUSIC_ID_NONE; p_SoundControl[REDSOUND_CONTROL_SE].m_volume = fullVolume; p_SoundControl[REDSOUND_CONTROL_MUSIC_SKIP].m_volume = fullVolume; p_SoundControl[REDSOUND_CONTROL_MUSIC_SECONDARY].m_volume = fullVolume; @@ -1604,12 +2073,12 @@ void CRedDriver::Init() m_Mute[REDSOUND_MUTE_HIGH_WORD] = 0; m_Mute[REDSOUND_MUTE_LOW_WORD] = 0; p_MusicNextPlay = (RedMusicPlayCommand*)RedNew(REDSOUND_MUSIC_NEXT_PLAY_BUFFER_SIZE); - p_MusicNextPlay->m_musicId = -1; - m_MusicPhraseStop = 0; + p_MusicNextPlay->m_musicId = REDSOUND_MUSIC_ID_NONE; + m_MusicPhraseStop = REDSOUND_MUSIC_PHRASE_STOP_OFF; p_Stream = (RedStreamDATA*)RedNew(REDSOUND_STREAM_BUFFER_SIZE); memset(p_Stream, 0, REDSOUND_STREAM_BUFFER_SIZE); m_DMAMode = 0; - memset(m_DmaControl, 0, sizeof(m_DmaControl)); + memset(m_DmaControl, 0, REDSOUND_DMA_CONTROL_SIZE); p_DmaControlNow[REDSOUND_DMA_MAIN_QUEUE_INDEX] = RedDriverMainDmaQueue(); p_DmaControlOld[REDSOUND_DMA_MAIN_QUEUE_INDEX] = RedDriverMainDmaQueue(); p_DmaControlNow[REDSOUND_DMA_STREAM_QUEUE_INDEX] = RedDriverStreamDmaQueue(); @@ -1659,13 +2128,13 @@ void CRedDriver::End() RedDriverSyncState& sync = RedDriverSync(); AXRegisterCallback(0); - m_ThreadControl = 0; + m_ThreadControl = REDSOUND_THREAD_CONTROL_STOP; OSSignalSemaphore(&sync.m_mainSemaphore); OSSignalSemaphore(&sync.m_waveSemaphore); OSSignalSemaphore(&sync.m_dmaSemaphore); OSSignalSemaphore(&sync.m_musicSemaphore); - while (m_ThreadExecute != 0) { - RedSleep(0); + while (m_ThreadExecute != REDSOUND_THREAD_FLAG_NONE) { + RedSleep(REDSOUND_THREAD_YIELD_SLEEP_US); } AXRegisterAuxACallback(0, 0); AXRegisterAuxBCallback(0, 0); @@ -1692,6 +2161,20 @@ int CRedDriver::GetProgramTime() return sum; } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 8b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +int CRedDriver::GetMasterTime() +{ + return m_RedMasterTime; +} + /* * --INFO-- * PAL Address: 0x801bec48 @@ -1720,7 +2203,7 @@ int CRedDriver::GetSoundMode() int soundMode = __OSReadROM(); if (soundMode == 0) { - m_SoundPlayMode = 1; + m_SoundPlayMode = REDSOUND_SOUND_MODE_MONO; } else { m_SoundPlayMode = m_SoundMode; } @@ -1744,7 +2227,7 @@ int CRedDriver::SetMusicData(void* musicData) RedMusicHEAD* copiedHeader; int headerSize; - result = -1; + result = REDSOUND_MUSIC_ID_NONE; if (((header->m_signature[0] == REDSOUND_MUSIC_SIGNATURE_0) && (header->m_signature[1] == REDSOUND_MUSIC_SIGNATURE_1)) && (header->m_signature[2] == REDSOUND_MUSIC_SIGNATURE_2)) { @@ -1756,13 +2239,27 @@ int CRedDriver::SetMusicData(void* musicData) result = localHeader.m_musicNo; _EntryExecCommand(_SetMusicData, (int)copiedHeader, 0, 0, 0, 0, 0, 0); } - } else if (m_ReportPrint != 0) { + } else if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { OSReport(sRedDriverMusicHeaderErrorFmt, sRedDriverLogPrefix, sRedDriverLogWarnColor, sRedDriverLogReset); fflush(__files + 1); } return result; } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 72b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedDriver::ClearMusicData(int musicID) +{ + _EntryExecCommand(_ClearMusicData, musicID, 0, 0, 0, 0, 0, 0); +} + /* * --INFO-- * PAL Address: 0x801bedec @@ -1782,6 +2279,65 @@ int CRedDriver::ReentryMusicData(int musicID) return musicID; } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 372b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +int CRedDriver::MusicPlayState(int musicID) +{ + RedExecCommand* commandNow; + unsigned int interruptLevel; + RedSoundCONTROL* soundControl; + int result; + RedExecCommand* command; + + interruptLevel = OSDisableInterrupts(); + result = 0; + soundControl = p_SoundControlBuffer; + if (((musicID == REDSOUND_MUSIC_ID_NONE) || + (soundControl[REDSOUND_CONTROL_MUSIC_PRIMARY].m_musicId == musicID)) && + (soundControl[REDSOUND_CONTROL_MUSIC_PRIMARY].m_activeTrackCount != 0)) { + result = 1; + } else if (((musicID == REDSOUND_MUSIC_ID_NONE) || + (soundControl[REDSOUND_CONTROL_MUSIC_SECONDARY].m_musicId == musicID)) && + (soundControl[REDSOUND_CONTROL_MUSIC_SECONDARY].m_activeTrackCount != 0)) { + result = 1; + } else if ((musicID == REDSOUND_MUSIC_ID_NONE) || + (soundControl[REDSOUND_CONTROL_MUSIC_SKIP].m_musicId == musicID)) { + result = 1; + } else if ((p_MusicNextPlay->m_musicId >= REDSOUND_MUSIC_ID_MIN) && + ((musicID == REDSOUND_MUSIC_ID_NONE) || (p_MusicNextPlay->m_musicId == musicID))) { + result = 1; + } + + if (result == 0) { + commandNow = p_ExecCommandNow; + command = p_ExecCommandOld; + while (commandNow != command) { + if ((command->m_func != 0) && + ((command->m_func == _MusicPlaySequence) || + (command->m_func == _MusicCrossPlaySequence) || + (command->m_func == _MusicNextPlaySequence)) && + ((musicID == REDSOUND_MUSIC_ID_NONE) || + (musicID == command->m_args[REDSOUND_EXEC_COMMAND_ARG0]))) { + result = 1; + break; + } + command++; + if (command == p_ExecCommand + REDSOUND_EXEC_COMMAND_COUNT) { + command = p_ExecCommand; + } + } + } + + OSRestoreInterrupts(interruptLevel); + return result; +} + /* * --INFO-- * PAL Address: 0x801bee48 @@ -1813,77 +2369,218 @@ int CRedDriver::MusicPlay(int musicID, int volume, int mode) /* * --INFO-- - * PAL Address: 0x801beee8 - * PAL Size: 88b + * PAL Address: UNUSED + * PAL Size: 272b * EN Address: TODO * EN Size: TODO * JP Address: TODO - * JP Size: TODO */ -int CRedDriver::MusicCrossPlay(int musicID, int volume, int mode) +int CRedDriver::MusicPlay(void* musicData, int volume, int mode) { - _EntryExecCommand(_MusicCrossPlaySequence, musicID, volume, mode, 0, 0, 0, 0); - return musicID; + int result; + RedMusicHEAD localHeader; + RedMusicHEAD* const header = (RedMusicHEAD*)musicData; + RedMusicHEAD* copiedHeader; + int headerSize; + + result = REDSOUND_MUSIC_ID_NONE; + if (((header->m_signature[0] == REDSOUND_MUSIC_SIGNATURE_0) && + (header->m_signature[1] == REDSOUND_MUSIC_SIGNATURE_1)) && + (header->m_signature[2] == REDSOUND_MUSIC_SIGNATURE_2)) { + memcpy(&localHeader, header, REDSOUND_MUSIC_HEADER_SIZE); + headerSize = localHeader.m_size; + copiedHeader = (RedMusicHEAD*)RedNew(headerSize); + if (copiedHeader == 0) { + return result; + } + memcpy(copiedHeader, header, headerSize); + result = copiedHeader->m_musicNo; + _EntryExecCommand(_SetMusicData, (int)copiedHeader, 0, 0, 0, 0, 0, 0); + _EntryExecCommand(_MusicPlaySequence, result, volume, mode, 0, 0, 0, 0); + } + return result; } /* * --INFO-- - * PAL Address: 0x801bef40 + * PAL Address: 0x801beee8 * PAL Size: 88b * EN Address: TODO * EN Size: TODO * JP Address: TODO * JP Size: TODO */ -int CRedDriver::MusicNextPlay(int musicID, int volume, int mode) +int CRedDriver::MusicCrossPlay(int musicID, int volume, int mode) { - _EntryExecCommand(_MusicNextPlaySequence, musicID, volume, mode, 0, 0, 0, 0); + _EntryExecCommand(_MusicCrossPlaySequence, musicID, volume, mode, 0, 0, 0, 0); return musicID; } /* * --INFO-- - * PAL Address: 0x801bef98 - * PAL Size: 72b + * PAL Address: UNUSED + * PAL Size: 272b * EN Address: TODO * EN Size: TODO * JP Address: TODO - * JP Size: TODO */ -void CRedDriver::MusicMasterVolume(int volume) +int CRedDriver::MusicCrossPlay(void* musicData, int volume, int mode) { - _EntryExecCommand(_MusicMasterVolume, volume, 0, 0, 0, 0, 0, 0); + int result; + RedMusicHEAD localHeader; + RedMusicHEAD* const header = (RedMusicHEAD*)musicData; + RedMusicHEAD* copiedHeader; + int headerSize; + + result = REDSOUND_MUSIC_ID_NONE; + if (((header->m_signature[0] == REDSOUND_MUSIC_SIGNATURE_0) && + (header->m_signature[1] == REDSOUND_MUSIC_SIGNATURE_1)) && + (header->m_signature[2] == REDSOUND_MUSIC_SIGNATURE_2)) { + memcpy(&localHeader, header, REDSOUND_MUSIC_HEADER_SIZE); + headerSize = localHeader.m_size; + copiedHeader = (RedMusicHEAD*)RedNew(headerSize); + if (copiedHeader == 0) { + return result; + } + memcpy(copiedHeader, header, headerSize); + result = copiedHeader->m_musicNo; + _EntryExecCommand(_SetMusicData, (int)copiedHeader, 0, 0, 0, 0, 0, 0); + _EntryExecCommand(_MusicCrossPlaySequence, result, volume, mode, 0, 0, 0, 0); + } + return result; } /* * --INFO-- - * PAL Address: 0x801befe0 - * PAL Size: 76b + * PAL Address: 0x801bef40 + * PAL Size: 88b * EN Address: TODO * EN Size: TODO * JP Address: TODO * JP Size: TODO */ -void CRedDriver::MusicFadeOut(int musicID, int fadeTime) +int CRedDriver::MusicNextPlay(int musicID, int volume, int mode) { - _EntryExecCommand(_MusicVolume, musicID, 0, fadeTime, 1, 0, 0, 0); + _EntryExecCommand(_MusicNextPlaySequence, musicID, volume, mode, 0, 0, 0, 0); + return musicID; } /* * --INFO-- - * PAL Address: 0x801bf02c - * PAL Size: 80b + * PAL Address: UNUSED + * PAL Size: 272b * EN Address: TODO * EN Size: TODO * JP Address: TODO - * JP Size: TODO */ -void CRedDriver::MusicVolume(int musicID, int volume, int frameCount) +int CRedDriver::MusicNextPlay(void* musicData, int volume, int mode) { - _EntryExecCommand(_MusicVolume, musicID, volume, frameCount, 0, 0, 0, 0); -} - -/* + int result; + RedMusicHEAD localHeader; + RedMusicHEAD* const header = (RedMusicHEAD*)musicData; + RedMusicHEAD* copiedHeader; + int headerSize; + + result = REDSOUND_MUSIC_ID_NONE; + if (((header->m_signature[0] == REDSOUND_MUSIC_SIGNATURE_0) && + (header->m_signature[1] == REDSOUND_MUSIC_SIGNATURE_1)) && + (header->m_signature[2] == REDSOUND_MUSIC_SIGNATURE_2)) { + memcpy(&localHeader, header, REDSOUND_MUSIC_HEADER_SIZE); + headerSize = localHeader.m_size; + copiedHeader = (RedMusicHEAD*)RedNew(headerSize); + if (copiedHeader == 0) { + return result; + } + memcpy(copiedHeader, header, headerSize); + result = copiedHeader->m_musicNo; + _EntryExecCommand(_SetMusicData, (int)copiedHeader, 0, 0, 0, 0, 0, 0); + _EntryExecCommand(_MusicNextPlaySequence, result, volume, mode, 0, 0, 0, 0); + } + return result; +} + +/* + * --INFO-- + * PAL Address: 0x801bef98 + * PAL Size: 72b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedDriver::MusicMasterVolume(int volume) +{ + _EntryExecCommand(_MusicMasterVolume, volume, 0, 0, 0, 0, 0, 0); +} + +/* + * --INFO-- + * PAL Address: 0x801befe0 + * PAL Size: 76b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedDriver::MusicFadeOut(int musicID, int fadeTime) +{ + _EntryExecCommand(_MusicVolume, musicID, 0, fadeTime, REDSOUND_MUSIC_VOLUME_MODE_FADE_OUT, 0, 0, 0); +} + +/* + * --INFO-- + * PAL Address: 0x801bf02c + * PAL Size: 80b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedDriver::MusicVolume(int musicID, int volume, int frameCount) +{ + _EntryExecCommand(_MusicVolume, musicID, volume, frameCount, REDSOUND_MUSIC_VOLUME_MODE_NORMAL, 0, 0, 0); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 76b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +void CRedDriver::MusicTempo(int tempo, int frameCount) +{ + _EntryExecCommand(_MusicTempo, 0, tempo, frameCount, 0, 0, 0, 0); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 76b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +void CRedDriver::MusicPitch(int pitch, int frameCount) +{ + _EntryExecCommand(_MusicPitch, 0, pitch, frameCount, 0, 0, 0, 0); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 76b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +void CRedDriver::MusicPause(int musicID, int pause) +{ + _EntryExecCommand(_MusicPause, musicID, pause, 0, 0, 0, 0, 0); +} + +/* * --INFO-- * PAL Address: 0x801bf07c * PAL Size: 72b @@ -1897,6 +2594,62 @@ void CRedDriver::SetMusicPhraseStop(int stop) _EntryExecCommand(_SetMusicPhraseStop, stop, 0, 0, 0, 0, 0, 0); } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 48b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +int CRedDriver::CheckMusicEntry(int musicID) +{ + return c_RedEntry.SearchMusicSequence(musicID); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 8b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedDriver::SetMusicFastSpeed(int speed) +{ + m_MusicFastSpeed = speed; +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 8b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +int CRedDriver::CheckMusicPhraseStop() +{ + return m_MusicPhraseStop; +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 40b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedDriver::DisplayMusicInfo() +{ + c_RedEntry.DisplayMusicInfo(); +} + /* * --INFO-- * PAL Address: 0x801bf0c4 @@ -1939,7 +2692,7 @@ void* CRedDriver::SetSeBlockData(int blockIndex, void* seBlockData) */ int CRedDriver::SetSeSepData(void* seSepData) { - int result = -1; + int result = REDSOUND_SESEP_ID_NONE; RedSeSepHEAD* const header = (RedSeSepHEAD*)seSepData; RedSeSepHEAD* copiedHeader; int headerSize; @@ -1956,7 +2709,7 @@ int CRedDriver::SetSeSepData(void* seSepData) result = copiedHeader->m_seNo; _EntryExecCommand(_SetSeSepData, (int)copiedHeader, 0, 0, 0, 0, 0, 0); } - } else if (m_ReportPrint != 0) { + } else if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { OSReport(sRedDriverSeSepHeaderErrorFmt, sRedDriverLogPrefix, sRedDriverLogWarnColor, sRedDriverLogReset); fflush(__files + 1); @@ -2011,6 +2764,20 @@ int CRedDriver::ReentrySeSepData(int id) return id; } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 48b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +int CRedDriver::CheckSeSepEntry(int id) +{ + return c_RedEntry.SearchSeSepSequence(id); +} + /* * --INFO-- * PAL Address: 0x801bf384 @@ -2034,7 +2801,7 @@ int CRedDriver::SePlayState(int seID) seInfoBase = &p_SoundControlBuffer[REDSOUND_CONTROL_SE].m_tracks; seInfo = *seInfoBase; do { - if (((u32)seInfo->m_command != 0) && ((seID == -1 || (seInfo->m_seId == seID)))) { + if (((u32)seInfo->m_command != 0) && ((seID == REDSOUND_SE_ID_ALL || (seInfo->m_seId == seID)))) { result = (int)seInfo; break; } @@ -2048,7 +2815,7 @@ int CRedDriver::SePlayState(int seID) (((command->m_func == _SeBlockPlay) || (command->m_func == _SeSepPlay)) || (command->m_func == _SeSepPlaySequence))) && - ((seID == -1 || (seID == command->m_args[0])))) { + ((seID == REDSOUND_SE_ID_ALL || (seID == command->m_args[REDSOUND_EXEC_COMMAND_ARG0])))) { result = 1; break; } @@ -2076,6 +2843,19 @@ void CRedDriver::SeStop(int id) _EntryExecCommand(_SeStop, id, 0, 0, 0, 0, 0, 0); } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 72b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +void CRedDriver::SeStopG(int group) +{ + _EntryExecCommand(_SeStopG, group, 0, 0, 0, 0, 0, 0); +} + /* * --INFO-- * PAL Address: 0x801bf4ec @@ -2101,7 +2881,7 @@ void CRedDriver::SeStopMG(int id1, int id2, int id3, int id4) */ int CRedDriver::SePlay(int bank, int sep, int autoID, int pan, int volume, int pitch) { - if (bank == -1) { + if (bank == REDSOUND_SE_BANK_SESEP) { if (sep >= 0) { _EntryExecCommand(_SeSepPlaySequence, autoID, sep, pan, volume, pitch, 0, 0); } @@ -2112,6 +2892,43 @@ int CRedDriver::SePlay(int bank, int sep, int autoID, int pan, int volume, int p return autoID; } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 312b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +int CRedDriver::SePlay(void* seSepData, int autoID, int pan, int volume, int pitch) +{ + int result = REDSOUND_SESEP_ID_NONE; + RedSeSepHEAD* const header = (RedSeSepHEAD*)seSepData; + RedSeSepHEAD* copiedHeader; + int headerSize; + + if (((((header->m_signature[0] == REDSOUND_SESEP_SIGNATURE_0) && + (header->m_signature[1] == REDSOUND_SESEP_SIGNATURE_1)) && + (header->m_signature[2] == REDSOUND_SESEP_SIGNATURE_2)) && + ((header->m_signature[3] == REDSOUND_SESEP_SIGNATURE_3 && + (header->m_signature[4] == REDSOUND_SESEP_SIGNATURE_4))))) { + headerSize = header->m_sizeAndFlags & REDSOUND_SESEP_SIZE_MASK; + copiedHeader = (RedSeSepHEAD*)RedNew(headerSize); + if (copiedHeader != 0) { + memcpy(copiedHeader, header, headerSize); + result = copiedHeader->m_seNo; + _EntryExecCommand(_SetSeSepData, (int)copiedHeader, 0, 0, 0, 0, 0, 0); + _EntryExecCommand(_SeSepPlaySequence, autoID, result, pan, volume, pitch, 0, 0); + } else { + result = REDSOUND_SESEP_ID_NONE; + } + } else if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { + OSReport(sRedDriverSeSepHeaderErrorFmt, sRedDriverLogPrefix, + sRedDriverLogWarnColor, sRedDriverLogReset); + } + return autoID; +} + /* * --INFO-- * PAL Address: 0x801bf604 @@ -2137,7 +2954,7 @@ void CRedDriver::SeMasterVolume(int volume) */ void CRedDriver::SeFadeOut(int seID, int fadeTime) { - _EntryExecCommand(_SeVolume, seID, 0, fadeTime, 1, 0, 0, 0); + _EntryExecCommand(_SeVolume, seID, 0, fadeTime, REDSOUND_SE_VOLUME_MODE_FADE_OUT, 0, 0, 0); } /* @@ -2151,7 +2968,7 @@ void CRedDriver::SeFadeOut(int seID, int fadeTime) */ void CRedDriver::SeVolume(int seID, int volume, int frameCount) { - _EntryExecCommand(_SeVolume, seID, volume, frameCount, 0, 0, 0, 0); + _EntryExecCommand(_SeVolume, seID, volume, frameCount, REDSOUND_SE_VOLUME_MODE_NORMAL, 0, 0, 0); } /* @@ -2211,9 +3028,9 @@ int CRedDriver::GetSeVolume(int seID, int mode) track = p_SoundControlBuffer[REDSOUND_CONTROL_SE].m_tracks; while (1) { - if (((u32)track->m_command != 0) && ((seID == -1) || (seID == track->m_seId))) { + if (((u32)track->m_command != 0) && ((seID == REDSOUND_SE_ID_ALL) || (seID == track->m_seId))) { if ((u32)track->m_command != 0) { - if (mode == 1) { + if (mode == REDSOUND_SE_VOLUME_QUERY_DELTA) { return track->m_mixVolumeDelta; } return track->m_mixVolume >> REDSOUND_FIXED_SHIFT; @@ -2243,7 +3060,7 @@ int CRedDriver::ReportSeLoop(int seID) track = p_SoundControlBuffer[REDSOUND_CONTROL_SE].m_tracks; while (1) { if ((track->m_command != 0) && - (((seID == -1) || (seID == track->m_seId)) && + (((seID == REDSOUND_SE_ID_ALL) || (seID == track->m_seId)) && ((track->m_loopReport & REDSOUND_TRACK_LOOP_REPORT_ACTIVE) != 0))) { return 1; } @@ -2269,6 +3086,50 @@ void CRedDriver::DisplaySePlayInfo() c_RedEntry.DisplaySePlayInfo(); } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 68b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedDriver::ClearSePlayLine() +{ + RedSoundCONTROL* control = p_SoundControlBuffer + REDSOUND_CONTROL_SE; + RedTrackDATA* track = control->m_tracks; + + do { + track->m_command = 0; + track++; + } while (track < control->m_tracks + REDSOUND_SE_TRACK_COUNT); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 80b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +RedTrackDATA* CRedDriver::GetSePlayTrack() +{ + RedTrackDATA* track = p_SoundControlBuffer[REDSOUND_CONTROL_SE].m_tracks; + RedTrackDATA* trackEnd = track; + trackEnd += REDSOUND_SE_TRACK_COUNT; + + do { + if (track->m_command != 0) { + return track; + } + track++; + } while (track < trackEnd); + return 0; +} + /* * --INFO-- * PAL Address: 0x801bf8e8 @@ -2290,8 +3151,8 @@ int CRedDriver::StreamPlayState(int streamID) result = 0; streamData = p_Stream; do { - if ((streamData->m_streamId != 0) && - ((streamID == -1) || (streamData->m_streamId == streamID))) { + if ((streamData->m_streamId != REDSOUND_STREAM_ID_NONE) && + ((streamID == REDSOUND_STREAM_ID_ALL) || (streamData->m_streamId == streamID))) { result = 1; break; } @@ -2303,7 +3164,8 @@ int CRedDriver::StreamPlayState(int streamID) command = p_ExecCommandOld; while (commandNow != command) { if ((command->m_func != 0) && (command->m_func == _StreamPlay) && - ((streamID == -1) || (streamID == command->m_args[0]))) { + ((streamID == REDSOUND_STREAM_ID_ALL) || + (streamID == command->m_args[REDSOUND_EXEC_COMMAND_ARG0]))) { result = 1; break; } @@ -2326,26 +3188,26 @@ int CRedDriver::StreamPlayState(int streamID) * JP Address: TODO * JP Size: TODO */ -int CRedDriver::GetStreamPlayPoint(int streamID, int* outPoint1, int* outPoint2) +int CRedDriver::GetStreamPlayPoint(int streamID, int* playPoint, int* readPoint) { RedStreamDATA* streamData; int found; found = 0; - if (outPoint1 != 0) { - *outPoint1 = 0; + if (playPoint != 0) { + *playPoint = 0; } - if (outPoint2 != 0) { - *outPoint2 = 0; + if (readPoint != 0) { + *readPoint = 0; } streamData = p_Stream; do { - if ((streamData->m_streamId != 0) && (streamData->m_streamId == streamID)) { - if (outPoint1 != 0) { - *outPoint1 = streamData->m_fileCursor; + if ((streamData->m_streamId != REDSOUND_STREAM_ID_NONE) && (streamData->m_streamId == streamID)) { + if (playPoint != 0) { + *playPoint = streamData->m_fileCursor; } - if (outPoint2 != 0) { - *outPoint2 = streamData->m_readOffset; + if (readPoint != 0) { + *readPoint = streamData->m_readOffset; } found = 1; break; @@ -2355,6 +3217,28 @@ int CRedDriver::GetStreamPlayPoint(int streamID, int* outPoint1, int* outPoint2) return found; } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 80b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +RedStreamDATA* CRedDriver::GetStreamPlayBlock(int streamID) +{ + RedStreamDATA* streamData = p_Stream; + + do { + if ((streamData->m_streamId != REDSOUND_STREAM_ID_NONE) && (streamData->m_streamId == streamID)) { + return streamData; + } + streamData++; + } while (streamData < p_Stream + REDSOUND_STREAM_COUNT); + return 0; +} + /* * --INFO-- * PAL Address: 0x801bfa74 @@ -2398,6 +3282,19 @@ void CRedDriver::StreamVolume(int streamID, int volume, int frameCount) _EntryExecCommand(_StreamVolume, streamID, volume, frameCount, 0, 0, 0, 0); } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 80b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +void CRedDriver::StreamPan(int streamID, int pan, int frameCount) +{ + _EntryExecCommand(_StreamPan, streamID, pan, frameCount, 0, 0, 0, 0); +} + /* * --INFO-- * PAL Address: 0x801bfb6c @@ -2466,22 +3363,22 @@ void CRedDriver::ClearWaveBank(int waveBank) void CRedDriver::SetWaveData(int slot, int waveID, void* waveData, int waveSize) { while (true) { - if (m_WaveSettingStatus == 0) { + if (m_WaveSettingStatus == REDSOUND_WORKER_IDLE) { break; } - RedSleep(0); + RedSleep(REDSOUND_THREAD_YIELD_SLEEP_US); } m_WaveSettingData.m_slot = reinterpret_cast(slot); m_WaveSettingData.m_waveId = waveID; m_WaveSettingData.m_waveData = waveData; - if (waveSize == -1) { + if (waveSize == REDSOUND_WAVE_SIZE_AUTO) { RedWaveHeadWD* const waveHeader = (RedWaveHeadWD*)waveData; - if ((waveHeader->m_signature[0] == REDSOUND_WAVE_SIGNATURE_0) && - (waveHeader->m_signature[1] == REDSOUND_WAVE_SIGNATURE_1)) { + if ((waveHeader->m_signature[0] == REDSOUND_WAVE_SIGNATURE_MAGIC0) && + (waveHeader->m_signature[1] == REDSOUND_WAVE_SIGNATURE_MAGIC1)) { int dataSize = waveHeader->m_tableCount * REDSOUND_WAVE_TABLE_ENTRY_SIZE; dataSize = (dataSize += REDSOUND_WAVE_SETTING_TABLE_ALIGN - 1) & REDSOUND_WAVE_SETTING_TABLE_ALIGN_MASK; dataSize += waveHeader->m_toneCount * REDSOUND_WAVE_TONE_ENTRY_SIZE; @@ -2516,6 +3413,34 @@ int CRedDriver::ReentryWaveData(int id) return id; } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 48b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +RedWaveHeadWD* CRedDriver::GetWaveInfo(int waveID) +{ + return c_RedEntry.SearchWaveBase(waveID); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 48b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +int CRedDriver::CheckWaveEntry(int waveID) +{ + return c_RedEntry.SearchWaveSequence(waveID); +} + /* * --INFO-- * PAL Address: 0x801bfdd0 @@ -2530,6 +3455,20 @@ void CRedDriver::DisplayWaveInfo() c_RedEntry.DisplayWaveInfo(); } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 40b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedDriver::DisplayMMemoryInfo() +{ + c_RedEntry.DisplayMMemoryInfo(); +} + /* * --INFO-- * PAL Address: 0x801BFDF8 @@ -2544,6 +3483,285 @@ void CRedDriver::SetReverb(int bank, int kind) ::SetReverb(bank, t_ReverbModeData[kind].m_kind, t_ReverbModeData[kind].m_params); } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 56b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedDriver::SetReverb(int bank, int kind, int* params) +{ + ::SetReverb(bank, kind, params); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 32b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +RedReverbSize* CRedDriver::GetReverbInfo() +{ + return ::GetReverbInfo(); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 8b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +RedReverbDepth* CRedDriver::GetReverbDepth() +{ + return p_ReverbDepth; +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 76b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedDriver::SetMute(unsigned int voiceNo, unsigned int mute) +{ + if (mute != 0) { + m_Mute[voiceNo / REDSOUND_MUTE_BITS_PER_WORD] |= 1 << (voiceNo % REDSOUND_MUTE_BITS_PER_WORD); + } else { + m_Mute[voiceNo / REDSOUND_MUTE_BITS_PER_WORD] &= ~(1 << (voiceNo % REDSOUND_MUTE_BITS_PER_WORD)); + } +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 624b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +int CRedDriver::PlayWaveItem(int waveNo, int itemNo, int key, int pan, int volume) +{ + RedVoiceDATA* voice; + RedWaveDATA* wave; + RedWaveHeadWD* waveHead; + int voiceIndex; + + waveHead = c_RedEntry.SearchWaveBase(waveNo); + if ((waveHead == 0) || (itemNo < 0) || (itemNo >= waveHead->m_toneCount)) { + return 0; + } + + wave = (RedWaveDATA*)((u8*)waveHead + waveHead->m_waveOffsets[itemNo]); + p_EditorTrack->m_waveBankData = waveHead; + p_EditorTrack->m_waveData = wave; + p_EditorTrack->m_waveBase = waveHead->m_aramAddress; + p_EditorTrack->m_note.m_key = key; + p_EditorTrack->m_note.m_velocity = REDSOUND_VOLUME_MAX; + p_EditorTrack->m_note.m_allocFlags = REDSOUND_NOTE_ALLOC_DIRECT_MASK; + p_EditorTrack->m_trackNo = REDSOUND_EDITOR_VOICE_LEFT + 1; + p_EditorTrack->m_volume = REDSOUND_VOLUME_FULL; + p_EditorTrack->m_expression = REDSOUND_VOLUME_DEFAULT; + p_EditorTrack->m_mixVolume = volume << REDSOUND_FIXED_SHIFT; + p_EditorTrack->m_pan = pan << REDSOUND_FIXED_SHIFT; + p_EditorTrack->m_reverbDepth = p_ReverbDepth[REDSOUND_REVERB_DEPTH_SE].m_depth; + p_EditorTrack->m_portamentPitch = key << REDSOUND_PITCH_BASE_NOTE_SHIFT; + p_EditorTrack->m_pitchBendRange = 2; + p_EditorTrack->m_voiceSwitch = REDSOUND_VOICE_SWITCH_DRY_STEREO; + + voice = EntryVoiceSearch(p_EditorTrack); + if (voice == 0) { + return 0; + } + + voiceIndex = voice - p_VoiceData; + p_EditorVoice[REDSOUND_EDITOR_VOICE_LEFT] = voiceIndex; + p_EditorVoice[REDSOUND_EDITOR_VOICE_RIGHT] = 0; + voice->m_track = p_EditorTrack; + voice->m_waveData = wave; + voice->m_trackVolume = &p_EditorTrack->m_volume; + voice->m_trackExpression = &p_EditorTrack->m_expression; + voice->m_trackPan = &p_EditorTrack->m_pan; + voice->m_stateFlags = REDSOUND_VOICE_STATE_PLAYING; + voice->m_voiceSwitch = p_EditorTrack->m_voiceSwitch; + if ((wave->m_reverbMix != 0) && (wave->m_reverbMix != 1)) { + voice->m_voiceSwitch |= REDSOUND_VOICE_SWITCH_REVERB_STEREO; + } + memcpy(&voice->m_adsr, wave->m_adsr, REDSOUND_TRACK_ADSR_SIZE); + voice->m_basePitch = key << REDSOUND_PITCH_BASE_NOTE_SHIFT; + if ((wave->m_flags & REDSOUND_WAVE_FLAG_USE_WAVE_KEY) != 0) { + voice->m_basePitch = wave->m_splitKey << REDSOUND_PITCH_BASE_NOTE_SHIFT; + } + voice->m_pitch = WavePitchCompute(key, 0); + voice->m_targetPitch = voice->m_pitch; + voice->m_envelopeLevel = REDSOUND_ENVELOPE_LEVEL_FULL; + voice->m_flags = REDSOUND_VOICE_FLAGS_START | REDSOUND_VOICE_FLAGS_ADPCM_DIRTY | + REDSOUND_VOICE_FLAGS_PITCH_DIRTY | REDSOUND_VOICE_FLAGS_ADSR_START; + voice->m_active = REDSOUND_VOICE_ACTIVE_ON; + voice->m_updateFlags = REDSOUND_VOICE_UPDATE_ALL; + SetVoiceVolumeMix(voice, pan, volume); + + return voiceIndex; +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 96b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedDriver::StopWaveItem() +{ + RedVoiceDATA* voice = p_VoiceData; + + do { + if (voice->m_track == p_EditorTrack) { + voice->m_flags |= REDSOUND_VOICE_FLAGS_RELEASED; + voice->m_active = REDSOUND_VOICE_ACTIVE_OFF; + voice->m_track = 0; + } + voice++; + } while (voice < p_VoiceData + REDSOUND_VOICE_COUNT); + + p_EditorVoice[REDSOUND_EDITOR_VOICE_LEFT] = 0; +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 96b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedDriver::SetWavePitch(int pitch) +{ + int* voiceNo; + + p_EditorTrack->m_pitch = pitch; + voiceNo = p_EditorVoice; + do { + int voiceIndex = *voiceNo; + if (voiceIndex != 0) { + (p_VoiceData + voiceIndex)->m_updateFlags |= REDSOUND_VOICE_UPDATE_PITCH; + } + voiceNo++; + } while (voiceNo <= p_EditorVoice + REDSOUND_EDITOR_VOICE_RIGHT); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 152b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedDriver::SetWaveTune(int key, int fineTune) +{ + int* voiceNo; + + p_EditorTrack->m_keyTranspose = key; + p_EditorTrack->m_note.m_key = key; + p_EditorTrack->m_fineTune = fineTune; + p_EditorTrack->m_portamentPitch = key << REDSOUND_PITCH_BASE_NOTE_SHIFT; + voiceNo = p_EditorVoice; + do { + int voiceIndex = *voiceNo; + if (voiceIndex != 0) { + RedVoiceDATA* voice = p_VoiceData + voiceIndex; + voice->m_basePitch = key << REDSOUND_PITCH_BASE_NOTE_SHIFT; + voice->m_updateFlags |= REDSOUND_VOICE_UPDATE_PITCH; + } + voiceNo++; + } while (voiceNo < p_EditorVoice + REDSOUND_EDITOR_VOICE_COUNT); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 160b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedDriver::SetWaveAdsr(int attack, RedAdsrDATA* adsr) +{ + int* voiceNo; + + memcpy(&p_EditorTrack->m_adsr, adsr, REDSOUND_TRACK_ADSR_SIZE); + voiceNo = p_EditorVoice; + do { + int voiceIndex = *voiceNo; + if (voiceIndex != 0) { + RedVoiceDATA* voice = p_VoiceData + voiceIndex; + memcpy(&voice->m_adsr, adsr, REDSOUND_TRACK_ADSR_SIZE); + voice->m_flags |= REDSOUND_VOICE_FLAGS_ADSR_START; + } + voiceNo++; + } while (voiceNo < p_EditorVoice + REDSOUND_EDITOR_VOICE_COUNT); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 176b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +int CRedDriver::WavePitchCompute(int key, int pitch) +{ + int basePitch = key << REDSOUND_PITCH_BASE_NOTE_SHIFT; + int pitchOffset; + RedWaveDATA* wave = p_EditorTrack->m_waveData; + + if (wave != 0) { + if ((wave->m_flags & REDSOUND_WAVE_FLAG_USE_WAVE_KEY) != 0) { + basePitch = wave->m_splitKey << REDSOUND_PITCH_BASE_NOTE_SHIFT; + } + pitchOffset = p_EditorTrack->m_keyTranspose + pitch; + basePitch += p_EditorTrack->m_pitch; + return PitchCompute(basePitch, pitchOffset, wave->m_pitch, p_EditorTrack->m_fineTune); + } + + return 0; +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 24b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +RedReverbModeData* CRedDriver::GetReverbModeTable(int mode) +{ + mode &= REDSOUND_REVERB_MODE_INDEX_MASK; + return t_ReverbModeData + mode; +} + /* * --INFO-- * PAL Address: 0x801bfe54 @@ -2553,9 +3771,9 @@ void CRedDriver::SetReverb(int bank, int kind) * JP Address: TODO * JP Size: TODO */ -void CRedDriver::SetReverbDepth(int bank, int mode, int depth) +void CRedDriver::SetReverbDepth(int bank, int depth, int frameCount) { - _EntryExecCommand(_SetReverbDepth, bank, mode, depth, 0, 0, 0, 0); + _EntryExecCommand(_SetReverbDepth, bank, depth, frameCount, 0, 0, 0, 0); } /* diff --git a/src/RedSound/RedEntry.cpp b/src/RedSound/RedEntry.cpp index 57472471de..7cc0105f6f 100644 --- a/src/RedSound/RedEntry.cpp +++ b/src/RedSound/RedEntry.cpp @@ -4,9 +4,113 @@ #include "ffcc/RedSound/RedMidiCtrl.h" #include "ffcc/RedSound/RedGlobals.h" #include "ffcc/RedSound/RedMemory.h" +#include "global.h" #include #include +STATIC_ASSERT(offsetof(RedHistoryBANK, m_id) == REDSOUND_HISTORY_BANK_ID_OFFSET); +STATIC_ASSERT(offsetof(RedHistoryBANK, m_historyNo) == REDSOUND_HISTORY_BANK_HISTORY_NO_OFFSET); +STATIC_ASSERT(offsetof(RedHistoryBANK, m_data) == REDSOUND_HISTORY_BANK_DATA_OFFSET); +STATIC_ASSERT(offsetof(RedHistoryBANK, m_size) == REDSOUND_HISTORY_BANK_SIZE_OFFSET); +STATIC_ASSERT(sizeof(RedHistoryBANK) == REDSOUND_HISTORY_BANK_ENTRY_SIZE); +STATIC_ASSERT(REDSOUND_WAVE_PRIMARY_BANK_SIZE == REDSOUND_WAVE_PRIMARY_BANK_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_WAVE_HISTORY_BANK_SIZE == REDSOUND_WAVE_HISTORY_BANK_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_WAVE_HISTORY_BANK_OFFSET == REDSOUND_WAVE_PRIMARY_BANK_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_WAVE_PRIMARY_BANK_SIZE + REDSOUND_WAVE_HISTORY_BANK_SIZE == REDSOUND_WAVE_BANK_SIZE); +STATIC_ASSERT(REDSOUND_WAVE_BANK_SIZE == REDSOUND_WAVE_BANK_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_SESEP_BANK_SIZE == REDSOUND_SESEP_BANK_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_MUSIC_BANK_SIZE == REDSOUND_MUSIC_BANK_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_WAVE_BANK_SIZE + REDSOUND_SESEP_BANK_SIZE + REDSOUND_MUSIC_BANK_SIZE == + REDSOUND_ENTRY_BANK_ARENA_SIZE); +STATIC_ASSERT(REDSOUND_ENTRY_BANK_ARENA_SIZE == REDSOUND_ENTRY_BANK_ARENA_ALLOC_SIZE); +STATIC_ASSERT(sizeof(RedMusicHEAD) == REDSOUND_MUSIC_HEADER_SIZE); +STATIC_ASSERT(offsetof(RedMusicHEAD, m_signature) == REDSOUND_MUSIC_HEADER_SIGNATURE_OFFSET); +STATIC_ASSERT(sizeof(((RedMusicHEAD*)0)->m_signature) == REDSOUND_MUSIC_SIGNATURE_SIZE); +STATIC_ASSERT(offsetof(RedMusicHEAD, m_musicNo) == REDSOUND_MUSIC_HEADER_MUSIC_NO_OFFSET); +STATIC_ASSERT(offsetof(RedMusicHEAD, m_waveNo) == REDSOUND_MUSIC_HEADER_WAVE_NO_OFFSET); +STATIC_ASSERT(offsetof(RedMusicHEAD, m_trackCount) == REDSOUND_MUSIC_HEADER_TRACK_COUNT_OFFSET); +STATIC_ASSERT(offsetof(RedMusicHEAD, m_reverbKind) == REDSOUND_MUSIC_HEADER_REVERB_KIND_OFFSET); +STATIC_ASSERT(offsetof(RedMusicHEAD, m_reverbDepth) == REDSOUND_MUSIC_HEADER_REVERB_DEPTH_OFFSET); +STATIC_ASSERT(offsetof(RedMusicHEAD, m_flags) == REDSOUND_MUSIC_HEADER_FLAGS_OFFSET); +STATIC_ASSERT(offsetof(RedMusicHEAD, m_reserved0E) == REDSOUND_MUSIC_HEADER_RESERVED0E_OFFSET); +STATIC_ASSERT(sizeof(((RedMusicHEAD*)0)->m_reserved0E) == REDSOUND_MUSIC_HEADER_RESERVED0E_SIZE); +STATIC_ASSERT(offsetof(RedMusicHEAD, m_size) == REDSOUND_MUSIC_HEADER_DATA_SIZE_OFFSET); +STATIC_ASSERT(offsetof(RedMusicHEAD, m_playFlags) == REDSOUND_MUSIC_HEADER_PLAY_FLAGS_OFFSET); +STATIC_ASSERT(offsetof(RedMusicHEAD, m_reserved18) == REDSOUND_MUSIC_HEADER_RESERVED18_OFFSET); +STATIC_ASSERT(sizeof(((RedMusicHEAD*)0)->m_reserved18) == REDSOUND_MUSIC_HEADER_RESERVED18_SIZE); +STATIC_ASSERT(offsetof(RedMusicHEAD, m_reserved1C) == REDSOUND_MUSIC_HEADER_RESERVED1C_OFFSET); +STATIC_ASSERT(sizeof(((RedMusicHEAD*)0)->m_reserved1C) == REDSOUND_MUSIC_HEADER_RESERVED1C_SIZE); +STATIC_ASSERT(offsetof(RedMusicTrackBlock, m_sizeLo) == REDSOUND_MUSIC_TRACK_BLOCK_SIZE_LO_OFFSET); +STATIC_ASSERT(offsetof(RedMusicTrackBlock, m_sizeHi0) == REDSOUND_MUSIC_TRACK_BLOCK_SIZE_HI0_OFFSET); +STATIC_ASSERT(offsetof(RedMusicTrackBlock, m_sizeHi1) == REDSOUND_MUSIC_TRACK_BLOCK_SIZE_HI1_OFFSET); +STATIC_ASSERT(offsetof(RedMusicTrackBlock, m_sizeHi2) == REDSOUND_MUSIC_TRACK_BLOCK_SIZE_HI2_OFFSET); +STATIC_ASSERT(offsetof(RedMusicTrackBlock, m_command) == REDSOUND_MUSIC_TRACK_BLOCK_COMMAND_OFFSET); +STATIC_ASSERT(sizeof(RedMusicTrackBlock) == REDSOUND_MUSIC_TRACK_BLOCK_MIN_SIZE); +STATIC_ASSERT(REDSOUND_MUSIC_TRACK_BLOCK_COMMAND_OFFSET + sizeof(((RedMusicTrackBlock*)0)->m_command) == + REDSOUND_MUSIC_TRACK_BLOCK_MIN_SIZE); +STATIC_ASSERT(offsetof(RedSeSepHEAD, m_signature) == REDSOUND_SESEP_SIGNATURE_OFFSET); +STATIC_ASSERT(sizeof(((RedSeSepHEAD*)0)->m_signature) == REDSOUND_SESEP_SIGNATURE_SIZE); +STATIC_ASSERT(offsetof(RedSeSepHEAD, m_seNo) == REDSOUND_SESEP_SE_NO_OFFSET); +STATIC_ASSERT(offsetof(RedSeSepHEAD, m_sizeAndFlags) == REDSOUND_SESEP_SIZE_AND_FLAGS_OFFSET); +STATIC_ASSERT(offsetof(RedSeSepHEAD, m_seInfoFlags) == REDSOUND_SESEP_INFO_OFFSET); +STATIC_ASSERT(offsetof(RedSeSepHEAD, m_waveNoLo) == REDSOUND_SESEP_WAVE_NO_LO_OFFSET); +STATIC_ASSERT(offsetof(RedSeSepHEAD, m_waveNoHi) == REDSOUND_SESEP_WAVE_NO_HI_OFFSET); +STATIC_ASSERT(offsetof(RedSeSepHEAD, m_reserved13) == REDSOUND_SESEP_RESERVED13_OFFSET); +STATIC_ASSERT(sizeof(((RedSeSepHEAD*)0)->m_reserved13) == REDSOUND_SESEP_RESERVED13_SIZE); +STATIC_ASSERT(sizeof(RedSeSepHEAD) == REDSOUND_SESEP_STRUCT_SIZE); +STATIC_ASSERT(REDSOUND_SESEP_INFO_OFFSET == REDSOUND_SESEP_HEADER_SIZE); +STATIC_ASSERT(REDSOUND_SESEP_RESERVED13_OFFSET + REDSOUND_SESEP_RESERVED13_SIZE == REDSOUND_SESEP_STRUCT_SIZE); +STATIC_ASSERT(offsetof(RedSeInfoSequence, m_offsetLo) == REDSOUND_SE_INFO_SEQUENCE_OFFSET_LO_OFFSET); +STATIC_ASSERT(offsetof(RedSeInfoSequence, m_offsetHiAndFlags) == REDSOUND_SE_INFO_SEQUENCE_OFFSET_HI_AND_FLAGS_OFFSET); +STATIC_ASSERT(sizeof(RedSeInfoSequence) == REDSOUND_SE_INFO_SEQUENCE_ENTRY_SIZE); +STATIC_ASSERT(offsetof(RedSeINFO, m_flagsAndCount) == REDSOUND_SE_INFO_FLAGS_AND_COUNT_OFFSET); +STATIC_ASSERT(offsetof(RedSeINFO, m_waveNoLo) == REDSOUND_SE_INFO_WAVE_NO_LO_OFFSET); +STATIC_ASSERT(offsetof(RedSeINFO, m_waveNoHi) == REDSOUND_SE_INFO_WAVE_NO_HI_OFFSET); +STATIC_ASSERT(offsetof(RedSeINFO, m_eraseTrack) == REDSOUND_SE_INFO_ERASE_TRACK_OFFSET); +STATIC_ASSERT(offsetof(RedSeINFO, m_attrMask) == REDSOUND_SE_INFO_ATTR_MASK_OFFSET); +STATIC_ASSERT(offsetof(RedSeINFO, m_sequence) == REDSOUND_SE_INFO_SEQUENCE_OFFSET); +STATIC_ASSERT(sizeof(RedSeINFO) == REDSOUND_SE_INFO_MIN_SIZE); +STATIC_ASSERT(REDSOUND_SE_INFO_SEQUENCE_OFFSET + REDSOUND_SE_INFO_SEQUENCE_ENTRY_SIZE == + REDSOUND_SE_INFO_MIN_SIZE); +STATIC_ASSERT(offsetof(RedSeBlockHEAD, m_signature) == REDSOUND_SE_BLOCK_SIGNATURE_OFFSET); +STATIC_ASSERT(sizeof(((RedSeBlockHEAD*)0)->m_signature) == REDSOUND_SE_BLOCK_SIGNATURE_SIZE); +STATIC_ASSERT(offsetof(RedSeBlockHEAD, m_reserved08) == REDSOUND_SE_BLOCK_RESERVED08_OFFSET); +STATIC_ASSERT(sizeof(((RedSeBlockHEAD*)0)->m_reserved08) == REDSOUND_SE_BLOCK_RESERVED08_SIZE); +STATIC_ASSERT(offsetof(RedSeBlockHEAD, m_seCount) == REDSOUND_SE_BLOCK_SE_COUNT_OFFSET); +STATIC_ASSERT(offsetof(RedSeBlockHEAD, m_size) == REDSOUND_SE_BLOCK_SIZE_OFFSET); +STATIC_ASSERT(offsetof(RedSeBlockHEAD, m_entries) == REDSOUND_SE_BLOCK_ENTRIES_OFFSET); +STATIC_ASSERT(sizeof(RedSeBlockHEAD) == REDSOUND_SE_BLOCK_STRUCT_SIZE); +STATIC_ASSERT(REDSOUND_SE_BLOCK_ENTRIES_OFFSET == REDSOUND_SE_BLOCK_HEADER_SIZE); +STATIC_ASSERT(REDSOUND_SE_BLOCK_RESERVED08_OFFSET + REDSOUND_SE_BLOCK_RESERVED08_SIZE == + REDSOUND_SE_BLOCK_SE_COUNT_OFFSET); +STATIC_ASSERT(REDSOUND_SE_BLOCK_ENTRIES_OFFSET + REDSOUND_SE_BLOCK_ENTRY_SIZE == + REDSOUND_SE_BLOCK_STRUCT_SIZE); +STATIC_ASSERT(offsetof(RedWaveHeadWD, m_signature) == REDSOUND_WAVE_HEAD_SIGNATURE_OFFSET); +STATIC_ASSERT(sizeof(((RedWaveHeadWD*)0)->m_signature) == REDSOUND_WAVE_SIGNATURE_SIZE); +STATIC_ASSERT(offsetof(RedWaveHeadWD, m_waveNo) == REDSOUND_WAVE_HEAD_WAVE_NO_OFFSET); +STATIC_ASSERT(offsetof(RedWaveHeadWD, m_waveSize) == REDSOUND_WAVE_HEAD_WAVE_SIZE_OFFSET); +STATIC_ASSERT(offsetof(RedWaveHeadWD, m_tableCount) == REDSOUND_WAVE_HEAD_TABLE_COUNT_OFFSET); +STATIC_ASSERT(offsetof(RedWaveHeadWD, m_toneCount) == REDSOUND_WAVE_HEAD_TONE_COUNT_OFFSET); +STATIC_ASSERT(offsetof(RedWaveHeadWD, m_aramAddress) == REDSOUND_WAVE_HEAD_ARAM_ADDRESS_OFFSET); +STATIC_ASSERT(offsetof(RedWaveHeadWD, m_loadSize) == REDSOUND_WAVE_HEAD_LOAD_SIZE_OFFSET); +STATIC_ASSERT(offsetof(RedWaveHeadWD, m_reserved18) == REDSOUND_WAVE_HEAD_RESERVED18_OFFSET); +STATIC_ASSERT(sizeof(((RedWaveHeadWD*)0)->m_reserved18) == REDSOUND_WAVE_HEAD_RESERVED18_SIZE); +STATIC_ASSERT(offsetof(RedWaveHeadWD, m_waveOffsets) == REDSOUND_WAVE_HEAD_OFFSETS_OFFSET); +STATIC_ASSERT(sizeof(RedWaveHeadWD) == REDSOUND_WAVE_HEAD_MIN_SIZE); +STATIC_ASSERT(REDSOUND_WAVE_HEADER_COPY_BASE_SIZE == REDSOUND_WAVE_HEAD_OFFSETS_OFFSET); +STATIC_ASSERT(REDSOUND_WAVE_HEAD_RESERVED18_OFFSET + REDSOUND_WAVE_HEAD_RESERVED18_SIZE == + REDSOUND_WAVE_HEAD_OFFSETS_OFFSET); +STATIC_ASSERT(REDSOUND_WAVE_HEAD_OFFSETS_OFFSET + REDSOUND_WAVE_TABLE_ENTRY_SIZE == + REDSOUND_WAVE_HEAD_MIN_SIZE); +STATIC_ASSERT(REDSOUND_WAVE_TONE_ENTRY_SIZE == REDSOUND_WAVE_DATA_SIZE); +STATIC_ASSERT(offsetof(CRedEntry, m_waveBankBase) == REDSOUND_ENTRY_WAVE_BANK_BASE_OFFSET); +STATIC_ASSERT(offsetof(CRedEntry, m_seSepBankBase) == REDSOUND_ENTRY_SESEP_BANK_BASE_OFFSET); +STATIC_ASSERT(offsetof(CRedEntry, m_musicBankBase) == REDSOUND_ENTRY_MUSIC_BANK_BASE_OFFSET); +STATIC_ASSERT(offsetof(CRedEntry, m_waveLoadNo) == REDSOUND_ENTRY_WAVE_LOAD_NO_OFFSET); +STATIC_ASSERT(offsetof(CRedEntry, m_waveLoadSize) == REDSOUND_ENTRY_WAVE_LOAD_SIZE_OFFSET); +STATIC_ASSERT(offsetof(CRedEntry, m_waveLoadAddress) == REDSOUND_ENTRY_WAVE_LOAD_ADDRESS_OFFSET); +STATIC_ASSERT(sizeof(CRedEntry) == REDSOUND_ENTRY_SIZE); + static const char sRedEntryColoredBlankLineFmt[] = "%s%s %s\n"; static const char sRedEntryLogPrefix[] = "\x1B[7;34mSound\x1B[0m:"; static const char sRedEntryErrorBannerFmt[] = "%s%s ******** ERROR ******** %s\n"; @@ -61,17 +165,117 @@ static const char sRedEntryInfoColor[] = "\x1B[4;34m"; static const char sRedEntryNewline[] = "\n"; static const char sRedEntryPrefixedNewlineFmt[] = "%s\n"; -enum RedEntryHeaderSignature { - REDSOUND_ENTRY_MUSIC_SIGNATURE_0 = 'B', - REDSOUND_ENTRY_MUSIC_SIGNATURE_1 = 'G', - REDSOUND_ENTRY_MUSIC_SIGNATURE_2 = 'M', - REDSOUND_ENTRY_SESEP_SIGNATURE_0 = 'S', - REDSOUND_ENTRY_SESEP_SIGNATURE_1 = 'e', - REDSOUND_ENTRY_SESEP_SIGNATURE_2 = 'S', - REDSOUND_ENTRY_SESEP_SIGNATURE_3 = 'e', - REDSOUND_ENTRY_SESEP_SIGNATURE_4 = 'p', +enum RedEntryStringLayout { + REDSOUND_ENTRY_COLORED_BLANK_LINE_FMT_SIZE = 0x2d, + REDSOUND_ENTRY_LOG_PREFIX_SIZE = 0x12, + REDSOUND_ENTRY_ERROR_BANNER_FMT_SIZE = 0x2d, + REDSOUND_ENTRY_ERASE_USING_WAVE_DATA_FMT_SIZE = 0x2e, + REDSOUND_ENTRY_WAVE_HEADER_BROKEN_FMT_SIZE = 0x1f, + REDSOUND_ENTRY_NO_WAVE_MEMORY_FREE_AREA_FMT_SIZE = 0x3d, + REDSOUND_ENTRY_WAVE_ENTRY_FMT_SIZE = 0x1f, + REDSOUND_ENTRY_AMEMORY_INFO_HEADER_FMT_SIZE = 0x21, + REDSOUND_ENTRY_AMEMORY_INFO_COLUMN_FMT_SIZE = 0x45, + REDSOUND_ENTRY_AMEMORY_WAVE_BANK_INFO_FMT_SIZE = 0x3c, + REDSOUND_ENTRY_AMEMORY_UNBANKED_WAVE_INFO_FMT_SIZE = 0x3b, + REDSOUND_ENTRY_AMEMORY_FREE_BLOCK_INFO_FMT_SIZE = 0x37, + REDSOUND_ENTRY_ENTRY_WAVE_COUNT_FMT_SIZE = 0x17, + REDSOUND_ENTRY_TOTAL_SIZE_FMT_SIZE = 0x1c, + REDSOUND_ENTRY_MAX_FREE_SIZE_FMT_SIZE = 0x1c, + REDSOUND_ENTRY_SESEP_HEADER_BROKEN_FMT_SIZE = 0x21, + REDSOUND_ENTRY_SE_PLAY_INFO_HEADER_FMT_SIZE = 0x21, + REDSOUND_ENTRY_SE_PLAY_INFO_COLUMN_FMT_SIZE = 0x20, + REDSOUND_ENTRY_SE_BLOCK_PLAY_INFO_FMT_SIZE = 0x2a, + REDSOUND_ENTRY_SESEP_PLAY_INFO_FMT_SIZE = 0x25, + REDSOUND_ENTRY_SE_EMPTY_PLAY_INFO_FMT_SIZE = 0x1c, + REDSOUND_ENTRY_MUSIC_HEADER_BROKEN_FMT_SIZE = 0x20, + REDSOUND_ENTRY_MUSIC_INFORMATION_HEADER_FMT_SIZE = 0x1f, + REDSOUND_ENTRY_MUSIC_INFO_COLUMN_FMT_SIZE = 0x22, + REDSOUND_ENTRY_MUSIC_INFO_PLAY_FMT_SIZE = 0x28, + REDSOUND_ENTRY_MUSIC_INFO_STOP_FMT_SIZE = 0x28, + REDSOUND_ENTRY_MMEMORY_INFO_HEADER_FMT_SIZE = 0x21, + REDSOUND_ENTRY_MMEMORY_INFO_COLUMN_FMT_SIZE = 0x35, + REDSOUND_ENTRY_MMEMORY_MUSIC_INFO_FMT_SIZE = 0x2d, + REDSOUND_ENTRY_MMEMORY_SE_BLOCK_INFO_FMT_SIZE = 0x2b, + REDSOUND_ENTRY_MMEMORY_WAVE_INFO_FMT_SIZE = 0x2c, + REDSOUND_ENTRY_MMEMORY_SE_INFO_FMT_SIZE = 0x2a, + REDSOUND_ENTRY_MMEMORY_FREE_BLOCK_INFO_FMT_SIZE = 0x2b, + REDSOUND_ENTRY_ENTRY_ITEMS_FMT_SIZE = 0x17, + REDSOUND_ENTRY_ERROR_COLOR_SIZE = 0x08, + REDSOUND_ENTRY_RESET_COLOR_SIZE = 0x05, + REDSOUND_ENTRY_HEADER_ERROR_COLOR_SIZE = 0x08, + REDSOUND_ENTRY_INFO_COLOR_SIZE = 0x08, + REDSOUND_ENTRY_NEWLINE_SIZE = 0x02, + REDSOUND_ENTRY_PREFIXED_NEWLINE_FMT_SIZE = 0x04, + REDSOUND_ENTRY_RODATA_STRING_SIZE = 0x53c, + REDSOUND_ENTRY_SDATA2_STRING_SIZE = 0x23, +}; + +enum RedEntryTiming { + REDSOUND_WAVE_LOAD_DMA_POLL_SLEEP_US = 1000, }; +STATIC_ASSERT(sizeof(sRedEntryColoredBlankLineFmt) == REDSOUND_ENTRY_COLORED_BLANK_LINE_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryLogPrefix) == REDSOUND_ENTRY_LOG_PREFIX_SIZE); +STATIC_ASSERT(sizeof(sRedEntryErrorBannerFmt) == REDSOUND_ENTRY_ERROR_BANNER_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryEraseUsingWaveDataFmt) == REDSOUND_ENTRY_ERASE_USING_WAVE_DATA_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryWaveHeaderBrokenFmt) == REDSOUND_ENTRY_WAVE_HEADER_BROKEN_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryNoWaveMemoryFreeAreaFmt) == REDSOUND_ENTRY_NO_WAVE_MEMORY_FREE_AREA_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryWaveEntryFmt) == REDSOUND_ENTRY_WAVE_ENTRY_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryAMemoryInfoHeaderFmt) == REDSOUND_ENTRY_AMEMORY_INFO_HEADER_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryAMemoryInfoColumnFmt) == REDSOUND_ENTRY_AMEMORY_INFO_COLUMN_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryAMemoryWaveBankInfoFmt) == REDSOUND_ENTRY_AMEMORY_WAVE_BANK_INFO_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryAMemoryUnbankedWaveInfoFmt) == REDSOUND_ENTRY_AMEMORY_UNBANKED_WAVE_INFO_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryAMemoryFreeBlockInfoFmt) == REDSOUND_ENTRY_AMEMORY_FREE_BLOCK_INFO_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryEntryWaveCountFmt) == REDSOUND_ENTRY_ENTRY_WAVE_COUNT_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryTotalSizeFmt) == REDSOUND_ENTRY_TOTAL_SIZE_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryMaxFreeSizeFmt) == REDSOUND_ENTRY_MAX_FREE_SIZE_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntrySeSepHeaderBrokenFmt) == REDSOUND_ENTRY_SESEP_HEADER_BROKEN_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntrySePlayInfoHeaderFmt) == REDSOUND_ENTRY_SE_PLAY_INFO_HEADER_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntrySePlayInfoColumnFmt) == REDSOUND_ENTRY_SE_PLAY_INFO_COLUMN_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntrySeBlockPlayInfoFmt) == REDSOUND_ENTRY_SE_BLOCK_PLAY_INFO_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntrySeSepPlayInfoFmt) == REDSOUND_ENTRY_SESEP_PLAY_INFO_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntrySeEmptyPlayInfoFmt) == REDSOUND_ENTRY_SE_EMPTY_PLAY_INFO_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryMusicHeaderBrokenFmt) == REDSOUND_ENTRY_MUSIC_HEADER_BROKEN_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryMusicInformationHeaderFmt) == REDSOUND_ENTRY_MUSIC_INFORMATION_HEADER_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryMusicInfoColumnFmt) == REDSOUND_ENTRY_MUSIC_INFO_COLUMN_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryMusicInfoPlayFmt) == REDSOUND_ENTRY_MUSIC_INFO_PLAY_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryMusicInfoStopFmt) == REDSOUND_ENTRY_MUSIC_INFO_STOP_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryMMemoryInfoHeaderFmt) == REDSOUND_ENTRY_MMEMORY_INFO_HEADER_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryMMemoryInfoColumnFmt) == REDSOUND_ENTRY_MMEMORY_INFO_COLUMN_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryMMemoryMusicInfoFmt) == REDSOUND_ENTRY_MMEMORY_MUSIC_INFO_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryMMemorySeBlockInfoFmt) == REDSOUND_ENTRY_MMEMORY_SE_BLOCK_INFO_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryMMemoryWaveInfoFmt) == REDSOUND_ENTRY_MMEMORY_WAVE_INFO_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryMMemorySeInfoFmt) == REDSOUND_ENTRY_MMEMORY_SE_INFO_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryMMemoryFreeBlockInfoFmt) == REDSOUND_ENTRY_MMEMORY_FREE_BLOCK_INFO_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryEntryItemsFmt) == REDSOUND_ENTRY_ENTRY_ITEMS_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryErrorColor) == REDSOUND_ENTRY_ERROR_COLOR_SIZE); +STATIC_ASSERT(sizeof(sRedEntryResetColor) == REDSOUND_ENTRY_RESET_COLOR_SIZE); +STATIC_ASSERT(sizeof(sRedEntryHeaderErrorColor) == REDSOUND_ENTRY_HEADER_ERROR_COLOR_SIZE); +STATIC_ASSERT(sizeof(sRedEntryInfoColor) == REDSOUND_ENTRY_INFO_COLOR_SIZE); +STATIC_ASSERT(sizeof(sRedEntryNewline) == REDSOUND_ENTRY_NEWLINE_SIZE); +STATIC_ASSERT(sizeof(sRedEntryPrefixedNewlineFmt) == REDSOUND_ENTRY_PREFIXED_NEWLINE_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedEntryColoredBlankLineFmt) + sizeof(sRedEntryLogPrefix) + sizeof(sRedEntryErrorBannerFmt) + + sizeof(sRedEntryEraseUsingWaveDataFmt) + sizeof(sRedEntryWaveHeaderBrokenFmt) + + sizeof(sRedEntryNoWaveMemoryFreeAreaFmt) + sizeof(sRedEntryWaveEntryFmt) + + sizeof(sRedEntryAMemoryInfoHeaderFmt) + sizeof(sRedEntryAMemoryInfoColumnFmt) + + sizeof(sRedEntryAMemoryWaveBankInfoFmt) + sizeof(sRedEntryAMemoryUnbankedWaveInfoFmt) + + sizeof(sRedEntryAMemoryFreeBlockInfoFmt) + sizeof(sRedEntryEntryWaveCountFmt) + + sizeof(sRedEntryTotalSizeFmt) + sizeof(sRedEntryMaxFreeSizeFmt) + + sizeof(sRedEntrySeSepHeaderBrokenFmt) + sizeof(sRedEntrySePlayInfoHeaderFmt) + + sizeof(sRedEntrySePlayInfoColumnFmt) + sizeof(sRedEntrySeBlockPlayInfoFmt) + + sizeof(sRedEntrySeSepPlayInfoFmt) + sizeof(sRedEntrySeEmptyPlayInfoFmt) + + sizeof(sRedEntryMusicHeaderBrokenFmt) + sizeof(sRedEntryMusicInformationHeaderFmt) + + sizeof(sRedEntryMusicInfoColumnFmt) + sizeof(sRedEntryMusicInfoPlayFmt) + + sizeof(sRedEntryMusicInfoStopFmt) + sizeof(sRedEntryMMemoryInfoHeaderFmt) + + sizeof(sRedEntryMMemoryInfoColumnFmt) + sizeof(sRedEntryMMemoryMusicInfoFmt) + + sizeof(sRedEntryMMemorySeBlockInfoFmt) + sizeof(sRedEntryMMemoryWaveInfoFmt) + + sizeof(sRedEntryMMemorySeInfoFmt) + sizeof(sRedEntryMMemoryFreeBlockInfoFmt) + + sizeof(sRedEntryEntryItemsFmt) == + REDSOUND_ENTRY_RODATA_STRING_SIZE); +STATIC_ASSERT(sizeof(sRedEntryErrorColor) + sizeof(sRedEntryResetColor) + sizeof(sRedEntryHeaderErrorColor) + + sizeof(sRedEntryInfoColor) + sizeof(sRedEntryNewline) + sizeof(sRedEntryPrefixedNewlineFmt) == + REDSOUND_ENTRY_SDATA2_STRING_SIZE); + /* * --INFO-- * PAL Address: 0x801c05f8 @@ -137,7 +341,7 @@ void CRedEntry::Init() bankIndex = bankIndex + 1; } while (bankIndex < REDSOUND_MUSIC_BANK_ENTRY_COUNT); - m_waveLoadNo = -1; + m_waveLoadNo = REDSOUND_WAVE_NO_NONE; } /* @@ -228,7 +432,7 @@ int CRedEntry::SearchWaveSequence(int waveNo) waveBank += 1; } - return -1; + return REDSOUND_HISTORY_BANK_NOT_FOUND; } /* @@ -247,7 +451,7 @@ int CRedEntry::SearchUseWave(int waveNo) RedSoundCONTROL* control = p_SoundControlBuffer + REDSOUND_CONTROL_MUSIC_SECONDARY; do { - if ((control->m_musicId >= 0) && (control->m_waveNo == waveNo)) { + if ((control->m_musicId >= REDSOUND_MUSIC_ID_MIN) && (control->m_waveNo == waveNo)) { found = 1; MusicStop(control->m_musicId); } @@ -280,19 +484,19 @@ int CRedEntry::SearchUseWave(int waveNo) */ int CRedEntry::WaveDelete(RedHistoryBANK* bank) { - int sequenceNo = -1; + int sequenceNo = REDSOUND_HISTORY_BANK_NOT_FOUND; int waveNo; if (bank->m_id >= 0) { WaveHistoryDelete(bank->m_historyNo); waveNo = bank->m_id; - bank->m_id = -1; + bank->m_id = REDSOUND_HISTORY_BANK_EMPTY_ID; bank->m_size = 0; sequenceNo = SearchWaveSequence(waveNo); if (sequenceNo < 0) { - if ((SearchUseWave(waveNo) != 0) && (m_ReportPrint != 0)) { + if ((SearchUseWave(waveNo) != 0) && (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF)) { OSReport(sRedEntryColoredBlankLineFmt, sRedEntryLogPrefix, sRedEntryErrorColor, sRedEntryResetColor); fflush(__files + 1); OSReport(sRedEntryErrorBannerFmt, sRedEntryLogPrefix, sRedEntryErrorColor, sRedEntryResetColor); @@ -303,8 +507,8 @@ int CRedEntry::WaveDelete(RedHistoryBANK* bank) OSReport(sRedEntryColoredBlankLineFmt, sRedEntryLogPrefix, sRedEntryErrorColor, sRedEntryResetColor); fflush(__files + 1); } - RedDeleteA(reinterpret_cast(bank->m_data)->m_aramAddress); - RedDelete(bank->m_data); + RedDeleteA(bank->m_waveHead->m_aramAddress); + RedDelete(bank->m_address); } bank->m_data = 0; @@ -334,7 +538,7 @@ int CRedEntry::WaveOldClear(int offset, int maxSize) do { if (history->m_historyNo > maxBankSize) { - arAddress = reinterpret_cast(history->m_data)->m_aramAddress; + arAddress = history->m_waveHead->m_aramAddress; if ((arAddress >= offset) && (arAddress < maxSize)) { maxBankSize = history->m_historyNo; selected = history; @@ -363,12 +567,12 @@ int CRedEntry::WaveHeadAdd(int waveBankNo, RedWaveHeadWD* waveHead, int waveNo) { if ((waveHead->m_signature[0] != REDSOUND_WAVE_SIGNATURE_MAGIC0) || (waveHead->m_signature[1] != REDSOUND_WAVE_SIGNATURE_MAGIC1)) { - if (m_ReportPrint != 0) { + if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { OSReport(sRedEntryWaveHeaderBrokenFmt, sRedEntryLogPrefix, sRedEntryHeaderErrorColor, sRedEntryResetColor); fflush(__files + 1); } - return -1; + return REDSOUND_WAVE_ADD_FAILED; } if (waveHead->m_loadSize < waveHead->m_waveSize) { @@ -384,8 +588,8 @@ int CRedEntry::WaveHeadAdd(int waveBankNo, RedWaveHeadWD* waveHead, int waveNo) } else if ((waveNo >= REDSOUND_WAVE_STAGE_RANGE_BEGIN) && (waveNo < REDSOUND_WAVE_STAGE_RANGE_END)) { waveHead->m_loadSize += REDSOUND_WAVE_STAGE_LOAD_BLOCK_ROUND; int blocks = waveHead->m_loadSize / REDSOUND_WAVE_STAGE_LOAD_BLOCK_SIZE; - blocks -= blocks >> 0x1F; - waveHead->m_loadSize = blocks * REDSOUND_WAVE_STAGE_LOAD_BLOCK_SIZE; + waveHead->m_loadSize = + (blocks - (blocks >> REDSOUND_SIGN_SHIFT)) * REDSOUND_WAVE_STAGE_LOAD_BLOCK_SIZE; } else if (((waveNo >= REDSOUND_WAVE_FIXED_RANGE0_BEGIN) && (waveNo < REDSOUND_WAVE_FIXED_RANGE0_END)) || ((waveNo >= REDSOUND_WAVE_FIXED_RANGE1_BEGIN) && (waveNo < REDSOUND_WAVE_FIXED_RANGE1_END)) || (waveNo == REDSOUND_WAVE_FIXED_SINGLE)) { @@ -430,9 +634,9 @@ int CRedEntry::WaveHeadAdd(int waveBankNo, RedWaveHeadWD* waveHead, int waveNo) (REDSOUND_WAVE_TABLE_ALIGN - 1)) & REDSOUND_WAVE_TABLE_ALIGN_MASK; copySize += waveHead->m_toneCount * REDSOUND_WAVE_TONE_ENTRY_SIZE + REDSOUND_WAVE_HEADER_COPY_BASE_SIZE; - void* copied = (void*)RedNew(copySize); + RedWaveHeadWD* copied = (RedWaveHeadWD*)RedNew(copySize); if (copied != 0) { - historyBank->m_data = (int)copied; + historyBank->m_waveHead = copied; historyBank->m_size = copySize; waveHead->m_aramAddress = arAddress; historyBank->m_id = waveNo; @@ -450,13 +654,13 @@ int CRedEntry::WaveHeadAdd(int waveBankNo, RedWaveHeadWD* waveHead, int waveNo) } } while (WaveOldClear(minOffset, maxOffset) != 0); - if (m_ReportPrint != 0) { + if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { OSReport(sRedEntryNoWaveMemoryFreeAreaFmt, sRedEntryLogPrefix, sRedEntryErrorColor, (int)waveHead->m_waveNo, waveHead->m_waveSize, sRedEntryResetColor); fflush(__files + 1); } - return -1; + return REDSOUND_WAVE_ADD_FAILED; } /* @@ -471,37 +675,37 @@ int CRedEntry::WaveHeadAdd(int waveBankNo, RedWaveHeadWD* waveHead, int waveNo) int CRedEntry::SetWaveData(int waveBankNo, void* waveData, int waveDataSize) { int waveNo; + int historyNo; int waveAddress; int waveSize; - void* waveDataTop; + u8* waveDataTop; if (waveDataSize == 0) { if ((m_waveLoadNo >= 0) && ((waveNo = SearchWaveSequence(m_waveLoadNo)) >= 0)) { WaveDelete(&m_waveBankBase[waveNo]); } - m_waveLoadNo = -1; - return -1; + m_waveLoadNo = REDSOUND_WAVE_NO_NONE; + return REDSOUND_WAVE_NO_NONE; } waveAddress = 0; if (m_waveLoadNo < 0) { - RedWaveHeadWD* waveHead = (RedWaveHeadWD*)waveData; - waveNo = waveHead->m_waveNo; + waveNo = ((RedWaveHeadWD*)waveData)->m_waveNo; if ((waveBankNo >= 0) && (waveNo != m_waveBankBase[waveBankNo].m_id)) { WaveDelete(&m_waveBankBase[waveBankNo]); } - int historyNo = SearchWaveSequence(waveNo); + historyNo = SearchWaveSequence(waveNo); if (historyNo >= 0) { if ((waveBankNo >= 0) && (historyNo != waveBankNo)) { m_waveBankBase[waveBankNo].m_id = m_waveBankBase[historyNo].m_id; m_waveBankBase[waveBankNo].m_historyNo = m_waveBankBase[historyNo].m_historyNo; - m_waveBankBase[waveBankNo].m_data = - m_waveBankBase[historyNo].m_data; + m_waveBankBase[waveBankNo].m_address = + m_waveBankBase[historyNo].m_address; m_waveBankBase[waveBankNo].m_size = m_waveBankBase[historyNo].m_size; historyNo = waveBankNo; @@ -509,26 +713,26 @@ int CRedEntry::SetWaveData(int waveBankNo, void* waveData, int waveDataSize) WaveHistoryChoice(&m_waveBankBase[historyNo]); } else { - m_waveLoadNo = waveHead->m_waveNo; - waveAddress = WaveHeadAdd(waveBankNo, waveHead, waveNo); + m_waveLoadNo = ((RedWaveHeadWD*)waveData)->m_waveNo; + waveAddress = WaveHeadAdd(waveBankNo, (RedWaveHeadWD*)waveData, waveNo); if (waveAddress < 0) { m_waveLoadSize = 0; - m_waveLoadNo = -1; - return -1; + m_waveLoadNo = REDSOUND_WAVE_NO_NONE; + return REDSOUND_WAVE_NO_NONE; } int waveHeadSize = - ((((waveHead->m_tableCount * REDSOUND_WAVE_TABLE_ENTRY_SIZE) + (REDSOUND_WAVE_TABLE_ALIGN - 1)) & + ((((((RedWaveHeadWD*)waveData)->m_tableCount * REDSOUND_WAVE_TABLE_ENTRY_SIZE) + (REDSOUND_WAVE_TABLE_ALIGN - 1)) & REDSOUND_WAVE_TABLE_ALIGN_MASK) + - waveHead->m_toneCount * REDSOUND_WAVE_TONE_ENTRY_SIZE) + + ((RedWaveHeadWD*)waveData)->m_toneCount * REDSOUND_WAVE_TONE_ENTRY_SIZE) + REDSOUND_WAVE_HEADER_COPY_BASE_SIZE; - waveSize = waveHead->m_waveSize; + waveSize = ((RedWaveHeadWD*)waveData)->m_waveSize; waveDataSize -= waveHeadSize; - waveDataTop = (void*)((unsigned char*)waveData + waveHeadSize); + waveDataTop = (u8*)waveData + waveHeadSize; } } else { waveAddress = m_waveLoadAddress; - waveDataTop = waveData; + waveDataTop = (u8*)waveData; waveSize = m_waveLoadSize; } @@ -547,16 +751,16 @@ int CRedEntry::SetWaveData(int waveBankNo, void* waveData, int waveDataSize) m_waveLoadAddress = waveAddress; while (RedDmaSearchID(dmaID) > 0) { - RedSleep(1000); + RedSleep(REDSOUND_WAVE_LOAD_DMA_POLL_SLEEP_US); } if (m_waveLoadSize < 1) { - if (m_ReportPrint != 0) { + if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { OSReport(sRedEntryWaveEntryFmt, sRedEntryLogPrefix, sRedEntryInfoColor, m_waveLoadNo, sRedEntryResetColor); fflush(__files + 1); } - m_waveLoadNo = -1; + m_waveLoadNo = REDSOUND_WAVE_NO_NONE; return 0; } } @@ -578,21 +782,21 @@ void CRedEntry::ClearWaveData(int waveNo) RedHistoryBANK* historyBank; if (waveNo < 0) { - if (waveNo == -1) { + if (waveNo == REDSOUND_WAVE_CLEAR_ALL) { for (historyBank = m_waveBankBase; historyBank < m_waveBankBase + REDSOUND_WAVE_BANK_ENTRY_COUNT; historyBank += 1) { if (historyBank->m_id >= 0) { WaveDelete(historyBank); } } - } else if (waveNo == -2) { + } else if (waveNo == REDSOUND_WAVE_CLEAR_UNBANKED) { for (historyBank = &m_waveBankBase[REDSOUND_WAVE_PRIMARY_BANK_ENTRY_COUNT]; historyBank < m_waveBankBase + REDSOUND_WAVE_BANK_ENTRY_COUNT; historyBank += 1) { if (historyBank->m_id >= 0) { WaveDelete(historyBank); } } - } else if (waveNo == -3) { + } else if (waveNo == REDSOUND_WAVE_CLEAR_UNBANKED_USED) { for (historyBank = &m_waveBankBase[REDSOUND_WAVE_PRIMARY_BANK_ENTRY_COUNT]; historyBank < m_waveBankBase + REDSOUND_WAVE_BANK_ENTRY_COUNT; historyBank += 1) { if ((historyBank->m_id >= 0) && (0 < historyBank->m_historyNo)) { @@ -621,7 +825,9 @@ void CRedEntry::ClearWaveDataM(int waveNo0, int waveNo1, int waveNo2, int waveNo { RedHistoryBANK* historyBank; - if (((waveNo0 == -1) && (waveNo1 == -1) && (waveNo2 == -1)) && (waveNo3 == -1)) { + if (((waveNo0 == REDSOUND_WAVE_NO_NONE) && (waveNo1 == REDSOUND_WAVE_NO_NONE) && + (waveNo2 == REDSOUND_WAVE_NO_NONE)) && + (waveNo3 == REDSOUND_WAVE_NO_NONE)) { return; } @@ -649,21 +855,21 @@ void CRedEntry::ClearWaveBank(int waveBankNo) RedHistoryBANK* historyBank; if (waveBankNo < 0) { - if (waveBankNo == -1) { + if (waveBankNo == REDSOUND_WAVE_CLEAR_ALL) { for (historyBank = m_waveBankBase; historyBank < m_waveBankBase + REDSOUND_WAVE_BANK_ENTRY_COUNT; historyBank += 1) { if (!(historyBank->m_id < 0)) { WaveDelete(historyBank); } } - } else if (waveBankNo == -2) { + } else if (waveBankNo == REDSOUND_WAVE_CLEAR_UNBANKED) { for (historyBank = &m_waveBankBase[REDSOUND_WAVE_PRIMARY_BANK_ENTRY_COUNT]; historyBank < m_waveBankBase + REDSOUND_WAVE_BANK_ENTRY_COUNT; historyBank += 1) { if (!(historyBank->m_id < 0)) { WaveDelete(historyBank); } } - } else if (waveBankNo == -3) { + } else if (waveBankNo == REDSOUND_WAVE_CLEAR_UNBANKED_USED) { for (historyBank = &m_waveBankBase[REDSOUND_WAVE_PRIMARY_BANK_ENTRY_COUNT]; historyBank < m_waveBankBase + REDSOUND_WAVE_BANK_ENTRY_COUNT; historyBank += 1) { if (!(historyBank->m_id < 0) && (0 < historyBank->m_historyNo)) { @@ -685,11 +891,11 @@ void CRedEntry::ClearWaveBank(int waveBankNo) * JP Address: TODO * JP Size: TODO */ -int CRedEntry::GetWaveBank(int waveNo) +RedHistoryBANK* CRedEntry::GetWaveBank(int waveNo) { if ((waveNo >= 0) && (waveNo < REDSOUND_WAVE_PRIMARY_BANK_ENTRY_COUNT)) { - return reinterpret_cast(&m_waveBankBase[waveNo]); + return &m_waveBankBase[waveNo]; } return 0; @@ -710,7 +916,7 @@ RedWaveHeadWD* CRedEntry::SearchWaveBase(int waveNo) do { if (waveNo == waveBank->m_id) { - return reinterpret_cast(waveBank->m_data); + return waveBank->m_waveHead; } waveBank += 1; } while (waveBank < m_waveBankBase + REDSOUND_WAVE_BANK_ENTRY_COUNT); @@ -750,7 +956,7 @@ void CRedEntry::WaveHistoryManager(int mode, int waveNo) int used; RedTrackDATA* track; - if (mode == 0) { + if (mode == REDSOUND_HISTORY_MODE_RELEASE) { used = 0; if ((p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_PRIMARY].m_activeTrackCount != 0) && (p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_PRIMARY].m_waveNo == waveNo)) { @@ -801,7 +1007,7 @@ void CRedEntry::WaveHistoryManager(int mode, int waveNo) */ void CRedEntry::DisplayWaveInfo() { - if (m_ReportPrint != 0) { + if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { OSReport(sRedEntryNewline); fflush(__files + 1); OSReport(sRedEntryAMemoryInfoHeaderFmt, sRedEntryLogPrefix); @@ -827,7 +1033,7 @@ void CRedEntry::DisplayWaveInfo() RedHistoryBANK* history = m_waveBankBase; do { - if ((history->m_size != 0) && (((RedWaveHeadWD*)history->m_data)->m_aramAddress == bank->m_address)) { + if ((history->m_size != 0) && (history->m_waveHead->m_aramAddress == bank->m_address)) { break; } history += 1; @@ -838,12 +1044,12 @@ void CRedEntry::DisplayWaveInfo() int index = reinterpret_cast(history) - reinterpret_cast(m_waveBankBase); OSReport(sRedEntryAMemoryWaveBankInfoFmt, sRedEntryLogPrefix, index / REDSOUND_HISTORY_BANK_ENTRY_SIZE, - (int)((RedWaveHeadWD*)history->m_data)->m_waveNo, ((RedWaveHeadWD*)history->m_data)->m_aramAddress, bank->m_size, + (int)history->m_waveHead->m_waveNo, history->m_waveHead->m_aramAddress, bank->m_size, freeSize, history->m_historyNo); fflush(__files + 1); } else { OSReport(sRedEntryAMemoryUnbankedWaveInfoFmt, sRedEntryLogPrefix, - (int)((RedWaveHeadWD*)history->m_data)->m_waveNo, ((RedWaveHeadWD*)history->m_data)->m_aramAddress, bank->m_size, + (int)history->m_waveHead->m_waveNo, history->m_waveHead->m_aramAddress, bank->m_size, freeSize, history->m_historyNo); fflush(__files + 1); } @@ -963,7 +1169,7 @@ int CRedEntry::SearchSeSepSequence(int seNo) { RedHistoryBANK* seSepBank = m_seSepBankBase; - if (seNo == -1) { + if (seNo == REDSOUND_SESEP_SEARCH_FIRST) { do { if (seSepBank->m_size != 0) { return seSepBank - m_seSepBankBase; @@ -979,7 +1185,7 @@ int CRedEntry::SearchSeSepSequence(int seNo) } while (seSepBank < m_seSepBankBase + REDSOUND_SESEP_BANK_ENTRY_COUNT); } - return -1; + return REDSOUND_HISTORY_BANK_NOT_FOUND; } /* @@ -994,17 +1200,17 @@ int CRedEntry::SearchSeSepSequence(int seNo) int CRedEntry::SeSepMemoryFree(RedHistoryBANK* bank) { int freedSize; - int waveNo = static_cast(reinterpret_cast(bank->m_data)->m_waveNoLo) + - static_cast(reinterpret_cast(bank->m_data)->m_waveNoHi) * REDSOUND_SESEP_WAVE_NO_HIGH_SCALE; + int waveNo = static_cast(bank->m_seSepHead->m_waveNoLo) + + static_cast(bank->m_seSepHead->m_waveNoHi) * REDSOUND_SESEP_WAVE_NO_HIGH_SCALE; - RedDelete(bank->m_data); + RedDelete(bank->m_address); SeSepHistoryDelete(bank->m_historyNo); freedSize = bank->m_size; bank->m_data = bank->m_size = 0; - bank->m_id = -1; + bank->m_id = REDSOUND_HISTORY_BANK_EMPTY_ID; - WaveHistoryManager(0, waveNo); + WaveHistoryManager(REDSOUND_HISTORY_MODE_RELEASE, waveNo); return freedSize; } @@ -1050,7 +1256,7 @@ RedHistoryBANK* CRedEntry::SeSepOldDelete() RedSeSepHEAD* CRedEntry::SeSepHeadAdd(RedSeSepHEAD* seSepHead) { RedHistoryBANK* bank = m_seSepBankBase; - int result = 0; + RedSeSepHEAD* result = 0; while ((bank->m_size != 0) && (bank < m_seSepBankBase + REDSOUND_SESEP_BANK_ENTRY_COUNT)) { @@ -1063,15 +1269,15 @@ RedSeSepHEAD* CRedEntry::SeSepHeadAdd(RedSeSepHEAD* seSepHead) if ((bank != 0) && (bank < m_seSepBankBase + REDSOUND_SESEP_BANK_ENTRY_COUNT)) { - bank->m_data = reinterpret_cast(seSepHead); - result = reinterpret_cast(seSepHead); + bank->m_seSepHead = seSepHead; + result = seSepHead; bank->m_size = seSepHead->m_sizeAndFlags & REDSOUND_SESEP_SIZE_MASK; bank->m_id = seSepHead->m_seNo; SeSepHistoryAdd(); bank->m_historyNo = 1; } - return reinterpret_cast(result); + return result; } /* @@ -1087,13 +1293,13 @@ RedSeSepHEAD* CRedEntry::SetSeSepData(RedSeSepHEAD* seSepHead) { int result; - if ((seSepHead->m_signature[0] != REDSOUND_ENTRY_SESEP_SIGNATURE_0) || - (seSepHead->m_signature[1] != REDSOUND_ENTRY_SESEP_SIGNATURE_1) || - (seSepHead->m_signature[2] != REDSOUND_ENTRY_SESEP_SIGNATURE_2) || - (seSepHead->m_signature[3] != REDSOUND_ENTRY_SESEP_SIGNATURE_3) || - (seSepHead->m_signature[4] != REDSOUND_ENTRY_SESEP_SIGNATURE_4)) { + if ((seSepHead->m_signature[0] != REDSOUND_SESEP_SIGNATURE_0) || + (seSepHead->m_signature[1] != REDSOUND_SESEP_SIGNATURE_1) || + (seSepHead->m_signature[2] != REDSOUND_SESEP_SIGNATURE_2) || + (seSepHead->m_signature[3] != REDSOUND_SESEP_SIGNATURE_3) || + (seSepHead->m_signature[4] != REDSOUND_SESEP_SIGNATURE_4)) { RedDelete(seSepHead); - if (m_ReportPrint != 0) { + if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { OSReport(sRedEntrySeSepHeaderBrokenFmt, sRedEntryLogPrefix, sRedEntryHeaderErrorColor, sRedEntryResetColor); fflush(__files + 1); } @@ -1104,7 +1310,7 @@ RedSeSepHEAD* CRedEntry::SetSeSepData(RedSeSepHEAD* seSepHead) if (result >= 0) { RedDelete(seSepHead); SeSepHistoryChoice(&m_seSepBankBase[result]); - result = m_seSepBankBase[result].m_data; + result = m_seSepBankBase[result].m_address; } else { result = reinterpret_cast(SeSepHeadAdd(seSepHead)); if (result == 0) { @@ -1128,7 +1334,7 @@ int CRedEntry::ClearSeSepData(int seNo) { int result = 0; - if (seNo == -1) { + if (seNo == REDSOUND_SESEP_CLEAR_ALL) { RedHistoryBANK* history = m_seSepBankBase; do { if (history->m_size != 0) { @@ -1162,7 +1368,7 @@ int CRedEntry::ClearSeSepDataMG(int bankNo, int sepNo, int groupNo, int kindNo) do { if (bank->m_size != 0) { - int seNo = bank->m_id / 1000; + int seNo = bank->m_id / REDSOUND_SE_MG_ID_DIVISOR; if ((bankNo != seNo) && (sepNo != seNo) && (groupNo != seNo) && (kindNo != seNo)) { SeSepMemoryFree(bank); } @@ -1227,7 +1433,7 @@ void CRedEntry::SeSepHistoryManager(int mode, int seNo) RedTrackDATA* track; int sequenceNo; - if (mode == 0) { + if (mode == REDSOUND_HISTORY_MODE_RELEASE) { sequenceNo = 0; track = p_SoundControlBuffer[REDSOUND_CONTROL_SE].m_tracks; @@ -1266,7 +1472,7 @@ void CRedEntry::SeSepHistoryManager(int mode, int seNo) */ void CRedEntry::DisplaySePlayInfo() { - if (m_ReportPrint != 0) { + if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { OSReport(sRedEntryNewline); fflush(__files + 1); OSReport(sRedEntrySePlayInfoHeaderFmt, sRedEntryLogPrefix); @@ -1276,36 +1482,35 @@ void CRedEntry::DisplaySePlayInfo() RedTrackDATA** trackHead = &p_SoundControlBuffer[REDSOUND_CONTROL_SE].m_tracks; RedTrackDATA* track = *trackHead; + int trackIndex; + int waveNo; do { if (track->m_command != 0) { if ((track->m_seSepId & REDSOUND_SE_BLOCK_DATA_FLAG) != 0) { - unsigned int seDataNo = (unsigned int)track->m_seSepId; - int songNo = (int)(seDataNo & REDSOUND_SE_BLOCK_ENTRY_MASK) >> REDSOUND_SE_BLOCK_BANK_SHIFT; - RedSeBlockHEAD* seBlock = p_SeBlockData[songNo]; - int* entries = seBlock->m_entries; - RedSeINFO* seqInfo = - reinterpret_cast(entries + seBlock->m_seCount); - seqInfo = reinterpret_cast( - reinterpret_cast(seqInfo) + - (entries[seDataNo & REDSOUND_SE_BLOCK_SEQUENCE_MASK] & REDSOUND_SE_BLOCK_ENTRY_MASK)); - int waveNo = (seqInfo->m_waveNoHi << 8) | seqInfo->m_waveNoLo; - int trackIndex = track - *trackHead; + unsigned int seBlockId = (unsigned int)track->m_seSepId; + int bank = (int)(seBlockId & REDSOUND_SE_BLOCK_ENTRY_MASK) / + REDSOUND_SE_BLOCK_SEQUENCE_COUNT; + int sequence = seBlockId & REDSOUND_SE_BLOCK_SEQUENCE_MASK; + RedSeBlockHEAD* seBlock = p_SeBlockData[bank]; + RedSeINFO* seqInfo = RedSeBlockGetInfo(seBlock, sequence); + waveNo = (seqInfo->m_waveNoHi * REDSOUND_SE_INFO_U16_HIGH_SCALE) | seqInfo->m_waveNoLo; + trackIndex = track - *trackHead; OSReport(sRedEntrySeBlockPlayInfoFmt, sRedEntryLogPrefix, - trackIndex + REDSOUND_SE_VOICE_BASE_INDEX, songNo, - seDataNo & REDSOUND_SE_BLOCK_SEQUENCE_MASK, waveNo); + trackIndex + REDSOUND_SE_VOICE_BASE_INDEX, bank, + sequence, waveNo); fflush(__files + 1); } else { RedHistoryBANK* seSepBank = SearchSeSepBank(track->m_seSepId); - RedSeSepHEAD* seSepHead = reinterpret_cast(seSepBank->m_data); - int trackIndex = track - *trackHead; - int waveNo = (seSepHead->m_waveNoHi << 8) | seSepHead->m_waveNoLo; + RedSeSepHEAD* seSepHead = seSepBank->m_seSepHead; + trackIndex = track - *trackHead; + waveNo = (seSepHead->m_waveNoHi * REDSOUND_SESEP_WAVE_NO_HIGH_SCALE) | seSepHead->m_waveNoLo; OSReport(sRedEntrySeSepPlayInfoFmt, sRedEntryLogPrefix, trackIndex + REDSOUND_SE_VOICE_BASE_INDEX, track->m_seSepId, waveNo); fflush(__files + 1); } } else { - int trackIndex = track - *trackHead; + trackIndex = track - *trackHead; OSReport(sRedEntrySeEmptyPlayInfoFmt, sRedEntryLogPrefix, trackIndex + REDSOUND_SE_VOICE_BASE_INDEX); fflush(__files + 1); @@ -1406,7 +1611,7 @@ int CRedEntry::SearchMusicSequence(int musicNo) musicBank += 1; } while (musicBank < m_musicBankBase + REDSOUND_MUSIC_BANK_ENTRY_COUNT); - return -1; + return REDSOUND_HISTORY_BANK_NOT_FOUND; } /* @@ -1420,12 +1625,12 @@ int CRedEntry::SearchMusicSequence(int musicNo) */ int CRedEntry::MusicMemoryFree(RedHistoryBANK* bank) { - WaveHistoryManager(0, reinterpret_cast(bank->m_data)->m_waveNo); - RedDelete(bank->m_data); + WaveHistoryManager(REDSOUND_HISTORY_MODE_RELEASE, bank->m_musicHead->m_waveNo); + RedDelete(bank->m_address); int freedSize = bank->m_size; bank->m_data = bank->m_size = 0; bank->m_historyNo = 0; - bank->m_id = -1; + bank->m_id = REDSOUND_HISTORY_BANK_EMPTY_ID; return freedSize; } @@ -1541,7 +1746,7 @@ void CRedEntry::MusicHistoryManager(int mode, int musicNo) { int musicSeq; - if (mode == 0) { + if (mode == REDSOUND_HISTORY_MODE_RELEASE) { musicSeq = 0; if ((p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_PRIMARY].m_activeTrackCount != 0) && (p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_PRIMARY].m_musicId == musicNo)) { @@ -1583,7 +1788,7 @@ void CRedEntry::MusicHistoryManager(int mode, int musicNo) */ RedMusicHEAD* CRedEntry::MusicHeadAdd(RedMusicHEAD* musicHead) { - int result = 0; + RedMusicHEAD* result = 0; RedHistoryBANK* bank = MusicOldChoice(); if ((bank != 0) && (bank->m_size != 0)) { MusicOldClear(); @@ -1591,15 +1796,15 @@ RedMusicHEAD* CRedEntry::MusicHeadAdd(RedMusicHEAD* musicHead) } if (bank != 0) { - bank->m_data = reinterpret_cast(musicHead); - result = reinterpret_cast(musicHead); + bank->m_musicHead = musicHead; + result = musicHead; bank->m_size = musicHead->m_size; bank->m_id = static_cast(musicHead->m_musicNo); MusicHistoryAdd(); bank->m_historyNo = 1; } - return reinterpret_cast(result); + return result; } /* @@ -1615,11 +1820,11 @@ RedMusicHEAD* CRedEntry::SetMusicData(RedMusicHEAD* musicHead) { int result; - if ((musicHead->m_signature[0] != REDSOUND_ENTRY_MUSIC_SIGNATURE_0) || - (musicHead->m_signature[1] != REDSOUND_ENTRY_MUSIC_SIGNATURE_1) || - (musicHead->m_signature[2] != REDSOUND_ENTRY_MUSIC_SIGNATURE_2)) { + if ((musicHead->m_signature[0] != REDSOUND_MUSIC_SIGNATURE_0) || + (musicHead->m_signature[1] != REDSOUND_MUSIC_SIGNATURE_1) || + (musicHead->m_signature[2] != REDSOUND_MUSIC_SIGNATURE_2)) { RedDelete(musicHead); - if (m_ReportPrint != 0) { + if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { OSReport(sRedEntryMusicHeaderBrokenFmt, sRedEntryLogPrefix, sRedEntryHeaderErrorColor, sRedEntryResetColor); fflush(__files + 1); } @@ -1630,7 +1835,7 @@ RedMusicHEAD* CRedEntry::SetMusicData(RedMusicHEAD* musicHead) if (result >= 0) { RedDelete(musicHead); MusicHistoryChoice(&m_musicBankBase[result]); - result = m_musicBankBase[result].m_data; + result = m_musicBankBase[result].m_address; } else { result = reinterpret_cast(MusicHeadAdd(musicHead)); if (result == 0) { @@ -1641,6 +1846,90 @@ RedMusicHEAD* CRedEntry::SetMusicData(RedMusicHEAD* musicHead) return reinterpret_cast(result); } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 204b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +int CRedEntry::ClearMusicData(int musicNo) +{ + int result = 0; + + if (musicNo == REDSOUND_MUSIC_CLEAR_ALL) { + RedHistoryBANK* history = m_musicBankBase; + do { + if (history->m_size != 0) { + if (history->m_historyNo != 0) { + MusicHistoryDelete(history->m_historyNo); + } + result += MusicMemoryFree(history); + } + history += 1; + } while (history < m_musicBankBase + REDSOUND_MUSIC_BANK_ENTRY_COUNT); + } else { + result = SearchMusicSequence(musicNo); + if (result >= 0) { + result = MusicMemoryFree(&m_musicBankBase[result]); + } + } + + return result; +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 428b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedEntry::DisplayMusicInfo() +{ + if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { + OSReport(sRedEntryNewline); + fflush(__files + 1); + OSReport(sRedEntryMusicInformationHeaderFmt, sRedEntryLogPrefix); + fflush(__files + 1); + OSReport(sRedEntryMusicInfoColumnFmt, sRedEntryLogPrefix); + fflush(__files + 1); + + RedHistoryBANK* history = m_musicBankBase; + do { + if (history->m_size != 0) { + int playing = 0; + if ((p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_PRIMARY].m_activeTrackCount != 0) && + (p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_PRIMARY].m_musicId == history->m_id)) { + playing = 1; + } + if ((p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_SECONDARY].m_activeTrackCount != 0) && + (p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_SECONDARY].m_musicId == history->m_id)) { + playing = 1; + } + + if (playing != 0) { + OSReport(sRedEntryMusicInfoPlayFmt, sRedEntryLogPrefix, history->m_id, + history->m_musicHead->m_waveNo, history->m_size); + fflush(__files + 1); + } else { + OSReport(sRedEntryMusicInfoStopFmt, sRedEntryLogPrefix, history->m_id, + history->m_musicHead->m_waveNo, history->m_size); + fflush(__files + 1); + } + } + history += 1; + } while (history < m_musicBankBase + REDSOUND_MUSIC_BANK_ENTRY_COUNT); + + OSReport(sRedEntryNewline); + fflush(__files + 1); + } +} + /* * --INFO-- * PAL Address: 0x801c2b70 @@ -1663,7 +1952,7 @@ void CRedEntry::DisplayMMemoryInfo() RedMemoryBlock* bankEntry; RedHistoryBANK* history; - if (m_ReportPrint == 0) { + if (m_ReportPrint == REDSOUND_REPORT_PRINT_OFF) { return; } @@ -1675,8 +1964,8 @@ void CRedEntry::DisplayMMemoryInfo() fflush(__files + 1); maxFreeSize = 0; - entryCount = 0; totalSize = 0; + entryCount = 0; nextAddress = c_RedMemory.GetMainBufferAddress(); memoryBank = c_RedMemory.GetMainBankAddress(); bankEntry = memoryBank; @@ -1695,7 +1984,7 @@ void CRedEntry::DisplayMMemoryInfo() history = m_musicBankBase; do { - if ((history->m_size != 0) && (history->m_data == bankEntry->m_address)) { + if ((history->m_size != 0) && (history->m_address == bankEntry->m_address)) { OSReport(sRedEntryMMemoryMusicInfoFmt, sRedEntryLogPrefix, reinterpret_cast(bankEntry->m_address)->m_musicNo, bankEntry->m_address, bankEntry->m_size, freeSize); @@ -1723,7 +2012,7 @@ void CRedEntry::DisplayMMemoryInfo() if (matched == 0) { history = m_waveBankBase; do { - if ((history->m_size != 0) && (history->m_data == bankEntry->m_address)) { + if ((history->m_size != 0) && (history->m_address == bankEntry->m_address)) { OSReport(sRedEntryMMemoryWaveInfoFmt, sRedEntryLogPrefix, reinterpret_cast(bankEntry->m_address)->m_waveNo, bankEntry->m_address, bankEntry->m_size, freeSize); @@ -1738,7 +2027,7 @@ void CRedEntry::DisplayMMemoryInfo() if (matched == 0) { history = m_seSepBankBase; do { - if ((history->m_size != 0) && (history->m_data == bankEntry->m_address)) { + if ((history->m_size != 0) && (history->m_address == bankEntry->m_address)) { OSReport(sRedEntryMMemorySeInfoFmt, sRedEntryLogPrefix, reinterpret_cast(bankEntry->m_address)->m_seNo, bankEntry->m_address, bankEntry->m_size, freeSize); diff --git a/src/RedSound/RedExecute.cpp b/src/RedSound/RedExecute.cpp index 7ff91ed5e8..89e52e42ed 100644 --- a/src/RedSound/RedExecute.cpp +++ b/src/RedSound/RedExecute.cpp @@ -4,17 +4,18 @@ #include "ffcc/RedSound/RedDriver.h" #include "ffcc/RedSound/RedMidiCtrl.h" #include "ffcc/RedSound/RedGlobals.h" +#include "global.h" #include "types.h" #include "dolphin/ax.h" #include "dolphin/axfx.h" #include -u32 t_TonePitch[] = { +u32 t_TonePitch[REDSOUND_NOTES_PER_OCTAVE] = { 131072, 138865, 147123, 155871, 165140, 174960, 185363, 196386, 208063, 220435, 233543, 247430, }; -int t_FinePitch[] = { +int t_FinePitch[REDSOUND_PITCH_FINE_COUNT] = { 65536, 65550, 65565, 65580, 65595, 65609, 65624, 65639, 65654, 65669, 65684, 65698, 65713, 65728, 65743, 65758, 65773, 65787, 65802, 65817, 65832, 65847, 65862, 65876, @@ -49,20 +50,20 @@ int t_FinePitch[] = { 69307, 69323, 69339, 69354, 69370, 69385, 69401, 69417, }; -int t_KeySignatureIndex[] = { +int t_KeySignatureIndex[REDSOUND_KEY_SIGNATURE_INDEX_COUNT] = { 11, 4, 9, 2, 7, 0, 5, 10, 11, 0, 5, 10, 3, 8, 1, 6, 25, 30, 23, 28, 33, 26, 31, 24, 34, 26, 31, 24, 29, 34, 27, 32, }; -signed char t_KeySignatureData[] = { +signed char t_KeySignatureData[REDSOUND_KEY_SIGNATURE_DATA_COUNT] = { 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, -1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, }; -signed char t_RandomData[] = { +signed char t_RandomData[REDSOUND_RANDOM_DATA_COUNT] = { -115, 0, -26, 99, -116, -94, 94, 31, 49, 108, 21, -3, -52, 62, -7, -123, -43, 127, 98, 1, 101, 69, -33, -113, 112, -86, 88, 111, 56, 96, 79, 126, 105, -17, 124, -85, 12, -50, -55, 66, 8, -42, -4, 5, -24, -9, -105, -34, @@ -81,7 +82,7 @@ signed char t_RandomData[] = { -76, -32, -121, -75, -96, -36, -54, -65, 92, -91, -62, 55, 59, 75, -39, -119, }; -s16 t_PanningData[] = { +s16 t_PanningData[REDSOUND_PAN_TABLE_COUNT] = { 256, 254, 253, 252, 251, 250, 248, 247, 246, 245, 244, 243, 241, 240, 239, 238, 237, 236, 234, 233, 232, 231, 230, 229, @@ -116,7 +117,7 @@ s16 t_PanningData[] = { 207, 213, 219, 225, 231, 237, 243, 249, }; -s16 t_PanningDataR[] = { +s16 t_PanningDataR[REDSOUND_PAN_TABLE_COUNT] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -163,22 +164,86 @@ static const float s_ReverbEffectScale = 100.0f; enum RedExecuteLayoutSize { REDSOUND_REVERB_DATA_COUNT = 2, REDSOUND_REVERB_DATA_BUFFER_SIZE = sizeof(RedReverbDATA) * REDSOUND_REVERB_DATA_COUNT, + REDSOUND_REVERB_DATA_ALLOC_SIZE = 0x18, + REDSOUND_REVERB_SIZE_ALLOC_SIZE = sizeof(u32), REDSOUND_REVERB_AUX_BUFFER_SIZE = 0x280, REDSOUND_REVERB_ALLOC_ALIGN = 0x20, REDSOUND_REVERB_ALLOC_ALIGN_MASK = REDSOUND_REVERB_ALLOC_ALIGN - 1, }; +enum RedExecuteSmallDataLayout { + REDSOUND_EXECUTE_SDATA_SIZE = 0x04, + REDSOUND_EXECUTE_SBSS_RANDOM_INDEX_OFFSET = 0x00, + REDSOUND_EXECUTE_SBSS_RANDOM_PAD_OFFSET = 0x01, + REDSOUND_EXECUTE_SBSS_RANDOM_PAD_SIZE = 3, + REDSOUND_EXECUTE_SBSS_REVERB_DATA_OFFSET = 0x04, + REDSOUND_EXECUTE_SBSS_REVERB_SIZE_OFFSET = 0x08, + REDSOUND_EXECUTE_SBSS_CHANGE_STATUS_OFFSET = 0x0C, + REDSOUND_EXECUTE_SBSS_SKIP_KEY_ON_OFFSET = 0x10, + REDSOUND_EXECUTE_SBSS_SIZE = 0x14, +}; + +struct RedExecuteSmallDataState { + volatile u8 m_randomIndex; + u8 m_randomIndexAlignPadding[REDSOUND_EXECUTE_SBSS_RANDOM_PAD_SIZE]; + RedReverbDATA* volatile m_reverbData; + RedReverbSize* m_reverbSize; + volatile u32 m_changeStatus; + RedKeyOnDATA* volatile m_skipKeyOn; +}; + enum RedReverbDelayChannelIndex { REDSOUND_REVERB_DELAY_LEFT = 0, REDSOUND_REVERB_DELAY_RIGHT = 1, REDSOUND_REVERB_DELAY_SURROUND = 2, }; +enum RedExecuteAxfxReverbLayout { + REDSOUND_AXFX_REVERB_STD_TEMP_DISABLE_OFFSET = 0x13C, + REDSOUND_AXFX_REVERB_STD_COLORATION_OFFSET = 0x140, + REDSOUND_AXFX_REVERB_STD_MIX_OFFSET = 0x144, + REDSOUND_AXFX_REVERB_STD_TIME_OFFSET = 0x148, + REDSOUND_AXFX_REVERB_STD_DAMPING_OFFSET = 0x14C, + REDSOUND_AXFX_REVERB_STD_PRE_DELAY_OFFSET = 0x150, + REDSOUND_AXFX_REVERB_STD_SIZE = 0x154, + + REDSOUND_AXFX_REVERB_HI_TEMP_DISABLE_OFFSET = 0x1C4, + REDSOUND_AXFX_REVERB_HI_COLORATION_OFFSET = 0x1C8, + REDSOUND_AXFX_REVERB_HI_MIX_OFFSET = 0x1CC, + REDSOUND_AXFX_REVERB_HI_TIME_OFFSET = 0x1D0, + REDSOUND_AXFX_REVERB_HI_DAMPING_OFFSET = 0x1D4, + REDSOUND_AXFX_REVERB_HI_PRE_DELAY_OFFSET = 0x1D8, + REDSOUND_AXFX_REVERB_HI_CROSSTALK_OFFSET = 0x1DC, + REDSOUND_AXFX_REVERB_HI_SIZE = 0x1E0, + + REDSOUND_AXFX_REVERB_HI_DPL2_TEMP_DISABLE_OFFSET = 0x254, + REDSOUND_AXFX_REVERB_HI_DPL2_COLORATION_OFFSET = 0x258, + REDSOUND_AXFX_REVERB_HI_DPL2_MIX_OFFSET = 0x25C, + REDSOUND_AXFX_REVERB_HI_DPL2_TIME_OFFSET = 0x260, + REDSOUND_AXFX_REVERB_HI_DPL2_DAMPING_OFFSET = 0x264, + REDSOUND_AXFX_REVERB_HI_DPL2_PRE_DELAY_OFFSET = 0x268, + REDSOUND_AXFX_REVERB_HI_DPL2_SIZE = 0x26C, + + REDSOUND_AXFX_DELAY_CHANNEL_COUNT = 3, + REDSOUND_AXFX_DELAY_CHANNEL_SIZE = sizeof(u32) * REDSOUND_AXFX_DELAY_CHANNEL_COUNT, + REDSOUND_AXFX_DELAY_DELAY_OFFSET = 0x3C, + REDSOUND_AXFX_DELAY_FEEDBACK_OFFSET = 0x48, + REDSOUND_AXFX_DELAY_OUTPUT_OFFSET = 0x54, + REDSOUND_AXFX_DELAY_SIZE = 0x60, + + REDSOUND_AXFX_CHORUS_BASE_DELAY_OFFSET = 0x90, + REDSOUND_AXFX_CHORUS_VARIATION_OFFSET = 0x94, + REDSOUND_AXFX_CHORUS_PERIOD_OFFSET = 0x98, + REDSOUND_AXFX_CHORUS_SIZE = 0x9C, +}; + enum RedExecuteAxVoiceLayout { - REDSOUND_AX_VOICE_LOOP_OFFSET = 0x148, + REDSOUND_AX_VOICE_TYPE_OFFSET = 0x148, REDSOUND_AX_MIX_CTRL_DRY_STEREO = 0x3, REDSOUND_AX_MIX_CTRL_AUX_A_STEREO = 0x30, REDSOUND_AX_MIX_CTRL_AUX_B_STEREO = 0x600, + REDSOUND_AX_SAMPLE_ADDR_SCALE = 2, + REDSOUND_AX_SAMPLE_START_BIAS = 1, }; enum RedExecutePitchModConst { @@ -194,6 +259,7 @@ enum RedExecuteVolumeModConst { REDSOUND_VOLUME_MOD_SCALE_SHIFT = 7, REDSOUND_VOLUME_TRACK_SCALE_SHIFT = 9, REDSOUND_VOLUME_MOD_WAVE_SHIFT = 4, + REDSOUND_SHAKE_PAN_SCALE_SHIFT = 0x10, }; enum RedControlTickWord { @@ -202,6 +268,11 @@ enum RedControlTickWord { REDSOUND_CONTROL_TICK_PER_MEASURE = 2, }; +enum RedMusicSkipTiming { + REDSOUND_MUSIC_SKIP_RETRY_SLEEP_US = 10000, + REDSOUND_MUSIC_SKIP_LOOP_SLEEP_US = 1000, +}; + enum RedExecuteAdsrStateIndex { REDSOUND_ADSR_STATE_STAGE = 0, REDSOUND_ADSR_STATE_STEP_FRAMES = 1, @@ -213,6 +284,201 @@ enum RedVoiceStartMaskIndex { REDSOUND_VOICE_START_MASK_HIGH = 1, }; +STATIC_ASSERT(sizeof(t_TonePitch) == REDSOUND_TONE_PITCH_TABLE_SIZE); +STATIC_ASSERT(REDSOUND_TONE_PITCH_TABLE_SIZE == REDSOUND_TONE_PITCH_TABLE_ALLOC_SIZE); +STATIC_ASSERT(sizeof(t_FinePitch) == REDSOUND_FINE_PITCH_TABLE_SIZE); +STATIC_ASSERT(REDSOUND_FINE_PITCH_TABLE_SIZE == REDSOUND_FINE_PITCH_TABLE_ALLOC_SIZE); +STATIC_ASSERT(sizeof(t_KeySignatureIndex) == REDSOUND_KEY_SIGNATURE_INDEX_TABLE_SIZE); +STATIC_ASSERT(REDSOUND_KEY_SIGNATURE_INDEX_TABLE_SIZE == REDSOUND_KEY_SIGNATURE_INDEX_TABLE_ALLOC_SIZE); +STATIC_ASSERT(sizeof(t_KeySignatureData) == REDSOUND_KEY_SIGNATURE_DATA_TABLE_SIZE); +STATIC_ASSERT(REDSOUND_KEY_SIGNATURE_DATA_TABLE_SIZE == REDSOUND_KEY_SIGNATURE_DATA_TABLE_ALLOC_SIZE); +STATIC_ASSERT(sizeof(t_RandomData) == REDSOUND_RANDOM_DATA_TABLE_SIZE); +STATIC_ASSERT(REDSOUND_RANDOM_DATA_TABLE_SIZE == REDSOUND_RANDOM_DATA_TABLE_ALLOC_SIZE); +STATIC_ASSERT(sizeof(t_PanningData) == REDSOUND_PAN_TABLE_SIZE); +STATIC_ASSERT(sizeof(t_PanningDataR) == REDSOUND_PAN_TABLE_SIZE); +STATIC_ASSERT(REDSOUND_PAN_TABLE_SIZE == REDSOUND_PAN_TABLE_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_PAN_TABLE_PAIR_SIZE == REDSOUND_PAN_TABLE_PAIR_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_FINE_PITCH_TABLE_OFFSET == REDSOUND_TONE_PITCH_TABLE_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_KEY_SIGNATURE_INDEX_TABLE_OFFSET == + REDSOUND_FINE_PITCH_TABLE_OFFSET + REDSOUND_FINE_PITCH_TABLE_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_KEY_SIGNATURE_DATA_TABLE_OFFSET == + REDSOUND_KEY_SIGNATURE_INDEX_TABLE_OFFSET + REDSOUND_KEY_SIGNATURE_INDEX_TABLE_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_RANDOM_DATA_TABLE_OFFSET == + REDSOUND_KEY_SIGNATURE_DATA_TABLE_OFFSET + REDSOUND_KEY_SIGNATURE_DATA_TABLE_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_PAN_TABLE_OFFSET == REDSOUND_RANDOM_DATA_TABLE_OFFSET + REDSOUND_RANDOM_DATA_TABLE_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_PAN_TABLE_R_OFFSET == REDSOUND_PAN_TABLE_OFFSET + REDSOUND_PAN_TABLE_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_EXECUTE_DATA_TABLE_END_OFFSET == + REDSOUND_PAN_TABLE_R_OFFSET + REDSOUND_PAN_TABLE_ALLOC_SIZE); +STATIC_ASSERT(sizeof(t_TonePitch) + sizeof(t_FinePitch) + sizeof(t_KeySignatureIndex) + + sizeof(t_KeySignatureData) + sizeof(t_RandomData) + sizeof(t_PanningData) + + sizeof(t_PanningDataR) == + REDSOUND_EXECUTE_DATA_TABLE_SIZE); +STATIC_ASSERT(REDSOUND_EXECUTE_DATA_TABLE_SIZE == REDSOUND_EXECUTE_DATA_TABLE_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_REVERB_DATA_BUFFER_SIZE == REDSOUND_REVERB_DATA_ALLOC_SIZE); +STATIC_ASSERT(sizeof(m_TerminateNote) == REDSOUND_EXECUTE_SDATA_SIZE); +STATIC_ASSERT(offsetof(RedExecuteSmallDataState, m_randomIndex) == REDSOUND_EXECUTE_SBSS_RANDOM_INDEX_OFFSET); +STATIC_ASSERT(offsetof(RedExecuteSmallDataState, m_randomIndexAlignPadding) == + REDSOUND_EXECUTE_SBSS_RANDOM_PAD_OFFSET); +STATIC_ASSERT(offsetof(RedExecuteSmallDataState, m_reverbData) == REDSOUND_EXECUTE_SBSS_REVERB_DATA_OFFSET); +STATIC_ASSERT(offsetof(RedExecuteSmallDataState, m_reverbSize) == REDSOUND_EXECUTE_SBSS_REVERB_SIZE_OFFSET); +STATIC_ASSERT(offsetof(RedExecuteSmallDataState, m_changeStatus) == REDSOUND_EXECUTE_SBSS_CHANGE_STATUS_OFFSET); +STATIC_ASSERT(offsetof(RedExecuteSmallDataState, m_skipKeyOn) == REDSOUND_EXECUTE_SBSS_SKIP_KEY_ON_OFFSET); +STATIC_ASSERT(sizeof(RedExecuteSmallDataState) == REDSOUND_EXECUTE_SBSS_SIZE); +STATIC_ASSERT(sizeof(m_RandomIndex) + REDSOUND_EXECUTE_SBSS_RANDOM_PAD_SIZE + sizeof(p_ReverbData) + + sizeof(p_ReverbSize) + sizeof(m_ChangeStatus) + sizeof(p_SkipKeyOn) == + REDSOUND_EXECUTE_SBSS_SIZE); +STATIC_ASSERT(offsetof(RedReverbDATA, m_callback) == REDSOUND_REVERB_CALLBACK_OFFSET); +STATIC_ASSERT(offsetof(RedReverbDATA, m_context) == REDSOUND_REVERB_CONTEXT_OFFSET); +STATIC_ASSERT(offsetof(RedReverbDATA, m_kind) == REDSOUND_REVERB_KIND_OFFSET); +STATIC_ASSERT(sizeof(RedReverbDATA) == REDSOUND_REVERB_SIZE); +STATIC_ASSERT(offsetof(RedReverbSize, m_requested) == REDSOUND_REVERB_SIZE_REQUESTED_OFFSET); +STATIC_ASSERT(offsetof(RedReverbSize, m_aligned) == REDSOUND_REVERB_SIZE_ALIGNED_OFFSET); +STATIC_ASSERT(sizeof(RedReverbSize) == REDSOUND_REVERB_SIZE_SIZE); +STATIC_ASSERT(offsetof(RedSavedTrackDATA, m_delta) == REDSOUND_MUSIC_TRACK_SAVE_COUNT * sizeof(int)); +STATIC_ASSERT(offsetof(RedSavedTrackDATA, m_flags) == REDSOUND_MUSIC_TRACK_SAVE_COUNT * 2 * sizeof(int)); +STATIC_ASSERT(offsetof(RedSavedTrackDATA, m_note) == REDSOUND_MUSIC_TRACK_SAVE_COUNT * 3 * sizeof(int)); +STATIC_ASSERT(sizeof(RedSavedTrackDATA) == REDSOUND_MUSIC_TRACK_SAVE_COUNT * 4 * sizeof(int)); +STATIC_ASSERT(offsetof(AXFX_REVERBSTD, tempDisableFX) == REDSOUND_AXFX_REVERB_STD_TEMP_DISABLE_OFFSET); +STATIC_ASSERT(offsetof(AXFX_REVERBSTD, coloration) == REDSOUND_AXFX_REVERB_STD_COLORATION_OFFSET); +STATIC_ASSERT(offsetof(AXFX_REVERBSTD, mix) == REDSOUND_AXFX_REVERB_STD_MIX_OFFSET); +STATIC_ASSERT(offsetof(AXFX_REVERBSTD, time) == REDSOUND_AXFX_REVERB_STD_TIME_OFFSET); +STATIC_ASSERT(offsetof(AXFX_REVERBSTD, damping) == REDSOUND_AXFX_REVERB_STD_DAMPING_OFFSET); +STATIC_ASSERT(offsetof(AXFX_REVERBSTD, preDelay) == REDSOUND_AXFX_REVERB_STD_PRE_DELAY_OFFSET); +STATIC_ASSERT(sizeof(AXFX_REVERBSTD) == REDSOUND_AXFX_REVERB_STD_SIZE); +STATIC_ASSERT(offsetof(AXFX_REVERBHI, tempDisableFX) == REDSOUND_AXFX_REVERB_HI_TEMP_DISABLE_OFFSET); +STATIC_ASSERT(offsetof(AXFX_REVERBHI, coloration) == REDSOUND_AXFX_REVERB_HI_COLORATION_OFFSET); +STATIC_ASSERT(offsetof(AXFX_REVERBHI, mix) == REDSOUND_AXFX_REVERB_HI_MIX_OFFSET); +STATIC_ASSERT(offsetof(AXFX_REVERBHI, time) == REDSOUND_AXFX_REVERB_HI_TIME_OFFSET); +STATIC_ASSERT(offsetof(AXFX_REVERBHI, damping) == REDSOUND_AXFX_REVERB_HI_DAMPING_OFFSET); +STATIC_ASSERT(offsetof(AXFX_REVERBHI, preDelay) == REDSOUND_AXFX_REVERB_HI_PRE_DELAY_OFFSET); +STATIC_ASSERT(offsetof(AXFX_REVERBHI, crosstalk) == REDSOUND_AXFX_REVERB_HI_CROSSTALK_OFFSET); +STATIC_ASSERT(sizeof(AXFX_REVERBHI) == REDSOUND_AXFX_REVERB_HI_SIZE); +STATIC_ASSERT(offsetof(AXFX_REVERBHI_DPL2, tempDisableFX) == REDSOUND_AXFX_REVERB_HI_DPL2_TEMP_DISABLE_OFFSET); +STATIC_ASSERT(offsetof(AXFX_REVERBHI_DPL2, coloration) == REDSOUND_AXFX_REVERB_HI_DPL2_COLORATION_OFFSET); +STATIC_ASSERT(offsetof(AXFX_REVERBHI_DPL2, mix) == REDSOUND_AXFX_REVERB_HI_DPL2_MIX_OFFSET); +STATIC_ASSERT(offsetof(AXFX_REVERBHI_DPL2, time) == REDSOUND_AXFX_REVERB_HI_DPL2_TIME_OFFSET); +STATIC_ASSERT(offsetof(AXFX_REVERBHI_DPL2, damping) == REDSOUND_AXFX_REVERB_HI_DPL2_DAMPING_OFFSET); +STATIC_ASSERT(offsetof(AXFX_REVERBHI_DPL2, preDelay) == REDSOUND_AXFX_REVERB_HI_DPL2_PRE_DELAY_OFFSET); +STATIC_ASSERT(sizeof(AXFX_REVERBHI_DPL2) == REDSOUND_AXFX_REVERB_HI_DPL2_SIZE); +STATIC_ASSERT(offsetof(AXFX_DELAY, delay) == REDSOUND_AXFX_DELAY_DELAY_OFFSET); +STATIC_ASSERT(sizeof(((AXFX_DELAY*)0)->delay) == REDSOUND_AXFX_DELAY_CHANNEL_SIZE); +STATIC_ASSERT(offsetof(AXFX_DELAY, feedback) == REDSOUND_AXFX_DELAY_FEEDBACK_OFFSET); +STATIC_ASSERT(sizeof(((AXFX_DELAY*)0)->feedback) == REDSOUND_AXFX_DELAY_CHANNEL_SIZE); +STATIC_ASSERT(offsetof(AXFX_DELAY, output) == REDSOUND_AXFX_DELAY_OUTPUT_OFFSET); +STATIC_ASSERT(sizeof(((AXFX_DELAY*)0)->output) == REDSOUND_AXFX_DELAY_CHANNEL_SIZE); +STATIC_ASSERT(REDSOUND_AXFX_DELAY_FEEDBACK_OFFSET == + REDSOUND_AXFX_DELAY_DELAY_OFFSET + REDSOUND_AXFX_DELAY_CHANNEL_SIZE); +STATIC_ASSERT(REDSOUND_AXFX_DELAY_OUTPUT_OFFSET == + REDSOUND_AXFX_DELAY_FEEDBACK_OFFSET + REDSOUND_AXFX_DELAY_CHANNEL_SIZE); +STATIC_ASSERT(REDSOUND_AXFX_DELAY_OUTPUT_OFFSET + REDSOUND_AXFX_DELAY_CHANNEL_SIZE == REDSOUND_AXFX_DELAY_SIZE); +STATIC_ASSERT(sizeof(AXFX_DELAY) == REDSOUND_AXFX_DELAY_SIZE); +STATIC_ASSERT(offsetof(AXFX_CHORUS, baseDelay) == REDSOUND_AXFX_CHORUS_BASE_DELAY_OFFSET); +STATIC_ASSERT(offsetof(AXFX_CHORUS, variation) == REDSOUND_AXFX_CHORUS_VARIATION_OFFSET); +STATIC_ASSERT(offsetof(AXFX_CHORUS, period) == REDSOUND_AXFX_CHORUS_PERIOD_OFFSET); +STATIC_ASSERT(sizeof(AXFX_CHORUS) == REDSOUND_AXFX_CHORUS_SIZE); +STATIC_ASSERT(offsetof(RedWaveADPCMInfo, m_data) == REDSOUND_WAVE_ADPCM_DATA_OFFSET); +STATIC_ASSERT(offsetof(RedWaveADPCMInfo, m_loop) == REDSOUND_WAVE_ADPCM_LOOP_OFFSET); +STATIC_ASSERT(sizeof(((RedWaveADPCMInfo*)0)->m_data) == REDSOUND_WAVE_ADPCM_DATA_SIZE); +STATIC_ASSERT(sizeof(((RedWaveADPCMInfo*)0)->m_loop) == REDSOUND_WAVE_ADPCM_LOOP_SIZE); +STATIC_ASSERT(sizeof(RedWaveADPCMInfo) == REDSOUND_WAVE_ADPCM_INFO_SIZE); +STATIC_ASSERT(offsetof(RedWaveDATA, m_flags) == REDSOUND_WAVE_FLAGS_OFFSET); +STATIC_ASSERT(offsetof(RedWaveDATA, m_sampleStart) == REDSOUND_WAVE_SAMPLE_START_OFFSET); +STATIC_ASSERT(offsetof(RedWaveDATA, m_loopStart) == REDSOUND_WAVE_LOOP_START_OFFSET); +STATIC_ASSERT(offsetof(RedWaveDATA, m_loopEnd) == REDSOUND_WAVE_LOOP_END_OFFSET); +STATIC_ASSERT(offsetof(RedWaveDATA, m_reserved10) == REDSOUND_WAVE_RESERVED10_OFFSET); +STATIC_ASSERT(sizeof(((RedWaveDATA*)0)->m_reserved10) == REDSOUND_WAVE_RESERVED10_SIZE); +STATIC_ASSERT(offsetof(RedWaveDATA, m_pitch) == REDSOUND_WAVE_PITCH_OFFSET); +STATIC_ASSERT(offsetof(RedWaveDATA, m_splitKey) == REDSOUND_WAVE_SPLIT_KEY_OFFSET); +STATIC_ASSERT(offsetof(RedWaveDATA, m_splitVelocity) == REDSOUND_WAVE_SPLIT_VELOCITY_OFFSET); +STATIC_ASSERT(offsetof(RedWaveDATA, m_volume) == REDSOUND_WAVE_VOLUME_OFFSET); +STATIC_ASSERT(offsetof(RedWaveDATA, m_pan) == REDSOUND_WAVE_PAN_OFFSET); +STATIC_ASSERT(offsetof(RedWaveDATA, m_reverbMix) == REDSOUND_WAVE_REVERB_MIX_OFFSET); +STATIC_ASSERT(offsetof(RedWaveDATA, m_reserved1D) == REDSOUND_WAVE_RESERVED1D_OFFSET); +STATIC_ASSERT(sizeof(((RedWaveDATA*)0)->m_reserved1D) == REDSOUND_WAVE_RESERVED1D_SIZE); +STATIC_ASSERT(offsetof(RedWaveDATA, m_adpcm) == REDSOUND_WAVE_ADPCM_OFFSET); +STATIC_ASSERT(sizeof(((RedWaveDATA*)0)->m_adpcm) == REDSOUND_WAVE_ADPCM_INFO_SIZE); +STATIC_ASSERT(offsetof(RedWaveDATA, m_adsr) == REDSOUND_WAVE_ADSR_OFFSET); +STATIC_ASSERT(sizeof(((RedWaveDATA*)0)->m_adsr) == REDSOUND_WAVE_ADSR_SIZE); +STATIC_ASSERT(REDSOUND_WAVE_ADSR_SIZE == REDSOUND_ADSR_DATA_SIZE); +STATIC_ASSERT(offsetof(RedWaveDATA, m_reserved5C) == REDSOUND_WAVE_RESERVED5C_OFFSET); +STATIC_ASSERT(sizeof(((RedWaveDATA*)0)->m_reserved5C) == REDSOUND_WAVE_RESERVED5C_SIZE); +STATIC_ASSERT(REDSOUND_WAVE_RESERVED10_OFFSET + REDSOUND_WAVE_RESERVED10_SIZE == REDSOUND_WAVE_PITCH_OFFSET); +STATIC_ASSERT(REDSOUND_WAVE_RESERVED1D_OFFSET + REDSOUND_WAVE_RESERVED1D_SIZE == REDSOUND_WAVE_ADPCM_OFFSET); +STATIC_ASSERT(REDSOUND_WAVE_ADSR_OFFSET + REDSOUND_WAVE_ADSR_SIZE == REDSOUND_WAVE_RESERVED5C_OFFSET); +STATIC_ASSERT(REDSOUND_WAVE_RESERVED5C_OFFSET + REDSOUND_WAVE_RESERVED5C_SIZE == REDSOUND_WAVE_DATA_SIZE); +STATIC_ASSERT(sizeof(RedWaveDATA) == REDSOUND_WAVE_DATA_SIZE); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_track) == REDSOUND_VOICE_TRACK_OFFSET); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_waveData) == REDSOUND_VOICE_WAVE_DATA_WORD * sizeof(int)); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_trackVolume) == REDSOUND_VOICE_TRACK_VOLUME_WORD * sizeof(int)); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_trackExpression) == REDSOUND_VOICE_TRACK_EXPRESSION_WORD * sizeof(int)); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_trackPan) == REDSOUND_VOICE_TRACK_PAN_WORD * sizeof(int)); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_axVoice) == REDSOUND_VOICE_AX_VOICE_WORD * sizeof(int)); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_key) == REDSOUND_VOICE_KEY_OFFSET); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_velocity) == REDSOUND_VOICE_VELOCITY_OFFSET); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_stateFlags) == REDSOUND_VOICE_STATE_FLAGS_OFFSET); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_reserved1B) == REDSOUND_VOICE_RESERVED1B_OFFSET); +STATIC_ASSERT(sizeof(((RedVoiceDATA*)0)->m_reserved1B) == REDSOUND_VOICE_RESERVED1B_SIZE); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_pitchModPhase) == REDSOUND_VOICE_PITCH_MOD_PHASE_WORD * sizeof(int)); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_pitchModFrames) == REDSOUND_VOICE_PITCH_MOD_FRAMES_WORD * sizeof(int)); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_pitchModFrame) == REDSOUND_VOICE_PITCH_MOD_FRAME_WORD * sizeof(int)); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_pitchModDelay) == + REDSOUND_VOICE_PITCH_MOD_DELAY_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_reserved2A) == REDSOUND_VOICE_RESERVED2A_OFFSET); +STATIC_ASSERT(sizeof(((RedVoiceDATA*)0)->m_reserved2A) == REDSOUND_VOICE_RESERVED2A_SIZE); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_volumeModPhase) == REDSOUND_VOICE_VOLUME_MOD_PHASE_WORD * sizeof(int)); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_volumeModFrames) == REDSOUND_VOICE_VOLUME_MOD_FRAMES_WORD * sizeof(int)); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_volumeModFrame) == REDSOUND_VOICE_VOLUME_MOD_FRAME_WORD * sizeof(int)); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_volumeModDelay) == + REDSOUND_VOICE_VOLUME_MOD_DELAY_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_reserved3A) == REDSOUND_VOICE_RESERVED3A_OFFSET); +STATIC_ASSERT(sizeof(((RedVoiceDATA*)0)->m_reserved3A) == REDSOUND_VOICE_RESERVED3A_SIZE); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_randomPitch) == REDSOUND_VOICE_RANDOM_PITCH_WORD * sizeof(int)); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_randomVolume) == REDSOUND_VOICE_RANDOM_VOLUME_WORD * sizeof(int)); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_randomPan) == REDSOUND_VOICE_RANDOM_PAN_WORD * sizeof(int)); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_reserved48) == REDSOUND_VOICE_RESERVED48_OFFSET); +STATIC_ASSERT(sizeof(((RedVoiceDATA*)0)->m_reserved48) == REDSOUND_VOICE_RESERVED48_SIZE); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_adsr) == REDSOUND_VOICE_ADSR_TIME_OFFSET); +STATIC_ASSERT(offsetof(RedAdsrDATA, m_time) == REDSOUND_ADSR_TIME_OFFSET); +STATIC_ASSERT(sizeof(((RedAdsrDATA*)0)->m_time) == + REDSOUND_VOICE_ADSR_TIME_COUNT * sizeof(unsigned short)); +STATIC_ASSERT(offsetof(RedAdsrDATA, m_level) == REDSOUND_ADSR_LEVEL_OFFSET); +STATIC_ASSERT(REDSOUND_ADSR_LEVEL_OFFSET == REDSOUND_VOICE_ADSR_LEVEL_OFFSET - REDSOUND_VOICE_ADSR_TIME_OFFSET); +STATIC_ASSERT(sizeof(((RedAdsrDATA*)0)->m_level) == REDSOUND_VOICE_ADSR_LEVEL_COUNT * sizeof(unsigned char)); +STATIC_ASSERT(sizeof(((RedVoiceDATA*)0)->m_adsr) == REDSOUND_TRACK_ADSR_SIZE); +STATIC_ASSERT(sizeof(RedAdsrDATA) == REDSOUND_ADSR_DATA_SIZE); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_adsrStage) == REDSOUND_VOICE_ADSR_STAGE_OFFSET); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_adsrStepFrames) == REDSOUND_VOICE_ADSR_STEP_FRAMES_WORD * sizeof(int)); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_adsrStepAdd) == REDSOUND_VOICE_ADSR_STEP_ADD_WORD * sizeof(int)); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_active) == REDSOUND_VOICE_ACTIVE_OFFSET); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_flags) == REDSOUND_VOICE_FLAGS_OFFSET); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_voiceSwitch) == REDSOUND_VOICE_SWITCH_OFFSET); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_pitch) == REDSOUND_VOICE_PITCH_WORD * sizeof(int)); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_targetPitch) == REDSOUND_VOICE_TARGET_PITCH_WORD * sizeof(int)); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_basePitch) == REDSOUND_VOICE_BASE_PITCH_WORD * sizeof(int)); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_reservedA4) == REDSOUND_VOICE_RESERVEDA4_OFFSET); +STATIC_ASSERT(sizeof(((RedVoiceDATA*)0)->m_reservedA4) == REDSOUND_VOICE_RESERVEDA4_SIZE); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_voiceIndex) == REDSOUND_VOICE_INDEX_OFFSET); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_adsrCurrentLevel) == REDSOUND_VOICE_ADSR_CURRENT_WORD * sizeof(int)); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_envelopeLevel) == REDSOUND_VOICE_ENVELOPE_WORD * sizeof(int)); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_reservedB4) == REDSOUND_VOICE_RESERVEDB4_OFFSET); +STATIC_ASSERT(sizeof(((RedVoiceDATA*)0)->m_reservedB4) == REDSOUND_VOICE_RESERVEDB4_SIZE); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_updateFlags) == REDSOUND_VOICE_UPDATE_FLAGS_OFFSET); +STATIC_ASSERT(offsetof(RedVoiceDATA, m_reservedBC) == REDSOUND_VOICE_RESERVEDBC_OFFSET); +STATIC_ASSERT(sizeof(((RedVoiceDATA*)0)->m_reservedBC) == REDSOUND_VOICE_RESERVEDBC_SIZE); +STATIC_ASSERT(REDSOUND_VOICE_RESERVED1B_OFFSET + REDSOUND_VOICE_RESERVED1B_SIZE == + REDSOUND_VOICE_PITCH_MOD_PHASE_WORD * sizeof(int)); +STATIC_ASSERT(REDSOUND_VOICE_RESERVED2A_OFFSET + REDSOUND_VOICE_RESERVED2A_SIZE == + REDSOUND_VOICE_VOLUME_MOD_PHASE_WORD * sizeof(int)); +STATIC_ASSERT(REDSOUND_VOICE_RESERVED3A_OFFSET + REDSOUND_VOICE_RESERVED3A_SIZE == + REDSOUND_VOICE_RANDOM_PITCH_WORD * sizeof(int)); +STATIC_ASSERT(REDSOUND_VOICE_RESERVED48_OFFSET + REDSOUND_VOICE_RESERVED48_SIZE == + REDSOUND_VOICE_ADSR_TIME_OFFSET); +STATIC_ASSERT(REDSOUND_VOICE_RESERVEDA4_OFFSET + REDSOUND_VOICE_RESERVEDA4_SIZE == REDSOUND_VOICE_INDEX_OFFSET); +STATIC_ASSERT(REDSOUND_VOICE_RESERVEDB4_OFFSET + REDSOUND_VOICE_RESERVEDB4_SIZE == REDSOUND_VOICE_UPDATE_FLAGS_OFFSET); +STATIC_ASSERT(REDSOUND_VOICE_RESERVEDBC_OFFSET + REDSOUND_VOICE_RESERVEDBC_SIZE == REDSOUND_VOICE_SIZE); +STATIC_ASSERT(sizeof(RedVoiceDATA) == REDSOUND_VOICE_SIZE); +STATIC_ASSERT(offsetof(AXVPB, pb) + offsetof(AXPB, type) == REDSOUND_AX_VOICE_TYPE_OFFSET); + /* * --INFO-- * PAL Address: 0x801c2fc4 @@ -224,9 +490,9 @@ enum RedVoiceStartMaskIndex { */ u8 GetRandomData() { - signed char* data = t_RandomData + m_RandomIndex; + u8 value = t_RandomData[m_RandomIndex]; m_RandomIndex++; - return *data; + return value; } /* @@ -241,28 +507,32 @@ u8 GetRandomData() int PitchCompute(int basePitch, int pitchOffset, int wavePitch, int fineTune) { int value; - int pitch; + u32 pitch; int octaveAdjust; int noteBand; octaveAdjust = 0; - pitch = (basePitch >> REDSOUND_FIXED_SHIFT) + (pitchOffset + (wavePitch >> 16)); - while (pitch < 0) { + basePitch >>= REDSOUND_FIXED_SHIFT; + pitch = pitchOffset + (wavePitch >> 16); + pitch = basePitch + pitch; + while ((int)pitch < 0) { pitch += REDSOUND_PITCH_OCTAVE_UNITS; octaveAdjust -= 1; } noteBand = (pitch >> REDSOUND_PITCH_NOTE_SHIFT) & REDSOUND_PITCH_NOTE_MASK; octaveAdjust += noteBand / REDSOUND_NOTES_PER_OCTAVE; - value = (int)((t_TonePitch[noteBand % REDSOUND_NOTES_PER_OCTAVE] >> (REDSOUND_PITCH_TONE_SHIFT - octaveAdjust)) * - t_FinePitch[pitch & REDSOUND_PITCH_FINE_MASK]) >> - REDSOUND_FIXED_SHIFT; + noteBand %= REDSOUND_NOTES_PER_OCTAVE; + value = t_TonePitch[noteBand] >> (REDSOUND_PITCH_TONE_SHIFT - octaveAdjust); + value *= t_FinePitch[pitch & REDSOUND_PITCH_FINE_MASK]; + value >>= REDSOUND_FIXED_SHIFT; if (fineTune != 0) { if (fineTune > 0) { value = value + ((int)(value * (fineTune + 1)) >> REDSOUND_PITCH_FINE_TUNE_POSITIVE_SHIFT); } else { - value = (int)(value * (fineTune & REDSOUND_PITCH_FINE_MASK)) >> REDSOUND_PITCH_FINE_TUNE_NEGATIVE_SHIFT; + value *= fineTune & REDSOUND_PITCH_FINE_MASK; + value >>= REDSOUND_PITCH_FINE_TUNE_NEGATIVE_SHIFT; } } @@ -328,7 +598,7 @@ void InitReverb() { p_ReverbData = (RedReverbDATA*)RedNew(REDSOUND_REVERB_DATA_BUFFER_SIZE); memset(p_ReverbData, 0, REDSOUND_REVERB_DATA_BUFFER_SIZE); - p_ReverbSize = (RedReverbSize*)RedNew(4); + p_ReverbSize = (RedReverbSize*)RedNew(REDSOUND_REVERB_SIZE_ALLOC_SIZE); } /* @@ -343,6 +613,7 @@ void InitReverb() static void _SetReverbData(RedReverbDATA* reverb, int* params) { int result = 0; + switch (reverb->m_kind) { case REDSOUND_REVERB_KIND_STD: { AXFX_REVERBSTD* std = (AXFX_REVERBSTD*)reverb->m_context; @@ -455,6 +726,20 @@ static void _ClearReverb(int bank) RedDelete((int)reverb->m_context); } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 8b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +static int _CompFX(float a, float b) +{ + return 1; +} + /* * --INFO-- * PAL Address: 0x801c3718 @@ -469,8 +754,7 @@ RedReverbSize* SetReverb(int bank, int kind, int* params) RedReverbDATA* reverb; int result; - p_ReverbSize->m_aligned = 0; - p_ReverbSize->m_requested = 0; + p_ReverbSize->m_requested = p_ReverbSize->m_aligned = 0; if (kind == REDSOUND_REVERB_KIND_NONE) { _ClearReverb(bank); @@ -492,10 +776,10 @@ RedReverbSize* SetReverb(int bank, int kind, int* params) _ClearReverb(1); } - reverb->m_kind = kind; + reverb->m_kind = (RedReverbKind)kind; switch (kind) { case REDSOUND_REVERB_KIND_STD: { - reverb->m_context = (void*)RedNew(sizeof(AXFX_REVERBSTD)); + reverb->m_context = (void*)RedNew(REDSOUND_AXFX_REVERB_STD_SIZE); reverb->m_callback = (int)AXFXReverbStdCallback; AXFX_REVERBSTD* std = (AXFX_REVERBSTD*)reverb->m_context; std->tempDisableFX = 0; @@ -508,7 +792,7 @@ RedReverbSize* SetReverb(int bank, int kind, int* params) break; } case REDSOUND_REVERB_KIND_HI: { - reverb->m_context = (void*)RedNew(sizeof(AXFX_REVERBHI)); + reverb->m_context = (void*)RedNew(REDSOUND_AXFX_REVERB_HI_SIZE); reverb->m_callback = (int)AXFXReverbHiCallback; AXFX_REVERBHI* hi = (AXFX_REVERBHI*)reverb->m_context; hi->tempDisableFX = 0; @@ -522,7 +806,7 @@ RedReverbSize* SetReverb(int bank, int kind, int* params) break; } case REDSOUND_REVERB_KIND_DELAY: { - reverb->m_context = (void*)RedNew(sizeof(AXFX_DELAY)); + reverb->m_context = (void*)RedNew(REDSOUND_AXFX_DELAY_SIZE); reverb->m_callback = (int)AXFXDelayCallback; AXFX_DELAY* delay = (AXFX_DELAY*)reverb->m_context; u32 delayValue = (u32)params[REDSOUND_REVERB_PARAM_DELAY]; @@ -541,7 +825,7 @@ RedReverbSize* SetReverb(int bank, int kind, int* params) break; } case REDSOUND_REVERB_KIND_CHORUS: { - reverb->m_context = (void*)RedNew(sizeof(AXFX_CHORUS)); + reverb->m_context = (void*)RedNew(REDSOUND_AXFX_CHORUS_SIZE); reverb->m_callback = (int)AXFXChorusCallback; AXFX_CHORUS* chorus = (AXFX_CHORUS*)reverb->m_context; chorus->baseDelay = (u32)params[REDSOUND_REVERB_PARAM_CHORUS_BASE_DELAY]; @@ -551,7 +835,7 @@ RedReverbSize* SetReverb(int bank, int kind, int* params) break; } case REDSOUND_REVERB_KIND_HI_DPL2: { - reverb->m_context = (void*)RedNew(sizeof(AXFX_REVERBHI_DPL2)); + reverb->m_context = (void*)RedNew(REDSOUND_AXFX_REVERB_HI_DPL2_SIZE); reverb->m_callback = (int)AXFXReverbHiCallbackDpl2; AXFX_REVERBHI_DPL2* hiDpl2 = (AXFX_REVERBHI_DPL2*)reverb->m_context; hiDpl2->tempDisableFX = 0; @@ -574,13 +858,26 @@ RedReverbSize* SetReverb(int bank, int kind, int* params) } } else { - p_ReverbSize->m_aligned = 0; - p_ReverbSize->m_requested = 0; + p_ReverbSize->m_requested = p_ReverbSize->m_aligned = 0; } return p_ReverbSize; } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 8b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +RedReverbSize* GetReverbInfo() +{ + return p_ReverbSize; +} + /* * --INFO-- * PAL Address: 0x801c3c44 @@ -687,10 +984,6 @@ void SetVoiceVolumeMix(RedVoiceDATA* voice, int pan, int volume) int auxLeftMix; int auxRightMix; RedTrackDATA* trackData = voice->m_track; - s16 leftPan; - s16 rightPan; - u16 monoMix; - int volFactor; AXPBMIX* mixData; if (trackData == 0) { @@ -701,28 +994,27 @@ void SetVoiceVolumeMix(RedVoiceDATA* voice, int pan, int volume) memset(mixData, 0, sizeof(*mixData)); switch (m_SoundPlayMode) { - case 1: - volFactor = (int)t_PanningData[REDSOUND_PAN_BYTE_CENTER]; - int monoBase = (volume * volFactor) >> 8; + case REDSOUND_SOUND_MODE_MONO: + auxLeftMix = (volume * t_PanningData[REDSOUND_PAN_BYTE_CENTER]) >> 8; if ((voice->m_voiceSwitch & REDSOUND_VOICE_SWITCH_DRY_STEREO) != 0) { - monoMix = (u16)monoBase; - mixData->vL = monoMix; - mixData->vR = monoMix; + mixData->vL = (u16)auxLeftMix; + mixData->vR = (u16)auxLeftMix; } if ((voice->m_voiceSwitch & REDSOUND_VOICE_SWITCH_REVERB_STEREO) != 0) { - u16 monoMix = (u16)((monoBase * ((trackData->m_reverbDepth >> REDSOUND_FIXED_SHIFT) + 1)) >> REDSOUND_AX_MIX_SHIFT); + auxLeftMix = + (auxLeftMix * ((trackData->m_reverbDepth >> REDSOUND_FIXED_SHIFT) + 1)) >> REDSOUND_AX_MIX_SHIFT; if ((voice->m_voiceSwitch & REDSOUND_VOICE_SWITCH_REVERB_AUX_A) != 0) { - mixData->vAuxAL = monoMix; - mixData->vAuxAR = monoMix; + mixData->vAuxAL = (u16)auxLeftMix; + mixData->vAuxAR = (u16)auxLeftMix; } else { - mixData->vAuxBL = monoMix; - mixData->vAuxBR = monoMix; + mixData->vAuxBL = (u16)auxLeftMix; + mixData->vAuxBR = (u16)auxLeftMix; } } break; - case 2: + case REDSOUND_SOUND_MODE_SURROUND: mixData->vL = (u16)((volume * t_PanningData[pan]) >> 8); mixData->vAuxBL = (u16)((volume * t_PanningDataR[pan]) >> 8); mixData->vR = (u16)((volume * t_PanningData[pan ^ REDSOUND_PAN_BYTE_MASK]) >> 8); @@ -730,7 +1022,7 @@ void SetVoiceVolumeMix(RedVoiceDATA* voice, int pan, int volume) if ((voice->m_voiceSwitch & REDSOUND_VOICE_SWITCH_REVERB_LEFT) != 0) { mixData->vAuxAL = - (s16)((int)((u32)mixData->vL * ((trackData->m_reverbDepth >> REDSOUND_FIXED_SHIFT) + 1)) >> REDSOUND_AX_MIX_SHIFT); + (u16)((int)((u32)mixData->vL * ((trackData->m_reverbDepth >> REDSOUND_FIXED_SHIFT) + 1)) >> REDSOUND_AX_MIX_SHIFT); mixData->vAuxAS = (u16)((int)((u32)mixData->vAuxBL * ((trackData->m_reverbDepth >> REDSOUND_FIXED_SHIFT) + 1)) >> @@ -753,21 +1045,19 @@ void SetVoiceVolumeMix(RedVoiceDATA* voice, int pan, int volume) pan = REDSOUND_PAN_BYTE_WRAP - pan; } - leftPan = t_PanningData[pan]; - rightPan = t_PanningData[pan ^ REDSOUND_PAN_BYTE_MASK]; - int leftMix = (volume * leftPan) >> 8; - int rightMix = (volume * rightPan) >> 8; + auxLeftMix = (volume * t_PanningData[pan]) >> 8; + auxRightMix = (volume * t_PanningData[pan ^ REDSOUND_PAN_BYTE_MASK]) >> 8; if ((voice->m_voiceSwitch & REDSOUND_VOICE_SWITCH_DRY_LEFT) != 0) { - mixData->vL = (u16)leftMix; + mixData->vL = (u16)auxLeftMix; } if ((voice->m_voiceSwitch & REDSOUND_VOICE_SWITCH_DRY_RIGHT) != 0) { - mixData->vR = (u16)rightMix; + mixData->vR = (u16)auxRightMix; } if ((voice->m_voiceSwitch & REDSOUND_VOICE_SWITCH_REVERB_LEFT) != 0) { - auxLeftMix = (leftMix * ((trackData->m_reverbDepth >> REDSOUND_FIXED_SHIFT) + 1)) >> REDSOUND_AX_MIX_SHIFT; + auxLeftMix = (auxLeftMix * ((trackData->m_reverbDepth >> REDSOUND_FIXED_SHIFT) + 1)) >> REDSOUND_AX_MIX_SHIFT; if ((voice->m_voiceSwitch & REDSOUND_VOICE_SWITCH_REVERB_AUX_A) != 0) { mixData->vAuxAL = (u16)auxLeftMix; } else { @@ -776,7 +1066,7 @@ void SetVoiceVolumeMix(RedVoiceDATA* voice, int pan, int volume) } if ((voice->m_voiceSwitch & REDSOUND_VOICE_SWITCH_REVERB_RIGHT) != 0) { - auxRightMix = (rightMix * ((trackData->m_reverbDepth >> REDSOUND_FIXED_SHIFT) + 1)) >> REDSOUND_AX_MIX_SHIFT; + auxRightMix = (auxRightMix * ((trackData->m_reverbDepth >> REDSOUND_FIXED_SHIFT) + 1)) >> REDSOUND_AX_MIX_SHIFT; if ((voice->m_voiceSwitch & REDSOUND_VOICE_SWITCH_REVERB_AUX_A) != 0) { mixData->vAuxAR = (u16)auxRightMix; } else { @@ -843,14 +1133,15 @@ static void _VolumeExecute(RedVoiceDATA* voice, int volume) } modVolume = voiceMix * envelopeMul >> 8; - tremoloValue = voice->m_track->m_tremoloFunc((unsigned int)voice->m_volumeModPhase >> REDSOUND_FIXED_SHIFT); - modVolume = modVolume * (tremoloValue >> REDSOUND_VOLUME_MOD_WAVE_SHIFT) >> REDSOUND_FIXED_SHIFT; + tremoloValue = voice->m_volumeModFrames; + envelopeMul = voice->m_track->m_tremoloFunc((unsigned int)voice->m_volumeModPhase >> REDSOUND_FIXED_SHIFT); + modVolume = modVolume * (envelopeMul >> REDSOUND_VOLUME_MOD_WAVE_SHIFT) >> REDSOUND_FIXED_SHIFT; - if (voice->m_volumeModFrames != 0) { - tremoloValue = voice->m_volumeModFrame; + if (tremoloValue != 0) { + envelopeMul = voice->m_volumeModFrame; voice->m_volumeModFrame = voice->m_volumeModFrame + 1; - modVolume = (modVolume * tremoloValue) / voice->m_volumeModFrames; - if (voice->m_volumeModFrame >= voice->m_volumeModFrames) { + modVolume = (modVolume * envelopeMul) / tremoloValue; + if (voice->m_volumeModFrame >= tremoloValue) { voice->m_volumeModFrames = 0; } } @@ -866,7 +1157,7 @@ static void _VolumeExecute(RedVoiceDATA* voice, int volume) } } - if (m_SoundPlayMode == 1) { + if (m_SoundPlayMode == REDSOUND_SOUND_MODE_MONO) { pan = REDSOUND_PAN_BYTE_CENTER; } else if ((voice->m_voiceSwitch & REDSOUND_VOICE_SWITCH_PAIRED_PAN) != 0) { if ((voice->m_voiceSwitch & REDSOUND_VOICE_SWITCH_PAIRED_LEFT) != 0) { @@ -889,7 +1180,7 @@ static void _VolumeExecute(RedVoiceDATA* voice, int volume) } pan = pan + voice->m_track->m_shakePan; - pan &= 0xff; + pan &= REDSOUND_PAN_BYTE_WRAP - 1; } if (voice->m_randomVolume != 0) { @@ -1023,12 +1314,12 @@ static RedWaveDATA* _WaveSplitSelect(RedWaveDATA* wave, RedNoteDATA* note) */ static void _VoiceDataAsign(RedTrackDATA* track, RedVoiceDATA* voice, RedNoteDATA* noteData, int* voiceMask) { - int octaveIndex; int workValue; int pitchWork[4]; + workValue = 0; voice->m_track = track; - voice->m_active = 1; + voice->m_active = REDSOUND_VOICE_ACTIVE_ON; if ((track->m_portamentTime != 0) && (track->m_portamentPitch >= 0)) { @@ -1036,40 +1327,38 @@ static void _VoiceDataAsign(RedTrackDATA* track, RedVoiceDATA* voice, RedNoteDAT voice->m_basePitch = track->m_portamentPitch; track->m_sweepDelta = track->m_portamentTime; pitchWork[0] = 0; - track->m_sweepAdd = - DataAddCompute(pitchWork, noteData->m_key * REDSOUND_PITCH_NOTE_UNIT - - (track->m_portamentPitch >> REDSOUND_FIXED_SHIFT), - &track->m_sweepDelta); + workValue = noteData->m_key * REDSOUND_PITCH_NOTE_UNIT - + (track->m_portamentPitch >> REDSOUND_FIXED_SHIFT); + track->m_sweepAdd = DataAddCompute(pitchWork, workValue, &track->m_sweepDelta); } else { track->m_portamentPitch = noteData->m_key << REDSOUND_PITCH_BASE_NOTE_SHIFT; if (voice->m_waveData != 0) { - if ((voice->m_waveData->m_flags & REDSOUND_WAVE_FLAG_USE_WAVE_KEY) == 0) { + if ((voice->m_waveData->m_flags & REDSOUND_WAVE_FLAG_USE_WAVE_KEY) != 0) { + voice->m_basePitch = + voice->m_waveData->m_splitKey << REDSOUND_PITCH_BASE_NOTE_SHIFT; + } else { voice->m_basePitch = noteData->m_key << REDSOUND_PITCH_BASE_NOTE_SHIFT; - if (track->m_keySignatureData != 0) { + if (voice->m_track->m_keySignatureData != 0) { workValue = voice->m_basePitch >> REDSOUND_PITCH_BASE_NOTE_SHIFT; - octaveIndex = workValue / REDSOUND_NOTES_PER_OCTAVE + (voice->m_basePitch >> REDSOUND_SIGN_SHIFT); pitchWork[0] = - track->m_keySignatureData[workValue + (octaveIndex - (octaveIndex >> REDSOUND_SIGN_SHIFT)) * -REDSOUND_NOTES_PER_OCTAVE]; + voice->m_track->m_keySignatureData[workValue % REDSOUND_NOTES_PER_OCTAVE]; voice->m_basePitch += pitchWork[0] * REDSOUND_PITCH_KEY_SIGNATURE_UNIT; } - } else { - voice->m_basePitch = - voice->m_waveData->m_splitKey << REDSOUND_PITCH_BASE_NOTE_SHIFT; } } } - *(int*)&voice->m_key = *(int*)¬eData->m_key; + *(int*)&voice->m_key = *(int*)noteData; voice->m_trackVolume = &track->m_volume; voice->m_trackExpression = &track->m_expression; voice->m_trackPan = &track->m_pan; - if (voice->m_waveData == 0) { - memset(voice->m_adsrTime, 0, REDSOUND_TRACK_ADSR_SIZE); - } else { - memcpy(voice->m_adsrTime, + if (voice->m_waveData != 0) { + memcpy(&voice->m_adsr, track->m_waveData->m_adsr, REDSOUND_TRACK_ADSR_SIZE); + } else { + memset(&voice->m_adsr, 0, REDSOUND_TRACK_ADSR_SIZE); } voice->m_voiceSwitch = track->m_voiceSwitch; @@ -1086,16 +1375,16 @@ static void _VoiceDataAsign(RedTrackDATA* track, RedVoiceDATA* voice, RedNoteDAT } pitchWork[0] = track->m_keyTranspose + track->m_pitchBend; - if ((voice->m_stateFlags & REDSOUND_VOICE_STATE_PLAYING_MASK) == 0) { - workValue = voice->m_basePitch + p_MusicPitchControl->m_value; - } else { + if ((voice->m_stateFlags & REDSOUND_VOICE_STATE_PLAYING_MASK) != 0) { workValue = voice->m_basePitch + track->m_pitch; + } else { + workValue = voice->m_basePitch + p_MusicPitchControl->m_value; } - if (voice->m_waveData == 0) { - workValue = 0; - } else { + if (voice->m_waveData != 0) { workValue = PitchCompute(workValue, pitchWork[0], voice->m_waveData->m_pitch, track->m_fineTune); + } else { + workValue = 0; } voice->m_pitch = workValue; @@ -1116,10 +1405,10 @@ static void _VoiceDataAsign(RedTrackDATA* track, RedVoiceDATA* voice, RedNoteDAT pitchWork[0] = REDSOUND_MOD_DELAY_PHASE_SCALE / (track->m_vibrateRate >> REDSOUND_FIXED_SHIFT); } - if (track->m_vibrateDelayDepth == 0) { - workValue = 0; - } else { + if (track->m_vibrateDelayDepth != 0) { workValue = track->m_vibrateDelayDepth * (pitchWork[0] * REDSOUND_MOD_DELAY_FRAME_SCALE); + } else { + workValue = 0; } voice->m_pitchModFrames = workValue; voice->m_pitchModFrame = 0; @@ -1133,10 +1422,10 @@ static void _VoiceDataAsign(RedTrackDATA* track, RedVoiceDATA* voice, RedNoteDAT pitchWork[0] = REDSOUND_MOD_DELAY_PHASE_SCALE / (track->m_tremoloRate >> REDSOUND_FIXED_SHIFT); } - if (track->m_tremoloDelayDepth == 0) { - workValue = 0; - } else { + if (track->m_tremoloDelayDepth != 0) { workValue = track->m_tremoloDelayDepth * (pitchWork[0] * REDSOUND_MOD_DELAY_FRAME_SCALE); + } else { + workValue = 0; } voice->m_volumeModFrames = workValue; voice->m_volumeModFrame = 0; @@ -1147,13 +1436,13 @@ static void _VoiceDataAsign(RedTrackDATA* track, RedVoiceDATA* voice, RedNoteDAT if ((voice->m_voiceSwitch & REDSOUND_VOICE_SWITCH_FUZZY_PITCH) != 0) { unsigned int random = GetRandomData(); - workValue = ((int)(random & REDSOUND_RANDOM_BYTE_MASK) + 1) * - (voice->m_pitch * voice->m_track->m_fuzzyPitchDepth); + workValue = voice->m_pitch * voice->m_track->m_fuzzyPitchDepth; + workValue *= (int)(random & REDSOUND_RANDOM_BYTE_MASK) + 1; pitchWork[0] = workValue >> REDSOUND_RANDOM_FUZZY_PITCH_SHIFT; - if ((random & REDSOUND_RANDOM_BYTE_SIGN_BIT) == 0) { - voice->m_randomPitch = pitchWork[0]; - } else { + if ((random & REDSOUND_RANDOM_BYTE_SIGN_BIT) != 0) { voice->m_randomPitch = -(pitchWork[0] >> 1); + } else { + voice->m_randomPitch = pitchWork[0]; } } else { voice->m_randomPitch = 0; @@ -1176,49 +1465,47 @@ static void _VoiceDataAsign(RedTrackDATA* track, RedVoiceDATA* voice, RedNoteDAT } if (voice->m_waveData != 0) { - memcpy(voice->m_adsrTime, + memcpy(&voice->m_adsr, voice->m_waveData->m_adsr, REDSOUND_TRACK_ADSR_SIZE); - if ((s8)track->m_adsrAL != -1) { - voice->m_adsrLevel[REDSOUND_VOICE_ADSR_ATTACK] = - track->m_adsrAL; + if ((s8)track->m_adsr.m_level[REDSOUND_VOICE_ADSR_ATTACK] != (s8)REDSOUND_TRACK_ADSR_DEFAULT_BYTE) { + voice->m_adsr.m_level[REDSOUND_VOICE_ADSR_ATTACK] = + track->m_adsr.m_level[REDSOUND_VOICE_ADSR_ATTACK]; } - if ((s16)track->m_adsrAR != -1) { - voice->m_adsrTime[REDSOUND_VOICE_ADSR_ATTACK] = - track->m_adsrAR; + if ((s16)track->m_adsr.m_time[REDSOUND_VOICE_ADSR_ATTACK] != REDSOUND_TRACK_ADSR_DEFAULT_WORD) { + voice->m_adsr.m_time[REDSOUND_VOICE_ADSR_ATTACK] = + track->m_adsr.m_time[REDSOUND_VOICE_ADSR_ATTACK]; } - if ((s8)track->m_adsrDL != -1) { - voice->m_adsrLevel[REDSOUND_VOICE_ADSR_DECAY] = - track->m_adsrDL; + if ((s8)track->m_adsr.m_level[REDSOUND_VOICE_ADSR_DECAY] != (s8)REDSOUND_TRACK_ADSR_DEFAULT_BYTE) { + voice->m_adsr.m_level[REDSOUND_VOICE_ADSR_DECAY] = + track->m_adsr.m_level[REDSOUND_VOICE_ADSR_DECAY]; } - if ((s16)track->m_adsrDR != -1) { - voice->m_adsrTime[REDSOUND_VOICE_ADSR_DECAY] = - track->m_adsrDR; + if ((s16)track->m_adsr.m_time[REDSOUND_VOICE_ADSR_DECAY] != REDSOUND_TRACK_ADSR_DEFAULT_WORD) { + voice->m_adsr.m_time[REDSOUND_VOICE_ADSR_DECAY] = + track->m_adsr.m_time[REDSOUND_VOICE_ADSR_DECAY]; } - if ((s8)track->m_adsrSL != -1) { - voice->m_adsrLevel[REDSOUND_VOICE_ADSR_SUSTAIN] = - track->m_adsrSL; + if ((s8)track->m_adsr.m_level[REDSOUND_VOICE_ADSR_SUSTAIN] != (s8)REDSOUND_TRACK_ADSR_DEFAULT_BYTE) { + voice->m_adsr.m_level[REDSOUND_VOICE_ADSR_SUSTAIN] = + track->m_adsr.m_level[REDSOUND_VOICE_ADSR_SUSTAIN]; } - if ((s16)track->m_adsrSR != -1) { - voice->m_adsrTime[REDSOUND_VOICE_ADSR_SUSTAIN] = - track->m_adsrSR; + if ((s16)track->m_adsr.m_time[REDSOUND_VOICE_ADSR_SUSTAIN] != REDSOUND_TRACK_ADSR_DEFAULT_WORD) { + voice->m_adsr.m_time[REDSOUND_VOICE_ADSR_SUSTAIN] = + track->m_adsr.m_time[REDSOUND_VOICE_ADSR_SUSTAIN]; } - if ((s8)track->m_adsrRL != -1) { - voice->m_adsrLevel[REDSOUND_VOICE_ADSR_RELEASE] = - track->m_adsrRL; + if ((s8)track->m_adsr.m_level[REDSOUND_VOICE_ADSR_RELEASE] != (s8)REDSOUND_TRACK_ADSR_DEFAULT_BYTE) { + voice->m_adsr.m_level[REDSOUND_VOICE_ADSR_RELEASE] = + track->m_adsr.m_level[REDSOUND_VOICE_ADSR_RELEASE]; } - if ((s16)track->m_adsrRR != -1) { - voice->m_adsrTime[REDSOUND_VOICE_ADSR_RELEASE] = - track->m_adsrRR; + if ((s16)track->m_adsr.m_time[REDSOUND_VOICE_ADSR_RELEASE] != REDSOUND_TRACK_ADSR_DEFAULT_WORD) { + voice->m_adsr.m_time[REDSOUND_VOICE_ADSR_RELEASE] = + track->m_adsr.m_time[REDSOUND_VOICE_ADSR_RELEASE]; } if ((voice->m_voiceSwitch & REDSOUND_VOICE_SWITCH_FUZZY_ADSR) != 0) { - u16 random = GetRandomData(); - u16 attack = (u16)(track->m_fuzzyAdsrDepth * - (random & REDSOUND_RANDOM_BYTE_MASK)); - voice->m_adsrTime[REDSOUND_VOICE_ADSR_ATTACK] = attack; + voice->m_adsr.m_time[REDSOUND_VOICE_ADSR_ATTACK] = + (u16)(track->m_fuzzyAdsrDepth * (GetRandomData() & REDSOUND_RANDOM_BYTE_MASK)); } } else { - memset(voice->m_adsrTime, 0, REDSOUND_TRACK_ADSR_SIZE); + memset(&voice->m_adsr, 0, REDSOUND_TRACK_ADSR_SIZE); } workValue = ((int)voice - (int)p_VoiceData) / REDSOUND_VOICE_SIZE; @@ -1283,6 +1570,27 @@ static RedVoiceDATA* _VoiceDataSelect(RedTrackDATA* track, RedNoteDATA* note, in return voiceData; } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 112b + * EN Address: UNUSED + * EN Size: 112b + * JP Address: TODO + * JP Size: TODO + */ +void SetAllVoiceAccess(RedSoundCONTROL* control, int mask) +{ + RedTrackDATA* track = control->m_tracks; + RedTrackDATA* trackEnd = track + control->m_trackCount; + do { + if (track->m_command != 0) { + SetVoiceAccess(track, mask); + } + track++; + } while (track < trackEnd); +} + /* * --INFO-- * PAL Address: 0x801c4d08 @@ -1335,24 +1643,24 @@ void SetVoiceSwitch(RedTrackDATA* track, int voiceSwitch) static void _AdsrStart(RedVoiceDATA* voice) { int* stage = &voice->m_adsrStage; - u8* adsrData = (u8*)voice->m_adsrTime; + RedAdsrDATA* adsrData = &voice->m_adsr; int prevLevel; int nextLevel; int stepFrames; - nextLevel = voice->m_adsrLevel[REDSOUND_VOICE_ADSR_ATTACK]; + nextLevel = adsrData->m_level[REDSOUND_VOICE_ADSR_ATTACK]; *stage = 0; do { prevLevel = nextLevel; - stepFrames = *(u16*)(adsrData + *stage * 2); - nextLevel = *(u8*)(adsrData + *stage + REDSOUND_VOICE_ADSR_LEVEL_BASE); + stepFrames = adsrData->m_time[*stage]; + nextLevel = RedAdsrGetStageLevel(adsrData, *stage); if (stepFrames != 0) { break; } *stage = *stage + 1; } while (*stage < REDSOUND_VOICE_ADSR_STAGE_COUNT); - stage[REDSOUND_ADSR_STATE_STEP_FRAMES] = stepFrames; + voice->m_adsrStepFrames = stepFrames; if (nextLevel != 0) { nextLevel += 1; nextLevel <<= 8; @@ -1369,7 +1677,7 @@ static void _AdsrStart(RedVoiceDATA* voice) } voice->m_adsrCurrentLevel = prevLevel; nextLevel |= REDSOUND_FIXED_HALF; - stage[REDSOUND_ADSR_STATE_STEP_ADD] = (nextLevel - prevLevel) / stepFrames; + voice->m_adsrStepAdd = (nextLevel - prevLevel) / stepFrames; } else { voice->m_adsrCurrentLevel = nextLevel; } @@ -1386,7 +1694,7 @@ static void _AdsrStart(RedVoiceDATA* voice) */ static void _AdsrDataCompute(RedVoiceDATA* voice) { - u8* adsrData = (u8*)voice->m_adsrTime; + u8* adsrData = (u8*)voice->m_adsr.m_time; int prevValue; int stepCount; int level; @@ -1397,7 +1705,7 @@ static void _AdsrDataCompute(RedVoiceDATA* voice) while (*stage < REDSOUND_VOICE_ADSR_STAGE_COUNT) { prevValue = level; level = (u32)*(u8*)(adsrData + *stage + REDSOUND_VOICE_ADSR_LEVEL_BASE); - stepCount = (u32)*(u16*)(adsrData + *stage * 2); + stepCount = (u32)*(u16*)(adsrData + *stage * REDSOUND_VOICE_ADSR_TIME_BYTE_STRIDE); if (level != 0) { level += 1; level <<= 8; @@ -1472,7 +1780,7 @@ static void _VoiceDropedCallback(void* dropped) voiceData = p_VoiceData; do { if ((voiceData->m_axVoice != 0) && (voiceData->m_axVoice == dropped)) { - voiceData->m_active = 0; + voiceData->m_active = REDSOUND_VOICE_ACTIVE_OFF; voiceData->m_track = 0; voiceData->m_axVoice = 0; } @@ -1491,183 +1799,177 @@ static void _VoiceDropedCallback(void* dropped) */ void EnvelopeKeyExecute() { - int* voiceData = (int*)p_VoiceData; + RedVoiceDATA* voiceData = p_VoiceData; while (true) { - if (voiceData[REDSOUND_VOICE_ACTIVE_WORD] != 0) { - int voice; - - if ((voiceData[REDSOUND_VOICE_FLAGS_WORD] & REDSOUND_VOICE_FLAGS_START) != 0) { - voice = voiceData[REDSOUND_VOICE_AX_VOICE_WORD]; - if ((voice != 0) && (((AXVPB*)voice)->priority != 0)) { - AXFreeVoice((AXVPB*)voice); - voiceData[REDSOUND_VOICE_AX_VOICE_WORD] = 0; + if (voiceData->m_active != REDSOUND_VOICE_ACTIVE_OFF) { + AXVPB* voice; + + if ((voiceData->m_flags & REDSOUND_VOICE_FLAGS_START) != 0) { + voice = voiceData->m_axVoice; + if ((voice != 0) && (voice->priority != 0)) { + AXFreeVoice(voice); + voiceData->m_axVoice = 0; } - if ((((u8*)voiceData)[REDSOUND_VOICE_STATE_FLAGS_OFFSET] & REDSOUND_VOICE_STATE_PLAYING_MASK) != 0) { - voiceData[REDSOUND_VOICE_AX_VOICE_WORD] = - (int)AXAcquireVoice(REDSOUND_VOICE_INDEX_MASK, _VoiceDropedCallback, 0); + if ((voiceData->m_stateFlags & REDSOUND_VOICE_STATE_PLAYING_MASK) != 0) { + voiceData->m_axVoice = AXAcquireVoice(REDSOUND_VOICE_INDEX_MASK, _VoiceDropedCallback, 0); } else { int prio = ((int)voiceData - (int)p_VoiceData) / REDSOUND_VOICE_SIZE; prio = (REDSOUND_VOICE_COUNT - prio >> 1) - 1; if (prio < 1) { prio = 1; } - voiceData[REDSOUND_VOICE_AX_VOICE_WORD] = (int)AXAcquireVoice(prio, _VoiceDropedCallback, 0); + voiceData->m_axVoice = AXAcquireVoice(prio, _VoiceDropedCallback, 0); } } - voice = voiceData[REDSOUND_VOICE_AX_VOICE_WORD]; + voice = voiceData->m_axVoice; if (voice == 0) { - voiceData[REDSOUND_VOICE_FLAGS_WORD] = 0; - voiceData[REDSOUND_VOICE_ACTIVE_WORD] = 0; + voiceData->m_flags = 0; + voiceData->m_active = REDSOUND_VOICE_ACTIVE_OFF; return; } u32 voiceFlags = 0; u32 envChanged = 0; - if ((voiceData[REDSOUND_VOICE_FLAGS_WORD] & REDSOUND_VOICE_FLAGS_PITCH_DIRTY) != 0) { - int pitch = voiceData[REDSOUND_VOICE_TARGET_PITCH_WORD]; + if ((voiceData->m_flags & REDSOUND_VOICE_FLAGS_PITCH_DIRTY) != 0) { + int pitch = voiceData->m_targetPitch; voiceFlags = AX_SYNC_FLAG_COPYRATIO; - ((AXVPB*)voice)->pb.src.ratioHi = (u16)(((u32)pitch >> 0x10) & 3); - ((AXVPB*)voice)->pb.src.ratioLo = (u16)pitch; + voice->pb.src.ratioHi = (u16)(((u32)pitch >> 0x10) & 3); + voice->pb.src.ratioLo = (u16)pitch; } - if ((voiceData[REDSOUND_VOICE_FLAGS_WORD] & REDSOUND_VOICE_FLAGS_ADPCM_DIRTY) != 0) { - if ((voiceData[REDSOUND_VOICE_SWITCH_WORD] & REDSOUND_VOICE_SWITCH_PAUSE) == 0) { - memcpy(&((AXVPB*)voice)->pb.mix, &((RedVoiceDATA*)voiceData)->m_axMix, sizeof(((AXVPB*)voice)->pb.mix)); + if ((voiceData->m_flags & REDSOUND_VOICE_FLAGS_ADPCM_DIRTY) != 0) { + if ((voiceData->m_voiceSwitch & REDSOUND_VOICE_SWITCH_PAUSE) == 0) { + memcpy(&voice->pb.mix, &voiceData->m_axMix, sizeof(voice->pb.mix)); } else { - memset(&((AXVPB*)voice)->pb.mix, 0, sizeof(((AXVPB*)voice)->pb.mix)); + memset(&voice->pb.mix, 0, sizeof(voice->pb.mix)); } - ((AXVPB*)voice)->pb.mixerCtrl = REDSOUND_AX_MIX_CTRL_DRY_STEREO; - if ((voiceData[REDSOUND_VOICE_SWITCH_WORD] & REDSOUND_VOICE_SWITCH_REVERB_STEREO) != 0) { - if ((voiceData[REDSOUND_VOICE_SWITCH_WORD] & REDSOUND_VOICE_SWITCH_REVERB_AUX_A) != 0) { - ((AXVPB*)voice)->pb.mixerCtrl |= REDSOUND_AX_MIX_CTRL_AUX_A_STEREO; + voice->pb.mixerCtrl = REDSOUND_AX_MIX_CTRL_DRY_STEREO; + if ((voiceData->m_voiceSwitch & REDSOUND_VOICE_SWITCH_REVERB_STEREO) != 0) { + if ((voiceData->m_voiceSwitch & REDSOUND_VOICE_SWITCH_REVERB_AUX_A) != 0) { + voice->pb.mixerCtrl |= REDSOUND_AX_MIX_CTRL_AUX_A_STEREO; } else { - ((AXVPB*)voice)->pb.mixerCtrl |= REDSOUND_AX_MIX_CTRL_AUX_B_STEREO; + voice->pb.mixerCtrl |= REDSOUND_AX_MIX_CTRL_AUX_B_STEREO; } } voiceFlags |= AX_SYNC_FLAG_COPYAXPBMIX | AX_SYNC_FLAG_COPYMXRCTRL; } - if (((voiceData[REDSOUND_VOICE_SWITCH_WORD] & REDSOUND_VOICE_SWITCH_PAUSE) == 0) && - ((voiceData[REDSOUND_VOICE_FLAGS_WORD] & REDSOUND_VOICE_FLAGS_ADSR_START) != 0)) { - _AdsrStart((RedVoiceDATA*)voiceData); + if (((voiceData->m_voiceSwitch & REDSOUND_VOICE_SWITCH_PAUSE) == 0) && + ((voiceData->m_flags & REDSOUND_VOICE_FLAGS_ADSR_START) != 0)) { + _AdsrStart(voiceData); envChanged = 1; } - if ((voiceData[REDSOUND_VOICE_FLAGS_WORD] & REDSOUND_VOICE_FLAGS_START) != 0) { - voiceData[REDSOUND_VOICE_FLAGS_WORD] &= REDSOUND_VOICE_FLAGS_CLEAR_RELEASE_ACTIVE_MASK; - RedWaveDATA* waveData = (RedWaveDATA*)voiceData[REDSOUND_VOICE_WAVE_DATA_WORD]; - RedTrackDATA* trackData = (RedTrackDATA*)voiceData[REDSOUND_VOICE_TRACK_WORD]; + if ((voiceData->m_flags & REDSOUND_VOICE_FLAGS_START) != 0) { + voiceData->m_flags &= REDSOUND_VOICE_FLAGS_CLEAR_RELEASE_ACTIVE_MASK; + RedWaveDATA* waveData = voiceData->m_waveData; + RedTrackDATA* trackData = voiceData->m_track; if ((waveData == 0) || (trackData == 0)) { - voiceData[REDSOUND_VOICE_ACTIVE_WORD] = 0; + voiceData->m_active = REDSOUND_VOICE_ACTIVE_OFF; } else { envChanged += 1; - int key = (trackData->m_waveBase + waveData->m_sampleStart + 1) * 2; - int keyBase = key - 2; + int key = (trackData->m_waveBase + waveData->m_sampleStart + REDSOUND_AX_SAMPLE_START_BIAS) * + REDSOUND_AX_SAMPLE_ADDR_SCALE; + int keyBase = key - REDSOUND_AX_SAMPLE_ADDR_SCALE; - *(u16*)(voice + REDSOUND_AX_VOICE_LOOP_OFFSET) = - (u16)((voiceData[REDSOUND_VOICE_SWITCH_WORD] & REDSOUND_VOICE_SWITCH_LOOP) != 0); - ((AXVPB*)voice)->pb.srcSelect = 1; - ((AXVPB*)voice)->pb.state = 1; + voice->pb.type = (u16)((voiceData->m_voiceSwitch & REDSOUND_VOICE_SWITCH_LOOP) != 0); + voice->pb.srcSelect = 1; + voice->pb.state = 1; - memcpy(&((AXVPB*)voice)->pb.adpcm, &waveData->m_adpcm.m_data, sizeof(waveData->m_adpcm.m_data)); - memcpy(&((AXVPB*)voice)->pb.adpcmLoop, &waveData->m_adpcm.m_loop, sizeof(waveData->m_adpcm.m_loop)); - memset(((AXVPB*)voice)->pb.src.last_samples, 0, sizeof(((AXVPB*)voice)->pb.src.last_samples)); - ((AXVPB*)voice)->pb.addr.format = 0; - *(u32*)&((AXVPB*)voice)->pb.addr.currentAddressHi = key; + memcpy(&voice->pb.adpcm, &waveData->m_adpcm.m_data, REDSOUND_WAVE_ADPCM_DATA_SIZE); + memcpy(&voice->pb.adpcmLoop, &waveData->m_adpcm.m_loop, REDSOUND_WAVE_ADPCM_LOOP_SIZE); + memset(voice->pb.src.last_samples, 0, sizeof(voice->pb.src.last_samples)); + voice->pb.addr.format = 0; + *(u32*)&voice->pb.addr.currentAddressHi = key; if (waveData->m_loopStart < 0) { - ((AXVPB*)voice)->pb.addr.loopFlag = 0; + voice->pb.addr.loopFlag = 0; key = keyBase; } else { - ((AXVPB*)voice)->pb.addr.loopFlag = 1; + voice->pb.addr.loopFlag = 1; key = keyBase + waveData->m_loopStart; } - ((AXVPB*)voice)->pb.addr.loopAddressHi = (u16)((u32)key >> 0x10); - ((AXVPB*)voice)->pb.addr.loopAddressLo = (u16)key; - *(u32*)&((AXVPB*)voice)->pb.addr.endAddressHi = keyBase + waveData->m_loopEnd; + voice->pb.addr.loopAddressHi = (u16)((u32)key >> 0x10); + voice->pb.addr.loopAddressLo = (u16)key; + *(u32*)&voice->pb.addr.endAddressHi = keyBase + waveData->m_loopEnd; voiceFlags |= AX_SYNC_FLAG_COPYADPCMLOOP | AX_SYNC_FLAG_COPYSRC | AX_SYNC_FLAG_COPYADPCM | AX_SYNC_FLAG_COPYCURADDR | AX_SYNC_FLAG_COPYADDR | AX_SYNC_FLAG_COPYTYPE | AX_SYNC_FLAG_COPYSTATE | AX_SYNC_FLAG_COPYSELECT; - voiceData[REDSOUND_VOICE_FLAGS_WORD] |= REDSOUND_VOICE_FLAGS_ADSR_START; - voiceData[REDSOUND_VOICE_ENVELOPE_WORD] = REDSOUND_ENVELOPE_LEVEL_FULL; - voiceData[REDSOUND_VOICE_ADSR_CURRENT_WORD] = 0; + voiceData->m_flags |= REDSOUND_VOICE_FLAGS_ADSR_START; + voiceData->m_envelopeLevel = REDSOUND_ENVELOPE_LEVEL_FULL; + voiceData->m_adsrCurrentLevel = 0; } } else { - if ((voiceData[REDSOUND_VOICE_FLAGS_WORD] & REDSOUND_VOICE_FLAGS_RELEASED) != 0) { - voiceData[REDSOUND_VOICE_FLAGS_WORD] |= REDSOUND_VOICE_FLAGS_RELEASE_ACTIVE; - voiceData[REDSOUND_VOICE_ADSR_STAGE_WORD] = REDSOUND_VOICE_ADSR_RELEASE; - voiceData[REDSOUND_VOICE_ADSR_STEP_FRAMES_WORD] = - (u16)((u8*)voiceData)[REDSOUND_VOICE_ADSR_TIME_RELEASE_BYTE_OFFSET]; - if (voiceData[REDSOUND_VOICE_ADSR_STEP_FRAMES_WORD] == 0) { - voiceData[REDSOUND_VOICE_ADSR_CURRENT_WORD] = 0; + if ((voiceData->m_flags & REDSOUND_VOICE_FLAGS_RELEASED) != 0) { + voiceData->m_flags |= REDSOUND_VOICE_FLAGS_RELEASE_ACTIVE; + voiceData->m_adsrStage = REDSOUND_VOICE_ADSR_RELEASE; + voiceData->m_adsrStepFrames = voiceData->m_adsr.m_time[REDSOUND_VOICE_ADSR_RELEASE]; + if (voiceData->m_adsrStepFrames == 0) { + voiceData->m_adsrCurrentLevel = 0; } else { - voiceData[REDSOUND_VOICE_ADSR_STEP_ADD_WORD] = -voiceData[REDSOUND_VOICE_ADSR_CURRENT_WORD]; - voiceData[REDSOUND_VOICE_ADSR_STEP_ADD_WORD] = - voiceData[REDSOUND_VOICE_ADSR_STEP_ADD_WORD] / voiceData[REDSOUND_VOICE_ADSR_STEP_FRAMES_WORD]; + voiceData->m_adsrStepAdd = -voiceData->m_adsrCurrentLevel; + voiceData->m_adsrStepAdd = voiceData->m_adsrStepAdd / voiceData->m_adsrStepFrames; } - voiceData[REDSOUND_VOICE_ENVELOPE_WORD] = - voiceData[REDSOUND_VOICE_ADSR_CURRENT_WORD] >> REDSOUND_FIXED_SHIFT; + voiceData->m_envelopeLevel = voiceData->m_adsrCurrentLevel >> REDSOUND_FIXED_SHIFT; } else { - if ((voiceData[REDSOUND_VOICE_SWITCH_WORD] & REDSOUND_VOICE_SWITCH_PAUSE) == 0) { - if ((voiceData[REDSOUND_VOICE_FLAGS_WORD] & REDSOUND_VOICE_FLAGS_ADSR_START) == 0) { - envChanged |= _AdsrDataExecute((RedVoiceDATA*)voiceData); - voiceData[REDSOUND_VOICE_ENVELOPE_WORD] = - voiceData[REDSOUND_VOICE_ADSR_CURRENT_WORD] >> REDSOUND_FIXED_SHIFT; + if ((voiceData->m_voiceSwitch & REDSOUND_VOICE_SWITCH_PAUSE) == 0) { + if ((voiceData->m_flags & REDSOUND_VOICE_FLAGS_ADSR_START) == 0) { + envChanged |= _AdsrDataExecute(voiceData); + voiceData->m_envelopeLevel = voiceData->m_adsrCurrentLevel >> REDSOUND_FIXED_SHIFT; } - voiceData[REDSOUND_VOICE_FLAGS_WORD] &= ~REDSOUND_VOICE_FLAGS_ADSR_START; + voiceData->m_flags &= ~REDSOUND_VOICE_FLAGS_ADSR_START; } } } - if (voiceData[REDSOUND_VOICE_ENVELOPE_WORD] < 1) { - voiceData[REDSOUND_VOICE_FLAGS_WORD] &= REDSOUND_VOICE_FLAGS_CLEAR_RELEASE_ACTIVE_MASK; - voiceData[REDSOUND_VOICE_ACTIVE_WORD] = 0; + if (voiceData->m_envelopeLevel < 1) { + voiceData->m_flags &= REDSOUND_VOICE_FLAGS_CLEAR_RELEASE_ACTIVE_MASK; + voiceData->m_active = REDSOUND_VOICE_ACTIVE_OFF; voiceFlags |= AX_SYNC_FLAG_COPYVOL | AX_SYNC_FLAG_COPYSTATE; - voiceData[REDSOUND_VOICE_TRACK_WORD] = 0; - ((AXVPB*)voice)->pb.state = 0; - voiceData[REDSOUND_VOICE_ADSR_CURRENT_WORD] = 0; - voiceData[REDSOUND_VOICE_ENVELOPE_WORD] = 0; - ((AXVPB*)voice)->pb.ve.currentVolume = 0; - ((AXVPB*)voice)->pb.ve.currentDelta = 0; + voiceData->m_track = 0; + voice->pb.state = 0; + voiceData->m_adsrCurrentLevel = 0; + voiceData->m_envelopeLevel = 0; + voice->pb.ve.currentVolume = 0; + voice->pb.ve.currentDelta = 0; } else if ((envChanged != 0) && - ((u32)((AXVPB*)voice)->pb.ve.currentVolume != - ((voiceData[REDSOUND_VOICE_ADSR_CURRENT_WORD] >> REDSOUND_FIXED_SHIFT) & 0xFFFFU))) { + ((u32)voice->pb.ve.currentVolume != + ((voiceData->m_adsrCurrentLevel >> REDSOUND_FIXED_SHIFT) & 0xFFFFU))) { voiceFlags |= AX_SYNC_FLAG_COPYVOL; - ((AXVPB*)voice)->pb.ve.currentDelta = 0; - ((AXVPB*)voice)->pb.ve.currentVolume = - (u16)(voiceData[REDSOUND_VOICE_ADSR_CURRENT_WORD] >> REDSOUND_FIXED_SHIFT); + voice->pb.ve.currentDelta = 0; + voice->pb.ve.currentVolume = (u16)(voiceData->m_adsrCurrentLevel >> REDSOUND_FIXED_SHIFT); } - ((AXVPB*)voice)->sync |= voiceFlags; + voice->sync |= voiceFlags; } else { - voiceData[REDSOUND_VOICE_ENVELOPE_WORD] = 0; - voiceData[REDSOUND_VOICE_WAVE_DATA_WORD] = 0; - int voice = voiceData[REDSOUND_VOICE_AX_VOICE_WORD]; + voiceData->m_envelopeLevel = 0; + voiceData->m_waveData = 0; + AXVPB* voice = voiceData->m_axVoice; if (voice != 0) { - if (((AXVPB*)voice)->pb.state != 0) { - ((AXVPB*)voice)->pb.state = 0; - ((AXVPB*)voice)->pb.ve.currentVolume = 0; - ((AXVPB*)voice)->sync |= AX_SYNC_FLAG_COPYVOL | AX_SYNC_FLAG_COPYSTATE; + if (voice->pb.state != 0) { + voice->pb.state = 0; + voice->pb.ve.currentVolume = 0; + voice->sync |= AX_SYNC_FLAG_COPYVOL | AX_SYNC_FLAG_COPYSTATE; } else { - if (((AXVPB*)voice)->priority != 0) { - AXFreeVoice((AXVPB*)voice); + if (voice->priority != 0) { + AXFreeVoice(voice); } - voiceData[REDSOUND_VOICE_AX_VOICE_WORD] = 0; - voiceData[REDSOUND_VOICE_TRACK_WORD] = 0; + voiceData->m_axVoice = 0; + voiceData->m_track = 0; } } } - voiceData[REDSOUND_VOICE_FLAGS_WORD] &= REDSOUND_VOICE_FLAGS_EXECUTE_KEEP_MASK; - voiceData += REDSOUND_VOICE_SIZE / sizeof(*voiceData); - if ((int*)(p_VoiceData + REDSOUND_VOICE_COUNT) <= voiceData) { + voiceData->m_flags &= REDSOUND_VOICE_FLAGS_EXECUTE_KEEP_MASK; + voiceData++; + if (p_VoiceData + REDSOUND_VOICE_COUNT <= voiceData) { return; } } @@ -1687,7 +1989,17 @@ static void _KeyOnControl() u32 voiceStartMask[2]; RedKeyOnSlot* reserve; RedVoiceDATA* voiceData; - int (*waveFunc)(int); + RedSwingFunc waveFunc; + int shakeDepth; + int shakeValue; + RedSoundCONTROL* soundControl; + RedTrackDATA* track; + RedTrackDATA* trackBase; + RedTrackDATA* trackData; + RedVoiceDATA* voice; + int volume; + int idx; + u32 bit; _VoiceEnvelopeCheck(); voiceStartMask[REDSOUND_VOICE_START_MASK_LOW] = 0; @@ -1706,13 +2018,13 @@ static void _KeyOnControl() if ((p_SoundControlBuffer->m_activeTrackCount != 0) && ((p_SoundControlBuffer->m_flags & REDSOUND_CONTROL_FLAG_PAUSE) == 0)) { - RedTrackDATA* track = p_SoundControlBuffer->m_tracks; + track = p_SoundControlBuffer->m_tracks; do { if ((track->m_command != 0) && (track->m_shakeFunc != 0)) { waveFunc = track->m_shakeFunc; - int shakeDepth = (track->m_shakeDepth >> REDSOUND_FIXED_SHIFT) + 1; - int shakeValue = waveFunc((u32)track->m_shakeOutput >> REDSOUND_FIXED_SHIFT); - track->m_shakePan = (shakeDepth * shakeValue) >> 0x10; + shakeDepth = (track->m_shakeDepth >> REDSOUND_FIXED_SHIFT) + 1; + shakeValue = waveFunc((u32)track->m_shakeOutput >> REDSOUND_FIXED_SHIFT); + track->m_shakePan = (shakeDepth * shakeValue) >> REDSOUND_SHAKE_PAN_SCALE_SHIFT; track->m_shakeOutput += track->m_shakeRate; } track++; @@ -1723,14 +2035,14 @@ static void _KeyOnControl() if ((p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_SECONDARY].m_activeTrackCount != 0) && ((p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_SECONDARY].m_flags & REDSOUND_CONTROL_FLAG_PAUSE) == 0)) { - RedTrackDATA* track = p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_SECONDARY].m_tracks; - RedTrackDATA* trackBase = p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_SECONDARY].m_tracks; + track = p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_SECONDARY].m_tracks; + trackBase = p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_SECONDARY].m_tracks; do { if ((track->m_command != 0) && (track->m_shakeFunc != 0)) { waveFunc = track->m_shakeFunc; - int shakeDepth = (track->m_shakeDepth >> REDSOUND_FIXED_SHIFT) + 1; - int shakeValue = waveFunc((u32)track->m_shakeOutput >> REDSOUND_FIXED_SHIFT); - track->m_shakePan = (shakeDepth * shakeValue) >> 0x10; + shakeDepth = (track->m_shakeDepth >> REDSOUND_FIXED_SHIFT) + 1; + shakeValue = waveFunc((u32)track->m_shakeOutput >> REDSOUND_FIXED_SHIFT); + track->m_shakePan = (shakeDepth * shakeValue) >> REDSOUND_SHAKE_PAN_SCALE_SHIFT; track->m_shakeOutput += track->m_shakeRate; } track++; @@ -1738,13 +2050,13 @@ static void _KeyOnControl() } { - RedTrackDATA* track = p_SoundControlBuffer[REDSOUND_CONTROL_SE].m_tracks; + track = p_SoundControlBuffer[REDSOUND_CONTROL_SE].m_tracks; do { if ((track->m_command != 0) && (track->m_shakeFunc != 0)) { waveFunc = track->m_shakeFunc; - int shakeDepth = (track->m_shakeDepth >> REDSOUND_FIXED_SHIFT) + 1; - int shakeValue = waveFunc((u32)track->m_shakeOutput >> REDSOUND_FIXED_SHIFT); - track->m_shakePan = (shakeDepth * shakeValue) >> 0x10; + shakeDepth = (track->m_shakeDepth >> REDSOUND_FIXED_SHIFT) + 1; + shakeValue = waveFunc((u32)track->m_shakeOutput >> REDSOUND_FIXED_SHIFT); + track->m_shakePan = (shakeDepth * shakeValue) >> REDSOUND_SHAKE_PAN_SCALE_SHIFT; track->m_shakeOutput += track->m_shakeRate; } track++; @@ -1752,19 +2064,18 @@ static void _KeyOnControl() } { - RedVoiceDATA* voice = p_VoiceData; + voice = p_VoiceData; do { - if ((voice->m_active != 0) && (voice->m_track != 0) && + if ((voice->m_active != REDSOUND_VOICE_ACTIVE_OFF) && (voice->m_track != 0) && ((voice->m_track->m_voiceSwitch & REDSOUND_VOICE_SWITCH_SKIP_UPDATE) == 0)) { if ((voice->m_updateFlags & REDSOUND_VOICE_UPDATE_VOLUME) != 0 || (voice->m_track->m_tremoloFunc != 0) || (voice->m_track->m_shakeFunc != 0)) { - int volume; - RedSoundCONTROL* soundControl = p_SoundControlBuffer; - RedTrackDATA* trackData = voice->m_track; + soundControl = p_SoundControlBuffer; + trackData = voice->m_track; if ((soundControl->m_tracks <= trackData) && (trackData < soundControl->m_tracks + soundControl->m_trackCount)) { - int idx = trackData->m_trackNo; + idx = trackData->m_trackNo; if (((1U << (idx % REDSOUND_MUTE_BITS_PER_WORD)) & m_Mute[idx / REDSOUND_MUTE_BITS_PER_WORD]) == 0) { volume = ((soundControl->m_volumeScale + 1) * @@ -1783,7 +2094,7 @@ static void _KeyOnControl() (trackData < soundControl[REDSOUND_CONTROL_MUSIC_SECONDARY].m_tracks + soundControl[REDSOUND_CONTROL_MUSIC_SECONDARY].m_trackCount)) { - int idx = trackData->m_trackNo; + idx = trackData->m_trackNo; if (((1U << (idx % REDSOUND_MUTE_BITS_PER_WORD)) & m_Mute[idx / REDSOUND_MUTE_BITS_PER_WORD]) == 0) { @@ -1817,8 +2128,8 @@ static void _KeyOnControl() } { - u32 bit = 1; - RedVoiceDATA* voice = p_VoiceData; + bit = 1; + voice = p_VoiceData; do { if ((voiceStartMask[REDSOUND_VOICE_START_MASK_LOW] & bit) != 0) { voiceStartMask[REDSOUND_VOICE_START_MASK_LOW] &= ~bit; @@ -1830,8 +2141,8 @@ static void _KeyOnControl() } { - u32 bit = 1; - RedVoiceDATA* voice = p_VoiceData + REDSOUND_MUTE_BITS_PER_WORD; + bit = 1; + voice = p_VoiceData + REDSOUND_MUTE_BITS_PER_WORD; do { if ((voiceStartMask[REDSOUND_VOICE_START_MASK_HIGH] & bit) != 0) { voiceStartMask[REDSOUND_VOICE_START_MASK_HIGH] &= ~bit; @@ -1872,7 +2183,7 @@ static void _ExecuteExtraData() musicBase = soundControl->m_tracks; voice = p_VoiceData; do { - if ((musicBase <= voice->m_track) && + if ((voice->m_track >= musicBase) && (voice->m_track < musicBase + soundControl->m_trackCount)) { voice->m_updateFlags |= REDSOUND_VOICE_UPDATE_VOLUME; } @@ -1883,6 +2194,8 @@ static void _ExecuteExtraData() soundControl++; } while (soundControl < p_SoundControlBuffer + REDSOUND_CONTROL_MUSIC_SKIP); + soundControl = p_SoundControlBuffer; + if (p_MusicTempoControl->m_count != 0) { p_MusicTempoControl->m_count--; p_MusicTempoControl->m_value += p_MusicTempoControl->m_step; @@ -1894,24 +2207,24 @@ static void _ExecuteExtraData() voice = p_VoiceData; do { if ((voice->m_stateFlags & REDSOUND_VOICE_STATE_PLAYING_MASK) == 0) { - voice->m_pitch = PitchCompute( - voice->m_basePitch + p_MusicPitchControl->m_value, - (int)voice->m_track->m_keyTranspose + (int)voice->m_track->m_pitchBend, - voice->m_waveData->m_pitch, - voice->m_track->m_fineTune); + int pitchBase = voice->m_basePitch; + int pitchOffset = (int)voice->m_track->m_keyTranspose + (int)voice->m_track->m_pitchBend; + voice->m_pitch = PitchCompute(pitchBase + p_MusicPitchControl->m_value, pitchOffset, + voice->m_waveData->m_pitch, + voice->m_track->m_fineTune); voice->m_updateFlags |= REDSOUND_VOICE_UPDATE_PITCH; } voice++; } while (voice < p_VoiceData + REDSOUND_VOICE_COUNT); } - soundControl = p_SoundControlBuffer; do { - if ((soundControl->m_tickCounter != 0) && (soundControl->m_volumeDelta != 0)) { + if ((soundControl->m_activeTrackCount != 0) && (soundControl->m_volumeDelta != 0)) { soundControl->m_volumeDelta--; soundControl->m_volume += soundControl->m_volumeAdd; if ((soundControl->m_flags & REDSOUND_CONTROL_FLAG_STOP_ON_VOLUME_ZERO) != 0) { - if ((soundControl->m_volumeDelta == 0) && (soundControl->m_musicId >= 0)) { + if ((soundControl->m_volumeDelta == 0) && + (soundControl->m_musicId >= REDSOUND_MUSIC_ID_MIN)) { MusicStop(soundControl->m_musicId); } } else { @@ -1952,48 +2265,48 @@ static void _MusicTrackDataExecute(RedTrackDATA* track, int frames) if (track->m_volumeDelta != 0) { int step; - if (frames < track->m_volumeDelta) { + if (track->m_volumeDelta > frames) { step = frames; } else { step = track->m_volumeDelta; } - updateFlags = REDSOUND_VOICE_UPDATE_VOLUME; + updateFlags |= REDSOUND_VOICE_UPDATE_VOLUME; track->m_volumeDelta -= step; track->m_volume += track->m_volumeAdd * step; } if (track->m_expressionDelta != 0) { int step; - if (frames < track->m_expressionDelta) { + if (track->m_expressionDelta > frames) { step = frames; } else { step = track->m_expressionDelta; } - updateFlags = REDSOUND_VOICE_UPDATE_VOLUME; + updateFlags |= REDSOUND_VOICE_UPDATE_VOLUME; track->m_expressionDelta -= step; track->m_expression += track->m_expressionAdd * step; } if (track->m_panDelta != 0) { int step; - if (frames < track->m_panDelta) { + if (track->m_panDelta > frames) { step = frames; } else { step = track->m_panDelta; } - updateFlags = REDSOUND_VOICE_UPDATE_VOLUME; + updateFlags |= REDSOUND_VOICE_UPDATE_VOLUME; track->m_panDelta -= step; track->m_pan += track->m_panAdd * step; } if (track->m_reverbDepthDelta != 0) { int step; - if (frames < track->m_reverbDepthDelta) { + if (track->m_reverbDepthDelta > frames) { step = frames; } else { step = track->m_reverbDepthDelta; } - updateFlags = REDSOUND_VOICE_UPDATE_VOLUME; + updateFlags |= REDSOUND_VOICE_UPDATE_VOLUME; track->m_reverbDepthDelta -= step; track->m_reverbDepth += track->m_reverbDepthAdd * step; } @@ -2002,7 +2315,7 @@ static void _MusicTrackDataExecute(RedTrackDATA* track, int frames) int step; int addPitch; - if (frames < track->m_sweepDelta) { + if (track->m_sweepDelta > frames) { step = frames; } else { step = track->m_sweepDelta; @@ -2030,7 +2343,7 @@ static void _MusicTrackDataExecute(RedTrackDATA* track, int frames) if (track->m_vibrateFunc != 0) { if (track->m_vibrateRateDelta != 0) { int step; - if (frames < track->m_vibrateRateDelta) { + if (track->m_vibrateRateDelta > frames) { step = frames; } else { step = track->m_vibrateRateDelta; @@ -2040,7 +2353,7 @@ static void _MusicTrackDataExecute(RedTrackDATA* track, int frames) } if (track->m_vibrateDepthDelta != 0) { int step; - if (frames < track->m_vibrateDepthDelta) { + if (track->m_vibrateDepthDelta > frames) { step = frames; } else { step = track->m_vibrateDepthDelta; @@ -2053,7 +2366,7 @@ static void _MusicTrackDataExecute(RedTrackDATA* track, int frames) if (track->m_tremoloFunc != 0) { if (track->m_tremoloRateDelta != 0) { int step; - if (frames < track->m_tremoloRateDelta) { + if (track->m_tremoloRateDelta > frames) { step = frames; } else { step = track->m_tremoloRateDelta; @@ -2063,7 +2376,7 @@ static void _MusicTrackDataExecute(RedTrackDATA* track, int frames) } if (track->m_tremoloDepthDelta != 0) { int step; - if (frames < track->m_tremoloDepthDelta) { + if (track->m_tremoloDepthDelta > frames) { step = frames; } else { step = track->m_tremoloDepthDelta; @@ -2077,7 +2390,7 @@ static void _MusicTrackDataExecute(RedTrackDATA* track, int frames) if (track->m_shakeFunc != 0) { if (track->m_shakeRateDelta != 0) { int step; - if (frames < track->m_shakeRateDelta) { + if (track->m_shakeRateDelta > frames) { step = frames; } else { step = track->m_shakeRateDelta; @@ -2087,7 +2400,7 @@ static void _MusicTrackDataExecute(RedTrackDATA* track, int frames) } if (track->m_shakeDepthDelta != 0) { int step; - if (frames < track->m_shakeDepthDelta) { + if (track->m_shakeDepthDelta > frames) { step = frames; } else { step = track->m_shakeDepthDelta; @@ -2101,7 +2414,7 @@ static void _MusicTrackDataExecute(RedTrackDATA* track, int frames) if (voiceData->m_track == track) { if (voiceData->m_pitchModDelay != 0) { int step; - if (frames < voiceData->m_pitchModDelay) { + if (voiceData->m_pitchModDelay > frames) { step = frames; } else { step = voiceData->m_pitchModDelay; @@ -2110,7 +2423,7 @@ static void _MusicTrackDataExecute(RedTrackDATA* track, int frames) } if (voiceData->m_volumeModDelay != 0) { int step; - if (frames < voiceData->m_volumeModDelay) { + if (voiceData->m_volumeModDelay > frames) { step = frames; } else { step = voiceData->m_volumeModDelay; @@ -2137,13 +2450,16 @@ static void _MidiTrackExecute(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track = control->m_tracks; do { if (track->m_command != 0) { - int step = frames; + int step; m_ChangeStatus = 0; if (track->m_deltaTime < frames) { step = track->m_deltaTime; + } else { + step = frames; } + int execStep = step; track->m_deltaTime -= frames; - _MusicTrackDataExecute(track, step); + _MusicTrackDataExecute(track, execStep); if (((track->m_flags & REDSOUND_TRACK_FLAG_TENUTO) == 0) && (track->m_deltaTime == 1)) { KeyOffSet(control, keyOnData, track); } @@ -2151,7 +2467,8 @@ static void _MidiTrackExecute(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, unsigned char* cmd = track->m_command; int delta; track->m_command = cmd + 1; - p_MidiControl_Function[*cmd](control, keyOnData, track); + RedMidiControlFunc func = p_MidiControl_Function[*cmd]; + func(control, keyOnData, track); if (track->m_command != 0) { if (track->m_deltaTime < 1) { delta = DeltaTimeSumup((unsigned char**)&track->m_command); @@ -2165,7 +2482,9 @@ static void _MidiTrackExecute(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, if (delta < 1) { delta = 1; } else if ((track->m_voiceSwitch & REDSOUND_VOICE_SWITCH_FUZZY_DELTA_TIME) != 0) { - delta += ((delta * track->m_fuzzyDeltaTimeDepth >> 8) * (int)GetRandomData()) >> 7; + int fuzzyDelta = delta * track->m_fuzzyDeltaTimeDepth >> 8; + s8 random = (s8)GetRandomData(); + delta += fuzzyDelta * random >> 7; if (delta < 1) { delta = 1; } @@ -2174,7 +2493,7 @@ static void _MidiTrackExecute(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, if (track->m_deltaTime < -1) { int execStep = delta; - if (track->m_deltaTime + delta > 0) { + if (track->m_deltaTime + execStep > 0) { execStep = -track->m_deltaTime; } _MusicTrackDataExecute(track, execStep); @@ -2226,7 +2545,7 @@ static int _MusicMidiNoteExecute(RedSoundCONTROL* control, RedKeyOnDATA* keyOnDa } control->m_skipFrames = 1; - if (m_MusicPhraseStop == 0) { + if (m_MusicPhraseStop == REDSOUND_MUSIC_PHRASE_STOP_OFF) { if ((control->m_flags & REDSOUND_CONTROL_FLAG_WHOLE_LOOP_END) != 0) { control->m_flags &= ~REDSOUND_CONTROL_FLAG_WHOLE_LOOP_END; if ((control->m_flags & REDSOUND_CONTROL_FLAG_WHOLE_LOOP_ACTIVE) != 0) { @@ -2251,25 +2570,25 @@ static void _MusicNoteExecute() { int i; u32 trackCount; - u32* soundControl; RedTrackDATA* track; + RedSavedTrackDATA* savedTrackData; int status = _MusicMidiNoteExecute(p_SoundControl, p_KeyOnData, 1); - while ((status == 0) && (m_MusicPhraseStop == 0) && + while ((status == 0) && (m_MusicPhraseStop == REDSOUND_MUSIC_PHRASE_STOP_OFF) && ((p_SoundControl->m_flags & REDSOUND_CONTROL_FLAG_WHOLE_LOOP_ACTIVE) != 0)) { p_SoundControl->m_activeTrackCount = p_SoundControl->m_savedActiveTrackCount; - memcpy(&p_SoundControl->m_measure, &p_SoundControl->m_savedMeasure, REDSOUND_CONTROL_SAVED_POSITION_SIZE); + memcpy(&p_SoundControl->m_measure, &p_SoundControl->m_savedPosition, REDSOUND_CONTROL_SAVED_POSITION_SIZE); memcpy(&p_SoundControl->m_tempo, &p_SoundControl->m_savedTempo, REDSOUND_CONTROL_SAVED_TEMPO_SIZE); - soundControl = (u32*)p_SoundControl; track = p_SoundControl->m_tracks; trackCount = p_SoundControl->m_trackCount; + savedTrackData = &p_SoundControl->m_savedTracks; i = 0; do { - track->m_command = (u8*)soundControl[i + REDSOUND_CONTROL_SAVED_COMMAND_WORD_OFFSET]; - track->m_deltaTime = soundControl[i + REDSOUND_CONTROL_SAVED_DELTA_WORD_OFFSET]; - track->m_flags = soundControl[i + REDSOUND_CONTROL_SAVED_FLAGS_WORD_OFFSET]; - *(int*)&track->m_note = soundControl[i + REDSOUND_CONTROL_SAVED_NOTE_WORD_OFFSET]; + track->m_command = savedTrackData->m_command[i]; + track->m_deltaTime = savedTrackData->m_delta[i]; + track->m_flags = savedTrackData->m_flags[i]; + *(int*)&track->m_note = *(int*)&savedTrackData->m_note[i]; track++; i++; } while (--trackCount != 0); @@ -2277,10 +2596,10 @@ static void _MusicNoteExecute() status = _MusicMidiNoteExecute(p_SoundControl, p_KeyOnData, 1); } - if ((p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_PRIMARY].m_musicId < 0) && - (p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_SECONDARY].m_musicId < 0) && - (p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_SKIP].m_musicId < 0)) { - m_MusicPhraseStop = 0; + if ((p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_PRIMARY].m_musicId < REDSOUND_MUSIC_ID_MIN) && + (p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_SECONDARY].m_musicId < REDSOUND_MUSIC_ID_MIN) && + (p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_SKIP].m_musicId < REDSOUND_MUSIC_ID_MIN)) { + m_MusicPhraseStop = REDSOUND_MUSIC_PHRASE_STOP_OFF; } } @@ -2315,7 +2634,7 @@ static int _MusicMidiNoteSkipExecute(RedSoundCONTROL* control, RedKeyOnDATA* key if ((control->m_activeTrackCount != 0) && ((control->m_flags & REDSOUND_CONTROL_FLAG_WHOLE_LOOP_END) == 0)) { m_MusicSkipLine--; frames = tick[REDSOUND_CONTROL_TICK_PER_MEASURE]; - RedSleep(1000); + RedSleep(REDSOUND_MUSIC_SKIP_LOOP_SLEEP_US); } } @@ -2350,14 +2669,16 @@ static void _SkipMusicEntry() RedKeyOnSlot* dst; RedSoundCONTROL* soundControl; RedControlRamp volume; + int keyOnEntryCount = 0; - if (p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_SKIP].m_musicId >= 0) { + if (p_SoundControlBuffer[REDSOUND_CONTROL_MUSIC_SKIP].m_musicId >= REDSOUND_MUSIC_ID_MIN) { src = p_SkipKeyOn->m_fixed; dst = p_KeyOnData->m_fixed; do { if ((src->m_track != 0) && (dst->m_track == 0)) { dst->m_track = src->m_track; *(int*)&dst->m_note = *(int*)&src->m_note; + keyOnEntryCount++; m_KeyOnEntry++; } src++; @@ -2365,20 +2686,31 @@ static void _SkipMusicEntry() } while (src < p_SkipKeyOn->m_priority); src = p_SkipKeyOn->m_priority; - for (dst = p_KeyOnData->m_priority; (dst < p_KeyOnData->m_normal) && (dst->m_track != 0); dst++) { + dst = p_KeyOnData->m_priority; + while (dst < p_KeyOnData->m_normal) { + if (dst->m_track == 0) { + break; + } + dst++; } while ((dst < p_KeyOnData->m_normal) && (src < p_SkipKeyOn->m_normal)) { if (src->m_track != 0) { dst->m_track = src->m_track; *(int*)&dst->m_note = *(int*)&src->m_note; dst++; + keyOnEntryCount++; m_KeyOnEntry++; } src++; } src = p_SkipKeyOn->m_normal; - for (dst = p_KeyOnData->m_normal; (dst < p_KeyOnData->m_normal + REDSOUND_KEY_ON_SLOT_COUNT) && (dst->m_track != 0); dst++) { + dst = p_KeyOnData->m_normal; + while (dst < p_KeyOnData->m_normal + REDSOUND_KEY_ON_SLOT_COUNT) { + if (dst->m_track == 0) { + break; + } + dst++; } while ((dst < p_KeyOnData->m_normal + REDSOUND_KEY_ON_SLOT_COUNT) && (src < p_SkipKeyOn->m_normal + REDSOUND_KEY_ON_SLOT_COUNT)) { @@ -2386,14 +2718,15 @@ static void _SkipMusicEntry() dst->m_track = src->m_track; *(int*)&dst->m_note = *(int*)&src->m_note; dst++; + keyOnEntryCount++; m_KeyOnEntry++; } src++; } soundControl = p_SoundControlBuffer; - if (soundControl[REDSOUND_CONTROL_MUSIC_PRIMARY].m_musicId != -1) { - if (soundControl[REDSOUND_CONTROL_MUSIC_SECONDARY].m_musicId != -1) { + if (soundControl[REDSOUND_CONTROL_MUSIC_PRIMARY].m_musicId != REDSOUND_MUSIC_ID_NONE) { + if (soundControl[REDSOUND_CONTROL_MUSIC_SECONDARY].m_musicId != REDSOUND_MUSIC_ID_NONE) { MusicStop(soundControl[REDSOUND_CONTROL_MUSIC_SECONDARY].m_musicId); } memcpy(&soundControl[REDSOUND_CONTROL_MUSIC_SECONDARY], soundControl, REDSOUND_CONTROL_SIZE); @@ -2403,11 +2736,11 @@ static void _SkipMusicEntry() memcpy(&volume, &soundControl[REDSOUND_CONTROL_MUSIC_SKIP].m_volume, sizeof(volume)); memset(&soundControl[REDSOUND_CONTROL_MUSIC_SKIP], 0, REDSOUND_CONTROL_SIZE); memcpy(&soundControl[REDSOUND_CONTROL_MUSIC_SKIP].m_volume, &volume, sizeof(volume)); - soundControl[REDSOUND_CONTROL_MUSIC_SKIP].m_musicId = -1; + soundControl[REDSOUND_CONTROL_MUSIC_SKIP].m_musicId = REDSOUND_MUSIC_ID_NONE; } RedDelete(p_SkipKeyOn); - m_MusicSkipComplete = 0; + m_MusicSkipComplete = REDSOUND_MUSIC_SKIP_NOT_COMPLETE; } @@ -2425,14 +2758,14 @@ void MusicSkipFunction() int activeTrackCount; int trackIndex; unsigned int trackCount; - u32* soundControl; + RedSavedTrackDATA* savedTrackData; RedSoundCONTROL* control; RedTrackDATA* track; do { p_SkipKeyOn = (RedKeyOnDATA*)RedNew(REDSOUND_KEY_ON_BUFFER_SIZE); if (p_SkipKeyOn == 0) { - RedSleep(10000); + RedSleep(REDSOUND_MUSIC_SKIP_RETRY_SLEEP_US); } } while (p_SkipKeyOn == 0); @@ -2441,24 +2774,24 @@ void MusicSkipFunction() activeTrackCount = _MusicMidiNoteSkipExecute(control, p_SkipKeyOn, 1); while ((activeTrackCount == 0) && ((control->m_flags & REDSOUND_CONTROL_FLAG_WHOLE_LOOP_ACTIVE) != 0)) { control->m_activeTrackCount = control->m_savedActiveTrackCount; - memcpy(&control->m_measure, &control->m_savedMeasure, REDSOUND_CONTROL_SAVED_POSITION_SIZE); + memcpy(&control->m_measure, &control->m_savedPosition, REDSOUND_CONTROL_SAVED_POSITION_SIZE); memcpy(&control->m_tempo, &control->m_savedTempo, REDSOUND_CONTROL_SAVED_TEMPO_SIZE); - soundControl = (u32*)control; + savedTrackData = &control->m_savedTracks; track = control->m_tracks; trackCount = control->m_trackCount; trackIndex = 0; do { - track->m_command = (u8*)soundControl[trackIndex + REDSOUND_CONTROL_SAVED_COMMAND_WORD_OFFSET]; - track->m_deltaTime = soundControl[trackIndex + REDSOUND_CONTROL_SAVED_DELTA_WORD_OFFSET]; - track->m_flags = soundControl[trackIndex + REDSOUND_CONTROL_SAVED_FLAGS_WORD_OFFSET]; - *(int*)&track->m_note = soundControl[trackIndex + REDSOUND_CONTROL_SAVED_NOTE_WORD_OFFSET]; + track->m_command = savedTrackData->m_command[trackIndex]; + track->m_deltaTime = savedTrackData->m_delta[trackIndex]; + track->m_flags = savedTrackData->m_flags[trackIndex]; + *(int*)&track->m_note = *(int*)&savedTrackData->m_note[trackIndex]; trackCount -= 1; trackIndex += 1; track += 1; } while (trackCount != 0); activeTrackCount = _MusicMidiNoteSkipExecute(control, p_SkipKeyOn, 1); } - m_MusicSkipComplete = 1; + m_MusicSkipComplete = REDSOUND_MUSIC_SKIP_COMPLETE; } @@ -2474,7 +2807,21 @@ void MusicSkipFunction() static void _SeTrackDataExecute(RedTrackDATA* track, int frames) { RedVoiceDATA* voice; - int step; + int volumeStep; + int expressionStep; + int panStep; + int reverbStep; + int mixStep; + int pitchStep; + int sweepStep; + int vibrateRateStep; + int vibrateDepthStep; + int tremoloRateStep; + int tremoloDepthStep; + int shakeRateStep; + int shakeDepthStep; + int pitchModDelayStep; + int volumeModDelayStep; if ((track->m_note.m_allocFlags & REDSOUND_NOTE_ALLOC_STREAM) != 0) { return; @@ -2486,85 +2833,85 @@ static void _SeTrackDataExecute(RedTrackDATA* track, int frames) } if (track->m_volumeDelta != 0) { - if (frames < track->m_volumeDelta) { - step = frames; + if (track->m_volumeDelta > frames) { + volumeStep = frames; } else { - step = track->m_volumeDelta; + volumeStep = track->m_volumeDelta; } - track->m_volumeDelta -= step; - track->m_volume += track->m_volumeAdd * step; + track->m_volumeDelta -= volumeStep; + track->m_volume += track->m_volumeAdd * volumeStep; voice->m_updateFlags |= REDSOUND_VOICE_UPDATE_VOLUME; } if (track->m_expressionDelta != 0) { - if (frames < track->m_expressionDelta) { - step = frames; + if (track->m_expressionDelta > frames) { + expressionStep = frames; } else { - step = track->m_expressionDelta; + expressionStep = track->m_expressionDelta; } - track->m_expressionDelta -= step; - track->m_expression += track->m_expressionAdd * step; + track->m_expressionDelta -= expressionStep; + track->m_expression += track->m_expressionAdd * expressionStep; voice->m_updateFlags |= REDSOUND_VOICE_UPDATE_VOLUME; } if (track->m_panDelta != 0) { - if (frames < track->m_panDelta) { - step = frames; + if (track->m_panDelta > frames) { + panStep = frames; } else { - step = track->m_panDelta; + panStep = track->m_panDelta; } - track->m_panDelta -= step; - track->m_pan += track->m_panAdd * step; + track->m_panDelta -= panStep; + track->m_pan += track->m_panAdd * panStep; voice->m_updateFlags |= REDSOUND_VOICE_UPDATE_VOLUME; } if (track->m_reverbDepthDelta != 0) { - if (frames < track->m_reverbDepthDelta) { - step = frames; + if (track->m_reverbDepthDelta > frames) { + reverbStep = frames; } else { - step = track->m_reverbDepthDelta; + reverbStep = track->m_reverbDepthDelta; } - track->m_reverbDepthDelta -= step; - track->m_reverbDepth += track->m_reverbDepthAdd * step; + track->m_reverbDepthDelta -= reverbStep; + track->m_reverbDepth += track->m_reverbDepthAdd * reverbStep; voice->m_updateFlags |= REDSOUND_VOICE_UPDATE_VOLUME; } if (track->m_mixVolumeDelta != 0) { - if (frames < track->m_mixVolumeDelta) { - step = frames; + if (track->m_mixVolumeDelta > frames) { + mixStep = frames; } else { - step = track->m_mixVolumeDelta; + mixStep = track->m_mixVolumeDelta; } - track->m_mixVolumeDelta -= step; - if ((track->m_mixVolumeDelta == 0) && (track->m_mixVolumeMode == 1)) { + track->m_mixVolumeDelta -= mixStep; + if ((track->m_mixVolumeDelta == 0) && (track->m_mixVolumeMode == REDSOUND_SE_VOLUME_MODE_FADE_OUT)) { track->m_command = (u8*)m_TerminateNote; track->m_deltaTime = 1; } - track->m_mixVolume += track->m_mixVolumeAdd * step; + track->m_mixVolume += track->m_mixVolumeAdd * mixStep; voice->m_updateFlags |= REDSOUND_VOICE_UPDATE_VOLUME; } if (track->m_pitchDelta != 0) { - if (frames < track->m_pitchDelta) { - step = frames; + if (track->m_pitchDelta > frames) { + pitchStep = frames; } else { - step = track->m_pitchDelta; + pitchStep = track->m_pitchDelta; } - track->m_pitchDelta -= step; - track->m_pitch += track->m_pitchAdd * step; + track->m_pitchDelta -= pitchStep; + track->m_pitch += track->m_pitchAdd * pitchStep; voice->m_updateFlags |= REDSOUND_VOICE_UPDATE_PITCH; } if (track->m_sweepDelta != 0) { - if (frames < track->m_sweepDelta) { - step = frames; + if (track->m_sweepDelta > frames) { + sweepStep = frames; } else { - step = track->m_sweepDelta; + sweepStep = track->m_sweepDelta; } - track->m_sweepDelta -= step; - track->m_portamentPitch += step * track->m_sweepAdd; + track->m_sweepDelta -= sweepStep; + track->m_portamentPitch += sweepStep * track->m_sweepAdd; voice->m_updateFlags |= REDSOUND_VOICE_UPDATE_PITCH; - voice->m_basePitch += step * track->m_sweepAdd; + voice->m_basePitch += sweepStep * track->m_sweepAdd; } if (((voice->m_updateFlags & REDSOUND_VOICE_UPDATE_PITCH) != 0) && (voice->m_waveData != 0)) { @@ -2576,83 +2923,83 @@ static void _SeTrackDataExecute(RedTrackDATA* track, int frames) if (track->m_vibrateFunc != 0) { if (track->m_vibrateRateDelta != 0) { - if (frames < track->m_vibrateRateDelta) { - step = frames; + if (track->m_vibrateRateDelta > frames) { + vibrateRateStep = frames; } else { - step = track->m_vibrateRateDelta; + vibrateRateStep = track->m_vibrateRateDelta; } - track->m_vibrateRateDelta = track->m_vibrateRateDelta - (short)step; - track->m_vibrateRate += track->m_vibrateRateAdd * step; + track->m_vibrateRateDelta = track->m_vibrateRateDelta - (short)vibrateRateStep; + track->m_vibrateRate += track->m_vibrateRateAdd * vibrateRateStep; } if (track->m_vibrateDepthDelta != 0) { - if (frames < track->m_vibrateDepthDelta) { - step = frames; + if (track->m_vibrateDepthDelta > frames) { + vibrateDepthStep = frames; } else { - step = track->m_vibrateDepthDelta; + vibrateDepthStep = track->m_vibrateDepthDelta; } - track->m_vibrateDepthDelta = track->m_vibrateDepthDelta - (short)step; - track->m_vibrateDepth += track->m_vibrateDepthAdd * step; + track->m_vibrateDepthDelta = track->m_vibrateDepthDelta - (short)vibrateDepthStep; + track->m_vibrateDepth += track->m_vibrateDepthAdd * vibrateDepthStep; } } if (track->m_tremoloFunc != 0) { if (track->m_tremoloRateDelta != 0) { - if (frames < track->m_tremoloRateDelta) { - step = frames; + if (track->m_tremoloRateDelta > frames) { + tremoloRateStep = frames; } else { - step = track->m_tremoloRateDelta; + tremoloRateStep = track->m_tremoloRateDelta; } - track->m_tremoloRateDelta = track->m_tremoloRateDelta - (short)step; - track->m_tremoloRate += track->m_tremoloRateAdd * step; + track->m_tremoloRateDelta = track->m_tremoloRateDelta - (short)tremoloRateStep; + track->m_tremoloRate += track->m_tremoloRateAdd * tremoloRateStep; } if (track->m_tremoloDepthDelta != 0) { - if (frames < track->m_tremoloDepthDelta) { - step = frames; + if (track->m_tremoloDepthDelta > frames) { + tremoloDepthStep = frames; } else { - step = track->m_tremoloDepthDelta; + tremoloDepthStep = track->m_tremoloDepthDelta; } - track->m_tremoloDepthDelta = track->m_tremoloDepthDelta - (short)step; - track->m_tremoloDepth += track->m_tremoloDepthAdd * step; + track->m_tremoloDepthDelta = track->m_tremoloDepthDelta - (short)tremoloDepthStep; + track->m_tremoloDepth += track->m_tremoloDepthAdd * tremoloDepthStep; } } if (track->m_shakeFunc != 0) { if (track->m_shakeRateDelta != 0) { - if (frames < track->m_shakeRateDelta) { - step = frames; + if (track->m_shakeRateDelta > frames) { + shakeRateStep = frames; } else { - step = track->m_shakeRateDelta; + shakeRateStep = track->m_shakeRateDelta; } - track->m_shakeRateDelta = track->m_shakeRateDelta - (short)step; - track->m_shakeRate += track->m_shakeRateAdd * step; + track->m_shakeRateDelta = track->m_shakeRateDelta - (short)shakeRateStep; + track->m_shakeRate += track->m_shakeRateAdd * shakeRateStep; } if (track->m_shakeDepthDelta != 0) { - if (frames < track->m_shakeDepthDelta) { - step = frames; + if (track->m_shakeDepthDelta > frames) { + shakeDepthStep = frames; } else { - step = track->m_shakeDepthDelta; + shakeDepthStep = track->m_shakeDepthDelta; } - track->m_shakeDepthDelta = track->m_shakeDepthDelta - (short)step; - track->m_shakeDepth += track->m_shakeDepthAdd * step; + track->m_shakeDepthDelta = track->m_shakeDepthDelta - (short)shakeDepthStep; + track->m_shakeDepth += track->m_shakeDepthAdd * shakeDepthStep; } } if (voice->m_pitchModDelay != 0) { - if (frames < voice->m_pitchModDelay) { - step = frames; + if (voice->m_pitchModDelay > frames) { + pitchModDelayStep = frames; } else { - step = voice->m_pitchModDelay; + pitchModDelayStep = voice->m_pitchModDelay; } - voice->m_pitchModDelay = voice->m_pitchModDelay - (short)step; + voice->m_pitchModDelay = voice->m_pitchModDelay - (short)pitchModDelayStep; } if (voice->m_volumeModDelay != 0) { - if (frames < voice->m_volumeModDelay) { - step = frames; + if (voice->m_volumeModDelay > frames) { + volumeModDelayStep = frames; } else { - step = voice->m_volumeModDelay; + volumeModDelayStep = voice->m_volumeModDelay; } - voice->m_volumeModDelay = voice->m_volumeModDelay - (short)step; + voice->m_volumeModDelay = voice->m_volumeModDelay - (short)volumeModDelayStep; } } @@ -2666,20 +3013,22 @@ static void _SeTrackDataExecute(RedTrackDATA* track, int frames) * JP Size: TODO */ static int _SeMidiNoteExecute( - RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* trackData, int frames, int tickStep) + RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track, int frames, int tickStep) { - RedTrackDATA* track = trackData; do { if ((track->m_command != 0) && ((track->m_voiceSwitch & REDSOUND_VOICE_SWITCH_PAUSE) == 0)) { track->m_seTickCounter -= tickStep * REDSOUND_SE_TICK_STEP; while (track->m_seTickCounter < 1) { - int step = frames; + int step; track->m_seTickCounter += REDSOUND_CONTROL_TICK_PERIOD; if (track->m_deltaTime < frames) { step = track->m_deltaTime; + } else { + step = frames; } + int execStep = step; track->m_deltaTime -= frames; - _SeTrackDataExecute(track, step); + _SeTrackDataExecute(track, execStep); if (((track->m_flags & REDSOUND_TRACK_FLAG_TENUTO) == 0) && (track->m_deltaTime == 1)) { KeyOffSet(control, keyOnData, track); } @@ -2691,7 +3040,8 @@ static int _SeMidiNoteExecute( track->m_loopStepCurrent += 1; cmd = track->m_command; track->m_command = cmd + 1; - p_MidiControl_Function[*cmd](control, keyOnData, track); + RedMidiControlFunc func = p_MidiControl_Function[*cmd]; + func(control, keyOnData, track); if (track->m_command != 0) { delta = DeltaTimeSumup((unsigned char**)&track->m_command); if (delta != 0) { @@ -2699,8 +3049,9 @@ static int _SeMidiNoteExecute( if (delta < 1) { delta = 1; } else if ((track->m_voiceSwitch & REDSOUND_VOICE_SWITCH_FUZZY_DELTA_TIME) != 0) { - delta += ((delta * track->m_fuzzyDeltaTimeDepth >> 8) * (int)GetRandomData()) >> - 7; + int fuzzyDelta = delta * track->m_fuzzyDeltaTimeDepth >> 8; + s8 random = (s8)GetRandomData(); + delta += fuzzyDelta * random >> 7; if (delta < 1) { delta = 1; } @@ -2709,7 +3060,7 @@ static int _SeMidiNoteExecute( if (track->m_deltaTime < -1) { int execStep = delta; - if (track->m_deltaTime + delta > 0) { + if (track->m_deltaTime + execStep > 0) { execStep = -track->m_deltaTime; } _SeTrackDataExecute(track, execStep); @@ -2725,8 +3076,8 @@ static int _SeMidiNoteExecute( } track++; } while (track < control->m_tracks + REDSOUND_SE_TRACK_COUNT); - control->m_updateFlags = 1; - return control->m_tickCounter; + control->m_skipFrames = 1; + return control->m_activeTrackCount; } /* @@ -2759,10 +3110,10 @@ void MainControl(int frames) if (mul != 0) { if (p_MusicTempoControl->m_value < 0) { step *= (int)mul; - step >>= 0x10; + step >>= REDSOUND_TEMPO_SCALE_SHIFT; } else { step *= (int)mul + 1; - step >>= 0xF; + step >>= REDSOUND_TEMPO_SCALE_POSITIVE_SHIFT; step += p_SoundControl->m_tempo >> REDSOUND_FIXED_SHIFT; } } @@ -2786,7 +3137,7 @@ void MainControl(int frames) memcpy(p_SoundControlBuffer, p_SoundControlBuffer + REDSOUND_CONTROL_MUSIC_SECONDARY, REDSOUND_CONTROL_SIZE); p_SoundControl->m_activeTrackCount = 0; p_SoundControl->m_trackCount = 0; - p_SoundControl->m_musicId = -1; + p_SoundControl->m_musicId = REDSOUND_MUSIC_ID_NONE; } p_SoundControl = p_SoundControlBuffer; } diff --git a/src/RedSound/RedMemory.cpp b/src/RedSound/RedMemory.cpp index 5f5203b00e..62805b077b 100644 --- a/src/RedSound/RedMemory.cpp +++ b/src/RedSound/RedMemory.cpp @@ -1,9 +1,24 @@ #include "ffcc/RedSound/RedMemory.h" #include "ffcc/RedSound/RedGlobals.h" +#include "global.h" #include "PowerPC_EABI_Support/Msl/MSL_C/MSL_Common/file_io.h" #include "PowerPC_EABI_Support/Msl/MSL_C/MSL_Common/string.h" #include +STATIC_ASSERT(offsetof(RedMemoryBlock, m_address) == REDSOUND_MEMORY_BLOCK_ADDRESS_OFFSET); +STATIC_ASSERT(offsetof(RedMemoryBlock, m_size) == REDSOUND_MEMORY_BLOCK_SIZE_OFFSET); +STATIC_ASSERT(sizeof(RedMemoryBlock) == REDSOUND_MEMORY_BLOCK_SIZE); +STATIC_ASSERT(REDSOUND_MEMORY_BLOCK_SIZE == (1 << REDSOUND_MEMORY_BLOCK_INDEX_SHIFT)); +STATIC_ASSERT(REDSOUND_MEMORY_BANK_SIZE == REDSOUND_MEMORY_BANK_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_MEMORY_BANK_SIZE == REDSOUND_MEMORY_BLOCK_SIZE * REDSOUND_MEMORY_BANK_BLOCK_COUNT); +STATIC_ASSERT(REDSOUND_MEMORY_AUX_BANK_OFFSET == REDSOUND_MEMORY_BANK_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_MEMORY_AUX_BANK_OFFSET == REDSOUND_MEMORY_MAIN_BANK_OFFSET + REDSOUND_MEMORY_BANK_SIZE); +STATIC_ASSERT(REDSOUND_MEMORY_BANK_TABLE_SIZE == REDSOUND_MEMORY_BANK_TABLE_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_MEMORY_BANK_TABLE_SIZE == REDSOUND_MEMORY_BANK_SIZE * REDSOUND_MEMORY_BANK_TABLE_COUNT); +STATIC_ASSERT(REDSOUND_MEMORY_DATA_BUFFER_OFFSET == REDSOUND_MEMORY_BANK_TABLE_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_MEMORY_AUX_BANK_OFFSET + REDSOUND_MEMORY_BANK_SIZE == REDSOUND_MEMORY_DATA_BUFFER_OFFSET); +STATIC_ASSERT(REDSOUND_MEMORY_DATA_BUFFER_OFFSET == REDSOUND_MEMORY_BANK_TABLE_SIZE); + static int m_DataBuffer; static int m_ADataBuffer; static int m_DataBufferSize; @@ -18,6 +33,56 @@ const char s_redMemoryAuxBankFullFmt[] = "%s%sA-Memory Bank Full !!%s\n"; const char sRedMemoryLogSuffixA[] = "\x1b[7;31m"; const char sRedMemoryLogSuffixB[] = "\x1b[0m"; +enum RedMemoryStringLayout { + REDSOUND_MEMORY_MAIN_BANK_FULL_FMT_SIZE = 0x1b, + REDSOUND_MEMORY_LOG_PREFIX_SIZE = 0x12, + REDSOUND_MEMORY_AUX_BANK_FULL_FMT_SIZE = 0x1d, + REDSOUND_MEMORY_LOG_SUFFIX_A_SIZE = 0x08, + REDSOUND_MEMORY_LOG_SUFFIX_B_SIZE = 0x05, + REDSOUND_MEMORY_RODATA_STRING_SIZE = 0x4a, + REDSOUND_MEMORY_SDATA2_STRING_SIZE = 0x0d, +}; + +enum RedMemorySmallDataLayout { + REDSOUND_MEMORY_SBSS_DATA_BUFFER_OFFSET = 0x00, + REDSOUND_MEMORY_SBSS_AUX_DATA_BUFFER_OFFSET = 0x04, + REDSOUND_MEMORY_SBSS_DATA_BUFFER_SIZE_OFFSET = 0x08, + REDSOUND_MEMORY_SBSS_AUX_DATA_BUFFER_SIZE_OFFSET = 0x0C, + REDSOUND_MEMORY_SBSS_BANK_TABLE_OFFSET = 0x10, + REDSOUND_MEMORY_SBSS_AUX_BANK_TABLE_OFFSET = 0x14, + REDSOUND_MEMORY_SBSS_SIZE = 0x18, +}; + +struct RedMemorySmallDataState { + int m_dataBuffer; + int m_auxDataBuffer; + int m_dataBufferSize; + int m_auxDataBufferSize; + RedMemoryBlock* m_memoryBank; + RedMemoryBlock* m_auxMemoryBank; +}; + +STATIC_ASSERT(sizeof(s_redMemoryMainBankFullFmt) == REDSOUND_MEMORY_MAIN_BANK_FULL_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedMemoryLogPrefix) == REDSOUND_MEMORY_LOG_PREFIX_SIZE); +STATIC_ASSERT(sizeof(s_redMemoryAuxBankFullFmt) == REDSOUND_MEMORY_AUX_BANK_FULL_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedMemoryLogSuffixA) == REDSOUND_MEMORY_LOG_SUFFIX_A_SIZE); +STATIC_ASSERT(sizeof(sRedMemoryLogSuffixB) == REDSOUND_MEMORY_LOG_SUFFIX_B_SIZE); +STATIC_ASSERT(sizeof(s_redMemoryMainBankFullFmt) + sizeof(sRedMemoryLogPrefix) + + sizeof(s_redMemoryAuxBankFullFmt) == + REDSOUND_MEMORY_RODATA_STRING_SIZE); +STATIC_ASSERT(sizeof(sRedMemoryLogSuffixA) + sizeof(sRedMemoryLogSuffixB) == REDSOUND_MEMORY_SDATA2_STRING_SIZE); +STATIC_ASSERT(offsetof(RedMemorySmallDataState, m_dataBuffer) == REDSOUND_MEMORY_SBSS_DATA_BUFFER_OFFSET); +STATIC_ASSERT(offsetof(RedMemorySmallDataState, m_auxDataBuffer) == REDSOUND_MEMORY_SBSS_AUX_DATA_BUFFER_OFFSET); +STATIC_ASSERT(offsetof(RedMemorySmallDataState, m_dataBufferSize) == REDSOUND_MEMORY_SBSS_DATA_BUFFER_SIZE_OFFSET); +STATIC_ASSERT(offsetof(RedMemorySmallDataState, m_auxDataBufferSize) == + REDSOUND_MEMORY_SBSS_AUX_DATA_BUFFER_SIZE_OFFSET); +STATIC_ASSERT(offsetof(RedMemorySmallDataState, m_memoryBank) == REDSOUND_MEMORY_SBSS_BANK_TABLE_OFFSET); +STATIC_ASSERT(offsetof(RedMemorySmallDataState, m_auxMemoryBank) == REDSOUND_MEMORY_SBSS_AUX_BANK_TABLE_OFFSET); +STATIC_ASSERT(sizeof(RedMemorySmallDataState) == REDSOUND_MEMORY_SBSS_SIZE); +STATIC_ASSERT(sizeof(m_DataBuffer) + sizeof(m_ADataBuffer) + sizeof(m_DataBufferSize) + sizeof(m_ADataBufferSize) + + sizeof(m_MemoryBank) + sizeof(m_AMemoryBank) == + REDSOUND_MEMORY_SBSS_SIZE); + /* * --INFO-- * PAL Address: 0x801bff34 @@ -74,7 +139,7 @@ int RedNew(int size) do { if ((slot->m_size == 0) || ((address + size) <= slot->m_address)) { if (m_MemoryBank[REDSOUND_MEMORY_BANK_LAST_INDEX].m_size > 0) { - if (m_ReportPrint != 0) { + if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { OSReport(s_redMemoryMainBankFullFmt, sRedMemoryLogPrefix, sRedMemoryLogSuffixA, sRedMemoryLogSuffixB); fflush(__files + 1); @@ -182,7 +247,7 @@ int RedNewA(int size, int offset, int maxSize) return 0; } if (m_AMemoryBank[REDSOUND_MEMORY_BANK_LAST_INDEX].m_size > 0) { - if (m_ReportPrint != 0) { + if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { OSReport(s_redMemoryAuxBankFullFmt, sRedMemoryLogPrefix, sRedMemoryLogSuffixA, sRedMemoryLogSuffixB); fflush(__files + 1); } @@ -195,7 +260,8 @@ int RedNewA(int size, int offset, int maxSize) maxSize = m_ADataBufferSize; } maxSize -= offset; - size = (size + REDSOUND_MEMORY_BANK_ALIGN_MASK) & ~REDSOUND_MEMORY_BANK_ALIGN_MASK; + size += REDSOUND_MEMORY_BANK_ALIGN_MASK; + size &= ~REDSOUND_MEMORY_BANK_ALIGN_MASK; currentAddress = rangeStart; result = REDSOUND_MEMORY_ALLOC_FAILED; maxGap = maxSize; @@ -235,9 +301,9 @@ int RedNewA(int size, int offset, int maxSize) if ((bestBlock != 0) && ((u32)(result + size) <= (u32)(rangeStart + maxSize))) { if (bestBlock->m_size > 0) { - int moveCount = (m_AMemoryBank + REDSOUND_MEMORY_BANK_BLOCK_COUNT) - (bestBlock + 1); - if (moveCount > 0) { - memmove(bestBlock + 1, bestBlock, moveCount * REDSOUND_MEMORY_BLOCK_SIZE); + gap = (m_AMemoryBank + REDSOUND_MEMORY_BANK_BLOCK_COUNT) - (bestBlock + 1); + if (gap > 0) { + memmove(bestBlock + 1, bestBlock, gap * REDSOUND_MEMORY_BLOCK_SIZE); } } bestBlock->m_address = result; diff --git a/src/RedSound/RedMidiCtrl.cpp b/src/RedSound/RedMidiCtrl.cpp index ace7502aa7..1b2ab2672f 100644 --- a/src/RedSound/RedMidiCtrl.cpp +++ b/src/RedSound/RedMidiCtrl.cpp @@ -4,9 +4,268 @@ #include "ffcc/RedSound/RedDriver.h" #include "ffcc/RedSound/RedMemory.h" #include "ffcc/RedSound/RedGlobals.h" +#include "global.h" #include "PowerPC_EABI_Support/Msl/MSL_C/MSL_Common/string.h" -static int m_SignDataTable[] = { +enum RedMidiSignTableSize { + REDSOUND_SIGN_DATA_TABLE_COUNT = 0x200, +}; + +enum RedMidiDataTableSize { + REDSOUND_SIGN_DATA_TABLE_OFFSET = 0x00, + REDSOUND_SIGN_DATA_TABLE_SIZE = REDSOUND_SIGN_DATA_TABLE_COUNT * sizeof(int), + REDSOUND_SIGN_DATA_TABLE_ALLOC_SIZE = 0x800, + REDSOUND_SWING_FUNCTION_TABLE_OFFSET = + REDSOUND_SIGN_DATA_TABLE_OFFSET + REDSOUND_SIGN_DATA_TABLE_ALLOC_SIZE, + REDSOUND_SWING_FUNCTION_TABLE_SIZE = REDSOUND_SWING_FUNCTION_COUNT * sizeof(RedSwingFunc), + REDSOUND_SWING_FUNCTION_TABLE_ALLOC_SIZE = 0x40, + REDSOUND_MIDI_CONTROL_FUNCTION_TABLE_OFFSET = + REDSOUND_SWING_FUNCTION_TABLE_OFFSET + REDSOUND_SWING_FUNCTION_TABLE_ALLOC_SIZE, + REDSOUND_MIDI_CONTROL_FUNCTION_TABLE_SIZE = + REDSOUND_MIDI_CONTROL_FUNCTION_COUNT * sizeof(RedMidiControlFunc), + REDSOUND_MIDI_CONTROL_FUNCTION_TABLE_ALLOC_SIZE = 0x200, + REDSOUND_MIDI_CTRL_DATA_END_OFFSET = + REDSOUND_MIDI_CONTROL_FUNCTION_TABLE_OFFSET + REDSOUND_MIDI_CONTROL_FUNCTION_TABLE_ALLOC_SIZE, + REDSOUND_MIDI_CTRL_DATA_SIZE = 0xA40, +}; + +STATIC_ASSERT(offsetof(RedTrackDATA, m_command) == REDSOUND_TRACK_COMMAND_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_reserved04) == REDSOUND_TRACK_RESERVED04_BYTE); +STATIC_ASSERT(sizeof(((RedTrackDATA*)0)->m_reserved04) == REDSOUND_TRACK_RESERVED04_SIZE); +STATIC_ASSERT(REDSOUND_TRACK_RESERVED04_BYTE + REDSOUND_TRACK_RESERVED04_SIZE == + REDSOUND_TRACK_LOOP_COMMAND_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_loopCommand) == REDSOUND_TRACK_LOOP_COMMAND_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(sizeof(((RedTrackDATA*)0)->m_loopCommand) == + REDSOUND_TRACK_LOOP_STACK_COUNT * sizeof(unsigned char*)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_waveBankData) == REDSOUND_TRACK_WAVE_BANK_DATA_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_waveData) == REDSOUND_TRACK_WAVE_DATA_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_keySignatureData) == + REDSOUND_TRACK_KEY_SIGNATURE_DATA_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_note) == REDSOUND_TRACK_NOTE_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_volume) == REDSOUND_TRACK_VOLUME_OFFSET); +STATIC_ASSERT(offsetof(RedTrackDATA, m_volumeAdd) == REDSOUND_TRACK_VOLUME_ADD_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_volumeDelta) == REDSOUND_TRACK_VOLUME_DELTA_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_expression) == REDSOUND_TRACK_EXPRESSION_OFFSET); +STATIC_ASSERT(offsetof(RedTrackDATA, m_expressionAdd) == REDSOUND_TRACK_EXPRESSION_ADD_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_expressionDelta) == REDSOUND_TRACK_EXPRESSION_DELTA_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_pan) == REDSOUND_TRACK_PAN_OFFSET); +STATIC_ASSERT(offsetof(RedTrackDATA, m_panAdd) == REDSOUND_TRACK_PAN_ADD_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_panDelta) == REDSOUND_TRACK_PAN_DELTA_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_mixVolume) == REDSOUND_TRACK_MIX_VOLUME_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_mixVolumeAdd) == REDSOUND_TRACK_MIX_VOLUME_ADD_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_mixVolumeDelta) == REDSOUND_TRACK_MIX_VOLUME_DELTA_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_mixVolumeMode) == REDSOUND_TRACK_MIX_VOLUME_MODE_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_pitch) == REDSOUND_TRACK_PITCH_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_pitchAdd) == REDSOUND_TRACK_PITCH_ADD_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_pitchDelta) == REDSOUND_TRACK_PITCH_DELTA_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_reverbDepth) == REDSOUND_TRACK_REVERB_DEPTH_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_reverbDepthAdd) == REDSOUND_TRACK_REVERB_DEPTH_ADD_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_reverbDepthDelta) == REDSOUND_TRACK_REVERB_DEPTH_DELTA_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_vibrateFunc) == REDSOUND_TRACK_VIBRATE_FUNC_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_vibrateRate) == REDSOUND_TRACK_VIBRATE_RATE_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_vibrateRateAdd) == + REDSOUND_TRACK_VIBRATE_RATE_ADD_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_vibrateDepth) == REDSOUND_TRACK_VIBRATE_DEPTH_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_vibrateDepthAdd) == + REDSOUND_TRACK_VIBRATE_DEPTH_ADD_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_reserved88) == REDSOUND_TRACK_RESERVED88_BYTE); +STATIC_ASSERT(sizeof(((RedTrackDATA*)0)->m_reserved88) == REDSOUND_TRACK_RESERVED88_SIZE); +STATIC_ASSERT(REDSOUND_TRACK_RESERVED88_BYTE + REDSOUND_TRACK_RESERVED88_SIZE == + REDSOUND_TRACK_VIBRATE_RATE_DELTA_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_vibrateRateDelta) == + REDSOUND_TRACK_VIBRATE_RATE_DELTA_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_vibrateDepthDelta) == + REDSOUND_TRACK_VIBRATE_DEPTH_DELTA_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_vibrateDelay) == + REDSOUND_TRACK_VIBRATE_DELAY_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_vibrateDelayDepth) == + REDSOUND_TRACK_VIBRATE_DELAY_DEPTH_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_tremoloFunc) == REDSOUND_TRACK_TREMOLO_FUNC_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_tremoloRate) == REDSOUND_TRACK_TREMOLO_RATE_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_tremoloRateAdd) == + REDSOUND_TRACK_TREMOLO_RATE_ADD_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_tremoloDepth) == REDSOUND_TRACK_TREMOLO_DEPTH_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_tremoloDepthAdd) == + REDSOUND_TRACK_TREMOLO_DEPTH_ADD_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_reservedA8) == REDSOUND_TRACK_RESERVEDA8_BYTE); +STATIC_ASSERT(sizeof(((RedTrackDATA*)0)->m_reservedA8) == REDSOUND_TRACK_RESERVEDA8_SIZE); +STATIC_ASSERT(REDSOUND_TRACK_RESERVEDA8_BYTE + REDSOUND_TRACK_RESERVEDA8_SIZE == + REDSOUND_TRACK_TREMOLO_RATE_DELTA_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_tremoloRateDelta) == + REDSOUND_TRACK_TREMOLO_RATE_DELTA_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_tremoloDepthDelta) == + REDSOUND_TRACK_TREMOLO_DEPTH_DELTA_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_tremoloDelay) == + REDSOUND_TRACK_TREMOLO_DELAY_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_tremoloDelayDepth) == + REDSOUND_TRACK_TREMOLO_DELAY_DEPTH_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_shakeFunc) == REDSOUND_TRACK_SHAKE_FUNC_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_shakeRate) == REDSOUND_TRACK_SHAKE_RATE_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_shakeRateAdd) == REDSOUND_TRACK_SHAKE_RATE_ADD_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_shakeDepth) == REDSOUND_TRACK_SHAKE_DEPTH_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_shakeDepthAdd) == REDSOUND_TRACK_SHAKE_DEPTH_ADD_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_shakeOutput) == REDSOUND_TRACK_SHAKE_OUTPUT_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_shakePan) == REDSOUND_TRACK_SHAKE_PAN_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_shakeRateDelta) == + REDSOUND_TRACK_SHAKE_RATE_DELTA_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_shakeDepthDelta) == + REDSOUND_TRACK_SHAKE_DEPTH_DELTA_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_adsr) == REDSOUND_TRACK_ADSR_TIME_ATTACK_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(offsetof(RedAdsrDATA, m_time) == REDSOUND_ADSR_TIME_OFFSET); +STATIC_ASSERT(offsetof(RedAdsrDATA, m_level) == REDSOUND_ADSR_LEVEL_OFFSET); +STATIC_ASSERT(REDSOUND_ADSR_LEVEL_OFFSET == REDSOUND_TRACK_ADSR_LEVEL_ATTACK_OFFSET - + REDSOUND_TRACK_ADSR_TIME_ATTACK_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(sizeof(RedAdsrDATA) == REDSOUND_TRACK_ADSR_SIZE); +STATIC_ASSERT(offsetof(RedTrackDATA, m_fuzzyPitchDepth) == + REDSOUND_TRACK_FUZZY_PITCH_DEPTH_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_fuzzyVolumeDepth) == + REDSOUND_TRACK_FUZZY_VOLUME_DEPTH_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_fuzzyPanDepth) == + REDSOUND_TRACK_FUZZY_PAN_DEPTH_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_fuzzyDeltaTimeDepth) == + REDSOUND_TRACK_FUZZY_DELTA_TIME_DEPTH_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_fuzzyAdsrDepth) == + REDSOUND_TRACK_FUZZY_ADSR_DEPTH_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_seSepId) == REDSOUND_TRACK_SE_SEP_ID_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_seId) == REDSOUND_TRACK_SE_ID_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_voiceSwitch) == REDSOUND_TRACK_VOICE_SWITCH_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_loopReport) == REDSOUND_TRACK_LOOP_REPORT_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_flags) == REDSOUND_TRACK_FLAGS_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_deltaTime) == REDSOUND_TRACK_DELTA_TIME_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_playTime) == REDSOUND_TRACK_PLAY_TIME_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_sweepDelta) == REDSOUND_TRACK_SWEEP_DELTA_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_sweepAdd) == REDSOUND_TRACK_SWEEP_ADD_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_portamentTime) == REDSOUND_TRACK_PORTAMENT_TIME_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_waveBase) == REDSOUND_TRACK_WAVE_BASE_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_portamentPitch) == REDSOUND_TRACK_PORTAMENT_PITCH_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_waveNo) == REDSOUND_TRACK_WAVE_NO_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_loopCount) == REDSOUND_TRACK_LOOP_COUNT_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(sizeof(((RedTrackDATA*)0)->m_loopCount) == REDSOUND_TRACK_LOOP_STACK_COUNT * sizeof(short)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_loopStep) == REDSOUND_TRACK_LOOP_STEP_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(sizeof(((RedTrackDATA*)0)->m_loopStep) == REDSOUND_TRACK_LOOP_STACK_COUNT * sizeof(short)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_step) == REDSOUND_TRACK_STEP_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_step2) == REDSOUND_TRACK_STEP2_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_loopDepth) == REDSOUND_TRACK_LOOP_DEPTH_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_pitchBend) == REDSOUND_TRACK_PITCH_BEND_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_pitchBendRaw) == + REDSOUND_TRACK_PITCH_BEND_RAW_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_keyTranspose) == REDSOUND_TRACK_KEY_TRANSPOSE_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_loopStepCurrent) == + REDSOUND_TRACK_LOOP_STEP_CURRENT_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_seTickCounter) == + REDSOUND_TRACK_SE_TICK_COUNTER_HALFWORD * sizeof(unsigned short)); +STATIC_ASSERT(offsetof(RedTrackDATA, m_fineTune) == REDSOUND_TRACK_FINE_TUNE_BYTE); +STATIC_ASSERT(offsetof(RedTrackDATA, m_reserved149) == REDSOUND_TRACK_RESERVED149_BYTE); +STATIC_ASSERT(sizeof(((RedTrackDATA*)0)->m_reserved149) == REDSOUND_TRACK_RESERVED149_SIZE); +STATIC_ASSERT(REDSOUND_TRACK_RESERVED149_BYTE + REDSOUND_TRACK_RESERVED149_SIZE == + REDSOUND_TRACK_PITCH_BEND_RANGE_BYTE); +STATIC_ASSERT(offsetof(RedTrackDATA, m_pitchBendRange) == REDSOUND_TRACK_PITCH_BEND_RANGE_BYTE); +STATIC_ASSERT(offsetof(RedTrackDATA, m_reserved14C) == REDSOUND_TRACK_RESERVED14C_BYTE); +STATIC_ASSERT(sizeof(((RedTrackDATA*)0)->m_reserved14C) == REDSOUND_TRACK_RESERVED14C_SIZE); +STATIC_ASSERT(REDSOUND_TRACK_RESERVED14C_BYTE + REDSOUND_TRACK_RESERVED14C_SIZE == + REDSOUND_TRACK_WAVE_BANK_NO_BYTE); +STATIC_ASSERT(offsetof(RedTrackDATA, m_waveBankNo) == REDSOUND_TRACK_WAVE_BANK_NO_BYTE); +STATIC_ASSERT(offsetof(RedTrackDATA, m_trackNo) == REDSOUND_TRACK_TRACK_NO_BYTE); +STATIC_ASSERT(offsetof(RedTrackDATA, m_eraseTrack) == REDSOUND_TRACK_ERASE_TRACK_BYTE); +STATIC_ASSERT(offsetof(RedTrackDATA, m_attrMask) == REDSOUND_TRACK_ATTR_MASK_BYTE); +STATIC_ASSERT(offsetof(RedTrackDATA, m_reserved151) == REDSOUND_TRACK_RESERVED151_BYTE); +STATIC_ASSERT(sizeof(((RedTrackDATA*)0)->m_reserved151) == REDSOUND_TRACK_RESERVED151_SIZE); +STATIC_ASSERT(REDSOUND_TRACK_RESERVED151_BYTE + REDSOUND_TRACK_RESERVED151_SIZE == REDSOUND_TRACK_SIZE); +STATIC_ASSERT(sizeof(RedTrackDATA) == REDSOUND_TRACK_SIZE); +STATIC_ASSERT(offsetof(RedNoteDATA, m_key) == REDSOUND_NOTE_KEY_OFFSET); +STATIC_ASSERT(offsetof(RedNoteDATA, m_velocity) == REDSOUND_NOTE_VELOCITY_OFFSET); +STATIC_ASSERT(offsetof(RedNoteDATA, m_allocFlags) == REDSOUND_NOTE_ALLOC_FLAGS_OFFSET); +STATIC_ASSERT(offsetof(RedNoteDATA, m_reserved03) == REDSOUND_NOTE_RESERVED03_OFFSET); +STATIC_ASSERT(sizeof(((RedNoteDATA*)0)->m_reserved03) == REDSOUND_NOTE_RESERVED03_SIZE); +STATIC_ASSERT(sizeof(RedNoteDATA) == REDSOUND_NOTE_SIZE); +STATIC_ASSERT(offsetof(RedKeyOnSlot, m_track) == REDSOUND_KEY_ON_SLOT_TRACK_OFFSET); +STATIC_ASSERT(offsetof(RedKeyOnSlot, m_note) == REDSOUND_KEY_ON_SLOT_NOTE_OFFSET); +STATIC_ASSERT(sizeof(RedKeyOnSlot) == REDSOUND_KEY_ON_SLOT_SIZE); +STATIC_ASSERT(sizeof(((RedKeyOnDATA*)0)->m_fixed) == REDSOUND_KEY_ON_PRIORITY_BYTE_OFFSET); +STATIC_ASSERT(offsetof(RedKeyOnDATA, m_priority) == REDSOUND_KEY_ON_PRIORITY_BYTE_OFFSET); +STATIC_ASSERT(sizeof(((RedKeyOnDATA*)0)->m_priority) == + REDSOUND_KEY_ON_NORMAL_BYTE_OFFSET - REDSOUND_KEY_ON_PRIORITY_BYTE_OFFSET); +STATIC_ASSERT(offsetof(RedKeyOnDATA, m_normal) == REDSOUND_KEY_ON_NORMAL_BYTE_OFFSET); +STATIC_ASSERT(sizeof(((RedKeyOnDATA*)0)->m_normal) == REDSOUND_KEY_ON_END_BYTE_OFFSET - REDSOUND_KEY_ON_NORMAL_BYTE_OFFSET); +STATIC_ASSERT(sizeof(RedKeyOnDATA) == REDSOUND_KEY_ON_END_BYTE_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_tracks) == REDSOUND_CONTROL_TRACKS_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_reserved04) == REDSOUND_CONTROL_RESERVED04_OFFSET); +STATIC_ASSERT(sizeof(((RedSoundCONTROL*)0)->m_reserved04) == REDSOUND_CONTROL_RESERVED04_SIZE); +STATIC_ASSERT(REDSOUND_CONTROL_RESERVED04_OFFSET + REDSOUND_CONTROL_RESERVED04_SIZE == + REDSOUND_CONTROL_KEY_SIGNATURE_DATA_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_keySignatureData) == REDSOUND_CONTROL_KEY_SIGNATURE_DATA_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_measure) == REDSOUND_CONTROL_MEASURE_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_tick) == REDSOUND_CONTROL_TICK_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_ticksPerMeasure) == REDSOUND_CONTROL_TICKS_PER_MEASURE_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_timeNumerator) == REDSOUND_CONTROL_TIME_NUMERATOR_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_timeDenominator) == REDSOUND_CONTROL_TIME_DENOMINATOR_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_volume) == REDSOUND_CONTROL_VOLUME_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_savedTracks.m_command) == + REDSOUND_CONTROL_SAVED_COMMAND_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(sizeof(((RedSavedTrackDATA*)0)->m_command) == REDSOUND_MUSIC_TRACK_SAVE_COUNT * sizeof(unsigned char*)); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_savedTracks.m_delta) == + REDSOUND_CONTROL_SAVED_DELTA_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(sizeof(((RedSavedTrackDATA*)0)->m_delta) == REDSOUND_MUSIC_TRACK_SAVE_COUNT * sizeof(int)); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_savedTracks.m_flags) == + REDSOUND_CONTROL_SAVED_FLAGS_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(sizeof(((RedSavedTrackDATA*)0)->m_flags) == REDSOUND_MUSIC_TRACK_SAVE_COUNT * sizeof(unsigned int)); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_savedTracks.m_note) == + REDSOUND_CONTROL_SAVED_NOTE_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(sizeof(((RedSavedTrackDATA*)0)->m_note) == REDSOUND_MUSIC_TRACK_SAVE_COUNT * sizeof(RedNoteDATA)); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_savedTempo) == + REDSOUND_CONTROL_SAVED_TEMPO_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_savedTempo.m_tempoAdd) == + (REDSOUND_CONTROL_SAVED_TEMPO_WORD_OFFSET + 1) * sizeof(int)); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_savedTempo.m_tempoDelta) == + (REDSOUND_CONTROL_SAVED_TEMPO_WORD_OFFSET + 2) * sizeof(int)); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_savedActiveTrackCount) == + REDSOUND_CONTROL_SAVED_ACTIVE_TRACK_COUNT_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_savedPosition) == + REDSOUND_CONTROL_SAVED_MEASURE_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_savedPosition.m_tick) == + REDSOUND_CONTROL_SAVED_TICK_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_savedPosition.m_ticksPerMeasure) == + REDSOUND_CONTROL_SAVED_TICKS_PER_MEASURE_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_tempo) == REDSOUND_CONTROL_TEMPO_WORD_OFFSET * sizeof(int)); +STATIC_ASSERT(sizeof(RedSoundControlPosition) == REDSOUND_CONTROL_SAVED_POSITION_ALLOC_SIZE); +STATIC_ASSERT(sizeof(RedSoundControlTempo) == REDSOUND_CONTROL_SAVED_TEMPO_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_CONTROL_SAVED_TEMPO_SIZE == REDSOUND_CONTROL_SAVED_TEMPO_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_CONTROL_SAVED_POSITION_SIZE == REDSOUND_CONTROL_SAVED_POSITION_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_CONTROL_SAVED_TEMPO_WORD_OFFSET + REDSOUND_CONTROL_SAVED_TEMPO_WORD_COUNT == + REDSOUND_CONTROL_SAVED_ACTIVE_TRACK_COUNT_WORD_OFFSET); +STATIC_ASSERT(REDSOUND_CONTROL_SAVED_MEASURE_WORD_OFFSET + REDSOUND_CONTROL_SAVED_POSITION_WORD_COUNT == + REDSOUND_CONTROL_TEMPO_WORD_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_masterVolume) == REDSOUND_CONTROL_MASTER_VOLUME_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_masterVolumeAdd) == REDSOUND_CONTROL_MASTER_VOLUME_ADD_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_masterVolumeDelta) == REDSOUND_CONTROL_MASTER_VOLUME_DELTA_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_reserved460) == REDSOUND_CONTROL_RESERVED460_OFFSET); +STATIC_ASSERT(sizeof(((RedSoundCONTROL*)0)->m_reserved460) == REDSOUND_CONTROL_RESERVED460_SIZE); +STATIC_ASSERT(REDSOUND_CONTROL_RESERVED460_OFFSET + REDSOUND_CONTROL_RESERVED460_SIZE == + REDSOUND_CONTROL_FLAGS_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_flags) == REDSOUND_CONTROL_FLAGS_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_musicId) == REDSOUND_CONTROL_MUSIC_ID_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_skipFrames) == REDSOUND_CONTROL_SKIP_FRAMES_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_elapsedTime) == REDSOUND_CONTROL_ELAPSED_TIME_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_waveNo) == REDSOUND_CONTROL_WAVE_NO_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_keySignature) == REDSOUND_CONTROL_KEY_SIGNATURE_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_loopBase) == REDSOUND_CONTROL_LOOP_BASE_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_updateFlags) == REDSOUND_CONTROL_UPDATE_FLAGS_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_tickCounter) == REDSOUND_CONTROL_TICK_COUNTER_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_activeTrackCount) == REDSOUND_CONTROL_ACTIVE_TRACK_COUNT_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_channelAlloc) == REDSOUND_CONTROL_CHANNEL_ALLOC_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_trackCount) == REDSOUND_CONTROL_TRACK_COUNT_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_volumeScale) == REDSOUND_CONTROL_VOLUME_SCALE_OFFSET); +STATIC_ASSERT(offsetof(RedSoundCONTROL, m_reserved493) == REDSOUND_CONTROL_RESERVED493_OFFSET); +STATIC_ASSERT(sizeof(((RedSoundCONTROL*)0)->m_reserved493) == REDSOUND_CONTROL_RESERVED493_SIZE); +STATIC_ASSERT(REDSOUND_CONTROL_RESERVED493_OFFSET + REDSOUND_CONTROL_RESERVED493_SIZE == REDSOUND_CONTROL_SIZE); +STATIC_ASSERT(sizeof(RedSoundCONTROL) == REDSOUND_CONTROL_SIZE); +STATIC_ASSERT(REDSOUND_CONTROL_WORD_COUNT * sizeof(int) == REDSOUND_CONTROL_SIZE); +STATIC_ASSERT(REDSOUND_CONTROL_SECONDARY_TRACKS_WORD_OFFSET * sizeof(int) == REDSOUND_CONTROL_SECONDARY_OFFSET); +STATIC_ASSERT(REDSOUND_CONTROL_SECONDARY_END_WORD_OFFSET * sizeof(int) == REDSOUND_CONTROL_SKIP_OFFSET); +STATIC_ASSERT(REDSOUND_CONTROL_MUSIC_END_WORD_OFFSET * sizeof(int) == + REDSOUND_CONTROL_SIZE * (REDSOUND_CONTROL_MUSIC_SKIP + 1)); + +static int m_SignDataTable[REDSOUND_SIGN_DATA_TABLE_COUNT] = { 0, 402, 804, 1206, 1608, 2010, 2412, 2814, 3216, 3617, 4019, 4420, 4821, 5222, 5623, 6023, 6424, 6824, 7224, 7623, 8022, 8421, 8820, 9218, @@ -72,30 +331,39 @@ static int m_SignDataTable[] = { 6424, 6023, 5623, 5222, 4821, 4420, 4019, 3617, 3216, 2814, 2412, 2010, 1608, 1206, 804, 402, }; - -static int SineSwing(int); -static int TriangleSwing(int); -static int SawSwing(int); -static int DutySwing(int); -static int RandomSwing(int); -static int SineSwingR(int); -static int TriangleSwingR(int); -static int DutySwingR(int); -static int SawSwingR(int); -static int RandomSwingR(int); - -RedSwingFunc SwingEntryFunction[] = { +STATIC_ASSERT(sizeof(m_SignDataTable) == REDSOUND_SIGN_DATA_TABLE_SIZE); +STATIC_ASSERT(REDSOUND_SIGN_DATA_TABLE_OFFSET == 0); +STATIC_ASSERT(REDSOUND_SIGN_DATA_TABLE_SIZE == REDSOUND_SIGN_DATA_TABLE_ALLOC_SIZE); + +static int SineSwing(int phase); +static int TriangleSwing(int phase); +static int SawSwing(int phase); +static int DutySwing(int phase); +static int RandomSwing(int phase); +static int SineSwingR(int phase); +static int TriangleSwingR(int phase); +static int DutySwingR(int phase); +static int SawSwingR(int phase); +static int RandomSwingR(int phase); + +RedSwingFunc SwingEntryFunction[REDSOUND_SWING_FUNCTION_COUNT] = { SineSwing, TriangleSwing, SawSwing, DutySwing, RandomSwing, DutySwing, DutySwing, DutySwing, SineSwingR, TriangleSwingR, SawSwingR, DutySwingR, RandomSwingR, DutySwingR, DutySwingR, DutySwingR, }; +STATIC_ASSERT(sizeof(SwingEntryFunction) == REDSOUND_SWING_FUNCTION_TABLE_SIZE); +STATIC_ASSERT(REDSOUND_SWING_FUNCTION_TABLE_OFFSET == REDSOUND_SIGN_DATA_TABLE_OFFSET + + REDSOUND_SIGN_DATA_TABLE_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_SWING_FUNCTION_TABLE_SIZE == REDSOUND_SWING_FUNCTION_TABLE_ALLOC_SIZE); enum RedMidiSwingConst { - REDSOUND_SWING_SINE_MASK = 0x1FF, + REDSOUND_SWING_SINE_MASK = REDSOUND_SIGN_DATA_TABLE_COUNT - 1, REDSOUND_SWING_PHASE_SIGN = 0x200, + REDSOUND_SWING_SAW_PHASE_SHIFT = 2, REDSOUND_SWING_PHASE_SHIFT = 8, REDSOUND_SWING_PHASE_MASK = 0xFF, + REDSOUND_SWING_PHASE_INVERT_MASK = 0xffffffffU, REDSOUND_SWING_QUADRANT_MASK = 3, REDSOUND_SWING_LEVEL_FULL = 0x10000, REDSOUND_SWING_RANDOM_REVERSE_PHASE = 0x40, @@ -111,6 +379,7 @@ enum RedMidiCommandConst { REDSOUND_MIDI_FUZZY_DEFAULT_DEPTH = 0x100, REDSOUND_MIDI_PITCH_BEND_HIGH_SCALE = 0x80, REDSOUND_MIDI_PITCH_BEND_CENTER = 0x2000, + REDSOUND_MIDI_KEY_TRANSPOSE_SHIFT = 8, REDSOUND_MIDI_DELTA_BUFFER_WORD_COUNT = 4, REDSOUND_MIDI_SINGLE_DELTA_WORD_COUNT = 1, REDSOUND_MIDI_WAVE_BANK_DIRECT = 0x10, @@ -144,104 +413,97 @@ enum RedMidiTimeSignatureCommandByte { REDSOUND_MIDI_TIME_SIGNATURE_DENOMINATOR = 1, }; -enum RedSoundControlSaveWordOffset { - REDSOUND_CONTROL_SAVE_COMMAND_WORD = 0x0A, - REDSOUND_CONTROL_SAVE_DELTA_WORD = 0x4A, - REDSOUND_CONTROL_SAVE_FLAGS_WORD = 0x8A, - REDSOUND_CONTROL_SAVE_NOTE_WORD = 0xCA, -}; - -static void __MidiCtrl_NoSupport(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_Pass(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_Stop(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_Sleep(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_WholeLoopStart(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_WholeLoopEnd(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_LoopStart(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_LoopEnd(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_LoopRepeat(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_TempoDirect(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_TempoChange(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ReverbDepthDirect(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ReverbDepthChange(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_TimeSignature(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_KeySignature(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_PhraseSignature(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_KeyOnSame(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_KeyOnNoteVelocity(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_KeyOnNote(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_KeyOnVelocity(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_KeyOffSame(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_KeyOffNoteVelocity(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_KeyOffNote(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_KeyOffVelocity(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_Wave(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_WaveWithBank(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_VolumeDirect(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_VolumeChange(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ExpressionDirect(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ExpressionChange(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_PanDirect(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_PanChange(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_PortamentOn(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_PortamentOff(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_SlurOn(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_SlurOff(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_Sweep(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_TenutoOn(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_TenutoOff(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ADSR_Default(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ADSR_AL(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ADSR_AR(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ADSR_DL(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ADSR_DR(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ADSR_SL(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ADSR_SR(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ADSR_RL(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ADSR_RR(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_SustainPedal(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ChannelAlloc(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ChannelPriority(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ChannelFix(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_VibrateOn(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_VibrateOff(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_VibrateDepthDirect(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_VibrateDepthChange(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_VibrateRateDirect(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_VibrateRateChange(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_VibrateType(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_VibrateDelay(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_TremoloOn(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_TremoloOff(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_TremoloDepthDirect(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_TremoloDepthChange(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_TremoloRateDirect(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_TremoloRateChange(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_TremoloType(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_TremoloDelay(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ShakeOn(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ShakeOff(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ShakeDepthDirect(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ShakeDepthChange(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ShakeRateDirect(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ShakeRateChange(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ShakeType(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_FineTuneAbsolute(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_FineTuneRelative(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_KeyTransposeAbsolute(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_KeyTransposeRelative(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void _PitchBendCompute(RedTrackDATA*, int); -static void __MidiCtrl_PitchBend(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_PitchBendRange(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ReverbOn(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ReverbOff(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_ReverbMix(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_StepRelative(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_StepRelative2(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_FuzzyOn(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); -static void __MidiCtrl_FuzzyOff(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA*); - -RedMidiControlFunc p_MidiControl_Function[] = { +static void __MidiCtrl_NoSupport(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_Pass(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_Stop(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_Sleep(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_WholeLoopStart(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_WholeLoopEnd(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_LoopStart(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_LoopEnd(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_LoopRepeat(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_TempoDirect(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_TempoChange(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ReverbDepthDirect(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ReverbDepthChange(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_TimeSignature(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_KeySignature(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_PhraseSignature(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_KeyOnSame(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_KeyOnNoteVelocity(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_KeyOnNote(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_KeyOnVelocity(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_KeyOffSame(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_KeyOffNoteVelocity(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_KeyOffNote(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_KeyOffVelocity(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_Wave(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_WaveWithBank(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_VolumeDirect(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_VolumeChange(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ExpressionDirect(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ExpressionChange(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_PanDirect(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_PanChange(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_PortamentOn(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_PortamentOff(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_SlurOn(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_SlurOff(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_Sweep(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_TenutoOn(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_TenutoOff(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ADSR_Default(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ADSR_AL(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ADSR_AR(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ADSR_DL(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ADSR_DR(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ADSR_SL(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ADSR_SR(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ADSR_RL(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ADSR_RR(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_SustainPedal(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ChannelAlloc(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ChannelPriority(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ChannelFix(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_VibrateOn(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_VibrateOff(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_VibrateDepthDirect(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_VibrateDepthChange(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_VibrateRateDirect(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_VibrateRateChange(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_VibrateType(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_VibrateDelay(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_TremoloOn(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_TremoloOff(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_TremoloDepthDirect(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_TremoloDepthChange(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_TremoloRateDirect(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_TremoloRateChange(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_TremoloType(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_TremoloDelay(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ShakeOn(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ShakeOff(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ShakeDepthDirect(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ShakeDepthChange(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ShakeRateDirect(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ShakeRateChange(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ShakeType(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_FineTuneAbsolute(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_FineTuneRelative(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_KeyTransposeAbsolute(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_KeyTransposeRelative(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void _PitchBendCompute(RedTrackDATA* track, int pitchBend); +static void __MidiCtrl_PitchBend(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_PitchBendRange(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ReverbOn(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ReverbOff(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_ReverbMix(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_StepRelative(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_StepRelative2(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_FuzzyOn(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); +static void __MidiCtrl_FuzzyOff(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track); + +RedMidiControlFunc p_MidiControl_Function[REDSOUND_MIDI_CONTROL_FUNCTION_COUNT] = { __MidiCtrl_Stop, __MidiCtrl_Sleep, __MidiCtrl_WholeLoopStart, __MidiCtrl_WholeLoopEnd, __MidiCtrl_LoopStart, __MidiCtrl_LoopEnd, __MidiCtrl_LoopRepeat, __MidiCtrl_NoSupport, __MidiCtrl_TempoDirect, @@ -286,6 +548,13 @@ RedMidiControlFunc p_MidiControl_Function[] = { __MidiCtrl_NoSupport, __MidiCtrl_NoSupport, __MidiCtrl_NoSupport, __MidiCtrl_NoSupport, __MidiCtrl_Pass, }; +STATIC_ASSERT(sizeof(p_MidiControl_Function) == REDSOUND_MIDI_CONTROL_FUNCTION_TABLE_SIZE); +STATIC_ASSERT(REDSOUND_MIDI_CONTROL_FUNCTION_TABLE_OFFSET == + REDSOUND_SWING_FUNCTION_TABLE_OFFSET + REDSOUND_SWING_FUNCTION_TABLE_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_MIDI_CONTROL_FUNCTION_TABLE_SIZE == REDSOUND_MIDI_CONTROL_FUNCTION_TABLE_ALLOC_SIZE); +STATIC_ASSERT(REDSOUND_MIDI_CTRL_DATA_END_OFFSET == REDSOUND_MIDI_CTRL_DATA_SIZE); +STATIC_ASSERT(sizeof(m_SignDataTable) + sizeof(SwingEntryFunction) + sizeof(p_MidiControl_Function) == + REDSOUND_MIDI_CTRL_DATA_SIZE); /* * --INFO-- @@ -347,7 +616,7 @@ void KeyOnReserve(RedKeyOnDATA* keyOnData, RedTrackDATA* track) slot = &keyOnData->m_fixed[track->m_trackNo]; if ((slot->m_track == 0) || (slot->m_track == track)) { slot->m_track = track; - *(unsigned int*)&slot->m_note = *(unsigned int*)&track->m_note; + RedNoteCopy(&slot->m_note, &track->m_note); m_KeyOnEntry++; } return; @@ -358,7 +627,7 @@ void KeyOnReserve(RedKeyOnDATA* keyOnData, RedTrackDATA* track) do { if (slot->m_track == 0) { slot->m_track = track; - *(unsigned int*)&slot->m_note = *(unsigned int*)&track->m_note; + RedNoteCopy(&slot->m_note, &track->m_note); m_KeyOnEntry++; break; } @@ -369,7 +638,7 @@ void KeyOnReserve(RedKeyOnDATA* keyOnData, RedTrackDATA* track) do { if (slot->m_track == 0) { slot->m_track = track; - *(unsigned int*)&slot->m_note = *(unsigned int*)&track->m_note; + RedNoteCopy(&slot->m_note, &track->m_note); m_KeyOnEntry++; break; } @@ -395,7 +664,7 @@ void KeyOffSet(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* if ((control == p_SoundControlBuffer + REDSOUND_CONTROL_MUSIC_SKIP) || ((track->m_flags & REDSOUND_TRACK_FLAG_SLUR) == 0)) { track->m_sweepDelta = 0; - key = ((char*)track)[REDSOUND_TRACK_NOTE_KEY_OFFSET]; + key = *(char*)&track->m_note.m_key; slot = keyOnData->m_fixed; do { if ((slot->m_track == track) && (slot->m_note.m_key == key)) { @@ -404,7 +673,7 @@ void KeyOffSet(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* slot++; } while (slot < keyOnData->m_normal + REDSOUND_KEY_ON_SLOT_COUNT); - key = ((char*)track)[REDSOUND_TRACK_NOTE_KEY_OFFSET]; + key = *(char*)&track->m_note.m_key; voice = p_VoiceData; do { if ((voice->m_track == track) && (voice->m_key == key)) { @@ -475,7 +744,7 @@ static int TriangleSwing(int phase) */ static int SawSwing(int phase) { - int result = (int)(char)(phase >> 2) << REDSOUND_SWING_PHASE_SHIFT; + int result = (int)(char)(phase >> REDSOUND_SWING_SAW_PHASE_SHIFT) << REDSOUND_SWING_PHASE_SHIFT; return result; } @@ -608,7 +877,8 @@ static int DutySwingR(int phase) */ static int SawSwingR(int phase) { - int result = (int)(char)((int)((u32)phase ^ 0xffffffff) >> 2) << REDSOUND_SWING_PHASE_SHIFT; + int result = (int)(char)((int)((u32)phase ^ REDSOUND_SWING_PHASE_INVERT_MASK) >> REDSOUND_SWING_SAW_PHASE_SHIFT) + << REDSOUND_SWING_PHASE_SHIFT; return result; } @@ -688,7 +958,8 @@ static void __MidiCtrl_Stop(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, R if (control < p_SoundControlBuffer + REDSOUND_CONTROL_SE) { control->m_activeTrackCount--; if ((control->m_activeTrackCount == 0) && - ((m_MusicPhraseStop == 1) || ((control->m_flags & REDSOUND_CONTROL_FLAG_WHOLE_LOOP_ACTIVE) == 0))) { + ((m_MusicPhraseStop == REDSOUND_MUSIC_PHRASE_STOP_ON) || + ((control->m_flags & REDSOUND_CONTROL_FLAG_WHOLE_LOOP_ACTIVE) == 0))) { voice = p_VoiceData; do { if ((voice->m_track >= control->m_tracks) && @@ -701,19 +972,19 @@ static void __MidiCtrl_Stop(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, R voice++; } while (voice < p_VoiceData + REDSOUND_VOICE_COUNT); - c_RedEntry.MusicHistoryManager(0, control->m_musicId); - c_RedEntry.WaveHistoryManager(0, control->m_waveNo); - control->m_musicId = -1; + c_RedEntry.MusicHistoryManager(REDSOUND_HISTORY_MODE_RELEASE, control->m_musicId); + c_RedEntry.WaveHistoryManager(REDSOUND_HISTORY_MODE_RELEASE, control->m_waveNo); + control->m_musicId = REDSOUND_MUSIC_ID_NONE; control->m_updateFlags = 0; RedDelete((int)control->m_tracks); control->m_tracks = 0; } } else { if (track->m_waveBankData != 0) { - c_RedEntry.WaveHistoryManager(0, track->m_waveBankData->m_waveNo); + c_RedEntry.WaveHistoryManager(REDSOUND_HISTORY_MODE_RELEASE, track->m_waveBankData->m_waveNo); } - c_RedEntry.SeSepHistoryManager(0, track->m_seSepId); - track->m_seId = 0; + c_RedEntry.SeSepHistoryManager(REDSOUND_HISTORY_MODE_RELEASE, track->m_seSepId); + track->m_seId = REDSOUND_SE_ID_NONE; } } @@ -728,7 +999,7 @@ static void __MidiCtrl_Stop(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, R */ static void __MidiCtrl_Sleep(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA*) { - if ((m_MusicPhraseStop == 1) && (control == p_SoundControlBuffer)) { + if ((m_MusicPhraseStop == REDSOUND_MUSIC_PHRASE_STOP_ON) && (control == p_SoundControlBuffer)) { RedTrackDATA* track = control->m_tracks; do { if (track->m_command != 0) { @@ -750,8 +1021,8 @@ static void __MidiCtrl_Sleep(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, */ static void __MidiCtrl_WholeLoopStart(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA* track) { - int* controlWords = (int*)control; int loopBase = control->m_loopBase; + RedSavedTrackDATA* savedTrackData = &control->m_savedTracks; control->m_flags |= REDSOUND_CONTROL_FLAG_WHOLE_LOOP_ACTIVE; @@ -760,24 +1031,24 @@ static void __MidiCtrl_WholeLoopStart(RedSoundCONTROL* control, RedKeyOnDATA* ke RedTrackDATA* scan; for (scan = control->m_tracks; scan < track; scan++) { - controlWords[slot + REDSOUND_CONTROL_SAVE_COMMAND_WORD] = (int)scan->m_command; - controlWords[slot + REDSOUND_CONTROL_SAVE_DELTA_WORD] = scan->m_deltaTime + deltaAdjust; - controlWords[slot + REDSOUND_CONTROL_SAVE_FLAGS_WORD] = scan->m_flags; - controlWords[slot + REDSOUND_CONTROL_SAVE_NOTE_WORD] = *(int*)&scan->m_note; + savedTrackData->m_command[slot] = scan->m_command; + savedTrackData->m_delta[slot] = scan->m_deltaTime + deltaAdjust; + savedTrackData->m_flags[slot] = scan->m_flags; + RedNoteCopy(&savedTrackData->m_note[slot], &scan->m_note); slot++; } { unsigned char* command; - RedTrackDATA* nextTrack = scan + 1; command = scan->m_command; int delta = DeltaTimeSumup(&command); - controlWords[slot + REDSOUND_CONTROL_SAVE_COMMAND_WORD] = (int)command; - controlWords[slot + REDSOUND_CONTROL_SAVE_DELTA_WORD] = scan->m_deltaTime + delta + deltaAdjust; - controlWords[slot + REDSOUND_CONTROL_SAVE_FLAGS_WORD] = scan->m_flags; - controlWords[slot + REDSOUND_CONTROL_SAVE_NOTE_WORD] = *(int*)&scan->m_note; + savedTrackData->m_command[slot] = command; + savedTrackData->m_delta[slot] = scan->m_deltaTime + delta + deltaAdjust; + savedTrackData->m_flags[slot] = scan->m_flags; + RedNoteCopy(&savedTrackData->m_note[slot], &scan->m_note); + RedTrackDATA* nextTrack = scan + 1; if ((nextTrack - control->m_tracks) < control->m_trackCount) { for (; nextTrack < control->m_tracks + control->m_trackCount; nextTrack++) { int currentDelta = deltaAdjust + (nextTrack->m_deltaTime - loopBase); @@ -794,23 +1065,23 @@ static void __MidiCtrl_WholeLoopStart(RedSoundCONTROL* control, RedKeyOnDATA* ke } } - controlWords[slot + 1 + REDSOUND_CONTROL_SAVE_COMMAND_WORD] = (int)nextTrack->m_command; - controlWords[slot + 1 + REDSOUND_CONTROL_SAVE_DELTA_WORD] = currentDelta; - controlWords[slot + 1 + REDSOUND_CONTROL_SAVE_FLAGS_WORD] = nextTrack->m_flags; - controlWords[slot + 1 + REDSOUND_CONTROL_SAVE_NOTE_WORD] = *(int*)&nextTrack->m_note; + savedTrackData->m_command[slot + 1] = nextTrack->m_command; + savedTrackData->m_delta[slot + 1] = currentDelta; + savedTrackData->m_flags[slot + 1] = nextTrack->m_flags; + RedNoteCopy(&savedTrackData->m_note[slot + 1], &nextTrack->m_note); slot++; } } } control->m_savedActiveTrackCount = control->m_activeTrackCount; - memmove(&control->m_savedMeasure, + memmove(&control->m_savedPosition, &control->m_measure, REDSOUND_CONTROL_SAVED_POSITION_SIZE); - control->m_savedTick -= deltaAdjust; - if (control->m_savedTick < 0) { - control->m_savedTick += control->m_savedTicksPerMeasure; - control->m_savedMeasure--; + control->m_savedPosition.m_tick -= deltaAdjust; + if (control->m_savedPosition.m_tick < 0) { + control->m_savedPosition.m_tick += control->m_savedPosition.m_ticksPerMeasure; + control->m_savedPosition.m_measure--; } memmove(&control->m_savedTempo, &control->m_tempo, @@ -829,7 +1100,7 @@ static void __MidiCtrl_WholeLoopStart(RedSoundCONTROL* control, RedKeyOnDATA* ke static void __MidiCtrl_WholeLoopEnd(RedSoundCONTROL* control, RedKeyOnDATA* keyOnData, RedTrackDATA*) { control->m_flags |= REDSOUND_CONTROL_FLAG_WHOLE_LOOP_END; - if ((m_MusicPhraseStop == 1) && (control == p_SoundControlBuffer)) { + if ((m_MusicPhraseStop == REDSOUND_MUSIC_PHRASE_STOP_ON) && (control == p_SoundControlBuffer)) { RedTrackDATA* track = control->m_tracks; do { if (track->m_command != 0) { @@ -964,7 +1235,7 @@ static void __MidiCtrl_ReverbDepthDirect(RedSoundCONTROL*, RedKeyOnDATA*, RedTra reverbDepth->m_step = 0; reverbDepth->m_count = 0; - SetVoiceAccess(track, 8); + SetVoiceAccess(track, REDSOUND_VOICE_FLAGS_ADPCM_DIRTY); } /* @@ -1204,7 +1475,7 @@ static void __MidiCtrl_Wave(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA* track waveTable = track->m_waveBankData->m_waveOffsets; track->m_waveData = (RedWaveDATA*)((int)track->m_waveBankData + waveTable[waveNo]); track->m_waveBase = track->m_waveBankData->m_aramAddress; - memset(&track->m_adsrAR, REDSOUND_TRACK_ADSR_DEFAULT_WORD, REDSOUND_TRACK_ADSR_SIZE); + memset(&track->m_adsr, REDSOUND_TRACK_ADSR_DEFAULT_WORD, REDSOUND_TRACK_ADSR_SIZE); } track->m_waveBankNo = REDSOUND_MIDI_WAVE_BANK_DIRECT; track->m_waveNo = waveNo; @@ -1231,13 +1502,13 @@ static void __MidiCtrl_WaveWithBank(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDAT waveNo = *track->m_command++; track->m_waveData = 0; track->m_waveBase = 0; - waveBank = (RedHistoryBANK*)c_RedEntry.GetWaveBank(bankNo); + waveBank = c_RedEntry.GetWaveBank(bankNo); if (waveBank != 0) { - waveBankData = (RedWaveHeadWD*)waveBank->m_data; + waveBankData = waveBank->m_waveHead; waveTable = waveBankData->m_waveOffsets; track->m_waveData = (RedWaveDATA*)((int)waveBankData + waveTable[waveNo]); track->m_waveBase = waveBankData->m_aramAddress; - memset(&track->m_adsrAR, REDSOUND_TRACK_ADSR_DEFAULT_WORD, REDSOUND_TRACK_ADSR_SIZE); + memset(&track->m_adsr, REDSOUND_TRACK_ADSR_DEFAULT_WORD, REDSOUND_TRACK_ADSR_SIZE); } track->m_waveBankNo = bankNo; track->m_waveNo = waveNo; @@ -1419,7 +1690,7 @@ static void __MidiCtrl_PortamentOn(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA static void __MidiCtrl_PortamentOff(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA* track) { track->m_portamentTime = 0; - track->m_portamentPitch = -1; + track->m_portamentPitch = REDSOUND_TRACK_PORTAMENT_PITCH_NONE; } /* @@ -1529,14 +1800,14 @@ static void __MidiCtrl_ADSR_Default(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDAT { RedVoiceDATA* voice; - *(int*)&track->m_adsrAR = REDSOUND_TRACK_ADSR_DEFAULT_WORD; - *(int*)&track->m_adsrSR = REDSOUND_TRACK_ADSR_DEFAULT_WORD; - memset(&track->m_adsrAR, REDSOUND_TRACK_ADSR_DEFAULT_WORD, REDSOUND_TRACK_ADSR_SIZE); + *(int*)&track->m_adsr.m_time[REDSOUND_VOICE_ADSR_ATTACK] = REDSOUND_TRACK_ADSR_DEFAULT_WORD; + *(int*)&track->m_adsr.m_time[REDSOUND_VOICE_ADSR_SUSTAIN] = REDSOUND_TRACK_ADSR_DEFAULT_WORD; + memset(&track->m_adsr, REDSOUND_TRACK_ADSR_DEFAULT_WORD, REDSOUND_TRACK_ADSR_SIZE); voice = p_VoiceData; do { if ((voice->m_track == track) && (voice->m_waveData != 0)) { - memcpy(voice->m_adsrTime, voice->m_waveData->m_adsr, REDSOUND_TRACK_ADSR_SIZE); + memcpy(&voice->m_adsr, voice->m_waveData->m_adsr, REDSOUND_TRACK_ADSR_SIZE); voice->m_flags |= REDSOUND_VOICE_FLAGS_ADSR_DIRTY; } voice++; @@ -1558,12 +1829,12 @@ static void __MidiCtrl_ADSR_AL(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA* tr RedVoiceDATA* voice; value = *track->m_command++; - track->m_adsrAL = value; + track->m_adsr.m_level[REDSOUND_VOICE_ADSR_ATTACK] = value; voice = p_VoiceData; do { if (voice->m_track == track) { - voice->m_adsrLevel[REDSOUND_VOICE_ADSR_ATTACK] = value; + voice->m_adsr.m_level[REDSOUND_VOICE_ADSR_ATTACK] = value; voice->m_flags |= REDSOUND_VOICE_FLAGS_ADSR_DIRTY; } voice++; @@ -1585,12 +1856,12 @@ static void __MidiCtrl_ADSR_AR(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA* tr int delta; delta = DeltaTimeSumup((unsigned char**)&track->m_command); - track->m_adsrAR = delta; + track->m_adsr.m_time[REDSOUND_VOICE_ADSR_ATTACK] = delta; voice = p_VoiceData; do { if (voice->m_track == track) { - voice->m_adsrTime[REDSOUND_VOICE_ADSR_ATTACK] = delta; + voice->m_adsr.m_time[REDSOUND_VOICE_ADSR_ATTACK] = delta; voice->m_flags |= REDSOUND_VOICE_FLAGS_ADSR_DIRTY; } voice++; @@ -1612,12 +1883,12 @@ static void __MidiCtrl_ADSR_DL(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA* tr RedVoiceDATA* voice; value = *track->m_command++; - track->m_adsrDL = value; + track->m_adsr.m_level[REDSOUND_VOICE_ADSR_DECAY] = value; voice = p_VoiceData; do { if (voice->m_track == track) { - voice->m_adsrLevel[REDSOUND_VOICE_ADSR_DECAY] = value; + voice->m_adsr.m_level[REDSOUND_VOICE_ADSR_DECAY] = value; voice->m_flags |= REDSOUND_VOICE_FLAGS_ADSR_DIRTY; } voice++; @@ -1639,12 +1910,12 @@ static void __MidiCtrl_ADSR_DR(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA* tr int delta; delta = DeltaTimeSumup((unsigned char**)&track->m_command); - track->m_adsrDR = delta; + track->m_adsr.m_time[REDSOUND_VOICE_ADSR_DECAY] = delta; voice = p_VoiceData; do { if (voice->m_track == track) { - voice->m_adsrTime[REDSOUND_VOICE_ADSR_DECAY] = delta; + voice->m_adsr.m_time[REDSOUND_VOICE_ADSR_DECAY] = delta; voice->m_flags |= REDSOUND_VOICE_FLAGS_ADSR_DIRTY; } voice++; @@ -1666,12 +1937,12 @@ static void __MidiCtrl_ADSR_SL(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA* tr RedVoiceDATA* voice; value = *track->m_command++; - track->m_adsrSL = value; + track->m_adsr.m_level[REDSOUND_VOICE_ADSR_SUSTAIN] = value; voice = p_VoiceData; do { if (voice->m_track == track) { - voice->m_adsrLevel[REDSOUND_VOICE_ADSR_SUSTAIN] = value; + voice->m_adsr.m_level[REDSOUND_VOICE_ADSR_SUSTAIN] = value; voice->m_flags |= REDSOUND_VOICE_FLAGS_ADSR_DIRTY; } voice++; @@ -1693,12 +1964,12 @@ static void __MidiCtrl_ADSR_SR(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA* tr int delta; delta = DeltaTimeSumup((unsigned char**)&track->m_command); - track->m_adsrSR = delta; + track->m_adsr.m_time[REDSOUND_VOICE_ADSR_SUSTAIN] = delta; voice = p_VoiceData; do { if (voice->m_track == track) { - voice->m_adsrTime[REDSOUND_VOICE_ADSR_SUSTAIN] = delta; + voice->m_adsr.m_time[REDSOUND_VOICE_ADSR_SUSTAIN] = delta; voice->m_flags |= REDSOUND_VOICE_FLAGS_ADSR_DIRTY; } voice++; @@ -1720,12 +1991,12 @@ static void __MidiCtrl_ADSR_RL(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA* tr RedVoiceDATA* voice; value = *track->m_command++; - track->m_adsrRL = value; + track->m_adsr.m_level[REDSOUND_VOICE_ADSR_RELEASE] = value; voice = p_VoiceData; do { if (voice->m_track == track) { - voice->m_adsrLevel[REDSOUND_VOICE_ADSR_RELEASE] = value; + voice->m_adsr.m_level[REDSOUND_VOICE_ADSR_RELEASE] = value; voice->m_flags |= REDSOUND_VOICE_FLAGS_ADSR_DIRTY; } voice++; @@ -1747,12 +2018,12 @@ static void __MidiCtrl_ADSR_RR(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA* tr int delta; delta = DeltaTimeSumup((unsigned char**)&track->m_command); - track->m_adsrRR = delta; + track->m_adsr.m_time[REDSOUND_VOICE_ADSR_RELEASE] = delta; voice = p_VoiceData; do { if (voice->m_track == track) { - voice->m_adsrTime[REDSOUND_VOICE_ADSR_RELEASE] = delta; + voice->m_adsr.m_time[REDSOUND_VOICE_ADSR_RELEASE] = delta; voice->m_flags |= REDSOUND_VOICE_FLAGS_ADSR_DIRTY; } voice++; @@ -2421,7 +2692,7 @@ static void __MidiCtrl_FineTuneRelative(RedSoundCONTROL*, RedKeyOnDATA*, RedTrac */ static void __MidiCtrl_KeyTransposeAbsolute(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA* track) { - track->m_keyTranspose = (short)(*(s8*)track->m_command++ << 8); + track->m_keyTranspose = (short)(*(s8*)track->m_command++ << REDSOUND_MIDI_KEY_TRANSPOSE_SHIFT); m_ChangeStatus |= REDSOUND_VOICE_UPDATE_PITCH; } @@ -2436,7 +2707,7 @@ static void __MidiCtrl_KeyTransposeAbsolute(RedSoundCONTROL*, RedKeyOnDATA*, Red */ static void __MidiCtrl_KeyTransposeRelative(RedSoundCONTROL*, RedKeyOnDATA*, RedTrackDATA* track) { - track->m_keyTranspose += *(s8*)track->m_command++ << 8; + track->m_keyTranspose += *(s8*)track->m_command++ << REDSOUND_MIDI_KEY_TRANSPOSE_SHIFT; m_ChangeStatus |= REDSOUND_VOICE_UPDATE_PITCH; } diff --git a/src/RedSound/RedSound.cpp b/src/RedSound/RedSound.cpp index 66ff51fe5a..ea9104ad90 100644 --- a/src/RedSound/RedSound.cpp +++ b/src/RedSound/RedSound.cpp @@ -2,7 +2,9 @@ #include "ffcc/RedSound/RedDriver.h" #include "ffcc/RedSound/RedMemory.h" #include "ffcc/RedSound/RedEntry.h" +#include "ffcc/RedSound/RedStream.h" #include "ffcc/RedSound/RedGlobals.h" +#include "global.h" #include "PowerPC_EABI_Support/Runtime/NMWException.h" #include "PowerPC_EABI_Support/Msl/MSL_C/MSL_Common/file_io.h" @@ -14,22 +16,83 @@ #include "dolphin/axart.h" enum RedSoundLocalSize { + REDSOUND_SOUND_OBJECT_SIZE = 0x01, + REDSOUND_GLOBAL_INIT_WORK_SIZE = 0x0C, REDSOUND_STANDBY_STATUS_COUNT = 0x40, REDSOUND_STANDBY_STATUS_SIZE = REDSOUND_STANDBY_STATUS_COUNT * sizeof(int), + REDSOUND_STANDBY_STATUS_OFFSET = REDSOUND_GLOBAL_INIT_WORK_SIZE, + REDSOUND_STANDBY_STATUS_ALLOC_SIZE = 0x100, + REDSOUND_BSS_SIZE = 0x10C, REDSOUND_STREAM_BANK_SIZE = 0x100, + REDSOUND_STREAM_BANK_COUNT = 4, + REDSOUND_STREAM_BANK_ENTRY_SIZE = REDSOUND_STREAM_BANK_SIZE / REDSOUND_STREAM_BANK_COUNT, + REDSOUND_STREAM_BANK_ID_OFFSET = 0x00, + REDSOUND_STREAM_BANK_DATA_OFFSET = 0x04, + REDSOUND_STREAM_BANK_FILE_SIZE_OFFSET = 0x08, + REDSOUND_STREAM_BANK_READ_POINT_OFFSET = 0x0C, + REDSOUND_STREAM_BANK_PLAY_POINT_OFFSET = 0x10, + REDSOUND_STREAM_BANK_RESERVED14_OFFSET = 0x14, + REDSOUND_STREAM_BANK_RESERVED14_SIZE = 0x04, + REDSOUND_STREAM_BANK_RESERVED18_OFFSET = 0x18, + REDSOUND_STREAM_BANK_RESERVED18_SIZE = REDSOUND_STREAM_BANK_ENTRY_SIZE - REDSOUND_STREAM_BANK_RESERVED18_OFFSET, + REDSOUND_AUTO_ID_MASK = 0x7FFFFFFF, }; -enum RedSoundStreamSignature { - REDSOUND_STREAM_SIGNATURE_0 = 'S', - REDSOUND_STREAM_SIGNATURE_1 = 'T', - REDSOUND_STREAM_SIGNATURE_2 = 'R', +enum RedSoundStringLayout { + REDSOUND_MEMORY_SETTING_ERROR_SIZE = 0x33, + REDSOUND_LOG_PREFIX_SIZE = 0x12, + REDSOUND_AMEMORY_SETTING_ERROR_SIZE = 0x33, + REDSOUND_AR_NOT_INITIALIZED_SIZE = 0x1f, + REDSOUND_INIT_OK_SIZE = 0x23, + REDSOUND_INIT_ERROR_SIZE = 0x28, + REDSOUND_INVALID_STREAM_DATA_SIZE = 0x31, + REDSOUND_DATE_SIZE = 0x0c, + REDSOUND_TIME_SIZE = 0x09, + REDSOUND_LOG_ERROR_COLOR_SIZE = 0x08, + REDSOUND_LOG_RESET_SIZE = 0x05, + REDSOUND_LOG_INFO_COLOR_SIZE = 0x08, + REDSOUND_RODATA_STRING_SIZE = 0x128, + REDSOUND_SDATA2_STRING_SIZE = 0x15, +}; + +enum RedSoundSmallDataLayout { + REDSOUND_SOUND_SBSS_DRIVER_OFFSET = 0x00, + REDSOUND_DRIVER_OBJECT_SIZE = 0x01, + REDSOUND_AUTO_ID_SIZE = 0x04, + REDSOUND_SOUND_SBSS_AUTO_ID_OFFSET = 0x04, + REDSOUND_STREAM_BANK_PTR_SIZE = 0x04, + REDSOUND_SOUND_SBSS_STREAM_BANK_OFFSET = 0x08, + REDSOUND_SBSS_PADDING_SIZE = 0x03, + REDSOUND_SBSS_SIZE = 0x0c, +}; + +struct RedSoundBssState { + u8 m_globalInitWork[REDSOUND_GLOBAL_INIT_WORK_SIZE]; + int m_standbyStatus[REDSOUND_STANDBY_STATUS_COUNT]; +}; + +struct RedSoundStreamBank { + int m_streamId; + RedStreamFile* m_streamData; + int m_fileSize; + int m_readPoint; + int m_playPoint; + int m_reserved14; + u8 m_reserved18[REDSOUND_STREAM_BANK_RESERVED18_SIZE]; +}; + +struct RedSoundSmallDataState { + CRedDriver m_driver; + u8 m_driverPadding[REDSOUND_SBSS_PADDING_SIZE]; + volatile unsigned int m_autoId; + RedSoundStreamBank* m_streamBank; }; // RedSound global linkage that is shared across Red* units. CRedDriver c_Driver; static int m_StandbyStatus[REDSOUND_STANDBY_STATUS_COUNT]; volatile unsigned int m_AutoID; -static void* p_StreamBank; +static RedSoundStreamBank* p_StreamBank; static const char sRedSoundMemorySettingError[] = "%s%s Memory Setting Error !! (0x%8.8X:0x%8.8X)%s\n"; static const char sRedSoundLogPrefix[] = "\x1B[7;34mSound\x1B[0m:"; static const char sRedSoundAMemorySettingError[] = "%s%sA-Memory Setting Error !! (0x%8.8X:0x%8.8X)%s\n"; @@ -43,6 +106,109 @@ static const char sRedSoundLogErrorColor[] = "\x1B[7;31m"; static const char sRedSoundLogReset[] = "\x1B[0m"; static const char sRedSoundLogInfoColor[] = "\x1B[4;34m"; +STATIC_ASSERT(sizeof(m_StandbyStatus) == REDSOUND_STANDBY_STATUS_SIZE); +STATIC_ASSERT(sizeof(CRedSound) == REDSOUND_SOUND_OBJECT_SIZE); +STATIC_ASSERT(offsetof(RedSoundStreamBank, m_streamId) == REDSOUND_STREAM_BANK_ID_OFFSET); +STATIC_ASSERT(offsetof(RedSoundStreamBank, m_streamData) == REDSOUND_STREAM_BANK_DATA_OFFSET); +STATIC_ASSERT(offsetof(RedSoundStreamBank, m_fileSize) == REDSOUND_STREAM_BANK_FILE_SIZE_OFFSET); +STATIC_ASSERT(offsetof(RedSoundStreamBank, m_readPoint) == REDSOUND_STREAM_BANK_READ_POINT_OFFSET); +STATIC_ASSERT(offsetof(RedSoundStreamBank, m_playPoint) == REDSOUND_STREAM_BANK_PLAY_POINT_OFFSET); +STATIC_ASSERT(offsetof(RedSoundStreamBank, m_reserved14) == REDSOUND_STREAM_BANK_RESERVED14_OFFSET); +STATIC_ASSERT(sizeof(((RedSoundStreamBank*)0)->m_reserved14) == REDSOUND_STREAM_BANK_RESERVED14_SIZE); +STATIC_ASSERT(offsetof(RedSoundStreamBank, m_reserved18) == REDSOUND_STREAM_BANK_RESERVED18_OFFSET); +STATIC_ASSERT(sizeof(((RedSoundStreamBank*)0)->m_reserved18) == REDSOUND_STREAM_BANK_RESERVED18_SIZE); +STATIC_ASSERT(REDSOUND_STREAM_BANK_RESERVED18_OFFSET + REDSOUND_STREAM_BANK_RESERVED18_SIZE == + REDSOUND_STREAM_BANK_ENTRY_SIZE); +STATIC_ASSERT(sizeof(RedSoundStreamBank) == REDSOUND_STREAM_BANK_ENTRY_SIZE); +STATIC_ASSERT(REDSOUND_STREAM_BANK_ENTRY_SIZE * REDSOUND_STREAM_BANK_COUNT == REDSOUND_STREAM_BANK_SIZE); +STATIC_ASSERT(offsetof(RedSoundBssState, m_globalInitWork) == 0); +STATIC_ASSERT(offsetof(RedSoundBssState, m_standbyStatus) == REDSOUND_STANDBY_STATUS_OFFSET); +STATIC_ASSERT(sizeof(RedSoundBssState) == REDSOUND_BSS_SIZE); +STATIC_ASSERT(REDSOUND_GLOBAL_INIT_WORK_SIZE + REDSOUND_STANDBY_STATUS_SIZE == REDSOUND_BSS_SIZE); +STATIC_ASSERT(REDSOUND_STANDBY_STATUS_SIZE == REDSOUND_STANDBY_STATUS_ALLOC_SIZE); +STATIC_ASSERT(sizeof(c_Driver) == REDSOUND_DRIVER_OBJECT_SIZE); +STATIC_ASSERT(sizeof(m_AutoID) == REDSOUND_AUTO_ID_SIZE); +STATIC_ASSERT(sizeof(p_StreamBank) == REDSOUND_STREAM_BANK_PTR_SIZE); +STATIC_ASSERT(offsetof(RedSoundSmallDataState, m_driver) == REDSOUND_SOUND_SBSS_DRIVER_OFFSET); +STATIC_ASSERT(offsetof(RedSoundSmallDataState, m_autoId) == REDSOUND_SOUND_SBSS_AUTO_ID_OFFSET); +STATIC_ASSERT(offsetof(RedSoundSmallDataState, m_streamBank) == REDSOUND_SOUND_SBSS_STREAM_BANK_OFFSET); +STATIC_ASSERT(sizeof(RedSoundSmallDataState) == REDSOUND_SBSS_SIZE); +STATIC_ASSERT(sizeof(c_Driver) + REDSOUND_SBSS_PADDING_SIZE + sizeof(m_AutoID) + sizeof(p_StreamBank) == + REDSOUND_SBSS_SIZE); +STATIC_ASSERT(sizeof(sRedSoundMemorySettingError) == REDSOUND_MEMORY_SETTING_ERROR_SIZE); +STATIC_ASSERT(sizeof(sRedSoundLogPrefix) == REDSOUND_LOG_PREFIX_SIZE); +STATIC_ASSERT(sizeof(sRedSoundAMemorySettingError) == REDSOUND_AMEMORY_SETTING_ERROR_SIZE); +STATIC_ASSERT(sizeof(sRedSoundARNotInitialized) == REDSOUND_AR_NOT_INITIALIZED_SIZE); +STATIC_ASSERT(sizeof(sRedSoundInitOk) == REDSOUND_INIT_OK_SIZE); +STATIC_ASSERT(sizeof(sRedSoundInitError) == REDSOUND_INIT_ERROR_SIZE); +STATIC_ASSERT(sizeof(sRedSoundInvalidStreamData) == REDSOUND_INVALID_STREAM_DATA_SIZE); +STATIC_ASSERT(sizeof(sRedSoundDate) == REDSOUND_DATE_SIZE); +STATIC_ASSERT(sizeof(sRedSoundTime) == REDSOUND_TIME_SIZE); +STATIC_ASSERT(sizeof(sRedSoundLogErrorColor) == REDSOUND_LOG_ERROR_COLOR_SIZE); +STATIC_ASSERT(sizeof(sRedSoundLogReset) == REDSOUND_LOG_RESET_SIZE); +STATIC_ASSERT(sizeof(sRedSoundLogInfoColor) == REDSOUND_LOG_INFO_COLOR_SIZE); +STATIC_ASSERT(sizeof(sRedSoundMemorySettingError) + sizeof(sRedSoundLogPrefix) + + sizeof(sRedSoundAMemorySettingError) + sizeof(sRedSoundARNotInitialized) + + sizeof(sRedSoundInitOk) + sizeof(sRedSoundInitError) + sizeof(sRedSoundInvalidStreamData) + + sizeof(sRedSoundDate) + sizeof(sRedSoundTime) == + REDSOUND_RODATA_STRING_SIZE); +STATIC_ASSERT(sizeof(sRedSoundLogErrorColor) + sizeof(sRedSoundLogReset) + sizeof(sRedSoundLogInfoColor) == + REDSOUND_SDATA2_STRING_SIZE); + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 160b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +static RedSoundStreamBank* _SearchEmptyStreamBank() +{ + RedSoundStreamBank* bank = p_StreamBank; + RedSoundStreamBank* bankEnd = p_StreamBank + REDSOUND_STREAM_BANK_COUNT; + + do { + if (bank->m_streamId == REDSOUND_STREAM_ID_NONE) { + return bank; + } + if (c_Driver.StreamPlayState(bank->m_streamId) == REDSOUND_STREAM_ID_NONE) { + bank->m_streamId = REDSOUND_STREAM_ID_NONE; + bank->m_streamData = 0; + bank->m_fileSize = 0; + bank->m_readPoint = 0; + bank->m_playPoint = 0; + return bank; + } + bank++; + } while (bank < bankEnd); + + return 0; +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 88b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +static RedSoundStreamBank* _SearchStreamBank(int streamId) +{ + RedSoundStreamBank* bank = p_StreamBank; + RedSoundStreamBank* bankEnd = p_StreamBank + REDSOUND_STREAM_BANK_COUNT; + + do { + if ((bank->m_streamId != REDSOUND_STREAM_ID_NONE) && (bank->m_streamId == streamId)) { + return bank; + } + bank++; + } while (bank < bankEnd); + + return 0; +} + /* * --INFO-- * PAL Address: 0x801cca34 @@ -83,7 +249,7 @@ unsigned int CRedSound::GetAutoID() { do { m_AutoID++; - m_AutoID &= 0x7FFFFFFF; + m_AutoID &= REDSOUND_AUTO_ID_MASK; } while ((int)m_AutoID == 0); return m_AutoID; @@ -128,7 +294,7 @@ int CRedSound::Init(void* mainBuffer, int mainBufferSize, int aramBuffer, int ar if (mainBufferSize > 0 && aramBufferSize > 0) { if ((((u32)mainBuffer & REDSOUND_MEMORY_BANK_ALIGN_MASK) != 0) || (((u32)mainBufferSize & REDSOUND_MEMORY_BANK_ALIGN_MASK) != 0)) { - if (m_ReportPrint != 0) { + if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { OSReport(sRedSoundMemorySettingError, sRedSoundLogPrefix, sRedSoundLogErrorColor, (u32)mainBuffer, mainBufferSize, sRedSoundLogReset); fflush(__files + 1); @@ -138,7 +304,7 @@ int CRedSound::Init(void* mainBuffer, int mainBufferSize, int aramBuffer, int ar if ((((u32)aramBuffer & REDSOUND_MEMORY_BANK_ALIGN_MASK) != 0) || (((u32)aramBufferSize & REDSOUND_MEMORY_BANK_ALIGN_MASK) != 0)) { - if (m_ReportPrint != 0) { + if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { OSReport(sRedSoundAMemorySettingError, sRedSoundLogPrefix, sRedSoundLogErrorColor, aramBuffer, aramBufferSize, sRedSoundLogReset); @@ -148,7 +314,7 @@ int CRedSound::Init(void* mainBuffer, int mainBufferSize, int aramBuffer, int ar } if (ARCheckInit() == 0) { - if (m_ReportPrint != 0) { + if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { OSReport(sRedSoundARNotInitialized, sRedSoundLogPrefix, sRedSoundLogErrorColor, sRedSoundLogReset); @@ -166,7 +332,7 @@ int CRedSound::Init(void* mainBuffer, int mainBufferSize, int aramBuffer, int ar Start(); c_Driver.Init(); - if (m_ReportPrint != 0) { + if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { OSReport(sRedSoundInitOk, sRedSoundLogPrefix, sRedSoundLogInfoColor, sRedSoundLogReset); fflush(__files + 1); @@ -174,7 +340,7 @@ int CRedSound::Init(void* mainBuffer, int mainBufferSize, int aramBuffer, int ar } else { mainBufferSize = 0; - if (m_ReportPrint != 0) { + if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { OSReport(sRedSoundInitError, sRedSoundLogPrefix, sRedSoundLogErrorColor, sRedSoundLogReset); @@ -196,8 +362,8 @@ int CRedSound::Init(void* mainBuffer, int mainBufferSize, int aramBuffer, int ar */ void CRedSound::Start() { -#define redSoundStreamBank (*(void* volatile*)&p_StreamBank) - redSoundStreamBank = (void*)RedNew(REDSOUND_STREAM_BANK_SIZE); +#define redSoundStreamBank (*(RedSoundStreamBank* volatile*)&p_StreamBank) + redSoundStreamBank = (RedSoundStreamBank*)RedNew(REDSOUND_STREAM_BANK_SIZE); memset((void*)redSoundStreamBank, 0, REDSOUND_STREAM_BANK_SIZE); #undef redSoundStreamBank } @@ -292,7 +458,7 @@ int CRedSound::ReportStandby(int id) * JP Address: TODO * JP Size: TODO */ -int CRedSound::DMAEntry(int type, int src, int dst, int length, int flags, void (*callback)(void*), void* userData) +int CRedSound::DMAEntry(int type, int src, int dst, int length, int flags, RedDmaCallback callback, void* userData) { return RedDmaEntry(type, src, dst, length, flags, callback, userData); } @@ -362,9 +528,9 @@ void CRedSound::SetReverb(int bank, int kind) * JP Address: TODO * JP Size: TODO */ -void CRedSound::SetReverbDepth(int bank, int sep, int depth) +void CRedSound::SetReverbDepth(int bank, int depth, int frameCount) { - c_Driver.SetReverbDepth(bank, sep, depth); + c_Driver.SetReverbDepth(bank, depth, frameCount); } /* @@ -381,6 +547,20 @@ void CRedSound::SetMusicData(void* musicData) c_Driver.SetMusicData(musicData); } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 44b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedSound::ClearMusicData(int musicId) +{ + c_Driver.ClearMusicData(musicId); +} + /* * --INFO-- * PAL Address: 0x801ccfa0 @@ -395,6 +575,19 @@ int CRedSound::ReentryMusicData(int bank) return c_Driver.ReentryMusicData(bank); } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 44b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +int CRedSound::MusicPlayState(int id) +{ + return c_Driver.MusicPlayState(id); +} + /* * --INFO-- * PAL Address: 0x801ccfcc @@ -423,6 +616,19 @@ void CRedSound::MusicPlay(int id, int vol, int fadeTime) c_Driver.MusicPlay(id, vol, fadeTime); } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 60b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +void CRedSound::MusicPlay(void* data, int vol, int fadeTime) +{ + c_Driver.MusicPlay(data, vol, fadeTime); +} + /* * --INFO-- * PAL Address: 0x801cd034 @@ -437,6 +643,19 @@ void CRedSound::MusicCrossPlay(int id, int vol, int fadeTime) c_Driver.MusicCrossPlay(id, vol, fadeTime); } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 60b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +void CRedSound::MusicCrossPlay(void* data, int vol, int fadeTime) +{ + c_Driver.MusicCrossPlay(data, vol, fadeTime); +} + /* * --INFO-- * PAL Address: 0x801cd070 @@ -451,6 +670,19 @@ void CRedSound::MusicNextPlay(int id, int vol, int fadeTime) c_Driver.MusicNextPlay(id, vol, fadeTime); } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 60b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +void CRedSound::MusicNextPlay(void* data, int vol, int fadeTime) +{ + c_Driver.MusicNextPlay(data, vol, fadeTime); +} + /* * --INFO-- * PAL Address: 0x801cd0ac @@ -493,6 +725,45 @@ void CRedSound::MusicVolume(int id, int volume, int fadeTime) c_Driver.MusicVolume(id, volume, fadeTime); } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 52b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +void CRedSound::MusicPitch(int pitch, int frameCount) +{ + c_Driver.MusicPitch(pitch, frameCount); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 52b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +void CRedSound::MusicTempo(int tempo, int frameCount) +{ + c_Driver.MusicTempo(tempo, frameCount); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 52b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +void CRedSound::MusicPause(int musicId, int pause) +{ + c_Driver.MusicPause(musicId, pause); +} + /* * --INFO-- * PAL Address: 0x801cd148 @@ -605,6 +876,19 @@ void CRedSound::SeStop(int id) c_Driver.SeStop(id); } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 44b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +void CRedSound::SeStopG(int group) +{ + c_Driver.SeStopG(group); +} + /* * --INFO-- * PAL Address: 0x801cd2c8 @@ -635,6 +919,65 @@ int CRedSound::SePlay(int seID, int sepID, int pan, int volume, int pitch) return autoID; } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 100b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +int CRedSound::SePlay(void* data, int pan, int volume, int pitch) +{ + int autoID = GetAutoID(); + c_Driver.SePlay(data, autoID, pan, volume, pitch); + return autoID; +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 180b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +int CRedSound::GetSeUsedWave(int bank, int seNo) +{ + int waveNo = REDSOUND_SESEP_ID_NONE; + + if ((bank >= 0) && (bank < REDSOUND_SE_BLOCK_BANK_COUNT)) { + RedSeBlockHEAD* block = p_SeBlockData[bank]; + if ((block != 0) && (seNo >= 0) && (seNo < block->m_seCount)) { + int* entries = block->m_entries; + if (entries[seNo] != REDSOUND_SE_BLOCK_ENTRY_EMPTY) { + RedSeINFO* info = RedSeBlockGetInfoFromEntries(block, entries, seNo); + waveNo = info->m_waveNoHi; + waveNo = info->m_waveNoLo | waveNo * REDSOUND_SE_INFO_U16_HIGH_SCALE; + } + } + } + + return waveNo; +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 48b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +int CRedSound::GetSeUsedWave(void* seSepData) +{ + RedSeSepHEAD* seSepHead = (RedSeSepHEAD*)seSepData; + int waveNo; + + waveNo = seSepHead->m_waveNoHi; + return seSepHead->m_waveNoLo | waveNo * REDSOUND_SESEP_WAVE_NO_HIGH_SCALE; +} + /* * --INFO-- * PAL Address: 0x801cd378 @@ -784,9 +1127,9 @@ int CRedSound::StreamPlayState(int streamID) * JP Address: TODO * JP Size: TODO */ -void CRedSound::GetStreamPlayPoint(int streamID, int* point1, int* point2) +void CRedSound::GetStreamPlayPoint(int streamID, int* playPoint, int* readPoint) { - c_Driver.GetStreamPlayPoint(streamID, point1, point2); + c_Driver.GetStreamPlayPoint(streamID, playPoint, readPoint); } /* @@ -803,6 +1146,41 @@ void CRedSound::StreamStop(int streamID) c_Driver.StreamStop(streamID); } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 244b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +int CRedSound::StreamStandby(void* streamHeader, int fileSize) +{ + int streamId = 0; + RedStreamHEAD* header = reinterpret_cast(streamHeader); + + if (header->m_signature[0] == REDSOUND_STREAM_SIGNATURE_0 && + header->m_signature[1] == REDSOUND_STREAM_SIGNATURE_1 && + header->m_signature[2] == REDSOUND_STREAM_SIGNATURE_2) { + RedSoundStreamBank* bank = _SearchEmptyStreamBank(); + if (bank != 0) { + streamId = GetAutoID(); + bank->m_streamId = streamId; + bank->m_streamData = reinterpret_cast(streamHeader); + bank->m_fileSize = fileSize; + bank->m_readPoint = bank->m_playPoint = 0; + bank->m_reserved14 = 0; + } + } else if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { + OSReport(sRedSoundInvalidStreamData, + sRedSoundLogPrefix, sRedSoundLogErrorColor, + sRedSoundLogReset); + fflush(__files + 1); + } + + return streamId; +} + /* * --INFO-- * PAL Address: 0x801cd5d8 @@ -815,13 +1193,14 @@ void CRedSound::StreamStop(int streamID) int CRedSound::StreamPlay(void* data, int fileSize, int pan, int volume) { int id = 0; - char* streamSignature = (char*)data; + RedStreamHEAD* streamHeader = (RedStreamHEAD*)data; - if (streamSignature[0] == REDSOUND_STREAM_SIGNATURE_0 && streamSignature[1] == REDSOUND_STREAM_SIGNATURE_1 && - streamSignature[2] == REDSOUND_STREAM_SIGNATURE_2) { + if (streamHeader->m_signature[0] == REDSOUND_STREAM_SIGNATURE_0 && + streamHeader->m_signature[1] == REDSOUND_STREAM_SIGNATURE_1 && + streamHeader->m_signature[2] == REDSOUND_STREAM_SIGNATURE_2) { id = GetAutoID(); c_Driver.StreamPlay(id, data, fileSize, pan, volume); - } else if (m_ReportPrint != 0) { + } else if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { OSReport(sRedSoundInvalidStreamData, sRedSoundLogPrefix, sRedSoundLogErrorColor, sRedSoundLogReset); @@ -831,6 +1210,26 @@ int CRedSound::StreamPlay(void* data, int fileSize, int pan, int volume) return id; } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 112b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +int CRedSound::StreamPlay(int streamId, int pan, int volume) +{ + RedSoundStreamBank* bank = _SearchStreamBank(streamId); + + if (bank != 0) { + c_Driver.StreamPlay(streamId, bank->m_streamData, bank->m_fileSize, pan, volume); + return streamId; + } + + return 0; +} + /* * --INFO-- * PAL Address: 0x801cd6b8 @@ -845,6 +1244,19 @@ void CRedSound::StreamVolume(int streamID, int volume, int frameCount) c_Driver.StreamVolume(streamID, volume, frameCount); } +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 60b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + */ +void CRedSound::StreamPan(int streamID, int pan, int frameCount) +{ + c_Driver.StreamPan(streamID, pan, frameCount); +} + /* * --INFO-- * PAL Address: 0x801cd6f4 @@ -961,3 +1373,531 @@ void CRedSound::TestProcess(int mode) { c_Driver.TestProcess(mode); } + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 40b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedSound::Sleep(int microseconds) +{ + RedSleep(microseconds); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 36b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +int CRedSound::GetMasterTime() +{ + return c_Driver.GetMasterTime(); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 40b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedSound::SetDMAMode(int mode) +{ + RedSetDMAMode(mode); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 36b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +RedReverbSize* CRedSound::GetReverbInfo() +{ + return c_Driver.GetReverbInfo(); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 36b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +RedReverbDepth* CRedSound::GetReverbDepth() +{ + return c_Driver.GetReverbDepth(); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 60b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedSound::SetReverb(int bank, int kind, int* params) +{ + c_Driver.SetReverb(bank, kind, params); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 52b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedSound::SetMute(unsigned int voiceNo, unsigned int mute) +{ + c_Driver.SetMute(voiceNo, mute); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 36b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedSound::DisplayMMemoryInfo() +{ + c_Driver.DisplayMMemoryInfo(); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 44b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +int CRedSound::CheckMusicEntry(int musicId) +{ + return c_Driver.CheckMusicEntry(musicId); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 44b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedSound::SetMusicFastSpeed(int speed) +{ + c_Driver.SetMusicFastSpeed(speed); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 36b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +int CRedSound::CheckMusicPhraseStop() +{ + return c_Driver.CheckMusicPhraseStop(); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 36b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedSound::DisplayMusicInfo() +{ + c_Driver.DisplayMusicInfo(); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 44b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +int CRedSound::CheckSeSepEntry(int sepId) +{ + return c_Driver.CheckSeSepEntry(sepId); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 36b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedSound::ClearSePlayLine() +{ + c_Driver.ClearSePlayLine(); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 44b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +RedStreamDATA* CRedSound::GetStreamPlayBlock(int streamId) +{ + return c_Driver.GetStreamPlayBlock(streamId); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 336b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedSound::GetStreamReadPoint(int streamId, int* readPoint) +{ + RedSoundStreamBank* bank = _SearchStreamBank(streamId); + + if (readPoint != 0) { + readPoint[0] = 0; + readPoint[1] = 0; + } + + if (bank != 0) { + int playPoint; + int currentReadPoint; + int delta; + + if (c_Driver.GetStreamPlayPoint(streamId, &playPoint, ¤tReadPoint) != 0) { + if (readPoint != 0) { + if (currentReadPoint >= bank->m_readPoint) { + delta = currentReadPoint - bank->m_readPoint; + } else { + delta = bank->m_fileSize - bank->m_readPoint + currentReadPoint; + } + readPoint[0] = delta; + if (playPoint >= bank->m_playPoint) { + readPoint[1] = playPoint - bank->m_playPoint; + } + } + bank->m_readPoint = currentReadPoint; + bank->m_playPoint = playPoint; + } else { + if (readPoint != 0) { + readPoint[0] = bank->m_fileSize - bank->m_readPoint; + readPoint[1] = bank->m_fileSize - bank->m_playPoint; + } + bank->m_streamId = REDSOUND_STREAM_ID_NONE; + bank->m_streamData = 0; + bank->m_fileSize = 0; + bank->m_readPoint = 0; + bank->m_playPoint = 0; + } + } +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 36b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +RedTrackDATA* CRedSound::GetSePlayTrack() +{ + return c_Driver.GetSePlayTrack(); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 48b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +int CRedSound::SearchWaveSequence(int waveNo) +{ + return c_RedEntry.SearchWaveSequence(waveNo); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 44b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +RedWaveHeadWD* CRedSound::GetWaveInfo(int waveNo) +{ + return c_Driver.GetWaveInfo(waveNo); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 44b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +int CRedSound::CheckWaveEntry(int waveNo) +{ + return c_Driver.CheckWaveEntry(waveNo); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 44b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +RedReverbModeData* CRedSound::GetReverbModeTable(int mode) +{ + return c_Driver.GetReverbModeTable(mode); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 28b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedSound::GetMakeTime(char** date, char** time) +{ + *date = (char*)sRedSoundDate; + *time = (char*)sRedSoundTime; +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 36b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +int CRedSound::GetMainBufferAddress() +{ + return c_RedMemory.GetMainBufferAddress(); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 36b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +int CRedSound::GetMainBufferSize() +{ + return c_RedMemory.GetMainBufferSize(); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 36b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +RedMemoryBlock* CRedSound::GetMainBankAddress() +{ + return c_RedMemory.GetMainBankAddress(); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 36b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +int CRedSound::GetABufferAddress() +{ + return c_RedMemory.GetABufferAddress(); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 36b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +RedMemoryBlock* CRedSound::GetABankAddress() +{ + return c_RedMemory.GetABankAddress(); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 8b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +RedSoundCONTROL* CRedSound::GetControlAddress() +{ + return p_SoundControlBuffer; +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 8b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +RedVoiceDATA* CRedSound::GetVoiceAddress() +{ + return p_VoiceData; +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 76b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +int CRedSound::PlayWaveItem(int waveNo, int itemNo, int key, int pan, int volume) +{ + return c_Driver.PlayWaveItem(waveNo, itemNo, key, pan, volume); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 36b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedSound::StopWaveItem() +{ + c_Driver.StopWaveItem(); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 44b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedSound::SetWavePitch(int pitch) +{ + c_Driver.SetWavePitch(pitch); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 52b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedSound::SetWaveTune(int key, int fineTune) +{ + c_Driver.SetWaveTune(key, fineTune); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 52b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void CRedSound::SetWaveAdsr(int attack, RedAdsrDATA* adsr) +{ + c_Driver.SetWaveAdsr(attack, adsr); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 52b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +int CRedSound::WavePitchCompute(int key, int pitch) +{ + return c_Driver.WavePitchCompute(key, pitch); +} diff --git a/src/RedSound/RedStream.cpp b/src/RedSound/RedStream.cpp index ffb2605567..c769bf0321 100644 --- a/src/RedSound/RedStream.cpp +++ b/src/RedSound/RedStream.cpp @@ -6,6 +6,7 @@ #include "ffcc/RedSound/RedMemory.h" #include "ffcc/RedSound/RedMidiCtrl.h" #include "ffcc/RedSound/RedGlobals.h" +#include "global.h" #include #include @@ -19,11 +20,25 @@ static const char sRedStreamLogErrorColor[] = "\x1B[7;31m"; static const char sRedStreamLogReset[] = "\x1B[0m"; static const char sRedStreamLogWarnColor[] = "\x1B[4;31m"; +enum RedStreamStringLayout { + REDSOUND_STREAM_BUFFER_DIDNT_SECURE_FMT_SIZE = 0x24, + REDSOUND_STREAM_LOG_PREFIX_SIZE = 0x12, + REDSOUND_STREAM_MAIN_MEMORY_DIDNT_CREATE_FMT_SIZE = 0x2d, + REDSOUND_STREAM_ARAM_MEMORY_DIDNT_CREATE_FMT_SIZE = 0x2d, + REDSOUND_STREAM_PAUSE_ON_FMT_SIZE = 0x1b, + REDSOUND_STREAM_PAUSE_OFF_FMT_SIZE = 0x1b, + REDSOUND_STREAM_LOG_ERROR_COLOR_SIZE = 0x08, + REDSOUND_STREAM_LOG_RESET_SIZE = 0x05, + REDSOUND_STREAM_LOG_WARN_COLOR_SIZE = 0x08, + REDSOUND_STREAM_RODATA_STRING_SIZE = 0xc6, + REDSOUND_STREAM_SDATA2_STRING_SIZE = 0x15, +}; + enum RedStreamLayoutSize { - REDSOUND_STREAM_PAGE_SIZE = 0x1000, REDSOUND_STREAM_STEREO_PLANE_SIZE = 0x2000, REDSOUND_STREAM_STEREO_PLANE_PAGE_COUNT = REDSOUND_STREAM_STEREO_PLANE_SIZE / REDSOUND_STREAM_PAGE_SIZE, - REDSOUND_STREAM_TRANSFER_BUFFER_SIZE = 0x4000, + REDSOUND_STREAM_TRANSFER_BUFFER_SIZE = REDSOUND_STREAM_STEREO_PLANE_SIZE * 2, + REDSOUND_STREAM_TRANSFER_BUFFER_ALLOC_SIZE = 0x4000, REDSOUND_STREAM_SAMPLE_ADVANCE = 0x200, REDSOUND_STREAM_FILE_HEADER_SIZE = sizeof(RedStreamHEAD), REDSOUND_STREAM_INITIAL_LOOP_END = 0x3fff, @@ -44,25 +59,120 @@ enum RedStreamChannelIndex { REDSOUND_STREAM_RIGHT_CHANNEL = 1, }; -struct RedStreamADPCMHeader { - AXPBADPCM m_data; - AXPBADPCMLOOP m_loop; +struct RedStreamStereoFrame { + unsigned int m_left[REDSOUND_STREAM_STEREO_FRAME_WORD_COUNT]; + unsigned int m_right[REDSOUND_STREAM_STEREO_FRAME_WORD_COUNT]; }; -struct RedStreamFile { - RedStreamHEAD m_header; - RedStreamADPCMHeader m_adpcm[1]; +struct RedStreamChannelFrame { + unsigned int m_word[REDSOUND_STREAM_STEREO_FRAME_WORD_COUNT]; }; -struct RedStreamStereoFrame { - unsigned int m_left[REDSOUND_STREAM_STEREO_FRAME_WORD_COUNT]; - unsigned int m_right[REDSOUND_STREAM_STEREO_FRAME_WORD_COUNT]; +enum RedStreamFrameLayoutSize { + REDSOUND_STREAM_STEREO_LEFT_FRAME_OFFSET = 0x00, + REDSOUND_STREAM_STEREO_RIGHT_FRAME_OFFSET = sizeof(unsigned int) * REDSOUND_STREAM_STEREO_FRAME_WORD_COUNT, + REDSOUND_STREAM_STEREO_FRAME_WORD_BYTES = sizeof(unsigned int), + REDSOUND_STREAM_STEREO_CHANNEL_FRAME_BYTES = sizeof(unsigned int) * REDSOUND_STREAM_STEREO_FRAME_WORD_COUNT, + REDSOUND_STREAM_STEREO_FRAME_SIZE = 0x10, + REDSOUND_STREAM_STEREO_FRAMES_PER_PAGE = REDSOUND_STREAM_PAGE_SIZE / REDSOUND_STREAM_STEREO_FRAME_SIZE, + REDSOUND_STREAM_LEFT_PRED_SCALE_OFFSET = REDSOUND_STREAM_PAGE_SIZE, + REDSOUND_STREAM_LOOP_START_SAMPLE = 2, + REDSOUND_STREAM_LOOP_ENABLED_MIN = 0, + REDSOUND_STREAM_ADSR_RELEASE_TIME = 10, }; +STATIC_ASSERT(offsetof(RedStreamHEAD, m_signature) == REDSOUND_STREAM_HEAD_SIGNATURE_OFFSET); +STATIC_ASSERT(sizeof(((RedStreamHEAD*)0)->m_signature) == REDSOUND_STREAM_SIGNATURE_SIZE); +STATIC_ASSERT(offsetof(RedStreamHEAD, m_reserved04) == REDSOUND_STREAM_HEAD_RESERVED04_OFFSET); +STATIC_ASSERT(sizeof(((RedStreamHEAD*)0)->m_reserved04) == REDSOUND_STREAM_HEAD_RESERVED04_SIZE); +STATIC_ASSERT(offsetof(RedStreamHEAD, m_loopEnd) == REDSOUND_STREAM_HEAD_LOOP_END_OFFSET); +STATIC_ASSERT(offsetof(RedStreamHEAD, m_loopStart) == REDSOUND_STREAM_HEAD_LOOP_START_OFFSET); +STATIC_ASSERT(offsetof(RedStreamHEAD, m_pitch) == REDSOUND_STREAM_HEAD_PITCH_OFFSET); +STATIC_ASSERT(offsetof(RedStreamHEAD, m_reserved18) == REDSOUND_STREAM_HEAD_RESERVED18_OFFSET); +STATIC_ASSERT(sizeof(((RedStreamHEAD*)0)->m_reserved18) == REDSOUND_STREAM_HEAD_RESERVED18_SIZE); +STATIC_ASSERT(offsetof(RedStreamHEAD, m_reserved18) + REDSOUND_STREAM_HEAD_RESERVED18_SIZE == + REDSOUND_STREAM_HEAD_CHANNEL_COUNT_OFFSET); +STATIC_ASSERT(offsetof(RedStreamHEAD, m_channelCount) == REDSOUND_STREAM_HEAD_CHANNEL_COUNT_OFFSET); +STATIC_ASSERT(offsetof(RedStreamHEAD, m_flags) == REDSOUND_STREAM_HEAD_FLAGS_OFFSET); +STATIC_ASSERT(offsetof(RedStreamHEAD, m_reserved1E) == REDSOUND_STREAM_HEAD_RESERVED1E_OFFSET); +STATIC_ASSERT(sizeof(((RedStreamHEAD*)0)->m_reserved1E) == REDSOUND_STREAM_HEAD_RESERVED1E_SIZE); +STATIC_ASSERT(offsetof(RedStreamHEAD, m_reserved1E) + REDSOUND_STREAM_HEAD_RESERVED1E_SIZE == + REDSOUND_STREAM_HEAD_SIZE); +STATIC_ASSERT(sizeof(RedStreamHEAD) == REDSOUND_STREAM_HEAD_SIZE); +STATIC_ASSERT(offsetof(RedStreamADPCMHeader, m_data) == REDSOUND_STREAM_ADPCM_DATA_OFFSET); +STATIC_ASSERT(offsetof(RedStreamADPCMHeader, m_loop) == REDSOUND_STREAM_ADPCM_LOOP_OFFSET); +STATIC_ASSERT(sizeof(((RedStreamADPCMHeader*)0)->m_data) == REDSOUND_STREAM_ADPCM_DATA_SIZE); +STATIC_ASSERT(sizeof(((RedStreamADPCMHeader*)0)->m_loop) == REDSOUND_STREAM_ADPCM_LOOP_SIZE); +STATIC_ASSERT(sizeof(RedStreamADPCMHeader) == REDSOUND_STREAM_ADPCM_HEADER_SIZE); +STATIC_ASSERT(offsetof(RedStreamFile, m_header) == REDSOUND_STREAM_FILE_HEAD_OFFSET); +STATIC_ASSERT(offsetof(RedStreamFile, m_adpcm) == REDSOUND_STREAM_FILE_ADPCM_OFFSET); +STATIC_ASSERT(sizeof(((RedStreamFile*)0)->m_adpcm) == + REDSOUND_STREAM_ADPCM_HEADER_SIZE * REDSOUND_STREAM_FILE_ADPCM_COUNT); +STATIC_ASSERT(offsetof(RedStreamFile, m_adpcm) + sizeof(((RedStreamFile*)0)->m_adpcm) == + REDSOUND_STREAM_FILE_ADPCM_END); +STATIC_ASSERT(offsetof(RedStreamFile, m_trailingPadding) == REDSOUND_STREAM_FILE_TRAILING_PAD_OFFSET); +STATIC_ASSERT(sizeof(((RedStreamFile*)0)->m_trailingPadding) == REDSOUND_STREAM_FILE_TRAILING_PAD_SIZE); +STATIC_ASSERT(sizeof(RedStreamFile) == REDSOUND_STREAM_FILE_SIZE); +STATIC_ASSERT(offsetof(RedStreamStereoFrame, m_left) == REDSOUND_STREAM_STEREO_LEFT_FRAME_OFFSET); +STATIC_ASSERT(sizeof(((RedStreamStereoFrame*)0)->m_left) == REDSOUND_STREAM_STEREO_CHANNEL_FRAME_BYTES); +STATIC_ASSERT(offsetof(RedStreamStereoFrame, m_right) == REDSOUND_STREAM_STEREO_RIGHT_FRAME_OFFSET); +STATIC_ASSERT(sizeof(((RedStreamStereoFrame*)0)->m_right) == REDSOUND_STREAM_STEREO_CHANNEL_FRAME_BYTES); +STATIC_ASSERT(sizeof(RedStreamStereoFrame) == REDSOUND_STREAM_STEREO_FRAME_SIZE); +STATIC_ASSERT(sizeof(((RedStreamChannelFrame*)0)->m_word) == REDSOUND_STREAM_STEREO_CHANNEL_FRAME_BYTES); +STATIC_ASSERT(sizeof(RedStreamChannelFrame) == REDSOUND_STREAM_STEREO_CHANNEL_FRAME_BYTES); +STATIC_ASSERT(REDSOUND_STREAM_STEREO_FRAMES_PER_PAGE * REDSOUND_STREAM_STEREO_FRAME_SIZE == + REDSOUND_STREAM_PAGE_SIZE); +STATIC_ASSERT(REDSOUND_STREAM_STEREO_PLANE_SIZE * REDSOUND_STREAM_STEREO_CHANNEL_COUNT == + REDSOUND_STREAM_TRANSFER_BUFFER_SIZE); +STATIC_ASSERT(REDSOUND_STREAM_TRANSFER_BUFFER_SIZE == REDSOUND_STREAM_TRANSFER_BUFFER_ALLOC_SIZE); +STATIC_ASSERT(offsetof(RedStreamStepData, m_value) == REDSOUND_STREAM_STEP_VALUE_OFFSET); +STATIC_ASSERT(offsetof(RedStreamStepData, m_step) == REDSOUND_STREAM_STEP_STEP_OFFSET); +STATIC_ASSERT(offsetof(RedStreamStepData, m_stepCount) == REDSOUND_STREAM_STEP_COUNT_OFFSET); +STATIC_ASSERT(sizeof(RedStreamStepData) == REDSOUND_STREAM_STEP_DATA_SIZE); +STATIC_ASSERT(offsetof(RedStreamDATA, m_track) == REDSOUND_STREAM_TRACK_OFFSET); +STATIC_ASSERT(offsetof(RedStreamDATA, m_voiceData) == REDSOUND_STREAM_VOICE_DATA_OFFSET); +STATIC_ASSERT(offsetof(RedStreamDATA, m_fileData) == REDSOUND_STREAM_FILE_DATA_OFFSET); +STATIC_ASSERT(offsetof(RedStreamDATA, m_buffer) == REDSOUND_STREAM_BUFFER_OFFSET); +STATIC_ASSERT(offsetof(RedStreamDATA, m_header) == REDSOUND_STREAM_HEADER_OFFSET); +STATIC_ASSERT(offsetof(RedStreamDATA, m_trackData) == REDSOUND_STREAM_TRACK_DATA_OFFSET); +STATIC_ASSERT(offsetof(RedStreamDATA, m_volume.m_value) == REDSOUND_STREAM_VOLUME_OFFSET); +STATIC_ASSERT(offsetof(RedStreamDATA, m_volume.m_step) == REDSOUND_STREAM_VOLUME_STEP_OFFSET); +STATIC_ASSERT(offsetof(RedStreamDATA, m_volume.m_stepCount) == REDSOUND_STREAM_VOLUME_STEP_COUNT_OFFSET); +STATIC_ASSERT(offsetof(RedStreamDATA, m_reservedFC) == REDSOUND_STREAM_RESERVED_FC_OFFSET); +STATIC_ASSERT(sizeof(((RedStreamDATA*)0)->m_reservedFC) == REDSOUND_STREAM_RESERVED_FC_SIZE); +STATIC_ASSERT(offsetof(RedStreamDATA, m_pan.m_value) == REDSOUND_STREAM_PAN_OFFSET); +STATIC_ASSERT(offsetof(RedStreamDATA, m_pan.m_step) == REDSOUND_STREAM_PAN_STEP_OFFSET); +STATIC_ASSERT(offsetof(RedStreamDATA, m_pan.m_stepCount) == REDSOUND_STREAM_PAN_STEP_COUNT_OFFSET); +STATIC_ASSERT(offsetof(RedStreamDATA, m_streamId) == REDSOUND_STREAM_ID_OFFSET); +STATIC_ASSERT(offsetof(RedStreamDATA, m_state) == REDSOUND_STREAM_STATE_OFFSET); +STATIC_ASSERT(offsetof(RedStreamDATA, m_dmaId) == REDSOUND_STREAM_DMA_ID_OFFSET); +STATIC_ASSERT(offsetof(RedStreamDATA, m_fileSize) == REDSOUND_STREAM_FILE_SIZE_OFFSET); +STATIC_ASSERT(offsetof(RedStreamDATA, m_fileCursor) == REDSOUND_STREAM_FILE_CURSOR_OFFSET); +STATIC_ASSERT(offsetof(RedStreamDATA, m_readOffset) == REDSOUND_STREAM_READ_OFFSET); +STATIC_ASSERT(offsetof(RedStreamDATA, m_streamCursor) == REDSOUND_STREAM_CURSOR_OFFSET); +STATIC_ASSERT(offsetof(RedStreamDATA, m_streamCursorBase) == REDSOUND_STREAM_CURSOR_BASE_OFFSET); +STATIC_ASSERT(offsetof(RedStreamDATA, m_aramBuffer) == REDSOUND_STREAM_ARAM_BUFFER_OFFSET); +STATIC_ASSERT(sizeof(RedStreamDATA) == REDSOUND_STREAM_DATA_SIZE); +STATIC_ASSERT(sizeof(sRedStreamBufferDidntSecureFmt) == REDSOUND_STREAM_BUFFER_DIDNT_SECURE_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedStreamLogPrefix) == REDSOUND_STREAM_LOG_PREFIX_SIZE); +STATIC_ASSERT(sizeof(sRedStreamMainMemoryDidntCreateFmt) == REDSOUND_STREAM_MAIN_MEMORY_DIDNT_CREATE_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedStreamAramMemoryDidntCreateFmt) == REDSOUND_STREAM_ARAM_MEMORY_DIDNT_CREATE_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedStreamPauseOnFmt) == REDSOUND_STREAM_PAUSE_ON_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedStreamPauseOffFmt) == REDSOUND_STREAM_PAUSE_OFF_FMT_SIZE); +STATIC_ASSERT(sizeof(sRedStreamLogErrorColor) == REDSOUND_STREAM_LOG_ERROR_COLOR_SIZE); +STATIC_ASSERT(sizeof(sRedStreamLogReset) == REDSOUND_STREAM_LOG_RESET_SIZE); +STATIC_ASSERT(sizeof(sRedStreamLogWarnColor) == REDSOUND_STREAM_LOG_WARN_COLOR_SIZE); +STATIC_ASSERT(sizeof(sRedStreamBufferDidntSecureFmt) + sizeof(sRedStreamLogPrefix) + + sizeof(sRedStreamMainMemoryDidntCreateFmt) + sizeof(sRedStreamAramMemoryDidntCreateFmt) + + sizeof(sRedStreamPauseOnFmt) + sizeof(sRedStreamPauseOffFmt) == + REDSOUND_STREAM_RODATA_STRING_SIZE); +STATIC_ASSERT(sizeof(sRedStreamLogErrorColor) + sizeof(sRedStreamLogReset) + sizeof(sRedStreamLogWarnColor) == + REDSOUND_STREAM_SDATA2_STRING_SIZE); + static RedStreamDATA* _SearchEmptyStreamData(); -static void _StreamStop(RedStreamDATA*); -static int _ArrangeStreamDataNoLoop(RedStreamDATA*, int, int); -static int _ArrangeStreamDataLoop(RedStreamDATA*, int, int); +static void _StreamStop(RedStreamDATA* streamData); +static int _ArrangeStreamDataNoLoop(RedStreamDATA* stream, int bufferIndex, int byteCount); +static int _ArrangeStreamDataLoop(RedStreamDATA* stream, int bufferIndex, int byteCount); /* * --INFO-- @@ -78,7 +188,7 @@ static RedStreamDATA* _SearchEmptyStreamData() RedStreamDATA* streamData = p_Stream; for (;;) { - if (streamData->m_streamId == 0) { + if (streamData->m_streamId == REDSOUND_STREAM_ID_NONE) { return streamData; } @@ -102,8 +212,8 @@ static RedStreamDATA* _SearchEmptyStreamData() static void _StreamStop(RedStreamDATA* streamData) { fflush(__files + 1); - if (streamData->m_streamId != 0) { - streamData->m_streamId = 0; + if (streamData->m_streamId != REDSOUND_STREAM_ID_NONE) { + streamData->m_streamId = REDSOUND_STREAM_ID_NONE; streamData->m_state = REDSOUND_STREAM_STATE_STOPPED; if (streamData->m_buffer != 0) { RedDelete(streamData->m_buffer); @@ -116,12 +226,12 @@ static void _StreamStop(RedStreamDATA* streamData) streamData->m_voiceData->m_flags |= REDSOUND_VOICE_FLAGS_RELEASED; streamData->m_track->m_note.m_allocFlags &= ~REDSOUND_NOTE_ALLOC_STREAM; streamData->m_voiceData->m_stateFlags &= REDSOUND_VOICE_STATE_CLEAR_STREAM_MASK; - streamData->m_voiceData->m_active = 0; + streamData->m_voiceData->m_active = REDSOUND_VOICE_ACTIVE_OFF; if (streamData->m_header.m_channelCount == REDSOUND_STREAM_STEREO_CHANNEL_COUNT) { streamData->m_voiceData[REDSOUND_STREAM_RIGHT_CHANNEL].m_flags |= REDSOUND_VOICE_FLAGS_RELEASED; streamData->m_track[REDSOUND_STREAM_RIGHT_CHANNEL].m_note.m_allocFlags &= ~REDSOUND_NOTE_ALLOC_STREAM; streamData->m_voiceData[REDSOUND_STREAM_RIGHT_CHANNEL].m_stateFlags &= REDSOUND_VOICE_STATE_CLEAR_STREAM_MASK; - streamData->m_voiceData[REDSOUND_STREAM_RIGHT_CHANNEL].m_active = 0; + streamData->m_voiceData[REDSOUND_STREAM_RIGHT_CHANNEL].m_active = REDSOUND_VOICE_ACTIVE_OFF; } } } @@ -218,17 +328,17 @@ static int _ArrangeStreamDataLoop(RedStreamDATA* stream, int bufferIndex, int by voiceData = stream->m_voiceData; srcFrame = (RedStreamStereoFrame*)(stream->m_fileData + stream->m_readOffset); rightDst = dstBase + REDSOUND_STREAM_STEREO_PLANE_SIZE; - srcEnd = srcFrame + REDSOUND_STREAM_PAGE_SIZE / sizeof(*srcFrame); + srcEnd = srcFrame + REDSOUND_STREAM_STEREO_FRAMES_PER_PAGE; leftDst = dstBase; do { - *(unsigned int*)leftDst = srcFrame->m_left[0]; - *(unsigned int*)(leftDst + 4) = srcFrame->m_left[1]; - leftDst = leftDst + 8; - *(unsigned int*)rightDst = srcFrame->m_right[0]; - *(unsigned int*)(rightDst + 4) = srcFrame->m_right[1]; + ((RedStreamChannelFrame*)leftDst)->m_word[0] = srcFrame->m_left[0]; + ((RedStreamChannelFrame*)leftDst)->m_word[1] = srcFrame->m_left[1]; + leftDst = leftDst + REDSOUND_STREAM_STEREO_CHANNEL_FRAME_BYTES; + ((RedStreamChannelFrame*)rightDst)->m_word[0] = srcFrame->m_right[0]; + ((RedStreamChannelFrame*)rightDst)->m_word[1] = srcFrame->m_right[1]; srcFrame = srcFrame + 1; - rightDst = rightDst + 8; + rightDst = rightDst + REDSOUND_STREAM_STEREO_CHANNEL_FRAME_BYTES; } while (srcFrame < srcEnd); stream->m_readOffset = stream->m_readOffset + REDSOUND_STREAM_PAGE_SIZE; @@ -237,16 +347,16 @@ static int _ArrangeStreamDataLoop(RedStreamDATA* stream, int bufferIndex, int by } srcFrame = (RedStreamStereoFrame*)(stream->m_fileData + stream->m_readOffset); - srcEnd = srcFrame + REDSOUND_STREAM_PAGE_SIZE / sizeof(*srcFrame); + srcEnd = srcFrame + REDSOUND_STREAM_STEREO_FRAMES_PER_PAGE; do { - *(unsigned int*)leftDst = srcFrame->m_left[0]; - *(unsigned int*)(leftDst + 4) = srcFrame->m_left[1]; - leftDst = leftDst + 8; - *(unsigned int*)rightDst = srcFrame->m_right[0]; - *(unsigned int*)(rightDst + 4) = srcFrame->m_right[1]; + ((RedStreamChannelFrame*)leftDst)->m_word[0] = srcFrame->m_left[0]; + ((RedStreamChannelFrame*)leftDst)->m_word[1] = srcFrame->m_left[1]; + leftDst = leftDst + REDSOUND_STREAM_STEREO_CHANNEL_FRAME_BYTES; + ((RedStreamChannelFrame*)rightDst)->m_word[0] = srcFrame->m_right[0]; + ((RedStreamChannelFrame*)rightDst)->m_word[1] = srcFrame->m_right[1]; srcFrame = srcFrame + 1; - rightDst = rightDst + 8; + rightDst = rightDst + REDSOUND_STREAM_STEREO_CHANNEL_FRAME_BYTES; } while (srcFrame < srcEnd); stream->m_readOffset = stream->m_readOffset + REDSOUND_STREAM_PAGE_SIZE; @@ -324,7 +434,8 @@ void StreamStop(int streamID) volatile RedStreamDATA* streamData = p_Stream; do { - if ((streamData->m_streamId != 0) && ((streamID == -1) || (streamID == streamData->m_streamId))) { + if ((streamData->m_streamId != REDSOUND_STREAM_ID_NONE) && + ((streamID == REDSOUND_STREAM_ID_ALL) || (streamID == streamData->m_streamId))) { _StreamStop((RedStreamDATA*)streamData); } streamData++; @@ -344,9 +455,11 @@ int StreamPlay(int streamID, void* streamHeader, int fileSize, int pan, int volu { int amemSize; int arOffset; + int arOffsetArg; int pitch; int channel; int sampleOffset; + RedStreamFile* streamFile; RedStreamADPCMHeader* headerData; RedStreamDATA* streamData; RedVoiceDATA* voice; @@ -363,24 +476,26 @@ int StreamPlay(int streamID, void* streamHeader, int fileSize, int pan, int volu } else { arOffset = REDSOUND_STREAM_ARAM_HIGH_OFFSET; } - streamData->m_aramBuffer = RedNewA(amemSize, 0, arOffset); + arOffsetArg = arOffset; + streamData->m_aramBuffer = RedNewA(amemSize, 0, arOffsetArg); if (streamData->m_aramBuffer == 0) { - c_RedEntry.WaveOldClear(0, arOffset); - streamData->m_aramBuffer = RedNewA(amemSize, 0, arOffset); + c_RedEntry.WaveOldClear(0, arOffsetArg); + streamData->m_aramBuffer = RedNewA(amemSize, 0, arOffsetArg); } if ((streamData->m_track != 0) && (streamData->m_buffer != 0) && (streamData->m_aramBuffer != 0)) { - sampleOffset = REDSOUND_STREAM_PAGE_SIZE; - headerData = reinterpret_cast(streamHeader)->m_adpcm; - headerData->m_data.pred_scale = (short)((s8*)streamHeader)[sampleOffset]; + sampleOffset = REDSOUND_STREAM_LEFT_PRED_SCALE_OFFSET; + streamFile = reinterpret_cast(streamHeader); + headerData = streamFile->m_adpcm; + headerData->m_data.pred_scale = (short)((s8*)streamFile)[sampleOffset]; headerData->m_data.yn1 = headerData->m_data.yn2 = 0; if (streamData->m_header.m_channelCount == REDSOUND_STREAM_STEREO_CHANNEL_COUNT) { - if (streamData->m_header.m_loopStart < 0) { + if (streamData->m_header.m_loopStart < REDSOUND_STREAM_LOOP_ENABLED_MIN) { sampleOffset += REDSOUND_STREAM_PAGE_SIZE; } else { - sampleOffset += 8; + sampleOffset += REDSOUND_STREAM_STEREO_RIGHT_FRAME_OFFSET; } - headerData[REDSOUND_STREAM_RIGHT_CHANNEL].m_data.pred_scale = (short)((s8*)streamHeader)[sampleOffset]; + headerData[REDSOUND_STREAM_RIGHT_CHANNEL].m_data.pred_scale = (short)((s8*)streamFile)[sampleOffset]; headerData[REDSOUND_STREAM_RIGHT_CHANNEL].m_data.yn1 = headerData[REDSOUND_STREAM_RIGHT_CHANNEL].m_data.yn2 = 0; } @@ -395,8 +510,8 @@ int StreamPlay(int streamID, void* streamHeader, int fileSize, int pan, int volu if (volume != 0) { volume = ((volume + 1) * REDSOUND_VOLUME_BYTE_SCALE - 1) * REDSOUND_FIXED_ONE; } - streamData->m_volume = volume; - streamData->m_volumeStepCount = 0; + streamData->m_volume.m_value = volume; + streamData->m_volume.m_stepCount = 0; pitch = PitchCompute(REDSOUND_STREAM_BASE_PITCH, 0, streamData->m_header.m_pitch, 0); channel = 0; do { @@ -404,7 +519,7 @@ int StreamPlay(int streamID, void* streamHeader, int fileSize, int pan, int volu voice->m_track = streamData->m_track + channel; voice->m_track->m_note.m_allocFlags |= REDSOUND_NOTE_ALLOC_STREAM; voice->m_stateFlags |= REDSOUND_VOICE_STATE_STREAM; - voice->m_voiceSwitch = REDSOUND_VOICE_SWITCH_DRY_STEREO | REDSOUND_VOICE_SWITCH_LOOP; + voice->m_voiceSwitch = REDSOUND_VOICE_SWITCH_STREAM_DEFAULT; if (streamData->m_header.m_flags != REDSOUND_STREAM_HEADER_REVERB_NONE) { voice->m_voiceSwitch |= REDSOUND_VOICE_SWITCH_REVERB_STEREO; } @@ -416,35 +531,35 @@ int StreamPlay(int streamID, void* streamHeader, int fileSize, int pan, int volu voice->m_track->m_reverbDepthDelta = 0; if (streamData->m_header.m_channelCount == REDSOUND_STREAM_STEREO_CHANNEL_COUNT) { if (channel == REDSOUND_STREAM_LEFT_CHANNEL) { - streamData->m_pan = 0; - streamData->m_panStepCount = 0; + streamData->m_pan.m_value = 0; + streamData->m_pan.m_stepCount = 0; } else { - streamData->m_pan = REDSOUND_VOLUME_DEFAULT; - streamData->m_panStepCount = 0; + streamData->m_pan.m_value = REDSOUND_VOLUME_DEFAULT; + streamData->m_pan.m_stepCount = 0; } } else { - streamData->m_pan = pan << REDSOUND_FIXED_SHIFT; - streamData->m_panStepCount = 0; + streamData->m_pan.m_value = pan << REDSOUND_FIXED_SHIFT; + streamData->m_pan.m_stepCount = 0; } - SetVoiceVolumeMix(streamData->m_voiceData + channel, streamData->m_pan >> REDSOUND_FIXED_SHIFT, - streamData->m_volume >> REDSOUND_FIXED_SHIFT); + SetVoiceVolumeMix(streamData->m_voiceData + channel, streamData->m_pan.m_value >> REDSOUND_FIXED_SHIFT, + streamData->m_volume.m_value >> REDSOUND_FIXED_SHIFT); (streamData->m_track + channel)->m_waveBase = streamData->m_aramBuffer + channel * REDSOUND_STREAM_STEREO_PLANE_SIZE; - memset(&streamData->m_trackData[channel], 0, sizeof(RedWaveDATA)); - memcpy(&streamData->m_trackData[channel].m_adpcm, &headerData[channel], sizeof(RedStreamADPCMHeader)); - voice->m_adsrLevel[REDSOUND_VOICE_ADSR_ATTACK] = voice->m_adsrLevel[REDSOUND_VOICE_ADSR_DECAY] = - voice->m_adsrLevel[REDSOUND_VOICE_ADSR_SUSTAIN] = 0; - voice->m_adsrLevel[REDSOUND_VOICE_ADSR_RELEASE] = REDSOUND_VOLUME_MAX; - voice->m_adsrTime[REDSOUND_VOICE_ADSR_ATTACK] = voice->m_adsrTime[REDSOUND_VOICE_ADSR_DECAY] = - voice->m_adsrTime[REDSOUND_VOICE_ADSR_SUSTAIN] = 0; - voice->m_adsrTime[REDSOUND_VOICE_ADSR_RELEASE] = 10; + memset(&streamData->m_trackData[channel], 0, REDSOUND_WAVE_DATA_SIZE); + memcpy(&streamData->m_trackData[channel].m_adpcm, &headerData[channel], REDSOUND_STREAM_ADPCM_HEADER_SIZE); + voice->m_adsr.m_level[REDSOUND_VOICE_ADSR_ATTACK] = voice->m_adsr.m_level[REDSOUND_VOICE_ADSR_DECAY] = + voice->m_adsr.m_level[REDSOUND_VOICE_ADSR_SUSTAIN] = 0; + voice->m_adsr.m_level[REDSOUND_VOICE_ADSR_RELEASE] = REDSOUND_VOLUME_MAX; + voice->m_adsr.m_time[REDSOUND_VOICE_ADSR_ATTACK] = voice->m_adsr.m_time[REDSOUND_VOICE_ADSR_DECAY] = + voice->m_adsr.m_time[REDSOUND_VOICE_ADSR_SUSTAIN] = 0; + voice->m_adsr.m_time[REDSOUND_VOICE_ADSR_RELEASE] = REDSOUND_STREAM_ADSR_RELEASE_TIME; streamData->m_trackData[channel].m_sampleStart = 0; streamData->m_trackData[channel].m_loopEnd = REDSOUND_STREAM_INITIAL_LOOP_END; - streamData->m_trackData[channel].m_loopStart = 2; + streamData->m_trackData[channel].m_loopStart = REDSOUND_STREAM_LOOP_START_SAMPLE; channel += 1; } while (channel < streamData->m_header.m_channelCount); int dmaID; - if (streamData->m_header.m_loopStart < 0) { + if (streamData->m_header.m_loopStart < REDSOUND_STREAM_LOOP_ENABLED_MIN) { dmaID = _ArrangeStreamDataNoLoop(streamData, 0, REDSOUND_STREAM_STEREO_PLANE_SIZE); } else { dmaID = _ArrangeStreamDataLoop(streamData, 0, REDSOUND_STREAM_STEREO_PLANE_SIZE); @@ -453,14 +568,14 @@ int StreamPlay(int streamID, void* streamHeader, int fileSize, int pan, int volu streamData->m_streamCursorBase = REDSOUND_STREAM_PAGE_SIZE; streamData->m_state = REDSOUND_STREAM_STATE_LOADING; } else { - if (m_ReportPrint != 0) { + if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { OSReport(sRedStreamBufferDidntSecureFmt, sRedStreamLogPrefix, sRedStreamLogErrorColor, sRedStreamLogReset); fflush(__files + 1); } if (streamData->m_buffer != 0) { RedDelete(streamData->m_buffer); } else { - if (m_ReportPrint != 0) { + if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { OSReport(sRedStreamMainMemoryDidntCreateFmt, sRedStreamLogPrefix, sRedStreamLogWarnColor, REDSOUND_STREAM_TRANSFER_BUFFER_SIZE, sRedStreamLogReset); @@ -470,7 +585,7 @@ int StreamPlay(int streamID, void* streamHeader, int fileSize, int pan, int volu if (streamData->m_aramBuffer != 0) { RedDeleteA(streamData->m_aramBuffer); } else { - if (m_ReportPrint != 0) { + if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { OSReport(sRedStreamAramMemoryDidntCreateFmt, sRedStreamLogPrefix, sRedStreamLogWarnColor, streamData->m_header.m_channelCount * REDSOUND_STREAM_STEREO_PLANE_SIZE, @@ -499,7 +614,7 @@ void SetStreamVolume(int streamID, int volume, int frameCount) if (frameCount < 1) { frameCount = 1; } else { - frameCount *= REDSOUND_MUSIC_FADE_TICKS_PER_SECOND; + frameCount *= REDSOUND_STREAM_FADE_TICKS_PER_SECOND; frameCount /= REDSOUND_FRAMES_PER_SECOND; } @@ -514,14 +629,55 @@ void SetStreamVolume(int streamID, int volume, int frameCount) streamData = p_Stream; do { - if ((streamData->m_streamId != 0) && ((streamID == -1) || (streamID == streamData->m_streamId))) { + if ((streamData->m_streamId != REDSOUND_STREAM_ID_NONE) && + ((streamID == REDSOUND_STREAM_ID_ALL) || (streamID == streamData->m_streamId))) { + if (frameCount > 0) { + int delta = volume - streamData->m_volume.m_value; + streamData->m_volume.m_step = delta / frameCount; + streamData->m_volume.m_stepCount = frameCount; + } else { + streamData->m_volume.m_value = volume; + streamData->m_volume.m_stepCount = 0; + } + } + streamData++; + } while (streamData < p_Stream + REDSOUND_STREAM_COUNT); +} + +/* + * --INFO-- + * PAL Address: UNUSED + * PAL Size: 184b + * EN Address: TODO + * EN Size: TODO + * JP Address: TODO + * JP Size: TODO + */ +void SetStreamPan(int streamID, int pan, int frameCount) +{ + volatile RedStreamDATA* streamData; + + if (frameCount < 1) { + frameCount = 1; + } else { + frameCount *= REDSOUND_STREAM_FADE_TICKS_PER_SECOND; + frameCount /= REDSOUND_FRAMES_PER_SECOND; + } + + pan &= REDSOUND_PAN_BYTE_MASK; + pan <<= REDSOUND_FIXED_SHIFT; + pan |= REDSOUND_FIXED_HALF; + streamData = p_Stream; + do { + if ((streamData->m_streamId != REDSOUND_STREAM_ID_NONE) && + ((streamID == REDSOUND_STREAM_ID_ALL) || (streamID == streamData->m_streamId))) { if (frameCount > 0) { - int delta = volume - streamData->m_volume; - streamData->m_volumeStep = delta / frameCount; - streamData->m_volumeStepCount = frameCount; + int delta = pan - streamData->m_pan.m_value; + streamData->m_pan.m_step = delta / frameCount; + streamData->m_pan.m_stepCount = frameCount; } else { - streamData->m_volume = volume; - streamData->m_volumeStepCount = 0; + streamData->m_pan.m_value = pan; + streamData->m_pan.m_stepCount = 0; } } streamData++; @@ -544,7 +700,7 @@ void StreamPause(int streamID, int pause) int volume; int pan; - if (m_ReportPrint != 0) { + if (m_ReportPrint != REDSOUND_REPORT_PRINT_OFF) { if (pause == REDSOUND_PAUSE_ON) { OSReport(sRedStreamPauseOnFmt, sRedStreamLogPrefix, streamID); } else { @@ -554,7 +710,8 @@ void StreamPause(int streamID, int pause) } streamData = p_Stream; do { - if ((streamData->m_streamId != 0) && ((streamID == -1) || (streamID == streamData->m_streamId))) { + if ((streamData->m_streamId != REDSOUND_STREAM_ID_NONE) && + ((streamID == REDSOUND_STREAM_ID_ALL) || (streamID == streamData->m_streamId))) { voiceData = streamData->m_voiceData; if (pause == REDSOUND_PAUSE_ON) { if (voiceData->m_axVoice != 0) { @@ -568,14 +725,14 @@ void StreamPause(int streamID, int pause) } else if (voiceData->m_axVoice != 0) { unsigned int pitch = PitchCompute(REDSOUND_STREAM_BASE_PITCH, 0, streamData->m_header.m_pitch, 0); short channelCount = streamData->m_header.m_channelCount; - volume = streamData->m_volume >> REDSOUND_FIXED_SHIFT; + volume = streamData->m_volume.m_value >> REDSOUND_FIXED_SHIFT; if (channelCount == REDSOUND_STREAM_STEREO_CHANNEL_COUNT) { voiceData->m_targetPitch = pitch; voiceData->m_flags |= REDSOUND_VOICE_FLAGS_PITCH_DIRTY; voiceData[REDSOUND_STREAM_RIGHT_CHANNEL].m_targetPitch = pitch; voiceData[REDSOUND_STREAM_RIGHT_CHANNEL].m_flags |= REDSOUND_VOICE_FLAGS_PITCH_DIRTY; } else { - pan = streamData->m_pan >> REDSOUND_FIXED_SHIFT; + pan = streamData->m_pan.m_value >> REDSOUND_FIXED_SHIFT; voiceData->m_targetPitch = pitch; voiceData->m_flags |= REDSOUND_VOICE_FLAGS_PITCH_DIRTY; } @@ -613,7 +770,7 @@ void StreamControl() samplePos |= voiceData->m_axVoice->pb.addr.currentAddressLo; if ((samplePos >= sampleStart) && (samplePos < sampleStart + REDSOUND_STREAM_STEREO_PLANE_SIZE)) { int stopped = 0; - if (streamData->m_header.m_loopStart < 0) { + if (streamData->m_header.m_loopStart < REDSOUND_STREAM_LOOP_ENABLED_MIN) { streamData->m_header.m_loopEnd = streamData->m_header.m_loopEnd - REDSOUND_STREAM_SAMPLE_ADVANCE; if (streamData->m_header.m_loopEnd < 1) { _StreamStop(streamData); @@ -636,7 +793,7 @@ void StreamControl() streamData->m_streamCursorBase = REDSOUND_STREAM_PAGE_SIZE; } - if (streamData->m_header.m_loopStart < 0) { + if (streamData->m_header.m_loopStart < REDSOUND_STREAM_LOOP_ENABLED_MIN) { dmaID = _ArrangeStreamDataNoLoop(streamData, side, REDSOUND_STREAM_PAGE_SIZE); } else { dmaID = _ArrangeStreamDataLoop(streamData, side, REDSOUND_STREAM_PAGE_SIZE); @@ -646,24 +803,25 @@ void StreamControl() } int changed = 0; - if (streamData->m_panStepCount != 0) { + if (streamData->m_pan.m_stepCount != 0) { changed += 1; - streamData->m_panStepCount -= 1; - streamData->m_pan += streamData->m_panStep; + streamData->m_pan.m_stepCount -= 1; + streamData->m_pan.m_value += streamData->m_pan.m_step; } - if (streamData->m_volumeStepCount != 0) { + if (streamData->m_volume.m_stepCount != 0) { changed += 1; - streamData->m_volumeStepCount -= 1; - streamData->m_volume += streamData->m_volumeStep; + streamData->m_volume.m_stepCount -= 1; + streamData->m_volume.m_value += streamData->m_volume.m_step; } if (changed != 0) { if (streamData->m_header.m_channelCount == REDSOUND_STREAM_STEREO_CHANNEL_COUNT) { - SetVoiceVolumeMix(voiceData, 0, streamData->m_volume >> REDSOUND_FIXED_SHIFT); + SetVoiceVolumeMix(voiceData, 0, streamData->m_volume.m_value >> REDSOUND_FIXED_SHIFT); voiceData += 1; - SetVoiceVolumeMix(voiceData, REDSOUND_VOLUME_MAX, streamData->m_volume >> REDSOUND_FIXED_SHIFT); + SetVoiceVolumeMix(voiceData, REDSOUND_VOLUME_MAX, + streamData->m_volume.m_value >> REDSOUND_FIXED_SHIFT); } else { - SetVoiceVolumeMix(voiceData, streamData->m_pan >> REDSOUND_FIXED_SHIFT, - streamData->m_volume >> REDSOUND_FIXED_SHIFT); + SetVoiceVolumeMix(voiceData, streamData->m_pan.m_value >> REDSOUND_FIXED_SHIFT, + streamData->m_volume.m_value >> REDSOUND_FIXED_SHIFT); } } } @@ -673,12 +831,12 @@ void StreamControl() streamData->m_state = REDSOUND_STREAM_STATE_PLAYING; voiceData->m_flags |= REDSOUND_VOICE_FLAGS_STREAM_START; voiceData->m_waveData = streamData->m_trackData; - voiceData->m_active = 1; + voiceData->m_active = REDSOUND_VOICE_ACTIVE_ON; if (streamData->m_header.m_channelCount == REDSOUND_STREAM_STEREO_CHANNEL_COUNT) { voiceData[REDSOUND_STREAM_RIGHT_CHANNEL].m_flags |= REDSOUND_VOICE_FLAGS_STREAM_START; voiceData[REDSOUND_STREAM_RIGHT_CHANNEL].m_waveData = &streamData->m_trackData[REDSOUND_STREAM_RIGHT_CHANNEL]; - voiceData[REDSOUND_STREAM_RIGHT_CHANNEL].m_active = 1; + voiceData[REDSOUND_STREAM_RIGHT_CHANNEL].m_active = REDSOUND_VOICE_ACTIVE_ON; } } diff --git a/src/memory.cpp b/src/memory.cpp index e027d84236..cef9af0b29 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -95,9 +95,6 @@ long long DAT_8032ec58; extern char DAT_8032f7e8[]; extern char DAT_8032f808[]; extern "C" void Printf__7CSystemFPce(CSystem* system, const char* format, ...); -extern "C" int DMAEntry__9CRedSoundFiiiiiPFPv_vPv( - CRedSound*, int, int, int, int, int, void (*)(void*), void*); -extern "C" int DMACheck__9CRedSoundFi(CRedSound*, int); extern "C" void _GXSetBlendMode__F12_GXBlendMode14_GXBlendFactor14_GXBlendFactor10_GXLogicOp(int, int, int, int); extern "C" void _GXSetAlphaCompare__F10_GXCompareUc10_GXAlphaOp10_GXCompareUc(int, int, int, int, int); extern "C" void _GXSetTevSwapMode__F13_GXTevStageID13_GXTevSwapSel13_GXTevSwapSel(int, int, int); @@ -959,11 +956,11 @@ void CMemory::CopyFromAMemory(void*, void*, unsigned long) */ void CMemory::CopyToAMemorySync(void* source, void* dest, unsigned long size) { - int dmaId = DMAEntry__9CRedSoundFiiiiiPFPv_vPv(RedSound(&Sound), 0, 0, reinterpret_cast(source), - reinterpret_cast(dest), static_cast(size), 0, 0); + int dmaId = RedSound(&Sound)->DMAEntry(0, 0, reinterpret_cast(source), reinterpret_cast(dest), + static_cast(size), 0, 0); CStopWatch watch(const_cast(s_stopwatchNoName)); watch.Start(); - while (DMACheck__9CRedSoundFi(RedSound(&Sound), dmaId) != 0) { + while (RedSound(&Sound)->DMACheck(dmaId) != 0) { watch.Stop(); watch.Get(); watch.Start(); @@ -982,11 +979,11 @@ void CMemory::CopyToAMemorySync(void* source, void* dest, unsigned long size) void CMemory::CopyFromAMemorySync(void* source, void* dest, unsigned long size) { CStopWatch watch(const_cast(s_stopwatchNoName)); - int dmaId = DMAEntry__9CRedSoundFiiiiiPFPv_vPv(RedSound(&Sound), 0, 1, reinterpret_cast(source), - reinterpret_cast(dest), static_cast(size), 0, 0); + int dmaId = RedSound(&Sound)->DMAEntry(0, 1, reinterpret_cast(source), reinterpret_cast(dest), + static_cast(size), 0, 0); watch.Start(); float timeout = FLOAT_8032f7d8; - while (DMACheck__9CRedSoundFi(RedSound(&Sound), dmaId) != 0) { + while (RedSound(&Sound)->DMACheck(dmaId) != 0) { watch.Stop(); if (watch.Get() < timeout) { watch.Start(); @@ -1789,13 +1786,12 @@ int CAmemCacheSet::GetData(short index, char* source, int line) m_rStage->alloc(static_cast(entry.m_size), allocSource, static_cast(line), 1)); entry.m_cacheData = reinterpret_cast(data); if (data != 0) { - int dmaId = DMAEntry__9CRedSoundFiiiiiPFPv_vPv( - RedSound(&Sound), 0, 1, reinterpret_cast(entry.m_cacheData), - reinterpret_cast(entry.m_workData), entry.m_size, 0, 0); + int dmaId = RedSound(&Sound)->DMAEntry(0, 1, reinterpret_cast(entry.m_cacheData), + reinterpret_cast(entry.m_workData), entry.m_size, 0, 0); CStopWatch watch(const_cast(s_stopwatchNoName)); watch.Start(); float timeout = FLOAT_8032f7d8; - while (DMACheck__9CRedSoundFi(RedSound(&Sound), dmaId) != 0) { + while (RedSound(&Sound)->DMACheck(dmaId) != 0) { watch.Stop(); if (watch.Get() < timeout) { watch.Start(); @@ -1900,11 +1896,11 @@ int CAmemCacheSet::SetData(void* src, int size, CAmemCache::TYPE type, int dmaCo if (entry.m_dmaCopy == 0) { memcpy(entry.m_workData, src, static_cast(entry.m_size)); } else { - int dmaId = DMAEntry__9CRedSoundFiiiiiPFPv_vPv( - RedSound(&Sound), 0, 0, reinterpret_cast(src), reinterpret_cast(entry.m_workData), entry.m_size, 0, 0); + int dmaId = RedSound(&Sound)->DMAEntry(0, 0, reinterpret_cast(src), + reinterpret_cast(entry.m_workData), entry.m_size, 0, 0); CStopWatch watch(const_cast(s_stopwatchNoName)); watch.Start(); - while (DMACheck__9CRedSoundFi(RedSound(&Sound), dmaId) != 0) { + while (RedSound(&Sound)->DMACheck(dmaId) != 0) { watch.Stop(); watch.Get(); watch.Start(); @@ -1952,11 +1948,11 @@ int CAmemCacheSet::SetData(void* src, int size, CAmemCache::TYPE type, int dmaCo if (entry.m_dmaCopy == 0) { memcpy(entry.m_workData, src, static_cast(entry.m_size)); } else { - int dmaId = DMAEntry__9CRedSoundFiiiiiPFPv_vPv( - RedSound(&Sound), 0, 0, reinterpret_cast(src), reinterpret_cast(entry.m_workData), entry.m_size, 0, 0); + int dmaId = RedSound(&Sound)->DMAEntry(0, 0, reinterpret_cast(src), + reinterpret_cast(entry.m_workData), entry.m_size, 0, 0); CStopWatch watch(const_cast(s_stopwatchNoName)); watch.Start(); - while (DMACheck__9CRedSoundFi(RedSound(&Sound), dmaId) != 0) { + while (RedSound(&Sound)->DMACheck(dmaId) != 0) { watch.Stop(); watch.Get(); watch.Start(); diff --git a/src/sound.cpp b/src/sound.cpp index 2cdf0047f2..8fd26b0213 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -1,5 +1,6 @@ #include "ffcc/sound.h" +#include "ffcc/RedSound/RedGlobals.h" #include "ffcc/RedSound/RedSound.h" #include "ffcc/color.h" #include "ffcc/game.h" @@ -68,56 +69,6 @@ extern double DOUBLE_80330d20; extern double DOUBLE_80330d28; extern "C" void __ct__9CRedSoundFv(void*); extern "C" void __dt__6CSoundFv(void*); -extern "C" unsigned int GetSoundMode__9CRedSoundFv(CRedSound*); -extern "C" void SetSoundMode__9CRedSoundFi(CRedSound*, int); -extern "C" void Init__9CRedSoundFPviii(CRedSound*, void*, int, int, int); -extern "C" void End__9CRedSoundFv(CRedSound*); -extern "C" int StreamPlayState__9CRedSoundFi(CRedSound*, int); -extern "C" void StreamStop__9CRedSoundFi(CRedSound*, int); -extern "C" int StreamPlay__9CRedSoundFPviii(CRedSound*, void*, int, int, int); -extern "C" void StreamVolume__9CRedSoundFiii(CRedSound*, int, int, int); -extern "C" int ReentryWaveData__9CRedSoundFi(CRedSound*, int); -extern "C" int ReentrySeSepData__9CRedSoundFi(CRedSound*, int); -extern "C" void SetSeSepData__9CRedSoundFPv(CRedSound*, void*); -extern "C" int SePlayState__9CRedSoundFi(CRedSound*, int); -extern "C" int ReportSeLoop__9CRedSoundFi(CRedSound*, int); -extern "C" int GetSeVolume__9CRedSoundFii(CRedSound*, int, int); -extern "C" unsigned int GetProgramTime__9CRedSoundFv(CRedSound*); -extern "C" void GetStreamPlayPoint__9CRedSoundFiPiPi(CRedSound*, int, int*, int*); -extern "C" unsigned int SetWaveData__9CRedSoundFiPvi(CRedSound*, int, void*, int); -extern "C" int ReportStandby__9CRedSoundFi(CRedSound*, int); -extern "C" void SePause__9CRedSoundFii(CRedSound*, int, int); -extern "C" void StreamPause__9CRedSoundFii(CRedSound*, int, int); -extern "C" void ReportPrint__9CRedSoundFi(CRedSound*, int); -extern "C" void TestProcess__9CRedSoundFi(CRedSound*, int); -extern "C" void DisplayWaveInfo__9CRedSoundFv(CRedSound*); -extern "C" void DisplaySePlayInfo__9CRedSoundFv(CRedSound*); -extern "C" void SeStop__9CRedSoundFi(CRedSound*, int); -extern "C" void SeStopMG__9CRedSoundFiiii(CRedSound*, int, int, int, int); -extern "C" void SeFadeOut__9CRedSoundFii(CRedSound*, int, int); -extern "C" void SePan__9CRedSoundFiii(CRedSound*, int, int, int); -extern "C" void SePitch__9CRedSoundFiii(CRedSound*, int, int, int); -extern "C" void SeVolume__9CRedSoundFiii(CRedSound*, int, int, int); -extern "C" int SePlay__9CRedSoundFiiiii(CRedSound*, int, int, int, int, int); -extern "C" void ClearSeSepData__9CRedSoundFi(CRedSound*, int); -extern "C" void ClearSeSepDataMG__9CRedSoundFiiii(CRedSound*, int, int, int, int); -extern "C" void ClearWaveData__9CRedSoundFi(CRedSound*, int); -extern "C" void ClearWaveDataM__9CRedSoundFiiii(CRedSound*, int, int, int, int); -extern "C" void MusicVolume__9CRedSoundFiii(CRedSound*, int, int, int); -extern "C" void MusicMasterVolume__9CRedSoundFi(CRedSound*, int); -extern "C" void SeMasterVolume__9CRedSoundFi(CRedSound*, int); -extern "C" int ReentryMusicData__9CRedSoundFi(CRedSound*, int); -extern "C" void SetMusicData__9CRedSoundFPv(CRedSound*, void*); -extern "C" void MusicStop__9CRedSoundFi(CRedSound*, int); -extern "C" void MusicPlay__9CRedSoundFiii(CRedSound*, int, int, int); -extern "C" void MusicCrossPlay__9CRedSoundFiii(CRedSound*, int, int, int); -extern "C" void MusicNextPlay__9CRedSoundFiii(CRedSound*, int, int, int); -extern "C" void MusicFadeOut__9CRedSoundFii(CRedSound*, int, int); -extern "C" void SetMusicPhraseStop__9CRedSoundFi(CRedSound*, int); -extern "C" void SetReverb__9CRedSoundFii(CRedSound*, int, int); -extern "C" void SetReverbDepth__9CRedSoundFiii(CRedSound*, int, int, int); -extern "C" void ClearWaveBank__9CRedSoundFi(CRedSound*, int); -extern "C" void SetSeBlockData__9CRedSoundFiPv(CRedSound*, int, void*); extern "C" CMemory::CStage* CreateStage__7CMemoryFUlPci(CMemory*, unsigned long, char*, int); extern "C" void DestroyStage__7CMemoryFPQ27CMemory6CStage(CMemory*, CMemory::CStage*); extern "C" void* __nwa__FUlPQ27CMemory6CStagePci(unsigned long, CMemory::CStage*, char*, int); @@ -449,17 +400,16 @@ void CSound::Init() ARInit(0, 0); ARQInit(); - Init__9CRedSoundFPviii(RedSound(this), SoundData(this).m_aramBuffer, 0x80000, 0x800000, 0x800000); - ReportPrint__9CRedSoundFi( - RedSound(this), (-SoundData(this).m_debugPrint | SoundData(this).m_debugPrint) >> 31); + RedSound(this)->Init(SoundData(this).m_aramBuffer, 0x80000, 0x800000, 0x800000); + RedSound(this)->ReportPrint((-SoundData(this).m_debugPrint | SoundData(this).m_debugPrint) >> 31); - u32 soundMode = GetSoundMode__9CRedSoundFv(RedSound(this)); - SetSoundMode__9CRedSoundFi(RedSound(this), (u32)__cntlzw((u32)__cntlzw(soundMode) >> 5) >> 5); + u32 soundMode = RedSound(this)->GetSoundMode(); + RedSound(this)->SetSoundMode((u32)__cntlzw((u32)__cntlzw(soundMode) >> 5) >> 5); - MusicMasterVolume__9CRedSoundFi(RedSound(this), SoundData(this).m_bgmMasterVolume); - SeMasterVolume__9CRedSoundFi(RedSound(this), SoundData(this).m_seMasterVolume); - SetReverb__9CRedSoundFii(RedSound(this), 1, 4); - SetReverbDepth__9CRedSoundFiii(RedSound(this), 1, 0x40, 0xF); + RedSound(this)->MusicMasterVolume(SoundData(this).m_bgmMasterVolume); + RedSound(this)->SeMasterVolume(SoundData(this).m_seMasterVolume); + RedSound(this)->SetReverb(1, 4); + RedSound(this)->SetReverbDepth(1, 0x40, 0xF); SoundData(this).m_waveFile = 0; SoundData(this).m_streamFile = 0; @@ -490,15 +440,15 @@ void CSound::Quit() Printf__7CSystemFPce(&System, s_soundLoadWaveErrorFmt); } - SetWaveData__9CRedSoundFiPvi(redSound, -1, nullptr, 0); + redSound->SetWaveData(-1, nullptr, 0); int shouldStopStream = 0; - if (sound.m_streamPlaying != 0 && StreamPlayState__9CRedSoundFi(redSound, sound.m_streamID) != 0) { + if (sound.m_streamPlaying != 0 && redSound->StreamPlayState(sound.m_streamID) != 0) { shouldStopStream = 1; } if (shouldStopStream != 0) { - StreamStop__9CRedSoundFi(redSound, sound.m_streamID); + redSound->StreamStop(sound.m_streamID); } CFile::CHandle*& streamFile = sound.m_streamFile; @@ -509,23 +459,23 @@ void CSound::Quit() sound.m_streamPlaying = 0; - SeStop__9CRedSoundFi(redSound, -1); - ClearSeSepData__9CRedSoundFi(redSound, -1); - ClearWaveData__9CRedSoundFi(redSound, -3); + redSound->SeStop(-1); + redSound->ClearSeSepData(-1); + redSound->ClearWaveData(-3); sound.m_seCount = 10000000; memset(sound.m_seWork, 0, sizeof(sound.m_seWork)); memset(sound.m_noFreeSeGroups, 0xFF, sizeof(sound.m_noFreeSeGroups)); memset(sound.m_noFreeWaves, 0xFF, sizeof(sound.m_noFreeWaves)); - ClearWaveBank__9CRedSoundFi(redSound, 500); - ClearWaveBank__9CRedSoundFi(redSound, 0); + redSound->ClearWaveBank(500); + redSound->ClearWaveBank(0); for (int i = 0; i < 4; i++) { - SetSeBlockData__9CRedSoundFiPv(redSound, i, nullptr); + redSound->SetSeBlockData(i, nullptr); } - End__9CRedSoundFv(redSound); + redSound->End(); u8*& streamBuffer = sound.m_streamBuffer; if (streamBuffer != 0) { @@ -635,7 +585,7 @@ void CSound::Realloc(int isMinMemoryMode) bool wasStreaming = false; if (streamPlaying != 0) { - if (StreamPlayState__9CRedSoundFi(redSound, streamID) != 0) { + if (redSound->StreamPlayState(streamID) != 0) { wasStreaming = true; } } @@ -675,7 +625,7 @@ void CSound::Realloc(int isMinMemoryMode) u32 reportFlag = sound.m_debugPrint; redSound->ReportPrint(((-reportFlag) | reportFlag) >> 31); - u32 soundMode = GetSoundMode__9CRedSoundFv(redSound); + u32 soundMode = redSound->GetSoundMode(); redSound->SetSoundMode((u32)__cntlzw((u32)__cntlzw(soundMode) >> 5) >> 5); redSound->MusicMasterVolume(sound.m_bgmMasterVolume); @@ -695,7 +645,7 @@ void CSound::Realloc(int isMinMemoryMode) return; } - if (ReentryWaveData__9CRedSoundFi(redSound, 0) == -1) { + if (redSound->ReentryWaveData(0) == -1) { if (waveFile != 0) { File.Close(waveFile); waveFile = 0; @@ -719,7 +669,7 @@ void CSound::Realloc(int isMinMemoryMode) } } - if (ReentryWaveData__9CRedSoundFi(redSound, 500) == -1) { + if (redSound->ReentryWaveData(500) == -1) { if (waveFile != 0) { File.Close(waveFile); waveFile = 0; @@ -763,7 +713,7 @@ void CSound::Realloc(int isMinMemoryMode) */ float CSound::GetPerformance() { - unsigned int programTime = GetProgramTime__9CRedSoundFv(RedSound(this)); + unsigned int programTime = RedSound(this)->GetProgramTime(); float numer = (float)(programTime / 0xF); float denom = (float)(((OS_TIMER_CLOCK / 125000) * 0x8235) >> 3); return 100.0f * (numer / denom); @@ -783,9 +733,8 @@ void CSound::PauseDiscError(int pause) u8* self = reinterpret_cast(this); if (reinterpret_cast(self)->m_pauseAllSe == 0) { - SePause__9CRedSoundFii(reinterpret_cast(self + 8), -1, static_cast(-pause | pause) >> 31); - StreamPause__9CRedSoundFii(reinterpret_cast(self + 8), -1, - (-static_cast(pause) | static_cast(pause)) >> 31); + RedSound(this)->SePause(-1, static_cast(-pause | pause) >> 31); + RedSound(this)->StreamPause(-1, (-static_cast(pause) | static_cast(pause)) >> 31); } } @@ -798,14 +747,15 @@ void CSound::CheckDriver(int mode) { u8* self = reinterpret_cast(this); CSoundLayout& sound = *reinterpret_cast(self); + CRedSound* redSound = RedSound(this); unsigned int oldPrint = sound.m_debugPrint; sound.m_debugPrint = 1; - ReportPrint__9CRedSoundFi(reinterpret_cast(self + 8), 1); - TestProcess__9CRedSoundFi(reinterpret_cast(self + 8), mode); - DisplayWaveInfo__9CRedSoundFv(reinterpret_cast(self + 8)); - DisplaySePlayInfo__9CRedSoundFv(reinterpret_cast(self + 8)); + redSound->ReportPrint(1); + redSound->TestProcess(mode); + redSound->DisplayWaveInfo(); + redSound->DisplaySePlayInfo(); sound.m_debugPrint = oldPrint; - ReportPrint__9CRedSoundFi(reinterpret_cast(self + 8), (-oldPrint | oldPrint) >> 0x1F); + redSound->ReportPrint((-oldPrint | oldPrint) >> 0x1F); } /* @@ -843,27 +793,27 @@ void CSound::Frame() seNo = -1; } else if (seNo < 4000) { int bank = seNo / 1000; - seNo = SePlay__9CRedSoundFiiiii(redSound, bank, seNo % 1000, pan, 0, 0); - SeVolume__9CRedSoundFiii(redSound, seNo, vol, 0x1E); + seNo = redSound->SePlay(bank, seNo % 1000, pan, 0, 0); + redSound->SeVolume(seNo, vol, 0x1E); } else { - seNo = SePlay__9CRedSoundFiiiii(redSound, -1, seNo, pan, 0, 0); - SeVolume__9CRedSoundFiii(redSound, seNo, vol, 0x1E); + seNo = redSound->SePlay(-1, seNo, pan, 0, 0); + redSound->SeVolume(seNo, vol, 0x1E); } *reinterpret_cast(se + 8) = seNo; *se &= 0xBF; } } else { - if (SePlayState__9CRedSoundFi(redSound, *reinterpret_cast(se + 8)) == 0) { + if (redSound->SePlayState(*reinterpret_cast(se + 8)) == 0) { *se &= 0x7F; } else { - int playing = ReportSeLoop__9CRedSoundFi(redSound, *reinterpret_cast(se + 8)); + int playing = redSound->ReportSeLoop(*reinterpret_cast(se + 8)); if ((playing != 0) && - (GetSeVolume__9CRedSoundFii(redSound, *reinterpret_cast(se + 8), 0) == 0) && - (GetSeVolume__9CRedSoundFii(redSound, *reinterpret_cast(se + 8), 1) == 0)) { + (redSound->GetSeVolume(*reinterpret_cast(se + 8), REDSOUND_SE_VOLUME_QUERY_VALUE) == 0) && + (redSound->GetSeVolume(*reinterpret_cast(se + 8), REDSOUND_SE_VOLUME_QUERY_DELTA) == 0)) { if ((*reinterpret_cast(CFlat + 0x129C) & 0x400000) != 0) { Printf__7CSystemFPce(&System, s_soundEnvSeStopFmt, *reinterpret_cast(se + 0xC)); } - SeStop__9CRedSoundFi(redSound, *reinterpret_cast(se + 8)); + redSound->SeStop(*reinterpret_cast(se + 8)); *se = (*se & 0xBF) | 0x40; goto next; } @@ -872,7 +822,7 @@ void CSound::Frame() if (*reinterpret_cast(se + 8) < 0) { Printf__7CSystemFPce(&System, s_soundMinusOneFmt); } else { - SePan__9CRedSoundFiii(redSound, *reinterpret_cast(se + 8), pan, 0x1E); + redSound->SePan(*reinterpret_cast(se + 8), pan, 0x1E); } se[2] = static_cast(pan); } @@ -881,7 +831,7 @@ void CSound::Frame() if (*reinterpret_cast(se + 8) < 0) { Printf__7CSystemFPce(&System, s_soundMinusOneFmt); } else { - SeVolume__9CRedSoundFiii(redSound, *reinterpret_cast(se + 8), volume, 0x1E); + redSound->SeVolume(*reinterpret_cast(se + 8), volume, 0x1E); } se[1] = static_cast(volume); } @@ -903,7 +853,7 @@ void CSound::Frame() } } - MusicVolume__9CRedSoundFiii(RedSound(this), -1, sound.m_curMusicVolume, 0); + RedSound(this)->MusicVolume(-1, sound.m_curMusicVolume, 0); } /* @@ -999,9 +949,9 @@ void CSound::loadWaveFrame() waveOffset += (int)readSize; waveState = 1; } else if (waveState == 1 && File.IsCompleted(waveFile)) { - SetWaveData__9CRedSoundFiPvi(redSound, waveID, File.m_readBuffer, (int)waveFile->m_chunkSize); + redSound->SetWaveData(waveID, File.m_readBuffer, (int)waveFile->m_chunkSize); - while (ReportStandby__9CRedSoundFi(RedSound(&Sound), 0) != 0) { + while (RedSound(&Sound)->ReportStandby(0) != 0) { } waveState = 0; @@ -1017,7 +967,7 @@ void CSound::loadWaveFrame() bool streamPlaying = false; int& isStreamEnabled = sound.m_streamPlaying; int& streamID = sound.m_streamID; - if (isStreamEnabled != 0 && StreamPlayState__9CRedSoundFi(redSound, streamID) != 0) { + if (isStreamEnabled != 0 && redSound->StreamPlayState(streamID) != 0) { streamPlaying = true; } @@ -1031,7 +981,7 @@ void CSound::loadWaveFrame() if (streamState == 0) { int playPoint[2]; - GetStreamPlayPoint__9CRedSoundFiPiPi(redSound, streamID, &playPoint[0], &playPoint[1]); + redSound->GetStreamPlayPoint(streamID, &playPoint[0], &playPoint[1]); unsigned int curHalf = (unsigned int)(playPoint[0] >> 16); if (streamHalf != curHalf) { @@ -1078,7 +1028,7 @@ void CSound::LoadWaveASync(int waveNo, int waveId, int syncMode) { if (waveNo < 0) { Printf__7CSystemFPce(&System, s_soundMinusOneFmt); - } else if (ReentryWaveData__9CRedSoundFi(RedSound(this), waveNo) == -1) { + } else if (RedSound(this)->ReentryWaveData(waveNo) == -1) { CSoundLayout& sound = SoundData(this); CFile::CHandle*& waveFile = sound.m_waveFile; if (waveFile != 0) { @@ -1087,7 +1037,7 @@ void CSound::LoadWaveASync(int waveNo, int waveId, int syncMode) Printf__7CSystemFPce(&System, s_soundLoadWaveErrorFmt); } - SetWaveData__9CRedSoundFiPvi(RedSound(this), -1, nullptr, 0); + RedSound(this)->SetWaveData(-1, nullptr, 0); char wavePath[244]; sprintf(wavePath, s_soundWavePathFmt, waveNo); @@ -1126,7 +1076,7 @@ void CSound::CancelLoadWaveASync() *reinterpret_cast(self + 0x10) = 0; Printf__7CSystemFPce(&System, s_soundLoadWaveErrorFmt); } - SetWaveData__9CRedSoundFiPvi(reinterpret_cast(self + 8), -1, nullptr, 0); + reinterpret_cast(self + 8)->SetWaveData(-1, nullptr, 0); } /* @@ -1159,7 +1109,7 @@ void CSound::LoadBgm(int bgmId) if (bgmId < 0) { Printf__7CSystemFPce(&System, s_soundMinusOneFmt); - } else if (ReentryMusicData__9CRedSoundFi(redSound, bgmId) == -1) { + } else if (redSound->ReentryMusicData(bgmId) == -1) { char musicPath[256]; sprintf(musicPath, s_soundMusicPathFmt, bgmId); @@ -1167,7 +1117,7 @@ void CSound::LoadBgm(int bgmId) if (handle != 0) { File.Read(handle); File.SyncCompleted(handle); - SetMusicData__9CRedSoundFPv(redSound, File.m_readBuffer); + redSound->SetMusicData(File.m_readBuffer); File.Close(handle); } } @@ -1184,14 +1134,14 @@ void CSound::LoadBgm(int bgmId) */ void CSound::PlayBgm(int bgmId) { - u8* self = reinterpret_cast(this); + CRedSound* redSound = RedSound(this); if (bgmId < 0) { Printf__7CSystemFPce(&System, s_soundMinusOneFmt); } else { - MusicStop__9CRedSoundFi(reinterpret_cast(self + 8), -1); - SetMusicPhraseStop__9CRedSoundFi(reinterpret_cast(self + 8), 0); - MusicPlay__9CRedSoundFiii(reinterpret_cast(self + 8), bgmId, 0x7F, 0); + redSound->MusicStop(-1); + redSound->SetMusicPhraseStop(REDSOUND_MUSIC_PHRASE_STOP_OFF); + redSound->MusicPlay(bgmId, 0x7F, 0); } } @@ -1206,13 +1156,13 @@ void CSound::PlayBgm(int bgmId) */ void CSound::CrossPlayBgm(int bgmId, int crossFrames) { - u8* self = reinterpret_cast(this); + CRedSound* redSound = RedSound(this); if (bgmId < 0) { Printf__7CSystemFPce(&System, s_soundMinusOneFmt); } else { - SetMusicPhraseStop__9CRedSoundFi(reinterpret_cast(self + 8), 0); - MusicCrossPlay__9CRedSoundFiii(reinterpret_cast(self + 8), bgmId, 0x7F, crossFrames); + redSound->SetMusicPhraseStop(REDSOUND_MUSIC_PHRASE_STOP_OFF); + redSound->MusicCrossPlay(bgmId, 0x7F, crossFrames); } } @@ -1227,13 +1177,13 @@ void CSound::CrossPlayBgm(int bgmId, int crossFrames) */ void CSound::PlayNextBgm(int bgmId) { - u8* self = reinterpret_cast(this); + CRedSound* redSound = RedSound(this); if (bgmId < 0) { Printf__7CSystemFPce(&System, s_soundMinusOneFmt); } else { - MusicNextPlay__9CRedSoundFiii(reinterpret_cast(self + 8), bgmId, 0x7F, 0); - SetMusicPhraseStop__9CRedSoundFi(reinterpret_cast(self + 8), 1); + redSound->MusicNextPlay(bgmId, 0x7F, 0); + redSound->SetMusicPhraseStop(REDSOUND_MUSIC_PHRASE_STOP_ON); } } @@ -1248,7 +1198,7 @@ void CSound::PlayNextBgm(int bgmId) */ void CSound::StopBgm() { - MusicStop__9CRedSoundFi(RedSound(this), -1); + RedSound(this)->MusicStop(-1); } /* @@ -1262,7 +1212,7 @@ void CSound::StopBgm() */ void CSound::FadeOutBgm(int fadeFrames) { - MusicFadeOut__9CRedSoundFii(RedSound(this), -1, fadeFrames); + RedSound(this)->MusicFadeOut(-1, fadeFrames); } /* @@ -1280,7 +1230,7 @@ void CSound::LoadBlock() CSoundLayout& sound = SoundData(this); CFile::CHandle*& waveFile = sound.m_waveFile; - if (ReentryWaveData__9CRedSoundFi(redSound, 0) == -1) { + if (redSound->ReentryWaveData(0) == -1) { if (waveFile != 0) { File.Close(waveFile); waveFile = 0; @@ -1304,7 +1254,7 @@ void CSound::LoadBlock() } } - if (ReentryWaveData__9CRedSoundFi(redSound, 500) == -1) { + if (redSound->ReentryWaveData(500) == -1) { if (waveFile != 0) { File.Close(waveFile); waveFile = 0; @@ -1352,12 +1302,12 @@ void CSound::LoadBlock() */ void CSound::FreeBlock() { - u8* sound = reinterpret_cast(this); + CRedSound* redSound = RedSound(this); - ClearWaveBank__9CRedSoundFi(reinterpret_cast(sound + 8), 500); - ClearWaveBank__9CRedSoundFi(reinterpret_cast(sound + 8), 0); + redSound->ClearWaveBank(500); + redSound->ClearWaveBank(0); for (int i = 0; i < 4; i++) { - SetSeBlockData__9CRedSoundFiPv(reinterpret_cast(sound + 8), i, 0); + redSound->SetSeBlockData(i, 0); } } @@ -1376,14 +1326,14 @@ void CSound::LoadSe(int seId) if (seId < 0) { Printf__7CSystemFPce(&System, s_soundMinusOneFmt); - } else if (ReentrySeSepData__9CRedSoundFi(redSound, seId) == -1) { + } else if (redSound->ReentrySeSepData(seId) == -1) { char sePath[264]; sprintf(sePath, s_soundSeSepPathFmt, seId); CFile::CHandle* handle = File.Open(sePath, 0, CFile::PRI_LOW); if (handle != 0) { File.Read(handle); File.SyncCompleted(handle); - SetSeSepData__9CRedSoundFPv(redSound, File.m_readBuffer); + redSound->SetSeSepData(File.m_readBuffer); File.Close(handle); if (System.m_execParam != 0) { Printf__7CSystemFPce(&System, s_soundLoadSeMergeFmt, seId); @@ -1404,8 +1354,8 @@ void CSound::LoadSe(int seId) void CSound::LoadSe(void* seData) { CRedSound* redSound = RedSound(this); - if (ReentrySeSepData__9CRedSoundFi(redSound, *reinterpret_cast((u8*)seData + 8)) == -1) { - SetSeSepData__9CRedSoundFPv(redSound, seData); + if (redSound->ReentrySeSepData(*reinterpret_cast((u8*)seData + 8)) == -1) { + redSound->SetSeSepData(seData); } } @@ -1427,17 +1377,17 @@ void CSound::LoadWave(int waveId) if (waveId < 0) { Printf__7CSystemFPce(&System, s_soundMinusOneFmt); } else { - if (ReentryWaveData__9CRedSoundFi(redSound, waveId) == -1) { + if (redSound->ReentryWaveData(waveId) == -1) { if (waveId < 0) { Printf__7CSystemFPce(&System, s_soundMinusOneFmt); - } else if (ReentryWaveData__9CRedSoundFi(redSound, waveId) == -1) { + } else if (redSound->ReentryWaveData(waveId) == -1) { if (waveFile != 0) { File.Close(waveFile); waveFile = 0; Printf__7CSystemFPce(&System, s_soundLoadWaveErrorFmt); } - SetWaveData__9CRedSoundFiPvi(redSound, -1, nullptr, 0); + redSound->SetWaveData(-1, nullptr, 0); char wavePath[260]; sprintf(wavePath, s_soundWavePathFmt, waveId); @@ -1476,14 +1426,14 @@ void CSound::LoadWave(void* waveData) CRedSound* redSound = RedSound(this); CFile::CHandle*& waveFile = SoundData(this).m_waveFile; - if (ReentryWaveData__9CRedSoundFi(redSound, reinterpret_cast(waveData)[1]) == -1) { + if (redSound->ReentryWaveData(reinterpret_cast(waveData)[1]) == -1) { if (waveFile != 0) { File.Close(waveFile); waveFile = 0; Printf__7CSystemFPce(&System, s_soundLoadWaveErrorFmt); } - SetWaveData__9CRedSoundFiPvi(redSound, -1, nullptr, 0); - SetWaveData__9CRedSoundFiPvi(redSound, -1, waveData, -1); + redSound->SetWaveData(-1, nullptr, 0); + redSound->SetWaveData(-1, waveData, -1); } } @@ -1501,7 +1451,7 @@ void CSound::FreeWave(int waveId) if (waveId < 0) { Printf__7CSystemFPce(&System, s_soundMinusOneFmt); } else { - ClearWaveData__9CRedSoundFi(RedSound(this), waveId); + RedSound(this)->ClearWaveData(waveId); } } @@ -1518,26 +1468,18 @@ void CSound::StopAndFreeAllSe(int clearMode) { u8* self = reinterpret_cast(this); CSoundLayout& sound = *reinterpret_cast(self); + CRedSound* redSound = RedSound(this); if (clearMode != 0) { - SeStop__9CRedSoundFi(reinterpret_cast(self + 8), -1); - ClearSeSepData__9CRedSoundFi(reinterpret_cast(self + 8), -1); - ClearWaveData__9CRedSoundFi(reinterpret_cast(self + 8), -3); + redSound->SeStop(-1); + redSound->ClearSeSepData(-1); + redSound->ClearWaveData(-3); } else { - SeStopMG__9CRedSoundFiiii(reinterpret_cast(self + 8), - sound.m_noFreeSeGroups[0], - sound.m_noFreeSeGroups[1], - sound.m_noFreeSeGroups[2], - sound.m_noFreeSeGroups[3]); - ClearSeSepDataMG__9CRedSoundFiiii(reinterpret_cast(self + 8), - sound.m_noFreeSeGroups[0], - sound.m_noFreeSeGroups[1], - sound.m_noFreeSeGroups[2], - sound.m_noFreeSeGroups[3]); - ClearWaveDataM__9CRedSoundFiiii(reinterpret_cast(self + 8), - sound.m_noFreeWaves[0], - sound.m_noFreeWaves[1], - sound.m_noFreeWaves[2], - sound.m_noFreeWaves[3]); + redSound->SeStopMG(sound.m_noFreeSeGroups[0], sound.m_noFreeSeGroups[1], + sound.m_noFreeSeGroups[2], sound.m_noFreeSeGroups[3]); + redSound->ClearSeSepDataMG(sound.m_noFreeSeGroups[0], sound.m_noFreeSeGroups[1], + sound.m_noFreeSeGroups[2], sound.m_noFreeSeGroups[3]); + redSound->ClearWaveDataM(sound.m_noFreeWaves[0], sound.m_noFreeWaves[1], + sound.m_noFreeWaves[2], sound.m_noFreeWaves[3]); } sound.m_seCount = 10000000; @@ -1558,22 +1500,20 @@ void CSound::StopAndFreeAllSe(int clearMode) int CSound::PlaySe(int seNo, int pan, int volume, int fadeFrames) { int seId; - u8* self = reinterpret_cast(this); + CRedSound* redSound = RedSound(this); if (seNo < 0) { Printf__7CSystemFPce(&System, s_soundMinusOneFmt); return -1; } else if (seNo < 4000) { - seId = SePlay__9CRedSoundFiiiii(reinterpret_cast(self + 8), seNo / 1000, seNo % 1000, pan, - volume & ~((-fadeFrames | fadeFrames) >> 0x1F), 0); + seId = redSound->SePlay(seNo / 1000, seNo % 1000, pan, volume & ~((-fadeFrames | fadeFrames) >> 0x1F), 0); if (fadeFrames != 0) { - SeVolume__9CRedSoundFiii(reinterpret_cast(self + 8), seId, volume, fadeFrames); + redSound->SeVolume(seId, volume, fadeFrames); } } else { - seId = SePlay__9CRedSoundFiiiii(reinterpret_cast(self + 8), -1, seNo, pan, - volume & ~((-fadeFrames | fadeFrames) >> 0x1F), 0); + seId = redSound->SePlay(-1, seNo, pan, volume & ~((-fadeFrames | fadeFrames) >> 0x1F), 0); if (fadeFrames != 0) { - SeVolume__9CRedSoundFiii(reinterpret_cast(self + 8), seId, volume, fadeFrames); + redSound->SeVolume(seId, volume, fadeFrames); } } @@ -1594,7 +1534,7 @@ void CSound::StopSe(int seId) if (seId < 0) { Printf__7CSystemFPce(&System, s_soundMinusOneFmt); } else { - SeStop__9CRedSoundFi(RedSound(this), seId); + RedSound(this)->SeStop(seId); } } @@ -1612,7 +1552,7 @@ void CSound::FadeOutSe(int seId, int fadeFrames) if (seId < 0) { Printf__7CSystemFPce(&System, s_soundMinusOneFmt); } else { - SeFadeOut__9CRedSoundFii(RedSound(this), seId, fadeFrames); + RedSound(this)->SeFadeOut(seId, fadeFrames); } } @@ -1735,16 +1675,16 @@ int CSound::PlaySe3DLine(int soundId, int lineIndex, float nearDistance, float f slot = -1; } else if (soundId < 4000) { int bank = soundId / 1000; - slot = SePlay__9CRedSoundFiiiii(reinterpret_cast(soundObj + 8), bank, soundId % 1000, panValue, - volumeValue & ~((int)(-fadeFrames | fadeFrames) >> 0x1F), 0); + slot = reinterpret_cast(soundObj + 8)->SePlay( + bank, soundId % 1000, panValue, volumeValue & ~((int)(-fadeFrames | fadeFrames) >> 0x1F), 0); if (fadeFrames != 0) { - SeVolume__9CRedSoundFiii(reinterpret_cast(soundObj + 8), slot, volumeValue, fadeFrames); + reinterpret_cast(soundObj + 8)->SeVolume(slot, volumeValue, fadeFrames); } } else { - slot = SePlay__9CRedSoundFiiiii(reinterpret_cast(soundObj + 8), -1, soundId, panValue, - volumeValue & ~((int)(-fadeFrames | fadeFrames) >> 0x1F), 0); + slot = reinterpret_cast(soundObj + 8)->SePlay( + -1, soundId, panValue, volumeValue & ~((int)(-fadeFrames | fadeFrames) >> 0x1F), 0); if (fadeFrames != 0) { - SeVolume__9CRedSoundFiii(reinterpret_cast(soundObj + 8), slot, volumeValue, fadeFrames); + reinterpret_cast(soundObj + 8)->SeVolume(slot, volumeValue, fadeFrames); } } @@ -1812,16 +1752,16 @@ int CSound::PlaySe3D(int soundId, Vec* pos, float nearDistance, float farDistanc slot = -1; } else if (soundId < 4000) { int bank = soundId / 1000; - slot = SePlay__9CRedSoundFiiiii(reinterpret_cast(soundObj + 8), bank, soundId % 1000, - panValue, volumeValue & ~((int)(-fadeFrames | fadeFrames) >> 0x1F), 0); + slot = reinterpret_cast(soundObj + 8)->SePlay( + bank, soundId % 1000, panValue, volumeValue & ~((int)(-fadeFrames | fadeFrames) >> 0x1F), 0); if (fadeFrames != 0) { - SeVolume__9CRedSoundFiii(reinterpret_cast(soundObj + 8), slot, volumeValue, fadeFrames); + reinterpret_cast(soundObj + 8)->SeVolume(slot, volumeValue, fadeFrames); } } else { - slot = SePlay__9CRedSoundFiiiii(reinterpret_cast(soundObj + 8), -1, soundId, panValue, - volumeValue & ~((int)(-fadeFrames | fadeFrames) >> 0x1F), 0); + slot = reinterpret_cast(soundObj + 8)->SePlay( + -1, soundId, panValue, volumeValue & ~((int)(-fadeFrames | fadeFrames) >> 0x1F), 0); if (fadeFrames != 0) { - SeVolume__9CRedSoundFiii(reinterpret_cast(soundObj + 8), slot, volumeValue, fadeFrames); + reinterpret_cast(soundObj + 8)->SeVolume(slot, volumeValue, fadeFrames); } } @@ -2017,7 +1957,7 @@ void CSound::StopSe3DGroup(int group) if (playId < 0) { Printf__7CSystemFPce(&System, s_soundMinusOneFmt); } else { - SeStop__9CRedSoundFi(RedSound(this), playId); + RedSound(this)->SeStop(playId); } reinterpret_cast(found)->m_bits.m_active = 0; } @@ -2089,7 +2029,7 @@ void CSound::StopSe3D(int se3dHandle) if (playId < 0) { Printf__7CSystemFPce(&System, s_soundMinusOneFmt, idx); } else { - SeStop__9CRedSoundFi(RedSound(this), playId); + RedSound(this)->SeStop(playId); } reinterpret_cast(found)->m_bits.m_active = 0; } @@ -2157,7 +2097,7 @@ _pppMngSt* CSound::FadeOutSe3D(int se3dHandle, int fadeFrames) if (playId < 0) { Printf__7CSystemFPce(&System, s_soundMinusOneFmt, fadeFrames, ret); } else { - SeFadeOut__9CRedSoundFii(RedSound(this), playId, fadeFrames); + RedSound(this)->SeFadeOut(playId, fadeFrames); } reinterpret_cast(found)->m_bits.m_active = 0; } @@ -2282,7 +2222,7 @@ void CSound::ChangeSe3DPitch(int se3dHandle, int pitch, int frames) found_entry: if (found != 0) { - SePitch__9CRedSoundFiii(RedSound(this), *reinterpret_cast(found + 8), pitch << 8, frames); + RedSound(this)->SePitch(*reinterpret_cast(found + 8), pitch << 8, frames); } } } @@ -2339,11 +2279,11 @@ void CSound::Add3DLine(int lineIndex, Vec* position) */ void CSound::SetReverb(int reverb, int depth) { - u8* self = reinterpret_cast(this); + CRedSound* redSound = RedSound(this); int depthValue = depth; - SetReverb__9CRedSoundFii(reinterpret_cast(self + 8), 1, reverb); - SetReverbDepth__9CRedSoundFiii(reinterpret_cast(self + 8), 1, depthValue, 0xF); + redSound->SetReverb(1, reverb); + redSound->SetReverbDepth(1, depthValue, 0xF); } /* @@ -2364,13 +2304,13 @@ void CSound::LoadStream(int streamID) bool isPlaying = false; if (sound.m_streamPlaying != 0) { - if (StreamPlayState__9CRedSoundFi(RedSound(this), sound.m_streamID) != 0) { + if (RedSound(this)->StreamPlayState(sound.m_streamID) != 0) { isPlaying = true; } } if (isPlaying) { - StreamStop__9CRedSoundFi(RedSound(this), sound.m_streamID); + RedSound(this)->StreamStop(sound.m_streamID); } if (sound.m_streamFile != 0) { @@ -2456,7 +2396,7 @@ void CSound::PlayStreamASync() } } - int streamNo = StreamPlay__9CRedSoundFPviii(redSound, streamBuffer, 0x20000, 0x40, clampedVolume); + int streamNo = redSound->StreamPlay(streamBuffer, 0x20000, 0x40, clampedVolume); sound.m_streamID = streamNo; sound.m_streamPlaying = 1; } @@ -2476,14 +2416,14 @@ void CSound::StopStream() bool shouldStop = false; if (sound.m_streamPlaying != 0) { - int state = StreamPlayState__9CRedSoundFi(RedSound(this), sound.m_streamID); + int state = RedSound(this)->StreamPlayState(sound.m_streamID); if (state != 0) { shouldStop = true; } } if (shouldStop) { - StreamStop__9CRedSoundFi(RedSound(this), sound.m_streamID); + RedSound(this)->StreamStop(sound.m_streamID); } CFile::CHandle* handle = sound.m_streamFile; @@ -2505,7 +2445,7 @@ void CSound::StopStream() */ void CSound::SetStreamVolume(int volume, int frames) { - StreamVolume__9CRedSoundFiii(RedSound(this), -1, volume, frames); + RedSound(this)->StreamVolume(-1, volume, frames); } /* @@ -2539,12 +2479,11 @@ void CSound::IsDebugPrint(int) */ void CSound::PauseAllSe(int pause) { - u8* self = reinterpret_cast(this); + CRedSound* redSound = RedSound(this); - SePause__9CRedSoundFii(reinterpret_cast(self + 8), -1, static_cast(-pause | pause) >> 31); - StreamPause__9CRedSoundFii(reinterpret_cast(self + 8), -1, - (-static_cast(pause) | static_cast(pause)) >> 31); - reinterpret_cast(self)->m_pauseAllSe = pause; + redSound->SePause(-1, static_cast(-pause | pause) >> 31); + redSound->StreamPause(-1, (-static_cast(pause) | static_cast(pause)) >> 31); + SoundData(this).m_pauseAllSe = pause; } /* diff --git a/tools/map/claim_doctor.py b/tools/map/claim_doctor.py index a53b458a50..4ff13bb4c5 100644 --- a/tools/map/claim_doctor.py +++ b/tools/map/claim_doctor.py @@ -57,6 +57,8 @@ class SectionDiagnosis: unclaimed_compiled_size: int pal_map_total: Optional[int] en_map_total: Optional[int] + pal_named_extent: Optional[int] + en_named_extent: Optional[int] pal_attributed_bytes: int en_attributed_bytes: int pal_symbols: tuple[str, ...] @@ -146,6 +148,32 @@ def get_compiled_sections(objdump_path: Path, object_path: Path) -> dict[str, in return sections +def build_map_named_extent_table(map_index: MapIndex) -> dict[str, dict[str, int]]: + section_starts: dict[tuple[str, str], int] = {} + symbol_ends: dict[tuple[str, str], int] = {} + for records in map_index.layout_by_symbol.values(): + for record in records: + if record.offset is None: + continue + key = (record.object_file, record.section) + if record.symbol_name == record.section: + section_starts[key] = record.offset + continue + if record.is_unused or record.size <= 0: + continue + end = record.offset + record.size + symbol_ends[key] = max(symbol_ends.get(key, end), end) + + table: dict[str, dict[str, int]] = defaultdict(dict) + for key, section_start in section_starts.items(): + symbol_end = symbol_ends.get(key) + if symbol_end is None or symbol_end < section_start: + continue + object_file, section = key + table[object_file][section] = symbol_end - section_start + return table + + def is_claimed(section_ranges: list[tuple[int, int]], symbol: ProjectSymbol) -> bool: return any(start <= symbol.address < end for start, end in section_ranges) @@ -207,6 +235,8 @@ def diagnose_section( claimed_size: int, pal_map_total: Optional[int], en_map_total: Optional[int], + pal_named_extent: Optional[int], + en_named_extent: Optional[int], pal_attr: AttributionSummary, en_attr: AttributionSummary, ) -> SectionDiagnosis: @@ -254,6 +284,18 @@ def diagnose_section( confidence = "medium" summary = f"near claim candidate: attributed current symbols are off by {delta:+d} bytes" score += 20.0 + elif ( + compiled_size > 0 + and pal_named_extent == compiled_size + and en_named_extent == compiled_size + and pal_map_total is not None + and en_map_total is not None + and pal_map_total == en_map_total + and 0 < pal_map_total - compiled_size <= 16 + ): + delta = compiled_size - pal_map_total + confidence = "info" + summary = f"matches named MAP symbols; object total is likely trailing alignment ({delta:+d} bytes)" elif compiled_size > 0 and best_total is not None and abs(compiled_size - best_total) <= 16: delta = compiled_size - best_total confidence = "medium" @@ -283,6 +325,8 @@ def diagnose_section( unclaimed_compiled_size=unclaimed_compiled_size, pal_map_total=pal_map_total, en_map_total=en_map_total, + pal_named_extent=pal_named_extent, + en_named_extent=en_named_extent, pal_attributed_bytes=pal_attributed_bytes, en_attributed_bytes=en_attributed_bytes, pal_symbols=tuple(pal_attr.symbols if pal_attr else ()), @@ -311,6 +355,8 @@ def collect_diagnoses( pal_attribution = build_attribution_table(pal_index, unclaimed_symbols) if pal_index else {} en_attribution = build_attribution_table(en_index, unclaimed_symbols) if en_index else {} + pal_named_extents = build_map_named_extent_table(pal_index) if pal_index else {} + en_named_extents = build_map_named_extent_table(en_index) if en_index else {} object_paths = build_object_path_index(build_root / "src") objdump_path = repo_root / "build" / "binutils" / "powerpc-eabi-objdump.exe" @@ -332,6 +378,8 @@ def collect_diagnoses( claimed_size = sum(end - start for start, end in sections.get(section, [])) pal_total = pal_index.object_section_size(object_file, section) if pal_index else None en_total = en_index.object_section_size(object_file, section) if en_index else None + pal_extent = pal_named_extents.get(object_file, {}).get(section) + en_extent = en_named_extents.get(object_file, {}).get(section) pal_attr = pal_attribution.get(object_file, {}).get(section, AttributionSummary()) en_attr = en_attribution.get(object_file, {}).get(section, AttributionSummary()) @@ -346,6 +394,8 @@ def collect_diagnoses( claimed_size, pal_total, en_total, + pal_extent, + en_extent, pal_attr, en_attr, ) @@ -412,6 +462,10 @@ def print_target_report(diagnoses: list[SectionDiagnosis]) -> None: f" PAL total={pal_total} PAL attributed={diagnosis.pal_attributed_bytes} " f"EN total={en_total} EN attributed={diagnosis.en_attributed_bytes}" ) + if diagnosis.pal_named_extent is not None or diagnosis.en_named_extent is not None: + pal_extent = diagnosis.pal_named_extent if diagnosis.pal_named_extent is not None else "n/a" + en_extent = diagnosis.en_named_extent if diagnosis.en_named_extent is not None else "n/a" + print(f" PAL named_extent={pal_extent} EN named_extent={en_extent}") print(f" {diagnosis.confidence}: {diagnosis.summary}") if diagnosis.pal_symbols: print(f" PAL examples: {', '.join(diagnosis.pal_symbols)}") @@ -435,6 +489,8 @@ def print_ranked_report(diagnoses: list[SectionDiagnosis], top: int) -> None: f"unclaimed_build={diagnosis.unclaimed_compiled_size} " f"pal_total={diagnosis.pal_map_total if diagnosis.pal_map_total is not None else 'n/a'} " f"en_total={diagnosis.en_map_total if diagnosis.en_map_total is not None else 'n/a'} " + f"pal_named={diagnosis.pal_named_extent if diagnosis.pal_named_extent is not None else 'n/a'} " + f"en_named={diagnosis.en_named_extent if diagnosis.en_named_extent is not None else 'n/a'} " f"pal_attr={diagnosis.pal_attributed_bytes} en_attr={diagnosis.en_attributed_bytes}" ) examples = [] diff --git a/tools/map/discrepancy.py b/tools/map/discrepancy.py index 9470b3480f..d0d2f573f9 100644 --- a/tools/map/discrepancy.py +++ b/tools/map/discrepancy.py @@ -118,6 +118,9 @@ def _entries(index: Optional[MapIndex], object_file: str) -> dict[str, list[Sect # Skip section-level records (e.g. the row whose symbol equals the section name). if rec.symbol_name == rec.section: continue + # Skip linker/bookkeeping rows that do not correspond to source symbols. + if "(entry of " in rec.symbol_name or rec.symbol_name.startswith("gap_"): + continue # Skip kind-only marker rows that re-state the section size. by_section.setdefault(rec.section, []).append( SectionEntry( diff --git a/tools/map/map_index.py b/tools/map/map_index.py index d5cb229351..832e439191 100644 --- a/tools/map/map_index.py +++ b/tools/map/map_index.py @@ -9,7 +9,10 @@ SECTION_HEADER_RE = re.compile(r"^\s*(\.\w+|extab|extabindex)\s+section layout\s*$") FOUND_IN_RE = re.compile(r"^\s*\d+\]\s*(.+?)\s*\(([^)]+)\)\s+found in\s+(.+?)\s*$") -OBJECT_LINE_RE = re.compile(r"\s+([^\s]+\.o)\s*$", re.IGNORECASE) +OBJECT_LINE_RE = re.compile( + r"\s+([^\s]+\.(?:o|c|cc|cpp|cxx|cp|c\+\+|s|asm))\s*$", + re.IGNORECASE, +) SOURCE_EXTENSIONS = ( ".c", ".cc", @@ -34,7 +37,10 @@ def _basename(path_str: str) -> str: def normalize_object_file(path_str: str) -> str: - return _basename(path_str) + name = _basename(path_str) + if _looks_like_source_file(name): + return f"{PurePosixPath(name).stem}.o" + return name def normalize_source_file(path_str: str) -> str: @@ -161,6 +167,9 @@ def _parse_layout_line(line: str, current_section: str) -> Optional[LayoutRecord if len(kind_split) == 2 and re.fullmatch(r"[0-9A-Fa-f]+", kind_split[0]): kind = kind_split[0] symbol_name = kind_split[1].strip() + archive_split = symbol_name.rsplit(maxsplit=1) + if len(archive_split) == 2 and archive_split[1].lower().endswith(".a"): + symbol_name = archive_split[0].strip() size = _parse_hex(size_text) if size is None: diff --git a/tools/objdiff_experiment.py b/tools/objdiff_experiment.py new file mode 100644 index 0000000000..dffe00dee9 --- /dev/null +++ b/tools/objdiff_experiment.py @@ -0,0 +1,569 @@ +#!/usr/bin/env python3 +"""Capture, build, and compare objdiff scores for quick matching experiments.""" + +from __future__ import annotations + +import argparse +import json +import re +import subprocess +import sys +import tempfile +from datetime import datetime, timezone +from pathlib import Path +from typing import Any + + +ROOT = Path(__file__).resolve().parents[1] +DEFAULT_TIMEOUT_SECONDS = 30 +EPSILON = 0.0001 +DEFAULT_ATTEMPT_LOG = ROOT / "build" / "agent" / "objdiff_experiments.jsonl" + + +def normalize_unit(unit: str) -> str: + if "/" in unit or "\\" in unit: + return unit.replace("\\", "/") + if unit.startswith("Red"): + return f"main/RedSound/{unit}" + return f"main/{unit}" + + +def find_objdiff() -> Path: + candidates = [ + ROOT / "build" / "tools" / "objdiff-cli.exe", + ROOT / "build" / "tools" / "objdiff-cli", + ROOT / "tools" / "objdiff-cli.exe", + ROOT / "tools" / "objdiff-cli", + ] + for candidate in candidates: + if candidate.exists(): + return candidate + raise FileNotFoundError("objdiff-cli not found; run tools/download_tool.py or ninja first") + + +def run_command(cmd: list[str], timeout: int, *, check: bool = True) -> subprocess.CompletedProcess[str]: + result = subprocess.run( + cmd, + cwd=ROOT, + capture_output=True, + text=True, + timeout=timeout, + ) + if check and result.returncode != 0: + print(result.stdout, end="") + print(result.stderr, end="", file=sys.stderr) + raise SystemExit(result.returncode) + return result + + +def run_ninja(timeout: int) -> bool: + print(f"Running ninja (timeout {timeout}s)...") + try: + result = run_command(["ninja"], timeout, check=False) + except subprocess.TimeoutExpired: + print(f"ninja timed out after {timeout}s", file=sys.stderr) + return False + + if result.returncode != 0: + print(result.stdout, end="") + print(result.stderr, end="", file=sys.stderr) + print(f"ninja failed with exit code {result.returncode}", file=sys.stderr) + return False + + for line in result.stdout.splitlines(): + if line.startswith("Progress:") or "RedSound:" in line or "build/GCCP01/main.dol:" in line: + print(line) + return True + + +def load_objdiff_json(unit: str, symbols: list[str], timeout: int) -> dict[str, Any]: + objdiff = find_objdiff() + with tempfile.NamedTemporaryFile(prefix="objdiff_experiment_", suffix=".json", delete=False) as tmp: + tmp_path = Path(tmp.name) + + cmd = [str(objdiff), "diff", "-p", ".", "-u", unit, "-o", str(tmp_path), "--format", "json"] + # objdiff-cli currently accepts at most one symbol filter. For grouped + # experiments, capture the unit and filter the compact snapshot in Python. + if len(symbols) <= 1: + cmd.extend(symbols) + try: + run_command(cmd, timeout, check=True) + with tmp_path.open("r", encoding="utf-8") as f: + return json.load(f) + finally: + try: + tmp_path.unlink() + except FileNotFoundError: + pass + + +def as_float(value: Any) -> float: + try: + return float(value) + except (TypeError, ValueError): + return 0.0 + + +def compact_snapshot(unit: str, symbols_filter: list[str], raw: dict[str, Any]) -> dict[str, Any]: + left = raw.get("left", {}) + + def compact_items(items: list[dict[str, Any]]) -> dict[str, dict[str, Any]]: + out: dict[str, dict[str, Any]] = {} + for item in items: + name = item.get("name") + if not name: + continue + out[name] = { + "size": int(item.get("size", 0) or 0), + "match_percent": as_float(item.get("match_percent")), + } + return out + + return { + "schema": 1, + "unit": unit, + "symbols_filter": symbols_filter, + "captured_at": datetime.now(timezone.utc).isoformat(timespec="seconds"), + "complete": bool(left.get("complete", False)), + "match_percent": as_float(left.get("match_percent")), + "sections": compact_items(left.get("sections", [])), + "symbols": compact_items(left.get("symbols", [])), + } + + +def capture_snapshot(unit: str, symbols: list[str], timeout: int) -> dict[str, Any]: + raw = load_objdiff_json(unit, symbols, timeout) + return compact_snapshot(unit, symbols, raw) + + +def symbol_by_name(raw: dict[str, Any], side: str) -> dict[str, dict[str, Any]]: + return {symbol.get("name", ""): symbol for symbol in raw.get(side, {}).get("symbols", []) if symbol.get("name")} + + +def instruction_text(item: dict[str, Any]) -> str: + instruction = item.get("instruction") + if not instruction: + return "" + return str(instruction.get("formatted", "")) + + +def mnemonic(item: dict[str, Any]) -> str: + instruction = item.get("instruction") or {} + parts = instruction.get("parts") or [] + if parts and isinstance(parts[0], dict): + opcode = parts[0].get("opcode") + if isinstance(opcode, dict): + return str(opcode.get("mnemonic", "")) + text = instruction_text(item) + return text.split(maxsplit=1)[0] if text != "" else "" + + +def extract_stack_frame(instructions: list[dict[str, Any]]) -> str | None: + for item in instructions[:8]: + text = instruction_text(item) + match = re.match(r"stwu r1, (-?0x[0-9a-f]+|-?\d+)\(r1\)", text) + if match: + return match.group(1) + return None + + +def extract_save_range(instructions: list[dict[str, Any]]) -> str | None: + for item in instructions[:16]: + text = instruction_text(item) + match = re.match(r"stmw (r\d+), (0x[0-9a-f]+|-?\d+)\(r1\)", text) + if match: + return f"{match.group(1)}..r31 at {match.group(2)}" + saved = [] + for item in instructions[:24]: + text = instruction_text(item) + match = re.match(r"stw (r\d+), (0x[0-9a-f]+|-?\d+)\(r1\)", text) + if match and match.group(1) != "r0": + saved.append(f"{match.group(1)}@{match.group(2)}") + return ", ".join(saved) if saved else None + + +def classify_diff(left_item: dict[str, Any], right_item: dict[str, Any]) -> str: + left_text = instruction_text(left_item) + right_text = instruction_text(right_item) + left_mnemonic = mnemonic(left_item) + right_mnemonic = mnemonic(right_item) + if left_text == "" or right_text == "": + return "insert/delete" + if left_mnemonic != right_mnemonic: + return "opcode/control-flow shape" + if left_mnemonic in {"cmpwi", "cmplwi", "cmpw", "cmplw"}: + return "signedness/compare shape" + if left_mnemonic in {"lwz", "lhz", "lha", "lbz", "stw", "sth", "stb"}: + return "load/store register or offset" + if left_mnemonic.startswith("b"): + return "branch target/structure" + if left_mnemonic in {"mr", "addi", "add", "subf", "mullw", "srawi", "srwi", "slwi", "rlwinm"}: + return "register allocation/expression shape" + if left_mnemonic in {"stwu", "stmw", "lmw"}: + return "stack frame/saved register pressure" + return "argument/register mismatch" + + +def print_instruction_window( + left_instructions: list[dict[str, Any]], + right_instructions: list[dict[str, Any]], + center: int, + radius: int, +) -> None: + start = max(0, center - radius) + end = min(max(len(left_instructions), len(right_instructions)), center + radius + 1) + for index in range(start, end): + left_item = left_instructions[index] if index < len(left_instructions) else {} + right_item = right_instructions[index] if index < len(right_instructions) else {} + marker = "!" if "diff_kind" in left_item or "diff_kind" in right_item else " " + print(f" {marker}[{index:03d}] ours: {instruction_text(left_item)}") + print(f" [{index:03d}] target: {instruction_text(right_item)}") + + +def explain_symbol(left: dict[str, Any], right: dict[str, Any], limit: int, window: int) -> None: + name = left.get("name") or right.get("name") or "" + match = left.get("match_percent") + size = left.get("size") or right.get("size") + print(f"\nExplanation: {name} ({as_float(match):.4f}%, {size}b)") + + left_instructions = left.get("instructions") or [] + right_instructions = right.get("instructions") or [] + left_frame = extract_stack_frame(left_instructions) + right_frame = extract_stack_frame(right_instructions) + if left_frame or right_frame: + print(f" stack frame: ours {left_frame or '?'} / target {right_frame or '?'}") + + left_save = extract_save_range(left_instructions) + right_save = extract_save_range(right_instructions) + if left_save or right_save: + print(f" saved regs: ours {left_save or '?'} / target {right_save or '?'}") + + diff_counts: dict[str, int] = {} + rows: list[tuple[int, str, str, str]] = [] + max_len = max(len(left_instructions), len(right_instructions)) + for i in range(max_len): + left_item = left_instructions[i] if i < len(left_instructions) else {} + right_item = right_instructions[i] if i < len(right_instructions) else {} + if "diff_kind" not in left_item and "diff_kind" not in right_item: + continue + diff_kind = str(left_item.get("diff_kind") or right_item.get("diff_kind") or "DIFF") + diff_counts[diff_kind] = diff_counts.get(diff_kind, 0) + 1 + if len(rows) < limit: + rows.append((i, classify_diff(left_item, right_item), instruction_text(left_item), instruction_text(right_item))) + + if diff_counts: + counts = ", ".join(f"{key}={value}" for key, value in sorted(diff_counts.items())) + print(f" diff kinds: {counts}") + else: + print(" no instruction diffs") + return + + print(" first diffs:") + for index, hint, left_text, right_text in rows: + print(f" [{index:03d}] {hint}") + print(f" ours: {left_text}") + print(f" target: {right_text}") + if window > 0: + print_instruction_window(left_instructions, right_instructions, index, window) + + +def explain_current_diff(unit: str, symbols: list[str], timeout: int, limit: int, window: int) -> None: + raw = load_objdiff_json(unit, symbols, timeout) + left_symbols = symbol_by_name(raw, "left") + right_symbols = symbol_by_name(raw, "right") + names = symbols or unmatched_symbol_names(left_symbols) + for name in names: + left = left_symbols.get(name) + right = right_symbols.get(name) + if not left or not right: + print(f"\nExplanation: {name}: symbol not present on both sides") + continue + explain_symbol(left, right, limit, window) + + +def is_real_symbol_name(name: str) -> bool: + return not name.startswith("@") and not name.startswith("[") + + +def unmatched_symbol_names(symbols: dict[str, dict[str, Any]]) -> list[str]: + return [ + name + for name, symbol in symbols.items() + if symbol.get("match_percent") is not None + and as_float(symbol.get("match_percent")) < 100.0 + and is_real_symbol_name(name) + ] + + +def source_path_for_unit(unit: str) -> Path: + parts = unit.split("/") + if parts and parts[0] == "main": + parts = parts[1:] + return ROOT / "src" / Path(*parts).with_suffix(".cpp") + + +def map_hits(symbol: str, map_name: str, limit: int) -> list[tuple[int, str]]: + path = ROOT / "orig" / map_name / "game.MAP" + if not path.exists(): + return [] + hits: list[tuple[int, str]] = [] + with path.open("r", encoding="utf-8", errors="replace") as f: + for lineno, line in enumerate(f, start=1): + if symbol in line: + hits.append((lineno, line.rstrip())) + if len(hits) >= limit: + break + return hits + + +def ghidra_hits(symbol: str, limit: int) -> list[Path]: + ghidra_dir = ROOT / "resources" / "ghidra-decomp-1-31-2026" + if not ghidra_dir.exists(): + return [] + hits = [path for path in ghidra_dir.glob("*.c") if symbol in path.name] + return sorted(hits)[:limit] + + +def print_context(unit: str, symbols: list[str], limit: int) -> None: + print("\nContext") + source_path = source_path_for_unit(unit) + if source_path.exists(): + print(f" source: {source_path.relative_to(ROOT)}") + else: + print(f" source: {source_path.relative_to(ROOT)} (missing)") + + for symbol in symbols: + print(f"\n {symbol}") + for map_name, label in (("GCCP01", "PAL"), ("GCCE01", "EN")): + hits = map_hits(symbol, map_name, limit) + if hits: + print(f" {label} MAP:") + for lineno, text in hits: + print(f" {map_name}/game.MAP:{lineno}: {text.strip()}") + else: + print(f" {label} MAP: no hit") + hits = ghidra_hits(symbol, limit) + if hits: + print(" Ghidra:") + for path in hits: + print(f" {path.relative_to(ROOT)}") + else: + print(" Ghidra: no filename hit") + + +def save_snapshot(path: Path, snapshot: dict[str, Any]) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + with path.open("w", encoding="utf-8") as f: + json.dump(snapshot, f, indent=2, sort_keys=True) + f.write("\n") + print(f"Saved baseline: {path}") + + +def load_snapshot(path: Path) -> dict[str, Any]: + with path.open("r", encoding="utf-8") as f: + snapshot = json.load(f) + if snapshot.get("schema") != 1: + raise SystemExit(f"unsupported snapshot schema in {path}") + return snapshot + + +def pct(value: float) -> str: + return f"{value:8.4f}%" + + +def compare_group(before: dict[str, Any], after: dict[str, Any], key: str) -> list[tuple[str, int, int, float, float]]: + out: list[tuple[str, int, int, float, float]] = [] + before_items = before.get(key, {}) + after_items = after.get(key, {}) + for name in sorted(set(before_items) | set(after_items)): + b = before_items.get(name, {}) + a = after_items.get(name, {}) + before_pct = as_float(b.get("match_percent")) + after_pct = as_float(a.get("match_percent")) + before_size = int(b.get("size", 0) or 0) + after_size = int(a.get("size", 0) or 0) + if abs(after_pct - before_pct) > EPSILON or before_size != after_size: + out.append((name, before_size, after_size, before_pct, after_pct)) + return out + + +def print_changes(title: str, changes: list[tuple[str, int, int, float, float]], limit: int) -> None: + if not changes: + print(f"{title}: no changes") + return + + print(title) + print(" delta before after size name") + sorted_changes = sorted(changes, key=lambda row: (row[4] - row[3], row[0])) + for name, before_size, after_size, before_pct, after_pct in sorted_changes[:limit]: + delta = after_pct - before_pct + size = f"{before_size}" if before_size == after_size else f"{before_size}->{after_size}" + print(f" {delta:+8.4f} {pct(before_pct)} {pct(after_pct)} {size:>9} {name}") + if len(changes) > limit: + print(f" ... {len(changes) - limit} more") + + +def has_regression(changes: list[tuple[str, int, int, float, float]]) -> bool: + return any(after_pct + EPSILON < before_pct for _, _, _, before_pct, after_pct in changes) + + +def has_progress(changes: list[tuple[str, int, int, float, float]]) -> bool: + return any(after_pct > before_pct + EPSILON for _, _, _, before_pct, after_pct in changes) + + +def serialize_changes(changes: list[tuple[str, int, int, float, float]]) -> list[dict[str, Any]]: + return [ + { + "name": name, + "before_size": before_size, + "after_size": after_size, + "before_pct": before_pct, + "after_pct": after_pct, + "delta": after_pct - before_pct, + } + for name, before_size, after_size, before_pct, after_pct in changes + ] + + +def record_attempt( + path: Path, + unit: str, + symbols: list[str], + result: str, + section_changes: list[tuple[str, int, int, float, float]], + symbol_changes: list[tuple[str, int, int, float, float]], + note: str | None, +) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + entry = { + "timestamp": datetime.now(timezone.utc).isoformat(timespec="seconds"), + "unit": unit, + "symbols": symbols, + "result": result, + "note": note or "", + "sections": serialize_changes(section_changes), + "symbols_changed": serialize_changes(symbol_changes), + } + with path.open("a", encoding="utf-8") as f: + json.dump(entry, f, sort_keys=True) + f.write("\n") + print(f"Recorded attempt: {path}") + + +def restore_paths(paths: list[Path], reason: str) -> None: + if not paths: + return + cmd = ["git", "restore", "--worktree", "--staged", "--"] + cmd.extend(str(path) for path in paths) + print(f"Reverting explicit paths after {reason}:") + for path in paths: + print(f" {path}") + run_command(cmd, DEFAULT_TIMEOUT_SECONDS, check=True) + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Capture, build, and compare objdiff scores for a unit/symbol experiment.", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=( + "Examples:\n" + " python3 tools/objdiff_experiment.py -u RedStream --save .agent/redstream.base.json\n" + " python3 tools/objdiff_experiment.py -u RedStream StreamControl__Fv --build --explain --context\n" + " python3 tools/objdiff_experiment.py -u main/RedSound/RedExecute SetReverb__FiiPi --baseline .agent/rev.json --build\n" + ), + ) + parser.add_argument("symbols", nargs="*", help="Optional symbol filters. Multiple symbols are filtered after capture.") + parser.add_argument("-u", "--unit", required=True, help="Objdiff unit, e.g. RedStream or main/RedSound/RedStream.") + parser.add_argument("--save", type=Path, help="Save the current objdiff snapshot and exit.") + parser.add_argument("--baseline", type=Path, help="Compare against a snapshot produced by --save.") + parser.add_argument("--build", action="store_true", help="Run ninja before capturing the after snapshot.") + parser.add_argument("--ninja-timeout", type=int, default=DEFAULT_TIMEOUT_SECONDS, help="ninja timeout in seconds.") + parser.add_argument("--objdiff-timeout", type=int, default=60, help="objdiff-cli timeout in seconds.") + parser.add_argument("--limit", type=int, default=30, help="Maximum changed rows to print per group.") + parser.add_argument("--explain", action="store_true", help="Print a compact instruction mismatch summary.") + parser.add_argument("--window", type=int, default=0, help="Instruction context radius for --explain diffs.") + parser.add_argument("--context", action="store_true", help="Print source, PAL/EN MAP, and Ghidra context.") + parser.add_argument( + "--revert-path", + action="append", + type=Path, + default=[], + help="Explicit path to git-restore if an auto-revert condition is met. May be repeated.", + ) + parser.add_argument( + "--revert-no-change", + action="store_true", + help="Also restore --revert-path files when the experiment has no objdiff score changes.", + ) + parser.add_argument( + "--no-rebuild-after-revert", + action="store_false", + dest="rebuild_after_revert", + help="Do not run ninja again after an automatic regression revert.", + ) + parser.add_argument( + "--record-attempt", + action="store_true", + help=f"Append experiment result to {DEFAULT_ATTEMPT_LOG.relative_to(ROOT)}.", + ) + parser.add_argument("--attempt-log", type=Path, default=DEFAULT_ATTEMPT_LOG, help="Attempt log path.") + parser.add_argument("--note", help="Short note to store with --record-attempt.") + return parser.parse_args() + + +def main() -> int: + args = parse_args() + unit = normalize_unit(args.unit) + symbols = list(args.symbols) + + if args.save and args.baseline: + raise SystemExit("--save and --baseline are mutually exclusive") + + if args.save: + snapshot = capture_snapshot(unit, symbols, args.objdiff_timeout) + save_snapshot(args.save, snapshot) + return 0 + + if args.baseline: + before = load_snapshot(args.baseline) + if before.get("unit") != unit: + print(f"warning: baseline unit {before.get('unit')} differs from requested unit {unit}", file=sys.stderr) + else: + print("Capturing before snapshot from current build...") + before = capture_snapshot(unit, symbols, args.objdiff_timeout) + + if args.build and not run_ninja(args.ninja_timeout): + return 1 + + print("Capturing after snapshot...") + after = capture_snapshot(unit, symbols, args.objdiff_timeout) + + section_changes = compare_group(before, after, "sections") + symbol_changes = compare_group(before, after, "symbols") + + print(f"Unit: {unit}") + if symbols: + print(f"Symbols: {', '.join(symbols)}") + print_changes("Sections", section_changes, args.limit) + print_changes("Symbols", symbol_changes, args.limit) + if args.explain: + explain_current_diff(unit, symbols, args.objdiff_timeout, args.limit, args.window) + if args.context: + context_symbols = symbols or unmatched_symbol_names(after.get("symbols", {})) + print_context(unit, context_symbols, args.limit) + + regressed = has_regression(section_changes) or has_regression(symbol_changes) + progressed = has_progress(section_changes) or has_progress(symbol_changes) + result = "regressed" if regressed else "improved" if progressed else "no_change" + if args.record_attempt: + record_attempt(args.attempt_log, unit, symbols, result, section_changes, symbol_changes, args.note) + should_revert = regressed or (args.revert_no_change and result == "no_change") + if should_revert and args.revert_path: + restore_paths(args.revert_path, result) + if args.rebuild_after_revert and not run_ninja(args.ninja_timeout): + return 1 + return 2 if regressed else 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/redsound_triage.py b/tools/redsound_triage.py new file mode 100644 index 0000000000..a1fbd5cc5c --- /dev/null +++ b/tools/redsound_triage.py @@ -0,0 +1,746 @@ +#!/usr/bin/env python3 +"""Summarize remaining RedSound objdiff mismatches by likely cause.""" + +from __future__ import annotations + +import argparse +import json +import re +from collections import Counter +from pathlib import Path +from typing import Any + +from objdiff_experiment import ( + DEFAULT_ATTEMPT_LOG, + ROOT, + as_float, + classify_diff, + extract_save_range, + extract_stack_frame, + instruction_text, + is_real_symbol_name, + load_objdiff_json, + mnemonic, + normalize_unit, + run_ninja, + source_path_for_unit, + symbol_by_name, +) +from map.map_index import LayoutRecord, MapIndex, load_map_index, normalize_object_file + + +REDSOUND_UNITS = [ + "RedSound", + "RedCommand", + "RedDriver", + "RedEntry", + "RedExecute", + "RedMemory", + "RedMidiCtrl", + "RedStream", +] + +SIZE_BUCKETS = [ + ("tiny", 0, 64), + ("small", 65, 256), + ("medium", 257, 768), + ("large", 769, 1536), + ("huge", 1537, None), +] + +ATTEMPT_RESULT_RANK = { + "": 0, + "improved": 1, + "no_change": 2, + "regressed": 3, +} + +CONTEXT_ATTEMPT_NOTE_PREFIXES = ( + "baseline context", +) + +MAP_PATHS = ( + ("PAL", ROOT / "orig" / "GCCP01" / "game.MAP"), + ("EN", ROOT / "orig" / "GCCE01" / "game.MAP"), +) + + +def short_unit(unit: str) -> str: + return unit.rsplit("/", 1)[-1] + + +def truncate(text: str, width: int) -> str: + if len(text) <= width: + return text + return text[: max(0, width - 3)] + "..." + + +def size_bucket(size: int) -> str: + for name, start, end in SIZE_BUCKETS: + if size >= start and (end is None or size <= end): + return name + return "unknown" + + +def diff_summary(left: dict[str, Any], right: dict[str, Any]) -> tuple[Counter[str], str]: + counts: Counter[str] = Counter() + first_hint = "no diffs" + left_instructions = left.get("instructions") or [] + right_instructions = right.get("instructions") or [] + max_len = max(len(left_instructions), len(right_instructions)) + for i in range(max_len): + left_item = left_instructions[i] if i < len(left_instructions) else {} + right_item = right_instructions[i] if i < len(right_instructions) else {} + if "diff_kind" not in left_item and "diff_kind" not in right_item: + continue + diff_kind = str(left_item.get("diff_kind") or right_item.get("diff_kind") or "DIFF") + counts[diff_kind] += 1 + if first_hint == "no diffs": + first_hint = classify_diff(left_item, right_item) + return counts, first_hint + + +def diff_instruction_pairs(left: dict[str, Any], right: dict[str, Any]) -> list[tuple[int, dict[str, Any], dict[str, Any]]]: + pairs: list[tuple[int, dict[str, Any], dict[str, Any]]] = [] + left_instructions = left.get("instructions") or [] + right_instructions = right.get("instructions") or [] + max_len = max(len(left_instructions), len(right_instructions)) + for i in range(max_len): + left_item = left_instructions[i] if i < len(left_instructions) else {} + right_item = right_instructions[i] if i < len(right_instructions) else {} + if "diff_kind" in left_item or "diff_kind" in right_item: + pairs.append((i, left_item, right_item)) + return pairs + + +def is_save_restore_only(left: dict[str, Any], right: dict[str, Any]) -> bool: + pairs = diff_instruction_pairs(left, right) + if len(pairs) != 2: + return False + return all( + mnemonic(left_item) == mnemonic(right_item) and mnemonic(left_item) in {"stmw", "lmw"} + for _, left_item, right_item in pairs + ) + + +def has_param_spill_mismatch(left: dict[str, Any], right: dict[str, Any]) -> bool: + pairs = diff_instruction_pairs(left, right) + for index, left_item, right_item in pairs: + if index > 16: + break + left_text = instruction_text(left_item) + right_text = instruction_text(right_item) + if right_text.startswith("stw r4, ") and left_text != right_text: + return True + if left_text.startswith("stw r4, ") and left_text != right_text: + return True + return False + + +def has_target_only_counter(left: dict[str, Any], right: dict[str, Any]) -> bool: + """Detect target-side locals that look like a simple dead/diagnostic counter.""" + pairs = diff_instruction_pairs(left, right) + target_only = [ + (index, instruction_text(left_item)) + for index, left_item, right_item in pairs + if instruction_text(right_item) == "" + ] + regs = set() + for _, text in target_only: + match = re.fullmatch(r"li (r(?:2[0-9]|3[0-1])), 0x0", text) + if match: + regs.add(match.group(1)) + for reg in regs: + if any(text == f"addi {reg}, {reg}, 0x1" for _, text in target_only): + return True + return False + + +def operands(item: dict[str, Any]) -> list[str]: + text = instruction_text(item) + if text == "" or " " not in text: + return [] + return [part.strip() for part in text.split(None, 1)[1].split(",")] + + +def mismatch_patterns( + left: dict[str, Any], + right: dict[str, Any], + left_frame: str | None, + right_frame: str | None, + left_save: str | None, + right_save: str | None, +) -> list[str]: + patterns: list[str] = [] + if is_save_restore_only(left, right): + patterns.append("save-only") + if has_param_spill_mismatch(left, right): + patterns.append("param-spill") + if has_target_only_counter(left, right): + patterns.append("target-counter") + if left_frame != right_frame or left_save != right_save: + patterns.append("stack") + + left_instructions = left.get("instructions") or [] + right_instructions = right.get("instructions") or [] + max_len = max(len(left_instructions), len(right_instructions)) + has_shape = False + has_regs = False + for i in range(max_len): + left_item = left_instructions[i] if i < len(left_instructions) else {} + right_item = right_instructions[i] if i < len(right_instructions) else {} + if "diff_kind" not in left_item and "diff_kind" not in right_item: + continue + left_text = instruction_text(left_item) + right_text = instruction_text(right_item) + if left_text == "" or right_text == "": + has_shape = True + continue + + left_mnemonic = mnemonic(left_item) + right_mnemonic = mnemonic(right_item) + if {left_mnemonic, right_mnemonic} == {"srawi", "srwi"}: + patterns.append("signed-shift") + elif {left_mnemonic, right_mnemonic} & {"cmpwi", "cmplwi", "cmpw", "cmplw"} and left_mnemonic != right_mnemonic: + patterns.append("signed-compare") + elif left_mnemonic != right_mnemonic: + has_shape = True + else: + left_ops = operands(left_item) + right_ops = operands(right_item) + if ( + left_mnemonic in {"add", "addi", "mullw", "slwi", "srawi", "srwi"} + and len(left_ops) >= 2 + and len(right_ops) >= 2 + and left_ops[0] in left_ops[1:] + and right_ops[0] not in right_ops[1:] + ): + patterns.append("temp-result") + elif left_ops != right_ops: + has_regs = True + + if has_shape: + patterns.append("shape") + if has_regs: + patterns.append("regs") + return sorted(set(patterns)) + + +def category( + left_frame: str | None, + right_frame: str | None, + left_save: str | None, + right_save: str | None, + counts: Counter[str], +) -> str: + structural_count = counts.get("DIFF_INSERT", 0) + counts.get("DIFF_DELETE", 0) + counts.get("DIFF_REPLACE", 0) + if structural_count: + return "structural" + if left_frame != right_frame or left_save != right_save: + return "stack" + if counts and set(counts) <= {"DIFF_ARG_MISMATCH"}: + return "regs" + if counts: + return "other" + return "data" + + +def summarize_symbol(unit: str, left: dict[str, Any], right: dict[str, Any]) -> dict[str, Any]: + left_instructions = left.get("instructions") or [] + right_instructions = right.get("instructions") or [] + left_frame = extract_stack_frame(left_instructions) + right_frame = extract_stack_frame(right_instructions) + left_save = extract_save_range(left_instructions) + right_save = extract_save_range(right_instructions) + counts, first_hint = diff_summary(left, right) + patterns = mismatch_patterns(left, right, left_frame, right_frame, left_save, right_save) + row = { + "unit": unit, + "symbol": left.get("name", ""), + "pct": as_float(left.get("match_percent")), + "size": int(left.get("size", 0) or 0), + "current_size": int(right.get("size", 0) or 0), + "diff_count": sum(counts.values()), + "category": category(left_frame, right_frame, left_save, right_save, counts), + "frame": f"{left_frame or '?'}->{right_frame or '?'}", + "save": f"{left_save or '?'}->{right_save or '?'}", + "counts": ",".join(f"{k.removeprefix('DIFF_')}={v}" for k, v in sorted(counts.items())) or "-", + "hint": first_hint, + "patterns": ",".join(patterns) or "-", + } + row["bucket"] = size_bucket(row["size"]) + return row + + +def collect_unit(unit: str, timeout: int) -> list[dict[str, Any]]: + normalized = normalize_unit(unit) + raw = load_objdiff_json(normalized, [], timeout) + left_symbols = symbol_by_name(raw, "left") + right_symbols = symbol_by_name(raw, "right") + rows = [] + for name, left in left_symbols.items(): + if not is_real_symbol_name(name): + continue + if left.get("match_percent") is None or as_float(left.get("match_percent")) >= 100.0: + continue + right = right_symbols.get(name) + if not right: + continue + rows.append(summarize_symbol(normalized, left, right)) + return rows + + +def object_path_for_unit(unit: str) -> Path: + normalized = normalize_unit(unit) + parts = normalized.split("/") + if parts[:2] == ["main", "RedSound"] and len(parts) == 3: + return ROOT / "build" / "GCCP01" / "src" / "RedSound" / f"{parts[2]}.o" + if parts[:1] == ["main"] and len(parts) == 2: + return ROOT / "build" / "GCCP01" / "src" / f"{parts[1]}.o" + return ROOT / "build" / "GCCP01" / "src" / f"{short_unit(normalized)}.o" + + +def stale_build_warnings(units: list[str]) -> list[str]: + warnings: list[str] = [] + for unit in units: + normalized = normalize_unit(unit) + source_path = source_path_for_unit(normalized) + object_path = object_path_for_unit(normalized) + if not source_path.exists(): + continue + if not object_path.exists(): + warnings.append(f"{short_unit(normalized)} has no object artifact yet; run with --build for fresh scores") + continue + if source_path.stat().st_mtime > object_path.stat().st_mtime + 0.001: + warnings.append( + f"{short_unit(normalized)} source is newer than {object_path.relative_to(ROOT)}; " + "scores may be stale, run with --build" + ) + return warnings + + +def print_rows(rows: list[dict[str, Any]], limit: int) -> None: + if not rows: + print("No mismatched RedSound symbols found.") + return + + show_attempts = any(row.get("attempt_count", 0) for row in rows[:limit]) + attempt_header = " attempts" if show_attempts else "" + print( + f"{'cat':<10} {'pct':>8} {'diffs':>5} {'size':>9} {'unit':<11} " + f"{'symbol':<55} {'patterns':<28} hint{attempt_header}" + ) + print("-" * (160 if show_attempts else 150)) + for row in rows[:limit]: + attempt = "" + if show_attempts: + count = row.get("attempt_count", 0) + if count: + attempt = f" {count}:{row.get('last_attempt_result', '')}" + print( + f"{row['category']:<10} {row['pct']:8.3f} {row['diff_count']:5d} " + f"{row['size']:4d}/{row['current_size']:<4d} " + f"{short_unit(row['unit']):<11} {truncate(row['symbol'], 55):<55} " + f"{truncate(row['patterns'], 28):<28} {row['hint']}{attempt}" + ) + if len(rows) > limit: + print(f"... {len(rows) - limit} more") + + +def select_bucket_rows(rows: list[dict[str, Any]], per_bucket: int) -> list[dict[str, Any]]: + selected: list[dict[str, Any]] = [] + for name, _, _ in SIZE_BUCKETS: + bucket_rows = [row for row in rows if row["bucket"] == name] + bucket_rows.sort(key=lambda row: (row["diff_count"], -row["pct"], row["category"], row["unit"], row["symbol"])) + selected.extend(bucket_rows[:per_bucket]) + return selected + + +def print_buckets(rows: list[dict[str, Any]], per_bucket: int) -> list[dict[str, Any]]: + if not rows: + print("No mismatched RedSound symbols found.") + return [] + + selected = select_bucket_rows(rows, per_bucket) + for name, _, _ in SIZE_BUCKETS: + bucket_rows = [row for row in selected if row["bucket"] == name] + if not bucket_rows: + continue + print(f"\n{name}:") + print_rows(bucket_rows, len(bucket_rows)) + return selected + + +def print_detail(rows: list[dict[str, Any]], limit: int) -> None: + for row in rows[:limit]: + print(f"\n{row['unit']} :: {row['symbol']}") + print(f" {row['category']} {row['pct']:.4f}% size target/current={row['size']}/{row['current_size']}") + print(f" total diffs {row['diff_count']}") + print(f" frame {row['frame']}") + print(f" save {row['save']}") + print(f" diffs {row['counts']}") + print(f" patt {row['patterns']}") + print(f" hint {row['hint']}") + + +def load_redsound_map_indexes() -> list[tuple[str, MapIndex]]: + indexes: list[tuple[str, MapIndex]] = [] + for label, path in MAP_PATHS: + if path.exists(): + indexes.append((label, load_map_index(path, label=label))) + return indexes + + +def layout_neighbors(index: MapIndex, symbol: str, unit: str, radius: int) -> list[tuple[str, LayoutRecord]]: + symbol_records = [ + record + for record in index.layout_records_for_symbol(symbol) + if record.offset is not None and record.object_file == normalize_object_file(f"{short_unit(unit)}.o") + ] + if not symbol_records: + symbol_records = [record for record in index.layout_records_for_symbol(symbol) if record.offset is not None] + if not symbol_records: + return [] + + center = symbol_records[0] + records = [ + record + for records in index.layout_by_symbol.values() + for record in records + if record.offset is not None + and record.section == center.section + and record.object_file == center.object_file + ] + records.sort(key=lambda record: (record.offset or 0, record.symbol_name)) + try: + center_index = next(i for i, record in enumerate(records) if record.symbol_name == center.symbol_name and record.offset == center.offset) + except StopIteration: + return [] + + start = max(0, center_index - radius) + end = min(len(records), center_index + radius + 1) + result: list[tuple[str, LayoutRecord]] = [] + for i, record in enumerate(records[start:end], start): + marker = ">" if i == center_index else " " + result.append((marker, record)) + return result + + +def print_map_neighbors(rows: list[dict[str, Any]], limit: int, radius: int) -> None: + if radius <= 0 or not rows: + return + indexes = load_redsound_map_indexes() + if not indexes: + print("\nMAP neighbors: no PAL/EN MAP files found") + return + print("\nMAP neighbors:") + for row in rows[:limit]: + print(f" {short_unit(row['unit'])} {row['symbol']}:") + for label, index in indexes: + neighbors = layout_neighbors(index, row["symbol"], row["unit"], radius) + if not neighbors: + print(f" {label}: no layout record") + continue + print(f" {label}:") + for marker, record in neighbors: + offset = f"{record.offset:08x}" if record.offset is not None else "UNUSED" + va = f"{record.virtual_address:08x}" if record.virtual_address is not None else "........" + print( + f" {marker} {record.section:<10} {offset} {record.size:05x} {va} " + f"{record.symbol_name}" + ) + + +def experiment_command(row: dict[str, Any]) -> str: + unit = short_unit(row["unit"]) + source_path = source_path_for_unit(row["unit"]) + try: + source_arg = source_path.relative_to(ROOT) + except ValueError: + source_arg = source_path + return ( + f"python3 tools/objdiff_experiment.py -u {unit} {row['symbol']} " + f"--build --explain --context --limit 8 --window 2 --record-attempt " + f"--revert-path {source_arg} --revert-no-change" + ) + + +def print_commands(rows: list[dict[str, Any]], limit: int) -> None: + if not rows: + return + print("\nExperiment commands:") + for row in rows[:limit]: + print(f" {experiment_command(row)}") + + +def attempt_key(unit: str, symbol: str) -> tuple[str, str]: + return normalize_unit(unit), symbol + + +def is_context_attempt(entry: dict[str, Any]) -> bool: + note = str(entry.get("note", "")).strip().lower() + return any(note.startswith(prefix) for prefix in CONTEXT_ATTEMPT_NOTE_PREFIXES) + + +def load_attempts(path: Path, include_context: bool = False) -> dict[tuple[str, str], dict[str, Any]]: + attempts: dict[tuple[str, str], dict[str, Any]] = {} + if not path.exists(): + return attempts + with path.open("r", encoding="utf-8") as f: + for line in f: + line = line.strip() + if not line: + continue + try: + entry = json.loads(line) + except json.JSONDecodeError: + continue + if not include_context and is_context_attempt(entry): + continue + unit = normalize_unit(str(entry.get("unit", ""))) + symbols = entry.get("symbols") or [""] + for symbol in symbols: + key = (unit, str(symbol)) + current = attempts.setdefault( + key, + { + "count": 0, + "last_result": "", + "last_note": "", + "last_time": "", + "results": Counter(), + "history": [], + }, + ) + current["count"] += 1 + result = entry.get("result", "") + current["last_result"] = result + current["last_note"] = entry.get("note", "") + current["last_time"] = entry.get("timestamp", "") + if result: + current["results"][result] += 1 + current["history"].append( + { + "result": result, + "note": entry.get("note", ""), + "timestamp": entry.get("timestamp", ""), + } + ) + return attempts + + +def annotate_attempts(rows: list[dict[str, Any]], attempts: dict[tuple[str, str], dict[str, Any]]) -> None: + for row in rows: + row_attempts = attempts.get(attempt_key(row["unit"], row["symbol"]), {}) + row["attempt_count"] = int(row_attempts.get("count", 0) or 0) + row["last_attempt_result"] = row_attempts.get("last_result", "") + row["last_attempt_note"] = row_attempts.get("last_note", "") + row["last_attempt_time"] = row_attempts.get("last_time", "") + results = row_attempts.get("results", Counter()) + row["attempt_results"] = dict(results) + row["attempt_history"] = list(row_attempts.get("history", [])) + + +def print_attempts(rows: list[dict[str, Any]], limit: int, history_limit: int = 0) -> None: + attempted = [row for row in rows if row.get("attempt_count", 0)] + if not attempted: + print("\nAttempts: none recorded for shown rows") + return + print("\nAttempts:") + for row in attempted[:limit]: + note = f" ({row['last_attempt_note']})" if row.get("last_attempt_note") else "" + results = row.get("attempt_results", {}) + result_summary = "" + if results: + result_summary = " [" + ", ".join(f"{key}={results[key]}" for key in sorted(results)) + "]" + print( + f" {short_unit(row['unit'])} {row['symbol']}: " + f"{row['attempt_count']} attempt(s){result_summary}, last={row['last_attempt_result']}{note}" + ) + if history_limit > 0: + history = row.get("attempt_history", [])[-history_limit:] + for entry in history: + entry_note = entry.get("note", "") + entry_result = entry.get("result", "") + timestamp = entry.get("timestamp", "") + when = f" {timestamp}" if timestamp else "" + print(f" - {entry_result}{when}: {entry_note}") + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("-u", "--unit", action="append", help="Limit to one unit. May be repeated.") + parser.add_argument("--category", choices=["regs", "stack", "structural", "other", "data"], help="Filter category.") + parser.add_argument("--pattern", action="append", help="Only show symbols whose pattern list includes this value.") + parser.add_argument("--min-pct", type=float, default=0.0, help="Only show symbols at or above this match percent.") + parser.add_argument("--max-pct", type=float, default=99.9999, help="Only show symbols below or equal to this percent.") + parser.add_argument("--limit", type=int, default=80, help="Maximum table rows to print.") + parser.add_argument( + "--sort", + choices=["attempts", "category", "easy", "pct", "size-delta", "symbol", "symbols", "unit"], + default="category", + help=( + "Sort order. attempts ranks least-tried symbols first; easy ranks fewest diffs first; " + "size-delta ranks target/current size gaps." + ), + ) + parser.add_argument("--detail", action="store_true", help="Print frame/save/diff details for shown rows.") + parser.add_argument( + "--map-neighbors", + type=int, + default=0, + help="Show N PAL/EN MAP layout neighbors before and after each displayed symbol.", + ) + parser.add_argument("--commands", action="store_true", help="Print ready-to-run objdiff_experiment commands.") + parser.add_argument("--attempts", action="store_true", help="Show attempt counts from the attempt log.") + parser.add_argument( + "--attempt-history", + type=int, + default=0, + help="With --attempts, show the last N attempt notes for each displayed symbol.", + ) + parser.add_argument("--attempt-log", type=Path, default=DEFAULT_ATTEMPT_LOG, help="Attempt log path.") + parser.add_argument( + "--include-context-attempts", + action="store_true", + help="Count baseline/context-only objdiff captures as attempts.", + ) + parser.add_argument("--min-attempts", type=int, help="Only show symbols with at least this many recorded attempts.") + parser.add_argument("--max-attempts", type=int, help="Only show symbols with at most this many recorded attempts.") + parser.add_argument( + "--buckets", + action="store_true", + help="Show the easiest symbols per function-size bucket after applying filters.", + ) + parser.add_argument("--bucket-limit", type=int, default=3, help="Rows to show per size bucket with --buckets.") + parser.add_argument( + "--fresh", + action="store_true", + help="Hide symbols whose latest recorded attempt regressed or made no change.", + ) + parser.add_argument( + "--skip-attempt-result", + action="append", + choices=["improved", "regressed", "no_change"], + default=[], + help="Hide symbols whose latest recorded attempt has this result. May be repeated.", + ) + parser.add_argument( + "--require-attempt-result", + action="append", + choices=["improved", "regressed", "no_change"], + default=[], + help="Only show symbols with at least one recorded attempt of this result. May be repeated.", + ) + parser.add_argument("--build", action="store_true", help="Run ninja before collecting objdiff rows.") + parser.add_argument("--ninja-timeout", type=int, default=30, help="ninja timeout in seconds for --build.") + parser.add_argument( + "--no-stale-warning", + action="store_true", + help="Do not warn when source files are newer than the compiled object artifacts.", + ) + parser.add_argument("--objdiff-timeout", type=int, default=60) + return parser.parse_args() + + +def main() -> int: + args = parse_args() + if args.build and not run_ninja(args.ninja_timeout): + return 1 + units = args.unit or REDSOUND_UNITS + if not args.build and not args.no_stale_warning: + warnings = stale_build_warnings(units) + if warnings: + print("Stale build warning:") + for warning in warnings: + print(f" {warning}") + rows: list[dict[str, Any]] = [] + for unit in units: + rows.extend(collect_unit(unit, args.objdiff_timeout)) + + rows = [ + row + for row in rows + if row["pct"] >= args.min_pct + and row["pct"] <= args.max_pct + and (args.category is None or row["category"] == args.category) + and (args.pattern is None or all(pattern in row["patterns"].split(",") for pattern in args.pattern)) + ] + needs_attempts = ( + args.attempts + or args.sort == "attempts" + or args.fresh + or args.skip_attempt_result + or args.require_attempt_result + or args.min_attempts is not None + or args.max_attempts is not None + ) + if needs_attempts: + annotate_attempts(rows, load_attempts(args.attempt_log, include_context=args.include_context_attempts)) + if args.min_attempts is not None: + rows = [row for row in rows if row.get("attempt_count", 0) >= args.min_attempts] + if args.max_attempts is not None: + rows = [row for row in rows if row.get("attempt_count", 0) <= args.max_attempts] + skipped_results = set(args.skip_attempt_result) + if args.fresh: + skipped_results.update({"regressed", "no_change"}) + if skipped_results: + rows = [row for row in rows if row.get("last_attempt_result") not in skipped_results] + if args.require_attempt_result: + required_results = set(args.require_attempt_result) + rows = [ + row + for row in rows + if required_results <= {result for result, count in row.get("attempt_results", {}).items() if count} + ] + if args.sort == "easy": + rows.sort(key=lambda row: (row["diff_count"], -row["pct"], row["category"], row["unit"], row["symbol"])) + elif args.sort == "attempts": + rows.sort( + key=lambda row: ( + row.get("attempt_count", 0), + ATTEMPT_RESULT_RANK.get(row.get("last_attempt_result", ""), 9), + row["diff_count"], + -row["pct"], + row["unit"], + row["symbol"], + ) + ) + elif args.sort == "pct": + rows.sort(key=lambda row: (-row["pct"], row["diff_count"], row["unit"], row["symbol"])) + elif args.sort == "size-delta": + rows.sort( + key=lambda row: ( + -abs(row["size"] - row["current_size"]), + row["diff_count"], + -row["pct"], + row["unit"], + row["symbol"], + ) + ) + elif args.sort in {"symbol", "symbols"}: + rows.sort(key=lambda row: (row["symbol"], row["unit"], row["diff_count"], -row["pct"])) + elif args.sort == "unit": + rows.sort(key=lambda row: (row["unit"], row["symbol"], row["diff_count"], -row["pct"])) + else: + rows.sort(key=lambda row: (row["category"], -row["pct"], row["diff_count"], row["unit"], row["symbol"])) + + counts = Counter(row["category"] for row in rows) + if counts: + print("Category counts: " + ", ".join(f"{key}={counts[key]}" for key in sorted(counts))) + shown_rows = print_buckets(rows, args.bucket_limit) if args.buckets else rows[: args.limit] + if not args.buckets: + print_rows(rows, args.limit) + if args.detail: + print_detail(shown_rows, len(shown_rows)) + if args.map_neighbors: + print_map_neighbors(shown_rows, len(shown_rows), args.map_neighbors) + if args.commands: + print_commands(shown_rows, len(shown_rows)) + if args.attempts: + print_attempts(shown_rows, len(shown_rows), args.attempt_history) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())