#include #include #include "data.h" #include "mikmod.h" typedef struct { SAMPLE *s; const char *data; size_t len; } Efx; #define EFX_CNT 8 static Efx efx[EFX_CNT] = { { NULL, (const char *)binary_gold_efx_start, (size_t)&binary_gold_efx_size}, { NULL, (const char *)binary_jump_efx_start, (size_t)&binary_jump_efx_size}, { NULL, (const char *)binary_warp_efx_start, (size_t)&binary_warp_efx_size}, { NULL, (const char *)binary_pickup_efx_start, (size_t)&binary_pickup_efx_size}, { NULL, (const char *)binary_time_efx_start, (size_t)&binary_time_efx_size}, { NULL, (const char *)binary_oneup_efx_start, (size_t)&binary_oneup_efx_size}, { NULL, (const char *)binary_hit_efx_start, (size_t)&binary_hit_efx_size}, { NULL, (const char *)binary_death_efx_start, (size_t)&binary_death_efx_size}, }; static uint8_t has_sound = 0; static uint8_t cur = 0; static uint32_t voice = 0; static MODULE *music = NULL; uint8_t sound_init() { MikMod_InitThreads(); MikMod_RegisterDriver(&drv_sb); MikMod_RegisterLoader(&load_it); md_mode |= DMODE_SOFT_SNDFX | DMODE_SOFT_MUSIC; md_volume = 128; md_sndfxvolume = 128; md_pansep = 0; md_mixfreq = 22050; if (MikMod_Init(NULL)) /* has_sound is 0 */ return 1; for (uint8_t i = 0; i < EFX_CNT; i++) { efx[i].s = Sample_LoadMem(efx[i].data, efx[i].len); if (!efx[i].s) return 0; } /* 1 voice for effects */ if (MikMod_SetNumVoices(-1, 1)) /* has_sound is 0 */ return 1; /* needs a song playing to get effects; have a "silence" pattern on 0 */ music = Player_LoadMem((const char *)binary_music_start, (size_t)&binary_music_size, 8, 0); if (!music) return 0; Player_Start(music); if (MikMod_EnableOutput()) /* has_sound is 0 */ return 1; has_sound = 1; return 1; } volatile static uint8_t divider = 0; /* To be called from the timer int, so we update every 1080ms approx by using a * counter and updating 1 in 20 interrupts */ void sound_update() { /* we shouldn't call this anyway */ if (!has_sound) return; if (++divider == 20) { divider = 0; MikMod_Update(); } } void sound_mute() { if (has_sound) MikMod_DisableOutput(); } void sound_unmute() { if (has_sound) MikMod_EnableOutput(); } void sound_free() { if (!has_sound) return; if (MikMod_Active()) MikMod_DisableOutput(); if (music) Player_Free(music); for (uint8_t i = 0; i < EFX_CNT; i++) if (efx[i].s) Sample_Free(efx[i].s); MikMod_Exit(); } void sound_music_pattern(uint16_t pat) { if (has_sound) Player_SetPosition(pat); } void sound_play_efx(uint8_t efxno) { if (!has_sound) return; if (cur > efxno && !Voice_Stopped(voice)) return; cur = efxno; voice = Sample_Play(efx[cur].s, 0, 0); }