diff --git a/backup.lst b/backup.lst
index a6680914..8ad58c58 100644
--- a/backup.lst
+++ b/backup.lst
@@ -34,14 +34,15 @@ launch\imagelib\
launch\extragen\
physic\
public\
-render\
server\
server\ents\
server\game\
server\global\
server\monsters\
vprogs\
-vsound\
+snd_al\
+snd_dx\
+vid_gl\
xtools\
xtools\bsplib
xtools\ripper
diff --git a/baserc/baserc.plg b/baserc/baserc.plg
deleted file mode 100644
index a6b1f243..00000000
--- a/baserc/baserc.plg
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-Build Log
-
---------------------Configuration: baserc - Win32 Debug--------------------
-
-Command Lines
-
-
-
-Results
-baserc.dll - 0 error(s), 0 warning(s)
-
-
-
diff --git a/client/client.plg b/client/client.plg
deleted file mode 100644
index 33666b63..00000000
--- a/client/client.plg
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-Build Log
-
---------------------Configuration: client - Win32 Debug--------------------
-
-Command Lines
-
-
-
-Results
-client.dll - 0 error(s), 0 warning(s)
-
-
-
diff --git a/client/hud/hud_msg.cpp b/client/hud/hud_msg.cpp
index fc399912..1cee60e6 100644
--- a/client/hud/hud_msg.cpp
+++ b/client/hud/hud_msg.cpp
@@ -410,7 +410,23 @@ int CHud :: MsgFunc_RoomType( const char *pszName, int iSize, void *pbuf )
int CHud :: MsgFunc_ScreenFade( const char *pszName, int iSize, void *pbuf )
{
- // FIXME: implement
+ BEGIN_READ( pszName, iSize, pbuf );
+
+ float fadeTime = READ_SHORT() / (1<<12);
+ float holdTime = READ_SHORT() / (1<<12);
+ int fadeFlags = READ_SHORT();
+
+ Vector m_FadeColor;
+
+ m_FadeColor.x = READ_BYTE(); // fade red
+ m_FadeColor.y = READ_BYTE(); // fade green
+ m_FadeColor.z = READ_BYTE(); // fade blue
+ float alpha = READ_BYTE(); // fade alpha
+
+ SetScreenFade( m_FadeColor, alpha, fadeTime, holdTime, fadeFlags );
+
+ END_READ();
+
return 1;
}
diff --git a/debug.bat b/debug.bat
index 8bb7126a..9fef79df 100644
--- a/debug.bat
+++ b/debug.bat
@@ -23,7 +23,7 @@ if errorlevel 1 set BUILD_ERROR=1
%MSDEV% physic/physic.dsp %CONFIG%"physic - Win32 Debug" %build_target%
if errorlevel 1 set BUILD_ERROR=1
-%MSDEV% render/render.dsp %CONFIG%"render - Win32 Debug" %build_target%
+%MSDEV% vid_gl/vid_gl.dsp %CONFIG%"vid_gl - Win32 Debug" %build_target%
if errorlevel 1 set BUILD_ERROR=1
%MSDEV% server/server.dsp %CONFIG%"server - Win32 Debug" %build_target%
@@ -32,7 +32,10 @@ if errorlevel 1 set BUILD_ERROR=1
%MSDEV% vprogs/vprogs.dsp %CONFIG%"vprogs - Win32 Debug" %build_target%
if errorlevel 1 set BUILD_ERROR=1
-%MSDEV% vsound/vsound.dsp %CONFIG%"vsound - Win32 Debug" %build_target%
+%MSDEV% snd_al/snd_al.dsp %CONFIG%"snd_al - Win32 Debug" %build_target%
+if errorlevel 1 set BUILD_ERROR=1
+
+%MSDEV% snd_dx/snd_dx.dsp %CONFIG%"snd_dx - Win32 Debug" %build_target%
if errorlevel 1 set BUILD_ERROR=1
%MSDEV% xtools/xtools.dsp %CONFIG%"xtools - Win32 Debug" %build_target%
@@ -63,10 +66,11 @@ if exist engine\engine.plg del /f /q engine\engine.plg
if exist launch\launch.plg del /f /q launch\launch.plg
if exist physic\physic.plg del /f /q physic\physic.plg
if exist server\server.plg del /f /q server\server.plg
-if exist render\render.plg del /f /q render\render.plg
+if exist vid_gl\vid_gl.plg del /f /q vid_gl\vid_gl.plg
if exist viewer\viewer.plg del /f /q viewer\viewer.plg
if exist vprogs\vprogs.plg del /f /q vprogs\vprogs.plg
-if exist vsound\vsound.plg del /f /q vsound\vsound.plg
+if exist snd_al\snd_al.plg del /f /q snd_al\snd_al.plg
+if exist snd_dx\snd_dx.plg del /f /q snd_dx\snd_dx.plg
if exist xtools\xtools.plg del /f /q xtools\xtools.plg
echo Build succeeded!
diff --git a/engine/client/cl_game.c b/engine/client/cl_game.c
index 132e7ea5..698facd4 100644
--- a/engine/client/cl_game.c
+++ b/engine/client/cl_game.c
@@ -31,6 +31,18 @@ edict_t *CL_GetEdictByIndex( int index )
return EDICT_NUM( index );
}
+/*
+====================
+CL_GetServerTime
+
+don't clamped time that come from server
+====================
+*/
+int CL_GetServerTime( void )
+{
+ return cl.frame.servertime;
+}
+
/*
====================
StudioEvent
diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c
index b3615e19..3056ff93 100644
--- a/engine/client/cl_main.c
+++ b/engine/client/cl_main.c
@@ -57,6 +57,10 @@ extern cvar_t *allow_download;
//======================================================================
//======================================================================
+bool CL_CheckKeydest( void )
+{
+ return (cls.key_dest != key_game);
+}
/*
=======================================================================
@@ -673,7 +677,8 @@ Call before entering a new level, or after changing dlls
void CL_PrepSound( void )
{
int i, sndcount;
-
+
+ MsgDev( D_LOAD, "CL_PrepSound: %s\n", cl.configstrings[CS_NAME] );
for( i = 0, sndcount = 0; i < MAX_SOUNDS && cl.configstrings[CS_SOUNDS+i+1][0]; i++ )
sndcount++; // total num sounds
@@ -707,7 +712,7 @@ void CL_PrepVideo( void )
return; // no map loaded
Cvar_SetValue( "scr_loading", 0.0f ); // reset progress bar
- MsgDev( D_LOAD, "CL_PrepRefresh: %s\n", cl.configstrings[CS_NAME] );
+ MsgDev( D_LOAD, "CL_PrepVideo: %s\n", cl.configstrings[CS_NAME] );
// let the render dll load the map
FS_FileBase( cl.configstrings[CS_MODELS+1], mapname );
re->BeginRegistration( mapname, pe->VisData()); // load map
@@ -1134,8 +1139,6 @@ void CL_InitLocal( void )
Cmd_AddCommand ("download", CL_Download_f, "download specified resource (by name)" );
CL_InitServerCommands ();
-
- UI_SetActiveMenu( UI_MAINMENU );
}
//============================================================================
@@ -1163,6 +1166,8 @@ CL_Frame
*/
void CL_Frame( int time )
{
+ bool clear;
+
if( host.type == HOST_DEDICATED )
return;
@@ -1184,7 +1189,9 @@ void CL_Frame( int time )
CL_SendCommand();
// predict all unacknowledged movements
- CL_PredictMovement ();
+ CL_PredictMovement();
+
+ Host_CheckChanges();
// allow rendering DLL change
if( cls.state == ca_active )
@@ -1198,8 +1205,10 @@ void CL_Frame( int time )
SCR_MakeScreenShot();
+ clear = (cls.state > ca_disconnected && cls.state < ca_active) ? true : false;
+
// update audio
- S_Update( cl.playernum + 1, cl.refdef.simorg, cl.refdef.simvel, cl.refdef.forward, cl.refdef.up );
+ S_Update( cl.playernum + 1, cl.refdef.simorg, cl.refdef.simvel, cl.axis, clear );
// advance local effects for next frame
CL_RunDLights ();
@@ -1228,15 +1237,14 @@ void CL_Init( void )
cl_paused = Cvar_Get( "paused", "0", 0, "game paused" );
Con_Init();
- VID_Init();
if( !CL_LoadProgs( "client" ))
Host_Error( "CL_InitGame: can't initialize client.dll\n" );
MSG_Init( &net_message, net_message_buffer, sizeof( net_message_buffer ));
- UI_Init();
- SCR_Init();
+ Host_CheckChanges ();
+
CL_InitLocal();
cls.initialized = true;
}
diff --git a/engine/client/cl_phys.c b/engine/client/cl_phys.c
index 185e96c9..fbecce16 100644
--- a/engine/client/cl_phys.c
+++ b/engine/client/cl_phys.c
@@ -339,6 +339,9 @@ void CL_PredictMovement (void)
pmove = EDICT_NUM( cl.playernum + 1 )->pvClientData->current;
+ // unpredicted pure angled values converted into axis
+ AngleVectors( cl.refdef.cl_viewangles, cl.axis[0], cl.axis[1], cl.axis[2] );
+
if( !cl_predict->value || cl.frame.ps.ed_flags & ESF_NO_PREDICTION )
{
// just set angles
diff --git a/engine/client/cl_scrn.c b/engine/client/cl_scrn.c
index d9348f6e..9ad37836 100644
--- a/engine/client/cl_scrn.c
+++ b/engine/client/cl_scrn.c
@@ -20,6 +20,7 @@ cvar_t *cl_testflashlight;
cvar_t *cl_levelshot_name;
cvar_t *cl_envshot_size;
cvar_t *cl_font;
+static bool scr_init = false;
void SCR_TimeRefresh_f( void );
void SCR_Loading_f( void );
@@ -393,10 +394,10 @@ void SCR_MakeScreenShot( void )
switch( cls.scrshot_action )
{
case scrshot_plaque:
- re->ScrShot( cls.shotname, VID_LEVELSHOT );
+ if( re ) re->ScrShot( cls.shotname, VID_LEVELSHOT );
break;
case scrshot_savegame:
- re->ScrShot( cls.shotname, VID_SAVESHOT );
+ if( re ) re->ScrShot( cls.shotname, VID_SAVESHOT );
break;
}
@@ -465,6 +466,12 @@ SCR_Init
*/
void SCR_Init( void )
{
+ if( scr_init ) return;
+
+ // must be init before startup video subsystem
+ scr_width = Cvar_Get( "width", "640", 0, "screen width" );
+ scr_height = Cvar_Get( "height", "480", 0, "screen height" );
+
scr_showpause = Cvar_Get( "scr_showpause", "1", 0, "show pause picture" );
scr_centertime = Cvar_Get( "scr_centertime", "2.5", 0, "centerprint hold time" );
scr_printspeed = Cvar_Get( "scr_printspeed", "8", 0, "centerprint speed of print" );
@@ -485,8 +492,23 @@ void SCR_Init( void )
Cmd_AddCommand( "viewpos", SCR_Viewpos_f, "prints current player origin" );
SCR_RegisterShaders();
+ UI_Init();
+
+ if( cls.state == ca_disconnected )
+ UI_SetActiveMenu( UI_MAINMENU );
+ scr_init = true;
}
void SCR_Shutdown( void )
{
+ if( !scr_init ) return;
+
+ Cmd_RemoveCommand( "timerefresh" );
+ Cmd_RemoveCommand( "loading" );
+ Cmd_RemoveCommand( "skyname" );
+ Cmd_RemoveCommand( "setfont" );
+ Cmd_RemoveCommand( "viewpos" );
+
+ UI_Shutdown();
+ scr_init = false;
}
\ No newline at end of file
diff --git a/engine/client/client.h b/engine/client/client.h
index bcdbbb61..a2070da5 100644
--- a/engine/client/client.h
+++ b/engine/client/client.h
@@ -118,6 +118,7 @@ typedef struct
float predicted_step; // for stair up smoothing
uint predicted_step_time;
+ vec3_t axis[3]; // cl_viewangles without applied any view effects
vec3_t predicted_origin; // generated by CL_PredictMovement
vec3_t predicted_angles;
vec3_t prediction_error;
@@ -450,6 +451,7 @@ bool CL_LoadProgs( const char *name );
void CL_ParseUserMessage( sizebuf_t *msg, int svc_num );
void CL_LinkUserMessage( char *pszName, const int svc_num );
void CL_SortUserMessages( void );
+int CL_GetServerTime( void );
float CL_GetLerpFrac( void );
edict_t *CL_AllocEdict( void );
void CL_InitEdict( edict_t *pEdict );
@@ -507,7 +509,6 @@ void CL_Download_f( void );
//
void SCR_Init( void );
void SCR_UpdateScreen( void );
-void VID_Init( void );
void SCR_Shutdown( void );
void SCR_RegisterShaders( void );
void SCR_AdjustSize( float *x, float *y, float *w, float *h );
diff --git a/engine/common.h b/engine/common.h
index d7c12e2a..eb40275a 100644
--- a/engine/common.h
+++ b/engine/common.h
@@ -121,6 +121,7 @@ int Host_CompareFileTime( long ft1, long ft2 );
void Host_AbortCurrentFrame( void );
void Host_WriteDefaultConfig( void );
void Host_WriteConfig( void );
+void Host_CheckChanges( void );
int Host_Milliseconds( void );
void Host_Print( const char *txt );
void Host_Error( const char *error, ... );
@@ -351,6 +352,7 @@ void CL_MouseEvent( int mx, int my );
void CL_AddLoopingSounds( void );
void CL_RegisterSounds( void );
void CL_Drop( void );
+bool CL_CheckKeydest( void );
char *Info_ValueForKey( char *s, char *key );
void Info_RemoveKey( char *s, char *key );
void Info_SetValueForKey( char *s, char *key, char *value );
diff --git a/engine/common/con_main.c b/engine/common/con_main.c
index 9f99276d..ad503497 100644
--- a/engine/common/con_main.c
+++ b/engine/common/con_main.c
@@ -87,9 +87,6 @@ void Con_ToggleConsole_f( void )
{
UI_SetActiveMenu( UI_CLOSEMENU );
cls.key_dest = key_console;
-
- if( com.atoi(cl.configstrings[CS_MAXCLIENTS]) == 1 && Host_ServerState())
- Cvar_SetValue( "paused", 1 );
}
}
@@ -659,7 +656,6 @@ void Con_Close( void )
Con_ClearNotify();
con.finalFrac = 0; // none visible
con.displayFrac = 0;
- Cvar_SetValue( "paused", 0 );
}
bool Con_Active( void )
diff --git a/engine/common/input.c b/engine/common/input.c
index 05ceaa5b..fad5bbe9 100644
--- a/engine/common/input.c
+++ b/engine/common/input.c
@@ -132,18 +132,18 @@ void IN_ActivateMouse( void )
width = GetSystemMetrics(SM_CXSCREEN);
height = GetSystemMetrics(SM_CYSCREEN);
- GetWindowRect( host.hWnd, &window_rect);
- if (window_rect.left < 0) window_rect.left = 0;
- if (window_rect.top < 0) window_rect.top = 0;
- if (window_rect.right >= width) window_rect.right = width - 1;
- if (window_rect.bottom >= height-1) window_rect.bottom = height - 1;
+ GetWindowRect( host.hWnd, &window_rect );
+ if( window_rect.left < 0 ) window_rect.left = 0;
+ if( window_rect.top < 0 ) window_rect.top = 0;
+ if( window_rect.right >= width ) window_rect.right = width - 1;
+ if( window_rect.bottom >= height - 1 ) window_rect.bottom = height - 1;
- window_center_x = (window_rect.right + window_rect.left)/2;
- window_center_y = (window_rect.top + window_rect.bottom)/2;
+ window_center_x = (window_rect.right + window_rect.left) / 2;
+ window_center_y = (window_rect.top + window_rect.bottom) / 2;
SetCursorPos( window_center_x, window_center_y );
SetCapture( host.hWnd );
- ClipCursor(&window_rect);
+ ClipCursor( &window_rect );
while( ShowCursor(false) >= 0 );
}
@@ -349,16 +349,16 @@ long IN_WndProc( void *hWnd, uint uMsg, uint wParam, long lParam )
RECT r;
int xPos, yPos, style;
- xPos = (short) LOWORD(lParam); // horizontal position
- yPos = (short) HIWORD(lParam); // vertical position
+ xPos = (short)LOWORD( lParam ); // horizontal position
+ yPos = (short)HIWORD( lParam ); // vertical position
r.left = r.top = 0;
r.right = r.bottom = 1;
style = GetWindowLong( hWnd, GWL_STYLE );
AdjustWindowRect( &r, style, FALSE );
- Cvar_SetValue( "r_xpos", xPos + r.left);
- Cvar_SetValue( "r_ypos", yPos + r.top);
+ Cvar_SetValue( "r_xpos", xPos + r.left );
+ Cvar_SetValue( "r_ypos", yPos + r.top );
scr_xpos->modified = false;
scr_ypos->modified = false;
}
diff --git a/engine/engine.plg b/engine/engine.plg
deleted file mode 100644
index 967c1ed8..00000000
--- a/engine/engine.plg
+++ /dev/null
@@ -1,96 +0,0 @@
-
-
-
-Build Log
-
---------------------Configuration: engine - Win32 Debug--------------------
-
-Command Lines
-Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP1F65.tmp" with contents
-[
-/nologo /MDd /W3 /Gm /Gi /GX /ZI /Od /I "./" /I "common" /I "server" /I "client" /I "uimenu" /I "../public" /I "../common" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"..\temp\engine\!debug/" /Fo"..\temp\engine\!debug/" /Fd"..\temp\engine\!debug/" /FD /c
-"D:\Xash3D\src_main\engine\client\cl_parse.c"
-]
-Creating command line "cl.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP1F65.tmp"
-Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP1F66.tmp" with contents
-[
-user32.lib msvcrtd.lib /nologo /subsystem:windows /dll /incremental:yes /pdb:"..\temp\engine\!debug/engine.pdb" /debug /machine:I386 /nodefaultlib:"msvcrt.lib" /out:"..\temp\engine\!debug/engine.dll" /implib:"..\temp\engine\!debug/engine.lib" /pdbtype:sept
-"\Xash3D\src_main\temp\engine\!debug\cinematic.obj"
-"\Xash3D\src_main\temp\engine\!debug\cl_cmds.obj"
-"\Xash3D\src_main\temp\engine\!debug\cl_demo.obj"
-"\Xash3D\src_main\temp\engine\!debug\cl_effects.obj"
-"\Xash3D\src_main\temp\engine\!debug\cl_frame.obj"
-"\Xash3D\src_main\temp\engine\!debug\cl_game.obj"
-"\Xash3D\src_main\temp\engine\!debug\cl_input.obj"
-"\Xash3D\src_main\temp\engine\!debug\cl_main.obj"
-"\Xash3D\src_main\temp\engine\!debug\cl_parse.obj"
-"\Xash3D\src_main\temp\engine\!debug\cl_phys.obj"
-"\Xash3D\src_main\temp\engine\!debug\cl_scrn.obj"
-"\Xash3D\src_main\temp\engine\!debug\cl_view.obj"
-"\Xash3D\src_main\temp\engine\!debug\com_library.obj"
-"\Xash3D\src_main\temp\engine\!debug\con_keys.obj"
-"\Xash3D\src_main\temp\engine\!debug\con_main.obj"
-"\Xash3D\src_main\temp\engine\!debug\con_utils.obj"
-"\Xash3D\src_main\temp\engine\!debug\engfuncs.obj"
-"\Xash3D\src_main\temp\engine\!debug\engine.obj"
-"\Xash3D\src_main\temp\engine\!debug\host.obj"
-"\Xash3D\src_main\temp\engine\!debug\infostring.obj"
-"\Xash3D\src_main\temp\engine\!debug\input.obj"
-"\Xash3D\src_main\temp\engine\!debug\net_chan.obj"
-"\Xash3D\src_main\temp\engine\!debug\net_huff.obj"
-"\Xash3D\src_main\temp\engine\!debug\net_msg.obj"
-"\Xash3D\src_main\temp\engine\!debug\sv_client.obj"
-"\Xash3D\src_main\temp\engine\!debug\sv_cmds.obj"
-"\Xash3D\src_main\temp\engine\!debug\sv_frame.obj"
-"\Xash3D\src_main\temp\engine\!debug\sv_game.obj"
-"\Xash3D\src_main\temp\engine\!debug\sv_init.obj"
-"\Xash3D\src_main\temp\engine\!debug\sv_main.obj"
-"\Xash3D\src_main\temp\engine\!debug\sv_move.obj"
-"\Xash3D\src_main\temp\engine\!debug\sv_phys.obj"
-"\Xash3D\src_main\temp\engine\!debug\sv_save.obj"
-"\Xash3D\src_main\temp\engine\!debug\sv_world.obj"
-"\Xash3D\src_main\temp\engine\!debug\ui_advanced.obj"
-"\Xash3D\src_main\temp\engine\!debug\ui_audio.obj"
-"\Xash3D\src_main\temp\engine\!debug\ui_controls.obj"
-"\Xash3D\src_main\temp\engine\!debug\ui_credits.obj"
-"\Xash3D\src_main\temp\engine\!debug\ui_defaults.obj"
-"\Xash3D\src_main\temp\engine\!debug\ui_demos.obj"
-"\Xash3D\src_main\temp\engine\!debug\ui_gameoptions.obj"
-"\Xash3D\src_main\temp\engine\!debug\ui_gotosite.obj"
-"\Xash3D\src_main\temp\engine\!debug\ui_ingame.obj"
-"\Xash3D\src_main\temp\engine\!debug\ui_loadgame.obj"
-"\Xash3D\src_main\temp\engine\!debug\ui_main.obj"
-"\Xash3D\src_main\temp\engine\!debug\ui_menu.obj"
-"\Xash3D\src_main\temp\engine\!debug\ui_mods.obj"
-"\Xash3D\src_main\temp\engine\!debug\ui_multiplayer.obj"
-"\Xash3D\src_main\temp\engine\!debug\ui_network.obj"
-"\Xash3D\src_main\temp\engine\!debug\ui_options.obj"
-"\Xash3D\src_main\temp\engine\!debug\ui_performance.obj"
-"\Xash3D\src_main\temp\engine\!debug\ui_playersetup.obj"
-"\Xash3D\src_main\temp\engine\!debug\ui_qmenu.obj"
-"\Xash3D\src_main\temp\engine\!debug\ui_quit.obj"
-"\Xash3D\src_main\temp\engine\!debug\ui_savegame.obj"
-"\Xash3D\src_main\temp\engine\!debug\ui_singleplayer.obj"
-"\Xash3D\src_main\temp\engine\!debug\ui_video.obj"
-]
-Creating command line "link.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP1F66.tmp"
-Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP1F67.bat" with contents
-[
-@echo off
-copy \Xash3D\src_main\temp\engine\!debug\engine.dll "D:\Xash3D\bin\engine.dll"
-]
-Creating command line "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP1F67.bat"
-Compiling...
-cl_parse.c
-Linking...
-Output Window
-Performing Custom Build Step on \Xash3D\src_main\temp\engine\!debug\engine.dll
-Скопировано файлов: 1.
-
-
-
-Results
-engine.dll - 0 error(s), 0 warning(s)
-
-
-
diff --git a/engine/host.c b/engine/host.c
index 131c5b70..d41e71dc 100644
--- a/engine/host.c
+++ b/engine/host.c
@@ -7,6 +7,8 @@
#include "input.h"
#include "client.h"
+#define MAX_RENDERS 8
+
physic_exp_t *pe;
render_exp_t *re;
vprogs_exp_t *vm;
@@ -14,13 +16,17 @@ vsound_exp_t *se;
host_parm_t host; // host parms
stdlib_api_t com, newcom;
-byte *zonepool;
-char *buildstring = __TIME__ " " __DATE__;
+byte *zonepool;
+char *buildstring = __TIME__ " " __DATE__;
+string video_dlls[MAX_RENDERS];
+string audio_dlls[MAX_RENDERS];
+int num_audio_dlls;
+int num_video_dlls;
+dll_info_t render_dll = { "", NULL, "CreateAPI", NULL, NULL, 0, sizeof(render_exp_t), sizeof(stdlib_api_t) };
+dll_info_t vsound_dll = { "", NULL, "CreateAPI", NULL, NULL, 0, sizeof(vsound_exp_t), sizeof(stdlib_api_t) };
dll_info_t physic_dll = { "physic.dll", NULL, "CreateAPI", NULL, NULL, 1, sizeof(physic_exp_t), sizeof(stdlib_api_t) };
-dll_info_t render_dll = { "render.dll", NULL, "CreateAPI", NULL, NULL, 0, sizeof(render_exp_t), sizeof(stdlib_api_t) };
dll_info_t vprogs_dll = { "vprogs.dll", NULL, "CreateAPI", NULL, NULL, 1, sizeof(vprogs_exp_t), sizeof(stdlib_api_t) };
-dll_info_t vsound_dll = { "vsound.dll", NULL, "CreateAPI", NULL, NULL, 0, sizeof(vsound_exp_t), sizeof(stdlib_api_t) };
cvar_t *timescale;
cvar_t *host_serverstate;
@@ -29,6 +35,8 @@ cvar_t *host_maxfps;
cvar_t *host_minfps;
cvar_t *host_framerate;
cvar_t *host_registered;
+cvar_t *host_audio;
+cvar_t *host_video;
// these cvars will be duplicated on each client across network
int Host_ServerState( void ) { return Cvar_VariableInteger( "host_serverstate" ); }
@@ -58,7 +66,7 @@ void Host_InitPhysic( void )
pi.ClientMove = SV_PlayerMove;
pi.GetModelVerts = SV_GetModelVerts;
- Sys_LoadLibrary( &physic_dll );
+ Sys_LoadLibrary( NULL, &physic_dll );
CreatePhysic = (void *)physic_dll.main;
pe = CreatePhysic( &newcom, &pi );
@@ -76,54 +84,11 @@ void Host_FreePhysic( void )
Sys_FreeLibrary( &physic_dll );
}
-void Host_InitRender( void )
-{
- static render_imp_t ri;
- launch_t CreateRender;
- bool result = false;
-
- ri.api_size = sizeof(render_imp_t);
-
- // studio callbacks
- ri.UpdateScreen = SCR_UpdateScreen;
- ri.StudioEvent = CL_StudioEvent;
- ri.StudioFxTransform = CL_StudioFxTransform;
- ri.ShowCollision = pe->DrawCollision;
- ri.GetClientEdict = CL_GetEdictByIndex;
- ri.GetLocalPlayer = CL_GetLocalPlayer;
- ri.GetMaxClients = CL_GetMaxClients;
- ri.GetLerpFrac = CL_GetLerpFrac;
- ri.WndProc = IN_WndProc;
-
- Sys_LoadLibrary( &render_dll );
-
- if( render_dll.link )
- {
- CreateRender = (void *)render_dll.main;
- re = CreateRender( &newcom, &ri );
-
- if( re->Init( true )) result = true;
- }
-
- // video system not started, run dedicated server
- if( !result ) Sys_NewInstance( va("#%s", GI->gamedir ), "Host_InitRender: fallback to dedicated mode\n" );
-}
-
-void Host_FreeRender( void )
-{
- if( render_dll.link )
- {
- re->Shutdown( true );
- Mem_Set( &re, 0, sizeof( re ));
- }
- Sys_FreeLibrary( &render_dll );
-}
-
void Host_InitVprogs( const int argc, const char **argv )
{
launch_t CreateVprogs;
- Sys_LoadLibrary( &vprogs_dll );
+ Sys_LoadLibrary( NULL, &vprogs_dll );
CreateVprogs = (void *)vprogs_dll.main;
vm = CreateVprogs( &newcom, NULL ); // second interface not allowed
@@ -136,11 +101,57 @@ void Host_FreeVprogs( void )
if( vprogs_dll.link )
{
vm->Free();
- Mem_Set( &vm, 0, sizeof(vm));
+ Mem_Set( &vm, 0, sizeof( vm ));
}
Sys_FreeLibrary( &vprogs_dll );
}
+void Host_FreeRender( void )
+{
+ if( render_dll.link )
+ {
+ SCR_Shutdown ();
+ re->Shutdown( true );
+ Mem_Set( &re, 0, sizeof( re ));
+ }
+ Sys_FreeLibrary( &render_dll );
+}
+
+bool Host_InitRender( void )
+{
+ static render_imp_t ri;
+ launch_t CreateRender;
+ bool result = false;
+
+ ri.api_size = sizeof( render_imp_t );
+
+ // studio callbacks
+ ri.UpdateScreen = SCR_UpdateScreen;
+ ri.StudioEvent = CL_StudioEvent;
+ ri.StudioFxTransform = CL_StudioFxTransform;
+ ri.ShowCollision = pe->DrawCollision;
+ ri.GetClientEdict = CL_GetEdictByIndex;
+ ri.GetLocalPlayer = CL_GetLocalPlayer;
+ ri.GetMaxClients = CL_GetMaxClients;
+ ri.GetLerpFrac = CL_GetLerpFrac;
+ ri.WndProc = IN_WndProc;
+
+ Sys_LoadLibrary( host_video->string, &render_dll );
+
+ if( render_dll.link )
+ {
+ CreateRender = (void *)render_dll.main;
+ re = CreateRender( &newcom, &ri );
+
+ if( re->Init( true )) result = true;
+ }
+
+ // video system not started, shutdown refresh subsystem
+ if( !result ) Host_FreeRender();
+
+ return result;
+}
+
void Host_FreeSound( void )
{
if( vsound_dll.link )
@@ -151,19 +162,20 @@ void Host_FreeSound( void )
Sys_FreeLibrary( &vsound_dll );
}
-void Host_InitSound( void )
+bool Host_InitSound( void )
{
- static vsound_imp_t si;
- launch_t CreateSound;
- bool result = false;
+ static vsound_imp_t si;
+ launch_t CreateSound;
+ bool result = false;
// phys callback
- si.api_size = sizeof(vsound_imp_t);
+ si.api_size = sizeof( vsound_imp_t );
si.GetSoundSpatialization = CL_GetEntitySoundSpatialization;
si.PointContents = CL_PointContents;
si.AddLoopingSounds = CL_AddLoopingSounds;
+ si.GetServerTime = CL_GetServerTime;
- Sys_LoadLibrary( &vsound_dll );
+ Sys_LoadLibrary( host_audio->string, &vsound_dll );
if( vsound_dll.link )
{
@@ -175,6 +187,68 @@ void Host_InitSound( void )
// audio system not started, shutdown sound subsystem
if( !result ) Host_FreeSound();
+
+ return result;
+}
+
+void Host_CheckChanges( void )
+{
+ int num_changes;
+
+ if( host_video->modified || host_audio->modified )
+ {
+ host.state = HOST_RESTART;
+ S_StopAllSounds(); // don't let them loop during the restart
+
+ if( host_video->modified ) cl.video_prepped = false;
+ if( host_audio->modified ) cl.audio_prepped = false;
+ }
+ else return;
+
+ num_changes = 0;
+
+ // restart or change renderer
+ while( host_video->modified )
+ {
+ host_video->modified = false;
+
+ Host_FreeRender(); // release render.dll
+ if( !Host_InitRender( )) // load it again
+ {
+ if( num_changes > num_video_dlls )
+ {
+ Sys_NewInstance( va("#%s", GI->gamefolder ), "fallback to dedicated mode\n" );
+ return;
+ }
+ if( !com.strcmp( video_dlls[num_changes], host_video->string ))
+ num_changes++; // already trying - failed
+ Cvar_FullSet( "host_video", video_dlls[num_changes], CVAR_SYSTEMINFO );
+ num_changes++;
+ }
+ else SCR_Init ();
+ }
+
+ num_changes = 0;
+
+ // restart or change sound engine
+ while( host_audio->modified )
+ {
+ host_audio->modified = false;
+
+ Host_FreeSound(); // release sound.dll
+ if( !Host_InitSound( )) // load it again
+ {
+ if( num_changes > num_audio_dlls )
+ {
+ MsgDev( D_ERROR, "couldn't initialize sound system\n" );
+ return;
+ }
+ if( !com.strcmp( audio_dlls[num_changes], host_audio->string ))
+ num_changes++; // already trying - failed
+ Cvar_FullSet( "host_audio", audio_dlls[num_changes], CVAR_SYSTEMINFO );
+ num_changes++;
+ }
+ }
}
/*
@@ -208,14 +282,7 @@ Restart the video subsystem
*/
void Host_VidRestart_f( void )
{
- host.state = HOST_RESTART;
- S_StopAllSounds(); // don't let them loop during the restart
- cl.video_prepped = false;
-
- Host_FreeRender(); // release render.dll
- Host_InitRender(); // load it again
-
- SCR_RegisterShaders(); // reload 2d-shaders
+ host_video->modified = true;
}
/*
@@ -227,12 +294,7 @@ Restart the audio subsystem
*/
void Host_SndRestart_f( void )
{
- host.state = HOST_RESTART;
- S_StopAllSounds(); // don't let them loop during the restart
- cl.audio_prepped = false;
-
- Host_FreeSound(); // release vsound.dll
- Host_InitSound(); // load it again
+ host_audio->modified = true;
}
void Host_ChangeGame_f( void )
@@ -263,25 +325,6 @@ void Host_Minimize_f( void )
if( host.hWnd ) ShowWindow( host.hWnd, SW_MINIMIZE );
}
-/*
-============
-VID_Init
-============
-*/
-void VID_Init( void )
-{
- scr_width = Cvar_Get( "width", "640", 0, "screen width" );
- scr_height = Cvar_Get( "height", "480", 0, "screen height" );
-
- Cmd_AddCommand( "minimize", Host_Minimize_f, "minimize main window to tray" );
- Cmd_AddCommand( "vid_restart", Host_VidRestart_f, "restarts video system" );
- Cmd_AddCommand( "snd_restart", Host_SndRestart_f, "restarts audio system" );
- Cmd_AddCommand( "game", Host_ChangeGame_f, "change game" );
-
- Host_InitRender();
- Host_InitSound();
-}
-
/*
=================
Host_InitEvents
@@ -429,7 +472,9 @@ int Host_ModifyTime( int msec )
{
// clients of remote servers do not want to clamp time, because
// it would skew their view of the server's time temporarily
- clamp_time = 5000;
+ if( cls.state == ca_cinematic )
+ clamp_time = (1000 / host_maxfps->integer);
+ else clamp_time = 5000;
}
if( msec > clamp_time ) msec = clamp_time;
@@ -467,6 +512,9 @@ void Host_Frame( void )
last_time = host.frametime[0];
time = Host_ModifyTime( time );
+ if( host.state == HOST_RESTART )
+ host.state = HOST_FRAME;
+
SV_Frame ( time ); // server frame
CL_Frame ( time ); // client frame
VM_Frame ( time ); // vprogs frame
@@ -559,14 +607,17 @@ void Host_Error_f( void )
Host_Crash_f
=================
*/
-static void Host_Crash_f (void)
+static void Host_Crash_f( void )
{
*(int *)0 = 0xffffffff;
}
void Host_InitCommon( const int argc, const char **argv )
{
- char dev_level[4];
+ char dev_level[4];
+ dll_info_t check_vid, check_snd;
+ search_t *dlls;
+ int i;
newcom = com;
@@ -584,6 +635,52 @@ void Host_InitCommon( const int argc, const char **argv )
zonepool = Mem_AllocPool( "Zone Engine" );
IN_Init();
+
+ // initialize audio\video multi-dlls system
+ num_video_dlls = num_audio_dlls = 0;
+ host_video = Cvar_Get( "host_video", "vid_gl.dll", CVAR_SYSTEMINFO, "name of video rendering library" );
+ host_audio = Cvar_Get( "host_audio", "snd_al.dll", CVAR_SYSTEMINFO, "name of sound rendering library" );
+
+ // make sure what global copy has no changed with any dll checking
+ Mem_Copy( &check_vid, &render_dll, sizeof( dll_info_t ));
+ Mem_Copy( &check_snd, &vsound_dll, sizeof( dll_info_t ));
+
+ // checking dlls don't invoke crash!
+ check_vid.crash = false;
+ check_snd.crash = false;
+
+ dlls = FS_Search( "*.dll", true );
+
+ // couldn't find any dlls, render is missing (but i'm don't know how laucnher find engine :)
+ // probably this should never happen
+ if( !dlls ) Sys_NewInstance( "й", "" );
+
+ for( i = 0; i < dlls->numfilenames; i++ )
+ {
+ if(!com.strnicmp( "vid_", dlls->filenames[i], 4 ))
+ {
+ // make sure what found library is valid
+ if( Sys_LoadLibrary( dlls->filenames[i], &check_vid ))
+ {
+ MsgDev( D_NOTE, "VideoLibrary[%i]: %s\n", num_video_dlls, dlls->filenames[i] );
+ com.strncpy( video_dlls[num_video_dlls], dlls->filenames[i], MAX_STRING );
+ Sys_FreeLibrary( &check_vid );
+ num_video_dlls++;
+ }
+ }
+ else if(!com.strnicmp( "snd_", dlls->filenames[i], 4 ))
+ {
+ // make sure what found library is valid
+ if( Sys_LoadLibrary( dlls->filenames[i], &check_snd ))
+ {
+ MsgDev( D_NOTE, "AudioLibrary[%i]: %s\n", num_audio_dlls, dlls->filenames[i] );
+ com.strncpy( audio_dlls[num_audio_dlls], dlls->filenames[i], MAX_STRING );
+ Sys_FreeLibrary( &check_snd );
+ num_audio_dlls++;
+ }
+ }
+ }
+ Mem_Free( dlls );
}
void Host_FreeCommon( void )
@@ -645,6 +742,14 @@ void Host_Init( const int argc, const char **argv )
Cmd_AddCommand( "quit", Sys_Quit, "quit the game" );
Cmd_AddCommand( "exit", Sys_Quit, "quit the game" );
}
+ else
+ {
+ Cmd_AddCommand( "minimize", Host_Minimize_f, "minimize main window to tray" );
+ Cmd_AddCommand( "vid_restart", Host_VidRestart_f, "restarts video system" );
+ Cmd_AddCommand( "snd_restart", Host_SndRestart_f, "restarts audio system" );
+ }
+
+ Cmd_AddCommand( "game", Host_ChangeGame_f, "change game" ); // allow to change game from the console
host.frametime[0] = Host_Milliseconds();
host.errorframe = 0;
}
diff --git a/engine/server/sv_cmds.c b/engine/server/sv_cmds.c
index 675be4c9..91a7d968 100644
--- a/engine/server/sv_cmds.c
+++ b/engine/server/sv_cmds.c
@@ -211,7 +211,7 @@ void SV_Map_f( void )
else spawn_entity = GI->sp_entity;
com.strncpy( filename, Cmd_Argv( 1 ), sizeof( filename ));
- if( !SV_MapIsValid( filename, spawn_entity ))
+ if( !SV_MapIsValid( filename, spawn_entity ) && host.developer <= 1 )
{
Msg( "SV_NewMap: invalid map %s\n", filename );
return;
diff --git a/engine/server/sv_game.c b/engine/server/sv_game.c
index 96fcc0e9..5e9d27c9 100644
--- a/engine/server/sv_game.c
+++ b/engine/server/sv_game.c
@@ -2329,6 +2329,8 @@ pfnIndexOfEdict
*/
int pfnIndexOfEdict( const edict_t *pEdict )
{
+ if( !pEdict || pEdict->free )
+ return 0;
return NUM_FOR_EDICT( pEdict );
}
diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c
index a84e3e56..76011979 100644
--- a/engine/server/sv_init.c
+++ b/engine/server/sv_init.c
@@ -252,6 +252,8 @@ void SV_SpawnServer( const char *server, const char *startspot )
Msg( "SpawnServer [^2%s^7]\n", server );
+ Cmd_ExecuteString( "latch\n" );
+
if( sv.state == ss_dead && !sv.loadgame )
SV_InitGame(); // the game is just starting
@@ -354,8 +356,6 @@ void SV_InitGame( void )
}
MsgDev( D_INFO, "Dll loaded for mod %s\n", svgame.dllFuncs.pfnGetGameDescription() );
-
- Cmd_ExecuteString( "latch\n" );
svs.initialized = true;
if( Cvar_VariableValue( "coop" ) && Cvar_VariableValue ( "deathmatch" ) && Cvar_VariableValue( "teamplay" ))
diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c
index a935af50..fdfced64 100644
--- a/engine/server/sv_main.c
+++ b/engine/server/sv_main.c
@@ -241,9 +241,6 @@ bool SV_CheckPaused( void )
int i, count;
sv_client_t *cl;
- if( !sv_paused->integer )
- return false;
-
// only pause if there is just a single client connected
for( i = count = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
{
@@ -259,6 +256,12 @@ bool SV_CheckPaused( void )
return false;
}
+ if( CL_CheckKeydest() )
+ return true;
+
+ if( !sv_paused->integer )
+ return false;
+
if( !sv_paused->integer )
Cvar_Set( "paused", "1" );
return true;
diff --git a/engine/uimenu/ui_video.c b/engine/uimenu/ui_video.c
index 942eca69..2f019913 100644
--- a/engine/uimenu/ui_video.c
+++ b/engine/uimenu/ui_video.c
@@ -323,7 +323,7 @@ static void UI_Video_UpdateConfig( void )
}
uiVideo.glExtensions.generic.name = uiVideoYesNo[(int)uiVideo.glExtensions.curValue];
- uiVideo.videoMode.generic.name = uiVideoModes[(int)uiVideo.videoMode.curValue + 1];
+ uiVideo.videoMode.generic.name = uiVideoModes[(int)uiVideo.videoMode.curValue];
uiVideo.fullScreen.generic.name = uiVideoYesNo[(int)uiVideo.fullScreen.curValue];
uiVideo.colorDepth.generic.name = uiVideoBits[(int)uiVideo.colorDepth.curValue];
uiVideo.hardwareGamma.generic.name = uiVideoYesNo[(int)uiVideo.hardwareGamma.curValue];
diff --git a/launch/cmd.c b/launch/cmd.c
index b93063d0..4cff13b2 100644
--- a/launch/cmd.c
+++ b/launch/cmd.c
@@ -45,17 +45,17 @@ Cbuf_AddText
Adds command text at the end of the buffer
============
*/
-void Cbuf_AddText(const char *text)
+void Cbuf_AddText( const char *text )
{
int l;
- l = com_strlen(text);
- if (cmd_text.cursize + l >= cmd_text.maxsize)
+ l = com.strlen( text );
+ if( cmd_text.cursize + l >= cmd_text.maxsize )
{
- MsgDev(D_WARN, "Cbuf_AddText: overflow\n");
+ MsgDev( D_WARN, "Cbuf_AddText: overflow\n" );
return;
}
- Mem_Copy(&cmd_text.data[cmd_text.cursize], (char *)text, l);
+ Mem_Copy( &cmd_text.data[cmd_text.cursize], text, l );
cmd_text.cursize += l;
}
@@ -73,22 +73,22 @@ void Cbuf_InsertText (const char *text)
{
int i, len;
- len = strlen( text ) + 1;
- if ( len + cmd_text.cursize > cmd_text.maxsize )
+ len = com.strlen( text ) + 1;
+ if( len + cmd_text.cursize > cmd_text.maxsize )
{
- MsgDev(D_WARN,"Cbuf_InsertText overflowed\n" );
+ MsgDev( D_WARN, "Cbuf_InsertText overflowed\n" );
return;
}
// move the existing command text
- for ( i = cmd_text.cursize - 1; i >= 0; i-- )
+ for( i = cmd_text.cursize - 1; i >= 0; i-- )
{
cmd_text.data[i + len] = cmd_text.data[i];
}
// copy the new text in
Mem_Copy( cmd_text.data, (char *)text, len - 1 );
- cmd_text.data[ len - 1 ] = '\n'; // add a \n
+ cmd_text.data[len - 1] = '\n'; // add a \n
cmd_text.cursize += len;
}
@@ -97,23 +97,23 @@ void Cbuf_InsertText (const char *text)
Cbuf_ExecuteText
============
*/
-void Cbuf_ExecuteText (int exec_when, const char *text)
+void Cbuf_ExecuteText( int exec_when, const char *text )
{
- switch (exec_when)
+ switch( exec_when )
{
case EXEC_NOW:
- if (text && strlen(text))
- Cmd_ExecuteString(text);
+ if( text && com.strlen( text ))
+ Cmd_ExecuteString( text );
else Cbuf_Execute();
break;
case EXEC_INSERT:
- Cbuf_InsertText (text);
+ Cbuf_InsertText( text );
break;
case EXEC_APPEND:
- Cbuf_AddText (text);
+ Cbuf_AddText( text );
break;
default:
- MsgDev( D_ERROR, "Cbuf_ExecuteText: bad execute target\n");
+ MsgDev( D_ERROR, "Cbuf_ExecuteText: bad execute target\n" );
break;
}
}
@@ -143,28 +143,33 @@ void Cbuf_Execute( void )
text = (char *)cmd_text.data;
quotes = 0;
- for (i = 0; i < cmd_text.cursize; i++)
+ for( i = 0; i < cmd_text.cursize; i++ )
{
- if (text[i] == '"') quotes++;
- if ( !(quotes&1) && text[i] == ';')
+ if( text[i] == '"') quotes++;
+ if(!( quotes & 1 ) && text[i] == ';' )
break; // don't break if inside a quoted string
- if (text[i] == '\n' || text[i] == '\r' ) break;
+ if( text[i] == '\n' || text[i] == '\r' ) break;
}
- if( i >= (MAX_CMD_LINE - 1)) i = MAX_CMD_LINE - 1;
- Mem_Copy (line, text, i);
+ if( i >= MAX_CMD_LINE - 1 )
+ Sys_Error( "Cbuf_Execute: command string owerflow\n" );
+
+ Mem_Copy( line, text, i );
line[i] = 0;
-
+
// delete the text from the command buffer and move remaining commands down
// this is necessary because commands (exec) can insert data at the
// beginning of the text buffer
- if (i == cmd_text.cursize) cmd_text.cursize = 0;
+ if( i == cmd_text.cursize )
+ {
+ cmd_text.cursize = 0;
+ }
else
{
i++;
cmd_text.cursize -= i;
- memmove (text, text+i, cmd_text.cursize);
+ memmove( text, text + i, cmd_text.cursize );
}
// execute the command line
@@ -195,7 +200,7 @@ void Cmd_StuffCmds_f( void )
if(Cmd_Argc() != 1)
{
- Msg("stuffcmds : execute command line parameters\n");
+ Msg( "stuffcmds : execute command line parameters\n");
return;
}
@@ -261,26 +266,27 @@ void Cmd_Exec_f (void)
{
string rcpath;
size_t len;
-
char *f;
+
if( Cmd_Argc() != 2 )
{
- Msg( "exec : execute a script file\n" );
+ Msg( "Usage: exec \n" );
return;
}
- com.snprintf( rcpath, MAX_STRING, "config/%s", Cmd_Argv(1));
+ com.snprintf( rcpath, MAX_STRING, "config/%s", Cmd_Argv( 1 ));
FS_DefaultExtension( rcpath, ".rc" ); // append as default
f = FS_LoadFile(rcpath, &len );
- if (!f)
+ if( !f )
{
- MsgDev( D_WARN, "couldn't exec %s\n", Cmd_Argv(1));
+ MsgDev( D_WARN, "couldn't exec %s\n", Cmd_Argv( 1 ));
return;
}
- MsgDev(D_INFO, "execing %s\n",Cmd_Argv(1));
- Cbuf_InsertText(f);
- Mem_Free(f);
+
+ MsgDev( D_INFO, "execing %s\n", Cmd_Argv( 1 ));
+ Cbuf_InsertText( f );
+ Mem_Free( f );
}
/*
@@ -331,10 +337,10 @@ typedef struct cmd_function_s
xcommand_t function;
} cmd_function_t;
-static int cmd_argc;
-static char *cmd_argv[MAX_STRING_TOKENS];
-static char cmd_tokenized[MAX_MSGLEN+MAX_STRING_TOKENS]; // will have 0 bytes inserted
-static cmd_function_t *cmd_functions; // possible commands to execute
+static int cmd_argc;
+static char *cmd_argv[MAX_STRING_TOKENS];
+static char cmd_tokenized[MAX_CMD_BUFFER]; // will have 0 bytes inserted
+static cmd_function_t *cmd_functions; // possible commands to execute
/*
============
@@ -390,7 +396,7 @@ are inserted in the apropriate place, The argv array
will point into this temporary buffer.
============
*/
-void Cmd_TokenizeString (const char *text_in)
+void Cmd_TokenizeString( const char *text_in )
{
const char *text;
char *textOut;
@@ -404,36 +410,37 @@ void Cmd_TokenizeString (const char *text_in)
while( 1 )
{
// this is usually something malicious
- if ( cmd_argc == MAX_STRING_TOKENS ) return;
+ if( cmd_argc == MAX_STRING_TOKENS ) return;
- while ( 1 )
+ while( 1 )
{
// skip whitespace
- while ( *text && *text <= ' ' ) text++;
- if ( !*text ) return; // all tokens parsed
+ while( *text && *text <= ' ' ) text++;
+ if( !*text ) return; // all tokens parsed
// skip // comments
- if ( text[0] == '/' && text[1] == '/' ) return; // all tokens parsed
+ if( text[0] == '/' && text[1] == '/' ) return; // all tokens parsed
// skip /* */ comments
- if ( text[0] == '/' && text[1] =='*' )
+ if( text[0] == '/' && text[1] =='*' )
{
- while(*text && ( text[0] != '*' || text[1] != '/' )) text++;
- if ( !*text ) return; // all tokens parsed
+ while( *text && ( text[0] != '*' || text[1] != '/' )) text++;
+ if( !*text ) return; // all tokens parsed
text += 2;
}
else break; // we are ready to parse a token
}
// handle quoted strings
- if ( *text == '"' )
+ if( *text == '"' )
{
cmd_argv[cmd_argc] = textOut;
cmd_argc++;
text++;
- while ( *text && *text != '"' ) *textOut++ = *text++;
+ while( *text && *text != '"' )
+ *textOut++ = *text++;
*textOut++ = 0;
- if ( !*text ) return; // all tokens parsed
+ if( !*text ) return; // all tokens parsed
text++;
continue;
}
@@ -443,12 +450,12 @@ void Cmd_TokenizeString (const char *text_in)
cmd_argc++;
// skip until whitespace, quote, or command
- while ( *text > ' ' )
+ while( *text > ' ' )
{
- if ( text[0] == '"' ) break;
- if ( text[0] == '/' && text[1] == '/' ) break;
+ if( text[0] == '"' ) break;
+ if( text[0] == '/' && text[1] == '/' ) break;
// skip /* */ comments
- if ( text[0] == '/' && text[1] =='*' ) break;
+ if( text[0] == '/' && text[1] =='*' ) break;
*textOut++ = *text++;
}
@@ -464,7 +471,7 @@ void Cmd_TokenizeString (const char *text_in)
Cmd_AddCommand
============
*/
-void Cmd_AddCommand (const char *cmd_name, xcommand_t function, const char *cmd_desc)
+void Cmd_AddCommand( const char *cmd_name, xcommand_t function, const char *cmd_desc )
{
cmd_function_t *cmd;
@@ -559,7 +566,7 @@ void Cmd_ExecuteString( const char *text )
if( !Cmd_Argc()) return; // no tokens
// check registered command functions
- for ( prev = &cmd_functions; *prev; prev = &cmd->next )
+ for( prev = &cmd_functions; *prev; prev = &cmd->next )
{
cmd = *prev;
if(!com.stricmp( cmd_argv[0], cmd->name ))
diff --git a/launch/cvar.c b/launch/cvar.c
index 8f22e4e9..ce49e203 100644
--- a/launch/cvar.c
+++ b/launch/cvar.c
@@ -301,7 +301,7 @@ cvar_t *Cvar_Set2 (const char *var_name, const char *value, bool force)
MsgDev(D_INFO, "%s is system variable.\n", var_name);
return var;
}
- if( var->flags & (CVAR_LATCH|CVAR_LATCH_VIDEO))
+ if( var->flags & (CVAR_LATCH|CVAR_LATCH_VIDEO|CVAR_LATCH_AUDIO))
{
if( var->latched_string )
{
@@ -315,26 +315,29 @@ cvar_t *Cvar_Set2 (const char *var_name, const char *value, bool force)
return var;
}
- if( Cvar_VariableInteger( "host_serverstate" ))
+ if( var->flags & CVAR_LATCH && Cvar_VariableInteger( "host_serverstate" ))
{
MsgDev( D_INFO, "%s will be changed upon restarting.\n", var->name );
var->latched_string = copystring( value );
}
+ else if( var->flags & CVAR_LATCH_VIDEO )
+ {
+ MsgDev( D_INFO, "%s will be changed upon restarting video.\n", var->name );
+ var->latched_string = copystring( value );
+ }
+ else if( var->flags & CVAR_LATCH_AUDIO )
+ {
+ MsgDev( D_INFO, "%s will be changed upon restarting audio.\n", var->name );
+ var->latched_string = copystring( value );
+ }
else
{
- if( var->flags & CVAR_LATCH_VIDEO )
- {
- MsgDev( D_INFO, "%s will be changed upon restarting video.\n", var->name );
- var->latched_string = copystring( value );
- }
- else
- {
- Mem_Free( var->string ); // free the old value string
- var->string = copystring( value );
- var->value = com.atof( var->string );
- var->integer = com.atoi( var->string );
- }
+ Mem_Free( var->string ); // free the old value string
+ var->string = copystring( value );
+ var->value = com.atof( var->string );
+ var->integer = com.atoi( var->string );
}
+
var->modified = true;
var->modificationCount++;
return var;
@@ -684,28 +687,31 @@ void Cvar_List_f( void )
if( match && !com_stricmpext( match, var->name ))
continue;
- if( var->flags & CVAR_SERVERINFO ) Msg( "S" );
+ if( var->flags & CVAR_SERVERINFO ) Msg( "SV " );
else Msg( " " );
- if( var->flags & CVAR_USERINFO ) Msg( "U" );
+ if( var->flags & CVAR_USERINFO ) Msg( "USER " );
else Msg( " " );
- if( var->flags & CVAR_READ_ONLY ) Msg( "R" );
+ if( var->flags & CVAR_READ_ONLY ) Msg( "READ " );
else Msg( " " );
- if( var->flags & CVAR_INIT ) Msg( "I" );
+ if( var->flags & CVAR_INIT ) Msg( "INIT " );
else Msg( " " );
- if( var->flags & CVAR_ARCHIVE ) Msg( "A" );
+ if( var->flags & CVAR_ARCHIVE ) Msg( "ARCH " );
else Msg( " " );
- if( var->flags & CVAR_LATCH ) Msg( "L" );
+ if( var->flags & CVAR_LATCH ) Msg( "LATCH" );
else Msg( " " );
- if( var->flags & CVAR_LATCH_VIDEO ) Msg( "V" );
+ if( var->flags & CVAR_LATCH_VIDEO ) Msg( "VIDEO" );
else Msg( " " );
- if( var->flags & CVAR_CHEAT ) Msg( "C" );
+ if( var->flags & CVAR_LATCH_AUDIO ) Msg( "AUDIO" );
+ else Msg( " " );
+
+ if( var->flags & CVAR_CHEAT ) Msg( "CHEAT" );
else Msg( " " );
Msg(" %s \"%s\"\n", var->name, var->string );
j++;
@@ -820,6 +826,35 @@ void Cvar_LatchedVideo_f( void )
}
}
+/*
+============
+Cvar_Latched_f
+
+Now all latched audio strings is valid
+============
+*/
+void Cvar_LatchedAudio_f( void )
+{
+ cvar_t *var;
+ cvar_t **prev;
+
+ prev = &cvar_vars;
+
+ while ( 1 )
+ {
+ var = *prev;
+ if( !var ) break;
+
+ if( var->flags & CVAR_LATCH_AUDIO && var->latched_string )
+ {
+ Cvar_FullSet( var->name, var->latched_string, var->flags );
+ Mem_Free( var->latched_string );
+ var->latched_string = NULL;
+ }
+ prev = &var->next;
+ }
+}
+
/*
============
Cvar_Init
@@ -842,7 +877,8 @@ void Cvar_Init( void )
Cmd_AddCommand ("seta", Cvar_SetA_f, "create or change the value of a console variable that will be saved to vars.rc");
Cmd_AddCommand ("reset", Cvar_Reset_f, "reset any type variable to initial value" );
Cmd_AddCommand ("latch", Cvar_Latched_f, "apply latched values" );
- Cmd_AddCommand ("vidlatch", Cvar_LatchedVideo_f, "apply latched values for renderer" );
+ Cmd_AddCommand ("vidlatch", Cvar_LatchedVideo_f, "apply latched values for video subsystem" );
+ Cmd_AddCommand ("sndlatch", Cvar_LatchedAudio_f, "apply latched values for audio subsytem" );
Cmd_AddCommand ("cvarlist", Cvar_List_f, "display all console variables beginning with the specified prefix" );
Cmd_AddCommand ("unsetall", Cvar_Restart_f, "reset all console variables to their default values" );
diff --git a/launch/launch.h b/launch/launch.h
index e04d5a7b..5e673880 100644
--- a/launch/launch.h
+++ b/launch/launch.h
@@ -144,7 +144,7 @@ void Sys_Sleep( int msec );
void Sys_Init( void );
void Sys_Exit( void );
void Sys_Abort( void );
-bool Sys_LoadLibrary ( dll_info_t *dll );
+bool Sys_LoadLibrary( const char *dll_name, dll_info_t *dll );
void* Sys_GetProcAddress ( dll_info_t *dll, const char* name );
void Sys_ShellExecute( const char *path, const char *parms, bool exit );
byte *Sys_LoadRes( const char *filename, size_t *size );
diff --git a/launch/launch.plg b/launch/launch.plg
deleted file mode 100644
index 7d3da586..00000000
--- a/launch/launch.plg
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-Build Log
-
---------------------Configuration: launch - Win32 Debug--------------------
-
-Command Lines
-
-
-
-Results
-launch.dll - 0 error(s), 0 warning(s)
-
-
-
diff --git a/launch/network.c b/launch/network.c
index e53182f0..7589feba 100644
--- a/launch/network.c
+++ b/launch/network.c
@@ -92,7 +92,7 @@ bool NET_OpenWinSock( void )
{
// initialize the Winsock function vectors (we do this instead of statically linking
// so we can run on Win 3.1, where there isn't necessarily Winsock)
- if( Sys_LoadLibrary( &winsock_dll ))
+ if( Sys_LoadLibrary( NULL, &winsock_dll ))
return true;
return false;
}
diff --git a/launch/system.c b/launch/system.c
index f248a196..0d3c3c68 100644
--- a/launch/system.c
+++ b/launch/system.c
@@ -409,8 +409,8 @@ void Sys_CreateInstance( void )
// export
launch_t CreateHost, CreateBaserc;
- srand( time( NULL )); // init random generator
- Sys_LoadLibrary( Sys.linked_dll ); // loading library if need
+ srand( time( NULL )); // init random generator
+ Sys_LoadLibrary( NULL, Sys.linked_dll ); // loading library if need
// pre initializations
switch( Sys.app_name )
@@ -424,7 +424,7 @@ void Sys_CreateInstance( void )
case HOST_STUDIO:
case HOST_WADLIB:
case HOST_RIPPER:
- Sys_LoadLibrary( &baserc_dll ); // load baserc
+ Sys_LoadLibrary( NULL, &baserc_dll ); // load baserc
CreateHost = (void *)Sys.linked_dll->main;
Host = CreateHost( &com, NULL ); // second interface not allowed
Sys.Init = Host->Init;
@@ -970,7 +970,7 @@ void Sys_Exit( void )
//=======================================================================
// DLL'S MANAGER SYSTEM
//=======================================================================
-bool Sys_LoadLibrary ( dll_info_t *dll )
+bool Sys_LoadLibrary( const char *dll_name, dll_info_t *dll )
{
const dllfunc_t *func;
bool native_lib = false;
@@ -978,9 +978,12 @@ bool Sys_LoadLibrary ( dll_info_t *dll )
// check errors
if( !dll ) return false; // invalid desc
- if( !dll->name ) return false;// nothing to load
if( dll->link ) return true; // already loaded
+ // check and replace names
+ if( dll_name && *dll_name ) dll->name = dll_name;
+ if( !dll->name || !*dll->name ) return false; // nothing to load
+
MsgDev( D_NOTE, "Sys_LoadLibrary: Loading %s", dll->name );
if( dll->fcts )
@@ -1003,7 +1006,7 @@ bool Sys_LoadLibrary ( dll_info_t *dll )
if( native_lib )
{
- if(( dll->main = Sys_GetProcAddress( dll, dll->entry )) == 0)
+ if(( dll->main = Sys_GetProcAddress( dll, dll->entry )) == 0 )
{
com.sprintf( errorstring, "Sys_LoadLibrary: %s has no valid entry point\n", dll->name );
goto error;
@@ -1060,19 +1063,19 @@ error:
void* Sys_GetProcAddress( dll_info_t *dll, const char* name )
{
- if(!dll || !dll->link) // invalid desc
+ if( !dll || !dll->link ) // invalid desc
return NULL;
- return (void *)GetProcAddress (dll->link, name);
+ return (void *)GetProcAddress( dll->link, name );
}
bool Sys_FreeLibrary( dll_info_t *dll )
{
// invalid desc or alredy freed
- if(!dll || !dll->link )
+ if( !dll || !dll->link )
return false;
- MsgDev(D_NOTE, "Sys_FreeLibrary: Unloading %s\n", dll->name );
+ MsgDev( D_NOTE, "Sys_FreeLibrary: Unloading %s\n", dll->name );
FreeLibrary( dll->link );
dll->link = NULL;
diff --git a/physic/physic.plg b/physic/physic.plg
deleted file mode 100644
index 3835ce2a..00000000
--- a/physic/physic.plg
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-Build Log
-
---------------------Configuration: physic - Win32 Debug--------------------
-
-Command Lines
-
-
-
-Results
-physic.dll - 0 error(s), 0 warning(s)
-
-
-
diff --git a/public/launch_api.h b/public/launch_api.h
index 554fe75b..435241a2 100644
--- a/public/launch_api.h
+++ b/public/launch_api.h
@@ -120,6 +120,7 @@ typedef enum
CVAR_CHEAT = BIT(9), // can not be changed if cheats are disabled
CVAR_NORESTART = BIT(10),// do not clear when a cvar_restart is issued
CVAR_LATCH_VIDEO = BIT(11),// save changes until render restart
+ CVAR_LATCH_AUDIO = BIT(12),// save changes until vsound restart
} cvar_flags_t;
typedef struct
@@ -271,8 +272,9 @@ writes into struct by offsets not names
*/
typedef struct dll_info_s
{
+ const char *name; // name of library
+
// generic interface
- const char *name; // library name
const dllfunc_t *fcts; // list of dll exports
const char *entry; // entrypoint name (internal libs only)
void *link; // hinstance of loading library
@@ -579,7 +581,7 @@ typedef struct stdilib_api_s
// filesystem simply user interface
byte *(*Com_LoadFile)(const char *path, long *filesize ); // load file into heap
bool (*Com_WriteFile)(const char *path, const void *data, long len ); // write file into disk
- bool (*Com_LoadLibrary)( dll_info_t *dll ); // load library
+ bool (*Com_LoadLibrary)( const char *name, dll_info_t *dll ); // load library
bool (*Com_FreeLibrary)( dll_info_t *dll ); // free library
void*(*Com_GetProcAddress)( dll_info_t *dll, const char* name ); // gpa
double (*Com_DoubleTime)( void ); // hi-res timer
diff --git a/public/vsound_api.h b/public/vsound_api.h
index d2dd28b5..fe362a3c 100644
--- a/public/vsound_api.h
+++ b/public/vsound_api.h
@@ -41,7 +41,7 @@ typedef struct vsound_exp_s
void (*StartStreaming)( void );
void (*StopStreaming)( void );
- void (*Frame)( int entnum, const vec3_t pos, const vec3_t vel, const vec3_t at, const vec3_t up );
+ void (*Frame)( int entnum, const vec3_t pos, const vec3_t vel, const vec3_t axis[3], bool clear );
void (*StopAllSounds)( void );
void (*FreeSounds)( void );
@@ -57,7 +57,7 @@ typedef struct vsound_imp_s
void (*GetSoundSpatialization)( int entnum, vec3_t origin, vec3_t velocity );
int (*PointContents)( const vec3_t point );
void (*AddLoopingSounds)( void );
-
+ int (*GetServerTime)( void );
} vsound_imp_t;
#endif//VSOUND_API_H
\ No newline at end of file
diff --git a/release.bat b/release.bat
index 663a785d..80e61c91 100644
--- a/release.bat
+++ b/release.bat
@@ -23,7 +23,7 @@ if errorlevel 1 set BUILD_ERROR=1
%MSDEV% physic/physic.dsp %CONFIG%"physic - Win32 Release" %build_target%
if errorlevel 1 set BUILD_ERROR=1
-%MSDEV% render/render.dsp %CONFIG%"render - Win32 Release" %build_target%
+%MSDEV% vid_gl/vid_gl.dsp %CONFIG%"vid_gl - Win32 Release" %build_target%
if errorlevel 1 set BUILD_ERROR=1
%MSDEV% server/server.dsp %CONFIG%"server - Win32 Release" %build_target%
@@ -32,7 +32,10 @@ if errorlevel 1 set BUILD_ERROR=1
%MSDEV% vprogs/vprogs.dsp %CONFIG%"vprogs - Win32 Release" %build_target%
if errorlevel 1 set BUILD_ERROR=1
-%MSDEV% vsound/vsound.dsp %CONFIG%"vsound - Win32 Release" %build_target%
+%MSDEV% snd_al/snd_al.dsp %CONFIG%"snd_al - Win32 Release" %build_target%
+if errorlevel 1 set BUILD_ERROR=1
+
+%MSDEV% snd_dx/snd_dx.dsp %CONFIG%"snd_dx - Win32 Release" %build_target%
if errorlevel 1 set BUILD_ERROR=1
%MSDEV% xtools/xtools.dsp %CONFIG%"xtools - Win32 Release" %build_target%
@@ -62,10 +65,11 @@ if exist client\client.plg del /f /q client\client.plg
if exist engine\engine.plg del /f /q engine\engine.plg
if exist launch\launch.plg del /f /q launch\launch.plg
if exist physic\physic.plg del /f /q physic\physic.plg
-if exist render\render.plg del /f /q render\render.plg
+if exist vid_gl\vid_gl.plg del /f /q vid_gl\vid_gl.plg
if exist server\server.plg del /f /q server\server.plg
if exist vprogs\vprogs.plg del /f /q vprogs\vprogs.plg
-if exist vsound\vsound.plg del /f /q vsound\vsound.plg
+if exist snd_al\snd_al.plg del /f /q snd_al\snd_al.plg
+if exist snd_dx\snd_dx.plg del /f /q snd_dx\snd_dx.plg
if exist xtools\xtools.plg del /f /q xtools\xtools.plg
echo Build succeeded!
diff --git a/server/ents/baseentity.cpp b/server/ents/baseentity.cpp
index 39b9d120..689148f9 100644
--- a/server/ents/baseentity.cpp
+++ b/server/ents/baseentity.cpp
@@ -288,8 +288,9 @@ void CBaseEntity :: ResetParent( void )
void CBaseEntity :: SetupPhysics( void )
{
//rebuild all parents
- if(pFlags & PF_LINKCHILD) LinkChild( this );
- if(m_physinit) return;
+ if( pFlags & PF_LINKCHILD ) LinkChild( this );
+
+ if( m_physinit ) return;
SetParent(); //set all parents
m_physinit = true;
PostSpawn();//post spawn
diff --git a/server/ents/baseinfo.cpp b/server/ents/baseinfo.cpp
index d6a3a77c..29baecc4 100644
--- a/server/ents/baseinfo.cpp
+++ b/server/ents/baseinfo.cpp
@@ -52,26 +52,31 @@ class CDecal : public CBaseEntity
public:
void KeyValue( KeyValueData *pkvd )
{
- if (FStrEq(pkvd->szKeyName, "texture"))
+ if( FStrEq( pkvd->szKeyName, "texture" ))
{
pev->skin = DECAL_INDEX( pkvd->szValue );
- if ( pev->skin >= 0 ) return;
+ if( pev->skin >= 0 ) return;
Msg( "Can't find decal %s\n", pkvd->szValue );
}
}
- void PostSpawn( void ) { if(FStringNull(pev->targetname))MakeDecal(); }
+ void PostSpawn( void ) { if( FStringNull( pev->targetname )) MakeDecal(); }
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { MakeDecal(); }
void MakeDecal( void )
{
if ( pev->skin < 0 ) { REMOVE_ENTITY(ENT(pev)); return; }
- TraceResult trace;
- int entityIndex, modelIndex;
- UTIL_TraceLine( pev->origin - Vector(5,5,5), pev->origin + Vector(5,5,5), ignore_monsters, ENT(pev), &trace );
- entityIndex = (short)ENTINDEX(trace.pHit);
- if ( entityIndex ) modelIndex = (int)VARS(trace.pHit)->modelindex;
+ TraceResult trace;
+ int entityIndex, modelIndex;
+
+ UTIL_TraceLine( pev->origin - Vector( 5, 5, 5 ), pev->origin + Vector( 5, 5, 5 ), ignore_monsters, ENT( pev ), &trace );
+
+ entityIndex = (short)ENTINDEX( trace.pHit );
+ if ( entityIndex ) modelIndex = (int)VARS( trace.pHit )->modelindex;
else modelIndex = 0;
- if(FStringNull(pev->targetname)) g_engfuncs.pfnStaticDecal( pev->origin, (int)pev->skin, entityIndex, modelIndex );
+ if( FStringNull( pev->targetname ))
+ {
+ g_engfuncs.pfnStaticDecal( pev->origin, (int)pev->skin, entityIndex, modelIndex );
+ }
else
{
MESSAGE_BEGIN( MSG_BROADCAST, gmsg.TempEntity );
@@ -81,7 +86,7 @@ public:
WRITE_COORD( pev->origin.z );
WRITE_SHORT( (int)pev->skin );
WRITE_SHORT( entityIndex );
- if(entityIndex) WRITE_SHORT( modelIndex );
+ if( entityIndex ) WRITE_SHORT( modelIndex );
MESSAGE_END();
}
diff --git a/server/monsters/player.cpp b/server/monsters/player.cpp
index 91471c39..a10ec504 100644
--- a/server/monsters/player.cpp
+++ b/server/monsters/player.cpp
@@ -402,7 +402,7 @@ void CBasePlayer :: TraceAttack( entvars_t *pevAttacker, float flDamage, Vector
if(bitsDamageType & DMG_NUCLEAR)
{
- m_FadeColor = Vector(255, 255, 255);
+ m_FadeColor = Vector( 255, 255, 255 );
m_FadeAlpha = 240;
m_iFadeFlags = 0;
m_iFadeTime = 25;
diff --git a/server/server.plg b/server/server.plg
deleted file mode 100644
index 35b71426..00000000
--- a/server/server.plg
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-Build Log
-
---------------------Configuration: server - Win32 Debug--------------------
-
-Command Lines
-
-
-
-Results
-server.dll - 0 error(s), 0 warning(s)
-
-
-
diff --git a/vsound/libogg.lib b/snd_al/libogg.lib
similarity index 100%
rename from vsound/libogg.lib
rename to snd_al/libogg.lib
diff --git a/vsound/s_export.c b/snd_al/s_export.c
similarity index 100%
rename from vsound/s_export.c
rename to snd_al/s_export.c
diff --git a/vsound/s_load.c b/snd_al/s_load.c
similarity index 87%
rename from vsound/s_load.c
rename to snd_al/s_load.c
index 75276201..55a657d8 100644
--- a/vsound/s_load.c
+++ b/snd_al/s_load.c
@@ -28,6 +28,7 @@ void S_SoundList_f( void )
{
sfx_t *sfx;
int i, samples = 0;
+ int totalSfx = 0;
Msg("\n");
Msg(" -samples -hz-- -format- -name--------\n");
@@ -35,46 +36,40 @@ void S_SoundList_f( void )
for( i = 0; i < s_numSfx; i++ )
{
sfx = &s_knownSfx[i];
- Msg("%4i: ", i);
-
if( sfx->loaded )
{
samples += sfx->samples;
- Msg("%8i ", sfx->samples);
- Msg("%5i ", sfx->rate);
+ Msg( "%8i ", sfx->samples );
+ Msg( "%5i ", sfx->rate );
switch( sfx->format )
{
- case AL_FORMAT_STEREO16: Msg("STEREO16 "); break;
- case AL_FORMAT_STEREO8: Msg("STEREO8 "); break;
- case AL_FORMAT_MONO16: Msg("MONO16 "); break;
- case AL_FORMAT_MONO8: Msg("MONO8 "); break;
- default: Msg("???????? "); break;
+ case AL_FORMAT_STEREO16: Msg( "STEREO16 " ); break;
+ case AL_FORMAT_STEREO8: Msg( "STEREO8 " ); break;
+ case AL_FORMAT_MONO16: Msg( "MONO16 " ); break;
+ case AL_FORMAT_MONO8: Msg( "MONO8 " ); break;
+ default: Msg( "???????? " ); break;
}
- if( sfx->name[0] == '#' ) Msg("%s", &sfx->name[1]);
- else Msg("sound/%s", sfx->name);
+ if( sfx->name[0] == '#' ) Msg( "%s", &sfx->name[1] );
+ else Msg( "sound/%s", sfx->name );
Msg( "\n" );
- }
- else
- {
- if( sfx->name[0] == '*' ) Msg(" placeholder %s\n", sfx->name);
- else Msg(" not loaded %s\n", sfx->name);
+ totalSfx++;
}
}
Msg("-------------------------------------------\n");
Msg("%i total samples\n", samples );
- Msg("%i total sounds\n", s_numSfx );
+ Msg("%i total sounds\n", totalSfx );
Msg("\n");
}
/*
- =======================================================================
+=======================================================================
WAV LOADING
- =======================================================================
+=======================================================================
*/
static byte *iff_data;
static byte *iff_dataPtr;
@@ -177,7 +172,7 @@ static bool S_LoadWAV( const char *name, byte **wav, wavinfo_t *info )
// dind "RIFF" chunk
S_FindChunk( "RIFF" );
- if(!(iff_dataPtr && !com.strncmp(iff_dataPtr+8, "WAVE", 4)))
+ if( !( iff_dataPtr && !com.strncmp( iff_dataPtr + 8, "WAVE", 4 )))
{
MsgDev( D_WARN, "S_LoadWAV: missing 'RIFF/WAVE' chunks (%s)\n", name );
Mem_Free( buffer );
@@ -186,7 +181,7 @@ static bool S_LoadWAV( const char *name, byte **wav, wavinfo_t *info )
// get "fmt " chunk
iff_data = iff_dataPtr + 12;
- S_FindChunk("fmt ");
+ S_FindChunk( "fmt " );
if( !iff_dataPtr )
{
MsgDev( D_WARN, "S_LoadWAV: missing 'fmt ' chunk (%s)\n", name );
@@ -497,11 +492,11 @@ S_LoadSound
*/
loadformat_t load_formats[] =
{
- {"sound/%s.%s", "ogg", S_LoadOGG},
- {"sound/%s.%s", "wav", S_LoadWAV},
- {"%s.%s", "ogg", S_LoadOGG},
- {"%s.%s", "wav", S_LoadWAV},
- {NULL, NULL}
+{ "sound/%s.%s", "ogg", S_LoadOGG },
+{ "sound/%s.%s", "wav", S_LoadWAV },
+{ "%s.%s", "ogg", S_LoadOGG },
+{ "%s.%s", "wav", S_LoadWAV },
+{ NULL, NULL }
};
bool S_LoadSound( sfx_t *sfx )
@@ -526,7 +521,7 @@ bool S_LoadSound( sfx_t *sfx )
Mem_Set( &info, 0, sizeof( info ));
// developer warning
- if( !anyformat ) MsgDev(D_NOTE, "Note: %s will be loading only with ext .%s\n", loadname, ext );
+ if( !anyformat ) MsgDev( D_NOTE, "Note: %s will be loading only with ext .%s\n", loadname, ext );
// now try all the formats in the selected list
for( format = load_formats; format->formatstring; format++ )
@@ -540,7 +535,7 @@ bool S_LoadSound( sfx_t *sfx )
}
sfx->default_sound = true;
- MsgDev(D_WARN, "FS_LoadSound: couldn't load %s\n", sfx->name );
+ MsgDev( D_WARN, "FS_LoadSound: couldn't load %s\n", sfx->name );
S_CreateDefaultSound( &data, &info );
info.loopstart = -1;
@@ -576,6 +571,7 @@ sfx_t *S_FindSound( const char *name )
return NULL;
}
+ // see if already loaded
for( i = 0; i < s_numSfx; i++ )
{
sfx = &s_knownSfx[i];
@@ -647,7 +643,7 @@ void S_EndRegistration( void )
// load everything in
for( i = 0, sfx = s_knownSfx; i < s_numSfx; i++, sfx++ )
{
- if( !sfx->name[0] )continue;
+ if( !sfx->name[0] ) continue;
S_LoadSound( sfx );
}
s_registering = false;
diff --git a/vsound/s_main.c b/snd_al/s_main.c
similarity index 91%
rename from vsound/s_main.c
rename to snd_al/s_main.c
index 0a8c0e3a..42847773 100644
--- a/vsound/s_main.c
+++ b/snd_al/s_main.c
@@ -13,8 +13,8 @@
static playSound_t s_playSounds[MAX_PLAYSOUNDS];
static playSound_t s_freePlaySounds;
static playSound_t s_pendingPlaySounds;
-static channel_t s_channels[MAX_CHANNELS];
-static listener_t s_listener;
+static channel_t s_channels[MAX_CHANNELS];
+static listener_t s_listener;
const guid_t DSPROPSETID_EAX20_ListenerProperties = {0x306a6a8, 0xb224, 0x11d2, {0x99, 0xe5, 0x0, 0x0, 0xe8, 0xd8, 0xc7, 0x22}};
const guid_t DSPROPSETID_EAX20_BufferProperties = {0x306a6a7, 0xb224, 0x11d2, {0x99, 0xe5, 0x0, 0x0, 0xe8, 0xd8, 0xc7, 0x22}};
@@ -350,6 +350,7 @@ static playSound_t *S_AllocPlaySound( void )
if( ps == &s_freePlaySounds )
return NULL; // No free playSounds
+ // unlink from freelist
ps->prev->next = ps->next;
ps->next->prev = ps->prev;
@@ -363,6 +364,7 @@ S_FreePlaySound
*/
static void S_FreePlaySound( playSound_t *ps )
{
+ // unlink from channel
ps->prev->next = ps->next;
ps->next->prev = ps->prev;
@@ -397,7 +399,7 @@ static void S_IssuePlaySounds( void )
ch = S_PickChannel( ps->entnum, ps->entchannel );
if(!ch)
{
- if( ps->sfx->name[0] == '#' ) MsgDev(D_ERROR, "dropped sound %s\n", &ps->sfx->name[1] );
+ if( ps->sfx->name[0] == '#' ) MsgDev( D_ERROR, "dropped sound %s\n", &ps->sfx->name[1] );
else MsgDev( D_ERROR, "dropped sound \"sound/%s\"\n", ps->sfx->name );
S_FreePlaySound( ps );
continue;
@@ -441,16 +443,16 @@ void S_StartSound( const vec3_t pos, int entnum, int channel, sound_t handle, fl
playSound_t *ps, *sort;
sfx_t *sfx = NULL;
- if(!al_state.initialized )
+ if( !al_state.initialized )
return;
sfx = S_GetSfxByHandle( handle );
if( !sfx ) return;
- // Make sure the sound is loaded
+ // make sure the sound is loaded
if( !S_LoadSound( sfx ))
return;
- // Allocate a playSound
+ // allocate a playSound
ps = S_AllocPlaySound();
if( !ps )
{
@@ -570,13 +572,13 @@ S_Update
Called once each time through the main loop
=================
*/
-void S_Update( int clientnum, const vec3_t position, const vec3_t velocity, const vec3_t at, const vec3_t up )
+void S_Update( int clientnum, const vec3_t position, const vec3_t velocity, const vec3_t axis[3], bool clear )
{
channel_t *ch;
int i;
if(!al_state.initialized ) return;
- //if( s_pause->integer ) return;
+// if( s_pause->integer || clear ) return;
// bump frame count
al_state.framecount++;
@@ -587,12 +589,12 @@ void S_Update( int clientnum, const vec3_t position, const vec3_t velocity, cons
VectorSet( s_listener.velocity, velocity[1], velocity[2], -velocity[0] );
// set listener orientation matrix
- s_listener.orientation[0] = at[1];
- s_listener.orientation[1] = -at[2];
- s_listener.orientation[2] = -at[0];
- s_listener.orientation[3] = up[1];
- s_listener.orientation[4] = -up[2];
- s_listener.orientation[5] = -up[0];
+ s_listener.orientation[0] = axis[0][1];
+ s_listener.orientation[1] = -axis[0][2];
+ s_listener.orientation[2] = -axis[0][0];
+ s_listener.orientation[3] = axis[2][1];
+ s_listener.orientation[4] = -axis[2][2];
+ s_listener.orientation[5] = -axis[2][0];
palListenerfv(AL_POSITION, s_listener.position);
palListenerfv(AL_VELOCITY, s_listener.velocity);
@@ -743,9 +745,11 @@ bool S_Init( void *hInst )
{
int num_mono_src, num_stereo_src;
+ Cmd_ExecuteString( "sndlatch\n" );
+
host_sound = Cvar_Get("host_sound", "1", CVAR_SYSTEMINFO, "enable sound system" );
- s_alDevice = Cvar_Get("s_device", "Generic Software", CVAR_LATCH|CVAR_ARCHIVE, "OpenAL current device name" );
- s_soundfx = Cvar_Get("s_soundfx", "1", CVAR_LATCH|CVAR_ARCHIVE, "allow OpenAl extensions" );
+ s_alDevice = Cvar_Get("s_device", "Generic Software", CVAR_LATCH_AUDIO|CVAR_ARCHIVE, "OpenAL current device name" );
+ s_soundfx = Cvar_Get("s_soundfx", "1", CVAR_LATCH_AUDIO|CVAR_ARCHIVE, "allow OpenAl extensions" );
s_check_errors = Cvar_Get("s_check_errors", "1", CVAR_ARCHIVE, "ignore audio engine errors" );
s_volume = Cvar_Get("s_volume", "1.0", CVAR_ARCHIVE, "sound volume" );
s_musicvolume = Cvar_Get("s_musicvolume", "1.0", CVAR_ARCHIVE, "background music volume" );
diff --git a/vsound/s_openal.c b/snd_al/s_openal.c
similarity index 96%
rename from vsound/s_openal.c
rename to snd_al/s_openal.c
index 0e8cbd0b..6474b7ef 100644
--- a/vsound/s_openal.c
+++ b/snd_al/s_openal.c
@@ -160,8 +160,8 @@ failed:
// release openal at all
Sys_FreeLibrary( &openal_dll );
- Mem_Set(&al_config, 0, sizeof(alconfig_t));
- Mem_Set(&al_state, 0, sizeof(alstate_t));
+ Mem_Set( &al_config, 0, sizeof( alconfig_t ));
+ Mem_Set( &al_state, 0, sizeof( alstate_t ));
return false;
}
@@ -331,7 +331,7 @@ static void S_InitExtensions( void )
bool S_Init_OpenAL( void )
{
- Sys_LoadLibrary( &openal_dll );
+ Sys_LoadLibrary( NULL, &openal_dll );
if( !openal_dll.link )
{
diff --git a/vsound/s_openal.h b/snd_al/s_openal.h
similarity index 100%
rename from vsound/s_openal.h
rename to snd_al/s_openal.h
diff --git a/vsound/s_stream.c b/snd_al/s_stream.c
similarity index 100%
rename from vsound/s_stream.c
rename to snd_al/s_stream.c
diff --git a/vsound/s_stream.h b/snd_al/s_stream.h
similarity index 100%
rename from vsound/s_stream.h
rename to snd_al/s_stream.h
diff --git a/vsound/vsound.dsp b/snd_al/snd_al.dsp
similarity index 75%
rename from vsound/vsound.dsp
rename to snd_al/snd_al.dsp
index 8d4e0ac8..db181710 100644
--- a/vsound/vsound.dsp
+++ b/snd_al/snd_al.dsp
@@ -1,24 +1,24 @@
-# Microsoft Developer Studio Project File - Name="vsound" - Package Owner=<4>
+# Microsoft Developer Studio Project File - Name="snd_al" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-CFG=vsound - Win32 Debug
+CFG=snd_al - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
-!MESSAGE NMAKE /f "vsound.mak".
+!MESSAGE NMAKE /f "snd_al.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
-!MESSAGE NMAKE /f "vsound.mak" CFG="vsound - Win32 Debug"
+!MESSAGE NMAKE /f "snd_al.mak" CFG="snd_al - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
-!MESSAGE "vsound - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "vsound - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "snd_al - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "snd_al - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
@@ -29,7 +29,7 @@ CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
-!IF "$(CFG)" == "vsound - Win32 Release"
+!IF "$(CFG)" == "snd_al - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
@@ -38,8 +38,8 @@ RSC=rc.exe
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "..\temp\vsound\!release"
-# PROP Intermediate_Dir "..\temp\vsound\!release"
+# PROP Output_Dir "..\temp\snd_al\!release"
+# PROP Intermediate_Dir "..\temp\snd_al\!release"
# PROP Ignore_Export_Lib 1
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PLATFORM_EXPORTS" /YX /FD /c
@@ -57,16 +57,16 @@ LINK32=link.exe
# ADD LINK32 libogg.lib vorbis.lib /nologo /dll /pdb:none /machine:I386 /nodefaultlib:"libcmt.lib" /opt:nowin98
# SUBTRACT LINK32 /profile
# Begin Custom Build
-TargetDir=\Xash3D\src_main\temp\vsound\!release
-InputPath=\Xash3D\src_main\temp\vsound\!release\vsound.dll
+TargetDir=\Xash3D\src_main\temp\snd_al\!release
+InputPath=\Xash3D\src_main\temp\snd_al\!release\snd_al.dll
SOURCE="$(InputPath)"
-"D:\Xash3D\bin\vsound.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- copy $(TargetDir)\vsound.dll "D:\Xash3D\bin\vsound.dll"
+"D:\Xash3D\bin\snd_al.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ copy $(TargetDir)\snd_al.dll "D:\Xash3D\bin\snd_al.dll"
# End Custom Build
-!ELSEIF "$(CFG)" == "vsound - Win32 Debug"
+!ELSEIF "$(CFG)" == "snd_al - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
@@ -75,8 +75,8 @@ SOURCE="$(InputPath)"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "..\temp\vsound\!debug"
-# PROP Intermediate_Dir "..\temp\vsound\!debug"
+# PROP Output_Dir "..\temp\snd_al\!debug"
+# PROP Intermediate_Dir "..\temp\snd_al\!debug"
# PROP Ignore_Export_Lib 1
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PLATFORM_EXPORTS" /YX /FD /GZ /c
@@ -94,12 +94,12 @@ LINK32=link.exe
# ADD LINK32 libogg.lib vorbis.lib /nologo /dll /debug /machine:I386 /nodefaultlib:"libcmt.lib" /pdbtype:sept
# SUBTRACT LINK32 /incremental:no /nodefaultlib
# Begin Custom Build
-TargetDir=\Xash3D\src_main\temp\vsound\!debug
-InputPath=\Xash3D\src_main\temp\vsound\!debug\vsound.dll
+TargetDir=\Xash3D\src_main\temp\snd_al\!debug
+InputPath=\Xash3D\src_main\temp\snd_al\!debug\snd_al.dll
SOURCE="$(InputPath)"
-"D:\Xash3D\bin\vsound.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- copy $(TargetDir)\vsound.dll "D:\Xash3D\bin\vsound.dll"
+"D:\Xash3D\bin\snd_al.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ copy $(TargetDir)\snd_al.dll "D:\Xash3D\bin\snd_al.dll"
# End Custom Build
@@ -107,8 +107,8 @@ SOURCE="$(InputPath)"
# Begin Target
-# Name "vsound - Win32 Release"
-# Name "vsound - Win32 Debug"
+# Name "snd_al - Win32 Release"
+# Name "snd_al - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
diff --git a/vsound/sound.h b/snd_al/sound.h
similarity index 93%
rename from vsound/sound.h
rename to snd_al/sound.h
index b1231f6a..b18643b9 100644
--- a/vsound/sound.h
+++ b/snd_al/sound.h
@@ -169,7 +169,7 @@ void S_Activate( bool active );
void S_SoundList_f( void );
bool S_CheckForErrors( void );
void S_StartSound(const vec3_t pos, int ent, int chan, sound_t sfx, float vol, float attn, float pitch, bool use_loop);
-void S_Update( int clientnum, const vec3_t pos, const vec3_t vel, const vec3_t at, const vec3_t up );
+void S_Update( int entnum, const vec3_t pos, const vec3_t vel, const vec3_t axis[3], bool clear );
void S_StreamRawSamples( int samples, int rate, int width, int channels, const byte *data );
bool S_AddLoopingSound( int entnum, sound_t handle, float volume, float attn );
void S_StartBackgroundTrack( const char *intro, const char *loop );
diff --git a/vsound/vorbis.lib b/snd_al/vorbis.lib
similarity index 100%
rename from vsound/vorbis.lib
rename to snd_al/vorbis.lib
diff --git a/snd_dx/s_direct.c b/snd_dx/s_direct.c
new file mode 100644
index 00000000..a187fa0c
--- /dev/null
+++ b/snd_dx/s_direct.c
@@ -0,0 +1,743 @@
+//=======================================================================
+// Copyright XashXT Group 2009 й
+// s_direct.c - sound hardware output
+//=======================================================================
+
+#include
+#include "sound.h"
+
+#define iDirectSoundCreate( a, b, c ) pDirectSoundCreate( a, b, c )
+
+static HRESULT ( _stdcall *pDirectSoundCreate)(GUID* lpGUID, LPDIRECTSOUND* lplpDS, IUnknown* pUnkOuter );
+
+static dllfunc_t dsound_funcs[] =
+{
+{ "DirectSoundCreate", (void **) &pDirectSoundCreate },
+{ NULL, NULL }
+};
+
+dll_info_t dsound_dll = { "dsound.dll", dsound_funcs, NULL, NULL, NULL, false, 0, 0 };
+
+// 64K is > 1 second at 16-bit, 22050 Hz
+#define WAV_BUFFERS 64
+#define WAV_MASK 0x3F
+#define WAV_BUFFER_SIZE 0x0400
+#define SECONDARY_BUFFER_SIZE 0x10000
+
+typedef enum
+{
+ SIS_SUCCESS,
+ SIS_FAILURE,
+ SIS_NOTAVAIL
+} si_state_t;
+
+cvar_t *s_wavonly;
+
+static HWND snd_hwnd;
+static bool dsound_init;
+static bool wav_init;
+static bool snd_firsttime = true, snd_isdirect, snd_iswave;
+static bool primary_format_set;
+static int snd_buffer_count = 0;
+static int sample16;
+static int snd_sent, snd_completed;
+
+/*
+=======================================================================
+Global variables. Must be visible to window-procedure function
+so it can unlock and free the data block after it has been played.
+=======================================================================
+*/
+DWORD locksize;
+HANDLE hData;
+HPSTR lpData, lpData2;
+HGLOBAL hWaveHdr;
+LPWAVEHDR lpWaveHdr;
+HWAVEOUT hWaveOut;
+WAVEOUTCAPS wavecaps;
+DWORD gSndBufSize;
+MMTIME mmstarttime;
+LPDIRECTSOUNDBUFFER pDSBuf, pDSPBuf;
+LPDIRECTSOUND pDS;
+
+bool SNDDMA_InitDirect( void *hInst );
+bool SNDDMA_InitWav( void );
+void SNDDMA_FreeSound( void );
+
+static const char *DSoundError( int error )
+{
+ switch( error )
+ {
+ case DSERR_BUFFERLOST:
+ return "DSERR_BUFFERLOST";
+ case DSERR_INVALIDCALL:
+ return "DSERR_INVALIDCALLS";
+ case DSERR_INVALIDPARAM:
+ return "DSERR_INVALIDPARAM";
+ case DSERR_PRIOLEVELNEEDED:
+ return "DSERR_PRIOLEVELNEEDED";
+ }
+ return "Unknown Error";
+}
+
+/*
+==================
+DS_CreateBuffers
+==================
+*/
+static bool DS_CreateBuffers( void *hInst )
+{
+ DSBUFFERDESC dsbuf;
+ DSBCAPS dsbcaps;
+ WAVEFORMATEX pformat, format;
+
+ Mem_Set( &format, 0, sizeof( format ));
+
+ format.wFormatTag = WAVE_FORMAT_PCM;
+ format.nChannels = dma.channels;
+ format.wBitsPerSample = dma.samplebits;
+ format.nSamplesPerSec = dma.speed;
+ format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8;
+ format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
+ format.cbSize = 0;
+
+ MsgDev( D_NOTE, "DS_CreateBuffers: initialize\n" );
+
+ MsgDev( D_NOTE, "DS_CreateBuffers: setting EXCLUSIVE coop level " );
+ if( DS_OK != pDS->lpVtbl->SetCooperativeLevel( pDS, hInst, DSSCL_EXCLUSIVE ))
+ {
+ MsgDev( D_NOTE, "- failed\n" );
+ SNDDMA_FreeSound();
+ return false;
+ }
+ MsgDev( D_NOTE, "- ok\n" );
+
+ // get access to the primary buffer, if possible, so we can set the sound hardware format
+ Mem_Set( &dsbuf, 0, sizeof( dsbuf ));
+ dsbuf.dwSize = sizeof( DSBUFFERDESC );
+ dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER;
+ dsbuf.dwBufferBytes = 0;
+ dsbuf.lpwfxFormat = NULL;
+
+ Mem_Set( &dsbcaps, 0, sizeof( dsbcaps ));
+ dsbcaps.dwSize = sizeof( dsbcaps );
+ primary_format_set = false;
+
+ MsgDev( D_NOTE, "DS_CreateBuffers: creating primary buffer " );
+ if( pDS->lpVtbl->CreateSoundBuffer( pDS, &dsbuf, &pDSPBuf, NULL ) == DS_OK )
+ {
+ pformat = format;
+
+ MsgDev( D_NOTE, "- ok\n" );
+ if( pDSPBuf->lpVtbl->SetFormat( pDSPBuf, &pformat ) != DS_OK )
+ {
+ if( snd_firsttime )
+ MsgDev( D_NOTE, "DS_CreateBuffers: setting primary sound format - failed\n" );
+ }
+ else
+ {
+ if( snd_firsttime )
+ MsgDev( D_NOTE, "DS_CreateBuffers: setting primary sound format - ok\n" );
+ primary_format_set = true;
+ }
+ }
+ else MsgDev( D_NOTE, "- failed\n" );
+
+ if( !primary_format_set || !s_primary->integer )
+ {
+ // create the secondary buffer we'll actually work with
+ Mem_Set( &dsbuf, 0, sizeof( dsbuf ));
+ dsbuf.dwSize = sizeof( DSBUFFERDESC );
+ dsbuf.dwFlags = (DSBCAPS_CTRLFREQUENCY|DSBCAPS_LOCSOFTWARE);
+ dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE;
+ dsbuf.lpwfxFormat = &format;
+
+ Mem_Set( &dsbcaps, 0, sizeof( dsbcaps ));
+ dsbcaps.dwSize = sizeof( dsbcaps );
+
+ MsgDev( D_NOTE, "DS_CreateBuffers: creating secondary buffer " );
+ if( pDS->lpVtbl->CreateSoundBuffer( pDS, &dsbuf, &pDSBuf, NULL ) == DS_OK )
+ {
+ MsgDev( D_NOTE, "- ok\n" );
+ }
+ else
+ {
+ // couldn't get hardware, fallback to software.
+ dsbuf.dwFlags = (DSBCAPS_LOCSOFTWARE|DSBCAPS_GETCURRENTPOSITION2);
+ if( pDS->lpVtbl->CreateSoundBuffer( pDS, &dsbuf, &pDSBuf, NULL ) != DS_OK )
+ {
+ MsgDev( D_NOTE, "- failed\n" );
+ SNDDMA_FreeSound ();
+ return false;
+ }
+ MsgDev( D_INFO, "- failed. forced to software\n" );
+ }
+
+ dma.channels = format.nChannels;
+ dma.samplebits = format.wBitsPerSample;
+ dma.speed = format.nSamplesPerSec;
+
+ if( pDSBuf->lpVtbl->GetCaps( pDSBuf, &dsbcaps ) != DS_OK )
+ {
+ MsgDev( D_ERROR, "DS_CreateBuffers: GetCaps failed\n");
+ SNDDMA_FreeSound ();
+ return false;
+ }
+ MsgDev( D_NOTE, "DS_CreateBuffers: using secondary sound buffer\n" );
+ }
+ else
+ {
+ MsgDev( D_NOTE, "DS_CreateBuffers: using primary sound buffer\n" );
+ MsgDev( D_NOTE, "DS_CreateBuffers: setting WRITEPRIMARY coop level " );
+ if( pDS->lpVtbl->SetCooperativeLevel( pDS, hInst, DSSCL_WRITEPRIMARY ) != DS_OK )
+ {
+ MsgDev( D_NOTE, "- failed\n" );
+ SNDDMA_FreeSound ();
+ return false;
+ }
+ MsgDev( D_NOTE, "- ok\n" );
+
+ if( pDSPBuf->lpVtbl->GetCaps( pDSPBuf, &dsbcaps ) != DS_OK )
+ {
+ MsgDev( D_ERROR, "DS_CreateBuffers: GetCaps failed\n");
+ SNDDMA_FreeSound ();
+ return false;
+ }
+ pDSBuf = pDSPBuf;
+ }
+
+ // make sure mixer is active
+ if( pDSBuf->lpVtbl->Play( pDSBuf, 0, 0, DSBPLAY_LOOPING ) != DS_OK )
+ {
+ MsgDev( D_ERROR, "DS_CreateBuffers: looped sound play failed\n" );
+ SNDDMA_FreeSound ();
+ return false;
+ }
+
+ // we don't want anyone to access the buffer directly w/o locking it first
+ lpData = NULL;
+ dma.samplepos = 0;
+ snd_hwnd = (HWND)hInst;
+ gSndBufSize = dsbcaps.dwBufferBytes;
+ dma.samples = gSndBufSize / (dma.samplebits / 8 );
+ dma.submission_chunk = 1;
+ dma.buffer = (byte *)lpData;
+ sample16 = (dma.samplebits / 8) - 1;
+
+ SNDDMA_BeginPainting();
+ if( dma.buffer ) Mem_Set( dma.buffer, 0, dma.samples * dma.samplebits / 8 );
+ SNDDMA_Submit();
+
+ return true;
+}
+
+/*
+==================
+DS_DestroyBuffers
+==================
+*/
+static void DS_DestroyBuffers( void )
+{
+ MsgDev( D_NOTE, "DS_DestroyBuffers: shutdown\n" );
+
+ if( pDS )
+ {
+ MsgDev( D_NOTE, "DS_DestroyBuffers: setting NORMAL coop level\n" );
+ pDS->lpVtbl->SetCooperativeLevel( pDS, snd_hwnd, DSSCL_NORMAL );
+ }
+
+ if( pDSBuf )
+ {
+ MsgDev( D_NOTE, "DS_DestroyBuffers: stopping and releasing sound buffer\n" );
+ pDSBuf->lpVtbl->Stop( pDSBuf );
+ pDSBuf->lpVtbl->Release( pDSBuf );
+ }
+
+ // only release primary buffer if it's not also the mixing buffer we just released
+ if( pDSPBuf && ( pDSBuf != pDSPBuf ))
+ {
+ MsgDev( D_NOTE, "DS_DestroyBuffers: releasing primary buffer\n" );
+ pDSPBuf->lpVtbl->Release( pDSPBuf );
+ }
+
+ pDSBuf = NULL;
+ pDSPBuf = NULL;
+ dma.buffer = NULL;
+}
+
+/*
+==================
+SNDDMA_FreeSound
+==================
+*/
+void SNDDMA_FreeSound( void )
+{
+ int i;
+
+ if( pDS )
+ {
+ DS_DestroyBuffers();
+ pDS->lpVtbl->Release( pDS );
+ Sys_FreeLibrary( &dsound_dll );
+ }
+
+ if( hWaveOut )
+ {
+ waveOutReset( hWaveOut );
+
+ if( lpWaveHdr )
+ {
+ for( i = 0; i < WAV_BUFFERS; i++ )
+ waveOutUnprepareHeader( hWaveOut, lpWaveHdr + i, sizeof( WAVEHDR ));
+ }
+
+ waveOutClose( hWaveOut );
+
+ if( hWaveHdr )
+ {
+ GlobalUnlock( hWaveHdr );
+ GlobalFree( hWaveHdr );
+ }
+
+ if( hData )
+ {
+ GlobalUnlock( hData );
+ GlobalFree( hData );
+ }
+
+ }
+
+ pDS = NULL;
+ pDSBuf = NULL;
+ pDSPBuf = NULL;
+ hWaveOut = 0;
+ hData = 0;
+ hWaveHdr = 0;
+ lpData = NULL;
+ lpWaveHdr = NULL;
+ dsound_init = false;
+ wav_init = false;
+}
+
+/*
+==================
+SNDDMA_InitDirect
+
+Direct-Sound support
+==================
+*/
+si_state_t SNDDMA_InitDirect( void *hInst )
+{
+ DSCAPS dscaps;
+ HRESULT hresult;
+
+ dma.channels = 2;
+ dma.samplebits = 16;
+
+ switch( s_khz->integer )
+ {
+ case 44: dma.speed = 44100; break;
+ case 22: dma.speed = 22050; break;
+ default: dma.speed = 11025; break;
+ }
+
+ MsgDev( D_NOTE, "SNDDMA_InitDirect: initializing DirectSound ");
+
+ if ( !dsound_dll.link )
+ {
+ if( !Sys_LoadLibrary( NULL, &dsound_dll ))
+ {
+ MsgDev( D_NOTE, "- failed\n" );
+ return SIS_FAILURE;
+ }
+ MsgDev( D_NOTE, "- ok\n" );
+ }
+
+ MsgDev( D_NOTE, "SNDDMA_InitDirect: creating DS object " );
+ if(( hresult = iDirectSoundCreate( NULL, &pDS, NULL )) != DS_OK )
+ {
+ if( hresult != DSERR_ALLOCATED )
+ {
+ MsgDev( D_NOTE, "- failed\n" );
+ return SIS_FAILURE;
+ }
+
+ MsgDev( D_NOTE, "- failed, hardware already in use\n" );
+ return SIS_NOTAVAIL;
+ }
+
+ MsgDev( D_NOTE, "- ok\n" );
+ dscaps.dwSize = sizeof( dscaps );
+
+ if( pDS->lpVtbl->GetCaps( pDS, &dscaps ) != DS_OK )
+ MsgDev( D_ERROR, "SNDDMA_InitDirect: GetCaps failed\n");
+
+ if( dscaps.dwFlags & DSCAPS_EMULDRIVER )
+ {
+ MsgDev( D_ERROR, "SNDDMA_InitDirect: no DSound driver found\n" );
+ SNDDMA_FreeSound();
+ return SIS_FAILURE;
+ }
+
+ if( !DS_CreateBuffers( hInst ))
+ return SIS_FAILURE;
+
+ dsound_init = true;
+
+ return SIS_SUCCESS;
+}
+
+
+/*
+==================
+SNDDM_InitWav
+
+Crappy windows multimedia base
+==================
+*/
+si_state_t SNDDMA_InitWav( void )
+{
+ WAVEFORMATEX format;
+ HRESULT hr;
+ int i;
+
+ snd_sent = 0;
+ snd_completed = 0;
+
+ dma.channels = 2;
+ dma.samplebits = 16;
+
+ switch( s_khz->integer )
+ {
+ case 44: dma.speed = 44100; break;
+ case 22: dma.speed = 22050; break;
+ default: dma.speed = 11025; break;
+ }
+
+ Mem_Set( &format, 0, sizeof( format ));
+ format.wFormatTag = WAVE_FORMAT_PCM;
+ format.nChannels = dma.channels;
+ format.wBitsPerSample = dma.samplebits;
+ format.nSamplesPerSec = dma.speed;
+ format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8;
+ format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
+ format.cbSize = 0;
+
+ // open a waveform device for output using window callback.
+ MsgDev( D_NOTE, "SNDDMA_InitWav: initializing wave sound " );
+ if((hr = waveOutOpen((LPHWAVEOUT)&hWaveOut, WAVE_MAPPER, &format, 0, 0, CALLBACK_NULL)) != MMSYSERR_NOERROR )
+ {
+ if( hr != MMSYSERR_ALLOCATED )
+ {
+ MsgDev( D_NOTE, "- failed\n" );
+ return SIS_FAILURE;
+ }
+
+ MsgDev( D_NOTE, "- failed, hardware already in use\n" );
+ return SIS_NOTAVAIL;
+ }
+
+ MsgDev( D_NOTE, "- ok\n" );
+
+ // allocate and lock memory for the waveform data. The memory
+ // for waveform data must be globally allocated with
+ // GMEM_MOVEABLE and GMEM_SHARE flags.
+
+ gSndBufSize = WAV_BUFFERS * WAV_BUFFER_SIZE;
+ hData = GlobalAlloc( GMEM_MOVEABLE|GMEM_SHARE, gSndBufSize );
+ if( !hData )
+ {
+ SNDDMA_FreeSound ();
+ return SIS_FAILURE;
+ }
+
+ lpData = GlobalLock( hData );
+ if( !lpData )
+ {
+ SNDDMA_FreeSound ();
+ return SIS_FAILURE;
+ }
+
+ Mem_Set( lpData, 0, gSndBufSize );
+
+ // Allocate and lock memory for the header. This memory must
+ // also be globally allocated with GMEM_MOVEABLE and
+ // GMEM_SHARE flags.
+ hWaveHdr = GlobalAlloc( GMEM_MOVEABLE|GMEM_SHARE, (DWORD)sizeof( WAVEHDR ) * WAV_BUFFERS );
+
+ if( hWaveHdr == NULL )
+ {
+ SNDDMA_FreeSound ();
+ return SIS_FAILURE;
+ }
+
+ lpWaveHdr = (LPWAVEHDR)GlobalLock( hWaveHdr );
+
+ if( lpWaveHdr == NULL )
+ {
+ SNDDMA_FreeSound();
+ return SIS_FAILURE;
+ }
+
+ Mem_Set( lpWaveHdr, 0, sizeof( WAVEHDR ) * WAV_BUFFERS );
+
+ // After allocation, set up and prepare headers.
+ for( i = 0; i < WAV_BUFFERS; i++ )
+ {
+ lpWaveHdr[i].dwBufferLength = WAV_BUFFER_SIZE;
+ lpWaveHdr[i].lpData = lpData + i * WAV_BUFFER_SIZE;
+
+ if( waveOutPrepareHeader( hWaveOut, lpWaveHdr+i, sizeof( WAVEHDR )) != MMSYSERR_NOERROR )
+ {
+ SNDDMA_FreeSound();
+ return SIS_FAILURE;
+ }
+ }
+
+ dma.samplepos = 0;
+ dma.samples = gSndBufSize / ( dma.samplebits / 8 );
+ dma.submission_chunk = 512;
+ dma.buffer = (byte *)lpData;
+ sample16 = (dma.samplebits / 8) - 1;
+ wav_init = true;
+
+ return SIS_SUCCESS;
+}
+
+/*
+==================
+SNDDMA_Init
+
+Try to find a sound device to mix for.
+Returns false if nothing is found.
+==================
+*/
+int SNDDMA_Init( void *hInst )
+{
+ si_state_t stat = SIS_FAILURE; // assume DirectSound won't initialize
+
+ Mem_Set( &dma, 0, sizeof( dma ));
+
+ s_wavonly = Cvar_Get( "s_wavonly", "0", CVAR_LATCH_AUDIO|CVAR_ARCHIVE, "force to use WaveOutput only" );
+ dsound_init = wav_init = 0;
+
+ // init DirectSound
+ if( !s_wavonly->integer )
+ {
+ if( snd_firsttime || snd_isdirect )
+ {
+ stat = SNDDMA_InitDirect( hInst );
+
+ if( stat == SIS_SUCCESS )
+ {
+ snd_isdirect = true;
+
+ if( snd_firsttime )
+ MsgDev( D_INFO, "Audio: DirectSound\n" );
+ }
+ else snd_isdirect = false;
+ }
+ }
+
+ // if DirectSound didn't succeed in initializing, try to initialize
+ // waveOut sound, unless DirectSound failed because the hardware is
+ // already allocated (in which case the user has already chosen not
+ // to have sound)
+ if( !dsound_init && ( stat != SIS_NOTAVAIL ))
+ {
+ if( snd_firsttime || snd_iswave )
+ {
+ stat = SNDDMA_InitWav();
+
+ if( stat == SIS_SUCCESS )
+ {
+ snd_iswave = true;
+ if( snd_firsttime )
+ MsgDev( D_INFO, "Audio: WaveOutput\n" );
+ }
+ else snd_iswave = false;
+ }
+ }
+ snd_buffer_count = 1;
+
+ if( !dsound_init && !wav_init )
+ {
+ if( snd_firsttime )
+ MsgDev( D_ERROR, "SNDDMA_Init: can't initialize sound device\n" );
+ return false;
+ }
+
+ snd_firsttime = false;
+ return true;
+}
+
+/*
+==============
+SNDDMA_GetDMAPos
+
+return the current sample position (in mono samples read)
+inside the recirculating dma buffer, so the mixing code will know
+how many sample are required to fill it up.
+===============
+*/
+int SNDDMA_GetDMAPos( void )
+{
+ int s;
+
+ if( dsound_init )
+ {
+ MMTIME mmtime;
+ DWORD dwWrite;
+
+ mmtime.wType = TIME_SAMPLES;
+ pDSBuf->lpVtbl->GetCurrentPosition( pDSBuf, &mmtime.u.sample, &dwWrite );
+ s = mmtime.u.sample - mmstarttime.u.sample;
+ }
+ else if( wav_init )
+ {
+ s = snd_sent * WAV_BUFFER_SIZE;
+ }
+
+
+ s >>= sample16;
+ s &= (dma.samples - 1);
+
+ return s;
+}
+
+/*
+==============
+SNDDMA_BeginPainting
+
+Makes sure dma.buffer is valid
+===============
+*/
+void SNDDMA_BeginPainting( void )
+{
+ int reps;
+ DWORD dwSize2;
+ DWORD *pbuf, *pbuf2;
+ HRESULT hr;
+ DWORD dwStatus;
+
+ if( !pDSBuf ) return;
+
+ // if the buffer was lost or stopped, restore it and/or restart it
+ if( pDSBuf->lpVtbl->GetStatus( pDSBuf, &dwStatus ) != DS_OK )
+ MsgDev( D_WARN, "SNDDMA_BeginPainting: 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 );
+
+ // lock the dsound buffer
+ dma.buffer = NULL;
+ reps = 0;
+
+ while(( hr = pDSBuf->lpVtbl->Lock( pDSBuf, 0, gSndBufSize, &pbuf, &locksize, &pbuf2, &dwSize2, 0 )) != DS_OK )
+ {
+ if( hr != DSERR_BUFFERLOST )
+ {
+ MsgDev( D_ERROR, "S_TransferStereo16: lock failed with error '%s'\n", DSoundError( hr ));
+ S_Shutdown ();
+ return;
+ }
+ else pDSBuf->lpVtbl->Restore( pDSBuf );
+
+ if( ++reps > 2 ) return;
+ }
+ dma.buffer = (byte *)pbuf;
+}
+
+/*
+==============
+SNDDMA_Submit
+
+Send sound to device if buffer isn't really the dma buffer
+Also unlocks the dsound buffer
+===============
+*/
+void SNDDMA_Submit( void )
+{
+ LPWAVEHDR h;
+ int wResult;
+
+ if( !dma.buffer )
+ return;
+
+ // unlock the dsound buffer
+ if( pDSBuf ) pDSBuf->lpVtbl->Unlock( pDSBuf, dma.buffer, locksize, NULL, 0 );
+
+ if( !wav_init ) return;
+
+ // find which sound blocks have completed
+ while( 1 )
+ {
+ if( snd_completed == snd_sent )
+ break;
+
+ if(!( lpWaveHdr[snd_completed & WAV_MASK].dwFlags & WHDR_DONE ))
+ break;
+ snd_completed++; // this buffer has been played
+ }
+
+ // submit a few new sound blocks
+ while(((snd_sent - snd_completed) >> sample16 ) < 8 )
+ {
+ h = lpWaveHdr + ( snd_sent & WAV_MASK );
+
+ if( paintedtime / 256 <= snd_sent )
+ break;
+ snd_sent++;
+
+ // Now the data block can be sent to the output device. The
+ // waveOutWrite function returns immediately and waveform
+ // data is sent to the output device in the background.
+ wResult = waveOutWrite( hWaveOut, h, sizeof( WAVEHDR ));
+
+ if( wResult != MMSYSERR_NOERROR )
+ {
+ MsgDev( D_ERROR, "S_TransferStereo16: failed to write block to device\n" );
+ SNDDMA_FreeSound ();
+ return;
+ }
+ }
+}
+
+/*
+==============
+SNDDMA_Shutdown
+
+Reset the sound device for exiting
+===============
+*/
+void SNDDMA_Shutdown( void )
+{
+ SNDDMA_FreeSound();
+}
+
+
+/*
+===========
+S_Activate
+
+Called when the main window gains or loses focus.
+The window have been destroyed and recreated
+between a deactivate and an activate.
+===========
+*/
+void S_Activate( bool active )
+{
+ if( active )
+ {
+ if( pDS && snd_hwnd && snd_isdirect )
+ DS_CreateBuffers( snd_hwnd );
+ }
+ else
+ {
+ if( pDS && snd_hwnd && snd_isdirect )
+ DS_DestroyBuffers();
+ }
+}
\ No newline at end of file
diff --git a/snd_dx/s_export.c b/snd_dx/s_export.c
new file mode 100644
index 00000000..dae202cf
--- /dev/null
+++ b/snd_dx/s_export.c
@@ -0,0 +1,52 @@
+//=======================================================================
+// Copyright XashXT Group 2007 й
+// s_export.c - sound library main
+//=======================================================================
+
+#include "sound.h"
+
+vsound_imp_t si;
+stdlib_api_t com;
+byte *sndpool;
+
+vsound_exp_t DLLEXPORT *CreateAPI( stdlib_api_t *input, vsound_imp_t *engfuncs )
+{
+ static vsound_exp_t snd;
+
+ com = *input;
+
+ // Sys_LoadLibrary can create fake instance, to check
+ // api version and api size, but second argument will be 0
+ // and always make exception, run simply check for avoid it
+ if( engfuncs ) si = *engfuncs;
+
+ // generic functions
+ snd.api_size = sizeof( vsound_exp_t );
+ snd.com_size = sizeof( stdlib_api_t );
+
+ snd.Init = S_Init;
+ snd.Shutdown = S_Shutdown;
+
+ // sound manager
+ snd.BeginRegistration = S_BeginRegistration;
+ snd.RegisterSound = S_RegisterSound;
+ snd.EndRegistration = S_EndRegistration;
+
+ snd.StartSound = S_StartSound;
+ snd.StreamRawSamples = S_StreamRawSamples;
+ snd.AddLoopingSound = S_AddLoopingSound;
+ snd.StartLocalSound = S_StartLocalSound;
+ snd.StartBackgroundTrack = S_StartBackgroundTrack;
+ snd.StopBackgroundTrack = S_StopBackgroundTrack;
+
+ snd.StartStreaming = S_StartStreaming;
+ snd.StopStreaming = S_StopStreaming;
+
+ snd.Frame = S_Update;
+ snd.StopAllSounds = S_StopAllSounds;
+ snd.FreeSounds = S_FreeSounds;
+
+ snd.Activate = S_Activate;
+
+ return &snd;
+}
\ No newline at end of file
diff --git a/snd_dx/s_load.c b/snd_dx/s_load.c
new file mode 100644
index 00000000..ec46ebe3
--- /dev/null
+++ b/snd_dx/s_load.c
@@ -0,0 +1,609 @@
+//=======================================================================
+// Copyright XashXT Group 2007 й
+// s_load.c - sound managment
+//=======================================================================
+
+#include "sound.h"
+#include "byteorder.h"
+
+// during registration it is possible to have more sounds
+// than could actually be referenced during gameplay,
+// because we don't want to free anything until we are
+// sure we won't need it.
+#define MAX_SFX 4096
+
+static sfx_t s_knownSfx[MAX_SFX];
+static int s_numSfx = 0;
+bool s_registering = false;
+int s_registration_sequence = 0;
+
+typedef struct loadformat_s
+{
+ char *formatstring;
+ char *ext;
+ bool (*loadfunc)( const char *name, byte **wav, wavinfo_t *info );
+} loadformat_t;
+
+/*
+=================
+S_SoundList_f
+=================
+*/
+void S_SoundList_f( void )
+{
+ int i;
+ sfx_t *sfx;
+ sfxcache_t *sc;
+ int size, totalSfx = 0;
+ int totalSize = 0;
+
+ for( i = 0, sfx = s_knownSfx; i < s_numSfx; i++, sfx++ )
+ {
+ if( !sfx->registration_sequence )
+ continue;
+
+ sc = sfx->cache;
+ if( sc )
+ {
+ size = sc->length * sc->width * (sc->stereo + 1);
+ totalSize += size;
+ if( sc->loopstart >= 0 ) Msg( "L" );
+ else Msg( " " );
+
+ if( sfx->name[0] == '#' )
+ Msg( " (%2db) %s : %s\n", sc->width * 8, memprint( size ), &sfx->name[1] );
+ else Msg( " (%2db) %s : sound/%s\n", sc->width * 8, memprint( size ), sfx->name );
+ totalSfx++;
+ }
+ }
+
+ Msg("-------------------------------------------\n");
+ Msg("%i total sounds\n", totalSfx );
+ Msg("%s total memory\n", memprint( totalSize ));
+ Msg("\n");
+}
+
+/*
+================
+S_ResampleSfx
+================
+*/
+void S_ResampleSfx( sfx_t *sfx, int inrate, int inwidth, byte *data )
+{
+ float stepscale;
+ int outcount, srcsample;
+ int i, sample, samplefrac, fracstep;
+ sfxcache_t *sc;
+
+ if( !sfx ) return;
+ sc = sfx->cache;
+ if( !sc ) return;
+
+ stepscale = (float)inrate / dma.speed; // this is usually 0.5, 1, or 2
+
+ outcount = sc->length / stepscale;
+ sc->length = outcount;
+ if( sc->loopstart != -1 )
+ sc->loopstart = sc->loopstart / stepscale;
+
+ sc->speed = dma.speed;
+ if( s_loadas8bit->integer )
+ sc->width = 1;
+ else sc->width = inwidth;
+ sc->stereo = 0;
+
+ // resample / decimate to the current source rate
+ if( stepscale == 1 && inwidth == 1 && sc->width == 1 )
+ {
+ // fast special case
+ for( i = 0; i < outcount; i++ )
+ ((signed char *)sc->data)[i] = (int)((unsigned char)(data[i]) - 128);
+ }
+ else
+ {
+ // general case
+ samplefrac = 0;
+ fracstep = stepscale * 256;
+ for( i = 0; i < outcount; i++ )
+ {
+ srcsample = samplefrac >> 8;
+ samplefrac += fracstep;
+
+ if( inwidth == 2 ) sample = LittleShort(((short *)data)[srcsample] );
+ else sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8;
+
+ if( sc->width == 2 ) ((short *)sc->data)[i] = sample;
+ else ((signed char *)sc->data)[i] = sample >> 8;
+ }
+ }
+}
+
+/*
+===============================================================================
+
+WAV loading
+
+===============================================================================
+*/
+static byte *iff_data;
+static byte *iff_dataPtr;
+static byte *iff_end;
+static byte *iff_lastChunk;
+static int iff_chunkLen;
+
+/*
+=================
+S_GetLittleShort
+=================
+*/
+static short S_GetLittleShort( void )
+{
+ short val = 0;
+
+ val += (*(iff_dataPtr+0) << 0);
+ val += (*(iff_dataPtr+1) << 8);
+ iff_dataPtr += 2;
+
+ return val;
+}
+
+/*
+=================
+S_GetLittleLong
+=================
+*/
+static int S_GetLittleLong( void )
+{
+ int val = 0;
+
+ val += (*(iff_dataPtr+0) << 0);
+ val += (*(iff_dataPtr+1) << 8);
+ val += (*(iff_dataPtr+2) << 16);
+ val += (*(iff_dataPtr+3) << 24);
+ iff_dataPtr += 4;
+
+ return val;
+}
+
+/*
+=================
+S_FindNextChunk
+=================
+*/
+static void S_FindNextChunk( const char *name )
+{
+ while( 1 )
+ {
+ iff_dataPtr = iff_lastChunk;
+ if( iff_dataPtr >= iff_end )
+ {
+ // didn't find the chunk
+ iff_dataPtr = NULL;
+ return;
+ }
+
+ iff_dataPtr += 4;
+ iff_chunkLen = S_GetLittleLong();
+ if (iff_chunkLen < 0)
+ {
+ iff_dataPtr = NULL;
+ return;
+ }
+
+ iff_dataPtr -= 8;
+ iff_lastChunk = iff_dataPtr + 8 + ((iff_chunkLen + 1) & ~1);
+ if(!com.strncmp( iff_dataPtr, name, 4 ))
+ return;
+ }
+}
+
+/*
+=================
+S_FindChunk
+=================
+*/
+static void S_FindChunk( const char *name )
+{
+ iff_lastChunk = iff_data;
+ S_FindNextChunk( name );
+}
+
+/*
+=================
+S_LoadWAV
+=================
+*/
+static bool S_LoadWAV( const char *name, byte **wav, wavinfo_t *info )
+{
+ byte *buffer, *out;
+ int length, samples;
+
+ buffer = FS_LoadFile( name, &length );
+ if( !buffer ) return false;
+
+ iff_data = buffer;
+ iff_end = buffer + length;
+
+ // dind "RIFF" chunk
+ S_FindChunk( "RIFF" );
+ if( !( iff_dataPtr && !com.strncmp( iff_dataPtr + 8, "WAVE", 4 )))
+ {
+ MsgDev( D_WARN, "S_LoadWAV: missing 'RIFF/WAVE' chunks (%s)\n", name );
+ Mem_Free( buffer );
+ return false;
+ }
+
+ // get "fmt " chunk
+ iff_data = iff_dataPtr + 12;
+ S_FindChunk( "fmt " );
+ if( !iff_dataPtr )
+ {
+ MsgDev( D_WARN, "S_LoadWAV: missing 'fmt ' chunk (%s)\n", name );
+ Mem_Free( buffer );
+ return false;
+ }
+
+ iff_dataPtr += 8;
+ if( S_GetLittleShort() != 1 )
+ {
+ MsgDev( D_WARN, "S_LoadWAV: microsoft PCM format only (%s)\n", name );
+ Mem_Free( buffer );
+ return false;
+ }
+
+ info->channels = S_GetLittleShort();
+ if( info->channels != 1 )
+ {
+ MsgDev( D_WARN, "S_LoadWAV: only mono WAV files supported (%s)\n", name );
+ Mem_Free( buffer );
+ return false;
+ }
+
+ info->rate = S_GetLittleLong();
+ iff_dataPtr += 4+2;
+
+ info->width = S_GetLittleShort() / 8;
+ if( info->width != 1 && info->width != 2 )
+ {
+ MsgDev( D_WARN, "S_LoadWAV: only 8 and 16 bit WAV files supported (%s)\n", name );
+ Mem_Free( buffer );
+ return false;
+ }
+
+ // get cue chunk
+ S_FindChunk( "cue " );
+ if( iff_dataPtr )
+ {
+ iff_dataPtr += 32;
+ info->loopstart = S_GetLittleLong();
+ S_FindNextChunk( "LIST" ); // if the next chunk is a LIST chunk, look for a cue length marker
+ if( iff_dataPtr )
+ {
+ if( !com.strncmp((const char *)iff_dataPtr + 28, "mark", 4 ))
+ {
+ // this is not a proper parse, but it works with CoolEdit...
+ iff_dataPtr += 24;
+ info->samples = info->loopstart + S_GetLittleLong(); // samples in loop
+ }
+ }
+ }
+ else
+ {
+ info->loopstart = -1;
+ info->samples = 0;
+ }
+
+ // find data chunk
+ S_FindChunk( "data" );
+ if( !iff_dataPtr )
+ {
+ MsgDev( D_WARN, "S_LoadWAV: missing 'data' chunk (%s)\n", name );
+ Mem_Free( buffer );
+ return false;
+ }
+
+ iff_dataPtr += 4;
+ samples = S_GetLittleLong() / info->width;
+
+ if( info->samples )
+ {
+ if( samples < info->samples )
+ {
+ MsgDev( D_ERROR, "S_LoadWAV: %s has a bad loop length\n", name );
+ Mem_Free( buffer );
+ return false;
+ }
+ }
+ else info->samples = samples;
+
+ if( info->samples <= 0 )
+ {
+ MsgDev( D_WARN, "S_LoadWAV: file with %i samples (%s)\n", info->samples, name );
+ Mem_Free( buffer );
+ return false;
+ }
+
+ // Load the data
+ *wav = out = Z_Malloc( info->samples * info->width );
+ Mem_Copy( out, buffer + (iff_dataPtr - buffer), info->samples * info->width );
+ Mem_Free( buffer );
+
+ return true;
+}
+
+/*
+=================
+S_UploadSound
+=================
+*/
+static void S_UploadSound( byte *data, wavinfo_t *info, sfx_t *sfx )
+{
+ sfxcache_t *sc;
+ size_t size, samples;
+ float stepscale;
+
+ // calculate buffer size
+ stepscale = (float)info->rate / dma.speed;
+ samples = info->samples / stepscale;
+ size = samples * info->width * info->channels;
+
+ sc = sfx->cache = Z_Malloc( size + sizeof( sfxcache_t ));
+ sc->length = info->samples;
+ sc->loopstart = info->loopstart;
+ sc->speed = info->rate;
+ sc->width = info->width;
+ sc->stereo = info->channels;
+
+ S_ResampleSfx( sfx, sc->speed, sc->width, data + info->dataofs );
+}
+
+/*
+=================
+S_CreateDefaultSound
+=================
+*/
+static void S_CreateDefaultSound( byte **wav, wavinfo_t *info )
+{
+ byte *out;
+ int i;
+
+ info->rate = 22050;
+ info->width = 2;
+ info->channels = 1;
+ info->samples = 11025;
+
+ *wav = out = Z_Malloc( info->samples * info->width );
+
+ if( s_check_errors->integer )
+ {
+ // create 1 kHz tone as default sound
+ for( i = 0; i < info->samples; i++ )
+ ((short *)out)[i] = com.sin( i * 0.1f ) * 20000;
+ }
+ else
+ {
+ // create silent sound
+ for( i = 0; i < info->samples; i++ )
+ ((short *)out)[i] = i;
+ }
+}
+
+/*
+=================
+S_LoadSound
+=================
+*/
+loadformat_t load_formats[] =
+{
+{ "sound/%s.%s", "wav", S_LoadWAV },
+{ "%s.%s", "wav", S_LoadWAV },
+{ NULL, NULL }
+};
+
+sfxcache_t *S_LoadSound( sfx_t *sfx )
+{
+ byte *data;
+ wavinfo_t info;
+ const char *ext;
+ string loadname, path;
+ loadformat_t *format;
+ bool anyformat;
+
+ if( !sfx ) return NULL;
+ if( sfx->name[0] == '*' ) return NULL;
+ if( sfx->cache ) return sfx->cache; // see if still in memory
+
+ // load it from disk
+ ext = FS_FileExtension( sfx->name );
+ anyformat = !com.stricmp( ext, "" ) ? true : false;
+
+ com.strncpy( loadname, sfx->name, sizeof( loadname ));
+ FS_StripExtension( loadname ); // remove extension if needed
+ Mem_Set( &info, 0, sizeof( info ));
+
+ // developer warning
+ if( !anyformat ) MsgDev( D_NOTE, "Note: %s will be loading only with ext .%s\n", loadname, ext );
+
+ // now try all the formats in the selected list
+ for( format = load_formats; format->formatstring; format++ )
+ {
+ if( anyformat || !com.stricmp( ext, format->ext ))
+ {
+ com.sprintf( path, format->formatstring, loadname, format->ext );
+ if( format->loadfunc( path, &data, &info ))
+ goto snd_loaded;
+ }
+ }
+
+ sfx->default_sound = true;
+ MsgDev( D_WARN, "FS_LoadSound: couldn't load %s\n", sfx->name );
+ S_CreateDefaultSound( &data, &info );
+ info.loopstart = -1;
+
+snd_loaded:
+
+ // load it in
+ S_UploadSound( data, &info, sfx );
+ Mem_Free( data );
+
+ return sfx->cache;
+}
+
+// =======================================================================
+// Load a sound
+// =======================================================================
+/*
+==================
+S_FindSound
+
+==================
+*/
+sfx_t *S_FindSound( const char *name )
+{
+ int i;
+ sfx_t *sfx;
+
+ if( !name || !name[0] ) return NULL;
+
+ if( com.strlen( name ) >= MAX_STRING )
+ {
+ MsgDev( D_ERROR, "S_FindSound: sound name too long: %s", name );
+ return NULL;
+ }
+
+ // see if already loaded
+ for( i = 0; i < s_numSfx; i++ )
+ {
+ sfx = &s_knownSfx[i];
+
+ if( !com.strcmp( sfx->name, name ))
+ {
+ // prolonge registration
+ sfx->registration_sequence = s_registration_sequence;
+ return sfx;
+ }
+ }
+
+ // find a free sfx slot spot
+ for( i = 0, sfx = s_knownSfx; i < s_numSfx; i++, sfx++)
+ {
+ if( !sfx->name[0] ) break; // free spot
+ }
+ if( i == s_numSfx )
+ {
+ if( s_numSfx == MAX_SFX )
+ {
+ MsgDev( D_ERROR, "S_FindName: MAX_SFX limit exceeded\n" );
+ return NULL;
+ }
+ s_numSfx++;
+ }
+
+ sfx = &s_knownSfx[i];
+ Mem_Set( sfx, 0, sizeof( *sfx ));
+ com.strncpy( sfx->name, name, MAX_STRING );
+ sfx->registration_sequence = s_registration_sequence;
+
+ return sfx;
+}
+
+/*
+=====================
+S_BeginRegistration
+
+=====================
+*/
+void S_BeginRegistration( void )
+{
+ s_registration_sequence++;
+ s_registering = true;
+}
+
+/*
+=====================
+S_EndRegistration
+
+=====================
+*/
+void S_EndRegistration( void )
+{
+ sfx_t *sfx;
+ int i;
+
+ // free any sounds not from this registration sequence
+ for( i = 0, sfx = s_knownSfx; i < s_numSfx; i++, sfx++ )
+ {
+ if( !sfx->name[0] ) continue;
+ if( sfx->registration_sequence != s_registration_sequence )
+ {
+ // don't need this sound
+ if( sfx->cache ) Mem_Free( sfx->cache );
+ Mem_Set( sfx, 0, sizeof( *sfx ));
+ }
+ }
+
+ // load everything in
+ for( i = 0, sfx = s_knownSfx; i < s_numSfx; i++, sfx++ )
+ {
+ if( !sfx->name[0] ) continue;
+ S_LoadSound( sfx );
+ }
+ s_registering = false;
+}
+
+/*
+==================
+S_RegisterSound
+
+==================
+*/
+sound_t S_RegisterSound( const char *name )
+{
+ sfx_t *sfx;
+
+ if( !sound_started )
+ return -1;
+
+ sfx = S_FindSound( name );
+ if( !sfx ) return -1;
+
+ sfx->registration_sequence = s_registration_sequence;
+ if( !s_registering ) S_LoadSound( sfx );
+
+ return sfx - s_knownSfx;
+}
+
+sfx_t *S_GetSfxByHandle( sound_t handle )
+{
+ if( handle < 0 || handle >= s_numSfx )
+ {
+ MsgDev( D_ERROR, "S_GetSfxByHandle: handle %i out of range (%i)\n", handle, s_numSfx );
+ return NULL;
+ }
+ return &s_knownSfx[handle];
+}
+
+/*
+=================
+S_FreeSounds
+=================
+*/
+void S_FreeSounds( void )
+{
+ sfx_t *sfx;
+ int i;
+
+ // stop all sounds
+ S_StopAllSounds();
+
+ // free all sounds
+ for( i = 0, sfx = s_knownSfx; i < s_numSfx; i++, sfx++ )
+ {
+ if( !sfx->name[0] ) continue;
+ if( sfx->cache ) Mem_Free( sfx->cache );
+ Mem_Set( sfx, 0, sizeof( *sfx ));
+ }
+
+ Mem_Set( s_knownSfx, 0, sizeof(s_knownSfx));
+ s_numSfx = 0;
+}
\ No newline at end of file
diff --git a/snd_dx/s_main.c b/snd_dx/s_main.c
new file mode 100644
index 00000000..9906f9a1
--- /dev/null
+++ b/snd_dx/s_main.c
@@ -0,0 +1,748 @@
+//=======================================================================
+// Copyright XashXT Group 2009 й
+// s_main.c - sound engine
+//=======================================================================
+
+#include "sound.h"
+
+// only begin attenuating sound volumes when outside the FULLVOLUME range
+#define SOUND_FULLVOLUME 80
+#define SOUND_LOOPATTENUATE 0.003
+#define MAX_PLAYSOUNDS 128
+
+dma_t dma;
+channel_t channels[MAX_CHANNELS];
+bool sound_started = false;
+vec3_t listener_origin;
+vec3_t listener_velocity;
+vec3_t listener_forward;
+vec3_t listener_right;
+vec3_t listener_up;
+
+int s_framecount; // for autosounds checking
+int s_clientnum; // cl.playernum + 1
+int soundtime; // sample PAIRS
+int paintedtime; // sample PAIRS
+byte *sndpool;
+
+playsound_t s_playsounds[MAX_PLAYSOUNDS];
+playsound_t s_freeplays;
+playsound_t s_pendingplays;
+int s_beginofs;
+
+cvar_t *host_sound;
+cvar_t *s_check_errors;
+cvar_t *s_volume;
+cvar_t *s_testsound;
+cvar_t *s_loadas8bit;
+cvar_t *s_khz;
+cvar_t *s_show;
+cvar_t *s_mixahead;
+cvar_t *s_primary;
+cvar_t *s_pause;
+
+/*
+=============================================================================
+
+ SOUNDS PROCESSING
+
+=============================================================================
+*/
+/*
+=================
+S_PickChannel
+=================
+*/
+channel_t *S_PickChannel( int entnum, int channel )
+{
+ int i;
+ int firstToDie = -1;
+ int oldestTime = 0x7fffffff;
+ channel_t *ch;
+
+ if( entnum < 0 || channel < 0 ) return NULL; // invalid channel or entnum
+
+ for( i = 0, ch = channels; i < MAX_CHANNELS; i++, ch++ )
+ {
+ // check if this channel is active
+ if( channel == CHAN_AUTO && !ch->sfx )
+ {
+ // free channel
+ firstToDie = i;
+ break;
+ }
+
+ // channel 0 never overrides
+ if( channel != CHAN_AUTO && ( ch->entnum == entnum && ch->entchannel == channel ))
+ {
+ // always override sound from same entity
+ firstToDie = i;
+ break;
+ }
+
+ // don't let monster sounds override player sounds
+ if( entnum != s_clientnum && ch->entnum == s_clientnum && ch->sfx )
+ continue;
+
+ // replace the oldest sound
+ if( ch->end - paintedtime < oldestTime )
+ {
+ oldestTime = ch->end - paintedtime;
+ firstToDie = i;
+ }
+ }
+
+ if( firstToDie == -1 )
+ return NULL;
+
+ ch = &channels[firstToDie];
+ Mem_Set( ch, 0, sizeof( *ch ));
+
+ return ch;
+}
+
+/*
+=================
+S_SpatializeOrigin
+
+Used for spatializing channels and autosounds
+=================
+*/
+void S_SpatializeOrigin( vec3_t pos, vec3_t vel, float master_vol, float dist_mult, int *left_vol, int *right_vol )
+{
+ float dot;
+ float dist;
+ float lscale, rscale, scale;
+ vec3_t source_vec;
+ vec3_t source_vel;
+
+ // calculate stereo seperation and distance attenuation
+ VectorSubtract( pos, listener_origin, source_vec );
+ VectorCopy( vel, source_vel );
+
+ dist = VectorNormalizeLength( source_vec );
+ dist -= SOUND_FULLVOLUME;
+ if( dist < 0 ) dist = 0; // close enough to be at full volume
+ dist *= dist_mult; // different attenuation levels
+
+ dot = DotProduct( listener_right, source_vec );
+
+ if( dma.channels == 1 || !dist_mult )
+ {
+ // no attenuation = no spatialization
+ rscale = 1.0f;
+ lscale = 1.0f;
+ }
+ else
+ {
+ rscale = 0.5f * (1.0f + dot);
+ lscale = 0.5f * (1.0f - dot);
+ }
+
+ // add in distance effect
+ scale = (1.0f - dist) * rscale;
+ *right_vol = (int)( master_vol * scale );
+ if( *right_vol < 0 ) *right_vol = 0;
+
+ scale = (1.0f - dist) * lscale;
+ *left_vol = (int)( master_vol * scale );
+ if( *left_vol < 0 ) *left_vol = 0;
+}
+
+/*
+=================
+S_Spatialize
+=================
+*/
+void S_SpatializeChannel( channel_t *ch )
+{
+ vec3_t position, velocity;
+
+ // anything coming from the view entity will always be full volume
+ if( ch->entnum == s_clientnum || !ch->dist_mult )
+ {
+ ch->leftvol = ch->master_vol;
+ ch->rightvol = ch->master_vol;
+ return;
+ }
+
+ if( ch->fixed_origin )
+ {
+ VectorCopy( ch->origin, position );
+ VectorSet( velocity, 0, 0, 0 );
+ }
+ else
+ {
+ if( ch->autosound ) si.GetSoundSpatialization( ch->loopnum, position, velocity );
+ else si.GetSoundSpatialization( ch->entnum, position, velocity );
+ }
+
+ S_SpatializeOrigin( position, velocity, ch->master_vol, ch->dist_mult, &ch->leftvol, &ch->rightvol );
+}
+
+
+/*
+=================
+S_AllocPlaysound
+=================
+*/
+playsound_t *S_AllocPlaysound( void )
+{
+ playsound_t *ps;
+
+ ps = s_freeplays.next;
+ if( ps == &s_freeplays )
+ return NULL; // no free playsounds
+
+ // unlink from freelist
+ ps->prev->next = ps->next;
+ ps->next->prev = ps->prev;
+
+ return ps;
+}
+
+
+/*
+=================
+S_FreePlaysound
+=================
+*/
+void S_FreePlaysound( playsound_t *ps )
+{
+ // unlink from channel
+ ps->prev->next = ps->next;
+ ps->next->prev = ps->prev;
+
+ // add to free list
+ ps->next = s_freeplays.next;
+ s_freeplays.next->prev = ps;
+ ps->prev = &s_freeplays;
+ s_freeplays.next = ps;
+}
+
+/*
+===============
+S_IssuePlaysound
+
+Take the next playsound and begin it on the channel
+This is never called directly by S_Play*, but only
+by the update loop.
+===============
+*/
+void S_IssuePlaysound( playsound_t *ps )
+{
+ channel_t *ch;
+ sfxcache_t *sc;
+
+ if( s_show->value ) MsgDev( D_INFO, "Issue %i\n", ps->begin );
+
+ // pick a channel to play on
+ ch = S_PickChannel( ps->entnum, ps->entchannel );
+ if( !ch )
+ {
+ if( ps->sfx->name[0] == '#' ) MsgDev( D_ERROR, "dropped sound %s\n", &ps->sfx->name[1] );
+ else MsgDev( D_ERROR, "dropped sound \"sound/%s\"\n", ps->sfx->name );
+ S_FreePlaysound( ps );
+ return;
+ }
+
+ // spatialize
+ if( ps->attenuation == ATTN_STATIC )
+ ch->dist_mult = ps->attenuation * 0.001;
+ else ch->dist_mult = ps->attenuation * 0.0005;
+
+ ch->master_vol = ps->volume;
+ ch->entnum = ps->entnum;
+ ch->entchannel = ps->entchannel;
+ ch->sfx = ps->sfx;
+ ch->use_loop = ps->use_loop;
+ VectorCopy( ps->origin, ch->origin );
+ ch->fixed_origin = ps->fixed_origin;
+
+ S_SpatializeChannel( ch );
+
+ ch->pos = 0;
+ sc = S_LoadSound( ch->sfx );
+ ch->end = paintedtime + sc->length;
+
+ // free the playsound
+ S_FreePlaysound( ps );
+}
+
+// =======================================================================
+// Start a sound effect
+// =======================================================================
+/*
+====================
+S_StartSound
+
+Validates the parms and ques the sound up
+if pos is NULL, the sound will be dynamically sourced from the entity
+Entchannel 0 will never override a playing sound
+====================
+*/
+void S_StartSound( const vec3_t pos, int ent, int chan, sound_t handle, float fvol, float attn, float pitch, bool loop )
+{
+ sfxcache_t *sc;
+ int vol, start;
+ playsound_t *ps, *sort;
+ sfx_t *sfx = NULL;
+ float timeofs = 0; // FIXME: implement into network protocol
+
+ if( !sound_started )
+ return;
+
+ sfx = S_GetSfxByHandle( handle );
+ if( !sfx ) return;
+
+ // make sure the sound is loaded
+ sc = S_LoadSound( sfx );
+ if( !sc ) return; // couldn't load the sound's data
+
+ vol = fvol * 255;
+
+ // allocate the playsound_t
+ ps = S_AllocPlaysound();
+ if( !ps )
+ {
+ if( sfx->name[0] == '#' ) MsgDev( D_ERROR, "dropped sound %s\n", &sfx->name[1] );
+ else MsgDev( D_ERROR, "dropped sound \"sound/%s\"\n", sfx->name );
+ return;
+ }
+
+ if( pos )
+ {
+ VectorCopy( pos, ps->origin );
+ ps->fixed_origin = true;
+ }
+ else ps->fixed_origin = false;
+
+ ps->entnum = ent;
+ ps->entchannel = chan;
+ ps->attenuation = attn;
+ ps->use_loop = loop;
+ ps->volume = vol;
+ ps->sfx = sfx;
+
+ // drift s_beginofs
+ start = si.GetServerTime() * 0.001 * dma.speed + s_beginofs;
+ if( start < paintedtime )
+ {
+ start = paintedtime;
+ s_beginofs = start - ( si.GetServerTime() * 0.001 * dma.speed );
+ }
+ else if( start > paintedtime + 0.3 * dma.speed )
+ {
+ start = paintedtime + 0.1 * dma.speed;
+ s_beginofs = start - ( si.GetServerTime() * 0.001 * dma.speed );
+ }
+ else s_beginofs -= 10;
+
+ if( !timeofs ) ps->begin = paintedtime;
+ else ps->begin = start + timeofs * dma.speed;
+
+ // sort into the pending sound list
+ for( sort = s_pendingplays.next; sort != &s_pendingplays && sort->begin < ps->begin; sort = sort->next );
+
+ ps->next = sort;
+ ps->prev = sort->prev;
+ ps->next->prev = ps;
+ ps->prev->next = ps;
+}
+
+/*
+==================
+S_StartLocalSound
+==================
+*/
+bool S_StartLocalSound( const char *name, float volume, float pitch, const float *origin )
+{
+ sound_t sfxHandle;
+
+ if( !sound_started )
+ return false;
+
+ sfxHandle = S_RegisterSound( name );
+ S_StartSound( origin, s_clientnum, CHAN_AUTO, sfxHandle, volume, ATTN_NONE, pitch, false );
+
+ return true;
+}
+
+/*
+==================
+S_ClearBuffer
+==================
+*/
+void S_ClearBuffer( void )
+{
+ int clear;
+
+ if( !sound_started )
+ return;
+
+ s_rawend = 0;
+
+ if( dma.samplebits == 8 )
+ clear = 0x80;
+ else clear = 0;
+
+ SNDDMA_BeginPainting ();
+ if( dma.buffer ) Mem_Set( dma.buffer, clear, dma.samples * dma.samplebits / 8 );
+ SNDDMA_Submit ();
+}
+
+/*
+==================
+S_StopAllSounds
+==================
+*/
+void S_StopAllSounds( void )
+{
+ int i;
+
+ if( !sound_started )
+ return;
+
+ // clear all the playsounds
+ Mem_Set( s_playsounds, 0, sizeof( s_playsounds ));
+ s_freeplays.next = s_freeplays.prev = &s_freeplays;
+ s_pendingplays.next = s_pendingplays.prev = &s_pendingplays;
+
+ for( i = 0; i < MAX_PLAYSOUNDS; i++ )
+ {
+ s_playsounds[i].prev = &s_freeplays;
+ s_playsounds[i].next = s_freeplays.next;
+ s_playsounds[i].prev->next = &s_playsounds[i];
+ s_playsounds[i].next->prev = &s_playsounds[i];
+ }
+
+ // clear all the channels
+ Mem_Set( channels, 0, sizeof( channels ));
+ S_ClearBuffer ();
+
+ s_framecount = 0;
+}
+
+/*
+==================
+S_AddLoopinSound
+
+Entities with a ->sound field will generated looped sounds
+that are automatically started, stopped, and merged together
+as the entities are sent to the client
+==================
+*/
+bool S_AddLoopingSound( int entnum, sound_t handle, float volume, float attn )
+{
+ channel_t *ch;
+ sfx_t *sfx = NULL;
+ int i;
+
+ if( !sound_started )
+ return false;
+ sfx = S_GetSfxByHandle( handle );
+
+ // default looped sound it's terrible :)
+ if( !sfx || sfx->default_sound || !sfx->cache )
+ return false;
+
+ // if this entity is already playing the same sound effect on an
+ // active channel, then simply update it
+ for( i = 0, ch = channels; i < MAX_CHANNELS; i++, ch++ )
+ {
+ if( ch->sfx != sfx ) continue;
+ if( !ch->autosound ) continue;
+ if( ch->loopnum != entnum ) continue;
+ if( ch->loopframe + 1 != s_framecount )
+ continue;
+
+ ch->loopframe = s_framecount;
+ break;
+ }
+ if( i != MAX_CHANNELS )
+ return false;
+
+ // otherwise pick a channel and start the sound effect
+ ch = S_PickChannel( 0, 0 );
+ if( !ch )
+ {
+ MsgDev( D_ERROR, "dropped sound \"sound/%s\"\n", sfx->name );
+ return false;
+ }
+
+ ch->sfx = sfx;
+ ch->use_loop = true; // autosounds never comes from S_StartLocalSound
+ ch->autosound = true; // remove next frame
+ ch->loopnum = entnum;
+ ch->loopframe = s_framecount;
+ ch->fixed_origin = false;
+ ch->dist_mult = ATTN_STATIC * 0.001;
+ ch->pos = paintedtime % sfx->cache->length;
+ ch->end = paintedtime + sfx->cache->length - ch->pos;
+
+ // now we can spatialize channel
+ S_SpatializeChannel( ch );
+
+ return true;
+}
+
+//=============================================================================
+
+void GetSoundtime( void )
+{
+ static int buffers, oldsamplepos;
+ int samplepos, fullsamples;
+
+ fullsamples = dma.samples / dma.channels;
+
+ // it is possible to miscount buffers
+ // if it has wrapped twice between
+ // calls to S_Update. Oh well.
+ 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();
+ }
+ }
+
+ oldsamplepos = samplepos;
+ soundtime = buffers * fullsamples + samplepos / dma.channels;
+}
+
+void S_UpdateChannels( void )
+{
+ uint endtime;
+ int samps;
+
+ if( !sound_started )
+ return;
+
+ SNDDMA_BeginPainting();
+
+ if( !dma.buffer )
+ return;
+
+ // updates DMA time
+ GetSoundtime();
+
+ // check to make sure that we haven't overshot
+ if( paintedtime < soundtime ) paintedtime = soundtime;
+
+ // mix ahead of current position
+ endtime = soundtime + s_mixahead->value * dma.speed;
+
+ // mix to an even submission block size
+ endtime = (endtime + dma.submission_chunk - 1) & ~(dma.submission_chunk - 1);
+ samps = dma.samples >> (dma.channels - 1);
+ if( endtime - soundtime > samps ) endtime = soundtime + samps;
+
+ S_PaintChannels( endtime );
+ SNDDMA_Submit();
+}
+
+/*
+============
+S_Update
+
+Called once each time through the main loop
+============
+*/
+void S_Update( int clientnum, const vec3_t position, const vec3_t velocity, const vec3_t axis[3], bool clear )
+{
+ int i, total;
+ channel_t *ch, *combine = NULL;
+
+ if( !sound_started )
+ return;
+
+ // bump frame count
+ s_framecount++;
+
+ // if the loading plaque is up, clear everything
+ // out to make sure we aren't looping a dirty
+ // dma buffer while loading
+ if( s_pause->integer || clear )
+ {
+ S_ClearBuffer();
+ return;
+ }
+
+ // rebuild scale tables if volume is modified
+ if( s_volume->modified ) S_InitScaletable();
+
+ s_clientnum = clientnum;
+ VectorCopy( position, listener_origin );
+ VectorCopy( velocity, listener_velocity );
+ VectorCopy( axis[0], listener_forward );
+ VectorCopy( axis[1], listener_right );
+ VectorCopy( axis[2], listener_up );
+
+ // Add looping sounds
+ si.AddLoopingSounds();
+
+ // update spatialization for dynamic sounds
+ for( i = 0, ch = channels; i < MAX_CHANNELS; i++, ch++ )
+ {
+ if( !ch->sfx ) continue;
+ if( ch->autosound )
+ {
+ if( ch->loopframe != s_framecount )
+ {
+ Mem_Set( ch, 0, sizeof( *ch )); // stopped
+ continue;
+ }
+ }
+
+ // respatialize channel
+ S_SpatializeChannel( ch );
+
+ if( !ch->leftvol && !ch->rightvol )
+ {
+ Mem_Set( ch, 0, sizeof( *ch )); // not audible
+ continue;
+ }
+ }
+
+ // debugging output
+ if( s_show->value )
+ {
+ for( i = total = 0, ch = channels; i < MAX_CHANNELS; i++, ch++ )
+ {
+ if( ch->sfx && ( ch->leftvol || ch->rightvol ))
+ {
+ MsgDev( D_INFO, "%3i %3i %s\n", ch->leftvol, ch->rightvol, ch->sfx->name );
+ total++;
+ }
+ }
+ Msg( "----(%i)---- painted: %i\n", total, paintedtime );
+ }
+
+ // mix some sound
+ S_UpdateChannels();
+}
+
+/*
+===============================================================================
+
+console functions
+
+===============================================================================
+*/
+void S_Play_f( void )
+{
+ if( Cmd_Argc() == 1 )
+ {
+ Msg( "Usage: playsound \n" );
+ return;
+ }
+ S_StartLocalSound( Cmd_Argv( 1 ), 1.0f, PITCH_NORM, NULL );
+}
+
+/*
+=================
+S_StopSound_f
+=================
+*/
+void S_StopSound_f( void )
+{
+ S_StopAllSounds();
+}
+
+/*
+=================
+S_SoundInfo_f
+=================
+*/
+void S_SoundInfo_f( void )
+{
+ if( !sound_started )
+ {
+ Msg( "sound system not started\n" );
+ return;
+ }
+
+ Msg( "%5d channel(s)\n", dma.channels );
+ Msg( "%5d samples\n", dma.samples );
+ Msg( "%5d bits/sample\n", dma.samplebits );
+ Msg( "%5d bytes/sec\n", dma.speed );
+
+ MsgDev( D_NOTE, "%5d samplepos\n", dma.samplepos );
+ MsgDev( D_NOTE, "%5d submission_chunk\n", dma.submission_chunk );
+ MsgDev( D_NOTE, "0x%x dma buffer\n", dma.buffer );
+}
+
+/*
+================
+S_Init
+================
+*/
+bool S_Init( void *hInst )
+{
+ Cmd_ExecuteString( "sndlatch\n" );
+
+ host_sound = Cvar_Get( "host_sound", "1", CVAR_SYSTEMINFO, "enable sound system" );
+ s_volume = Cvar_Get( "s_volume", "0.7", CVAR_ARCHIVE, "sound volume" );
+ s_khz = Cvar_Get( "s_khz", "11", CVAR_LATCH_AUDIO|CVAR_ARCHIVE, "output sound frequency" );
+ s_loadas8bit = Cvar_Get( "s_loadas8bit", "1", CVAR_LATCH_AUDIO|CVAR_ARCHIVE, "resample all sounds to 8-bit" );
+ s_mixahead = Cvar_Get( "s_mixahead", "0.2", CVAR_ARCHIVE, "how much sound to mix ahead of time" );
+ s_show = Cvar_Get( "s_show", "0", 0, "show playing sounds" );
+ s_testsound = Cvar_Get( "s_testsound", "0", 0, "generate sine 1 khz wave to testing audio subsystem" );
+ s_primary = Cvar_Get( "s_primary", "0", CVAR_LATCH_AUDIO|CVAR_ARCHIVE, "use direct primary buffer" );
+ s_check_errors = Cvar_Get( "s_check_errors", "1", CVAR_ARCHIVE, "ignore audio engine errors" );
+ s_pause = Cvar_Get( "paused", "0", 0, "sound engine pause" );
+
+ Cmd_AddCommand( "playsound", S_Play_f, "playing a specified sound file" );
+ Cmd_AddCommand( "stopsound", S_StopSound_f, "stop all sounds" );
+ Cmd_AddCommand( "soundlist", S_SoundList_f, "display loaded sounds" );
+ Cmd_AddCommand( "s_info", S_SoundInfo_f, "print sound system information" );
+
+ if( !host_sound->integer )
+ {
+ MsgDev( D_INFO, "Audio: disabled\n" );
+ return false;
+ }
+
+ if( !SNDDMA_Init( hInst ))
+ {
+ MsgDev( D_INFO, "S_Init: sound system can't initialized\n" );
+ return false;
+ }
+ S_InitScaletable();
+
+ sndpool = Mem_AllocPool( "Sound Zone" );
+ sound_started = true;
+ soundtime = 0;
+ paintedtime = 0;
+
+ S_StopAllSounds ();
+
+ return true;
+}
+
+// =======================================================================
+// Shutdown sound engine
+// =======================================================================
+void S_Shutdown( void )
+{
+ Cmd_RemoveCommand( "playsound" );
+ Cmd_RemoveCommand( "stopsound" );
+ Cmd_RemoveCommand( "soundlist" );
+ Cmd_RemoveCommand( "s_info" );
+
+ if( !sound_started ) return;
+ sound_started = false;
+
+ SNDDMA_Shutdown();
+
+ S_FreeSounds();
+ Mem_FreePool( &sndpool );
+}
\ No newline at end of file
diff --git a/snd_dx/s_mix.c b/snd_dx/s_mix.c
new file mode 100644
index 00000000..5a1fd32f
--- /dev/null
+++ b/snd_dx/s_mix.c
@@ -0,0 +1,327 @@
+/*
+Copyright (C) 1997-2001 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_mix.c -- portable code to mix sounds for snd_dma.c
+
+#include "sound.h"
+
+#define PAINTBUFFER_SIZE 2048
+portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE];
+int snd_scaletable[32][256];
+int *snd_p, snd_linear_count, snd_vol;
+short *snd_out;
+
+void S_WriteLinearBlastStereo16( void )
+{
+ int i, val;
+
+ for( i = 0; i < snd_linear_count; i += 2 )
+ {
+ val = snd_p[i]>>8;
+ if( val > 0x7fff ) snd_out[i] = 0x7fff;
+ else if( val < (short)0x8000 )
+ snd_out[i] = (short)0x8000;
+ else snd_out[i] = val;
+
+ val = snd_p[i+1]>>8;
+ if( val > 0x7fff ) snd_out[i+1] = 0x7fff;
+ else if( val < (short)0x8000 )
+ snd_out[i+1] = (short)0x8000;
+ else snd_out[i+1] = val;
+ }
+}
+
+void S_TransferStereo16( dword *pbuf, int endtime )
+{
+ int lpos, lpaintedtime;
+
+ snd_p = (int *)paintbuffer;
+ lpaintedtime = paintedtime;
+
+ while( lpaintedtime < endtime )
+ {
+ // handle recirculating buffer issues
+ lpos = lpaintedtime & ((dma.samples >> 1) - 1);
+
+ snd_out = (short *) pbuf + (lpos << 1);
+
+ snd_linear_count = (dma.samples>>1) - lpos;
+ if( lpaintedtime + snd_linear_count > endtime )
+ snd_linear_count = endtime - lpaintedtime;
+
+ snd_linear_count <<= 1;
+
+ // write a linear blast of samples
+ S_WriteLinearBlastStereo16();
+
+ snd_p += snd_linear_count;
+ lpaintedtime += (snd_linear_count >> 1);
+ }
+}
+
+/*
+===================
+S_TransferPaintBuffer
+
+===================
+*/
+void S_TransferPaintBuffer( int endtime )
+{
+ int out_idx, count;
+ int step, val;
+ int *p, out_mask;
+ dword *pbuf;
+
+ pbuf = (dword *)dma.buffer;
+
+ if( s_testsound->integer )
+ {
+ int i, count;
+
+ // write a fixed sine wave
+ count = (endtime - paintedtime);
+ for( i = 0; i < count; i++ )
+ {
+ paintbuffer[i].left = com.sin(( paintedtime + i ) * 0.1f ) * 20000 * 256;
+ paintbuffer[i].right = paintbuffer[i].left;
+ }
+ }
+
+
+ if( dma.samplebits == 16 && dma.channels == 2 )
+ {
+ // optimized case
+ S_TransferStereo16( pbuf, endtime );
+ }
+ else
+ {
+ // general case
+ p = (int *)paintbuffer;
+ count = (endtime - paintedtime) * dma.channels;
+ out_mask = dma.samples - 1;
+ out_idx = paintedtime * dma.channels & out_mask;
+ step = 3 - dma.channels;
+
+ if( dma.samplebits == 16 )
+ {
+ short *out = (short *)pbuf;
+
+ while( count-- )
+ {
+ val = *p >> 8;
+ p += step;
+ if( val > 0x7fff ) val = 0x7fff;
+ else if( val < (short)0x8000 )
+ val = (short)0x8000;
+ out[out_idx] = val;
+ out_idx = (out_idx + 1) & out_mask;
+ }
+ }
+ else if( dma.samplebits == 8 )
+ {
+ byte *out = (byte *)pbuf;
+
+ while( count-- )
+ {
+ val = *p >> 8;
+ p += step;
+ if( val > 0x7fff ) val = 0x7fff;
+ else if( val < (short)0x8000 )
+ val = (short)0x8000;
+ out[out_idx] = (val>>8) + 128;
+ out_idx = (out_idx + 1) & out_mask;
+ }
+ }
+ }
+}
+
+/*
+===============================================================================
+
+CHANNEL MIXING
+
+===============================================================================
+*/
+void S_PaintChannelFrom8( channel_t *ch, sfxcache_t *sc, int count, int offset )
+{
+ int data;
+ int *lscale, *rscale;
+ byte *sfx;
+ portable_samplepair_t *samp;
+ int i;
+
+ if( ch->leftvol > 255 ) ch->leftvol = 255;
+ if( ch->rightvol > 255 ) ch->rightvol = 255;
+
+ lscale = snd_scaletable[ch->leftvol>>3];
+ rscale = snd_scaletable[ch->rightvol>>3];
+ sfx = (signed char *)sc->data + ch->pos;
+
+ samp = &paintbuffer[offset];
+
+ for( i = 0; i < count; i++, samp++ )
+ {
+ data = sfx[i];
+ samp->left += lscale[data];
+ samp->right += rscale[data];
+ }
+ ch->pos += count;
+}
+
+void S_PaintChannelFrom16( channel_t *ch, sfxcache_t *sc, int count, int offset )
+{
+ int data;
+ int left, right;
+ int leftvol, rightvol;
+ signed short *sfx;
+ portable_samplepair_t *samp;
+ int i;
+
+ leftvol = ch->leftvol * snd_vol;
+ rightvol = ch->rightvol * snd_vol;
+ sfx = (signed short *)sc->data + ch->pos;
+
+ samp = &paintbuffer[offset];
+
+ for( i = 0; i < count; i++, samp++ )
+ {
+ data = sfx[i];
+ left = ( data * leftvol ) >> 8;
+ right = (data * rightvol) >> 8;
+ samp->left += left;
+ samp->right += right;
+ }
+ ch->pos += count;
+}
+
+void S_PaintChannels( int endtime )
+{
+ channel_t *ch;
+ sfxcache_t *sc;
+ playsound_t *ps;
+ int i, end, ltime, count;
+
+ snd_vol = s_volume->value * 256;
+
+ while( paintedtime < endtime )
+ {
+ // if paintbuffer is smaller than DMA buffer
+ end = endtime;
+ if( endtime - paintedtime > PAINTBUFFER_SIZE )
+ end = paintedtime + PAINTBUFFER_SIZE;
+
+ // start any playsounds
+ while( 1 )
+ {
+ ps = s_pendingplays.next;
+ if( ps == &s_pendingplays )
+ break; // no more pending sounds
+ if( ps->begin <= paintedtime )
+ {
+ S_IssuePlaysound( ps );
+ continue;
+ }
+
+ if( ps->begin < end ) end = ps->begin; // stop here
+ break;
+ }
+
+ // clear the paint buffer
+ if( s_rawend < paintedtime )
+ {
+ Mem_Set( paintbuffer, 0, (end - paintedtime) * sizeof( portable_samplepair_t ));
+ }
+ else
+ {
+ int stop;
+
+ // copy from the streaming sound source
+ stop = (end < s_rawend) ? end : s_rawend;
+
+ for( i = paintedtime; i < stop; i++ )
+ paintbuffer[i - paintedtime] = s_rawsamples[i & (MAX_RAW_SAMPLES - 1)];
+
+ for( ; i < end; i++ )
+ paintbuffer[i-paintedtime].left = paintbuffer[i-paintedtime].right = 0;
+ }
+
+ // paint in the channels.
+ for( i = 0, ch = channels; i < MAX_CHANNELS; i++, ch++ )
+ {
+ ltime = paintedtime;
+
+ while( ltime < end )
+ {
+ if( !ch->sfx || ( !ch->leftvol && !ch->rightvol ))
+ break;
+
+ // max painting is to the end of the buffer
+ count = end - ltime;
+
+ // might be stopped by running out of data
+ if( ch->end - ltime < count ) count = ch->end - ltime;
+
+ sc = S_LoadSound( ch->sfx );
+ if( !sc ) break;
+
+ if( count > 0 && ch->sfx )
+ {
+ if( sc->width == 1 )
+ S_PaintChannelFrom8( ch, sc, count, ltime - paintedtime );
+ else S_PaintChannelFrom16( ch, sc, count, ltime - paintedtime );
+
+ ltime += count;
+ }
+
+ // if at end of loop, restart
+ if( ltime >= ch->end )
+ {
+ if( ch->autosound && ch->use_loop )
+ { // autolooping sounds always go back to start
+ ch->pos = 0;
+ ch->end = ltime + sc->length;
+ }
+ else if( sc->loopstart >= 0 && ch->use_loop )
+ {
+ ch->pos = sc->loopstart;
+ ch->end = ltime + sc->length - ch->pos;
+ }
+ else ch->sfx = NULL; // channel just stopped
+ }
+ }
+ }
+
+ // transfer out according to DMA format
+ S_TransferPaintBuffer( end );
+ paintedtime = end;
+ }
+}
+
+void S_InitScaletable( void )
+{
+ int i, j;
+ int scale;
+
+ for( i = 0; i < 32; i++ )
+ {
+ scale = i * 8 * 256 * s_volume->value;
+ for( j = 0; j < 256; j++ ) snd_scaletable[i][j] = ((signed char)j) * scale;
+ }
+ s_volume->modified = false;
+}
diff --git a/snd_dx/s_stream.c b/snd_dx/s_stream.c
new file mode 100644
index 00000000..fb545a45
--- /dev/null
+++ b/snd_dx/s_stream.c
@@ -0,0 +1,135 @@
+//=======================================================================
+// Copyright XashXT Group 2009 й
+// s_stream.c - sound streaming
+//=======================================================================
+
+#include "sound.h"
+#include "byteorder.h"
+
+portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES];
+int s_rawend;
+static bg_track_t s_bgTrack;
+
+/*
+=================
+S_StartBackgroundTrack
+=================
+*/
+void S_StartBackgroundTrack( const char *introTrack, const char *loopTrack )
+{
+ if( !sound_started ) return;
+ S_StopBackgroundTrack();
+
+ // start it up
+ com.snprintf( s_bgTrack.introName, sizeof(s_bgTrack.introName), "media/%s.ogg", introTrack);
+ com.snprintf( s_bgTrack.loopName, sizeof(s_bgTrack.loopName), "media/%s.ogg", loopTrack );
+
+ S_StartStreaming();
+
+ // UNDONE: process streaming
+}
+
+void S_StopBackgroundTrack( void )
+{
+ if( !sound_started ) return;
+
+ S_StopStreaming();
+
+ // UNDONE: close background track
+ Mem_Set( &s_bgTrack, 0, sizeof( bg_track_t ));
+}
+
+void S_StartStreaming( void )
+{
+ // UNDONE: allocate static channel for streaimng
+}
+
+void S_StopStreaming( void )
+{
+}
+
+/*
+============
+S_StreamRawSamples
+
+Cinematic streaming and voice over network
+============
+*/
+void S_StreamRawSamples( int samples, int rate, int width, int channels, const byte *data )
+{
+ int i, src, dst;
+ float scale;
+
+ if( !sound_started )
+ return;
+
+ if( s_rawend < paintedtime ) s_rawend = paintedtime;
+ scale = (float)rate / dma.speed;
+
+ if( channels == 2 && width == 2 )
+ {
+ if( scale == 1.0f )
+ {
+ // optimized case
+ for( i = 0; i < samples; i++ )
+ {
+ dst = s_rawend & (MAX_RAW_SAMPLES - 1);
+ s_rawend++;
+ s_rawsamples[dst].left = LittleShort(((short *)data)[i*2]) << 8;
+ s_rawsamples[dst].right = LittleShort(((short *)data)[i*2+1]) << 8;
+ }
+ }
+ else
+ {
+ for( i = src = 0; src < samples; i++ )
+ {
+ src = i * scale;
+ if( src >= samples ) break;
+
+ dst = s_rawend & (MAX_RAW_SAMPLES - 1);
+ s_rawend++;
+ s_rawsamples[dst].left = LittleShort(((short *)data)[src*2]) << 8;
+ s_rawsamples[dst].right = LittleShort(((short *)data)[src*2+1]) << 8;
+ }
+ }
+ }
+ else if( channels == 1 && width == 2 )
+ {
+ for( i = src = 0; src < samples; i++ )
+ {
+ src = i * scale;
+ if( src >= samples ) break;
+
+ dst = s_rawend & (MAX_RAW_SAMPLES - 1);
+ s_rawend++;
+ s_rawsamples[dst].left = LittleShort(((short *)data)[src]) << 8;
+ s_rawsamples[dst].right = LittleShort(((short *)data)[src]) << 8;
+ }
+ }
+ else if( channels == 2 && width == 1 )
+ {
+ for( i = src = 0; src < samples; i++ )
+ {
+ src = i * scale;
+ if( src >= samples ) break;
+
+ dst = s_rawend & (MAX_RAW_SAMPLES - 1);
+ s_rawend++;
+ s_rawsamples[dst].left = ((char *)data)[src*2] << 16;
+ s_rawsamples[dst].right = ((char *)data)[src*2+1] << 16;
+ }
+ }
+ else if( channels == 1 && width == 1 )
+ {
+ for( i = src = 0; src < samples; i++ )
+ {
+ src = i * scale;
+ if( src >= samples ) break;
+
+ dst = s_rawend & (MAX_RAW_SAMPLES - 1);
+ s_rawend++;
+ s_rawsamples[dst].left = (((byte *)data)[src]-128) << 16;
+ s_rawsamples[dst].right = (((byte *)data)[src]-128) << 16;
+ }
+ }
+}
\ No newline at end of file
diff --git a/snd_dx/snd_dx.dsp b/snd_dx/snd_dx.dsp
new file mode 100644
index 00000000..78cd625e
--- /dev/null
+++ b/snd_dx/snd_dx.dsp
@@ -0,0 +1,153 @@
+# Microsoft Developer Studio Project File - Name="snd_dx" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=snd_dx - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "snd_dx.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "snd_dx.mak" CFG="snd_dx - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "snd_dx - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "snd_dx - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "snd_dx - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\temp\snd_dx\!release"
+# PROP Intermediate_Dir "..\temp\snd_dx\!release"
+# PROP Ignore_Export_Lib 1
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PLATFORM_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../public" /I "../common" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /opt:nowin98
+# ADD LINK32 winmm.lib /nologo /dll /pdb:none /machine:I386 /nodefaultlib:"libcmt.lib" /opt:nowin98
+# SUBTRACT LINK32 /profile
+# Begin Custom Build
+TargetDir=\Xash3D\src_main\temp\snd_dx\!release
+InputPath=\Xash3D\src_main\temp\snd_dx\!release\snd_dx.dll
+SOURCE="$(InputPath)"
+
+"D:\Xash3D\bin\snd_dx.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ copy $(TargetDir)\snd_dx.dll "D:\Xash3D\bin\snd_dx.dll"
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "snd_dx - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\temp\snd_dx\!debug"
+# PROP Intermediate_Dir "..\temp\snd_dx\!debug"
+# PROP Ignore_Export_Lib 1
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PLATFORM_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /Gi /GX /ZI /Od /I "./" /I "../public" /I "../common" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /FD /GZ /c
+# SUBTRACT CPP /YX
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 winmm.lib /nologo /dll /debug /machine:I386 /nodefaultlib:"libcmt.lib" /pdbtype:sept
+# SUBTRACT LINK32 /incremental:no /nodefaultlib
+# Begin Custom Build
+TargetDir=\Xash3D\src_main\temp\snd_dx\!debug
+InputPath=\Xash3D\src_main\temp\snd_dx\!debug\snd_dx.dll
+SOURCE="$(InputPath)"
+
+"D:\Xash3D\bin\snd_dx.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ copy $(TargetDir)\snd_dx.dll "D:\Xash3D\bin\snd_dx.dll"
+
+# End Custom Build
+
+!ENDIF
+
+# Begin Target
+
+# Name "snd_dx - Win32 Release"
+# Name "snd_dx - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\s_direct.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\s_export.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\s_load.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\s_main.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\s_mix.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\s_stream.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\s_openal.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sound.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/snd_dx/sound.h b/snd_dx/sound.h
new file mode 100644
index 00000000..1d35c090
--- /dev/null
+++ b/snd_dx/sound.h
@@ -0,0 +1,190 @@
+//=======================================================================
+// Copyright XashXT Group 2009 й
+// sound.h - sndlib main header
+//=======================================================================
+
+#ifndef SOUND_H
+#define SOUND_H
+
+#include
+#include "launch_api.h"
+#include "qfiles_ref.h"
+#include "vsound_api.h"
+
+extern stdlib_api_t com;
+extern vsound_imp_t si;
+extern byte *sndpool;
+
+#include "mathlib.h"
+
+typedef struct
+{
+ int left;
+ int right;
+} portable_samplepair_t;
+
+typedef struct
+{
+ int length;
+ int loopstart;
+ int speed; // not needed, because converted on load?
+ int width;
+ int stereo;
+ byte data[1]; // variable sized
+} sfxcache_t;
+
+typedef struct sfx_s
+{
+ string name;
+ sfxcache_t *cache;
+
+ int registration_sequence;
+ bool default_sound;
+} sfx_t;
+
+// a playsound_t will be generated by each call to S_StartSound,
+// when the mixer reaches playsound->begin, the playsound will
+// be assigned to a channel
+typedef struct playsound_s
+{
+ struct playsound_s *prev, *next;
+ sfx_t *sfx;
+ float volume;
+ float attenuation;
+ int entnum;
+ int entchannel;
+ bool fixed_origin; // use origin field instead of entnum's origin
+ bool use_loop;
+ vec3_t origin;
+ uint begin; // begin on this sample
+} playsound_t;
+
+typedef struct
+{
+ 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;
+ byte *buffer;
+} dma_t;
+
+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 OBSOLETE?
+ int entnum; // to allow overriding a specific sound
+ int loopnum; // entity num that playing autosound
+ int loopframe; // for stopping looping sounds
+ int entchannel; //
+ vec3_t origin; // only use if fixed_origin is set
+ vec_t dist_mult; // distance multiplier (attenuation/clipK)
+ int master_vol; // 0-255 master volume
+ bool fixed_origin; // use origin instead of fetching entnum's origin
+ bool autosound; // from an entity->sound, cleared each frame
+ bool use_loop; // don't loop default and local sounds
+} 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;
+
+typedef struct
+{
+ string introName;
+ string loopName;
+ bool looping;
+ file_t *file;
+ int start;
+ int rate;
+ uint format;
+ void *vorbisFile;
+} bg_track_t;
+
+/*
+====================================================================
+
+ SYSTEM SPECIFIC FUNCTIONS
+
+====================================================================
+*/
+#define Host_Error com.error
+#define Z_Malloc( size ) Mem_Alloc( sndpool, size )
+
+// initializes cycling through a DMA buffer and returns information on it
+bool SNDDMA_Init( void *hInst );
+int SNDDMA_GetDMAPos( void );
+void SNDDMA_Shutdown( void );
+void SNDDMA_BeginPainting( void );
+void SNDDMA_Submit( void );
+
+//====================================================================
+
+#define MAX_CHANNELS 64
+#define MAX_RAW_SAMPLES 8192
+
+extern channel_t channels[MAX_CHANNELS];
+extern int paintedtime;
+extern int s_rawend;
+extern vec3_t listener_origin;
+extern vec3_t listener_forward;
+extern vec3_t listener_right;
+extern vec3_t listener_up;
+extern dma_t dma;
+extern playsound_t s_pendingplays;
+extern bool sound_started;
+
+extern cvar_t *s_check_errors;
+extern cvar_t *s_volume;
+extern cvar_t *s_nosound;
+extern cvar_t *s_loadas8bit;
+extern cvar_t *s_khz;
+extern cvar_t *s_show;
+extern cvar_t *s_mixahead;
+extern cvar_t *s_testsound;
+extern cvar_t *s_primary;
+
+extern portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES];
+
+void S_InitScaletable( void );
+sfxcache_t *S_LoadSound( sfx_t *sfx );
+void S_IssuePlaysound( playsound_t *ps );
+void S_PaintChannels( int endtime );
+
+bool S_Init( void *hInst );
+void S_Shutdown( void );
+void S_Activate( bool active );
+void S_SoundList_f( void );
+void S_SoundInfo_f( void );
+
+// if origin is NULL, the sound will be dynamically sourced from the entity
+void S_StartSound( const vec3_t pos, int ent, int chan, sound_t sfx, float vol, float attn, float pitch, bool use_loop);
+void S_Update( int entnum, const vec3_t pos, const vec3_t vel, const vec3_t axis[3], bool clear );
+void S_StreamRawSamples( int samples, int rate, int width, int channels, const byte *data );
+bool S_AddLoopingSound( int entnum, sound_t handle, float volume, float attn );
+void S_StartBackgroundTrack( const char *intro, const char *loop );
+channel_t *S_PickChannel( int entNum, int entChannel );
+int S_StartLocalSound( const char *name, float volume, float pitch, const float *org );
+sfx_t *S_GetSfxByHandle( sound_t handle );
+void S_StopBackgroundTrack( void );
+void S_StartStreaming( void );
+void S_StopStreaming( void );
+void S_StopAllSounds( void );
+void S_FreeSounds( void );
+
+void S_BeginRegistration( void );
+sound_t S_RegisterSound( const char *sample );
+void S_EndRegistration( void );
+
+#endif//SOUND_H
\ No newline at end of file
diff --git a/todo.log b/todo.log
index 3593b84c..630b25ea 100644
--- a/todo.log
+++ b/todo.log
@@ -155,6 +155,10 @@ Beta 13.12.09
128. fixup sprites lerping OK
129. fixup sound orientation OK
130. don't show console on changelevel OK
-131. support for doom3-style parsing
+131. support for doom3-style materials parsing
132. implement SENTENCE_system
-133. rebuild vsound.dll
+133. new sound\render system version replacement OK
+134. dx sound engine complete OK
+135. implement dsp, lypsync and vox
+136. re-vision uimenu
+137. complete rewriting physic.dll
diff --git a/render/cin.c b/vid_gl/cin.c
similarity index 100%
rename from render/cin.c
rename to vid_gl/cin.c
diff --git a/render/cin.h b/vid_gl/cin.h
similarity index 100%
rename from render/cin.h
rename to vid_gl/cin.h
diff --git a/render/r_aliasq.c b/vid_gl/r_aliasq.c
similarity index 100%
rename from render/r_aliasq.c
rename to vid_gl/r_aliasq.c
diff --git a/render/r_aliasq.old b/vid_gl/r_aliasq.old
similarity index 100%
rename from render/r_aliasq.old
rename to vid_gl/r_aliasq.old
diff --git a/render/r_backend.c b/vid_gl/r_backend.c
similarity index 100%
rename from render/r_backend.c
rename to vid_gl/r_backend.c
diff --git a/render/r_backend.h b/vid_gl/r_backend.h
similarity index 100%
rename from render/r_backend.h
rename to vid_gl/r_backend.h
diff --git a/render/r_bloom.c b/vid_gl/r_bloom.c
similarity index 100%
rename from render/r_bloom.c
rename to vid_gl/r_bloom.c
diff --git a/render/r_cin.c b/vid_gl/r_cin.c
similarity index 100%
rename from render/r_cin.c
rename to vid_gl/r_cin.c
diff --git a/render/r_cull.c b/vid_gl/r_cull.c
similarity index 100%
rename from render/r_cull.c
rename to vid_gl/r_cull.c
diff --git a/render/r_draw.c b/vid_gl/r_draw.c
similarity index 100%
rename from render/r_draw.c
rename to vid_gl/r_draw.c
diff --git a/render/r_image.c b/vid_gl/r_image.c
similarity index 96%
rename from render/r_image.c
rename to vid_gl/r_image.c
index c1a84a57..dfcf6901 100644
--- a/render/r_image.c
+++ b/vid_gl/r_image.c
@@ -443,7 +443,7 @@ void R_TextureList_f( void )
Msg( "---------------------------------------------------------\n" );
Msg( "%i total textures\n", texCount );
- Msg( "%.2f total megabytes of textures\n", bytes/1048576.0 );
+ Msg( "%s total memory used\n", memprint( bytes ));
Msg( "\n" );
}
diff --git a/render/r_light.c b/vid_gl/r_light.c
similarity index 100%
rename from render/r_light.c
rename to vid_gl/r_light.c
diff --git a/render/r_local.h b/vid_gl/r_local.h
similarity index 96%
rename from render/r_local.h
rename to vid_gl/r_local.h
index fab8ccc2..baeea7cf 100644
--- a/render/r_local.h
+++ b/vid_gl/r_local.h
@@ -124,7 +124,7 @@ enum
#define FOG_TEXTURE_WIDTH 256
#define FOG_TEXTURE_HEIGHT 32
-#define VID_DEFAULTMODE "4"
+#define VID_DEFAULTMODE "0"
#define SHADOW_PLANAR 1
#define SHADOW_MAPPING 2
diff --git a/render/r_main.c b/vid_gl/r_main.c
similarity index 100%
rename from render/r_main.c
rename to vid_gl/r_main.c
diff --git a/render/r_math.c b/vid_gl/r_math.c
similarity index 100%
rename from render/r_math.c
rename to vid_gl/r_math.c
diff --git a/render/r_math.h b/vid_gl/r_math.h
similarity index 100%
rename from render/r_math.h
rename to vid_gl/r_math.h
diff --git a/render/r_mesh.c b/vid_gl/r_mesh.c
similarity index 100%
rename from render/r_mesh.c
rename to vid_gl/r_mesh.c
diff --git a/render/r_mesh.h b/vid_gl/r_mesh.h
similarity index 100%
rename from render/r_mesh.h
rename to vid_gl/r_mesh.h
diff --git a/render/r_model.c b/vid_gl/r_model.c
similarity index 100%
rename from render/r_model.c
rename to vid_gl/r_model.c
diff --git a/render/r_model.h b/vid_gl/r_model.h
similarity index 100%
rename from render/r_model.h
rename to vid_gl/r_model.h
diff --git a/render/r_opengl.c b/vid_gl/r_opengl.c
similarity index 92%
rename from render/r_opengl.c
rename to vid_gl/r_opengl.c
index 30b867f3..c39c2038 100644
--- a/render/r_opengl.c
+++ b/vid_gl/r_opengl.c
@@ -239,7 +239,7 @@ bool R_SetPixelformat( void )
size_t gamma_size;
byte *savedGamma;
- Sys_LoadLibrary( &opengl_dll ); // load opengl32.dll
+ Sys_LoadLibrary( NULL, &opengl_dll ); // load opengl32.dll
if( !opengl_dll.link ) return false;
glw_state.minidriver = false; // FIXME
@@ -490,6 +490,20 @@ bool R_CreateWindow( int width, int height, bool fullscreen )
r_ypos = Cvar_Get( "r_ypos", "22", CVAR_ARCHIVE, "window position by vertical" );
x = r_xpos->integer;
y = r_ypos->integer;
+
+ // adjust window coordinates if necessary
+ // so that the window is completely on screen
+ if( x < 0 ) x = 0;
+ if( y < 0 ) y = 0;
+
+ if( Cvar_VariableInteger( "r_mode" ) != glConfig.prev_mode )
+ {
+ if((x + w > glw_state.desktopWidth) || (y + h > glw_state.desktopHeight))
+ {
+ x = ( glw_state.desktopWidth - w ) / 2;
+ y = ( glw_state.desktopHeight - h ) / 2;
+ }
+ }
}
glw_state.hWnd = CreateWindowEx( exstyle, "Xash Window", wndname, stylebits, x, y, w, h, NULL, NULL, glw_state.hInst, NULL );
@@ -522,13 +536,21 @@ bool R_CreateWindow( int width, int height, bool fullscreen )
rserr_t R_ChangeDisplaySettings( int vid_mode, bool fullscreen )
{
- int width, height;
-
+ int width, height;
+ HDC hDC;
+
R_SaveVideoMode( vid_mode );
width = r_width->integer;
height = r_height->integer;
+ // check our desktop attributes
+ hDC = GetDC( GetDesktopWindow() );
+ glw_state.desktopBitsPixel = GetDeviceCaps( hDC, BITSPIXEL );
+ glw_state.desktopWidth = GetDeviceCaps( hDC, HORZRES );
+ glw_state.desktopHeight = GetDeviceCaps( hDC, VERTRES );
+ ReleaseDC( GetDesktopWindow(), hDC );
+
// destroy the existing window
if( glw_state.hWnd ) R_Free_OpenGL();
diff --git a/render/r_opengl.h b/vid_gl/r_opengl.h
similarity index 97%
rename from render/r_opengl.h
rename to vid_gl/r_opengl.h
index 02e4fb1b..c764e23a 100644
--- a/render/r_opengl.h
+++ b/vid_gl/r_opengl.h
@@ -1107,6 +1107,10 @@ typedef struct
HINSTANCE hinstOpenGL; // HINSTANCE for the OpenGL library
+ int desktopBitsPixel;
+ int desktopWidth;
+ int desktopHeight;
+
bool software; // software emulation uses RB_RenderShader()
bool initialized; // OpenGL subsystem started
bool minidriver;
diff --git a/render/r_poly.c b/vid_gl/r_poly.c
similarity index 100%
rename from render/r_poly.c
rename to vid_gl/r_poly.c
diff --git a/render/r_program.c b/vid_gl/r_program.c
similarity index 100%
rename from render/r_program.c
rename to vid_gl/r_program.c
diff --git a/render/r_register.c b/vid_gl/r_register.c
similarity index 97%
rename from render/r_register.c
rename to vid_gl/r_register.c
index 4c50e10a..962c1222 100644
--- a/render/r_register.c
+++ b/vid_gl/r_register.c
@@ -522,8 +522,8 @@ void GL_InitCommands( void )
r_environment_color = Cvar_Get( "r_environment_color", "128 128 128", CVAR_ARCHIVE, "map environment light color" );
r_ignorehwgamma = Cvar_Get( "r_ignorehwgamma", "0", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "ignore hardware gamma (e.g. not support)" );
- r_overbrightbits = Cvar_Get( "r_overbrightbits", "1", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "renderer overbright bits" );
- r_mapoverbrightbits = Cvar_Get( "r_mapoverbrightbits", "2", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "current map overbright bits" );
+ r_overbrightbits = Cvar_Get( "r_overbrightbits", "0", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "renderer overbright bits" );
+ r_mapoverbrightbits = Cvar_Get( "r_mapoverbrightbits", "0", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "current map overbright bits" );
r_vertexbuffers = Cvar_Get( "r_vertexbuffers", "0", CVAR_ARCHIVE, "store vertex data in VBOs" );
r_detailtextures = Cvar_Get( "r_detailtextures", "1", CVAR_ARCHIVE, "enable or disable detail textures" );
diff --git a/render/r_shader.c b/vid_gl/r_shader.c
similarity index 100%
rename from render/r_shader.c
rename to vid_gl/r_shader.c
diff --git a/render/r_shader.h b/vid_gl/r_shader.h
similarity index 100%
rename from render/r_shader.h
rename to vid_gl/r_shader.h
diff --git a/render/r_shadow.c b/vid_gl/r_shadow.c
similarity index 100%
rename from render/r_shadow.c
rename to vid_gl/r_shadow.c
diff --git a/render/r_shadow.h b/vid_gl/r_shadow.h
similarity index 100%
rename from render/r_shadow.h
rename to vid_gl/r_shadow.h
diff --git a/render/r_sky.c b/vid_gl/r_sky.c
similarity index 100%
rename from render/r_sky.c
rename to vid_gl/r_sky.c
diff --git a/render/r_sprite.c b/vid_gl/r_sprite.c
similarity index 100%
rename from render/r_sprite.c
rename to vid_gl/r_sprite.c
diff --git a/render/r_studio.c b/vid_gl/r_studio.c
similarity index 100%
rename from render/r_studio.c
rename to vid_gl/r_studio.c
diff --git a/render/r_surf.c b/vid_gl/r_surf.c
similarity index 100%
rename from render/r_surf.c
rename to vid_gl/r_surf.c
diff --git a/render/render.plg b/vid_gl/render.plg
similarity index 100%
rename from render/render.plg
rename to vid_gl/render.plg
diff --git a/render/render.dsp b/vid_gl/vid_gl.dsp
similarity index 79%
rename from render/render.dsp
rename to vid_gl/vid_gl.dsp
index 71c6c097..7aaa702f 100644
--- a/render/render.dsp
+++ b/vid_gl/vid_gl.dsp
@@ -1,24 +1,24 @@
-# Microsoft Developer Studio Project File - Name="render" - Package Owner=<4>
+# Microsoft Developer Studio Project File - Name="vid_gl" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-CFG=render - Win32 Release
+CFG=vid_gl - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
-!MESSAGE NMAKE /f "render.mak".
+!MESSAGE NMAKE /f "vid_gl.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
-!MESSAGE NMAKE /f "render.mak" CFG="render - Win32 Release"
+!MESSAGE NMAKE /f "vid_gl.mak" CFG="vid_gl - Win32 Release"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
-!MESSAGE "render - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "render - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "vid_gl - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "vid_gl - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
@@ -29,7 +29,7 @@ CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
-!IF "$(CFG)" == "render - Win32 Release"
+!IF "$(CFG)" == "vid_gl - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
@@ -38,8 +38,8 @@ RSC=rc.exe
# PROP BASE Target_Dir "."
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "..\temp\render\!release"
-# PROP Intermediate_Dir "..\temp\render\!release"
+# PROP Output_Dir "..\temp\vid_gl\!release"
+# PROP Intermediate_Dir "..\temp\vid_gl\!release"
# PROP Ignore_Export_Lib 1
# PROP Target_Dir "."
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
@@ -57,16 +57,16 @@ LINK32=link.exe
# ADD LINK32 msvcrt.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /pdb:none /machine:I386 /nodefaultlib:"libc.lib" /libpath:"../public/libs/"
# SUBTRACT LINK32 /debug
# Begin Custom Build
-TargetDir=\Xash3D\src_main\temp\render\!release
-InputPath=\Xash3D\src_main\temp\render\!release\render.dll
+TargetDir=\Xash3D\src_main\temp\vid_gl\!release
+InputPath=\Xash3D\src_main\temp\vid_gl\!release\vid_gl.dll
SOURCE="$(InputPath)"
-"D:\Xash3D\bin\render.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- copy $(TargetDir)\render.dll "D:\Xash3D\bin\render.dll"
+"D:\Xash3D\bin\vid_gl.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ copy $(TargetDir)\vid_gl.dll "D:\Xash3D\bin\vid_gl.dll"
# End Custom Build
-!ELSEIF "$(CFG)" == "render - Win32 Debug"
+!ELSEIF "$(CFG)" == "vid_gl - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
@@ -75,8 +75,8 @@ SOURCE="$(InputPath)"
# PROP BASE Target_Dir "."
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "..\temp\render\!debug"
-# PROP Intermediate_Dir "..\temp\render\!debug"
+# PROP Output_Dir "..\temp\vid_gl\!debug"
+# PROP Intermediate_Dir "..\temp\vid_gl\!debug"
# PROP Ignore_Export_Lib 1
# PROP Target_Dir "."
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
@@ -94,12 +94,12 @@ LINK32=link.exe
# ADD LINK32 msvcrtd.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /nodefaultlib:"msvcrt.lib" /pdbtype:sept
# SUBTRACT LINK32 /profile /incremental:no /map
# Begin Custom Build
-TargetDir=\Xash3D\src_main\temp\render\!debug
-InputPath=\Xash3D\src_main\temp\render\!debug\render.dll
+TargetDir=\Xash3D\src_main\temp\vid_gl\!debug
+InputPath=\Xash3D\src_main\temp\vid_gl\!debug\vid_gl.dll
SOURCE="$(InputPath)"
-"D:\Xash3D\bin\render.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- copy $(TargetDir)\render.dll "D:\Xash3D\bin\render.dll"
+"D:\Xash3D\bin\vid_gl.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ copy $(TargetDir)\vid_gl.dll "D:\Xash3D\bin\vid_gl.dll"
# End Custom Build
@@ -107,8 +107,8 @@ SOURCE="$(InputPath)"
# Begin Target
-# Name "render - Win32 Release"
-# Name "render - Win32 Debug"
+# Name "vid_gl - Win32 Release"
+# Name "vid_gl - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
diff --git a/render/warpsin.h b/vid_gl/warpsin.h
similarity index 100%
rename from render/warpsin.h
rename to vid_gl/warpsin.h
diff --git a/vprogs/vprogs.plg b/vprogs/vprogs.plg
deleted file mode 100644
index d5eb623c..00000000
--- a/vprogs/vprogs.plg
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-Build Log
-
---------------------Configuration: vprogs - Win32 Debug--------------------
-
-Command Lines
-
-
-
-Results
-vprogs.dll - 0 error(s), 0 warning(s)
-
-
-
diff --git a/vsound/vsound.plg b/vsound/vsound.plg
deleted file mode 100644
index 548624db..00000000
--- a/vsound/vsound.plg
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-Build Log
-
---------------------Configuration: vsound - Win32 Debug--------------------
-
-Command Lines
-
-
-
-Results
-vsound.dll - 0 error(s), 0 warning(s)
-
-
-
diff --git a/xash.dsw b/xash.dsw
index 55f0de32..940f311e 100644
--- a/xash.dsw
+++ b/xash.dsw
@@ -87,7 +87,7 @@ Package=<4>
###############################################################################
-Project: "render"=".\render\render.dsp" - Package Owner=<4>
+Project: "vid_gl"=".\vid_gl\vid_gl.dsp" - Package Owner=<4>
Package=<5>
{{{
@@ -111,7 +111,19 @@ Package=<4>
###############################################################################
-Project: "vsound"=".\vsound\vsound.dsp" - Package Owner=<4>
+Project: "snd_al"=".\snd_al\snd_al.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "snd_dx"=".\snd_dx\snd_dx.dsp" - Package Owner=<4>
Package=<5>
{{{
diff --git a/xtools/bsplib/leakfile.c b/xtools/bsplib/leakfile.c
index c0aed17e..b0649734 100644
--- a/xtools/bsplib/leakfile.c
+++ b/xtools/bsplib/leakfile.c
@@ -73,7 +73,7 @@ void LeakFile( tree_t *tree )
MsgDev( D_NOTE, "--- LeakFile ---\n" );
// write the points to the file
- com.sprintf( filename, "%s.lin", source );
+ com.sprintf( filename, "maps/%s.lin", source );
linefile = FS_Open( filename, "w" );
if( !linefile ) Sys_Error( "couldn't open %s\n", filename );
diff --git a/xtools/xtools.c b/xtools/xtools.c
index 45dcc507..a7b6783e 100644
--- a/xtools/xtools.c
+++ b/xtools/xtools.c
@@ -77,7 +77,7 @@ void InitCommon( const int argc, const char **argv )
PrepareBSPModel( (int)argc, (char **)argv );
break;
case HOST_QCCLIB:
- Sys_LoadLibrary( &vprogs_dll ); // load qcclib
+ Sys_LoadLibrary( NULL, &vprogs_dll ); // load qcclib
CreateVprogs = (void *)vprogs_dll.main;
PRVM = CreateVprogs( &com, NULL ); // second interface not allowed
diff --git a/xtools/xtools.plg b/xtools/xtools.plg
deleted file mode 100644
index 2a5b16d7..00000000
--- a/xtools/xtools.plg
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-Build Log
-
---------------------Configuration: xtools - Win32 Debug--------------------
-
-Command Lines
-
-
-
-Results
-xtools.dll - 0 error(s), 0 warning(s)
-
-
-