aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwyatt8740 <wyatt8740@users.noreply.github.com>2023-10-02 00:13:07 -0400
committerwyatt8740 <wyatt8740@users.noreply.github.com>2023-10-02 00:13:07 -0400
commit91df067e453c519ab1a8a919398c05ef87df5898 (patch)
tree02c2e604a9177b4cad6020d0cb379dbee7d9d7e1
parent72d9253ab2e5e0630c824c7130a40b7158323bc9 (diff)
downloadquake-pum-91df067e453c519ab1a8a919398c05ef87df5898.tar.gz
dos2unix, makefile linking flags
-rw-r--r--WinQuake/Makefile4
-rw-r--r--WinQuake/cvar.h206
-rw-r--r--WinQuake/d_ifacea.h38
-rw-r--r--WinQuake/r_shared.h322
-rw-r--r--WinQuake/snd_dma.c2056
-rw-r--r--WinQuake/sound.h366
6 files changed, 1496 insertions, 1496 deletions
diff --git a/WinQuake/Makefile b/WinQuake/Makefile
index 4f111f5..1d91748 100644
--- a/WinQuake/Makefile
+++ b/WinQuake/Makefile
@@ -19,7 +19,7 @@ else
SDL_CONFIG ?= sdl-config
endif
SDL_CFLAGS := $(shell $(SDL_CONFIG) --cflags) -DUSE_SDL2
-SDL_LIBS := $(shell $(SDL_CONFIG) --libs)
+SDL_LIBS := $(shell $(SDL_CONFIG) --libs) -lXi -lX11 -lXt -lXxf86vm -lXss -lXrandr -lXcursor -lwayland-client -lxkbcommon -lwayland-cursor -ldrm -lwayland-egl -lgbm -lXinerama -lpulse -lasound
BASEVERSION=1.09
VERSION=$(BASEVERSION)$(GLIBC)
@@ -61,7 +61,7 @@ RELEASE_CFLAGS=$(BASE_CFLAGS) -g -mtune=native -O3 -march=native
DEBUG_CFLAGS=$(BASE_CFLAGS) -g
LDFLAGS=-lm -m32
SVGALDFLAGS=-lvga
-XLDFLAGS=-L/usr/X11R6/lib -lX11 -lXext /usr/lib/i386-linux-gnu/libXxf86dga.so.1.0.0
+XLDFLAGS=-L/usr/X11R6/lib -L/usr/lib/i386-linux-gnu -lX11 -lXext /usr/lib/i386-linux-gnu/libXxf86dga.so.1.0.0
XCFLAGS=-DX11
MESAGLLDFLAGS=-L/usr/lib/X11 -L/usr/local/lib -L$(MESA_DIR)/lib -lMesaGL -lglide2x -lX11 -lXext -ldl
diff --git a/WinQuake/cvar.h b/WinQuake/cvar.h
index ef5a0ed..506859c 100644
--- a/WinQuake/cvar.h
+++ b/WinQuake/cvar.h
@@ -1,103 +1,103 @@
-/*
-Copyright (C) 1996-1997 Id Software, Inc.
-
-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.
-
-*/
-// cvar.h
-
-/*
-
-cvar_t variables are used to hold scalar or string variables that can be changed or displayed at the console or prog code as well as accessed directly
-in C code.
-
-it is sufficient to initialize a cvar_t with just the first two fields, or
-you can add a ,true flag for variables that you want saved to the configuration
-file when the game is quit:
-
-cvar_t r_draworder = {"r_draworder","1"};
-cvar_t scr_screensize = {"screensize","1",true};
-
-Cvars must be registered before use, or they will have a 0 value instead of the float interpretation of the string. Generally, all cvar_t declarations should be registered in the apropriate init function before any console commands are executed:
-Cvar_RegisterVariable (&host_framerate);
-
-
-C code usually just references a cvar in place:
-if ( r_draworder.value )
-
-It could optionally ask for the value to be looked up for a string name:
-if (Cvar_VariableValue ("r_draworder"))
-
-Interpreted prog code can access cvars with the cvar(name) or
-cvar_set (name, value) internal functions:
-teamplay = cvar("teamplay");
-cvar_set ("registered", "1");
-
-The user can access cvars from the console in two ways:
-r_draworder prints the current value
-r_draworder 0 sets the current value to 0
-Cvars are restricted from having the same names as commands to keep this
-interface from being ambiguous.
-*/
-
-/* for sdl */
-#if defined(USE_SDL2)
-#define CVAR_NONE 0
-#endif
-/* sdl end */
-
-typedef struct cvar_s
-{
- char *name;
- char *string;
- qboolean archive; // set to true to cause it to be saved to vars.rc
- qboolean server; // notifies players when changed
- float value;
- struct cvar_s *next;
-} cvar_t;
-
-void Cvar_RegisterVariable (cvar_t *variable);
-// registers a cvar that allready has the name, string, and optionally the
-// archive elements set.
-
-void Cvar_Set (char *var_name, char *value);
-// equivelant to "<name> <variable>" typed at the console
-
-void Cvar_SetValue (char *var_name, float value);
-// expands value to a string and calls Cvar_Set
-
-float Cvar_VariableValue (char *var_name);
-// returns 0 if not defined or non numeric
-
-char *Cvar_VariableString (char *var_name);
-// returns an empty string if not defined
-
-char *Cvar_CompleteVariable (char *partial);
-// attempts to match a partial variable name for command line completion
-// returns NULL if nothing fits
-
-qboolean Cvar_Command (void);
-// called by Cmd_ExecuteString when Cmd_Argv(0) doesn't match a known
-// command. Returns true if the command was a variable reference that
-// was handled. (print or change)
-
-void Cvar_WriteVariables (FILE *f);
-// Writes lines containing "set variable value" for all variables
-// with the archive flag set to true.
-
-cvar_t *Cvar_FindVar (char *var_name);
-
-extern cvar_t *cvar_vars;
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+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.
+
+*/
+// cvar.h
+
+/*
+
+cvar_t variables are used to hold scalar or string variables that can be changed or displayed at the console or prog code as well as accessed directly
+in C code.
+
+it is sufficient to initialize a cvar_t with just the first two fields, or
+you can add a ,true flag for variables that you want saved to the configuration
+file when the game is quit:
+
+cvar_t r_draworder = {"r_draworder","1"};
+cvar_t scr_screensize = {"screensize","1",true};
+
+Cvars must be registered before use, or they will have a 0 value instead of the float interpretation of the string. Generally, all cvar_t declarations should be registered in the apropriate init function before any console commands are executed:
+Cvar_RegisterVariable (&host_framerate);
+
+
+C code usually just references a cvar in place:
+if ( r_draworder.value )
+
+It could optionally ask for the value to be looked up for a string name:
+if (Cvar_VariableValue ("r_draworder"))
+
+Interpreted prog code can access cvars with the cvar(name) or
+cvar_set (name, value) internal functions:
+teamplay = cvar("teamplay");
+cvar_set ("registered", "1");
+
+The user can access cvars from the console in two ways:
+r_draworder prints the current value
+r_draworder 0 sets the current value to 0
+Cvars are restricted from having the same names as commands to keep this
+interface from being ambiguous.
+*/
+
+/* for sdl */
+#if defined(USE_SDL2)
+#define CVAR_NONE 0
+#endif
+/* sdl end */
+
+typedef struct cvar_s
+{
+ char *name;
+ char *string;
+ qboolean archive; // set to true to cause it to be saved to vars.rc
+ qboolean server; // notifies players when changed
+ float value;
+ struct cvar_s *next;
+} cvar_t;
+
+void Cvar_RegisterVariable (cvar_t *variable);
+// registers a cvar that allready has the name, string, and optionally the
+// archive elements set.
+
+void Cvar_Set (char *var_name, char *value);
+// equivelant to "<name> <variable>" typed at the console
+
+void Cvar_SetValue (char *var_name, float value);
+// expands value to a string and calls Cvar_Set
+
+float Cvar_VariableValue (char *var_name);
+// returns 0 if not defined or non numeric
+
+char *Cvar_VariableString (char *var_name);
+// returns an empty string if not defined
+
+char *Cvar_CompleteVariable (char *partial);
+// attempts to match a partial variable name for command line completion
+// returns NULL if nothing fits
+
+qboolean Cvar_Command (void);
+// called by Cmd_ExecuteString when Cmd_Argv(0) doesn't match a known
+// command. Returns true if the command was a variable reference that
+// was handled. (print or change)
+
+void Cvar_WriteVariables (FILE *f);
+// Writes lines containing "set variable value" for all variables
+// with the archive flag set to true.
+
+cvar_t *Cvar_FindVar (char *var_name);
+
+extern cvar_t *cvar_vars;
diff --git a/WinQuake/d_ifacea.h b/WinQuake/d_ifacea.h
index 1d5d5d5..c93369e 100644
--- a/WinQuake/d_ifacea.h
+++ b/WinQuake/d_ifacea.h
@@ -1,22 +1,22 @@
-/*
-Copyright (C) 1996-1997 Id Software, Inc.
-
-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.
-
-*/
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+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.
+
+*/
//
// d_ifacea.h
//
diff --git a/WinQuake/r_shared.h b/WinQuake/r_shared.h
index 0f33e2b..a70f125 100644
--- a/WinQuake/r_shared.h
+++ b/WinQuake/r_shared.h
@@ -1,161 +1,161 @@
-/*
-Copyright (C) 1996-1997 Id Software, Inc.
-
-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 GLQUAKE
-// r_shared.h: general refresh-related stuff shared between the refresh and the
-// driver
-
-// FIXME: clean up and move into d_iface.h
-
-#ifndef _R_SHARED_H_
-#define _R_SHARED_H_
-
-#define MAXVERTS 16 // max points in a surface polygon
-#define MAXWORKINGVERTS (MAXVERTS+4) // max points in an intermediate
- // polygon (while processing)
-// !!! if this is changed, it must be changed in d_ifacea.h too !!!
-// wyatt
-// define MAXHEIGHT 1024
-#define MAXHEIGHT 2048
-// wyatt
-// define MAXWIDTH 1280
-#define MAXWIDTH 2560
-#define MAXDIMENSION ((MAXHEIGHT > MAXWIDTH) ? MAXHEIGHT : MAXWIDTH)
-
-#define SIN_BUFFER_SIZE (MAXDIMENSION+CYCLE)
-
-#define INFINITE_DISTANCE 0x10000 // distance that's always guaranteed to
- // be farther away than anything in
- // the scene
-
-//===================================================================
-
-extern void R_DrawLine (polyvert_t *polyvert0, polyvert_t *polyvert1);
-
-extern int cachewidth;
-extern pixel_t *cacheblock;
-extern int screenwidth;
-
-extern float pixelAspect;
-
-extern int r_drawnpolycount;
-
-extern cvar_t r_clearcolor;
-
-extern int sintable[SIN_BUFFER_SIZE];
-extern int intsintable[SIN_BUFFER_SIZE];
-
-extern vec3_t vup, base_vup;
-extern vec3_t vpn, base_vpn;
-extern vec3_t vright, base_vright;
-extern entity_t *currententity;
-
-#define NUMSTACKEDGES 2400
-#define MINEDGES NUMSTACKEDGES
-#define NUMSTACKSURFACES 800
-#define MINSURFACES NUMSTACKSURFACES
-#define MAXSPANS 3000
-
-// !!! if this is changed, it must be changed in asm_draw.h too !!!
-typedef struct espan_s
-{
- int u, v, count;
- struct espan_s *pnext;
-} espan_t;
-
-// FIXME: compress, make a union if that will help
-// insubmodel is only 1, flags is fewer than 32, spanstate could be a byte
-typedef struct surf_s
-{
- struct surf_s *next; // active surface stack in r_edge.c
- struct surf_s *prev; // used in r_edge.c for active surf stack
- struct espan_s *spans; // pointer to linked list of spans to draw
- int key; // sorting key (BSP order)
- int last_u; // set during tracing
- int spanstate; // 0 = not in span
- // 1 = in span
- // -1 = in inverted span (end before
- // start)
- int flags; // currentface flags
- void *data; // associated data like msurface_t
- entity_t *entity;
- float nearzi; // nearest 1/z on surface, for mipmapping
- qboolean insubmodel;
- float d_ziorigin, d_zistepu, d_zistepv;
-
- int pad[2]; // to 64 bytes
-} surf_t;
-
-extern surf_t *surfaces, *surface_p, *surf_max;
-
-// surfaces are generated in back to front order by the bsp, so if a surf
-// pointer is greater than another one, it should be drawn in front
-// surfaces[1] is the background, and is used as the active surface stack.
-// surfaces[0] is a dummy, because index 0 is used to indicate no surface
-// attached to an edge_t
-
-//===================================================================
-
-extern vec3_t sxformaxis[4]; // s axis transformed into viewspace
-extern vec3_t txformaxis[4]; // t axis transformed into viewspac
-
-extern vec3_t modelorg, base_modelorg;
-
-extern float xcenter, ycenter;
-extern float xscale, yscale;
-extern float xscaleinv, yscaleinv;
-extern float xscaleshrink, yscaleshrink;
-
-extern int d_lightstylevalue[256]; // 8.8 frac of base light value
-
-extern void TransformVector (vec3_t in, vec3_t out);
-extern void SetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv,
- fixed8_t endvertu, fixed8_t endvertv);
-
-extern int r_skymade;
-extern void R_MakeSky (void);
-
-extern int ubasestep, errorterm, erroradjustup, erroradjustdown;
-
-// flags in finalvert_t.flags
-#define ALIAS_LEFT_CLIP 0x0001
-#define ALIAS_TOP_CLIP 0x0002
-#define ALIAS_RIGHT_CLIP 0x0004
-#define ALIAS_BOTTOM_CLIP 0x0008
-#define ALIAS_Z_CLIP 0x0010
-// !!! if this is changed, it must be changed in d_ifacea.h too !!!
-#define ALIAS_ONSEAM 0x0020 // also defined in modelgen.h;
- // must be kept in sync
-#define ALIAS_XY_CLIP_MASK 0x000F
-
-// !!! if this is changed, it must be changed in asm_draw.h too !!!
-typedef struct edge_s
-{
- fixed16_t u;
- fixed16_t u_step;
- struct edge_s *prev, *next;
- unsigned short surfs[2];
- struct edge_s *nextremove;
- float nearzi;
- medge_t *owner;
-} edge_t;
-
-#endif // _R_SHARED_H_
-
-#endif // GLQUAKE
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+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 GLQUAKE
+// r_shared.h: general refresh-related stuff shared between the refresh and the
+// driver
+
+// FIXME: clean up and move into d_iface.h
+
+#ifndef _R_SHARED_H_
+#define _R_SHARED_H_
+
+#define MAXVERTS 16 // max points in a surface polygon
+#define MAXWORKINGVERTS (MAXVERTS+4) // max points in an intermediate
+ // polygon (while processing)
+// !!! if this is changed, it must be changed in d_ifacea.h too !!!
+// wyatt
+// define MAXHEIGHT 1024
+#define MAXHEIGHT 2048
+// wyatt
+// define MAXWIDTH 1280
+#define MAXWIDTH 2560
+#define MAXDIMENSION ((MAXHEIGHT > MAXWIDTH) ? MAXHEIGHT : MAXWIDTH)
+
+#define SIN_BUFFER_SIZE (MAXDIMENSION+CYCLE)
+
+#define INFINITE_DISTANCE 0x10000 // distance that's always guaranteed to
+ // be farther away than anything in
+ // the scene
+
+//===================================================================
+
+extern void R_DrawLine (polyvert_t *polyvert0, polyvert_t *polyvert1);
+
+extern int cachewidth;
+extern pixel_t *cacheblock;
+extern int screenwidth;
+
+extern float pixelAspect;
+
+extern int r_drawnpolycount;
+
+extern cvar_t r_clearcolor;
+
+extern int sintable[SIN_BUFFER_SIZE];
+extern int intsintable[SIN_BUFFER_SIZE];
+
+extern vec3_t vup, base_vup;
+extern vec3_t vpn, base_vpn;
+extern vec3_t vright, base_vright;
+extern entity_t *currententity;
+
+#define NUMSTACKEDGES 2400
+#define MINEDGES NUMSTACKEDGES
+#define NUMSTACKSURFACES 800
+#define MINSURFACES NUMSTACKSURFACES
+#define MAXSPANS 3000
+
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct espan_s
+{
+ int u, v, count;
+ struct espan_s *pnext;
+} espan_t;
+
+// FIXME: compress, make a union if that will help
+// insubmodel is only 1, flags is fewer than 32, spanstate could be a byte
+typedef struct surf_s
+{
+ struct surf_s *next; // active surface stack in r_edge.c
+ struct surf_s *prev; // used in r_edge.c for active surf stack
+ struct espan_s *spans; // pointer to linked list of spans to draw
+ int key; // sorting key (BSP order)
+ int last_u; // set during tracing
+ int spanstate; // 0 = not in span
+ // 1 = in span
+ // -1 = in inverted span (end before
+ // start)
+ int flags; // currentface flags
+ void *data; // associated data like msurface_t
+ entity_t *entity;
+ float nearzi; // nearest 1/z on surface, for mipmapping
+ qboolean insubmodel;
+ float d_ziorigin, d_zistepu, d_zistepv;
+
+ int pad[2]; // to 64 bytes
+} surf_t;
+
+extern surf_t *surfaces, *surface_p, *surf_max;
+
+// surfaces are generated in back to front order by the bsp, so if a surf
+// pointer is greater than another one, it should be drawn in front
+// surfaces[1] is the background, and is used as the active surface stack.
+// surfaces[0] is a dummy, because index 0 is used to indicate no surface
+// attached to an edge_t
+
+//===================================================================
+
+extern vec3_t sxformaxis[4]; // s axis transformed into viewspace
+extern vec3_t txformaxis[4]; // t axis transformed into viewspac
+
+extern vec3_t modelorg, base_modelorg;
+
+extern float xcenter, ycenter;
+extern float xscale, yscale;
+extern float xscaleinv, yscaleinv;
+extern float xscaleshrink, yscaleshrink;
+
+extern int d_lightstylevalue[256]; // 8.8 frac of base light value
+
+extern void TransformVector (vec3_t in, vec3_t out);
+extern void SetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv,
+ fixed8_t endvertu, fixed8_t endvertv);
+
+extern int r_skymade;
+extern void R_MakeSky (void);
+
+extern int ubasestep, errorterm, erroradjustup, erroradjustdown;
+
+// flags in finalvert_t.flags
+#define ALIAS_LEFT_CLIP 0x0001
+#define ALIAS_TOP_CLIP 0x0002
+#define ALIAS_RIGHT_CLIP 0x0004
+#define ALIAS_BOTTOM_CLIP 0x0008
+#define ALIAS_Z_CLIP 0x0010
+// !!! if this is changed, it must be changed in d_ifacea.h too !!!
+#define ALIAS_ONSEAM 0x0020 // also defined in modelgen.h;
+ // must be kept in sync
+#define ALIAS_XY_CLIP_MASK 0x000F
+
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct edge_s
+{
+ fixed16_t u;
+ fixed16_t u_step;
+ struct edge_s *prev, *next;
+ unsigned short surfs[2];
+ struct edge_s *nextremove;
+ float nearzi;
+ medge_t *owner;
+} edge_t;
+
+#endif // _R_SHARED_H_
+
+#endif // GLQUAKE
diff --git a/WinQuake/snd_dma.c b/WinQuake/snd_dma.c
index adb5504..f0bd51b 100644
--- a/WinQuake/snd_dma.c
+++ b/WinQuake/snd_dma.c
@@ -1,1028 +1,1028 @@
-/*
-Copyright (C) 1996-1997 Id Software, Inc.
-
-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.
-
-*/
-// snd_dma.c -- main control for any streaming sound output device
-
-#include "quakedef.h"
-
-#ifdef _WIN32
-#include "winquake.h"
-#endif
-
-void S_Play(void);
-void S_PlayVol(void);
-void S_SoundList(void);
-void S_Update_();
-void S_StopAllSounds(qboolean clear);
-void S_StopAllSoundsC(void);
-
-// =======================================================================
-// Internal sound data & structures
-// =======================================================================
-
-channel_t channels[MAX_CHANNELS];
-int total_channels;
-
-int snd_blocked = 0;
-static qboolean snd_ambient = 1;
-qboolean snd_initialized = false;
-
-// pointer should go away
-volatile dma_t *shm = 0;
-volatile dma_t sn;
-
-vec3_t listener_origin;
-vec3_t listener_forward;
-vec3_t listener_right;
-vec3_t listener_up;
-vec_t sound_nominal_clip_dist=1000.0;
-
-int soundtime; // sample PAIRS
-int paintedtime; // sample PAIRS
-
-
-#define MAX_SFX 512
-sfx_t *known_sfx; // hunk allocated [MAX_SFX]
-int num_sfx;
-
-sfx_t *ambient_sfx[NUM_AMBIENTS];
-
-int desired_speed = 11025;
-int desired_bits = 16;
-
-int sound_started=0;
-
-cvar_t bgmvolume = {"bgmvolume", "1", true};
-cvar_t volume = {"volume", "0.7", true};
-
-cvar_t nosound = {"nosound", "0"};
-cvar_t precache = {"precache", "1"};
-cvar_t loadas8bit = {"loadas8bit", "0"};
-/* for sdl */
-#if defined(USE_SDL2)
-cvar_t sndspeed = {"sndspeed", "11025", CVAR_NONE};
-cvar_t snd_mixspeed = {"snd_mixspeed", "44100", CVAR_NONE};
-#endif
-cvar_t bgmbuffer = {"bgmbuffer", "4096"};
-cvar_t ambient_level = {"ambient_level", "0.3"};
-cvar_t ambient_fade = {"ambient_fade", "100"};
-cvar_t snd_noextraupdate = {"snd_noextraupdate", "0"};
-cvar_t snd_show = {"snd_show", "0"};
-cvar_t _snd_mixahead = {"_snd_mixahead", "0.1", true};
-
-
-// ====================================================================
-// User-setable variables
-// ====================================================================
-
-
-//
-// Fake dma is a synchronous faking of the DMA progress used for
-// isolating performance in the renderer. The fakedma_updates is
-// number of times S_Update() is called per second.
-//
-
-qboolean fakedma = false;
-int fakedma_updates = 15;
-
-
-void S_AmbientOff (void)
-{
- snd_ambient = false;
-}
-
-
-void S_AmbientOn (void)
-{
- snd_ambient = true;
-}
-
-
-void S_SoundInfo_f(void)
-{
- if (!sound_started || !shm)
- {
- Con_Printf ("sound system not started\n");
- return;
- }
-
- Con_Printf("%5d stereo\n", shm->channels - 1);
- Con_Printf("%5d samples\n", shm->samples);
- Con_Printf("%5d samplepos\n", shm->samplepos);
- Con_Printf("%5d samplebits\n", shm->samplebits);
- Con_Printf("%5d submission_chunk\n", shm->submission_chunk);
- Con_Printf("%5d speed\n", shm->speed);
- Con_Printf("0x%x dma buffer\n", shm->buffer);
- Con_Printf("%5d total_channels\n", total_channels);
-}
-
-
-/*
-================
-S_Startup
-================
-*/
-
-void S_Startup (void)
-{
- int rc;
-
- if (!snd_initialized)
- return;
-
- if (!fakedma)
- {
-#if defined(USE_SDL2)
- /* Since I borrowed a lot of the SDL2 code from Quakespasm, I
- found this to be the easiest way to retrofit it: */
- rc = SNDDMA_Init(&sn);
-#else
- /* in the original code from Id, no argument is used here: */
- rc = SNDDMA_Init();
-#endif
- if (!rc)
- {
-#ifndef _WIN32
- Con_Printf("S_Startup: SNDDMA_Init failed.\n");
-#endif
- sound_started = 0;
- return;
- }
- }
-
- sound_started = 1;
-}
-
-
-/*
-================
-S_Init
-================
-*/
-void S_Init (void)
-{
-
- Con_Printf("\nSound Initialization\n");
-
- if (COM_CheckParm("-nosound"))
- return;
-
- if (COM_CheckParm("-simsound"))
- fakedma = true;
-
- Cmd_AddCommand("play", S_Play);
- Cmd_AddCommand("playvol", S_PlayVol);
- Cmd_AddCommand("stopsound", S_StopAllSoundsC);
- Cmd_AddCommand("soundlist", S_SoundList);
- Cmd_AddCommand("soundinfo", S_SoundInfo_f);
-
- Cvar_RegisterVariable(&nosound);
- Cvar_RegisterVariable(&volume);
- Cvar_RegisterVariable(&precache);
- Cvar_RegisterVariable(&loadas8bit);
- Cvar_RegisterVariable(&bgmvolume);
- Cvar_RegisterVariable(&bgmbuffer);
- Cvar_RegisterVariable(&ambient_level);
- Cvar_RegisterVariable(&ambient_fade);
- Cvar_RegisterVariable(&snd_noextraupdate);
- Cvar_RegisterVariable(&snd_show);
- Cvar_RegisterVariable(&_snd_mixahead);
-
- if (host_parms.memsize < 0x800000)
- {
- Cvar_Set ("loadas8bit", "1");
- Con_Printf ("loading all sounds as 8bit\n");
- }
-
-
-
- snd_initialized = true;
-
- S_Startup ();
-
- SND_InitScaletable ();
-
- known_sfx = Hunk_AllocName (MAX_SFX*sizeof(sfx_t), "sfx_t");
- num_sfx = 0;
-
-// create a piece of DMA memory
-
- if (fakedma)
- {
- shm = (void *) Hunk_AllocName(sizeof(*shm), "shm");
- shm->splitbuffer = 0;
- shm->samplebits = 16;
- shm->speed = 22050;
- shm->channels = 2;
- shm->samples = 32768;
- shm->samplepos = 0;
- shm->soundalive = true;
- shm->gamealive = true;
- shm->submission_chunk = 1;
- shm->buffer = Hunk_AllocName(1<<16, "shmbuf");
- }
-
- Con_Printf ("Sound sampling rate: %i\n", shm->speed);
-
- // provides a tick sound until washed clean
-
-// if (shm->buffer)
-// shm->buffer[4] = shm->buffer[5] = 0x7f; // force a pop for debugging
-
- ambient_sfx[AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav");
- ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav");
-
- S_StopAllSounds (true);
-}
-
-
-// =======================================================================
-// Shutdown sound engine
-// =======================================================================
-
-void S_Shutdown(void)
-{
-
- if (!sound_started)
- return;
-
- if (shm)
- shm->gamealive = 0;
-
- shm = 0;
- sound_started = 0;
-
- if (!fakedma)
- {
- SNDDMA_Shutdown();
- }
-}
-
-
-// =======================================================================
-// Load a sound
-// =======================================================================
-
-/*
-==================
-S_FindName
-
-==================
-*/
-sfx_t *S_FindName (char *name)
-{
- int i;
- sfx_t *sfx;
-
- if (!name)
- Sys_Error ("S_FindName: NULL\n");
-
- if (Q_strlen(name) >= MAX_QPATH)
- Sys_Error ("Sound name too long: %s", name);
-
-// see if already loaded
- for (i=0 ; i < num_sfx ; i++)
- if (!Q_strcmp(known_sfx[i].name, name))
- {
- return &known_sfx[i];
- }
-
- if (num_sfx == MAX_SFX)
- Sys_Error ("S_FindName: out of sfx_t");
-
- sfx = &known_sfx[i];
- strcpy (sfx->name, name);
-
- num_sfx++;
-
- return sfx;
-}
-
-
-/*
-==================
-S_TouchSound
-
-==================
-*/
-void S_TouchSound (char *name)
-{
- sfx_t *sfx;
-
- if (!sound_started)
- return;
-
- sfx = S_FindName (name);
- Cache_Check (&sfx->cache);
-}
-
-/*
-==================
-S_PrecacheSound
-
-==================
-*/
-sfx_t *S_PrecacheSound (char *name)
-{
- sfx_t *sfx;
-
- if (!sound_started || nosound.value)
- return NULL;
-
- sfx = S_FindName (name);
-
-// cache it in
- if (precache.value)
- S_LoadSound (sfx);
-
- return sfx;
-}
-
-
-//=============================================================================
-
-/*
-=================
-SND_PickChannel
-=================
-*/
-channel_t *SND_PickChannel(int entnum, int entchannel)
-{
- int ch_idx;
- int first_to_die;
- int life_left;
-
-// Check for replacement sound, or find the best one to replace
- first_to_die = -1;
- life_left = 0x7fffffff;
- for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++)
- {
- if (entchannel != 0 // channel 0 never overrides
- && channels[ch_idx].entnum == entnum
- && (channels[ch_idx].entchannel == entchannel || entchannel == -1) )
- { // allways override sound from same entity
- first_to_die = ch_idx;
- break;
- }
-
- // don't let monster sounds override player sounds
- if (channels[ch_idx].entnum == cl.viewentity && entnum != cl.viewentity && channels[ch_idx].sfx)
- continue;
-
- if (channels[ch_idx].end - paintedtime < life_left)
- {
- life_left = channels[ch_idx].end - paintedtime;
- first_to_die = ch_idx;
- }
- }
-
- if (first_to_die == -1)
- return NULL;
-
- if (channels[first_to_die].sfx)
- channels[first_to_die].sfx = NULL;
-
- return &channels[first_to_die];
-}
-
-/*
-=================
-SND_Spatialize
-=================
-*/
-void SND_Spatialize(channel_t *ch)
-{
- vec_t dot;
- vec_t ldist, rdist, dist;
- vec_t lscale, rscale, scale;
- vec3_t source_vec;
- sfx_t *snd;
-
-// anything coming from the view entity will allways be full volume
- if (ch->entnum == cl.viewentity)
- {
- ch->leftvol = ch->master_vol;
- ch->rightvol = ch->master_vol;
- return;
- }
-
-// calculate stereo seperation and distance attenuation
-
- snd = ch->sfx;
- VectorSubtract(ch->origin, listener_origin, source_vec);
-
- dist = VectorNormalize(source_vec) * ch->dist_mult;
-
- dot = DotProduct(listener_right, source_vec);
-
- if (shm->channels == 1)
- {
- rscale = 1.0;
- lscale = 1.0;
- }
- else
- {
- rscale = 1.0 + dot;
- lscale = 1.0 - dot;
- }
-
-// add in distance effect
- scale = (1.0 - dist) * rscale;
- ch->rightvol = (int) (ch->master_vol * scale);
- if (ch->rightvol < 0)
- ch->rightvol = 0;
-
- scale = (1.0 - dist) * lscale;
- ch->leftvol = (int) (ch->master_vol * scale);
- if (ch->leftvol < 0)
- ch->leftvol = 0;
-}
-
-
-// =======================================================================
-// Start a sound effect
-// =======================================================================
-
-void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation)
-{
- channel_t *target_chan, *check;
- sfxcache_t *sc;
- int vol;
- int ch_idx;
- int skip;
-
- if (!sound_started)
- return;
-
- if (!sfx)
- return;
-
- if (nosound.value)
- return;
-
- vol = fvol*255;
-
-// pick a channel to play on
- target_chan = SND_PickChannel(entnum, entchannel);
- if (!target_chan)
- return;
-
-// spatialize
- memset (target_chan, 0, sizeof(*target_chan));
- VectorCopy(origin, target_chan->origin);
- target_chan->dist_mult = attenuation / sound_nominal_clip_dist;
- target_chan->master_vol = vol;
- target_chan->entnum = entnum;
- target_chan->entchannel = entchannel;
- SND_Spatialize(target_chan);
-
- if (!target_chan->leftvol && !target_chan->rightvol)
- return; // not audible at all
-
-// new channel
- sc = S_LoadSound (sfx);
- if (!sc)
- {
- target_chan->sfx = NULL;
- return; // couldn't load the sound's data
- }
-
- target_chan->sfx = sfx;
- target_chan->pos = 0.0;
- target_chan->end = paintedtime + sc->length;
-
-// if an identical sound has also been started this frame, offset the pos
-// a bit to keep it from just making the first one louder
- check = &channels[NUM_AMBIENTS];
- for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++, check++)
- {
- if (check == target_chan)
- continue;
- if (check->sfx == sfx && !check->pos)
- {
- skip = rand () % (int)(0.1*shm->speed);
- if (skip >= target_chan->end)
- skip = target_chan->end - 1;
- target_chan->pos += skip;
- target_chan->end -= skip;
- break;
- }
-
- }
-}
-
-void S_StopSound(int entnum, int entchannel)
-{
- int i;
-
- for (i=0 ; i<MAX_DYNAMIC_CHANNELS ; i++)
- {
- if (channels[i].entnum == entnum
- && channels[i].entchannel == entchannel)
- {
- channels[i].end = 0;
- channels[i].sfx = NULL;
- return;
- }
- }
-}
-
-void S_StopAllSounds(qboolean clear)
-{
- int i;
-
- if (!sound_started)
- return;
-
- total_channels = MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS; // no statics
-
- for (i=0 ; i<MAX_CHANNELS ; i++)
- if (channels[i].sfx)
- channels[i].sfx = NULL;
-
- Q_memset(channels, 0, MAX_CHANNELS * sizeof(channel_t));
-
- if (clear)
- S_ClearBuffer ();
-}
-
-void S_StopAllSoundsC (void)
-{
- S_StopAllSounds (true);
-}
-
-void S_ClearBuffer (void)
-{
- int clear;
-
-#ifdef _WIN32
- if (!sound_started || !shm || (!shm->buffer && !pDSBuf))
-#else
- if (!sound_started || !shm || !shm->buffer)
-#endif
- return;
-
- if (shm->samplebits == 8)
- clear = 0x80;
- else
- clear = 0;
-
-#ifdef _WIN32
- if (pDSBuf)
- {
- DWORD dwSize;
- DWORD *pData;
- int reps;
- HRESULT hresult;
-
- reps = 0;
-
- while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pData, &dwSize, NULL, NULL, 0)) != DS_OK)
- {
- if (hresult != DSERR_BUFFERLOST)
- {
- Con_Printf ("S_ClearBuffer: DS::Lock Sound Buffer Failed\n");
- S_Shutdown ();
- return;
- }
-
- if (++reps > 10000)
- {
- Con_Printf ("S_ClearBuffer: DS: couldn't restore buffer\n");
- S_Shutdown ();
- return;
- }
- }
-
- Q_memset(pData, clear, shm->samples * shm->samplebits/8);
-
- pDSBuf->lpVtbl->Unlock(pDSBuf, pData, dwSize, NULL, 0);
-
- }
- else
-#endif
- {
- Q_memset(shm->buffer, clear, shm->samples * shm->samplebits/8);
- }
-}
-
-
-/*
-=================
-S_StaticSound
-=================
-*/
-void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation)
-{
- channel_t *ss;
- sfxcache_t *sc;
-
- if (!sfx)
- return;
-
- if (total_channels == MAX_CHANNELS)
- {
- Con_Printf ("total_channels == MAX_CHANNELS\n");
- return;
- }
-
- ss = &channels[total_channels];
- total_channels++;
-
- sc = S_LoadSound (sfx);
- if (!sc)
- return;
-
- if (sc->loopstart == -1)
- {
- Con_Printf ("Sound %s not looped\n", sfx->name);
- return;
- }
-
- ss->sfx = sfx;
- VectorCopy (origin, ss->origin);
- ss->master_vol = vol;
- ss->dist_mult = (attenuation/64) / sound_nominal_clip_dist;
- ss->end = paintedtime + sc->length;
-
- SND_Spatialize (ss);
-}
-
-
-//=============================================================================
-
-/*
-===================
-S_UpdateAmbientSounds
-===================
-*/
-void S_UpdateAmbientSounds (void)
-{
- mleaf_t *l;
- float vol;
- int ambient_channel;
- channel_t *chan;
-
- if (!snd_ambient)
- return;
-
-// calc ambient sound levels
- if (!cl.worldmodel)
- return;
-
- l = Mod_PointInLeaf (listener_origin, cl.worldmodel);
- if (!l || !ambient_level.value)
- {
- for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++)
- channels[ambient_channel].sfx = NULL;
- return;
- }
-
- for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++)
- {
- chan = &channels[ambient_channel];
- chan->sfx = ambient_sfx[ambient_channel];
-
- vol = ambient_level.value * l->ambient_sound_level[ambient_channel];
- if (vol < 8)
- vol = 0;
-
- // don't adjust volume too fast
- if (chan->master_vol < vol)
- {
- chan->master_vol += host_frametime * ambient_fade.value;
- if (chan->master_vol > vol)
- chan->master_vol = vol;
- }
- else if (chan->master_vol > vol)
- {
- chan->master_vol -= host_frametime * ambient_fade.value;
- if (chan->master_vol < vol)
- chan->master_vol = vol;
- }
-
- chan->leftvol = chan->rightvol = chan->master_vol;
- }
-}
-
-
-/*
-============
-S_Update
-
-Called once each time through the main loop
-============
-*/
-void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
-{
- int i, j;
- int total;
- channel_t *ch;
- channel_t *combine;
-
- if (!sound_started || (snd_blocked > 0))
- return;
-
- VectorCopy(origin, listener_origin);
- VectorCopy(forward, listener_forward);
- VectorCopy(right, listener_right);
- VectorCopy(up, listener_up);
-
-// update general area ambient sound sources
- S_UpdateAmbientSounds ();
-
- combine = NULL;
-
-// update spatialization for static and dynamic sounds
- ch = channels+NUM_AMBIENTS;
- for (i=NUM_AMBIENTS ; i<total_channels; i++, ch++)
- {
- if (!ch->sfx)
- continue;
- SND_Spatialize(ch); // respatialize channel
- if (!ch->leftvol && !ch->rightvol)
- continue;
-
- // try to combine static sounds with a previous channel of the same
- // sound effect so we don't mix five torches every frame
-
- if (i >= MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS)
- {
- // see if it can just use the last one
- if (combine && combine->sfx == ch->sfx)
- {
- combine->leftvol += ch->leftvol;
- combine->rightvol += ch->rightvol;
- ch->leftvol = ch->rightvol = 0;
- continue;
- }
- // search for one
- combine = channels+MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS;
- for (j=MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS ; j<i; j++, combine++)
- if (combine->sfx == ch->sfx)
- break;
-
- if (j == total_channels)
- {
- combine = NULL;
- }
- else
- {
- if (combine != ch)
- {
- combine->leftvol += ch->leftvol;
- combine->rightvol += ch->rightvol;
- ch->leftvol = ch->rightvol = 0;
- }
- continue;
- }
- }
-
-
- }
-
-//
-// debugging output
-//
- if (snd_show.value)
- {
- total = 0;
- ch = channels;
- for (i=0 ; i<total_channels; i++, ch++)
- if (ch->sfx && (ch->leftvol || ch->rightvol) )
- {
- //Con_Printf ("%3i %3i %s\n", ch->leftvol, ch->rightvol, ch->sfx->name);
- total++;
- }
-
- Con_Printf ("----(%i)----\n", total);
- }
-
-// mix some sound
- S_Update_();
-}
-
-void GetSoundtime(void)
-{
- int samplepos;
- static int buffers;
- static int oldsamplepos;
- int fullsamples;
-
- fullsamples = shm->samples / shm->channels;
-
-// it is possible to miscount buffers if it has wrapped twice between
-// calls to S_Update. Oh well.
-#ifdef __sun__
- soundtime = SNDDMA_GetSamples();
-#else
- samplepos = SNDDMA_GetDMAPos();
-
-
- if (samplepos < oldsamplepos)
- {
- buffers++; // buffer wrapped
-
- if (paintedtime > 0x40000000)
- { // time to chop things off to avoid 32 bit limits
- buffers = 0;
- paintedtime = fullsamples;
- S_StopAllSounds (true);
- }
- }
- oldsamplepos = samplepos;
-
- soundtime = buffers*fullsamples + samplepos/shm->channels;
-#endif
-}
-
-void S_ExtraUpdate (void)
-{
-
-#ifdef _WIN32
- IN_Accumulate ();
-#endif
-
- if (snd_noextraupdate.value)
- return; // don't pollute timings
- S_Update_();
-}
-
-void S_Update_(void)
-{
- unsigned endtime;
- int samps;
-
- if (!sound_started || (snd_blocked > 0))
- return;
-
-// Updates DMA time
- GetSoundtime();
-
-// check to make sure that we haven't overshot
- if (paintedtime < soundtime)
- {
- //Con_Printf ("S_Update_ : overflow\n");
- paintedtime = soundtime;
- }
-
-// mix ahead of current position
- endtime = soundtime + _snd_mixahead.value * shm->speed;
- samps = shm->samples >> (shm->channels-1);
- if (endtime - soundtime > samps)
- endtime = soundtime + samps;
-
-#ifdef _WIN32
-// if the buffer was lost or stopped, restore it and/or restart it
- {
- DWORD dwStatus;
-
- if (pDSBuf)
- {
- if (pDSBuf->lpVtbl->GetStatus (pDSBuf, &dwStatus) != DD_OK)
- Con_Printf ("Couldn't get sound buffer status\n");
-
- if (dwStatus & DSBSTATUS_BUFFERLOST)
- pDSBuf->lpVtbl->Restore (pDSBuf);
-
- if (!(dwStatus & DSBSTATUS_PLAYING))
- pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);
- }
- }
-#endif
-
- S_PaintChannels (endtime);
-
- SNDDMA_Submit ();
-}
-
-/*
-===============================================================================
-
-console functions
-
-===============================================================================
-*/
-
-void S_Play(void)
-{
- static int hash=345;
- int i;
- char name[256];
- sfx_t *sfx;
-
- i = 1;
- while (i<Cmd_Argc())
- {
- if (!Q_strrchr(Cmd_Argv(i), '.'))
- {
- Q_strcpy(name, Cmd_Argv(i));
- Q_strcat(name, ".wav");
- }
- else
- Q_strcpy(name, Cmd_Argv(i));
- sfx = S_PrecacheSound(name);
- S_StartSound(hash++, 0, sfx, listener_origin, 1.0, 1.0);
- i++;
- }
-}
-
-void S_PlayVol(void)
-{
- static int hash=543;
- int i;
- float vol;
- char name[256];
- sfx_t *sfx;
-
- i = 1;
- while (i<Cmd_Argc())
- {
- if (!Q_strrchr(Cmd_Argv(i), '.'))
- {
- Q_strcpy(name, Cmd_Argv(i));
- Q_strcat(name, ".wav");
- }
- else
- Q_strcpy(name, Cmd_Argv(i));
- sfx = S_PrecacheSound(name);
- vol = Q_atof(Cmd_Argv(i+1));
- S_StartSound(hash++, 0, sfx, listener_origin, vol, 1.0);
- i+=2;
- }
-}
-
-void S_SoundList(void)
-{
- int i;
- sfx_t *sfx;
- sfxcache_t *sc;
- int size, total;
-
- total = 0;
- for (sfx=known_sfx, i=0 ; i<num_sfx ; i++, sfx++)
- {
- sc = Cache_Check (&sfx->cache);
- if (!sc)
- continue;
- size = sc->length*sc->width*(sc->stereo+1);
- total += size;
- if (sc->loopstart >= 0)
- Con_Printf ("L");
- else
- Con_Printf (" ");
- Con_Printf("(%2db) %6i : %s\n",sc->width*8, size, sfx->name);
- }
- Con_Printf ("Total resident: %i\n", total);
-}
-
-
-void S_LocalSound (char *sound)
-{
- sfx_t *sfx;
-
- if (nosound.value)
- return;
- if (!sound_started)
- return;
-
- sfx = S_PrecacheSound (sound);
- if (!sfx)
- {
- Con_Printf ("S_LocalSound: can't cache %s\n", sound);
- return;
- }
- S_StartSound (cl.viewentity, -1, sfx, vec3_origin, 1, 1);
-}
-
-
-void S_ClearPrecache (void)
-{
-}
-
-
-void S_BeginPrecaching (void)
-{
-}
-
-
-void S_EndPrecaching (void)
-{
-}
-
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+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.
+
+*/
+// snd_dma.c -- main control for any streaming sound output device
+
+#include "quakedef.h"
+
+#ifdef _WIN32
+#include "winquake.h"
+#endif
+
+void S_Play(void);
+void S_PlayVol(void);
+void S_SoundList(void);
+void S_Update_();
+void S_StopAllSounds(qboolean clear);
+void S_StopAllSoundsC(void);
+
+// =======================================================================
+// Internal sound data & structures
+// =======================================================================
+
+channel_t channels[MAX_CHANNELS];
+int total_channels;
+
+int snd_blocked = 0;
+static qboolean snd_ambient = 1;
+qboolean snd_initialized = false;
+
+// pointer should go away
+volatile dma_t *shm = 0;
+volatile dma_t sn;
+
+vec3_t listener_origin;
+vec3_t listener_forward;
+vec3_t listener_right;
+vec3_t listener_up;
+vec_t sound_nominal_clip_dist=1000.0;
+
+int soundtime; // sample PAIRS
+int paintedtime; // sample PAIRS
+
+
+#define MAX_SFX 512
+sfx_t *known_sfx; // hunk allocated [MAX_SFX]
+int num_sfx;
+
+sfx_t *ambient_sfx[NUM_AMBIENTS];
+
+int desired_speed = 11025;
+int desired_bits = 16;
+
+int sound_started=0;
+
+cvar_t bgmvolume = {"bgmvolume", "1", true};
+cvar_t volume = {"volume", "0.7", true};
+
+cvar_t nosound = {"nosound", "0"};
+cvar_t precache = {"precache", "1"};
+cvar_t loadas8bit = {"loadas8bit", "0"};
+/* for sdl */
+#if defined(USE_SDL2)
+cvar_t sndspeed = {"sndspeed", "11025", CVAR_NONE};
+cvar_t snd_mixspeed = {"snd_mixspeed", "44100", CVAR_NONE};
+#endif
+cvar_t bgmbuffer = {"bgmbuffer", "4096"};
+cvar_t ambient_level = {"ambient_level", "0.3"};
+cvar_t ambient_fade = {"ambient_fade", "100"};
+cvar_t snd_noextraupdate = {"snd_noextraupdate", "0"};
+cvar_t snd_show = {"snd_show", "0"};
+cvar_t _snd_mixahead = {"_snd_mixahead", "0.1", true};
+
+
+// ====================================================================
+// User-setable variables
+// ====================================================================
+
+
+//
+// Fake dma is a synchronous faking of the DMA progress used for
+// isolating performance in the renderer. The fakedma_updates is
+// number of times S_Update() is called per second.
+//
+
+qboolean fakedma = false;
+int fakedma_updates = 15;
+
+
+void S_AmbientOff (void)
+{
+ snd_ambient = false;
+}
+
+
+void S_AmbientOn (void)
+{
+ snd_ambient = true;
+}
+
+
+void S_SoundInfo_f(void)
+{
+ if (!sound_started || !shm)
+ {
+ Con_Printf ("sound system not started\n");
+ return;
+ }
+
+ Con_Printf("%5d stereo\n", shm->channels - 1);
+ Con_Printf("%5d samples\n", shm->samples);
+ Con_Printf("%5d samplepos\n", shm->samplepos);
+ Con_Printf("%5d samplebits\n", shm->samplebits);
+ Con_Printf("%5d submission_chunk\n", shm->submission_chunk);
+ Con_Printf("%5d speed\n", shm->speed);
+ Con_Printf("0x%x dma buffer\n", shm->buffer);
+ Con_Printf("%5d total_channels\n", total_channels);
+}
+
+
+/*
+================
+S_Startup
+================
+*/
+
+void S_Startup (void)
+{
+ int rc;
+
+ if (!snd_initialized)
+ return;
+
+ if (!fakedma)
+ {
+#if defined(USE_SDL2)
+ /* Since I borrowed a lot of the SDL2 code from Quakespasm, I
+ found this to be the easiest way to retrofit it: */
+ rc = SNDDMA_Init(&sn);
+#else
+ /* in the original code from Id, no argument is used here: */
+ rc = SNDDMA_Init();
+#endif
+ if (!rc)
+ {
+#ifndef _WIN32
+ Con_Printf("S_Startup: SNDDMA_Init failed.\n");
+#endif
+ sound_started = 0;
+ return;
+ }
+ }
+
+ sound_started = 1;
+}
+
+
+/*
+================
+S_Init
+================
+*/
+void S_Init (void)
+{
+
+ Con_Printf("\nSound Initialization\n");
+
+ if (COM_CheckParm("-nosound"))
+ return;
+
+ if (COM_CheckParm("-simsound"))
+ fakedma = true;
+
+ Cmd_AddCommand("play", S_Play);
+ Cmd_AddCommand("playvol", S_PlayVol);
+ Cmd_AddCommand("stopsound", S_StopAllSoundsC);
+ Cmd_AddCommand("soundlist", S_SoundList);
+ Cmd_AddCommand("soundinfo", S_SoundInfo_f);
+
+ Cvar_RegisterVariable(&nosound);
+ Cvar_RegisterVariable(&volume);
+ Cvar_RegisterVariable(&precache);
+ Cvar_RegisterVariable(&loadas8bit);
+ Cvar_RegisterVariable(&bgmvolume);
+ Cvar_RegisterVariable(&bgmbuffer);
+ Cvar_RegisterVariable(&ambient_level);
+ Cvar_RegisterVariable(&ambient_fade);
+ Cvar_RegisterVariable(&snd_noextraupdate);
+ Cvar_RegisterVariable(&snd_show);
+ Cvar_RegisterVariable(&_snd_mixahead);
+
+ if (host_parms.memsize < 0x800000)
+ {
+ Cvar_Set ("loadas8bit", "1");
+ Con_Printf ("loading all sounds as 8bit\n");
+ }
+
+
+
+ snd_initialized = true;
+
+ S_Startup ();
+
+ SND_InitScaletable ();
+
+ known_sfx = Hunk_AllocName (MAX_SFX*sizeof(sfx_t), "sfx_t");
+ num_sfx = 0;
+
+// create a piece of DMA memory
+
+ if (fakedma)
+ {
+ shm = (void *) Hunk_AllocName(sizeof(*shm), "shm");
+ shm->splitbuffer = 0;
+ shm->samplebits = 16;
+ shm->speed = 22050;
+ shm->channels = 2;
+ shm->samples = 32768;
+ shm->samplepos = 0;
+ shm->soundalive = true;
+ shm->gamealive = true;
+ shm->submission_chunk = 1;
+ shm->buffer = Hunk_AllocName(1<<16, "shmbuf");
+ }
+
+ Con_Printf ("Sound sampling rate: %i\n", shm->speed);
+
+ // provides a tick sound until washed clean
+
+// if (shm->buffer)
+// shm->buffer[4] = shm->buffer[5] = 0x7f; // force a pop for debugging
+
+ ambient_sfx[AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav");
+ ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav");
+
+ S_StopAllSounds (true);
+}
+
+
+// =======================================================================
+// Shutdown sound engine
+// =======================================================================
+
+void S_Shutdown(void)
+{
+
+ if (!sound_started)
+ return;
+
+ if (shm)
+ shm->gamealive = 0;
+
+ shm = 0;
+ sound_started = 0;
+
+ if (!fakedma)
+ {
+ SNDDMA_Shutdown();
+ }
+}
+
+
+// =======================================================================
+// Load a sound
+// =======================================================================
+
+/*
+==================
+S_FindName
+
+==================
+*/
+sfx_t *S_FindName (char *name)
+{
+ int i;
+ sfx_t *sfx;
+
+ if (!name)
+ Sys_Error ("S_FindName: NULL\n");
+
+ if (Q_strlen(name) >= MAX_QPATH)
+ Sys_Error ("Sound name too long: %s", name);
+
+// see if already loaded
+ for (i=0 ; i < num_sfx ; i++)
+ if (!Q_strcmp(known_sfx[i].name, name))
+ {
+ return &known_sfx[i];
+ }
+
+ if (num_sfx == MAX_SFX)
+ Sys_Error ("S_FindName: out of sfx_t");
+
+ sfx = &known_sfx[i];
+ strcpy (sfx->name, name);
+
+ num_sfx++;
+
+ return sfx;
+}
+
+
+/*
+==================
+S_TouchSound
+
+==================
+*/
+void S_TouchSound (char *name)
+{
+ sfx_t *sfx;
+
+ if (!sound_started)
+ return;
+
+ sfx = S_FindName (name);
+ Cache_Check (&sfx->cache);
+}
+
+/*
+==================
+S_PrecacheSound
+
+==================
+*/
+sfx_t *S_PrecacheSound (char *name)
+{
+ sfx_t *sfx;
+
+ if (!sound_started || nosound.value)
+ return NULL;
+
+ sfx = S_FindName (name);
+
+// cache it in
+ if (precache.value)
+ S_LoadSound (sfx);
+
+ return sfx;
+}
+
+
+//=============================================================================
+
+/*
+=================
+SND_PickChannel
+=================
+*/
+channel_t *SND_PickChannel(int entnum, int entchannel)
+{
+ int ch_idx;
+ int first_to_die;
+ int life_left;
+
+// Check for replacement sound, or find the best one to replace
+ first_to_die = -1;
+ life_left = 0x7fffffff;
+ for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++)
+ {
+ if (entchannel != 0 // channel 0 never overrides
+ && channels[ch_idx].entnum == entnum
+ && (channels[ch_idx].entchannel == entchannel || entchannel == -1) )
+ { // allways override sound from same entity
+ first_to_die = ch_idx;
+ break;
+ }
+
+ // don't let monster sounds override player sounds
+ if (channels[ch_idx].entnum == cl.viewentity && entnum != cl.viewentity && channels[ch_idx].sfx)
+ continue;
+
+ if (channels[ch_idx].end - paintedtime < life_left)
+ {
+ life_left = channels[ch_idx].end - paintedtime;
+ first_to_die = ch_idx;
+ }
+ }
+
+ if (first_to_die == -1)
+ return NULL;
+
+ if (channels[first_to_die].sfx)
+ channels[first_to_die].sfx = NULL;
+
+ return &channels[first_to_die];
+}
+
+/*
+=================
+SND_Spatialize
+=================
+*/
+void SND_Spatialize(channel_t *ch)
+{
+ vec_t dot;
+ vec_t ldist, rdist, dist;
+ vec_t lscale, rscale, scale;
+ vec3_t source_vec;
+ sfx_t *snd;
+
+// anything coming from the view entity will allways be full volume
+ if (ch->entnum == cl.viewentity)
+ {
+ ch->leftvol = ch->master_vol;
+ ch->rightvol = ch->master_vol;
+ return;
+ }
+
+// calculate stereo seperation and distance attenuation
+
+ snd = ch->sfx;
+ VectorSubtract(ch->origin, listener_origin, source_vec);
+
+ dist = VectorNormalize(source_vec) * ch->dist_mult;
+
+ dot = DotProduct(listener_right, source_vec);
+
+ if (shm->channels == 1)
+ {
+ rscale = 1.0;
+ lscale = 1.0;
+ }
+ else
+ {
+ rscale = 1.0 + dot;
+ lscale = 1.0 - dot;
+ }
+
+// add in distance effect
+ scale = (1.0 - dist) * rscale;
+ ch->rightvol = (int) (ch->master_vol * scale);
+ if (ch->rightvol < 0)
+ ch->rightvol = 0;
+
+ scale = (1.0 - dist) * lscale;
+ ch->leftvol = (int) (ch->master_vol * scale);
+ if (ch->leftvol < 0)
+ ch->leftvol = 0;
+}
+
+
+// =======================================================================
+// Start a sound effect
+// =======================================================================
+
+void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation)
+{
+ channel_t *target_chan, *check;
+ sfxcache_t *sc;
+ int vol;
+ int ch_idx;
+ int skip;
+
+ if (!sound_started)
+ return;
+
+ if (!sfx)
+ return;
+
+ if (nosound.value)
+ return;
+
+ vol = fvol*255;
+
+// pick a channel to play on
+ target_chan = SND_PickChannel(entnum, entchannel);
+ if (!target_chan)
+ return;
+
+// spatialize
+ memset (target_chan, 0, sizeof(*target_chan));
+ VectorCopy(origin, target_chan->origin);
+ target_chan->dist_mult = attenuation / sound_nominal_clip_dist;
+ target_chan->master_vol = vol;
+ target_chan->entnum = entnum;
+ target_chan->entchannel = entchannel;
+ SND_Spatialize(target_chan);
+
+ if (!target_chan->leftvol && !target_chan->rightvol)
+ return; // not audible at all
+
+// new channel
+ sc = S_LoadSound (sfx);
+ if (!sc)
+ {
+ target_chan->sfx = NULL;
+ return; // couldn't load the sound's data
+ }
+
+ target_chan->sfx = sfx;
+ target_chan->pos = 0.0;
+ target_chan->end = paintedtime + sc->length;
+
+// if an identical sound has also been started this frame, offset the pos
+// a bit to keep it from just making the first one louder
+ check = &channels[NUM_AMBIENTS];
+ for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++, check++)
+ {
+ if (check == target_chan)
+ continue;
+ if (check->sfx == sfx && !check->pos)
+ {
+ skip = rand () % (int)(0.1*shm->speed);
+ if (skip >= target_chan->end)
+ skip = target_chan->end - 1;
+ target_chan->pos += skip;
+ target_chan->end -= skip;
+ break;
+ }
+
+ }
+}
+
+void S_StopSound(int entnum, int entchannel)
+{
+ int i;
+
+ for (i=0 ; i<MAX_DYNAMIC_CHANNELS ; i++)
+ {
+ if (channels[i].entnum == entnum
+ && channels[i].entchannel == entchannel)
+ {
+ channels[i].end = 0;
+ channels[i].sfx = NULL;
+ return;
+ }
+ }
+}
+
+void S_StopAllSounds(qboolean clear)
+{
+ int i;
+
+ if (!sound_started)
+ return;
+
+ total_channels = MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS; // no statics
+
+ for (i=0 ; i<MAX_CHANNELS ; i++)
+ if (channels[i].sfx)
+ channels[i].sfx = NULL;
+
+ Q_memset(channels, 0, MAX_CHANNELS * sizeof(channel_t));
+
+ if (clear)
+ S_ClearBuffer ();
+}
+
+void S_StopAllSoundsC (void)
+{
+ S_StopAllSounds (true);
+}
+
+void S_ClearBuffer (void)
+{
+ int clear;
+
+#ifdef _WIN32
+ if (!sound_started || !shm || (!shm->buffer && !pDSBuf))
+#else
+ if (!sound_started || !shm || !shm->buffer)
+#endif
+ return;
+
+ if (shm->samplebits == 8)
+ clear = 0x80;
+ else
+ clear = 0;
+
+#ifdef _WIN32
+ if (pDSBuf)
+ {
+ DWORD dwSize;
+ DWORD *pData;
+ int reps;
+ HRESULT hresult;
+
+ reps = 0;
+
+ while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pData, &dwSize, NULL, NULL, 0)) != DS_OK)
+ {
+ if (hresult != DSERR_BUFFERLOST)
+ {
+ Con_Printf ("S_ClearBuffer: DS::Lock Sound Buffer Failed\n");
+ S_Shutdown ();
+ return;
+ }
+
+ if (++reps > 10000)
+ {
+ Con_Printf ("S_ClearBuffer: DS: couldn't restore buffer\n");
+ S_Shutdown ();
+ return;
+ }
+ }
+
+ Q_memset(pData, clear, shm->samples * shm->samplebits/8);
+
+ pDSBuf->lpVtbl->Unlock(pDSBuf, pData, dwSize, NULL, 0);
+
+ }
+ else
+#endif
+ {
+ Q_memset(shm->buffer, clear, shm->samples * shm->samplebits/8);
+ }
+}
+
+
+/*
+=================
+S_StaticSound
+=================
+*/
+void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation)
+{
+ channel_t *ss;
+ sfxcache_t *sc;
+
+ if (!sfx)
+ return;
+
+ if (total_channels == MAX_CHANNELS)
+ {
+ Con_Printf ("total_channels == MAX_CHANNELS\n");
+ return;
+ }
+
+ ss = &channels[total_channels];
+ total_channels++;
+
+ sc = S_LoadSound (sfx);
+ if (!sc)
+ return;
+
+ if (sc->loopstart == -1)
+ {
+ Con_Printf ("Sound %s not looped\n", sfx->name);
+ return;
+ }
+
+ ss->sfx = sfx;
+ VectorCopy (origin, ss->origin);
+ ss->master_vol = vol;
+ ss->dist_mult = (attenuation/64) / sound_nominal_clip_dist;
+ ss->end = paintedtime + sc->length;
+
+ SND_Spatialize (ss);
+}
+
+
+//=============================================================================
+
+/*
+===================
+S_UpdateAmbientSounds
+===================
+*/
+void S_UpdateAmbientSounds (void)
+{
+ mleaf_t *l;
+ float vol;
+ int ambient_channel;
+ channel_t *chan;
+
+ if (!snd_ambient)
+ return;
+
+// calc ambient sound levels
+ if (!cl.worldmodel)
+ return;
+
+ l = Mod_PointInLeaf (listener_origin, cl.worldmodel);
+ if (!l || !ambient_level.value)
+ {
+ for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++)
+ channels[ambient_channel].sfx = NULL;
+ return;
+ }
+
+ for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++)
+ {
+ chan = &channels[ambient_channel];
+ chan->sfx = ambient_sfx[ambient_channel];
+
+ vol = ambient_level.value * l->ambient_sound_level[ambient_channel];
+ if (vol < 8)
+ vol = 0;
+
+ // don't adjust volume too fast
+ if (chan->master_vol < vol)
+ {
+ chan->master_vol += host_frametime * ambient_fade.value;
+ if (chan->master_vol > vol)
+ chan->master_vol = vol;
+ }
+ else if (chan->master_vol > vol)
+ {
+ chan->master_vol -= host_frametime * ambient_fade.value;
+ if (chan->master_vol < vol)
+ chan->master_vol = vol;
+ }
+
+ chan->leftvol = chan->rightvol = chan->master_vol;
+ }
+}
+
+
+/*
+============
+S_Update
+
+Called once each time through the main loop
+============
+*/
+void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
+{
+ int i, j;
+ int total;
+ channel_t *ch;
+ channel_t *combine;
+
+ if (!sound_started || (snd_blocked > 0))
+ return;
+
+ VectorCopy(origin, listener_origin);
+ VectorCopy(forward, listener_forward);
+ VectorCopy(right, listener_right);
+ VectorCopy(up, listener_up);
+
+// update general area ambient sound sources
+ S_UpdateAmbientSounds ();
+
+ combine = NULL;
+
+// update spatialization for static and dynamic sounds
+ ch = channels+NUM_AMBIENTS;
+ for (i=NUM_AMBIENTS ; i<total_channels; i++, ch++)
+ {
+ if (!ch->sfx)
+ continue;
+ SND_Spatialize(ch); // respatialize channel
+ if (!ch->leftvol && !ch->rightvol)
+ continue;
+
+ // try to combine static sounds with a previous channel of the same
+ // sound effect so we don't mix five torches every frame
+
+ if (i >= MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS)
+ {
+ // see if it can just use the last one
+ if (combine && combine->sfx == ch->sfx)
+ {
+ combine->leftvol += ch->leftvol;
+ combine->rightvol += ch->rightvol;
+ ch->leftvol = ch->rightvol = 0;
+ continue;
+ }
+ // search for one
+ combine = channels+MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS;
+ for (j=MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS ; j<i; j++, combine++)
+ if (combine->sfx == ch->sfx)
+ break;
+
+ if (j == total_channels)
+ {
+ combine = NULL;
+ }
+ else
+ {
+ if (combine != ch)
+ {
+ combine->leftvol += ch->leftvol;
+ combine->rightvol += ch->rightvol;
+ ch->leftvol = ch->rightvol = 0;
+ }
+ continue;
+ }
+ }
+
+
+ }
+
+//
+// debugging output
+//
+ if (snd_show.value)
+ {
+ total = 0;
+ ch = channels;
+ for (i=0 ; i<total_channels; i++, ch++)
+ if (ch->sfx && (ch->leftvol || ch->rightvol) )
+ {
+ //Con_Printf ("%3i %3i %s\n", ch->leftvol, ch->rightvol, ch->sfx->name);
+ total++;
+ }
+
+ Con_Printf ("----(%i)----\n", total);
+ }
+
+// mix some sound
+ S_Update_();
+}
+
+void GetSoundtime(void)
+{
+ int samplepos;
+ static int buffers;
+ static int oldsamplepos;
+ int fullsamples;
+
+ fullsamples = shm->samples / shm->channels;
+
+// it is possible to miscount buffers if it has wrapped twice between
+// calls to S_Update. Oh well.
+#ifdef __sun__
+ soundtime = SNDDMA_GetSamples();
+#else
+ samplepos = SNDDMA_GetDMAPos();
+
+
+ if (samplepos < oldsamplepos)
+ {
+ buffers++; // buffer wrapped
+
+ if (paintedtime > 0x40000000)
+ { // time to chop things off to avoid 32 bit limits
+ buffers = 0;
+ paintedtime = fullsamples;
+ S_StopAllSounds (true);
+ }
+ }
+ oldsamplepos = samplepos;
+
+ soundtime = buffers*fullsamples + samplepos/shm->channels;
+#endif
+}
+
+void S_ExtraUpdate (void)
+{
+
+#ifdef _WIN32
+ IN_Accumulate ();
+#endif
+
+ if (snd_noextraupdate.value)
+ return; // don't pollute timings
+ S_Update_();
+}
+
+void S_Update_(void)
+{
+ unsigned endtime;
+ int samps;
+
+ if (!sound_started || (snd_blocked > 0))
+ return;
+
+// Updates DMA time
+ GetSoundtime();
+
+// check to make sure that we haven't overshot
+ if (paintedtime < soundtime)
+ {
+ //Con_Printf ("S_Update_ : overflow\n");
+ paintedtime = soundtime;
+ }
+
+// mix ahead of current position
+ endtime = soundtime + _snd_mixahead.value * shm->speed;
+ samps = shm->samples >> (shm->channels-1);
+ if (endtime - soundtime > samps)
+ endtime = soundtime + samps;
+
+#ifdef _WIN32
+// if the buffer was lost or stopped, restore it and/or restart it
+ {
+ DWORD dwStatus;
+
+ if (pDSBuf)
+ {
+ if (pDSBuf->lpVtbl->GetStatus (pDSBuf, &dwStatus) != DD_OK)
+ Con_Printf ("Couldn't get sound buffer status\n");
+
+ if (dwStatus & DSBSTATUS_BUFFERLOST)
+ pDSBuf->lpVtbl->Restore (pDSBuf);
+
+ if (!(dwStatus & DSBSTATUS_PLAYING))
+ pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);
+ }
+ }
+#endif
+
+ S_PaintChannels (endtime);
+
+ SNDDMA_Submit ();
+}
+
+/*
+===============================================================================
+
+console functions
+
+===============================================================================
+*/
+
+void S_Play(void)
+{
+ static int hash=345;
+ int i;
+ char name[256];
+ sfx_t *sfx;
+
+ i = 1;
+ while (i<Cmd_Argc())
+ {
+ if (!Q_strrchr(Cmd_Argv(i), '.'))
+ {
+ Q_strcpy(name, Cmd_Argv(i));
+ Q_strcat(name, ".wav");
+ }
+ else
+ Q_strcpy(name, Cmd_Argv(i));
+ sfx = S_PrecacheSound(name);
+ S_StartSound(hash++, 0, sfx, listener_origin, 1.0, 1.0);
+ i++;
+ }
+}
+
+void S_PlayVol(void)
+{
+ static int hash=543;
+ int i;
+ float vol;
+ char name[256];
+ sfx_t *sfx;
+
+ i = 1;
+ while (i<Cmd_Argc())
+ {
+ if (!Q_strrchr(Cmd_Argv(i), '.'))
+ {
+ Q_strcpy(name, Cmd_Argv(i));
+ Q_strcat(name, ".wav");
+ }
+ else
+ Q_strcpy(name, Cmd_Argv(i));
+ sfx = S_PrecacheSound(name);
+ vol = Q_atof(Cmd_Argv(i+1));
+ S_StartSound(hash++, 0, sfx, listener_origin, vol, 1.0);
+ i+=2;
+ }
+}
+
+void S_SoundList(void)
+{
+ int i;
+ sfx_t *sfx;
+ sfxcache_t *sc;
+ int size, total;
+
+ total = 0;
+ for (sfx=known_sfx, i=0 ; i<num_sfx ; i++, sfx++)
+ {
+ sc = Cache_Check (&sfx->cache);
+ if (!sc)
+ continue;
+ size = sc->length*sc->width*(sc->stereo+1);
+ total += size;
+ if (sc->loopstart >= 0)
+ Con_Printf ("L");
+ else
+ Con_Printf (" ");
+ Con_Printf("(%2db) %6i : %s\n",sc->width*8, size, sfx->name);
+ }
+ Con_Printf ("Total resident: %i\n", total);
+}
+
+
+void S_LocalSound (char *sound)
+{
+ sfx_t *sfx;
+
+ if (nosound.value)
+ return;
+ if (!sound_started)
+ return;
+
+ sfx = S_PrecacheSound (sound);
+ if (!sfx)
+ {
+ Con_Printf ("S_LocalSound: can't cache %s\n", sound);
+ return;
+ }
+ S_StartSound (cl.viewentity, -1, sfx, vec3_origin, 1, 1);
+}
+
+
+void S_ClearPrecache (void)
+{
+}
+
+
+void S_BeginPrecaching (void)
+{
+}
+
+
+void S_EndPrecaching (void)
+{
+}
+
diff --git a/WinQuake/sound.h b/WinQuake/sound.h
index f5e8b35..46a36a0 100644
--- a/WinQuake/sound.h
+++ b/WinQuake/sound.h
@@ -1,183 +1,183 @@
-/*
-Copyright (C) 1996-1997 Id Software, Inc.
-
-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.
-
-*/
-// sound.h -- client sound i/o functions
-
-#ifndef __SOUND__
-#define __SOUND__
-
-#define DEFAULT_SOUND_PACKET_VOLUME 255
-#define DEFAULT_SOUND_PACKET_ATTENUATION 1.0
-
-// !!! if this is changed, it much be changed in asm_i386.h too !!!
-typedef struct
-{
- int left;
- int right;
-} portable_samplepair_t;
-
-typedef struct sfx_s
-{
- char name[MAX_QPATH];
- cache_user_t cache;
-} sfx_t;
-
-// !!! if this is changed, it much be changed in asm_i386.h too !!!
-typedef struct
-{
- int length;
- int loopstart;
- int speed;
- int width;
- int stereo;
- byte data[1]; // variable sized
-} sfxcache_t;
-
-typedef struct
-{
- qboolean gamealive;
- qboolean soundalive;
- qboolean splitbuffer;
- int channels;
- int samples; // mono samples in buffer
- int submission_chunk; // don't mix less than this #
- int samplepos; // in mono samples
- int samplebits;
- int speed;
- unsigned char *buffer;
-} dma_t;
-
-// !!! if this is changed, it much be changed in asm_i386.h too !!!
-typedef struct
-{
- sfx_t *sfx; // sfx number
- int leftvol; // 0-255 volume
- int rightvol; // 0-255 volume
- int end; // end time in global paintsamples
- int pos; // sample position in sfx
- int looping; // where to loop, -1 = no looping
- int entnum; // to allow overriding a specific sound
- int entchannel; //
- vec3_t origin; // origin of sound effect
- vec_t dist_mult; // distance multiplier (attenuation/clipK)
- int master_vol; // 0-255 master volume
-} channel_t;
-
-typedef struct
-{
- int rate;
- int width;
- int channels;
- int loopstart;
- int samples;
- int dataofs; // chunk starts this many bytes from file start
-} wavinfo_t;
-
-void S_Init (void);
-void S_Startup (void);
-void S_Shutdown (void);
-void S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation);
-void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation);
-void S_StopSound (int entnum, int entchannel);
-void S_StopAllSounds(qboolean clear);
-void S_ClearBuffer (void);
-void S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up);
-void S_ExtraUpdate (void);
-
-sfx_t *S_PrecacheSound (char *sample);
-void S_TouchSound (char *sample);
-void S_ClearPrecache (void);
-void S_BeginPrecaching (void);
-void S_EndPrecaching (void);
-void S_PaintChannels(int endtime);
-void S_InitPaintChannels (void);
-
-// picks a channel based on priorities, empty slots, number of channels
-channel_t *SND_PickChannel(int entnum, int entchannel);
-
-// spatializes a channel
-void SND_Spatialize(channel_t *ch);
-
-// initializes cycling through a DMA buffer and returns information on it
-#if defined(USE_SDL2)
-/* Probably the easiest way to retrofit quakespasm's SDL2 audio code into
- Id Quake. */
-qboolean SNDDMA_Init(dma_t *dma);
-#else
-qboolean SNDDMA_Init(void);
-#endif
-
-// gets the current DMA position
-int SNDDMA_GetDMAPos(void);
-
-// shutdown the DMA xfer.
-void SNDDMA_Shutdown(void);
-
-// ====================================================================
-// User-setable variables
-// ====================================================================
-
-#define MAX_CHANNELS 128
-#define MAX_DYNAMIC_CHANNELS 8
-
-
-extern channel_t channels[MAX_CHANNELS];
-// 0 to MAX_DYNAMIC_CHANNELS-1 = normal entity sounds
-// MAX_DYNAMIC_CHANNELS to MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS -1 = water, etc
-// MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS to total_channels = static sounds
-
-extern int total_channels;
-
-//
-// Fake dma is a synchronous faking of the DMA progress used for
-// isolating performance in the renderer. The fakedma_updates is
-// number of times S_Update() is called per second.
-//
-
-extern qboolean fakedma;
-extern int fakedma_updates;
-extern int paintedtime;
-extern vec3_t listener_origin;
-extern vec3_t listener_forward;
-extern vec3_t listener_right;
-extern vec3_t listener_up;
-extern volatile dma_t *shm;
-extern volatile dma_t sn;
-extern vec_t sound_nominal_clip_dist;
-
-extern cvar_t loadas8bit;
-extern cvar_t bgmvolume;
-extern cvar_t volume;
-
-extern qboolean snd_initialized;
-
-extern int snd_blocked;
-
-void S_LocalSound (char *s);
-sfxcache_t *S_LoadSound (sfx_t *s);
-
-wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength);
-
-void SND_InitScaletable (void);
-void SNDDMA_Submit(void);
-
-void S_AmbientOff (void);
-void S_AmbientOn (void);
-
-#endif
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+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.
+
+*/
+// sound.h -- client sound i/o functions
+
+#ifndef __SOUND__
+#define __SOUND__
+
+#define DEFAULT_SOUND_PACKET_VOLUME 255
+#define DEFAULT_SOUND_PACKET_ATTENUATION 1.0
+
+// !!! if this is changed, it much be changed in asm_i386.h too !!!
+typedef struct
+{
+ int left;
+ int right;
+} portable_samplepair_t;
+
+typedef struct sfx_s
+{
+ char name[MAX_QPATH];
+ cache_user_t cache;
+} sfx_t;
+
+// !!! if this is changed, it much be changed in asm_i386.h too !!!
+typedef struct
+{
+ int length;
+ int loopstart;
+ int speed;
+ int width;
+ int stereo;
+ byte data[1]; // variable sized
+} sfxcache_t;
+
+typedef struct
+{
+ qboolean gamealive;
+ qboolean soundalive;
+ qboolean splitbuffer;
+ int channels;
+ int samples; // mono samples in buffer
+ int submission_chunk; // don't mix less than this #
+ int samplepos; // in mono samples
+ int samplebits;
+ int speed;
+ unsigned char *buffer;
+} dma_t;
+
+// !!! if this is changed, it much be changed in asm_i386.h too !!!
+typedef struct
+{
+ sfx_t *sfx; // sfx number
+ int leftvol; // 0-255 volume
+ int rightvol; // 0-255 volume
+ int end; // end time in global paintsamples
+ int pos; // sample position in sfx
+ int looping; // where to loop, -1 = no looping
+ int entnum; // to allow overriding a specific sound
+ int entchannel; //
+ vec3_t origin; // origin of sound effect
+ vec_t dist_mult; // distance multiplier (attenuation/clipK)
+ int master_vol; // 0-255 master volume
+} channel_t;
+
+typedef struct
+{
+ int rate;
+ int width;
+ int channels;
+ int loopstart;
+ int samples;
+ int dataofs; // chunk starts this many bytes from file start
+} wavinfo_t;
+
+void S_Init (void);
+void S_Startup (void);
+void S_Shutdown (void);
+void S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation);
+void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation);
+void S_StopSound (int entnum, int entchannel);
+void S_StopAllSounds(qboolean clear);
+void S_ClearBuffer (void);
+void S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up);
+void S_ExtraUpdate (void);
+
+sfx_t *S_PrecacheSound (char *sample);
+void S_TouchSound (char *sample);
+void S_ClearPrecache (void);
+void S_BeginPrecaching (void);
+void S_EndPrecaching (void);
+void S_PaintChannels(int endtime);
+void S_InitPaintChannels (void);
+
+// picks a channel based on priorities, empty slots, number of channels
+channel_t *SND_PickChannel(int entnum, int entchannel);
+
+// spatializes a channel
+void SND_Spatialize(channel_t *ch);
+
+// initializes cycling through a DMA buffer and returns information on it
+#if defined(USE_SDL2)
+/* Probably the easiest way to retrofit quakespasm's SDL2 audio code into
+ Id Quake. */
+qboolean SNDDMA_Init(dma_t *dma);
+#else
+qboolean SNDDMA_Init(void);
+#endif
+
+// gets the current DMA position
+int SNDDMA_GetDMAPos(void);
+
+// shutdown the DMA xfer.
+void SNDDMA_Shutdown(void);
+
+// ====================================================================
+// User-setable variables
+// ====================================================================
+
+#define MAX_CHANNELS 128
+#define MAX_DYNAMIC_CHANNELS 8
+
+
+extern channel_t channels[MAX_CHANNELS];
+// 0 to MAX_DYNAMIC_CHANNELS-1 = normal entity sounds
+// MAX_DYNAMIC_CHANNELS to MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS -1 = water, etc
+// MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS to total_channels = static sounds
+
+extern int total_channels;
+
+//
+// Fake dma is a synchronous faking of the DMA progress used for
+// isolating performance in the renderer. The fakedma_updates is
+// number of times S_Update() is called per second.
+//
+
+extern qboolean fakedma;
+extern int fakedma_updates;
+extern int paintedtime;
+extern vec3_t listener_origin;
+extern vec3_t listener_forward;
+extern vec3_t listener_right;
+extern vec3_t listener_up;
+extern volatile dma_t *shm;
+extern volatile dma_t sn;
+extern vec_t sound_nominal_clip_dist;
+
+extern cvar_t loadas8bit;
+extern cvar_t bgmvolume;
+extern cvar_t volume;
+
+extern qboolean snd_initialized;
+
+extern int snd_blocked;
+
+void S_LocalSound (char *s);
+sfxcache_t *S_LoadSound (sfx_t *s);
+
+wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength);
+
+void SND_InitScaletable (void);
+void SNDDMA_Submit(void);
+
+void S_AmbientOff (void);
+void S_AmbientOn (void);
+
+#endif