From 1c51b9b561889cf8fa845c10200b874c29b3d047 Mon Sep 17 00:00:00 2001 From: Alejandro Pulver Date: Wed, 2 Aug 2006 20:14:46 +0000 Subject: EDuke32 is a Windows/Linux/UNIX version of Duke Nukem 3D aimed at highly extending what can be edited in the game. EDuke32 combines the work that JonoF and Ken Silverman have put in to JFDuke3D with the original EDuke work done by Matt Saettler, while simultaneously adding tons of new and useful features. Consequently, EDuke32 is the most advanced version of Duke Nukem 3D in existence. EDuke32 is developed and maintained by Richard "TerminX" Gobeille and the EDuke32 team. This port includes icculus.org/duke3d patches for sound and joystick support. WWW: http://eduke32.com/ --- games/eduke32/Makefile | 55 + games/eduke32/distinfo | 9 + games/eduke32/files/patch-Makefile | 57 + games/eduke32/files/patch-Makefile.deps | 14 + games/eduke32/files/patch-source__game.c | 11 + .../files/patch-source__jaudiolib___multivc.h | 15 + .../files/patch-source__jaudiolib__debugio.h | 33 + games/eduke32/files/patch-source__jaudiolib__dma.h | 86 + .../eduke32/files/patch-source__jaudiolib__dpmi.h | 46 + games/eduke32/files/patch-source__jaudiolib__dsl.c | 260 ++ games/eduke32/files/patch-source__jaudiolib__dsl.h | 53 + .../files/patch-source__jaudiolib__interrup.h | 53 + .../files/patch-source__jaudiolib__nodpmi.c | 53 + .../files/patch-source__jaudiolib__platform.h | 64 + .../files/patch-source__jaudiolib__sdlmusic.c | 481 ++++ .../files/patch-source__jaudiolib__unixglob.c | 152 ++ .../files/patch-source__jaudiolib__unixpitch.c | 215 ++ .../files/patch-source__jaudiolib__unixvoc.c | 2880 ++++++++++++++++++++ .../eduke32/files/patch-source__jaudiolib__util.h | 15 + games/eduke32/pkg-descr | 11 + games/eduke32/pkg-plist | 6 + 21 files changed, 4569 insertions(+) create mode 100644 games/eduke32/Makefile create mode 100644 games/eduke32/distinfo create mode 100644 games/eduke32/files/patch-Makefile create mode 100644 games/eduke32/files/patch-Makefile.deps create mode 100644 games/eduke32/files/patch-source__game.c create mode 100644 games/eduke32/files/patch-source__jaudiolib___multivc.h create mode 100644 games/eduke32/files/patch-source__jaudiolib__debugio.h create mode 100644 games/eduke32/files/patch-source__jaudiolib__dma.h create mode 100644 games/eduke32/files/patch-source__jaudiolib__dpmi.h create mode 100644 games/eduke32/files/patch-source__jaudiolib__dsl.c create mode 100644 games/eduke32/files/patch-source__jaudiolib__dsl.h create mode 100644 games/eduke32/files/patch-source__jaudiolib__interrup.h create mode 100644 games/eduke32/files/patch-source__jaudiolib__nodpmi.c create mode 100644 games/eduke32/files/patch-source__jaudiolib__platform.h create mode 100644 games/eduke32/files/patch-source__jaudiolib__sdlmusic.c create mode 100644 games/eduke32/files/patch-source__jaudiolib__unixglob.c create mode 100644 games/eduke32/files/patch-source__jaudiolib__unixpitch.c create mode 100644 games/eduke32/files/patch-source__jaudiolib__unixvoc.c create mode 100644 games/eduke32/files/patch-source__jaudiolib__util.h create mode 100644 games/eduke32/pkg-descr create mode 100644 games/eduke32/pkg-plist (limited to 'games/eduke32') diff --git a/games/eduke32/Makefile b/games/eduke32/Makefile new file mode 100644 index 000000000000..c93594927a8c --- /dev/null +++ b/games/eduke32/Makefile @@ -0,0 +1,55 @@ +# New ports collection makefile for: eduke32 +# Date Created: 1 Aug 2006 +# Whom: alepulver +# +# $FreeBSD$ + +PORTNAME= eduke32 +PORTVERSION= 20060718 +CATEGORIES= games +MASTER_SITES= ${MASTER_SITE_SOURCEFORGE} +MASTER_SITE_SUBDIR= ${PORTNAME} +DISTFILES= ${PORTNAME}_src_${PORTVERSION}.zip \ + txbuild_src_${PORTVERSION}.zip + +MAINTAINER= alepulver@FreeBSD.org +COMMENT= Duke Nukem 3D Port based on JFDuke and EDuke + +BUILD_DEPENDS= nasm:${PORTSDIR}/devel/nasm + +USE_ZIP= yes +USE_GCC= 3.2+ +USE_GMAKE= yes +USE_GL= yes +USE_GNOME= gtk20 +USE_SDL= mixer sdl +WRKSRC= ${WRKDIR}/${PORTNAME}_src_${PORTVERSION} + +post-patch: + @${REINPLACE_CMD} -Ee \ + 's|^(EROOT=)../build/|\1../txbuild_src_${PORTVERSION}/|; \ + s|^(CC=).*|\1${CC}|; \ + s|^(CXX=).*|\1${CXX}|; \ + s|^(NASMFLAGS=).*|\1 -s -f elf|; \ + s|/usr/X11R6|${X11BASE}|; \ + s|sdl-config|${SDL_CONFIG}|' \ + ${WRKSRC}/Makefile \ + ${WRKDIR}/txbuild_src_${PORTVERSION}/Makefile \ + ${WRKDIR}/txbuild_src_${PORTVERSION}/Makefile.shared + @${REINPLACE_CMD} -e 's|/usr/share/games/eduke32|${DN3DDIR}|' \ + ${WRKSRC}/source/game.c ${WRKSRC}/source/astub.c + +do-install: +.for f in eduke32 mapster32 + ${INSTALL_PROGRAM} ${WRKSRC}/${f} ${PREFIX}/bin +.endfor +.if !defined(NOPORTDOCS) +.for f in ChangeLog *.sample + ${MKDIR} ${DOCSDIR} + ${INSTALL_DATA} ${WRKSRC}/${f} ${DOCSDIR} +.endfor +.endif + +.include "${.CURDIR}/../duke3d-data/Makefile.include" + +.include diff --git a/games/eduke32/distinfo b/games/eduke32/distinfo new file mode 100644 index 000000000000..1ce5d69603d9 --- /dev/null +++ b/games/eduke32/distinfo @@ -0,0 +1,9 @@ +MD5 (eduke32_src_20060718.zip) = 1c037c953c1bdc76647c3434408e7db2 +SHA256 (eduke32_src_20060718.zip) = 4271a8470aa81217b554df0d9eb1864ef3d5b8ff6ca87d985b3bb46cbe3d373f +SIZE (eduke32_src_20060718.zip) = 684828 +MD5 (txbuild_src_20060718.zip) = c2427bca6834f44c6731ea3973bc0d4b +SHA256 (txbuild_src_20060718.zip) = 7329be9c1507a7a68a3216ab9d3e78d7ea0279fd302b0683af3e73a1c620777d +SIZE (txbuild_src_20060718.zip) = 692726 +MD5 (eduke32_src_20060314_unix_sound_fix.patch.gz) = 29e974d05ece187457ac8b8cbebcb411 +SHA256 (eduke32_src_20060314_unix_sound_fix.patch.gz) = 9b0d3ac09b2359f0644a7370e321f2146727efeebef898347096b687c0d3a25f +SIZE (eduke32_src_20060314_unix_sound_fix.patch.gz) = 22529 diff --git a/games/eduke32/files/patch-Makefile b/games/eduke32/files/patch-Makefile new file mode 100644 index 000000000000..75236d13b102 --- /dev/null +++ b/games/eduke32/files/patch-Makefile @@ -0,0 +1,57 @@ +--- Makefile.orig Tue Jul 18 16:14:46 2006 ++++ Makefile Wed Aug 2 01:01:47 2006 +@@ -69,15 +69,12 @@ + + AUDIOLIB_FX_STUB=$(OBJ)audiolib_fxstub.$o + AUDIOLIB_MUSIC_STUB=$(OBJ)audiolib_musicstub.$o +-AUDIOLIB_JFAUD=$(OBJ)jfaud_sounds.$o ++AUDIOLIB_JFAUD=$(OBJ)sounds.$o + AUDIOLIB_FX=$(OBJ)mv_mix.$o \ + $(OBJ)mv_mix16.$o \ + $(OBJ)mvreverb.$o \ +- $(OBJ)pitch.$o \ +- $(OBJ)multivoc.$o \ + $(OBJ)ll_man.$o \ +- $(OBJ)fx_man.$o \ +- $(OBJ)dsoundout.$o ++ $(OBJ)fx_man.$o + AUDIOLIB_MUSIC=$(OBJ)midi.$o \ + $(OBJ)mpu401.$o \ + $(OBJ)music.$o +@@ -112,13 +109,16 @@ + endif + + ifeq ($(RENDERTYPE),SDL) +- OURCFLAGS+= $(subst -Dmain=SDL_main,,$(shell sdl-config --cflags)) ++ OURCFLAGS+= $(subst -Dmain=SDL_main,,$(shell sdl-config --cflags) -D__cdecl=" ") ++ LIBS+= $(shell sdl-config --libs) -lSDL_mixer + +- ifneq (0,$(JFAUD)) +- AUDIOLIBOBJ=$(AUDIOLIB_JFAUD) +- else +- AUDIOLIBOBJ=$(AUDIOLIB_MUSIC_STUB) $(AUDIOLIB_FX_STUB) $(OBJ)sounds.$o +- endif ++ AUDIOLIB_FX+= $(OBJ)dsl.$o \ ++ $(OBJ)nodpmi.$o \ ++ $(OBJ)unixpitch.$o \ ++ $(OBJ)unixvoc.$o ++ ++ AUDIOLIB_MUSIC=$(OBJ)sdlmusic.$o $(OBJ)unixglob.$o ++ AUDIOLIBOBJ=$(AUDIOLIB_JFAUD) $(AUDIOLIB_MUSIC) $(AUDIOLIB_FX) + + ifeq (1,$(HAVE_GTK2)) + OURCFLAGS+= -DHAVE_GTK2 $(shell pkg-config --cflags gtk+-2.0) +@@ -180,11 +180,12 @@ + $(CC) $(CFLAGS) $(OURCFLAGS) -o $@ $^ -Wl + strip duke3d_w32$(EXESUFFIX) + ++AUDIOLIB=$(SRC)/jaudiolib + include Makefile.deps + + .PHONY: enginelib editorlib + enginelib editorlib: +- -mkdir $(EOBJ) ++ mkdir -p $(EOBJ) + $(MAKE) -C $(EROOT) "OBJ=$(CURDIR)/$(EOBJ)" \ + SUPERBUILD=$(SUPERBUILD) POLYMOST=$(POLYMOST) \ + USE_OPENGL=$(USE_OPENGL) USE_A_C=$(USE_A_C) \ diff --git a/games/eduke32/files/patch-Makefile.deps b/games/eduke32/files/patch-Makefile.deps new file mode 100644 index 000000000000..f396e10c5433 --- /dev/null +++ b/games/eduke32/files/patch-Makefile.deps @@ -0,0 +1,14 @@ +--- ./Makefile.deps.orig Tue Jul 18 16:14:46 2006 ++++ ./Makefile.deps Wed Aug 2 00:41:11 2006 +@@ -45,6 +45,11 @@ + $(OBJ)scriplib.$o: $(SRC)jmact/scriplib.c $(SRC)jmact/scriplib.h $(SRC)jmact/util_lib.h $(SRC)jmact/_scrplib.h $(SRC)jmact/types.h $(EINC)compat.h + + # jAudioLib objects ++$(OBJ)dsl.$o: $(SRC)jaudiolib/dsl.c $(SRC)jaudiolib/util.h ++$(OBJ)nodpmi.$o: $(SRC)jaudiolib/nodpmi.c $(SRC)jaudiolib/dpmi.h ++$(OBJ)unixpitch.$o: $(SRC)jaudiolib/unixpitch.c $(SRC)jaudiolib/pitch.h ++$(OBJ)unixvoc.$o: $(SRC)jaudiolib/unixvoc.c $(SRC)jaudiolib/usrhooks.h $(SRC)jaudiolib/linklist.h $(SRC)jaudiolib/pitch.h $(SRC)jaudiolib/multivoc.h $(SRC)jaudiolib/_multivc.h ++ + $(OBJ)audiolib_fxstub.$o: $(SRC)jaudiolib/audiolib_fxstub.c $(SRC)jaudiolib/fx_man.h + $(OBJ)audiolib_musicstub.$o: $(SRC)jaudiolib/audiolib_musicstub.c $(SRC)jaudiolib/music.h + diff --git a/games/eduke32/files/patch-source__game.c b/games/eduke32/files/patch-source__game.c new file mode 100644 index 000000000000..4d94d06a1b54 --- /dev/null +++ b/games/eduke32/files/patch-source__game.c @@ -0,0 +1,11 @@ +--- source/game.c.orig Tue Jul 18 16:14:46 2006 ++++ source/game.c Wed Aug 2 01:12:20 2006 +@@ -8887,7 +8887,7 @@ + + i = CONFIG_ReadSetup(); + +-#if defined RENDERTYPEWIN || (defined RENDERTYPESDL && !defined __APPLE__ && defined HAVE_GTK2) ++#if 0 + if (i < 0 || ForceSetup || CommandSetup) { + if (quitevent || !startwin_run()) { + uninitengine(); diff --git a/games/eduke32/files/patch-source__jaudiolib___multivc.h b/games/eduke32/files/patch-source__jaudiolib___multivc.h new file mode 100644 index 000000000000..4054b41d1d92 --- /dev/null +++ b/games/eduke32/files/patch-source__jaudiolib___multivc.h @@ -0,0 +1,15 @@ +--- ./source/jaudiolib/_multivc.h.orig Tue Jul 18 16:14:46 2006 ++++ ./source/jaudiolib/_multivc.h Wed Aug 2 00:35:30 2006 +@@ -67,8 +67,11 @@ + #define SILENCE_8BIT 0x80808080 + //#define SILENCE_16BIT_PAS 0 + +-//#define MixBufferSize 256 ++#ifdef WINDOWS + #define MixBufferSize (MV_GetBufferSize(MV_RequestedMixRate)) ++#else ++#define MixBufferSize 256 ++#endif + + #define NumberOfBuffers 16 + #define TotalBufferSize ( MixBufferSize * NumberOfBuffers ) diff --git a/games/eduke32/files/patch-source__jaudiolib__debugio.h b/games/eduke32/files/patch-source__jaudiolib__debugio.h new file mode 100644 index 000000000000..c069b572f584 --- /dev/null +++ b/games/eduke32/files/patch-source__jaudiolib__debugio.h @@ -0,0 +1,33 @@ +--- ./source/jaudiolib/debugio.h.orig Wed Aug 2 00:35:30 2006 ++++ ./source/jaudiolib/debugio.h Wed Aug 2 00:35:30 2006 +@@ -0,0 +1,30 @@ ++/* ++Copyright (C) 1994-1995 Apogee Software, Ltd. ++ ++This program is free software; you can redistribute it and/or ++modify it under the terms of the GNU 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 General Public License for more details. ++ ++You should have received a copy of the GNU General Public License ++along with this program; if not, write to the Free Software ++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ ++*/ ++#ifndef __DEBUGIO_H ++#define __DEBUGIO_H ++ ++void DB_SetXY( int x, int y ); ++void DB_PutChar( char ch ); ++int DB_PrintString( char *string ); ++int DB_PrintNum( int number ); ++int DB_PrintUnsigned( unsigned long number, int radix ); ++int DB_printf( char *fmt, ... ); ++ ++#endif diff --git a/games/eduke32/files/patch-source__jaudiolib__dma.h b/games/eduke32/files/patch-source__jaudiolib__dma.h new file mode 100644 index 000000000000..0486890e7654 --- /dev/null +++ b/games/eduke32/files/patch-source__jaudiolib__dma.h @@ -0,0 +1,86 @@ +--- ./source/jaudiolib/dma.h.orig Wed Aug 2 00:35:30 2006 ++++ ./source/jaudiolib/dma.h Wed Aug 2 00:35:30 2006 +@@ -0,0 +1,83 @@ ++/* ++Copyright (C) 1994-1995 Apogee Software, Ltd. ++ ++This program is free software; you can redistribute it and/or ++modify it under the terms of the GNU 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 General Public License for more details. ++ ++You should have received a copy of the GNU General Public License ++along with this program; if not, write to the Free Software ++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ ++*/ ++/********************************************************************** ++ file: DMA.H ++ ++ author: James R. Dose ++ date: February 4, 1994 ++ ++ Public header file for DMA.C ++ ++ (c) Copyright 1994 James R. Dose. All Rights Reserved. ++**********************************************************************/ ++ ++#ifndef __DMA_H ++#define __DMA_H ++ ++enum DMA_ERRORS ++ { ++ DMA_Error = -1, ++ DMA_Ok = 0, ++ DMA_ChannelOutOfRange, ++ DMA_InvalidChannel ++ }; ++ ++enum DMA_Modes ++ { ++ DMA_SingleShotRead, ++ DMA_SingleShotWrite, ++ DMA_AutoInitRead, ++ DMA_AutoInitWrite ++ }; ++ ++char *DMA_ErrorString ++ ( ++ int ErrorNumber ++ ); ++ ++int DMA_VerifyChannel ++ ( ++ int channel ++ ); ++ ++int DMA_SetupTransfer ++ ( ++ int channel, ++ char *address, ++ int length, ++ int mode ++ ); ++ ++int DMA_EndTransfer ++ ( ++ int channel ++ ); ++ ++char *DMA_GetCurrentPos ++ ( ++ int channel ++ ); ++ ++int DMA_GetTransferCount ++ ( ++ int channel ++ ); ++ ++#endif diff --git a/games/eduke32/files/patch-source__jaudiolib__dpmi.h b/games/eduke32/files/patch-source__jaudiolib__dpmi.h new file mode 100644 index 000000000000..16083784f49b --- /dev/null +++ b/games/eduke32/files/patch-source__jaudiolib__dpmi.h @@ -0,0 +1,46 @@ +--- ./source/jaudiolib/dpmi.h.orig Wed Aug 2 00:35:30 2006 ++++ ./source/jaudiolib/dpmi.h Wed Aug 2 00:35:30 2006 +@@ -0,0 +1,43 @@ ++/* ++Copyright (C) 1994-1995 Apogee Software, Ltd. ++ ++This program is free software; you can redistribute it and/or ++modify it under the terms of the GNU 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 General Public License for more details. ++ ++You should have received a copy of the GNU General Public License ++along with this program; if not, write to the Free Software ++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ ++*/ ++/********************************************************************** ++ module: DPMI.H ++ ++ author: James R. Dose ++ date: March 31, 1994 ++ ++ Inline functions for performing DPMI calls. ++ ++ (c) Copyright 1994 James R. Dose. All Rights Reserved. ++**********************************************************************/ ++ ++#ifndef __DPMI_H ++#define __DPMI_H ++ ++enum DPMI_Errors ++ { ++ DPMI_Warning = -2, ++ DPMI_Error = -1, ++ DPMI_Ok = 0 ++ }; ++ ++int DPMI_GetDOSMemory( void **ptr, int *descriptor, unsigned length ); ++int DPMI_FreeDOSMemory( int descriptor ); ++#endif diff --git a/games/eduke32/files/patch-source__jaudiolib__dsl.c b/games/eduke32/files/patch-source__jaudiolib__dsl.c new file mode 100644 index 000000000000..c21616cc0b9c --- /dev/null +++ b/games/eduke32/files/patch-source__jaudiolib__dsl.c @@ -0,0 +1,260 @@ +--- ./source/jaudiolib/dsl.c.orig Wed Aug 2 00:35:30 2006 ++++ ./source/jaudiolib/dsl.c Wed Aug 2 00:35:30 2006 +@@ -0,0 +1,257 @@ ++/* ++Copyright (C) 2003-2004 Ryan C. Gordon. and James Bentler ++ ++This program is free software; you can redistribute it and/or ++modify it under the terms of the GNU 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 General Public License for more details. ++ ++You should have received a copy of the GNU General Public License ++along with this program; if not, write to the Free Software ++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ ++Originally written by Ryan C. Gordon. (icculus@clutteredmind.org) ++Adapted to work with JonoF's port by James Bentler (bentler@cs.umn.edu) ++ ++*/ ++#include ++#include ++ ++#include "dsl.h" ++#include "util.h" ++ ++#include "SDL.h" ++#include "SDL_mixer.h" ++ ++extern volatile int MV_MixPage; ++ ++static int DSL_ErrorCode = DSL_Ok; ++ ++static int mixer_initialized; ++ ++static void ( *_CallBackFunc )( void ); ++static volatile char *_BufferStart; ++static int _BufferSize; ++static int _NumDivisions; ++static int _SampleRate; ++static int _remainder; ++ ++static Mix_Chunk *blank; ++static unsigned char *blank_buf; ++ ++/* ++possible todo ideas: cache sdl/sdl mixer error messages. ++*/ ++ ++char *DSL_ErrorString( int ErrorNumber ) ++{ ++ char *ErrorString; ++ ++ switch (ErrorNumber) { ++ case DSL_Warning: ++ case DSL_Error: ++ ErrorString = DSL_ErrorString(DSL_ErrorCode); ++ break; ++ ++ case DSL_Ok: ++ ErrorString = "SDL Driver ok."; ++ break; ++ ++ case DSL_SDLInitFailure: ++ ErrorString = "SDL Audio initialization failed."; ++ break; ++ ++ case DSL_MixerActive: ++ ErrorString = "SDL Mixer already initialized."; ++ break; ++ ++ case DSL_MixerInitFailure: ++ ErrorString = "SDL Mixer initialization failed."; ++ break; ++ ++ default: ++ ErrorString = "Unknown SDL Driver error."; ++ break; ++ } ++ ++ return ErrorString; ++} ++ ++static void DSL_SetErrorCode(int ErrorCode) ++{ ++ DSL_ErrorCode = ErrorCode; ++} ++ ++int DSL_Init( void ) ++{ ++ DSL_SetErrorCode(DSL_Ok); ++ ++ if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { ++ DSL_SetErrorCode(DSL_SDLInitFailure); ++ ++ return DSL_Error; ++ } ++ ++ return DSL_Ok; ++} ++ ++void DSL_Shutdown( void ) ++{ ++ DSL_StopPlayback(); ++} ++ ++static void mixer_callback(int chan, void *stream, int len, void *udata) ++{ ++ Uint8 *stptr; ++ Uint8 *fxptr; ++ int copysize; ++ ++ /* len should equal _BufferSize, else this is screwed up */ ++ ++ stptr = (Uint8 *)stream; ++ ++ if (_remainder > 0) { ++ copysize = min(len, _remainder); ++ ++ fxptr = (Uint8 *)(&_BufferStart[MV_MixPage * ++ _BufferSize]); ++ ++ memcpy(stptr, fxptr+(_BufferSize-_remainder), copysize); ++ ++ len -= copysize; ++ _remainder -= copysize; ++ ++ stptr += copysize; ++ } ++ ++ while (len > 0) { ++ /* new buffer */ ++ ++ _CallBackFunc(); ++ ++ fxptr = (Uint8 *)(&_BufferStart[MV_MixPage * ++ _BufferSize]); ++ ++ copysize = min(len, _BufferSize); ++ ++ memcpy(stptr, fxptr, copysize); ++ ++ len -= copysize; ++ ++ stptr += copysize; ++ } ++ ++ _remainder = len; ++} ++ ++int DSL_BeginBufferedPlayback( char *BufferStart, ++ int BufferSize, int NumDivisions, unsigned SampleRate, ++ int MixMode, void ( *CallBackFunc )( void ) ) ++{ ++ Uint16 format; ++ Uint8 *tmp; ++ int channels; ++ int chunksize; ++ ++ if (mixer_initialized) { ++ DSL_SetErrorCode(DSL_MixerActive); ++ ++ return DSL_Error; ++ } ++ ++ _CallBackFunc = CallBackFunc; ++ _BufferStart = BufferStart; ++ _BufferSize = (BufferSize / NumDivisions); ++ _NumDivisions = NumDivisions; ++ _SampleRate = SampleRate; ++ ++ _remainder = 0; ++ ++ format = (MixMode & SIXTEEN_BIT) ? AUDIO_S16SYS : AUDIO_U8; ++ channels = (MixMode & STEREO) ? 2 : 1; ++ ++/* ++ 23ms is typically ideal (11025,22050,44100) ++ 46ms isn't bad ++*/ ++ ++ chunksize = 512; ++ ++ if (SampleRate >= 16000) chunksize *= 2; ++ if (SampleRate >= 32000) chunksize *= 2; ++ ++/* ++// SDL mixer does this already ++ if (MixMode & SIXTEEN_BIT) chunksize *= 2; ++ if (MixMode & STEREO) chunksize *= 2; ++*/ ++ ++ if (Mix_OpenAudio(SampleRate, format, channels, chunksize) < 0) { ++ DSL_SetErrorCode(DSL_MixerInitFailure); ++ ++ return DSL_Error; ++ } ++ ++/* ++ Mix_SetPostMix(mixer_callback, NULL); ++*/ ++ /* have to use a channel because postmix will overwrite the music... */ ++ Mix_RegisterEffect(0, mixer_callback, NULL, NULL); ++ ++ /* create a dummy sample just to allocate that channel */ ++ blank_buf = (Uint8 *)malloc(4096); ++ memset(blank_buf, 0, 4096); ++ ++ blank = Mix_QuickLoad_RAW(blank_buf, 4096); ++ ++ Mix_PlayChannel(0, blank, -1); ++ ++ mixer_initialized = 1; ++ ++ return DSL_Ok; ++} ++ ++void DSL_StopPlayback( void ) ++{ ++ if (mixer_initialized) { ++ Mix_HaltChannel(0); ++ } ++ ++ if (blank != NULL) { ++ Mix_FreeChunk(blank); ++ } ++ ++ blank = NULL; ++ ++ if (blank_buf != NULL) { ++ free(blank_buf); ++ } ++ ++ blank_buf = NULL; ++ ++ if (mixer_initialized) { ++ Mix_CloseAudio(); ++ } ++ ++ mixer_initialized = 0; ++} ++ ++unsigned DSL_GetPlaybackRate( void ) ++{ ++ return _SampleRate; ++} ++ ++unsigned long DisableInterrupts( void ) ++{ ++ return 0; ++} ++ ++void RestoreInterrupts( unsigned long flags ) ++{ ++} diff --git a/games/eduke32/files/patch-source__jaudiolib__dsl.h b/games/eduke32/files/patch-source__jaudiolib__dsl.h new file mode 100644 index 000000000000..d1778619868e --- /dev/null +++ b/games/eduke32/files/patch-source__jaudiolib__dsl.h @@ -0,0 +1,53 @@ +--- ./source/jaudiolib/dsl.h.orig Wed Aug 2 00:35:30 2006 ++++ ./source/jaudiolib/dsl.h Wed Aug 2 00:35:30 2006 +@@ -0,0 +1,50 @@ ++/* ++Copyright (C) 2003-2004 Ryan C. Gordon. and James Bentler ++ ++This program is free software; you can redistribute it and/or ++modify it under the terms of the GNU 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 General Public License for more details. ++ ++You should have received a copy of the GNU General Public License ++along with this program; if not, write to the Free Software ++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ ++Originally written by Ryan C. Gordon. (icculus@clutteredmind.org) ++Adapted to work with JonoF's port by James Bentler (bentler@cs.umn.edu) ++ ++*/ ++#ifndef AUDIOLIB__DSL_H ++#define AUDIOLIB__DSL_H ++ ++#define MONO_8BIT 0 ++#define STEREO 1 ++#define SIXTEEN_BIT 2 ++#define STEREO_16BIT ( STEREO | SIXTEEN_BIT ) ++ ++enum DSL_ERRORS ++ { ++ DSL_Warning = -2, ++ DSL_Error = -1, ++ DSL_Ok = 0, ++ DSL_SDLInitFailure, ++ DSL_MixerActive, ++ DSL_MixerInitFailure ++ }; ++ ++char *DSL_ErrorString( int ErrorNumber ); ++int DSL_Init( void ); ++void DSL_StopPlayback( void ); ++unsigned DSL_GetPlaybackRate( void ); ++int DSL_BeginBufferedPlayback( char *BufferStart, ++ int BufferSize, int NumDivisions, unsigned SampleRate, ++ int MixMode, void ( *CallBackFunc )( void ) ); ++void DSL_Shutdown( void ); ++ ++#endif diff --git a/games/eduke32/files/patch-source__jaudiolib__interrup.h b/games/eduke32/files/patch-source__jaudiolib__interrup.h new file mode 100644 index 000000000000..4b48a4cd8053 --- /dev/null +++ b/games/eduke32/files/patch-source__jaudiolib__interrup.h @@ -0,0 +1,53 @@ +--- ./source/jaudiolib/interrup.h.orig Wed Aug 2 00:35:30 2006 ++++ ./source/jaudiolib/interrup.h Wed Aug 2 00:35:30 2006 +@@ -0,0 +1,50 @@ ++/* ++Copyright (C) 1994-1995 Apogee Software, Ltd. ++ ++This program is free software; you can redistribute it and/or ++modify it under the terms of the GNU 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 General Public License for more details. ++ ++You should have received a copy of the GNU General Public License ++along with this program; if not, write to the Free Software ++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ ++*/ ++/********************************************************************** ++ module: INTERRUP.H ++ ++ author: James R. Dose ++ date: March 31, 1994 ++ ++ Inline functions for disabling and restoring the interrupt flag. ++ ++ (c) Copyright 1994 James R. Dose. All Rights Reserved. ++**********************************************************************/ ++ ++#ifndef __INTERRUPT_H ++#define __INTERRUPT_H ++ ++unsigned long DisableInterrupts( void ); ++void RestoreInterrupts( unsigned long flags ); ++ ++#ifdef PLAT_DOS ++#pragma aux DisableInterrupts = \ ++ "pushfd", \ ++ "pop eax", \ ++ "cli" \ ++ modify [ eax ]; ++ ++#pragma aux RestoreInterrupts = \ ++ "push eax", \ ++ "popfd" \ ++ parm [ eax ]; ++#endif ++ ++#endif diff --git a/games/eduke32/files/patch-source__jaudiolib__nodpmi.c b/games/eduke32/files/patch-source__jaudiolib__nodpmi.c new file mode 100644 index 000000000000..ff45bcfaeb0f --- /dev/null +++ b/games/eduke32/files/patch-source__jaudiolib__nodpmi.c @@ -0,0 +1,53 @@ +--- ./source/jaudiolib/nodpmi.c.orig Wed Aug 2 00:35:30 2006 ++++ ./source/jaudiolib/nodpmi.c Wed Aug 2 00:35:30 2006 +@@ -0,0 +1,50 @@ ++/* ++Copyright (C) 1994-1995 Apogee Software, Ltd. ++ ++This program is free software; you can redistribute it and/or ++modify it under the terms of the GNU 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 General Public License for more details. ++ ++You should have received a copy of the GNU General Public License ++along with this program; if not, write to the Free Software ++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ ++*/ ++/********************************************************************** ++ module: NODPMI.C ++ ++ Functions for faking DPMI calls. ++ ++**********************************************************************/ ++ ++#include ++#include ++#include "dpmi.h" ++ ++#define TRUE ( 1 == 1 ) ++#define FALSE ( !TRUE ) ++ ++int DPMI_GetDOSMemory( void **ptr, int *descriptor, unsigned length ) ++{ ++ /* Lovely... */ ++ ++ *ptr = (void *)malloc(length); ++ ++ *descriptor = (int) *ptr; ++ ++ return (descriptor == 0) ? DPMI_Error : DPMI_Ok; ++} ++ ++int DPMI_FreeDOSMemory( int descriptor ) ++{ ++ free((void *)descriptor); ++ ++ return (descriptor == 0) ? DPMI_Error : DPMI_Ok; ++} diff --git a/games/eduke32/files/patch-source__jaudiolib__platform.h b/games/eduke32/files/patch-source__jaudiolib__platform.h new file mode 100644 index 000000000000..6f980716f42a --- /dev/null +++ b/games/eduke32/files/patch-source__jaudiolib__platform.h @@ -0,0 +1,64 @@ +--- ./source/jaudiolib/platform.h.orig Wed Aug 2 00:35:30 2006 ++++ ./source/jaudiolib/platform.h Wed Aug 2 00:35:30 2006 +@@ -0,0 +1,61 @@ ++#ifndef _INCLUDE_PLATFORM_H_ ++#define _INCLUDE_PLATFORM_H_ ++ ++#if (!defined __EXPORT__) ++#define __EXPORT__ ++#endif ++ ++#if (defined __WATCOMC__) ++#define snprintf _snprintf ++#endif ++ ++static __inline unsigned short _swap16(unsigned short D) ++{ ++#if PLATFORM_MACOSX ++ register unsigned short returnValue; ++ __asm__ volatile("lhbrx %0,0,%1" ++ : "=r" (returnValue) ++ : "r" (&D) ++ ); ++ return returnValue; ++#else ++ return((D<<8)|(D>>8)); ++#endif ++} ++ ++static __inline unsigned int _swap32(unsigned int D) ++{ ++#if PLATFORM_MACOSX ++ register unsigned int returnValue; ++ __asm__ volatile("lwbrx %0,0,%1" ++ : "=r" (returnValue) ++ : "r" (&D) ++ ); ++ return returnValue; ++#else ++ return((D<<24)|((D<<8)&0x00FF0000)|((D>>8)&0x0000FF00)|(D>>24)); ++#endif ++} ++ ++#if PLATFORM_MACOSX ++#define PLATFORM_BIGENDIAN 1 ++#define BUILDSWAP_INTEL16(x) _swap16(x) ++#define BUILDSWAP_INTEL32(x) _swap32(x) ++#else ++#if __BYTE_ORDER == __LITTLE_ENDIAN ++#define PLATFORM_LITTLEENDIAN 1 ++#define BUILDSWAP_INTEL16(x) (x) ++#define BUILDSWAP_INTEL32(x) (x) ++#else ++#define PLATFORM_BIGENDIAN 1 ++#define BUILDSWAP_INTEL16(x) _swap16(x) ++#define BUILDSWAP_INTEL32(x) _swap32(x) ++#endif ++#endif ++ ++extern int has_altivec; /* PowerPC-specific. */ ++ ++#endif /* !defined _INCLUDE_PLATFORM_H_ */ ++ ++/* end of platform.h ... */ ++ diff --git a/games/eduke32/files/patch-source__jaudiolib__sdlmusic.c b/games/eduke32/files/patch-source__jaudiolib__sdlmusic.c new file mode 100644 index 000000000000..59c1b5147d85 --- /dev/null +++ b/games/eduke32/files/patch-source__jaudiolib__sdlmusic.c @@ -0,0 +1,481 @@ +--- ./source/jaudiolib/sdlmusic.c.orig Wed Aug 2 00:35:30 2006 ++++ ./source/jaudiolib/sdlmusic.c Wed Aug 2 00:35:30 2006 +@@ -0,0 +1,478 @@ ++/* ++Copyright (C) 2003-2004 Ryan C. Gordon. and James Bentler ++ ++This program is free software; you can redistribute it and/or ++modify it under the terms of the GNU 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 General Public License for more details. ++ ++You should have received a copy of the GNU General Public License ++along with this program; if not, write to the Free Software ++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ ++Originally written by Ryan C. Gordon. (icculus@clutteredmind.org) ++Adapted to work with JonoF's port by James Bentler (bentler@cs.umn.edu) ++ ++*/ ++/* ++ * A reimplementation of Jim Dose's FX_MAN routines, using SDL_mixer 1.2. ++ * Whee. FX_MAN is also known as the "Apogee Sound System", or "ASS" for ++ * short. How strangely appropriate that seems. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "duke3d.h" ++#include "cache1d.h" ++ ++#ifndef MAX_PATH ++#define MAX_PATH 256 ++#endif ++ ++#if (defined __WATCOMC__) ++// This is probably out of date. --ryan. ++#include "dukesnd_watcom.h" ++#endif ++ ++#if (!defined __WATCOMC__) ++#define cdecl ++#endif ++ ++#include "SDL.h" ++#include "SDL_mixer.h" ++#include "music.h" ++ ++#define __FX_TRUE (1 == 1) ++#define __FX_FALSE (!__FX_TRUE) ++ ++#define DUKESND_DEBUG "DUKESND_DEBUG" ++ ++#ifndef min ++#define min(a, b) (((a) < (b)) ? (a) : (b)) ++#endif ++ ++#ifndef max ++#define max(a, b) (((a) > (b)) ? (a) : (b)) ++#endif ++ ++void GetUnixPathFromEnvironment( char *fullname, int32 length, const char *filename ); ++ ++int MUSIC_ErrorCode = MUSIC_Ok; ++ ++static char warningMessage[80]; ++static char errorMessage[80]; ++static int fx_initialized = 0; ++static int numChannels = MIX_CHANNELS; ++static void (*callback)(unsigned long); ++static int reverseStereo = 0; ++static int reverbDelay = 256; ++static int reverbLevel = 0; ++static int fastReverb = 0; ++static FILE *debug_file = NULL; ++static int initialized_debugging = 0; ++static int mixerIsStereo = 1; ++ ++// This gets called all over the place for information and debugging messages. ++// If the user set the DUKESND_DEBUG environment variable, the messages ++// go to the file that is specified in that variable. Otherwise, they ++// are ignored for the expense of the function call. If DUKESND_DEBUG is ++// set to "-" (without the quotes), then the output goes to stdout. ++static void musdebug(const char *fmt, ...) ++{ ++ va_list ap; ++ ++ if (debug_file) ++ { ++ fprintf(debug_file, "DUKEMUS: "); ++ va_start(ap, fmt); ++ vfprintf(debug_file, fmt, ap); ++ va_end(ap); ++ fprintf(debug_file, "\n"); ++ fflush(debug_file); ++ } // if ++} // musdebug ++ ++static void init_debugging(void) ++{ ++ const char *envr; ++ ++ if (initialized_debugging) ++ return; ++ ++ envr = getenv(DUKESND_DEBUG); ++ if (envr != NULL) ++ { ++ if (strcmp(envr, "-") == 0) ++ debug_file = stdout; ++ else ++ debug_file = fopen(envr, "w"); ++ ++ if (debug_file == NULL) ++ fprintf(stderr, "DUKESND: -WARNING- Could not open debug file!\n"); ++ else ++ setbuf(debug_file, NULL); ++ } // if ++ ++ initialized_debugging = 1; ++} // init_debugging ++ ++static void setWarningMessage(const char *msg) ++{ ++ strncpy(warningMessage, msg, sizeof (warningMessage)); ++ // strncpy() doesn't add the null char if there isn't room... ++ warningMessage[sizeof (warningMessage) - 1] = '\0'; ++ musdebug("Warning message set to [%s].", warningMessage); ++} // setErrorMessage ++ ++ ++static void setErrorMessage(const char *msg) ++{ ++ strncpy(errorMessage, msg, sizeof (errorMessage)); ++ // strncpy() doesn't add the null char if there isn't room... ++ errorMessage[sizeof (errorMessage) - 1] = '\0'; ++ musdebug("Error message set to [%s].", errorMessage); ++} // setErrorMessage ++ ++// The music functions... ++ ++char *MUSIC_ErrorString(int ErrorNumber) ++{ ++ switch (ErrorNumber) ++ { ++ case MUSIC_Warning: ++ return(warningMessage); ++ ++ case MUSIC_Error: ++ return(errorMessage); ++ ++ case MUSIC_Ok: ++ return("OK; no error."); ++ ++ case MUSIC_ASSVersion: ++ return("Incorrect sound library version."); ++ ++ case MUSIC_SoundCardError: ++ return("General sound card error."); ++ ++ case MUSIC_InvalidCard: ++ return("Invalid sound card."); ++ ++ case MUSIC_MidiError: ++ return("MIDI error."); ++ ++ case MUSIC_MPU401Error: ++ return("MPU401 error."); ++ ++ case MUSIC_TaskManError: ++ return("Task Manager error."); ++ ++ //case MUSIC_FMNotDetected: ++ // return("FM not detected error."); ++ ++ case MUSIC_DPMI_Error: ++ return("DPMI error."); ++ ++ default: ++ return("Unknown error."); ++ } // switch ++ ++ assert(0); // shouldn't hit this point. ++ return(NULL); ++} // MUSIC_ErrorString ++ ++ ++static int music_initialized = 0; ++static int music_context = 0; ++static int music_loopflag = MUSIC_PlayOnce; ++static char *music_songdata = NULL; ++static Mix_Music *music_musicchunk = NULL; ++ ++int MUSIC_Init(int SoundCard, int Address) ++{ ++ init_debugging(); ++ ++ musdebug("INIT! card=>%d, address=>%d...", SoundCard, Address); ++ ++ if (music_initialized) ++ { ++ setErrorMessage("Music system is already initialized."); ++ return(MUSIC_Error); ++ } // if ++ ++ SoundCard = 1; ++ ++ music_initialized = 1; ++ return(MUSIC_Ok); ++} // MUSIC_Init ++ ++ ++int MUSIC_Shutdown(void) ++{ ++ musdebug("shutting down sound subsystem."); ++ ++ MUSIC_StopSong(); ++ music_context = 0; ++ music_initialized = 0; ++ music_loopflag = MUSIC_PlayOnce; ++ return(MUSIC_Ok); ++} // MUSIC_Shutdown ++ ++ ++void MUSIC_SetMaxFMMidiChannel(int channel) ++{ ++ musdebug("STUB ... MUSIC_SetMaxFMMidiChannel(%d).\n", channel); ++} // MUSIC_SetMaxFMMidiChannel ++ ++ ++void MUSIC_SetVolume(int volume) ++{ ++ volume = max( 0, volume ); ++ volume = min( volume, 255 ); ++ ++ Mix_VolumeMusic(volume >> 1); // convert 0-255 to 0-128. ++} // MUSIC_SetVolume ++ ++ ++void MUSIC_SetMidiChannelVolume(int channel, int volume) ++{ ++ musdebug("STUB ... MUSIC_SetMidiChannelVolume(%d, %d).\n", channel, volume); ++} // MUSIC_SetMidiChannelVolume ++ ++ ++void MUSIC_ResetMidiChannelVolumes(void) ++{ ++ musdebug("STUB ... MUSIC_ResetMidiChannelVolumes().\n"); ++} // MUSIC_ResetMidiChannelVolumes ++ ++ ++int MUSIC_GetVolume(void) ++{ ++ return(Mix_VolumeMusic(-1) << 1); // convert 0-128 to 0-255. ++} // MUSIC_GetVolume ++ ++ ++void MUSIC_SetLoopFlag(int loopflag) ++{ ++ music_loopflag = loopflag; ++} // MUSIC_SetLoopFlag ++ ++ ++int MUSIC_SongPlaying(void) ++{ ++ return((Mix_PlayingMusic()) ? __FX_TRUE : __FX_FALSE); ++} // MUSIC_SongPlaying ++ ++ ++void MUSIC_Continue(void) ++{ ++ if (Mix_PausedMusic()) ++ Mix_ResumeMusic(); ++ else if (music_songdata) ++ MUSIC_PlaySong(music_songdata, MUSIC_PlayOnce); ++} // MUSIC_Continue ++ ++ ++void MUSIC_Pause(void) ++{ ++ Mix_PauseMusic(); ++} // MUSIC_Pause ++ ++ ++int MUSIC_StopSong(void) ++{ ++ //if (!fx_initialized) ++ if (!Mix_QuerySpec(NULL, NULL, NULL)) ++ { ++ setErrorMessage("Need FX system initialized, too. Sorry."); ++ return(MUSIC_Error); ++ } // if ++ ++ if ( (Mix_PlayingMusic()) || (Mix_PausedMusic()) ) ++ Mix_HaltMusic(); ++ ++ if (music_musicchunk) ++ Mix_FreeMusic(music_musicchunk); ++ ++ music_songdata = NULL; ++ music_musicchunk = NULL; ++ return(MUSIC_Ok); ++} // MUSIC_StopSong ++ ++ ++int MUSIC_PlaySong(unsigned char *song, int loopflag) ++{ ++ //SDL_RWops *rw; ++ ++ MUSIC_StopSong(); ++ ++ music_songdata = song; ++ ++ // !!! FIXME: This could be a problem...SDL/SDL_mixer wants a RWops, which ++ // !!! FIXME: is an i/o abstraction. Since we already have the MIDI data ++ // !!! FIXME: in memory, we fake it with a memory-based RWops. None of ++ // !!! FIXME: this is a problem, except the RWops wants to know how big ++ // !!! FIXME: its memory block is (so it can do things like seek on an ++ // !!! FIXME: offset from the end of the block), and since we don't have ++ // !!! FIXME: this information, we have to give it SOMETHING. ++ ++ /* !!! ARGH! There's no LoadMUS_RW ?! ++ rw = SDL_RWFromMem((void *) song, (10 * 1024) * 1024); // yikes. ++ music_musicchunk = Mix_LoadMUS_RW(rw); ++ Mix_PlayMusic(music_musicchunk, (loopflag == MUSIC_PlayOnce) ? 0 : -1); ++ */ ++ ++ return(MUSIC_Ok); ++} // MUSIC_PlaySong ++ ++ ++extern char ApogeePath[256] = "/tmp/"; ++ ++// Duke3D-specific. --ryan. ++void PlayMusic(char *_filename) ++{ ++ //char filename[MAX_PATH]; ++ //strcpy(filename, _filename); ++ //FixFilePath(filename); ++ ++ char filename[MAX_PATH]; ++ long handle; ++ long size; ++ void *song; ++ long rc; ++ ++ MUSIC_StopSong(); ++ ++ // Read from a groupfile, write it to disk so SDL_mixer can read it. ++ // Lame. --ryan. ++ handle = kopen4load(_filename, 0); ++ if (handle == -1) ++ return; ++ ++ size = kfilelength(handle); ++ if (size == -1) ++ { ++ kclose(handle); ++ return; ++ } // if ++ ++ song = malloc(size); ++ if (song == NULL) ++ { ++ kclose(handle); ++ return; ++ } // if ++ ++ rc = kread(handle, song, size); ++ kclose(handle); ++ if (rc != size) ++ { ++ free(song); ++ return; ++ } // if ++ ++ // save the file somewhere, so SDL_mixer can load it ++ GetUnixPathFromEnvironment(filename, MAX_PATH, "tmpsong.mid"); ++ handle = SafeOpenWrite(filename, filetype_binary); ++ ++ SafeWrite(handle, song, size); ++ close(handle); ++ free(song); ++ ++ //music_songdata = song; ++ ++ music_musicchunk = Mix_LoadMUS(filename); ++ if (music_musicchunk != NULL) ++ { ++ // !!! FIXME: I set the music to loop. Hope that's okay. --ryan. ++ Mix_PlayMusic(music_musicchunk, -1); ++ } // if ++} ++ ++ ++void MUSIC_SetContext(int context) ++{ ++ musdebug("STUB ... MUSIC_SetContext().\n"); ++ music_context = context; ++} // MUSIC_SetContext ++ ++ ++int MUSIC_GetContext(void) ++{ ++ return(music_context); ++} // MUSIC_GetContext ++ ++ ++void MUSIC_SetSongTick(unsigned long PositionInTicks) ++{ ++ musdebug("STUB ... MUSIC_SetSongTick().\n"); ++} // MUSIC_SetSongTick ++ ++ ++void MUSIC_SetSongTime(unsigned long milliseconds) ++{ ++ musdebug("STUB ... MUSIC_SetSongTime().\n"); ++}// MUSIC_SetSongTime ++ ++ ++void MUSIC_SetSongPosition(int measure, int beat, int tick) ++{ ++ musdebug("STUB ... MUSIC_SetSongPosition().\n"); ++} // MUSIC_SetSongPosition ++ ++ ++void MUSIC_GetSongPosition(songposition *pos) ++{ ++ musdebug("STUB ... MUSIC_GetSongPosition().\n"); ++} // MUSIC_GetSongPosition ++ ++ ++void MUSIC_GetSongLength(songposition *pos) ++{ ++ musdebug("STUB ... MUSIC_GetSongLength().\n"); ++} // MUSIC_GetSongLength ++ ++ ++int MUSIC_FadeVolume(int tovolume, int milliseconds) ++{ ++ Mix_FadeOutMusic(milliseconds); ++ return(MUSIC_Ok); ++} // MUSIC_FadeVolume ++ ++ ++int MUSIC_FadeActive(void) ++{ ++ return((Mix_FadingMusic() == MIX_FADING_OUT) ? __FX_TRUE : __FX_FALSE); ++} // MUSIC_FadeActive ++ ++ ++void MUSIC_StopFade(void) ++{ ++ musdebug("STUB ... MUSIC_StopFade().\n"); ++} // MUSIC_StopFade ++ ++ ++void MUSIC_RerouteMidiChannel(int channel, int cdecl (*function)( int event, int c1, int c2 )) ++{ ++ musdebug("STUB ... MUSIC_RerouteMidiChannel().\n"); ++} // MUSIC_RerouteMidiChannel ++ ++ ++void MUSIC_RegisterTimbreBank(unsigned char *timbres) ++{ ++ musdebug("STUB ... MUSIC_RegisterTimbreBank().\n"); ++} // MUSIC_RegisterTimbreBank ++ ++ ++void MUSIC_Update(void) ++{ ++} diff --git a/games/eduke32/files/patch-source__jaudiolib__unixglob.c b/games/eduke32/files/patch-source__jaudiolib__unixglob.c new file mode 100644 index 000000000000..3b498d0f0d91 --- /dev/null +++ b/games/eduke32/files/patch-source__jaudiolib__unixglob.c @@ -0,0 +1,152 @@ +--- ./source/jaudiolib/unixglob.c.orig Wed Aug 2 00:35:30 2006 ++++ ./source/jaudiolib/unixglob.c Wed Aug 2 00:35:30 2006 +@@ -0,0 +1,149 @@ ++/* ++Copyright (C) 2003-2004 Ryan C. Gordon. and James Bentler ++ ++This program is free software; you can redistribute it and/or ++modify it under the terms of the GNU 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 General Public License for more details. ++ ++You should have received a copy of the GNU General Public License ++along with this program; if not, write to the Free Software ++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ ++Originally written by Ryan C. Gordon. (icculus@clutteredmind.org) ++Adapted to work with JonoF's port by James Bentler (bentler@cs.umn.edu) ++ ++*/ ++ ++static char ApogeePath[256] = "/tmp/"; ++ ++#define PATH_SEP_CHAR '/' ++#define PATH_SEP_STR "/" ++#define ROOTDIR "/" ++#define CURDIR "./" ++ ++#include "duke3d.h" ++#include ++#include ++ ++#ifndef MAX_PATH ++#define MAX_PATH 256 ++#endif ++ ++void FixFilePath(char *filename) ++{ ++ char *ptr; ++ char *lastsep = filename; ++ ++ if ((!filename) || (*filename == '\0')) ++ return; ++ ++ if (access(filename, F_OK) == 0) /* File exists; we're good to go. */ ++ return; ++ ++ for (ptr = filename; 1; ptr++) ++ { ++ if (*ptr == '\\') ++ *ptr = PATH_SEP_CHAR; ++ ++ if ((*ptr == PATH_SEP_CHAR) || (*ptr == '\0')) ++ { ++ char pch = *ptr; ++ struct dirent *dent = NULL; ++ DIR *dir; ++ ++ if ((pch == PATH_SEP_CHAR) && (*(ptr + 1) == '\0')) ++ return; /* eos is pathsep; we're done. */ ++ ++ if (lastsep == ptr) ++ continue; /* absolute path; skip to next one. */ ++ ++ *ptr = '\0'; ++ if (lastsep == filename) { ++ dir = opendir((*lastsep == PATH_SEP_CHAR) ? ROOTDIR : CURDIR); ++ ++ if (*lastsep == PATH_SEP_CHAR) { ++ lastsep++; ++ } ++ } ++ else ++ { ++ *lastsep = '\0'; ++ dir = opendir(filename); ++ *lastsep = PATH_SEP_CHAR; ++ lastsep++; ++ } ++ ++ if (dir == NULL) ++ { ++ *ptr = PATH_SEP_CHAR; ++ return; /* maybe dir doesn't exist? give up. */ ++ } ++ ++ while ((dent = readdir(dir)) != NULL) ++ { ++ if (strcasecmp(dent->d_name, lastsep) == 0) ++ { ++ /* found match; replace it. */ ++ strcpy(lastsep, dent->d_name); ++ break; ++ } ++ } ++ ++ closedir(dir); ++ *ptr = pch; ++ lastsep = ptr; ++ ++ if (dent == NULL) ++ return; /* no match. oh well. */ ++ ++ if (pch == '\0') /* eos? */ ++ return; ++ } ++ } ++} ++ ++int32 SafeOpenWrite (const char *_filename, int32 filetype) ++{ ++ int handle; ++ char filename[MAX_PATH]; ++ strncpy(filename, _filename, sizeof (filename)); ++ filename[sizeof (filename) - 1] = '\0'; ++ FixFilePath(filename); ++ ++ handle = open(filename,O_RDWR | O_BINARY | O_CREAT | O_TRUNC ++ , S_IREAD | S_IWRITE); ++ ++ if (handle == -1) ++ Error ("Error opening %s: %s",filename,strerror(errno)); ++ ++ return handle; ++} ++ ++ ++void SafeWrite (int32 handle, void *buffer, int32 count) ++{ ++ unsigned iocount; ++ ++ while (count) ++ { ++ iocount = count > 0x8000 ? 0x8000 : count; ++ if (write (handle,buffer,iocount) != (int)iocount) ++ Error ("File write failure writing %ld bytes",count); ++ buffer = (void *)( (byte *)buffer + iocount ); ++ count -= iocount; ++ } ++} ++ ++ ++ ++void GetUnixPathFromEnvironment( char *fullname, int32 length, const char *filename ) ++{ ++ snprintf(fullname, length-1, "%s%s", ApogeePath, filename); ++} diff --git a/games/eduke32/files/patch-source__jaudiolib__unixpitch.c b/games/eduke32/files/patch-source__jaudiolib__unixpitch.c new file mode 100644 index 000000000000..2f112d779556 --- /dev/null +++ b/games/eduke32/files/patch-source__jaudiolib__unixpitch.c @@ -0,0 +1,215 @@ +--- ./source/jaudiolib/unixpitch.c.orig Wed Aug 2 00:35:30 2006 ++++ ./source/jaudiolib/unixpitch.c Wed Aug 2 00:35:30 2006 +@@ -0,0 +1,212 @@ ++/* ++Copyright (C) 1994-1995 Apogee Software, Ltd. ++ ++This program is free software; you can redistribute it and/or ++modify it under the terms of the GNU 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 General Public License for more details. ++ ++You should have received a copy of the GNU General Public License ++along with this program; if not, write to the Free Software ++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ ++*/ ++/********************************************************************** ++ module: PITCH.C ++ ++ author: James R. Dose ++ date: June 14, 1993 ++ ++ Routines for pitch scaling. ++ ++ (c) Copyright 1993 James R. Dose. All Rights Reserved. ++**********************************************************************/ ++ ++#include ++//#include ++#include "dpmi.h" ++#include "standard.h" ++#include "pitch.h" ++ ++#define MAXDETUNE 25 ++ ++static unsigned long PitchTable[ 12 ][ MAXDETUNE ] = ++ { ++ { 0x10000, 0x10097, 0x1012f, 0x101c7, 0x10260, 0x102f9, 0x10392, 0x1042c, ++ 0x104c6, 0x10561, 0x105fb, 0x10696, 0x10732, 0x107ce, 0x1086a, 0x10907, ++ 0x109a4, 0x10a41, 0x10adf, 0x10b7d, 0x10c1b, 0x10cba, 0x10d59, 0x10df8, ++ 0x10e98 }, ++ { 0x10f38, 0x10fd9, 0x1107a, 0x1111b, 0x111bd, 0x1125f, 0x11302, 0x113a5, ++ 0x11448, 0x114eb, 0x1158f, 0x11634, 0x116d8, 0x1177e, 0x11823, 0x118c9, ++ 0x1196f, 0x11a16, 0x11abd, 0x11b64, 0x11c0c, 0x11cb4, 0x11d5d, 0x11e06, ++ 0x11eaf }, ++ { 0x11f59, 0x12003, 0x120ae, 0x12159, 0x12204, 0x122b0, 0x1235c, 0x12409, ++ 0x124b6, 0x12563, 0x12611, 0x126bf, 0x1276d, 0x1281c, 0x128cc, 0x1297b, ++ 0x12a2b, 0x12adc, 0x12b8d, 0x12c3e, 0x12cf0, 0x12da2, 0x12e55, 0x12f08, ++ 0x12fbc }, ++ { 0x1306f, 0x13124, 0x131d8, 0x1328d, 0x13343, 0x133f9, 0x134af, 0x13566, ++ 0x1361d, 0x136d5, 0x1378d, 0x13846, 0x138fe, 0x139b8, 0x13a72, 0x13b2c, ++ 0x13be6, 0x13ca1, 0x13d5d, 0x13e19, 0x13ed5, 0x13f92, 0x1404f, 0x1410d, ++ 0x141cb }, ++ { 0x1428a, 0x14349, 0x14408, 0x144c8, 0x14588, 0x14649, 0x1470a, 0x147cc, ++ 0x1488e, 0x14951, 0x14a14, 0x14ad7, 0x14b9b, 0x14c5f, 0x14d24, 0x14dea, ++ 0x14eaf, 0x14f75, 0x1503c, 0x15103, 0x151cb, 0x15293, 0x1535b, 0x15424, ++ 0x154ee }, ++ { 0x155b8, 0x15682, 0x1574d, 0x15818, 0x158e4, 0x159b0, 0x15a7d, 0x15b4a, ++ 0x15c18, 0x15ce6, 0x15db4, 0x15e83, 0x15f53, 0x16023, 0x160f4, 0x161c5, ++ 0x16296, 0x16368, 0x1643a, 0x1650d, 0x165e1, 0x166b5, 0x16789, 0x1685e, ++ 0x16934 }, ++ { 0x16a09, 0x16ae0, 0x16bb7, 0x16c8e, 0x16d66, 0x16e3e, 0x16f17, 0x16ff1, ++ 0x170ca, 0x171a5, 0x17280, 0x1735b, 0x17437, 0x17513, 0x175f0, 0x176ce, ++ 0x177ac, 0x1788a, 0x17969, 0x17a49, 0x17b29, 0x17c09, 0x17cea, 0x17dcc, ++ 0x17eae }, ++ { 0x17f91, 0x18074, 0x18157, 0x1823c, 0x18320, 0x18406, 0x184eb, 0x185d2, ++ 0x186b8, 0x187a0, 0x18888, 0x18970, 0x18a59, 0x18b43, 0x18c2d, 0x18d17, ++ 0x18e02, 0x18eee, 0x18fda, 0x190c7, 0x191b5, 0x192a2, 0x19391, 0x19480, ++ 0x1956f }, ++ { 0x1965f, 0x19750, 0x19841, 0x19933, 0x19a25, 0x19b18, 0x19c0c, 0x19d00, ++ 0x19df4, 0x19ee9, 0x19fdf, 0x1a0d5, 0x1a1cc, 0x1a2c4, 0x1a3bc, 0x1a4b4, ++ 0x1a5ad, 0x1a6a7, 0x1a7a1, 0x1a89c, 0x1a998, 0x1aa94, 0x1ab90, 0x1ac8d, ++ 0x1ad8b }, ++ { 0x1ae89, 0x1af88, 0x1b088, 0x1b188, 0x1b289, 0x1b38a, 0x1b48c, 0x1b58f, ++ 0x1b692, 0x1b795, 0x1b89a, 0x1b99f, 0x1baa4, 0x1bbaa, 0x1bcb1, 0x1bdb8, ++ 0x1bec0, 0x1bfc9, 0x1c0d2, 0x1c1dc, 0x1c2e6, 0x1c3f1, 0x1c4fd, 0x1c609, ++ 0x1c716 }, ++ { 0x1c823, 0x1c931, 0x1ca40, 0x1cb50, 0x1cc60, 0x1cd70, 0x1ce81, 0x1cf93, ++ 0x1d0a6, 0x1d1b9, 0x1d2cd, 0x1d3e1, 0x1d4f6, 0x1d60c, 0x1d722, 0x1d839, ++ 0x1d951, 0x1da69, 0x1db82, 0x1dc9c, 0x1ddb6, 0x1ded1, 0x1dfec, 0x1e109, ++ 0x1e225 }, ++ { 0x1e343, 0x1e461, 0x1e580, 0x1e6a0, 0x1e7c0, 0x1e8e0, 0x1ea02, 0x1eb24, ++ 0x1ec47, 0x1ed6b, 0x1ee8f, 0x1efb4, 0x1f0d9, 0x1f1ff, 0x1f326, 0x1f44e, ++ 0x1f576, 0x1f69f, 0x1f7c9, 0x1f8f3, 0x1fa1e, 0x1fb4a, 0x1fc76, 0x1fda3, ++ 0x1fed1 } ++ }; ++ ++ ++//static int PITCH_Installed = FALSE; ++ ++ ++/*--------------------------------------------------------------------- ++ Function: PITCH_Init ++ ++ Initializes pitch table. ++---------------------------------------------------------------------*/ ++/* ++void PITCH_Init ++ ( ++ void ++ ) ++ ++ { ++ int note; ++ int detune; ++ ++ if ( !PITCH_Installed ) ++ { ++ for( note = 0; note < 12; note++ ) ++ { ++ for( detune = 0; detune < MAXDETUNE; detune++ ) ++ { ++ PitchTable[ note ][ detune ] = 0x10000 * ++ pow( 2, ( note * MAXDETUNE + detune ) / ( 12.0 * MAXDETUNE ) ); ++ } ++ } ++ ++ PITCH_Installed = TRUE; ++ } ++ } ++*/ ++ ++/********************************************************************** ++ ++ Memory locked functions: ++ ++**********************************************************************/ ++ ++ ++#define PITCH_LockStart PITCH_GetScale ++ ++ ++/*--------------------------------------------------------------------- ++ Function: PITCH_GetScale ++ ++ Returns a fixed-point value to scale number the specified amount. ++---------------------------------------------------------------------*/ ++ ++unsigned long PITCH_GetScale ++ ( ++ int pitchoffset ++ ) ++ ++ { ++ unsigned long scale; ++ int octaveshift; ++ int noteshift; ++ int note; ++ int detune; ++ ++// if ( !PITCH_Installed ) ++// { ++// PITCH_Init(); ++// } ++ ++ if ( pitchoffset == 0 ) ++ { ++ return( PitchTable[ 0 ][ 0 ] ); ++ } ++ ++ noteshift = pitchoffset % 1200; ++ if ( noteshift < 0 ) ++ { ++ noteshift += 1200; ++ } ++ ++ note = noteshift / 100; ++ detune = ( noteshift % 100 ) / ( 100 / MAXDETUNE ); ++ octaveshift = ( pitchoffset - noteshift ) / 1200; ++ ++ if ( detune < 0 ) ++ { ++ detune += ( 100 / MAXDETUNE ); ++ note--; ++ if ( note < 0 ) ++ { ++ note += 12; ++ octaveshift--; ++ } ++ } ++ ++ scale = PitchTable[ note ][ detune ]; ++ ++ if ( octaveshift < 0 ) ++ { ++ scale >>= -octaveshift; ++ } ++ else ++ { ++ scale <<= octaveshift; ++ } ++ ++ return( scale ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: PITCH_LockEnd ++ ++ Used for determining the length of the functions to lock in memory. ++---------------------------------------------------------------------*/ ++ ++static void PITCH_LockEnd ++ ( ++ void ++ ) ++ ++ { ++ } diff --git a/games/eduke32/files/patch-source__jaudiolib__unixvoc.c b/games/eduke32/files/patch-source__jaudiolib__unixvoc.c new file mode 100644 index 000000000000..eb475a196596 --- /dev/null +++ b/games/eduke32/files/patch-source__jaudiolib__unixvoc.c @@ -0,0 +1,2880 @@ +--- ./source/jaudiolib/unixvoc.c.orig Wed Aug 2 00:35:30 2006 ++++ ./source/jaudiolib/unixvoc.c Wed Aug 2 00:35:30 2006 +@@ -0,0 +1,2877 @@ ++/* ++Copyright (C) 1994-1995 Apogee Software, Ltd. ++ ++This program is free software; you can redistribute it and/or ++modify it under the terms of the GNU 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 General Public License for more details. ++ ++ou should have received a copy of the GNU General Public License ++long with this program; if not, write to the Free Software ++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ ++*/ ++/********************************************************************** ++ module: MULTIVOC.C ++ ++ author: James R. Dose ++ date: December 20, 1993 ++ ++ Routines to provide multichannel digitized sound playback for ++ Sound Blaster compatible sound cards. ++ ++ (c) Copyright 1993 James R. Dose. All Rights Reserved. ++**********************************************************************/ ++ ++#include ++#include ++#include ++#include ++ ++#include "util.h" ++#include "dpmi.h" ++#include "usrhooks.h" ++#include "interrup.h" ++#include "dma.h" ++#include "linklist.h" ++#include "dsl.h" ++ ++#include "pitch.h" ++#include "multivoc.h" ++#include "_multivc.h" ++#include "debugio.h" ++ ++// platform.h is from the build engine, but I need the byteswapping macros... --ryan. ++#include "platform.h" ++ ++#define RoundFixed( fixedval, bits ) \ ++ ( \ ++ ( \ ++ (fixedval) + ( 1 << ( (bits) - 1 ) )\ ++ ) >> (bits) \ ++ ) ++ ++#define IS_QUIET( ptr ) ( ( void * )( ptr ) == ( void * )&MV_VolumeTable[ 0 ] ) ++ ++static int MV_ReverbLevel; ++static int MV_ReverbDelay; ++static VOLUME16 *MV_ReverbTable = NULL; ++ ++//static signed short MV_VolumeTable[ MV_MaxVolume + 1 ][ 256 ]; ++static signed short MV_VolumeTable[ 63 + 1 ][ 256 ]; ++ ++//static Pan MV_PanTable[ MV_NumPanPositions ][ MV_MaxVolume + 1 ]; ++static Pan MV_PanTable[ MV_NumPanPositions ][ 63 + 1 ]; ++ ++static int MV_Installed = FALSE; ++static int MV_SoundCard = 1; ++static int MV_TotalVolume = MV_MaxTotalVolume; ++static int MV_MaxVoices = 1; ++static int MV_Recording; ++ ++static int MV_BufferSize = MixBufferSize; ++static int MV_BufferLength; ++ ++static int MV_NumberOfBuffers = NumberOfBuffers; ++ ++static int MV_MixMode = MONO_8BIT; ++static int MV_Channels = 1; ++static int MV_Bits = 8; ++ ++static int MV_Silence = SILENCE_8BIT; ++static int MV_SwapLeftRight = FALSE; ++ ++static int MV_RequestedMixRate; ++static int MV_MixRate; ++ ++static int MV_DMAChannel = -1; ++static int MV_BuffShift; ++ ++static int MV_TotalMemory; ++ ++static int MV_BufferDescriptor; ++static int MV_BufferEmpty[ NumberOfBuffers ]; ++char *MV_MixBuffer[ NumberOfBuffers + 1 ]; ++ ++static VoiceNode *MV_Voices = NULL; ++ ++static volatile VoiceNode VoiceList; ++static volatile VoiceNode VoicePool; ++ ++/*static*/ int MV_MixPage = 0; ++static int MV_VoiceHandle = MV_MinVoiceHandle; ++ ++static void ( *MV_CallBackFunc )( unsigned long ) = NULL; ++static void ( *MV_RecordFunc )( char *ptr, int length ) = NULL; ++static void ( *MV_MixFunction )( VoiceNode *voice, int buffer ); ++ ++static int MV_MaxVolume = 63; ++ ++char *MV_HarshClipTable; ++char *MV_MixDestination; ++short *MV_LeftVolume; ++short *MV_RightVolume; ++int MV_SampleSize = 1; ++int MV_RightChannelOffset; ++ ++unsigned long MV_MixPosition; ++ ++int MV_ErrorCode = MV_Ok; ++ ++#define MV_SetErrorCode( status ) \ ++ MV_ErrorCode = ( status ); ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_ErrorString ++ ++ Returns a pointer to the error message associated with an error ++ number. A -1 returns a pointer the current error. ++---------------------------------------------------------------------*/ ++ ++char *MV_ErrorString ++ ( ++ int ErrorNumber ++ ) ++ ++ { ++ char *ErrorString; ++ ++ switch( ErrorNumber ) ++ { ++ case MV_Warning : ++ case MV_Error : ++ ErrorString = MV_ErrorString( MV_ErrorCode ); ++ break; ++ ++ case MV_Ok : ++ ErrorString = "Multivoc ok."; ++ break; ++ ++ case MV_UnsupportedCard : ++ ErrorString = "Selected sound card is not supported by Multivoc."; ++ break; ++ ++ case MV_NotInstalled : ++ ErrorString = "Multivoc not installed."; ++ break; ++ ++ case MV_NoVoices : ++ ErrorString = "No free voices available to Multivoc."; ++ break; ++ ++ case MV_NoMem : ++ ErrorString = "Out of memory in Multivoc."; ++ break; ++ ++ case MV_VoiceNotFound : ++ ErrorString = "No voice with matching handle found."; ++ break; ++ ++ case MV_DPMI_Error : ++ ErrorString = "DPMI Error in Multivoc."; ++ break; ++ ++ case MV_InvalidVOCFile : ++ ErrorString = "Invalid VOC file passed in to Multivoc."; ++ break; ++ ++ case MV_InvalidWAVFile : ++ ErrorString = "Invalid WAV file passed in to Multivoc."; ++ break; ++ ++ case MV_InvalidMixMode : ++ ErrorString = "Invalid mix mode request in Multivoc."; ++ break; ++ ++ case MV_IrqFailure : ++ ErrorString = "Playback failed, possibly due to an invalid or conflicting IRQ."; ++ break; ++ ++ case MV_DMAFailure : ++ ErrorString = "Playback failed, possibly due to an invalid or conflicting DMA channel."; ++ break; ++ ++ case MV_DMA16Failure : ++ ErrorString = "Playback failed, possibly due to an invalid or conflicting DMA channel. \n" ++ "Make sure the 16-bit DMA channel is correct."; ++ break; ++ ++ case MV_NullRecordFunction : ++ ErrorString = "Null record function passed to MV_StartRecording."; ++ break; ++ ++ default : ++ ErrorString = "Unknown Multivoc error code."; ++ break; ++ } ++ ++ return( ErrorString ); ++ } ++ ++ ++/********************************************************************** ++ ++ Memory locked functions: ++ ++**********************************************************************/ ++ ++ ++#define MV_LockStart MV_Mix ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_Mix ++ ++ Mixes the sound into the buffer. ++---------------------------------------------------------------------*/ ++ ++static void MV_Mix ++ ( ++ VoiceNode *voice, ++ int buffer ++ ) ++ ++ { ++ char *start; ++ int length; ++ long voclength; ++ unsigned long position; ++ unsigned long rate; ++ unsigned long FixedPointBufferSize; ++ ++ if ( ( voice->length == 0 ) && ++ ( voice->GetSound != NULL ) && ++ ( voice->GetSound( voice ) != KeepPlaying ) ) ++ { ++ return; ++ } ++ ++ length = MixBufferSize; ++ FixedPointBufferSize = voice->FixedPointBufferSize; ++ ++ MV_MixDestination = MV_MixBuffer[ buffer ]; ++ MV_LeftVolume = voice->LeftVolume; ++ MV_RightVolume = voice->RightVolume; ++ ++ if ( ( MV_Channels == 2 ) && ( IS_QUIET( MV_LeftVolume ) ) ) ++ { ++ MV_LeftVolume = MV_RightVolume; ++ MV_MixDestination += MV_RightChannelOffset; ++ } ++ ++ // Add this voice to the mix ++ while( length > 0 ) ++ { ++ start = voice->sound; ++ rate = voice->RateScale; ++ position = voice->position; ++ ++ // Check if the last sample in this buffer would be ++ // beyond the length of the sample block ++ if ( ( position + FixedPointBufferSize ) >= voice->length ) ++ { ++ if ( position < voice->length ) ++ { ++ voclength = ( voice->length - position + rate - 1 ) / rate; ++ } ++ else ++ { ++ voice->GetSound( voice ); ++ return; ++ } ++ } ++ else ++ { ++ voclength = length; ++ } ++ ++ voice->mix( position, rate, start, voclength ); ++ ++ if ( voclength & 1 ) ++ { ++ MV_MixPosition += rate; ++ voclength -= 1; ++ } ++ voice->position = MV_MixPosition; ++ ++ length -= voclength; ++ ++ if ( voice->position >= voice->length ) ++ { ++ // Get the next block of sound ++ if ( voice->GetSound( voice ) != KeepPlaying ) ++ { ++ return; ++ } ++ ++ if ( length > 0 ) ++ { ++ // Get the position of the last sample in the buffer ++ FixedPointBufferSize = voice->RateScale * ( length - 1 ); ++ } ++ } ++ } ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_PlayVoice ++ ++ Adds a voice to the play list. ++---------------------------------------------------------------------*/ ++ ++void MV_PlayVoice ++ ( ++ VoiceNode *voice ++ ) ++ ++ { ++ unsigned flags; ++ ++ flags = DisableInterrupts(); ++ LL_SortedInsertion( &VoiceList, voice, prev, next, VoiceNode, priority ); ++ ++ RestoreInterrupts( flags ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_StopVoice ++ ++ Removes the voice from the play list and adds it to the free list. ++---------------------------------------------------------------------*/ ++ ++void MV_StopVoice ++ ( ++ VoiceNode *voice ++ ) ++ ++ { ++ unsigned flags; ++ ++ flags = DisableInterrupts(); ++ ++ // move the voice from the play list to the free list ++ LL_Remove( voice, next, prev ); ++ LL_Add( (VoiceNode *)&VoicePool, voice, next, prev ); ++ ++ RestoreInterrupts( flags ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_ServiceVoc ++ ++ Starts playback of the waiting buffer and mixes the next one. ++---------------------------------------------------------------------*/ ++ ++// static int backcolor = 1; ++ ++static int MV_ServiceVoc(int dummy_arg) ++ { ++ VoiceNode *voice; ++ VoiceNode *next; ++ char *buffer; ++ ++ // Toggle which buffer we'll mix next ++ MV_MixPage++; ++ if ( MV_MixPage >= MV_NumberOfBuffers ) ++ { ++ MV_MixPage -= MV_NumberOfBuffers; ++ } ++ ++ if ( MV_ReverbLevel == 0 ) ++ { ++ // Initialize buffer ++ //Commented out so that the buffer is always cleared. ++ //This is so the guys at Echo Speech can mix into the ++ //buffer even when no sounds are playing. ++ //if ( !MV_BufferEmpty[ MV_MixPage ] ) ++ { ++ ClearBuffer_DW( MV_MixBuffer[ MV_MixPage ], MV_Silence, MV_BufferSize >> 2 ); ++ MV_BufferEmpty[ MV_MixPage ] = TRUE; ++ } ++ } ++ else ++ { ++ char *end; ++ char *source; ++ char *dest; ++ int count; ++ int length; ++ ++ end = MV_MixBuffer[ 0 ] + MV_BufferLength;; ++ dest = MV_MixBuffer[ MV_MixPage ]; ++ source = MV_MixBuffer[ MV_MixPage ] - MV_ReverbDelay; ++ if ( source < MV_MixBuffer[ 0 ] ) ++ { ++ source += MV_BufferLength; ++ } ++ ++ length = MV_BufferSize; ++ while( length > 0 ) ++ { ++ count = length; ++ if ( source + count > end ) ++ { ++ count = end - source; ++ } ++ ++ if ( MV_Bits == 16 ) ++ { ++ if ( MV_ReverbTable != NULL ) ++ MV_16BitReverb( source, dest, (const VOLUME16 *)MV_ReverbTable, count / 2 ); ++ else ++ MV_16BitReverbFast( source, dest, count / 2, MV_ReverbLevel ); ++ } ++ else ++ { ++ if ( MV_ReverbTable != NULL ) ++ MV_8BitReverb( source, dest, (const VOLUME16 *)MV_ReverbTable, count ); ++ else ++ MV_8BitReverbFast( source, dest, count, MV_ReverbLevel ); ++ } ++ ++ // if we go through the loop again, it means that we've wrapped around the buffer ++ source = MV_MixBuffer[ 0 ]; ++ dest += count; ++ length -= count; ++ } ++ } ++ ++ // Play any waiting voices ++ for( voice = VoiceList.next; voice != &VoiceList; voice = next ) ++ { ++// if ( ( voice < &MV_Voices[ 0 ] ) || ( voice > &MV_Voices[ 8 ] ) ) ++// { ++// SetBorderColor(backcolor++); ++// break; ++// } ++ ++ MV_BufferEmpty[ MV_MixPage ] = FALSE; ++ ++ if (MV_MixFunction != NULL) ++ MV_MixFunction( voice, MV_MixPage ); ++ ++ next = voice->next; ++ ++ // Is this voice done? ++ if ( !voice->Playing ) ++ { ++ MV_StopVoice( voice ); ++ ++ if ( MV_CallBackFunc ) ++ { ++ MV_CallBackFunc( voice->callbackval ); ++ } ++ } ++ } ++ } ++ ++ ++int leftpage = -1; ++int rightpage = -1; ++ ++void MV_ServiceGus( char **ptr, unsigned long *length ) ++ { ++ if ( leftpage == MV_MixPage ) ++ { ++ MV_ServiceVoc(0); ++ } ++ ++ leftpage = MV_MixPage; ++ ++ *ptr = MV_MixBuffer[ MV_MixPage ]; ++ *length = MV_BufferSize; ++ } ++ ++void MV_ServiceRightGus( char **ptr, unsigned long *length ) ++ { ++ if ( rightpage == MV_MixPage ) ++ { ++ MV_ServiceVoc(0); ++ } ++ ++ rightpage = MV_MixPage; ++ ++ *ptr = MV_MixBuffer[ MV_MixPage ] + MV_RightChannelOffset; ++ *length = MV_BufferSize; ++ } ++ ++/*--------------------------------------------------------------------- ++ Function: MV_GetNextVOCBlock ++ ++ Interperate the information of a VOC format sound file. ++---------------------------------------------------------------------*/ ++static __inline unsigned int get_le32(void *p0) ++{ ++ //unsigned char *p = p0; ++ //return p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24); ++ unsigned int val = *((unsigned int *) p0); ++ return(BUILDSWAP_INTEL32(val)); ++} ++ ++static __inline unsigned int get_le16(void *p0) ++{ ++ //unsigned char *p = p0; ++ //return p[0] | (p[1]<<8); ++ unsigned short val = *((unsigned short *) p0); ++ return( (unsigned int) (BUILDSWAP_INTEL16(val)) ); ++} ++ ++playbackstatus MV_GetNextVOCBlock ++ ( ++ VoiceNode *voice ++ ) ++ ++ { ++ unsigned char *ptr; ++ int blocktype=0; ++ int lastblocktype=0; ++ unsigned long blocklength=0l; ++ unsigned long samplespeed=0l; ++ unsigned int tc=0; ++ int packtype=0; ++ int voicemode=0; ++ int done=0; ++ unsigned BitsPerSample; ++ unsigned Channels; ++ unsigned Format; ++ ++ if ( voice->BlockLength > 0 ) ++ { ++ voice->position -= voice->length; ++ voice->sound += voice->length >> 16; ++ if ( voice->bits == 16 ) ++ { ++ voice->sound += voice->length >> 16; ++ } ++ voice->length = min( voice->BlockLength, 0x8000 ); ++ voice->BlockLength -= voice->length; ++ voice->length <<= 16; ++ return( KeepPlaying ); ++ } ++ ++ if ( ( voice->length > 0 ) && ( voice->LoopEnd != NULL ) && ++ ( voice->LoopStart != NULL ) ) ++ { ++ voice->BlockLength = voice->LoopSize; ++ voice->sound = voice->LoopStart; ++ voice->position = 0; ++ voice->length = min( voice->BlockLength, 0x8000 ); ++ voice->BlockLength -= voice->length; ++ voice->length <<= 16; ++ return( KeepPlaying ); ++ } ++ ++ ptr = ( unsigned char * )voice->NextBlock; ++ ++ voice->Playing = TRUE; ++ ++ voicemode = 0; ++ lastblocktype = 0; ++ packtype = 0; ++ ++ done = FALSE; ++ while( !done ) ++ { ++ // Stop playing if we get a NULL pointer ++ if ( ptr == NULL ) ++ { ++ voice->Playing = FALSE; ++ done = TRUE; ++ break; ++ } ++ ++ { ++ unsigned tmp = get_le32(ptr); ++ blocktype = tmp&255; ++ blocklength = tmp>>8; ++ } ++ ptr += 4; ++ ++ switch( blocktype ) ++ { ++ case 0 : ++ // End of data ++ if ( ( voice->LoopStart == NULL ) || ++ ( (unsigned char *)voice->LoopStart >= ( ptr - 4 ) ) ) ++ { ++ voice->Playing = FALSE; ++ done = TRUE; ++ } ++ else ++ { ++ voice->BlockLength = ( ptr - 4 ) - (unsigned char *)voice->LoopStart; ++ voice->sound = voice->LoopStart; ++ voice->position = 0; ++ voice->length = min( voice->BlockLength, 0x8000 ); ++ voice->BlockLength -= voice->length; ++ voice->length <<= 16; ++ return( KeepPlaying ); ++ } ++ break; ++ ++ case 1 : ++ // Sound data block ++ voice->bits = 8; ++ if ( lastblocktype != 8 ) ++ { ++ tc = ( unsigned int )*ptr << 8; ++ packtype = *( ptr + 1 ); ++ } ++ ++ ptr += 2; ++ blocklength -= 2; ++ ++ samplespeed = 256000000L / ( 65536 - tc ); ++ ++ // Skip packed or stereo data ++ if ( ( packtype != 0 ) || ( voicemode != 0 ) ) ++ { ++ ptr += blocklength; ++ } ++ else ++ { ++ done = TRUE; ++ } ++ voicemode = 0; ++ break; ++ ++ case 2 : ++ // Sound continuation block ++ samplespeed = voice->SamplingRate; ++ done = TRUE; ++ break; ++ ++ case 3 : ++ // Silence ++ // Not implimented. ++ ptr += blocklength; ++ break; ++ ++ case 4 : ++ // Marker ++ // Not implimented. ++ ptr += blocklength; ++ break; ++ ++ case 5 : ++ // ASCII string ++ // Not implimented. ++ ptr += blocklength; ++ break; ++ ++ case 6 : ++ // Repeat begin ++ if ( voice->LoopEnd == NULL ) ++ { ++ voice->LoopCount = get_le16(ptr); ++ voice->LoopStart = ptr + blocklength; ++ } ++ ptr += blocklength; ++ break; ++ ++ case 7 : ++ // Repeat end ++ ptr += blocklength; ++ if ( lastblocktype == 6 ) ++ { ++ voice->LoopCount = 0; ++ } ++ else ++ { ++ if ( ( voice->LoopCount > 0 ) && ( voice->LoopStart != NULL ) ) ++ { ++ ptr = voice->LoopStart; ++ if ( voice->LoopCount < 0xffff ) ++ { ++ voice->LoopCount--; ++ if ( voice->LoopCount == 0 ) ++ { ++ voice->LoopStart = NULL; ++ } ++ } ++ } ++ } ++ break; ++ ++ case 8 : ++ // Extended block ++ voice->bits = 8; ++ tc = get_le16(ptr); ++ packtype = *( ptr + 2 ); ++ voicemode = *( ptr + 3 ); ++ ptr += blocklength; ++ break; ++ ++ case 9 : ++ // New sound data block ++ samplespeed = get_le32(ptr); ++ BitsPerSample = ptr[4]; ++ Channels = ptr[5]; ++ Format = get_le16(ptr+6); ++ ++ if ( ( BitsPerSample == 8 ) && ( Channels == 1 ) && ++ ( Format == VOC_8BIT ) ) ++ { ++ ptr += 12; ++ blocklength -= 12; ++ voice->bits = 8; ++ done = TRUE; ++ } ++ else if ( ( BitsPerSample == 16 ) && ( Channels == 1 ) && ++ ( Format == VOC_16BIT ) ) ++ { ++ ptr += 12; ++ blocklength -= 12; ++ voice->bits = 16; ++ done = TRUE; ++ } ++ else ++ { ++ ptr += blocklength; ++ } ++ break; ++ ++ default : ++ // Unknown data. Probably not a VOC file. ++ voice->Playing = FALSE; ++ done = TRUE; ++ break; ++ } ++ ++ lastblocktype = blocktype; ++ } ++ ++ if ( voice->Playing ) ++ { ++ voice->NextBlock = ptr + blocklength; ++ voice->sound = ptr; ++ ++ voice->SamplingRate = samplespeed; ++ voice->RateScale = ( voice->SamplingRate * voice->PitchScale ) / MV_MixRate; ++ ++ // Multiply by MixBufferSize - 1 ++ voice->FixedPointBufferSize = ( voice->RateScale * MixBufferSize ) - ++ voice->RateScale; ++ ++ if ( voice->LoopEnd != NULL ) ++ { ++ if ( blocklength > ( unsigned long )voice->LoopEnd ) ++ { ++ blocklength = ( unsigned long )voice->LoopEnd; ++ } ++ else ++ { ++ voice->LoopEnd = ( char * )blocklength; ++ } ++ ++ voice->LoopStart = voice->sound + ( unsigned long )voice->LoopStart; ++ voice->LoopEnd = voice->sound + ( unsigned long )voice->LoopEnd; ++ voice->LoopSize = voice->LoopEnd - voice->LoopStart; ++ } ++ ++ if ( voice->bits == 16 ) ++ { ++ blocklength /= 2; ++ } ++ ++ voice->position = 0; ++ voice->length = min( blocklength, 0x8000 ); ++ voice->BlockLength = blocklength - voice->length; ++ voice->length <<= 16; ++ ++ MV_SetVoiceMixMode( voice ); ++ ++ return( KeepPlaying ); ++ } ++ ++ return( NoMoreData ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_GetNextDemandFeedBlock ++ ++ Controls playback of demand fed data. ++---------------------------------------------------------------------*/ ++ ++playbackstatus MV_GetNextDemandFeedBlock ++ ( ++ VoiceNode *voice ++ ) ++ ++ { ++ if ( voice->BlockLength > 0 ) ++ { ++ voice->position -= voice->length; ++ voice->sound += voice->length >> 16; ++ voice->length = min( voice->BlockLength, 0x8000 ); ++ voice->BlockLength -= voice->length; ++ voice->length <<= 16; ++ ++ return( KeepPlaying ); ++ } ++ ++ if ( voice->DemandFeed == NULL ) ++ { ++ return( NoMoreData ); ++ } ++ ++ voice->position = 0; ++ ( voice->DemandFeed )( &voice->sound, &voice->BlockLength ); ++ voice->length = min( voice->BlockLength, 0x8000 ); ++ voice->BlockLength -= voice->length; ++ voice->length <<= 16; ++ ++ if ( ( voice->length > 0 ) && ( voice->sound != NULL ) ) ++ { ++ return( KeepPlaying ); ++ } ++ return( NoMoreData ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_GetNextRawBlock ++ ++ Controls playback of demand fed data. ++---------------------------------------------------------------------*/ ++ ++playbackstatus MV_GetNextRawBlock ++ ( ++ VoiceNode *voice ++ ) ++ ++ { ++ if ( voice->BlockLength <= 0 ) ++ { ++ if ( voice->LoopStart == NULL ) ++ { ++ voice->Playing = FALSE; ++ return( NoMoreData ); ++ } ++ ++ voice->BlockLength = voice->LoopSize; ++ voice->NextBlock = voice->LoopStart; ++ voice->length = 0; ++ voice->position = 0; ++ } ++ ++ voice->sound = voice->NextBlock; ++ voice->position -= voice->length; ++ voice->length = min( voice->BlockLength, 0x8000 ); ++ voice->NextBlock += voice->length; ++ if ( voice->bits == 16 ) ++ { ++ voice->NextBlock += voice->length; ++ } ++ voice->BlockLength -= voice->length; ++ voice->length <<= 16; ++ ++ return( KeepPlaying ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_GetNextWAVBlock ++ ++ Controls playback of demand fed data. ++---------------------------------------------------------------------*/ ++ ++playbackstatus MV_GetNextWAVBlock ++ ( ++ VoiceNode *voice ++ ) ++ ++ { ++ if ( voice->BlockLength <= 0 ) ++ { ++ if ( voice->LoopStart == NULL ) ++ { ++ voice->Playing = FALSE; ++ return( NoMoreData ); ++ } ++ ++ voice->BlockLength = voice->LoopSize; ++ voice->NextBlock = voice->LoopStart; ++ voice->length = 0; ++ voice->position = 0; ++ } ++ ++ voice->sound = voice->NextBlock; ++ voice->position -= voice->length; ++ voice->length = min( voice->BlockLength, 0x8000 ); ++ voice->NextBlock += voice->length; ++ if ( voice->bits == 16 ) ++ { ++ voice->NextBlock += voice->length; ++ } ++ voice->BlockLength -= voice->length; ++ voice->length <<= 16; ++ ++ return( KeepPlaying ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_ServiceRecord ++ ++ Starts recording of the waiting buffer. ++---------------------------------------------------------------------*/ ++ ++static void MV_ServiceRecord ++ ( ++ void ++ ) ++ ++ { ++ if ( MV_RecordFunc ) ++ { ++ MV_RecordFunc( MV_MixBuffer[ 0 ] + MV_MixPage * MixBufferSize, ++ MixBufferSize ); ++ } ++ ++ // Toggle which buffer we'll mix next ++ MV_MixPage++; ++ if ( MV_MixPage >= NumberOfBuffers ) ++ { ++ MV_MixPage = 0; ++ } ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_GetVoice ++ ++ Locates the voice with the specified handle. ++---------------------------------------------------------------------*/ ++ ++VoiceNode *MV_GetVoice ++ ( ++ int handle ++ ) ++ ++ { ++ VoiceNode *voice; ++ unsigned flags; ++ ++ flags = DisableInterrupts(); ++ ++ for( voice = VoiceList.next; voice != &VoiceList; voice = voice->next ) ++ { ++ if ( handle == voice->handle ) ++ { ++ break; ++ } ++ } ++ ++ RestoreInterrupts( flags ); ++ ++ if ( voice == &VoiceList ) ++ { ++ MV_SetErrorCode( MV_VoiceNotFound ); ++ ++ // SBF - should this return null? ++ return NULL; ++ } ++ ++ return( voice ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_VoicePlaying ++ ++ Checks if the voice associated with the specified handle is ++ playing. ++---------------------------------------------------------------------*/ ++ ++int MV_VoicePlaying ++ ( ++ int handle ++ ) ++ ++ { ++ VoiceNode *voice; ++ ++ if ( !MV_Installed ) ++ { ++ MV_SetErrorCode( MV_NotInstalled ); ++ return( FALSE ); ++ } ++ ++ voice = MV_GetVoice( handle ); ++ ++ if ( voice == NULL ) ++ { ++ return( FALSE ); ++ } ++ ++ return( TRUE ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_KillAllVoices ++ ++ Stops output of all currently active voices. ++---------------------------------------------------------------------*/ ++ ++int MV_KillAllVoices ++ ( ++ void ++ ) ++ ++ { ++ if ( !MV_Installed ) ++ { ++ MV_SetErrorCode( MV_NotInstalled ); ++ return( MV_Error ); ++ } ++ ++ // Remove all the voices from the list ++ while( VoiceList.next != &VoiceList ) ++ { ++ MV_Kill( VoiceList.next->handle ); ++ } ++ ++ return( MV_Ok ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_Kill ++ ++ Stops output of the voice associated with the specified handle. ++---------------------------------------------------------------------*/ ++ ++int MV_Kill ++ ( ++ int handle ++ ) ++ ++ { ++ VoiceNode *voice; ++ unsigned flags; ++ unsigned long callbackval; ++ ++ if ( !MV_Installed ) ++ { ++ MV_SetErrorCode( MV_NotInstalled ); ++ return( MV_Error ); ++ } ++ ++ flags = DisableInterrupts(); ++ ++ voice = MV_GetVoice( handle ); ++ if ( voice == NULL ) ++ { ++ RestoreInterrupts( flags ); ++ MV_SetErrorCode( MV_VoiceNotFound ); ++ return( MV_Error ); ++ } ++ ++ callbackval = voice->callbackval; ++ ++ MV_StopVoice( voice ); ++ ++ RestoreInterrupts( flags ); ++ ++ if ( MV_CallBackFunc ) ++ { ++ MV_CallBackFunc( callbackval ); ++ } ++ ++ return( MV_Ok ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_VoicesPlaying ++ ++ Determines the number of currently active voices. ++---------------------------------------------------------------------*/ ++ ++int MV_VoicesPlaying ++ ( ++ void ++ ) ++ ++ { ++ VoiceNode *voice; ++ int NumVoices = 0; ++ unsigned flags; ++ ++ if ( !MV_Installed ) ++ { ++ MV_SetErrorCode( MV_NotInstalled ); ++ return( 0 ); ++ } ++ ++ flags = DisableInterrupts(); ++ ++ for( voice = VoiceList.next; voice != &VoiceList; voice = voice->next ) ++ { ++ NumVoices++; ++ } ++ ++ RestoreInterrupts( flags ); ++ ++ return( NumVoices ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_AllocVoice ++ ++ Retrieve an inactive or lower priority voice for output. ++---------------------------------------------------------------------*/ ++ ++VoiceNode *MV_AllocVoice ++ ( ++ int priority ++ ) ++ ++ { ++ VoiceNode *voice; ++ VoiceNode *node; ++ unsigned flags; ++ ++//return( NULL ); ++ if ( MV_Recording ) ++ { ++ return( NULL ); ++ } ++ ++ flags = DisableInterrupts(); ++ ++ // Check if we have any free voices ++ if ( LL_Empty( &VoicePool, next, prev ) ) ++ { ++ // check if we have a higher priority than a voice that is playing. ++ voice = VoiceList.next; ++ for( node = voice->next; node != &VoiceList; node = node->next ) ++ { ++ if ( node->priority < voice->priority ) ++ { ++ voice = node; ++ } ++ } ++ ++ if ( priority >= voice->priority ) ++ { ++ MV_Kill( voice->handle ); ++ } ++ } ++ ++ // Check if any voices are in the voice pool ++ if ( LL_Empty( &VoicePool, next, prev ) ) ++ { ++ // No free voices ++ RestoreInterrupts( flags ); ++ return( NULL ); ++ } ++ ++ voice = VoicePool.next; ++ LL_Remove( voice, next, prev ); ++ RestoreInterrupts( flags ); ++ ++ // Find a free voice handle ++ do ++ { ++ MV_VoiceHandle++; ++ if ( MV_VoiceHandle < MV_MinVoiceHandle ) ++ { ++ MV_VoiceHandle = MV_MinVoiceHandle; ++ } ++ } ++ while( MV_VoicePlaying( MV_VoiceHandle ) ); ++ ++ voice->handle = MV_VoiceHandle; ++ ++ return( voice ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_VoiceAvailable ++ ++ Checks if a voice can be play at the specified priority. ++---------------------------------------------------------------------*/ ++ ++int MV_VoiceAvailable ++ ( ++ int priority ++ ) ++ ++ { ++ VoiceNode *voice; ++ VoiceNode *node; ++ unsigned flags; ++ ++ // Check if we have any free voices ++ if ( !LL_Empty( &VoicePool, next, prev ) ) ++ { ++ return( TRUE ); ++ } ++ ++ flags = DisableInterrupts(); ++ ++ // check if we have a higher priority than a voice that is playing. ++ voice = VoiceList.next; ++ for( node = VoiceList.next; node != &VoiceList; node = node->next ) ++ { ++ if ( node->priority < voice->priority ) ++ { ++ voice = node; ++ } ++ } ++ ++ RestoreInterrupts( flags ); ++ ++ if ( ( voice != &VoiceList ) && ( priority >= voice->priority ) ) ++ { ++ return( TRUE ); ++ } ++ ++ return( FALSE ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_SetVoicePitch ++ ++ Sets the pitch for the specified voice. ++---------------------------------------------------------------------*/ ++ ++void MV_SetVoicePitch ++ ( ++ VoiceNode *voice, ++ unsigned long rate, ++ int pitchoffset ++ ) ++ ++ { ++ voice->SamplingRate = rate; ++ voice->PitchScale = PITCH_GetScale( pitchoffset ); ++ voice->RateScale = ( rate * voice->PitchScale ) / MV_MixRate; ++ ++ // Multiply by MixBufferSize - 1 ++ voice->FixedPointBufferSize = ( voice->RateScale * MixBufferSize ) - ++ voice->RateScale; ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_SetPitch ++ ++ Sets the pitch for the voice associated with the specified handle. ++---------------------------------------------------------------------*/ ++ ++int MV_SetPitch ++ ( ++ int handle, ++ int pitchoffset ++ ) ++ ++ { ++ VoiceNode *voice; ++ ++ if ( !MV_Installed ) ++ { ++ MV_SetErrorCode( MV_NotInstalled ); ++ return( MV_Error ); ++ } ++ ++ voice = MV_GetVoice( handle ); ++ if ( voice == NULL ) ++ { ++ MV_SetErrorCode( MV_VoiceNotFound ); ++ return( MV_Error ); ++ } ++ ++ MV_SetVoicePitch( voice, voice->SamplingRate, pitchoffset ); ++ ++ return( MV_Ok ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_SetFrequency ++ ++ Sets the frequency for the voice associated with the specified handle. ++---------------------------------------------------------------------*/ ++ ++int MV_SetFrequency ++ ( ++ int handle, ++ int frequency ++ ) ++ ++ { ++ VoiceNode *voice; ++ ++ if ( !MV_Installed ) ++ { ++ MV_SetErrorCode( MV_NotInstalled ); ++ return( MV_Error ); ++ } ++ ++ voice = MV_GetVoice( handle ); ++ if ( voice == NULL ) ++ { ++ MV_SetErrorCode( MV_VoiceNotFound ); ++ return( MV_Error ); ++ } ++ ++ MV_SetVoicePitch( voice, frequency, 0 ); ++ ++ return( MV_Ok ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_GetVolumeTable ++ ++ Returns a pointer to the volume table associated with the specified ++ volume. ++---------------------------------------------------------------------*/ ++ ++static short *MV_GetVolumeTable ++ ( ++ int vol ++ ) ++ ++ { ++ int volume; ++ short *table; ++ ++ volume = MIX_VOLUME( vol ); ++ ++ table = (short *)&MV_VolumeTable[ volume ]; ++ ++ return( table ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_SetVoiceMixMode ++ ++ Selects which method should be used to mix the voice. ++---------------------------------------------------------------------*/ ++ ++static void MV_SetVoiceMixMode ++ ( ++ VoiceNode *voice ++ ) ++ ++ { ++ unsigned flags; ++ int test; ++ ++ flags = DisableInterrupts(); ++ ++ test = T_DEFAULT; ++ if ( MV_Bits == 8 ) ++ { ++ test |= T_8BITS; ++ } ++ ++ if ( voice->bits == 16 ) ++ { ++ test |= T_16BITSOURCE; ++ } ++ ++ if ( MV_Channels == 1 ) ++ { ++ test |= T_MONO; ++ } ++ else ++ { ++ if ( IS_QUIET( voice->RightVolume ) ) ++ { ++ test |= T_RIGHTQUIET; ++ } ++ else if ( IS_QUIET( voice->LeftVolume ) ) ++ { ++ test |= T_LEFTQUIET; ++ } ++ } ++ ++ // Default case ++ voice->mix = MV_Mix8BitMono; ++ ++ switch( test ) ++ { ++ case T_8BITS | T_MONO | T_16BITSOURCE : ++ voice->mix = MV_Mix8BitMono16; ++ break; ++ ++ case T_8BITS | T_MONO : ++ voice->mix = MV_Mix8BitMono; ++ break; ++ ++ case T_8BITS | T_16BITSOURCE | T_LEFTQUIET : ++ MV_LeftVolume = MV_RightVolume; ++ voice->mix = MV_Mix8BitMono16; ++ break; ++ ++ case T_8BITS | T_LEFTQUIET : ++ MV_LeftVolume = MV_RightVolume; ++ voice->mix = MV_Mix8BitMono; ++ break; ++ ++ case T_8BITS | T_16BITSOURCE | T_RIGHTQUIET : ++ voice->mix = MV_Mix8BitMono16; ++ break; ++ ++ case T_8BITS | T_RIGHTQUIET : ++ voice->mix = MV_Mix8BitMono; ++ break; ++ ++ case T_8BITS | T_16BITSOURCE : ++ voice->mix = MV_Mix8BitStereo16; ++ break; ++ ++ case T_8BITS : ++ voice->mix = MV_Mix8BitStereo; ++ break; ++ ++ case T_MONO | T_16BITSOURCE : ++ voice->mix = MV_Mix16BitMono16; ++ break; ++ ++ case T_MONO : ++ voice->mix = MV_Mix16BitMono; ++ break; ++ ++ case T_16BITSOURCE | T_LEFTQUIET : ++ MV_LeftVolume = MV_RightVolume; ++ voice->mix = MV_Mix16BitMono16; ++ break; ++ ++ case T_LEFTQUIET : ++ MV_LeftVolume = MV_RightVolume; ++ voice->mix = MV_Mix16BitMono; ++ break; ++ ++ case T_16BITSOURCE | T_RIGHTQUIET : ++ voice->mix = MV_Mix16BitMono16; ++ break; ++ ++ case T_RIGHTQUIET : ++ voice->mix = MV_Mix16BitMono; ++ break; ++ ++ case T_16BITSOURCE : ++ voice->mix = MV_Mix16BitStereo16; ++ break; ++ ++ case T_SIXTEENBIT_STEREO : ++ voice->mix = MV_Mix16BitStereo; ++ break; ++ ++ default : ++ voice->mix = MV_Mix8BitMono; ++ } ++ ++ RestoreInterrupts( flags ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_SetVoiceVolume ++ ++ Sets the stereo and mono volume level of the voice associated ++ with the specified handle. ++---------------------------------------------------------------------*/ ++ ++void MV_SetVoiceVolume ++ ( ++ VoiceNode *voice, ++ int vol, ++ int left, ++ int right ++ ) ++ ++ { ++ if ( MV_Channels == 1 ) ++ { ++ left = vol; ++ right = vol; ++ } ++ ++ if ( MV_SwapLeftRight ) ++ { ++ // SBPro uses reversed panning ++ voice->LeftVolume = MV_GetVolumeTable( right ); ++ voice->RightVolume = MV_GetVolumeTable( left ); ++ } ++ else ++ { ++ voice->LeftVolume = MV_GetVolumeTable( left ); ++ voice->RightVolume = MV_GetVolumeTable( right ); ++ } ++ ++ MV_SetVoiceMixMode( voice ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_EndLooping ++ ++ Stops the voice associated with the specified handle from looping ++ without stoping the sound. ++---------------------------------------------------------------------*/ ++ ++int MV_EndLooping ++ ( ++ int handle ++ ) ++ ++ { ++ VoiceNode *voice; ++ unsigned flags; ++ ++ if ( !MV_Installed ) ++ { ++ MV_SetErrorCode( MV_NotInstalled ); ++ return( MV_Error ); ++ } ++ ++ flags = DisableInterrupts(); ++ ++ voice = MV_GetVoice( handle ); ++ if ( voice == NULL ) ++ { ++ RestoreInterrupts( flags ); ++ MV_SetErrorCode( MV_VoiceNotFound ); ++ return( MV_Warning ); ++ } ++ ++ voice->LoopCount = 0; ++ voice->LoopStart = NULL; ++ voice->LoopEnd = NULL; ++ ++ RestoreInterrupts( flags ); ++ ++ return( MV_Ok ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_SetPan ++ ++ Sets the stereo and mono volume level of the voice associated ++ with the specified handle. ++---------------------------------------------------------------------*/ ++ ++int MV_SetPan ++ ( ++ int handle, ++ int vol, ++ int left, ++ int right ++ ) ++ ++ { ++ VoiceNode *voice; ++ ++ if ( !MV_Installed ) ++ { ++ MV_SetErrorCode( MV_NotInstalled ); ++ return( MV_Error ); ++ } ++ ++ voice = MV_GetVoice( handle ); ++ if ( voice == NULL ) ++ { ++ MV_SetErrorCode( MV_VoiceNotFound ); ++ return( MV_Warning ); ++ } ++ ++ MV_SetVoiceVolume( voice, vol, left, right ); ++ ++ return( MV_Ok ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_Pan3D ++ ++ Set the angle and distance from the listener of the voice associated ++ with the specified handle. ++---------------------------------------------------------------------*/ ++ ++int MV_Pan3D ++ ( ++ int handle, ++ int angle, ++ int distance ++ ) ++ ++ { ++ int left; ++ int right; ++ int mid; ++ int volume; ++ int status; ++ ++ if ( distance < 0 ) ++ { ++ distance = -distance; ++ angle += MV_NumPanPositions / 2; ++ } ++ ++ volume = MIX_VOLUME( distance ); ++ ++ // Ensure angle is within 0 - 31 ++ angle &= MV_MaxPanPosition; ++ ++ left = MV_PanTable[ angle ][ volume ].left; ++ right = MV_PanTable[ angle ][ volume ].right; ++ mid = max( 0, 255 - distance ); ++ ++ status = MV_SetPan( handle, mid, left, right ); ++ ++ return( status ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_SetReverb ++ ++ Sets the level of reverb to add to mix. ++---------------------------------------------------------------------*/ ++ ++void MV_SetReverb ++ ( ++ int reverb ++ ) ++ ++ { ++ MV_ReverbLevel = MIX_VOLUME( reverb ); ++ MV_ReverbTable = &MV_VolumeTable[ MV_ReverbLevel ]; ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_SetFastReverb ++ ++ Sets the level of reverb to add to mix. ++---------------------------------------------------------------------*/ ++ ++void MV_SetFastReverb ++ ( ++ int reverb ++ ) ++ ++ { ++ MV_ReverbLevel = max( 0, min( 16, reverb ) ); ++ MV_ReverbTable = NULL; ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_GetMaxReverbDelay ++ ++ Returns the maximum delay time for reverb. ++---------------------------------------------------------------------*/ ++ ++int MV_GetMaxReverbDelay ++ ( ++ void ++ ) ++ ++ { ++ int maxdelay; ++ ++ maxdelay = MixBufferSize * MV_NumberOfBuffers; ++ ++ return maxdelay; ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_GetReverbDelay ++ ++ Returns the current delay time for reverb. ++---------------------------------------------------------------------*/ ++ ++int MV_GetReverbDelay ++ ( ++ void ++ ) ++ ++ { ++ return MV_ReverbDelay / MV_SampleSize; ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_SetReverbDelay ++ ++ Sets the delay level of reverb to add to mix. ++---------------------------------------------------------------------*/ ++ ++void MV_SetReverbDelay ++ ( ++ int delay ++ ) ++ ++ { ++ int maxdelay; ++ ++ maxdelay = MV_GetMaxReverbDelay(); ++ MV_ReverbDelay = max( MixBufferSize, min( delay, maxdelay ) ); ++ MV_ReverbDelay *= MV_SampleSize; ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_SetMixMode ++ ++ Prepares Multivoc to play stereo of mono digitized sounds. ++---------------------------------------------------------------------*/ ++ ++int MV_SetMixMode ++ ( ++ int numchannels, ++ int samplebits ++ ) ++ ++ { ++ int mode; ++ ++ if ( !MV_Installed ) ++ { ++ MV_SetErrorCode( MV_NotInstalled ); ++ return( MV_Error ); ++ } ++ ++ mode = 0; ++ if ( numchannels == 2 ) ++ { ++ mode |= STEREO; ++ } ++ if ( samplebits == 16 ) ++ { ++ mode |= SIXTEEN_BIT; ++ } ++ ++ MV_MixMode = mode; ++ ++ MV_Channels = 1; ++ if ( MV_MixMode & STEREO ) ++ { ++ MV_Channels = 2; ++ } ++ ++ MV_Bits = 8; ++ if ( MV_MixMode & SIXTEEN_BIT ) ++ { ++ MV_Bits = 16; ++ } ++ ++ MV_BuffShift = 7 + MV_Channels; ++ MV_SampleSize = sizeof( MONO8 ) * MV_Channels; ++ ++ if ( MV_Bits == 8 ) ++ { ++ MV_Silence = SILENCE_8BIT; ++ } ++ else ++ { ++ MV_Silence = SILENCE_16BIT; ++ MV_BuffShift += 1; ++ MV_SampleSize *= 2; ++ } ++ ++ MV_BufferSize = MixBufferSize * MV_SampleSize; ++ MV_NumberOfBuffers = TotalBufferSize / MV_BufferSize; ++ MV_BufferLength = TotalBufferSize; ++ ++ MV_RightChannelOffset = MV_SampleSize / 2; ++ ++ return( MV_Ok ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_StartPlayback ++ ++ Starts the sound playback engine. ++---------------------------------------------------------------------*/ ++ ++int MV_StartPlayback ++ ( ++ void ++ ) ++ ++ { ++ int status; ++ int buffer; ++ ++ // Initialize the buffers ++ ClearBuffer_DW( MV_MixBuffer[ 0 ], MV_Silence, TotalBufferSize >> 2 ); ++ for( buffer = 0; buffer < MV_NumberOfBuffers; buffer++ ) ++ { ++ MV_BufferEmpty[ buffer ] = TRUE; ++ } ++ ++ // Set the mix buffer variables ++ MV_MixPage = 1; ++ ++ MV_MixFunction = MV_Mix; ++ ++ status = DSL_BeginBufferedPlayback( MV_MixBuffer[ 0 ], ++ TotalBufferSize, MV_NumberOfBuffers, ++ MV_RequestedMixRate, MV_MixMode, MV_ServiceVoc ); ++ ++ if ( status != DSL_Ok ) ++ { ++ MV_SetErrorCode( MV_BlasterError ); ++ return( MV_Error ); ++ } ++ ++ MV_MixRate = DSL_GetPlaybackRate(); ++ ++ return( MV_Ok ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_StopPlayback ++ ++ Stops the sound playback engine. ++---------------------------------------------------------------------*/ ++ ++void MV_StopPlayback ++ ( ++ void ++ ) ++ ++ { ++ VoiceNode *voice; ++ VoiceNode *next; ++ unsigned flags; ++ ++ DSL_StopPlayback(); ++ ++ // Make sure all callbacks are done. ++ flags = DisableInterrupts(); ++ ++ for( voice = VoiceList.next; voice != &VoiceList; voice = next ) ++ { ++ next = voice->next; ++ ++ MV_StopVoice( voice ); ++ ++ if ( MV_CallBackFunc ) ++ { ++ MV_CallBackFunc( voice->callbackval ); ++ } ++ } ++ ++ RestoreInterrupts( flags ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_StartRecording ++ ++ Starts the sound recording engine. ++---------------------------------------------------------------------*/ ++ ++int MV_StartRecording ++ ( ++ int MixRate, ++ void ( *function )( char *ptr, int length ) ++ ) ++ ++ { ++ MV_SetErrorCode( MV_UnsupportedCard ); ++ return( MV_Error ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_StopRecord ++ ++ Stops the sound record engine. ++---------------------------------------------------------------------*/ ++ ++void MV_StopRecord ++ ( ++ void ++ ) ++ ++ { ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_StartDemandFeedPlayback ++ ++ Plays a digitized sound from a user controlled buffering system. ++---------------------------------------------------------------------*/ ++ ++int MV_StartDemandFeedPlayback ++ ( ++ void ( *function )( char **ptr, unsigned long *length ), ++ int rate, ++ int pitchoffset, ++ int vol, ++ int left, ++ int right, ++ int priority, ++ unsigned long callbackval ++ ) ++ ++ { ++ VoiceNode *voice; ++ ++ if ( !MV_Installed ) ++ { ++ MV_SetErrorCode( MV_NotInstalled ); ++ return( MV_Error ); ++ } ++ ++ // Request a voice from the voice pool ++ voice = MV_AllocVoice( priority ); ++ if ( voice == NULL ) ++ { ++ MV_SetErrorCode( MV_NoVoices ); ++ return( MV_Error ); ++ } ++ ++ voice->wavetype = DemandFeed; ++ voice->bits = 8; ++ voice->GetSound = MV_GetNextDemandFeedBlock; ++ voice->NextBlock = NULL; ++ voice->DemandFeed = function; ++ voice->LoopStart = NULL; ++ voice->LoopCount = 0; ++ voice->BlockLength = 0; ++ voice->position = 0; ++ voice->sound = NULL; ++ voice->length = 0; ++ voice->BlockLength = 0; ++ voice->Playing = TRUE; ++ voice->next = NULL; ++ voice->prev = NULL; ++ voice->priority = priority; ++ voice->callbackval = callbackval; ++ ++ MV_SetVoicePitch( voice, rate, pitchoffset ); ++ MV_SetVoiceVolume( voice, vol, left, right ); ++ MV_PlayVoice( voice ); ++ ++ return( voice->handle ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_PlayRaw ++ ++ Begin playback of sound data with the given sound levels and ++ priority. ++---------------------------------------------------------------------*/ ++ ++int MV_PlayRaw ++ ( ++ char *ptr, ++ unsigned long length, ++ unsigned rate, ++ int pitchoffset, ++ int vol, ++ int left, ++ int right, ++ int priority, ++ unsigned long callbackval ++ ) ++ ++ { ++ int status; ++ ++ status = MV_PlayLoopedRaw( ptr, length, NULL, NULL, rate, pitchoffset, ++ vol, left, right, priority, callbackval ); ++ ++ return( status ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_PlayLoopedRaw ++ ++ Begin playback of sound data with the given sound levels and ++ priority. ++---------------------------------------------------------------------*/ ++ ++int MV_PlayLoopedRaw ++ ( ++ char *ptr, ++ long length, ++ char *loopstart, ++ char *loopend, ++ unsigned rate, ++ int pitchoffset, ++ int vol, ++ int left, ++ int right, ++ int priority, ++ unsigned long callbackval ++ ) ++ ++ { ++ VoiceNode *voice; ++ ++ if ( !MV_Installed ) ++ { ++ MV_SetErrorCode( MV_NotInstalled ); ++ return( MV_Error ); ++ } ++ ++ // Request a voice from the voice pool ++ voice = MV_AllocVoice( priority ); ++ if ( voice == NULL ) ++ { ++ MV_SetErrorCode( MV_NoVoices ); ++ return( MV_Error ); ++ } ++ ++ voice->wavetype = Raw; ++ voice->bits = 8; ++ voice->GetSound = MV_GetNextRawBlock; ++ voice->Playing = TRUE; ++ voice->NextBlock = ptr; ++ voice->position = 0; ++ voice->BlockLength = length; ++ voice->length = 0; ++ voice->next = NULL; ++ voice->prev = NULL; ++ voice->priority = priority; ++ voice->callbackval = callbackval; ++ voice->LoopStart = loopstart; ++ voice->LoopEnd = loopend; ++ voice->LoopSize = ( voice->LoopEnd - voice->LoopStart ) + 1; ++ ++ MV_SetVoicePitch( voice, rate, pitchoffset ); ++ MV_SetVoiceVolume( voice, vol, left, right ); ++ MV_PlayVoice( voice ); ++ ++ return( voice->handle ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_PlayWAV ++ ++ Begin playback of sound data with the given sound levels and ++ priority. ++---------------------------------------------------------------------*/ ++ ++int MV_PlayWAV ++ ( ++ char *ptr, ++ int pitchoffset, ++ int vol, ++ int left, ++ int right, ++ int priority, ++ unsigned long callbackval ++ ) ++ ++ { ++ int status; ++ ++ status = MV_PlayLoopedWAV( ptr, -1, -1, pitchoffset, vol, left, right, ++ priority, callbackval ); ++ ++ return( status ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_PlayWAV3D ++ ++ Begin playback of sound data at specified angle and distance ++ from listener. ++---------------------------------------------------------------------*/ ++ ++int MV_PlayWAV3D ++ ( ++ char *ptr, ++ int pitchoffset, ++ int angle, ++ int distance, ++ int priority, ++ unsigned long callbackval ++ ) ++ ++ { ++ int left; ++ int right; ++ int mid; ++ int volume; ++ int status; ++ ++ if ( !MV_Installed ) ++ { ++ MV_SetErrorCode( MV_NotInstalled ); ++ return( MV_Error ); ++ } ++ ++ if ( distance < 0 ) ++ { ++ distance = -distance; ++ angle += MV_NumPanPositions / 2; ++ } ++ ++ volume = MIX_VOLUME( distance ); ++ ++ // Ensure angle is within 0 - 31 ++ angle &= MV_MaxPanPosition; ++ ++ left = MV_PanTable[ angle ][ volume ].left; ++ right = MV_PanTable[ angle ][ volume ].right; ++ mid = max( 0, 255 - distance ); ++ ++ status = MV_PlayWAV( ptr, pitchoffset, mid, left, right, priority, ++ callbackval ); ++ ++ return( status ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_PlayLoopedWAV ++ ++ Begin playback of sound data with the given sound levels and ++ priority. ++---------------------------------------------------------------------*/ ++ ++int MV_PlayLoopedWAV ++ ( ++ char *ptr, ++ long loopstart, ++ long loopend, ++ int pitchoffset, ++ int vol, ++ int left, ++ int right, ++ int priority, ++ unsigned long callbackval ++ ) ++ ++ { ++ riff_header *riff; ++ format_header *format; ++ data_header *data; ++ VoiceNode *voice; ++ int length; ++ int absloopend; ++ int absloopstart; ++ ++ if ( !MV_Installed ) ++ { ++ MV_SetErrorCode( MV_NotInstalled ); ++ return( MV_Error ); ++ } ++ ++ riff = ( riff_header * )ptr; ++ ++ if ( ( strncmp( riff->RIFF, "RIFF", 4 ) != 0 ) || ++ ( strncmp( riff->WAVE, "WAVE", 4 ) != 0 ) || ++ ( strncmp( riff->fmt, "fmt ", 4) != 0 ) ) ++ { ++ MV_SetErrorCode( MV_InvalidWAVFile ); ++ return( MV_Error ); ++ } ++ ++ format = ( format_header * )( riff + 1 ); ++ data = ( data_header * )( ( ( char * )format ) + riff->format_size ); ++ ++ // Check if it's PCM data. ++ if ( format->wFormatTag != 1 ) ++ { ++ MV_SetErrorCode( MV_InvalidWAVFile ); ++ return( MV_Error ); ++ } ++ ++ if ( format->nChannels != 1 ) ++ { ++ MV_SetErrorCode( MV_InvalidWAVFile ); ++ return( MV_Error ); ++ } ++ ++ if ( ( format->nBitsPerSample != 8 ) && ++ ( format->nBitsPerSample != 16 ) ) ++ { ++ MV_SetErrorCode( MV_InvalidWAVFile ); ++ return( MV_Error ); ++ } ++ ++ if ( strncmp( data->DATA, "data", 4 ) != 0 ) ++ { ++ MV_SetErrorCode( MV_InvalidWAVFile ); ++ return( MV_Error ); ++ } ++ ++ // Request a voice from the voice pool ++ voice = MV_AllocVoice( priority ); ++ if ( voice == NULL ) ++ { ++ MV_SetErrorCode( MV_NoVoices ); ++ return( MV_Error ); ++ } ++ ++ voice->wavetype = WAV; ++ voice->bits = format->nBitsPerSample; ++ voice->GetSound = MV_GetNextWAVBlock; ++ ++ length = data->size; ++ absloopstart = loopstart; ++ absloopend = loopend; ++ if ( voice->bits == 16 ) ++ { ++ loopstart *= 2; ++ data->size &= ~1; ++ loopend *= 2; ++ length /= 2; ++ } ++ ++ loopend = min( loopend, (long)data->size ); ++ absloopend = min( absloopend, length ); ++ ++ voice->Playing = TRUE; ++ voice->DemandFeed = NULL; ++ voice->LoopStart = NULL; ++ voice->LoopCount = 0; ++ voice->position = 0; ++ voice->length = 0; ++ voice->BlockLength = absloopend; ++ voice->NextBlock = ( char * )( data + 1 ); ++ voice->next = NULL; ++ voice->prev = NULL; ++ voice->priority = priority; ++ voice->callbackval = callbackval; ++ voice->LoopStart = voice->NextBlock + loopstart; ++ voice->LoopEnd = voice->NextBlock + loopend; ++ voice->LoopSize = absloopend - absloopstart; ++ ++ if ( ( loopstart >= (long)data->size ) || ( loopstart < 0 ) ) ++ { ++ voice->LoopStart = NULL; ++ voice->LoopEnd = NULL; ++ voice->BlockLength = length; ++ } ++ ++ MV_SetVoicePitch( voice, format->nSamplesPerSec, pitchoffset ); ++ MV_SetVoiceVolume( voice, vol, left, right ); ++ MV_PlayVoice( voice ); ++ ++ return( voice->handle ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_PlayVOC3D ++ ++ Begin playback of sound data at specified angle and distance ++ from listener. ++---------------------------------------------------------------------*/ ++ ++int MV_PlayVOC3D ++ ( ++ char *ptr, ++ int pitchoffset, ++ int angle, ++ int distance, ++ int priority, ++ unsigned long callbackval ++ ) ++ ++ { ++ int left; ++ int right; ++ int mid; ++ int volume; ++ int status; ++ ++ if ( !MV_Installed ) ++ { ++ MV_SetErrorCode( MV_NotInstalled ); ++ return( MV_Error ); ++ } ++ ++ if ( distance < 0 ) ++ { ++ distance = -distance; ++ angle += MV_NumPanPositions / 2; ++ } ++ ++ volume = MIX_VOLUME( distance ); ++ ++ // Ensure angle is within 0 - 31 ++ angle &= MV_MaxPanPosition; ++ ++ left = MV_PanTable[ angle ][ volume ].left; ++ right = MV_PanTable[ angle ][ volume ].right; ++ mid = max( 0, 255 - distance ); ++ ++ status = MV_PlayVOC( ptr, pitchoffset, mid, left, right, priority, ++ callbackval ); ++ ++ return( status ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_PlayVOC ++ ++ Begin playback of sound data with the given sound levels and ++ priority. ++---------------------------------------------------------------------*/ ++ ++int MV_PlayVOC ++ ( ++ char *ptr, ++ int pitchoffset, ++ int vol, ++ int left, ++ int right, ++ int priority, ++ unsigned long callbackval ++ ) ++ ++ { ++ int status; ++ ++ status = MV_PlayLoopedVOC( ptr, -1, -1, pitchoffset, vol, left, right, ++ priority, callbackval ); ++ ++ return( status ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_PlayLoopedVOC ++ ++ Begin playback of sound data with the given sound levels and ++ priority. ++---------------------------------------------------------------------*/ ++ ++int MV_PlayLoopedVOC ++ ( ++ char *ptr, ++ long loopstart, ++ long loopend, ++ int pitchoffset, ++ int vol, ++ int left, ++ int right, ++ int priority, ++ unsigned long callbackval ++ ) ++ ++ { ++ VoiceNode *voice; ++ int status; ++ unsigned short nextpos; ++ ++ if ( !MV_Installed ) ++ { ++ MV_SetErrorCode( MV_NotInstalled ); ++ return( MV_Error ); ++ } ++ ++ // Make sure it's a valid VOC file. ++ status = strncmp( ptr, "Creative Voice File", 19 ); ++ if ( status != 0 ) ++ { ++ MV_SetErrorCode( MV_InvalidVOCFile ); ++ return( MV_Error ); ++ } ++ ++ // Request a voice from the voice pool ++ voice = MV_AllocVoice( priority ); ++ if ( voice == NULL ) ++ { ++ MV_SetErrorCode( MV_NoVoices ); ++ return( MV_Error ); ++ } ++ ++ voice->wavetype = VOC; ++ voice->bits = 8; ++ voice->GetSound = MV_GetNextVOCBlock; ++ ++ nextpos = *( unsigned short * )( ptr + 0x14 ); ++ voice->NextBlock = ptr + BUILDSWAP_INTEL16(nextpos); ++ ++ voice->DemandFeed = NULL; ++ voice->LoopStart = NULL; ++ voice->LoopCount = 0; ++ voice->BlockLength = 0; ++ voice->PitchScale = PITCH_GetScale( pitchoffset ); ++ voice->length = 0; ++ voice->next = NULL; ++ voice->prev = NULL; ++ voice->priority = priority; ++ voice->callbackval = callbackval; ++ voice->LoopStart = ( char * )loopstart; ++ voice->LoopEnd = ( char * )loopend; ++ voice->LoopSize = loopend - loopstart + 1; ++ ++ if ( loopstart < 0 ) ++ { ++ voice->LoopStart = NULL; ++ voice->LoopEnd = NULL; ++ } ++ ++ MV_SetVoiceVolume( voice, vol, left, right ); ++ MV_PlayVoice( voice ); ++ ++ return( voice->handle ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_LockEnd ++ ++ Used for determining the length of the functions to lock in memory. ++---------------------------------------------------------------------*/ ++ ++static void MV_LockEnd ++ ( ++ void ++ ) ++ ++ { ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_CreateVolumeTable ++ ++ Create the table used to convert sound data to a specific volume ++ level. ++---------------------------------------------------------------------*/ ++ ++void MV_CreateVolumeTable ++ ( ++ int index, ++ int volume, ++ int MaxVolume ++ ) ++ ++ { ++ int val; ++ int level; ++ int i; ++ ++ level = ( volume * MaxVolume ) / MV_MaxTotalVolume; ++ if ( MV_Bits == 16 ) ++ { ++ for( i = 0; i < 65536; i += 256 ) ++ { ++ val = i - 0x8000; ++ val *= level; ++ val /= MV_MaxVolume; ++ MV_VolumeTable[ index ][ i / 256 ] = val; ++ } ++ } ++ else ++ { ++ for( i = 0; i < 256; i++ ) ++ { ++ val = i - 0x80; ++ val *= level; ++ val /= MV_MaxVolume; ++ MV_VolumeTable[ volume ][ i ] = val; ++ } ++ } ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_CalcVolume ++ ++ Create the table used to convert sound data to a specific volume ++ level. ++---------------------------------------------------------------------*/ ++ ++void MV_CalcVolume ++ ( ++ int MaxVolume ++ ) ++ ++ { ++ int volume; ++ ++ for( volume = 0; volume < 128; volume++ ) ++ { ++ MV_HarshClipTable[ volume ] = 0; ++ MV_HarshClipTable[ volume + 384 ] = 255; ++ } ++ for( volume = 0; volume < 256; volume++ ) ++ { ++ MV_HarshClipTable[ volume + 128 ] = volume; ++ } ++ ++ // For each volume level, create a translation table with the ++ // appropriate volume calculated. ++ for( volume = 0; volume <= MV_MaxVolume; volume++ ) ++ { ++ MV_CreateVolumeTable( volume, volume, MaxVolume ); ++ } ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_CalcPanTable ++ ++ Create the table used to determine the stereo volume level of ++ a sound located at a specific angle and distance from the listener. ++---------------------------------------------------------------------*/ ++ ++void MV_CalcPanTable ++ ( ++ void ++ ) ++ ++ { ++ int level; ++ int angle; ++ int distance; ++ int HalfAngle; ++ int ramp; ++ ++ HalfAngle = ( MV_NumPanPositions / 2 ); ++ ++ for( distance = 0; distance <= MV_MaxVolume; distance++ ) ++ { ++ level = ( 255 * ( MV_MaxVolume - distance ) ) / MV_MaxVolume; ++ for( angle = 0; angle <= HalfAngle / 2; angle++ ) ++ { ++ ramp = level - ( ( level * angle ) / ++ ( MV_NumPanPositions / 4 ) ); ++ ++ MV_PanTable[ angle ][ distance ].left = ramp; ++ MV_PanTable[ HalfAngle - angle ][ distance ].left = ramp; ++ MV_PanTable[ HalfAngle + angle ][ distance ].left = level; ++ MV_PanTable[ MV_MaxPanPosition - angle ][ distance ].left = level; ++ ++ MV_PanTable[ angle ][ distance ].right = level; ++ MV_PanTable[ HalfAngle - angle ][ distance ].right = level; ++ MV_PanTable[ HalfAngle + angle ][ distance ].right = ramp; ++ MV_PanTable[ MV_MaxPanPosition - angle ][ distance ].right = ramp; ++ } ++ } ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_SetVolume ++ ++ Sets the volume of digitized sound playback. ++---------------------------------------------------------------------*/ ++ ++void MV_SetVolume ++ ( ++ int volume ++ ) ++ ++ { ++ volume = max( 0, volume ); ++ volume = min( volume, MV_MaxTotalVolume ); ++ ++ MV_TotalVolume = volume; ++ ++ // Calculate volume table ++ MV_CalcVolume( volume ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_GetVolume ++ ++ Returns the volume of digitized sound playback. ++---------------------------------------------------------------------*/ ++ ++int MV_GetVolume ++ ( ++ void ++ ) ++ ++ { ++ return( MV_TotalVolume ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_SetCallBack ++ ++ Set the function to call when a voice stops. ++---------------------------------------------------------------------*/ ++ ++void MV_SetCallBack ++ ( ++ void ( *function )( unsigned long ) ++ ) ++ ++ { ++ MV_CallBackFunc = function; ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_SetReverseStereo ++ ++ Set the orientation of the left and right channels. ++---------------------------------------------------------------------*/ ++ ++void MV_SetReverseStereo ++ ( ++ int setting ++ ) ++ ++ { ++ MV_SwapLeftRight = setting; ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_GetReverseStereo ++ ++ Returns the orientation of the left and right channels. ++---------------------------------------------------------------------*/ ++ ++int MV_GetReverseStereo ++ ( ++ void ++ ) ++ ++ { ++ return( MV_SwapLeftRight ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_TestPlayback ++ ++ Checks if playback has started. ++---------------------------------------------------------------------*/ ++ ++int MV_TestPlayback(void) ++ { ++ return MV_Ok; ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_Init ++ ++ Perform the initialization of variables and memory used by ++ Multivoc. ++---------------------------------------------------------------------*/ ++ ++int MV_Init ++ ( ++ int soundcard, ++ int MixRate, ++ int Voices, ++ int numchannels, ++ int samplebits ++ ) ++ ++ { ++ char *ptr; ++ int status; ++ int buffer; ++ int index; ++ ++ if ( MV_Installed ) ++ { ++ MV_Shutdown(); ++ } ++ ++ MV_SetErrorCode( MV_Ok ); ++ ++ MV_TotalMemory = Voices * sizeof( VoiceNode ) + sizeof( HARSH_CLIP_TABLE_8 ); ++ status = USRHOOKS_GetMem( ( void ** )&ptr, MV_TotalMemory ); ++ if ( status != USRHOOKS_Ok ) ++ { ++ MV_SetErrorCode( MV_NoMem ); ++ return( MV_Error ); ++ } ++ ++ MV_Voices = ( VoiceNode * )ptr; ++ MV_HarshClipTable = ptr + ( MV_TotalMemory - sizeof( HARSH_CLIP_TABLE_8 ) ); ++ ++ // Set number of voices before calculating volume table ++ MV_MaxVoices = Voices; ++ ++ LL_Reset( (VoiceNode *)&VoiceList, next, prev ); ++ LL_Reset( (VoiceNode *)&VoicePool, next, prev ); ++ ++ for( index = 0; index < Voices; index++ ) ++ { ++ LL_Add( (VoiceNode *)&VoicePool, &MV_Voices[ index ], next, prev ); ++ } ++ ++ // Allocate mix buffer within 1st megabyte ++ status = DPMI_GetDOSMemory( ( void ** )&ptr, &MV_BufferDescriptor, ++ 2 * TotalBufferSize ); ++ ++ if ( status ) ++ { ++ USRHOOKS_FreeMem( MV_Voices ); ++ MV_Voices = NULL; ++ MV_TotalMemory = 0; ++ ++ MV_SetErrorCode( MV_NoMem ); ++ return( MV_Error ); ++ } ++ ++ MV_SetReverseStereo( FALSE ); ++ ++ // Initialize the sound card ++ status = DSL_Init(); ++ if ( status != DSL_Ok ) ++ { ++ MV_SetErrorCode( MV_BlasterError ); ++ } ++ ++ if ( MV_ErrorCode != MV_Ok ) ++ { ++ status = MV_ErrorCode; ++ ++ USRHOOKS_FreeMem( MV_Voices ); ++ MV_Voices = NULL; ++ MV_TotalMemory = 0; ++ ++ DPMI_FreeDOSMemory( MV_BufferDescriptor ); ++ ++ MV_SetErrorCode( status ); ++ return( MV_Error ); ++ } ++ ++ MV_SoundCard = soundcard; ++ MV_Installed = TRUE; ++ MV_CallBackFunc = NULL; ++ MV_RecordFunc = NULL; ++ MV_Recording = FALSE; ++ MV_ReverbLevel = 0; ++ MV_ReverbTable = NULL; ++ ++ // Set the sampling rate ++ MV_RequestedMixRate = MixRate; ++ ++ // Set Mixer to play stereo digitized sound ++ MV_SetMixMode( numchannels, samplebits ); ++ MV_ReverbDelay = MV_BufferSize * 3; ++ ++ MV_MixBuffer[ MV_NumberOfBuffers ] = ptr; ++ for( buffer = 0; buffer < MV_NumberOfBuffers; buffer++ ) ++ { ++ MV_MixBuffer[ buffer ] = ptr; ++ ptr += MV_BufferSize; ++ } ++ ++ // Calculate pan table ++ MV_CalcPanTable(); ++ ++ MV_SetVolume( MV_MaxTotalVolume ); ++ ++ // Start the playback engine ++ status = MV_StartPlayback(); ++ if ( status != MV_Ok ) ++ { ++ // Preserve error code while we shutdown. ++ status = MV_ErrorCode; ++ MV_Shutdown(); ++ MV_SetErrorCode( status ); ++ return( MV_Error ); ++ } ++ ++ if ( MV_TestPlayback() != MV_Ok ) ++ { ++ status = MV_ErrorCode; ++ MV_Shutdown(); ++ MV_SetErrorCode( status ); ++ return( MV_Error ); ++ } ++ ++ return( MV_Ok ); ++ } ++ ++ ++/*--------------------------------------------------------------------- ++ Function: MV_Shutdown ++ ++ Restore any resources allocated by Multivoc back to the system. ++---------------------------------------------------------------------*/ ++ ++int MV_Shutdown ++ ( ++ void ++ ) ++ ++ { ++ int buffer; ++ unsigned flags; ++ ++ if ( !MV_Installed ) ++ { ++ return( MV_Ok ); ++ } ++ ++ flags = DisableInterrupts(); ++ ++ MV_KillAllVoices(); ++ ++ MV_Installed = FALSE; ++ ++ // Stop the sound recording engine ++ if ( MV_Recording ) ++ { ++ MV_StopRecord(); ++ } ++ ++ // Stop the sound playback engine ++ MV_StopPlayback(); ++ ++ // Shutdown the sound card ++ DSL_Shutdown(); ++ ++ RestoreInterrupts( flags ); ++ ++ // Free any voices we allocated ++ USRHOOKS_FreeMem( MV_Voices ); ++ MV_Voices = NULL; ++ MV_TotalMemory = 0; ++ ++ LL_Reset( (VoiceNode *)&VoiceList, next, prev ); ++ LL_Reset( (VoiceNode *)&VoicePool, next, prev ); ++ ++ MV_MaxVoices = 1; ++ ++ // Release the descriptor from our mix buffer ++ DPMI_FreeDOSMemory( MV_BufferDescriptor ); ++ for( buffer = 0; buffer < NumberOfBuffers; buffer++ ) ++ { ++ MV_MixBuffer[ buffer ] = NULL; ++ } ++ ++ return( MV_Ok ); ++ } diff --git a/games/eduke32/files/patch-source__jaudiolib__util.h b/games/eduke32/files/patch-source__jaudiolib__util.h new file mode 100644 index 000000000000..fe8012b97e07 --- /dev/null +++ b/games/eduke32/files/patch-source__jaudiolib__util.h @@ -0,0 +1,15 @@ +--- ./source/jaudiolib/util.h.orig Wed Aug 2 00:35:30 2006 ++++ ./source/jaudiolib/util.h Wed Aug 2 00:35:30 2006 +@@ -0,0 +1,12 @@ ++#ifndef AUDIOLIB__UTIL_H ++#define AUDIOLIB__UTIL_H ++ ++#ifndef min ++#define min(a, b) ((a) < (b) ? (a) : (b)) ++#endif ++ ++#ifndef max ++#define max(a, b) ((a) > (b) ? (a) : (b)) ++#endif ++ ++#endif diff --git a/games/eduke32/pkg-descr b/games/eduke32/pkg-descr new file mode 100644 index 000000000000..0faf5667c94f --- /dev/null +++ b/games/eduke32/pkg-descr @@ -0,0 +1,11 @@ +EDuke32 is a Windows/Linux/UNIX version of Duke Nukem 3D aimed at highly +extending what can be edited in the game. EDuke32 combines the work that JonoF +and Ken Silverman have put in to JFDuke3D with the original EDuke work done by +Matt Saettler, while simultaneously adding tons of new and useful features. +Consequently, EDuke32 is the most advanced version of Duke Nukem 3D in +existence. EDuke32 is developed and maintained by Richard "TerminX" Gobeille +and the EDuke32 team. + +This port includes icculus.org/duke3d patches for sound and joystick support. + +WWW: http://eduke32.com/ diff --git a/games/eduke32/pkg-plist b/games/eduke32/pkg-plist new file mode 100644 index 000000000000..999b44cc729d --- /dev/null +++ b/games/eduke32/pkg-plist @@ -0,0 +1,6 @@ +bin/eduke32 +bin/mapster32 +%%PORTDOCS%%%%DOCSDIR%%/ChangeLog +%%PORTDOCS%%%%DOCSDIR%%/duke3d.def.sample +%%PORTDOCS%%%%DOCSDIR%%/enhance.con.sample +%%PORTDOCS%%@dirrm %%DOCSDIR%% -- cgit v1.2.3