/* MikMod sound library (c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*============================================================================== $Id: drv_wss.c,v 1.4 2004/02/10 17:52:18 raph Exp $ Driver for Windows Sound System under DOS ==============================================================================*/ /* Written by Andrew Zabolotny */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef DRV_WSS #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_FCNTL_H #include #endif #include "mikmod_internals.h" #include "doswss.h" static void WSS_CommandLine(CHAR *cmdline) { char *ptr, *end; if ((ptr=MD_GetAtom("port",cmdline,0))) { wss.port = strtol(ptr, &end, 16); free(ptr); } if ((ptr=MD_GetAtom("irq",cmdline,0))) { wss.irq = strtol(ptr, &end, 10); free(ptr); } if ((ptr=MD_GetAtom("dma",cmdline,0))) { wss.dma = strtol(ptr, &end, 10); free(ptr); } } static BOOL WSS_IsThere(void) { return wss_detect(); } static BOOL WSS_Init(void) { if (!wss_open()) { _mm_errno = MMERR_INVALID_DEVICE; return 1; } /* Adjust mixing frequency according to card capabilities */ md_mixfreq = wss_adjust_freq(md_mixfreq); return VC_Init(); } static void WSS_Exit(void) { VC_Exit(); wss_close(); } /* The last buffer byte filled with sound */ static unsigned int buff_tail = 0; static void WSS_Callback(void) { unsigned int dma_size, dma_pos; ULONG (*mixer)(SBYTE *buf, ULONG todo); wss_query_dma(&dma_size, &dma_pos); /* There isn't much sense in filling less than 256 bytes */ dma_pos &= ~255; /* If nothing to mix, quit */ if (buff_tail == dma_pos) return; if (Player_Paused_internal()) mixer = VC_SilenceBytes; else mixer = VC_WriteBytes; /* If DMA pointer still didn't wrapped around ... */ if (dma_pos > buff_tail) { buff_tail += mixer (wss.dma_buff->linear + buff_tail, dma_pos - buff_tail); /* If we arrived right to the DMA buffer end, jump to the beginning */ if (buff_tail >= dma_size) buff_tail = 0; } else { /* If wrapped around, fill first to the end of buffer */ mixer (wss.dma_buff->linear + buff_tail, dma_size - buff_tail); /* Now fill from buffer beginning to current DMA pointer */ buff_tail = mixer (wss.dma_buff->linear, dma_pos); } } static void WSS_Update(void) { /* Do nothing: the real update is done during SB interrupts */ } static BOOL WSS_PlayStart(void) { if (VC_PlayStart()) return 1; /* Set our routine to be called during WSS IRQs */ buff_tail = 0; wss.timer_callback = WSS_Callback; /* Start cyclic DMA transfer */ if (!wss_start_dma(((md_mode & DMODE_16BITS) ? WSSMODE_16BITS | WSSMODE_SIGNED : 0) | ((md_mode & DMODE_STEREO) ? WSSMODE_STEREO : 0), md_mixfreq)) { _mm_errno = MMERR_DOSWSS_STARTDMA; return 1; } /* Enable speaker output */ wss_output(TRUE); return 0; } static BOOL WSS_Reset(void) { wss_reset(); VC_Exit(); return VC_Init(); } static void WSS_PlayStop(void) { wss.timer_callback = NULL; wss_output(FALSE); wss_stop_dma(); VC_PlayStop(); } MDRIVER drv_wss = { NULL, "Windows Sound System", "Windows Sound System (CS423*,ESS*) v1.0", 0, 255, "wss", "port:c:32C,530,604,E80,F40,530:Windows Sound System base I/O port\n" "irq:c:2,3,5,7,10,5:Windows Sound System IRQ\n" "dma:c:0,1,3,0:Windows Sound System DMA channel\n", WSS_CommandLine, WSS_IsThere, VC_SampleLoad, VC_SampleUnload, VC_SampleSpace, VC_SampleLength, WSS_Init, WSS_Exit, WSS_Reset, VC_SetNumVoices, WSS_PlayStart, WSS_PlayStop, WSS_Update, NULL, VC_VoiceSetVolume, VC_VoiceGetVolume, VC_VoiceSetFrequency, VC_VoiceGetFrequency, VC_VoiceSetPanning, VC_VoiceGetPanning, VC_VoicePlay, VC_VoiceStop, VC_VoiceStopped, VC_VoiceGetPosition, VC_VoiceRealVolume }; #else /* ifdef DRV_WSS */ MISSING(drv_wss); #endif /* ex:set ts=4: */