X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=dosdemo;a=blobdiff_plain;f=src%2Fdos%2Faudos.c;fp=src%2Fdos%2Faudos.c;h=513bf89ab556c54c5a675b4c7232fc5fc9bcc3d0;hp=0000000000000000000000000000000000000000;hb=93f68e445b0a4f10f2b15383aafed8a216a4a228;hpb=1329933c9afad7e3d0a7ce1f9839910706672f00 diff --git a/src/dos/audos.c b/src/dos/audos.c new file mode 100644 index 0000000..513bf89 --- /dev/null +++ b/src/dos/audos.c @@ -0,0 +1,211 @@ +#include +#include +#include +#include +#include "audio.h" +#include "midasdll.h" + +#define SET_MUS_VOL(vol) \ + do { \ + int mv = (vol) * vol_master >> 10; \ + MIDASsetMusicVolume(modplay, mv ? mv + 1 : 0); \ + } while(0) + +extern int force_snd_config; + +static MIDASmodulePlayHandle modplay; +static struct au_module *curmod; + +static int vol_master, vol_mus, vol_sfx; + +int au_init(void) +{ + modplay = 0; + curmod = 0; + vol_master = vol_mus = vol_sfx = 255; + + MIDASstartup(); + + if(force_snd_config || (!MIDASloadConfig("sound.cfg") && !MIDASdetectSoundCard())) { + if(MIDASconfig()) { + if(!MIDASsaveConfig("sound.cfg")) { + fprintf(stderr, "failed to save sound card configuration\n"); + } + } + } + + MIDASinit(); + + MIDASstartBackgroundPlay(0); + return 0; +} + +void au_shutdown(void) +{ + if(curmod) { + au_stop_module(curmod); + } + MIDASstopBackgroundPlay(); + MIDASclose(); +} + +struct au_module *au_load_module(const char *fname) +{ + static MIDASmoduleInfo info; + struct au_module *mod; + char *name, *end; + + if(!(mod = malloc(sizeof *mod))) { + fprintf(stderr, "au_load_module: failed to allocate module\n"); + return 0; + } + + if(!(mod->impl = MIDASloadModule((char*)fname))) { + fprintf(stderr, "au_load_module: failed to load module: %s\n", fname); + free(mod); + return 0; + } + + name = 0; + if(MIDASgetModuleInfo(mod->impl, &info)) { + name = info.songName; + end = name + strlen(name) - 1; + while(end >= name && isspace(*end)) { + *end-- = 0; + } + if(!*name) name = 0; + } + + if(!name) { + /* fallback to using the filename */ + if((name = strrchr(fname, '/')) || (name = strrchr(fname, '\\'))) { + name++; + } else { + name = (char*)fname; + } + } + + if(!(mod->name = malloc(strlen(name) + 1))) { + fprintf(stderr, "au_load_module: mod->name malloc failed\n"); + MIDASfreeModule(mod->impl); + return 0; + } + strcpy(mod->name, name); + + printf("loaded module \"%s\" (%s)\n", name, fname); + return mod; +} + +void au_free_module(struct au_module *mod) +{ + if(!mod) return; + + if(mod == curmod) { + au_stop_module(curmod); + } + MIDASfreeModule(mod->impl); + free(mod->name); + free(mod); +} + +int au_play_module(struct au_module *mod) +{ + if(curmod) { + if(curmod == mod) return 0; + au_stop_module(curmod); + } + + if(!(modplay = MIDASplayModule(mod->impl, 1))) { + fprintf(stderr, "au_play_module: failed to play module: %s\n", mod->name); + return -1; + } + SET_MUS_VOL(vol_mus); + curmod = mod; + return 0; +} + +void au_update(void) +{ +} + +int au_stop_module(struct au_module *mod) +{ + if(mod && curmod != mod) return -1; + if(!curmod) return -1; + + MIDASstopModule(modplay); + curmod = 0; + return 0; +} + +int au_module_state(struct au_module *mod) +{ + if(mod) { + return curmod == mod ? AU_PLAYING : AU_STOPPED; + } + return curmod ? AU_PLAYING : AU_STOPPED; +} + +int au_volume(int vol) +{ + AU_VOLADJ(vol_master, vol); + if(vol != vol_master) { + vol_master = vol; + + au_sfx_volume(vol_sfx); + au_music_volume(vol_mus); + } + return vol_master; +} + +int au_sfx_volume(int vol) +{ + AU_VOLADJ(vol_sfx, vol); + vol_sfx = vol; + + /* TODO set sfx volume */ + return vol_sfx; +} + + +int au_music_volume(int vol) +{ + AU_VOLADJ(vol_mus, vol); + vol_mus = vol; + + if(curmod) { + SET_MUS_VOL(vol); + } + return vol_mus; +} + +/* when using MIDAS, we can't access the PIT directly, so we don't build timer.c + * and implement all the timer functions here, using MIDAS callbacks + */ +static volatile unsigned long ticks; +static unsigned long tick_interval; + +static void MIDAS_CALL midas_timer(void) +{ + ticks++; +} + +/* macro to divide and round to the nearest integer */ +#define DIV_ROUND(a, b) \ + ((a) / (b) + ((a) % (b)) / ((b) / 2)) + +void init_timer(int res_hz) +{ + MIDASsetTimerCallbacks(res_hz * 1000, 0, midas_timer, 0, 0); + tick_interval = DIV_ROUND(1000, res_hz); +} + +void reset_timer(void) +{ + ticks = 0; +} + +unsigned long get_msec(void) +{ + return ticks * tick_interval; +}