diff --git a/src/mips/modplayer/Makefile b/src/mips/modplayer/Makefile index f485991cd..8aeb31f75 100644 --- a/src/mips/modplayer/Makefile +++ b/src/mips/modplayer/Makefile @@ -10,5 +10,6 @@ timewarped.o \ include ../common.mk -timewarped.o: timewarped.hit - $(PREFIX)-objcopy -I binary --set-section-alignment .data=4 --rename-section .data=.rodata,alloc,load,readonly,data,contents -O $(FORMAT) -B mips timewarped.hit timewarped.o +# convert HIT files to bin +%.o: %.hit + $(PREFIX)-objcopy -I binary --set-section-alignment .data=4 --rename-section .data=.rodata,alloc,load,readonly,data,contents -O $(FORMAT) -B mips $< $@ diff --git a/src/mips/modplayer/README.md b/src/mips/modplayer/README.md index 0f2148431..03912094b 100644 --- a/src/mips/modplayer/README.md +++ b/src/mips/modplayer/README.md @@ -2,4 +2,8 @@ This code is a reverse engineering of the file MODPLAY.BIN, located in the zip f The current API behaves roughly the same the original one. The code should provide information about the alterations made to it. -The demo song, "timewarped", written by [Jesster](https://modarchive.org/index.php?request=view_profile&query=69138), comes from [the modarchive](https://modarchive.org/index.php?request=view_by_moduleid&query=106481) with a [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/) license, allowing non-commercial adaptations. The file has been converted from MOD to HIT using the MODCONV.EXE software provided by Hitmen. +The demo song, "timewarped", written by [Jester](https://modarchive.org/index.php?request=view_profile&query=69138), comes from [the modarchive](https://modarchive.org/index.php?request=view_by_moduleid&query=106481) with a [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/) license, allowing non-commercial adaptations. The file has been converted from MOD to HIT using the MODCONV.EXE software provided by Hitmen. + +# Creating MOD files + +You can use the opensource [openMPT](https://openmpt.org/) to create MOD (OpenTracker) files. Keep in mind that Hitmen's `MODCONV.EXE` utility only allows 16 channels MODs. diff --git a/src/mips/modplayer/modplayer.c b/src/mips/modplayer/modplayer.c index 5d884eab1..2d3aa3753 100644 --- a/src/mips/modplayer/modplayer.c +++ b/src/mips/modplayer/modplayer.c @@ -133,9 +133,11 @@ static void SPUUploadInstruments(uint32_t SpuAddr, const uint8_t* data, uint32_t static void SPUUnMute() { SPU_CTRL = 0xc000; } -static void SPUSetVoiceVolume(int voiceID, uint16_t left, uint16_t right) { - SPU_VOICES[voiceID].volumeLeft = left >> 2; - SPU_VOICES[voiceID].volumeRight = right >> 2; +static uint32_t s_masterVolume = 16384; + +static void SPUSetVoiceVolume(int voiceID, uint32_t left, uint32_t right) { + SPU_VOICES[voiceID].volumeLeft = (left * s_masterVolume) >> 16; + SPU_VOICES[voiceID].volumeRight = (right * s_masterVolume) >> 16; } static void SPUSetStartAddress(int voiceID, uint32_t spuAddr) { SPU_VOICES[voiceID].sampleStartAddr = spuAddr >> 3; } @@ -804,3 +806,18 @@ void MOD_PlayNote(unsigned channel, unsigned sampleID, unsigned note, int16_t vo int32_t newPeriod = channelData->period = MOD_PeriodTable[note]; SETVOICESAMPLERATE(channel, newPeriod); } + +void MOD_PlaySoundEffect(unsigned channel, unsigned sampleID, unsigned note, int16_t volume) { + uint32_t s_prevVolume = s_masterVolume; + s_masterVolume = 16384; + MOD_PlayNote( channel, sampleID, note, volume); + s_masterVolume = s_prevVolume; +} + +void MOD_SetMusicVolume(uint32_t musicVolume) { + s_masterVolume = musicVolume; + const unsigned channels = MOD_Channels; + for (unsigned channel = 0; channel < MOD_Channels; channel++) { + SETVOICEVOLUME(channel, s_channelData[channel].volume); + } +} \ No newline at end of file diff --git a/src/mips/modplayer/modplayer.h b/src/mips/modplayer/modplayer.h index 8a27a6631..3d2bb09fa 100644 --- a/src/mips/modplayer/modplayer.h +++ b/src/mips/modplayer/modplayer.h @@ -146,5 +146,12 @@ void MOD_Relocate(uint8_t* buffer); // setting the volume of the voice to 0. void MOD_PlayNote(unsigned voiceID, unsigned sampleID, unsigned note, int16_t volume); +// Plays a sound effect +// As opposed to MOD_PlayNote(), MOD_PlaySoundEffect()'s volume is absolute. 0 == mute, 63 == max SPU voice volume +void MOD_PlaySoundEffect(unsigned channel, unsigned sampleID, unsigned note, int16_t volume); + // Added API to reset the SPU and silence everything. void MOD_Silence(); + +// Set MOD Volume to musicVolume, where musicVolume is between 0 and 65535. +void MOD_SetMusicVolume(uint32_t musicVolume); \ No newline at end of file