Compare commits

..

6 Commits

Author SHA1 Message Date
Alibek Omarov
8c9b62cb03 Documentation: gameinfo: add a note about liblist.gam and gameinfo.txt changes 2025-01-07 10:10:25 +03:00
Alibek Omarov
9ff6eed0bf filesystem: wscript: check d_type field in struct dirent, as this is an extension and some supported ports (like psvita) don't have it 2025-01-07 10:10:18 +03:00
Alibek Omarov
b6196c3c95 filesystem: re-enable folder check for array returned by listdirectory with dirs_only set to true
According to glibc manual, not all filesystems support it and some might return DT_UNKNOWN.
2025-01-07 10:10:18 +03:00
Alibek Omarov
1ee2186f72 filesystem: massively rework how scanning game directories work
* No more conversion from liblist.gam to gameinfo.txt. We are using liblist.gam directly now.
  gameinfo.txt being native format to Xash3D not only remains, it takes priority over liblist.gam.
* Quake game directories now don't receive autogenerated gameinfo.txt.
* Empty directories don't get gameinfo.txt either, finally making it easier to support HD addon folders.
* If user still wishes to generate gameinfo.txt, there is now command fs_make_gameinfo that creates
  gameinfo.txt for currently running game.
* No more creating empty folders for RoDir. They are now created on demand.
2025-01-07 10:10:18 +03:00
Alibek Omarov
6099d5eadd wscript: fix bsp2 build bruh 2025-01-07 08:34:43 +03:00
Alibek Omarov
3d68e13585 filesystem: add utility function FS_CheckForQuakePak that parses Quake PAK file and looks for specific files in it's root
Used to properly detect Quake game dirs.
2025-01-07 07:55:43 +03:00
148 changed files with 2988 additions and 3920 deletions

View File

@@ -1,10 +1,10 @@
task:
name: freebsd-14-amd64
freebsd_instance:
image_family: freebsd-14-2
image_family: freebsd-14-0
setup_script:
- pkg update
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2
- pkg install -y pkgconf git sdl2 python fontconfig opus
- git submodule update --init --recursive
test_script:
- ./scripts/cirrus/build_freebsd.sh dedicated
@@ -16,7 +16,7 @@ task:
image_family: freebsd-15-0-snap
setup_script:
- pkg update
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2
- pkg install -y pkgconf git sdl2 python fontconfig opus
- git submodule update --init --recursive
test_script:
- ./scripts/cirrus/build_freebsd.sh dedicated

View File

@@ -66,7 +66,7 @@ jobs:
targetos: apple
targetarch: amd64
env:
SDL_VERSION: 2.30.12
SDL_VERSION: 2.30.10
GH_CPU_ARCH: ${{ matrix.targetarch }}
GH_CROSSCOMPILING: ${{ matrix.cross }}
steps:
@@ -87,7 +87,6 @@ jobs:
path: artifacts/*
flatpak:
runs-on: ubuntu-latest
continue-on-error: true
strategy:
matrix:
include:
@@ -101,7 +100,7 @@ jobs:
with:
submodules: recursive
- name: Build flatpak (Compat.i386)
uses: FWGS/flatpak-github-actions/flatpak-builder@v6.3-fix
uses: FWGS/flatpak-github-actions/flatpak-builder@v6.3
with:
bundle: ${{ matrix.app }}.flatpak
manifest-path: scripts/flatpak/${{ matrix.app }}.yml

View File

@@ -25,4 +25,5 @@ def build(bld):
name = 'extras.pk3',
files = srcdir.ant_glob('**/*'),
relative_to = srcdir,
compresslevel = 0,
install_path = install_path)

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
[![builds.sr.ht status](https://builds.sr.ht/~a1batross/xash3d-fwgs.svg)](https://builds.sr.ht/~a1batross/xash3d-fwgs?) [![GitHub Actions Status](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml/badge.svg)](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml) [![FreeBSD Build Status](https://img.shields.io/cirrus/github/FWGS/xash3d-fwgs?label=freebsd%20build)](https://cirrus-ci.com/github/FWGS/xash3d-fwgs) [![Discord Server](https://img.shields.io/discord/355697768582610945.svg)](http://fwgsdiscord.mentality.rip/) \
[![Download Stable](https://img.shields.io/badge/download-stable-yellow)](https://github.com/FWGS/xash3d-fwgs/releases/latest) [![Download Testing](https://img.shields.io/badge/downloads-testing-orange)](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous)
Xash3D ([pronounced](https://ipa-reader.com/?text=ks%C9%91%CA%82) `[ksɑʂ]`) FWGS is a game engine, aimed to provide compatibility with Half-Life Engine and extend it, as well as to give game developers well known workflow.
Xash3D (pronounced `[ksɑʂ]`) FWGS is a game engine, aimed to provide compatibility with Half-Life Engine and extend it, as well as to give game developers well known workflow.
Xash3D FWGS is a heavily modified fork of an original [Xash3D Engine](https://www.moddb.com/engines/xash3d-engine) by Unkle Mike.
@@ -65,21 +65,21 @@ This repository contains our fork of HLSDK and restored source code for Half-Lif
* Only for 32-bit engine on 64-bit x86 operating system:
* Enable i386 on your system: `$ sudo dpkg --add-architecture i386`.
* Install `aptitude` ([why?](https://github.com/FWGS/xash3d-fwgs/issues/1828#issuecomment-2415131759)): `$ sudo apt update && sudo apt upgrade && sudo apt install aptitude`
* Install development tools: `$ sudo aptitude --without-recommends install git build-essential gcc-multilib g++-multilib libsdl2-dev:i386 libfreetype-dev:i386 libopus-dev:i386 libbz2-dev:i386`.
* Install development tools: `$ sudo aptitude --without-recommends install git build-essential gcc-multilib g++-multilib libsdl2-dev:i386 libfontconfig-dev:i386 libfreetype-dev:i386 libopus-dev:i386 libbz2-dev:i386`.
* Set PKG_CONFIG_PATH environment variable to point at 32-bit libraries: `$ export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig`.
* For 64-bit engine on 64-bit x86 and other non-x86 systems:
* Install development tools: `$ sudo apt install git build-essential python libsdl2-dev libfreetype6-dev libopus-dev libbz2-dev`.
* Install development tools: `$ sudo apt install git build-essential python libsdl2-dev libfontconfig-dev libfreetype6-dev libopus-dev libbz2-dev`.
* Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`.
##### RedHat/Fedora
* Only for 32-bit engine on 64-bit x86 operating system:
* Install development tools: `$ sudo dnf install git gcc gcc-c++ glibc-devel.i686 SDL2-devel.i686 opus-devel.i686 freetype-devel.i686 bzip2-devel.i686`.
* Install development tools: `$ sudo dnf install git gcc gcc-c++ glibc-devel.i686 SDL2-devel.i686 opus-devel.i686 fontconfig-devel.i686 freetype-devel.i686 bzip2-devel.i686`.
* Set PKG_CONFIG_PATH environment variable to point at 32-bit libraries: `$ export PKG_CONFIG_PATH=/usr/lib/pkgconfig`.
* For 64-bit engine on 64-bit x86 and other non-x86 systems:
* Install development tools: `$ sudo dnf install git gcc gcc-c++ SDL2-devel opus-devel freetype-devel bzip2-devel`.
* Install development tools: `$ sudo dnf install git gcc gcc-c++ SDL2-devel opus-devel fontconfig-devel freetype-devel bzip2-devel`.
* Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`.

View File

@@ -30,18 +30,6 @@ public class XashActivity extends SDLActivity {
AndroidBug5497Workaround.assistActivity(this);
}
@Override
public void onDestroy()
{
super.onDestroy();
// Now that we don't exit from native code, we need to exit here, resetting
// application state (actually global variables that we don't cleanup on exit)
//
// When the issue with global variables will be resolved, remove that exit() call
System.exit(0);
}
@Override
protected String[] getLibraries() {
return new String[]{"SDL2", "xash"};

View File

@@ -16,6 +16,8 @@ GNU General Public License for more details.
#ifndef BSPFILE_H
#define BSPFILE_H
//#define SUPPORT_BSP2_FORMAT // allow to loading Darkplaces BSP2 maps (with broke binary compatibility)
/*
==============================================================================
@@ -63,6 +65,7 @@ BRUSH MODELS
#define MAX_MAP_CLIPNODES_BSP2 524288
// these limis not using by modelloader but only for displaying 'mapstats' correctly
#ifdef SUPPORT_BSP2_FORMAT
#define MAX_MAP_MODELS 2048 // embedded models
#define MAX_MAP_ENTSTRING 0x200000 // 2 Mb should be enough
#define MAX_MAP_PLANES 131072 // can be increased without problems
@@ -72,6 +75,18 @@ BRUSH MODELS
#define MAX_MAP_VERTS 524288 // can be increased without problems
#define MAX_MAP_FACES 262144 // can be increased without problems
#define MAX_MAP_MARKSURFACES 524288 // can be increased without problems
#else
// increased to match PrimeXT compilers
#define MAX_MAP_MODELS 1024 // embedded models
#define MAX_MAP_ENTSTRING 0x100000 // 1 Mb should be enough
#define MAX_MAP_PLANES 65536 // can be increased without problems
#define MAX_MAP_NODES 32767 // because negative shorts are leafs
#define MAX_MAP_CLIPNODES MAX_MAP_CLIPNODES_HLBSP // because negative shorts are contents
#define MAX_MAP_LEAFS 32767 // signed short limit
#define MAX_MAP_VERTS 65535 // unsigned short limit
#define MAX_MAP_FACES 65535 // unsigned short limit
#define MAX_MAP_MARKSURFACES 65535 // unsigned short limit
#endif
#define MAX_MAP_ENTITIES 8192 // network limit
#define MAX_MAP_TEXINFO MAX_MAP_FACES // in theory each face may have personal texinfo

View File

@@ -60,29 +60,26 @@ typedef struct
vec3_t position;
} mvertex_t;
typedef struct mclipnode32_s
typedef struct
{
int planenum;
int children[2]; // negative numbers are contents
} mclipnode32_t;
typedef struct mclipnode16_s
{
int planenum;
short children[2]; // negative numbers are contents
} mclipnode16_t;
int planenum;
#ifdef SUPPORT_BSP2_FORMAT
int children[2]; // negative numbers are contents
#else
short children[2]; // negative numbers are contents
#endif
} mclipnode_t;
// size is matched but representation is not
typedef struct medge32_s
typedef struct
{
#ifdef SUPPORT_BSP2_FORMAT
unsigned int v[2];
} medge32_t;
typedef struct medge16_s
{
#else
unsigned short v[2];
unsigned int cachededgeoffset;
} medge16_t;
#endif
} medge_t;
typedef struct texture_s
{
@@ -159,31 +156,13 @@ typedef struct mnode_s
// node specific
mplane_t *plane;
#if !XASH_64BIT
union
{
struct mnode_s *children_[2];
struct
{
// the ordering is important
int child_0_leaf : 1;
int child_0_off : 23;
int firstsurface_1 : 8;
int child_1_leaf : 1;
int child_1_off : 23;
int numsurfaces_1 : 8;
};
};
unsigned short firstsurface_0;
unsigned short numsurfaces_0;
struct mnode_s *children[2];
#ifdef SUPPORT_BSP2_FORMAT
int firstsurface;
int numsurfaces;
#else
// in 64-bit ABI this struct has 4 more bytes of padding, let's use it!
struct mnode_s *children_[2];
unsigned short firstsurface_0;
unsigned short numsurfaces_0;
unsigned short firstsurface_1;
unsigned short numsurfaces_1;
unsigned short firstsurface;
unsigned short numsurfaces;
#endif
} mnode_t;
@@ -224,6 +203,7 @@ typedef struct mleaf_s
int nummarksurfaces;
int cluster; // helper to acess to uncompressed visdata
byte ambient_sound_level[NUM_AMBIENTS];
} mleaf_t;
// surface extradata
@@ -311,11 +291,7 @@ struct msurface_s
typedef struct hull_s
{
union
{
mclipnode16_t *clipnodes16;
mclipnode32_t *clipnodes32;
};
mclipnode_t *clipnodes;
mplane_t *planes;
int firstclipnode;
int lastclipnode;
@@ -365,12 +341,7 @@ typedef struct model_s
mvertex_t *vertexes;
int numedges;
union
{
medge16_t *edges16;
medge32_t *edges32;
};
medge_t *edges;
int numnodes;
mnode_t *nodes;
@@ -385,11 +356,7 @@ typedef struct model_s
int *surfedges;
int numclipnodes;
union
{
mclipnode16_t *clipnodes16;
mclipnode32_t *clipnodes32;
};
mclipnode_t *clipnodes;
int nummarksurfaces;
msurface_t **marksurfaces;
@@ -583,68 +550,16 @@ typedef struct
#define ANIM_CYCLE 2
#define MOD_FRAMES 20
#define MAX_DEMOS 32
#define MAX_MOVIES 8
#define MAX_CDTRACKS 32
#define MAX_CLIENT_SPRITES 512 // SpriteTextures (0-256 hud, 256-512 client)
#define MAX_REQUESTS 64
STATIC_CHECK_SIZEOF( mnode_t, 52, 72 );
STATIC_CHECK_SIZEOF( mextrasurf_t, 324, 496 );
STATIC_CHECK_SIZEOF( decal_t, 60, 88 );
STATIC_CHECK_SIZEOF( mfaceinfo_t, 176, 304 );
// model flags (stored in model_t->flags)
#define MODEL_QBSP2 BIT( 28 ) // uses 32-bit types
// access functions
static inline mnode_t *node_child( const mnode_t *n, int side, const model_t *mod )
{
#if !XASH_64BIT
if( unlikely( mod->flags & MODEL_QBSP2 )) // MODEL_QBSP2
{
if( side == 0 )
{
if( n->child_0_leaf )
return (mnode_t *)(mod->leafs + n->child_0_off);
else
return (mnode_t *)(mod->nodes + n->child_0_off);
}
else
{
if( n->child_1_leaf )
return (mnode_t *)(mod->leafs + n->child_1_off);
else
return (mnode_t *)(mod->nodes + n->child_1_off);
}
}
return n->children_[side];
#else
return n->children_[side];
#endif
}
static inline void node_children( mnode_t *children[2], const mnode_t *n, const model_t *mod )
{
children[0] = node_child( n, 0, mod );
children[1] = node_child( n, 1, mod );
}
static inline int node_firstsurface( const mnode_t *n, const model_t *mod )
{
if( mod->flags & MODEL_QBSP2 )
return n->firstsurface_0 + ( n->firstsurface_1 << 16 );
else
return n->firstsurface_0;
}
static inline int node_numsurfaces( const mnode_t *n, const model_t *mod )
{
if( mod->flags & MODEL_QBSP2 )
return n->numsurfaces_0 + ( n->numsurfaces_1 << 16 );
else
return n->numsurfaces_0;
}
#endif//COM_MODEL_H

View File

@@ -16,31 +16,41 @@
#include STDINT_H
#include <assert.h>
typedef uint8_t byte;
typedef float vec_t;
typedef vec_t vec2_t[2];
typedef vec_t vec3_t[3];
typedef vec_t vec4_t[4];
typedef vec_t quat_t[4];
typedef byte rgba_t[4]; // unsigned byte colorpack
typedef byte rgb_t[3]; // unsigned byte colorpack
typedef vec_t matrix3x4[3][4];
typedef vec_t matrix4x4[4][4];
typedef uint32_t poolhandle_t;
typedef unsigned char byte;
typedef int sound_t;
typedef float vec_t;
typedef vec_t vec2_t[2];
typedef vec_t vec3_t[3];
typedef vec_t vec4_t[4];
typedef vec_t quat_t[4];
typedef byte rgba_t[4]; // unsigned byte colorpack
typedef byte rgb_t[3]; // unsigned byte colorpack
typedef vec_t matrix3x4[3][4];
typedef vec_t matrix4x4[4][4];
typedef uint32_t poolhandle_t;
#undef true
#undef false
// true and false are keywords in C++ and C23
#if !__cplusplus && __STDC_VERSION__ < 202311L
enum { false, true };
#endif
#ifndef __cplusplus
typedef enum { false, true } qboolean;
#else
typedef int qboolean;
#endif
#define MAX_STRING 256 // generic string
#define MAX_VA_STRING 1024 // compatibility macro
#define MAX_SYSPATH 1024 // system filepath
#define MAX_MODS 512 // environment games that engine can keep visible
typedef uint64_t longtime_t;
#define MAX_STRING 256 // generic string
#define MAX_INFO_STRING 256 // infostrings are transmitted across network
#define MAX_SERVERINFO_STRING 512 // server handles too many settings. expand to 1024?
#define MAX_LOCALINFO_STRING 32768 // localinfo used on server and not sended to the clients
#define MAX_SYSPATH 1024 // system filepath
#define MAX_VA_STRING 1024 // string length returned by va()
#define MAX_PRINT_MSG 8192 // how many symbols can handle single call of Con_Printf or Con_DPrintf
#define MAX_TOKEN 2048 // parse token length
#define MAX_MODS 512 // environment games that engine can keep visible
#define MAX_USERMSG_LENGTH 2048 // don't modify it's relies on a client-side definitions
#define BIT( n ) ( 1U << ( n ))
#define BIT64( n ) ( 1ULL << ( n ))
@@ -199,16 +209,35 @@ _inline float LittleFloat( float f )
#endif
typedef unsigned int dword;
typedef unsigned int uint;
typedef char string[MAX_STRING];
typedef off_t fs_offset_t;
typedef unsigned int dword;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef char string[MAX_STRING];
typedef struct file_s file_t; // normal file
typedef struct stream_s stream_t; // sound stream for background music playing
typedef off_t fs_offset_t;
#if XASH_WIN32
typedef int fs_size_t; // return type of _read, _write funcs
typedef int fs_size_t; // return type of _read, _write funcs
#else /* !XASH_WIN32 */
typedef ssize_t fs_size_t;
typedef ssize_t fs_size_t;
#endif /* !XASH_WIN32 */
typedef struct dllfunc_s
{
const char *name;
void **func;
} dllfunc_t;
typedef struct dll_info_s
{
const char *name; // name of library
const dllfunc_t *fcts; // list of dll exports
const size_t num_fcts;
qboolean crash; // crash if dll not found
void *link; // hinstance of loading library
} dll_info_t;
typedef void (*setpair_t)( const char *key, const void *value, const void *buffer, void *numpairs );
typedef void *(*pfnCreateInterface_t)( const char *, int * );
// config strings are a general means of communication from

View File

@@ -153,7 +153,6 @@ static void CL_WriteErrorMessage( int current_count, sizebuf_t *msg )
FS_Write( fp, &cls.starting_count, sizeof( int ));
FS_Write( fp, &current_count, sizeof( int ));
FS_Write( fp, &cls.legacymode, sizeof( cls.legacymode ));
FS_Write( fp, MSG_GetData( msg ), MSG_GetMaxBytes( msg ));
FS_Close( fp );
@@ -169,7 +168,7 @@ list last 32 messages for debugging net troubleshooting
*/
void CL_WriteMessageHistory( void )
{
oldcmd_t *old;
oldcmd_t *old, *failcommand;
sizebuf_t *msg = &net_message;
int i, thecmd;
@@ -193,49 +192,9 @@ void CL_WriteMessageHistory( void )
thecmd++;
}
old = &cls_message_debug.oldcmd[thecmd];
Con_Printf( S_RED "BAD: " S_DEFAULT "%i %04i %s\n", old->frame_number, old->starting_offset, CL_MsgInfo( old->command ));
CL_WriteErrorMessage( old->starting_offset, msg );
failcommand = &cls_message_debug.oldcmd[thecmd];
Con_Printf( "BAD: %3i:%s\n", MSG_GetNumBytesRead( msg ) - 1, CL_MsgInfo( failcommand->command ));
if( host_developer.value >= DEV_EXTENDED )
CL_WriteErrorMessage( MSG_GetNumBytesRead( msg ) - 1, msg );
cls_message_debug.parsing = false;
}
void CL_ReplayBufferDat_f( void )
{
file_t *f = FS_Open( Cmd_Argv( 1 ), "rb", true );
sizebuf_t msg;
char buffer[NET_MAX_MESSAGE];
int starting_count, current_count, protocol;
fs_offset_t len;
if( !f )
return;
FS_Read( f, &starting_count, sizeof( starting_count ));
FS_Read( f, &current_count, sizeof( current_count ));
FS_Read( f, &protocol, sizeof( protocol ));
cls.legacymode = protocol;
len = FS_Read( f, buffer, sizeof( buffer ));
FS_Close( f );
MSG_Init( &msg, __func__, buffer, len );
Delta_Shutdown();
Delta_Init();
clgame.maxEntities = MAX_EDICTS;
clgame.entities = Mem_Calloc( clgame.mempool, sizeof( *clgame.entities ) * clgame.maxEntities );
// ad-hoc implement
#if 0
{
const int message_pos = 12; // put real number here
MSG_SeekToBit( &msg, ( message_pos - 12 + 1 ) << 3, SEEK_SET );
CL_ParseYourMom( &msg, protocol );
}
#endif
Sys_Quit( __func__ );
}

View File

@@ -373,7 +373,7 @@ CL_WriteDemoUserMessage
Dumps the user message (demoaction)
====================
*/
void GAME_EXPORT CL_WriteDemoUserMessage( int size, byte *buffer )
void CL_WriteDemoUserMessage( const byte *buffer, size_t size )
{
if( !cls.demorecording || cls.demowaiting )
return;
@@ -624,10 +624,11 @@ static void CL_ReadDemoUserCmd( qboolean discard )
if( !discard )
{
const usercmd_t nullcmd = { 0 };
usercmd_t nullcmd;
sizebuf_t buf;
demoangle_t *a;
memset( &nullcmd, 0, sizeof( nullcmd ));
MSG_Init( &buf, "UserCmd", data, sizeof( data ));
// a1ba: I have no proper explanation why

View File

@@ -127,10 +127,8 @@ static void R_SplitEntityOnNode( mnode_t *node )
}
// recurse down the contacted sides
if( sides & 1 )
R_SplitEntityOnNode( node_child( node, 0, cl.worldmodel ));
if( sides & 2 )
R_SplitEntityOnNode( node_child( node, 1, cl.worldmodel ));
if( sides & 1 ) R_SplitEntityOnNode( node->children[0] );
if( sides & 2 ) R_SplitEntityOnNode( node->children[1] );
}
/*

View File

@@ -2229,3 +2229,4 @@ void CL_ThinkParticle( double frametime, particle_t *p )
break;
}
}

View File

@@ -556,7 +556,7 @@ static void CL_InitTitles( const char *filename )
Q_snprintf( name, sizeof( name ), TEXT_MSGNAME, i );
cl_textmessage[i].pName = copystringpool( clgame.mempool, name );
cl_textmessage[i].pName = _copystring( clgame.mempool, name, __FILE__, __LINE__ );
cl_textmessage[i].pMessage = cl_textbuffer[i];
}
@@ -2408,8 +2408,9 @@ CL_FindModelIndex
*/
static int GAME_EXPORT CL_FindModelIndex( const char *m )
{
char filepath[MAX_QPATH];
int i;
char filepath[MAX_QPATH];
static float lasttimewarn;
int i;
if( !COM_CheckString( m ))
return 0;
@@ -2426,6 +2427,13 @@ static int GAME_EXPORT CL_FindModelIndex( const char *m )
return i+1;
}
if( lasttimewarn < host.realtime )
{
// tell user about problem (but don't spam console)
Con_DPrintf( S_ERROR "Could not find index for model %s: not precached\n", filepath );
lasttimewarn = host.realtime + 1.0f;
}
return 0;
}
@@ -3348,6 +3356,28 @@ DemoApi implementation
=================
*/
/*
=================
Demo_IsRecording
=================
*/
static int GAME_EXPORT Demo_IsRecording( void )
{
return cls.demorecording;
}
/*
=================
Demo_IsPlayingback
=================
*/
static int GAME_EXPORT Demo_IsPlayingback( void )
{
return cls.demoplayback;
}
/*
=================
Demo_IsTimeDemo
@@ -3359,6 +3389,17 @@ static int GAME_EXPORT Demo_IsTimeDemo( void )
return cls.timedemo;
}
/*
=================
Demo_WriteBuffer
=================
*/
static void GAME_EXPORT Demo_WriteBuffer( int size, byte *buffer )
{
CL_WriteDemoUserMessage( buffer, size );
}
/*
=================
NetworkApi implementation
@@ -3544,6 +3585,28 @@ static int GAME_EXPORT NetAPI_CompareAdr( netadr_t *a, netadr_t *b )
return NET_CompareAdr( *a, *b );
}
/*
=================
NetAPI_StringToAdr
=================
*/
static int GAME_EXPORT NetAPI_StringToAdr( char *s, netadr_t *a )
{
return NET_StringToAdr( s, a );
}
/*
=================
NetAPI_ValueForKey
=================
*/
static const char * GAME_EXPORT NetAPI_ValueForKey( const char *s, const char *key )
{
return Info_ValueForKey( s, key );
}
/*
=================
NetAPI_RemoveKey
@@ -3740,10 +3803,10 @@ static event_api_t gEventApi =
static demo_api_t gDemoApi =
{
(void *)CL_IsRecordDemo,
(void *)CL_IsPlaybackDemo,
Demo_IsRecording,
Demo_IsPlayingback,
Demo_IsTimeDemo,
CL_WriteDemoUserMessage,
Demo_WriteBuffer,
};
net_api_t gNetApi =
@@ -3755,8 +3818,8 @@ net_api_t gNetApi =
NetAPI_CancelAllRequests,
NetAPI_AdrToString,
NetAPI_CompareAdr,
(void *)NET_StringToAdr,
Info_ValueForKey,
NetAPI_StringToAdr,
NetAPI_ValueForKey,
NetAPI_RemoveKey,
NetAPI_SetValueForKey,
};

View File

@@ -76,7 +76,6 @@ static CVAR_DEFINE_AUTO( cl_upmax, "1200", FCVAR_ARCHIVE, "max allowed incoming
CVAR_DEFINE_AUTO( cl_lw, "1", FCVAR_ARCHIVE|FCVAR_USERINFO, "enable client weapon predicting" );
CVAR_DEFINE_AUTO( cl_charset, "utf-8", FCVAR_ARCHIVE, "1-byte charset to use (iconv style)" );
CVAR_DEFINE_AUTO( cl_trace_consistency, "0", FCVAR_ARCHIVE, "enable consistency info tracing (good for developers)" );
CVAR_DEFINE_AUTO( cl_trace_stufftext, "0", FCVAR_ARCHIVE, "enable stufftext (server-to-client console commands) tracing (good for developers)" );
CVAR_DEFINE_AUTO( cl_trace_messages, "0", FCVAR_ARCHIVE|FCVAR_CHEAT, "enable message names tracing (good for developers)" );
CVAR_DEFINE_AUTO( cl_trace_events, "0", FCVAR_ARCHIVE|FCVAR_CHEAT, "enable events tracing (good for developers)" );
@@ -148,6 +147,11 @@ qboolean CL_IsRecordDemo( void )
return cls.demorecording;
}
qboolean CL_IsTimeDemo( void )
{
return cls.timedemo;
}
qboolean CL_DisableVisibility( void )
{
return cls.envshot_disable_vis;
@@ -594,7 +598,7 @@ CL_CreateCmd
*/
static void CL_CreateCmd( void )
{
usercmd_t nullcmd = { 0 }, *cmd;
usercmd_t nullcmd, *cmd;
runcmd_t *pcmd;
qboolean active;
double accurate_ms;
@@ -646,6 +650,7 @@ static void CL_CreateCmd( void )
}
else
{
memset( &nullcmd, 0, sizeof( nullcmd ));
cmd = &nullcmd;
}
@@ -718,20 +723,11 @@ static void CL_WritePacket( void )
int numbackup, maxbackup, maxcmds;
const connprotocol_t proto = cls.legacymode;
// FIXME: on Xash protocol we don't send move commands until ca_active
// to prevent outgoing_command outrun incoming_acknowledged
// which is fatal for some buggy mods like TFC
//
// ... but GoldSrc don't have (real) ca_validate state, so we consider
// ca_validate the same as ca_active, otherwise we don't pass validation
// of server-side mods like ReAuthCheck
const connstate_t min_state = proto == PROTO_GOLDSRC ? ca_validate : ca_active;
// don't send anything if playing back a demo
if( cls.demoplayback || cls.state < ca_connected || cls.state == ca_cinematic )
return;
if( cls.state < min_state )
if( cls.state <= ca_connected )
{
Netchan_TransmitBits( &cls.netchan, 0, "" );
return;
@@ -829,7 +825,7 @@ static void CL_WritePacket( void )
buf.pData[key] = CRC32_BlockSequence( &buf.pData[key + 1], size, cls.netchan.outgoing_sequence );
COM_Munge( &buf.pData[key + 1], Q_min( size, 255 ), cls.netchan.outgoing_sequence );
}
else if( !Host_IsLocalClient( ))
else
{
int size = MSG_GetRealBytesWritten( &buf ) - key - 1;
buf.pData[key] = CRC32_BlockSequence( &buf.pData[key + 1], size, cls.netchan.outgoing_sequence );
@@ -1598,9 +1594,6 @@ void CL_SetupNetchanForProtocol( connprotocol_t proto )
}
break;
default:
if( !Host_IsLocalClient( ))
SetBits( flags, NETCHAN_USE_LZSS );
cls.extensions = Q_atoi( Info_ValueForKey( Cmd_Argv( 1 ), "ext" ));
if( FBitSet( cls.extensions, NET_EXT_SPLITSIZE ))
@@ -1768,8 +1761,8 @@ static size_t NONNULL CL_BuildMasterServerScanRequest( char *buf, size_t size, u
// let master know about client version
Info_SetValueForKey( info, "clver", XASH_VERSION, remaining );
Info_SetValueForKey( info, "nat", nat ? "1" : "0", remaining );
Info_SetValueForKey( info, "commit", g_buildcommit, remaining );
Info_SetValueForKey( info, "branch", g_buildbranch, remaining );
Info_SetValueForKey( info, "commit", Q_buildcommit(), remaining );
Info_SetValueForKey( info, "branch", Q_buildbranch(), remaining );
Info_SetValueForKey( info, "os", Q_buildos(), remaining );
Info_SetValueForKey( info, "arch", Q_buildarch(), remaining );
@@ -3394,7 +3387,6 @@ static void CL_InitLocal( void )
Cvar_RegisterVariable( &rcon_address );
Cvar_RegisterVariable( &cl_trace_consistency );
Cvar_RegisterVariable( &cl_trace_stufftext );
Cvar_RegisterVariable( &cl_trace_messages );
Cvar_RegisterVariable( &cl_trace_events );
@@ -3489,8 +3481,6 @@ static void CL_InitLocal( void )
Cmd_AddCommand ("fullserverinfo", CL_FullServerinfo_f, "sent by server when serverinfo changes" );
Cmd_AddCommand ("upload", CL_BeginUpload_f, "uploading file to the server" );
Cmd_AddRestrictedCommand( "replaybufferdat", CL_ReplayBufferDat_f, "development and debugging tool" );
Cmd_AddRestrictedCommand ("quit", CL_Quit_f, "quit from game" );
Cmd_AddRestrictedCommand ("exit", CL_Quit_f, "quit from game" );
@@ -3668,8 +3658,6 @@ void CL_Init( void )
if( !CL_LoadProgs( libpath ))
Host_Error( "can't initialize %s: %s\n", libpath, COM_GetLibraryError( ));
ID_Init();
cls.build_num = 0;
cls.initialized = true;
cl.maxclients = 1; // allow to drawing player in menu

View File

@@ -1614,23 +1614,6 @@ void CL_UpdateUserPings( sizebuf_t *msg )
}
}
static const char *CL_CheckTypeToString( int check_type )
{
// renamed so they have same width and look better in console output
switch( check_type )
{
case force_exactfile:
return "exactfile";
case force_model_samebounds:
return "samebounds";
case force_model_specifybounds:
return "specbounds";
case force_model_specifybounds_if_avail:
return "specbounds2";
}
return "unknown";
}
static void CL_SendConsistencyInfo( sizebuf_t *msg, connprotocol_t proto )
{
qboolean user_changed_diskfile;
@@ -1896,9 +1879,6 @@ static void CL_ParseConsistencyInfo( sizebuf_t *msg, connprotocol_t proto )
return;
}
if( cl_trace_consistency.value )
Con_Printf( "Server wants consistency of the following resources:\n" );
skip_crc_change = NULL;
lastcheck = 0;
@@ -1930,7 +1910,7 @@ static void CL_ParseConsistencyInfo( sizebuf_t *msg, connprotocol_t proto )
pc = &cl.consistency_list[cl.num_consistency];
cl.num_consistency++;
memset( pc, 0, sizeof( *pc ));
memset( pc, 0, sizeof( consistency_t ));
pc->filename = pResource->szFileName;
pc->issound = (pResource->type == t_sound);
pc->orig_index = delta;
@@ -1943,9 +1923,6 @@ static void CL_ParseConsistencyInfo( sizebuf_t *msg, connprotocol_t proto )
pc->check_type = pResource->rguc_reserved[0];
}
if( cl_trace_consistency.value )
Con_Printf( "%s\t%s\t%s\n", COM_ResourceTypeFromIndex( pResource->type ), CL_CheckTypeToString( pc->check_type ), pc->filename );
skip_crc_change = pResource;
lastcheck = delta;
}

View File

@@ -91,11 +91,11 @@ static void CL_ParseNewMovevars( sizebuf_t *msg )
typedef struct delta_header_t
{
qboolean remove;
qboolean custom;
qboolean instanced;
uint16_t instanced_baseline_index;
uint16_t offset;
qboolean remove : 1;
qboolean custom : 1;
qboolean instanced : 1;
uint instanced_baseline_index : 6;
uint offset : 6;
} delta_header_t;
static int CL_ParseDeltaHeader( sizebuf_t *msg, qboolean delta, int oldnum, struct delta_header_t *hdr )
@@ -160,47 +160,33 @@ static int CL_GetEntityDelta( const struct delta_header_t *hdr, int entnum )
return DT_ENTITY_STATE_T;
}
static int CL_FlushEntityPacketGS( frame_t *frame, sizebuf_t *msg )
static void CL_FlushEntityPacketGS( frame_t *frame, sizebuf_t *msg )
{
int playerbytes = 0, numbase = 0;
frame->valid = false;
cl.validsequence = 0; // can't render a frame
// read it all but ignore it
while( 1 )
{
int newnum, bufstart;
int num = 0;
entity_state_t from = { 0 }, to;
delta_header_t hdr;
qboolean player;
if( MSG_ReadWord( msg ) != 0 )
{
MSG_SeekToBit( msg, -16, SEEK_CUR );
numbase = newnum = CL_ParseDeltaHeader( msg, true, numbase, &hdr );
num = CL_ParseDeltaHeader( msg, false, num, &hdr );
}
else break;
if( MSG_CheckOverflow( msg ))
Host_Error( "%s: overflow\n", __func__ );
player = CL_IsPlayerIndex( newnum );
bufstart = MSG_GetNumBytesRead( msg );
if( hdr.remove )
continue;
Delta_ReadGSFields( msg, CL_GetEntityDelta( &hdr, newnum ), &from, &to, cl.mtime[0] );
if( player )
playerbytes += MSG_GetNumBytesRead( msg ) - bufstart;
Delta_ReadGSFields( msg, CL_GetEntityDelta( &hdr, num ), &from, &to, cl.mtime[0] );
}
if( MSG_CheckOverflow( msg ))
Host_Error( "%s: overflow\n", __func__ );
return playerbytes;
}
static void CL_DeltaEntityGS( const delta_header_t *hdr, sizebuf_t *msg, frame_t *frame, int newnum, const entity_state_t *from )
@@ -217,7 +203,7 @@ static void CL_DeltaEntityGS( const delta_header_t *hdr, sizebuf_t *msg, frame_t
if(( newnum < 0 ) || ( newnum >= clgame.maxEntities ))
{
Con_DPrintf( S_ERROR "CL_DeltaEntity: invalid newnum: %d\n", newnum );
Host_Error( "%s: bad delta entity number: %i\n", __func__, newnum );
Host_Error( "%s: bad delta entity number: %i", __func__, newnum );
return;
}
@@ -281,7 +267,7 @@ static void CL_CopyPacketEntity( frame_t *frame, int num, const entity_state_t *
static int CL_ParsePacketEntitiesGS( sizebuf_t *msg, qboolean delta )
{
frame_t *frame, *oldframe;
int oldindex, oldnum, numbase = 0;
int oldindex, newnum, oldnum, numbase = 0;
entity_state_t *oldent;
int count;
int playerbytes = 0;
@@ -328,7 +314,7 @@ static int CL_ParsePacketEntitiesGS( sizebuf_t *msg, qboolean delta )
// read it all but ignore it
while( 1 )
{
int bufstart, newnum;
int bufstart;
qboolean player;
delta_header_t hdr;
int val = MSG_ReadWord( msg );
@@ -548,7 +534,7 @@ void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
{
if( MSG_CheckOverflow( msg ))
{
Host_Error( "%s: overflow!\n", __func__ );
Host_Error( "CL_ParseServerMessage: overflow!\n" );
return;
}

View File

@@ -138,7 +138,10 @@ intptr_t CL_RenderGetParm( const int parm, const int arg, const qboolean checkRe
switch( parm )
{
case PARM_BSP2_SUPPORTED:
#ifdef SUPPORT_BSP2_FORMAT
return 1;
#endif
return 0;
case PARAM_GAMEPAUSED:
return cl.paused;
case PARM_CLIENT_INGAME:
@@ -233,11 +236,6 @@ static intptr_t pfnRenderGetParm( int parm, int arg )
return CL_RenderGetParm( parm, arg, true );
}
static void pfnAVI_StreamSound( void *avi, int entnum, float fvol, float attn, float synctime )
{
return; // stub, use AVI_SetParm and AVI_Think to stream AVI sound
}
static render_api_t gRenderAPI =
{
pfnRenderGetParm, // GL_RenderGetParm,
@@ -270,7 +268,7 @@ static render_api_t gRenderAPI =
NULL, // R_UploadStretchRaw,
(void*)AVI_FreeVideo,
(void*)AVI_IsActive,
(void*)pfnAVI_StreamSound,
S_StreamAviSamples,
NULL,
NULL,
NULL, // GL_Bind,

View File

@@ -567,54 +567,57 @@ R_FizzEffect
Create a fizz effect
==============
*/
void GAME_EXPORT R_FizzEffect( cl_entity_t *ent, int modelIndex, int density )
void GAME_EXPORT R_FizzEffect( cl_entity_t *pent, int modelIndex, int density )
{
const float base_time = cl.time - 0.1f;
model_t *mod = CL_ModelHandle( modelIndex );
vec3_t volume, mins, maxs;
vec2_t speed;
int i;
TEMPENTITY *pTemp;
int i, width, depth;
float angle, maxHeight, speed;
float xspeed, yspeed, zspeed;
vec3_t origin;
model_t *mod;
if( !ent || !ent->model || !modelIndex || !mod )
if( !pent || !pent->model || !modelIndex )
return;
VectorCopy( ent->model->mins, mins );
VectorCopy( ent->model->maxs, maxs );
if(( mod = CL_ModelHandle( modelIndex )) == NULL )
return;
if( ent->angles[1] != 0.0f )
{
const float base_speed = ( ent->curstate.rendercolor.b ? -1.0f : 1.0f ) * ( ent->curstate.rendercolor.r * 256.0f + ent->curstate.rendercolor.g );
SinCos( DEG2RAD( ent->angles[1] ), &speed[1], &speed[0] );
speed[0] *= base_speed;
speed[1] *= base_speed;
}
else speed[0] = speed[1] = 0.0f;
maxHeight = pent->model->maxs[2] - pent->model->mins[2];
width = pent->model->maxs[0] - pent->model->mins[0];
depth = pent->model->maxs[1] - pent->model->mins[1];
VectorSubtract( maxs, mins, volume );
speed = ( pent->curstate.rendercolor.r<<8 | pent->curstate.rendercolor.g );
if( pent->curstate.rendercolor.b )
speed = -speed;
angle = DEG2RAD( pent->angles[YAW] );
SinCos( angle, &yspeed, &xspeed );
xspeed *= speed;
yspeed *= speed;
for( i = 0; i <= density; i++ )
{
TEMPENTITY *tent;
vec3_t origin;
origin[0] = mod->mins[0] + COM_RandomLong( 0, width - 1 );
origin[1] = mod->mins[1] + COM_RandomLong( 0, depth - 1 );
origin[2] = mod->mins[2];
pTemp = CL_TempEntAlloc( origin, mod );
VectorCopy( mins, origin );
origin[0] += COM_RandomLong( 0, (int)volume[0] - 1 );
origin[1] += COM_RandomLong( 0, (int)volume[1] - 1 );
if ( !pTemp ) return;
if( !( tent = CL_TempEntAlloc( origin, mod )))
return;
pTemp->flags |= FTENT_SINEWAVE;
tent->x = origin[0];
tent->y = origin[1];
tent->die = base_time;
tent->flags |= FTENT_SINEWAVE;
tent->entity.curstate.rendermode = kRenderTransAlpha;
Vector2Copy( speed, tent->entity.baseline.origin );
pTemp->x = origin[0];
pTemp->y = origin[1];
tent->entity.baseline.origin[2] = COM_RandomLong( 80, 140 );
tent->die += volume[2] / tent->entity.baseline.origin[2];
tent->entity.curstate.frame = COM_RandomLong( 0, tent->frameMax );
tent->entity.curstate.scale = 1.0f / COM_RandomFloat( 2.0f, 5.0f );
zspeed = COM_RandomLong( 80, 140 );
VectorSet( pTemp->entity.baseline.origin, xspeed, yspeed, zspeed );
pTemp->die = cl.time + ( maxHeight / zspeed ) - 0.1f;
pTemp->entity.curstate.frame = COM_RandomLong( 0, pTemp->frameMax );
// Set sprite scale
pTemp->entity.curstate.scale = 1.0f / COM_RandomFloat( 2.0f, 5.0f );
pTemp->entity.curstate.rendermode = kRenderTransAlpha;
pTemp->entity.curstate.renderamt = 255;
}
}

View File

@@ -466,8 +466,8 @@ static void R_ShowTree_r( mnode_t *node, float x, float y, float scale, int show
R_DrawNodeConnection( x, y, x + scale, y + scale );
}
R_ShowTree_r( node_child( node, 1, cl.worldmodel ), x - scale, y + scale, downScale, shownodes, viewleaf );
R_ShowTree_r( node_child( node, 0, cl.worldmodel ), x + scale, y + scale, downScale, shownodes, viewleaf );
R_ShowTree_r( node->children[1], x - scale, y + scale, downScale, shownodes, viewleaf );
R_ShowTree_r( node->children[0], x + scale, y + scale, downScale, shownodes, viewleaf );
world.recursion_level--;
}
@@ -482,7 +482,7 @@ static void R_ShowTree( void )
return;
world.recursion_level = 0;
viewleaf = Mod_PointInLeaf( refState.vieworg, cl.worldmodel->nodes, cl.worldmodel );
viewleaf = Mod_PointInLeaf( refState.vieworg, cl.worldmodel->nodes );
ref.dllFuncs.TriRenderMode( kRenderTransTexture );

View File

@@ -688,7 +688,6 @@ extern convar_t r_showtextures;
extern convar_t cl_bmodelinterp;
extern convar_t cl_lw; // local weapons
extern convar_t cl_charset;
extern convar_t cl_trace_consistency;
extern convar_t cl_trace_stufftext;
extern convar_t cl_trace_messages;
extern convar_t cl_trace_events;
@@ -737,7 +736,6 @@ void CL_ClearResourceLists( void );
//
// cl_debug.c
//
void CL_ReplayBufferDat_f( void );
void CL_Parse_Debug( qboolean enable );
void CL_Parse_RecordCommand( int cmd, int startoffset );
void CL_ResetFrame( frame_t *frame );
@@ -769,7 +767,7 @@ void CL_StartupDemoHeader( void );
void CL_DrawDemoRecording( void );
void CL_WriteDemoUserCmd( int cmdnumber );
void CL_WriteDemoMessage( qboolean startup, int start, sizebuf_t *msg );
void CL_WriteDemoUserMessage( int size, byte *buffer );
void CL_WriteDemoUserMessage( const byte *buffer, size_t size );
qboolean CL_DemoReadMessage( byte *buffer, size_t *length );
void CL_DemoInterpolateAngles( void );
void CL_CheckStartupDemos( void );
@@ -1121,7 +1119,7 @@ void Con_PageUp( int lines );
//
// s_main.c
//
typedef int sound_t;
void S_StreamAviSamples( void *Avi, int entnum, float fvol, float attn, float synctime );
void S_StartBackgroundTrack( const char *intro, const char *loop, int position, qboolean fullpath );
void S_StopBackgroundTrack( void );
void S_StreamSetPause( int pause );
@@ -1210,13 +1208,6 @@ void Key_EnableTextInput( qboolean enable, qboolean force );
int Key_ToUpper( int key );
void OSK_Draw( void );
//
// identification.c
//
void ID_Init( void );
const char *ID_GetMD5( void );
void GAME_EXPORT ID_SetCustomClientID( const char *id );
extern rgba_t g_color_table[8];
extern triangleapi_t gTriApi;
extern net_api_t gNetApi;

View File

@@ -622,7 +622,7 @@ int Con_UtfProcessCharForce( int in )
// TODO: get rid of global state where possible
static utfstate_t state = { 0 };
uint32_t ch = Q_DecodeUTF8( &state, in );
int ch = Q_DecodeUTF8( &state, in );
if( g_codepage == 1251 )
return Q_UnicodeToCP1251( ch );
@@ -2092,7 +2092,10 @@ void Con_RunConsole( void )
}
else
{
g_codepage = 0;
Con_Printf( S_WARN "Unknown charset %s, defaulting to cp1252", con_charset.string );
Cvar_DirectSet( &con_charset, "cp1252" );
g_codepage = 1252;
}
cls.accept_utf8 = !Q_stricmp( cl_charset.string, "utf-8" );

View File

@@ -43,6 +43,7 @@ static struct joy_axis_s
short val;
short prevval;
} joyaxis[MAX_AXES] = { 0 };
static byte currentbinding; // add posibility to remap keys, to place it in joykeys[]
static qboolean joy_initialized;
static CVAR_DEFINE_AUTO( joy_pitch, "100.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "joystick pitch sensitivity" );
@@ -59,9 +60,9 @@ static CVAR_DEFINE_AUTO( joy_pitch_deadzone, DEFAULT_JOY_DEADZONE, FCVAR_ARCHIVE
static CVAR_DEFINE_AUTO( joy_yaw_deadzone, DEFAULT_JOY_DEADZONE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "yaw axis deadzone. Value from 0 to 32767" );
static CVAR_DEFINE_AUTO( joy_axis_binding, "sfpyrl", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "axis hardware id to engine inner axis binding, "
"s - side, f - forward, y - yaw, p - pitch, r - left trigger, l - right trigger" );
static CVAR_DEFINE_AUTO( joy_found, "0", FCVAR_READ_ONLY, "is joystick is connected" );
static CVAR_DEFINE_AUTO( joy_index, "0", FCVAR_READ_ONLY, "current active joystick" );
CVAR_DEFINE_AUTO( joy_enable, "1", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable joystick" );
static CVAR_DEFINE_AUTO( joy_have_gyro, "0", FCVAR_READ_ONLY, "tells whether current active gamepad has gyroscope or not" );
static CVAR_DEFINE_AUTO( joy_calibrated, "0", FCVAR_READ_ONLY, "tells whether current active gamepad gyroscope has been calibrated or not" );
/*
============
@@ -70,30 +71,7 @@ Joy_IsActive
*/
qboolean Joy_IsActive( void )
{
return joy_enable.value;
}
/*
===========
Joy_SetCapabilities
===========
*/
void Joy_SetCapabilities( qboolean have_gyro )
{
Cvar_FullSet( joy_have_gyro.name, have_gyro ? "1" : "0", joy_have_gyro.flags );
}
/*
===========
Joy_SetCalibrationState
===========
*/
void Joy_SetCalibrationState( joy_calibration_state_t state )
{
if( (int)joy_calibrated.value == state )
return;
Cvar_FullSet( joy_calibrated.name, va( "%d", state ), joy_calibrated.flags );
return joy_found.value && joy_enable.value;
}
/*
@@ -103,7 +81,7 @@ Joy_HatMotionEvent
DPad events
============
*/
static void Joy_HatMotionEvent( int value )
void Joy_HatMotionEvent( byte hat, byte value )
{
struct
{
@@ -118,6 +96,9 @@ static void Joy_HatMotionEvent( int value )
};
int i;
if( !joy_found.value )
return;
for( i = 0; i < ARRAYSIZE( keys ); i++ )
{
if( value & keys[i].mask )
@@ -244,7 +225,7 @@ static void Joy_ProcessStick( const engineAxis_t engineAxis, short value )
val |= Joy_GetHatValueForAxis( JOY_AXIS_SIDE );
val |= Joy_GetHatValueForAxis( JOY_AXIS_FWD );
Joy_HatMotionEvent( val );
Joy_HatMotionEvent( 0, val );
}
}
@@ -255,9 +236,23 @@ Joy_AxisMotionEvent
Axis events
=============
*/
void Joy_AxisMotionEvent( engineAxis_t engineAxis, short value )
void Joy_AxisMotionEvent( byte axis, short value )
{
if( engineAxis >= JOY_AXIS_NULL )
if( !joy_found.value )
return;
if( axis >= MAX_AXES )
{
Con_Reportf( "Only 6 axes is supported\n" );
return;
}
Joy_KnownAxisMotionEvent( joyaxesmap[axis], value );
}
void Joy_KnownAxisMotionEvent( engineAxis_t engineAxis, short value )
{
if( engineAxis == JOY_AXIS_NULL )
return;
if( value == joyaxis[engineAxis].val )
@@ -271,14 +266,66 @@ void Joy_AxisMotionEvent( engineAxis_t engineAxis, short value )
/*
=============
Joy_GyroEvent
Joy_BallMotionEvent
Gyroscope events
Trackball events. UNDONE
=============
*/
void Joy_GyroEvent( vec3_t data )
void Joy_BallMotionEvent( byte ball, short xrel, short yrel )
{
//if( !joy_found.value )
// return;
}
/*
=============
Joy_ButtonEvent
Button events
=============
*/
void Joy_ButtonEvent( byte button, byte down )
{
if( !joy_found.value )
return;
// generic game button code.
if( button > 32 )
{
int origbutton = button;
button = ( button & 31 ) + K_AUX1;
Con_Reportf( "Only 32 joybuttons is supported, converting %i button ID to %s\n", origbutton, Key_KeynumToString( button ) );
}
else button += K_AUX1;
Key_Event( button, down );
}
/*
=============
Joy_RemoveEvent
Called when joystick is removed. For future expansion
=============
*/
void Joy_RemoveEvent( void )
{
if( joy_found.value )
Cvar_FullSet( "joy_found", "0", FCVAR_READ_ONLY );
}
/*
=============
Joy_RemoveEvent
Called when joystick is removed. For future expansion
=============
*/
void Joy_AddEvent( void )
{
if( joy_enable.value && !joy_found.value )
Cvar_FullSet( "joy_found", "1", FCVAR_READ_ONLY );
}
/*
@@ -317,19 +364,14 @@ void Joy_FinalizeMove( float *fw, float *side, float *dpitch, float *dyaw )
*fw -= joy_forward.value * (float)joyaxis[JOY_AXIS_FWD ].val/(float)SHRT_MAX; // must be form -1.0 to 1.0
*side += joy_side.value * (float)joyaxis[JOY_AXIS_SIDE].val/(float)SHRT_MAX;
#if !defined(XASH_SDL)
*dpitch += joy_pitch.value * (float)joyaxis[JOY_AXIS_PITCH].val/(float)SHRT_MAX * host.realframetime; // abs axis rotate is frametime related
*dyaw -= joy_yaw.value * (float)joyaxis[JOY_AXIS_YAW ].val/(float)SHRT_MAX * host.realframetime;
#else
// HACKHACK: SDL have inverted look axis.
*dpitch -= joy_pitch.value * (float)joyaxis[JOY_AXIS_PITCH].val/(float)SHRT_MAX * host.realframetime;
*dyaw += joy_yaw.value * (float)joyaxis[JOY_AXIS_YAW ].val/(float)SHRT_MAX * host.realframetime;
}
static void Joy_CalibrateGyro_f( void )
{
if( !joy_have_gyro.value )
{
Con_Printf( "Current active gamepad doesn't have gyroscope\n" );
return;
}
Platform_CalibrateGamepadGyro();
#endif
}
/*
@@ -341,8 +383,6 @@ Main init procedure
*/
void Joy_Init( void )
{
Cmd_AddRestrictedCommand( "joy_calibrate_gyro", Joy_CalibrateGyro_f, "calibrate gamepad gyroscope. You must to put gamepad on stationary surface" );
Cvar_RegisterVariable( &joy_pitch );
Cvar_RegisterVariable( &joy_yaw );
Cvar_RegisterVariable( &joy_side );
@@ -362,9 +402,11 @@ void Joy_Init( void )
Cvar_RegisterVariable( &joy_yaw_deadzone );
Cvar_RegisterVariable( &joy_axis_binding );
Cvar_RegisterVariable( &joy_found );
// we doesn't loaded config.cfg yet, so this cvar is not archive.
// change by +set joy_index in cmdline
Cvar_RegisterVariable( &joy_index );
Cvar_RegisterVariable( &joy_have_gyro );
Cvar_RegisterVariable( &joy_calibrated );
Cvar_RegisterVariable( &joy_enable );
// renamed from -nojoy to -noenginejoy to not conflict with
@@ -375,7 +417,7 @@ void Joy_Init( void )
return;
}
Platform_JoyInit();
Cvar_FullSet( "joy_found", va( "%d", Platform_JoyInit( joy_index.value )), FCVAR_READ_ONLY );
joy_initialized = true;
}
@@ -389,5 +431,8 @@ Shutdown joystick code
*/
void Joy_Shutdown( void )
{
Platform_JoyShutdown();
if( joy_initialized )
{
Cvar_FullSet( "joy_found", 0, FCVAR_READ_ONLY );
}
}

View File

@@ -266,7 +266,7 @@ static qboolean Touch_DumpConfig( const char *name, const char *profilename )
}
FS_Printf( f, "//=======================================================================\n");
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch());
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), Q_buildcommit(), Q_buildbranch(), Q_buildos(), Q_buildarch());
FS_Printf( f, "//\t\t\ttouchscreen config\n" );
FS_Printf( f, "//=======================================================================\n" );
FS_Printf( f, "\ntouch_config_file \"%s\"\n", profilename );
@@ -902,10 +902,9 @@ static void Touch_AddButton_f( void )
rgba_t color;
int argc = Cmd_Argc( );
touch_button_t *button = NULL;
const char *name, *command;
const char *name, *texture, *command;
float x1, y1, x2, y2;
qboolean privileged = Cmd_CurrentCommandIsPrivileged();
string texture;
if( argc < 4 )
{
@@ -914,18 +913,9 @@ static void Touch_AddButton_f( void )
}
name = Cmd_Argv( 1 );
Q_strncpy( texture, Cmd_Argv( 2 ), sizeof( texture ));
texture = Cmd_Argv( 2 );
command = Cmd_Argv( 3 );
// HACKHACK: old engine specifically used .tga for touch buttons
// and because new engine extras.pk3 don't have .tga textures
// (which instead were converted to .png) strip extension to let
// to let imagelib choose better format
//
// Remove this when old engine migration would be done
if( Q_stricmp( COM_FileExtension( texture ), "tga" ))
COM_StripExtension( texture );
if( argc < 8 )
{
x1 = y1 = 0.4f;

View File

@@ -104,21 +104,18 @@ typedef enum engineAxis_e
JOY_AXIS_NULL
} engineAxis_t;
typedef enum joy_calibration_state_s
{
JOY_NOT_CALIBRATED = 0,
JOY_CALIBRATING,
JOY_FAILED_TO_CALIBRATE,
JOY_CALIBRATED
} joy_calibration_state_t;
qboolean Joy_IsActive( void );
void Joy_SetCapabilities( qboolean have_gyro );
void Joy_SetCalibrationState( joy_calibration_state_t state );
void Joy_AxisMotionEvent( engineAxis_t engineAxis, short value );
void Joy_GyroEvent( vec3_t data );
void Joy_HatMotionEvent( byte hat, byte value );
void Joy_AxisMotionEvent( byte axis, short value );
void Joy_KnownAxisMotionEvent( engineAxis_t engineAxis, short value );
void Joy_BallMotionEvent( byte ball, short xrel, short yrel );
void Joy_ButtonEvent( byte button, byte down );
void Joy_AddEvent( void );
void Joy_RemoveEvent( void );
void Joy_FinalizeMove( float *fw, float *side, float *dpitch, float *dyaw );
void Joy_Init( void );
void Joy_Shutdown( void );
void Joy_EnableTextInput(qboolean enable, qboolean force);
#endif//INPUT_H

View File

@@ -51,7 +51,7 @@ static const keyname_t keynames[] =
{"CTRL", K_CTRL, "+attack" },
{"SHIFT", K_SHIFT, "+speed" },
{"CAPSLOCK", K_CAPSLOCK, "" },
{"SCROLLOCK", K_SCROLLLOCK, "" },
{"SCROLLOCK", K_SCROLLOCK, "" },
{"F1", K_F1, "cmd help" },
{"F2", K_F2, "menu_savegame" },
{"F3", K_F3, "menu_loadgame" },
@@ -215,7 +215,7 @@ const char *Key_KeynumToString( int keynum )
return "<OUT OF RANGE>";
// check for printable ascii (don't use quote)
if( keynum > 32 && keynum < 127 && keynum != '"' && keynum != ';' && keynum != K_SCROLLLOCK )
if( keynum > 32 && keynum < 127 && keynum != '"' && keynum != ';' && keynum != K_SCROLLOCK )
{
tinystr[0] = keynum;
tinystr[1] = 0;
@@ -861,9 +861,7 @@ void GAME_EXPORT Key_ClearStates( void )
for( i = 0; i < 256; i++ )
{
if( i >= K_MOUSE1 && i <= K_MOUSE5 )
IN_MouseEvent( i - K_MOUSE1, false );
else
if( keys[i].down && i < K_MOUSE1 && i > K_MOUSE5 )
Key_Event( i, false );
keys[i].down = 0;
@@ -871,6 +869,9 @@ void GAME_EXPORT Key_ClearStates( void )
keys[i].gamedown = 0;
}
for( i = K_MOUSE1; i < K_MOUSE5; i++ ) // from K_MOUSE1 to K_MOUSE5
IN_MouseEvent( i - K_MOUSE1, false );
if( clgame.hInstance )
clgame.dllFuncs.IN_ClearStates();
}
@@ -1107,7 +1108,7 @@ static qboolean OSK_KeyEvent( int key, int down )
/*
=============
OSK_EnableTextInput
Joy_EnableTextInput
Enables built-in IME
=============

View File

@@ -470,16 +470,16 @@ out_free:
* This is a stack of the clipnodes we have traversed
* "sides" indicates which side we went down each time
*/
static int node_stack[MAX_CLIPNODE_DEPTH];
static mclipnode_t *node_stack[MAX_CLIPNODE_DEPTH];
static int side_stack[MAX_CLIPNODE_DEPTH];
static uint node_stack_depth;
static void push_node( int nodenum, int side )
static void push_node( mclipnode_t *node, int side )
{
if( node_stack_depth == MAX_CLIPNODE_DEPTH )
Host_Error( "node stack overflow\n" );
node_stack[node_stack_depth] = nodenum;
node_stack[node_stack_depth] = node;
side_stack[node_stack_depth] = side;
node_stack_depth++;
}
@@ -502,27 +502,22 @@ static void free_hull_polys( hullnode_t *hull_polys )
}
}
static void hull_windings_r( hull_t *hull, int nodenum, hullnode_t *polys, hull_model_t *model );
static void hull_windings_r( hull_t *hull, mclipnode_t *node, hullnode_t *polys, hull_model_t *model );
static void do_hull_recursion( hull_t *hull, int nodenum, int side, hullnode_t *polys, hull_model_t *model )
static void do_hull_recursion( hull_t *hull, mclipnode_t *node, int side, hullnode_t *polys, hull_model_t *model )
{
winding_t *w, *next;
int childnum;
if( world.version == QBSP2_VERSION )
childnum = hull->clipnodes32[nodenum].children[side];
else
childnum = hull->clipnodes16[nodenum].children[side];
if( childnum >= 0 )
if( node->children[side] >= 0 )
{
push_node( nodenum, side );
hull_windings_r( hull, childnum, polys, model );
mclipnode_t *child = hull->clipnodes + node->children[side];
push_node( node, side );
hull_windings_r( hull, child, polys, model );
pop_node();
}
else
{
switch( childnum )
switch( node->children[side] )
{
case CONTENTS_EMPTY:
case CONTENTS_WATER:
@@ -547,25 +542,20 @@ static void do_hull_recursion( hull_t *hull, int nodenum, int side, hullnode_t *
}
break;
default:
Host_Error( "bad contents: %i\n", childnum );
Host_Error( "bad contents: %i\n", node->children[side] );
break;
}
}
}
static void hull_windings_r( hull_t *hull, int nodenum, hullnode_t *polys, hull_model_t *model )
static void hull_windings_r( hull_t *hull, mclipnode_t *node, hullnode_t *polys, hull_model_t *model )
{
mplane_t *plane;
mplane_t *plane = hull->planes + node->planenum;
hullnode_t frontlist = LIST_HEAD_INIT( frontlist );
hullnode_t backlist = LIST_HEAD_INIT( backlist );
winding_t *w, *next, *front, *back;
int i;
if( world.version == QBSP2_VERSION )
plane = hull->planes + hull->clipnodes32[nodenum].planenum;
else
plane = hull->planes + hull->clipnodes16[nodenum].planenum;
list_for_each_entry_safe( w, next, polys, chain )
{
// PARANIOA - PAIR CHECK
@@ -611,13 +601,7 @@ static void hull_windings_r( hull_t *hull, int nodenum, hullnode_t *polys, hull_
for( i = 0; w && i < node_stack_depth; i++ )
{
mplane_t *p;
if( world.version == QBSP2_VERSION )
p = hull->planes + hull->clipnodes32[node_stack[i]].planenum;
else
p = hull->planes + hull->clipnodes16[node_stack[i]].planenum;
mplane_t *p = hull->planes + node_stack[i]->planenum;
w = winding_clip( w, p, false, side_stack[i], 0.00001 );
}
@@ -641,8 +625,8 @@ static void hull_windings_r( hull_t *hull, int nodenum, hullnode_t *polys, hull_
Con_Printf( S_WARN "new winding was clipped away!\n" );
}
do_hull_recursion( hull, nodenum, 0, &frontlist, model );
do_hull_recursion( hull, nodenum, 1, &backlist, model );
do_hull_recursion( hull, node, 0, &frontlist, model );
do_hull_recursion( hull, node, 1, &backlist, model );
}
static void remove_paired_polys( hull_model_t *model )
@@ -671,7 +655,7 @@ static void make_hull_windings( hull_t *hull, hull_model_t *model )
if( hull->planes != NULL )
{
hull_windings_r( hull, hull->firstclipnode, &head, model );
hull_windings_r( hull, hull->clipnodes + hull->firstclipnode, &head, model );
remove_paired_polys( model );
}
Con_Reportf( "%i hull polys\n", model->num_polys );

View File

@@ -300,12 +300,6 @@ static qboolean R_Init_Video_( const int type )
return R_Init_Video( type );
}
static mleaf_t *pfnMod_PointInLeaf( const vec3_t p, mnode_t *node )
{
// FIXME: get rid of this on next RefAPI update
return Mod_PointInLeaf( p, node, cl.models[1] );
}
static const ref_api_t gEngfuncs =
{
pfnEngineGetParm,
@@ -346,7 +340,7 @@ static const ref_api_t gEngfuncs =
Mod_SampleSizeForFace,
Mod_BoxVisible,
pfnMod_PointInLeaf,
Mod_PointInLeaf,
R_DrawWorldHull,
R_DrawModelHull,

View File

@@ -312,7 +312,7 @@ static int DLY_Init( int idelay, float delay )
cur = &rgsxdly[idelay];
cur->cdelaysamplesmax = ((int)(delay * idsp_dma_speed) << sxhires) + 1;
cur->lpdelayline = (int *)Mem_Calloc( sndpool, cur->cdelaysamplesmax * sizeof( int ));
cur->lpdelayline = (int *)Z_Calloc( cur->cdelaysamplesmax * sizeof( int ));
cur->xfade = 0;
// init modulation

View File

@@ -107,18 +107,17 @@ S_CreateDefaultSound
*/
static wavdata_t *S_CreateDefaultSound( void )
{
wavdata_t *sc;
uint samples = SOUND_DMA_SPEED;
uint channels = 1;
uint width = 2;
size_t size = samples * width * channels;
wavdata_t *sc;
sc = Mem_Calloc( sndpool, sizeof( wavdata_t ) + size );
sc->width = width;
sc->channels = channels;
sc = Mem_Calloc( sndpool, sizeof( wavdata_t ));
sc->width = 2;
sc->channels = 1;
sc->loopStart = 0;
sc->rate = SOUND_DMA_SPEED;
sc->samples = samples;
sc->size = size;
sc->samples = SOUND_DMA_SPEED;
sc->size = sc->samples * sc->width * sc->channels;
sc->buffer = Mem_Calloc( sndpool, sc->size );
return sc;
}

View File

@@ -996,7 +996,7 @@ static void S_UpdateAmbientSounds( void )
// calc ambient sound levels
if( !cl.worldmodel ) return;
leaf = Mod_PointInLeaf( s_listener.origin, cl.worldmodel->nodes, cl.worldmodel );
leaf = Mod_PointInLeaf( s_listener.origin, cl.worldmodel->nodes );
if( !leaf || !s_ambient_level.value )
{
@@ -1207,6 +1207,86 @@ void S_RawSamples( uint samples, uint rate, word width, word channels, const byt
S_RawEntSamples( entnum, samples, rate, width, channels, data, snd_vol );
}
/*
===================
S_PositionedRawSamples
===================
*/
void S_StreamAviSamples( void *Avi, int entnum, float fvol, float attn, float synctime )
{
int bufferSamples;
int fileSamples;
byte raw[MAX_RAW_SAMPLES];
float duration = 0.0f;
int r, fileBytes;
rawchan_t *ch = NULL;
if( !dma.initialized || s_listener.paused || !CL_IsInGame( ))
return;
if( entnum < 0 || entnum >= GI->max_edicts )
return;
if( !( ch = S_FindRawChannel( entnum, true )))
return;
if( ch->sound_info.rate == 0 )
{
if( !AVI_GetAudioInfo( Avi, &ch->sound_info ))
return; // no audiotrack
}
ch->master_vol = bound( 0, fvol * 255, 255 );
ch->dist_mult = (attn / SND_CLIP_DISTANCE);
// see how many samples should be copied into the raw buffer
if( ch->s_rawend < soundtime )
ch->s_rawend = soundtime;
// position is changed, synchronization is lost etc
if( fabs( ch->oldtime - synctime ) > s_mixahead.value )
ch->sound_info.loopStart = AVI_TimeToSoundPosition( Avi, synctime * 1000 );
ch->oldtime = synctime; // keep actual time
while( ch->s_rawend < soundtime + ch->max_samples )
{
wavdata_t *info = &ch->sound_info;
bufferSamples = ch->max_samples - (ch->s_rawend - soundtime);
// decide how much data needs to be read from the file
fileSamples = bufferSamples * ((float)info->rate / SOUND_DMA_SPEED );
if( fileSamples <= 1 ) return; // no more samples need
// our max buffer size
fileBytes = fileSamples * ( info->width * info->channels );
if( fileBytes > sizeof( raw ))
{
fileBytes = sizeof( raw );
fileSamples = fileBytes / ( info->width * info->channels );
}
// read audio stream
r = AVI_GetAudioChunk( Avi, raw, info->loopStart, fileBytes );
info->loopStart += r; // advance play position
if( r < fileBytes )
{
fileBytes = r;
fileSamples = r / ( info->width * info->channels );
}
if( r > 0 )
{
// add to raw buffer
ch->s_rawend = S_RawSamplesStereo( ch->rawsamples, ch->s_rawend, ch->max_samples,
fileSamples, info->rate, info->width, info->channels, raw );
}
else break; // no more samples for this frame
}
}
/*
===================
S_FreeIdleRawChannels
@@ -1874,15 +1954,14 @@ qboolean S_Init( void )
Cmd_AddCommand( "spk", S_SayReliable_f, "reliable play a specified sententce" );
Cmd_AddCommand( "speak", S_Say_f, "playing a specified sententce" );
sndpool = Mem_AllocPool( "Sound Zone" );
dma.backendName = "None";
if( !SNDDMA_Init( ))
if( !SNDDMA_Init( ) )
{
Con_Printf( "Audio: sound system can't be initialized\n" );
Mem_FreePool( &sndpool );
return false;
}
sndpool = Mem_AllocPool( "Sound Zone" );
soundtime = 0;
paintedtime = 0;

View File

@@ -16,7 +16,6 @@ GNU General Public License for more details.
#include "common.h"
#include "sound.h"
#include "client.h"
#include "soundlib.h"
static bg_track_t s_bgTrack;
static musicfade_t musicfade; // controlled by game dlls
@@ -213,7 +212,7 @@ void S_StreamBackgroundTrack( void )
while( ch->s_rawend < soundtime + ch->max_samples )
{
const stream_t *info = s_bgTrack.stream;
wavdata_t *info = FS_StreamInfo( s_bgTrack.stream );
bufferSamples = ch->max_samples - (ch->s_rawend - soundtime);

View File

@@ -557,7 +557,7 @@ static void VOX_ReadSentenceFile_( byte *buf, fs_offset_t size )
int index = cszrawsentences;
int size = strlen( name ) + strlen( value ) + 2;
rgpszrawsentence[index] = Mem_Malloc( sndpool, size );
rgpszrawsentence[index] = Mem_Malloc( host.mempool, size );
memcpy( rgpszrawsentence[index], name, size );
rgpszrawsentence[index][size - 1] = 0;
cszrawsentences++;

View File

@@ -114,6 +114,7 @@ typedef struct rawchan_s
vec3_t origin; // only use if fixed_origin is set
volatile uint s_rawend;
float oldtime; // catch time jumps
wavdata_t sound_info; // advance play position
size_t max_samples; // buffer length
portable_samplepair_t rawsamples[]; // variable sized
} rawchan_t;
@@ -170,8 +171,6 @@ typedef struct
int source; // may be game, menu, etc
} bg_track_t;
typedef int sound_t;
//====================================================================
#define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS)

View File

@@ -29,20 +29,17 @@ static void Sound_Reset( void )
static MALLOC_LIKE( FS_FreeSound, 1 ) wavdata_t *SoundPack( void )
{
wavdata_t *pack = Mem_Malloc( host.soundpool, sizeof( *pack ) + sound.size );
wavdata_t *pack = Mem_Calloc( host.soundpool, sizeof( wavdata_t ));
pack->buffer = sound.wav;
pack->width = sound.width;
pack->rate = sound.rate;
pack->type = sound.type;
pack->size = sound.size;
pack->loopStart = sound.loopstart;
pack->samples = sound.samples;
pack->type = sound.type;
pack->flags = sound.flags;
pack->rate = sound.rate;
pack->width = sound.width;
pack->channels = sound.channels;
memcpy( pack->buffer, sound.wav, sound.size );
Mem_Free( sound.wav );
sound.wav = NULL;
pack->flags = sound.flags;
return pack;
}
@@ -135,6 +132,7 @@ free WAV buffer
void FS_FreeSound( wavdata_t *pack )
{
if( !pack ) return;
if( pack->buffer ) Mem_Free( pack->buffer );
Mem_Free( pack );
}
@@ -201,6 +199,33 @@ stream_t *FS_OpenStream( const char *filename )
return stream;
}
/*
================
FS_StreamInfo
get basic stream info
================
*/
wavdata_t *FS_StreamInfo( stream_t *stream )
{
static wavdata_t info;
if( !stream ) return NULL;
// fill structure
info.loopStart = 0;
info.rate = stream->rate;
info.width = stream->width;
info.channels = stream->channels;
info.flags = SOUND_STREAM;
info.size = stream->size;
info.buffer = NULL;
info.samples = 0; // not actual for streams
info.type = stream->type;
return &info;
}
/*
================
FS_ReadStream

View File

@@ -17,7 +17,7 @@ GNU General Public License for more details.
#include "base_cmd.h"
#include "cdll_int.h"
#define HASH_SIZE 64 // 64 * 4 * 4 == 1024 bytes
#define HASH_SIZE 128 // 128 * 4 * 4 == 2048 bytes
typedef struct base_command_hashmap_s base_command_hashmap_t;
@@ -26,11 +26,10 @@ struct base_command_hashmap_s
base_command_t *basecmd; // base command: cvar, alias or command
base_command_hashmap_t *next;
base_command_type_e type; // type for faster searching
char name[]; // key for searching
char name[1]; // key for searching
};
static base_command_hashmap_t *hashed_cmds[HASH_SIZE];
static poolhandle_t basecmd_pool;
#define BaseCmd_HashKey( x ) COM_HashKey( name, HASH_SIZE )
@@ -43,27 +42,11 @@ Find base command in bucket
*/
static base_command_hashmap_t *BaseCmd_FindInBucket( base_command_hashmap_t *bucket, base_command_type_e type, const char *name )
{
base_command_hashmap_t *i;
base_command_hashmap_t *i = bucket;
for( ; i && ( i->type != type || Q_stricmp( name, i->name ) ); // filter out
i = i->next );
for( i = bucket; i != NULL; i = i->next )
{
int cmp;
if( i->type != type )
continue;
cmp = Q_stricmp( i->name, name );
if( cmp < 0 )
continue;
if( cmp > 0 )
break;
return i;
}
return NULL;
return i;
}
/*
@@ -107,31 +90,27 @@ void BaseCmd_FindAll( const char *name, base_command_t **cmd, base_command_t **a
base_command_hashmap_t *base = BaseCmd_GetBucket( name );
base_command_hashmap_t *i = base;
ASSERT( cmd && alias && cvar );
*cmd = *alias = *cvar = NULL;
for( ; i; i = i->next )
{
int cmp = Q_stricmp( i->name, name );
if( cmp < 0 )
continue;
if( cmp > 0 )
break;
switch( i->type )
if( !Q_stricmp( i->name, name ) )
{
case HM_CMD:
*cmd = i->basecmd;
break;
case HM_CMDALIAS:
*alias = i->basecmd;
break;
case HM_CVAR:
*cvar = i->basecmd;
break;
default:
break;
switch( i->type )
{
case HM_CMD:
*cmd = i->basecmd;
break;
case HM_CMDALIAS:
*alias = i->basecmd;
break;
case HM_CVAR:
*cvar = i->basecmd;
break;
default: break;
}
}
}
}
@@ -149,14 +128,14 @@ void BaseCmd_Insert( base_command_type_e type, base_command_t *basecmd, const ch
uint hash = BaseCmd_HashKey( name );
size_t len = Q_strlen( name );
elem = Mem_Malloc( basecmd_pool, sizeof( base_command_hashmap_t ) + len + 1 );
elem = Z_Malloc( sizeof( base_command_hashmap_t ) + len );
elem->basecmd = basecmd;
elem->type = type;
Q_strncpy( elem->name, name, len + 1 );
// link the variable in alphanumerical order
for( cur = NULL, find = hashed_cmds[hash];
find && Q_stricmp( find->name, elem->name ) < 0;
find && Q_strcmp( find->name, elem->name ) < 0;
cur = find, find = find->next );
if( cur ) cur->next = elem;
@@ -177,23 +156,9 @@ void BaseCmd_Remove( base_command_type_e type, const char *name )
uint hash = BaseCmd_HashKey( name );
base_command_hashmap_t *i, *prev;
for( prev = NULL, i = hashed_cmds[hash]; i != NULL; prev = i, i = i->next )
{
int cmp;
if( i->type != type )
continue;
cmp = Q_stricmp( i->name, name );
if( cmp < 0 )
continue;
if( cmp > 0 )
i = NULL;
break;
}
for( prev = NULL, i = hashed_cmds[hash]; i &&
( Q_strcmp( i->name, name ) || i->type != type); // filter out
prev = i, i = i->next );
if( !i )
{
@@ -218,15 +183,9 @@ initialize base command hashmap system
*/
void BaseCmd_Init( void )
{
basecmd_pool = Mem_AllocPool( "BaseCmd" );
memset( hashed_cmds, 0, sizeof( hashed_cmds ) );
}
void BaseCmd_Shutdown( void )
{
Mem_FreePool( &basecmd_pool );
}
/*
============
BaseCmd_Stats_f

View File

@@ -32,7 +32,6 @@ typedef enum base_command_type
typedef void base_command_t;
void BaseCmd_Init( void );
void BaseCmd_Shutdown( void );
base_command_t *BaseCmd_Find( base_command_type_e type, const char *name );
void BaseCmd_FindAll( const char *name,
base_command_t **cmd, base_command_t **alias, base_command_t **cvar );

View File

@@ -46,7 +46,6 @@ static cmdalias_t *cmd_alias;
static uint cmd_condition;
static int cmd_condlevel;
static qboolean cmd_currentCommandIsPrivileged;
static poolhandle_t cmd_pool;
static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPrivileged );
@@ -433,7 +432,7 @@ static void Cmd_Alias_f( void )
{
if( !Q_strcmp( s, a->name ))
{
Mem_Free( a->value );
Z_Free( a->value );
break;
}
}
@@ -442,7 +441,7 @@ static void Cmd_Alias_f( void )
{
cmdalias_t *cur, *prev;
a = Mem_Malloc( cmd_pool, sizeof( cmdalias_t ));
a = Z_Malloc( sizeof( cmdalias_t ));
Q_strncpy( a->name, s, sizeof( a->name ));
@@ -470,7 +469,7 @@ static void Cmd_Alias_f( void )
}
Q_strncat( cmd, "\n", sizeof( cmd ));
a->value = copystringpool( cmd_pool, cmd );
a->value = copystring( cmd );
}
/*
@@ -530,7 +529,7 @@ struct cmd_s
char *name;
xcommand_t function;
int flags;
char desc[];
char *desc;
};
static int cmd_argc;
@@ -637,7 +636,7 @@ void Cmd_TokenizeString( const char *text )
// clear the args from the last string
for( i = 0; i < cmd_argc; i++ )
Mem_Free( cmd_argv[i] );
Z_Free( cmd_argv[i] );
cmd_argc = 0; // clear previous args
cmd_args = NULL;
@@ -671,7 +670,7 @@ void Cmd_TokenizeString( const char *text )
if( cmd_argc < MAX_CMD_TOKENS )
{
cmd_argv[cmd_argc] = copystringpool( cmd_pool, cmd_token );
cmd_argv[cmd_argc] = copystring( cmd_token );
cmd_argc++;
}
}
@@ -684,8 +683,7 @@ Cmd_AddCommandEx
*/
int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd_desc, int iFlags, const char *funcname )
{
cmd_t *cmd, *cur, *prev;
size_t desc_len;
cmd_t *cmd, *cur, *prev;
if( !COM_CheckString( cmd_name ))
{
@@ -709,8 +707,8 @@ int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd
// unfortunately, we lose original command this way
if( FBitSet( cmd->flags, CMD_OVERRIDABLE ))
{
desc_len = Q_strlen( cmd->desc ) + 1;
Q_strncpy( cmd->desc, cmd_desc, desc_len );
Mem_Free( cmd->desc );
cmd->desc = copystring( cmd_desc );
cmd->function = function;
cmd->flags = iFlags;
@@ -725,10 +723,9 @@ int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd
}
// use a small malloc to avoid zone fragmentation
desc_len = Q_strlen( cmd_desc ) + 1;
cmd = Mem_Malloc( cmd_pool, sizeof( cmd_t ) + desc_len );
cmd->name = copystringpool( cmd_pool, cmd_name );
Q_strncpy( cmd->desc, cmd_desc, desc_len );
cmd = Z_Malloc( sizeof( cmd_t ) );
cmd->name = copystring( cmd_name );
cmd->desc = copystring( cmd_desc );
cmd->function = function;
cmd->flags = iFlags;
@@ -775,6 +772,9 @@ void GAME_EXPORT Cmd_RemoveCommand( const char *cmd_name )
if( cmd->name )
Mem_Free( cmd->name );
if( cmd->desc )
Mem_Free( cmd->desc );
Mem_Free( cmd );
return;
}
@@ -1202,6 +1202,7 @@ void Cmd_Unlink( int group )
*prev = cmd->next;
if( cmd->name ) Mem_Free( cmd->name );
if( cmd->desc ) Mem_Free( cmd->desc );
Mem_Free( cmd );
count++;
@@ -1339,7 +1340,6 @@ Cmd_Init
*/
void Cmd_Init( void )
{
cmd_pool = Mem_AllocPool( "Console Commands" );
cmd_functions = NULL;
cmd_condition = 0;
cmd_alias = NULL;
@@ -1366,11 +1366,6 @@ void Cmd_Init( void )
#endif
}
void Cmd_Shutdown( void )
{
Mem_FreePool( &cmd_pool );
}
#if XASH_ENGINE_TESTS
#include "tests.h"

View File

@@ -72,6 +72,8 @@ GNU General Public License for more details.
#define CVAR_GLCONFIG_DESCRIPTION "enable or disable %s"
#define DEFAULT_BSP_BUILD_ERROR "%s can't be loaded in this build. Please rebuild engine with enabled SUPPORT_BSP2_FORMAT\n"
#define DEFAULT_UPDATE_PAGE "https://github.com/FWGS/xash3d-fwgs/releases/latest"
#define XASH_ENGINE_NAME "Xash3D FWGS"

View File

@@ -76,14 +76,23 @@ XASH SPECIFIC - sort of hack that works only in Xash3D not in GoldSrc
#define HACKS_RELATED_HLMODS // some HL-mods works differently under Xash and can't be fixed without some hacks at least at current time
enum dev_level_e
enum
{
DEV_NONE = 0,
DEV_NORMAL,
DEV_EXTENDED
};
typedef enum instance_e
enum
{
D_INFO = 1, // "-dev 1", shows various system messages
D_WARN, // "-dev 2", shows not critical system warnings
D_ERROR, // "-dev 3", shows critical warnings
D_REPORT, // "-dev 4", special case for game reports
D_NOTE // "-dev 5", show system notifications for engine developers
};
typedef enum
{
HOST_NORMAL, // listen server, singleplayer
HOST_DEDICATED,
@@ -99,14 +108,14 @@ typedef enum instance_e
#include "com_model.h"
#include "com_strings.h"
#include "crtlib.h"
#define FSCALLBACK_OVERRIDE_OPEN
#define FSCALLBACK_OVERRIDE_LOADFILE
#define FSCALLBACK_OVERRIDE_MALLOC_LIKE
#include "fscallback.h"
#include "cvar.h"
#include "con_nprint.h"
#include "crclib.h"
#include "ref_api.h"
#define FSCALLBACK_OVERRIDE_OPEN
#define FSCALLBACK_OVERRIDE_LOADFILE
#define FSCALLBACK_OVERRIDE_MALLOC_LIKE
#include "fscallback.h"
// PERFORMANCE INFO
#define MIN_FPS 20.0f // host minimum fps value for maxfps.
@@ -137,11 +146,6 @@ typedef enum instance_e
#define MAX_STATIC_ENTITIES 32 // static entities that moved on the client when level is spawn
#endif
#define MAX_SERVERINFO_STRING 512 // server handles too many settings. expand to 1024?
#define MAX_PRINT_MSG 8192 // how many symbols can handle single call of Con_Printf or Con_DPrintf
#define MAX_TOKEN 2048 // parse token length
#define MAX_USERMSG_LENGTH 2048 // don't modify it's relies on a client-side definitions
#define GameState (&host.game)
#define FORCE_DRAW_VERSION_TIME 5.0 // draw version for 5 seconds
@@ -185,7 +189,7 @@ GAMEINFO stuff
internal shared gameinfo structure (readonly for engine parts)
========================================================================
*/
typedef enum host_status_e
typedef enum
{
HOST_INIT = 0, // initalize operations
HOST_FRAME, // host running
@@ -196,7 +200,7 @@ typedef enum host_status_e
HOST_CRASHED // an exception handler called
} host_status_t;
typedef enum host_state_e
typedef enum
{
STATE_RUNFRAME = 0,
STATE_LOAD_LEVEL,
@@ -205,7 +209,7 @@ typedef enum host_state_e
STATE_GAME_SHUTDOWN,
} host_state_t;
typedef struct game_status_e
typedef struct
{
host_state_t curstate;
host_state_t nextstate;
@@ -216,7 +220,7 @@ typedef struct game_status_e
qboolean newGame; // unload the server.dll before start a new map
} game_status_t;
typedef enum keydest_e
typedef enum
{
key_console = 0,
key_game,
@@ -224,7 +228,7 @@ typedef enum keydest_e
key_message
} keydest_t;
typedef enum rdtype_e
typedef enum
{
RD_NONE = 0,
RD_CLIENT,
@@ -234,7 +238,7 @@ typedef enum rdtype_e
#include "net_ws.h"
// console field
typedef struct field_e
typedef struct
{
string buffer;
int cursor;
@@ -252,7 +256,7 @@ typedef struct host_redirect_s
int lines;
} host_redirect_t;
typedef struct soundlist_e
typedef struct
{
char name[MAX_QPATH];
short entnum;
@@ -293,10 +297,11 @@ typedef struct host_parm_s
host_status_t status; // global host state
game_status_t game; // game manager
instance_t type; // running at
uint type; // running at
poolhandle_t mempool; // static mempool for misc allocations
poolhandle_t imagepool; // imagelib mempool
poolhandle_t soundpool; // soundlib mempool
string finalmsg; // server shutdown final message
string downloadfile; // filename to be downloading
int downloadcount; // how many files remain to downloading
char deferred_cmd[128];// deferred commands
@@ -428,7 +433,6 @@ int Cmd_Argc( void );
const char *Cmd_Args( void ) RETURNS_NONNULL;
const char *Cmd_Argv( int arg ) RETURNS_NONNULL;
void Cmd_Init( void );
void Cmd_Shutdown( void );
void Cmd_Unlink( int group );
int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd_desc, int flags, const char *funcname );
@@ -487,7 +491,7 @@ internal sound format
typically expanded to wav buffer
========================================================================
*/
typedef enum sndformat_e
typedef enum
{
WF_UNKNOWN = 0,
WF_PCMDATA,
@@ -498,7 +502,7 @@ typedef enum sndformat_e
} sndformat_t;
// wavdata output flags
typedef enum sndFlags_e
typedef enum
{
// wavdata->flags
SOUND_LOOPED = BIT( 0 ), // this is looped sound (contain cue markers)
@@ -508,29 +512,29 @@ typedef enum sndFlags_e
SOUND_RESAMPLE = BIT( 12 ), // resample sound to specified rate
} sndFlags_t;
typedef struct wavdata_s
typedef struct
{
size_t size; // for bounds checking
word rate; // num samples per second (e.g. 11025 - 11 khz)
byte width; // resolution - bum bits divided by 8 (8 bit is 1, 16 bit is 2)
byte channels; // num channels (1 - mono, 2 - stereo)
uint loopStart; // offset at this point sound will be looping while playing more than only once
uint samples; // total samplecount in wav
uint type; // compression type
uint flags; // misc sound flags
word rate; // num samples per second (e.g. 11025 - 11 khz)
byte width; // resolution - bum bits divided by 8 (8 bit is 1, 16 bit is 2)
byte channels; // num channels (1 - mono, 2 - stereo)
byte buffer[]; // sound buffer
byte *buffer; // sound buffer
size_t size; // for bounds checking
} wavdata_t;
//
// soundlib
//
typedef struct stream_s stream_t;
void Sound_Init( void );
void Sound_Shutdown( void );
void FS_FreeSound( wavdata_t *pack );
void FS_FreeStream( stream_t *stream );
wavdata_t *FS_LoadSound( const char *filename, const byte *buffer, size_t size ) MALLOC_LIKE( FS_FreeSound, 1 ) WARN_UNUSED_RESULT;
stream_t *FS_OpenStream( const char *filename ) MALLOC_LIKE( FS_FreeStream, 1 ) WARN_UNUSED_RESULT;
wavdata_t *FS_StreamInfo( stream_t *stream );
int FS_ReadStream( stream_t *stream, int bytes, void *buffer );
int FS_SetStreamPos( stream_t *stream, int newpos );
int FS_GetStreamPos( stream_t *stream );
@@ -556,7 +560,6 @@ void Host_Error( const char *error, ... ) FORMAT_CHECK( 1 );
void Host_ValidateEngineFeatures( uint32_t mask, uint32_t features );
void Host_Frame( double time );
void Host_Credits( void );
void Host_ExitInMain( void );
//
// host_state.c
@@ -575,19 +578,11 @@ CLIENT / SERVER SYSTEMS
==============================================================
*/
#if !XASH_DEDICATED
void CL_Init( void );
void CL_Shutdown( void );
void Host_ClientBegin( void );
void Host_ClientFrame( void );
int CL_Active( void );
#else
static inline void CL_Init( void ) { }
static inline void CL_Shutdown( void ) { }
static inline void Host_ClientBegin( void ) { Cbuf_Execute(); }
static inline void Host_ClientFrame( void ) { }
static inline int CL_Active( void ) { return 0; }
#endif
void SV_Init( void );
void SV_Shutdown( const char *finalmsg );
@@ -625,7 +620,6 @@ int pfnNumberOfEntities( void );
int pfnIsInGame( void );
float pfnTime( void );
#define copystring( s ) _copystring( host.mempool, s, __FILE__, __LINE__ )
#define copystringpool( pool, s ) _copystring( pool, s, __FILE__, __LINE__ )
#define SV_CopyString( s ) _copystring( svgame.stringspool, s, __FILE__, __LINE__ )
#define freestring( s ) if( s != NULL ) { Mem_Free( s ); s = NULL; }
char *_copystring( poolhandle_t mempool, const char *s, const char *filename, int fileline );
@@ -676,7 +670,6 @@ int CSCR_WriteGameCVars( file_t *cfg, const char *scriptfilename );
//
// hpak.c
//
const char *COM_ResourceTypeFromIndex( int index );
void HPAK_Init( void );
qboolean HPAK_GetDataPointer( const char *filename, struct resource_s *pRes, byte **buffer, int *size );
qboolean HPAK_ResourceForHash( const char *filename, byte *hash, struct resource_s *pRes );
@@ -710,32 +703,13 @@ typedef enum connprotocol_e
struct physent_s;
struct sv_client_s;
typedef struct sizebuf_s sizebuf_t;
int SV_GetMaxClients( void );
#if !XASH_DEDICATED
qboolean CL_Initialized( void );
qboolean CL_IsInGame( void );
qboolean CL_IsInConsole( void );
qboolean CL_IsIntermission( void );
qboolean CL_DisableVisibility( void );
qboolean CL_IsRecordDemo( void );
qboolean CL_IsPlaybackDemo( void );
qboolean UI_CreditsActive( void );
int CL_GetMaxClients( void );
#else
static inline qboolean CL_Initialized( void ) { return false; }
static inline qboolean CL_IsInGame( void ) { return true; } // always true for dedicated
static inline qboolean CL_IsInConsole( void ) { return false; }
static inline qboolean CL_IsIntermission( void ) { return false; }
static inline qboolean CL_DisableVisibility( void ) { return false; }
static inline qboolean CL_IsRecordDemo( void ) { return false; }
static inline qboolean CL_IsPlaybackDemo( void ) { return false; }
static inline qboolean UI_CreditsActive( void ) { return false; }
static inline int CL_GetMaxClients( void ) { return SV_GetMaxClients(); }
#endif
qboolean CL_Initialized( void );
char *CL_Userinfo( void );
void CL_CharEvent( int key );
qboolean CL_DisableVisibility( void );
byte *COM_LoadFile( const char *filename, int usehunk, int *pLength ) MALLOC_LIKE( free, 1 );
struct cmd_s *Cmd_GetFirstFunctionHandle( void );
struct cmd_s *Cmd_GetNextFunctionHandle( struct cmd_s *cmd );
@@ -753,7 +727,13 @@ const char *CL_MsgInfo( int cmd );
void SV_DrawDebugTriangles( void );
void SV_DrawOrthoTriangles( void );
double CL_GetDemoFramerate( void );
qboolean UI_CreditsActive( void );
void CL_StopPlayback( void );
int CL_GetMaxClients( void );
int SV_GetMaxClients( void );
qboolean CL_IsRecordDemo( void );
qboolean CL_IsTimeDemo( void );
qboolean CL_IsPlaybackDemo( void );
qboolean SV_Initialized( void );
void CL_ProcessFile( qboolean successfully_received, const char *filename );
int SV_GetSaveComment( const char *savename, char *comment );
@@ -866,6 +846,13 @@ void V_CheckGamma( void );
void V_CheckGammaEnd( void );
intptr_t V_GetGammaPtr( int parm );
//
// identification.c
//
void ID_Init( void );
const char *ID_GetMD5( void );
void GAME_EXPORT ID_SetCustomClientID( const char *id );
//
// masterlist.c
//

View File

@@ -1395,7 +1395,7 @@ void Host_WriteConfig( void )
{
Con_Reportf( "%s()\n", __func__ );
FS_Printf( f, "//=======================================================================\n");
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch());
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), Q_buildcommit(), Q_buildbranch(), Q_buildos(), Q_buildarch());
FS_Printf( f, "//\t\tconfig.cfg - archive of cvars\n" );
FS_Printf( f, "//=======================================================================\n" );
Key_WriteBindings( f );
@@ -1443,7 +1443,7 @@ void GAME_EXPORT Host_WriteServerConfig( const char *name )
if(( f = FS_Open( newconfigfile, "w", false )) != NULL )
{
FS_Printf( f, "//=======================================================================\n" );
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch());
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), Q_buildcommit(), Q_buildbranch(), Q_buildos(), Q_buildarch());
FS_Printf( f, "//\t\tgame.cfg - multiplayer server temporare config\n" );
FS_Printf( f, "//=======================================================================\n" );
@@ -1478,7 +1478,7 @@ void Host_WriteOpenGLConfig( void )
{
Con_Reportf( "%s()\n", __func__ );
FS_Printf( f, "//=======================================================================\n" );
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch());
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), Q_buildcommit(), Q_buildbranch(), Q_buildos(), Q_buildarch());
FS_Printf( f, "//\t\t%s - archive of renderer implementation cvars\n", name );
FS_Printf( f, "//=======================================================================\n" );
FS_Printf( f, "\n" );
@@ -1508,7 +1508,7 @@ void Host_WriteVideoConfig( void )
{
Con_Reportf( "%s()\n", __func__ );
FS_Printf( f, "//=======================================================================\n" );
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch());
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), Q_buildcommit(), Q_buildbranch(), Q_buildos(), Q_buildarch());
FS_Printf( f, "//\t\tvideo.cfg - archive of renderer variables\n");
FS_Printf( f, "//=======================================================================\n" );
Cvar_WriteVariables( f, FCVAR_RENDERINFO );
@@ -1534,7 +1534,7 @@ void Key_EnumCmds_f( void )
if( f )
{
FS_Printf( f, "//=======================================================================\n");
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch());
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), Q_buildcommit(), Q_buildbranch(), Q_buildos(), Q_buildarch());
FS_Printf( f, "//\t\thelp.txt - xash commands and console variables\n");
FS_Printf( f, "//=======================================================================\n");

View File

@@ -19,7 +19,6 @@ GNU General Public License for more details.
#include "eiface.h" // ARRAYSIZE
static convar_t *cvar_vars = NULL; // head of list
static poolhandle_t cvar_pool;
CVAR_DEFINE_AUTO( cmd_scripting, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED, "enable simple condition checking and variable operations" );
typedef struct cvar_filter_quirks_s
@@ -433,7 +432,7 @@ convar_t *Cvar_Get( const char *name, const char *value, int flags, const char *
{
// directly set value
freestring( var->string );
var->string = copystringpool( cvar_pool, value );
var->string = copystring( value );
var->value = Q_atof( var->string );
SetBits( var->flags, flags );
@@ -453,18 +452,18 @@ convar_t *Cvar_Get( const char *name, const char *value, int flags, const char *
Con_Reportf( "%s change description from %s to %s\n", var->name, var->desc, var_desc );
// update description if needs
freestring( var->desc );
var->desc = copystringpool( cvar_pool, var_desc );
var->desc = copystring( var_desc );
}
return var;
}
// allocate a new cvar
var = Mem_Malloc( cvar_pool, sizeof( *var ));
var->name = copystringpool( cvar_pool, name );
var->string = copystringpool( cvar_pool, value );
var->def_string = copystringpool( cvar_pool, value );
var->desc = copystringpool( cvar_pool, var_desc );
var = Z_Malloc( sizeof( *var ));
var->name = copystring( name );
var->string = copystring( value );
var->def_string = copystring( value );
var->desc = copystring( var_desc );
var->value = Q_atof( var->string );
var->flags = flags|FCVAR_ALLOCATED;
@@ -550,7 +549,7 @@ void Cvar_RegisterVariable( convar_t *var )
if( FBitSet( var->flags, FCVAR_EXTENDED ))
var->def_string = var->string; // just swap pointers
var->string = copystringpool( cvar_pool, var->string );
var->string = copystring( var->string );
var->value = Q_atof( var->string );
// find the supposed position in chain (alphanumerical order)
@@ -680,7 +679,7 @@ static convar_t *Cvar_Set2( const char *var_name, const char *value )
// and finally changed the cvar itself
freestring( var->string );
var->string = copystringpool( cvar_pool, pszValue );
var->string = copystring( pszValue );
var->value = Q_atof( var->string );
// tell engine about changes
@@ -739,7 +738,7 @@ void GAME_EXPORT Cvar_DirectSet( convar_t *var, const char *value )
// and finally changed the cvar itself
freestring( var->string );
var->string = copystringpool( cvar_pool, pszValue );
var->string = copystring( pszValue );
var->value = Q_atof( var->string );
// tell engine about changes
@@ -782,7 +781,7 @@ void Cvar_FullSet( const char *var_name, const char *value, int flags )
}
freestring( var->string );
var->string = copystringpool( cvar_pool, value );
var->string = copystring( value );
var->value = Q_atof( var->string );
SetBits( var->flags, flags );
@@ -1190,7 +1189,6 @@ static void Cvar_List_f( void )
for( var = cvar_vars; var; var = var->next )
{
char value[MAX_VA_STRING];
char *p;
if( var->name[0] == '@' )
continue; // never shows system cvars
@@ -1198,9 +1196,7 @@ static void Cvar_List_f( void )
if( match && !Q_strnicmpext( match, var->name, matchlen ))
continue;
p = Q_strchr( var->string, '^' );
if( IsColorString( p ))
if( Q_colorstr( var->string ))
Q_snprintf( value, sizeof( value ), "\"%s\"", var->string );
else Q_snprintf( value, sizeof( value ), "\"^2%s^7\"", var->string );
@@ -1261,7 +1257,7 @@ pending_cvar_t *Cvar_PrepareToUnlink( int group )
continue;
namelen = Q_strlen( cv->name ) + 1;
p = Mem_Malloc( cvar_pool, sizeof( *list ) + namelen );
p = Mem_Malloc( host.mempool, sizeof( *list ) + namelen );
p->next = NULL;
p->cv_cur = cv;
p->cv_next = cv->next;
@@ -1337,7 +1333,6 @@ Reads in all archived cvars
*/
void Cvar_Init( void )
{
cvar_pool = Mem_AllocPool( "Console Variables" );
cvar_vars = NULL;
cvar_active_filter_quirks = NULL;
Cvar_RegisterVariable( &cmd_scripting );
@@ -1350,11 +1345,6 @@ void Cvar_Init( void )
Cmd_AddCommand( "cvarlist", Cvar_List_f, "display all console variables beginning with the specified prefix" );
}
void Cvar_Shutdown( void )
{
Mem_FreePool( &cvar_pool );
}
/*
============
Cvar_PostFSInit

View File

@@ -30,8 +30,6 @@ typedef struct pending_cvar_s
char cv_name[];
} pending_cvar_t;
typedef void (*setpair_t)( const char *key, const void *value, const void *buffer, void *numpairs );
cvar_t *Cvar_GetList( void );
#define Cvar_FindVar( name ) Cvar_FindVarExt( name, 0 )
convar_t *Cvar_FindVarExt( const char *var_name, int ignore_group );
@@ -54,7 +52,6 @@ void Cvar_Reset( const char *var_name );
void Cvar_SetCheatState( void );
qboolean Cvar_CommandWithPrivilegeCheck( convar_t *v, qboolean isPrivileged );
void Cvar_Init( void );
void Cvar_Shutdown( void );
void Cvar_PostFSInit( void );
void Cvar_Unlink( int group );

View File

@@ -49,6 +49,52 @@ const char *CL_MsgInfo( int cmd )
return sz;
}
int GAME_EXPORT CL_Active( void )
{
return false;
}
qboolean CL_Initialized( void )
{
return false;
}
qboolean CL_IsInGame( void )
{
return true; // always active for dedicated servers
}
qboolean CL_IsInConsole( void )
{
return false;
}
qboolean CL_IsIntermission( void )
{
return false;
}
qboolean CL_IsPlaybackDemo( void )
{
return false;
}
qboolean CL_IsRecordDemo( void )
{
return false;
}
qboolean CL_DisableVisibility( void )
{
return false;
}
void CL_Init( void )
{
}
void Key_Init( void )
{
@@ -84,6 +130,16 @@ void CL_WriteMessageHistory( void )
}
void Host_ClientBegin( void )
{
Cbuf_Execute();
}
void Host_ClientFrame( void )
{
}
void Host_InputFrame( void )
{
}
@@ -103,6 +159,11 @@ void GAME_EXPORT S_StopSound(int entnum, int channel, const char *soundname)
}
int GAME_EXPORT CL_GetMaxClients( void )
{
return 0;
}
void IN_TouchInitConfig( void )
{
@@ -113,6 +174,11 @@ void CL_Disconnect( void )
}
void CL_Shutdown( void )
{
}
void R_ClearStaticEntities( void )
{
@@ -123,6 +189,11 @@ void Host_Credits( void )
}
qboolean UI_CreditsActive( void )
{
return false;
}
void S_StopBackgroundTrack( void )
{
@@ -133,6 +204,11 @@ void SCR_BeginLoadingPlaque( qboolean is_background )
}
int S_GetCurrentDynamicSounds( soundlist_t *pout, int size )
{
return 0;
}
void S_StopAllSounds( qboolean ambient )
{

View File

@@ -183,23 +183,14 @@ static qboolean FS_DetermineRootDirectory( char *out, size_t size )
#elif XASH_PSVITA
if( PSVita_GetBasePath( out, size ))
return true;
Sys_Error( "couldn't find %s data directory", XASH_ENGINE_NAME );
Sys_Error( "couldn't find Xash3D data directory" );
return false;
#elif ( XASH_SDL == 2 ) && !XASH_NSWITCH // GetBasePath not impl'd in switch-sdl2
path = SDL_GetBasePath();
#if XASH_APPLE
if( path != NULL && Q_stristr( path, ".app" ))
{
SDL_free((void *)path );
path = SDL_GetPrefPath( NULL, XASH_ENGINE_NAME );
}
#endif
if( path != NULL )
{
Q_strncpy( out, path, size );
SDL_free((void *)path );
SDL_free(( void *)path );
return true;
}

View File

@@ -43,27 +43,6 @@ GNU General Public License for more details.
static pfnChangeGame pChangeGame = NULL;
host_parm_t host; // host parms
#if XASH_ANDROID
static jmp_buf return_from_main_buf;
/*
===============
Host_ExitInMain
On some platforms (e.g. Android) we can't exit with exit(3) as calling it would
kill wrapper process (e.g. app_process) too early, before all resources would
be freed, contexts released, files closed, etc, etc...
To fix this, we create jmp_buf in Host_Main function, when jumping into with
non-zero value will immediately return from it with `error_on_exit`.
===============
*/
void Host_ExitInMain( void )
{
longjmp( return_from_main_buf, 1 );
}
#endif // XASH_ANDROID
#ifdef XASH_ENGINE_TESTS
struct tests_stats_s tests_stats;
#endif
@@ -201,6 +180,7 @@ static void Sys_PrintUsage( const char *exename )
O("-daemonize ", "run engine as a daemon")
#endif
#if XASH_SDL == 2
O("-sdl_joy_old_api ","use SDL legacy joystick API")
O("-sdl_renderer <n> ","use alternative SDL_Renderer for software")
#endif // XASH_SDL
#if XASH_ANDROID && !XASH_SDL
@@ -382,8 +362,9 @@ static void Host_NewInstance( const char *name, const char *finalmsg )
if( !pChangeGame ) return;
host.change_game = true;
Q_strncpy( host.finalmsg, finalmsg, sizeof( host.finalmsg ));
if( !Sys_NewInstance( name, finalmsg ))
if( !Sys_NewInstance( name ))
pChangeGame( name ); // call from hl.exe
}
@@ -857,6 +838,7 @@ void GAME_EXPORT Host_Error( const char *error, ... )
recursive = true;
Q_strncpy( hosterror2, hosterror1, sizeof( hosterror2 ));
host.errorframe = host.framecount; // to avoid multply calls per frame
Q_snprintf( host.finalmsg, sizeof( host.finalmsg ), "Server crashed: %s", hosterror1 );
// clearing cmd buffer to prevent execute any commands
COM_InitHostState();
@@ -1130,7 +1112,7 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
#if XASH_DEDICATED
Platform_SetupSigtermHandling();
#endif
Platform_Init( Host_IsDedicated( ) || developer >= DEV_EXTENDED, basedir );
Platform_Init( Host_IsDedicated( ) || developer >= DEV_EXTENDED );
FS_Init( basedir );
Sys_InitLog();
@@ -1232,7 +1214,7 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
Cvar_Getf( "buildnum", FCVAR_READ_ONLY, "returns a current build number", "%i", Q_buildnum_compat());
Cvar_Getf( "ver", FCVAR_READ_ONLY, "shows an engine version", "%i/%s (hw build %i)", PROTOCOL_VERSION, XASH_COMPAT_VERSION, Q_buildnum_compat());
Cvar_Getf( "host_ver", FCVAR_READ_ONLY, "detailed info about this build", "%i " XASH_VERSION " %s %s %s", Q_buildnum(), Q_buildos(), Q_buildarch(), g_buildcommit);
Cvar_Getf( "host_ver", FCVAR_READ_ONLY, "detailed info about this build", "%i " XASH_VERSION " %s %s %s", Q_buildnum(), Q_buildos(), Q_buildarch(), Q_buildcommit());
Cvar_Getf( "host_lowmemorymode", FCVAR_READ_ONLY, "indicates if engine compiled for low RAM consumption (0 - normal, 1 - low engine limits, 2 - low protocol limits)", "%i", XASH_LOW_MEMORY );
Mod_Init();
@@ -1255,6 +1237,7 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
CL_Init();
HTTP_Init();
ID_Init();
SoundList_Init();
if( Host_IsDedicated( ))
@@ -1338,11 +1321,6 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
// check after all configs were executed
HPAK_CheckIntegrity( hpk_custom_file.string );
#if XASH_ANDROID
if( setjmp( return_from_main_buf ))
return error_on_exit;
#endif // XASH_ANDROID
// main window message loop
while( !host.crashed )
{
@@ -1381,6 +1359,9 @@ void Host_ShutdownWithReason( const char *reason )
if( host.status != HOST_ERR_FATAL )
host.status = HOST_SHUTDOWN; // prepare host to normal shutdown
if( !host.change_game )
Q_strncpy( host.finalmsg, "Server shutdown", sizeof( host.finalmsg ));
#if !XASH_DEDICATED
if( host.type == HOST_NORMAL && !error )
Host_WriteConfig();
@@ -1398,14 +1379,10 @@ void Host_ShutdownWithReason( const char *reason )
Host_FreeCommon();
Platform_Shutdown();
BaseCmd_Shutdown();
Cmd_Shutdown();
Cvar_Shutdown();
// must be last, console uses this
Mem_FreePool( &host.mempool );
// restore filter
Sys_RestoreCrashHandler();
Sys_CloseLog( reason );
Sys_CloseLog();
}

View File

@@ -38,7 +38,7 @@ static void HPAK_MaxSize_f( void )
Con_Printf( S_ERROR "hpk_maxsize is deprecated, use hpk_max_size\n" );
}
const char *COM_ResourceTypeFromIndex( int type )
static const char *HPAK_TypeFromIndex( int type )
{
switch( type )
{
@@ -104,7 +104,7 @@ static void HPAK_CreatePak( const char *filename, resource_t *pResource, byte *p
string pakname;
byte md5[16];
file_t *fout;
MD5Context_t ctx = { 0 };
MD5Context_t ctx;
if( !COM_CheckString( filename ))
return;
@@ -125,6 +125,7 @@ static void HPAK_CreatePak( const char *filename, resource_t *pResource, byte *p
}
// let's hash it.
memset( &ctx, 0, sizeof( MD5Context_t ));
MD5Init( &ctx );
if( pData == NULL )
@@ -213,7 +214,7 @@ void HPAK_AddLump( qboolean bUseQueue, const char *name, resource_t *pResource,
file_t *file_src;
file_t *file_dst;
byte md5[16];
MD5Context_t ctx = { 0 };
MD5Context_t ctx;
if( pData == NULL && pFile == NULL )
return;
@@ -225,6 +226,7 @@ void HPAK_AddLump( qboolean bUseQueue, const char *name, resource_t *pResource,
}
// hash it
memset( &ctx, 0, sizeof( MD5Context_t ));
MD5Init( &ctx );
if( !pData )
@@ -461,7 +463,7 @@ static qboolean HPAK_Validate( const char *filename, qboolean quiet, qboolean de
if( !quiet )
{
Con_Printf( "%i: %s %s %s: ", i, COM_ResourceTypeFromIndex( pRes->type ),
Con_Printf( "%i: %s %s %s: ", i, HPAK_TypeFromIndex( pRes->type ),
Q_pretifymem( pRes->nDownloadSize, 2 ), pRes->szFileName );
}
@@ -942,7 +944,7 @@ static void HPAK_List_f( void )
{
entry = &directory.entries[nCurrent];
COM_FileBase( entry->resource.szFileName, lumpname, sizeof( lumpname ));
type = COM_ResourceTypeFromIndex( entry->resource.type );
type = HPAK_TypeFromIndex( entry->resource.type );
size = Q_memprint( entry->resource.nDownloadSize );
Con_Printf( "%i: %10s %s %s\n : %s\n", nCurrent + 1, type, size, lumpname, MD5_Print( entry->resource.rgucMD5_hash ));
@@ -1037,7 +1039,7 @@ static void HPAK_Extract_f( void )
continue;
COM_FileBase( entry->resource.szFileName, lumpname, sizeof( lumpname ) );
type = COM_ResourceTypeFromIndex( entry->resource.type );
type = HPAK_TypeFromIndex( entry->resource.type );
size = Q_memprint( entry->resource.nDownloadSize );
Con_Printf( "Extracting %i: %10s %s %s\n", nCurrent + 1, type, size, lumpname );

View File

@@ -611,7 +611,7 @@ void GAME_EXPORT ID_SetCustomClientID( const char *id )
void ID_Init( void )
{
MD5Context_t hash = { 0 };
MD5Context_t hash = {0};
byte md5[16];
int i;
@@ -632,7 +632,7 @@ void ID_Init( void )
#elif XASH_WIN32
{
CHAR szBuf[MAX_PATH];
ID_GetKeyData( HKEY_CURRENT_USER, "Software\\"XASH_ENGINE_NAME"\\", "xash_id", szBuf, MAX_PATH );
ID_GetKeyData( HKEY_CURRENT_USER, "Software\\Xash3D\\", "xash_id", szBuf, MAX_PATH );
sscanf(szBuf, "%016"PRIX64, &id);
id ^= SYSTEM_XOR_MASK;
@@ -686,7 +686,7 @@ void ID_Init( void )
{
CHAR Buf[MAX_PATH];
sprintf( Buf, "%016"PRIX64, id^SYSTEM_XOR_MASK );
ID_SetKeyData( HKEY_CURRENT_USER, "Software\\"XASH_ENGINE_NAME"\\", REG_SZ, "xash_id", Buf, Q_strlen(Buf) );
ID_SetKeyData( HKEY_CURRENT_USER, "Software\\Xash3D\\", REG_SZ, "xash_id", Buf, Q_strlen(Buf) );
}
#else
{

View File

@@ -28,20 +28,12 @@ Image_LoadPAL
qboolean Image_LoadPAL( const char *name, const byte *buffer, fs_offset_t filesize )
{
int rendermode = LUMP_NORMAL;
byte pal[768];
if( filesize > sizeof( pal ))
if( filesize != 768 )
{
Con_DPrintf( S_ERROR "%s: (%s) have invalid size (%li should be less or equal than %d)\n", __func__, name, (long)filesize, sizeof( pal ));
Con_DPrintf( S_ERROR "%s: (%s) have invalid size (%li should be %d)\n", __func__, name, (long)filesize, 768 );
return false;
}
else if( filesize < sizeof( pal ) && buffer != NULL )
{
// palette might be truncated, fill it with zeros
memset( pal, 0, sizeof( pal ));
memcpy( pal, buffer, filesize );
buffer = pal;
}
if( name[0] == '#' )
{

View File

@@ -385,35 +385,6 @@ static const mlumpinfo_t extlumps[EXTRA_LUMPS] =
},
};
#define BOX_CLIPNODES_INITIALIZER \
{ \
.planenum = 0, \
.children = { CONTENTS_EMPTY, 1 }, \
}, \
{ \
.planenum = 1, \
.children = { 2, CONTENTS_EMPTY }, \
}, \
{ \
.planenum = 2, \
.children = { CONTENTS_EMPTY, 3 }, \
}, \
{ \
.planenum = 3, \
.children = { 4, CONTENTS_EMPTY }, \
}, \
{ \
.planenum = 4, \
.children = { CONTENTS_EMPTY, 5 }, \
}, \
{ \
.planenum = 5, \
.children = { CONTENTS_SOLID, CONTENTS_EMPTY }, \
}, \
const mclipnode16_t box_clipnodes16[6] = { BOX_CLIPNODES_INITIALIZER };
const mclipnode32_t box_clipnodes32[6] = { BOX_CLIPNODES_INITIALIZER };
/*
===============================================================================
@@ -482,7 +453,7 @@ static int Mod_LoadTextureFromWadList( wadlist_t *list, const char *name, rgbdat
return -1;
}
static fs_offset_t Mod_CalculateMipTexSize( const mip_t *mt, qboolean palette )
static fs_offset_t Mod_CalculateMipTexSize( mip_t *mt, qboolean palette )
{
if( !mt )
return 0;
@@ -885,7 +856,7 @@ Mod_PointInLeaf
==================
*/
mleaf_t *Mod_PointInLeaf( const vec3_t p, mnode_t *node, model_t *mod )
mleaf_t *Mod_PointInLeaf( const vec3_t p, mnode_t *node )
{
Assert( node != NULL );
@@ -893,7 +864,7 @@ mleaf_t *Mod_PointInLeaf( const vec3_t p, mnode_t *node, model_t *mod )
{
if( node->contents < 0 )
return (mleaf_t *)node;
node = node_child( node, PlaneDiff( p, node->plane ) <= 0, mod );
node = node->children[PlaneDiff( p, node->plane ) <= 0];
}
// never reached
@@ -914,7 +885,7 @@ byte *Mod_GetPVSForPoint( const vec3_t p )
ASSERT( worldmodel != NULL );
leaf = Mod_PointInLeaf( p, worldmodel->nodes, worldmodel );
leaf = Mod_PointInLeaf( p, worldmodel->nodes );
if( leaf && leaf->cluster >= 0 )
return Mod_DecompressPVS( leaf->compressed_vis, world.visbytes );
@@ -934,14 +905,14 @@ static void Mod_FatPVS_RecursiveBSPNode( const vec3_t org, float radius, byte *v
float d = PlaneDiff( org, node->plane );
if( d > radius )
node = node_child( node, 0, worldmodel );
node = node->children[0];
else if( d < -radius )
node = node_child( node, 1, worldmodel );
node = node->children[1];
else
{
// go down both sides
Mod_FatPVS_RecursiveBSPNode( org, radius, visbuffer, visbytes, node_child( node, 0, worldmodel ), phs );
node = node_child( node, 1, worldmodel );
Mod_FatPVS_RecursiveBSPNode( org, radius, visbuffer, visbytes, node->children[0], phs );
node = node->children[1];
}
}
@@ -979,7 +950,7 @@ int Mod_FatPVS( const vec3_t org, float radius, byte *visbuffer, int visbytes, q
ASSERT( worldmodel != NULL );
leaf = Mod_PointInLeaf( org, worldmodel->nodes, worldmodel );
leaf = Mod_PointInLeaf( org, worldmodel->nodes );
bytes = Q_min( bytes, visbytes );
// enable full visibility for some reasons
@@ -1038,16 +1009,20 @@ static void Mod_BoxLeafnums_r( leaflist_t *ll, mnode_t *node )
sides = BOX_ON_PLANE_SIDE( ll->mins, ll->maxs, node->plane );
if( sides == 1 )
node = node_child( node, 0, worldmodel );
{
node = node->children[0];
}
else if( sides == 2 )
node = node_child( node, 1, worldmodel );
{
node = node->children[1];
}
else
{
// go down both
if( ll->topnode == -1 )
ll->topnode = node - worldmodel->nodes;
Mod_BoxLeafnums_r( ll, node_child( node, 0, worldmodel ));
node = node_child( node, 1, worldmodel );
Mod_BoxLeafnums_r( ll, node->children[0] );
node = node->children[1];
}
}
}
@@ -1104,6 +1079,35 @@ qboolean Mod_BoxVisible( const vec3_t mins, const vec3_t maxs, const byte *visbi
return false;
}
/*
=============
Mod_HeadnodeVisible
=============
*/
qboolean Mod_HeadnodeVisible( mnode_t *node, const byte *visbits, int *lastleaf )
{
if( !node || node->contents == CONTENTS_SOLID )
return false;
if( node->contents < 0 )
{
if( !CHECKVISBIT( visbits, ((mleaf_t *)node)->cluster ))
return false;
if( lastleaf )
*lastleaf = ((mleaf_t *)node)->cluster;
return true;
}
if( Mod_HeadnodeVisible( node->children[0], visbits, lastleaf ))
return true;
if( Mod_HeadnodeVisible( node->children[1], visbits, lastleaf ))
return true;
return false;
}
/*
=================
Mod_FindModelOrigin
@@ -1260,35 +1264,22 @@ Mod_GetFaceContents
determine face contents by name
==================
*/
static mvertex_t *Mod_GetVertexByNumber( model_t *mod, int surfedge, const dbspmodel_t *bmod )
static mvertex_t *Mod_GetVertexByNumber( model_t *mod, int surfedge )
{
int lindex = mod->surfedges[surfedge];
int lindex;
medge_t *edge;
if( bmod->version == QBSP2_VERSION )
lindex = mod->surfedges[surfedge];
if( lindex > 0 )
{
if( lindex > 0 )
{
medge32_t *edge = &mod->edges32[lindex];
return &mod->vertexes[edge->v[0]];
}
else
{
medge32_t *edge = &mod->edges32[-lindex];
return &mod->vertexes[edge->v[1]];
}
edge = &mod->edges[lindex];
return &mod->vertexes[edge->v[0]];
}
else
{
if( lindex > 0 )
{
medge16_t *edge = &mod->edges16[lindex];
return &mod->vertexes[edge->v[0]];
}
else
{
medge16_t *edge = &mod->edges16[-lindex];
return &mod->vertexes[edge->v[1]];
}
edge = &mod->edges[-lindex];
return &mod->vertexes[edge->v[1]];
}
}
@@ -1373,7 +1364,7 @@ Mod_CalcSurfaceExtents
Fills in surf->texturemins[] and surf->extents[]
=================
*/
static void Mod_CalcSurfaceExtents( model_t *mod, msurface_t *surf, const dbspmodel_t *bmod )
static void Mod_CalcSurfaceExtents( model_t *mod, msurface_t *surf )
{
// this place is VERY critical to precision
// keep it as float, don't use double, because it causes issues with lightmap
@@ -1400,16 +1391,8 @@ static void Mod_CalcSurfaceExtents( model_t *mod, msurface_t *surf, const dbspmo
if( e >= mod->numedges || e <= -mod->numedges )
Host_Error( "%s: bad edge\n", __func__ );
if( bmod->version == QBSP2_VERSION )
{
if( e >= 0 ) v = &mod->vertexes[mod->edges32[e].v[0]];
else v = &mod->vertexes[mod->edges32[-e].v[1]];
}
else
{
if( e >= 0 ) v = &mod->vertexes[mod->edges16[e].v[0]];
else v = &mod->vertexes[mod->edges16[-e].v[1]];
}
if( e >= 0 ) v = &mod->vertexes[mod->edges[e].v[0]];
else v = &mod->vertexes[mod->edges[-e].v[1]];
for( j = 0; j < 2; j++ )
{
@@ -1463,7 +1446,7 @@ Mod_CalcSurfaceBounds
fills in surf->mins and surf->maxs
=================
*/
static void Mod_CalcSurfaceBounds( model_t *mod, msurface_t *surf, const dbspmodel_t *bmod )
static void Mod_CalcSurfaceBounds( model_t *mod, msurface_t *surf )
{
int i, e;
mvertex_t *v;
@@ -1477,16 +1460,8 @@ static void Mod_CalcSurfaceBounds( model_t *mod, msurface_t *surf, const dbspmod
if( e >= mod->numedges || e <= -mod->numedges )
Host_Error( "%s: bad edge\n", __func__ );
if( bmod->version == QBSP2_VERSION )
{
if( e >= 0 ) v = &mod->vertexes[mod->edges32[e].v[0]];
else v = &mod->vertexes[mod->edges32[-e].v[1]];
}
else
{
if( e >= 0 ) v = &mod->vertexes[mod->edges16[e].v[0]];
else v = &mod->vertexes[mod->edges16[-e].v[1]];
}
if( e >= 0 ) v = &mod->vertexes[mod->edges[e].v[0]];
else v = &mod->vertexes[mod->edges[-e].v[1]];
AddPointToBounds( v->position, surf->info->mins, surf->info->maxs );
}
@@ -1498,7 +1473,7 @@ static void Mod_CalcSurfaceBounds( model_t *mod, msurface_t *surf, const dbspmod
Mod_CreateFaceBevels
=================
*/
static void Mod_CreateFaceBevels( model_t *mod, msurface_t *surf, const dbspmodel_t *bmod )
static void Mod_CreateFaceBevels( model_t *mod, msurface_t *surf )
{
vec3_t delta, edgevec;
byte *facebevel;
@@ -1531,8 +1506,8 @@ static void Mod_CreateFaceBevels( model_t *mod, msurface_t *surf, const dbspmode
{
mplane_t *dest = &fb->edges[i];
v0 = Mod_GetVertexByNumber( mod, surf->firstedge + i, bmod );
v1 = Mod_GetVertexByNumber( mod, surf->firstedge + (i + 1) % surf->numedges, bmod );
v0 = Mod_GetVertexByNumber( mod, surf->firstedge + i );
v1 = Mod_GetVertexByNumber( mod, surf->firstedge + (i + 1) % surf->numedges );
VectorSubtract( v1->position, v0->position, edgevec );
CrossProduct( faceNormal, edgevec, dest->normal );
VectorNormalize( dest->normal );
@@ -1546,7 +1521,7 @@ static void Mod_CreateFaceBevels( model_t *mod, msurface_t *surf, const dbspmode
// compute face radius
for( i = 0; i < surf->numedges; i++ )
{
v0 = Mod_GetVertexByNumber( mod, surf->firstedge + i, bmod );
v0 = Mod_GetVertexByNumber( mod, surf->firstedge + i );
VectorSubtract( v0->position, fb->origin, delta );
radius = DotProduct( delta, delta );
fb->radius = Q_max( radius, fb->radius );
@@ -1558,15 +1533,13 @@ static void Mod_CreateFaceBevels( model_t *mod, msurface_t *surf, const dbspmode
Mod_SetParent
=================
*/
static void Mod_SetParent( model_t *mod, mnode_t *node, mnode_t *parent )
static void Mod_SetParent( mnode_t *node, mnode_t *parent )
{
node->parent = parent;
if( node->contents < 0 )
return; // it's leaf
Mod_SetParent( mod, node_child( node, 0, mod ), node );
Mod_SetParent( mod, node_child( node, 1, mod ), node );
if( node->contents < 0 ) return; // it's leaf
Mod_SetParent( node->children[0], node );
Mod_SetParent( node->children[1], node );
}
/*
@@ -1574,7 +1547,7 @@ static void Mod_SetParent( model_t *mod, mnode_t *node, mnode_t *parent )
CountClipNodes_r
==================
*/
static void CountClipNodes16_r( mclipnode16_t *src, hull_t *hull, int nodenum )
static void CountClipNodes_r( mclipnode_t *src, hull_t *hull, int nodenum )
{
// leaf?
if( nodenum < 0 ) return;
@@ -1583,11 +1556,16 @@ static void CountClipNodes16_r( mclipnode16_t *src, hull_t *hull, int nodenum )
Host_Error( "MAX_MAP_CLIPNODES limit exceeded\n" );
hull->lastclipnode++;
CountClipNodes16_r( src, hull, src[nodenum].children[0] );
CountClipNodes16_r( src, hull, src[nodenum].children[1] );
CountClipNodes_r( src, hull, src[nodenum].children[0] );
CountClipNodes_r( src, hull, src[nodenum].children[1] );
}
static void CountClipNodes32_r( mclipnode32_t *src, hull_t *hull, int nodenum )
/*
==================
CountClipNodes32_r
==================
*/
static void CountClipNodes32_r( dclipnode32_t *src, hull_t *hull, int nodenum )
{
// leaf?
if( nodenum < 0 ) return;
@@ -1600,27 +1578,15 @@ static void CountClipNodes32_r( mclipnode32_t *src, hull_t *hull, int nodenum )
CountClipNodes32_r( src, hull, src[nodenum].children[1] );
}
static void CountDClipNodes_r( dclipnode32_t *src, hull_t *hull, int nodenum )
{
// leaf?
if( nodenum < 0 ) return;
if( hull->lastclipnode == MAX_MAP_CLIPNODES )
Host_Error( "MAX_MAP_CLIPNODES limit exceeded\n" );
hull->lastclipnode++;
CountDClipNodes_r( src, hull, src[nodenum].children[0] );
CountDClipNodes_r( src, hull, src[nodenum].children[1] );
}
/*
==================
RemapClipNodes_r
==================
*/
static int RemapClipNodes_r( dbspmodel_t *bmod, dclipnode32_t *srcnodes, hull_t *hull, int nodenum )
static int RemapClipNodes_r( dclipnode32_t *srcnodes, hull_t *hull, int nodenum )
{
dclipnode32_t *src;
dclipnode32_t *src;
mclipnode_t *out;
int i, c;
// leaf?
@@ -1633,22 +1599,13 @@ static int RemapClipNodes_r( dbspmodel_t *bmod, dclipnode32_t *srcnodes, hull_t
src = srcnodes + nodenum;
c = hull->lastclipnode;
out = &hull->clipnodes[c];
hull->lastclipnode++;
if( bmod->version == QBSP2_VERSION )
{
mclipnode32_t *out = &hull->clipnodes32[c];
out->planenum = src->planenum;
for( i = 0; i < 2; i++ )
out->children[i] = RemapClipNodes_r( bmod, srcnodes, hull, src->children[i] );
}
else
{
mclipnode16_t *out = &hull->clipnodes16[c];
out->planenum = src->planenum;
for( i = 0; i < 2; i++ )
out->children[i] = RemapClipNodes_r( bmod, srcnodes, hull, src->children[i] );
}
out->planenum = src->planenum;
for( i = 0; i < 2; i++ )
out->children[i] = RemapClipNodes_r( srcnodes, hull, src->children[i] );
return c;
}
@@ -1660,64 +1617,34 @@ Mod_MakeHull0
Duplicate the drawing hull structure as a clipping hull
=================
*/
static void Mod_MakeHull0( model_t *mod, const dbspmodel_t *bmod )
static void Mod_MakeHull0( model_t *mod )
{
hull_t *hull = &mod->hulls[0];
int i;
mnode_t *in, *child;
mclipnode_t *out;
hull_t *hull;
int i, j;
hull = &mod->hulls[0];
hull->clipnodes = out = Mem_Malloc( mod->mempool, mod->numnodes * sizeof( *out ));
in = mod->nodes;
hull->firstclipnode = 0;
hull->lastclipnode = mod->numnodes - 1;
hull->planes = mod->planes;
if( bmod->version == QBSP2_VERSION )
for( i = 0; i < mod->numnodes; i++, out++, in++ )
{
mclipnode32_t *out;
mnode_t *in = mod->nodes;
out->planenum = in->plane - mod->planes;
hull->clipnodes32 = out = Mem_Malloc( mod->mempool, mod->numnodes * sizeof( *hull->clipnodes32 ));
for( i = 0; i < mod->numnodes; i++, out++, in++ )
for( j = 0; j < 2; j++ )
{
int j;
child = in->children[j];
out->planenum = in->plane - mod->planes;
for( j = 0; j < 2; j++ )
{
mnode_t *child = node_child( in, j, mod );
if( child->contents < 0 )
out->children[j] = child->contents;
else
out->children[j] = child - mod->nodes;
}
if( child->contents < 0 )
out->children[j] = child->contents;
else out->children[j] = child - mod->nodes;
}
}
else
{
mclipnode16_t *out;
mnode_t *in = mod->nodes;
hull->clipnodes16 = out = Mem_Malloc( mod->mempool, mod->numnodes * sizeof( *hull->clipnodes16 ));
for( i = 0; i < mod->numnodes; i++, out++, in++ )
{
int j;
out->planenum = in->plane - mod->planes;
for( j = 0; j < 2; j++ )
{
mnode_t *child = node_child( in, j, mod );
if( child->contents < 0 )
out->children[j] = child->contents;
else
out->children[j] = child - mod->nodes;
}
}
}
}
/*
@@ -1761,18 +1688,15 @@ static void Mod_SetupHull( dbspmodel_t *bmod, model_t *mod, poolhandle_t mempool
if( VectorIsNull( hull->clip_mins ) && VectorIsNull( hull->clip_maxs ))
return; // no hull specified
CountDClipNodes_r( bmod->clipnodes_out, hull, headnode );
CountClipNodes32_r( bmod->clipnodes_out, hull, headnode );
// fit array to real count
if( bmod->version == QBSP2_VERSION )
hull->clipnodes32 = Mem_Malloc( mempool, sizeof( *hull->clipnodes32 ) * hull->lastclipnode );
else
hull->clipnodes16 = Mem_Malloc( mempool, sizeof( *hull->clipnodes16 ) * hull->lastclipnode );
hull->clipnodes = (mclipnode_t *)Mem_Malloc( mempool, sizeof( mclipnode_t ) * hull->lastclipnode );
hull->planes = mod->planes; // share planes
hull->lastclipnode = 0; // restart counting
RemapClipNodes_r( bmod, bmod->clipnodes_out, hull, headnode ); // remap clipnodes to 16-bit indexes
// remap clipnodes to 16-bit indexes
RemapClipNodes_r( bmod->clipnodes_out, hull, headnode );
}
static qboolean Mod_LoadLitfile( model_t *mod, const char *ext, size_t expected_size, color24 **out, size_t *outsize )
@@ -1780,8 +1704,7 @@ static qboolean Mod_LoadLitfile( model_t *mod, const char *ext, size_t expected_
char modelname[64], path[64];
int iCompare;
fs_offset_t datasize;
file_t *f;
uint hdr[2];
byte *in;
COM_FileBase( mod->name, modelname, sizeof( modelname ));
Q_snprintf( path, sizeof( path ), "maps/%s.%s", modelname, ext );
@@ -1792,15 +1715,31 @@ static qboolean Mod_LoadLitfile( model_t *mod, const char *ext, size_t expected_
if( iCompare < 0 ) // this may happens if level-designer used -onlyents key for hlcsg
Con_Printf( S_WARN "%s probably is out of date\n", path );
f = FS_Open( path, "rb", false );
in = FS_LoadFile( path, &datasize, false );
if( !f )
if( !in )
{
Con_Printf( S_ERROR "couldn't load %s\n", path );
return false;
}
datasize = FS_FileLength( f );
if( datasize <= 8 ) // header + version
{
Con_Printf( S_ERROR "%s is too short\n", path );
goto cleanup_and_error;
}
if( LittleLong( ((uint *)in)[0] ) != IDDELUXEMAPHEADER )
{
Con_Printf( S_ERROR "%s is corrupted\n", path );
goto cleanup_and_error;
}
if( LittleLong( ((uint *)in)[1] ) != DELUXEMAP_VERSION )
{
Con_Printf( S_ERROR "has %s mismatched version (%u should be %u)\n", path, LittleLong( ((uint *)in)[1] ), DELUXEMAP_VERSION );
goto cleanup_and_error;
}
// skip header bytes
datasize -= 8;
@@ -1811,33 +1750,14 @@ static qboolean Mod_LoadLitfile( model_t *mod, const char *ext, size_t expected_
goto cleanup_and_error;
}
if( FS_Read( f, hdr, sizeof( hdr )) != sizeof( hdr ))
{
Con_Printf( S_ERROR "failed reading header from %s\n", path );
goto cleanup_and_error;
}
if( LittleLong( hdr[0] ) != IDDELUXEMAPHEADER )
{
Con_Printf( S_ERROR "%s is corrupted\n", path );
goto cleanup_and_error;
}
if( LittleLong( hdr[1] ) != DELUXEMAP_VERSION )
{
Con_Printf( S_ERROR "has %s mismatched version (%u should be %u)\n", path, LittleLong( hdr[1] ), DELUXEMAP_VERSION );
goto cleanup_and_error;
}
*out = Mem_Malloc( mod->mempool, datasize );
memcpy( *out, in + 8, datasize );
*outsize = datasize;
FS_Read( f, *out, datasize );
FS_Close( f );
Mem_Free( in );
return true;
cleanup_and_error:
FS_Close( f );
Mem_Free( in );
return false;
}
@@ -1852,7 +1772,6 @@ for embedded submodels
static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod )
{
qboolean colored = false;
qboolean qbsp2 = false;
poolhandle_t mempool;
char *ents;
dmodel_t *bm;
@@ -1864,9 +1783,6 @@ static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod )
if( FBitSet( mod->flags, MODEL_COLORED_LIGHTING ))
colored = true;
if( FBitSet( mod->flags, MODEL_QBSP2 ))
qbsp2 = true;
mod->numframes = 2; // regular and alternate animation
// set up the submodels
@@ -1879,10 +1795,7 @@ static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod )
mod->hulls[0].lastclipnode = bm->headnode[0]; // need to be real count
// counting a real number of clipnodes per each submodel
if( bmod->version == QBSP2_VERSION )
CountClipNodes32_r( mod->hulls[0].clipnodes32, &mod->hulls[0], bm->headnode[0] );
else
CountClipNodes16_r( mod->hulls[0].clipnodes16, &mod->hulls[0], bm->headnode[0] );
CountClipNodes_r( mod->hulls[0].clipnodes, &mod->hulls[0], bm->headnode[0] );
// but hulls1-3 is build individually for a each given submodel
for( j = 1; j < MAX_MAP_HULLS; j++ )
@@ -1900,7 +1813,6 @@ static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod )
// this bit will be shared between all the submodels include worldmodel
if( colored ) SetBits( mod->flags, MODEL_COLORED_LIGHTING );
if( qbsp2 ) SetBits( mod->flags, MODEL_QBSP2 );
if( i != 0 )
{
@@ -2223,15 +2135,15 @@ Mod_LoadEdges
*/
static void Mod_LoadEdges( model_t *mod, dbspmodel_t *bmod )
{
medge_t *out;
int i;
mod->edges = out = Mem_Malloc( mod->mempool, bmod->numedges * sizeof( medge_t ));
mod->numedges = bmod->numedges;
if( bmod->version == QBSP2_VERSION )
{
dedge32_t *in = bmod->edges32;
medge32_t *out;
mod->edges32 = out = Mem_Malloc( mod->mempool, bmod->numedges * sizeof( *out ));
dedge32_t *in = (dedge32_t *)bmod->edges32;
for( i = 0; i < bmod->numedges; i++, in++, out++ )
{
@@ -2241,9 +2153,7 @@ static void Mod_LoadEdges( model_t *mod, dbspmodel_t *bmod )
}
else
{
dedge_t *in = bmod->edges;
medge16_t *out;
mod->edges16 = out = Mem_Malloc( mod->mempool, bmod->numedges * sizeof( *out ));
dedge_t *in = (dedge_t *)bmod->edges;
for( i = 0; i < bmod->numedges; i++, in++, out++ )
{
@@ -2359,7 +2269,7 @@ static qboolean Mod_SearchForTextureReplacement( char *out, size_t size, const c
return false;
}
static void Mod_InitSkyClouds( model_t *mod, const mip_t *mt, texture_t *tx, qboolean custom_palette )
static void Mod_InitSkyClouds( model_t *mod, mip_t *mt, texture_t *tx, qboolean custom_palette )
{
#if !XASH_DEDICATED
rgbdata_t r_temp, *r_sky;
@@ -2516,6 +2426,9 @@ done:
static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureIndex )
{
texture_t *texture = NULL;
mip_t *mipTex = NULL;
qboolean usesCustomPalette = false;
uint32_t txFlags = 0;
char texpath[MAX_VA_STRING];
char safemtname[16]; // only for external textures
@@ -2523,10 +2436,12 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
// don't load texture data on dedicated server, as there is no renderer.
// but count the wadusage for automatic precache
texture_t *texture = mod->textures[textureIndex];
const mip_t *mipTex = Mod_GetMipTexForTexture( bmod, textureIndex );
const qboolean usesCustomPalette = Mod_CalcMipTexUsesCustomPalette( mod, bmod, textureIndex );
const qboolean iswater = Mod_LooksLikeWaterTexture( mipTex->name );
//
// FIXME: for ENGINE_IMPROVED_LINETRACE we need to load textures on server too
// but there is no facility for this yet
texture = mod->textures[textureIndex];
mipTex = Mod_GetMipTexForTexture( bmod, textureIndex );
usesCustomPalette = Mod_CalcMipTexUsesCustomPalette( mod, bmod, textureIndex );
// check for multi-layered sky texture (quake1 specific)
if( bmod->isworld && Q_strncmp( mipTex->name, "sky", 3 ) == 0 && ( mipTex->width / mipTex->height ) == 2 )
@@ -2535,13 +2450,11 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
return;
}
// FIXME: for ENGINE_IMPROVED_LINETRACE we need to load textures on server too
// but there is no facility for this yet
if( FBitSet( host.features, ENGINE_IMPROVED_LINETRACE ) && mipTex->name[0] == '{' )
SetBits( txFlags, TF_KEEP_SOURCE ); // Paranoia2 texture alpha-tracing
// check if this is water to keep the source texture and expand it to RGBA (so ripple effect works)
if( iswater )
if( Mod_LooksLikeWaterTexture( mipTex->name ))
SetBits( txFlags, TF_KEEP_SOURCE | TF_EXPAND_SOURCE );
// Texture loading order:
@@ -2606,13 +2519,8 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
texture->gl_texturenum = R_GetBuiltinTexture( REF_DEFAULT_TEXTURE );
}
texture->fb_texturenum = 0;
// Check for luma texture
// a1ba: ignore for water because fb_texturenum will be used to store ripple texture
if( iswater )
return;
texture->fb_texturenum = 0;
if( load_external ) // external textures will not have TF_HAS_LUMA flag because it set only from WAD images loader
{
if( Mod_SearchForTextureReplacement( texpath, sizeof( texpath ), mod->name, safemtname, "_luma" ))
@@ -3005,9 +2913,9 @@ static void Mod_LoadSurfaces( model_t *mod, dbspmodel_t *bmod )
if( FBitSet( out->texinfo->flags, TEX_SPECIAL ))
SetBits( out->flags, SURF_DRAWTILED );
Mod_CalcSurfaceBounds( mod, out, bmod );
Mod_CalcSurfaceExtents( mod, out, bmod );
Mod_CreateFaceBevels( mod, out, bmod );
Mod_CalcSurfaceBounds( mod, out );
Mod_CalcSurfaceExtents( mod, out );
Mod_CreateFaceBevels( mod, out );
// grab the second sample to detect colored lighting
if( test_lightsize > 0 && lightofs != -1 )
@@ -3054,6 +2962,7 @@ static void Mod_LoadSurfaces( model_t *mod, dbspmodel_t *bmod )
if( samples == 1 || samples == 3 )
{
bmod->lightmap_samples = (int)samples;
Con_Reportf( "lighting: %s\n", (bmod->lightmap_samples == 1) ? "monochrome" : "colored" );
bmod->lightmap_samples = Q_max( bmod->lightmap_samples, 1 ); // avoid division by zero
}
else Con_DPrintf( S_WARN "lighting invalid samplecount: %g, defaulting to %i\n", samples, bmod->lightmap_samples );
@@ -3085,62 +2994,16 @@ static void Mod_LoadNodes( model_t *mod, dbspmodel_t *bmod )
out->minmaxs[j+3] = in->maxs[j];
}
#if !XASH_64BIT
if( in->firstface >= BIT( 24 ))
{
Host_Error( "%s: face index limit exceeded on node %i\n", __func__, i );
return;
}
if( in->numfaces >= BIT( 24 ))
{
Host_Error( "%s: face count limit exceeded on node %i\n", __func__, i );
return;
}
#endif
p = in->planenum;
out->plane = mod->planes + p;
out->firstsurface_0 = in->firstface & 0xFFFF;
out->numsurfaces_0 = in->numfaces & 0xFFFF;
out->firstsurface_1 = in->firstface >> 16;
out->numsurfaces_1 = in->numfaces >> 16;
out->firstsurface = in->firstface;
out->numsurfaces = in->numfaces;
for( j = 0; j < 2; j++ )
{
p = in->children[j];
#if XASH_64BIT
if( p >= 0 ) out->children_[j] = mod->nodes + p;
else out->children_[j] = (mnode_t *)(mod->leafs + ( -1 - p ));
#else
if( j == 0 )
{
if( p >= 0 )
{
out->child_0_leaf = 0;
out->child_0_off = p;
}
else
{
out->child_0_leaf = 1;
out->child_0_off = -1 - p;
}
}
else
{
if( p >= 0 )
{
out->child_1_leaf = 0;
out->child_1_off = p;
}
else
{
out->child_1_leaf = 1;
out->child_1_off = -1 - p;
}
}
#endif
if( p >= 0 ) out->children[j] = mod->nodes + p;
else out->children[j] = (mnode_t *)(mod->leafs + ( -1 - p ));
}
}
else
@@ -3155,20 +3018,20 @@ static void Mod_LoadNodes( model_t *mod, dbspmodel_t *bmod )
p = in->planenum;
out->plane = mod->planes + p;
out->firstsurface_0 = in->firstface;
out->numsurfaces_0 = in->numfaces;
out->firstsurface = in->firstface;
out->numsurfaces = in->numfaces;
for( j = 0; j < 2; j++ )
{
p = in->children[j];
if( p >= 0 ) out->children_[j] = mod->nodes + p;
else out->children_[j] = (mnode_t *)(mod->leafs + ( -1 - p ));
if( p >= 0 ) out->children[j] = mod->nodes + p;
else out->children[j] = (mnode_t *)(mod->leafs + ( -1 - p ));
}
}
}
// sets nodes and leafs
Mod_SetParent( mod, mod->nodes, NULL );
Mod_SetParent( mod->nodes, NULL );
}
/*
@@ -3550,8 +3413,6 @@ static void Mod_LoadLighting( model_t *mod, dbspmodel_t *bmod )
break;
}
Con_Reportf( "lighting: %s\n", FBitSet( mod->flags, MODEL_COLORED_LIGHTING ) ? "colored" : "monochrome" );
// not supposed to be load ?
if( FBitSet( host.features, ENGINE_LOAD_DELUXEDATA ))
{
@@ -3630,6 +3491,13 @@ static qboolean Mod_LoadBmodelLumps( model_t *mod, const byte *mod_base, qboolea
Q_strncpy( loadstat.name, mod->name, sizeof( loadstat.name ));
wadvalue[0] = '\0';
#ifndef SUPPORT_BSP2_FORMAT
if( header->version == QBSP2_VERSION )
{
Con_Printf( S_ERROR DEFAULT_BSP_BUILD_ERROR, mod->name );
return false;
}
#endif
switch( header->version )
{
case HLBSP_VERSION:
@@ -3652,9 +3520,6 @@ static qboolean Mod_LoadBmodelLumps( model_t *mod, const byte *mod_base, qboolea
// everything else
srclumps[0].lumpnumber = LUMP_ENTITIES;
srclumps[1].lumpnumber = LUMP_PLANES;
if( header->version == QBSP2_VERSION )
SetBits( mod->flags, MODEL_QBSP2 );
break;
default:
Con_Printf( S_ERROR "%s has wrong version number (%i should be %i)\n", mod->name, header->version, HLBSP_VERSION );
@@ -3705,7 +3570,7 @@ static qboolean Mod_LoadBmodelLumps( model_t *mod, const byte *mod_base, qboolea
Mod_LoadClipnodes( mod, bmod );
// preform some post-initalization
Mod_MakeHull0( mod, bmod );
Mod_MakeHull0( mod );
Mod_SetupSubmodels( mod, bmod );
if( isworld )
@@ -3795,6 +3660,15 @@ qboolean Mod_TestBmodelLumps( file_t *f, const char *name, const byte *mod_base,
if( silent )
SetBits( flags, LUMP_SILENT );
#ifndef SUPPORT_BSP2_FORMAT
if( header->version == QBSP2_VERSION )
{
if( !FBitSet( flags, LUMP_SILENT ))
Con_Printf( S_ERROR DEFAULT_BSP_BUILD_ERROR, name );
return false;
}
#endif
switch( header->version )
{
case HLBSP_VERSION:

View File

@@ -135,8 +135,6 @@ extern poolhandle_t com_studiocache;
extern convar_t mod_studiocache;
extern convar_t r_wadtextures;
extern convar_t r_showhull;
extern const mclipnode16_t box_clipnodes16[6];
extern const mclipnode32_t box_clipnodes32[6];
//
// model.c
@@ -169,12 +167,13 @@ void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *loaded );
//
void Mod_LoadBrushModel( model_t *mod, const void *buffer, qboolean *loaded );
qboolean Mod_TestBmodelLumps( file_t *f, const char *name, const byte *mod_base, qboolean silent, dlump_t *entities );
qboolean Mod_HeadnodeVisible( mnode_t *node, const byte *visbits, int *lastleaf );
int Mod_FatPVS( const vec3_t org, float radius, byte *visbuffer, int visbytes, qboolean merge, qboolean fullvis, qboolean false );
qboolean Mod_BoxVisible( const vec3_t mins, const vec3_t maxs, const byte *visbits );
int Mod_CheckLump( const char *filename, const int lump, int *lumpsize );
int Mod_ReadLump( const char *filename, const int lump, void **lumpdata, int *lumpsize );
int Mod_SaveLump( const char *filename, const int lump, void *lumpdata, int lumpsize );
mleaf_t *Mod_PointInLeaf( const vec3_t p, mnode_t *node, model_t *mod );
mleaf_t *Mod_PointInLeaf( const vec3_t p, mnode_t *node );
int Mod_SampleSizeForFace( const msurface_t *surf );
byte *Mod_GetPVSForPoint( const vec3_t p );
void Mod_UnloadBrushModel( model_t *mod );

View File

@@ -50,8 +50,9 @@ static matrix3x4 studio_bones[MAXSTUDIOBONES];
static uint studio_hull_hitgroup[MAXSTUDIOBONES];
static uint cache_hull_hitgroup[MAXSTUDIOBONES];
static mstudiocache_t cache_studio[STUDIO_CACHESIZE];
static mplane_t studio_planes[MAXSTUDIOBONES * 6];
static mplane_t cache_planes[MAXSTUDIOBONES * 6];
static mclipnode_t studio_clipnodes[6];
static mplane_t studio_planes[768];
static mplane_t cache_planes[768];
// current cache state
static int cache_current;
@@ -65,14 +66,25 @@ Mod_InitStudioHull
*/
void Mod_InitStudioHull( void )
{
int i;
int i, side;
if( studio_hull[0].planes != NULL )
return; // already initailized
for( i = 0; i < 6; i++ )
{
studio_clipnodes[i].planenum = i;
side = i & 1;
studio_clipnodes[i].children[side] = CONTENTS_EMPTY;
if( i != 5 ) studio_clipnodes[i].children[side^1] = i + 1;
else studio_clipnodes[i].children[side^1] = CONTENTS_SOLID;
}
for( i = 0; i < MAXSTUDIOBONES; i++ )
{
studio_hull[i].clipnodes16 = (mclipnode16_t *)box_clipnodes16;
studio_hull[i].clipnodes = studio_clipnodes;
studio_hull[i].planes = &studio_planes[i*6];
studio_hull[i].firstclipnode = 0;
studio_hull[i].lastclipnode = 5;
@@ -258,11 +270,6 @@ hull_t *Mod_HullForStudio( model_t *model, float frame, int sequence, vec3_t ang
for( i = j = 0; i < mod_studiohdr->numhitboxes; i++, j += 6 )
{
if( world.version == QBSP2_VERSION )
studio_hull[i].clipnodes32 = (mclipnode32_t *)box_clipnodes32;
else
studio_hull[i].clipnodes16 = (mclipnode16_t *)box_clipnodes16;
if( bSkipShield && i == 21 )
continue; // CS stuff
@@ -868,7 +875,7 @@ void Mod_LoadStudioModel( model_t *mod, const void *buffer, qboolean *loaded )
mod->type = mod_studio;
phdr = R_StudioLoadHeader( mod, buffer );
if( !phdr || phdr->length < sizeof( studiohdr_t )) // garbage value in length
if( !phdr )
return; // bad model
#if !XASH_DEDICATED

View File

@@ -258,7 +258,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
{
char tempname[MAX_QPATH];
fs_offset_t length = 0;
qboolean loaded, loaded2 = false;
qboolean loaded;
byte *buf;
model_info_t *p;
@@ -279,7 +279,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
buf = FS_LoadFile( tempname, &length, false );
if( !buf || length < sizeof( uint ))
if( !buf )
{
memset( mod, 0, sizeof( model_t ));
@@ -329,12 +329,11 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
// let the server.dll load custom data
svgame.physFuncs.Mod_ProcessUserData( mod, true, buf );
}
loaded2 = true;
}
#if !XASH_DEDICATED
else
{
loaded2 = ref.dllFuncs.Mod_ProcessRenderData( mod, true, buf );
loaded = ref.dllFuncs.Mod_ProcessRenderData( mod, true, buf );
}
#endif
}
@@ -346,7 +345,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
hdr->pposeverts = NULL;
}
if( !loaded || !loaded2 )
if( !loaded )
{
Mod_FreeModel( mod );
Mem_Free( buf );
@@ -611,41 +610,3 @@ void Mod_NeedCRC( const char *name, qboolean needCRC )
if( needCRC ) SetBits( p->flags, FCRC_SHOULD_CHECKSUM );
else ClearBits( p->flags, FCRC_SHOULD_CHECKSUM );
}
#if XASH_ENGINE_TESTS
static const uint8_t *fuzz_data;
static size_t fuzz_size;
static byte *Fuzz_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly )
{
byte *buf = Mem_Malloc( host.mempool, fuzz_size );
memcpy( buf, fuzz_data, fuzz_size );
*filesizeptr = fuzz_size;
return buf;
}
int EXPORT Fuzz_Mod_LoadModel( const uint8_t *Data, size_t Size );
int EXPORT Fuzz_Mod_LoadModel( const uint8_t *Data, size_t Size )
{
model_t mod = { .name = "test", .needload = NL_NEEDS_LOADED };
Memory_Init();
host.type = HOST_DEDICATED;
host.mempool = Mem_AllocPool( "fuzzing pool" );
fuzz_data = Data;
fuzz_size = Size;
refState.draw_surfaces = NULL;
g_fsapi.LoadFile = Fuzz_LoadFile;
if( Mod_LoadModel( &mod, false ) && mod.mempool )
Mem_FreePool( &mod.mempool );
Mem_FreePool( &host.mempool );
return 0;
}
#endif // XASH_ENGINE_TESTS

View File

@@ -18,177 +18,11 @@ GNU General Public License for more details.
#include "net_buffer.h"
#include "xash3d_mathlib.h"
static const uint32_t BitWriteMasks[32][32] =
{ {
0xfffffffe, 0xfffffffc, 0xfffffff8, 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80, 0xffffff00,
0xfffffe00, 0xfffffc00, 0xfffff800, 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000, 0xffff0000,
0xfffe0000, 0xfffc0000, 0xfff80000, 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000, 0xff000000,
0xfe000000, 0xfc000000, 0xf8000000, 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000, 0x00000000,
}, {
0xfffffffd, 0xfffffff9, 0xfffffff1, 0xffffffe1, 0xffffffc1, 0xffffff81, 0xffffff01, 0xfffffe01,
0xfffffc01, 0xfffff801, 0xfffff001, 0xffffe001, 0xffffc001, 0xffff8001, 0xffff0001, 0xfffe0001,
0xfffc0001, 0xfff80001, 0xfff00001, 0xffe00001, 0xffc00001, 0xff800001, 0xff000001, 0xfe000001,
0xfc000001, 0xf8000001, 0xf0000001, 0xe0000001, 0xc0000001, 0x80000001, 0x00000001, 0x00000001,
}, {
0xfffffffb, 0xfffffff3, 0xffffffe3, 0xffffffc3, 0xffffff83, 0xffffff03, 0xfffffe03, 0xfffffc03,
0xfffff803, 0xfffff003, 0xffffe003, 0xffffc003, 0xffff8003, 0xffff0003, 0xfffe0003, 0xfffc0003,
0xfff80003, 0xfff00003, 0xffe00003, 0xffc00003, 0xff800003, 0xff000003, 0xfe000003, 0xfc000003,
0xf8000003, 0xf0000003, 0xe0000003, 0xc0000003, 0x80000003, 0x00000003, 0x00000003, 0x00000003,
}, {
0xfffffff7, 0xffffffe7, 0xffffffc7, 0xffffff87, 0xffffff07, 0xfffffe07, 0xfffffc07, 0xfffff807,
0xfffff007, 0xffffe007, 0xffffc007, 0xffff8007, 0xffff0007, 0xfffe0007, 0xfffc0007, 0xfff80007,
0xfff00007, 0xffe00007, 0xffc00007, 0xff800007, 0xff000007, 0xfe000007, 0xfc000007, 0xf8000007,
0xf0000007, 0xe0000007, 0xc0000007, 0x80000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007,
}, {
0xffffffef, 0xffffffcf, 0xffffff8f, 0xffffff0f, 0xfffffe0f, 0xfffffc0f, 0xfffff80f, 0xfffff00f,
0xffffe00f, 0xffffc00f, 0xffff800f, 0xffff000f, 0xfffe000f, 0xfffc000f, 0xfff8000f, 0xfff0000f,
0xffe0000f, 0xffc0000f, 0xff80000f, 0xff00000f, 0xfe00000f, 0xfc00000f, 0xf800000f, 0xf000000f,
0xe000000f, 0xc000000f, 0x8000000f, 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f,
}, {
0xffffffdf, 0xffffff9f, 0xffffff1f, 0xfffffe1f, 0xfffffc1f, 0xfffff81f, 0xfffff01f, 0xffffe01f,
0xffffc01f, 0xffff801f, 0xffff001f, 0xfffe001f, 0xfffc001f, 0xfff8001f, 0xfff0001f, 0xffe0001f,
0xffc0001f, 0xff80001f, 0xff00001f, 0xfe00001f, 0xfc00001f, 0xf800001f, 0xf000001f, 0xe000001f,
0xc000001f, 0x8000001f, 0x0000001f, 0x0000001f, 0x0000001f, 0x0000001f, 0x0000001f, 0x0000001f,
}, {
0xffffffbf, 0xffffff3f, 0xfffffe3f, 0xfffffc3f, 0xfffff83f, 0xfffff03f, 0xffffe03f, 0xffffc03f,
0xffff803f, 0xffff003f, 0xfffe003f, 0xfffc003f, 0xfff8003f, 0xfff0003f, 0xffe0003f, 0xffc0003f,
0xff80003f, 0xff00003f, 0xfe00003f, 0xfc00003f, 0xf800003f, 0xf000003f, 0xe000003f, 0xc000003f,
0x8000003f, 0x0000003f, 0x0000003f, 0x0000003f, 0x0000003f, 0x0000003f, 0x0000003f, 0x0000003f,
}, {
0xffffff7f, 0xfffffe7f, 0xfffffc7f, 0xfffff87f, 0xfffff07f, 0xffffe07f, 0xffffc07f, 0xffff807f,
0xffff007f, 0xfffe007f, 0xfffc007f, 0xfff8007f, 0xfff0007f, 0xffe0007f, 0xffc0007f, 0xff80007f,
0xff00007f, 0xfe00007f, 0xfc00007f, 0xf800007f, 0xf000007f, 0xe000007f, 0xc000007f, 0x8000007f,
0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f,
}, {
0xfffffeff, 0xfffffcff, 0xfffff8ff, 0xfffff0ff, 0xffffe0ff, 0xffffc0ff, 0xffff80ff, 0xffff00ff,
0xfffe00ff, 0xfffc00ff, 0xfff800ff, 0xfff000ff, 0xffe000ff, 0xffc000ff, 0xff8000ff, 0xff0000ff,
0xfe0000ff, 0xfc0000ff, 0xf80000ff, 0xf00000ff, 0xe00000ff, 0xc00000ff, 0x800000ff, 0x000000ff,
0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
}, {
0xfffffdff, 0xfffff9ff, 0xfffff1ff, 0xffffe1ff, 0xffffc1ff, 0xffff81ff, 0xffff01ff, 0xfffe01ff,
0xfffc01ff, 0xfff801ff, 0xfff001ff, 0xffe001ff, 0xffc001ff, 0xff8001ff, 0xff0001ff, 0xfe0001ff,
0xfc0001ff, 0xf80001ff, 0xf00001ff, 0xe00001ff, 0xc00001ff, 0x800001ff, 0x000001ff, 0x000001ff,
0x000001ff, 0x000001ff, 0x000001ff, 0x000001ff, 0x000001ff, 0x000001ff, 0x000001ff, 0x000001ff,
}, {
0xfffffbff, 0xfffff3ff, 0xffffe3ff, 0xffffc3ff, 0xffff83ff, 0xffff03ff, 0xfffe03ff, 0xfffc03ff,
0xfff803ff, 0xfff003ff, 0xffe003ff, 0xffc003ff, 0xff8003ff, 0xff0003ff, 0xfe0003ff, 0xfc0003ff,
0xf80003ff, 0xf00003ff, 0xe00003ff, 0xc00003ff, 0x800003ff, 0x000003ff, 0x000003ff, 0x000003ff,
0x000003ff, 0x000003ff, 0x000003ff, 0x000003ff, 0x000003ff, 0x000003ff, 0x000003ff, 0x000003ff,
}, {
0xfffff7ff, 0xffffe7ff, 0xffffc7ff, 0xffff87ff, 0xffff07ff, 0xfffe07ff, 0xfffc07ff, 0xfff807ff,
0xfff007ff, 0xffe007ff, 0xffc007ff, 0xff8007ff, 0xff0007ff, 0xfe0007ff, 0xfc0007ff, 0xf80007ff,
0xf00007ff, 0xe00007ff, 0xc00007ff, 0x800007ff, 0x000007ff, 0x000007ff, 0x000007ff, 0x000007ff,
0x000007ff, 0x000007ff, 0x000007ff, 0x000007ff, 0x000007ff, 0x000007ff, 0x000007ff, 0x000007ff,
}, {
0xffffefff, 0xffffcfff, 0xffff8fff, 0xffff0fff, 0xfffe0fff, 0xfffc0fff, 0xfff80fff, 0xfff00fff,
0xffe00fff, 0xffc00fff, 0xff800fff, 0xff000fff, 0xfe000fff, 0xfc000fff, 0xf8000fff, 0xf0000fff,
0xe0000fff, 0xc0000fff, 0x80000fff, 0x00000fff, 0x00000fff, 0x00000fff, 0x00000fff, 0x00000fff,
0x00000fff, 0x00000fff, 0x00000fff, 0x00000fff, 0x00000fff, 0x00000fff, 0x00000fff, 0x00000fff,
}, {
0xffffdfff, 0xffff9fff, 0xffff1fff, 0xfffe1fff, 0xfffc1fff, 0xfff81fff, 0xfff01fff, 0xffe01fff,
0xffc01fff, 0xff801fff, 0xff001fff, 0xfe001fff, 0xfc001fff, 0xf8001fff, 0xf0001fff, 0xe0001fff,
0xc0001fff, 0x80001fff, 0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff,
0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff,
}, {
0xffffbfff, 0xffff3fff, 0xfffe3fff, 0xfffc3fff, 0xfff83fff, 0xfff03fff, 0xffe03fff, 0xffc03fff,
0xff803fff, 0xff003fff, 0xfe003fff, 0xfc003fff, 0xf8003fff, 0xf0003fff, 0xe0003fff, 0xc0003fff,
0x80003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff,
0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff,
}, {
0xffff7fff, 0xfffe7fff, 0xfffc7fff, 0xfff87fff, 0xfff07fff, 0xffe07fff, 0xffc07fff, 0xff807fff,
0xff007fff, 0xfe007fff, 0xfc007fff, 0xf8007fff, 0xf0007fff, 0xe0007fff, 0xc0007fff, 0x80007fff,
0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff,
0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff,
}, {
0xfffeffff, 0xfffcffff, 0xfff8ffff, 0xfff0ffff, 0xffe0ffff, 0xffc0ffff, 0xff80ffff, 0xff00ffff,
0xfe00ffff, 0xfc00ffff, 0xf800ffff, 0xf000ffff, 0xe000ffff, 0xc000ffff, 0x8000ffff, 0x0000ffff,
0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff,
0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff,
}, {
0xfffdffff, 0xfff9ffff, 0xfff1ffff, 0xffe1ffff, 0xffc1ffff, 0xff81ffff, 0xff01ffff, 0xfe01ffff,
0xfc01ffff, 0xf801ffff, 0xf001ffff, 0xe001ffff, 0xc001ffff, 0x8001ffff, 0x0001ffff, 0x0001ffff,
0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff,
0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff,
}, {
0xfffbffff, 0xfff3ffff, 0xffe3ffff, 0xffc3ffff, 0xff83ffff, 0xff03ffff, 0xfe03ffff, 0xfc03ffff,
0xf803ffff, 0xf003ffff, 0xe003ffff, 0xc003ffff, 0x8003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff,
0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff,
0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff,
}, {
0xfff7ffff, 0xffe7ffff, 0xffc7ffff, 0xff87ffff, 0xff07ffff, 0xfe07ffff, 0xfc07ffff, 0xf807ffff,
0xf007ffff, 0xe007ffff, 0xc007ffff, 0x8007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff,
0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff,
0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff,
}, {
0xffefffff, 0xffcfffff, 0xff8fffff, 0xff0fffff, 0xfe0fffff, 0xfc0fffff, 0xf80fffff, 0xf00fffff,
0xe00fffff, 0xc00fffff, 0x800fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff,
0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff,
0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff,
}, {
0xffdfffff, 0xff9fffff, 0xff1fffff, 0xfe1fffff, 0xfc1fffff, 0xf81fffff, 0xf01fffff, 0xe01fffff,
0xc01fffff, 0x801fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff,
0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff,
0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff,
}, {
0xffbfffff, 0xff3fffff, 0xfe3fffff, 0xfc3fffff, 0xf83fffff, 0xf03fffff, 0xe03fffff, 0xc03fffff,
0x803fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff,
0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff,
0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff,
}, {
0xff7fffff, 0xfe7fffff, 0xfc7fffff, 0xf87fffff, 0xf07fffff, 0xe07fffff, 0xc07fffff, 0x807fffff,
0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff,
0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff,
0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff,
}, {
0xfeffffff, 0xfcffffff, 0xf8ffffff, 0xf0ffffff, 0xe0ffffff, 0xc0ffffff, 0x80ffffff, 0x00ffffff,
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
}, {
0xfdffffff, 0xf9ffffff, 0xf1ffffff, 0xe1ffffff, 0xc1ffffff, 0x81ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
}, {
0xfbffffff, 0xf3ffffff, 0xe3ffffff, 0xc3ffffff, 0x83ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff,
0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff,
0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff,
0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff,
}, {
0xf7ffffff, 0xe7ffffff, 0xc7ffffff, 0x87ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff,
0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff,
0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff,
0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff,
}, {
0xefffffff, 0xcfffffff, 0x8fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff,
0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff,
0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff,
0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff,
}, {
0xdfffffff, 0x9fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff,
0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff,
0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff,
0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff,
}, {
0xbfffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff,
0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff,
0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff,
0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff,
}, {
0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff,
0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff,
0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff,
0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff,
} };
static const uint32_t ExtraMasks[32] =
{
0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
};
// precalculated bit masks for WriteUBitLong.
// Using these tables instead of doing the calculations
// gives a 33% speedup in WriteUBitLong.
static uint32_t BitWriteMasks[32][33];
static uint32_t ExtraMasks[32];
const char *const svc_strings[svc_lastmsg+1] =
{
"svc_bad",
@@ -298,41 +132,65 @@ const char *const svc_quake_strings[svc_lastmsg+1] =
[svc_fog] = "svc_quake_fog",
};
void MSG_InitMasks( void )
{
uint startbit, endbit;
uint maskBit, nBitsLeft;
for( startbit = 0; startbit < 32; startbit++ )
{
for( nBitsLeft = 0; nBitsLeft < 33; nBitsLeft++ )
{
endbit = startbit + nBitsLeft;
BitWriteMasks[startbit][nBitsLeft] = (uint)BIT( startbit ) - 1;
if( endbit < 32 ) BitWriteMasks[startbit][nBitsLeft] |= ~((uint)BIT( endbit ) - 1 );
}
}
for( maskBit = 0; maskBit < 32; maskBit++ )
ExtraMasks[maskBit] = (uint)BIT( maskBit ) - 1;
}
void MSG_WriteUBitLong( sizebuf_t *sb, uint curData, int numbits )
{
int nBitsLeft = numbits;
int iCurBit = sb->iCurBit;
uint iDWord = iCurBit >> 5; // Mask in a dword.
uint32_t iCurBitMasked;
int nBitsWritten;
Assert( numbits >= 1 && numbits <= 32 );
Assert( numbits >= 0 && numbits <= 32 );
// bounds checking..
if( MSG_Overflow( sb, numbits ))
if(( sb->iCurBit + numbits ) > sb->nDataBits )
{
sb->bOverflow = true;
sb->iCurBit = sb->nDataBits;
return;
}
iCurBitMasked = iCurBit & 31;
((uint32_t *)sb->pData)[iDWord] &= BitWriteMasks[iCurBitMasked][nBitsLeft-1];
((uint32_t *)sb->pData)[iDWord] |= curData << iCurBitMasked;
// did it span a dword?
nBitsWritten = 32 - iCurBitMasked;
if( nBitsWritten < nBitsLeft )
else
{
nBitsLeft -= nBitsWritten;
iCurBit += nBitsWritten;
curData >>= nBitsWritten;
int nBitsLeft = numbits;
int iCurBit = sb->iCurBit;
uint iDWord = iCurBit >> 5; // Mask in a dword.
uint32_t iCurBitMasked;
int nBitsWritten;
Assert(( iDWord * 4 + sizeof( int )) <= (uint)MSG_GetMaxBytes( sb ));
iCurBitMasked = iCurBit & 31;
((uint32_t *)sb->pData)[iDWord+1] &= BitWriteMasks[iCurBitMasked][nBitsLeft-1];
((uint32_t *)sb->pData)[iDWord+1] |= curData << iCurBitMasked;
((uint32_t *)sb->pData)[iDWord] &= BitWriteMasks[iCurBitMasked][nBitsLeft];
((uint32_t *)sb->pData)[iDWord] |= curData << iCurBitMasked;
// did it span a dword?
nBitsWritten = 32 - iCurBitMasked;
if( nBitsWritten < nBitsLeft )
{
nBitsLeft -= nBitsWritten;
iCurBit += nBitsWritten;
curData >>= nBitsWritten;
iCurBitMasked = iCurBit & 31;
((uint32_t *)sb->pData)[iDWord+1] &= BitWriteMasks[iCurBitMasked][nBitsLeft];
((uint32_t *)sb->pData)[iDWord+1] |= curData << iCurBitMasked;
}
sb->iCurBit += numbits;
}
sb->iCurBit += numbits;
}
/*
@@ -380,7 +238,7 @@ qboolean MSG_WriteBits( sizebuf_t *sb, const void *pData, int nBits )
int nBitsLeft = nBits;
// get output dword-aligned.
while((( uintptr_t )pOut & 3 ) != 0 && nBitsLeft >= 8 )
while((( uint32_t )pOut & 3 ) != 0 && nBitsLeft >= 8 )
{
MSG_WriteUBitLong( sb, *pOut, 8 );
@@ -417,14 +275,16 @@ qboolean MSG_WriteBits( sizebuf_t *sb, const void *pData, int nBits )
void MSG_WriteBitAngle( sizebuf_t *sb, float fAngle, int numbits )
{
const uint shift = ( 1 << numbits );
const uint mask = shift - 1;
uint mask, shift;
int d;
// clamp the angle before receiving
fAngle = fmod( fAngle, 360.0f );
if( fAngle < 0 ) fAngle += 360.0f;
shift = ( 1 << numbits );
mask = shift - 1;
d = (int)(( fAngle * shift ) / 360.0f );
d &= mask;
@@ -578,8 +438,9 @@ uint MSG_ReadUBitLong( sizebuf_t *sb, int numbits )
return 0; // end of message
}
if( MSG_Overflow( sb, numbits ))
if(( sb->iCurBit + numbits ) > sb->nDataBits )
{
sb->bOverflow = true;
sb->iCurBit = sb->nDataBits;
return 0;
}
@@ -652,9 +513,13 @@ qboolean MSG_ReadBits( sizebuf_t *sb, void *pOutData, int nBits )
float MSG_ReadBitAngle( sizebuf_t *sb, int numbits )
{
float shift = (float)( 1 << numbits );
int i = MSG_ReadUBitLong( sb, numbits );
float fReturn = (float)i * ( 360.0f / shift );
float fReturn, shift;
int i;
shift = (float)( 1 << numbits );
i = MSG_ReadUBitLong( sb, numbits );
fReturn = (float)i * ( 360.0f / shift );
// clamp the finale angle
if( fReturn < -180.0f ) fReturn += 360.0f;
@@ -666,11 +531,11 @@ float MSG_ReadBitAngle( sizebuf_t *sb, int numbits )
// Append numbits least significant bits from data to the current bit stream
int MSG_ReadSBitLong( sizebuf_t *sb, int numbits )
{
int r;
int r, sign;
if( sb->iAlternateSign )
{
int sign = MSG_ReadOneBit( sb );
sign = MSG_ReadOneBit( sb );
r = MSG_ReadUBitLong( sb, numbits - 1 );
if( sign )
@@ -679,7 +544,9 @@ int MSG_ReadSBitLong( sizebuf_t *sb, int numbits )
else
{
r = MSG_ReadUBitLong( sb, numbits - 1 );
if( MSG_ReadOneBit( sb ))
sign = MSG_ReadOneBit( sb );
if( sign )
r = -( BIT( numbits - 1 ) - r );
}
@@ -800,12 +667,12 @@ qboolean MSG_ReadBytes( sizebuf_t *sb, void *pOut, int nBytes )
static char *MSG_ReadStringExt( sizebuf_t *sb, qboolean bLine )
{
static char string[4096];
int l = 0;
int l = 0, c;
do
{
// use MSG_ReadByte so -1 is out of bounds
int c = MSG_ReadByte( sb );
c = MSG_ReadByte( sb );
if( c == 0 ) break;
else if( bLine && c == '\n' )
@@ -998,6 +865,8 @@ static void Test_Buffer_ExciseBits( void )
void Test_RunBuffer( void )
{
MSG_InitMasks();
TRUN( Test_Buffer_BitByte( ));
TRUN( Test_Buffer_Write( ));
TRUN( Test_Buffer_Read( ));

View File

@@ -193,6 +193,7 @@ static inline void MSG_StartBitWriting( sizebuf_t *sb )
sb->iAlternateSign++;
}
void MSG_InitMasks( void ); // called once at startup engine
void MSG_ExciseBits( sizebuf_t *sb, int startbit, int bitstoremove );
// Bit-write functions

View File

@@ -272,6 +272,8 @@ void Netchan_Init( void )
Cvar_FullSet( net_qport.name, buf, net_qport.flags );
net_mempool = Mem_AllocPool( "Network Pool" );
MSG_InitMasks(); // initialize bit-masks
}
void Netchan_Shutdown( void )
@@ -341,7 +343,6 @@ void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, voi
chan->split = FBitSet( flags, NETCHAN_USE_LEGACY_SPLIT ) ? true : false;
chan->use_munge = FBitSet( flags, NETCHAN_USE_MUNGE ) ? true : false;
chan->use_bz2 = FBitSet( flags, NETCHAN_USE_BZIP2 ) ? true : false;
chan->use_lzss = FBitSet( flags, NETCHAN_USE_LZSS ) ? true : false;
chan->gs_netchan = FBitSet( flags, NETCHAN_GOLDSRC ) ? true : false;
MSG_Init( &chan->message, "NetData", chan->message_buf, sizeof( chan->message_buf ));
@@ -767,7 +768,7 @@ static void Netchan_CreateFragments_( netchan_t *chan, sizebuf_t *msg )
Host_Error( "%s: BZ2 compression is not supported for server", __func__ );
#endif
}
else if( chan->use_lzss && !LZSS_IsCompressed( MSG_GetData( msg ), MSG_GetMaxBytes( msg )))
else if( !chan->use_bz2 && !LZSS_IsCompressed( MSG_GetData( msg ), MSG_GetMaxBytes( msg )))
{
uint uCompressedSize = 0;
uint uSourceSize = MSG_GetNumBytesWritten( msg );
@@ -1174,7 +1175,7 @@ qboolean Netchan_CopyNormalFragments( netchan_t *chan, sizebuf_t *msg, size_t *l
p = n;
}
if( chan->use_bz2 && !memcmp( MSG_GetData( msg ), "BZ2", 4 ))
if( chan->use_bz2 && !memcmp( MSG_GetData( msg ), "BZ2", 4 ) )
{
#if !XASH_DEDICATED
byte buf[0x10000];
@@ -1195,7 +1196,7 @@ qboolean Netchan_CopyNormalFragments( netchan_t *chan, sizebuf_t *msg, size_t *l
Host_Error( "%s: BZ2 compression is not supported for server\n", __func__ );
#endif
}
else if( chan->use_lzss && LZSS_IsCompressed( MSG_GetData( msg ), size ))
else if( !chan->use_bz2 && LZSS_IsCompressed( MSG_GetData( msg ), size ))
{
uint uDecompressedLen = LZSS_GetActualSize( MSG_GetData( msg ), size );
byte buf[NET_MAX_MESSAGE];
@@ -1346,7 +1347,7 @@ qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg )
Host_Error( "%s: BZ2 compression is not supported for server", __func__ );
#endif
}
else if( chan->use_lzss && LZSS_IsCompressed( buffer, nsize + 1 ))
else if( LZSS_IsCompressed( buffer, nsize + 1 ))
{
byte *uncompressedBuffer;

View File

@@ -2282,6 +2282,10 @@ void Test_RunDelta( void )
char buffer[4096] = { 0 };
const double timebase = 123.123;
// a1ba: netbuffer bitmasks are initialized in netchan for some reason
// initialize it ourselves just in case
MSG_InitMasks(); // initialize bit-masks
Delta_AddField( dt, "dt_string", DT_STRING, 1, 1.0f, 1.0f );
Delta_AddField( dt, "dt_timewindow_big", DT_TIMEWINDOW_BIG, 24, 1000.f, 1.0f );
Delta_AddField( dt, "dt_timewindow_8", DT_TIMEWINDOW_8, 8, 1.0f, 1.0f );

View File

@@ -326,7 +326,7 @@ static int HTTP_FileConnect( httpfile_t *file )
if( !COM_CheckStringEmpty( http_useragent.string ) || !Q_strcmp( http_useragent.string, "xash3d" ))
{
Q_snprintf( useragent, sizeof( useragent ), "%s/%s (%s-%s; build %d; %s)",
XASH_ENGINE_NAME, XASH_VERSION, Q_buildos( ), Q_buildarch( ), Q_buildnum( ), g_buildcommit );
XASH_ENGINE_NAME, XASH_VERSION, Q_buildos( ), Q_buildarch( ), Q_buildnum( ), Q_buildcommit( ));
}
else Q_strncpy( useragent, http_useragent.string, sizeof( useragent ));
@@ -505,14 +505,11 @@ static int HTTP_FileDecompress( httpfile_t *file )
if( zlib_result == Z_OK || zlib_result == Z_STREAM_END )
{
g_fsapi.WriteFile( name, data_out, decompressed_len );
HTTP_FreeFile( file, false );
Mem_Free( data_in );
}
else HTTP_FreeFile( file, true );
Mem_Free( data_in );
Mem_Free( data_out );
g_fsapi.WriteFile( name, data_out, decompressed_len );
HTTP_FreeFile( file, false );
return 1;
}

View File

@@ -214,7 +214,6 @@ typedef enum netchan_flags_e
NETCHAN_USE_MUNGE = BIT( 1 ),
NETCHAN_USE_BZIP2 = BIT( 2 ),
NETCHAN_GOLDSRC = BIT( 3 ),
NETCHAN_USE_LZSS = BIT( 4 ), // mutually exclusive with bzip2
} netchan_flags_t;
// Network Connection Channel
@@ -286,7 +285,6 @@ typedef struct netchan_s
qboolean split;
qboolean use_munge;
qboolean use_bz2;
qboolean use_lzss;
qboolean gs_netchan;
} netchan_t;

View File

@@ -112,9 +112,6 @@ msurface_t *PM_RecursiveSurfCheck( model_t *mod, mnode_t *node, vec3_t p1, vec3_
int i, side;
msurface_t *surf;
vec3_t mid;
mnode_t *children[2];
int numsurfaces, firstsurface;
loc0:
if( node->contents < 0 )
return NULL;
@@ -122,17 +119,15 @@ loc0:
t1 = PlaneDiff( p1, node->plane );
t2 = PlaneDiff( p2, node->plane );
node_children( children, node, mod );
if( t1 >= -FRAC_EPSILON && t2 >= -FRAC_EPSILON )
{
node = children[0];
node = node->children[0];
goto loc0;
}
if( t1 < FRAC_EPSILON && t2 < FRAC_EPSILON )
{
node = children[1];
node = node->children[1];
goto loc0;
}
@@ -142,15 +137,13 @@ loc0:
VectorLerp( p1, frac, p2, mid );
if(( surf = PM_RecursiveSurfCheck( mod, children[side], p1, mid )) != NULL )
if(( surf = PM_RecursiveSurfCheck( mod, node->children[side], p1, mid )) != NULL )
return surf;
// walk through real faces
numsurfaces = node_numsurfaces( node, mod );
firstsurface = node_firstsurface( node, mod );
for( i = 0; i < numsurfaces; i++ )
for( i = 0; i < node->numsurfaces; i++ )
{
msurface_t *surf = &mod->surfaces[firstsurface + i];
msurface_t *surf = &mod->surfaces[node->firstsurface + i];
mextrasurf_t *info = surf->info;
mfacebevel_t *fb = info->bevel;
int j, contents;
@@ -179,7 +172,7 @@ loc0:
return NULL; // through the fence
}
return PM_RecursiveSurfCheck( mod, children[side^1], mid, p2 );
return PM_RecursiveSurfCheck( mod, node->children[side^1], mid, p2 );
}
/*
@@ -234,9 +227,6 @@ static int PM_TestLine_r( model_t *mod, mnode_t *node, vec_t p1f, vec_t p2f, con
float frac, midf;
int i, r, side;
vec3_t mid;
mnode_t *children[2];
int numsurfaces, firstsurface;
loc0:
if( node->contents < 0 )
{
@@ -252,17 +242,15 @@ loc0:
front = PlaneDiff( start, node->plane );
back = PlaneDiff( stop, node->plane );
node_children( children, node, mod );
if( front >= -FRAC_EPSILON && back >= -FRAC_EPSILON )
{
node = children[0];
node = node->children[0];
goto loc0;
}
if( front < FRAC_EPSILON && back < FRAC_EPSILON )
{
node = children[1];
node = node->children[1];
goto loc0;
}
@@ -273,7 +261,7 @@ loc0:
VectorLerp( start, frac, stop, mid );
midf = p1f + ( p2f - p1f ) * frac;
r = PM_TestLine_r( mod, children[side], p1f, midf, start, mid, trace );
r = PM_TestLine_r( mod, node->children[side], p1f, midf, start, mid, trace );
if( r != CONTENTS_EMPTY )
{
@@ -284,11 +272,9 @@ loc0:
}
// walk through real faces
numsurfaces = node_numsurfaces( node, mod );
firstsurface = node_firstsurface( node, mod );
for( i = 0; i < numsurfaces; i++ )
for( i = 0; i < node->numsurfaces; i++ )
{
msurface_t *surf = &mod->surfaces[firstsurface + i];
msurface_t *surf = &mod->surfaces[node->firstsurface + i];
mextrasurf_t *info = surf->info;
mfacebevel_t *fb = info->bevel;
int j, contents;
@@ -322,7 +308,7 @@ loc0:
return contents;
}
return PM_TestLine_r( mod, children[!side], midf, p2f, mid, stop, trace );
return PM_TestLine_r( mod, node->children[!side], midf, p2f, mid, stop, trace );
}
int PM_TestLineExt( playermove_t *pmove, physent_t *ents, int numents, const vec3_t start, const vec3_t end, int flags )

View File

@@ -25,7 +25,8 @@ GNU General Public License for more details.
#define PM_AllowHitBoxTrace( model, hull ) ( model && model->type == mod_studio && ( FBitSet( model->flags, STUDIO_TRACE_HITBOX ) || hull == 2 ))
static mplane_t pm_boxplanes[6];
static hull_t pm_boxhull;
static mclipnode_t pm_boxclipnodes[6];
static hull_t pm_boxhull;
// default hullmins
static const vec3_t pm_hullmins[MAX_MAP_HULLS] =
@@ -64,15 +65,23 @@ can just be stored out and get a proper hull_t structure.
*/
void PM_InitBoxHull( void )
{
int i;
int i, side;
pm_boxhull.clipnodes16 = (mclipnode16_t *)box_clipnodes16;
pm_boxhull.clipnodes = pm_boxclipnodes;
pm_boxhull.planes = pm_boxplanes;
pm_boxhull.firstclipnode = 0;
pm_boxhull.lastclipnode = 5;
for( i = 0; i < 6; i++ )
{
pm_boxclipnodes[i].planenum = i;
side = i & 1;
pm_boxclipnodes[i].children[side] = CONTENTS_EMPTY;
if( i != 5 ) pm_boxclipnodes[i].children[side^1] = i + 1;
else pm_boxclipnodes[i].children[side^1] = CONTENTS_SOLID;
pm_boxplanes[i].type = i>>1;
pm_boxplanes[i].normal[i>>1] = 1.0f;
pm_boxplanes[i].signbits = 0;
@@ -97,11 +106,6 @@ static hull_t *PM_HullForBox( const vec3_t mins, const vec3_t maxs )
pm_boxplanes[4].dist = maxs[2];
pm_boxplanes[5].dist = mins[2];
if( world.version == QBSP2_VERSION )
pm_boxhull.clipnodes32 = (mclipnode32_t *)box_clipnodes32;
else
pm_boxhull.clipnodes16 = (mclipnode16_t *)box_clipnodes16;
return &pm_boxhull;
}
@@ -118,21 +122,10 @@ int GAME_EXPORT PM_HullPointContents( hull_t *hull, int num, const vec3_t p )
if( !hull || !hull->planes ) // fantom bmodels?
return CONTENTS_NONE;
if( world.version == QBSP2_VERSION )
while( num >= 0 )
{
while( num >= 0 )
{
plane = &hull->planes[hull->clipnodes32[num].planenum];
num = hull->clipnodes32[num].children[PlaneDiff( p, plane ) < 0];
}
}
else
{
while( num >= 0 )
{
plane = &hull->planes[hull->clipnodes16[num].planenum];
num = hull->clipnodes16[num].children[PlaneDiff( p, plane ) < 0];
}
plane = &hull->planes[hull->clipnodes[num].planenum];
num = hull->clipnodes[num].children[PlaneDiff( p, plane ) < 0];
}
return num;
}
@@ -200,7 +193,7 @@ PM_RecursiveHullCheck
*/
qboolean PM_RecursiveHullCheck( hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, pmtrace_t *trace )
{
int children[2];
mclipnode_t *node;
mplane_t *plane;
float t1, t2;
float frac, midf;
@@ -233,31 +226,21 @@ loc0:
Host_Error( "%s: bad node number %i\n", __func__, num );
// find the point distances
if( world.version == QBSP2_VERSION )
{
children[0] = hull->clipnodes32[num].children[0];
children[1] = hull->clipnodes32[num].children[1];
plane = hull->planes + hull->clipnodes32[num].planenum;
}
else
{
children[0] = hull->clipnodes16[num].children[0];
children[1] = hull->clipnodes16[num].children[1];
plane = hull->planes + hull->clipnodes16[num].planenum;
}
node = hull->clipnodes + num;
plane = hull->planes + node->planenum;
t1 = PlaneDiff( p1, plane );
t2 = PlaneDiff( p2, plane );
if( t1 >= 0.0f && t2 >= 0.0f )
{
num = children[0];
num = node->children[0];
goto loc0;
}
if( t1 < 0.0f && t2 < 0.0f )
{
num = children[1];
num = node->children[1];
goto loc0;
}
@@ -274,14 +257,14 @@ loc0:
VectorLerp( p1, frac, p2, mid );
// move up to the node
if( !PM_RecursiveHullCheck( hull, children[side], p1f, midf, p1, mid, trace ))
if( !PM_RecursiveHullCheck( hull, node->children[side], p1f, midf, p1, mid, trace ))
return false;
// this recursion can not be optimized because mid would need to be duplicated on a stack
if( PM_HullPointContents( hull, children[side^1], mid ) != CONTENTS_SOLID )
if( PM_HullPointContents( hull, node->children[side^1], mid ) != CONTENTS_SOLID )
{
// go past the node
return PM_RecursiveHullCheck( hull, children[side^1], midf, p2f, mid, p2, trace );
return PM_RecursiveHullCheck( hull, node->children[side^1], midf, p2f, mid, p2, trace );
}
// never got out of the solid area

View File

@@ -89,6 +89,16 @@ void Sound_Shutdown( void )
Mem_FreePool( &host.soundpool );
}
static byte *Sound_Copy( size_t size )
{
byte *out;
out = Mem_Realloc( host.soundpool, sound.tempbuffer, size );
sound.tempbuffer = NULL;
return out;
}
uint GAME_EXPORT Sound_GetApproxWavePlayLen( const char *filepath )
{
string name;
@@ -368,7 +378,6 @@ static qboolean Sound_ResampleInternal( wavdata_t *sc, int outrate, int outwidth
const int inwidth = sc->width;
const int inchannels = sc->channels;
const int incount = sc->samples;
const int insize = sc->size;
qboolean handled = false;
double stepscale;
double t1, t2;
@@ -422,30 +431,22 @@ static qboolean Sound_ResampleInternal( wavdata_t *sc, int outrate, int outwidth
else // upsample case, w/ interpolation
handled = Sound_ConvertUpsample( sc, inwidth, inchannels, incount, outwidth, outchannels, outcount, stepscale );
if( !handled )
{
// restore previously changed data
sc->rate = inrate;
sc->width = inwidth;
sc->channels = inchannels;
sc->samples = incount;
sc->size = insize;
t2 = Sys_DoubleTime();
if( handled )
{
if( t2 - t1 > 0.01f ) // critical, report to mod developer
Con_Printf( S_WARN "%s: from [%d bit %d Hz %dch] to [%d bit %d Hz %dch] (took %.3fs)\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels, t2 - t1 );
else
Con_Reportf( "%s: from [%d bit %d Hz %dch] to [%d bit %d Hz %dch] (took %.3fs)\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels, t2 - t1 );
}
else
Con_Printf( S_ERROR "%s: unsupported from [%d bit %d Hz %dch] to [%d bit %d Hz %dch]\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels );
return false;
}
t2 = Sys_DoubleTime();
sc->rate = outrate;
sc->width = outwidth;
if( t2 - t1 > 0.01f ) // critical, report to mod developer
Con_Printf( S_WARN "%s: from [%d bit %d Hz %dch] to [%d bit %d Hz %dch] (took %.3fs)\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels, t2 - t1 );
else
Con_Reportf( "%s: from [%d bit %d Hz %dch] to [%d bit %d Hz %dch] (took %.3fs)\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels, t2 - t1 );
return true;
return handled;
}
qboolean Sound_Process( wavdata_t **wav, int rate, int width, int channels, uint flags )
@@ -463,11 +464,8 @@ qboolean Sound_Process( wavdata_t **wav, int rate, int width, int channels, uint
if( result )
{
snd = Mem_Realloc( host.soundpool, snd, sizeof( *snd ) + snd->size );
memcpy( snd->buffer, sound.tempbuffer, snd->size );
Mem_Free( sound.tempbuffer );
sound.tempbuffer = NULL;
Mem_Free( snd->buffer ); // free original image buffer
snd->buffer = Sound_Copy( snd->size ); // unzone buffer
}
}

View File

@@ -109,44 +109,44 @@ void Sys_InitLog( void )
// fit to 80 columns for easier read on standard terminal
fputs( "================================================================================\n", s_ld.logfile );
fprintf( s_ld.logfile, "%s (%i, %s, %s, %s-%s)\n", s_ld.title, Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch());
fprintf( s_ld.logfile, "%s (%i, %s, %s, %s-%s)\n", s_ld.title, Q_buildnum(), Q_buildcommit(), Q_buildbranch(), Q_buildos(), Q_buildarch());
fprintf( s_ld.logfile, "Game started at %s\n", Q_timestamp( TIME_FULL ));
fputs( "================================================================================\n", s_ld.logfile );
fflush( s_ld.logfile );
}
}
void Sys_CloseLog( const char *finalmsg )
void Sys_CloseLog( void )
{
Sys_FlushStdout(); // flush to stdout to ensure all data was written
if( !s_ld.logfile )
return;
char event_name[64];
// continue logged
if( !finalmsg )
switch( host.status )
{
switch( host.status )
{
case HOST_CRASHED:
finalmsg = "crashed";
break;
case HOST_ERR_FATAL:
finalmsg = "stopped with error";
break;
default:
finalmsg = "stopped";
break;
}
case HOST_CRASHED:
Q_strncpy( event_name, "crashed", sizeof( event_name ));
break;
case HOST_ERR_FATAL:
Q_strncpy( event_name, "stopped with error", sizeof( event_name ));
break;
default:
if( !host.change_game ) Q_strncpy( event_name, "stopped", sizeof( event_name ));
else Q_strncpy( event_name, host.finalmsg, sizeof( event_name ));
break;
}
fputc( '\n', s_ld.logfile );
fputs( "================================================================================\n", s_ld.logfile );
fprintf( s_ld.logfile, "%s (%i, %s, %s, %s-%s)\n", s_ld.title, Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch());
fprintf( s_ld.logfile, "Stopped with reason \"%s\" at %s\n", finalmsg, Q_timestamp( TIME_FULL ));
fputs( "================================================================================\n", s_ld.logfile );
fclose( s_ld.logfile );
s_ld.logfile = NULL;
Sys_FlushStdout(); // flush to stdout to ensure all data was written
if( s_ld.logfile )
{
fputc( '\n', s_ld.logfile );
fputs( "================================================================================\n", s_ld.logfile );
fprintf( s_ld.logfile, "%s (%i, %s, %s, %s-%s)\n", s_ld.title, Q_buildnum(), Q_buildcommit(), Q_buildbranch(), Q_buildos(), Q_buildarch());
fprintf( s_ld.logfile, "Stopped with reason \"%s\" at %s\n", event_name, Q_timestamp( TIME_FULL ));
fputs( "================================================================================\n", s_ld.logfile );
fclose( s_ld.logfile );
s_ld.logfile = NULL;
}
}
#if XASH_COLORIZE_CONSOLE

View File

@@ -420,12 +420,6 @@ void Sys_Error( const char *error, ... )
_exit->_Exit->asm._exit->_exit
As we do not need atexit(), just throw hidden exception
*/
// Hey, you, making an Emscripten port!
// What if we're not supposed to use exit() on Emscripten and instead we should
// exit from the main() function? Would this fix this bug? Test this case, pls.
#error "Read the comment above"
#include <emscripten.h>
#define exit my_exit
void my_exit(int ret)
@@ -444,11 +438,7 @@ Sys_Quit
void Sys_Quit( const char *reason )
{
Host_ShutdownWithReason( reason );
#if XASH_ANDROID
Host_ExitInMain();
#else
exit( error_on_exit );
#endif
}
/*
@@ -539,7 +529,7 @@ but since engine will be unloaded during this call
it explicitly doesn't use internal allocation or string copy utils
==================
*/
qboolean Sys_NewInstance( const char *gamedir, const char *finalmsg )
qboolean Sys_NewInstance( const char *gamedir )
{
#if XASH_NSWITCH
char newargs[4096];
@@ -550,7 +540,7 @@ qboolean Sys_NewInstance( const char *gamedir, const char *finalmsg )
// just restart the entire thing
printf( "envSetNextLoad exe: `%s`\n", exe );
printf( "envSetNextLoad argv:\n`%s`\n", newargs );
Host_ShutdownWithReason( finalmsg );
Host_ShutdownWithReason( "changing game" );
envSetNextLoad( exe, newargs );
exit( 0 );
#else
@@ -588,7 +578,7 @@ qboolean Sys_NewInstance( const char *gamedir, const char *finalmsg )
#if XASH_PSVITA
// under normal circumstances it's always going to be the same path
exe = strdup( "app0:/eboot.bin" );
Host_ShutdownWithReason( finalmsg );
Host_ShutdownWithReason( "changing game" );
sceAppMgrLoadExec( exe, newargs, NULL );
#else
exelen = wai_getExecutablePath( NULL, 0, NULL );
@@ -596,7 +586,7 @@ qboolean Sys_NewInstance( const char *gamedir, const char *finalmsg )
wai_getExecutablePath( exe, exelen, NULL );
exe[exelen] = 0;
Host_ShutdownWithReason( finalmsg );
Host_ShutdownWithReason( "changing game" );
execv( exe, newargs );
#endif

View File

@@ -41,15 +41,6 @@ NOTE: never change this structure because all dll descriptions in xash code
writes into struct by offsets not names
========================================================================
*/
typedef struct dll_info_s
{
const char *name; // name of library
const dllfunc_t *fcts; // list of dll exports
const size_t num_fcts;
qboolean crash; // crash if dll not found
void *link; // hinstance of loading library
} dll_info_t;
extern int error_on_exit;
double Sys_DoubleTime( void );
char *Sys_GetClipboardData( void );
@@ -65,8 +56,11 @@ void Sys_DebugBreak( void );
qboolean _Sys_GetParmFromCmdLine( const char *parm, char *out, size_t size );
qboolean Sys_GetIntFromCmdLine( const char *parm, int *out );
void Sys_Print( const char *pMsg );
void Sys_PrintLog( const char *pMsg );
void Sys_InitLog( void );
void Sys_CloseLog( void );
void Sys_Quit( const char *reason ) NORETURN;
qboolean Sys_NewInstance( const char *gamedir, const char *finalmsg );
qboolean Sys_NewInstance( const char *gamedir );
void *Sys_GetNativeObject( const char *obj );
//
@@ -74,7 +68,7 @@ void *Sys_GetNativeObject( const char *obj );
//
char *Sys_Input( void );
void Sys_DestroyConsole( void );
void Sys_CloseLog( const char *finalmsg );
void Sys_CloseLog( void );
void Sys_InitLog( void );
void Sys_PrintLog( const char *pMsg );
int Sys_LogFileNo( void );

View File

@@ -68,13 +68,7 @@ extern "C" {
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
#if (_MSC_VER >= 1900)
#include <stdbool.h>
#else
#define bool int
#define false 0
#define true 1
#endif
static int WAI_PREFIX(getModulePath_)(HMODULE module, char* out, int capacity, int* dirname_length)
{
@@ -249,11 +243,6 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
#endif
#endif
#if !defined(WAI_STRINGIZE)
#define WAI_STRINGIZE(s)
#define WAI_STRINGIZE_(s) #s
#endif
#if defined(__ANDROID__) || defined(ANDROID)
#include <fcntl.h>
#include <sys/mman.h>
@@ -276,20 +265,20 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
for (;;)
{
char buffer[128 + PATH_MAX];
uintptr_t low, high;
char buffer[PATH_MAX < 1024 ? 1024 : PATH_MAX];
uint64_t low, high;
char perms[5];
uint64_t offset;
uint32_t major, minor, inode;
char path[PATH_MAX + 1];
uint32_t major, minor;
char path[PATH_MAX];
uint32_t inode;
if (!fgets(buffer, sizeof(buffer), maps))
break;
if (sscanf(buffer, "%" SCNxPTR "-%" SCNxPTR " %s %" SCNx64 " %x:%x %u %" WAI_STRINGIZE(PATH_MAX) "[^\n]\n", &low, &high, perms, &offset, &major, &minor, &inode, path) == 8)
if (sscanf(buffer, "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " %x:%x %u %s\n", &low, &high, perms, &offset, &major, &minor, &inode, path) == 8)
{
void* _addr = WAI_RETURN_ADDRESS();
uintptr_t addr = (uintptr_t)_addr;
uint64_t addr = (uintptr_t)WAI_RETURN_ADDRESS();
if (low <= addr && addr <= high)
{
char* resolved;

View File

@@ -31,8 +31,7 @@ extern "C" {
* @param out destination buffer, optional
* @param capacity destination buffer capacity
* @param dirname_length optional recipient for the length of the dirname part
* of the path. Available only when `capacity` is large enough to retrieve the
* path.
* of the path.
*
* @return the length of the executable path on success (without a terminal NUL
* character), otherwise `-1`
@@ -53,8 +52,7 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length);
* @param out destination buffer, optional
* @param capacity destination buffer capacity
* @param dirname_length optional recipient for the length of the dirname part
* of the path. Available only when `capacity` is large enough to retrieve the
* path.
* of the path.
*
* @return the length of the module path on success (without a terminal NUL
* character), otherwise `-1`

View File

@@ -18,7 +18,7 @@ GNU General Public License for more details.
#include "common.h"
#define MEMHEADER_SENTINEL1 0xA1BAU
#define MEMHEADER_SENTINEL1 0xDEADF00DU
#define MEMHEADER_SENTINEL2 0xDFU
#ifdef XASH_CUSTOM_SWAP
@@ -51,29 +51,31 @@ static void *Q_realloc( void *mem, size_t size )
#define Q_realloc realloc
#endif
// keep this structure as compact as possible while keeping it aligned
// on ILP32 it's 24 bytes, which is aligned to 8 byte boundary
// on LP64 it's 40 bytes, which is also aligned to 8 byte boundary
typedef struct memheader_s
{
struct memheader_s *next, *prev; // next and previous memheaders in chain belonging to pool
const char *filename; // file name and line where Mem_Alloc was called
size_t size; // size of the memory after the header (excluding header and sentinel2)
poolhandle_t poolptr; // pool this memheader belongs to
uint16_t fileline;
uint16_t sentinel1; // must be equal to MEMHEADER_SENTINEL1
struct memheader_s *next; // next and previous memheaders in chain belonging to pool
struct memheader_s *prev;
const char *filename; // file name and line where Mem_Alloc was called
size_t size; // size of the memory after the header (excluding header and sentinel2)
poolhandle_t poolptr; // pool this memheader belongs to
int fileline;
#if !XASH_64BIT
uint32_t pad0; // doesn't have value, only to make Mem_Alloc return aligned addresses on ILP32
#endif
uint32_t sentinel1; // should always be MEMHEADER_SENTINEL1
// immediately followed by data, which is followed by a MEMHEADER_SENTINEL2 byte
} memheader_t;
typedef struct mempool_s
{
struct memheader_s *chain; // chain of individual memory allocations
size_t totalsize; // total memory allocated in this pool (inside memheaders)
size_t realsize; // total memory allocated in this pool (actual malloc total)
size_t lastchecksize; // updated each time the pool is displayed by memlist
const char *filename; // file name and line where Mem_AllocPool was called
int fileline;
char name[64]; // name of the pool
struct memheader_s *chain; // chain of individual memory allocations
size_t totalsize; // total memory allocated in this pool (inside memheaders)
size_t realsize; // total memory allocated in this pool (actual malloc total)
size_t lastchecksize; // updated each time the pool is displayed by memlist
const char *filename; // file name and line where Mem_AllocPool was called
int fileline;
char name[64]; // name of the pool
} mempool_t;
static mempool_t *poolchain = NULL; // critical stuff
@@ -231,7 +233,10 @@ static void Mem_FreeBlock( memheader_t *mem, const char *filename, int fileline
void _Mem_Free( void *data, const char *filename, int fileline )
{
if( data == NULL )
{
Sys_Error( "%s: data == NULL (called at %s:%i)\n", __func__, filename, fileline );
return;
}
Mem_FreeBlock((memheader_t *)((byte *)data - sizeof( memheader_t )), filename, fileline );
}
@@ -516,5 +521,4 @@ Memory_Init
void Memory_Init( void )
{
poolchain = NULL; // init mem chain
poolcount = 0;
}

View File

@@ -16,8 +16,11 @@
#ifndef EDICT_H
#define EDICT_H
#define MAX_ENT_LEAFS_32 24 // Orignally was 16
#define MAX_ENT_LEAFS_16 48
#ifdef SUPPORT_BSP2_FORMAT
#define MAX_ENT_LEAFS 24 // Orignally was 16
#else
#define MAX_ENT_LEAFS 48
#endif
#include "progdefs.h"
@@ -30,12 +33,11 @@ struct edict_s
int headnode; // -1 to use normal leaf check
int num_leafs;
union
{
int leafnums32[MAX_ENT_LEAFS_32];
short leafnums16[MAX_ENT_LEAFS_16];
};
#ifdef SUPPORT_BSP2_FORMAT
int leafnums[MAX_ENT_LEAFS];
#else
short leafnums[MAX_ENT_LEAFS];
#endif
float freetime; // sv.time when the object was freed
void* pvPrivateData; // Alloced and freed by engine, used by DLLs

View File

@@ -1,164 +1,186 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
/***
*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
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.
*/
// taken from Quake-2 source code and modified for GoldSrc compatibility
#ifndef KEYDEFS_H
#define KEYDEFS_H
//
// these are the key numbers that should be passed to Key_Event
// normal keys should be passed as lowercased ascii
//
#define K_TAB 9
#define K_ENTER 13
#define K_ESCAPE 27
#define K_SPACE 32
#define K_SCROLLLOCK 70
#define K_BACKSPACE 127
#define K_UPARROW 128
#define K_DOWNARROW 129
#define K_LEFTARROW 130
#define K_RIGHTARROW 131
#define K_ALT 132
#define K_CTRL 133
#define K_SHIFT 134
#define K_F1 135
#define K_F2 136
#define K_F3 137
#define K_F4 138
#define K_F5 139
#define K_F6 140
#define K_F7 141
#define K_F8 142
#define K_F9 143
#define K_F10 144
#define K_F11 145
#define K_F12 146
#define K_INS 147
#define K_DEL 148
#define K_PGDN 149
#define K_PGUP 150
#define K_HOME 151
#define K_END 152
#define K_TAB 9
#define K_ENTER 13
#define K_ESCAPE 27
#define K_SPACE 32
#define K_SCROLLOCK 70
#define K_KP_HOME 160
#define K_KP_UPARROW 161
#define K_KP_PGUP 162
#define K_KP_LEFTARROW 163
#define K_KP_5 164
// normal keys should be passed as lowercased ascii
#define K_BACKSPACE 127
#define K_UPARROW 128
#define K_DOWNARROW 129
#define K_LEFTARROW 130
#define K_RIGHTARROW 131
#define K_ALT 132
#define K_CTRL 133
#define K_SHIFT 134
#define K_F1 135
#define K_F2 136
#define K_F3 137
#define K_F4 138
#define K_F5 139
#define K_F6 140
#define K_F7 141
#define K_F8 142
#define K_F9 143
#define K_F10 144
#define K_F11 145
#define K_F12 146
#define K_INS 147
#define K_DEL 148
#define K_PGDN 149
#define K_PGUP 150
#define K_HOME 151
#define K_END 152
#define K_KP_HOME 160
#define K_KP_UPARROW 161
#define K_KP_PGUP 162
#define K_KP_LEFTARROW 163
#define K_KP_5 164
#define K_KP_RIGHTARROW 165
#define K_KP_END 166
#define K_KP_DOWNARROW 167
#define K_KP_PGDN 168
#define K_KP_ENTER 169
#define K_KP_INS 170
#define K_KP_DEL 171
#define K_KP_SLASH 172
#define K_KP_MINUS 173
#define K_KP_PLUS 174
#define K_CAPSLOCK 175
#define K_KP_MUL 176
#define K_WIN 177
#define K_KP_NUMLOCK 178
#define K_KP_END 166
#define K_KP_DOWNARROW 167
#define K_KP_PGDN 168
#define K_KP_ENTER 169
#define K_KP_INS 170
#define K_KP_DEL 171
#define K_KP_SLASH 172
#define K_KP_MINUS 173
#define K_KP_PLUS 174
#define K_CAPSLOCK 175
#define K_KP_MUL 176
#define K_WIN 177
#define K_KP_NUMLOCK 178
//
// joystick buttons
//
#define K_JOY1 203
#define K_JOY2 204
#define K_JOY3 205
#define K_JOY4 206
#define K_JOY1 203 // LTRIGGER (L2)
#define K_JOY2 204 // RTRIGGER (R2)
#define K_JOY3 205
#define K_JOY4 206
//
// aux keys are for multi-buttoned joysticks to generate so they can use
// the normal binding process
//
#define K_AUX1 207
#define K_AUX2 208
#define K_AUX3 209
#define K_AUX4 210
#define K_AUX5 211
#define K_AUX6 212
#define K_AUX7 213
#define K_AUX8 214
#define K_AUX9 215
#define K_AUX10 216
#define K_AUX11 217
#define K_AUX12 218
#define K_AUX13 219
#define K_AUX14 220
#define K_AUX15 221
#define K_AUX16 222
#define K_AUX17 223
#define K_AUX18 224
#define K_AUX19 225
#define K_AUX20 226
#define K_AUX21 227
#define K_AUX22 228
#define K_AUX23 229
#define K_AUX24 230
#define K_AUX25 231
#define K_AUX26 232
#define K_AUX27 233
#define K_AUX28 234
#define K_AUX29 235
#define K_AUX30 236
#define K_AUX31 237
#define K_AUX32 238
#define K_AUX1 207
#define K_A_BUTTON K_AUX1
//
// button names for game pads
//
#define K_A_BUTTON K_AUX1
#define K_B_BUTTON K_AUX2
#define K_X_BUTTON K_AUX3
#define K_Y_BUTTON K_AUX4
#define K_L1_BUTTON K_AUX5
#define K_R1_BUTTON K_AUX6
#define K_BACK_BUTTON K_AUX7
#define K_MODE_BUTTON K_AUX8
#define K_START_BUTTON K_AUX9
#define K_LSTICK K_AUX10
#define K_RSTICK K_AUX11
#define K_L2_BUTTON K_AUX12
#define K_R2_BUTTON K_AUX13
#define K_C_BUTTON K_AUX14
#define K_Z_BUTTON K_AUX15
#define K_DPAD_UP K_AUX16
#define K_DPAD_DOWN K_AUX17
#define K_DPAD_LEFT K_AUX18
#define K_DPAD_RIGHT K_AUX19
#define K_MISC_BUTTON K_AUX20
#define K_PADDLE1_BUTTON K_AUX21
#define K_AUX2 208
#define K_B_BUTTON K_AUX2
#define K_AUX3 209
#define K_X_BUTTON K_AUX3
#define K_AUX4 210
#define K_Y_BUTTON K_AUX4
#define K_AUX5 211
#define K_L1_BUTTON K_AUX5
#define K_AUX6 212
#define K_R1_BUTTON K_AUX6
#define K_AUX7 213
#define K_BACK_BUTTON K_AUX7
#define K_AUX8 214
#define K_MODE_BUTTON K_AUX8
#define K_AUX9 215
#define K_START_BUTTON K_AUX9
#define K_AUX10 216
#define K_LSTICK K_AUX10
#define K_AUX11 217
#define K_RSTICK K_AUX11
#define K_AUX12 218
#define K_L2_BUTTON K_AUX12
#define K_AUX13 219
#define K_R2_BUTTON K_AUX13
#define K_AUX14 220
#define K_C_BUTTON K_AUX14
#define K_AUX15 221
#define K_Z_BUTTON K_AUX15
#define K_AUX16 222
#define K_DPAD_UP K_AUX16
#define K_AUX17 223
#define K_DPAD_DOWN K_AUX17
#define K_AUX18 224
#define K_DPAD_LEFT K_AUX18
#define K_AUX19 225
#define K_DPAD_RIGHT K_AUX19
#define K_AUX20 226
#define K_MISC_BUTTON K_AUX20 // Xbox Series X share button, PS5 microphone button, Nintendo Switch Pro capture button
#define K_AUX21 227
#define K_PADDLE1_BUTTON K_AUX21 // Xbox Elite paddle P1-P4
#define K_AUX22 228
#define K_PADDLE2_BUTTON K_AUX22
#define K_AUX23 229
#define K_PADDLE3_BUTTON K_AUX23
#define K_AUX24 230
#define K_PADDLE4_BUTTON K_AUX24
#define K_TOUCHPAD K_AUX25
#define K_AUX25 231
#define K_TOUCHPAD K_AUX25 // PS4/PS5 touchpad button
#define K_AUX26 232
#define K_AUX27 233
#define K_AUX28 234
#define K_AUX29 235
#define K_AUX30 236
#define K_AUX31 237
#define K_AUX32 238
#define K_MWHEELDOWN 239
#define K_MWHEELUP 240
#define K_PAUSE 255
//
// mouse buttons generate virtual keys
//
#define K_MWHEELDOWN 239
#define K_MWHEELUP 240
#define K_MOUSE1 241
#define K_MOUSE2 242
#define K_MOUSE3 243
#define K_MOUSE4 244
#define K_MOUSE5 245
#define K_MOUSE1 241
#define K_MOUSE2 242
#define K_MOUSE3 243
#define K_MOUSE4 244
#define K_MOUSE5 245
#define K_PAUSE 255
#endif//KEYDEFS_H

View File

@@ -32,7 +32,7 @@
#include <android/log.h>
#include "linker.h"
static const Elf_Sym *soinfo_elf_lookup( const struct soinfo *si, unsigned hash, const char *name )
static const Elf_Sym *soinfo_elf_lookup( const soinfo *si, unsigned hash, const char *name )
{
const Elf_Sym *symtab = si->symtab;
const char *strtab = si->strtab;
@@ -87,14 +87,14 @@ static unsigned elfhash( const unsigned char *name )
Binary Interface) where in Chapter 5 it discuss resolving "Shared
Object Dependencies" in breadth first search order.
*/
static const Elf_Sym *dlsym_handle_lookup( const struct soinfo *si, const char *name )
static const Elf_Sym *dlsym_handle_lookup( const soinfo *si, const char *name )
{
return soinfo_elf_lookup( si, elfhash((const unsigned char *)name ), name );
}
void *dlsym_weak( void *handle, const char *symbol )
extern "C" void *dlsym_weak( void *handle, const char *symbol )
{
const struct soinfo *found = (struct soinfo *)handle;
const soinfo *found = (soinfo *)handle;
const Elf_Sym *sym = dlsym_handle_lookup( found, symbol );
if( sym != NULL )

View File

@@ -31,8 +31,10 @@
#include <unistd.h>
#include <sys/types.h>
#include <stdbool.h>
// #include <elf.h>
#include <linux/elf.h>
// #include <sys/exec_elf.h>
// #include <link.h>
// a1ba: we don't really need custom linker on Android 64, because
// it's only intended to workaround bug which persist on Android < 4.4
@@ -67,8 +69,8 @@ struct link_map_t {
uintptr_t l_addr;
char *l_name;
uintptr_t l_ld;
struct link_map_t *l_next;
struct link_map_t *l_prev;
link_map_t *l_next;
link_map_t *l_prev;
};
// Values for r_debug->state
@@ -83,7 +85,7 @@ enum {
#define SOINFO_NAME_LEN 128
typedef void (*linker_function_t)( void );
typedef void (*linker_function_t)();
// Android uses REL for 32-bit but only uses RELA for 64-bit.
#if defined( __LP64__ )
@@ -91,6 +93,7 @@ typedef void (*linker_function_t)( void );
#endif
struct soinfo {
public:
char name[SOINFO_NAME_LEN];
const Elf_Phdr *phdr;
size_t phnum;
@@ -109,7 +112,7 @@ struct soinfo {
uint32_t unused3; // DO NOT USE, maintained for compatibility
#endif
struct soinfo *next;
soinfo *next;
unsigned flags;
const char *strtab;
@@ -161,8 +164,8 @@ struct soinfo {
unsigned mips_gotsym;
#endif
size_t ref_count;
struct link_map_t link_map;
size_t ref_count;
link_map_t link_map;
bool constructors_called;
@@ -174,6 +177,14 @@ struct soinfo {
bool has_text_relocations;
#endif
bool has_DT_SYMBOLIC;
void CallConstructors();
void CallDestructors();
void CallPreInitConstructors();
private:
void CallArray( const char *array_name, linker_function_t *functions, size_t count, bool reverse );
void CallFunction( const char *function_name, linker_function_t function );
};
#endif

View File

@@ -91,6 +91,11 @@ void GAME_EXPORT Platform_SetMousePos(int x, int y)
}
int Platform_JoyInit( int numjoy )
{
return 0;
}
void Platform_EnableTextInput( qboolean enable )
{
keystate.chars = enable;

View File

@@ -184,7 +184,7 @@ qboolean SNDDMA_Init( void )
return false;
}
dma.buffer = Mem_Malloc( sndpool, samples * 2 ); //allocate pcm frame buffer
dma.buffer = Z_Malloc( samples * 2 ); //allocate pcm frame buffer
dma.samplepos = 0;
dma.samples = samples;
dma.format.width = 2;

View File

@@ -281,8 +281,13 @@ void GAME_EXPORT Platform_SetMousePos(int x, int y)
}
void Platform_Vibrate( float life, char flags )
void Platform_Vibrate(float life, char flags)
{
}
int Platform_JoyInit( int numjoy )
{
return 0;
}
#endif

View File

@@ -55,7 +55,7 @@ char *Posix_Input( void );
#endif
#if XASH_SDL
void SDLash_Init( const char *basedir );
void SDLash_Init( void );
void SDLash_Shutdown( void );
#endif
@@ -104,7 +104,7 @@ void Linux_SetTimer( float time );
int Linux_GetProcessID( void );
#endif
static inline void Platform_Init( qboolean con_showalways, const char *basedir )
static inline void Platform_Init( qboolean con_showalways )
{
#if XASH_POSIX
// daemonize as early as possible, because we need to close our file descriptors
@@ -112,7 +112,7 @@ static inline void Platform_Init( qboolean con_showalways, const char *basedir )
#endif
#if XASH_SDL
SDLash_Init( basedir );
SDLash_Init( );
#endif
#if XASH_ANDROID
@@ -178,7 +178,7 @@ static inline void Platform_Sleep( int msec )
#endif
}
#if XASH_WIN32 || XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD || XASH_ANDROID || XASH_LINUX || XASH_APPLE
#if XASH_WIN32 || XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD || XASH_ANDROID || XASH_LINUX
void Sys_SetupCrashHandler( void );
void Sys_RestoreCrashHandler( void );
#else
@@ -199,8 +199,7 @@ static inline void Sys_RestoreCrashHandler( void )
==============================================================================
*/
void Platform_Vibrate( float life, char flags ); // left for compatibility
void Platform_Vibrate2( float time, int low_freq, int high_freq, uint flags );
void Platform_Vibrate( float life, char flags );
/*
==============================================================================
@@ -210,27 +209,7 @@ void Platform_Vibrate2( float time, int low_freq, int high_freq, uint flags );
==============================================================================
*/
// Gamepad support
#if XASH_SDL
int Platform_JoyInit( void ); // returns number of connected gamepads, negative if error
void Platform_JoyShutdown( void );
void Platform_CalibrateGamepadGyro( void );
#else
static inline int Platform_JoyInit( void )
{
return 0;
}
static inline void Platform_JoyShutdown( void )
{
}
static inline void Platform_CalibrateGamepadGyro( void )
{
}
#endif
int Platform_JoyInit( int numjoy ); // returns number of connected gamepads, negative if error
// Text input
void Platform_EnableTextInput( qboolean enable );
key_modifier_t Platform_GetKeyModifiers( void );

View File

@@ -1,85 +0,0 @@
/*
crashhandler.c - advanced crashhandler
Copyright (C) 2016 Mittorn
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 3 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.
*/
// on Glibc (which potentially might not be only Linux) systems we
// have backtrace() and backtrace_symbols() calls, which replace for us
// platform-specific code
#if HAVE_EXECINFO
#include "common.h"
#include <execinfo.h>
#include <signal.h>
void Sys_Crash( int signal, siginfo_t *si, void *context )
{
char message[8192];
int len, logfd, i = 0;
int size;
void *addrs[16];
char **syms;
// safe actions first, stack and memory may be corrupted
len = Q_snprintf( message, sizeof( message ), "Ver: " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s, %s-%s)\n",
Q_buildnum(), g_buildcommit, Q_buildos(), Q_buildarch() );
#if !XASH_FREEBSD && !XASH_NETBSD && !XASH_OPENBSD && !XASH_APPLE // they don't have si_ptr
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p %p\n", signal, si->si_errno, si->si_code, si->si_addr, si->si_ptr );
#else
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p\n", signal, si->si_errno, si->si_code, si->si_addr );
#endif
write( STDERR_FILENO, message, len );
// flush buffers before writing directly to descriptors
fflush( stdout );
fflush( stderr );
// now get log fd and write trace directly to log
logfd = Sys_LogFileNo();
write( logfd, message, len );
size = backtrace( addrs, sizeof( addrs ) / sizeof( addrs[0] ));
syms = backtrace_symbols( addrs, size );
for( i = 0; i < size && syms; i++ )
{
size_t symlen = Q_strlen( syms[i] );
char ch = '\n';
write( logfd, syms[i], symlen );
write( logfd, &ch, 1 );
write( STDERR_FILENO, syms[i], symlen );
write( STDERR_FILENO, &ch, 1 );
len += Q_snprintf( message + len, sizeof( message ) - len, "%2d: %s\n", i, syms[i] );
}
// put MessageBox as Sys_Error
Msg( "%s\n", message );
#ifdef XASH_SDL
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
#endif
host.crashed = true;
Platform_MessageBox( "Xash Error", message, false );
// log saved, now we can try to save configs and close log correctly, it may crash
if( host.type == HOST_NORMAL )
CL_Crashed();
host.status = HOST_CRASHED;
Sys_Quit( "crashed" );
}
#endif // HAVE_EXECINFO

View File

@@ -18,8 +18,7 @@ GNU General Public License for more details.
// while this is mostly POSIX-compatible functions
// the contents of ucontext_t is platform-dependent
// before adding new OS here, check platform.h
#define _XOPEN_SOURCE 1 // required for ucontext
#if XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD || XASH_ANDROID || XASH_LINUX || XASH_APPLE
#if XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD || XASH_ANDROID || XASH_LINUX
#ifndef XASH_OPENBSD
#include <ucontext.h>
#endif
@@ -27,11 +26,6 @@ GNU General Public License for more details.
#include <sys/mman.h>
#include "library.h"
void Sys_Crash( int signal, siginfo_t *si, void *context );
static struct sigaction oldFilter;
#if !HAVE_EXECINFO
#define STACK_BACKTRACE_STR "Stack backtrace:\n"
#define STACK_DUMP_STR "Stack dump:\n"
@@ -39,6 +33,8 @@ static struct sigaction oldFilter;
#define STACK_DUMP_STR_LEN ( sizeof( STACK_DUMP_STR ) - 1 )
#define ALIGN( x, y ) (((uintptr_t) ( x ) + (( y ) - 1 )) & ~(( y ) - 1 ))
static struct sigaction oldFilter;
static int Sys_PrintFrame( char *buf, int len, int i, void *addr )
{
Dl_info dlinfo;
@@ -57,7 +53,7 @@ static int Sys_PrintFrame( char *buf, int len, int i, void *addr )
return Q_snprintf( buf, len, "%2d: %p\n", i, addr ); // print only address
}
void Sys_Crash( int signal, siginfo_t *si, void *context )
static void Sys_Crash( int signal, siginfo_t *si, void *context)
{
void *pc = NULL, **bp = NULL, **sp = NULL; // this must be set for every OS!
char message[8192];
@@ -117,9 +113,9 @@ void Sys_Crash( int signal, siginfo_t *si, void *context )
// safe actions first, stack and memory may be corrupted
len = Q_snprintf( message, sizeof( message ), "Ver: " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s, %s-%s)\n",
Q_buildnum(), g_buildcommit, Q_buildos(), Q_buildarch() );
Q_buildnum(), Q_buildcommit(), Q_buildos(), Q_buildarch() );
#if !XASH_FREEBSD && !XASH_NETBSD && !XASH_OPENBSD && !XASH_APPLE
#if !XASH_FREEBSD && !XASH_NETBSD && !XASH_OPENBSD
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p %p\n", signal, si->si_errno, si->si_code, si->si_addr, si->si_ptr );
#else
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p\n", signal, si->si_errno, si->si_code, si->si_addr );
@@ -204,8 +200,6 @@ void Sys_Crash( int signal, siginfo_t *si, void *context )
Sys_Quit( "crashed" );
}
#endif // !HAVE_EXECINFO
void Sys_SetupCrashHandler( void )
{
struct sigaction act = { 0 };

View File

@@ -88,8 +88,52 @@ GNU General Public License for more details.
#define SDL_SCANCODE_PRINTSCREEN SDLK_PRINT
#define SDL_SCANCODE_UNKNOWN SDLK_UNKNOWN
#define SDL_GetScancodeName( x ) "unknown"
#define SDL_JoystickID Uint8
#endif
static int SDLash_GameControllerButtonMapping[] =
{
#if XASH_NSWITCH // devkitPro/SDL has inverted Nintendo layout for SDL_GameController
K_B_BUTTON, K_A_BUTTON, K_Y_BUTTON, K_X_BUTTON,
#else
K_A_BUTTON, K_B_BUTTON, K_X_BUTTON, K_Y_BUTTON,
#endif
K_BACK_BUTTON, K_MODE_BUTTON, K_START_BUTTON,
K_LSTICK, K_RSTICK,
K_L1_BUTTON, K_R1_BUTTON,
K_DPAD_UP, K_DPAD_DOWN, K_DPAD_LEFT, K_DPAD_RIGHT,
K_MISC_BUTTON,
K_PADDLE1_BUTTON, K_PADDLE2_BUTTON, K_PADDLE3_BUTTON, K_PADDLE4_BUTTON,
K_TOUCHPAD,
};
// Swap axis to follow default axis binding:
// LeftX, LeftY, RightX, RightY, TriggerRight, TriggerLeft
static int SDLash_GameControllerAxisMapping[] =
{
JOY_AXIS_SIDE, // SDL_CONTROLLER_AXIS_LEFTX,
JOY_AXIS_FWD, // SDL_CONTROLLER_AXIS_LEFTY,
JOY_AXIS_PITCH, // SDL_CONTROLLER_AXIS_RIGHTX,
JOY_AXIS_YAW, // SDL_CONTROLLER_AXIS_RIGHTY,
JOY_AXIS_LT, // SDL_CONTROLLER_AXIS_TRIGGERLEFT,
JOY_AXIS_RT, // SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
};
static qboolean SDLash_IsInstanceIDAGameController( SDL_JoystickID joyId )
{
#if !SDL_VERSION_ATLEAST( 2, 0, 4 )
// HACKHACK: if we're not initialized g_joy, then we're probably using gamecontroller api
// so return true
if( !g_joy )
return true;
return false;
#else
if( SDL_GameControllerFromInstanceID( joyId ) != NULL )
return true;
return false;
#endif
}
/*
=============
SDLash_KeyEvent
@@ -221,7 +265,7 @@ static void SDLash_KeyEvent( SDL_KeyboardEvent key )
break;
}
case SDL_SCANCODE_PAUSE: keynum = K_PAUSE; break;
case SDL_SCANCODE_SCROLLLOCK: keynum = K_SCROLLLOCK; break;
case SDL_SCANCODE_SCROLLLOCK: keynum = K_SCROLLOCK; break;
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
case SDL_SCANCODE_APPLICATION: keynum = K_WIN; break; // (compose key) ???
// don't console spam on known functional buttons, not used in engine
@@ -364,6 +408,50 @@ static void SDLash_ActiveEvent( int gain )
}
}
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
static size_t num_open_game_controllers = 0;
static void SDLash_GameController_Add( int index )
{
extern convar_t joy_enable; // private to input system
SDL_GameController *controller;
if( !joy_enable.value )
return;
controller = SDL_GameControllerOpen( index );
if( !controller )
{
Con_Reportf( "Failed to open SDL GameController %d: %s\n", index, SDL_GetError( ) );
SDL_ClearError( );
return;
}
#if SDL_VERSION_ATLEAST( 2, 0, 6 )
Con_Reportf( "Added controller: %s (%i:%i:%i)\n",
SDL_GameControllerName( controller ),
SDL_GameControllerGetVendor( controller ),
SDL_GameControllerGetProduct( controller ),
SDL_GameControllerGetProductVersion( controller ));
#endif // SDL_VERSION_ATLEAST( 2, 0, 6 )
++num_open_game_controllers;
if( num_open_game_controllers == 1 )
Joy_AddEvent( );
}
static void SDLash_GameController_Remove( SDL_JoystickID joystick_id )
{
Con_Reportf( "Removed controller %i\n", joystick_id );
// `Joy_RemoveEvent` sets `joy_found` to `0`.
// We only want to do this when all the game controllers have been removed.
--num_open_game_controllers;
if( num_open_game_controllers == 0 )
Joy_RemoveEvent( );
}
#endif
/*
=============
SDLash_EventFilter
@@ -391,6 +479,28 @@ static void SDLash_EventHandler( SDL_Event *event )
SDLash_KeyEvent( event->key );
break;
/* Joystick events */
case SDL_JOYAXISMOTION:
if ( !SDLash_IsInstanceIDAGameController( event->jaxis.which ))
Joy_AxisMotionEvent( event->jaxis.axis, event->jaxis.value );
break;
case SDL_JOYBALLMOTION:
if ( !SDLash_IsInstanceIDAGameController( event->jball.which ))
Joy_BallMotionEvent( event->jball.ball, event->jball.xrel, event->jball.yrel );
break;
case SDL_JOYHATMOTION:
if ( !SDLash_IsInstanceIDAGameController( event->jhat.which ))
Joy_HatMotionEvent( event->jhat.hat, event->jhat.value );
break;
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
if ( !SDLash_IsInstanceIDAGameController( event->jbutton.which ))
Joy_ButtonEvent( event->jbutton.button, event->jbutton.state );
break;
case SDL_QUIT:
Sys_Quit( "caught SDL_QUIT" );
break;
@@ -458,17 +568,46 @@ static void SDLash_EventHandler( SDL_Event *event )
SDLash_InputEvent( event->text );
break;
case SDL_JOYDEVICEADDED:
Joy_AddEvent();
break;
case SDL_JOYDEVICEREMOVED:
Joy_RemoveEvent();
break;
/* GameController API */
case SDL_CONTROLLERAXISMOTION:
{
if( !Joy_IsActive( ))
break;
if( event->caxis.axis >= 0 && event->caxis.axis < ARRAYSIZE( SDLash_GameControllerAxisMapping ))
{
Joy_KnownAxisMotionEvent( SDLash_GameControllerAxisMapping[event->caxis.axis], event->caxis.value );
}
break;
}
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
{
if( !Joy_IsActive( ))
break;
// TODO: Use joyinput funcs, for future multiple gamepads support
if( event->cbutton.button >= 0 && event->cbutton.button < ARRAYSIZE( SDLash_GameControllerButtonMapping ))
{
Key_Event( SDLash_GameControllerButtonMapping[event->cbutton.button], event->cbutton.state );
}
break;
}
case SDL_CONTROLLERDEVICEADDED:
SDLash_GameController_Add( event->cdevice.which );
break;
case SDL_CONTROLLERDEVICEREMOVED:
case SDL_CONTROLLERTOUCHPADDOWN:
case SDL_CONTROLLERTOUCHPADMOTION:
case SDL_CONTROLLERTOUCHPADUP:
case SDL_CONTROLLERSENSORUPDATE:
SDLash_HandleGameControllerEvent( event );
SDLash_GameController_Remove( event->cdevice.which );
break;
case SDL_WINDOWEVENT:

View File

@@ -28,16 +28,14 @@ void GL_InitExtensions( void );
qboolean GL_DeleteContext( void );
void VID_SaveWindowSize( int width, int height, qboolean maximized );
// joystick events
extern SDL_Joystick *g_joy;
//
// in_sdl.c
//
void SDLash_InitCursors( void );
void SDLash_FreeCursors( void );
//
// joy_sdl.c
//
void SDLash_HandleGameControllerEvent( SDL_Event *ev );
#endif // XASH_SDL
#endif // KEYWRAPPER_H

View File

@@ -1,6 +1,6 @@
/*
in_sdl.c - SDL input component
Copyright (C) 2018-2025 a1batross
vid_sdl.c - SDL input component
Copyright (C) 2018 a1batross
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
@@ -12,6 +12,7 @@ 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.
*/
#if !XASH_DEDICATED
#include <SDL.h>
#include "common.h"
@@ -23,6 +24,7 @@ GNU General Public License for more details.
#include "sound.h"
#include "vid_common.h"
SDL_Joystick *g_joy = NULL;
#if !SDL_VERSION_ATLEAST( 2, 0, 0 )
#define SDL_WarpMouseInWindow( win, x, y ) SDL_WarpMouse( ( x ), ( y ) )
#else
@@ -124,6 +126,20 @@ void Platform_SetClipboardText( const char *buffer )
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
}
/*
=============
Platform_Vibrate
=============
*/
void Platform_Vibrate( float time, char flags )
{
#if SDL_VERSION_ATLEAST( 2, 0, 9 )
if( g_joy )
SDL_JoystickRumble( g_joy, 0xFFFF, 0xFFFF, time * 1000.0f );
#endif // SDL_VERSION_ATLEAST( 2, 0, 9 )
}
#if !XASH_PSVITA
/*
@@ -141,6 +157,120 @@ void Platform_EnableTextInput( qboolean enable )
#endif // !XASH_PSVITA
/*
=============
SDLash_JoyInit_Old
=============
*/
static int SDLash_JoyInit_Old( int numjoy )
{
int num;
int i;
Con_Reportf( "Joystick: SDL\n" );
if( SDL_WasInit( SDL_INIT_JOYSTICK ) != SDL_INIT_JOYSTICK &&
SDL_InitSubSystem( SDL_INIT_JOYSTICK ) )
{
Con_Reportf( "Failed to initialize SDL Joysitck: %s\n", SDL_GetError() );
return 0;
}
if( g_joy )
{
SDL_JoystickClose( g_joy );
}
num = SDL_NumJoysticks();
if( num > 0 )
Con_Reportf( "%i joysticks found:\n", num );
else
{
Con_Reportf( "No joystick found.\n" );
return 0;
}
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
for( i = 0; i < num; i++ )
Con_Reportf( "%i\t: %s\n", i, SDL_JoystickNameForIndex( i ) );
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
Con_Reportf( "Pass +set joy_index N to command line, where N is number, to select active joystick\n" );
g_joy = SDL_JoystickOpen( numjoy );
if( !g_joy )
{
Con_Reportf( "Failed to select joystick: %s\n", SDL_GetError( ) );
return 0;
}
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
Con_Reportf( "Selected joystick: %s\n"
"\tAxes: %i\n"
"\tHats: %i\n"
"\tButtons: %i\n"
"\tBalls: %i\n",
SDL_JoystickName( g_joy ), SDL_JoystickNumAxes( g_joy ), SDL_JoystickNumHats( g_joy ),
SDL_JoystickNumButtons( g_joy ), SDL_JoystickNumBalls( g_joy ) );
SDL_GameControllerEventState( SDL_DISABLE );
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
SDL_JoystickEventState( SDL_ENABLE );
return num;
}
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
/*
=============
SDLash_JoyInit_New
=============
*/
static int SDLash_JoyInit_New( int numjoy )
{
int count, numJoysticks, i;
Con_Reportf( "Joystick: SDL GameController API\n" );
if( SDL_WasInit( SDL_INIT_GAMECONTROLLER ) != SDL_INIT_GAMECONTROLLER &&
SDL_InitSubSystem( SDL_INIT_GAMECONTROLLER ) )
{
Con_Reportf( "Failed to initialize SDL GameController API: %s\n", SDL_GetError() );
return 0;
}
SDL_GameControllerAddMappingsFromFile( "controllermappings.txt" );
count = 0;
numJoysticks = SDL_NumJoysticks();
for ( i = 0; i < numJoysticks; i++ )
if( SDL_IsGameController( i ) )
++count;
return count;
}
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
/*
=============
Platform_JoyInit
=============
*/
int Platform_JoyInit( int numjoy )
{
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
// SDL_Joystick is now an old API
// SDL_GameController is preferred
if( !Sys_CheckParm( "-sdl_joy_old_api" ) )
return SDLash_JoyInit_New(numjoy);
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
return SDLash_JoyInit_Old(numjoy);
}
/*
========================
SDLash_InitCursors
@@ -288,3 +418,5 @@ key_modifier_t Platform_GetKeyModifiers( void )
return KeyModifier_None;
#endif
}
#endif // XASH_DEDICATED

View File

@@ -1,391 +0,0 @@
/*
joy_sdl.c - SDL gamepads
Copyright (C) 2018-2025 a1batross
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 3 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.
*/
#include <SDL.h>
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
#include "common.h"
#include "keydefs.h"
#include "input.h"
#include "client.h"
#include "events.h"
static const int g_button_mapping[] =
{
#if XASH_NSWITCH // devkitPro/SDL has inverted Nintendo layout for SDL_GameController
K_B_BUTTON, K_A_BUTTON, K_Y_BUTTON, K_X_BUTTON,
#else
K_A_BUTTON, K_B_BUTTON, K_X_BUTTON, K_Y_BUTTON,
#endif
K_BACK_BUTTON, K_MODE_BUTTON, K_START_BUTTON,
K_LSTICK, K_RSTICK,
K_L1_BUTTON, K_R1_BUTTON,
K_DPAD_UP, K_DPAD_DOWN, K_DPAD_LEFT, K_DPAD_RIGHT,
K_MISC_BUTTON,
K_PADDLE1_BUTTON, K_PADDLE2_BUTTON, K_PADDLE3_BUTTON, K_PADDLE4_BUTTON,
K_TOUCHPAD,
};
// Swap axis to follow default axis binding:
static const engineAxis_t g_axis_mapping[] =
{
JOY_AXIS_SIDE, // SDL_CONTROLLER_AXIS_LEFTX,
JOY_AXIS_FWD, // SDL_CONTROLLER_AXIS_LEFTY,
JOY_AXIS_PITCH, // SDL_CONTROLLER_AXIS_RIGHTX,
JOY_AXIS_YAW, // SDL_CONTROLLER_AXIS_RIGHTY,
JOY_AXIS_LT, // SDL_CONTROLLER_AXIS_TRIGGERLEFT,
JOY_AXIS_RT, // SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
};
static SDL_JoystickID g_current_gamepad_id = -1; // used to send rumble to
static SDL_GameController *g_current_gamepad;
static SDL_GameController **g_gamepads;
static size_t g_num_gamepads;
#define CALIBRATION_TIME 10.0f
static struct
{
float time;
vec3_t data;
vec3_t calibrated_values;
int samples;
} gyrocal;
static void SDLash_RestartCalibration( void )
{
Joy_SetCalibrationState( JOY_NOT_CALIBRATED );
memset( &gyrocal, 0, sizeof( gyrocal ));
gyrocal.time = host.realtime + CALIBRATION_TIME;
Con_Printf( "Starting gyroscope calibration...\n" );
}
static void SDLash_FinalizeCalibration( void )
{
float data_rate = 10.0f; // let's say we're polling at 10Hz?
int min_samples;
#if SDL_VERSION_ATLEAST( 2, 0, 16 )
data_rate = SDL_GameControllerGetSensorDataRate( g_current_gamepad, SDL_SENSOR_GYRO );
if( !data_rate )
data_rate = 10.0f;
#endif
min_samples = Q_rint( CALIBRATION_TIME * data_rate * 0.75f );
// we waited for few seconds and got too few samples
if( gyrocal.samples <= min_samples )
{
Joy_SetCalibrationState( JOY_FAILED_TO_CALIBRATE );
return;
}
VectorScale( gyrocal.data, 1.0f / gyrocal.samples, gyrocal.calibrated_values );
Joy_SetCalibrationState( JOY_CALIBRATED );
Con_Printf( "Calibration done. Result: %f %f %f\n", gyrocal.calibrated_values[0], gyrocal.calibrated_values[1], gyrocal.calibrated_values[2] );
gyrocal.time = 0.0f;
}
static void SDLash_GameControllerAddMappings( const char *name )
{
fs_offset_t len = 0;
byte *p = FS_LoadFile( name, &len, false );
if( !p )
return;
if( len > 0 && len < INT32_MAX ) // function accepts int, SDL3 fixes this
{
SDL_RWops *rwops = SDL_RWFromConstMem( p, (int)len );
SDL_GameControllerAddMappingsFromRW( rwops, true );
}
Mem_Free( p );
}
static void SDLash_SetActiveGameController( SDL_JoystickID id )
{
SDL_GameController *oldgc;
if( g_current_gamepad_id == id )
return;
g_current_gamepad_id = id;
oldgc = g_current_gamepad;
#if SDL_VERSION_ATLEAST( 2, 0, 14 )
SDL_GameControllerSetSensorEnabled( oldgc, SDL_SENSOR_GYRO, SDL_FALSE );
#endif // SDL_VERSION_ATLEAST( 2, 0, 14 )
if( id < 0 )
{
g_current_gamepad = NULL;
Joy_SetCapabilities( false );
Joy_SetCalibrationState( JOY_NOT_CALIBRATED );
}
else
{
qboolean have_gyro = false;
g_current_gamepad = SDL_GameControllerFromInstanceID( id );
#if SDL_VERSION_ATLEAST( 2, 0, 14 )
have_gyro = SDL_GameControllerHasSensor( g_current_gamepad, SDL_SENSOR_GYRO );
if( have_gyro )
{
SDL_GameControllerSetSensorEnabled( g_current_gamepad, SDL_SENSOR_GYRO, SDL_TRUE );
SDLash_RestartCalibration();
}
#endif // SDL_VERSION_ATLEAST( 2, 0, 14 )
Joy_SetCapabilities( have_gyro );
}
}
static void SDLash_GameControllerAdded( int device_index )
{
SDL_GameController *gc;
SDL_GameController **list;
gc = SDL_GameControllerOpen( device_index );
if( !gc )
{
Con_Printf( S_ERROR "SDL_GameControllerOpen: %s\n", SDL_GetError( ));
return;
}
list = Mem_Realloc( host.mempool, g_gamepads, sizeof( *list ) * ( g_num_gamepads + 1 ));
list[g_num_gamepads++] = gc;
g_gamepads = list;
// set as current device if none other set
if( g_current_gamepad_id < 0 )
{
SDL_Joystick *joy = SDL_GameControllerGetJoystick( gc );
if( joy )
SDLash_SetActiveGameController( SDL_JoystickInstanceID( joy ));
}
Con_Printf( "Detected \"%s\" game controller.\nMapping string: %s\n", SDL_GameControllerName( gc ), SDL_GameControllerMapping( gc ));
}
static void SDLash_GameControllerRemoved( SDL_JoystickID id )
{
size_t i;
if( id == g_current_gamepad_id )
SDLash_SetActiveGameController( -1 );
// now close the device
for( i = 0; i < g_num_gamepads; i++ )
{
SDL_GameController *gc = g_gamepads[i];
SDL_Joystick *joy;
if( !gc )
continue;
joy = SDL_GameControllerGetJoystick( gc );
if( !joy )
continue;
if( SDL_JoystickInstanceID( joy ) == id )
{
Con_Printf( "Game controller \"%s\" was disconnected\n", SDL_GameControllerName( gc ));
SDL_GameControllerClose( gc );
g_gamepads[i] = NULL;
}
}
}
static void SDLash_GameControllerSensorUpdate( SDL_ControllerSensorEvent sensor )
{
vec3_t data;
if( sensor.which != g_current_gamepad_id )
return;
if( sensor.sensor != SDL_SENSOR_GYRO )
return;
if( gyrocal.time != 0.0f )
{
if( host.realtime > gyrocal.time )
SDLash_FinalizeCalibration();
VectorAdd( gyrocal.data, sensor.data, gyrocal.data );
gyrocal.samples++;
Joy_SetCalibrationState( JOY_CALIBRATING );
return;
}
VectorSubtract( sensor.data, gyrocal.calibrated_values, data );
Joy_GyroEvent( data );
}
void SDLash_HandleGameControllerEvent( SDL_Event *ev )
{
int x;
switch( ev->type )
{
case SDL_CONTROLLERAXISMOTION:
SDLash_SetActiveGameController( ev->caxis.which );
x = ev->caxis.axis;
if( x >= 0 && x < ARRAYSIZE( g_axis_mapping ))
Joy_AxisMotionEvent( g_axis_mapping[x], ev->caxis.value );
break;
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
SDLash_SetActiveGameController( ev->cbutton.which );
x = ev->cbutton.button;
if( x >= 0 && x < ARRAYSIZE( g_button_mapping ))
Key_Event( g_button_mapping[x], ev->cbutton.state );
break;
case SDL_CONTROLLERDEVICEREMOVED:
SDLash_GameControllerRemoved( ev->cdevice.which );
break;
case SDL_CONTROLLERDEVICEADDED:
SDLash_GameControllerAdded( ev->cdevice.which );
break;
#if SDL_VERSION_ATLEAST( 2, 0, 14 )
case SDL_CONTROLLERSENSORUPDATE:
SDLash_GameControllerSensorUpdate( ev->csensor );
break;
#endif
}
}
void Platform_CalibrateGamepadGyro( void )
{
SDLash_RestartCalibration();
}
void Platform_Vibrate2( float time, int val1, int val2, uint flags )
{
#if SDL_VERSION_ATLEAST( 2, 0, 9 )
SDL_GameController *gc = g_current_gamepad;
Uint32 ms;
if( g_current_gamepad_id < 0 || !gc )
return;
if( val1 < 0 )
val1 = COM_RandomLong( 0x7FFF, 0xFFFF );
if( val2 < 0 )
val2 = COM_RandomLong( 0x7FFF, 0xFFFF );
ms = (Uint32)ceil( time );
SDL_GameControllerRumble( gc, val1, val2, ms );
#endif // SDL_VERSION_ATLEAST( 2, 0, 9 )
}
/*
=============
Platform_Vibrate
=============
*/
void Platform_Vibrate( float time, char flags )
{
Platform_Vibrate2( time, -1, -1, flags );
}
/*
=============
Platform_JoyInit
=============
*/
int Platform_JoyInit( void )
{
int count, numJoysticks, i;
Con_Reportf( "Joystick: SDL GameController API\n" );
if( SDL_WasInit( SDL_INIT_GAMECONTROLLER ) != SDL_INIT_GAMECONTROLLER &&
SDL_InitSubSystem( SDL_INIT_GAMECONTROLLER ))
{
Con_Reportf( "Failed to initialize SDL GameController API: %s\n", SDL_GetError( ));
return 0;
}
SDLash_GameControllerAddMappings( "gamecontrollerdb.txt" ); // shipped in extras.pk3
SDLash_GameControllerAddMappings( "controllermappings.txt" );
count = 0;
numJoysticks = SDL_NumJoysticks();
for ( i = 0; i < numJoysticks; i++ )
{
if( SDL_IsGameController( i ))
++count;
}
return count;
}
/*
=============
Platform_JoyShutdown
=============
*/
void Platform_JoyShutdown( void )
{
size_t i;
SDLash_SetActiveGameController( -1 );
for( i = 0; i < g_num_gamepads; i++ )
{
if( !g_gamepads[i] )
continue;
SDL_GameControllerClose( g_gamepads[i] );
g_gamepads[i] = NULL;
}
Mem_Free( g_gamepads );
g_gamepads = NULL;
g_num_gamepads = 0;
SDL_QuitSubSystem( SDL_INIT_GAMECONTROLLER );
}
#else // SDL_VERSION_ATLEAST( 2, 0, 0 )
void Platform_Vibrate( float time, char flags )
{
}
int Platform_JoyInit( void )
{
return 0;
}
void Platform_JoyShutdown( void )
{
}
#endif

View File

@@ -175,7 +175,7 @@ qboolean SNDDMA_Init( void )
if( !samplecount )
samplecount = 0x8000;
dma.samples = samplecount * obtained.channels;
dma.buffer = Mem_Malloc( sndpool, dma.samples * 2 );
dma.buffer = Z_Calloc( dma.samples * 2 );
dma.samplepos = 0;
sdl_format = obtained.format;

View File

@@ -20,9 +20,9 @@ GNU General Public License for more details.
#if XASH_TIMER == TIMER_SDL
double Platform_DoubleTime( void )
{
static Uint64 g_PerformanceFrequency;
static Uint64 g_ClockStart;
Uint64 CurrentTime;
static longtime_t g_PerformanceFrequency;
static longtime_t g_ClockStart;
longtime_t CurrentTime;
if( !g_PerformanceFrequency )
{
@@ -41,65 +41,8 @@ void Platform_MessageBox( const char *title, const char *message, qboolean paren
}
#endif // XASH_MESSAGEBOX == MSGBOX_SDL
static const char *SDLash_CategoryToString( int category )
void SDLash_Init( void )
{
switch( category )
{
case SDL_LOG_CATEGORY_APPLICATION: return "App";
case SDL_LOG_CATEGORY_ERROR: return "Error";
case SDL_LOG_CATEGORY_ASSERT: return "Assert";
case SDL_LOG_CATEGORY_SYSTEM: return "System";
case SDL_LOG_CATEGORY_AUDIO: return "Audio";
case SDL_LOG_CATEGORY_VIDEO: return "Video";
case SDL_LOG_CATEGORY_RENDER: return "Render";
case SDL_LOG_CATEGORY_INPUT: return "Input";
case SDL_LOG_CATEGORY_TEST: return "Test";
default: return "Unknown";
}
}
static void SDLCALL SDLash_LogOutputFunction( void *userdata, int category, SDL_LogPriority priority, const char *message )
{
switch( priority )
{
case SDL_LOG_PRIORITY_CRITICAL:
case SDL_LOG_PRIORITY_ERROR:
Con_Printf( S_ERROR S_BLUE "SDL" S_DEFAULT ": [%s] %s\n", SDLash_CategoryToString( category ), message );
break;
case SDL_LOG_PRIORITY_WARN:
Con_DPrintf( S_WARN S_BLUE "SDL" S_DEFAULT ": [%s] %s\n", SDLash_CategoryToString( category ), message );
break;
case SDL_LOG_PRIORITY_INFO:
Con_Reportf( S_NOTE S_BLUE "SDL" S_DEFAULT ": [%s] %s\n", SDLash_CategoryToString( category ), message );
break;
default:
Con_Reportf( S_BLUE "SDL" S_DEFAULT ": [%s] %s\n", SDLash_CategoryToString( category ), message );
break;
}
}
void SDLash_Init( const char *basedir )
{
#if XASH_APPLE
char *path = SDL_GetBasePath();
if( path != NULL )
{
char buf[MAX_VA_STRING];
Q_snprintf( buf, sizeof( buf ), "%s%s/extras.pk3", path, basedir );
setenv( "XASH3D_EXTRAS_PAK1", buf, true );
}
#endif
SDL_LogSetOutputFunction( SDLash_LogOutputFunction, NULL );
if( host_developer.value >= 2 )
SDL_LogSetAllPriority( SDL_LOG_PRIORITY_VERBOSE );
else if( host_developer.value >= 1 )
SDL_LogSetAllPriority( SDL_LOG_PRIORITY_WARN );
else
SDL_LogSetAllPriority( SDL_LOG_PRIORITY_ERROR );
#ifndef SDL_INIT_EVENTS
#define SDL_INIT_EVENTS 0
#endif

View File

@@ -145,7 +145,7 @@ void Wcon_ShowConsole( qboolean show )
void Wcon_DisableInput( void )
{
if( host.type != HOST_DEDICATED || !s_wcd.hWnd )
if( host.type != HOST_DEDICATED )
return;
s_wcd.inputEnabled = false;
@@ -469,9 +469,6 @@ print into window console
*/
void Wcon_WinPrint( const char *pMsg )
{
if( !s_wcd.hWnd )
return;
int nLen;
if( s_wcd.consoleTextLen )
{
@@ -518,18 +515,13 @@ void Wcon_CreateConsole( qboolean con_showalways )
}
s_wcd.attached = ( AttachConsole( ATTACH_PARENT_PROCESS ) != 0 );
if( s_wcd.attached )
{
if( s_wcd.attached ) {
GetConsoleTitle( &s_wcd.previousTitle, sizeof( s_wcd.previousTitle ));
s_wcd.previousCodePage = GetConsoleCP();
s_wcd.previousOutputCodePage = GetConsoleOutputCP();
}
else
{
if( host.type != HOST_DEDICATED && host_developer.value == DEV_NONE )
return; // don't initialize console in case of regular game startup, it's useless anyway
else
AllocConsole();
else {
AllocConsole();
}
SetConsoleTitle( s_wcd.title );
@@ -578,7 +570,7 @@ register console commands (dedicated only)
*/
void Wcon_InitConsoleCommands( void )
{
if( host.type != HOST_DEDICATED || !s_wcd.hWnd )
if( host.type != HOST_DEDICATED )
return;
Cmd_AddCommand( "clear", Wcon_Clear_f, "clear console history" );
@@ -596,7 +588,7 @@ void Wcon_DestroyConsole( void )
// last text message into console or log
Con_Reportf( "%s: Unloading xash.dll\n", __func__ );
Sys_CloseLog( NULL );
Sys_CloseLog();
if( !s_wcd.attached )
{
@@ -631,7 +623,7 @@ char *Wcon_Input( void )
DWORD eventsCount;
static INPUT_RECORD events[1024];
if( !s_wcd.inputEnabled || !s_wcd.hWnd )
if( !s_wcd.inputEnabled )
return NULL;
while( true )
@@ -674,7 +666,7 @@ set server status string in console
*/
void Platform_SetStatus( const char *pStatus )
{
if( s_wcd.attached || !s_wcd.hWnd )
if( s_wcd.attached )
return;
Q_strncpy( s_wcd.statusLine, pStatus, sizeof( s_wcd.statusLine ) - 1 );

View File

@@ -138,7 +138,7 @@ static void Sys_StackTrace( PEXCEPTION_POINTERS pInfo )
#endif
len = Q_snprintf( message, sizeof( message ), "Ver: " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s, %s-%s)\n",
Q_buildnum(), g_buildcommit, Q_buildos(), Q_buildarch() );
Q_buildnum(), Q_buildcommit(), Q_buildos(), Q_buildarch() );
len += Q_snprintf( message + len, 1024 - len, "Sys_Crash: address %p, code %p\n",
pInfo->ExceptionRecord->ExceptionAddress, (void*)pInfo->ExceptionRecord->ExceptionCode );
@@ -213,14 +213,14 @@ static void Sys_GetMinidumpFileName( const char *processName, char *mdmpFileName
struct tm *currentLocalTime = localtime( &currentUtcTime );
Q_snprintf( mdmpFileName, bufferSize, "%s_%s_crash_%d%.2d%.2d_%.2d%.2d%.2d.mdmp",
processName,
g_buildcommit,
currentLocalTime->tm_year + 1900,
currentLocalTime->tm_mon + 1,
currentLocalTime->tm_mday,
currentLocalTime->tm_hour,
currentLocalTime->tm_min,
currentLocalTime->tm_sec );
processName,
Q_buildcommit(),
currentLocalTime->tm_year + 1900,
currentLocalTime->tm_mon + 1,
currentLocalTime->tm_mday,
currentLocalTime->tm_hour,
currentLocalTime->tm_min,
currentLocalTime->tm_sec);
}
static qboolean Sys_WriteMinidump(PEXCEPTION_POINTERS exceptionInfo, MINIDUMP_TYPE minidumpType)

View File

@@ -80,7 +80,6 @@ GNU General Public License for more details.
#define MODEL_LIQUID BIT( 2 ) // model has only point hull
#define MODEL_TRANSPARENT BIT( 3 ) // have transparent surfaces
#define MODEL_COLORED_LIGHTING BIT( 4 ) // lightmaps stored as RGB
#define MODEL_WORLD BIT( 29 ) // it's a worldmodel
#define MODEL_CLIENT BIT( 30 ) // client sprite

View File

@@ -66,9 +66,6 @@ extern int SV_UPDATE_BACKUP;
#define MAX_PUSHED_ENTS 256
#define MAX_VIEWENTS 128
#define MAX_LOCALINFO_STRING 32768 // localinfo used on server and not sended to the clients
#define MAX_ENT_LEAFS( ext ) (( ext ) ? MAX_ENT_LEAFS_32 : MAX_ENT_LEAFS_16 )
#define FCL_RESEND_USERINFO BIT( 0 )
#define FCL_RESEND_MOVEVARS BIT( 1 )
@@ -499,24 +496,10 @@ qboolean SV_ProcessUserAgent( netadr_t from, const char *useragent );
qboolean SV_InitGame( void );
void SV_ActivateServer( int runPhysics );
qboolean SV_SpawnServer( const char *server, const char *startspot, qboolean background );
model_t *SV_ModelHandle( int modelindex );
void SV_DeactivateServer( void );
void SV_FreeTestPacket( void );
/*
================
SV_ModelHandle
get model by handle
================
*/
static inline model_t *GAME_EXPORT SV_ModelHandle( int modelindex )
{
if( modelindex < 0 || modelindex >= MAX_MODELS )
return NULL;
return sv.models[modelindex];
}
//
// sv_phys.c
//
@@ -688,6 +671,7 @@ void SV_ClearGameState( void );
// sv_pmove.c
//
void SV_InitClientMove( void );
qboolean SV_PlayerIsFrozen( edict_t *pClient );
void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd, int random_seed );
//

View File

@@ -305,7 +305,6 @@ static void SV_ConnectClient( netadr_t from )
int challenge;
const char *s;
int extensions;
uint netchan_flags = 0;
if( Cmd_Argc() < 5 )
{
@@ -432,9 +431,7 @@ static void SV_ConnectClient( netadr_t from )
newcl->listeners = -1;
// initailize netchan
if( !Host_IsLocalClient( ))
SetBits( netchan_flags, NETCHAN_USE_LZSS );
Netchan_Setup( NS_SERVER, &newcl->netchan, from, qport, newcl, SV_GetFragmentSize, netchan_flags );
Netchan_Setup( NS_SERVER, &newcl->netchan, from, qport, newcl, SV_GetFragmentSize, 0 );
MSG_Init( &newcl->datagram, "Datagram", newcl->datagram_buf, sizeof( newcl->datagram_buf )); // datagram buf
Q_strncpy( newcl->hashedcdkey, Info_ValueForKey( protinfo, "uuid" ), 32 );
@@ -453,6 +450,8 @@ static void SV_ConnectClient( netadr_t from )
newcl->delta_sequence = -1;
newcl->flags = 0;
// reset any remaining events
memset( &newcl->events, 0, sizeof( newcl->events ));
@@ -478,7 +477,7 @@ static void SV_ConnectClient( netadr_t from )
// reset stats
newcl->next_checkpingtime = -1.0;
newcl->packet_loss = 0;
newcl->packet_loss = 0.0f;
// if this was the first client on the server, or the last client
// the server can hold, send a heartbeat to the master.
@@ -1171,7 +1170,7 @@ SV_EstablishTimeBase
Finangles latency and the like.
===================
*/
static void SV_EstablishTimeBase( sv_client_t *cl, const usercmd_t *cmds, int dropped, int numbackup, int numcmds )
static void SV_EstablishTimeBase( sv_client_t *cl, usercmd_t *cmds, int dropped, int numbackup, int numcmds )
{
double runcmd_time = 0.0;
int i, cmdnum = dropped;
@@ -2227,7 +2226,7 @@ SV_SendBuildInfo_f
static qboolean SV_SendBuildInfo_f( sv_client_t *cl )
{
SV_ClientPrintf( cl, "Server running " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s, %s-%s)\n",
Q_buildnum(), g_buildcommit, Q_buildos(), Q_buildarch() );
Q_buildnum(), Q_buildcommit(), Q_buildos(), Q_buildarch() );
return true;
}
@@ -2870,20 +2869,14 @@ static qboolean SV_EntCreate_f( sv_client_t *cl )
// XashXT does not implement SV_CreateEntity, use saverestore export
if( !ent && svgame.physFuncs.pfnCreateEntitiesInRestoreList )
{
ENTITYTABLE table = {
.classname = classname,
.id = -1,
.size = 1,
.flags = 1337,
};
SAVERESTOREDATA data = {
.tableCount = 1,
.pTable = &table
};
svgame.physFuncs.pfnCreateEntitiesInRestoreList( &data, table.flags, false );
SAVERESTOREDATA data = { 0 };
ENTITYTABLE table = { 0 };
data.tableCount = 1;
data.pTable = &table;
table.classname = classname;
table.id = -1;
table.size = 1;
svgame.physFuncs.pfnCreateEntitiesInRestoreList( &data, 0, false );
ent = table.pent;
}
@@ -3219,20 +3212,6 @@ void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
}
}
static qboolean SV_PlayerIsFrozen( const edict_t *pClient )
{
if( sv_background_freeze.value && sv.background )
return true;
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
return false;
if( FBitSet( pClient->v.flags, FL_FROZEN ))
return true;
return false;
}
/*
==================
SV_ParseClientMove
@@ -3247,20 +3226,29 @@ each of the backup packets.
*/
static void SV_ParseClientMove( sv_client_t *cl, sizebuf_t *msg )
{
const usercmd_t nullcmd = { 0 }, *from = &nullcmd; // first cmd are starting from null-compressed usercmd_t
client_frame_t *frame = &cl->frames[cl->netchan.incoming_acknowledged & SV_UPDATE_MASK];
usercmd_t cmds[CMD_BACKUP] = { 0 }, *to;
edict_t *player = cl->edict;
model_t *model;
client_frame_t *frame;
int key, size, checksum1, checksum2;
int i, numbackup, totalcmds, numcmds;
usercmd_t nullcmd, *to, *from;
usercmd_t cmds[CMD_BACKUP];
float packet_loss;
edict_t *player;
model_t *model;
int key = MSG_GetRealBytesRead( msg );
int checksum1 = MSG_ReadByte( msg );
int packet_loss = MSG_ReadByte( msg );
int numbackup = MSG_ReadByte( msg );
int numcmds = MSG_ReadByte( msg );
int totalcmds = numcmds + numbackup;
int i;
player = cl->edict;
frame = &cl->frames[cl->netchan.incoming_acknowledged & SV_UPDATE_MASK];
memset( &nullcmd, 0, sizeof( usercmd_t ));
memset( cmds, 0, sizeof( cmds ));
key = MSG_GetRealBytesRead( msg );
checksum1 = MSG_ReadByte( msg );
packet_loss = MSG_ReadByte( msg );
numbackup = MSG_ReadByte( msg );
numcmds = MSG_ReadByte( msg );
totalcmds = numcmds + numbackup;
net_drop -= (numcmds - 1);
if( totalcmds < 0 || totalcmds >= CMD_MASK )
@@ -3270,6 +3258,8 @@ static void SV_ParseClientMove( sv_client_t *cl, sizebuf_t *msg )
return;
}
from = &nullcmd; // first cmd are starting from null-compressed usercmd_t
for( i = totalcmds - 1; i >= 0; i-- )
{
to = &cmds[i];
@@ -3280,17 +3270,14 @@ static void SV_ParseClientMove( sv_client_t *cl, sizebuf_t *msg )
if( cl->state != cs_spawned )
return;
if( !Host_IsLocalClient( ))
{
// if the checksum fails, ignore the rest of the packet
int size = MSG_GetRealBytesRead( msg ) - key - 1;
int checksum2 = CRC32_BlockSequence( msg->pData + key + 1, size, cl->netchan.incoming_sequence );
// if the checksum fails, ignore the rest of the packet
size = MSG_GetRealBytesRead( msg ) - key - 1;
checksum2 = CRC32_BlockSequence( msg->pData + key + 1, size, cl->netchan.incoming_sequence );
if( checksum2 != checksum1 )
{
Con_Reportf( S_ERROR "%s: failed command checksum for %s (%d != %d)\n", __func__, cl->name, checksum2, checksum1 );
return;
}
if( checksum2 != checksum1 )
{
Con_Reportf( S_ERROR "%s: failed command checksum for %s (%d != %d)\n", __func__, cl->name, checksum2, checksum1 );
return;
}
cl->packet_loss = packet_loss;

View File

@@ -492,15 +492,14 @@ SV_EmitPings
*/
static void SV_EmitPings( sizebuf_t *msg )
{
sv_client_t *cl;
int i;
sv_client_t *cl;
int packet_loss;
int i, ping;
MSG_BeginServerCmd( msg, svc_pings );
for( i = 0, cl = svs.clients; i < svs.maxclients; i++, cl++ )
{
int packet_loss, ping;
if( cl->state != cs_spawned )
continue;

View File

@@ -328,7 +328,7 @@ static qboolean SV_CheckClientVisiblity( sv_client_t *cl, const byte *mask )
else
VectorCopy( cl->edict->v.origin, vieworg );
leaf = Mod_PointInLeaf( vieworg, sv.worldmodel->nodes, sv.worldmodel );
leaf = Mod_PointInLeaf( vieworg, sv.worldmodel->nodes );
if( CHECKVISBIT( mask, leaf->cluster ))
return true; // visible from player view or camera view
@@ -342,7 +342,7 @@ static qboolean SV_CheckClientVisiblity( sv_client_t *cl, const byte *mask )
continue;
VectorAdd( view->v.origin, view->v.view_ofs, vieworg );
leaf = Mod_PointInLeaf( vieworg, sv.worldmodel->nodes, sv.worldmodel );
leaf = Mod_PointInLeaf( vieworg, sv.worldmodel->nodes );
if( CHECKVISBIT( mask, leaf->cluster ))
return true; // visible from portal camera view
@@ -1732,7 +1732,7 @@ static edict_t* GAME_EXPORT pfnFindClientInPVS( edict_t *pEdict )
VectorAdd( pEdict->v.origin, pEdict->v.view_ofs, view );
}
leaf = Mod_PointInLeaf( view, sv.worldmodel->nodes, sv.worldmodel );
leaf = Mod_PointInLeaf( view, sv.worldmodel->nodes );
if( CHECKVISBIT( clientpvs, leaf->cluster ))
return pClient; // client which currently in PVS
@@ -4291,35 +4291,6 @@ static byte *GAME_EXPORT pfnSetFatPAS( const float *org )
return fatphs;
}
/*
=============
Mod_HeadnodeVisible
=============
*/
static qboolean Mod_HeadnodeVisible( model_t *mod, mnode_t *node, const byte *visbits, int *lastleaf )
{
if( !node || node->contents == CONTENTS_SOLID )
return false;
if( node->contents < 0 )
{
if( !CHECKVISBIT( visbits, ((mleaf_t *)node)->cluster ))
return false;
if( lastleaf )
*lastleaf = ((mleaf_t *)node)->cluster;
return true;
}
if( Mod_HeadnodeVisible( mod, node_child( node, 0, mod ), visbits, lastleaf ))
return true;
if( Mod_HeadnodeVisible( mod, node_child( node, 1, mod ), visbits, lastleaf ))
return true;
return false;
}
/*
=============
pfnCheckVisibility
@@ -4329,7 +4300,6 @@ pfnCheckVisibility
static int GAME_EXPORT pfnCheckVisibility( const edict_t *ent, byte *pset )
{
int i, leafnum;
qboolean large_leafs = FBitSet( sv.worldmodel->flags, MODEL_QBSP2 );
if( !SV_IsValidEdict( ent ))
return 0;
@@ -4345,28 +4315,17 @@ static int GAME_EXPORT pfnCheckVisibility( const edict_t *ent, byte *pset )
// check individual leafs
for( i = 0; i < ent->num_leafs; i++ )
{
if( large_leafs )
{
if( CHECKVISBIT( pset, ent->leafnums32[i] ))
return 1; // visible passed by leaf
}
else
{
if( CHECKVISBIT( pset, ent->leafnums16[i] ))
return 1; // visible passed by leaf
}
if( CHECKVISBIT( pset, ent->leafnums[i] ))
return 1; // visible passed by leaf
}
return 0;
}
else
{
for( i = 0; i < MAX_ENT_LEAFS( large_leafs ); i++ )
for( i = 0; i < MAX_ENT_LEAFS; i++ )
{
if( large_leafs )
leafnum = ent->leafnums32[i];
else
leafnum = ent->leafnums16[i];
leafnum = ent->leafnums[i];
if( leafnum == -1 ) break;
if( CHECKVISBIT( pset, leafnum ))
@@ -4374,15 +4333,11 @@ static int GAME_EXPORT pfnCheckVisibility( const edict_t *ent, byte *pset )
}
// too many leafs for individual check, go by headnode
if( !Mod_HeadnodeVisible( sv.worldmodel, &sv.worldmodel->nodes[ent->headnode], pset, &leafnum ))
if( !Mod_HeadnodeVisible( &sv.worldmodel->nodes[ent->headnode], pset, &leafnum ))
return 0;
if( large_leafs )
((edict_t *)ent)->leafnums32[ent->num_leafs] = leafnum;
else
((edict_t *)ent)->leafnums16[ent->num_leafs] = leafnum;
((edict_t *)ent)->num_leafs = (ent->num_leafs + 1) % MAX_ENT_LEAFS( large_leafs );
((edict_t *)ent)->leafnums[ent->num_leafs] = leafnum;
((edict_t *)ent)->num_leafs = (ent->num_leafs + 1) % MAX_ENT_LEAFS;
return 2; // visible passed by headnode
}

View File

@@ -273,6 +273,20 @@ int GAME_EXPORT SV_GenericIndex( const char *filename )
return i;
}
/*
================
SV_ModelHandle
get model by handle
================
*/
model_t *GAME_EXPORT SV_ModelHandle( int modelindex )
{
if( modelindex < 0 || modelindex >= MAX_MODELS )
return NULL;
return sv.models[modelindex];
}
static resourcetype_t SV_DetermineResourceType( const char *filename )
{
if( !Q_strncmp( filename, DEFAULT_SOUNDPATH, sizeof( DEFAULT_SOUNDPATH ) - 1 ) && Sound_SupportedFileFormat( COM_FileExtension( filename )))

View File

@@ -970,7 +970,7 @@ void SV_Init( void )
MSG_Init( &net_message, "NetMessage", net_message_buffer, sizeof( net_message_buffer ));
Q_snprintf( versionString, sizeof( versionString ), XASH_ENGINE_NAME ": " XASH_VERSION "-%s(%s-%s),%i,%i",
g_buildcommit, Q_buildos(), Q_buildarch(), PROTOCOL_VERSION, Q_buildnum() );
Q_buildcommit(), Q_buildos(), Q_buildarch(), PROTOCOL_VERSION, Q_buildnum() );
Cvar_FullSet( "sv_version", versionString, FCVAR_READ_ONLY );

View File

@@ -23,6 +23,19 @@ GNU General Public License for more details.
static qboolean has_update = false;
static void SV_GetTrueOrigin( sv_client_t *cl, int edictnum, vec3_t origin );
qboolean SV_PlayerIsFrozen( edict_t *pClient )
{
if( sv_background_freeze.value && sv.background )
return true;
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
return false;
if( FBitSet( pClient->v.flags, FL_FROZEN ))
return true;
return false;
}
void SV_ClipPMoveToEntity( physent_t *pe, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, pmtrace_t *tr )
{
Assert( tr != NULL );

View File

@@ -2279,7 +2279,7 @@ int GAME_EXPORT SV_GetSaveComment( const char *savename, char *comment )
if( tag == 0x0065 )
{
Q_strncpy( comment, "<old version "XASH_ENGINE_NAME" unsupported>", MAX_STRING );
Q_strncpy( comment, "<old version Xash3D unsupported>", MAX_STRING );
FS_Close( f );
return 0;
}

View File

@@ -40,8 +40,9 @@ HULL BOXES
===============================================================================
*/
static hull_t box_hull;
static mplane_t box_planes[6];
static hull_t box_hull;
static mclipnode_t box_clipnodes[6];
static mplane_t box_planes[6];
/*
===================
@@ -53,15 +54,23 @@ can just be stored out and get a proper hull_t structure.
*/
static void SV_InitBoxHull( void )
{
int i;
int i, side;
box_hull.clipnodes16 = (mclipnode16_t *)box_clipnodes16;
box_hull.clipnodes = box_clipnodes;
box_hull.planes = box_planes;
box_hull.firstclipnode = 0;
box_hull.lastclipnode = 5;
for( i = 0; i < 6; i++ )
{
box_clipnodes[i].planenum = i;
side = i & 1;
box_clipnodes[i].children[side] = CONTENTS_EMPTY;
if( i != 5 ) box_clipnodes[i].children[side^1] = i + 1;
else box_clipnodes[i].children[side^1] = CONTENTS_SOLID;
box_planes[i].type = i>>1;
box_planes[i].normal[i>>1] = 1;
box_planes[i].signbits = 0;
@@ -158,11 +167,6 @@ static hull_t *SV_HullForBox( const vec3_t mins, const vec3_t maxs )
box_planes[4].dist = maxs[2];
box_planes[5].dist = mins[2];
if( world.version == QBSP2_VERSION )
box_hull.clipnodes32 = (mclipnode32_t *)box_clipnodes32;
else
box_hull.clipnodes16 = (mclipnode16_t *)box_clipnodes16;
return &box_hull;
}
@@ -590,7 +594,7 @@ SV_FindTouchedLeafs
===============
*/
static void SV_FindTouchedLeafs( edict_t *ent, model_t *mod, mnode_t *node, int *headnode )
static void SV_FindTouchedLeafs( edict_t *ent, mnode_t *node, int *headnode )
{
int sides;
mleaf_t *leaf;
@@ -601,19 +605,16 @@ static void SV_FindTouchedLeafs( edict_t *ent, model_t *mod, mnode_t *node, int
// add an efrag if the node is a leaf
if( node->contents < 0 )
{
if( ent->num_leafs > MAX_ENT_LEAFS( FBitSet( mod->flags, MODEL_QBSP2 )))
if( ent->num_leafs > ( MAX_ENT_LEAFS - 1 ))
{
// continue counting leafs,
// so we know how many it's overrun
ent->num_leafs = (MAX_ENT_LEAFS( FBitSet( mod->flags, MODEL_QBSP2 )) + 1);
ent->num_leafs = (MAX_ENT_LEAFS + 1);
}
else
{
leaf = (mleaf_t *)node;
if( FBitSet( mod->flags, MODEL_QBSP2 ))
ent->leafnums32[ent->num_leafs] = leaf->cluster;
else
ent->leafnums16[ent->num_leafs] = leaf->cluster;
ent->leafnums[ent->num_leafs] = leaf->cluster;
ent->num_leafs++;
}
return;
@@ -623,13 +624,11 @@ static void SV_FindTouchedLeafs( edict_t *ent, model_t *mod, mnode_t *node, int
sides = BOX_ON_PLANE_SIDE( ent->v.absmin, ent->v.absmax, node->plane );
if(( sides == 3 ) && ( *headnode == -1 ))
*headnode = node - mod->nodes;
*headnode = node - sv.worldmodel->nodes;
// recurse down the contacted sides
if( sides & 1 )
SV_FindTouchedLeafs( ent, mod, node_child( node, 0, mod ), headnode );
if( sides & 2 )
SV_FindTouchedLeafs( ent, mod, node_child( node, 1, mod ), headnode );
if( sides & 1 ) SV_FindTouchedLeafs( ent, node->children[0], headnode );
if( sides & 2 ) SV_FindTouchedLeafs( ent, node->children[1], headnode );
}
/*
@@ -651,7 +650,7 @@ void GAME_EXPORT SV_LinkEdict( edict_t *ent, qboolean touch_triggers )
if( ent->v.movetype == MOVETYPE_FOLLOW && SV_IsValidEdict( ent->v.aiment ))
{
memcpy( ent->leafnums32, ent->v.aiment->leafnums32, sizeof( ent->leafnums32 ));
memcpy( ent->leafnums, ent->v.aiment->leafnums, sizeof( ent->leafnums ));
ent->num_leafs = ent->v.aiment->num_leafs;
ent->headnode = ent->v.aiment->headnode;
}
@@ -663,11 +662,11 @@ void GAME_EXPORT SV_LinkEdict( edict_t *ent, qboolean touch_triggers )
headnode = -1;
if( ent->v.modelindex )
SV_FindTouchedLeafs( ent, sv.worldmodel, sv.worldmodel->nodes, &headnode );
SV_FindTouchedLeafs( ent, sv.worldmodel->nodes, &headnode );
if( ent->num_leafs > MAX_ENT_LEAFS( FBitSet( sv.worldmodel->flags, MODEL_QBSP2 )))
if( ent->num_leafs > MAX_ENT_LEAFS )
{
memset( ent->leafnums32, -1, sizeof( ent->leafnums32 ));
memset( ent->leafnums, -1, sizeof( ent->leafnums ));
ent->num_leafs = 0; // so we use headnode instead
ent->headnode = headnode;
}
@@ -1519,8 +1518,6 @@ static qboolean SV_RecursiveLightPoint( model_t *model, mnode_t *node, const vec
float front, back, frac;
int i, side;
vec3_t mid;
mnode_t *children[2];
int numsurfaces, firstsurface;
// didn't hit anything
if( !node || node->contents < 0 )
@@ -1530,29 +1527,25 @@ static qboolean SV_RecursiveLightPoint( model_t *model, mnode_t *node, const vec
front = PlaneDiff( start, node->plane );
back = PlaneDiff( end, node->plane );
node_children( children, node, model );
side = front < 0.0f;
if(( back < 0.0f ) == side )
return SV_RecursiveLightPoint( model, children[side], start, end, point_color );
return SV_RecursiveLightPoint( model, node->children[side], start, end, point_color );
frac = front / ( front - back );
VectorLerp( start, frac, end, mid );
// co down front side
if( SV_RecursiveLightPoint( model, children[side], start, mid, point_color ))
if( SV_RecursiveLightPoint( model, node->children[side], start, mid, point_color ))
return true; // hit something
if(( back < 0.0f ) == side )
return false; // didn't hit anything
// check for impact on this node
numsurfaces = node_numsurfaces( node, model );
firstsurface = node_firstsurface( node, model );
for( i = 0; i < numsurfaces; i++ )
for( i = 0; i < node->numsurfaces; i++ )
{
const msurface_t *surf = &model->surfaces[firstsurface + i];
const msurface_t *surf = &model->surfaces[node->firstsurface + i];
const mextrasurf_t *info = surf->info;
int smax, tmax, map, size;
int sample_size;
@@ -1603,7 +1596,7 @@ static qboolean SV_RecursiveLightPoint( model_t *model, mnode_t *node, const vec
}
// go down back side
return SV_RecursiveLightPoint( model, children[!side], mid, end, point_color );
return SV_RecursiveLightPoint( model, node->children[!side], mid, end, point_color );
}
/*

View File

@@ -5,19 +5,9 @@
from waflib import Logs
from waflib.extras import pthread
import os
from copy import copy
top = '.'
EXECINFO_TEST = '''#include <execinfo.h>
int main(int argc, char **argv)
{
backtrace(0, 0);
backtrace_symbols(0, 0);
return 0;
}
'''
def options(opt):
grp = opt.add_option_group('Engine options')
@@ -47,85 +37,98 @@ def options(opt):
opt.load('sdl2')
def find_sdl(conf):
err_msg = '%s not available! If you want to build dedicated server, specify --dedicated'
if conf.env.DEST_OS in ['nswitch', 'psvita']:
err_msg = '%s not available!'
conf.load('sdl2')
if conf.options.SDL3:
if not conf.env.HAVE_SDL3:
conf.fatal(err_msg % 'SDL3')
conf.env.XASH_SDL = 3
else:
if not conf.env.HAVE_SDL2:
conf.fatal(err_msg % 'SDL2')
conf.env.XASH_SDL = 2
def configure(conf):
# Common dependencies, will be linked to both dedicated server and client
if conf.env.DEST_OS == 'linux':
conf.check_cc(lib='rt')
if conf.env.MAGX:
conf.define('XASH_CRASHHANDLER', 0)
elif conf.env.DEST_OS == 'haiku':
conf.env.LIB_HAIKU = ['network']
conf.env.LIBPATH_HAIKU = ['/boot/system/lib']
elif conf.env.DEST_OS == 'wasi':
conf.options.NO_ASYNC_RESOLVE = True
conf.env.CFLAGS += ['-mllvm', '-wasm-enable-sjlj']
elif conf.env.DEST_OS == 'sunos':
conf.check_cc(lib='socket')
# check for dedicated server build
if conf.options.DEDICATED:
conf.define('XASH_DEDICATED', 1)
elif conf.env.DEST_OS == 'dos':
conf.options.STATIC = True
conf.options.NO_ASYNC_RESOLVE = True
if not conf.check_cc( fragment='int main(){ int i = socket();}', lib = 'wattcpwl', mandatory=False ):
conf.define('XASH_NO_NETWORK',1)
elif conf.env.DEST_OS == 'nswitch':
# re-enable undefined reference errors
conf.env.CXXFLAGS += ['-Wl,--no-undefined']
conf.env.CFLAGS += ['-Wl,--no-undefined']
# allow the SDL2 sanity check to complete properly by linking in lm normally
conf.env.LDFLAGS += ['-lm']
conf.load('sdl2')
if not conf.env.HAVE_SDL2:
conf.fatal('SDL2 not availiable! Install switch-sdl2!')
conf.define('XASH_SDL', 2)
# then remove them to avoid them getting linked to shared objects
conf.env.LIB_SDL2.remove('stdc++') # remove libstdc++ linking from SDL2, we link it later
conf.env.LDFLAGS.remove('-lm')
elif conf.env.DEST_OS == 'psvita':
# allow the SDL2 sanity check to complete properly by linking in some deps missing from the pkg-config file
extra_libs = ['-lstdc++', '-lm', '-lSceShaccCgExt', '-lSceShaccCg_stub', '-ltaihen_stub', '-lSceKernelDmacMgr_stub']
conf.env.LDFLAGS += extra_libs
conf.load('sdl2')
if not conf.env.HAVE_SDL2:
conf.fatal('SDL2 not availiable! Install switch-sdl2!')
conf.define('XASH_SDL', 2)
# then remove them to avoid them getting linked to shared objects
for lib in extra_libs:
conf.env.LDFLAGS.remove(lib)
elif conf.options.FBDEV_SW:
# unused, XASH_LINUX without XASH_SDL gives fbdev & alsa support
# conf.define('XASH_FBDEV', 1)
conf.check_cc( lib = 'asound' )
elif conf.options.SDL12:
conf.define('XASH_SDL', 12)
conf.check_cfg(package='sdl', args='--cflags --libs', uselib_store='SDL2' )
conf.env.HAVE_SDL2 = True
else:
conf.load('sdl2')
if conf.options.SDL3:
if not conf.env.HAVE_SDL3:
conf.fatal('SDL3 not available! If you want to build dedicated server, specify --dedicated')
conf.define('XASH_SDL', 3)
else:
if not conf.env.HAVE_SDL2:
conf.fatal('SDL2 not available! If you want to build dedicated server, specify --dedicated')
conf.define('XASH_SDL', 2)
if conf.env.DEST_OS == 'haiku':
conf.env.LIB_HAIKU = ['network']
conf.env.LIBPATH_HAIKU = ['/boot/system/lib']
if conf.env.DEST_OS == 'wasi':
conf.options.NO_ASYNC_RESOLVE = True
conf.env.append_unique('CFLAGS', '-mllvm')
conf.env.append_unique('CFLAGS', '-wasm-enable-sjlj')
if conf.env.DEST_OS == 'sunos':
conf.check_cc(lib='socket')
if conf.options.STATIC:
conf.env.STATIC = True
conf.define('XASH_NO_LIBDL',1)
if not conf.env.DEST_OS in ['win32', 'android'] and not conf.options.NO_ASYNC_RESOLVE:
conf.check_pthreads(mode='c')
if conf.env.DEST_OS == 'linux':
conf.check_cc(lib='rt')
if hasattr(conf.options, 'DLLEMU'):
conf.define_cond('XASH_DLL_LOADER', conf.options.DLLEMU)
if conf.env.MAGX:
conf.define('XASH_CRASHHANDLER', 0)
conf.env.ENGINE_TESTS = conf.options.ENGINE_TESTS
if conf.options.ENGINE_FUZZ:
conf.env.append_unique('CFLAGS', '-fsanitize=fuzzer-no-link')
conf.env.append_unique('LINKFLAGS', '-fsanitize=fuzzer')
# Client-only dependencies
if conf.env.CLIENT:
if conf.env.DEST_OS in ['nswitch', 'psvita']:
extra_libs = ['-lm']
if conf.env.DEST_OS == 'psvita':
extra_libs = ['-lstdc++', '-lm', '-lSceShaccCgExt', '-lSceShaccCg_stub', '-ltaihen_stub', '-lSceKernelDmacMgr_stub']
conf.env.append_unique('CXXFLAGS', ['-Wl,--no-undefined'])
conf.env.append_unique('CFLAGS', ['-Wl,--no-undefined'])
conf.env.LDFLAGS += extra_libs
find_sdl(conf)
for lib in extra_libs: conf.env.LDFLAGS.remove(lib)
if conf.env.DEST_OS == 'nswitch': # remove libstdc++ linking from SDL2, we link it later
conf.env.LIB_SDL2.remove('stdc++')
elif conf.env.DEST_OS == 'linux' and conf.options.FBDEV_SW:
conf.check_cc(lib='asound')
elif conf.options.SDL12: # TODO: move to sdl2.py
conf.check_cfg(package='sdl', args='--cflags --libs', uselib_store='SDL2')
conf.env.XASH_SDL = 12
conf.env.HAVE_SDL2 = True
else:
find_sdl(conf)
if conf.options.STATIC:
conf.env.STATIC = True
conf.define('XASH_NO_LIBDL', 1)
if not conf.env.DEST_OS in ['win32', 'android'] and not conf.options.NO_ASYNC_RESOLVE:
conf.check_pthreads(mode='c')
if hasattr(conf.options, 'DLLEMU'):
conf.define_cond('XASH_DLL_LOADER', conf.options.DLLEMU)
conf.check_cc(fragment=EXECINFO_TEST, msg='Checking for glibc backtrace()', mandatory=False, define_name='HAVE_EXECINFO')
conf.define('ENGINE_DLL', 1)
conf.define_cond('XASH_ENGINE_TESTS', conf.options.ENGINE_TESTS)
conf.define_cond('XASH_ENGINE_TESTS', conf.env.ENGINE_TESTS)
conf.define_cond('XASH_STATIC_LIBS', conf.env.STATIC_LINKING)
conf.define_cond('XASH_CUSTOM_SWAP', conf.options.CUSTOM_SWAP)
conf.define_cond('XASH_ENABLE_MAIN', conf.env.DISABLE_LAUNCHER)
conf.define_cond('XASH_NO_ASYNC_NS_RESOLVE', conf.options.NO_ASYNC_RESOLVE)
conf.define_cond('PSAPI_VERSION', conf.env.DEST_OS == 'win32') # will be defined as 1
@@ -136,103 +139,140 @@ def build(bld):
# public includes for renderers and utils use
bld(name = 'engine_includes', export_includes = '. common common/imagelib', use = 'filesystem_includes')
libs = ['engine_includes', 'public', 'dllemu', 'werror']
includes = ['server', 'client', 'client/vgui', 'common/soundlib']
is_cxx_link = False
libs = [ 'engine_includes', 'public', 'dllemu', 'werror' ]
# basic build: dedicated only
source = bld.path.ant_glob(['common/*.c', 'common/imagelib/*.c', 'common/soundlib/*.c', 'server/*.c'])
source = bld.path.ant_glob([
'common/*.c',
'common/imagelib/*.c',
'common/soundlib/*.c',
'server/*.c'])
# include platform-specific sources, this shall not fail if directory doesn't exist
source += bld.path.ant_glob('platform/%s/*.c' % bld.env.DEST_OS)
# Android _is_ Linux based, after all
if bld.env.DEST_OS == 'android':
source += bld.path.ant_glob('platform/linux/*.c')
# include common POSIX conformant code
if bld.env.DEST_OS not in ['win32', 'dos']:
source += bld.path.ant_glob('platform/posix/*.c')
# include sources for optional features
if bld.get_define('XASH_CUSTOM_SWAP'):
source += ['platform/misc/kmalloc.c', 'platform/misc/sbrk.c']
if bld.get_define('XASH_STATIC_LIBS'):
source += ['platform/misc/lib_static.c']
if bld.env.ENGINE_TESTS:
source += bld.path.ant_glob(['tests/*.c'])
if bld.env.DEST_OS == 'win32':
libs += ['USER32', 'SHELL32', 'GDI32', 'ADVAPI32', 'DBGHELP', 'PSAPI', 'WS2_32']
elif bld.env.DEST_OS == 'nswitch':
libs += ['SOLDER']
libs += ['USER32', 'SHELL32', 'GDI32', 'ADVAPI32', 'DBGHELP', 'PSAPI', 'WS2_32' ]
source += bld.path.ant_glob(['platform/win32/*.c'])
elif bld.env.DEST_OS not in ['dos', 'nswitch', 'psvita']: #posix
libs += [ 'M', 'RT', 'PTHREAD', 'ASOUND']
if not bld.env.STATIC:
libs += ['DL']
source += bld.path.ant_glob(['platform/posix/*.c'])
if bld.env.DEST_OS == 'linux':
source += bld.path.ant_glob(['platform/linux/*.c'])
if bld.env.DEST_OS == 'irix':
source += bld.path.ant_glob(['platform/irix/*.c'])
if bld.env.DEST_OS == 'dos':
source += bld.path.ant_glob(['platform/dos/*.c'])
source += bld.path.ant_glob(['platform/stub/s_stub.c'])
if bld.env.DEST_OS == 'haiku':
libs.append('HAIKU')
if bld.get_define('XASH_CUSTOM_SWAP'):
source += bld.path.ant_glob(['platform/misc/kmalloc.c', 'platform/misc/sbrk.c'])
if bld.env.STATIC_LINKING:
source += bld.path.ant_glob(['platform/misc/lib_static.c'])
is_cxx_link = True
if bld.env.HAVE_SDL2 or bld.env.HAVE_SDL3:
libs.append('SDL3' if bld.env.HAVE_SDL3 else 'SDL2')
source += bld.path.ant_glob(['platform/sdl/*.c'])
if bld.env.MAGX:
libs.append('MAGX')
is_cxx_link = True
if bld.env.DEST_OS == 'android':
libs += ['LOG']
source += bld.path.ant_glob(['platform/android/*.cpp', 'platform/android/*.c', 'platform/linux/*.c'])
if bld.env.DEST_OS == 'nswitch':
libs += [ 'SOLDER' ]
source += bld.path.ant_glob(['platform/posix/*.c'])
source += bld.path.ant_glob(['platform/nswitch/*.c'])
# HACK: link in the entirety of libstdc++ so that dynamic libs could use all of it without manual exporting
# we can't do this right away because std::filesystem will complain about not having pathconf(),
# which we have defined in sys_nswitch.c
bld.env.LDFLAGS += ['-v', '-Wl,--whole-archive', '-lstdc++', '-Wl,--no-whole-archive', '-lm']
elif bld.env.DEST_OS == 'psvita':
libs += ['VRTLD']
if bld.env.DEST_OS == 'psvita':
libs += [ 'VRTLD' ]
source += bld.path.ant_glob(['platform/posix/*.c'])
source += bld.path.ant_glob(['platform/psvita/*.c'])
# HACK: link in the entirety of libstdc++ so that dynamic libs could use all of it without manual exporting
# also link in all the funky dependencies that aren't in SDL2's LDFLAGS
bld.env.LDFLAGS += ['-Wl,--whole-archive', '-lstdc++', '-lpthread', '-Wl,--no-whole-archive',
'-lm', '-lSceShaccCgExt', '-lkubridge_stub', '-ltaihen_stub', '-lSceShaccCg_stub', '-lSceKernelModulemgr_stub', '-lSceSblSsMgr_stub', '-lSceVshBridge_stub', '-lSceKernelDmacMgr_stub',
bld.env.LDFLAGS += [
'-Wl,--whole-archive',
'-lstdc++',
'-lpthread',
'-Wl,--no-whole-archive',
'-lm',
'-lSceShaccCgExt',
'-lkubridge_stub',
'-ltaihen_stub',
'-lSceShaccCg_stub',
'-lSceKernelModulemgr_stub',
'-lSceSblSsMgr_stub',
'-lSceVshBridge_stub',
'-lSceKernelDmacMgr_stub'
]
else: # POSIX
libs += ['M', 'RT', 'PTHREAD', 'ASOUND', 'HAIKU', 'MAGX', 'LOG', 'SOCKET']
if not bld.env.STATIC:
libs += ['DL']
if bld.env.SERVER:
# TODO: avoid possible name collision when client is built without launcher
# but dedicated server is enabled. They're both called 'xash' in this case
bld.program(
source = copy(source),
target = 'xash',
use = copy(libs),
includes = includes,
defines = 'XASH_ENABLE_MAIN=1 XASH_DEDICATED=1',
rpath = bld.env.DEFAULT_RPATH,
install_path = bld.env.BINDIR,
)
if bld.env.DEST_OS == 'sunos':
libs.append('SOCKET')
if bld.env.CLIENT:
defines = []
if bld.env.XASH_SDL:
libs += ['SDL3' if bld.env.HAVE_SDL3 else 'SDL2']
source += bld.path.ant_glob(['platform/sdl/*.c'])
defines += ['XASH_SDL=%d' % bld.env.XASH_SDL]
# add client files
if not bld.env.DEDICATED:
source += bld.path.ant_glob([
'client/*.c',
'client/vgui/*.c',
'client/avi/*.c',
'client/soundlib/*.c',
'client/soundlib/libmpg/*.c',
])
is_cxx_link = True
libs += ['bzip2', 'MultiEmulator', 'opus', 'opusfile', 'vorbis', 'vorbisfile']
# add client files
if not bld.env.DEDICATED:
source += bld.path.ant_glob('client/**/*.c')
libs += ['bzip2', 'MultiEmulator', 'opus', 'opusfile', 'vorbis', 'vorbisfile']
rpath = bld.env.DEFAULT_RPATH
# Android port is linked differently
if bld.env.DEST_OS == 'android':
f = bld.shlib
install_path = bld.env.LIBDIR
defines += ['XASH_ENABLE_MAIN=1', 'XASH_SDLMAIN=1']
elif not bld.env.LAUNCHER:
f = bld.program
install_path = bld.env.BINDIR
defines += ['XASH_ENABLE_MAIN=1']
# Switch and PSVita have custom parameters
if bld.env.DEST_OS in ['nswitch', 'psvita']:
rpath = None
install_path = None
features = 'cxx c cxxprogram cprogram'
# Always build as shared library on Android
elif bld.env.DISABLE_LAUNCHER and bld.env.DEST_OS != 'android':
install_path = bld.env.BINDIR
if bld.env.STATIC:
features = 'cxx c cxxprogram_static cprogram_static'
elif is_cxx_link:
features = 'cxx c cxxprogram cprogram'
else:
f = bld.shlib
install_path = bld.env.LIBDIR
features = 'c cprogram'
else:
install_path = bld.env.LIBDIR
if is_cxx_link:
features = 'cxx c cxxshlib cshlib'
else:
features = 'c cshlib'
if bld.env.DEST_OS in ['nswitch', 'psvita']:
install_path = None
f(source = source,
target = 'xash',
includes = includes,
features = 'cxx c',
use = libs,
defines = defines,
install_path = install_path,
special_install_path = bld.env.BINDIR,
nacp = 'platform/nswitch/xash3d-fwgs.nacp',
icon = 'platform/nswitch/icon.jpg',
sce_sys = 'platform/psvita/sce_sys',
title_id = 'XASH10000',
app_name = 'xash3d-fwgs',
rpath = bld.env.DEFAULT_RPATH,
)
bld(source = source,
target = 'xash',
features = features,
includes = 'server client client/vgui common/soundlib',
use = libs,
install_path = install_path,
nro_install_path = bld.env.BINDIR,
nacp = 'platform/nswitch/xash3d-fwgs.nacp',
icon = 'platform/nswitch/icon.jpg',
sce_sys = 'platform/psvita/sce_sys',
title_id = 'XASH10000',
app_name = 'xash3d-fwgs',
rpath = rpath,
)

View File

@@ -242,7 +242,7 @@ static byte *FS_LoadAndroidAssetsFile( searchpath_t *search, const char *path, i
if( filesize ) *filesize = 0;
asset = AAssetManager_open( search->assets->asset_manager, path, AASSET_MODE_BUFFER );
asset = AAssetManager_open( search->assets->asset_manager, path, AASSET_MODE_RANDOM );
if( !asset )
return NULL;

Some files were not shown because too many files have changed in this diff Show More