Compare commits

..

300 Commits

Author SHA1 Message Date
Alibek Omarov
21f4d1486c 3rdparty: add MultiEmulator by 2010kohtep
* patched to be portable, turned into a static library
* integrated to the engine
2024-10-15 06:15:45 +03:00
Alibek Omarov
a32c702dbd engine: client: avoid useless check on empty clc_resourcelist, which will never be false 2024-10-15 06:15:22 +03:00
Alibek Omarov
23a5ed71de engine: easier MSG_EndBitWriting byte padding 2024-10-15 06:14:37 +03:00
Alibek Omarov
245dc97cfb engine: semi-correct printing GoldSrc client messages 2024-10-15 06:12:31 +03:00
Alibek Omarov
ece204c30f engine: common: add cvars net_send_debug and net_recv_debug to print server/client messages to console 2024-10-15 06:11:57 +03:00
Alibek Omarov
1bd59096fd engine: client: implement miscellaneous, often unused, GoldSrc protocol messages 2024-10-15 06:10:25 +03:00
Alibek Omarov
0b02c2c6a7 engine: client: fix disconnect on GoldSrc servers 2024-10-15 06:08:21 +03:00
Alibek Omarov
6a61a499e9 engine: client: don't send useless/empty clc_move commands while we're connecting to server 2024-10-15 06:07:57 +03:00
Alibek Omarov
6b1c283082 engine: client: fix svc_event parsing 2024-10-15 06:07:06 +03:00
Alibek Omarov
5402a9611e engine: common: fix discarded const qualifier 2024-10-14 19:41:36 +03:00
Alibek Omarov
43e06ccd45 engine: common: make some simple functions inlined 2024-10-14 19:20:47 +03:00
Alibek Omarov
f52c825bf5 engine: make some global variables static and const, make even more functions static if possible 2024-10-14 19:19:46 +03:00
Alibek Omarov
bf8b709372 engine: move pm_debug particle functions to client, as they are never used on server 2024-10-14 19:11:26 +03:00
Alibek Omarov
fdf82e5270 engine: client: cleanup tent and efx code, make global variables static, remove unused functions 2024-10-14 18:08:01 +03:00
Alibek Omarov
0224a1b66b engine: client: better debug messages for GoldSrc entities packet parsing 2024-10-14 17:59:17 +03:00
Alibek Omarov
505ad6d69b engine: server: reinitalize delta in case if delta was shutdown by client and some tables were omitted (movevars after using GoldSrc server) 2024-10-14 06:56:17 +03:00
Alibek Omarov
5bcd573821 engine: remove goldsrc meta delta table reinitialization 2024-10-14 06:54:41 +03:00
Alibek Omarov
c5a291d9c7 engine: minor refactoring 2024-10-14 05:17:21 +03:00
Alibek Omarov
232a8c1148 engine: common: net_ws: don't expect more than 5 splits for GoldSrc protocol 2024-10-14 05:17:03 +03:00
Alibek Omarov
663f6eaf5c ref: turn r_shadows into extended convar_t 2024-10-14 04:18:35 +03:00
Alibek Omarov
9d3210259c ref: set hullcolor (used by r_drawentities) as const 2024-10-14 04:15:48 +03:00
Alibek Omarov
4ec6c2f7cf engine: client: support vox sentence that starts with leading slash 2024-10-14 04:13:10 +03:00
Alibek Omarov
8452bec877 engine: client: reduce reads of cls.legacymode 2024-10-14 04:13:10 +03:00
Alibek Omarov
0d4296e0e1 engine: client: explicitly pass protocol to svc_time parser 2024-10-14 04:13:10 +03:00
Alibek Omarov
2b85da3bc9 engine: client: fix parsing svc_setpause and svc_goldsrc_timescale for GoldSrc protocol 2024-10-14 04:13:10 +03:00
Alibek Omarov
17f194b9a3 engine: client: consolidate usermsg registering and parsing for multiple protocols 2024-10-14 04:13:10 +03:00
Alibek Omarov
ff47fbaedc engine: client: another fix baselines and entities parsing for GoldSrc, ensure we always call MSG_EndBitWriting 2024-10-14 04:13:10 +03:00
Alibek Omarov
87c88f7463 engine: client: fix svc_particles parsing on GoldSrc protocol 2024-10-14 04:13:10 +03:00
Alibek Omarov
60fd5f7ab8 engine: client: stub svc_restoresound for legacy protocol, it's only used during save restore which is unuseful for us
* Set sequence flag for restored sound, even though we don't support sequences anymore.
2024-10-14 04:13:10 +03:00
Alibek Omarov
5ceab059dc engine: client: add function for parsing common protocol messages, which structure is enforced by server DLL compatibility 2024-10-14 04:13:10 +03:00
Alibek Omarov
67c898f9ad engine: client: improve server data parsing for GoldSrc, restore nick name and remove unuseful userinfo keys before connection 2024-10-14 04:13:10 +03:00
Alibek Omarov
d903187eea public: make crc value init functions inline, move hex2char/ex2string to crclib and make them private to it 2024-10-14 04:13:10 +03:00
54ac
653f0841e4 ref: gl: restore r_shadows (#1843) 2024-10-13 17:15:29 +03:00
Alibek Omarov
10bfadb556 engine: client: support svc_disconnect reason messages for GoldSrc protocol 2024-10-11 20:58:46 +03:00
Alibek Omarov
0b2cc066dd engine: fix signed integers encoding with alternate format for GoldSrc protocol 2024-10-11 20:36:09 +03:00
Alibek Omarov
60ab13d216 engine: client: always add [Xash3D] to the nickname on GoldSrc servers 2024-10-11 19:32:16 +03:00
Alibek Omarov
f90c658567 engine: client: skip voice data for GoldSrc protocol to avoid svc_bad 2024-10-11 19:31:41 +03:00
Alibek Omarov
0c54895877 engine: client: add unmunge function for consistency info for GoldSrc protocol 2024-10-11 18:41:17 +03:00
Alibek Omarov
4eb54328f8 engine: client: various connection setup fixes for GoldSrc proto
* always add "steam" to getchallenge message
* cdkey md5 should be sent with lowercase
* strip null terminator from connect message
2024-10-11 18:41:16 +03:00
Alibek Omarov
b1189db9c5 engine: client: avoid clc_move spam when we're connected but not spawned yet 2024-10-11 00:08:21 +03:00
Alibek Omarov
869578f1ba engine: client: lie about sv_version for GoldSrc protocol 2024-10-11 00:08:21 +03:00
Alibek Omarov
3320f776ce engine: client: implement correct clc_fileconsistency response for GoldSrc 2024-10-11 00:08:21 +03:00
Alibek Omarov
1d64635783 engine: correctly check for cls.legacymode, as it's not a boolean anymore 2024-10-11 00:08:21 +03:00
Alibek Omarov
bbb076c0d4 engine: client: voice: don't print about unsupported codec with empty string name 2024-10-10 23:40:23 +03:00
Alibek Omarov
fe2a4d0428 engine: common: net_encode: remove DT_SIGNED_GS flag just in case 2024-10-10 23:40:23 +03:00
Alibek Omarov
6bdc1941e6 engine: common: netchan: only compress with BZip2 when it's efficient 2024-10-10 23:40:23 +03:00
Alibek Omarov
9188905145 engine: client: fix map CRC match with GoldSrc protocol 2024-10-10 23:40:23 +03:00
Alibek Omarov
3f2fbb10d8 engine: client: only send continueloading for legacy protocol 2024-10-10 23:40:23 +03:00
Alibek Omarov
9c97235fe8 engine: client: implement GoldSrc connectionless print message 2024-10-10 23:40:23 +03:00
Alibek Omarov
70a13b47db engine: client: implement randomized cdkey for GoldSrc protocol 2024-10-10 23:40:22 +03:00
Alibek Omarov
18afaf0eaf engine: client: more accurate clc_move for GoldSrc protocol 2024-10-10 23:38:55 +03:00
Alibek Omarov
8b8c3d8116 scripts: waifulib: xcompile: define WebAssembly target as DEST_OS wasi 2024-10-10 16:13:54 +03:00
Alibek Omarov
514fc9fe43 public: reserve identifier for WebAssembly port 2024-10-10 16:13:20 +03:00
Alibek Omarov
5d8923d69c scripts: waifulib: sdl2: fix build on macOS 2024-10-10 15:44:32 +03:00
Alibek Omarov
5db880af57 engine: wscript: add an ability to build with SDL3 2024-10-10 06:13:56 +03:00
Alibek Omarov
c05db9ce58 waf: upgrade waifu to latest master 2024-10-10 06:13:32 +03:00
Alibek Omarov
04079abe00 scripts: waifulib: re-export sdl2.py from waifu repository, add sdl3 compatibility 2024-10-10 06:13:23 +03:00
Alibek Omarov
8054b69f73 readme: add GoldSrc protocol support, add RedHat/Fedora build instructions, better wording [skip ci] 2024-10-10 01:58:56 +03:00
SNMetamorph
b5ee777466 Documentation: added article about GoldSrc network protocol support 2024-10-10 01:52:44 +03:00
Alibek Omarov
96f3061709 ref: gl: show texture size in memory, skip empty pages, skip empty 0-th texture 2024-10-09 02:44:26 +03:00
Alibek Omarov
420c5a4ff3 ref: gl: set numeric value for wrappers macros, similar to build.h macros 2024-10-09 02:01:10 +03:00
Alibek Omarov
e8f6476e8c ref: gl: patch to compile with nanogl (nanogl doesn't impement glTexCoord3f) 2024-10-09 00:31:05 +03:00
Alibek Omarov
65ec35b732 engine: client: fix bug in temp entity parsing caused by find and replace 2024-10-08 23:02:02 +03:00
Alibek Omarov
8d731b5d15 engine: common: fix for dedicated again 2024-10-08 16:41:25 +03:00
Alibek Omarov
38c0dc4551 3rdparty: bzip2: properly use stdio-free version, don't include tests and utils to the build 2024-10-08 15:39:56 +03:00
Alibek Omarov
4d8cb0469f scripts: gha: build Linux binaries with bundled deps, to avoid external dependency on libbz2 2024-10-08 13:09:34 +03:00
Alibek Omarov
62cb8f5ba6 3rdparty: bzip2: forgot to add actual bz_version.h file 2024-10-08 13:07:42 +03:00
Alibek Omarov
97c75d96d5 3rdparty: bzip2: build with BZ_NO_STDIO 2024-10-08 13:06:02 +03:00
Alibek Omarov
f5ae806b31 ref: gl: add r_showtextures implementation by ncuxonaT
Main changes made by me besides engine differences:
* Text color changed to pure white for better readability
* An attempt to draw texture name in full size
2024-10-08 12:56:07 +03:00
Alibek Omarov
482dc3a5a5 engine: client: fix joining current protocol servers 2024-10-08 12:43:29 +03:00
Alibek Omarov
a8539ac004 3rdparty: bzip2: add pre-generated bz_version.h header as some generators (like cmake.py) don't understand subst yet 2024-10-08 12:27:41 +03:00
Alibek Omarov
9970c56218 engine: common: disable bzip2 for dedicated server, it's not used there 2024-10-08 12:14:37 +03:00
Alibek Omarov
480218412a engine: client: remove voidptr hack from IN_EngineAppendMove, just use usercmd_t directly 2024-10-08 04:07:03 +03:00
Alibek Omarov
6ae09d2866 engine: client: support GoldSrc signon and refactor parsing delta entities for current and legacy protocols 2024-10-08 04:07:03 +03:00
Alibek Omarov
609680b328 engine: client: support parsing GoldSrc event messages 2024-10-08 04:07:03 +03:00
Alibek Omarov
ccbe370c8e engine: client: add support for parsing GoldSrc messages 2024-10-08 04:07:03 +03:00
Alibek Omarov
9706e47643 engine: client: refactor and implement GoldSrc-specific parsing bits in common message parsing code 2024-10-08 03:28:02 +03:00
Alibek Omarov
d98361f782 engine: client: add support for parsing GoldSrc svc_temp_entity 2024-10-08 03:28:02 +03:00
Alibek Omarov
ba7c789ec9 engine: common: add GoldSrc delta support 2024-10-08 03:28:02 +03:00
Alibek Omarov
d128997d40 engine: common: add GoldSrc bitbuf operations, add support for GoldSrc signed integers 2024-10-08 03:28:02 +03:00
Alibek Omarov
61342547ce engine: common: add support for GoldSrc split packet 2024-10-08 03:28:02 +03:00
Alibek Omarov
c1a5f173b8 engine: common: add GoldSrc netchan support 2024-10-08 03:28:02 +03:00
Alibek Omarov
f5c5b7b2c8 engine: common: add buffer munge functions 2024-10-08 03:28:02 +03:00
Alibek Omarov
057b47555d 3rdparty: bzip2: add wscript for bzip2, check for system-wide bzip2, add readme note 2024-10-08 03:28:02 +03:00
Alibek Omarov
43299f6747 3rdparty: add bzip2 submodule 2024-10-08 03:28:02 +03:00
Alibek Omarov
03bf6cb719 engine: client: get rid of PROTOCOL_GOLDSRC_VERSION, as connprotocol_t enum does it's job 2024-10-08 03:27:32 +03:00
Alibek Omarov
3a1bb12830 engine: client: rename CL_LegacyMode to CL_Protocol 2024-10-08 03:27:09 +03:00
Alibek Omarov
5efa68757e engine: remove unused svc_deltapacketbones 2024-10-08 03:27:09 +03:00
Alibek Omarov
afaf5bf3ea engine: improve security a little bit by properly checking customization files starting with \!MD5
Implement basic test for COM_IsSafeFileToDownload

Move COM_ParseFileSafe test to libpublic
2024-10-08 03:22:53 +03:00
SNMetamorph
50c805826f engine: implemented handling SIGTERM signal for proper stopping dedicated server 2024-10-08 01:05:26 +03:00
Alibek Omarov
35ae9f4a64 engine: client: don't save thirdperson value, it's not used anywhere 2024-10-07 21:00:16 +03:00
Alibek Omarov
d7d96c02a2 engine: client: implement cvar showpause for GoldSrc compatibility 2024-10-07 20:59:44 +03:00
Alibek Omarov
dd03723144 readme: add libopus-dev to dependencies list on Debian/Ubuntu 2024-10-07 18:09:32 +03:00
xiaodo
26f07196ea engine: Format Codes. 2024-10-07 17:22:27 +03:00
xiaodo
8c291fdfe3 engine: fix CenterPrint Wrong Y Position. 2024-10-07 17:22:27 +03:00
xiaodoxd
d1e118f07c Fix CenterPrint Wrong X Position 2024-10-07 17:22:27 +03:00
Alibek Omarov
6c531c14e6 engine: common: cvar: compatibility hack for mods that depend on HL25 widescreen FOV
Fixes Natural Selection 3.3 beta 9.
2024-10-04 19:09:43 +03:00
Alibek Omarov
433213c915 engine: server: fix cvar description for mp_footsteps 2024-10-04 19:07:44 +03:00
Alibek Omarov
ab0c0b18c2 engine: server: remove limit on sv_zmax value as it breaks Natural Selection mod 2024-10-04 19:07:08 +03:00
Alibek Omarov
29fd5f9fbe engine: server: remove FCVAR_SERVER flag from sv_zmax
The problem is that FCVAR_SERVER flagged cvars get saved to listenserver.cfg.

The game code usually sets sv_zmax value to worldspawn parameters and
listenserver.cfg gets generated before server DLL gets initialized.
2024-10-04 19:04:34 +03:00
Alibek Omarov
882d8afc93 engine: server: stub SV_RestartDecals for dedicated server 2024-10-04 01:28:22 +03:00
Alibek Omarov
e11635d15c engine: server: slight refactoring, hide client calls under XASH_DEDICATED, remove useless dedicated stub 2024-10-04 01:22:59 +03:00
Alibek Omarov
5d79d93aac engine: server: use safe cvar unlinking for mods that deallocate cvars (like HL Unified SDK) 2024-10-03 15:32:14 +03:00
Alibek Omarov
7ccf651fd0 engine: cvar: implement safer cvar unlinking in case when game deallocates cvar 2024-10-03 15:32:14 +03:00
Alibek Omarov
67af41cce8 engine: common: net_ws: more minor refactoring, avoid memcpy for same type structs 2024-10-02 23:30:42 +03:00
Alibek Omarov
e2c96e62e1 engine: common: net_ws: drop IPv4 mapped as IPv6 support, it's an artifact from dual-stacking experiments and not used anymore 2024-10-02 23:26:28 +03:00
Alibek Omarov
2ecae442fc engine: common: net_ws: minor refactoring 2024-10-02 23:25:12 +03:00
Alibek Omarov
a1060b0eb5 engine: add v6only master servers, add v6only flag for NET_StringToAdrNB 2024-10-02 23:23:08 +03:00
Alibek Omarov
ddd8de888f engine: add macro XASH_NO_IPV6_RESOLVE to completely skip resolving addresses with family AF_INET6 2024-10-02 23:21:25 +03:00
Alibek Omarov
a758dffbc1 public: avoid useless copy in Q_timestamp 2024-10-02 22:18:16 +03:00
Alibek Omarov
87775faeca engine: common: properly check if we can destroy resolve mutexes. Add net_resolve_debug cvar to enable printing resolve thread debug messages. 2024-10-02 22:16:51 +03:00
Alibek Omarov
ef0fc46ed8 wscript: allow async resolving for NSwitch 2024-10-02 00:55:53 +03:00
Alibek Omarov
138b4fa247 wscript: allow async resolving for PSVita 2024-10-02 00:55:53 +03:00
Alibek Omarov
47d1f3459c engine: common: try to implement DNS resolve thread through SDL2 functions if SDL2 build is enabled 2024-10-02 00:55:53 +03:00
Alibek Omarov
4712aae834 engine: server: move autoprecaching wads after parsing reslists
An attempt to avoid assert() in HL Unified SDK.
2024-09-30 18:46:01 +03:00
Ivan Avdeev
2900ee1cde engine: allow specifying screenshot filenames in command directly 2024-09-30 17:15:09 +03:00
Alibek Omarov
c6c4178dd2 engine: client: set TE_SPRAY to collide with world, fixes c7ad8e4bf 2024-09-30 04:15:22 +03:00
Alibek Omarov
a3ce0e6b1b public: tests: test_efp: mark Test_ExtractFilePath as static 2024-09-30 04:00:28 +03:00
Alibek Omarov
0b1ad3b7f0 engine: imagelib: fix mismatched dealloc in a test 2024-09-30 04:00:28 +03:00
Alibek Omarov
37fb46f092 wscript: enable mismatched-dealloc and free-nonheap-object, now that we mark all malloc-like functions with malloc attribute 2024-09-30 04:00:28 +03:00
Alibek Omarov
bc8bf9a9fb engine: add const on delta functions 2024-09-30 04:00:28 +03:00
Alibek Omarov
9e28c98911 engine: print to stderr if writing message to logfile failed 2024-09-30 04:00:28 +03:00
Alibek Omarov
0a1269d52d filesystem: zip: fix non-heap object dealloc 2024-09-30 04:00:28 +03:00
Alibek Omarov
2e5bc31c9e filesystem: set malloc like attribute for imported zone memory allocator functions 2024-09-30 04:00:28 +03:00
Alibek Omarov
1b335fd945 ref: soft: set malloc like attribute for imported zone memory allocator functions 2024-09-30 04:00:28 +03:00
Alibek Omarov
0c8b2d007a ref: gl: set malloc like attribute for imported zone memory allocator functions 2024-09-30 04:00:28 +03:00
Alibek Omarov
9ee1b32e2d engine: set malloc like and warn_unused_result attributes on common allocation functions, fs, image and soundlib 2024-09-30 04:00:28 +03:00
Alibek Omarov
953ad98a16 engine: workaround buggy stringop-overflow 2024-09-30 04:00:28 +03:00
Alibek Omarov
1357057bd8 common: add GCC malloc and warn_unused_result attribute macro 2024-09-30 04:00:28 +03:00
Alibek Omarov
35c9323de6 public: make vec3_origin and identity matrix inlined 2024-09-30 00:15:47 +03:00
Alibek Omarov
13a0afef06 public: reorganize mathlib, inline more functions 2024-09-30 00:15:47 +03:00
Alibek Omarov
c7ad8e4bf6 engine: client: more accurate implementation of TE_SPRAY and TE_SPRITE_SPRAY 2024-09-29 20:36:09 +03:00
Alibek Omarov
f1754bdd5f wscript: disable cast-align diagnostic, it's mostly useless 2024-09-29 20:36:09 +03:00
Alibek Omarov
c462a1c500 wscript: add commented out freevgui subproject 2024-09-29 20:36:09 +03:00
Alibek Omarov
0bba184994 public: add VectorUnpack macro to read vector values into variables 2024-09-29 20:33:33 +03:00
Alibek Omarov
178602ea1f engine: fix loading map in Dark Future mod with broken mark surface id 2024-09-05 15:23:23 +03:00
Alibek Omarov
2eb8f88a20 engine: move attenuation none sound spatialize fix to bugcomp mode, as Xash native games use this 2024-09-05 13:50:15 +03:00
Alibek Omarov
96d11df06c Revert "engine: client: sounds with zero attenuation must get spatialized anyway"
This reverts commit 0870536405.
2024-09-05 13:27:54 +03:00
Alibek Omarov
950d210ec5 Revert ABI2, it wasn't meant to end up in master branch. 2024-09-05 04:31:50 +03:00
Alibek Omarov
55c1bddac5 ref: gl: implement generating VBO only when gl_vbo was set to 1
* Make it safer by creating a function that returns VBO state, was it
  generated or enabled by user
2024-09-05 04:10:56 +03:00
Alibek Omarov
ac50c762d7 ref: gl: slight refactoring, split large R_RenderBrushPoly to smaller functions
* Use R_RenderDetailsForSurface in R_AddSurfToVBO instead of copypaste
* Use existing VBO's R_CheckLightMap in R_RenderLightmapForSurface
2024-09-05 02:40:57 +03:00
Alibek Omarov
5c2ab150b3 ref: gl: move forcing gl_vbo to 0 after checking GL extensions out from R_GenerateVBO 2024-09-05 01:47:14 +03:00
Alibek Omarov
0870536405 engine: client: sounds with zero attenuation must get spatialized anyway 2024-09-05 01:28:55 +03:00
Alibek Omarov
b47ede477a engine: server: strip 64-bit string pool stuff for now, to not mess up abi2 2024-09-05 01:28:55 +03:00
Alibek Omarov
eef5cc17b3 breaking engine headers by replacing int with string_t where it's supposed to be 2024-09-05 01:28:55 +03:00
Alibek Omarov
ad2191333d engine: add _st64 prefix to load abi2 binaries 2024-09-05 01:28:55 +03:00
SNMetamorph
a85cac497d ref: disabled verbose reporting about tracer invalid color index 2024-09-03 15:31:51 +03:00
SNMetamorph
e0c69d7df5 gha: fixed binaries signing in Windows workflow 2024-08-30 07:34:40 +03:00
Alibek Omarov
ff3d91ceb4 engine: add aaaa.mentality.rip:27011 master server 2024-08-28 19:56:41 +03:00
Alibek Omarov
5777431577 engine: common: insert spaces between arguments in echo command 2024-08-22 16:45:42 +03:00
Alibek Omarov
cd86f80203 engine: common: make MSG_WriteOneBit inlined, as it's usually called with literal argument 2024-08-22 12:51:47 +03:00
Alibek Omarov
8c885d3f37 mainui: update 2024-08-22 12:50:01 +03:00
Alibek Omarov
dddb46a6d0 mainui: update 2024-08-21 18:14:21 +03:00
Alibek Omarov
6b0f378c5b engine: client: ensure requested (but failed) renderer won't be loaded twice 2024-08-21 12:18:06 +03:00
Alibek Omarov
9dd7f37d42 Revert "engine: client: add missing ref_null to R_CollectRendererNames"
This reverts commit 69ec810ed0.
2024-08-21 12:18:06 +03:00
Alibek Omarov
9f10fb6472 engine: client: ensure RefDll cvars have FCVAR_REFDLL flag, clean up them automatically. Don't unload failed renderer, it will be done in R_UnloadProgs 2024-08-21 12:18:06 +03:00
Alibek Omarov
64dbccb9bd engine: platform: sdl: do not call SDL_VideoQuit in R_Free_Video, as one failed renderer will shut down whole SDL video subsystem 2024-08-21 12:18:06 +03:00
Alibek Omarov
9a432a5a13 common: rewrite cvardef.h from scratch based on Quake definitions
* unify cvar.h and cvardef.h, enable private definitions only for refdll and engine

* add FCVAR_REFDLL for easier RefDll cvars cleanup
2024-08-21 12:18:06 +03:00
Alibek Omarov
842e494fa6 common: add macro for simultaneously checking data type size for ILP32 and LP64 2024-08-21 12:00:35 +03:00
Alibek Omarov
7fc9ee154a engine: client: fail with Sys_Error when no renderer is loaded, as we can't recover from it 2024-08-19 13:25:07 +03:00
Alibek Omarov
5f84010c2a engine: server: enable allocating 64-bit string pool closer to server library only for Linux amd64, as mmap() isn't reliable anywhere else 2024-08-19 13:22:04 +03:00
Alibek Omarov
3dcd6cb80b wscript: set crosscompiling msvc toolchain on 64-bit systems 2024-08-18 14:13:51 +03:00
Alibek Omarov
79e94bf766 Revert "scripts: gha: use 64-bit compiler for 32-bit target for faster compilation on Win32"
This reverts commit 3de370f3d5.
2024-08-18 14:13:01 +03:00
Alibek Omarov
3de370f3d5 scripts: gha: use 64-bit compiler for 32-bit target for faster compilation on Win32 2024-08-18 14:04:54 +03:00
Alibek Omarov
c84d2f4624 gha: first attempt at signing binaries 2024-08-18 13:52:02 +03:00
Alibek Omarov
380a9f7a6f scripts: add self-signed certificate for win32
* There is no infrastructure to use signtool during win32 builds yet.
2024-08-18 12:24:17 +03:00
Alibek Omarov
a6c7b67d0d filesystem: include errno.h for Win32 2024-08-17 17:32:50 +03:00
Alibek Omarov
c13c1f2577 public: wscript: always define alloca header as malloc.h on Win32 2024-08-17 13:17:48 +03:00
Alibek Omarov
151405618f engine: client: input: slight refactoring of mouse grabbing, add verbose output for debugging mouse issues 2024-08-16 12:59:54 +03:00
Alibek Omarov
70e11cc309 engine: platform: sdl: borderless fullscreen windows don't need to restore desktop resolution
* This fixes the case when we switch from windowed to borderless, minimize the window
  and restore makes it lose it's fullscreen state
2024-08-16 12:25:08 +03:00
Alibek Omarov
7619824d80 engine: platform: sdl: return correct value from SW_CreateBuffer on success 2024-08-16 11:36:36 +03:00
Alibek Omarov
f3d181b5ee engine: platform: psvita: explicitly export __aeabi_ul2f 2024-08-16 02:22:25 +03:00
Alibek Omarov
55055a70f0 engine: client: allocate mods list for UI on demand 2024-08-15 12:27:43 +03:00
Alibek Omarov
22d3ba674e engine: client: ensure demoheader will be written when we're recording demo and changed level 2024-08-14 19:10:00 +03:00
Alibek Omarov
ac487a2133 mainui: update 2024-08-14 10:29:42 +03:00
Alibek Omarov
4da3a14adc mainui: update 2024-08-13 19:25:32 +03:00
Alibek Omarov
69ec810ed0 engine: client: add missing ref_null to R_CollectRendererNames 2024-08-13 19:16:59 +03:00
Alibek Omarov
2df01316ce engine: client: add two new APIs for mainui to get extended new gameinfo structure 2024-08-13 18:28:07 +03:00
Alibek Omarov
3a67aefee2 filesystem: check rodir too when checking falldir existence too, just in case 2024-08-13 17:25:25 +03:00
Alibek Omarov
d114dffcb4 filesystem: add new gameinfo.txt key: demomap 2024-08-13 17:22:06 +03:00
Alibek Omarov
7bb5d9a67a gha: give github 20s to process remaining artifacts upload before downloading them. Upgrade Flatpak Docker image 2024-08-12 11:43:01 +03:00
Alibek Omarov
a6b1e57ae1 gha: simplify uploading releases by using gh cli tool 2024-08-12 11:26:36 +03:00
Alibek Omarov
c70c13eb5c gha: don't upload flatpak, action does it for us. Print found artifacts, as it seems actions/download-artifact sometimes skips some 2024-08-12 10:44:25 +03:00
Alibek Omarov
d905ea354e scripts: gha: do not waste time building bshift, just copy binary from mobile_hacks 2024-08-12 10:27:26 +03:00
Alibek Omarov
99cec81894 gha: update flatpak actions 2024-08-12 10:07:41 +03:00
Alibek Omarov
5d5bccf1bb gha: should've been doing this in a branch meh 2024-08-12 09:53:45 +03:00
Alibek Omarov
6fcf0a77af scripts: gha: fix typo 2024-08-12 09:43:02 +03:00
Alibek Omarov
e7477c0abf gha: update more actions, use gh delete release instead of delete-tag-and-release 2024-08-12 09:37:55 +03:00
Alibek Omarov
85540855c3 gha: update actions/checkout and actions/upload-artifact 2024-08-12 09:12:32 +03:00
Alibek Omarov
2dc220b42f gha: add build for macOS ARM and x86
Very barebones, doesn't build universal app, doesn't build dmg
2024-08-12 09:12:13 +03:00
Alibek Omarov
2d6cadbf1b waf: update to latest waifu 2024-08-12 08:38:52 +03:00
Alibek Omarov
340871e03a engine: platform: sdl: correct the message about glblit in ref_soft 2024-08-11 18:32:10 +03:00
Alibek Omarov
e222a74960 ref: soft: fail to the engine if CreateBuffer has failed (otherwise it sits in infinite loop) 2024-08-11 18:28:45 +03:00
Alibek Omarov
ab499d5095 scripts: waifulib: vgui: fix vgui_support getting automatically enabled on x86 machines with unsupported OS 2024-08-11 18:08:20 +03:00
Alibek Omarov
a5f7027229 readme: better wording 2024-08-10 15:03:07 +03:00
Alibek Omarov
bf5cf897e2 readme: add IPA pronounciation for word 'Xash' 2024-08-10 15:02:31 +03:00
Alibek Omarov
d33c1af549 wscript: don't force 32-bit for OSX users, as OSX don't support launching 32-bit applications since Catalina
Add `-4` or `--32bits` configure flag to specifically target 32-bit engine
2024-08-10 15:01:42 +03:00
Alibek Omarov
677464d04d ref: rename glpoly_t to glpoly2_t to make the changes more obvious and easier to notice 2024-08-10 13:46:00 +03:00
Alibek Omarov
d2d6ed8bd4 filesystem: fix zip_t and pack_t definition so it have true standard flexible array member 2024-08-10 13:46:00 +03:00
Alibek Omarov
bd2a44dbdd engine: common: fix fragbuf_t definition so it has true standard flexible array member 2024-08-10 13:46:00 +03:00
Alibek Omarov
e9ee4beb9f engine: client: fix rawchan_t definition so it has true standard flexible array member 2024-08-10 13:46:00 +03:00
Alibek Omarov
3b3f057f6f engine: common: fix winding_t definition so it has true standard flexible array member 2024-08-10 13:46:00 +03:00
Alibek Omarov
a9dec51e59 ref: fix glpoly_t definition so it has true standard flexible array member 2024-08-10 13:46:00 +03:00
Alibek Omarov
257312ad7c 3rdparty: update extras 2024-08-10 13:45:41 +03:00
Владислав Сухов
6ee8a2dfa7 scripts: sailfish: bump engine version to 0.21 2024-08-09 12:41:47 +03:00
Владислав Сухов
75c5e9cfa7 engine: bump engine version to 0.21 2024-08-09 12:41:47 +03:00
Gleb Mazovetskiy
1a94f2b585 Enable vsync by default
This is the first setting I change after installing xash3d-fwgs. Some distros even patch xash3d-fwgs to enable vsync by default (e.g. Batocera).

Let's enable vsync by default here.
2024-08-09 09:14:50 +03:00
Alibek Omarov
f0b4c42c68 engine: common: faster and simpler Netchan_OutOfBand 2024-08-08 04:37:16 +03:00
Alibek Omarov
9be061735f engine: client: fix misleading gcc warning about printf format string not being literal 2024-08-08 04:36:40 +03:00
Alibek Omarov
6bfa525080 engine: common: faster and simpler MSG_WriteString 2024-08-08 04:35:55 +03:00
Alibek Omarov
8fcaf18897 engine: client: remove useless copy in NetAPI_SendRequest 2024-08-08 04:32:58 +03:00
Alibek Omarov
f558cde266 engine: client: fix build with -Wincompatible-pointer-types-discards-qualifiers 2024-08-08 04:31:51 +03:00
Alibek Omarov
b508a33f5d engine: client: minor refactoring in CL_DecayLights, get rid of pointer iterating in for-loop 2024-08-07 09:23:09 +03:00
Alibek Omarov
b4db99006b engine: client: always print timedemo result 2024-08-07 08:46:55 +03:00
Alibek Omarov
8994f079a5 engine: common: don't uselessly copy data in Netchan_OutOfBound when playing a demo 2024-08-07 02:28:58 +03:00
Alibek Omarov
b2d184cfa5 engine: common: add unit tests for net_buffer functions 2024-08-07 02:28:13 +03:00
Alibek Omarov
92dc92379f engine: client: minor refactoring, turn quake stats into an enum 2024-08-06 08:42:23 +03:00
Alibek Omarov
2a6862ceb9 engine: soundlib: fix buffer overflow with truncated WAV files containing CoolEdit cue mark 2024-08-06 08:41:36 +03:00
Alibek Omarov
4c569e1d5f engine: client: ensure loading plaque was removed after we request spawn on legacy protocol 2024-08-03 11:27:45 +03:00
Alibek Omarov
4420ffd49e engine: fix buffer overflow in Sys_PrintLog 2024-08-03 11:27:45 +03:00
Alibek Omarov
fb7f57cf6a engine: client: switch efrags to dynamic allocation (as suggested on insideqc by @mh) 2024-08-03 11:27:45 +03:00
Alibek Omarov
8be3bdac5d engine: client: add command listdemo to show information about demo file (isn't really useful, just reads file header) 2024-08-03 11:01:17 +03:00
Alibek Omarov
2785376bd3 ref: remove unused function declarations 2024-08-03 09:14:56 +03:00
Alibek Omarov
d6e77e531d engine: fix memory leak in netchan
frag_message_buf wasn't always freed alongside with fragbuf_t
instead of ensuring frag_message_buf being freed, I turned it into
a flexible array member
2024-08-03 08:40:33 +03:00
Alibek Omarov
e686b1410d engine: client: set default fullscreen value in vid_fullscreen cvar definition 2024-07-31 00:53:58 +03:00
Alibek Omarov
2c23a1e0a0 engine: platform: sdl: fix going fullscreen after manually changing VIDRESTART cvars (like width and height) 2024-07-31 00:53:29 +03:00
Alibek Omarov
47eb9e8c8f engine: client: replace same struct type memcpys by assignments 2024-07-31 00:06:22 +03:00
Alibek Omarov
712b354421 engine: common: replace same struct type memcpys by assignments 2024-07-31 00:06:22 +03:00
Alibek Omarov
18ef4922de engine: server: replace same struct type memcpys by assignments 2024-07-31 00:06:22 +03:00
Alibek Omarov
274f9d5846 filesystem: replace same struct type memcpys by assignments 2024-07-31 00:06:15 +03:00
Alibek Omarov
f6fa085fe4 ref: gl: replace same struct type memcpys by assignments 2024-07-31 00:06:07 +03:00
Alibek Omarov
9ab0f04ba5 ref: null: replace same struct type memcpys by assignments 2024-07-31 00:05:57 +03:00
Alibek Omarov
fb7854f1ef ref: soft: replace same struct type memcpys by assignments 2024-07-31 00:05:44 +03:00
Владислав Сухов
1086c31503 engine: client: in_touch.c: make the voicechat and spray buttons multiplayer only 2024-07-30 17:52:28 +03:00
Alibek Omarov
3a47248a09 extras: update submodule 2024-07-30 15:34:20 +03:00
Владислав Сухов
71a333261b engine: client: in_touch.c: added voicechat touch button 2024-07-30 15:33:35 +03:00
Alibek Omarov
5ea2e295c1 engine: prevent rescanning filesystem when new player connects or on late precache
By reusing a padding hole in resource_t structure, we put a bit indicating that this archive
was already mounted by filesystem and skip it.

Because we associate this with resource, theoretical use of late precache with archives
will rescan filesystem and allow using newly downloaded assets.
2024-07-30 15:25:48 +03:00
Alibek Omarov
1fc7547a53 engine: client: clean up scr_viewsize remnants, don't tell client.dll scr_viewsize cvar value 2024-07-30 15:25:20 +03:00
Alibek Omarov
a7d63649f8 engine: add checks to verify resource_t, customization_t and HPAK data structs sizes 2024-07-30 15:25:20 +03:00
Alibek Omarov
2f26fcdc2a public: disallow backslashes in COM_PathSlashFix 2024-07-30 15:25:20 +03:00
Alibek Omarov
107d4cdd61 engine: client: fix buffer overrun in S_TrimEnd 2024-07-30 15:25:20 +03:00
Alibek Omarov
52f9aad4d0 filesystem: add new call to fs_stdio C API to check whether we support that archive format 2024-07-30 15:25:20 +03:00
Alibek Omarov
7bb5175084 Turn downloaded/ and custom/ into com_strings.h definitions, like sound path and saves path 2024-07-30 15:25:20 +03:00
Alibek Omarov
dd570b616b engine: client: properly exit from touch editor to menu when user have chosen to cancel and reset 2024-07-29 05:11:41 +03:00
Alibek Omarov
943a30af04 engine: client: add privileged flag to touch_in_menu and touch_enable 2024-07-29 05:08:35 +03:00
Alibek Omarov
eabed60e56 engine: automatically turn-on touch emulation while editing touch from menu 2024-07-29 05:06:10 +03:00
Alibek Omarov
f793413a79 mainui: update 2024-07-29 05:05:20 +03:00
Alibek Omarov
f4a3b8571d engine: fix inverted check in debug log output
Why there is even this check in the first place???
2024-07-29 04:48:21 +03:00
Alibek Omarov
da6586b847 ref: gl: fix white border around the screen in Base Defense mod 2024-07-28 23:58:09 +03:00
Alibek Omarov
4a5f34089d engine: client: fix TriColor4fRendermode 2024-07-28 20:50:20 +03:00
Alibek Omarov
90da9659d1 engine: client: vgui: enable texturing in VGUI by default, just in case reset color too 2024-07-28 20:03:32 +03:00
Alibek Omarov
2e30acf611 engine: client: voice: allow restoring voice after toggling voice_enable while connected to server 2024-07-28 17:12:32 +03:00
Alibek Omarov
5554d13f7f engine: client: fix buffer overflow in voice sound mixer 2024-07-28 16:41:20 +03:00
Alibek Omarov
a5ef33b302 mainui: update 2024-07-28 14:51:09 +03:00
Alibek Omarov
9a2588f7eb engine: client: console: fix a rare crash when we're in game, console is enabled but it's empty
With ui_allowconsole toggle it's easy to reproduce: join game without console, go to menu,
enable console and return back to game.
2024-07-28 14:48:40 +03:00
Alibek Omarov
cac5852e68 ref: enable multiplayer high defintion model in menu preview 2024-07-28 14:45:10 +03:00
Alibek Omarov
d52d50e283 engine: client: set user name as default value for name cvar. Add ui_username cvar with user name. 2024-07-28 14:44:03 +03:00
Alibek Omarov
6911da8581 engine: client: add ui_allowconsole command that enables console
To be used by UI
2024-07-28 13:32:52 +03:00
Alibek Omarov
e70f9a67b8 engine: host: always enable console for dedicated 2024-07-26 11:08:34 +03:00
Alibek Omarov
173aa7333a scripts: waifulib: vgui: add option to disable vgui platform support checks, try to lookup DEST_CPU subdirectories for prebuilt library 2024-07-24 07:04:53 +03:00
Alibek Omarov
2396b2d4db ref: gl: add VBO generating/uploading times 2024-07-22 22:24:19 +03:00
Alibek Omarov
6120c0daec engine: print command line args alongside developer level during init 2024-07-22 22:15:56 +03:00
Alibek Omarov
790f9bde54 engine: client: hack mobile API init because of incorrectly defined export in hlsdk-portable 2024-07-21 21:18:00 +03:00
Alibek Omarov
7a469fb481 engine: always use original player hulls for pmove trace, because mods can write invalid data in pmove->player_{mins,maxs} 2024-07-21 11:01:18 +03:00
Alibek Omarov
d4a2011a59 wscript: add configuration option for building xar 2024-07-21 05:36:58 +03:00
Alibek Omarov
9165832caf mainui: update 2024-07-21 05:34:23 +03:00
Владислав Сухов
d274a5c13c Documentation: supported-mod-list: added new supported mods (from mobile_hacks branch of hlsdk-portable) 2024-07-21 05:16:30 +03:00
Владислав Сухов
e6bd15c68b Documentation: supported-mod-list: fix dead links 2024-07-21 05:16:30 +03:00
Alibek Omarov
38bef99f98 engine: client: fix opening Quake demos 2024-07-21 05:01:31 +03:00
Alibek Omarov
95ff9e7165 engine: client: prevent empty lightstyle console flood 2024-07-21 05:01:16 +03:00
Alibek Omarov
2fddbdddee engine: client: fix ScreenFade under quake compatibility mode 2024-07-21 04:33:46 +03:00
Alibek Omarov
465e812ed9 engine: client: fix EF_DIMLIGHT under quake compatibility mode 2024-07-21 04:33:31 +03:00
Alibek Omarov
3b1fb79a85 engine: client: use Host_IsQuakeCompatible instead of checking host.features bit 2024-07-21 04:32:38 +03:00
Alibek Omarov
0f8f35b415 engine: fix alias model loading 2024-07-21 04:15:56 +03:00
Alibek Omarov
a133b1c2a9 engine: remove unused texFlags argument in Mod_LoadSpriteModel 2024-07-21 03:04:21 +03:00
Alibek Omarov
fa74acb5f0 Revert "engine: client: make client engfuncs const"
This reverts commit 14ae9b312d.
2024-07-21 02:53:28 +03:00
Alibek Omarov
836b4c358f Revert "engine: server: make physic engfuncs const"
This reverts commit 5af9511505.
2024-07-21 02:53:23 +03:00
Alibek Omarov
982e32d108 engine: client: don't mistakingly tell user about failed mobile api, when it's just not used by client.dll 2024-07-21 02:07:38 +03:00
Alibek Omarov
024a335505 engine: move wcon definitions to platform.h 2024-07-21 02:06:51 +03:00
Alibek Omarov
963cbf61e4 filesystem: fix loading libraries from archives on Windows 2024-07-21 01:49:34 +03:00
Alibek Omarov
6d98d2c7c3 engine: check XASH3D_GAME if -game argument wasn't found, do not override default base directory
Clarify that `--gamedir` configure option and `XASH_GAMEDIR` macro specify base directory
2024-07-21 01:04:50 +03:00
Alibek Omarov
64726f13e1 engine: client: more accurate R_BeamKill reimplementation
Reverse engineered from HL25 hw.so
2024-07-19 07:13:14 +03:00
Alibek Omarov
85dfaaa2c2 engine: imagelib: add LUMP_TEXGAMMA palette kind to only pass HL textures through texgamma, not Quake 2024-07-19 06:34:51 +03:00
Alibek Omarov
42a915b04a wscript: enforce -Werror=format-extra-args 2024-07-18 01:28:35 +03:00
Alibek Omarov
42a8aa6c66 mainui: update 2024-07-18 01:27:30 +03:00
Alibek Omarov
56464d3291 engine: when colorizing standard output, use bold text, as it makes it more visible (especially with black text) 2024-07-17 22:53:35 +03:00
Alibek Omarov
aed96ee753 engine: common: reduce large static arrays amount for logging by adding generic function accepting va_list 2024-07-17 22:27:20 +03:00
Alibek Omarov
a937320c65 engine: wscript: add ffmpeg hidden option, just to make it easier for me to switch between branches 2024-07-17 22:27:20 +03:00
Alibek Omarov
a81a0cb059 engine: client: make menu engfuncs const 2024-07-16 15:23:03 +03:00
Alibek Omarov
5af9511505 engine: server: make physic engfuncs const 2024-07-16 15:23:03 +03:00
Alibek Omarov
14ae9b312d engine: client: make client engfuncs const 2024-07-16 15:23:03 +03:00
Alibek Omarov
2d3e5c2e0b engine: client: make renderer engfuncs const 2024-07-16 15:23:03 +03:00
Alibek Omarov
17950fec3e filesystem: make engfuncs const 2024-07-16 15:23:03 +03:00
Alibek Omarov
2009140da8 ref: make gReffuncs const 2024-07-16 15:23:03 +03:00
Alibek Omarov
2a394eee62 filesystem: make g_api const 2024-07-16 15:23:03 +03:00
Alibek Omarov
09a7585643 engine: soundlib: super micro-optimization, reallocate buffer in Image_Copy rather than allocating and copying 2024-07-16 05:11:06 +03:00
Alibek Omarov
a09084ceba engine: imagelib: super micro-optimization, reallocate buffer in Image_Copy rather than allocating and copying 2024-07-16 05:10:29 +03:00
Alibek Omarov
147e5dceff engine: request SDL to ungrab mouse before signaling debugger to stop 2024-07-16 05:09:02 +03:00
Alibek Omarov
3510afd30b engine: zone: allow moving allocation from one pool to another during realloc 2024-07-16 05:06:44 +03:00
Alibek Omarov
d3586c2143 engine: soundlib: add support for converting stereo to mono and back, attempt to simplify conversion boilerplate 2024-07-16 05:05:50 +03:00
209 changed files with 10458 additions and 4083 deletions

View File

@@ -43,80 +43,82 @@ jobs:
- os: windows-2019 # always use the oldest possible for 32-bit because of older compilers, and better support of certain legacy OSes
targetos: win32
targetarch: i386
- os: macos-14 # in GitHub documentation, it's an ARM64 machine
targetos: apple
targetarch: arm64
- os: macos-12 # in GitHub documentation, it's an x86 machine
targetos: apple
targetarch: amd64
env:
SDL_VERSION: 2.30.3
GH_CPU_ARCH: ${{ matrix.targetarch }}
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install dependencies
run: bash scripts/gha/deps_${{ matrix.targetos }}.sh
- name: Build engine
env:
FWGS_PFX_PASSWORD: ${{ secrets.FWGS_PFX_PASSWORD }}
run: bash scripts/gha/build_${{ matrix.targetos }}.sh
- name: Upload engine (artifacts)
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: artifact-${{ matrix.targetos }}-${{ matrix.targetarch }}
path: artifacts/*
flatpak:
name: "Flatpak"
runs-on: ubuntu-latest
strategy:
matrix:
include:
- app: su.xash.Engine.Compat.i386
container:
image: bilelmoussaoui/flatpak-github-actions:freedesktop-22.08
image: bilelmoussaoui/flatpak-github-actions:freedesktop-23.08
options: --privileged
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: recursive
- name: Build flatpak (Compat.i386)
uses: FWGS/flatpak-github-actions/flatpak-builder@v6.1
uses: FWGS/flatpak-github-actions/flatpak-builder@v6.3
with:
bundle: ${{ matrix.app }}.flatpak
manifest-path: scripts/flatpak/${{ matrix.app }}.yml
- name: Upload engine (artifacts)
uses: actions/upload-artifact@v3
with:
name: artifact-${{ matrix.targetos }}-${{ matrix.targetarch }}
path: artifacts/*
release:
name: "Upload releases"
runs-on: ubuntu-latest
needs: [build, flatpak]
if: ${{ github.event_name == 'push' }}
steps:
- name: Remove old release
uses: FWGS/delete-tag-and-release@v0.2.1-dev
with:
tag_name: ${{ github.ref_name == 'master' && 'continuous' || format('continuous-{0}', github.ref_name) }}
delete_release: true
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Fetch artifacts
uses: actions/download-artifact@v3.0.1
with:
path: artifacts/
- name: Repackage binaries and allow GitHub to process removed release for few seconds
- name: Remove old release, fetch artifacts, repackage binaries and upload new release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_TAG: ${{ github.ref_name == 'master' && 'continuous' || format('continuous-{0}', github.ref_name) }}
run: |
cd artifacts/
for i in artifact-* su.xash.Engine.*; do
gh release delete "$RELEASE_TAG" \
--yes \
--cleanup-tag \
--repo "$GITHUB_REPOSITORY" || true
sleep 20s
gh run download "$GITHUB_RUN_ID" \
--dir artifacts/ \
--repo "$GITHUB_REPOSITORY"
pushd artifacts/
echo "Found artifacts:"
ls
for i in $(find -mindepth 1 -maxdepth 1 -type d); do
mv "$i"/* .
rm -rf "$i"
done
ls -R .
cd ../
echo "Repackaged artifacts:"
ls -R
popd
sleep 20s
- name: Upload new release
uses: FWGS/action-gh-release@v0.1.15
with:
name: Xash3D FWGS Continuous ${{ github.ref_name }} Build
tag_name: ${{ github.ref_name == 'master' && 'continuous' || format('continuous-{0}', github.ref_name) }}
prerelease: true
token: ${{ secrets.GITHUB_TOKEN }}
files: artifacts/*
draft: false
gh release create "$RELEASE_TAG" artifacts/* \
--title "Xash3D FWGS Continuous ${{ github.ref_name }} Build" \
--target $GITHUB_SHA \
--repo "$GITHUB_REPOSITORY" \
--prerelease

3
.gitmodules vendored
View File

@@ -19,3 +19,6 @@
[submodule "3rdparty/xash-extras"]
path = 3rdparty/extras/xash-extras
url = https://github.com/FWGS/xash-extras
[submodule "3rdparty/bzip2/bzip2"]
path = 3rdparty/bzip2/bzip2
url = https://gitlab.com/bzip2/bzip2

21
3rdparty/MultiEmulator/LICENSE vendored Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2017-2018 Alexander Belkin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

25
3rdparty/MultiEmulator/README.md vendored Normal file
View File

@@ -0,0 +1,25 @@
# MultiEmulator
**MultiEmulator** - project for GoldSource Engine, which provides ability to generate tickets with a specific SteamID key, using all available emulators for this engine.
Ticket is processed by the game server of Half-Life 1 and modifications using **DProto** or **ReUnion** modules. If the server does not have these modules, then MultiEmulator won't work.
# Ticket generators
Currently available ticket generators:
* OldRevEmu
* AVSMP
* Setti
* SteamEmu
* RevEmu
* SC2009
* RevEmu2013
Currently under development generators:
* SmartSteamEmu (SSE3)
# How to use?
Each file in the **MultiEmulator\Source\Emulators** folder contains a **Generate** function that writes a ticket to the **pDest** argument for the emulator of the same name as a header file. As a result of the function, the size of the written ticket is returned. If the generator can set an arbitrary SteamID, the function will have the **nSteamID** argument, in which the required SteamID is specified.
# Examples
As an example, the DLL was developed that searches InitiateGameConnection method in ISteamUser interface, which generates Steam ticket, and inserts in its place own generator, which creates RevEmu2013 ticket with SteamID equal to 3333333. You can find this project in **Example** folder, you just need to compile it and perform DLL injection in hl.exe process with any known injection method.

View File

@@ -0,0 +1,37 @@
#ifndef MULTI_EMULATOR_H
#define MULTI_EMULATOR_H
#if defined( __GNUC__ )
#if defined( __i386__ )
#define ME_EXPORT __attribute__(( visibility( "default" ), force_align_arg_pointer ))
#else
#define ME_EXPORT __attribute__(( visibility ( "default" )))
#endif
#else
#if defined( _MSC_VER )
#define ME_EXPORT __declspec( dllexport )
#else
#define ME_EXPORT
#endif
#endif
#include <string.h>
#if __cplusplus
extern "C"
{
#endif
int ME_EXPORT GenerateRevEmu2013( void *pDest, int nSteamID );
int ME_EXPORT GenerateSC2009( void *pDest, int nSteamID );
int ME_EXPORT GenerateOldRevEmu( void *pDest, int nSteamID );
int ME_EXPORT GenerateSteamEmu( void *pDest, int nSteamID );
int ME_EXPORT GenerateRevEmu( void *pDest, int nSteamID );
int ME_EXPORT GenerateSetti( void *pDest );
int ME_EXPORT GenerateAVSMP( void *pDest, int nSteamID, int bUniverse );
#if __cplusplus
}
#endif
#endif // MULTI_EMULATOR_H

13
3rdparty/MultiEmulator/src/AVSMP.cpp vendored Normal file
View File

@@ -0,0 +1,13 @@
#include "multi_emulator.h"
/* bUniverse param is "y" value in "STEAM_x:y:z" */
int GenerateAVSMP(void *pDest, int nSteamID, int bUniverse)
{
auto pTicket = (int *)pDest;
pTicket[0] = 0x14; // +0, header
pTicket[3] = (nSteamID << 1) | (bUniverse ? 1 : 0); // +12, SteamId, Low part
pTicket[4] = 0x01100001; // +16, SteamId, High part
return 28;
}

1376
3rdparty/MultiEmulator/src/CRijndael.cpp vendored Normal file

File diff suppressed because it is too large Load Diff

187
3rdparty/MultiEmulator/src/CRijndael.h vendored Normal file
View File

@@ -0,0 +1,187 @@
#ifndef __RIJNDAEL_H__
#define __RIJNDAEL_H__
#include <exception>
#include <stdexcept>
#include <cstring>
#include <string>
using namespace std;
//Rijndael (pronounced Reindaal) is a block cipher, designed by Joan Daemen and Vincent Rijmen as a candidate algorithm for the AES.
//The cipher has a variable block length and key length. The authors currently specify how to use keys with a length
//of 128, 192, or 256 bits to encrypt blocks with al length of 128, 192 or 256 bits (all nine combinations of
//key length and block length are possible). Both block length and key length can be extended very easily to
// multiples of 32 bits.
//Rijndael can be implemented very efficiently on a wide range of processors and in hardware.
//This implementation is based on the Java Implementation used with the Cryptix toolkit found at:
//http://www.esat.kuleuven.ac.be/~rijmen/rijndael/rijndael.zip
//Java code authors: Raif S. Naffah, Paulo S. L. M. Barreto
//This Implementation was tested against KAT test published by the authors of the method and the
//results were identical.
class CRijndael
{
public:
//Operation Modes
//The Electronic Code Book (ECB), Cipher Block Chaining (CBC) and Cipher Feedback Block (CFB) modes
//are implemented.
//In ECB mode if the same block is encrypted twice with the same key, the resulting
//ciphertext blocks are the same.
//In CBC Mode a ciphertext block is obtained by first xoring the
//plaintext block with the previous ciphertext block, and encrypting the resulting value.
//In CFB mode a ciphertext block is obtained by encrypting the previous ciphertext block
//and xoring the resulting value with the plaintext.
enum { ECB = 0, CBC = 1, CFB = 2 };
private:
enum { DEFAULT_BLOCK_SIZE = 16 };
enum { MAX_BLOCK_SIZE = 32, MAX_ROUNDS = 14, MAX_KC = 8, MAX_BC = 8 };
//Auxiliary Functions
//Multiply two elements of GF(2^m)
static int Mul(int a, int b)
{
return (a != 0 && b != 0) ? sm_alog[(sm_log[a & 0xFF] + sm_log[b & 0xFF]) % 255] : 0;
}
//Convenience method used in generating Transposition Boxes
static int Mul4(int a, char b[])
{
if (a == 0)
return 0;
a = sm_log[a & 0xFF];
int a0 = (b[0] != 0) ? sm_alog[(a + sm_log[b[0] & 0xFF]) % 255] & 0xFF : 0;
int a1 = (b[1] != 0) ? sm_alog[(a + sm_log[b[1] & 0xFF]) % 255] & 0xFF : 0;
int a2 = (b[2] != 0) ? sm_alog[(a + sm_log[b[2] & 0xFF]) % 255] & 0xFF : 0;
int a3 = (b[3] != 0) ? sm_alog[(a + sm_log[b[3] & 0xFF]) % 255] & 0xFF : 0;
return a0 << 24 | a1 << 16 | a2 << 8 | a3;
}
public:
//CONSTRUCTOR
CRijndael();
//DESTRUCTOR
virtual ~CRijndael();
//Expand a user-supplied key material into a session key.
// key - The 128/192/256-bit user-key to use.
// chain - initial chain block for CBC and CFB modes.
// keylength - 16, 24 or 32 bytes
// blockSize - The block size in bytes of this Rijndael (16, 24 or 32 bytes).
void MakeKey(char const* key, char const* chain, int keylength = DEFAULT_BLOCK_SIZE, int blockSize = DEFAULT_BLOCK_SIZE);
private:
//Auxiliary Function
void Xor(char* buff, char const* chain)
{
if (false == m_bKeyInit)
throw runtime_error(sm_szErrorMsg1);
for (int i = 0; i<m_blockSize; i++)
*(buff++) ^= *(chain++);
}
//Convenience method to encrypt exactly one block of plaintext, assuming
//Rijndael's default block size (128-bit).
// in - The plaintext
// result - The ciphertext generated from a plaintext using the key
void DefEncryptBlock(char const* in, char* result);
//Convenience method to decrypt exactly one block of plaintext, assuming
//Rijndael's default block size (128-bit).
// in - The ciphertext.
// result - The plaintext generated from a ciphertext using the session key.
void DefDecryptBlock(char const* in, char* result);
public:
//Encrypt exactly one block of plaintext.
// in - The plaintext.
// result - The ciphertext generated from a plaintext using the key.
void EncryptBlock(char const* in, char* result);
//Decrypt exactly one block of ciphertext.
// in - The ciphertext.
// result - The plaintext generated from a ciphertext using the session key.
void DecryptBlock(char const* in, char* result);
void Encrypt(char const* in, char* result, size_t n, int iMode = ECB);
void Decrypt(char const* in, char* result, size_t n, int iMode = ECB);
//Get Key Length
int GetKeyLength()
{
if (false == m_bKeyInit)
throw runtime_error(sm_szErrorMsg1);
return m_keylength;
}
//Block Size
int GetBlockSize()
{
if (false == m_bKeyInit)
throw runtime_error(sm_szErrorMsg1);
return m_blockSize;
}
//Number of Rounds
int GetRounds()
{
if (false == m_bKeyInit)
throw runtime_error(sm_szErrorMsg1);
return m_iROUNDS;
}
void ResetChain()
{
memcpy(m_chain, m_chain0, m_blockSize);
}
public:
//Null chain
static char const* sm_chain0;
private:
static const int sm_alog[256];
static const int sm_log[256];
static const char sm_S[256];
static const char sm_Si[256];
static const int sm_T1[256];
static const int sm_T2[256];
static const int sm_T3[256];
static const int sm_T4[256];
static const int sm_T5[256];
static const int sm_T6[256];
static const int sm_T7[256];
static const int sm_T8[256];
static const int sm_U1[256];
static const int sm_U2[256];
static const int sm_U3[256];
static const int sm_U4[256];
static const char sm_rcon[30];
static const int sm_shifts[3][4][2];
//Error Messages
static char const* sm_szErrorMsg1;
static char const* sm_szErrorMsg2;
//Key Initialization Flag
bool m_bKeyInit;
//Encryption (m_Ke) round key
int m_Ke[MAX_ROUNDS + 1][MAX_BC];
//Decryption (m_Kd) round key
int m_Kd[MAX_ROUNDS + 1][MAX_BC];
//Key Length
int m_keylength;
//Block Size
int m_blockSize;
//Number of Rounds
int m_iROUNDS;
//Chain Block
char m_chain0[MAX_BLOCK_SIZE];
char m_chain[MAX_BLOCK_SIZE];
//Auxiliary private use buffers
int tk[MAX_KC];
int a[MAX_BC];
int t[MAX_BC];
};
#endif // __RIJNDAEL_H__

View File

@@ -0,0 +1,128 @@
//DoubleBuffering.cpp Source File
#include "DoubleBuffering.h"
#include <cassert>
#include <exception>
#include <string.h>
using namespace std;
CDoubleBuffering::CDoubleBuffering(ifstream& in, char* pcBuff, int iSize, int iDataLen) : m_rin(in),
m_iDataLen(iDataLen), m_bEOF(false), m_iSize(iSize), m_iSize2(iSize >> 1), m_pcBuff(pcBuff)
{
//m_iSize should be even
if(m_iSize%2 != 0)
throw runtime_error("CDoubleBuffering: m_iSize should be Even Number!");
//Check file
if(!in.is_open() || in.bad())
throw runtime_error("CDoubleBuffering: Referenced File not Opened or in Bad State!");
//Check construction data
if(m_iDataLen<1 || m_iSize2<m_iDataLen)
throw runtime_error("CDoubleBuffering: Illegal Construction Data!");
in.read(m_pcBuff, m_iSize2);
m_iEnd = m_rin.gcount();
m_iCurPos = 0;
m_iBuf = 0;
}
int CDoubleBuffering::GetData(char* pszDataBuf, int iDataLen)
{
if(-1 == iDataLen)
iDataLen = m_iDataLen;
if(iDataLen<1 || m_iSize2<iDataLen)
throw runtime_error("CDoubleBuffering::GetData(): Illegal iDataLen!");
if(true == m_bEOF)
return 0;
//Estimate the next position
int iCurPos = m_iCurPos + iDataLen;
if(0 == m_iBuf) //First Buffer
{
if(iCurPos >= m_iEnd)
{
//Read the next buffer
if(m_rin.eof())
{
m_bEOF = true;
//Take everything remained
int iRead = m_iEnd-m_iCurPos;
memcpy(pszDataBuf, m_pcBuff+m_iCurPos, iRead);
return iRead;
}
else
{
m_rin.read(m_pcBuff+m_iEnd, m_iSize2);
m_iEnd += m_rin.gcount();
if(iCurPos > m_iEnd) //Still greater, then EOF attained
{
assert(m_rin.eof());
m_bEOF = true;
//Take everything remained
int iRead = m_iEnd-m_iCurPos;
memcpy(pszDataBuf, m_pcBuff+m_iCurPos, iRead);
return iRead;
}
else
{
memcpy(pszDataBuf, m_pcBuff+m_iCurPos, iDataLen);
m_iCurPos = iCurPos;
assert(m_iCurPos >= m_iSize2);
m_iBuf = 1;
return iDataLen;
}
}
}
else
{
memcpy(pszDataBuf, m_pcBuff+m_iCurPos, iDataLen);
m_iCurPos = iCurPos;
return iDataLen;
}
}
else //1 == m_iBuf, Second Buffer
{
if(iCurPos >= m_iEnd)
{
//Read the next buffer
if(m_rin.eof())
{
m_bEOF = true;
//Take everything remained
int iRead = m_iEnd-m_iCurPos;
memcpy(pszDataBuf, m_pcBuff+m_iCurPos, iRead);
return iRead;
}
else
{
m_rin.read(m_pcBuff, m_iSize2);
m_iEnd = m_rin.gcount();
iCurPos %= m_iSize;
if(iCurPos > m_iEnd) //Still greater, then EOF attained
{
assert(m_rin.eof());
m_bEOF = true;
//Take everything remained
int iRead = m_iSize-m_iCurPos;
memcpy(pszDataBuf, m_pcBuff+m_iCurPos, iRead);
memcpy(pszDataBuf+iRead, m_pcBuff, m_iEnd);
return iRead + m_iEnd;
}
else
{
int iRead = m_iSize-m_iCurPos;
memcpy(pszDataBuf, m_pcBuff+m_iCurPos, iRead);
memcpy(pszDataBuf+iRead, m_pcBuff, iDataLen-iRead);
m_iCurPos = iCurPos;
assert(m_iCurPos < m_iSize2);
m_iBuf = 0;
return iDataLen;
}
}
}
else
{
memcpy(pszDataBuf, m_pcBuff+m_iCurPos, iDataLen);
m_iCurPos = iCurPos;
return iDataLen;
}
}
}

View File

@@ -0,0 +1,40 @@
//DoubleBuffering.h Header File
#ifndef __DOUBLEBUFFERING_H__
#define __DOUBLEBUFFERING_H__
//Typical DISCLAIMER:
//The code in this project is Copyright (C) 2003 by George Anescu. You have the right to
//use and distribute the code in any way you see fit as long as this paragraph is included
//with the distribution. No warranties or claims are made as to the validity of the
//information and code contained herein, so use it at your own risk.
#include <fstream>
using namespace std;
class CDoubleBuffering
{
public:
//Constructor
CDoubleBuffering(ifstream& in, char* pcBuff, int iSize, int iDataLen);
//Get Next Data Buffer
int GetData(char* pszDataBuf, int iDataLen=-1);
private:
ifstream& m_rin;
int m_iSize;
int m_iSize2; //m_iSize/2
int m_iDataLen;
//Current Position
int m_iCurPos;
//End Position
int m_iEnd;
//Which Buffer
int m_iBuf;
char* m_pcBuff;
//EOF attained
bool m_bEOF;
};
#endif //__DOUBLEBUFFERING_H__

View File

@@ -0,0 +1,38 @@
//MessageDigest.cpp
#include "MessageDigest.h"
#include "DoubleBuffering.h"
#include <exception>
#include <fstream>
#include <strstream>
using namespace std;
//Digesting a Full File
void IMessageDigest::DigestFile(string const& rostrFileIn, char* pcDigest)
{
//Is the User's responsability to ensure that pcDigest is appropriately allocated
//Open Input File
ifstream in(rostrFileIn.c_str(), ios::binary);
if(!in)
{
ostrstream ostr;
ostr << "FileDigest ERROR: in IMessageDigest::DigestFile(): Cannot open File " << rostrFileIn << "!" << ends;
string ostrMsg = ostr.str();
ostr.freeze(false);
throw runtime_error(ostrMsg);
}
//Resetting first
Reset();
//Reading from file
char szLargeBuff[BUFF_LEN+1] = {0};
char szBuff[DATA_LEN+1] = {0};
CDoubleBuffering oDoubleBuffering(in, szLargeBuff, BUFF_LEN, DATA_LEN);
int iRead;
while((iRead=oDoubleBuffering.GetData(szBuff)) > 0)
AddData(szBuff, iRead);
in.close();
//Final Step
FinalDigest(pcDigest);
}

View File

@@ -0,0 +1,47 @@
//MessageDigest.h
#ifndef __MESSAGEDIGEST_H__
#define __MESSAGEDIGEST_H__
#include <string>
using namespace std;
//Typical DISCLAIMER:
//The code in this project is Copyright (C) 2003 by George Anescu. You have the right to
//use and distribute the code in any way you see fit as long as this paragraph is included
//with the distribution. No warranties or claims are made as to the validity of the
//information and code contained herein, so use it at your own risk.
//General Message Digest Interface
class IMessageDigest
{
public:
//CONSTRUCTOR
IMessageDigest() : m_bAddData(false) {}
//DESTRUCTOR
virtual ~IMessageDigest() {}
//Update context to reflect the concatenation of another buffer of bytes
virtual void AddData(char const* pcData, int iDataLength) = 0;
//Final wrapup - pad to BLOCKSIZE-byte boundary with the bit pattern
//10000...(64-bit count of bits processed, MSB-first)
virtual void FinalDigest(char* pcDigest) = 0;
//Reset current operation in order to prepare for a new one
virtual void Reset() = 0;
//Digesting a Full File
void DigestFile(string const& rostrFileIn, char* pcDigest);
protected:
enum { BLOCKSIZE=64 };
//Control Flag
bool m_bAddData;
//The core of the MessageDigest algorithm, this alters an existing MessageDigest hash to
//reflect the addition of 64 bytes of new data
virtual void Transform() = 0;
private:
enum { DATA_LEN=384, BUFF_LEN=1024 };
};
#endif // __MESSAGEDIGEST_H__

View File

@@ -0,0 +1,13 @@
#include "multi_emulator.h"
int GenerateOldRevEmu(void* pDest, int nSteamID)
{
auto pTicket = (int*)pDest;
auto pbTicket = (unsigned char*)pDest;
pTicket[0] = 0xFFFF; // +0, header
pTicket[1] = (nSteamID ^ 0xC9710266) << 1; // +4, SteamId
*(short *)&pbTicket[8] = 0; // +8, unknown, in original emulator must be 0
return 10;
}

27
3rdparty/MultiEmulator/src/RevEmu.cpp vendored Normal file
View File

@@ -0,0 +1,27 @@
#include "multi_emulator.h"
#include "StrUtils.h"
#include "RevSpoofer.h"
int GenerateRevEmu(void *pDest, int nSteamID)
{
char szhwid[64];
CreateRandomString(szhwid, 16);
if (!RevSpoofer::Spoof(szhwid, nSteamID))
return 0;
auto pTicket = (int *)pDest;
auto revHash = RevSpoofer::Hash(szhwid);
pTicket[0] = 'J'; // +0, header
pTicket[1] = revHash; // +4, hash of string at +24 offset
pTicket[2] = 'r' << 16 | 'e' << 8 | 'v';// +8, magic number
pTicket[3] = 0; // +12, unknown number, must always be 0
pTicket[4] = revHash << 1; // +16, SteamId, Low part
pTicket[5] = 0x01100001; // +20, SteamId, High part
strcpy((char *)&pTicket[6], szhwid); // +24, string for hash
return 152;
}

View File

@@ -0,0 +1,55 @@
#include "multi_emulator.h"
#include "StrUtils.h"
#include "RevSpoofer.h"
#include "CRijndael.h"
#include "SHA.h"
#include <time.h>
int GenerateRevEmu2013(void *pDest, int nSteamID)
{
char szhwid[64];
CreateRandomString(szhwid, 32);
if (!RevSpoofer::Spoof(szhwid, nSteamID))
return 0;
auto pTicket = (int *)pDest;
auto pbTicket = (unsigned char *)pDest;
auto revHash = RevSpoofer::Hash(szhwid);
pTicket[0] = 'S'; // +0
pTicket[1] = revHash; // +4
pTicket[2] = 'r' << 16 | 'e' << 8 | 'v';;// +8
pTicket[3] = 0; // +12
pTicket[4] = revHash << 1; // +16
pTicket[5] = 0x01100001; // +20
pTicket[6] = (int)time(0) + 90123; // +24
pbTicket[27] = ~(pbTicket[27] + pbTicket[24]);
pTicket[7] = ~(int)time(0); // +28
pTicket[8] = revHash * 2 >> 3; // +32
pTicket[9] = 0; // +36
static const char c_szAESKeyRand[] = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
char szAESHashRand[32];
auto AESRand = CRijndael();
AESRand.MakeKey(c_szAESKeyRand, CRijndael::sm_chain0, 32, 32);
AESRand.EncryptBlock(szhwid, szAESHashRand);
memcpy(&pbTicket[40], szAESHashRand, 32);
static const char c_szAESKeyRev[] = "_YOU_SERIOUSLY_NEED_TO_GET_LAID_";
char AESHashRev[32];
auto AESRev = CRijndael();
AESRev.MakeKey(c_szAESKeyRev, CRijndael::sm_chain0, 32, 32);
AESRev.EncryptBlock(c_szAESKeyRand, AESHashRev);
memcpy(&pbTicket[72], AESHashRev, 32);
char szSHAHash[32];
auto sha = CSHA(CSHA::SHA256);
sha.AddData(szhwid, 32);
sha.FinalDigest(szSHAHash);
memcpy(&pbTicket[104], szSHAHash, 32);
return 194;
}

View File

@@ -0,0 +1,96 @@
#include "RevSpoofer.h"
#include <string.h>
#define astrlen(x) sizeof(x) - 1
static char s_szDictionary[] = { "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" };
static int iInputLen;
static unsigned int uTreasure;
bool ScanLast3(char *pszInput, unsigned int uPrevHash)
{
unsigned int h1, h2, h3, hh;
for (int i1 = 0; i1 < astrlen(s_szDictionary); i1++)
{
h1 = uPrevHash ^ ((uPrevHash >> 2) + (uPrevHash << 5) + s_szDictionary[i1]);
hh = h1 ^ ((h1 >> 2) + (h1 << 5));
hh = hh ^ ((hh >> 2) + (hh << 5));
if ((hh ^ uTreasure) >> (8 + 5 + 3))
continue;
for (int i2 = 0; i2 < astrlen(s_szDictionary); i2++)
{
h2 = h1 ^ ((h1 >> 2) + (h1 << 5) + s_szDictionary[i2]);
hh = h2 ^ ((h2 >> 2) + (h2 << 5));
if ((hh ^ uTreasure) >> (8 + 3))
continue;
for (int i3 = 0; i3 < astrlen(s_szDictionary); i3++)
{
h3 = h2 ^ ((h2 >> 2) + (h2 << 5) + s_szDictionary[i3]);
if (h3 == uTreasure)
{
pszInput[iInputLen - 3] = s_szDictionary[i1];
pszInput[iInputLen - 2] = s_szDictionary[i2];
pszInput[iInputLen - 1] = s_szDictionary[i3];
return true;
}
}
}
}
return false;
}
bool ScanNext(char* pszInput, int uIndex, unsigned int uPrevHash)
{
bool res;
for (int i = 0; i < astrlen(s_szDictionary); i++)
{
auto h = uPrevHash ^ ((uPrevHash >> 2) + (uPrevHash << 5) + s_szDictionary[i]);
if (uIndex + 1 < iInputLen - 3)
res = ScanNext(pszInput, uIndex + 1, h);
else
res = ScanLast3(pszInput, h);
if (res)
{
pszInput[uIndex] = s_szDictionary[i];
return true;
}
}
return false;
}
namespace RevSpoofer
{
bool Spoof(char *pszDest, int uSID)
{
uTreasure = uSID;
iInputLen = strlen(pszDest);
auto i = iInputLen - 7;
i = (i < 0) ? 0 : i;
pszDest[i] = '\0';
auto h = Hash(pszDest);
return ScanNext(pszDest, i, h);
}
unsigned int Hash(char *pszString)
{
int i = 0;
unsigned int nHash = 0x4E67C6A7;
int c = pszString[i++];
while (c)
{
nHash = nHash ^ ((nHash >> 2) + (nHash << 5) + c);
c = pszString[i++];
}
return nHash;
}
}

View File

@@ -0,0 +1,7 @@
#pragma once
namespace RevSpoofer
{
bool Spoof(char *pszDest, int uSID);
unsigned int Hash(char *pszString);
}

52
3rdparty/MultiEmulator/src/SC2009.cpp vendored Normal file
View File

@@ -0,0 +1,52 @@
#include "multi_emulator.h"
#include "StrUtils.h"
#include "RevSpoofer.h"
#include "CRijndael.h"
#include "SHA.h"
int GenerateSC2009(void* pDest, int nSteamID)
{
char hwid[64];
CreateRandomString(hwid, 32);
if (!RevSpoofer::Spoof(hwid, nSteamID))
return 0;
auto pTicket = (int*)pDest;
auto pbTicket = (unsigned char*)pDest;
auto revHash = RevSpoofer::Hash(hwid);
pTicket[0] = 'S'; // +0
pTicket[1] = revHash; // +4
pTicket[2] = 'r' << 16 | 'e' << 8 | 'v';;// +8
pTicket[3] = 0; // +12
pTicket[4] = revHash << 1; // +16
pTicket[5] = 0x01100001; // +20
/* Encrypt HWID with AESKeyRand key and save it in the ticket. */
static const char AESKeyRand[] = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
char AESHashRand[32];
auto AESRand = CRijndael();
AESRand.MakeKey(AESKeyRand, CRijndael::sm_chain0, 32, 32);
AESRand.EncryptBlock(hwid, AESHashRand);
memcpy(&pbTicket[24], AESHashRand, 32);
/* Encrypt AESKeyRand with AESKeyRev key and save it in the ticket.
* AESKeyRev key is identical to the key in dproto/reunion. */
static const char AESKeyRev[] = "_YOU_SERIOUSLY_NEED_TO_GET_LAID_";
char AESHashRev[32];
auto AESRev = CRijndael();
AESRev.MakeKey(AESKeyRev, CRijndael::sm_chain0, 32, 32);
AESRev.EncryptBlock(AESKeyRand, AESHashRev);
memcpy(&pbTicket[56], AESHashRev, 32);
/* Perform HWID hashing and save hash to the ticket. */
char SHAHash[32];
auto sha = CSHA(CSHA::SHA256);
sha.AddData(hwid, 32);
sha.FinalDigest(SHAHash);
memcpy(&pbTicket[88], SHAHash, 32);
return 178;
}

734
3rdparty/MultiEmulator/src/SHA.cpp vendored Normal file
View File

@@ -0,0 +1,734 @@
//SHA.cpp
#include "SHA.h"
#include <exception>
#include <strstream>
#include <string.h>
using namespace std;
const unsigned int CSHA::sm_K160[4] =
{
0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6
};
const unsigned int CSHA::sm_H160[SHA160LENGTH] =
{
0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0
};
const unsigned int CSHA::sm_K256[64] =
{
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
const unsigned int CSHA::sm_H256[SHA256LENGTH] =
{
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
};
const SUI64 CSHA::sm_H384[SHA512LENGTH] =
{
{0xcbbb9d5d, 0xc1059ed8},
{0x629a292a, 0x367cd507},
{0x9159015a, 0x3070dd17},
{0x152fecd8, 0xf70e5939},
{0x67332667, 0xffc00b31},
{0x8eb44a87, 0x68581511},
{0xdb0c2e0d, 0x64f98fa7},
{0x47b5481d, 0xbefa4fa4}
};
const SUI64 CSHA::sm_K512[80] =
{
{0x428a2f98, 0xd728ae22}, {0x71374491, 0x23ef65cd},
{0xb5c0fbcf, 0xec4d3b2f}, {0xe9b5dba5, 0x8189dbbc},
{0x3956c25b, 0xf348b538}, {0x59f111f1, 0xb605d019},
{0x923f82a4, 0xaf194f9b}, {0xab1c5ed5, 0xda6d8118},
{0xd807aa98, 0xa3030242}, {0x12835b01, 0x45706fbe},
{0x243185be, 0x4ee4b28c}, {0x550c7dc3, 0xd5ffb4e2},
{0x72be5d74, 0xf27b896f}, {0x80deb1fe, 0x3b1696b1},
{0x9bdc06a7, 0x25c71235}, {0xc19bf174, 0xcf692694},
{0xe49b69c1, 0x9ef14ad2}, {0xefbe4786, 0x384f25e3},
{0x0fc19dc6, 0x8b8cd5b5}, {0x240ca1cc, 0x77ac9c65},
{0x2de92c6f, 0x592b0275}, {0x4a7484aa, 0x6ea6e483},
{0x5cb0a9dc, 0xbd41fbd4}, {0x76f988da, 0x831153b5},
{0x983e5152, 0xee66dfab}, {0xa831c66d, 0x2db43210},
{0xb00327c8, 0x98fb213f}, {0xbf597fc7, 0xbeef0ee4},
{0xc6e00bf3, 0x3da88fc2}, {0xd5a79147, 0x930aa725},
{0x06ca6351, 0xe003826f}, {0x14292967, 0x0a0e6e70},
{0x27b70a85, 0x46d22ffc}, {0x2e1b2138, 0x5c26c926},
{0x4d2c6dfc, 0x5ac42aed}, {0x53380d13, 0x9d95b3df},
{0x650a7354, 0x8baf63de}, {0x766a0abb, 0x3c77b2a8},
{0x81c2c92e, 0x47edaee6}, {0x92722c85, 0x1482353b},
{0xa2bfe8a1, 0x4cf10364}, {0xa81a664b, 0xbc423001},
{0xc24b8b70, 0xd0f89791}, {0xc76c51a3, 0x0654be30},
{0xd192e819, 0xd6ef5218}, {0xd6990624, 0x5565a910},
{0xf40e3585, 0x5771202a}, {0x106aa070, 0x32bbd1b8},
{0x19a4c116, 0xb8d2d0c8}, {0x1e376c08, 0x5141ab53},
{0x2748774c, 0xdf8eeb99}, {0x34b0bcb5, 0xe19b48a8},
{0x391c0cb3, 0xc5c95a63}, {0x4ed8aa4a, 0xe3418acb},
{0x5b9cca4f, 0x7763e373}, {0x682e6ff3, 0xd6b2b8a3},
{0x748f82ee, 0x5defb2fc}, {0x78a5636f, 0x43172f60},
{0x84c87814, 0xa1f0ab72}, {0x8cc70208, 0x1a6439ec},
{0x90befffa, 0x23631e28}, {0xa4506ceb, 0xde82bde9},
{0xbef9a3f7, 0xb2c67915}, {0xc67178f2, 0xe372532b},
{0xca273ece, 0xea26619c}, {0xd186b8c7, 0x21c0c207},
{0xeada7dd6, 0xcde0eb1e}, {0xf57d4f7f, 0xee6ed178},
{0x06f067aa, 0x72176fba}, {0x0a637dc5, 0xa2c898a6},
{0x113f9804, 0xbef90dae}, {0x1b710b35, 0x131c471b},
{0x28db77f5, 0x23047d84}, {0x32caab7b, 0x40c72493},
{0x3c9ebe0a, 0x15c9bebc}, {0x431d67c4, 0x9c100d4c},
{0x4cc5d4be, 0xcb3e42b6}, {0x597f299c, 0xfc657e2a},
{0x5fcb6fab, 0x3ad6faec}, {0x6c44198c, 0x4a475817}
};
const SUI64 CSHA::sm_H512[SHA512LENGTH] =
{
{0x6a09e667, 0xf3bcc908},
{0xbb67ae85, 0x84caa73b},
{0x3c6ef372, 0xfe94f82b},
{0xa54ff53a, 0x5f1d36f1},
{0x510e527f, 0xade682d1},
{0x9b05688c, 0x2b3e6c1f},
{0x1f83d9ab, 0xfb41bd6b},
{0x5be0cd19, 0x137e2179}
};
//CONSTRUCTOR
CSHA::CSHA(int iMethod)
{
//Check the method
switch(iMethod)
{
case SHA160:
{
for(int i=0; i<SHA160LENGTH; i++)
m_auiBuf[i] = sm_H160[i];
m_auiBits[0] = 0;
m_auiBits[1] = 0;
}
break;
case SHA256:
{
for(int i=0; i<SHA256LENGTH; i++)
m_auiBuf[i] = sm_H256[i];
m_auiBits[0] = 0;
m_auiBits[1] = 0;
}
break;
case SHA384:
{
for(int i=0; i<SHA512LENGTH; i++)
m_aoui64Buf[i] = sm_H384[i];
m_aoui64Bits[0].m_uiLeft = 0;
m_aoui64Bits[0].m_uiRight = 0;
m_aoui64Bits[1].m_uiLeft = 0;
m_aoui64Bits[1].m_uiRight = 0;
}
break;
case SHA512:
{
for(int i=0; i<SHA512LENGTH; i++)
m_aoui64Buf[i] = sm_H512[i];
m_aoui64Bits[0].m_uiLeft = 0;
m_aoui64Bits[0].m_uiRight = 0;
m_aoui64Bits[1].m_uiLeft = 0;
m_aoui64Bits[1].m_uiRight = 0;
}
break;
default:
{
ostrstream ostr;
ostr << "FileDigest ERROR: in CSHA() Constructor, Illegal Method " << iMethod << "!" << ends;
string ostrMsg = ostr.str();
ostr.freeze(false);
throw runtime_error(ostrMsg);
}
}
m_iMethod = iMethod;
}
//Update context to reflect the concatenation of another buffer of bytes.
void CSHA::AddData(char const* pcData, int iDataLength)
{
if(iDataLength < 0)
throw runtime_error(string("FileDigest ERROR: in CSHA::AddData(), Data Length should be >= 0!"));
unsigned int uiT;
switch(m_iMethod)
{
case SHA160:
case SHA256:
{
//Update bitcount
uiT = m_auiBits[0];
if((m_auiBits[0] = uiT + ((unsigned int)iDataLength << 3)) < uiT)
m_auiBits[1]++; //Carry from low to high
m_auiBits[1] += iDataLength >> 29;
uiT = (uiT >> 3) & (BLOCKSIZE-1); //Bytes already
//Handle any leading odd-sized chunks
if(uiT != 0)
{
unsigned char* puc = (unsigned char*)m_aucIn + uiT;
uiT = BLOCKSIZE - uiT;
if(iDataLength < uiT)
{
memcpy(puc, pcData, iDataLength);
return;
}
memcpy(puc, pcData, uiT);
Transform();
pcData += uiT;
iDataLength -= uiT;
}
//Process data in 64-byte chunks
while(iDataLength >= BLOCKSIZE)
{
memcpy(m_aucIn, pcData, BLOCKSIZE);
Transform();
pcData += BLOCKSIZE;
iDataLength -= BLOCKSIZE;
}
//Handle any remaining bytes of data
memcpy(m_aucIn, pcData, iDataLength);
}
break;
case SHA384:
case SHA512:
{
uiT = m_aoui64Bits[0].m_uiRight;
unsigned int uiU = m_aoui64Bits[0].m_uiLeft;
if((m_aoui64Bits[0].m_uiRight = uiT + ((unsigned int)iDataLength << 3)) < uiT)
m_aoui64Bits[0].m_uiLeft++; //Carry from low to high
unsigned int uiV = m_aoui64Bits[1].m_uiRight;
if((m_aoui64Bits[0].m_uiLeft += iDataLength >> 29) < uiU)
m_aoui64Bits[1].m_uiRight++;
if(m_aoui64Bits[1].m_uiRight < uiV)
m_aoui64Bits[1].m_uiLeft++;
uiT = (uiT >> 3) & (BLOCKSIZE2-1); //Bytes already
//Handle any leading odd-sized chunks
if(uiT != 0)
{
unsigned char* puc = (unsigned char*)m_aucIn + uiT;
uiT = BLOCKSIZE2 - uiT;
if(iDataLength < uiT)
{
memcpy(puc, pcData, iDataLength);
return;
}
memcpy(puc, pcData, uiT);
Transform();
pcData += uiT;
iDataLength -= uiT;
}
//Process data in 64-byte chunks
while(iDataLength >= BLOCKSIZE2)
{
memcpy(m_aucIn, pcData, BLOCKSIZE2);
Transform();
pcData += BLOCKSIZE2;
iDataLength -= BLOCKSIZE2;
}
//Handle any remaining bytes of data
memcpy(m_aucIn, pcData, iDataLength);
}
break;
}
//Set the flag
m_bAddData = true;
}
//Final wrapup - pad to 64-byte boundary with the bit pattern
//1 0*(64-bit count of bits processed, MSB-first)
void CSHA::FinalDigest(char* pcDigest)
{
//Is the User's responsability to ensure that pcDigest is properly allocated 20, 32,
//48 or 64 bytes, depending on the method
if(false == m_bAddData)
throw runtime_error(string("FileDigest ERROR: in CSHA::FinalDigest(), No data Added before call!"));
switch(m_iMethod)
{
case SHA160:
case SHA256:
{
unsigned int uiCount;
unsigned char *puc;
//Compute number of bytes mod 64
uiCount = (m_auiBits[0] >> 3) & (BLOCKSIZE-1);
//Set the first char of padding to 0x80. This is safe since there is
//always at least one byte free
puc = m_aucIn + uiCount;
*puc++ = 0x80;
//Bytes of padding needed to make 64 bytes
uiCount = BLOCKSIZE - uiCount - 1;
//Pad out to 56 mod 64
if(uiCount < 8)
{
//Two lots of padding: Pad the first block to 64 bytes
memset(puc, 0, uiCount);
Transform();
//Now fill the next block with 56 bytes
memset(m_aucIn, 0, BLOCKSIZE-8);
}
else
{
//Pad block to 56 bytes
memset(puc, 0, uiCount - 8);
}
//Append length in bits and transform
Word2Bytes(m_auiBits[1], &m_aucIn[BLOCKSIZE-8]);
Word2Bytes(m_auiBits[0], &m_aucIn[BLOCKSIZE-4]);
Transform();
switch(m_iMethod)
{
case SHA160:
{
for(int i=0; i<SHA160LENGTH; i++,pcDigest+=4)
Word2Bytes(m_auiBuf[i], reinterpret_cast<unsigned char*>(pcDigest));
}
break;
case SHA256:
{
for(int i=0; i<SHA256LENGTH; i++,pcDigest+=4)
Word2Bytes(m_auiBuf[i], reinterpret_cast<unsigned char*>(pcDigest));
}
break;
}
}
break;
case SHA384:
case SHA512:
{
unsigned char *puc;
//Compute number of bytes mod 128
unsigned int uiCount = (m_aoui64Bits[0].m_uiRight >> 3) & (BLOCKSIZE2-1);
//Set the first char of padding to 0x80. This is safe since there is
//always at least one byte free
puc = m_aucIn + uiCount;
*puc++ = 0x80;
//Bytes of padding needed to make 128 bytes
uiCount = BLOCKSIZE2 - uiCount - 1;
//Pad out to 112 mod 128
if(uiCount < 16)
{
//Two lots of padding: Pad the first block to 128 bytes
memset(puc, 0, uiCount);
Transform();
//Now fill the next block with 112 bytes
memset(m_aucIn, 0, BLOCKSIZE2-16);
}
else
{
//Pad block to 112 bytes
memset(puc, 0, uiCount - 16);
}
//Append length in bits and transform
Word2Bytes(m_aoui64Bits[1], &m_aucIn[BLOCKSIZE2-16]);
Word2Bytes(m_aoui64Bits[0], &m_aucIn[BLOCKSIZE2-8]);
Transform();
switch(m_iMethod)
{
case SHA384:
{
for(int i=0; i<SHA384LENGTH; i++,pcDigest+=8)
Word2Bytes(m_aoui64Buf[i], reinterpret_cast<unsigned char*>(pcDigest));
}
break;
case SHA512:
{
for(int i=0; i<SHA512LENGTH; i++,pcDigest+=8)
Word2Bytes(m_aoui64Buf[i], reinterpret_cast<unsigned char*>(pcDigest));
}
break;
}
}
break;
}
//Reinitialize
Reset();
}
//Reset current operation in order to prepare a new one
void CSHA::Reset()
{
//Reinitialize
switch(m_iMethod)
{
case SHA160:
{
for(int i=0; i<SHA160LENGTH; i++)
m_auiBuf[i] = sm_H160[i];
m_auiBits[0] = 0;
m_auiBits[1] = 0;
}
break;
case SHA256:
{
for(int i=0; i<SHA256LENGTH; i++)
m_auiBuf[i] = sm_H256[i];
m_auiBits[0] = 0;
m_auiBits[1] = 0;
}
break;
case SHA384:
{
for(int i=0; i<SHA512LENGTH; i++)
m_aoui64Buf[i] = sm_H384[i];
m_aoui64Bits[0].m_uiLeft = 0;
m_aoui64Bits[0].m_uiRight = 0;
m_aoui64Bits[1].m_uiLeft = 0;
m_aoui64Bits[1].m_uiRight = 0;
}
break;
case SHA512:
{
for(int i=0; i<SHA512LENGTH; i++)
m_aoui64Buf[i] = sm_H512[i];
m_aoui64Bits[0].m_uiLeft = 0;
m_aoui64Bits[0].m_uiRight = 0;
m_aoui64Bits[1].m_uiLeft = 0;
m_aoui64Bits[1].m_uiRight = 0;
}
}
//Reset the flag
m_bAddData = false;
}
//The core of the SHA algorithm, this alters an existing SHA hash to
//reflect the addition of 16 longwords of new data.
void CSHA::Transform()
{
switch(m_iMethod)
{
case SHA160:
{
//Expansion of m_aucIn
unsigned char* pucIn = m_aucIn;
unsigned int auiW[80];
int i;
for(i=0; i<16; i++,pucIn+=4)
Bytes2Word(pucIn, auiW[i]);
for(i=16; i<80; i++)
auiW[i] = CircularShift(1, auiW[i-3]^auiW[i-8]^auiW[i-14]^auiW[i-16]);
unsigned int temp;
unsigned int A, B, C, D, E;
A = m_auiBuf[0];
B = m_auiBuf[1];
C = m_auiBuf[2];
D = m_auiBuf[3];
E = m_auiBuf[4];
for(i=0; i<20; i++)
{
temp = CircularShift(5, A) + ((B & C) | ((~B) & D)) + E + auiW[i] + sm_K160[0];
E = D;
D = C;
C = CircularShift(30, B);
B = A;
A = temp;
}
for(i=20; i<40; i++)
{
temp = CircularShift(5, A) + (B ^ C ^ D) + E + auiW[i] + sm_K160[1];
E = D;
D = C;
C = CircularShift(30, B);
B = A;
A = temp;
}
for(i=40; i<60; i++)
{
temp = CircularShift(5, A) + ((B & C) | (B & D) | (C & D)) + E + auiW[i] + sm_K160[2];
E = D;
D = C;
C = CircularShift(30, B);
B = A;
A = temp;
}
for(i=60; i<80; i++)
{
temp = CircularShift(5, A) + (B ^ C ^ D) + E + auiW[i] + sm_K160[3];
E = D;
D = C;
C = CircularShift(30, B);
B = A;
A = temp;
}
m_auiBuf[0] += A;
m_auiBuf[1] += B;
m_auiBuf[2] += C;
m_auiBuf[3] += D;
m_auiBuf[4] += E;
}
break;
case SHA256:
{
//Expansion of m_aucIn
unsigned char* pucIn = m_aucIn;
unsigned int auiW[64];
int i;
for(i=0; i<16; i++,pucIn+=4)
Bytes2Word(pucIn, auiW[i]);
for(i=16; i<64; i++)
auiW[i] = sig1(auiW[i-2]) + auiW[i-7] + sig0(auiW[i-15]) + auiW[i-16];
//OR
//for(i=0; i<48; i++)
// auiW[i+16] = sig1(auiW[i+14]) + auiW[i+9] + sig0(auiW[i+1]) + auiW[i];
unsigned int a, b, c, d, e, f, g, h, t;
a = m_auiBuf[0];
b = m_auiBuf[1];
c = m_auiBuf[2];
d = m_auiBuf[3];
e = m_auiBuf[4];
f = m_auiBuf[5];
g = m_auiBuf[6];
h = m_auiBuf[7];
t = h + SIG1(e) + CH(e, f, g) + sm_K256[0] + auiW[0]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K256[1] + auiW[1]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K256[2] + auiW[2]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K256[3] + auiW[3]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K256[4] + auiW[4]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K256[5] + auiW[5]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K256[6] + auiW[6]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K256[7] + auiW[7]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K256[8] + auiW[8]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K256[9] + auiW[9]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K256[10] + auiW[10]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K256[11] + auiW[11]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K256[12] + auiW[12]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K256[13] + auiW[13]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K256[14] + auiW[14]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K256[15] + auiW[15]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K256[16] + auiW[16]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K256[17] + auiW[17]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K256[18] + auiW[18]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K256[19] + auiW[19]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K256[20] + auiW[20]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K256[21] + auiW[21]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K256[22] + auiW[22]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K256[23] + auiW[23]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K256[24] + auiW[24]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K256[25] + auiW[25]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K256[26] + auiW[26]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K256[27] + auiW[27]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K256[28] + auiW[28]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K256[29] + auiW[29]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K256[30] + auiW[30]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K256[31] + auiW[31]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K256[32] + auiW[32]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K256[33] + auiW[33]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K256[34] + auiW[34]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K256[35] + auiW[35]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K256[36] + auiW[36]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K256[37] + auiW[37]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K256[38] + auiW[38]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K256[39] + auiW[39]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K256[40] + auiW[40]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K256[41] + auiW[41]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K256[42] + auiW[42]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K256[43] + auiW[43]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K256[44] + auiW[44]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K256[45] + auiW[45]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K256[46] + auiW[46]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K256[47] + auiW[47]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K256[48] + auiW[48]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K256[49] + auiW[49]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K256[50] + auiW[50]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K256[51] + auiW[51]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K256[52] + auiW[52]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K256[53] + auiW[53]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K256[54] + auiW[54]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K256[55] + auiW[55]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K256[56] + auiW[56]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K256[57] + auiW[57]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K256[58] + auiW[58]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K256[59] + auiW[59]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K256[60] + auiW[60]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K256[61] + auiW[61]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K256[62] + auiW[62]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K256[63] + auiW[63]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
//OR
/*
unsigned int a, b, c, d, e, f, g, h, t1, t2;
a = m_auiBuf[0];
b = m_auiBuf[1];
c = m_auiBuf[2];
d = m_auiBuf[3];
e = m_auiBuf[4];
f = m_auiBuf[5];
g = m_auiBuf[6];
h = m_auiBuf[7];
//
for(i=0; i<64; i++)
{
t1 = h + SIG1(e) + CH(e, f, g) + sm_K256[i] + auiW[i];
t2 = SIG0(a) + MAJ(a, b, c);
h = g;
g = f;
f = e;
e = d+t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
*/
m_auiBuf[0] += a;
m_auiBuf[1] += b;
m_auiBuf[2] += c;
m_auiBuf[3] += d;
m_auiBuf[4] += e;
m_auiBuf[5] += f;
m_auiBuf[6] += g;
m_auiBuf[7] += h;
}
break;
case SHA384:
case SHA512:
{
//Expansion of m_aucIn
unsigned char* pucIn = m_aucIn;
SUI64 aoui64W[80];
int i;
for(i=0; i<16; i++,pucIn+=8)
Bytes2Word(pucIn, aoui64W[i]);
for(i=16; i<80; i++)
aoui64W[i] = sig1(aoui64W[i-2]) + aoui64W[i-7] + sig0(aoui64W[i-15]) + aoui64W[i-16];
SUI64 a, b, c, d, e, f, g, h, t;
a = m_aoui64Buf[0];
b = m_aoui64Buf[1];
c = m_aoui64Buf[2];
d = m_aoui64Buf[3];
e = m_aoui64Buf[4];
f = m_aoui64Buf[5];
g = m_aoui64Buf[6];
h = m_aoui64Buf[7];
t = h + SIG1(e) + CH(e, f, g) + sm_K512[0] + aoui64W[0]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K512[1] + aoui64W[1]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K512[2] + aoui64W[2]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K512[3] + aoui64W[3]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K512[4] + aoui64W[4]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K512[5] + aoui64W[5]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K512[6] + aoui64W[6]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K512[7] + aoui64W[7]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K512[8] + aoui64W[8]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K512[9] + aoui64W[9]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K512[10] + aoui64W[10]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K512[11] + aoui64W[11]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K512[12] + aoui64W[12]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K512[13] + aoui64W[13]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K512[14] + aoui64W[14]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K512[15] + aoui64W[15]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K512[16] + aoui64W[16]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K512[17] + aoui64W[17]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K512[18] + aoui64W[18]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K512[19] + aoui64W[19]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K512[20] + aoui64W[20]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K512[21] + aoui64W[21]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K512[22] + aoui64W[22]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K512[23] + aoui64W[23]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K512[24] + aoui64W[24]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K512[25] + aoui64W[25]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K512[26] + aoui64W[26]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K512[27] + aoui64W[27]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K512[28] + aoui64W[28]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K512[29] + aoui64W[29]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K512[30] + aoui64W[30]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K512[31] + aoui64W[31]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K512[32] + aoui64W[32]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K512[33] + aoui64W[33]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K512[34] + aoui64W[34]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K512[35] + aoui64W[35]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K512[36] + aoui64W[36]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K512[37] + aoui64W[37]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K512[38] + aoui64W[38]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K512[39] + aoui64W[39]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K512[40] + aoui64W[40]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K512[41] + aoui64W[41]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K512[42] + aoui64W[42]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K512[43] + aoui64W[43]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K512[44] + aoui64W[44]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K512[45] + aoui64W[45]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K512[46] + aoui64W[46]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K512[47] + aoui64W[47]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K512[48] + aoui64W[48]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K512[49] + aoui64W[49]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K512[50] + aoui64W[50]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K512[51] + aoui64W[51]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K512[52] + aoui64W[52]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K512[53] + aoui64W[53]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K512[54] + aoui64W[54]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K512[55] + aoui64W[55]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K512[56] + aoui64W[56]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K512[57] + aoui64W[57]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K512[58] + aoui64W[58]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K512[59] + aoui64W[59]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K512[60] + aoui64W[60]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K512[61] + aoui64W[61]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K512[62] + aoui64W[62]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K512[63] + aoui64W[63]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K512[64] + aoui64W[64]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K512[65] + aoui64W[65]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K512[66] + aoui64W[66]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K512[67] + aoui64W[67]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K512[68] + aoui64W[68]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K512[69] + aoui64W[69]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K512[70] + aoui64W[70]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K512[71] + aoui64W[71]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K512[72] + aoui64W[72]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K512[73] + aoui64W[73]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K512[74] + aoui64W[74]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K512[75] + aoui64W[75]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K512[76] + aoui64W[76]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K512[77] + aoui64W[77]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K512[78] + aoui64W[78]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K512[79] + aoui64W[79]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
m_aoui64Buf[0] += a;
m_aoui64Buf[1] += b;
m_aoui64Buf[2] += c;
m_aoui64Buf[3] += d;
m_aoui64Buf[4] += e;
m_aoui64Buf[5] += f;
m_aoui64Buf[6] += g;
m_aoui64Buf[7] += h;
}
break;
}
}

379
3rdparty/MultiEmulator/src/SHA.h vendored Normal file
View File

@@ -0,0 +1,379 @@
//SHA.h
#ifndef __SHA_H__
#define __SHA_H__
#include "MessageDigest.h"
//Typical DISCLAIMER:
//The code in this project is Copyright (C) 2003 by George Anescu. You have the right to
//use and distribute the code in any way you see fit as long as this paragraph is included
//with the distribution. No warranties or claims are made as to the validity of the
//information and code contained herein, so use it at your own risk.
//Structure for representing an Unsigned Integer on 64 bits
struct SUI64
{
//Data
unsigned int m_uiLeft;
unsigned int m_uiRight;
//Operators
SUI64& operator++()
{
unsigned int uiTemp = m_uiRight;
m_uiRight++;
if(m_uiRight < uiTemp)
m_uiLeft++;
return *this;
}
SUI64& operator--()
{
unsigned int uiTemp = m_uiRight;
m_uiRight--;
if(m_uiRight > uiTemp)
m_uiLeft--;
return *this;
}
SUI64& operator+=(SUI64 const& roUI64)
{
m_uiRight += roUI64.m_uiRight;
if(m_uiRight < roUI64.m_uiRight)
m_uiLeft++;
m_uiLeft += roUI64.m_uiLeft;
return *this;
}
SUI64& operator|=(SUI64 const& roUI64)
{
m_uiRight |= roUI64.m_uiRight;
m_uiLeft |= roUI64.m_uiLeft;
return *this;
}
SUI64& operator&=(SUI64 const& roUI64)
{
m_uiRight &= roUI64.m_uiRight;
m_uiLeft &= roUI64.m_uiLeft;
return *this;
}
SUI64& operator^=(SUI64 const& roUI64)
{
m_uiRight ^= roUI64.m_uiRight;
m_uiLeft ^= roUI64.m_uiLeft;
return *this;
}
SUI64& operator<<=(unsigned int uiBits)
{
if(uiBits < 32)
{
(m_uiLeft <<= uiBits) |= (m_uiRight >> (32-uiBits));
m_uiRight <<= uiBits;
}
else
{
m_uiLeft = m_uiRight << (uiBits-32);
m_uiRight = 0;
}
return *this;
}
SUI64& operator>>=(unsigned int uiBits)
{
if(uiBits < 32)
{
(m_uiRight >>= uiBits) |= (m_uiLeft << (32-uiBits));
m_uiLeft >>= uiBits;
}
else
{
m_uiRight = m_uiLeft >> (uiBits-32);
m_uiLeft = 0;
}
return *this;
}
bool operator>(SUI64 const& roUI64) const
{
if(m_uiLeft == roUI64.m_uiLeft)
return m_uiRight > roUI64.m_uiRight;
else
return m_uiLeft > roUI64.m_uiLeft;
}
bool operator<(SUI64 const& roUI64) const
{
if(m_uiLeft == roUI64.m_uiLeft)
return m_uiRight < roUI64.m_uiRight;
else
return m_uiLeft < roUI64.m_uiLeft;
}
};
inline SUI64 operator+(SUI64 const& roUI64_1, SUI64 const& roUI64_2)
{
SUI64 temp = roUI64_1;
temp += roUI64_2;
return temp;
}
inline SUI64 operator|(SUI64 const& roUI64_1, SUI64 const& roUI64_2)
{
SUI64 temp = roUI64_1;
temp |= roUI64_2;
return temp;
}
inline SUI64 operator&(SUI64 const& roUI64_1, SUI64 const& roUI64_2)
{
SUI64 temp = roUI64_1;
temp &= roUI64_2;
return temp;
}
inline SUI64 operator^(SUI64 const& roUI64_1, SUI64 const& roUI64_2)
{
SUI64 temp = roUI64_1;
temp ^= roUI64_2;
return temp;
}
inline SUI64 operator<<(SUI64 const& roUI64, unsigned int uiBits)
{
SUI64 temp = roUI64;
temp <<= uiBits;
return temp;
}
inline SUI64 operator>>(SUI64 const& roUI64, unsigned int uiBits)
{
SUI64 temp = roUI64;
temp >>= uiBits;
return temp;
}
inline bool operator>(SUI64 const& roUI64_1, SUI64 const& roUI64_2)
{
return roUI64_1.operator>(roUI64_2);
}
inline bool operator<(SUI64 const& roUI64_1, SUI64 const& roUI64_2)
{
return roUI64_1.operator<(roUI64_2);
}
//SHA Message Digest algorithm
//SHA160 TEST VALUES:
//1)"abc"
//"A9993E364706816ABA3E25717850C26C9CD0D89D"
//
//2)"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
//"84983E441C3BD26EBAAE4AA1F95129E5E54670F1"
//
//3)1,000,000 repetitions of "a".
//"34AA973CD4C4DAA4F61EEB2BDBAD27316534016F"
//
//SHA256 TEST VALUES:
//1)One-Block Message "abc"
//"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
//
//2)"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
//"248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
//
//3)Multi-Block Message "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
//"CF5B16A778AF8380036CE59E7B0492370B249B11E8F07A51AFAC45037AFEE9D1"
//
//4)Long Message "a" 1,000,000 times
//"cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"
//
//SHA384 TEST VALUES:
//1)One-Block Message "abc"
//"cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7"
//
//2)Multi-Block Message "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
//"09330C33F71147E83D192FC782CD1B4753111B173B3B05D22FA08086E3B0F712FCC7C71A557E2DB966C3E9FA91746039"
//
//3)Long Message "a" 1,000,000 times
//"9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985"
//
//SHA512 TEST VALUES:
//1)One-Block Message "abc"
//"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a8
//36ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
//
//2)"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
//"8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4
//331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"
//
//3)""
//"CF83E1357EEFB8BDF1542850D66D8007D620E4050B5715DC83F4A921D36CE9CE47D0D13C5D85F2B0
//FF8318D2877EEC2F63B931BD47417A81A538327AF927DA3E"
//
//4)Long Message "a" 1,000,000 times
//"E718483D0CE769644E2E42C7BC15B4638E1F98B13B2044285632A803AFA973EBDE0FF244877EA60A
//4CB0432CE577C31BEB009C5C2C49AA2E4EADB217AD8CC09B"
class CSHA : public IMessageDigest
{
public:
enum { SHA160=0, SHA256=1, SHA384=2, SHA512=3 };
//CONSTRUCTOR
CSHA(int iMethod=SHA160);
//Update context to reflect the concatenation of another buffer of bytes.
void AddData(char const* pcData, int iDataLength);
//Final wrapup - pad to 64-byte boundary with the bit pattern
//1 0*(64-bit count of bits processed, MSB-first)
void FinalDigest(char* pcDigest);
//Reset current operation in order to prepare a new one
void Reset();
private:
//Transformation Function
void Transform();
//The Method
int m_iMethod;
enum { BLOCKSIZE2 = BLOCKSIZE<<1 };
//For 32 bits Integers
enum { SHA160LENGTH=5, SHA256LENGTH=8 };
//Context Variables
unsigned int m_auiBuf[SHA256LENGTH]; //Maximum for SHA256
unsigned int m_auiBits[2];
unsigned char m_aucIn[BLOCKSIZE2]; //128 bytes for SHA384, SHA512
//Internal auxiliary static functions
static unsigned int CircularShift(unsigned int uiBits, unsigned int uiWord);
static unsigned int CH(unsigned int x, unsigned int y, unsigned int z);
static unsigned int MAJ(unsigned int x, unsigned int y, unsigned int z);
static unsigned int SIG0(unsigned int x);
static unsigned int SIG1(unsigned int x);
static unsigned int sig0(unsigned int x);
static unsigned int sig1(unsigned int x);
static void Bytes2Word(unsigned char const* pcBytes, unsigned int& ruiWord);
static void Word2Bytes(unsigned int const& ruiWord, unsigned char* pcBytes);
static const unsigned int sm_K160[4];
static const unsigned int sm_H160[SHA160LENGTH];
static const unsigned int sm_K256[64];
static const unsigned int sm_H256[SHA256LENGTH];
//For 64 bits Integers
enum { SHA384LENGTH=6, SHA512LENGTH=8 };
//Context Variables
SUI64 m_aoui64Buf[SHA512LENGTH]; //Maximum for SHA512
SUI64 m_aoui64Bits[2];
//Internal auxiliary static functions
static SUI64 CircularShift(unsigned int uiBits, SUI64 const& roui64Word);
static SUI64 CH(SUI64 const& x, SUI64 const& y, SUI64 const& z);
static SUI64 MAJ(SUI64 const& x, SUI64 const& y, SUI64 const& z);
static SUI64 SIG0(SUI64 const& x);
static SUI64 SIG1(SUI64 const& x);
static SUI64 sig0(SUI64 const& x);
static SUI64 sig1(SUI64 const& x);
static void Bytes2Word(unsigned char const* pcBytes, SUI64& ruiWord);
static void Word2Bytes(SUI64 const& ruiWord, unsigned char* pcBytes);
static const SUI64 sm_H384[SHA512LENGTH]; //Dim is as 512
static const SUI64 sm_K512[80];
static const SUI64 sm_H512[SHA512LENGTH];
};
inline unsigned int CSHA::CircularShift(unsigned int uiBits, unsigned int uiWord)
{
return (uiWord << uiBits) | (uiWord >> (32-uiBits));
}
inline unsigned int CSHA::CH(unsigned int x, unsigned int y, unsigned int z)
{
return ((x&(y^z))^z);
}
inline unsigned int CSHA::MAJ(unsigned int x, unsigned int y, unsigned int z)
{
return (((x|y)&z)|(x&y));
}
inline unsigned int CSHA::SIG0(unsigned int x)
{
return ((x >> 2)|(x << 30)) ^ ((x >> 13)|(x << 19)) ^ ((x >> 22)|(x << 10));
}
inline unsigned int CSHA::SIG1(unsigned int x)
{
return ((x >> 6)|(x << 26)) ^ ((x >> 11)|(x << 21)) ^ ((x >> 25)|(x << 7));
}
inline unsigned int CSHA::sig0(unsigned int x)
{
return ((x >> 7)|(x << 25)) ^ ((x >> 18)|(x << 14)) ^ (x >> 3);
}
inline unsigned int CSHA::sig1(unsigned int x)
{
return ((x >> 17)|(x << 15)) ^ ((x >> 19)|(x << 13)) ^ (x >> 10);
}
inline void CSHA::Bytes2Word(unsigned char const* pcBytes, unsigned int& ruiWord)
{
ruiWord = (unsigned int)*(pcBytes+3) | (unsigned int)(*(pcBytes+2)<<8) |
(unsigned int)(*(pcBytes+1)<<16) | (unsigned int)(*pcBytes<<24);
}
inline void CSHA::Word2Bytes(unsigned int const& ruiWord, unsigned char* pcBytes)
{
pcBytes += 3;
*pcBytes = ruiWord & 0xff;
*--pcBytes = (ruiWord>>8) & 0xff;
*--pcBytes = (ruiWord>>16) & 0xff;
*--pcBytes = (ruiWord>>24) & 0xff;
}
inline SUI64 CSHA::CircularShift(unsigned int uiBits, SUI64 const& roui64Word)
{
return (roui64Word << uiBits) | (roui64Word >> (64-uiBits));
}
inline SUI64 CSHA::CH(SUI64 const& x, SUI64 const& y, SUI64 const& z)
{
return ((x&(y^z))^z);
}
inline SUI64 CSHA::MAJ(SUI64 const& x, SUI64 const& y, SUI64 const& z)
{
return (((x|y)&z)|(x&y));
}
inline SUI64 CSHA::SIG0(SUI64 const& x)
{
return ((x >> 28)|(x << 36)) ^ ((x >> 34)|(x << 30)) ^ ((x >> 39)|(x << 25));
}
inline SUI64 CSHA::SIG1(SUI64 const& x)
{
return ((x >> 14)|(x << 50)) ^ ((x >> 18)|(x << 46)) ^ ((x >> 41)|(x << 23));
}
inline SUI64 CSHA::sig0(SUI64 const& x)
{
return ((x >> 1)|(x << 63)) ^ ((x >> 8)|(x << 56)) ^ (x >> 7);
}
inline SUI64 CSHA::sig1(SUI64 const& x)
{
return ((x >> 19)|(x << 45)) ^ ((x >> 61)|(x << 3)) ^ (x >> 6);
}
inline void CSHA::Bytes2Word(unsigned char const* pcBytes, SUI64& ruiWord)
{
Bytes2Word(pcBytes+4, ruiWord.m_uiRight);
Bytes2Word(pcBytes, ruiWord.m_uiLeft);
}
inline void CSHA::Word2Bytes(SUI64 const& ruiWord, unsigned char* pcBytes)
{
Word2Bytes(ruiWord.m_uiRight, pcBytes+4);
Word2Bytes(ruiWord.m_uiLeft, pcBytes);
}
#endif // __SHA_H__

13
3rdparty/MultiEmulator/src/Setti.cpp vendored Normal file
View File

@@ -0,0 +1,13 @@
#include "multi_emulator.h"
int GenerateSetti(void *pDest)
{
auto pTicket = (int *)pDest;
pTicket[0] = 0xD4CA7F7B;
pTicket[1] = 0xC7DB6023;
pTicket[2] = 0x6D6A2E1F;
pTicket[5] = 0xB4C43105;
return 768;
}

18
3rdparty/MultiEmulator/src/SteamEmu.cpp vendored Normal file
View File

@@ -0,0 +1,18 @@
#include "multi_emulator.h"
int GenerateSteamEmu(void *pDest, int nSteamID)
{
auto pTicket = (int *)pDest;
pTicket[20] = -1; // +80, dproto/reunion wants this value to be -1, but if this value
// does not match -1, then instead of SteamID in [21] cell
// client IP address that xored with 0x25730981 number should
// be used. But dproto/reunion will just skip ticket validation
// in that case.
pTicket[21] = nSteamID; // +84, SteamId, low part. Actually, this is just system volume serial
// number, which comes from GetVolumeInformationA() function. If
// function failed (returned 0), then instead of volume serial number
// 777 number will be written to the ticket.
return 768;
}

12
3rdparty/MultiEmulator/src/StrUtils.cpp vendored Normal file
View File

@@ -0,0 +1,12 @@
#include "StrUtils.h"
#include <stdlib.h>
void CreateRandomString(char *pszDest, int nLength)
{
static const char c_szAlphaNum[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (int i = 0; i < nLength; ++i)
pszDest[i] = c_szAlphaNum[rand() % (sizeof(c_szAlphaNum) - 1)];
pszDest[nLength] = '\0';
}

3
3rdparty/MultiEmulator/src/StrUtils.h vendored Normal file
View File

@@ -0,0 +1,3 @@
#pragma once
void CreateRandomString(char *pszDest, int nLength);

24
3rdparty/MultiEmulator/wscript vendored Normal file
View File

@@ -0,0 +1,24 @@
#! /usr/bin/env python
# encoding: utf-8
# mittorn, 2018
from waflib import Logs
import os
top = '.'
def options(opt):
return
def configure(conf):
return
def build(bld):
bld.stlib(
source = bld.path.ant_glob(['src/*.cpp']),
target = 'MultiEmulator',
features = 'cxx',
includes = ['include/', 'src/'],
export_includes = ['include/'],
subsystem = bld.env.MSVC_SUBSYSTEM
)

1
3rdparty/bzip2/bz_version.h vendored Normal file
View File

@@ -0,0 +1 @@
#define BZ_VERSION "1.1.0-fwgs"

1
3rdparty/bzip2/bzip2 vendored Submodule

Submodule 3rdparty/bzip2/bzip2 added at 66c46b8c94

34
3rdparty/bzip2/wscript vendored Normal file
View File

@@ -0,0 +1,34 @@
#! /usr/bin/env python
# encoding: utf-8
def options(opt):
pass
def configure(conf):
conf.define('_GNU_SOURCE', 1)
conf.define('BZ_NO_STDIO', 1)
if conf.env.DEST_OS == 'win32':
conf.define('BZ_LCCWIN32', 1)
else:
conf.define('BZ_UNIX', 1)
def build(bld):
# bld(
# features = 'subst',
# source = 'bzip2/bz_version.h.in',
# target = 'bz_version.h',
# BZ_VERSION='1.1.0-fwgs'
# )
bz_sources = ['bzip2/blocksort.c', 'bzip2/huffman.c', 'bzip2/crctable.c', 'bzip2/randtable.c', 'bzip2/compress.c', 'bzip2/decompress.c', 'bzip2/bzlib.c']
bld.stlib(
source = bz_sources,
target = 'bzip2',
# use = 'bz_version.h',
features = 'c',
includes = ['.', 'bzip2/'],
subsystem = bld.env.MSVC_SUBSYSTEM,
export_includes = ['bzip2/']
)

View File

@@ -14,3 +14,4 @@ When `-bugcomp` is specified with argument, it interpreted as flags separated wi
| ------- | ----------- | ---------------------------- |
| `peoei` | Reverts `pfnPEntityOfEntIndex` behavior to GoldSrc, where it returns NULL for last player due to incorrect player index comparison | * Counter-Strike: Condition Zero - Deleted Scenes |
| `gsmrf` | Rewrites message at the moment when Game DLL attempts to write an internal engine message, usually specific to GoldSrc protocol. Right now only supports `svc_spawnstaticsound`, more messages added by request. | * MetaMod/AMXModX based mods |
| `sp_attn_none` | Makes sounds with attenuation zero spatialized, i.e. have a stereo effect. | Possibly, every game that was made for GoldSrc. |

View File

@@ -78,6 +78,7 @@ These strings are specific to Xash3D FWGS.
| `internal_vgui_support` | boolean | 0 | Only for programmers! Required to be set as 1 for PrimeXT!<br>When set to 1, the engine will not load vgui_support DLL, as VGUI support is done (or intentionally ignored) on the game side. |
| `render_picbutton_text` | boolean | 0 | When set to 1, the UI will not use prerendered `btns_main.bmp` and dynamically render them instead |
| `quicksave_aged_count` | integer | 2 | Quick saves limit used in saves rotation |
| `demomap` | string | Empty string | The name of the demo chapter map (Half-Life Uplink) |
## Note on GoldSrc liblist.gam support

View File

@@ -0,0 +1,14 @@
# Support for GoldSrc network protocol
This feature is still work-in-progress, but for now it's available for all users, and we appreciate any bug-reports and contributions around it.
For connecting to GoldSrc-based servers, use this command:
```
connect ip:port gs
```
But keep in mind, there are requirement for server to be able to accept connections from Xash3D-based clients: it should accept HLTV connections.
Without this requirement, you will just get "Steam validation rejected" error on connecting.
That is because proper authorization with Steam API is not implemented in engine yet (but we have plans on it).
In case of ReHLDS with Reunion plugin, by default it rejects HLTV clients. But connections from HLTV can be easily enabled in `reunion.cfg` file.

View File

@@ -19,7 +19,22 @@
- [List of XashXT-based mods](#list-of-xashxt-based-mods)
- [List of maps for They Hunger](#list-of-maps-for-they-hunger)
- [List of games and mods with custom gamedll](#list-of-games-and-mods-with-custom-gamedll)
- [List of mods for Counter Strike(Android only)](#list-of-mods-for-counter-strike)
- [List of mods for Counter Strike](#list-of-mods-for-counter-strike)
- [List of supported mods from mobile_hacks branch of HLSDK Portable by FWGS](#list-of-supported-mods-from-mobile_hacks-branch-of-hlsdk-portable-by-fwgs)
# List of supported mods from mobile_hacks branch of HLSDK Portable by FWGS
1. [Afraid of Monsters](https://www.moddb.com/mods/afraid-of-monsters/downloads/afraid-of-monsters-v1)
2. [Big Lolly](https://www.moddb.com/mods/big-lolly)
3. [Half-Life: Blue Shift](https://store.steampowered.com/app/130/HalfLife_Blue_Shift/)
4. [Half-Secret](https://www.moddb.com/mods/half-secret)
5. [Case Closed](https://www.moddb.com/mods/caseclosed)
6. [Bloody Pizza - Vendetta](https://www.moddb.com/games/half-life/addons/bloody-pizza-vendetta)
7. [Borderlands](https://www.moddb.com/games/half-life/addons/borderlands-v04)
8. [Half-Life: Induction](https://www.moddb.com/mods/half-life-induction/downloads/half-life-induction-12)
9. [Redemption/Absolute Redemption](https://www.moddb.com/mods/absolute-redemption)
10. [Sewer beta](https://www.moddb.com/games/half-life/addons/sewer-beta)
11. [Times of Troubles](https://www.moddb.com/mods/times-of-troubles)
12. [Half-Life: Urbicide](https://www.moddb.com/mods/half-life-urbicide)
# List of Half-Life-based mods
Originally this list was written by *Qwertyus*(*Qortez*)
@@ -176,7 +191,7 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
143. [Operation: Nova](http://www.moddb.com/mods/half-life-operation-nova) (there is an inner bug with an M60 machinegun on a map with Osprey: it can be activated and used if you are staying in front of it, not behind it)
144. [Optimum Fear](https://www.fileplanet.com/7472/0/fileinfo/Optimum-Fear)
145. [Outrun](http://www.moddb.com/mods/outrun)
146. [Outwards (Day One)](https://drive.google.com/file/d/1mjQ8wUazYbwTq9Ocg0Vs0raq4avbTRne/view?usp=sharing)
146. [Outwards (Day One)](https://web.archive.org/web/20161026104825/http://visgi.info/maps/)
147. [Overhaul Pack](http://www.moddb.com/mods/half-life-overhaul-pack) (Just HD pack for Half-Life)
148. [P.I.Z.D.E.C.](https://www.runthinkshootlive.com/posts/pizdec/)
149. [pagoda](http://www.moddb.com/mods/pagoda1)
@@ -282,7 +297,7 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
6. [Catacombs: Part 1](https://www.runthinkshootlive.com/posts/catacombs/)
7. [Cro-man's Office Mappack](http://twhl.info/vault.php?map=5547)
8. [Half-Life Episode Two Demo Alpha v1.0](http://hl.loess.ru/?mod=451)
9. [Hazardous-Course (first version of Hazardous-Course 2)](https://drive.google.com/file/d/16djJZSpNWKyScSxSyMqX-u_S-2i400rl/view?usp=sharing)
9. [Hazardous-Course (first version of Hazardous-Course 2)](https://web.archive.org/web/20110512012317/http://www.richmans-maps.ch.vu/)
10. [High Tech v0.2](http://hl.loess.ru/?mod=499)
11. [HL Shadows, Part 1](https://www.fileplanet.com/7466/0/fileinfo/'HL-Shadows',-Part-1)
12. [HLNewEnd](http://twhl.info/vault.php?map=2275)
@@ -305,11 +320,11 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
29. [Shortcut v1.0 Beta](https://www.runthinkshootlive.com/posts/shortcut/)
30. [Stoka](https://www.ceskemody.cz/mapy.php?lng=1&clanek=222&razeni_hra=1&pn=stoka)
31. [Striker's Compo 26](http://twhl.info/vault.php?map=5190) (buggy)
32. [Technology Test 2](https://drive.google.com/file/d/1LfldzsMIN5j07bgtNkfY5v0Xl0S9de_G/view?usp=sharing)
32. [Technology Test 2](https://web.archive.org/web/20110512012317/http://www.richmans-maps.ch.vu/)
33. [The Gate Playable Demo](https://www.fileplanet.com/116347/110000/fileinfo/The-Gate-Playable-Demo)
34. [They are Back](https://www.runthinkshootlive.com/posts/they-are-back/)
35. [Tiefseelabor( Deep Sea Laboratory )](https://www.runthinkshootlive.com/posts/deep-sea-laboratory/)
36. [Time-Shift](https://drive.google.com/file/d/1pK1s-2SIlSMQHVRPMLdC_94wTa__8_DX/view?usp=sharing)
36. [Time-Shift](https://web.archive.org/web/20110512012317/http://www.richmans-maps.ch.vu/)
37. [Train Single Beta](https://cs-mapping.com.ua/forum/showthread.php?t=36394) (Remove **gfx.wad** from **TrainSingle** folder)
38. [WAR: The Killer Beta 0.1](http://www.moddb.com/mods/war)
39. [White Force Beta( Residual Point prototype )](http://www.moddb.com/mods/hl-residual-point/downloads/white-force-beta-2002)
@@ -379,7 +394,7 @@ Mods:
5. [Half-Life Baby v1.4](http://www.moddb.com/games/half-life/addons/half-life-baby) (it's an unfinished but playable mod; after installing of the mod open **liblist.gam** or **gameinfo.txt** file in the mod's folder and correct the line **gamedll "..\hlbaby\dlls\hl.dll"** for **gamedll "dlls\hl.dll"**, otherwise you'll not be able to start a game)
6. [Half-Secret](http://www.moddb.com/mods/half-secret) (this mod has custom **weapon_snark** code)
7. [Induction](http://www.moddb.com/mods/half-life-induction) (this mod has new item - **item_flashlight**)
8. [Lost in Black Mesa(first version without HLFX)](https://drive.google.com/file/d/1bEnm_AxJs-ly8hTEZIQBw_v2BsXdSiGa/view?usp=sharing)
8. [Lost in Black Mesa(first version without HLFX)](https://web.archive.org/web/20160407041812/http://half-life.ru/forum/showthread.php?threadid=13959) (download links dead!)
9. [Soldier](http://www.moddb.com/mods/half-life-soldier)
10. [Solo Operations](http://www.moddb.com/mods/solo-operations)
11. [The Blood v1.1](http://hl.loess.ru/?mods=&search=The+Blood) (there are some inner bugs in the mod, but they don't interfere with a game progress)
@@ -440,7 +455,7 @@ Mods:
51. [Data-base](https://www.runthinkshootlive.com/posts/database/)
52. [de_dust2_azabetfeN](https://cs-mapping.com.ua/forum/showthread.php?t=36394) (remove **cl_dlls** & **dlls** folders from inside of mod's directory before you start the game)
53. [De-railed](http://twhl.info/competitions.php?results=7)
54. [Dead Shift Beta](http://www.moddb.com/mods/dead-shift) - [Demo 1](https://www.gamewatcher.com/mods/half-life-mod/dead-shift-1-0-beta) & [Demo 2](https://drive.google.com/file/d/1uHvr8xONogTTNOy-8X6G4ehFV6Eawvbq/view?usp=sharing)
54. [Dead Shift Beta](http://www.moddb.com/mods/dead-shift) - [Demo 1](https://www.gamewatcher.com/mods/half-life-mod/dead-shift-1-0-beta) & [Demo 2](https://web.archive.org/web/20151030005310/http://www.gamefront.com/files/13532512)
55. [Deep](http://twhl.info/vault.php?map=1669)
56. [Desert Attack](http://fyzzer.narod.ru/index.html)
57. [Desert Combat Demo](https://www.fileplanet.com/190487/190000/fileinfo/Half-Life---Desert-Combat-Mod) (despite a big file size there's only one small unfinished map)
@@ -498,8 +513,8 @@ Mods:
109. [Hospital](https://gamebanana.com/maps/167446) (you need to edit **liblist.gam** file in the mod's folder - delete *gamedll & type* strings from it before you start to play)
110. [Hostage](https://www.runthinkshootlive.com/posts/hostage-2/)
111. [House](http://www.artpeter.net/Data/HalfLife/Hl.php)
112. [Impulse 101 Fun - The Train](https://drive.google.com/file/d/1jAuMCCmREH0mfAEAscqaG8FQGa2uNknb/view?usp=sharing) (map from *TWHL* by *Archie* aka *The Hunter*)
113. [In America](https://drive.google.com/file/d/1gOC8zfnUvBxRy8Rr8juNiUNbLYjoZpnn/view?usp=sharing)
112. [Impulse 101 Fun - The Train](http://web.archive.org/web/20070305075816/http://www.twhl.co.za/mapvault/2817.zip) (map from *TWHL* by *Archie* aka *The Hunter*)
113. [In America](https://web.archive.org/web/20170221213409/http://www.lambda-force.org/load/half_life/karty/half_life_in_america/18-1-0-476)
114. [In the Kitchen](http://twhl.info/vault.php?map=4314)
115. [Infiltration](https://www.fileplanet.com/7467/0/fileinfo/Infiltration)
116. [Interactivity & Lots of Entities](http://twhl.info/vault.php?map=5744) (link dead!)

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 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.
@@ -11,12 +11,12 @@ Xash3D FWGS is a heavily modified fork of an original [Xash3D Engine](https://ww
If you like Xash3D FWGS, consider supporting individual engine maintainers. By supporting us, you help to continue developing this game engine further. The sponsorship links are available in [documentation](Documentation/donate.md).
## Fork features
* Steam Half-Life (HLSDK 2.4) support.
* Steam Half-Life (HLSDK 2.5) support.
* Crossplatform and modern compilers support: supports Windows, Linux, BSD & Android on x86 & ARM and [many more](Documentation/ports.md).
* Better multiplayer support: multiple master servers, headless dedicated server, voice chat and IPv6 support.
* Better multiplayer: multiple master servers, headless dedicated server, voice chat, [GoldSrc protocol support](Documentation/goldsrc-protocol-support.md) and IPv6 support.
* Multiple renderers support: OpenGL, GLESv1, GLESv2 and Software.
* Advanced virtual filesystem: `.pk3` and `.pk3dir` support, compatibility with GoldSrc FS module, fast case-insensitivity emulation for crossplatform.
* Mobility API: better game integration on mobile devices (vibration, touch controls)
* Mobility API: better game integration on mobile devices (vibration, touch controls).
* Different input methods: touch and gamepad in addition to mouse & keyboard.
* TrueType font rendering, as a part of mainui_cpp.
* External VGUI support module.
@@ -28,29 +28,28 @@ If you like Xash3D FWGS, consider supporting individual engine maintainers. By s
1) Copy engine binaries to some directory.
2) Copy `valve` directory from [Half-Life](https://store.steampowered.com/app/70/HalfLife/) to directory with engine binaries.
If your CPU is NOT x86 compatible or you're running 64-bit version of the engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-portable).
This repository contains our fork of HLSDK and restored source code for some of the mods. Not all of them, of course.
This repository contains our fork of HLSDK and restored source code for Half-Life expansions and some mods.
You still needed to copy `valve` directory as all game resources located there.
3) Run the main executable (`xash3d.exe` or AppImage).
For additional info, run Xash3D with `-help` command line key.
## Contributing
* Before sending an issue, check if someone already reported your issue. Make sure you're following "How To Ask Questions The Smart Way" guide by Eric Steven Raymond. Read more: http://www.catb.org/~esr/faqs/smart-questions.html
* Issues are accepted in both English and Russian
* Before sending an issue, check if someone already reported your issue. Make sure you're following "How To Ask Questions The Smart Way" guide by Eric Steven Raymond. Read more: http://www.catb.org/~esr/faqs/smart-questions.html.
* Issues are accepted in both English and Russian.
* Before sending a PR, check if you followed our contribution guide in CONTRIBUTING.md file.
## Build instructions
We are using Waf build system. If you have some Waf-related questions, I recommend you to read https://waf.io/book/
We are using Waf build system. If you have some Waf-related questions, I recommend you to read [Waf Book](https://waf.io/book/).
NOTE: NEVER USE GitHub's ZIP ARCHIVES. GitHub doesn't include external dependencies we're using!
### Prerequisites
If your CPU is x86 compatible, we are building 32-bit code by default. This was done to maintain compatibility with Steam releases of Half-Life and based on it's engine games.
If your CPU is x86 compatible and you're on Windows or Linux, we are building 32-bit code by default. This was done to maintain compatibility with Steam releases of Half-Life and based on it's engine games.
Even if Xash3D FWGS does support targetting 64-bit, you can't load games without recompiling them from source code!
If your CPU is NOT x86 compatible or you decided build 64-bit version of engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-portable).
This repository contains our fork of HLSDK and restored source code for some of the mods. Not all of them, of course.
This repository contains our fork of HLSDK and restored source code for Half-Life expansions and some mods.
#### Windows (Visual Studio)
* Install Visual Studio.
@@ -62,31 +61,39 @@ This repository contains our fork of HLSDK and restored source code for some of
#### GNU/Linux
##### Debian/Ubuntu
* Enable i386 on your system, if you're compiling 32-bit engine on amd64. If not, skip this
* For 32-bit engine on 64-bit x86 operating system:
* Enable i386 on your system: `$ sudo dpkg --add-architecture i386`.
* Install development tools: `$ sudo apt install build-essential gcc-multilib g++-multilib python libsdl2-dev:i386 libfontconfig-dev:i386 libfreetype6-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`.
`$ sudo dpkg --add-architecture i386`
* Install development tools
* For 32-bit engine on amd64: \
`$ sudo apt install build-essential gcc-multilib g++-multilib python libsdl2-dev:i386 libfontconfig-dev:i386 libfreetype6-dev:i386`
* For everything else: \
`$ sudo apt install build-essential python libsdl2-dev libfontconfig-dev libfreetype6-dev`
* Clone this repostory:
`$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`
* For non-x86 systems:
* Install development tools: `$ sudo apt install 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
* For 32-bit engine on 64-bit x86 operating system:
* Install development tools: `$ sudo dnf install 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 non-x86 systems:
* Install development tools: `$ sudo dnf install 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`.
### Building
#### Windows (Visual Studio)
0) Open command line
0) Open command line.
1) Navigate to `xash3d-fwgs` directory.
2) Carefully examine which build options are available: `waf --help`
3) Configure build: `waf configure -T release --sdl2=c:/path/to/SDL2`
4) Compile: `waf build`
5) Install: `waf install --destdir=c:/path/to/any/output/directory`
2) (optional) Examine which build options are available: `waf --help`.
3) Configure build: `waf configure --sdl2=c:/path/to/SDL2`.
4) Compile: `waf build`.
5) Install: `waf install --destdir=c:/path/to/any/output/directory`.
#### Linux
If compiling 32-bit on amd64, you may need to supply `export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig` prior to running configure.
If compiling 32-bit on amd64, make sure `PKG_CONFIG_PATH` from the previous step is set correctly, prior to running configure.
0) Examine which build options are available: `./waf --help`
1) Configure build: `./waf configure -T release`
(You need to pass `-8` to compile 64-bit engine on 64-bit x86 processor)
2) Compile: `./waf build`
3) Install(optional): `./waf install --destdir=/path/to/any/output/directory`
0) (optional) Examine which build options are available: `./waf --help`.
1) Configure build: `./waf configure` (you need to pass `-8` to compile 64-bit engine on 64-bit x86 processor).
2) Compile: `./waf build`.
3) Install: `./waf install --destdir=/path/to/any/output/directory`.

View File

@@ -127,14 +127,23 @@ typedef struct
int flags; // sky or slime, no lightmap or 256 subdivision
} mtexinfo_t;
typedef struct glpoly_s
// a1ba: changed size to avoid undefined behavior. Check your allocations if you take this header!
// For example:
// before: malloc( sizeof( glpoly_t ) + ( numverts - 4 ) * VERTEXSIZE * sizeof( float ))
// after (C): malloc( sizeof( glpoly_t ) + numverts * VERTEXSIZE * sizeof( float ))
// after (C++): malloc( sizeof( glpoly_t ) + ( numverts - 1 ) * VERTEXSIZE * sizeof( float ))
typedef struct glpoly2_s
{
struct glpoly_s *next;
struct glpoly_s *chain;
struct glpoly2_s *next;
struct glpoly2_s *chain;
int numverts;
int flags; // for SURF_UNDERWATER
float verts[4][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2)
} glpoly_t;
#ifdef __cplusplus
float verts[1][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2)
#else
float verts[][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2)
#endif
} glpoly2_t;
typedef struct mnode_s
{
@@ -173,7 +182,7 @@ struct decal_s
short entityIndex; // Entity this is attached to
// Xash3D specific
vec3_t position; // location of the decal center in world space.
glpoly_t *polys; // precomputed decal vertices
glpoly2_t *polys; // precomputed decal vertices
intptr_t reserved[4]; // just for future expansions or mod-makers
};
@@ -246,7 +255,7 @@ struct msurface_s
int light_s, light_t; // gl lightmap coordinates
glpoly_t *polys; // multiple if warped
glpoly2_t *polys; // multiple if warped
struct msurface_s *texturechain;
mtexinfo_t *texinfo;
@@ -488,7 +497,8 @@ typedef struct
int flags;
float size;
int reserved[8]; // VBO offsets
const trivertex_t **pposeverts; // only valid during loading, used to build GL mesh
intptr_t reserved[7]; // VBO offsets
int numposes;
int poseverts;
@@ -531,17 +541,10 @@ typedef struct
#define MAX_MOVIES 8
#define MAX_CDTRACKS 32
#define MAX_CLIENT_SPRITES 512 // SpriteTextures (0-256 hud, 256-512 client)
#define MAX_EFRAGS 8192 // Arcane Dimensions required
#define MAX_REQUESTS 64
#if ! XASH_64BIT
STATIC_ASSERT( sizeof( mextrasurf_t ) == 324, "mextrasurf_t unexpected size" );
STATIC_ASSERT( sizeof( decal_t ) == 60, "decal_t unexpected size");
STATIC_ASSERT( sizeof( mfaceinfo_t ) == 176, "mfaceinfo_t unexpected size");
#else
STATIC_ASSERT( sizeof( mextrasurf_t) == 496, "mextrasurf_t unexpected size");
STATIC_ASSERT( sizeof( decal_t ) == 88, "decal_t unexpected size");
STATIC_ASSERT( sizeof( mfaceinfo_t ) == 304, "mfaceinfo_t unexpected size");
#endif
STATIC_CHECK_SIZEOF( mextrasurf_t, 324, 496 );
STATIC_CHECK_SIZEOF( decal_t, 60, 88 );
STATIC_CHECK_SIZEOF( mfaceinfo_t, 176, 304 );
#endif//COM_MODEL_H

View File

@@ -1,49 +1,122 @@
/***
*
* 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.
*
****/
#ifndef CVARDEF_H
#define CVARDEF_H
/*
cvardef.h - quake cvar definition
Copyright (C) 1997-2001 Id Software, Inc.
Copyright (C) 2024 Alibek Omarov
#define FCVAR_ARCHIVE (1<<0) // set to cause it to be saved to vars.rc
#define FCVAR_USERINFO (1<<1) // changes the client's info string
#define FCVAR_SERVER (1<<2) // notifies players when changed
#define FCVAR_EXTDLL (1<<3) // defined by external DLL
#define FCVAR_CLIENTDLL (1<<4) // defined by the client dll
#define FCVAR_PROTECTED (1<<5) // It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value
#define FCVAR_SPONLY (1<<6) // This cvar cannot be changed by clients connected to a multiplayer server.
#define FCVAR_PRINTABLEONLY (1<<7) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ).
#define FCVAR_UNLOGGED (1<<8) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log
#define FCVAR_NOEXTRAWHITEPACE (1<<9) // strip trailing/leading white space from this cvar
#define FCVAR_PRIVILEGED (1<<10) // only available in privileged mode
#define FCVAR_FILTERABLE (1<<11) // filtered in unprivileged mode if cl_filterstuffcmd is 1
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.
// Xash3D extensions
#define FCVAR_GLCONFIG (1<<12) // write it into <renderer>.cfg(see RefAPI)
#define FCVAR_CHANGED (1<<13) // set each time the cvar is changed
#define FCVAR_GAMEUIDLL (1<<14) // defined by the menu DLL
#define FCVAR_CHEAT (1<<15) // can not be changed if cheats are disabled
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.
// a1ba: let's reuse higher bits for flags extensions from now on
#define FCVAR_LATCH (1<<30) // notify client what this cvar will be applied only after server restart (but don't does more nothing)
See the GNU General Public License for more details.
typedef struct cvar_s
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef CVAR
#define CVAR
#include STDINT_H
#include "xash3d_types.h"
/*
cvar_t variables are used to hold scalar or string variables that can be changed
or displayed at the console or prog code as well as accessed directly
in C code.
The user can access cvars from the console in three ways:
r_draworder prints the current value
r_draworder 0 sets the current value to 0
set r_draworder 0 as above, but creates the cvar if not present
Cvars are restricted from having the same names as commands to keep this
interface from being ambiguous.
The are also occasionally used to communicated information between different
modules of the program.
*/
enum
{
char *name;
char *string;
int flags;
float value;
struct cvar_s *next;
} cvar_t;
// GoldSrc compatibility flags
FCVAR_ARCHIVE = 1 << 0, // set to cause it to be saved to vars.rc
FCVAR_USERINFO = 1 << 1, // added to userinfo when changed
FCVAR_SERVER = 1 << 2, // added to serverinfo when changed, will notify clients by default
FCVAR_EXTDLL = 1 << 3, // defined by server.dll
FCVAR_CLIENTDLL = 1 << 4, // defined by client.dll
FCVAR_PROTECTED = 1 << 5, // private server cvar
FCVAR_SPONLY = 1 << 6, // can be set only in singleplayer
FCVAR_PRINTABLEONLY = 1 << 7, // only allows printable characters
FCVAR_UNLOGGED = 1 << 8, // disables notifying client about server cvar change
FCVAR_NOEXTRAWHITESPACE = 1 << 9, // removes space characters from the beginning and the end of the string
FCVAR_PRIVILEGED = 1 << 10, // only available in privileged mode
FCVAR_FILTERABLE = 1 << 11, // treated as privileged if cl_filterstuffcmd is 1, otherwise ignored
#endif//CVARDEF_H
// Xash3D public flags
// FCVAR_LATCH = 1 << 11, // deprecated Xash3D flag, conflicts with FCVAR_FILTERABLE. Use another FCVAR_LATCH!
FCVAR_GLCONFIG = 1 << 12, // set to cause it to be saved to <renderer>.cfg (see RefAPI)
FCVAR_CHANGED = 1 << 13, // set each time the cvar changed
FCVAR_GAMEUIDLL = 1 << 14, // defined by menu.dll
FCVAR_CHEAT = 1 << 15, // cannot be changed if sv_cheats is 0
#if REF_DLL || ENGINE_DLL // Xash3D internal flags, MUST NOT be used outside of engine
FCVAR_RENDERINFO = 1 << 16, // set to cause it to be saved to video.cfg
FCVAR_READ_ONLY = 1 << 17, // display only, cannot be set by user at all
FCVAR_EXTENDED = 1 << 18, // extended cvar structure
FCVAR_ALLOCATED = 1 << 19, // allocated by the engine, must be freed with Mem_Free
FCVAR_VIDRESTART = 1 << 20, // triggers video subsystem to recreate/modify window parameters
FCVAR_TEMPORARY = 1 << 21, // only used to temporarly hold some value, can be unlinked
FCVAR_MOVEVARS = 1 << 22, // access to movevars_t structure, synchornized between client and server
FCVAR_USER_CREATED = 1 << 23, // created by a set command
FCVAR_REFDLL = 1 << 29, // (Xash3D FWGS internal flag) defined by the renderer DLL
#endif // REF_DLL || ENGINE_DLL
FCVAR_LATCH = 1 << 30, // (Xash3D FWGS public flag, was FCVAR_FILTERABLE in Xash3D) save changes until server restart
};
struct cvar_s {
char *name;
char *string;
uint32_t flags;
float value;
struct cvar_s *next;
};
typedef struct cvar_s cvar_t;
STATIC_CHECK_SIZEOF( struct cvar_s, 20, 32 );
#if REF_DLL || ENGINE_DLL // Xash3D internal cvar format, MUST NOT be used outside of engine
struct convar_s {
char *name;
char *string;
uint32_t flags;
float value;
struct convar_s *next;
char *desc;
char *def_string;
};
typedef struct convar_s convar_t;
#if XASH_64BIT
#define CVAR_SENTINEL (uintptr_t)0xDEADBEEFDEADBEEF
#else
#define CVAR_SENTINEL (uintptr_t)0xDEADBEEF
#endif
#define CVAR_CHECK_SENTINEL( cv ) ((uintptr_t)(cv)->next == CVAR_SENTINEL)
#define CVAR_DEFINE( cv, cvname, cvstr, cvflags, cvdesc ) \
convar_t cv = { (char*)cvname, (char*)cvstr, cvflags, 0.0f, (void *)CVAR_SENTINEL, (char*)cvdesc, NULL }
#define CVAR_DEFINE_AUTO( cv, cvstr, cvflags, cvdesc ) CVAR_DEFINE( cv, #cv, cvstr, cvflags, cvdesc )
#endif // REF_DLL || ENGINE_DLL
#endif // CVAR

View File

@@ -30,7 +30,7 @@ GAMEINFO stuff
internal shared gameinfo structure (readonly for engine parts)
========================================================================
*/
typedef struct
typedef struct GAMEINFO_s
{
// filesystem info
char gamefolder[64]; // used for change game '-game x'
@@ -50,4 +50,48 @@ typedef struct
int gamemode;
} GAMEINFO;
/*
========================================================================
Extended GameInfo struct introduced in Xash3D FWGS
GAMEINFO can't be reliably extended, as nor engine, nor menu can't be
sure about struct size. By adding struct versioning, we can check the
presense for extra fields.
========================================================================
*/
#define GAMEINFO_VERSION 2
typedef enum gametype_e
{
GAME_NORMAL,
GAME_SINGLEPLAYER_ONLY,
GAME_MULTIPLAYER_ONLY,
} gametype_t;
typedef struct gameinfo2_s
{
int gi_version; // should be set to desired struct version, e.g. GAMEINFO_VERSION
// filesystem info
char gamefolder[64]; // used for change game
char startmap[64]; // map to start singleplayer game from
char trainmap[64]; // map to start hazardous course from (if specified)
char demomap[64]; // map to start demo chapter from (if specified)
char title[64]; // game title
char iconpath[64]; // path to game icon
char version[16]; // game version (optional)
uint32_t flags; // gameinfo flags, extended to fit more flags
// mod info
char game_url[256]; // link to a developer's site
char update_url[256]; // link to updates page
char type[64]; // single, toolkit, multiplayer, etc
char date[64]; // release date
uint64_t size; // size in bytes
gametype_t gamemode;
} gameinfo2_t;
#endif//GAMEINFO_H

View File

@@ -30,6 +30,6 @@ typedef struct
int state; // low bit is down state
} kbutton_t;
STATIC_ASSERT( sizeof( kbutton_t ) == 12, "kbutton_t isn't 12 bytes!" );
STATIC_CHECK_SIZEOF( kbutton_t, 12, 12 );
#endif // KBUTTON_H

View File

@@ -69,6 +69,6 @@ typedef struct netadr_s
} netadr_t;
#pragma pack( pop )
STATIC_ASSERT( sizeof( netadr_t ) == 20, "netadr_t isn't 20 bytes!" );
STATIC_CHECK_SIZEOF( netadr_t, 20, 20 );
#endif // NET_ADR_H

View File

@@ -56,6 +56,8 @@ color24 gTracerColors[] =
};
*/
#define TRACER_COLORINDEX_DEFAULT 4
// Temporary entity array
#define TENTPRIORITY_LOW 0
#define TENTPRIORITY_HIGH 1

View File

@@ -79,11 +79,22 @@ typedef uint64_t longtime_t;
#define GAME_EXPORT
#endif
#define MALLOC __attribute__(( malloc ))
// added in GCC 11
#if __GNUC__ >= 11
// might want to set noclone due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116893
// but it's easier to not force mismatched-dealloc to error yet
#define MALLOC_LIKE( x, y ) __attribute__(( malloc( x, y )))
#else
#define MALLOC_LIKE( x, y ) MALLOC
#endif
#define NORETURN __attribute__(( noreturn ))
#define NONNULL __attribute__(( nonnull ))
#define _format( x ) __attribute__(( format( printf, x, x + 1 )))
#define ALLOC_CHECK( x ) __attribute__(( alloc_size( x )))
#define NO_ASAN __attribute__(( no_sanitize( "address" )))
#define WARN_UNUSED_RESULT __attribute__(( warn_unused_result ))
#define RENAME_SYMBOL( x ) asm( x )
#else
#if defined( _MSC_VER )
@@ -99,6 +110,9 @@ typedef uint64_t longtime_t;
#define _format( x )
#define ALLOC_CHECK( x )
#define RENAME_SYMBOL( x )
#define MALLOC
#define MALLOC_LIKE( x, y )
#define WARN_UNUSED_RESULT
#endif
#if __GNUC__ >= 3
@@ -130,6 +144,15 @@ typedef uint64_t longtime_t;
#define STATIC_ASSERT( x, y ) STATIC_ASSERT_2( __LINE__, x, y )
#endif
// at least, statically check size of some public structures
#if XASH_64BIT
#define STATIC_CHECK_SIZEOF( type, size32, size64 ) \
STATIC_ASSERT( sizeof( type ) == size64, #type " unexpected size" )
#else
#define STATIC_CHECK_SIZEOF( type, size32, size64 ) \
STATIC_ASSERT( sizeof( type ) == size32, #type " unexpected size" )
#endif
#if !defined( __cplusplus ) && __STDC_VERSION__ >= 199101L // not C++ and C99 or newer
#define XASH_RESTRICT restrict
#elif _MSC_VER || __GNUC__ || __clang__ // compiler-specific extensions

View File

@@ -74,7 +74,7 @@ typedef struct
float size;
} daliashdr_t;
STATIC_ASSERT( sizeof( daliashdr_t ) == 84, "invalid daliashdr_t size" );
STATIC_CHECK_SIZEOF( daliashdr_t, 84, 84 );
typedef struct
{
@@ -83,7 +83,7 @@ typedef struct
int32_t t;
} stvert_t;
STATIC_ASSERT( sizeof( stvert_t ) == 12, "invalid stvert_t size" );
STATIC_CHECK_SIZEOF( stvert_t, 12, 12 );
typedef struct dtriangle_s
{
@@ -91,7 +91,7 @@ typedef struct dtriangle_s
int32_t vertindex[3];
} dtriangle_t;
STATIC_ASSERT( sizeof( dtriangle_t ) == 16, "invalid dtriangle_t size" );
STATIC_CHECK_SIZEOF( dtriangle_t, 16, 16 );
#define DT_FACES_FRONT 0x0010
#define ALIAS_ONSEAM 0x0020
@@ -103,7 +103,7 @@ typedef struct
char name[16]; // frame name from grabbing
} daliasframe_t;
STATIC_ASSERT( sizeof( daliasframe_t ) == 24, "invalid daliasframe_t size" );
STATIC_CHECK_SIZEOF( daliasframe_t, 24, 24 );
typedef struct
{
@@ -112,41 +112,41 @@ typedef struct
trivertex_t bboxmax; // lightnormal isn't used
} daliasgroup_t;
STATIC_ASSERT( sizeof( daliasgroup_t ) == 12, "invalid daliasgrou_t size" );
STATIC_CHECK_SIZEOF( daliasgroup_t, 12, 12 );
typedef struct
{
int32_t numskins;
} daliasskingroup_t;
STATIC_ASSERT( sizeof( daliasskingroup_t ) == 4, "invalid daliasskingroup_t size" );
STATIC_CHECK_SIZEOF( daliasskingroup_t, 4, 4 );
typedef struct
{
float interval;
} daliasinterval_t;
STATIC_ASSERT( sizeof( daliasinterval_t ) == 4, "invalid daliasinterval_t size" );
STATIC_CHECK_SIZEOF( daliasinterval_t, 4, 4 );
typedef struct
{
float interval;
} daliasskininterval_t;
STATIC_ASSERT( sizeof( daliasskininterval_t ) == 4, "invalid daliasskininterval_t size" );
STATIC_CHECK_SIZEOF( daliasskininterval_t, 4, 4 );
typedef struct
{
uint32_t type; // was aliasframetype_t
} daliasframetype_t;
STATIC_ASSERT( sizeof( daliasframetype_t ) == 4, "invalid daliasframetype_t size" );
STATIC_CHECK_SIZEOF( daliasframetype_t, 4, 4 );
typedef struct
{
uint32_t type; // was aliasskintype_t
} daliasskintype_t;
STATIC_ASSERT( sizeof( daliasskintype_t ) == 4, "invalid daliasskintype_t size" );
STATIC_CHECK_SIZEOF( daliasskintype_t, 4, 4 );
#endif//ALIAS_H

View File

@@ -274,6 +274,13 @@ void CL_GenericShot_f( void )
string checkname;
int i;
// allow overriding screenshot by users request
if( Cmd_Argc() > 1 )
{
Q_strncpy( cls.shotname, Cmd_Argv( 1 ), sizeof( cls.shotname ));
break;
}
if( type == scrshot_snapshot )
{
fmt = "../%s_%04d.png";

View File

@@ -40,6 +40,8 @@ GNU General Public License for more details.
#define IDEMOHEADER (('M'<<24)+('E'<<16)+('D'<<8)+'I') // little-endian "IDEM"
#define DEMO_PROTOCOL 3
#define PROTOCOL_GOLDSRC_VERSION_DEMO (PROTOCOL_GOLDSRC_VERSION | (BIT( 7 ))) // should be 48, only to differentiate it from PROTOCOL_LEGACY_VERSION
const char *demo_cmd[dem_lastcmd+1] =
{
"dem_unknown",
@@ -79,7 +81,7 @@ typedef struct
typedef struct
{
demoentry_t *entries; // track entry info
int numentries; // number of tracks
int32_t numentries; // number of tracks
} demodirectory_t;
// add angles
@@ -120,7 +122,7 @@ static int CL_GetDemoNetProtocol( connprotocol_t proto )
case PROTO_QUAKE:
return PROTOCOL_VERSION_QUAKE;
case PROTO_GOLDSRC:
return PROTOCOL_GOLDSRC_VERSION;
return PROTOCOL_GOLDSRC_VERSION_DEMO;
}
return PROTOCOL_VERSION;
@@ -136,7 +138,7 @@ static connprotocol_t CL_GetProtocolFromDemo( int net_protocol )
return PROTO_LEGACY;
case PROTOCOL_VERSION_QUAKE:
return PROTO_QUAKE;
case PROTOCOL_GOLDSRC_VERSION:
case PROTOCOL_GOLDSRC_VERSION_DEMO:
return PROTO_GOLDSRC;
}
@@ -327,10 +329,6 @@ void CL_WriteDemoMessage( qboolean startup, int start, sizebuf_t *msg )
if( !file ) return;
// past the start but not recording a demo.
if( !startup && !cls.demorecording )
return;
swlen = MSG_GetNumBytesWritten( msg ) - start;
if( swlen <= 0 ) return;
@@ -710,7 +708,7 @@ static void CL_DemoStartPlayback( int mode )
demo.starttime = CL_GetDemoPlaybackClock(); // for determining whether to read another message
Netchan_Setup( NS_CLIENT, &cls.netchan, net_from, Cvar_VariableInteger( "net_qport" ), NULL, CL_GetFragmentSize );
Netchan_Setup( NS_CLIENT, &cls.netchan, net_from, Cvar_VariableInteger( "net_qport" ), NULL, CL_GetFragmentSize, 0 );
memset( demo.cmds, 0, sizeof( demo.cmds ));
demo.angle_position = 1;
@@ -1150,6 +1148,7 @@ show stats
*/
static void CL_FinishTimeDemo( void )
{
qboolean temp = host.allow_console;
int frames;
double time;
@@ -1160,7 +1159,9 @@ static void CL_FinishTimeDemo( void )
time = host.realtime - cls.td_starttime;
if( !time ) time = 1.0;
host.allow_console = true;
Con_Printf( "timedemo result: %i frames %5.3f seconds %5.3f fps\n", frames, time, frames / time );
host.allow_console = temp;
if( Sys_CheckParm( "-timedemo" ))
CL_Quit_f();
@@ -1449,6 +1450,51 @@ void CL_Record_f( void )
CL_WriteDemoHeader( demopath );
}
static qboolean CL_ParseDemoHeader( const char *callee, const char *filename, file_t *f, demoheader_t *hdr, int32_t *numentries )
{
if( FS_Read( f, hdr, sizeof( *hdr )) != sizeof( *hdr ) || hdr->id != IDEMOHEADER )
{
Con_Printf( S_ERROR "%s: %s is not in supported format or not a demo file\n", callee, filename );
return false;
}
// force null terminate strings
hdr->mapname[sizeof( hdr->mapname ) - 1] = 0;
hdr->comment[sizeof( hdr->comment ) - 1] = 0;
hdr->gamedir[sizeof( hdr->gamedir ) - 1] = 0;
if( hdr->dem_protocol != DEMO_PROTOCOL )
{
Con_Printf( S_ERROR "%s: demo protocol outdated (%i should be %i)\n",
callee, hdr->net_protocol, DEMO_PROTOCOL );
return false;
}
if( hdr->net_protocol != PROTOCOL_VERSION && hdr->net_protocol != PROTOCOL_LEGACY_VERSION )
{
Con_Printf( S_ERROR "%s: net protocol outdated (%i should be %i or %i)\n",
callee, hdr->net_protocol, PROTOCOL_VERSION, PROTOCOL_LEGACY_VERSION );
return false;
}
if( FS_Seek( f, hdr->directory_offset, SEEK_SET ) < 0
|| FS_Read( f, numentries, sizeof( *numentries )) != sizeof( *numentries ))
{
Con_Printf( S_ERROR "%s: can't find directory offset in %s, demo file corrupted\n",
callee, filename );
return false;
}
if(( *numentries < 1 ) || ( *numentries > 1024 ))
{
Con_Printf( S_ERROR "%s: demo have bogus # of directory entries: %i\n",
callee, *numentries );
return false;
}
return true;
}
/*
====================
CL_PlayDemo_f
@@ -1469,9 +1515,7 @@ void CL_PlayDemo_f( void )
}
if( cls.demoplayback )
{
CL_StopPlayback();
}
if( cls.demorecording )
{
@@ -1520,53 +1564,33 @@ void CL_PlayDemo_f( void )
}
if( neg ) cls.forcetrack = -cls.forcetrack;
cls.legacymode = PROTO_QUAKE;
CL_DemoStartPlayback( DEMO_QUAKE1 );
cls.legacymode = PROTO_QUAKE;
return; // quake demo is started
}
// read in the demo header
FS_Read( cls.demofile, &demo.header, sizeof( demoheader_t ));
if( demo.header.id != IDEMOHEADER )
if( !CL_ParseDemoHeader( Cmd_Argv( 0 ), filename, cls.demofile, &demo.header, &demo.directory.numentries ))
{
Con_Printf( S_ERROR "%s is not a demo file\n", demoname );
CL_DemoAborted();
return;
}
if( demo.header.dem_protocol != DEMO_PROTOCOL )
{
Con_Printf( S_ERROR "playdemo: demo protocol outdated (%i should be %i)\n", demo.header.dem_protocol, DEMO_PROTOCOL );
CL_DemoAborted();
return;
}
if( demo.header.net_protocol != PROTOCOL_VERSION &&
demo.header.net_protocol != PROTOCOL_LEGACY_VERSION )
{
Con_Printf( S_ERROR "playdemo: net protocol outdated (%i should be %i)\n", demo.header.net_protocol, PROTOCOL_VERSION );
CL_DemoAborted();
return;
}
// now read in the directory structure.
FS_Seek( cls.demofile, demo.header.directory_offset, SEEK_SET );
FS_Read( cls.demofile, &demo.directory.numentries, sizeof( int ));
if( demo.directory.numentries < 1 || demo.directory.numentries > 1024 )
{
Con_Printf( S_ERROR "demo had bogus # of directory entries: %i\n", demo.directory.numentries );
CL_DemoAborted();
return;
}
// allocate demo entries
demo.directory.entries = Mem_Malloc( cls.mempool, sizeof( demoentry_t ) * demo.directory.numentries );
demo.directory.entries = Mem_Malloc( cls.mempool, sizeof( *demo.directory.entries ) * demo.directory.numentries );
for( i = 0; i < demo.directory.numentries; i++ )
{
FS_Read( cls.demofile, &demo.directory.entries[i], sizeof( demoentry_t ));
demoentry_t *entry = &demo.directory.entries[i];
if( FS_Read( cls.demofile, entry, sizeof( *entry )) != sizeof( *entry ))
{
Con_Printf( S_ERROR "%s: demo entry %i of %s corrupted", Cmd_Argv( 0 ), i, filename );
CL_DemoAborted();
return;
}
entry->description[sizeof( entry->description ) - 1] = 0;
}
demo.entryIndex = 0;
@@ -1680,3 +1704,78 @@ void CL_Stop_f( void )
S_StopBackgroundTrack();
}
}
void CL_ListDemo_f( void )
{
demoheader_t hdr;
int32_t num_entries;
file_t *f;
char filename[MAX_QPATH];
char demoname[MAX_QPATH];
int i;
if( Cmd_Argc() < 2 )
{
Con_Printf( S_USAGE "%s <demoname>\n", Cmd_Argv( 0 ));
return;
}
Q_strncpy( demoname, Cmd_Argv( 1 ), sizeof( demoname ));
COM_StripExtension( demoname );
Q_snprintf( filename, sizeof( filename ), "%s.dem", demoname );
f = FS_Open( filename, "rb", true );
if( !f )
{
Con_Printf( S_ERROR "couldn't open %s\n", filename );
return;
}
if( !CL_ParseDemoHeader( Cmd_Argv( 0 ), filename, f, &hdr, &num_entries ))
{
FS_Close( f );
return;
}
Con_Printf( "Demo contents for %s:\n"
"\tProtocol: %i net/%i demo\n"
"\tFPS: %g\n"
"\tMap: %s\n"
"\tComment: %s\n"
"\tGame: %s\n",
filename, hdr.net_protocol, hdr.dem_protocol, hdr.host_fps, hdr.mapname,
hdr.comment, hdr.gamedir );
for( i = 0; i < num_entries; i++ )
{
demoentry_t entry;
Con_Printf( "Demo entry #%i:\n", i );
if( FS_Read( f, &entry, sizeof( entry )) != sizeof( entry ))
{
Con_Printf( S_ERROR "can't read demo entry\n" );
FS_Close( f );
return;
}
entry.description[sizeof( entry.description ) - 1] = 0;
if( entry.entrytype == DEMO_STARTUP )
{
// startup entries don't have anything useful
Con_Printf( "\tEntry type: " S_YELLOW "startup" S_DEFAULT "\n" );
}
else
{
Con_Printf( "\tEntry type: " S_GREEN "normal" S_DEFAULT " (%i)\n"
"\tEntry playback time/frames: %.2f seconds/%i frames\n"
"\tEntry flags: 0x%x\n"
"\tEntry description: %s\n",
entry.entrytype, entry.playback_time, entry.playback_frames,
entry.flags, entry.description );
}
}
FS_Close( f );
}

View File

@@ -28,10 +28,51 @@ GNU General Public License for more details.
===============================================================================
*/
#define NUM_EFRAGS_ALLOC 64 // alloc 64 efrags (1-2kb each alloc)
static efrag_t **lastlink;
static mnode_t *r_pefragtopnode;
static vec3_t r_emins, r_emaxs;
static cl_entity_t *r_addent;
static int cl_efrags_num;
static efrag_t *cl_efrags;
static efrag_t *CL_AllocEfrags( int num )
{
int i;
efrag_t *efrags;
if( !cl.worldmodel )
{
Host_Error( "%s: called with NULL world\n", __func__ );
return NULL;
}
if( num == 0 )
return NULL;
// set world to be the owner, so it will get automatically cleaned up
efrags = Mem_Calloc( cl.worldmodel->mempool, sizeof( *efrags ) * num );
// initialize linked list
for( i = 0; i < num - 1; i++ )
efrags[i].entnext = &efrags[i + 1];
cl_efrags_num += num;
return efrags;
}
/*
==============
CL_ClearEfrags
==============
*/
void CL_ClearEfrags( void )
{
cl_efrags_num = 0;
cl_efrags = NULL;
}
/*
===================
@@ -56,14 +97,11 @@ static void R_SplitEntityOnNode( mnode_t *node )
leaf = (mleaf_t *)node;
// grab an efrag off the free list
ef = clgame.free_efrags;
ef = cl_efrags;
if( !ef )
{
Con_Printf( S_ERROR "too many efrags!\n" );
return; // no free fragments...
}
ef = CL_AllocEfrags( NUM_EFRAGS_ALLOC );
clgame.free_efrags = ef->entnext;
cl_efrags = ef->entnext;
ef->entity = r_addent;
// add the entity link
@@ -133,35 +171,29 @@ R_StoreEfrags
*/
void R_StoreEfrags( efrag_t **ppefrag, int framecount )
{
cl_entity_t *pent;
model_t *clmodel;
efrag_t *pefrag;
efrag_t *pefrag;
cl_entity_t *pent;
model_t *clmodel;
while(( pefrag = *ppefrag ) != NULL )
{
pent = pefrag->entity;
clmodel = pent->model;
switch( clmodel->type )
{
case mod_alias:
case mod_brush:
case mod_studio:
case mod_sprite:
if( pent->visframe != framecount )
{
if( CL_AddVisibleEntity( pent, ET_FRAGMENTED ))
{
// mark that we've recorded this entity for this frame
pent->curstate.messagenum = cl.parsecount;
pent->visframe = framecount;
}
}
// how this could happen?
if( unlikely( clmodel->type < mod_brush || clmodel->type > mod_studio ))
continue;
ppefrag = &pefrag->leafnext;
break;
default:
break;
if( pent->visframe != framecount )
{
if( CL_AddVisibleEntity( pent, ET_FRAGMENTED ))
{
// mark that we've recorded this entity for this frame
pent->curstate.messagenum = cl.parsecount;
pent->visframe = framecount;
}
}
ppefrag = &pefrag->leafnext;
}
}

View File

@@ -25,13 +25,16 @@ static CVAR_DEFINE_AUTO( tracerspeed, "6000", 0, "tracer speed" );
static CVAR_DEFINE_AUTO( tracerlength, "0.8", 0, "tracer length factor" );
static CVAR_DEFINE_AUTO( traceroffset, "30", 0, "tracer starting offset" );
particle_t *cl_active_particles;
particle_t *cl_active_tracers;
particle_t *cl_free_particles;
particle_t *cl_particles = NULL; // particle pool
static particle_t *cl_active_particles;
static particle_t *cl_active_tracers;
static particle_t *cl_free_particles;
static particle_t *cl_particles = NULL; // particle pool
static vec3_t cl_avelocities[NUMVERTEXNORMALS];
static float cl_lasttimewarn = 0.0f;
// expand debugging BBOX particle hulls by this many units.
#define BOX_GAP 0.0f
/*
================
R_LookupColor
@@ -250,7 +253,7 @@ static particle_t *R_AllocTracer( const vec3_t org, const vec3_t vel, float life
VectorCopy( vel, p->vel );
p->die = cl.time + life;
p->ramp = tracerlength.value;
p->color = 4; // select custom color
p->color = TRACER_COLORINDEX_DEFAULT; // select custom color
p->packedColor = 255; // alpha
return p;
@@ -262,9 +265,9 @@ VIEWBEAMS MANAGEMENT
==============================================================
*/
BEAM *cl_active_beams;
BEAM *cl_free_beams;
BEAM *cl_viewbeams = NULL; // beams pool
static BEAM *cl_active_beams;
static BEAM *cl_free_beams;
static BEAM *cl_viewbeams = NULL; // beams pool
/*
@@ -636,12 +639,24 @@ and all particle trails (if this is a beamfollow)
*/
void GAME_EXPORT R_BeamKill( int deadEntity )
{
cl_entity_t *pDeadEntity;
BEAM *beam;
pDeadEntity = R_BeamGetEntity( deadEntity );
if( !pDeadEntity ) return;
for( beam = cl_active_beams; beam; beam = beam->next )
{
if( FBitSet( beam->flags, FBEAM_STARTENTITY ) && beam->startEntity == deadEntity )
{
if( beam->type != TE_BEAMFOLLOW )
beam->die = cl.time;
CL_KillDeadBeams( pDeadEntity );
ClearBits( beam->flags, FBEAM_STARTENTITY );
}
if( FBitSet( beam->flags, FBEAM_ENDENTITY ) && beam->endEntity == deadEntity )
{
beam->die = cl.time;
ClearBits( beam->flags, FBEAM_ENDENTITY );
}
}
}
/*
@@ -1094,9 +1109,7 @@ void GAME_EXPORT R_ParticleExplosion2( const vec3_t org, int colorStart, int col
int colorMod = 0, packedColor;
particle_t *p;
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
packedColor = 255; // use old code for blob particles
else packedColor = 0;
packedColor = Host_IsQuakeCompatible( ) ? 255 : 0; // use old code for blob particles
for( i = 0; i < 512; i++ )
{
@@ -1129,9 +1142,7 @@ void GAME_EXPORT R_BlobExplosion( const vec3_t org )
particle_t *p;
int i, j, packedColor;
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
packedColor = 255; // use old code for blob particles
else packedColor = 0;
packedColor = Host_IsQuakeCompatible( ) ? 255 : 0; // use old code for blob particles
for( i = 0; i < 1024; i++ )
{
@@ -1593,6 +1604,73 @@ void GAME_EXPORT R_RocketTrail( vec3_t start, vec3_t end, int type )
}
}
/*
===============
PM_ParticleLine
draw line from particles
================
*/
static void PM_ParticleLine( const vec3_t start, const vec3_t end, int pcolor, float life, float zvel )
{
float len, curdist;
vec3_t diff, pos;
// determine distance
VectorSubtract( end, start, diff );
len = VectorNormalizeLength( diff );
curdist = 0;
while( curdist <= len )
{
VectorMA( start, curdist, diff, pos );
CL_Particle( pos, pcolor, life, 0, zvel );
curdist += 2.0f;
}
}
/*
================
PM_DrawRectangle
================
*/
static void PM_DrawRectangle( const vec3_t tl, const vec3_t bl, const vec3_t tr, const vec3_t br, int pcolor, float life )
{
PM_ParticleLine( tl, bl, pcolor, life, 0 );
PM_ParticleLine( bl, br, pcolor, life, 0 );
PM_ParticleLine( br, tr, pcolor, life, 0 );
PM_ParticleLine( tr, tl, pcolor, life, 0 );
}
/*
================
PM_DrawBBox
================
*/
static void PM_DrawBBox( const vec3_t mins, const vec3_t maxs, const vec3_t origin, int pcolor, float life )
{
vec3_t p[8], tmp;
float gap = BOX_GAP;
int i;
for( i = 0; i < 8; i++ )
{
tmp[0] = (i & 1) ? mins[0] - gap : maxs[0] + gap;
tmp[1] = (i & 2) ? mins[1] - gap : maxs[1] + gap ;
tmp[2] = (i & 4) ? mins[2] - gap : maxs[2] + gap ;
VectorAdd( tmp, origin, tmp );
VectorCopy( tmp, p[i] );
}
for( i = 0; i < 6; i++ )
{
PM_DrawRectangle( p[boxpnt[i][1]], p[boxpnt[i][0]], p[boxpnt[i][2]], p[boxpnt[i][3]], pcolor, life );
}
}
/*
================
R_ParticleLine
@@ -1756,25 +1834,6 @@ void GAME_EXPORT R_StreakSplash( const vec3_t pos, const vec3_t dir, int color,
}
}
/*
===============
R_DebugParticle
just for debug purposes
===============
*/
void R_DebugParticle( const vec3_t pos, byte r, byte g, byte b )
{
particle_t *p;
p = R_AllocParticle( NULL );
if( !p ) return;
VectorCopy( pos, p->org );
p->color = R_LookupColor( r, g, b );
p->die = cl.time + 0.01f;
}
/*
===============
CL_Particle

View File

@@ -380,7 +380,7 @@ CL_ParseReliableEvent
=============
*/
void CL_ParseReliableEvent( sizebuf_t *msg )
void CL_ParseReliableEvent( sizebuf_t *msg, connprotocol_t proto )
{
int event_index;
event_args_t nullargs, args;
@@ -390,11 +390,19 @@ void CL_ParseReliableEvent( sizebuf_t *msg )
event_index = MSG_ReadUBitLong( msg, MAX_EVENT_BITS );
if( MSG_ReadOneBit( msg ))
delay = (float)MSG_ReadWord( msg ) * (1.0f / 100.0f);
// reliable events not use delta-compression just null-compression
MSG_ReadDeltaEvent( msg, &nullargs, &args );
if( proto == PROTO_GOLDSRC )
{
Delta_ReadGSFields( msg, DT_EVENT_T, &nullargs, &args, 0.0f );
if( MSG_ReadOneBit( msg ))
delay = (float)MSG_ReadWord( msg ) * (1.0f / 100.0f);
}
else
{
if( MSG_ReadOneBit( msg ))
delay = (float)MSG_ReadWord( msg ) * (1.0f / 100.0f);
MSG_ReadDeltaEvent( msg, &nullargs, &args );
}
if( args.entindex > 0 && args.entindex <= cl.maxclients )
args.angles[PITCH] *= -3.0f;
@@ -409,33 +417,42 @@ CL_ParseEvent
=============
*/
void CL_ParseEvent( sizebuf_t *msg )
void CL_ParseEvent( sizebuf_t *msg, connprotocol_t proto )
{
int event_index;
int i, num_events;
int packet_index;
event_args_t nullargs, args;
const event_args_t nullargs = { 0 };
event_args_t args = { 0 };
entity_state_t *state;
float delay;
memset( &nullargs, 0, sizeof( nullargs ));
memset( &args, 0, sizeof( args ));
int entity_bits;
num_events = MSG_ReadUBitLong( msg, 5 );
if( proto == PROTO_GOLDSRC )
entity_bits = MAX_GOLDSRC_ENTITY_BITS;
else if( proto == PROTO_LEGACY )
entity_bits = MAX_LEGACY_ENTITY_BITS;
else entity_bits = MAX_ENTITY_BITS;
// parse events queue
for( i = 0 ; i < num_events; i++ )
{
event_index = MSG_ReadUBitLong( msg, MAX_EVENT_BITS );
if( MSG_ReadOneBit( msg ))
packet_index = MSG_ReadUBitLong( msg, cls.legacymode ? MAX_LEGACY_ENTITY_BITS : MAX_ENTITY_BITS );
else packet_index = -1;
if( MSG_ReadOneBit( msg ))
{
MSG_ReadDeltaEvent( msg, &nullargs, &args );
packet_index = MSG_ReadUBitLong( msg, entity_bits );
if( MSG_ReadOneBit( msg ))
{
if( proto == PROTO_GOLDSRC )
Delta_ReadGSFields( msg, DT_EVENT_T, &nullargs, &args, 0.0f );
else MSG_ReadDeltaEvent( msg, &nullargs, &args );
}
}
else packet_index = -1;
if( MSG_ReadOneBit( msg ))
delay = (float)MSG_ReadWord( msg ) * (1.0f / 100.0f);

View File

@@ -95,8 +95,7 @@ static void CL_ResetPositions( cl_entity_t *ent )
ent->current_position = 1;
memset( ent->ph, 0, sizeof( position_history_t ) * HISTORY_MAX );
memcpy( &ent->ph[1], &store, sizeof( position_history_t ));
memcpy( &ent->ph[0], &store, sizeof( position_history_t ));
ent->ph[1] = ent->ph[0] = store;
}
/*
@@ -175,7 +174,7 @@ static qboolean CL_EntityCustomLerp( cl_entity_t *e )
// INTERPOLATION IN GRAVGUNMOD COOP
// MUST BE REMOVED ONCE WE REMOVE 48 PROTO SUPPORT
case MOVETYPE_TOSS:
if( cls.legacymode && e->model && e->model->type == mod_studio )
if( cls.legacymode == PROTO_LEGACY && e->model && e->model->type == mod_studio )
return false;
}
@@ -670,9 +669,9 @@ FRAME PARSING
=========================================================================
*/
static qboolean CL_ParseEntityNumFromPacket( sizebuf_t *msg, int *newnum )
static qboolean CL_ParseEntityNumFromPacket( sizebuf_t *msg, int *newnum, connprotocol_t proto )
{
if( cls.legacymode )
if( proto == PROTO_LEGACY )
{
*newnum = MSG_ReadWord( msg );
if( *newnum == 0 )
@@ -695,7 +694,7 @@ CL_FlushEntityPacket
Read and ignore whole entity packet.
=================
*/
static void CL_FlushEntityPacket( sizebuf_t *msg )
static void CL_FlushEntityPacket( sizebuf_t *msg, connprotocol_t proto )
{
int newnum;
entity_state_t from, to;
@@ -708,7 +707,7 @@ static void CL_FlushEntityPacket( sizebuf_t *msg )
// read it all, but ignore it
while( 1 )
{
if( !CL_ParseEntityNumFromPacket( msg, &newnum ))
if( !CL_ParseEntityNumFromPacket( msg, &newnum, proto ))
break; // done
if( MSG_CheckOverflow( msg ))
@@ -718,6 +717,47 @@ static void CL_FlushEntityPacket( sizebuf_t *msg )
}
}
qboolean CL_ValidateDeltaPacket( uint oldpacket, frame_t *oldframe )
{
int subtracted = ( cls.netchan.incoming_sequence - oldpacket ) & 0xFF;
if( subtracted == 0 )
{
Con_NPrintf( 2, "^3Warning:^1 update too old\n^7\n" );
return false;
}
if( subtracted >= CL_UPDATE_MASK )
{
// we can't use this, it is too old
Con_NPrintf( 2, "^3Warning:^1 delta frame is too old^7\n" );
return false;
}
if(( cls.next_client_entities - oldframe->first_entity ) > ( cls.num_client_entities - NUM_PACKET_ENTITIES ))
{
Con_NPrintf( 2, "^3Warning:^1 delta frame is too old^7\n" );
return false;
}
return true;
}
int CL_UpdateOldEntNum( int oldindex, frame_t *oldframe, entity_state_t **oldent )
{
if( !oldframe )
{
*oldent = NULL;
return MAX_ENTNUMBER;
}
if( oldindex >= oldframe->num_entities )
return MAX_ENTNUMBER;
*oldent = &cls.packet_entities[(oldframe->first_entity + oldindex) % cls.num_client_entities];
return (*oldent)->number;
}
/*
=================
CL_DeltaEntity
@@ -752,7 +792,7 @@ static void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_s
if( has_update )
alive = MSG_ReadDeltaEntity( msg, old, state, newnum, delta_type, cl.mtime[0] );
else memcpy( state, old, sizeof( entity_state_t ));
else *state = *old;
if( !alive )
{
@@ -788,7 +828,7 @@ An svc_packetentities has just been parsed, deal with the
rest of the data stream.
==================
*/
int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta, connprotocol_t proto )
{
frame_t *newframe, *oldframe;
int oldindex, newnum, oldnum;
@@ -804,7 +844,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
CL_WriteDemoJumpTime();
// sentinel count. save it for debug checking
if( cls.legacymode )
if( proto == PROTO_LEGACY )
count = MSG_ReadWord( msg );
else count = MSG_ReadUBitLong( msg, MAX_VISIBLE_PACKET_BITS ) + 1;
@@ -818,32 +858,12 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
if( delta )
{
int subtracted;
oldpacket = MSG_ReadByte( msg );
subtracted = ( cls.netchan.incoming_sequence - oldpacket ) & 0xFF;
if( subtracted == 0 )
{
Con_NPrintf( 2, "^3Warning:^1 update too old\n^7\n" );
CL_FlushEntityPacket( msg );
return playerbytes;
}
if( subtracted >= CL_UPDATE_MASK )
{
// we can't use this, it is too old
Con_NPrintf( 2, "^3Warning:^1 delta frame is too old^7\n" );
CL_FlushEntityPacket( msg );
return playerbytes;
}
uint oldpacket = MSG_ReadByte( msg );
oldframe = &cl.frames[oldpacket & CL_UPDATE_MASK];
if(( cls.next_client_entities - oldframe->first_entity ) > ( cls.num_client_entities - NUM_PACKET_ENTITIES ))
if( !CL_ValidateDeltaPacket( oldpacket, oldframe ))
{
Con_NPrintf( 2, "^3Warning:^1 delta frame is too old^7\n" );
CL_FlushEntityPacket( msg );
CL_FlushEntityPacket( msg, proto );
return playerbytes;
}
}
@@ -861,27 +881,11 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
oldent = NULL;
oldindex = 0;
if( !oldframe )
{
oldnum = MAX_ENTNUMBER;
}
else
{
if( oldindex >= oldframe->num_entities )
{
oldnum = MAX_ENTNUMBER;
}
else
{
oldent = &cls.packet_entities[(oldframe->first_entity+oldindex) % cls.num_client_entities];
oldnum = oldent->number;
}
}
oldnum = CL_UpdateOldEntNum( oldindex, oldframe, &oldent );
while( 1 )
{
if( !CL_ParseEntityNumFromPacket( msg, &newnum ))
if( !CL_ParseEntityNumFromPacket( msg, &newnum, proto ))
break; // done
if( MSG_CheckOverflow( msg ))
@@ -893,17 +897,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
{
// one or more entities from the old packet are unchanged
CL_DeltaEntity( msg, newframe, oldnum, oldent, false );
oldindex++;
if( oldindex >= oldframe->num_entities )
{
oldnum = MAX_ENTNUMBER;
}
else
{
oldent = &cls.packet_entities[(oldframe->first_entity+oldindex) % cls.num_client_entities];
oldnum = oldent->number;
}
oldnum = CL_UpdateOldEntNum( ++oldindex, oldframe, &oldent );
}
if( oldnum == newnum )
@@ -912,17 +906,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
bufStart = MSG_GetNumBytesRead( msg );
CL_DeltaEntity( msg, newframe, newnum, oldent, true );
if( player ) playerbytes += MSG_GetNumBytesRead( msg ) - bufStart;
oldindex++;
if( oldindex >= oldframe->num_entities )
{
oldnum = MAX_ENTNUMBER;
}
else
{
oldent = &cls.packet_entities[(oldframe->first_entity+oldindex) % cls.num_client_entities];
oldnum = oldent->number;
}
oldnum = CL_UpdateOldEntNum( ++oldindex, oldframe, &oldent );
continue;
}
@@ -941,17 +925,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
{
// one or more entities from the old packet are unchanged
CL_DeltaEntity( msg, newframe, oldnum, oldent, false );
oldindex++;
if( oldindex >= oldframe->num_entities )
{
oldnum = MAX_ENTNUMBER;
}
else
{
oldent = &cls.packet_entities[(oldframe->first_entity+oldindex) % cls.num_client_entities];
oldnum = oldent->number;
}
oldnum = CL_UpdateOldEntNum( ++oldindex, oldframe, &oldent );
}
if( newframe->num_entities != count && newframe->num_entities != 0 )
@@ -973,7 +947,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
cls.signon = SIGNONS;
// Clear loading plaque.
CL_SignonReply ();
CL_SignonReply( proto );
}
return playerbytes;
@@ -1291,7 +1265,7 @@ static void CL_LinkPacketEntities( frame_t *frame )
// ABSOLUTELY STUPID HACK TO ALLOW MONSTERS
// INTERPOLATION IN GRAVGUNMOD COOP
// MUST BE REMOVED ONCE WE REMOVE 48 PROTO SUPPORT
else if( cls.legacymode && ent->model->type == mod_studio && ent->curstate.movetype == MOVETYPE_TOSS )
else if( cls.legacymode == PROTO_LEGACY && ent->model->type == mod_studio && ent->curstate.movetype == MOVETYPE_TOSS )
{
if( !CL_InterpolateModel( ent ))
continue;

View File

@@ -34,10 +34,10 @@ GNU General Public License for more details.
#define MAX_TEXTCHANNELS 8 // must be power of two (GoldSrc uses 4 channels)
#define TEXT_MSGNAME "TextMessage%i"
char cl_textbuffer[MAX_TEXTCHANNELS][2048];
client_textmessage_t cl_textmessage[MAX_TEXTCHANNELS];
static char cl_textbuffer[MAX_TEXTCHANNELS][2048];
static client_textmessage_t cl_textmessage[MAX_TEXTCHANNELS];
static dllfunc_t cdll_exports[] =
static const dllfunc_t cdll_exports[] =
{
{ "Initialize", (void **)&clgame.dllFuncs.pfnInitialize },
{ "HUD_VidInit", (void **)&clgame.dllFuncs.pfnVidInit },
@@ -80,7 +80,7 @@ static dllfunc_t cdll_exports[] =
};
// optional exports
static dllfunc_t cdll_new_exports[] = // allowed only in SDK 2.3 and higher
static const dllfunc_t cdll_new_exports[] = // allowed only in SDK 2.3 and higher
{
{ "HUD_GetStudioModelInterface", (void **)&clgame.dllFuncs.pfnGetStudioModelInterface },
{ "HUD_DirectorMessage", (void **)&clgame.dllFuncs.pfnDirectorMessage },
@@ -140,11 +140,7 @@ returns true if thirdperson is enabled
*/
qboolean CL_IsThirdPerson( void )
{
cl.local.thirdperson = clgame.dllFuncs.CL_IsThirdPerson();
if( cl.local.thirdperson )
return true;
return false;
return clgame.dllFuncs.CL_IsThirdPerson() ? true : false;
}
/*
@@ -252,18 +248,18 @@ static int CL_AdjustXPos( float x, int width, int totalWidth )
if( x == -1 )
{
xPos = ( refState.width - width ) * 0.5f;
xPos = ( clgame.scrInfo.iWidth - width ) * 0.5f;
}
else
{
if ( x < 0 )
xPos = (1.0f + x) * refState.width - totalWidth; // Alight right
xPos = (1.0f + x) * clgame.scrInfo.iWidth - totalWidth; // Alight right
else // align left
xPos = x * refState.width;
xPos = x * clgame.scrInfo.iWidth;
}
if( xPos + width > refState.width )
xPos = refState.width - width;
if( xPos + width > clgame.scrInfo.iWidth )
xPos = clgame.scrInfo.iWidth - width;
else if( xPos < 0 )
xPos = 0;
@@ -283,19 +279,19 @@ static int CL_AdjustYPos( float y, int height )
if( y == -1 ) // centered?
{
yPos = ( refState.height - height ) * 0.5f;
yPos = ( clgame.scrInfo.iHeight - height ) * 0.5f;
}
else
{
// Alight bottom?
if( y < 0 )
yPos = (1.0f + y) * refState.height - height; // Alight bottom
yPos = (1.0f + y) * clgame.scrInfo.iHeight - height; // Alight bottom
else // align top
yPos = y * refState.height;
yPos = y * clgame.scrInfo.iHeight;
}
if( yPos + height > refState.height )
yPos = refState.height - height;
if( yPos + height > clgame.scrInfo.iHeight )
yPos = clgame.scrInfo.iHeight - height;
else if( yPos < 0 )
yPos = 0;
@@ -560,7 +556,19 @@ static void CL_DrawScreenFade( void )
if( !alpha )
return;
if( FBitSet( sf->fadeFlags, FFADE_MODULATE ))
if( !FBitSet( sf->fadeFlags, FFADE_MODULATE ))
{
ref.dllFuncs.GL_SetRenderMode( kRenderTransTexture );
ref.dllFuncs.Color4ub( sf->fader, sf->fadeg, sf->fadeb, alpha );
}
else if( Host_IsQuakeCompatible( ))
{
// Quake Wrapper and Quake Remake use FFADE_MODULATE for item pickups
// so hack the check here
ref.dllFuncs.GL_SetRenderMode( kRenderTransAdd );
ref.dllFuncs.Color4ub( sf->fader, sf->fadeg, sf->fadeb, alpha );
}
else
{
ref.dllFuncs.GL_SetRenderMode( kRenderScreenFadeModulate );
@@ -570,11 +578,6 @@ static void CL_DrawScreenFade( void )
(uint16_t)( sf->fadeb * alpha + ( 255 - alpha ) * 255 ) >> 8,
255 );
}
else
{
ref.dllFuncs.GL_SetRenderMode( kRenderTransTexture );
ref.dllFuncs.Color4ub( sf->fader, sf->fadeg, sf->fadeb, alpha );
}
ref.dllFuncs.R_DrawStretchPic( 0, 0, refState.width, refState.height, 0, 0, 1, 1,
R_GetBuiltinTexture( REF_WHITE_TEXTURE ));
@@ -1012,7 +1015,8 @@ void CL_DrawHUD( int state )
CL_DrawCrosshair ();
CL_DrawCenterPrint ();
clgame.dllFuncs.pfnRedraw( cl.time, cl.intermission );
CL_DrawLoadingOrPaused( cls.pauseIcon );
if( showpause.value )
CL_DrawLoadingOrPaused( cls.pauseIcon );
break;
case CL_LOADING:
CL_DrawLoadingOrPaused( cls.loadingBar );
@@ -1182,7 +1186,7 @@ static qboolean CL_LoadHudSprite( const char *szSpriteName, model_t *m_pSprite,
if( type == SPR_CLIENT || type == SPR_HUDSPRITE )
SetBits( m_pSprite->flags, MODEL_CLIENT );
m_pSprite->numtexinfo = texFlags; // store texFlags into numtexinfo
m_pSprite->numtexinfo = texFlags; // store texFlags for renderer into numtexinfo
if( !FS_FileExists( szSpriteName, false ) )
{
@@ -1209,7 +1213,7 @@ static qboolean CL_LoadHudSprite( const char *szSpriteName, model_t *m_pSprite,
ref.dllFuncs.Mod_LoadMapSprite( m_pSprite, buf, size, &loaded );
else
{
Mod_LoadSpriteModel( m_pSprite, buf, &loaded, texFlags );
Mod_LoadSpriteModel( m_pSprite, buf, &loaded );
ref.dllFuncs.Mod_ProcessRenderData( m_pSprite, true, buf );
}
@@ -2428,8 +2432,8 @@ static void GAME_EXPORT pfnLocalPlayerBounds( int hull, float *mins, float *maxs
{
if( hull >= 0 && hull < 4 )
{
if( mins ) VectorCopy( clgame.pmove->player_mins[hull], mins );
if( maxs ) VectorCopy( clgame.pmove->player_maxs[hull], maxs );
if( mins ) VectorCopy( host.player_mins[hull], mins );
if( maxs ) VectorCopy( host.player_maxs[hull], maxs );
}
}
@@ -2497,9 +2501,17 @@ CL_PushTraceBounds
*/
static void GAME_EXPORT CL_PushTraceBounds( int hullnum, const float *mins, const float *maxs )
{
if( !host.trace_bounds_pushed )
{
memcpy( host.player_mins_backup, host.player_mins, sizeof( host.player_mins_backup ));
memcpy( host.player_maxs_backup, host.player_maxs, sizeof( host.player_maxs_backup ));
host.trace_bounds_pushed = true;
}
hullnum = bound( 0, hullnum, 3 );
VectorCopy( mins, clgame.pmove->player_mins[hullnum] );
VectorCopy( maxs, clgame.pmove->player_maxs[hullnum] );
VectorCopy( mins, host.player_mins[hullnum] );
VectorCopy( maxs, host.player_maxs[hullnum] );
}
/*
@@ -2510,8 +2522,15 @@ CL_PopTraceBounds
*/
static void GAME_EXPORT CL_PopTraceBounds( void )
{
memcpy( clgame.pmove->player_mins, host.player_mins, sizeof( host.player_mins ));
memcpy( clgame.pmove->player_maxs, host.player_maxs, sizeof( host.player_maxs ));
if( !host.trace_bounds_pushed )
{
Con_Reportf( S_ERROR "%s called without push!\n", __func__ );
return;
}
host.trace_bounds_pushed = false;
memcpy( host.player_mins, host.player_mins_backup, sizeof( host.player_mins ));
memcpy( host.player_maxs, host.player_maxs_backup, sizeof( host.player_maxs ));
}
/*
@@ -3283,7 +3302,7 @@ Heavy legacy of Quake...
*/
void TriColor4fRendermode( float r, float g, float b, float a, int rendermode )
{
if( clgame.ds.renderMode == kRenderTransAlpha )
if( rendermode == kRenderTransAlpha )
{
clgame.ds.triRGBA[3] = a / 255.0f;
ref.dllFuncs.Color4f( r, g, b, a );
@@ -3415,7 +3434,6 @@ NetAPI_SendRequest
static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags, double timeout, netadr_t *remote_address, net_api_response_func_t response )
{
net_request_t *nr = NULL;
string req;
int i;
if( !response )
@@ -3467,8 +3485,7 @@ static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags,
nr->flags = flags;
// local servers request
Q_snprintf( req, sizeof( req ), "netinfo %i %i %i", FBitSet( flags, FNETAPI_LEGACY_PROTOCOL ) ? PROTOCOL_LEGACY_VERSION : PROTOCOL_VERSION, context, request );
Netchan_OutOfBandPrint( NS_CLIENT, nr->resp.remote_address, "%s", req );
Netchan_OutOfBandPrint( NS_CLIENT, nr->resp.remote_address, "netinfo %i %i %i", FBitSet( flags, FNETAPI_LEGACY_PROTOCOL ) ? PROTOCOL_LEGACY_VERSION : PROTOCOL_VERSION, context, request );
}
/*

View File

@@ -25,6 +25,14 @@ static void UI_UpdateUserinfo( void );
gameui_static_t gameui;
static void UI_ToggleAllowConsole_f( void )
{
host.allow_console = host.allow_console_init = true;
if( gameui.globals )
gameui.globals->developer = true;
}
void UI_UpdateMenu( float realtime )
{
if( !gameui.hInstance ) return;
@@ -399,17 +407,21 @@ void Host_Credits( void )
gameui.dllFuncs.pfnFinalCredits();
}
static void UI_ConvertGameInfo( GAMEINFO *out, gameinfo_t *in )
static void UI_ConvertGameInfo( gameinfo2_t *out, const gameinfo_t *in )
{
out->gi_version = GAMEINFO_VERSION;
Q_strncpy( out->gamefolder, in->gamefolder, sizeof( out->gamefolder ));
Q_strncpy( out->startmap, in->startmap, sizeof( out->startmap ));
Q_strncpy( out->trainmap, in->trainmap, sizeof( out->trainmap ));
Q_strncpy( out->demomap, in->demomap, sizeof( out->demomap ));
Q_strncpy( out->title, in->title, sizeof( out->title ));
Q_snprintf( out->version, sizeof( out->version ), "%g", in->version );
Q_strncpy( out->iconpath, in->iconpath, sizeof( out->iconpath ));
Q_strncpy( out->game_url, in->game_url, sizeof( out->game_url ));
Q_strncpy( out->update_url, in->update_url, sizeof( out->update_url ));
Q_strncpy( out->size, Q_pretifymem( in->size, 0 ), sizeof( out->size ));
out->size = in->size;
Q_strncpy( out->type, in->type, sizeof( out->type ));
Q_strncpy( out->date, in->date, sizeof( out->date ));
@@ -427,6 +439,31 @@ static void UI_ConvertGameInfo( GAMEINFO *out, gameinfo_t *in )
SetBits( out->flags, GFL_ANIMATED_TITLE );
}
static void UI_ToOldGameInfo( GAMEINFO *out, const gameinfo2_t *in )
{
Q_strncpy( out->gamefolder, in->gamefolder, sizeof( out->gamefolder ));
Q_strncpy( out->startmap, in->startmap, sizeof( out->startmap ));
Q_strncpy( out->trainmap, in->trainmap, sizeof( out->trainmap ));
Q_strncpy( out->title, in->title, sizeof( out->title ));
Q_strncpy( out->version, in->version, sizeof( out->version ));
out->flags = in->flags & 0xFFFF;
Q_strncpy( out->game_url, in->game_url, sizeof( out->game_url ));
Q_strncpy( out->update_url, in->update_url, sizeof( out->update_url ));
Q_strncpy( out->size, Q_memprint( in->size ), sizeof( out->size ));
Q_strncpy( out->type, in->type, sizeof( out->type ));
Q_strncpy( out->date, in->date, sizeof( out->date ));
out->gamemode = in->gamemode;
}
static void UI_GetModsInfo( void )
{
int i;
gameui.modsInfo = Mem_Calloc( gameui.mempool, sizeof( *gameui.modsInfo ) * FI->numgames );
for( i = 0; i < FI->numgames; i++ )
UI_ConvertGameInfo( &gameui.modsInfo[i], FI->games[i] );
}
/*
====================
PIC_DrawGeneric
@@ -924,11 +961,12 @@ pfnGetGameInfo
=========
*/
static int GAME_EXPORT pfnGetGameInfo( GAMEINFO *pgameinfo )
static int GAME_EXPORT pfnGetOldGameInfo( GAMEINFO *pgameinfo )
{
if( !pgameinfo ) return 0;
if( !pgameinfo )
return 0;
*pgameinfo = gameui.gameInfo;
UI_ToOldGameInfo( pgameinfo, &gameui.gameInfo );
return 1;
}
@@ -940,8 +978,26 @@ pfnGetGamesList
*/
static GAMEINFO ** GAME_EXPORT pfnGetGamesList( int *numGames )
{
if( numGames ) *numGames = FI->numgames;
return gameui.modsInfo;
if( numGames )
*numGames = FI->numgames;
if( !gameui.oldModsInfo )
{
int i;
if( !gameui.modsInfo )
UI_GetModsInfo();
// first allocate array of pointers
gameui.oldModsInfo = Mem_Calloc( gameui.mempool, sizeof( *gameui.oldModsInfo ) * FI->numgames );
for( i = 0; i < FI->numgames; i++ )
{
gameui.oldModsInfo[i] = Mem_Calloc( gameui.mempool, sizeof( *gameui.oldModsInfo[i] ));
UI_ToOldGameInfo( gameui.oldModsInfo[i], &gameui.modsInfo[i] );
}
}
return gameui.oldModsInfo;
}
/*
@@ -1114,7 +1170,7 @@ static void GAME_EXPORT pfnSetCursor( void *hCursor )
}
// engine callbacks
static ui_enginefuncs_t gEngfuncs =
static const ui_enginefuncs_t gEngfuncs =
{
pfnPIC_Load,
GL_FreeImage,
@@ -1178,7 +1234,7 @@ static ui_enginefuncs_t gEngfuncs =
pfnKeyGetState,
pfnMemAlloc,
pfnMemFree,
pfnGetGameInfo,
pfnGetOldGameInfo,
pfnGetGamesList,
pfnGetFilesList,
SV_GetSaveComment,
@@ -1225,6 +1281,28 @@ static char *pfnParseFileSafe( char *data, char *buf, const int size, unsigned i
return COM_ParseFileSafe( data, buf, size, flags, len, NULL );
}
static gameinfo2_t *pfnGetGameInfo( int gi_version )
{
if( gi_version != gameui.gameInfo.gi_version )
return NULL;
return &gameui.gameInfo;
}
static gameinfo2_t *pfnGetModInfo( int gi_version, int i )
{
if( i < 0 || i >= FI->numgames )
return NULL;
if( !gameui.modsInfo )
UI_GetModsInfo();
if( gi_version != gameui.modsInfo[i].gi_version )
return NULL;
return &gameui.modsInfo[i];
}
static ui_extendedfuncs_t gExtendedfuncs =
{
pfnEnableTextInput,
@@ -1238,6 +1316,8 @@ static ui_extendedfuncs_t gExtendedfuncs =
NET_CompareAdrSort,
Sys_GetNativeObject,
&gNetApi,
pfnGetGameInfo,
pfnGetModInfo,
};
void UI_UnloadProgs( void )
@@ -1247,6 +1327,7 @@ void UI_UnloadProgs( void )
// deinitialize game
gameui.dllFuncs.pfnShutdown();
Cmd_RemoveCommand( "ui_allowconsole" );
Cvar_FullSet( "host_gameuiloaded", "0", FCVAR_READ_ONLY );
Cvar_Unlink( FCVAR_GAMEUIDLL );
@@ -1306,7 +1387,7 @@ qboolean UI_LoadProgs( void )
gameui.use_extended_api = false;
// make local copy of engfuncs to prevent overwrite it with user dll
memcpy( &gpEngfuncs, &gEngfuncs, sizeof( gpEngfuncs ));
gpEngfuncs = gEngfuncs;
gameui.mempool = Mem_AllocPool( "Menu Pool" );
@@ -1320,7 +1401,7 @@ qboolean UI_LoadProgs( void )
}
// make local copy of engfuncs to prevent overwrite it with user dll
memcpy( &gpExtendedfuncs, &gExtendedfuncs, sizeof( gExtendedfuncs ));
gpExtendedfuncs = gExtendedfuncs;
memset( &gameui.dllFuncs2, 0, sizeof( gameui.dllFuncs2 ));
// try to initialize new extended API
@@ -1355,13 +1436,7 @@ qboolean UI_LoadProgs( void )
}
Cvar_FullSet( "host_gameuiloaded", "1", FCVAR_READ_ONLY );
// setup gameinfo
for( i = 0; i < FI->numgames; i++ )
{
gameui.modsInfo[i] = Mem_Calloc( gameui.mempool, sizeof( GAMEINFO ));
UI_ConvertGameInfo( gameui.modsInfo[i], FI->games[i] );
}
Cmd_AddRestrictedCommand( "ui_allowconsole", UI_ToggleAllowConsole_f, "unlocks developer console" );
UI_ConvertGameInfo( &gameui.gameInfo, FI->GameInfo ); // current gameinfo

View File

@@ -30,6 +30,7 @@ GNU General Public License for more details.
#define CL_CONNECTION_RETRIES 10
#define CL_TEST_RETRIES 5
CVAR_DEFINE_AUTO( showpause, "1", 0, "show pause logo when paused" );
CVAR_DEFINE_AUTO( mp_decals, "300", FCVAR_ARCHIVE, "decals limit in multiplayer" );
static CVAR_DEFINE_AUTO( dev_overview, "0", 0, "draw level in overview-mode" );
static CVAR_DEFINE_AUTO( cl_resend, "6.0", 0, "time to resend connect" );
@@ -75,7 +76,7 @@ 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_stufftext, "0", FCVAR_ARCHIVE|FCVAR_CHEAT, "enable stufftext (server-to-client console commands) 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)" );
static CVAR_DEFINE_AUTO( cl_nat, "0", 0, "show servers running under NAT" );
@@ -87,12 +88,14 @@ CVAR_DEFINE_AUTO( cl_fixmodelinterpolationartifacts, "1", 0, "try to fix up mode
//
// userinfo
//
static CVAR_DEFINE_AUTO( name, "player", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_PRINTABLEONLY|FCVAR_FILTERABLE, "player name" );
static char username[32];
static CVAR_DEFINE_AUTO( name, username, FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_PRINTABLEONLY|FCVAR_FILTERABLE, "player name" );
static CVAR_DEFINE_AUTO( model, "", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player model ('player' is a singleplayer model)" );
static CVAR_DEFINE_AUTO( topcolor, "0", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player top color" );
static CVAR_DEFINE_AUTO( bottomcolor, "0", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player bottom color" );
CVAR_DEFINE_AUTO( rate, "3500", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player network rate" );
client_t cl;
client_static_t cls;
clgame_static_t clgame;
@@ -168,6 +171,11 @@ int CL_IsDevOverviewMode( void )
return 0;
}
connprotocol_t CL_Protocol( void )
{
return cls.legacymode;
}
/*
===============
CL_CheckClientState
@@ -215,7 +223,7 @@ CL_SignonReply
An svc_signonnum has been received, perform a client side setup
=====================
*/
void CL_SignonReply( void )
void CL_SignonReply( connprotocol_t proto )
{
// g-cont. my favorite message :-)
Con_Reportf( "%s: %i\n", __func__, cls.signon );
@@ -223,7 +231,7 @@ void CL_SignonReply( void )
switch( cls.signon )
{
case 1:
CL_ServerCommand( true, "begin" );
CL_ServerCommand( true, proto == PROTO_GOLDSRC ? "sendents" : "begin" );
if( host_developer.value >= DEV_EXTENDED )
Mem_PrintStats();
break;
@@ -591,7 +599,7 @@ static void CL_CreateCmd( void )
int input_override;
int i, ms;
if( cls.state < ca_connected || cls.state == ca_cinematic )
if( cls.state <= ca_connected || cls.state == ca_cinematic )
return;
// store viewangles in case it's will be freeze
@@ -642,7 +650,7 @@ static void CL_CreateCmd( void )
active = (( cls.signon == SIGNONS ) && !cl.paused && !cls.demoplayback );
Platform_PreCreateMove();
clgame.dllFuncs.CL_CreateMove( host.frametime, cmd, active );
IN_EngineAppendMove( host.frametime, cmd, active );
IN_EngineAppendMove( host.frametime, cmd, active );
CL_PopPMStates();
@@ -672,26 +680,28 @@ static void CL_CreateCmd( void )
void CL_WriteUsercmd( sizebuf_t *msg, int from, int to )
{
usercmd_t nullcmd;
usercmd_t *f, *t;
const usercmd_t nullcmd = { 0 };
const usercmd_t *f;
usercmd_t *t;
Assert( from == -1 || ( from >= 0 && from < MULTIPLAYER_BACKUP ));
Assert( to >= 0 && to < MULTIPLAYER_BACKUP );
if( from == -1 )
{
memset( &nullcmd, 0, sizeof( nullcmd ));
f = &nullcmd;
}
else
{
f = &cl.commands[from].cmd;
}
t = &cl.commands[to].cmd;
// write it into the buffer
MSG_WriteDeltaUsercmd( msg, f, t );
if( cls.legacymode == PROTO_GOLDSRC )
{
MSG_StartBitWriting( msg );
Delta_WriteGSFields( msg, DT_USERCMD_T, f, t, 0.0f );
MSG_EndBitWriting( msg );
}
else MSG_WriteDeltaUsercmd( msg, f, t );
}
/*
@@ -708,8 +718,8 @@ static void CL_WritePacket( void )
qboolean send_command = false;
byte data[MAX_CMD_BUFFER];
int i, from, to, key, size;
int numbackup = 2;
int numcmds;
int numbackup = 2, maxbackup;
int numcmds, maxcmds;
int newcmds;
int cmdnumber;
@@ -717,24 +727,41 @@ static void CL_WritePacket( void )
if( cls.demoplayback || cls.state < ca_connected || cls.state == ca_cinematic )
return;
if( cls.state <= ca_validate )
{
Netchan_TransmitBits( &cls.netchan, 0, "" );
return;
}
CL_ComputePacketLoss ();
memset( data, 0, sizeof( data ));
MSG_Init( &buf, "ClientData", data, sizeof( data ));
// Determine number of backup commands to send along
numbackup = bound( 0, cl_cmdbackup.value, cls.legacymode ? MAX_LEGACY_BACKUP_CMDS : MAX_BACKUP_COMMANDS );
if( cls.state == ca_connected ) numbackup = 0;
switch( cls.legacymode )
{
case PROTO_GOLDSRC:
maxbackup = MAX_GOLDSRC_BACKUP_CMDS;
maxcmds = MAX_GOLDSRC_TOTAL_CMDS;
break;
case PROTO_LEGACY:
maxbackup = MAX_LEGACY_BACKUP_CMDS;
maxcmds = MAX_LEGACY_TOTAL_CMDS;
break;
default:
maxbackup = MAX_BACKUP_COMMANDS;
maxcmds = MAX_TOTAL_CMDS;
break;
}
numbackup = bound( 0, cl_cmdbackup.value, maxbackup );
// clamp cmdrate
if( cl_cmdrate.value < 10.0f )
{
Cvar_DirectSet( &cl_cmdrate, "10" );
}
else if( cl_cmdrate.value > 100.0f )
{
Cvar_DirectSet( &cl_cmdrate, "100" );
}
// Check to see if we can actually send this command
@@ -790,12 +817,15 @@ static void CL_WritePacket( void )
// begin a client move command
MSG_BeginClientCmd( &buf, clc_move );
if( cls.legacymode == PROTO_GOLDSRC )
MSG_WriteByte( &buf, 0 ); // length
// save the position for a checksum byte
key = MSG_GetRealBytesWritten( &buf );
MSG_WriteByte( &buf, 0 );
// write packet lossage percentation
MSG_WriteByte( &buf, cls.packet_loss );
MSG_WriteByte( &buf, bound( 0, (int)cls.packet_loss, 100 ) );
// say how many backups we'll be sending
MSG_WriteByte( &buf, numbackup );
@@ -804,8 +834,10 @@ static void CL_WritePacket( void )
newcmds = ( cls.netchan.outgoing_sequence - cls.lastoutgoingcommand );
// put an upper/lower bound on this
newcmds = bound( 0, newcmds, cls.legacymode ? MAX_LEGACY_TOTAL_CMDS: MAX_TOTAL_CMDS );
if( cls.state == ca_connected ) newcmds = 0;
newcmds = bound( 0, newcmds, maxcmds );
if( cls.state == ca_connected )
newcmds = 0;
MSG_WriteByte( &buf, newcmds );
@@ -826,8 +858,20 @@ static void CL_WritePacket( void )
}
// calculate a checksum over the move commands
size = MSG_GetRealBytesWritten( &buf ) - key - 1;
buf.pData[key] = CRC32_BlockSequence( buf.pData + key + 1, size, cls.netchan.outgoing_sequence );
if( cls.legacymode == PROTO_GOLDSRC )
{
size = MSG_GetRealBytesWritten( &buf ) - key - 1;
buf.pData[key - 1] = Q_min( size, 255 );
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
{
size = MSG_GetRealBytesWritten( &buf ) - key - 1;
buf.pData[key] = CRC32_BlockSequence( buf.pData + key + 1, size, cls.netchan.outgoing_sequence );
}
// message we are constructing.
i = cls.netchan.outgoing_sequence & CL_UPDATE_MASK;
@@ -997,6 +1041,62 @@ void CL_Drop( void )
CL_Disconnect();
}
static void CL_GetCDKey( char *protinfo, size_t protinfosize )
{
byte hash[16] = { 0 };
MD5Context_t ctx = { 0 };
char key[64];
int keylength;
keylength = Q_snprintf( key, sizeof( key ), "%u", COM_RandomLong( 0, 0x7fffffff ));
MD5Init( &ctx );
MD5Update( &ctx, key, keylength );
MD5Final( hash, &ctx );
Q_strnlwr( MD5_Print( hash ), key, sizeof( key ));
Info_SetValueForKey( protinfo, "cdkey", key, protinfosize );
}
#include "multi_emulator.h"
static CVAR_DEFINE_AUTO( cl_ticket_generator, "revemu2013", FCVAR_ARCHIVE, "you wouldn't steal a car" );
static size_t CL_GenerateSteamTicket( byte *buf, size_t size )
{
const char *s = ID_GetMD5();
uint32_t crc;
CRC32_Init( &crc );
CRC32_ProcessBuffer( &crc, s, Q_strlen( s ));
crc = CRC32_Final( crc );
if( !Q_stricmp( cl_ticket_generator.string, "revemu2013" ))
return GenerateRevEmu2013( buf, crc );
if( !Q_stricmp( cl_ticket_generator.string, "sc2009" ))
return GenerateSC2009( buf, crc );
if( !Q_stricmp( cl_ticket_generator.string, "oldrevemu" ))
return GenerateOldRevEmu( buf, crc );
if( !Q_stricmp( cl_ticket_generator.string, "steamemu" ))
return GenerateSteamEmu( buf, crc );
if( !Q_stricmp( cl_ticket_generator.string, "revemu" ))
return GenerateRevEmu( buf, crc );
if( !Q_stricmp( cl_ticket_generator.string, "setti" ))
return GenerateSetti( buf );
if( !Q_stricmp( cl_ticket_generator.string, "avsmp" ))
return GenerateAVSMP( buf, crc, true );
Con_Printf( "%s: unknown generator %s, supported are: revemu2003, sc2009, oldrevemu, steamemu, revemu, setti, avsmp\n", __func__, cl_ticket_generator.string );
memset( buf, 0, size );
return size;
}
/*
=======================
CL_SendConnectPacket
@@ -1036,18 +1136,68 @@ static void CL_SendConnectPacket( void )
input_devices = IN_CollectInputDevices();
IN_LockInputDevices( true );
Cvar_SetCheatState();
Cvar_FullSet( "sv_cheats", "0", FCVAR_READ_ONLY | FCVAR_SERVER );
// GoldSrc doesn't need sv_cheats set to 0, it's handled by svc_goldsrc_sendextrainfo
// it also doesn't need useragent string
if( cls.legacymode != PROTO_GOLDSRC )
{
Cvar_SetCheatState();
Cvar_FullSet( "sv_cheats", "0", FCVAR_READ_ONLY | FCVAR_SERVER );
Info_SetValueForKeyf( protinfo, "d", sizeof( protinfo ), "%d", input_devices );
Info_SetValueForKey( protinfo, "v", XASH_VERSION, sizeof( protinfo ) );
Info_SetValueForKeyf( protinfo, "b", sizeof( protinfo ), "%d", Q_buildnum( ));
Info_SetValueForKey( protinfo, "o", Q_buildos(), sizeof( protinfo ) );
Info_SetValueForKey( protinfo, "a", Q_buildarch(), sizeof( protinfo ) );
Info_SetValueForKeyf( protinfo, "d", sizeof( protinfo ), "%d", input_devices );
Info_SetValueForKey( protinfo, "v", XASH_VERSION, sizeof( protinfo ) );
Info_SetValueForKeyf( protinfo, "b", sizeof( protinfo ), "%d", Q_buildnum( ));
Info_SetValueForKey( protinfo, "o", Q_buildos(), sizeof( protinfo ) );
Info_SetValueForKey( protinfo, "a", Q_buildarch(), sizeof( protinfo ) );
}
}
if( cls.legacymode )
if( cls.legacymode == PROTO_GOLDSRC )
{
byte send_buf[1024];
byte steam_cert[512];
string new_name;
const char *name;
size_t steam_cert_len;
sizebuf_t send;
protinfo[0] = 0;
steam_cert_len = CL_GenerateSteamTicket( steam_cert, sizeof( steam_cert ));
Info_SetValueForKey( protinfo, "prot", "3", sizeof( protinfo )); // steam auth type
Info_SetValueForKeyf( protinfo, "unique", sizeof( protinfo ), "%i", 0xffffffff );
Info_SetValueForKey( protinfo, "raw", "steam", sizeof( protinfo ));
CL_GetCDKey( protinfo, sizeof( protinfo ));
// remove keys set for legacy protocol
Info_RemoveKey( cls.userinfo, "cl_maxpacket" );
Info_RemoveKey( cls.userinfo, "cl_maxpayload" );
name = Info_ValueForKey( cls.userinfo, "name" );
if( Q_strnicmp( name, "[Xash3D]", 8 ))
{
Q_snprintf( new_name, sizeof( new_name ), "[Xash3D]%s", name );
Info_SetValueForKey( cls.userinfo, "name", new_name, sizeof( cls.userinfo ));
}
MSG_Init( &send, "GoldSrcConnect", send_buf, sizeof( send_buf ));
MSG_WriteLong( &send, NET_HEADER_OUTOFBANDPACKET );
MSG_WriteStringf( &send, "connect %i %i \"%s\" \"%s\"\n",
PROTOCOL_GOLDSRC_VERSION, cls.challenge, protinfo, cls.userinfo );
MSG_SeekToBit( &send, -8, SEEK_CUR ); // rewrite null terminator
MSG_WriteBytes( &send, steam_cert, steam_cert_len );
if( MSG_CheckOverflow( &send ))
Con_Printf( S_ERROR "%s: %s overflow!\n", __func__, MSG_GetName( &send ) );
NET_SendPacket( NS_CLIENT, MSG_GetNumBytesWritten( &send ), MSG_GetData( &send ), adr );
Con_Printf( "Trying to connect with GoldSrc 48 protocol\n" );
}
else if( cls.legacymode == PROTO_LEGACY )
{
// reset nickname from cvar value
Info_SetValueForKey( cls.userinfo, "name", name.string, sizeof( cls.userinfo ));
// set related userinfo keys
if( cl_dlmax.value >= 40000 || cl_dlmax.value < 100 )
Info_SetValueForKey( cls.userinfo, "cl_maxpacket", "1400", sizeof( cls.userinfo ) );
@@ -1061,15 +1211,19 @@ static void CL_SendConnectPacket( void )
Netchan_OutOfBandPrint( NS_CLIENT, adr, "connect %i %i %i \"%s\" %d \"%s\"\n",
PROTOCOL_LEGACY_VERSION, Q_atoi( qport ), cls.challenge, cls.userinfo, NET_LEGACY_EXT_SPLIT, protinfo );
Con_Printf( "Trying to connect by legacy protocol\n" );
Con_Printf( "Trying to connect with legacy protocol\n" );
}
else
{
int extensions = NET_EXT_SPLITSIZE;
// reset nickname from cvar value
Info_SetValueForKey( cls.userinfo, "name", name.string, sizeof( cls.userinfo ));
if( cl_dlmax.value > FRAGMENT_MAX_SIZE || cl_dlmax.value < FRAGMENT_MIN_SIZE )
Cvar_SetValue( "cl_dlmax", FRAGMENT_DEFAULT_SIZE );
// remove keys set for legacy protocol
Info_RemoveKey( cls.userinfo, "cl_maxpacket" );
Info_RemoveKey( cls.userinfo, "cl_maxpayload" );
@@ -1078,7 +1232,7 @@ static void CL_SendConnectPacket( void )
Info_SetValueForKeyf( protinfo, "ext", sizeof( protinfo ), "%d", extensions);
Netchan_OutOfBandPrint( NS_CLIENT, adr, "connect %i %i \"%s\" \"%s\"\n", PROTOCOL_VERSION, cls.challenge, protinfo, cls.userinfo );
Con_Printf( "Trying to connect by modern protocol\n" );
Con_Printf( "Trying to connect with modern protocol\n" );
}
cls.timestart = Sys_DoubleTime();
@@ -1100,6 +1254,14 @@ static int CL_GetTestFragmentSize( void )
return FRAGMENT_MIN_SIZE;
}
static void CL_SendGetChallenge( netadr_t to, connprotocol_t proto )
{
if( proto == PROTO_GOLDSRC )
Netchan_OutOfBandPrint( NS_CLIENT, to, "getchallenge steam\n" );
else
Netchan_OutOfBandPrint( NS_CLIENT, to, "getchallenge\n" );
}
/*
=================
CL_CheckForResend
@@ -1113,7 +1275,7 @@ static void CL_CheckForResend( void )
net_gai_state_t res;
float resendTime;
qboolean bandwidthTest;
if( cls.internetservers_wait )
CL_SendMasterServerScanRequest();
@@ -1139,13 +1301,13 @@ static void CL_CheckForResend( void )
else if( cl_resend.value > CL_MAX_RESEND_TIME )
Cvar_SetValue( "cl_resend", CL_MAX_RESEND_TIME );
bandwidthTest = !cls.legacymode && cl_test_bandwidth.value && cls.connect_retry <= CL_TEST_RETRIES;
bandwidthTest = cls.legacymode == PROTO_CURRENT && cl_test_bandwidth.value && cls.connect_retry <= CL_TEST_RETRIES;
resendTime = bandwidthTest ? 1.0f : cl_resend.value;
if(( host.realtime - cls.connect_time ) < resendTime )
return;
res = NET_StringToAdrNB( cls.servername, &adr );
res = NET_StringToAdrNB( cls.servername, &adr, false );
if( res == NET_EAI_NONAME )
{
@@ -1174,7 +1336,7 @@ static void CL_CheckForResend( void )
// too many fails use default connection method
Con_Printf( "Bandwidth test failed, fallback to default connecting method\n" );
Con_Printf( "Connecting to %s... (retry #%i)\n", cls.servername, cls.connect_retry + 1 );
Netchan_OutOfBandPrint( NS_CLIENT, adr, "getchallenge\n" );
CL_SendGetChallenge( adr, cls.legacymode );
Cvar_SetValue( "cl_dlmax", FRAGMENT_MIN_SIZE );
cls.connect_time = host.realtime;
cls.connect_retry++;
@@ -1194,7 +1356,7 @@ static void CL_CheckForResend( void )
if( bandwidthTest )
Netchan_OutOfBandPrint( NS_CLIENT, adr, "bandwidth %i %i\n", PROTOCOL_VERSION, cls.max_fragment_size );
else
Netchan_OutOfBandPrint( NS_CLIENT, adr, "getchallenge\n" );
CL_SendGetChallenge( adr, cls.legacymode );
}
static resource_t *CL_AddResource( resourcetype_t type, const char *name, int size, qboolean bFatalIfMissing, int index )
@@ -1272,15 +1434,16 @@ static void CL_Connect_f( void )
{
const char *s = Cmd_Argv( 2 );
if( !Q_strcmp( s, "current" ) || !Q_strcmp( s, "49" ))
if( !Q_stricmp( s, "current" ) || !Q_strcmp( s, "49" ))
proto = PROTO_CURRENT;
else if( !Q_strcmp( s, "legacy" ) || !Q_strcmp( s, "48" ))
else if( !Q_stricmp( s, "legacy" ) || !Q_strcmp( s, "48" ))
proto = PROTO_LEGACY;
else if( !Q_stricmp( s, "goldsrc" ) || !Q_strcmp( s, "gs" ))
proto = PROTO_GOLDSRC;
else
{
// quake protocol only used for demos
// goldsrc protocol is not supported yet
Con_Printf( "Unknown protocol. Supported are: current, legacy\n" );
Con_Printf( "Unknown protocol. Supported are: 49 (current), 48 (legacy), gs (goldsrc)\n" );
return;
}
}
@@ -1428,7 +1591,7 @@ CL_SendDisconnectMessage
Sends a disconnect message to the server
=====================
*/
static void CL_SendDisconnectMessage( void )
static void CL_SendDisconnectMessage( connprotocol_t proto )
{
sizebuf_t buf;
byte data[32];
@@ -1437,7 +1600,9 @@ static void CL_SendDisconnectMessage( void )
MSG_Init( &buf, "LastMessage", data, sizeof( data ));
MSG_BeginClientCmd( &buf, clc_stringcmd );
MSG_WriteString( &buf, "disconnect" );
if( proto == PROTO_GOLDSRC )
MSG_WriteString( &buf, "dropclient\n" );
else MSG_WriteString( &buf, "disconnect" );
if( !cls.netchan.remote_address.type )
cls.netchan.remote_address.type = NA_LOOPBACK;
@@ -1475,29 +1640,29 @@ static void CL_Reconnect( qboolean setup_netchan )
{
if( setup_netchan )
{
Netchan_Setup( NS_CLIENT, &cls.netchan, net_from, Cvar_VariableInteger( "net_qport" ), NULL, CL_GetFragmentSize );
uint flags = 0;
if( cls.legacymode )
switch( cls.legacymode )
{
unsigned int extensions = Q_atoi( Cmd_Argv( 1 ) );
if( extensions & NET_LEGACY_EXT_SPLIT )
case PROTO_GOLDSRC:
SetBits( flags, NETCHAN_USE_MUNGE | NETCHAN_USE_BZIP2 | NETCHAN_GOLDSRC );
break;
case PROTO_LEGACY:
if( FBitSet( Q_atoi( Cmd_Argv( 1 )), NET_LEGACY_EXT_SPLIT ))
{
// only enable incoming split for legacy mode
cls.netchan.split = true;
SetBits( flags, NETCHAN_USE_LEGACY_SPLIT );
Con_Reportf( "^2NET_EXT_SPLIT enabled^7 (packet sizes is %d/%d)\n", (int)cl_dlmax.value, 65536 );
}
}
else
{
break;
default:
cls.extensions = Q_atoi( Info_ValueForKey( Cmd_Argv( 1 ), "ext" ));
if( cls.extensions & NET_EXT_SPLITSIZE )
{
if( FBitSet( cls.extensions, NET_EXT_SPLITSIZE ))
Con_Reportf( "^2NET_EXT_SPLITSIZE enabled^7 (packet size is %d)\n", (int)cl_dlmax.value );
}
break;
}
Netchan_Setup( NS_CLIENT, &cls.netchan, net_from, Cvar_VariableInteger( "net_qport" ), NULL, CL_GetFragmentSize, flags );
}
else
{
@@ -1532,8 +1697,6 @@ This is also called on Host_Error, so it shouldn't cause any errors
*/
void CL_Disconnect( void )
{
cls.legacymode = PROTO_CURRENT;
if( cls.state == ca_disconnected )
return;
@@ -1544,7 +1707,7 @@ void CL_Disconnect( void )
CL_Stop_f();
// send a disconnect message to the server
CL_SendDisconnectMessage();
CL_SendDisconnectMessage( cls.legacymode );
CL_ClearState ();
S_StopBackgroundTrack ();
@@ -1560,6 +1723,7 @@ void CL_Disconnect( void )
cls.set_lastdemo = false;
cls.connect_retry = 0;
cls.signon = 0;
cls.legacymode = PROTO_CURRENT;
// back to menu in non-developer mode
if( host_developer.value || cls.key_dest == key_menu )
@@ -1587,7 +1751,7 @@ void CL_Crashed( void )
CL_Stop_f(); // stop any demos
// send a disconnect message to the server
CL_SendDisconnectMessage();
CL_SendDisconnectMessage( cls.legacymode );
Host_WriteOpenGLConfig();
Host_WriteConfig(); // write config
@@ -1651,7 +1815,7 @@ static size_t NONNULL CL_BuildMasterServerScanRequest( char *buf, size_t size, u
Q_snprintf( temp, sizeof( temp ), "%d", Q_buildnum() );
Info_SetValueForKey( info, "buildnum", temp, remaining );
Q_snprintf( temp, sizeof( temp ), "%x", *key );
Info_SetValueForKey( info, "key", temp, remaining );
@@ -2045,7 +2209,7 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
Con_Reportf( "%s: %s : %s\n", __func__, NET_AdrToString( from ), c );
// server connection
if( !Q_strcmp( c, "client_connect" ))
if( !Q_strcmp( c, "client_connect" ) || !Q_strcmp( c, S2C_CONNECTION ))
{
if( !CL_IsFromConnectingServer( from ))
return;
@@ -2085,6 +2249,14 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
Cbuf_AddText( args );
Cbuf_AddText( "\n" );
}
else if( c[0] == 'l' )
{
char *s = args + 1;
Con_Printf( S_CYAN "r:" S_DEFAULT " %s", s );
if( !COM_CheckStringEmpty( s ) || s[Q_strlen( s ) - 1] != '\n' )
Con_Printf( "\n" );
}
else if( !Q_strcmp( c, "print" ))
{
// print command from somewhere
@@ -2118,7 +2290,7 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
{
// too many fails use default connection method
Con_Printf( "hi-speed connection is failed, use default method\n" );
Netchan_OutOfBandPrint( NS_CLIENT, from, "getchallenge\n" );
CL_SendGetChallenge( from, cls.legacymode );
Cvar_SetValue( "cl_dlmax", FRAGMENT_DEFAULT_SIZE );
cls.connect_time = host.realtime;
return;
@@ -2140,7 +2312,7 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
// packet was sucessfully delivered, adjust the fragment size and get challenge
Con_DPrintf( "CRC %x is matched, get challenge, fragment size %d\n", crcValue, cls.max_fragment_size );
Netchan_OutOfBandPrint( NS_CLIENT, from, "getchallenge\n" );
CL_SendGetChallenge( from, cls.legacymode );
Cvar_SetValue( "cl_dlmax", cls.max_fragment_size );
cls.connect_time = host.realtime;
}
@@ -2150,7 +2322,7 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
{
// too many fails use default connection method
Con_Printf( "hi-speed connection is failed, use default method\n" );
Netchan_OutOfBandPrint( NS_CLIENT, from, "getchallenge\n" );
CL_SendGetChallenge( from, cls.legacymode );
Cvar_SetValue( "cl_dlmax", FRAGMENT_MIN_SIZE );
cls.connect_time = host.realtime;
return;
@@ -2167,7 +2339,7 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
// ping from somewhere
Netchan_OutOfBandPrint( NS_CLIENT, from, "ack" );
}
else if( !Q_strcmp( c, "challenge" ))
else if( !Q_strcmp( c, "challenge" ) || !Q_strcmp( c, S2C_CHALLENGE ))
{
// this message only used during connection
// it doesn't make sense after client_connect
@@ -2204,7 +2376,7 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
// dropped the connection but it is still getting packets from us
CL_Disconnect_f();
}
else if( !Q_strcmp( c, "errormsg" ))
else if( !Q_strcmp( c, "errormsg" ) || c[0] == S2C_REJECT || c[0] == S2C_REJECT_BADPASSWORD )
{
char formatted_msg[MAX_VA_STRING];
@@ -2212,12 +2384,16 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
return;
args = MSG_ReadString( msg );
if( c[0] == S2C_REJECT || c[0] == S2C_REJECT_BADPASSWORD )
args++; // skip one byte
Q_snprintf( formatted_msg, sizeof( formatted_msg ), "^3Server message^7\n%s", args );
// in case we're in console or it's classic mainui which doesn't support messageboxes
if( !UI_IsVisible() || !UI_ShowMessageBox( formatted_msg ))
Msg( "%s\n", formatted_msg );
CL_Disconnect_f();
}
else if( !Q_strcmp( c, "updatemsg" ))
{
@@ -2345,14 +2521,11 @@ static void CL_ParseNetMessage( sizebuf_t *msg, void (*parsefn)( sizebuf_t * ))
// after we have parsed the frame
if( !cls.demoplayback )
{
if( cls.demorecording && !cls.demowaiting )
{
CL_WriteDemoMessage( false, cls.starting_count, msg );
}
else if( cls.state != ca_active )
{
if( cls.state != ca_active )
CL_WriteDemoMessage( true, cls.starting_count, msg );
}
if( cls.demorecording && !cls.demowaiting )
CL_WriteDemoMessage( false, cls.starting_count, msg );
}
}
@@ -2379,6 +2552,8 @@ static void CL_ReadNetMessage( void )
parsefn = CL_ParseQuakeMessage;
break;
case PROTO_GOLDSRC:
parsefn = CL_ParseGoldSrcServerMessage;
break;
default:
ASSERT( 0 );
return;
@@ -2592,7 +2767,6 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
{
int sound_len = sizeof( DEFAULT_SOUNDPATH ) - 1;
byte rgucMD5_hash[16];
const char *pfilename;
resource_t *p;
if( COM_CheckString( filename ) && successfully_received )
@@ -2600,10 +2774,10 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
if( filename[0] != '!' )
Con_Printf( "processing %s\n", filename );
if( !Q_strnicmp( filename, "downloaded/", 11 ))
if( !Q_strnicmp( filename, DEFAULT_DOWNLOADED_DIRECTORY, sizeof( DEFAULT_DOWNLOADED_DIRECTORY ) - 1 ))
{
// skip "downloaded/" part to avoid mismatch with needed resources list
filename += 11;
filename += sizeof( DEFAULT_DOWNLOADED_DIRECTORY ) - 1;
}
}
else if( !successfully_received )
@@ -2611,10 +2785,11 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
Con_Printf( S_ERROR "server failed to transmit file '%s'\n", CL_CleanFileName( filename ));
}
if( cls.legacymode )
if( cls.legacymode == PROTO_LEGACY )
{
if( host.downloadcount > 0 )
host.downloadcount--;
if( !host.downloadcount )
{
MSG_WriteByte( &cls.netchan.message, clc_stringcmd );
@@ -2669,7 +2844,7 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
else
{
Con_Printf( "Downloaded %i bytes for purported %i byte file, ignoring download\n",
cls.netchan.tempbuffersize, p->nDownloadSize );
cls.netchan.tempbuffersize, p->nDownloadSize );
}
if( cls.netchan.tempbuffer )
@@ -2699,7 +2874,7 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
MSG_Init( &msg, "Resource Registration", msg_buf, sizeof( msg_buf ));
if( CL_PrecacheResources( ))
CL_RegisterResources( &msg );
CL_RegisterResources( &msg, cls.legacymode );
if( MSG_GetNumBytesWritten( &msg ) > 0 )
{
@@ -2759,17 +2934,26 @@ tell server about changed userinfo
*/
void CL_UpdateInfo( const char *key, const char *value )
{
if( !cls.legacymode )
{
CL_ServerCommand( true, "setinfo \"%s\" \"%s\"\n", key, value );
}
else
switch( cls.legacymode )
{
case PROTO_LEGACY:
if( cls.state != ca_active )
return;
break;
MSG_BeginClientCmd( &cls.netchan.message, clc_legacy_userinfo );
MSG_WriteString( &cls.netchan.message, cls.userinfo );
break;
case PROTO_GOLDSRC:
if( !Q_stricmp( key, "name" ) && Q_strnicmp( value, "[Xash3D]", 8 ))
{
// always prepend [Xash3D] on GoldSrc protocol :)
CL_ServerCommand( true, "setinfo \"%s\" \"[Xash3D]%s\"\n", key, value );
break;
}
// intentional fallthrough
default:
CL_ServerCommand( true, "setinfo \"%s\" \"%s\"\n", key, value );
break;
}
}
@@ -2829,19 +3013,26 @@ static void CL_Physinfo_f( void )
static qboolean CL_ShouldRescanFilesystem( void )
{
resource_t *res;
qboolean retval = false;
for( res = cl.resourcesonhand.pNext; res && res != &cl.resourcesonhand; res = res->pNext )
{
if( res->type == t_generic )
{
const char *ext = COM_FileExtension( res->szFileName );
// TODO: query supported archives format from fs_stdio
// TODO: query if was already opened
if( !Q_stricmp( ext, "wad" ) || !Q_stricmp( ext, "pk3" ) || !Q_stricmp( ext, "pak" ))
return true;
if( !g_fsapi.IsArchiveExtensionSupported( ext, IAES_ONLY_REAL_ARCHIVES ))
continue;
if( FBitSet( res->ucExtraFlags, RES_EXTRA_ARCHIVE_CHECKED ))
continue;
SetBits( res->ucExtraFlags, RES_EXTRA_ARCHIVE_CHECKED );
retval = true;
}
}
return false;
return retval;
}
qboolean CL_PrecacheResources( void )
@@ -3041,6 +3232,9 @@ static void CL_InitLocal( void )
cl.resourcesneeded.pNext = cl.resourcesneeded.pPrev = &cl.resourcesneeded;
cl.resourcesonhand.pNext = cl.resourcesonhand.pPrev = &cl.resourcesonhand;
Cvar_RegisterVariable( &cl_ticket_generator );
Cvar_RegisterVariable( &showpause );
Cvar_RegisterVariable( &mp_decals );
Cvar_RegisterVariable( &dev_overview );
Cvar_RegisterVariable( &cl_resend );
@@ -3074,8 +3268,9 @@ static void CL_InitLocal( void )
// userinfo
Cvar_RegisterVariable( &cl_nopred );
Q_strncpy( username, Sys_GetCurrentUser(), sizeof( username )); // initialize before registering variable
Cvar_RegisterVariable( &name );
Cvar_DirectSet( &name, Sys_GetCurrentUser( ));
Cvar_Get( "ui_username", username, FCVAR_READ_ONLY|FCVAR_PRIVILEGED, "default user name" );
Cvar_RegisterVariable( &model );
Cvar_RegisterVariable( &cl_updaterate );
Cvar_RegisterVariable( &cl_dlmax );
@@ -3151,6 +3346,7 @@ static void CL_InitLocal( void )
Cmd_AddCommand ("demos", CL_Demos_f, "restart looping demos defined by the last startdemos command" );
Cmd_AddCommand ("movie", CL_PlayVideo_f, "play a movie" );
Cmd_AddCommand ("stop", CL_Stop_f, "stop playing or recording a demo" );
Cmd_AddCommand( "listdemo", CL_ListDemo_f, "list demo entries" );
Cmd_AddCommand ("info", NULL, "collect info about local servers with specified protocol" );
Cmd_AddCommand ("escape", CL_Escape_f, "escape from game to menu" );
Cmd_AddCommand ("togglemenu", CL_Escape_f, "toggle between game and menu" );

View File

@@ -20,8 +20,6 @@ GNU General Public License for more details.
#include "input.h"
#include "platform/platform.h"
static mobile_engfuncs_t *gMobileEngfuncs;
static CVAR_DEFINE_AUTO( vibration_length, "1.0", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "vibration length" );
static CVAR_DEFINE_AUTO( vibration_enable, "1", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "enable vibration" );
@@ -30,17 +28,9 @@ static float g_font_scale;
static void pfnVibrate( float life, char flags )
{
if( !vibration_enable.value )
if( !vibration_enable.value || life < 0.0f )
return;
if( life < 0.0f )
{
Con_Reportf( S_WARN "Negative vibrate time: %f\n", life );
return;
}
//Con_Reportf( "Vibrate: %f %d\n", life, flags );
// here goes platform-specific backends
Platform_Vibrate( life * vibration_length.value, flags );
}
@@ -53,7 +43,7 @@ static void Vibrate_f( void )
return;
}
pfnVibrate( Q_atof( Cmd_Argv(1) ), VIBRATE_NORMAL );
pfnVibrate( Q_atof( Cmd_Argv( 1 )), VIBRATE_NORMAL );
}
static void pfnEnableTextInput( int enable )
@@ -102,7 +92,7 @@ static char *pfnParseFileSafe( char *data, char *buf, const int size, unsigned i
return COM_ParseFileSafe( data, buf, size, flags, len, NULL );
}
static mobile_engfuncs_t gpMobileEngfuncs =
static const mobile_engfuncs_t gMobileEngfuncs =
{
MOBILITY_API_VERSION,
pfnVibrate,
@@ -122,21 +112,38 @@ static mobile_engfuncs_t gpMobileEngfuncs =
qboolean Mobile_Init( void )
{
qboolean success = false;
pfnMobilityInterface ExportToClient;
// find a mobility interface
ExportToClient = COM_GetProcAddress( clgame.hInstance, MOBILITY_CLIENT_EXPORT );
gMobileEngfuncs = &gpMobileEngfuncs;
if( ExportToClient && !ExportToClient( gMobileEngfuncs ) )
success = true;
Cmd_AddCommand( "vibrate", (xcommand_t)Vibrate_f, "Vibrate for specified time");
Cmd_AddCommand( "vibrate", Vibrate_f, "Vibrate for specified time");
Cvar_RegisterVariable( &vibration_length );
Cvar_RegisterVariable( &vibration_enable );
return success;
// find mobility interface
if(( ExportToClient = COM_GetProcAddress( clgame.hInstance, MOBILITY_CLIENT_EXPORT )))
{
static mobile_engfuncs_t mobile_engfuncs; // keep a copy, don't let user change engine pointers
mobile_engfuncs = gMobileEngfuncs;
if( !ExportToClient( &mobile_engfuncs ))
{
Con_Reportf( "%s: ^2initailized extended MobilityAPI ^7ver. %i\n", __func__, MOBILITY_API_VERSION );
return true;
}
// make sure that mobile functions are cleared
#if 1
// some SDKs define export as returning void, breaking the contract
// ignore result for now...
return true;
#else
memset( &mobile_engfuncs, 0, sizeof( mobile_engfuncs ));
return false; // just tell user about problems
#endif
}
return true; // mobile interface is missed
}
void Mobile_Shutdown( void )

View File

@@ -63,9 +63,9 @@ static byte netcolors[NETGRAPH_NET_COLORS+NETGRAPH_LERP_HEIGHT][4] =
// other will be generated through NetGraph_InitColors()
};
static byte sendcolor[4] = { 88, 29, 130, 255 };
static byte holdcolor[4] = { 255, 0, 0, 200 };
static byte extrap_base_color[4] = { 255, 255, 255, 255 };
static const byte sendcolor[4] = { 88, 29, 130, 255 };
static const byte holdcolor[4] = { 255, 0, 0, 200 };
static const byte extrap_base_color[4] = { 255, 255, 255, 255 };
static netbandwidthgraph_t netstat_graph[NET_TIMINGS];
static float packet_loss;
static float packet_choke;
@@ -79,7 +79,7 @@ NetGraph_DrawRect
NetGraph_FillRGBA shortcut
==========
*/
static void NetGraph_DrawRect( wrect_t *rect, byte colors[4] )
static void NetGraph_DrawRect( const wrect_t *rect, const byte colors[4] )
{
ref.dllFuncs.Color4ub( colors[0], colors[1], colors[2], colors[3] ); // color for this quad

File diff suppressed because it is too large Load Diff

View File

@@ -137,12 +137,7 @@ static void CL_LegacyParseSoundPacket( sizebuf_t *msg, qboolean is_ambient )
if( FBitSet( flags, SND_SENTENCE ))
{
char sentenceName[32];
//if( FBitSet( flags, SND_SEQUENCE ))
//Q_snprintf( sentenceName, sizeof( sentenceName ), "!#%i", sound + MAX_SOUNDS );
//else
Q_snprintf( sentenceName, sizeof( sentenceName ), "!%i", sound );
handle = S_RegisterSound( sentenceName );
}
else handle = cl.sound_index[sound]; // see precached sound
@@ -320,7 +315,7 @@ dispatch messages
void CL_ParseLegacyServerMessage( sizebuf_t *msg )
{
size_t bufStart, playerbytes;
int cmd, param1, param2;
int cmd;
int old_background;
const char *s;
@@ -345,6 +340,9 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg )
// record command for debugging spew on parse problem
CL_Parse_RecordCommand( cmd, bufStart );
if( CL_ParseCommonDLLMessage( msg, PROTO_LEGACY, cmd, bufStart ))
continue;
// other commands
switch( cmd )
{
@@ -359,7 +357,7 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg )
Host_AbortCurrentFrame ();
break;
case svc_legacy_event:
CL_ParseEvent( msg );
CL_ParseEvent( msg, PROTO_LEGACY );
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_legacy_changing:
@@ -421,7 +419,7 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg )
break;
case svc_time:
CL_ParseServerTime( msg );
CL_ParseServerTime( msg, PROTO_LEGACY );
break;
case svc_print:
Con_Printf( "%s", MSG_ReadString( msg ));
@@ -446,19 +444,19 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg )
break;
case svc_serverdata:
Cbuf_Execute(); // make sure any stuffed commands are done
CL_ParseServerData( msg, true );
CL_ParseServerData( msg, PROTO_LEGACY );
break;
case svc_lightstyle:
CL_ParseLightStyle( msg );
CL_ParseLightStyle( msg, PROTO_LEGACY );
break;
case svc_updateuserinfo:
CL_UpdateUserinfo( msg, true );
CL_UpdateUserinfo( msg, PROTO_LEGACY );
break;
case svc_deltatable:
Delta_ParseTableField( msg );
break;
case svc_clientdata:
CL_ParseClientData( msg );
CL_ParseClientData( msg, PROTO_LEGACY );
cl.frames[cl.parsecountmod].graphdata.client += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_resource:
@@ -468,82 +466,58 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg )
CL_UpdateUserPings( msg );
break;
case svc_particle:
CL_ParseParticles( msg );
CL_ParseParticles( msg, PROTO_LEGACY );
break;
case svc_restoresound:
CL_ParseRestoreSoundPacket( msg );
cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart;
Con_Printf( S_ERROR "%s: svc_restoresound: implement me!\n", __func__ );
break;
case svc_spawnstatic:
CL_LegacyParseStaticEntity( msg );
break;
case svc_event_reliable:
CL_ParseReliableEvent( msg );
CL_ParseReliableEvent( msg, PROTO_LEGACY );
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_spawnbaseline:
CL_ParseBaseline( msg, true );
break;
case svc_temp_entity:
CL_ParseTempEntity( msg );
cl.frames[cl.parsecountmod].graphdata.tentities += MSG_GetNumBytesRead( msg ) - bufStart;
CL_ParseBaseline( msg, PROTO_LEGACY );
break;
case svc_setpause:
cl.paused = ( MSG_ReadOneBit( msg ) != 0 );
break;
case svc_signonnum:
CL_ParseSignon( msg );
CL_ParseSignon( msg, PROTO_LEGACY );
break;
case svc_centerprint:
CL_CenterPrint( MSG_ReadString( msg ), 0.25f );
break;
case svc_intermission:
cl.intermission = 1;
break;
case svc_legacy_modelindex:
CL_LegacyPrecacheModel( msg );
break;
case svc_legacy_soundindex:
CL_LegacyPrecacheSound( msg );
break;
case svc_cdtrack:
param1 = MSG_ReadByte( msg );
param1 = bound( 1, param1, MAX_CDTRACKS ); // tracknum
param2 = MSG_ReadByte( msg );
param2 = bound( 1, param2, MAX_CDTRACKS ); // loopnum
S_StartBackgroundTrack( clgame.cdtracks[param1-1], clgame.cdtracks[param2-1], 0, false );
break;
case svc_restore:
CL_ParseRestore( msg );
break;
case svc_legacy_eventindex:
CL_LegacyPrecacheEvent(msg);
break;
case svc_weaponanim:
param1 = MSG_ReadByte( msg ); // iAnim
param2 = MSG_ReadByte( msg ); // body
CL_WeaponAnim( param1, param2 );
break;
case svc_bspdecal:
CL_ParseStaticDecal( msg );
break;
case svc_roomtype:
param1 = MSG_ReadShort( msg );
Cvar_SetValue( "room_type", param1 );
break;
case svc_addangle:
CL_ParseAddAngle( msg );
break;
case svc_usermessage:
CL_RegisterUserMessage( msg );
CL_RegisterUserMessage( msg, PROTO_LEGACY );
break;
case svc_packetentities:
playerbytes = CL_ParsePacketEntities( msg, false );
playerbytes = CL_ParsePacketEntities( msg, false, PROTO_LEGACY );
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
break;
case svc_deltapacketentities:
playerbytes = CL_ParsePacketEntities( msg, true );
playerbytes = CL_ParsePacketEntities( msg, true, PROTO_LEGACY );
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
break;
@@ -590,9 +564,6 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg )
case svc_hltv:
CL_ParseHLTV( msg );
break;
case svc_director:
CL_ParseDirector( msg );
break;
case svc_resourcelocation:
CL_ParseResLocation( msg );
break;
@@ -603,7 +574,7 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg )
CL_ParseCvarValue( msg, true, PROTO_LEGACY );
break;
default:
CL_ParseUserMessage( msg, cmd );
CL_ParseUserMessage( msg, cmd, PROTO_LEGACY );
cl.frames[cl.parsecountmod].graphdata.usr += MSG_GetNumBytesRead( msg ) - bufStart;
break;
}
@@ -615,7 +586,7 @@ void CL_LegacyPrecache_f( void )
int spawncount, i;
model_t *mod;
if( !cls.legacymode )
if( cls.legacymode != PROTO_LEGACY )
return;
spawncount = Q_atoi( Cmd_Argv( 1 ));
@@ -656,10 +627,5 @@ void CL_LegacyPrecache_f( void )
// Include server count in case server disconnects and changes level during d/l
MSG_BeginClientCmd( &cls.netchan.message, clc_stringcmd );
MSG_WriteStringf( &cls.netchan.message, "begin %i", spawncount );
cls.signon = SIGNONS;
}
qboolean CL_LegacyMode( void )
{
return cls.legacymode == PROTO_LEGACY;
cls.signon = SIGNONS - 1;
}

762
engine/client/cl_parse_gs.c Normal file
View File

@@ -0,0 +1,762 @@
/*
cl_parse.c - parse a message received from the server (GoldSrc 48 protocol)
Copyright (C) 2008 Uncle Mike
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 "common.h"
#include "client.h"
#include "net_encode.h"
#include "particledef.h"
#include "cl_tent.h"
#include "shake.h"
#include "hltv.h"
#include "input.h"
#include "server.h"
static void CL_ParseExtraInfo( sizebuf_t *msg )
{
string clientfallback;
Q_strncpy( clientfallback, MSG_ReadString( msg ), sizeof( clientfallback ));
if( COM_CheckStringEmpty( clientfallback ))
Con_Reportf( S_ERROR "%s: TODO: add fallback directory %s!\n", __func__ );
if( MSG_ReadByte( msg ))
{
Cvar_FullSet( "sv_cheats", "1", FCVAR_READ_ONLY | FCVAR_SERVER );
}
else
{
Cvar_SetCheatState();
Cvar_FullSet( "sv_cheats", "0", FCVAR_READ_ONLY | FCVAR_SERVER );
}
}
static void CL_ParseNewMovevars( sizebuf_t *msg )
{
Delta_InitClient(); // finalize client delta's
clgame.movevars.gravity = MSG_ReadFloat( msg );
clgame.movevars.stopspeed = MSG_ReadFloat( msg );
clgame.movevars.maxspeed = MSG_ReadFloat( msg );
clgame.movevars.spectatormaxspeed = MSG_ReadFloat( msg );
clgame.movevars.accelerate = MSG_ReadFloat( msg );
clgame.movevars.airaccelerate = MSG_ReadFloat( msg );
clgame.movevars.wateraccelerate = MSG_ReadFloat( msg );
clgame.movevars.friction = MSG_ReadFloat( msg );
clgame.movevars.edgefriction = MSG_ReadFloat( msg );
clgame.movevars.waterfriction = MSG_ReadFloat( msg );
clgame.movevars.entgravity = MSG_ReadFloat( msg );
clgame.movevars.bounce = MSG_ReadFloat( msg );
clgame.movevars.stepsize = MSG_ReadFloat( msg );
clgame.movevars.maxvelocity = MSG_ReadFloat( msg );
clgame.movevars.zmax = MSG_ReadFloat( msg );
clgame.movevars.waveHeight = MSG_ReadFloat( msg );
clgame.movevars.footsteps = MSG_ReadByte( msg );
clgame.movevars.rollangle = MSG_ReadFloat( msg );
clgame.movevars.rollspeed = MSG_ReadFloat( msg );
clgame.movevars.skycolor_r = MSG_ReadFloat( msg );
clgame.movevars.skycolor_g = MSG_ReadFloat( msg );
clgame.movevars.skycolor_b = MSG_ReadFloat( msg );
clgame.movevars.skyvec_x = MSG_ReadFloat( msg );
clgame.movevars.skyvec_y = MSG_ReadFloat( msg );
clgame.movevars.skyvec_z = MSG_ReadFloat( msg );
Q_strncpy( clgame.movevars.skyName, MSG_ReadString( msg ), sizeof( clgame.movevars.skyName ));
// water alpha is not allowed
if( !FBitSet( world.flags, FWORLD_WATERALPHA ))
clgame.movevars.wateralpha = 1.0f;
// update sky if changed
if( Q_strcmp( clgame.oldmovevars.skyName, clgame.movevars.skyName ) && cl.video_prepped )
R_SetupSky( clgame.movevars.skyName );
clgame.oldmovevars = clgame.movevars;
clgame.entities->curstate.scale = clgame.movevars.waveHeight;
// keep features an actual!
clgame.oldmovevars.features = clgame.movevars.features = host.features;
}
typedef struct delta_header_t
{
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 )
{
int entnum = oldnum;
memset( hdr, 0, sizeof( *hdr ));
if( !delta )
{
// if we have one bit set, then it's a next entity in line
// if we have next bit NON set, then it's a one of next 64 entities
// if not, it's a new entity
if( MSG_ReadOneBit( msg ))
entnum++;
else if( MSG_ReadOneBit( msg ) == 0 )
entnum += MSG_ReadUBitLong( msg, 6 );
else
entnum = MSG_ReadUBitLong( msg, MAX_GOLDSRC_ENTITY_BITS );
}
else
{
// does this packet encode entity deletion?
hdr->remove = MSG_ReadOneBit( msg );
// same logic as above
if( MSG_ReadOneBit( msg ) == 0 )
entnum += MSG_ReadUBitLong( msg, 6 );
else entnum = MSG_ReadUBitLong( msg, MAX_GOLDSRC_ENTITY_BITS );
}
// if we are not removing this entity
if( !hdr->remove )
{
hdr->custom = MSG_ReadOneBit( msg );
// do we got instanced baselines in svc_spawnbaselines?
if( cl.instanced_baseline_count )
{
hdr->instanced = MSG_ReadOneBit( msg );
if( hdr->instanced )
hdr->instanced_baseline_index = MSG_ReadUBitLong( msg, 6 );
}
if( !delta && !hdr->instanced )
{
if( MSG_ReadOneBit( msg ))
hdr->offset = MSG_ReadUBitLong( msg, 6 );
}
}
return entnum;
}
static int CL_GetEntityDelta( const struct delta_header_t *hdr, int entnum )
{
if( hdr->custom )
return DT_CUSTOM_ENTITY_STATE_T;
if( CL_IsPlayerIndex( entnum ))
return DT_ENTITY_STATE_PLAYER_T;
return DT_ENTITY_STATE_T;
}
static void CL_FlushEntityPacketGS( frame_t *frame, sizebuf_t *msg )
{
frame->valid = false;
cl.validsequence = 0; // can't render a frame
// read it all but ignore it
while( 1 )
{
int num = 0;
entity_state_t from = { 0 }, to;
delta_header_t hdr;
if( MSG_ReadWord( msg ) != 0 )
{
MSG_SeekToBit( msg, -16, SEEK_CUR );
num = CL_ParseDeltaHeader( msg, false, num, &hdr );
}
else break;
if( MSG_CheckOverflow( msg ))
Host_Error( "%s: overflow\n", __func__ );
if( hdr.remove )
continue;
Delta_ReadGSFields( msg, CL_GetEntityDelta( &hdr, num ), &from, &to, cl.mtime[0] );
}
}
static void CL_DeltaEntityGS( const delta_header_t *hdr, sizebuf_t *msg, frame_t *frame, int newnum, const entity_state_t *from )
{
cl_entity_t *ent;
entity_state_t *to;
qboolean newent = from == NULL;
int pack = frame->num_entities;
qboolean has_update = msg != NULL;
// alloc next slot to store update
to = &cls.packet_entities[cls.next_client_entities % cls.num_client_entities];
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", __func__, newnum );
return;
}
ent = CL_EDICT_NUM( newnum );
if( hdr->remove )
{
if( !newent )
CL_KillDeadBeams( ent );
else
Con_Printf( S_WARN "%s: entity remove on non-delta update (%d)\n", __func__, newnum );
return;
}
ent->index = newnum; // enumerate entity index
if( newent )
{
if( hdr->instanced )
from = &cl.instanced_baseline[hdr->instanced_baseline_index];
else if( hdr->offset != 0 )
from = &cls.packet_entities[(cls.next_client_entities - hdr->offset) % cls.num_client_entities];
else
from = &ent->baseline;
}
if( has_update )
Delta_ReadGSFields( msg, CL_GetEntityDelta( hdr, newnum ), from, to, cl.mtime[0] );
else memcpy( to, from, sizeof( entity_state_t ));
to->entityType = hdr->custom ? ENTITY_BEAM : ENTITY_NORMAL;
to->number = newnum;
if( newent )
{
// interpolation must be reset
SETVISBIT( frame->flags, pack );
// release beams from previous entity
CL_KillDeadBeams( ent );
}
// add entity to packet
cls.next_client_entities++;
frame->num_entities++;
}
static void CL_CopyPacketEntity( frame_t *frame, int num, const entity_state_t *from )
{
delta_header_t fakehdr =
{
.custom = FBitSet( from->entityType, ENTITY_BEAM ) == ENTITY_BEAM,
};
CL_DeltaEntityGS( &fakehdr, NULL, frame, num, from );
}
static int CL_ParsePacketEntitiesGS( sizebuf_t *msg, qboolean delta )
{
frame_t *frame, *oldframe;
int oldindex, newnum, oldnum, numbase = 0;
entity_state_t *oldent;
int count;
int playerbytes = 0;
// save first uncompressed packet as timestamp
if( cls.changelevel && !delta && cls.demorecording )
CL_WriteDemoJumpTime();
count = MSG_ReadWord( msg );
frame = &cl.frames[cl.parsecountmod];
memset( frame->flags, 0, sizeof( frame->flags ));
frame->first_entity = cls.next_client_entities;
frame->num_entities = 0;
frame->valid = true;
if( delta )
{
uint oldpacket = MSG_ReadByte( msg );
oldframe = &cl.frames[oldpacket & CL_UPDATE_MASK];
if( !CL_ValidateDeltaPacket( oldpacket, oldframe ))
{
MSG_StartBitWriting( msg );
CL_FlushEntityPacketGS( frame, msg );
MSG_EndBitWriting( msg );
return playerbytes;
}
}
else
{
oldframe = NULL;
cl.send_reply = true;
cls.demowaiting = false;
}
cl.validsequence = cls.netchan.incoming_sequence;
MSG_StartBitWriting( msg );
oldent = NULL;
oldindex = 0;
oldnum = CL_UpdateOldEntNum( oldindex, oldframe, &oldent );
// read it all but ignore it
while( 1 )
{
int bufstart;
qboolean player;
delta_header_t hdr;
int val = MSG_ReadWord( msg );
if( val )
{
MSG_SeekToBit( msg, -16, SEEK_CUR );
numbase = newnum = CL_ParseDeltaHeader( msg, delta, numbase, &hdr );
}
else break;
if( MSG_CheckOverflow( msg ))
Host_Error( "%s: overflow\n", __func__ );
player = CL_IsPlayerIndex( newnum );
while( oldnum < newnum )
{
if( !delta )
Con_Printf( S_WARN "%s: old frame copy on non-delta update (%d < %d)\n", __func__, oldnum, newnum );
// one or more entities from the old packet are unchanged
CL_CopyPacketEntity( frame, oldnum, oldent );
oldnum = CL_UpdateOldEntNum( ++oldindex, oldframe, &oldent );
}
bufstart = MSG_GetNumBytesRead( msg );
if( oldnum == newnum )
{
if( !delta )
Con_Printf( S_WARN "%s: delta entity on non-delta update (%d)\n", __func__, oldnum );
// from delta
CL_DeltaEntityGS( &hdr, msg, frame, newnum, oldent );
oldnum = CL_UpdateOldEntNum( ++oldindex, oldframe, &oldent );
}
else if( oldnum > newnum )
{
// from baseline
CL_DeltaEntityGS( &hdr, msg, frame, newnum, NULL );
}
if( player ) playerbytes += MSG_GetNumBytesRead( msg ) - bufstart;
}
if( MSG_CheckOverflow( msg ))
Host_Error( "%s: overflow\n", __func__ );
// any remaining entities in the old frame are copied over
while( oldnum != MAX_ENTNUMBER )
{
// one or more entities from the old packet are unchanged
CL_CopyPacketEntity( frame, oldnum, oldent );
oldnum = CL_UpdateOldEntNum( ++oldindex, oldframe, &oldent );
}
MSG_EndBitWriting( msg );
if( frame->num_entities != count )
Con_Reportf( S_WARN "CL_Parse%sPacketEntitiesGS: (%i should be %i)\n", delta ? "Delta" : "", frame->num_entities, count );
if( !frame->valid )
return playerbytes;
CL_ProcessPacket( frame );
CL_SetSolidEntities();
// first update, received world, remove loading plaque
if( cls.signon == ( SIGNONS - 1 ))
{
cls.signon = SIGNONS;
CL_SignonReply( PROTO_GOLDSRC );
}
return playerbytes;
}
static float MSG_ReadGSBitCoord( sizebuf_t *sb )
{
float value = 0;
int ival, fval;
ival = MSG_ReadOneBit( sb );
fval = MSG_ReadOneBit( sb );
if( ival || fval )
{
int sign = MSG_ReadOneBit( sb );
if( ival )
ival = MSG_ReadUBitLong( sb, 12 );
if( fval )
fval = MSG_ReadUBitLong( sb, 3 );
value = (float)( fval / 8.0 + ival );
if( sign )
value = -value;
}
return value;
}
static void MSG_ReadGSBitVec3Coord( sizebuf_t *sb, vec3_t fa )
{
qboolean x, y, z;
VectorClear( fa );
x = MSG_ReadOneBit( sb );
y = MSG_ReadOneBit( sb );
z = MSG_ReadOneBit( sb );
if( x )
fa[0] = MSG_ReadGSBitCoord( sb );
if( y )
fa[1] = MSG_ReadGSBitCoord( sb );
if( z )
fa[2] = MSG_ReadGSBitCoord( sb );
}
static void CL_ParseSoundPacketGS( sizebuf_t *msg )
{
vec3_t pos;
int chan, sound;
float volume, attn;
int flags, pitch, entnum;
sound_t handle = 0;
MSG_StartBitWriting( msg );
flags = MSG_ReadUBitLong( msg, 9 );
if( FBitSet( flags, SND_VOLUME ))
volume = (float)MSG_ReadByte( msg ) / 255.0f;
else volume = VOL_NORM;
if( FBitSet( flags, SND_ATTENUATION ))
attn = (float)MSG_ReadByte( msg ) / 64.0f;
else attn = ATTN_NONE;
chan = MSG_ReadUBitLong( msg, 3 );
entnum = MSG_ReadUBitLong( msg, MAX_GOLDSRC_ENTITY_BITS );
if( FBitSet( flags, SND_LEGACY_LARGE_INDEX ))
sound = MSG_ReadWord( msg );
else sound = MSG_ReadByte( msg );
MSG_ReadGSBitVec3Coord( msg, pos );
if( FBitSet( flags, SND_PITCH ))
pitch = MSG_ReadByte( msg );
else pitch = PITCH_NORM;
MSG_EndBitWriting( msg );
ClearBits( flags, SND_LEGACY_LARGE_INDEX );
if( FBitSet( flags, SND_SENTENCE ))
{
char sentenceName[32];
Q_snprintf( sentenceName, sizeof( sentenceName ), "!%i", sound );
handle = S_RegisterSound( sentenceName );
}
else handle = cl.sound_index[sound]; // see precached sound
if( !cl.audio_prepped )
return; // too early
// g-cont. sound and ambient sound have only difference with channel
if( chan == CHAN_STATIC )
{
S_AmbientSound( pos, entnum, handle, volume, attn, pitch, flags );
}
else
{
S_StartSound( pos, entnum, chan, handle, volume, attn, pitch, flags );
}
}
static void CL_ParseSpawnStaticSound( sizebuf_t *msg )
{
vec3_t pos;
int handle, entnum, pitch, flags;
float volume, attn;
MSG_ReadVec3Coord( msg, pos );
handle = MSG_ReadShort( msg );
volume = MSG_ReadByte( msg ) * ( 1.0f / 255.0f );
attn = MSG_ReadByte( msg ) * ( 1.0f / 64.0f );
entnum = MSG_ReadShort( msg );
pitch = MSG_ReadByte( msg );
flags = MSG_ReadByte( msg );
S_AmbientSound( pos, entnum, handle, volume, attn, pitch, flags );
}
/*
=====================================================================
ACTION MESSAGES
=====================================================================
*/
/*
=====================
CL_ParseGoldSrcServerMessage
dispatch messages
=====================
*/
void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
{
size_t bufStart, playerbytes;
int cmd, param1;
const char *s;
// parse the message
while( 1 )
{
if( MSG_CheckOverflow( msg ))
{
Host_Error( "CL_ParseServerMessage: overflow!\n" );
return;
}
// mark start position
bufStart = MSG_GetNumBytesRead( msg );
// end of message (align bits)
if( MSG_GetNumBitsLeft( msg ) < 8 )
break;
cmd = MSG_ReadServerCmd( msg );
// record command for debugging spew on parse problem
CL_Parse_RecordCommand( cmd, bufStart );
if( CL_ParseCommonDLLMessage( msg, PROTO_GOLDSRC, cmd, bufStart ))
continue;
// other commands
switch( cmd )
{
case svc_bad:
Host_Error( "svc_bad\n" );
break;
case svc_nop:
case svc_spawnstatic:
case svc_goldsrc_damage:
case svc_goldsrc_killedmonster:
case svc_goldsrc_foundsecret:
// this does nothing
break;
case svc_disconnect:
s = MSG_ReadString( msg );
if( COM_CheckStringEmpty( s ))
Con_Printf( "Server issued disconnect. Reason: %s\n", s );
CL_Drop ();
Host_AbortCurrentFrame ();
break;
case svc_event:
MSG_StartBitWriting( msg );
CL_ParseEvent( msg, PROTO_GOLDSRC );
MSG_EndBitWriting( msg );
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_goldsrc_version:
param1 = MSG_ReadLong( msg );
if( param1 != PROTOCOL_GOLDSRC_VERSION )
Host_Error( "Server use invalid protocol (%i should be %i)\n", param1, PROTOCOL_GOLDSRC_VERSION );
break;
case svc_setview:
CL_ParseViewEntity( msg );
break;
case svc_sound:
CL_ParseSoundPacketGS( msg );
cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_time:
CL_ParseServerTime( msg, PROTO_GOLDSRC );
break;
case svc_print:
Con_Printf( "%s", MSG_ReadString( msg ));
break;
case svc_stufftext:
s = MSG_ReadString( msg );
if( cl_trace_stufftext.value )
{
size_t len = Q_strlen( s );
Con_Printf( "Stufftext: %s%c", s, len && s[len-1] == '\n' ? '\0' : '\n' );
}
#ifdef HACKS_RELATED_HLMODS
// disable Cry Of Fear antisave protection
if( !Q_strnicmp( s, "disconnect", 10 ) && cls.signon != SIGNONS )
break; // too early
#endif
Cbuf_AddFilteredText( s );
break;
case svc_setangle:
CL_ParseSetAngle( msg );
break;
case svc_goldsrc_serverinfo:
Cbuf_Execute(); // make sure any stuffed commands are done
CL_ParseServerData( msg, PROTO_GOLDSRC );
break;
case svc_lightstyle:
CL_ParseLightStyle( msg, PROTO_GOLDSRC );
break;
case svc_updateuserinfo:
CL_UpdateUserinfo( msg, PROTO_GOLDSRC );
break;
case svc_goldsrc_deltadescription:
Delta_ParseTableField_GS( msg );
break;
case svc_clientdata:
MSG_StartBitWriting( msg );
CL_ParseClientData( msg, PROTO_GOLDSRC );
MSG_EndBitWriting( msg );
cl.frames[cl.parsecountmod].graphdata.client += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_goldsrc_stopsound:
param1 = MSG_ReadWord( msg );
S_StopSound( param1 >> 3, param1 & 7, NULL );
cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_pings:
MSG_StartBitWriting( msg );
CL_UpdateUserPings( msg );
MSG_EndBitWriting( msg );
break;
case svc_particle:
CL_ParseParticles( msg, PROTO_GOLDSRC );
break;
case svc_event_reliable:
MSG_StartBitWriting( msg );
CL_ParseReliableEvent( msg, PROTO_GOLDSRC );
MSG_EndBitWriting( msg );
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_spawnbaseline:
MSG_StartBitWriting( msg );
CL_ParseBaseline( msg, PROTO_GOLDSRC );
MSG_EndBitWriting( msg );
break;
case svc_setpause:
cl.paused = ( MSG_ReadByte( msg ) != 0 );
break;
case svc_signonnum:
CL_ParseSignon( msg, PROTO_GOLDSRC );
break;
case svc_centerprint:
CL_CenterPrint( MSG_ReadString( msg ), 0.25f );
break;
case svc_goldsrc_spawnstaticsound:
CL_ParseSpawnStaticSound( msg );
break;
case svc_finale:
CL_ParseFinaleCutscene( msg, 2 );
break;
case svc_restore:
CL_ParseRestore( msg );
break;
case svc_cutscene:
CL_ParseFinaleCutscene( msg, 3 );
break;
case svc_goldsrc_decalname:
param1 = MSG_ReadByte( msg );
s = MSG_ReadString( msg );
Q_strncpy( host.draw_decals[param1], s, sizeof( host.draw_decals[param1] ));
break;
case svc_addangle:
CL_ParseAddAngle( msg );
break;
case svc_goldsrc_newusermsg:
CL_RegisterUserMessage( msg, PROTO_GOLDSRC );
break;
case svc_packetentities:
playerbytes = CL_ParsePacketEntitiesGS( msg, false );
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
break;
case svc_deltapacketentities:
playerbytes = CL_ParsePacketEntitiesGS( msg, true );
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
break;
case svc_choke:
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].choked = true;
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].receivedtime = -2.0;
break;
case svc_resourcelist:
MSG_StartBitWriting( msg );
CL_ParseResourceList( msg, PROTO_GOLDSRC );
MSG_EndBitWriting( msg );
break;
case svc_goldsrc_newmovevars:
CL_ParseNewMovevars( msg );
break;
case svc_resourcerequest:
CL_ParseResourceRequest( msg );
break;
case svc_customization:
CL_ParseCustomization( msg );
break;
case svc_crosshairangle:
CL_ParseCrosshairAngle( msg );
break;
case svc_soundfade:
CL_ParseSoundFade( msg );
break;
case svc_filetxferfailed:
CL_ParseFileTransferFailed( msg );
break;
case svc_hltv:
CL_ParseHLTV( msg );
break;
case svc_voiceinit:
CL_ParseVoiceInit( msg );
break;
case svc_voicedata:
CL_ParseVoiceData( msg, PROTO_GOLDSRC );
cl.frames[cl.parsecountmod].graphdata.voicebytes += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_resourcelocation:
CL_ParseResLocation( msg );
break;
case svc_goldsrc_sendextrainfo:
CL_ParseExtraInfo( msg );
break;
case svc_goldsrc_timescale:
// we can set sys_timescale to anything we want but in GoldSrc it's locked for
// HLTV and demoplayback. Do we really want to have it then if both are out of scope?
Con_Reportf( S_ERROR "%s: svc_goldsrc_timescale: implement me!\n", __func__ );
MSG_ReadFloat( msg );
break;
case svc_goldsrc_sendcvarvalue:
CL_ParseCvarValue( msg, false, PROTO_GOLDSRC );
break;
case svc_goldsrc_sendcvarvalue2:
CL_ParseCvarValue( msg, true, PROTO_GOLDSRC );
break;
case svc_exec:
CL_ParseExec( msg );
break;
default:
CL_ParseUserMessage( msg, cmd, PROTO_LEGACY );
cl.frames[cl.parsecountmod].graphdata.usr += MSG_GetNumBytesRead( msg ) - bufStart;
break;
}
}
}

View File

@@ -59,7 +59,7 @@ void GAME_EXPORT CL_PopPMStates( void )
CL_IsPredicted
===============
*/
qboolean CL_IsPredicted( void )
static qboolean CL_IsPredicted( void )
{
if( cl_nopred.value || cl.intermission )
return false;
@@ -544,8 +544,8 @@ void GAME_EXPORT CL_SetSolidPlayers( int playernum )
// some fields needs to be override from cls.predicted_players
VectorCopy( player->origin, pe->origin );
VectorCopy( player->angles, pe->angles );
VectorCopy( clgame.pmove->player_mins[player->usehull], pe->mins );
VectorCopy( clgame.pmove->player_maxs[player->usehull], pe->maxs );
VectorCopy( host.player_mins[player->usehull], pe->mins );
VectorCopy( host.player_maxs[player->usehull], pe->maxs );
pe->movetype = player->movetype;
pe->solid = player->solid;
}

View File

@@ -22,22 +22,24 @@ GNU General Public License for more details.
#include "hltv.h"
#include "input.h"
#define STAT_HEALTH 0
#define STAT_FRAGS 1
#define STAT_WEAPON 2
#define STAT_AMMO 3
#define STAT_ARMOR 4
#define STAT_WEAPONFRAME 5
#define STAT_SHELLS 6
#define STAT_NAILS 7
#define STAT_ROCKETS 8
#define STAT_CELLS 9
#define STAT_ACTIVEWEAPON 10
#define STAT_TOTALSECRETS 11
#define STAT_TOTALMONSTERS 12
#define STAT_SECRETS 13 // bumped on client side by svc_foundsecret
#define STAT_MONSTERS 14 // bumped by svc_killedmonster
#define MAX_STATS 32
enum {
STAT_HEALTH = 0,
STAT_FRAGS,
STAT_WEAPON,
STAT_AMMO,
STAT_ARMOR,
STAT_WEAPONFRAME,
STAT_SHELLS,
STAT_NAILS,
STAT_ROCKETS,
STAT_CELLS,
STAT_ACTIVEWEAPON,
STAT_TOTALSECRETS,
STAT_TOTALMONSTERS,
STAT_SECRETS, // bumped on client side by svc_foundsecret
STAT_MONSTERS, // bumped by svc_killedmonster
MAX_STATS = 32,
};
static char cmd_buf[8192];
static char msg_buf[8192];
@@ -328,7 +330,7 @@ static void CL_ParseQuakeServerInfo( sizebuf_t *msg )
clgame.movevars.gravity = 800.0f; // quake doesn't write gravity in demos
clgame.movevars.maxvelocity = 2000.0f;
memcpy( &clgame.oldmovevars, &clgame.movevars, sizeof( movevars_t ));
clgame.oldmovevars = clgame.movevars;
}
/*
@@ -429,7 +431,7 @@ static void CL_ParseQuakeEntityData( sizebuf_t *msg, int bits )
cls.signon = SIGNONS;
// Clear loading plaque.
CL_SignonReply ();
CL_SignonReply( PROTO_QUAKE );
}
// alloc next slot to store update
@@ -624,7 +626,7 @@ CL_ParseStaticEntity
===================
*/
static void CL_ParseStaticEntity( sizebuf_t *msg )
static void CL_ParseQuakeStaticEntity( sizebuf_t *msg )
{
entity_state_t state;
cl_entity_t *ent;
@@ -715,8 +717,7 @@ static void CL_ParseQuakeBaseline( sizebuf_t *msg )
ent = CL_EDICT_NUM( newnum );
ent->index = newnum;
ent->player = CL_IsPlayerIndex( newnum );
memcpy( &ent->baseline, &state, sizeof( entity_state_t ));
memcpy( &ent->prevstate, &state, sizeof( entity_state_t ));
ent->prevstate = ent->baseline = state;
}
/*
@@ -949,7 +950,7 @@ void CL_ParseQuakeMessage( sizebuf_t *msg )
break;
case svc_time:
Cbuf_AddText( "\n" ); // new frame was started
CL_ParseServerTime( msg );
CL_ParseServerTime( msg, PROTO_QUAKE );
break;
case svc_print:
str = MSG_ReadString( msg );
@@ -1005,7 +1006,7 @@ void CL_ParseQuakeMessage( sizebuf_t *msg )
CL_ParseQuakeDamage( msg );
break;
case svc_spawnstatic:
CL_ParseStaticEntity( msg );
CL_ParseQuakeStaticEntity( msg );
break;
case svc_spawnbinary:
// never used in Quake

File diff suppressed because it is too large Load Diff

View File

@@ -77,7 +77,6 @@ void R_MultiGunshot( const vec3_t org, const vec3_t dir, const vec3_t noise, int
void R_FireField( float *org, int radius, int modelIndex, int count, int flags, float life );
void R_PlayerSprites( int client, int modelIndex, int count, int size );
void R_Sprite_WallPuff( struct tempent_s *pTemp, float scale );
void R_DebugParticle( const vec3_t pos, byte r, byte g, byte b );
void R_RicochetSound( const vec3_t pos );
struct dlight_s *CL_AllocDlight( int key );
struct dlight_s *CL_AllocElight( int key );

View File

@@ -35,7 +35,7 @@ static void V_CalcViewRect( void )
int sb_lines;
float size;
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
if( Host_IsQuakeCompatible( ))
{
// intermission is always full screen
if( cl.intermission ) size = 120.0f;
@@ -144,7 +144,9 @@ static void V_SetRefParams( ref_params_t *fd )
VectorCopy( cl.viewangles, fd->cl_viewangles );
fd->health = cl.local.health;
VectorCopy( cl.crosshairangle, fd->crosshairangle );
fd->viewsize = scr_viewsize.value;
if( Host_IsQuakeCompatible( ))
fd->viewsize = scr_viewsize.value;
else fd->viewsize = 120.0f;
VectorCopy( cl.punchangle, fd->punchangle );
fd->maxclients = cl.maxclients;

View File

@@ -129,7 +129,6 @@ typedef struct
// misc local info
qboolean repredicting; // repredicting in progress
qboolean thirdperson;
qboolean apply_effects; // local player will not added but we should apply their effects: flashlight etc
float idealpitch;
int viewmodel;
@@ -278,6 +277,8 @@ typedef struct
int lostpackets; // count lost packets and show dialog in menu
double frametime_remainder;
uint worldmapCRC;
} client_t;
/*
@@ -309,14 +310,6 @@ typedef enum
CL_CHANGELEVEL, // draw 'loading' during changelevel
} scrstate_t;
typedef enum
{
PROTO_CURRENT = 0, // Xash3D 49
PROTO_LEGACY = 1, // Xash3D 48
PROTO_QUAKE = 2, // Quake 15
PROTO_GOLDSRC = 3, // GoldSrc 48
} connprotocol_t;
typedef struct
{
char name[32];
@@ -501,7 +494,6 @@ typedef struct
net_request_t net_requests[MAX_REQUESTS]; // no reason to keep more
efrag_t *free_efrags; // linked efrags
cl_entity_t viewent; // viewmodel
qboolean client_dll_uses_sdl;
@@ -518,8 +510,9 @@ typedef struct
player_info_t playerinfo; // local playerinfo
gameui_draw_t ds; // draw2d stuff (menu images)
GAMEINFO gameInfo; // current gameInfo
GAMEINFO *modsInfo[MAX_MODS]; // simplified gameInfo for MainUI
gameinfo2_t gameInfo; // current gameInfo
gameinfo2_t *modsInfo; // simplified gameInfo for MainUI, allocated by demand
GAMEINFO **oldModsInfo; // simplified gameInfo for older MainUI, allocated by demand
ui_globalvars_t *globals;
@@ -660,6 +653,7 @@ extern gameui_static_t gameui;
//
// cvars
//
extern convar_t showpause;
extern convar_t mp_decals;
extern convar_t cl_logomaxdim;
extern convar_t cl_allow_download;
@@ -760,7 +754,7 @@ qboolean CL_PrecacheResources( void );
void CL_SetupOverviewParams( void );
void CL_UpdateFrameLerp( void );
int CL_IsDevOverviewMode( void );
void CL_SignonReply( void );
void CL_SignonReply( connprotocol_t proto );
void CL_ClearState( void );
//
@@ -784,13 +778,14 @@ void CL_Demos_f( void );
void CL_DeleteDemo_f( void );
void CL_Record_f( void );
void CL_Stop_f( void );
void CL_ListDemo_f( void );
int CL_GetDemoComment( const char *demoname, char *comment );
//
// cl_events.c
//
void CL_ParseEvent( sizebuf_t *msg );
void CL_ParseReliableEvent( sizebuf_t *msg );
void CL_ParseEvent( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseReliableEvent( sizebuf_t *msg, connprotocol_t proto );
void CL_SetEventIndex( const char *szEvName, int ev_index );
void CL_PlaybackEvent( int flags, const edict_t *pInvoker, word eventindex, float delay, float *origin,
float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 );
@@ -867,20 +862,21 @@ _inline cl_entity_t *CL_EDICT_NUM( int n )
// cl_parse.c
//
void CL_ParseSetAngle( sizebuf_t *msg );
void CL_ParseServerData( sizebuf_t *msg, qboolean legacy );
void CL_ParseLightStyle( sizebuf_t *msg );
void CL_UpdateUserinfo( sizebuf_t *msg, qboolean legacy );
void CL_ParseServerData( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseLightStyle( sizebuf_t *msg, connprotocol_t proto );
void CL_UpdateUserinfo( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseResource( sizebuf_t *msg );
void CL_ParseClientData( sizebuf_t *msg );
void CL_ParseClientData( sizebuf_t *msg, connprotocol_t proto );
void CL_UpdateUserPings( sizebuf_t *msg );
void CL_ParseParticles( sizebuf_t *msg );
void CL_ParseParticles( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseRestoreSoundPacket( sizebuf_t *msg );
void CL_ParseBaseline( sizebuf_t *msg, qboolean legacy );
void CL_ParseSignon( sizebuf_t *msg );
void CL_ParseBaseline( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseSignon( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseRestore( sizebuf_t *msg );
void CL_ParseStaticDecal( sizebuf_t *msg );
void CL_ParseAddAngle( sizebuf_t *msg );
void CL_RegisterUserMessage( sizebuf_t *msg );
void CL_RegisterUserMessage( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseResourceList( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseMovevars( sizebuf_t *msg );
void CL_ParseResourceRequest( sizebuf_t *msg );
void CL_ParseCustomization( sizebuf_t *msg );
@@ -889,18 +885,22 @@ void CL_ParseSoundFade( sizebuf_t *msg );
void CL_ParseFileTransferFailed( sizebuf_t *msg );
void CL_ParseHLTV( sizebuf_t *msg );
void CL_ParseDirector( sizebuf_t *msg );
void CL_ParseVoiceInit( sizebuf_t *msg );
void CL_ParseVoiceData( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseResLocation( sizebuf_t *msg );
void CL_ParseCvarValue( sizebuf_t *msg, const qboolean ext, const connprotocol_t proto );
void CL_ParseServerMessage( sizebuf_t *msg );
void CL_ParseTempEntity( sizebuf_t *msg );
qboolean CL_ParseCommonDLLMessage( sizebuf_t *msg, connprotocol_t proto, int svc_num, int startoffset );
void CL_ParseTempEntity( sizebuf_t *msg, connprotocol_t proto );
qboolean CL_DispatchUserMessage( const char *pszName, int iSize, void *pbuf );
qboolean CL_RequestMissingResources( void );
void CL_RegisterResources ( sizebuf_t *msg );
void CL_RegisterResources( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseViewEntity( sizebuf_t *msg );
void CL_ParseServerTime( sizebuf_t *msg );
void CL_ParseUserMessage( sizebuf_t *msg, int svc_num );
void CL_ParseServerTime( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseUserMessage( sizebuf_t *msg, int svc_num, connprotocol_t proto );
void CL_ParseFinaleCutscene( sizebuf_t *msg, int level );
void CL_ParseTextMessage( sizebuf_t *msg );
void CL_ParseExec( sizebuf_t *msg );
void CL_BatchResourceRequest( qboolean initialize );
int CL_EstimateNeededResources( void );
@@ -910,6 +910,11 @@ int CL_EstimateNeededResources( void );
void CL_ParseLegacyServerMessage( sizebuf_t *msg );
void CL_LegacyPrecache_f( void );
//
// cl_parse_gs.c
//
void CL_ParseGoldSrcServerMessage( sizebuf_t *msg );
//
// cl_scrn.c
//
@@ -951,7 +956,6 @@ void CL_SetSolidPlayers( int playernum );
void CL_InitClientMove( void );
void CL_PredictMovement( qboolean repredicting );
void CL_CheckPredictionError( void );
qboolean CL_IsPredicted( void );
int CL_WaterEntity( const float *rgflPos );
cl_entity_t *CL_GetWaterEntity( const float *rgflPos );
pmtrace_t *CL_VisTraceLine( vec3_t start, vec3_t end, int flags );
@@ -974,7 +978,9 @@ void CL_ParseQuakeMessage( sizebuf_t *msg );
//
struct channel_s;
struct rawchan_s;
int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta );
qboolean CL_ValidateDeltaPacket( uint oldpacket, frame_t *oldframe );
int CL_UpdateOldEntNum( int oldindex, frame_t *oldframe, entity_state_t **oldent );
int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta, connprotocol_t proto );
qboolean CL_AddVisibleEntity( cl_entity_t *ent, int entityType );
void CL_ResetLatchedVars( cl_entity_t *ent, qboolean full_reset );
qboolean CL_GetEntitySpatialization( struct channel_s *ch );
@@ -1024,7 +1030,6 @@ void CL_InitParticles( void );
void CL_ClearParticles( void );
void CL_FreeParticles( void );
void CL_InitTempEnts( void );
void CL_ClearTempEnts( void );
void CL_FreeTempEnts( void );
void CL_TempEntUpdate( void );
void CL_InitViewBeams( void );

View File

@@ -1753,7 +1753,7 @@ static void Con_DrawNotify( void )
if( host.allow_console && ( !Cvar_VariableInteger( "cl_background" ) && !Cvar_VariableInteger( "sv_background" )))
{
for( i = CON_LINES_COUNT - con.num_times; i < CON_LINES_COUNT; i++ )
for( i = Q_max( 0, CON_LINES_COUNT - con.num_times ); i < CON_LINES_COUNT; i++ )
{
con_lineinfo_t *l = &CON_LINES( i );

View File

@@ -142,7 +142,7 @@ static struct touch_s
touchdefaultbutton_t g_DefaultButtons[256];
int g_LastDefaultButton;
static CVAR_DEFINE_AUTO( touch_in_menu, "0", FCVAR_FILTERABLE, "draw touch in menu (for internal use only)" );
static CVAR_DEFINE_AUTO( touch_in_menu, "0", FCVAR_PRIVILEGED, "draw touch in menu (for internal use only)" );
static CVAR_DEFINE_AUTO( touch_forwardzone, "0.06", FCVAR_FILTERABLE, "forward touch zone" );
static CVAR_DEFINE_AUTO( touch_sidezone, "0.06", FCVAR_FILTERABLE, "side touch zone" );
static CVAR_DEFINE_AUTO( touch_pitch, "90", FCVAR_FILTERABLE, "touch pitch sensitivity" );
@@ -163,8 +163,8 @@ static CVAR_DEFINE_AUTO( touch_dpad_radius, "1.0", FCVAR_FILTERABLE, "dpad radiu
static CVAR_DEFINE_AUTO( touch_joy_radius, "1.0", FCVAR_FILTERABLE, "joy radius multiplier" );
static CVAR_DEFINE_AUTO( touch_move_indicator, "0.0", FCVAR_FILTERABLE, "indicate move events (0 to disable)" );
static CVAR_DEFINE_AUTO( touch_joy_texture, "touch_default/joy", FCVAR_FILTERABLE, "texture for move indicator");
static CVAR_DEFINE_AUTO( touch_emulate, "0", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "emulate touch with mouse" );
CVAR_DEFINE_AUTO( touch_enable, DEFAULT_TOUCH_ENABLE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable touch controls" );
CVAR_DEFINE_AUTO( touch_emulate, "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "emulate touch with mouse" );
// code looks smaller with it
#define B(x) (button->x)
@@ -767,14 +767,18 @@ static void Touch_ReloadConfig_f( void )
touch.state = state_none;
if( touch.edit )
touch.edit->finger = -1;
if( touch.selection )
touch.selection->finger = -1;
touch.edit = touch.selection = NULL;
touch.resize_finger = touch.move_finger = touch.look_finger = touch.wheel_finger = -1;
if( FS_FileExists( touch_config_file.string, true ) )
{
if( touch_in_menu.value )
Cvar_DirectSet( &touch_in_menu, "0" );
if( FS_FileExists( touch_config_file.string, true ))
Cbuf_AddTextf( "exec \"%s\"\n", touch_config_file.string );
}
else
{
Touch_LoadDefaults_f();
@@ -1010,7 +1014,7 @@ static void Touch_DisableEdit_f( void )
{
Cvar_Set( "touch_in_menu", "0" );
}
else if( cls.key_dest == key_game )
else if( cls.key_dest == key_game )
Touch_WriteConfig();
}
@@ -1087,18 +1091,19 @@ void Touch_Init( void )
Touch_AddDefaultButton( "jump", "touch_default/jump", "+jump", 0.880000, 0.227228, 1.000000, 0.454457, color, 2, 1, 0 );
Touch_AddDefaultButton( "attack", "touch_default/shoot", "+attack", 0.760000, 0.530200, 0.880000, 0.757428, color, 2, 1, 0 );
Touch_AddDefaultButton( "attack2", "touch_default/shoot_alt", "+attack2", 0.760000, 0.302971, 0.880000, 0.530200, color, 2, 1, 0 );
Touch_AddDefaultButton( "loadquick", "touch_default/load", "loadquick", 0.680000, 0.000000, 0.760000, 0.151486, color, 2, 1, 16 );
Touch_AddDefaultButton( "savequick", "touch_default/save", "savequick", 0.760000, 0.000000, 0.840000, 0.151486, color, 2, 1, 16 );
Touch_AddDefaultButton( "messagemode", "touch_default/keyboard", "messagemode", 0.760000, 0.000000, 0.840000, 0.151486, color, 2, 1, 8 );
Touch_AddDefaultButton( "loadquick", "touch_default/load", "loadquick", 0.760000, 0.000000, 0.840000, 0.142222, color, 2, 1, 16 );
Touch_AddDefaultButton( "savequick", "touch_default/save", "savequick", 0.840000, 0.000000, 0.920000, 0.142222, color, 2, 1, 16 );
Touch_AddDefaultButton( "messagemode", "touch_default/keyboard", "messagemode", 0.840000, 0.000000, 0.920000, 0.142222, color, 2, 1, 8 );
Touch_AddDefaultButton( "reload", "touch_default/reload", "+reload", 0.000000, 0.302971, 0.120000, 0.530200, color, 2, 1, 0 );
Touch_AddDefaultButton( "flashlight", "touch_default/flash_light_filled", "impulse 100", 0.920000, 0.000000, 1.000000, 0.151486, color, 2, 1, 0 );
Touch_AddDefaultButton( "scores", "touch_default/map", "+showscores", 0.680000, 0.000000, 0.760000, 0.151486, color, 2, 1, 8 );
Touch_AddDefaultButton( "scores", "touch_default/map", "+showscores", 0.760000, 0.000000, 0.840000, 0.142222, color, 2, 1, 8 );
Touch_AddDefaultButton( "show_numbers", "touch_default/show_weapons", "exec touch_default/numbers.cfg", 0.440000, 0.833171, 0.520000, 0.984656, color, 2, 1, 0 );
Touch_AddDefaultButton( "duck", "touch_default/crouch", "+duck", 0.880000, 0.757428, 1.000000, 0.984656, color, 2, 1, 0 );
Touch_AddDefaultButton( "tduck", "touch_default/tduck", ";+duck", 0.560000, 0.833171, 0.620000, 0.946785, color, 2, 1, 0 );
Touch_AddDefaultButton( "edit", "touch_default/settings", "touch_enableedit", 0.420000, 0.000000, 0.500000, 0.151486, color, 2, 1, 32 );
Touch_AddDefaultButton( "menu", "touch_default/menu", "escape", 0.000000, 0.833171, 0.080000, 0.984656, color, 2, 1, 0 );
Touch_AddDefaultButton( "spray", "touch_default/spray", "impulse 201", 0.840000, 0.000000, 0.920000, 0.151486, color, 2, 1, 0 );
Touch_AddDefaultButton( "spray", "touch_default/spray", "impulse 201", 0.680000, 0.000000, 0.760000, 0.142222, color, 2, 1, 8 );
Touch_AddDefaultButton( "voicechat", "touch_default/microphone", "+voicerecord", 0.780000, 0.817778, 0.860000, 0.960000, color, 2, 1, 8 );
Cmd_AddCommand( "touch_addbutton", Touch_AddButton_f, "add native touch button" );
Cmd_AddCommand( "touch_removebutton", IN_TouchRemoveButton_f, "remove native touch button" );
@@ -2122,7 +2127,7 @@ void Touch_KeyEvent( int key, int down )
float x, y;
int finger, xi, yi;
if( !touch_emulate.value )
if( !Touch_Emulated( ))
{
if( touch_enable.value )
return;
@@ -2176,6 +2181,11 @@ qboolean Touch_WantVisibleCursor( void )
return ( touch_enable.value && touch_emulate.value ) || touch.clientonly;
}
qboolean Touch_Emulated( void )
{
return touch_emulate.value || touch_in_menu.value;
}
void Touch_Shutdown( void )
{
if( !touch.initialized )

View File

@@ -47,6 +47,8 @@ static CVAR_DEFINE_AUTO( cl_forwardspeed, "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL
static CVAR_DEFINE_AUTO( cl_backspeed, "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL | FCVAR_FILTERABLE, "Default back move speed" );
static CVAR_DEFINE_AUTO( cl_sidespeed, "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL | FCVAR_FILTERABLE, "Default side move speed" );
static CVAR_DEFINE_AUTO( m_grab_debug, "0", FCVAR_PRIVILEGED, "show debug messages on mouse state change" );
/*
================
IN_CollectInputDevices
@@ -116,6 +118,7 @@ static void IN_StartupMouse( void )
Cvar_RegisterVariable( &m_yaw );
Cvar_RegisterVariable( &look_filter );
Cvar_RegisterVariable( &m_rawinput );
Cvar_RegisterVariable( &m_grab_debug );
// You can use -nomouse argument to prevent using mouse from client
// -noenginemouse will disable all mouse input
@@ -202,68 +205,81 @@ void IN_ToggleClientMouse( int newstate, int oldstate )
}
}
static void IN_SetRelativeMouseMode( qboolean set, qboolean verbose )
{
static qboolean s_bRawInput;
if( set && !s_bRawInput )
{
#if XASH_SDL == 2
SDL_GetRelativeMouseState( NULL, NULL );
SDL_SetRelativeMouseMode( SDL_TRUE );
#endif
s_bRawInput = true;
if( verbose )
Con_Printf( "%s: true\n", __func__ );
}
else if( !set && s_bRawInput )
{
#if XASH_SDL == 2
SDL_GetRelativeMouseState( NULL, NULL );
SDL_SetRelativeMouseMode( SDL_FALSE );
#endif
s_bRawInput = false;
if( verbose )
Con_Printf( "%s: false\n", __func__ );
}
}
static void IN_SetMouseGrab( qboolean set, qboolean verbose )
{
static qboolean s_bMouseGrab;
if( set && !s_bMouseGrab )
{
#if XASH_SDL
SDL_SetWindowGrab( host.hWnd, SDL_TRUE );
#endif
s_bMouseGrab = true;
if( verbose )
Con_Printf( "%s: true\n", __func__ );
}
else if( !set && s_bMouseGrab )
{
#if XASH_SDL
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
#endif
s_bMouseGrab = false;
if( verbose )
Con_Printf( "%s: false\n", __func__ );
}
}
static void IN_CheckMouseState( qboolean active )
{
static qboolean s_bRawInput, s_bMouseGrab;
qboolean use_raw_input, verbose;
#if XASH_WIN32
qboolean useRawInput = ( m_rawinput.value && clgame.client_dll_uses_sdl ) || clgame.dllFuncs.pfnLookEvent != NULL;
use_raw_input = ( m_rawinput.value && clgame.client_dll_uses_sdl ) || clgame.dllFuncs.pfnLookEvent != NULL;
#else
qboolean useRawInput = true; // always use SDL code
use_raw_input = true; // always use SDL code
#endif
verbose = m_grab_debug.value ? true : false;
if( m_ignore.value )
return;
active = false;
if( active && useRawInput && !host.mouse_visible && cls.state == ca_active )
{
if( !s_bRawInput )
{
#if XASH_SDL == 2
SDL_GetRelativeMouseState( NULL, NULL );
SDL_SetRelativeMouseMode( SDL_TRUE );
#endif
// Con_Printf( "Enable relative mode\n" );
s_bRawInput = true;
}
}
if( active && use_raw_input && !host.mouse_visible && cls.state == ca_active )
IN_SetRelativeMouseMode( true, verbose );
else
{
if( s_bRawInput )
{
#if XASH_SDL == 2
SDL_GetRelativeMouseState( NULL, NULL );
SDL_SetRelativeMouseMode( SDL_FALSE );
#endif
// Con_Printf( "Disable relative mode\n" );
s_bRawInput = false;
}
}
IN_SetRelativeMouseMode( false, verbose );
if( active && !host.mouse_visible && cls.state == ca_active )
{
if( !s_bMouseGrab )
{
#if XASH_SDL
SDL_SetWindowGrab( host.hWnd, SDL_TRUE );
#endif
// Con_Printf( "Enable grab\n" );
s_bMouseGrab = true;
}
}
IN_SetMouseGrab( true, verbose );
else
{
if( s_bMouseGrab )
{
#if XASH_SDL
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
#endif
// Con_Printf( "Disable grab\n" );
s_bMouseGrab = false;
}
}
IN_SetMouseGrab( false, verbose );
}
/*
@@ -316,7 +332,7 @@ static void IN_MouseMove( void )
if( !in_mouseinitialized )
return;
if( touch_emulate.value )
if( Touch_Emulated( ))
{
// touch emulation overrides all input
Touch_KeyEvent( 0, 0 );
@@ -347,7 +363,7 @@ void IN_MouseEvent( int key, int down )
else ClearBits( in_mstate, BIT( key ));
// touch emulation overrides all input
if( touch_emulate.value )
if( Touch_Emulated( ))
{
Touch_KeyEvent( K_MOUSE1 + key, down );
}
@@ -553,10 +569,9 @@ IN_EngineAppendMove
Called from cl_main.c after generating command in client
================
*/
void IN_EngineAppendMove( float frametime, void *cmd1, qboolean active )
void IN_EngineAppendMove( float frametime, usercmd_t *cmd, qboolean active )
{
float forward, side, pitch, yaw;
usercmd_t *cmd = cmd1;
if( clgame.dllFuncs.pfnLookEvent )
return;

View File

@@ -25,6 +25,7 @@ INPUT
*/
#include "keydefs.h"
#include "usercmd.h"
//
// input.c
@@ -43,7 +44,7 @@ void IN_ToggleClientMouse( int newstate, int oldstate );
uint IN_CollectInputDevices( void );
void IN_LockInputDevices( qboolean lock );
void IN_EngineAppendMove( float frametime, void *cmd, qboolean active );
void IN_EngineAppendMove( float frametime, usercmd_t *cmd, qboolean active );
extern convar_t m_yaw;
extern convar_t m_pitch;
@@ -58,7 +59,6 @@ typedef enum
} touchEventType;
extern convar_t touch_enable;
extern convar_t touch_emulate;
void Touch_Draw( void );
void Touch_SetClientOnly( byte state );
@@ -74,6 +74,7 @@ void Touch_ResetDefaultButtons( void );
int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy );
void Touch_KeyEvent( int key, int down );
qboolean Touch_WantVisibleCursor( void );
qboolean Touch_Emulated( void );
void Touch_NotifyResize( void );
//

View File

@@ -10,7 +10,7 @@ ref_globals_t refState;
static const char* r_skyBoxSuffix[SKYBOX_MAX_SIDES] = { "rt", "bk", "lf", "ft", "up", "dn" };
CVAR_DEFINE_AUTO( gl_vsync, "0", FCVAR_ARCHIVE, "enable vertical syncronization" );
CVAR_DEFINE_AUTO( gl_vsync, "1", FCVAR_ARCHIVE, "enable vertical syncronization" );
CVAR_DEFINE_AUTO( r_showtextures, "0", FCVAR_CHEAT, "show all uploaded textures" );
CVAR_DEFINE_AUTO( r_adjust_fov, "1", FCVAR_ARCHIVE, "making FOV adjustment for wide-screens" );
CVAR_DEFINE_AUTO( r_decals, "4096", FCVAR_ARCHIVE, "sets the maximum number of decals" );
@@ -171,6 +171,22 @@ static intptr_t pfnEngineGetParm( int parm, int arg )
return CL_RenderGetParm( parm, arg, false ); // prevent recursion
}
static cvar_t *pfnCvar_Get( const char *szName, const char *szValue, int flags, const char *description )
{
return (cvar_t *)Cvar_Get( szName, szValue, flags | FCVAR_REFDLL, description );
}
static void pfnCvar_RegisterVariable( convar_t *var )
{
SetBits( var->flags, FCVAR_REFDLL );
Cvar_RegisterVariable( var );
}
static void pfnCvar_FullSet( const char *var_name, const char *value, int flags )
{
Cvar_FullSet( var_name, value, flags | FCVAR_REFDLL );
}
static void pfnStudioEvent( const mstudioevent_t *event, const cl_entity_t *e )
{
clgame.dllFuncs.pfnStudioEvent( event, e );
@@ -285,18 +301,18 @@ static qboolean R_Init_Video_( const int type )
return R_Init_Video( type );
}
static ref_api_t gEngfuncs =
static const ref_api_t gEngfuncs =
{
pfnEngineGetParm,
(void*)Cvar_Get,
pfnCvar_Get,
(void*)Cvar_FindVarExt,
Cvar_VariableValue,
Cvar_VariableString,
Cvar_SetValue,
Cvar_Set,
Cvar_RegisterVariable,
Cvar_FullSet,
pfnCvar_RegisterVariable,
pfnCvar_FullSet,
Cmd_AddRefCommand,
Cmd_RemoveCommand,
@@ -431,7 +447,7 @@ static void R_UnloadProgs( void )
Cvar_FullSet( "host_refloaded", "0", FCVAR_READ_ONLY );
Cvar_Unlink( FCVAR_RENDERINFO | FCVAR_GLCONFIG );
Cvar_Unlink( FCVAR_RENDERINFO | FCVAR_GLCONFIG | FCVAR_REFDLL );
Cmd_Unlink( CMD_REFDLL );
COM_FreeLibrary( ref.hInstance );
@@ -473,7 +489,7 @@ static qboolean R_LoadProgs( const char *name )
if( ref.hInstance ) R_UnloadProgs();
FS_AllowDirectPaths( true );
if( !(ref.hInstance = COM_LoadLibrary( name, false, true ) ))
if( !( ref.hInstance = COM_LoadLibrary( name, false, true )))
{
FS_AllowDirectPaths( false );
Con_Reportf( "%s: can't load renderer library %s: %s\n", __func__, name, COM_GetLibraryError() );
@@ -482,32 +498,26 @@ static qboolean R_LoadProgs( const char *name )
FS_AllowDirectPaths( false );
if( !( GetRefAPI = (REFAPI)COM_GetProcAddress( ref.hInstance, GET_REF_API )) )
if( !( GetRefAPI = (REFAPI)COM_GetProcAddress( ref.hInstance, GET_REF_API )))
{
COM_FreeLibrary( ref.hInstance );
Con_Reportf( "%s: can't find GetRefAPI entry point in %s\n", __func__, name );
ref.hInstance = NULL;
return false;
}
// make local copy of engfuncs to prevent overwrite it with user dll
memcpy( &gpEngfuncs, &gEngfuncs, sizeof( gpEngfuncs ));
gpEngfuncs = gEngfuncs;
if( GetRefAPI( REF_API_VERSION, &ref.dllFuncs, &gpEngfuncs, &refState ) != REF_API_VERSION )
{
COM_FreeLibrary( ref.hInstance );
Con_Reportf( "%s: can't init renderer API: wrong version\n", __func__ );
ref.hInstance = NULL;
return false;
}
refState.developer = host_developer.value;
if( !ref.dllFuncs.R_Init( ) )
if( !ref.dllFuncs.R_Init( ))
{
COM_FreeLibrary( ref.hInstance );
Con_Reportf( "%s: can't init renderer!\n", __func__ ); //, ref.dllFuncs.R_GetInitError() );
ref.hInstance = NULL;
return false;
}
@@ -544,21 +554,19 @@ static void R_GetRendererName( char *dest, size_t size, const char *opt )
{
if( !Q_strstr( opt, "." OS_LIB_EXT ))
{
const char *format;
#ifdef XASH_INTERNAL_GAMELIBS
if( !Q_strcmp( opt, "ref_" ))
format = "%s";
else
format = "ref_%s";
#define FMT1 "%s"
#define FMT2 "ref_%s"
#else
if( !Q_strcmp( opt, "ref_" ))
format = OS_LIB_PREFIX "%s." OS_LIB_EXT;
else
format = OS_LIB_PREFIX "ref_%s." OS_LIB_EXT;
#define FMT1 OS_LIB_PREFIX "%s." OS_LIB_EXT
#define FMT2 OS_LIB_PREFIX "ref_%s." OS_LIB_EXT
#endif
Q_snprintf( dest, size, format, opt );
if( !Q_strncmp( opt, "ref_", 4 ))
Q_snprintf( dest, size, FMT1, opt );
else
Q_snprintf( dest, size, FMT2, opt );
#undef FMT1
#undef FMT2
}
else
{
@@ -670,7 +678,8 @@ static void R_CollectRendererNames( void )
qboolean R_Init( void )
{
qboolean success = false;
string requested;
string requested_cmdline;
string requested_cvar;
Cvar_RegisterVariable( &gl_vsync );
Cvar_RegisterVariable( &r_showtextures );
@@ -720,15 +729,16 @@ qboolean R_Init( void )
// 1. Command line `-ref` argument.
// 2. `ref_dll` cvar.
// 3. Detected renderers in `DEFAULT_RENDERERS` order.
requested[0] = 0;
requested_cmdline[0] = 0;
requested_cvar[0] = 0;
if( !success && Sys_GetParmFromCmdLine( "-ref", requested ))
success = R_LoadRenderer( requested );
if( Sys_GetParmFromCmdLine( "-ref", requested_cmdline ))
success = R_LoadRenderer( requested_cmdline );
if( !success && COM_CheckString( r_refdll.string ))
if( !success && COM_CheckString( r_refdll.string ) && Q_stricmp( requested_cmdline, r_refdll.string ))
{
Q_strncpy( requested, r_refdll.string, sizeof( requested ));
success = R_LoadRenderer( requested );
Q_strncpy( requested_cvar, r_refdll.string, sizeof( requested_cvar ));
success = R_LoadRenderer( requested_cvar );
}
if( !success )
@@ -738,7 +748,10 @@ qboolean R_Init( void )
for( i = 0; i < ref.numRenderers && !success; i++ )
{
// skip renderer that was requested but failed to load
if( !Q_strcmp( requested, ref.shortNames[i] ))
if( !Q_strcmp( requested_cmdline, ref.shortNames[i] ))
continue;
if( !Q_strcmp( requested_cvar, ref.shortNames[i] ))
continue;
success = R_LoadRenderer( ref.shortNames[i] );
@@ -747,7 +760,7 @@ qboolean R_Init( void )
if( !success )
{
Host_Error( "Can't initialize any renderer. Check your video drivers!\n" );
Sys_Error( "Can't initialize any renderer. Check your video drivers!\n" );
return false;
}

View File

@@ -155,11 +155,11 @@ wavdata_t *S_LoadSound( sfx_t *sfx )
if( !sc ) sc = S_CreateDefaultSound();
if( sc->rate < SOUND_11k ) // some bad sounds
Sound_Process( &sc, SOUND_11k, sc->width, SOUND_RESAMPLE );
Sound_Process( &sc, SOUND_11k, sc->width, sc->channels, SOUND_RESAMPLE );
else if( sc->rate > SOUND_11k && sc->rate < SOUND_22k ) // some bad sounds
Sound_Process( &sc, SOUND_22k, sc->width, SOUND_RESAMPLE );
Sound_Process( &sc, SOUND_22k, sc->width, sc->channels, SOUND_RESAMPLE );
else if( sc->rate > SOUND_22k && sc->rate < SOUND_44k ) // some bad sounds
Sound_Process( &sc, SOUND_44k, sc->width, SOUND_RESAMPLE );
Sound_Process( &sc, SOUND_44k, sc->width, sc->channels, SOUND_RESAMPLE );
sfx->cache = sc;

View File

@@ -524,8 +524,11 @@ static void SND_Spatialize( channel_t *ch )
dist = VectorNormalizeLength( source_vec );
dot = DotProduct( s_listener.right, source_vec );
// don't pan sounds with no attenuation
if( ch->dist_mult <= 0.0f ) dot = 0.0f;
if( !FBitSet( host.bugcomp, BUGCOMP_SPATIALIZE_SOUND_WITH_ATTN_NONE ))
{
// don't pan sounds with no attenuation
if( ch->dist_mult <= 0.0f ) dot = 0.0f;
}
// fill out channel volumes for single location
S_SpatializeChannel( &ch->leftvol, &ch->rightvol, ch->master_vol, gain, dot, dist * ch->dist_mult );
@@ -1092,7 +1095,7 @@ rawchan_t *S_FindRawChannel( int entnum, qboolean create )
if( !raw_channels[best] )
{
raw_samples = MAX_RAW_SAMPLES;
raw_channels[best] = Mem_Calloc( sndpool, sizeof( *ch ) + sizeof( portable_samplepair_t ) * ( raw_samples - 1 ));
raw_channels[best] = Mem_Calloc( sndpool, sizeof( *ch ) + sizeof( portable_samplepair_t ) * raw_samples );
}
ch = raw_channels[best];
@@ -1891,7 +1894,7 @@ S_VoiceRecordStart_f
*/
static void S_VoiceRecordStart_f( void )
{
if( cls.state != ca_active || cls.legacymode )
if( cls.state != ca_active )
return;
Voice_RecordStart();

View File

@@ -923,7 +923,7 @@ static void S_MixUpsample( int sampleCount, int filtertype )
static void MIX_MixRawSamplesBuffer( int end )
{
portable_samplepair_t *pbuf, *roombuf, *streambuf;
uint i, j, stop;
uint i, j, stop;
roombuf = MIX_GetPFrontFromIPaint( IROOMBUFFER );
streambuf = MIX_GetPFrontFromIPaint( ISTREAMBUFFER );
@@ -956,7 +956,11 @@ static void MIX_MixRawSamplesBuffer( int end )
}
if( ch->entnum > 0 )
SND_MoveMouthRaw( ch, &ch->rawsamples[paintedtime & ( ch->max_samples - 1 )], stop - paintedtime );
{
int pos = paintedtime & ( ch->max_samples - 1 );
SND_MoveMouthRaw( ch, &ch->rawsamples[pos], bound( 0, ch->max_samples - pos, stop - paintedtime ));
}
}
}

View File

@@ -96,7 +96,7 @@ static int S_TrimEnd( const wavdata_t *wav, int end )
if( width == 1 )
{
const int8_t *data = (const int8_t *)&wav->buffer[channels * width * end];
const int8_t *data = (const int8_t *)&wav->buffer[channels * width * ( end - 1 )];
for( i = 0; i < TRIM_SCAN_MAX && end > 0; i++ )
{
@@ -109,7 +109,7 @@ static int S_TrimEnd( const wavdata_t *wav, int end )
}
else if( width == 2 )
{
const int16_t *data = (const int16_t *)&wav->buffer[channels * width * end];
const int16_t *data = (const int16_t *)&wav->buffer[channels * width * ( end - 1 )];
for( i = 0; i < TRIM_SCAN_MAX && end > 0; i++ )
{
@@ -248,6 +248,12 @@ static const char *VOX_GetDirectory( char *szpath, const char *psz, int nsize )
const char *p;
int len;
// HACKHACK: some modders send strings like "/fvox/_period four"
// which should get parsed as "_period four" said by fvox
// it might be incorrect but ignore first slash here for now
if( psz[0] == '/' )
psz++;
// search / backwards
p = Q_strrchr( psz, '/' );
@@ -595,8 +601,8 @@ static void Test_VOX_GetDirectory( void )
{
"", "", "vox/",
"bark bark", "bark bark", "vox/",
"barney/meow", "meow", "barney/"
"barney/meow", "meow", "barney/",
"/fvox/_period", "_period", "fvox/",
};
int i;

View File

@@ -116,7 +116,7 @@ typedef struct rawchan_s
float oldtime; // catch time jumps
wavdata_t sound_info; // advance play position
size_t max_samples; // buffer length
portable_samplepair_t rawsamples[1]; // variable sized
portable_samplepair_t rawsamples[]; // variable sized
} rawchan_t;
typedef struct channel_s

View File

@@ -50,7 +50,9 @@ static CVAR_DEFINE_AUTO( vgui_utf8, "0", FCVAR_ARCHIVE, "enable utf-8 support fo
static void GAME_EXPORT VGUI_DrawInit( void )
{
memset( vgui.textures, 0, sizeof( vgui.textures ));
memset( vgui.color, 0, sizeof( vgui.color ));
vgui.texture_id = vgui.bound_texture = 0;
vgui.enable_texture = true;
}
static void GAME_EXPORT VGUI_DrawShutdown( void )
@@ -280,7 +282,7 @@ qboolean VGui_LoadProgs( HINSTANCE hInstance )
void (*F)( vguiapi_t* );
qboolean client = hInstance != NULL;
memcpy( &vgui.dllFuncs, &gEngfuncs, sizeof( vgui.dllFuncs ));
vgui.dllFuncs = gEngfuncs;
// not loading interface from client.dll, load vgui_support.dll instead
if( !client )
@@ -371,7 +373,7 @@ void VGui_Shutdown( void )
COM_FreeLibrary( vgui.hInstance );
// drop pointers to now unloaded vgui_support
memcpy( &vgui.dllFuncs, &gEngfuncs, sizeof( vgui.dllFuncs ));
vgui.dllFuncs = gEngfuncs;
vgui.hInstance = NULL;
}

View File

@@ -26,7 +26,7 @@ static CVAR_DEFINE_AUTO( vid_scale, "1.0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "p
CVAR_DEFINE_AUTO( vid_highdpi, "1", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "enable High-DPI mode" );
CVAR_DEFINE_AUTO( vid_maximized, "0", FCVAR_RENDERINFO, "window maximized state, read-only" );
CVAR_DEFINE( vid_fullscreen, "fullscreen", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "fullscreen state (0 windowed, 1 fullscreen, 2 borderless)" );
CVAR_DEFINE( vid_fullscreen, "fullscreen", DEFAULT_FULLSCREEN, FCVAR_RENDERINFO|FCVAR_VIDRESTART, "fullscreen state (0 windowed, 1 fullscreen, 2 borderless)" );
CVAR_DEFINE( window_width, "width", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen width" );
CVAR_DEFINE( window_height, "height", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen height" );
CVAR_DEFINE( window_xpos, "_window_xpos", "-1", FCVAR_RENDERINFO, "window position by horizontal" );

View File

@@ -32,6 +32,11 @@ CVAR_DEFINE_AUTO( voice_inputfromfile, "0", FCVAR_PRIVILEGED, "input voice from
static void Voice_ApplyGainAdjust( int16_t *samples, int count, float scale );
// in case user enabled voice after connection
// can't keep in `voice` struct because it gets zeroed on shutdown
static string voice_codec_init;
static int voice_quality_init;
/*
===============================================================================
@@ -391,13 +396,16 @@ void Voice_RecordStart( void )
{
Voice_RecordStop();
if( !voice.initialized )
return;
if( voice_inputfromfile.value )
{
voice.input_file = FS_LoadSound( "voice_input.wav", NULL, 0 );
if( voice.input_file )
{
Sound_Process( &voice.input_file, voice.samplerate, voice.width, SOUND_RESAMPLE );
Sound_Process( &voice.input_file, voice.samplerate, voice.width, VOICE_PCM_CHANNELS, SOUND_RESAMPLE );
voice.input_file_pos = 0;
voice.start_time = Sys_DoubleTime();
@@ -410,7 +418,7 @@ void Voice_RecordStart( void )
}
}
if( !Voice_IsRecording() )
if( !Voice_IsRecording( ) && voice.device_opened )
voice.is_recording = VoiceCapture_Activate( true );
if( Voice_IsRecording() )
@@ -591,10 +599,17 @@ void Voice_Idle( double frametime )
{
int i;
if( FBitSet( voice_enable.flags, FCVAR_CHANGED ) && !voice_enable.value )
if( FBitSet( voice_enable.flags, FCVAR_CHANGED ))
{
Voice_Shutdown();
return;
ClearBits( voice_enable.flags, FCVAR_CHANGED );
if( voice_enable.value )
{
if( cls.state == ca_active && COM_CheckString( voice_codec_init ) && voice_quality_init != 0 )
Voice_Init( voice_codec_init, voice_quality_init, false );
}
else
Voice_Shutdown();
}
// update local player status first
@@ -613,6 +628,20 @@ Initialize the voice subsystem
*/
qboolean Voice_Init( const char *pszCodecName, int quality, qboolean preinit )
{
if( Q_strcmp( pszCodecName, VOICE_OPUS_CUSTOM_CODEC ))
{
if( COM_CheckStringEmpty( pszCodecName ))
Con_Printf( S_ERROR "Server requested unsupported codec: %s\n", pszCodecName );
// reset saved codec name, we won't enable voice for this connection
voice_codec_init[0] = 0;
voice_quality_init = 0;
return false;
}
Q_strncpy( voice_codec_init, pszCodecName, sizeof( voice_codec_init ));
voice_quality_init = quality;
if( !voice_enable.value )
return false;
@@ -620,13 +649,6 @@ qboolean Voice_Init( const char *pszCodecName, int quality, qboolean preinit )
if( Q_strcmp( pszCodecName, voice.codec ) || voice.quality != quality )
{
Voice_Shutdown();
if( Q_strcmp( pszCodecName, VOICE_OPUS_CUSTOM_CODEC ))
{
Con_Printf( S_ERROR "Server requested unsupported codec: %s\n", pszCodecName );
return false;
}
voice.autogain.block_size = 128;
if( !Voice_InitCustomMode( ))

View File

@@ -25,7 +25,7 @@ typedef enum
T_COUNT
} cvartype_t;
const char *cvartypes[] = { NULL, "BOOL", "NUMBER", "LIST", "STRING" };
static const char *const cvartypes[] = { NULL, "BOOL", "NUMBER", "LIST", "STRING" };
typedef struct parserstate_s
{

View File

@@ -24,18 +24,27 @@ GNU General Public License for more details.
typedef struct
{
byte *data;
int cursize;
int maxsize;
byte *const data;
const int maxsize;
int cursize;
} cmdbuf_t;
qboolean cmd_wait;
cmdbuf_t cmd_text, filteredcmd_text;
byte cmd_text_buf[MAX_CMD_BUFFER];
byte filteredcmd_text_buf[MAX_CMD_BUFFER];
cmdalias_t *cmd_alias;
uint cmd_condition;
int cmd_condlevel;
static qboolean cmd_wait;
static byte cmd_text_buf[MAX_CMD_BUFFER];
static byte filteredcmd_text_buf[MAX_CMD_BUFFER];
static cmdbuf_t cmd_text =
{
.data = cmd_text_buf,
.maxsize = ARRAYSIZE( cmd_text_buf ),
};
static cmdbuf_t filteredcmd_text =
{
.data = filteredcmd_text_buf,
.maxsize = ARRAYSIZE( filteredcmd_text_buf ),
};
static cmdalias_t *cmd_alias;
static uint cmd_condition;
static int cmd_condlevel;
static qboolean cmd_currentCommandIsPrivileged;
static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPrivileged );
@@ -48,20 +57,6 @@ static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPr
=============================================================================
*/
/*
============
Cbuf_Init
============
*/
static void Cbuf_Init( void )
{
cmd_text.data = cmd_text_buf;
filteredcmd_text.data = filteredcmd_text_buf;
filteredcmd_text.maxsize = cmd_text.maxsize = MAX_CMD_BUFFER;
filteredcmd_text.cursize = cmd_text.cursize = 0;
}
/*
============
Cbuf_Clear
@@ -387,7 +382,7 @@ static void Cmd_Echo_f( void )
int i;
for( i = 1; i < Cmd_Argc(); i++ )
Con_Printf( "%s", Cmd_Argv( i ));
Con_Printf( "%s ", Cmd_Argv( i ));
Con_Printf( "\n" );
}
@@ -1387,8 +1382,6 @@ Cmd_Init
*/
void Cmd_Init( void )
{
Cbuf_Init();
cmd_functions = NULL;
cmd_condition = 0;
cmd_alias = NULL;

View File

@@ -52,12 +52,18 @@ GNU General Public License for more details.
#define DEFAULT_EXTERNAL_PALETTE "gfx/palette.pal"
// path to folders where placed all sounds
// path to sound files
#define DEFAULT_SOUNDPATH "sound/"
// path store saved games
// path to saved games
#define DEFAULT_SAVE_DIRECTORY "save/"
// path to download games
#define DEFAULT_DOWNLOADED_DIRECTORY "downloaded/"
// path to user mod directory
#define DEFAULT_CUSTOM_DIRECTORY "custom/"
// fallback to this skybox
#define DEFAULT_SKYBOX_NAME "desert"
@@ -72,7 +78,7 @@ GNU General Public License for more details.
#define XASH_ENGINE_NAME "Xash3D FWGS"
#define XASH_DEDICATED_SERVER_NAME "XashDS"
#define XASH_VERSION "0.20" // engine current version
#define XASH_VERSION "0.21" // engine current version
#define XASH_COMPAT_VERSION "0.99" // version we are based on
#endif//COM_STRINGS_H

View File

@@ -23,7 +23,7 @@ GNU General Public License for more details.
#include "client.h"
#include "library.h"
static const char *file_exts[] =
static const char *const file_exts[] =
{
// ban text files that don't make sense as resource
"cfg", "lst", "ini", "log",
@@ -759,25 +759,6 @@ void GAME_EXPORT COM_FreeFile( void *buffer )
free( buffer );
}
/*
=============
COM_NormalizeAngles
=============
*/
void COM_NormalizeAngles( vec3_t angles )
{
int i;
for( i = 0; i < 3; i++ )
{
if( angles[i] > 180.0f )
angles[i] -= 360.0f;
else if( angles[i] < -180.0f )
angles[i] += 360.0f;
}
}
/*
=============
pfnGetModelType
@@ -843,7 +824,7 @@ int GAME_EXPORT COM_CompareFileTime( const char *filename1, const char *filename
if( ft1 == -1 || ft2 == -1 )
return bRet;
*iCompare = Host_CompareFileTime( ft1, ft2 );
*iCompare = ft1 < ft2 ? -1 : ( ft1 > ft2 ? 1 : 0 );
bRet = 1;
}
@@ -898,18 +879,40 @@ qboolean COM_IsSafeFileToDownload( const char *filename )
char lwrfilename[4096];
const char *first, *last;
const char *ext;
size_t len;
int i;
if( !COM_CheckString( filename ))
return false;
ext = COM_FileExtension( lwrfilename );
ext = COM_FileExtension( filename );
len = Q_strlen( filename );
// only allow extensionless files that start with !MD5
if( !Q_strncmp( filename, "!MD5", 4 ) && ext[0] == 0 )
if( !Q_strncmp( filename, "!MD5", 4 ))
{
if( COM_CheckStringEmpty( ext ))
return false;
len = Q_strlen( filename );
if( len != 36 )
return false;
for( i = 4; i < len; i++ )
{
if(( filename[i] >= '0' && filename[i] <= '9' ) ||
( filename[i] >= 'A' && filename[i] <= 'F' ))
continue;
return false;
}
return true;
}
Q_strnlwr( filename, lwrfilename, sizeof( lwrfilename ));
ext = COM_FileExtension( lwrfilename );
if( Q_strpbrk( lwrfilename, "\\:~" ) || Q_strstr( lwrfilename, ".." ) )
return false;
@@ -1042,28 +1045,13 @@ void GAME_EXPORT pfnResetTutorMessageDecayData( void )
void Test_RunCommon( void )
{
char *file = (char *)"q asdf \"qwerty\" \"f \\\"f\" meowmeow\n// comment \"stuff ignored\"\nbark";
int len;
char buf[5];
Msg( "Checking COM_IsSafeFileToDownload...\n" );
Msg( "Checking COM_ParseFile...\n" );
file = COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len, NULL );
TASSERT( !Q_strcmp( buf, "q" ) && len == 1);
file = COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len, NULL );
TASSERT( !Q_strcmp( buf, "asdf" ) && len == 4);
file = COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len, NULL );
TASSERT( !Q_strcmp( buf, "qwer" ) && len == -1);
file = COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len, NULL );
TASSERT( !Q_strcmp( buf, "f \"f" ) && len == 4);
file = COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len, NULL );
TASSERT( !Q_strcmp( buf, "meow" ) && len == -1);
file = COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len, NULL );
TASSERT( !Q_strcmp( buf, "bark" ) && len == 4);
TASSERT_EQi( COM_IsSafeFileToDownload( "!MD5AAB5E8B307672DA86FBD10AC302BC732" ), true );
TASSERT_EQi( COM_IsSafeFileToDownload( "!MD56f1ffd8c96bd64c9c27955309f6ecfe6" ), false );
TASSERT_EQi( COM_IsSafeFileToDownload( "!MD5AAB5E8B307672DA86FBD10AC302B.exe" ), false );
TASSERT_EQi( COM_IsSafeFileToDownload( "!MD5/../../valve/resource/GameMenu.res" ), false );
TASSERT_EQi( COM_IsSafeFileToDownload( "not-a-virus-trust-me.bat" ), false );
TASSERT_EQi( COM_IsSafeFileToDownload( "a-texture.png" ), true );
}
#endif

View File

@@ -112,6 +112,9 @@ typedef enum
#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
@@ -165,6 +168,7 @@ extern convar_t sys_timescale;
extern convar_t cl_filterstuffcmd;
extern convar_t rcon_password;
extern convar_t hpk_custom_file;
extern convar_t con_gamemaps;
#define Mod_AllowMaterials() ( host_allow_materials.value != 0.0f && !FBitSet( host.features, ENGINE_DISABLE_HDTEXTURES ))
@@ -273,6 +277,9 @@ typedef enum bugcomp_e
// rewrites mod's attempts to write GoldSrc-specific messages into Xash protocol
// (new wrappers are added by request)
BUGCOMP_MESSAGE_REWRITE_FACILITY_FLAG = BIT( 1 ),
// makes sound with no attenuation spatialized, like in GoldSrc
BUGCOMP_SPATIALIZE_SOUND_WITH_ATTN_NONE = BIT( 2 ),
} bugcomp_t;
typedef struct host_parm_s
@@ -314,6 +321,11 @@ typedef struct host_parm_s
vec3_t player_mins[MAX_MAP_HULLS]; // 4 hulls allowed
vec3_t player_maxs[MAX_MAP_HULLS]; // 4 hulls allowed
// for CL_{Push,Pop}TraceBounds
vec3_t player_mins_backup[MAX_MAP_HULLS];
vec3_t player_maxs_backup[MAX_MAP_HULLS];
qboolean trace_bounds_pushed;
qboolean allow_console; // allow console in dev-mode or multiplayer game
qboolean allow_console_init; // initial value to allow the console
qboolean key_overstrike; // key overstrike mode
@@ -354,12 +366,49 @@ extern host_parm_t host;
typedef void (*xcommand_t)( void );
//
// zone.c
//
void Memory_Init( void );
void _Mem_Free( void *data, const char *filename, int fileline );
void *_Mem_Realloc( poolhandle_t poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline )
ALLOC_CHECK( 3 ) WARN_UNUSED_RESULT;
void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline )
ALLOC_CHECK( 2 ) MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
poolhandle_t _Mem_AllocPool( const char *name, const char *filename, int fileline )
WARN_UNUSED_RESULT;
void _Mem_FreePool( poolhandle_t *poolptr, const char *filename, int fileline );
void _Mem_EmptyPool( poolhandle_t poolptr, const char *filename, int fileline );
void _Mem_Check( const char *filename, int fileline );
qboolean Mem_IsAllocatedExt( poolhandle_t poolptr, void *data );
void Mem_PrintList( size_t minallocationsize );
void Mem_PrintStats( void );
#define Mem_Malloc( pool, size ) _Mem_Alloc( pool, size, false, __FILE__, __LINE__ )
#define Mem_Calloc( pool, size ) _Mem_Alloc( pool, size, true, __FILE__, __LINE__ )
#define Mem_Realloc( pool, ptr, size ) _Mem_Realloc( pool, ptr, size, true, __FILE__, __LINE__ )
#define Mem_Free( mem ) _Mem_Free( mem, __FILE__, __LINE__ )
#define Mem_AllocPool( name ) _Mem_AllocPool( name, __FILE__, __LINE__ )
#define Mem_FreePool( pool ) _Mem_FreePool( pool, __FILE__, __LINE__ )
#define Mem_EmptyPool( pool ) _Mem_EmptyPool( pool, __FILE__, __LINE__ )
#define Mem_IsAllocated( mem ) Mem_IsAllocatedExt( NULL, mem )
#define Mem_Check() _Mem_Check( __FILE__, __LINE__ )
//
// filesystem_engine.c
//
void FS_Init( const char *basedir );
void FS_Shutdown( void );
void *FS_GetNativeObject( const char *obj );
int FS_Close( file_t *file );
search_t *FS_Search( const char *pattern, int caseinsensitive, int gamedironly )
MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
file_t *FS_Open( const char *filepath, const char *mode, qboolean gamedironly )
MALLOC_LIKE( FS_Close, 1 ) WARN_UNUSED_RESULT;
byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly )
MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
byte *FS_LoadDirectFile( const char *path, fs_offset_t *filesizeptr )
MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
//
// cmd.c
@@ -392,30 +441,6 @@ void Cmd_ExecuteString( const char *text );
void Cmd_ForwardToServer( void );
void Cmd_Escape( char *newCommand, const char *oldCommand, int len );
//
// zone.c
//
void Memory_Init( void );
void *_Mem_Realloc( poolhandle_t poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline ) ALLOC_CHECK( 3 );
void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline ) ALLOC_CHECK( 2 );
poolhandle_t _Mem_AllocPool( const char *name, const char *filename, int fileline );
void _Mem_FreePool( poolhandle_t *poolptr, const char *filename, int fileline );
void _Mem_EmptyPool( poolhandle_t poolptr, const char *filename, int fileline );
void _Mem_Free( void *data, const char *filename, int fileline );
void _Mem_Check( const char *filename, int fileline );
qboolean Mem_IsAllocatedExt( poolhandle_t poolptr, void *data );
void Mem_PrintList( size_t minallocationsize );
void Mem_PrintStats( void );
#define Mem_Malloc( pool, size ) _Mem_Alloc( pool, size, false, __FILE__, __LINE__ )
#define Mem_Calloc( pool, size ) _Mem_Alloc( pool, size, true, __FILE__, __LINE__ )
#define Mem_Realloc( pool, ptr, size ) _Mem_Realloc( pool, ptr, size, true, __FILE__, __LINE__ )
#define Mem_Free( mem ) _Mem_Free( mem, __FILE__, __LINE__ )
#define Mem_AllocPool( name ) _Mem_AllocPool( name, __FILE__, __LINE__ )
#define Mem_FreePool( pool ) _Mem_FreePool( pool, __FILE__, __LINE__ )
#define Mem_EmptyPool( pool ) _Mem_EmptyPool( pool, __FILE__, __LINE__ )
#define Mem_IsAllocated( mem ) Mem_IsAllocatedExt( NULL, mem )
#define Mem_Check() _Mem_Check( __FILE__, __LINE__ )
//
// imagelib
@@ -426,10 +451,10 @@ void Image_Setup( void );
void Image_Init( void );
void Image_Shutdown( void );
void Image_AddCmdFlags( uint flags );
rgbdata_t *FS_LoadImage( const char *filename, const byte *buffer, size_t size );
qboolean FS_SaveImage( const char *filename, rgbdata_t *pix );
rgbdata_t *FS_CopyImage( rgbdata_t *in );
void FS_FreeImage( rgbdata_t *pack );
rgbdata_t *FS_LoadImage( const char *filename, const byte *buffer, size_t size ) MALLOC_LIKE( FS_FreeImage, 1 ) WARN_UNUSED_RESULT;
qboolean FS_SaveImage( const char *filename, rgbdata_t *pix );
rgbdata_t *FS_CopyImage( rgbdata_t *in ) MALLOC_LIKE( FS_FreeImage, 1 ) WARN_UNUSED_RESULT;
extern const bpc_desc_t PFDesc[]; // image get pixelformat
qboolean Image_Process( rgbdata_t **pix, int width, int height, uint flags, float reserved );
void Image_PaletteHueReplace( byte *palSrc, int newHue, int start, int end, int pal_size );
@@ -484,15 +509,15 @@ typedef struct
//
void Sound_Init( void );
void Sound_Shutdown( void );
wavdata_t *FS_LoadSound( const char *filename, const byte *buffer, size_t size );
void FS_FreeSound( wavdata_t *pack );
stream_t *FS_OpenStream( const char *filename );
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 );
void FS_FreeStream( stream_t *stream );
qboolean Sound_Process( wavdata_t **wav, int rate, int width, uint flags );
qboolean Sound_Process( wavdata_t **wav, int rate, int width, int channels, uint flags );
uint Sound_GetApproxWavePlayLen( const char *filepath );
qboolean Sound_SupportedFileFormat( const char *fileext );
@@ -504,7 +529,6 @@ typedef void( *pfnChangeGame )( const char *progname );
qboolean Host_IsQuakeCompatible( void );
void EXPORT Host_Shutdown( void );
int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGame, pfnChangeGame func );
int Host_CompareFileTime( int ft1, int ft2 );
void Host_EndGame( qboolean abort, const char *message, ... ) _format( 2 );
void Host_AbortCurrentFrame( void ) NORETURN;
void Host_WriteServerConfig( const char *name );
@@ -556,7 +580,7 @@ qboolean SV_Active( void );
char *COM_MemFgets( byte *pMemFile, int fileSize, int *filePos, char *pBuffer, int bufferSize );
void COM_HexConvert( const char *pszInput, int nInputLength, byte *pOutput );
int COM_SaveFile( const char *filename, const void *data, int len );
byte* COM_LoadFileForMe( const char *filename, int *pLength );
byte *COM_LoadFileForMe( const char *filename, int *pLength ) MALLOC_LIKE( free, 1 );
qboolean COM_IsSafeFileToDownload( const char *filename );
cvar_t *pfnCVarGetPointer( const char *szVarName );
int pfnDrawConsoleString( int x, int y, char *string );
@@ -646,6 +670,15 @@ void HPAK_FlushHostQueue( void );
#define INPUT_DEVICE_JOYSTICK (1<<2)
#define INPUT_DEVICE_VR (1<<3)
typedef enum connprotocol_e
{
PROTO_CURRENT = 0, // Xash3D 49
PROTO_LEGACY, // Xash3D 48
PROTO_QUAKE, // Quake 15
PROTO_GOLDSRC, // GoldSrc 48
} connprotocol_t;
// shared calls
struct physent_s;
struct sv_client_s;
@@ -656,10 +689,9 @@ qboolean CL_IsThirdPerson( void );
qboolean CL_IsIntermission( void );
qboolean CL_Initialized( void );
char *CL_Userinfo( void );
void CL_LegacyUpdateInfo( void );
void CL_CharEvent( int key );
qboolean CL_DisableVisibility( void );
byte *COM_LoadFile( const char *filename, int usehunk, int *pLength );
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 );
struct cmdalias_s *Cmd_AliasGetList( void );
@@ -737,13 +769,34 @@ void UI_ShowConnectionWarning( void );
void Cmd_Null_f( void );
void Rcon_Print( host_redirect_t *rd, const char *pMsg );
qboolean COM_ParseVector( char **pfile, float *v, size_t size );
void COM_NormalizeAngles( vec3_t angles );
int COM_FileSize( const char *filename );
void COM_FreeFile( void *buffer );
int COM_CompareFileTime( const char *filename1, const char *filename2, int *iCompare );
char *va( const char *format, ... ) _format( 1 );
qboolean CRC32_MapFile( dword *crcvalue, const char *filename, qboolean multiplayer );
static inline void COM_NormalizeAngles( vec3_t angles )
{
int i;
for( i = 0; i < 3; i++ )
{
if( angles[i] > 180.0f )
angles[i] -= 360.0f;
else if( angles[i] < -180.0f )
angles[i] += 360.0f;
}
}
#if !XASH_DEDICATED
connprotocol_t CL_Protocol( void );
#else
static inline connprotocol_t CL_Protocol( void )
{
return PROTO_CURRENT;
}
#endif
static inline qboolean Host_IsLocalGame( void )
{
if( SV_Active( ))
@@ -793,6 +846,16 @@ void NET_MasterClear( void );
void NET_MasterShutdown( void );
qboolean NET_GetMaster( netadr_t from, uint *challenge, double *last_heartbeat );
//
// munge.c
//
void COM_Munge( byte *data, size_t len, int seq );
void COM_UnMunge( byte *data, size_t len, int seq );
void COM_Munge2( byte *data, size_t len, int seq );
void COM_UnMunge2( byte *data, size_t len, int seq );
void COM_Munge3( byte *data, size_t len, int seq );
void COM_UnMunge3( byte *data, size_t len, int seq );
//
// sounds.c
//

View File

@@ -18,8 +18,6 @@ GNU General Public License for more details.
#include "const.h"
#include "kbutton.h"
extern convar_t con_gamemaps;
#define CON_MAXCMDS 4096 // auto-complete intermediate list
typedef struct autocomplete_list_s
@@ -1012,13 +1010,14 @@ int GAME_EXPORT Cmd_CheckMapsList( int fRefresh )
return Cmd_CheckMapsList_R( fRefresh, true );
}
autocomplete_list_t cmd_list[] =
static const autocomplete_list_t cmd_list[] =
{
{ "map_background", 1, Cmd_GetMapList },
{ "changelevel2", 1, Cmd_GetMapList },
{ "changelevel", 1, Cmd_GetMapList },
{ "playdemo", 1, Cmd_GetDemoList, },
{ "timedemo", 1, Cmd_GetDemoList, },
{ "listdemo", 1, Cmd_GetDemoList, },
{ "playvol", 1, Cmd_GetSoundList },
{ "hpkval", 1, Cmd_GetCustomList },
{ "hpklist", 1, Cmd_GetCustomList },
@@ -1074,7 +1073,7 @@ for various cmds
*/
static qboolean Cmd_AutocompleteName( const char *source, int arg, char *buffer, size_t bufsize )
{
autocomplete_list_t *list;
const autocomplete_list_t *list;
for( list = cmd_list; list->name; list++ )
{
@@ -1201,7 +1200,7 @@ void Con_CompleteCommand( field_t *field )
if( !con.matchCount ) return; // no matches
memcpy( &temp, con.completionField, sizeof( field_t ) );
temp = *con.completionField;
// autocomplete second arg
if( (Cmd_Argc() >= 2) || ((Cmd_Argc() == 1) && nextcmd) )

View File

@@ -92,7 +92,7 @@ static void Sys_StackTrace( PEXCEPTION_POINTERS pInfo )
STACKFRAME64 stackframe;
DWORD image;
memcpy( &context, pInfo->ContextRecord, sizeof( CONTEXT ));
context = *pInfo->ContextRecord;
options = SymGetOptions();
options |= SYMOPT_DEBUG;

View File

@@ -18,17 +18,17 @@ GNU General Public License for more details.
#include "base_cmd.h"
#include "eiface.h" // ARRAYSIZE
convar_t *cvar_vars = NULL; // head of list
static convar_t *cvar_vars = NULL; // head of list
CVAR_DEFINE_AUTO( cmd_scripting, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED, "enable simple condition checking and variable operations" );
#ifdef HACKS_RELATED_HLMODS
typedef struct cvar_filter_quirks_s
{
const char *gamedir; // gamedir to enable for
const char *cvars; // list of cvars should be excluded from filter
} cvar_filter_quirks_t;
static cvar_filter_quirks_t cvar_filter_quirks[] =
#ifdef HACKS_RELATED_HLMODS
static const cvar_filter_quirks_t cvar_filter_quirks[] =
{
// EXAMPLE:
//{
@@ -44,10 +44,10 @@ static cvar_filter_quirks_t cvar_filter_quirks[] =
"cl_dodmusic" // Day of Defeat Beta 1.3 cvar
},
};
static cvar_filter_quirks_t *cvar_active_filter_quirks = NULL;
#endif
static const cvar_filter_quirks_t *cvar_active_filter_quirks = NULL;
CVAR_DEFINE_AUTO( cl_filterstuffcmd, "1", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "filter commands coming from server" );
/*
@@ -70,15 +70,14 @@ find the specified variable by name
*/
convar_t *Cvar_FindVarExt( const char *var_name, int ignore_group )
{
// TODO: ignore group for cvar
#if defined(XASH_HASHED_VARS)
return (convar_t *)BaseCmd_Find( HM_CVAR, var_name );
#else
convar_t *var;
convar_t *var;
if( !var_name )
return NULL;
#if defined(XASH_HASHED_VARS) // TODO: ignore_group
var = BaseCmd_Find( HM_CVAR, var_name );
#else
for( var = cvar_vars; var; var = var->next )
{
if( ignore_group && FBitSet( ignore_group, var->flags ))
@@ -87,9 +86,13 @@ convar_t *Cvar_FindVarExt( const char *var_name, int ignore_group )
if( !Q_stricmp( var_name, var->name ))
return var;
}
return NULL;
#endif
// HACKHACK: HL25 compatibility
if( !var && !Q_stricmp( var_name, "gl_widescreen_yfov" ))
var = Cvar_FindVarExt( "r_adjust_fov", ignore_group );
return var;
}
/*
@@ -230,7 +233,7 @@ static const char *Cvar_ValidateString( convar_t *var, const char *value )
if( !COM_CheckStringEmpty( szNew ) ) Q_strncpy( szNew, "empty", sizeof( szNew ));
}
if( FBitSet( var->flags, FCVAR_NOEXTRAWHITEPACE ))
if( FBitSet( var->flags, FCVAR_NOEXTRAWHITESPACE ))
{
char *szVal = szNew;
int len = 0;
@@ -272,6 +275,15 @@ static qboolean Cvar_ValidateVarName( const char *s, qboolean isvalue )
return true;
}
static void Cvar_Free( convar_t *var )
{
freestring( var->name );
freestring( var->string );
freestring( var->def_string );
freestring( var->desc );
Mem_Free( var );
}
/*
============
Cvar_UnlinkVar
@@ -311,17 +323,13 @@ static int Cvar_UnlinkVar( const char *var_name, int group )
#endif
// unlink variable from list
freestring( var->string );
*prev = var->next;
// only allocated cvars can throw these fields
if( FBitSet( var->flags, FCVAR_ALLOCATED ))
{
freestring( var->name );
freestring( var->def_string );
freestring( var->desc );
Mem_Free( var );
}
Cvar_Free( var );
else
freestring( var->string );
count++;
}
@@ -610,7 +618,7 @@ static convar_t *Cvar_Set2( const char *var_name, const char *value )
return Cvar_Get( var_name, value, FCVAR_USER_CREATED, NULL );
}
else
{
{
if( !Cmd_CurrentCommandIsPrivileged( ))
{
if( FBitSet( var->flags, FCVAR_PRIVILEGED ))
@@ -966,7 +974,6 @@ static qboolean Cvar_ShouldSetCvar( convar_t *v, qboolean isPrivileged )
if( cl_filterstuffcmd.value <= 0.0f )
return true;
#ifdef HACKS_RELATED_HLMODS
// check if game-specific filter exceptions should be applied
// TODO: for cmd exceptions, make generic function
if( cvar_active_filter_quirks )
@@ -997,7 +1004,6 @@ static qboolean Cvar_ShouldSetCvar( convar_t *v, qboolean isPrivileged )
}
}
}
#endif
if( FBitSet( v->flags, FCVAR_FILTERABLE ))
return false;
@@ -1217,6 +1223,20 @@ static void Cvar_List_f( void )
Con_Printf( "\n%i cvars\n", count );
}
static qboolean Cvar_ValidateUnlinkGroup( int group )
{
if( FBitSet( group, FCVAR_EXTDLL ) && !Cvar_VariableInteger( "host_gameloaded" ))
return false;
if( FBitSet( group, FCVAR_CLIENTDLL ) && !Cvar_VariableInteger( "host_clientloaded" ))
return false;
if( FBitSet( group, FCVAR_GAMEUIDLL ) && !Cvar_VariableInteger( "host_gameuiloaded" ))
return false;
return true;
}
/*
============
Cvar_Unlink
@@ -1228,19 +1248,95 @@ void Cvar_Unlink( int group )
{
int count;
if( Cvar_VariableInteger( "host_gameloaded" ) && FBitSet( group, FCVAR_EXTDLL ))
return;
if( Cvar_VariableInteger( "host_clientloaded" ) && FBitSet( group, FCVAR_CLIENTDLL ))
return;
if( Cvar_VariableInteger( "host_gameuiloaded" ) && FBitSet( group, FCVAR_GAMEUIDLL ))
if( !Cvar_ValidateUnlinkGroup( group ))
return;
count = Cvar_UnlinkVar( NULL, group );
Con_Reportf( "unlink %i cvars\n", count );
}
pending_cvar_t *Cvar_PrepareToUnlink( int group )
{
pending_cvar_t *list = NULL;
pending_cvar_t *tail = NULL;
convar_t *cv;
for( cv = cvar_vars; cv != NULL; cv = cv->next )
{
size_t namelen;
pending_cvar_t *p;
if( !FBitSet( cv->flags, group ))
continue;
namelen = Q_strlen( cv->name ) + 1;
p = Mem_Malloc( host.mempool, sizeof( *list ) + namelen );
p->next = NULL;
p->cv_cur = cv;
p->cv_next = cv->next;
p->cv_allocated = FBitSet( cv->flags, FCVAR_ALLOCATED ) ? true : false;
Q_strncpy( p->cv_name, cv->name, namelen );
if( list == NULL )
list = p;
else
tail->next = p;
tail = p;
}
return list;
}
void Cvar_UnlinkPendingCvars( pending_cvar_t *list )
{
int count = 0;
while( list != NULL )
{
pending_cvar_t *next = list->next;
convar_t *cv_prev, *cv;
for( cv_prev = NULL, cv = cvar_vars; cv != NULL; cv_prev = cv, cv = cv->next )
{
if( cv == list->cv_cur )
break;
}
if( cv == NULL )
{
Con_Reportf( "%s: can't find %s in variable list\n", __func__, list->cv_name );
Mem_Free( list );
list = next;
continue;
}
// unlink cvar from list
BaseCmd_Remove( HM_CVAR, list->cv_name );
if( cv_prev != NULL )
cv_prev->next = list->cv_next;
else cvar_vars = list->cv_next;
if( list->cv_allocated )
Cvar_Free( list->cv_cur );
else
{
// TODO: can't free cvar string here because
// it's not safe to access cv_cur and
// can't save string pointer because it could've been changed
// and pointer to it is already lost
// freestring( list->cv_string );
}
// now free pending cvar
Mem_Free( list );
list = next;
count++;
}
Con_Reportf( "unlink %i cvars\n", count );
}
/*
============
Cvar_Init

View File

@@ -18,45 +18,18 @@ GNU General Public License for more details.
#include "cvardef.h"
#ifdef XASH_64BIT
#define CVAR_SENTINEL 0xDEADBEEFDEADBEEF
#else
#define CVAR_SENTINEL 0xDEADBEEF
#endif
#define CVAR_CHECK_SENTINEL( cv ) ((uintptr_t)(cv)->next == CVAR_SENTINEL)
// NOTE: if this is changed, it must be changed in cvardef.h too
typedef struct convar_s
// As some mods dynamically allocate cvars and free them without notifying the engine
// let's construct a list of cvars that must be removed
typedef struct pending_cvar_s
{
// this part shared with cvar_t
char *name;
char *string;
int flags;
float value;
struct convar_s *next;
struct pending_cvar_s *next;
// this part unique for convar_t
char *desc; // variable descrition info
char *def_string; // keep pointer to initial value
} convar_t;
convar_t *cv_cur; // preserve the data that might get freed
convar_t *cv_next;
qboolean cv_allocated; // if it's allocated by us, it's safe to access cv_cur
char cv_name[];
} pending_cvar_t;
// cvar internal flags
#define FCVAR_RENDERINFO (1<<16) // save to a seperate config called video.cfg
#define FCVAR_READ_ONLY (1<<17) // cannot be set by user at all, and can't be requested by CvarGetPointer from game dlls
#define FCVAR_EXTENDED (1<<18) // this is convar_t (sets on registration)
#define FCVAR_ALLOCATED (1<<19) // this convar_t is fully dynamic allocated (include description)
#define FCVAR_VIDRESTART (1<<20) // recreate the window is cvar with this flag was changed
#define FCVAR_TEMPORARY (1<<21) // these cvars holds their values and can be unlink in any time
#define FCVAR_MOVEVARS (1<<22) // this cvar is a part of movevars_t struct that shared between client and server
#define FCVAR_USER_CREATED (1<<23) // created by a set command (dll's used)
#define CVAR_DEFINE( cv, cvname, cvstr, cvflags, cvdesc ) \
convar_t cv = { (char*)cvname, (char*)cvstr, cvflags, 0.0f, (void *)CVAR_SENTINEL, (char*)cvdesc, NULL }
#define CVAR_DEFINE_AUTO( cv, cvstr, cvflags, cvdesc ) \
CVAR_DEFINE( cv, #cv, cvstr, cvflags, cvdesc )
#ifndef REF_DLL
cvar_t *Cvar_GetList( void );
#define Cvar_FindVar( name ) Cvar_FindVarExt( name, 0 )
convar_t *Cvar_FindVarExt( const char *var_name, int ignore_group );
@@ -81,6 +54,8 @@ qboolean Cvar_CommandWithPrivilegeCheck( convar_t *v, qboolean isPrivileged );
void Cvar_Init( void );
void Cvar_PostFSInit( void );
void Cvar_Unlink( int group );
#endif // REF_DLL
pending_cvar_t *Cvar_PrepareToUnlink( int group );
void Cvar_UnlinkPendingCvars( pending_cvar_t *pending_cvars );
#endif//CVAR_H

View File

@@ -134,11 +134,6 @@ void GAME_EXPORT S_StopSound(int entnum, int channel, const char *soundname)
}
int S_GetCurrentStaticSounds( soundlist_t *pout, int size )
{
return 0;
}
int GAME_EXPORT CL_GetMaxClients( void )
{
return 0;

View File

@@ -27,6 +27,31 @@ fs_globals_t *FI;
static pfnCreateInterface_t fs_pfnCreateInterface;
static HINSTANCE fs_hInstance;
search_t *FS_Search( const char *pattern, int caseinsensitive, int gamedironly )
{
return g_fsapi.Search( pattern, caseinsensitive, gamedironly );
}
int FS_Close( file_t *file )
{
return g_fsapi.Close( file );
}
file_t *FS_Open( const char *filepath, const char *mode, qboolean gamedironly )
{
return g_fsapi.Open( filepath, mode, gamedironly );
}
byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly )
{
return g_fsapi.LoadFile( path, filesizeptr, gamedironly );
}
byte *FS_LoadDirectFile( const char *path, fs_offset_t *filesizeptr )
{
return g_fsapi.LoadDirectFile( path, filesizeptr );
}
static void COM_StripDirectorySlash( char *pname )
{
size_t len;
@@ -59,7 +84,7 @@ static void FS_Path_f_( void )
FS_Path_f();
}
static fs_interface_t fs_memfuncs =
static const fs_interface_t fs_memfuncs =
{
Con_Printf,
Con_DPrintf,
@@ -221,7 +246,13 @@ void FS_Init( const char *basedir )
COM_StripDirectorySlash( rodir );
if( !Sys_GetParmFromCmdLine( "-game", gamedir ))
Q_strncpy( gamedir, basedir, sizeof( gamedir )); // gamedir == basedir
{
char *env = getenv( "XASH3D_GAME" );
if( env )
Q_strncpy( gamedir, env, sizeof( gamedir ));
else
Q_strncpy( gamedir, basedir, sizeof( gamedir )); // gamedir == basedir
}
FS_LoadProgs();

View File

@@ -40,7 +40,7 @@ GNU General Public License for more details.
#include "render_api.h" // decallist_t
#include "tests.h"
pfnChangeGame pChangeGame = NULL;
static pfnChangeGame pChangeGame = NULL;
host_parm_t host; // host parms
#ifdef XASH_ENGINE_TESTS
@@ -49,8 +49,8 @@ struct tests_stats_s tests_stats;
CVAR_DEFINE( host_developer, "developer", "0", FCVAR_FILTERABLE, "engine is in development-mode" );
CVAR_DEFINE_AUTO( sys_timescale, "1.0", FCVAR_FILTERABLE, "scale frame time" );
CVAR_DEFINE_AUTO( sys_ticrate, "100", FCVAR_SERVER, "framerate in dedicated mode" );
static CVAR_DEFINE_AUTO( sys_ticrate, "100", FCVAR_SERVER, "framerate in dedicated mode" );
static CVAR_DEFINE_AUTO( host_serverstate, "0", FCVAR_READ_ONLY, "displays current server state" );
static CVAR_DEFINE_AUTO( host_gameloaded, "0", FCVAR_READ_ONLY, "inidcates a loaded game.dll" );
static CVAR_DEFINE_AUTO( host_clientloaded, "0", FCVAR_READ_ONLY, "inidcates a loaded client.dll" );
@@ -69,13 +69,14 @@ typedef struct feature_message_s
const char *arg;
} feature_message_t;
static feature_message_t bugcomp_features[] =
static const feature_message_t bugcomp_features[] =
{
{ BUGCOMP_PENTITYOFENTINDEX_FLAG, "pfnPEntityOfEntIndex bugfix revert", "peoei" },
{ BUGCOMP_MESSAGE_REWRITE_FACILITY_FLAG, "GoldSrc Message Rewrite Facility", "gsmrf" },
{ BUGCOMP_SPATIALIZE_SOUND_WITH_ATTN_NONE, "spatialize sounds with zero attenuation", "sp_attn_none" },
};
static feature_message_t engine_features[] =
static const feature_message_t engine_features[] =
{
{ ENGINE_WRITE_LARGE_COORD, "Big World Support" },
{ ENGINE_QUAKE_COMPATIBLE, "Quake Compatibility" },
@@ -199,19 +200,6 @@ static void Sys_PrintUsage( const char *exename )
Sys_Quit();
}
int Host_CompareFileTime( int ft1, int ft2 )
{
if( ft1 < ft2 )
{
return -1;
}
else if( ft1 > ft2 )
{
return 1;
}
return 0;
}
void Host_ShutdownServer( void )
{
SV_Shutdown( "Server was killed\n" );
@@ -222,7 +210,7 @@ void Host_ShutdownServer( void )
Host_PrintEngineFeatures
================
*/
static void Host_PrintFeatures( uint32_t flags, const char *s, feature_message_t *features, size_t size )
static void Host_PrintFeatures( uint32_t flags, const char *s, const feature_message_t *features, size_t size )
{
size_t i;
@@ -245,8 +233,20 @@ void Host_ValidateEngineFeatures( uint32_t features )
uint32_t mask = ENGINE_FEATURES_MASK;
#if !XASH_DEDICATED
if( !Host_IsDedicated( ) && cls.legacymode )
mask = ENGINE_LEGACY_FEATURES_MASK;
if( !Host_IsDedicated( ))
{
switch( cls.legacymode )
{
case PROTO_CURRENT:
break;
case PROTO_LEGACY:
mask = ENGINE_LEGACY_FEATURES_MASK;
break;
default:
mask = 0;
break;
}
}
#endif
// don't allow unsupported bits
@@ -1028,8 +1028,8 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
}
#endif
// always enable console for Quake
if( !host.allow_console && ( Sys_CheckParm( "-console" ) || !Q_strnicmp( exename, "quake", 5 )))
// always enable console for Quake and dedicated
if( !host.allow_console && ( Host_IsDedicated() || Sys_CheckParm( "-console" ) || !Q_strnicmp( exename, "quake", 5 )))
host.allow_console = true;
// member console allowing
@@ -1071,6 +1071,9 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
Host_RunTests( 0 );
#endif
#if XASH_DEDICATED
Platform_SetupSigtermHandling();
#endif
Platform_Init( Host_IsDedicated( ) || developer >= DEV_EXTENDED );
FS_Init( basedir );
@@ -1078,7 +1081,16 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
// print current developer level to simplify processing users feedback
if( developer > 0 )
Con_Printf( "Developer level: ^3%i\n", developer );
{
int i;
Con_Printf( "Program args: " S_YELLOW );
for( i = 0; i < host.argc; i++ )
Con_Printf( "%s ", host.argv[i] );
Con_Printf( S_DEFAULT "\n" );
Con_Printf( "Developer level: " S_YELLOW "%i" S_DEFAULT "\n", developer );
}
host.bugcomp = Host_CheckBugcomp();

View File

@@ -67,7 +67,7 @@ typedef struct dresource_s
} dresource_t;
#pragma pack( pop )
STATIC_ASSERT( sizeof( dresource_t ) == 136, "invalid dresource_t size, HPAKs won't be compatible (no custom logo in multiplayer!)" );
STATIC_CHECK_SIZEOF( dresource_t, 136, 136 );
typedef struct
{
@@ -76,6 +76,8 @@ typedef struct
int infotableofs;
} hpak_header_t;
STATIC_CHECK_SIZEOF( hpak_header_t, 12, 12 );
typedef struct
{
dresource_t resource;
@@ -83,6 +85,8 @@ typedef struct
int disksize;
} hpak_lump_t;
STATIC_CHECK_SIZEOF( hpak_lump_t, 144, 144 );
typedef struct
{
int count;

View File

@@ -108,12 +108,13 @@ typedef struct imglib_s
enum
{
LUMP_NORMAL = 0, // no alpha
LUMP_MASKED, // 1-bit alpha channel masked texture
LUMP_GRADIENT, // gradient image (decals)
LUMP_EXTENDED, // bmp images have extened palette with alpha-channel
LUMP_HALFLIFE, // get predefined half-life palette
LUMP_QUAKE1 // get predefined quake palette
LUMP_NORMAL = 0, // no alpha
LUMP_MASKED, // 1-bit alpha channel masked texture
LUMP_GRADIENT, // gradient image (decals)
LUMP_EXTENDED, // bmp images have extened palette with alpha-channel
LUMP_HALFLIFE, // get predefined half-life palette
LUMP_QUAKE1, // get predefined quake palette
LUMP_TEXGAMMA, // apply texgamma on top of palette, for half-life mips
};
enum

View File

@@ -110,7 +110,7 @@ void Image_Reset( void )
image.size = 0;
}
static rgbdata_t *ImagePack( void )
static MALLOC_LIKE( FS_FreeImage, 1 ) rgbdata_t *ImagePack( void )
{
rgbdata_t *pack;
@@ -547,7 +547,7 @@ static void Test_CheckImage( const char *name, rgbdata_t *rgb )
TASSERT( load->size == rgb->size )
TASSERT( memcmp(load->buffer, rgb->buffer, rgb->size ) == 0 )
Mem_Free( load );
FS_FreeImage( load );
}
void Test_RunImagelib( void )

View File

@@ -174,8 +174,8 @@ byte *Image_Copy( size_t size )
{
byte *out;
out = Mem_Malloc( host.imagepool, size );
memcpy( out, image.tempbuffer, size );
out = Mem_Realloc( host.imagepool, image.tempbuffer, size );
image.tempbuffer = NULL;
return out;
}
@@ -293,9 +293,18 @@ static void Image_SetPalette( const byte *pal, uint *d_table )
case LUMP_NORMAL:
for( i = 0; i < 256; i++ )
{
rgba[0] = TextureToGamma( pal[i*3+0] );
rgba[1] = TextureToGamma( pal[i*3+1] );
rgba[2] = TextureToGamma( pal[i*3+2] );
memcpy( rgba, &pal[i * 3], 3 );
rgba[3] = 0xFF;
memcpy( &uirgba, rgba, sizeof( uirgba ));
d_table[i] = uirgba;
}
break;
case LUMP_TEXGAMMA:
for( i = 0; i < 256; i++ )
{
rgba[0] = TextureToGamma( pal[i * 3 + 0] );
rgba[1] = TextureToGamma( pal[i * 3 + 1] );
rgba[2] = TextureToGamma( pal[i * 3 + 2] );
rgba[3] = 0xFF;
memcpy( &uirgba, rgba, sizeof( uirgba ));
d_table[i] = uirgba;
@@ -1374,20 +1383,20 @@ static qboolean Image_RemapInternal( rgbdata_t *pic, int topColor, int bottomCol
return true;
}
qboolean Image_Process(rgbdata_t **pix, int width, int height, uint flags, float reserved )
qboolean Image_Process( rgbdata_t **pix, int width, int height, uint flags, float reserved )
{
rgbdata_t *pic = *pix;
qboolean result = true;
byte *out;
// check for buffers
if( !pic || !pic->buffer )
if( unlikely( !pic || !pic->buffer ))
{
image.force_flags = 0;
return false;
}
if( !flags )
if( unlikely( !flags ))
{
// clear any force flags
image.force_flags = 0;
@@ -1432,7 +1441,7 @@ qboolean Image_Process(rgbdata_t **pix, int width, int height, uint flags, float
pic->width = w, pic->height = h;
pic->size = w * h * PFDesc[pic->type].bpp;
Mem_Free( pic->buffer ); // free original image buffer
pic->buffer = Image_Copy( pic->size ); // unzone buffer (don't touch image.tempbuffer)
pic->buffer = Image_Copy( pic->size ); // unzone buffer
}
else
{

View File

@@ -427,8 +427,18 @@ qboolean Image_LoadMIP( const char *name, const byte *buffer, fs_offset_t filesi
}
if( pal_type == PAL_QUAKE1 )
{
SetBits( image.flags, IMAGE_QUAKEPAL );
rendermode = LUMP_NORMAL;
// if texture was converted from quake to half-life with no palette changes
// then applying texgamma might make it too dark or even outright broken
rendermode = LUMP_NORMAL;
}
else
{
// half-life mips need texgamma applied
rendermode = LUMP_TEXGAMMA;
}
}
Image_GetPaletteLMP( pal, rendermode );

View File

@@ -23,9 +23,8 @@ GNU General Public License for more details.
#include "build.h"
#include "common.h"
#define E_GAME "XASH3D_GAME" // default env dir to start from
#ifndef XASH_GAMEDIR
#define XASH_GAMEDIR "valve"
#define XASH_GAMEDIR "valve" // !!! Replace with your default (base) game directory !!!
#endif
#if XASH_WIN32
@@ -47,12 +46,7 @@ static void Sys_ChangeGame( const char *progname )
static int Sys_Start( void )
{
const char *game = getenv( E_GAME );
if( !game )
game = XASH_GAMEDIR;
Q_strncpy( szGameDir, game, sizeof( szGameDir ));
Q_strncpy( szGameDir, XASH_GAMEDIR, sizeof( szGameDir ));
#if XASH_EMSCRIPTEN
#ifdef EMSCRIPTEN_LIB_FS
@@ -73,7 +67,7 @@ static int Sys_Start( void )
IOS_LaunchDialog();
#endif
return Host_Main( szArgc, szArgv, game, 0, Sys_ChangeGame );
return Host_Main( szArgc, szArgv, szGameDir, 0, Sys_ChangeGame );
}
int main( int argc, char **argv )

View File

@@ -21,6 +21,7 @@ typedef struct master_s
struct master_s *next;
qboolean sent; // TODO: get rid of this internal state
qboolean save;
qboolean v6only;
string address;
netadr_t adr; // temporary, rewritten after each send
@@ -45,7 +46,7 @@ NET_GetMasterHostByName
*/
static net_gai_state_t NET_GetMasterHostByName( master_t *m )
{
net_gai_state_t res = NET_StringToAdrNB( m->address, &m->adr );
net_gai_state_t res = NET_StringToAdrNB( m->address, &m->adr, m->v6only );
if( res == NET_EAI_OK )
return res;
@@ -251,7 +252,7 @@ NET_AddMaster
Add master to the list
========================
*/
static void NET_AddMaster( const char *addr, qboolean save )
static void NET_AddMaster( const char *addr, qboolean save, qboolean v6only )
{
master_t *master, *last;
@@ -261,10 +262,11 @@ static void NET_AddMaster( const char *addr, qboolean save )
return;
}
master = Mem_Malloc( host.mempool, sizeof( master_t ) );
master = Mem_Malloc( host.mempool, sizeof( *master ) );
Q_strncpy( master->address, addr, sizeof( master->address ));
master->sent = false;
master->save = save;
master->v6only = v6only;
master->next = NULL;
master->adr.type = 0;
@@ -283,7 +285,7 @@ static void NET_AddMaster_f( void )
return;
}
NET_AddMaster( Cmd_Argv( 1 ), true ); // save them into config
NET_AddMaster( Cmd_Argv( 1 ), true, false ); // save them into config
ml.modified = true; // save config
}
@@ -316,15 +318,14 @@ static void NET_ListMasters_f( void )
master_t *list;
int i;
Msg( "Master servers\n=============\n" );
Con_Printf( "Master servers:\n" );
for( i = 1, list = ml.list; list; i++, list = list->next )
{
Msg( "%d\t%s", i, list->address );
Con_Printf( "%d\t%s", i, list->address );
if( list->adr.type != 0 )
Msg( "\t%s\n", NET_AdrToString( list->adr ));
else Msg( "\n" );
Con_Printf( "\t%s\n", NET_AdrToString( list->adr ));
else Con_Printf( "\n" );
}
}
@@ -354,11 +355,15 @@ static void NET_LoadMasters( void )
// format: master <addr>\n
while( ( pfile = COM_ParseFile( pfile, token, sizeof( token ) ) ) )
{
if( !Q_strcmp( token, "master" ) ) // load addr
if( !Q_strcmp( token, "master" )) // load addr
{
pfile = COM_ParseFile( pfile, token, sizeof( token ) );
NET_AddMaster( token, true );
NET_AddMaster( token, true, false );
}
else if( !Q_strcmp( token, "master6" ))
{
pfile = COM_ParseFile( pfile, token, sizeof( token ) );
NET_AddMaster( token, true, true );
}
}
@@ -396,7 +401,7 @@ void NET_SaveMasters( void )
for( m = ml.list; m; m = m->next )
{
if( m->save )
FS_Printf( f, "master %s\n", m->address );
FS_Printf( f, "%s %s\n", m->v6only ? "master6" : "master", m->address );
}
FS_Close( f );
@@ -418,9 +423,10 @@ void NET_InitMasters( void )
Cvar_RegisterVariable( &sv_verbose_heartbeats );
// keep main master always there
NET_AddMaster( MASTERSERVER_ADR, false );
NET_AddMaster( "aaaa.mentality.rip:27010", false ); // IPv6-only
NET_AddMaster( "mentality.rip:27011", false );
NET_AddMaster( MASTERSERVER_ADR, false, false );
NET_AddMaster( "aaaa.mentality.rip:27010", false, true ); // IPv6-only
NET_AddMaster( "mentality.rip:27011", false, false ); // testing server, might be offline
NET_AddMaster( "aaaa.mentality.rip:27011", false, true ); // IPv6-only, testing server, might be offline
NET_LoadMasters( );
}

241
engine/common/mod_alias.c Normal file
View File

@@ -0,0 +1,241 @@
/*
mod_alias.c - alias model loading
Copyright (C) 2010 Uncle Mike
Copyright (C) 2024 Alibek Omarov
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 "common.h"
#include "alias.h"
#if !XASH_DEDICATED
#include "ref_common.h"
#endif // XASH_DEDICATED
#include "mod_local.h"
#include "xash3d_mathlib.h"
static int g_posenum = 0;
static const trivertex_t *g_poseverts[MAXALIASFRAMES];
static const void *Mod_LoadAliasFrame( const daliasframe_t *pdaliasframe, maliasframedesc_t *frame, const aliashdr_t *aliashdr )
{
const trivertex_t *pinframe;
int i;
Q_strncpy( frame->name, pdaliasframe->name, sizeof( frame->name ));
frame->firstpose = g_posenum;
frame->numposes = 1;
for( i = 0; i < 3; i++ )
{
frame->bboxmin.v[i] = pdaliasframe->bboxmin.v[i];
frame->bboxmax.v[i] = pdaliasframe->bboxmax.v[i];
}
pinframe = (const trivertex_t *)(pdaliasframe + 1);
g_poseverts[g_posenum] = pinframe;
g_posenum++;
pinframe += aliashdr->numverts;
return (void *)pinframe;
}
static const void *Mod_LoadAliasGroup( const daliasgroup_t *pingroup, maliasframedesc_t *frame, const aliashdr_t *aliashdr )
{
const daliasinterval_t *pin_intervals;
const void *ptemp;
int i, numframes;
frame->firstpose = g_posenum;
frame->numposes = numframes = pingroup->numframes;
for( i = 0; i < 3; i++ )
{
frame->bboxmin.v[i] = pingroup->bboxmin.v[i];
frame->bboxmax.v[i] = pingroup->bboxmax.v[i];
}
pin_intervals = (const daliasinterval_t *)(pingroup + 1);
// all the intervals are always equal 0.1 so we don't care about them
frame->interval = pin_intervals->interval;
pin_intervals += numframes;
ptemp = (void *)pin_intervals;
for( i = 0; i < numframes; i++ )
{
g_poseverts[g_posenum] = (const trivertex_t *)((const daliasframe_t *)ptemp + 1);
ptemp = g_poseverts[g_posenum] + aliashdr->numverts;
g_posenum++;
}
return ptemp;
}
static void Mod_CalcAliasBounds( model_t *mod, const aliashdr_t *aliashdr )
{
int i, j, k;
float radius;
float dist;
vec3_t v;
ClearBounds( mod->mins, mod->maxs );
radius = 0.0f;
// process verts
for( i = 0; i < aliashdr->numposes; i++ )
{
for( j = 0; j < aliashdr->numverts; j++ )
{
for( k = 0; k < 3; k++ )
v[k] = g_poseverts[i][j].v[k] * aliashdr->scale[k] + aliashdr->scale_origin[k];
AddPointToBounds( v, mod->mins, mod->maxs );
dist = DotProduct( v, v );
if( radius < dist )
radius = dist;
}
}
mod->radius = sqrt( radius );
}
static const void *Mod_LoadAllSkins( model_t *mod, int numskins, const daliasskintype_t *pskintype, const aliashdr_t *aliashdr )
{
int i, size;
if(( numskins < 1 ) || ( numskins > MAX_SKINS ))
Host_Error( "%s: Invalid # of skins: %d\n", __func__, numskins );
size = aliashdr->skinwidth * aliashdr->skinheight;
// just skipping textures, renderer will take care of them later
for( i = 0; i < numskins; i++ )
{
if( pskintype->type == ALIAS_SKIN_SINGLE )
{
const byte *ptexture = (const byte *)&pskintype[1];
pskintype = (const daliasskintype_t *)( ptexture + size );
}
else
{
const daliasskingroup_t *pinskingroup = (const daliasskingroup_t *)&pskintype[1];
const daliasskininterval_t *pinskinintervals = (const daliasskininterval_t *)&pinskingroup[1];
const byte *ptexture = (const byte *)&pinskinintervals[pinskingroup->numskins];
pskintype = (const daliasskintype_t *)( ptexture + size );
}
}
return pskintype;
}
/*
====================
Mod_LoadAliasModel
load alias model
====================
*/
void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *loaded )
{
const daliasframetype_t *pframetype;
const daliasskintype_t *pskintype;
const dtriangle_t *pintriangles;
const daliashdr_t *pinmodel;
const stvert_t *pinstverts;
aliashdr_t *m_pAliasHeader;
size_t size;
char poolname[MAX_VA_STRING];
int i;
if( loaded ) *loaded = false;
pinmodel = (const daliashdr_t *)buffer;
i = pinmodel->version;
if( i != ALIAS_VERSION )
{
Con_DPrintf( S_ERROR "%s has wrong version number (%i should be %i)\n", mod->name, i, ALIAS_VERSION );
return;
}
if( pinmodel->numverts <= 0 || pinmodel->numtris <= 0 || pinmodel->numframes <= 0 )
return; // how is it possible to make that?
Q_snprintf( poolname, sizeof( poolname ), "^2%s^7", mod->name );
mod->mempool = Mem_AllocPool( poolname );
size = sizeof( aliashdr_t ) + (pinmodel->numframes - 1) * sizeof( maliasframedesc_t );
mod->cache.data = m_pAliasHeader = Mem_Calloc( mod->mempool, size );
// endian-adjust and copy the data, starting with the alias model header
m_pAliasHeader->numverts = pinmodel->numverts;
if( m_pAliasHeader->numverts > MAXALIASVERTS )
{
Con_DPrintf( S_ERROR "model %s has too many vertices\n", mod->name );
return;
}
mod->flags = pinmodel->flags; // share effects flags
m_pAliasHeader->boundingradius = pinmodel->boundingradius;
m_pAliasHeader->numskins = pinmodel->numskins;
m_pAliasHeader->skinwidth = pinmodel->skinwidth;
m_pAliasHeader->skinheight = pinmodel->skinheight;
m_pAliasHeader->numtris = pinmodel->numtris;
mod->numframes = m_pAliasHeader->numframes = pinmodel->numframes;
m_pAliasHeader->size = pinmodel->size;
for( i = 0; i < 3; i++ )
{
m_pAliasHeader->scale[i] = pinmodel->scale[i];
m_pAliasHeader->scale_origin[i] = pinmodel->scale_origin[i];
m_pAliasHeader->eyeposition[i] = pinmodel->eyeposition[i];
}
// load the skins
pskintype = (const daliasskintype_t *)&pinmodel[1];
pskintype = Mod_LoadAllSkins( mod, m_pAliasHeader->numskins, pskintype, m_pAliasHeader );
// will be done at renderer side...
// load base s and t vertices
pinstverts = (const stvert_t *)pskintype;
// will be done at renderer side...
// load triangle lists
pintriangles = (const dtriangle_t *)&pinstverts[m_pAliasHeader->numverts];
// will be done at renderer side
// load the frames
pframetype = (const daliasframetype_t *)&pintriangles[m_pAliasHeader->numtris];
m_pAliasHeader->pposeverts = g_poseverts; // store the pointer to be accessed by renderer
g_posenum = 0;
for( i = 0; i < m_pAliasHeader->numframes; i++ )
{
aliasframetype_t frametype = pframetype->type;
if( frametype == ALIAS_SINGLE )
pframetype = (const daliasframetype_t *)Mod_LoadAliasFrame((const daliasframe_t *)&pframetype[1], &m_pAliasHeader->frames[i], m_pAliasHeader );
else pframetype = (const daliasframetype_t *)Mod_LoadAliasGroup(( const daliasgroup_t *)&pframetype[1], &m_pAliasHeader->frames[i], m_pAliasHeader );
}
m_pAliasHeader->numposes = g_posenum;
Mod_CalcAliasBounds( mod, m_pAliasHeader );
mod->type = mod_alias;
if( loaded ) *loaded = true; // done
}

View File

@@ -30,13 +30,6 @@ GNU General Public License for more details.
#define MIPTEX_CUSTOM_PALETTE_SIZE_BYTES ( sizeof( int16_t ) + 768 )
typedef struct wadlist_s
{
char wadnames[MAX_MAP_WADS][32];
int wadusage[MAX_MAP_WADS];
int count;
} wadlist_t;
typedef struct leaflist_s
{
int count;
@@ -136,7 +129,6 @@ typedef struct
dclipnode32_t *clipnodes_out; // temporary 32-bit array to hold clipnodes
// misc stuff
wadlist_t wadlist;
int lightmap_samples; // samples per lightmap (1 or 3)
int version; // model version
qboolean isworld;
@@ -206,7 +198,7 @@ static mlumpinfo_t srclumps[HEADER_LUMPS] =
{ LUMP_MODELS, 1, MAX_MAP_MODELS, sizeof( dmodel_t ), -1, "models", CHECK_OVERFLOW, (const void **)&srcmodel.submodels, &srcmodel.numsubmodels },
};
static mlumpinfo_t extlumps[EXTRA_LUMPS] =
static const mlumpinfo_t extlumps[EXTRA_LUMPS] =
{
{ LUMP_LIGHTVECS, 0, MAX_MAP_LIGHTING, sizeof( byte ), -1, "deluxmaps", USE_EXTRAHEADER, (const void **)&srcmodel.deluxdata, &srcmodel.deluxdatasize },
{ LUMP_FACEINFO, 0, MAX_MAP_FACEINFO, sizeof( dfaceinfo_t ), -1, "faceinfos", CHECK_OVERFLOW|USE_EXTRAHEADER, (const void **)&srcmodel.faceinfo, &srcmodel.numfaceinfo },
@@ -355,7 +347,7 @@ Mod_LoadLump
generic loader
=================
*/
static void Mod_LoadLump( const byte *in, mlumpinfo_t *info, mlumpstat_t *stat, int flags )
static void Mod_LoadLump( const byte *in, const mlumpinfo_t *info, mlumpstat_t *stat, int flags )
{
int version = ((dheader_t *)in)->version;
size_t numelems, real_entrysize;
@@ -1835,7 +1827,7 @@ static void Mod_LoadEntities( model_t *mod, dbspmodel_t *bmod )
world.generator[0] = '\0';
world.compiler[0] = '\0';
world.message[0] = '\0';
bmod->wadlist.count = 0;
world.wadlist.count = 0;
// parse all the wads for loading textures in right ordering
while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL )
@@ -1878,12 +1870,12 @@ static void Mod_LoadEntities( model_t *mod, dbspmodel_t *bmod )
// make sure that wad is really exist
if( FS_FileExists( va( "%s.wad", token ), false ))
{
int num = bmod->wadlist.count++;
Q_strncpy( bmod->wadlist.wadnames[num], token, sizeof( bmod->wadlist.wadnames[0] ));
bmod->wadlist.wadusage[num] = 0;
int num = world.wadlist.count++;
Q_strncpy( world.wadlist.wadnames[num], token, sizeof( world.wadlist.wadnames[0] ));
world.wadlist.wadusage[num] = 0;
}
if( bmod->wadlist.count >= MAX_MAP_WADS )
if( world.wadlist.count >= MAX_MAP_WADS )
break; // too many wads...
}
}
@@ -2030,24 +2022,35 @@ static void Mod_LoadMarkSurfaces( model_t *mod, dbspmodel_t *bmod )
if( bmod->version == QBSP2_VERSION )
{
dmarkface32_t *in = bmod->markfaces32;
const dmarkface32_t *in = bmod->markfaces32;
for( i = 0; i < bmod->nummarkfaces; i++, in++ )
for( i = 0; i < bmod->nummarkfaces; i++ )
{
if( *in < 0 || *in >= mod->numsurfaces )
Host_Error( "%s: bad surface number in '%s'\n", __func__, mod->name );
out[i] = mod->surfaces + *in;
if( in[i] < 0 || in[i] >= mod->numsurfaces )
Host_Error( "%s: bad surface number %i at %i (max %i) in '%s'\n", __func__, in[i], i, mod->numsurfaces, mod->name );
out[i] = mod->surfaces + in[i];
}
}
else
{
dmarkface_t *in = bmod->markfaces;
const dmarkface_t *in = bmod->markfaces;
for( i = 0; i < bmod->nummarkfaces; i++, in++ )
for( i = 0; i < bmod->nummarkfaces; i++ )
{
if( *in < 0 || *in >= mod->numsurfaces )
Host_Error( "%s: bad surface number in '%s'\n", __func__, mod->name );
out[i] = mod->surfaces + *in;
// NOTE: some of the buggy compilers have written a broken BSP file
// with marksurface pointing at negative surface, for example darkf6.bsp
// and darkf26.bsp in darkfuture mod. GoldSrc straight up writes
// invalid pointer to a surface. Try to fix up these cases...
if( mod->numsurfaces <= INT16_MAX && (int16_t)in[i] < 0 )
{
Con_Printf( S_WARN "%s: fixing up bad surface number %i at %i (max %i) in '%s'\n", __func__, in[i], i, mod->numsurfaces, mod->name );
out[i] = mod->surfaces;
continue;
}
if( in[i] < 0 || in[i] >= mod->numsurfaces )
Host_Error( "%s: bad surface number %i at %i (max %i) in '%s'\n", __func__, in[i], i, mod->numsurfaces, mod->name );
out[i] = mod->surfaces + in[i];
}
}
}
@@ -2309,9 +2312,9 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
}
// Try WAD texture (force while r_wadtextures is 1)
if( !texture->gl_texturenum && (( r_wadtextures.value && bmod->wadlist.count > 0 ) || mipTex->offsets[0] <= 0 ))
if( !texture->gl_texturenum && (( r_wadtextures.value && world.wadlist.count > 0 ) || mipTex->offsets[0] <= 0 ))
{
int wadIndex = Mod_FindTextureInWadList( &bmod->wadlist, mipTex->name, texpath, sizeof( texpath ));
int wadIndex = Mod_FindTextureInWadList( &world.wadlist, mipTex->name, texpath, sizeof( texpath ));
if( wadIndex >= 0 )
{
@@ -2319,7 +2322,7 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
if( !Host_IsDedicated( ))
texture->gl_texturenum = ref.dllFuncs.GL_LoadTexture( texpath, NULL, 0, txFlags );
#endif // !XASH_DEDICATED
bmod->wadlist.wadusage[wadIndex]++;
world.wadlist.wadusage[wadIndex]++;
}
}
@@ -2377,12 +2380,12 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
// doesn't exist there. The original texture is already loaded, but cannot be modified.
// Instead, load the original texture again and convert it to luma.
wadIndex = Mod_FindTextureInWadList( &bmod->wadlist, texture->name, texpath, sizeof( texpath ));
wadIndex = Mod_FindTextureInWadList( &world.wadlist, texture->name, texpath, sizeof( texpath ));
if( wadIndex >= 0 )
{
src = FS_LoadFile( texpath, &srcSize, false );
bmod->wadlist.wadusage[wadIndex]++;
world.wadlist.wadusage[wadIndex]++;
}
// OK, loading it from wad or hi-res version
@@ -3415,18 +3418,14 @@ static qboolean Mod_LoadBmodelLumps( model_t *mod, const byte *mod_base, qboolea
Mod_CalcPHS( mod );
}
for( i = 0; i < bmod->wadlist.count; i++ )
for( i = 0; i < world.wadlist.count; i++ )
{
string wadname;
if( !bmod->wadlist.wadusage[i] )
if( !world.wadlist.wadusage[i] )
continue;
Q_snprintf( wadname, sizeof( wadname ), "%s.wad", bmod->wadlist.wadnames[i] );
// a1ba: automatically precache used wad files so client will download it
if( SV_Active( ))
SV_GenericIndex( wadname );
Q_snprintf( wadname, sizeof( wadname ), "%s.wad", world.wadlist.wadnames[i] );
if( !wadlist_warn )
{

View File

@@ -74,7 +74,7 @@ typedef struct winding_s
struct winding_s *pair;
hullnode_t chain;
int numpoints;
vec3_t p[4]; // variable sized
vec3_t p[]; // variable sized
} winding_t;
typedef struct
@@ -83,6 +83,12 @@ typedef struct
uint num_polys;
} hull_model_t;
typedef struct wadlist_s
{
char wadnames[MAX_MAP_WADS][32];
int wadusage[MAX_MAP_WADS];
int count;
} wadlist_t;
typedef struct world_static_s
{
@@ -119,6 +125,8 @@ typedef struct world_static_s
// Potentially Hearable Set
byte *compressed_phs;
size_t *phsofs;
wadlist_t wadlist;
} world_static_t;
#ifndef REF_DLL
@@ -149,6 +157,11 @@ qboolean Mod_ValidateCRC( const char *name, CRC32_t crc );
void Mod_NeedCRC( const char *name, qboolean needCRC );
void Mod_FreeUnused( void );
//
// mod_alias.c
//
void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *loaded );
//
// mod_bmodel.c
//
@@ -194,7 +207,7 @@ void Mod_ClearStudioCache( void );
//
// mod_sprite.c
//
void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, uint texFlags );
void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded );
#endif
#endif//MOD_LOCAL_H

View File

@@ -30,7 +30,7 @@ Mod_LoadSpriteModel
load sprite model
====================
*/
void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, uint texFlags )
void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded )
{
dsprite_q1_t *pinq1;
dsprite_hl_t *pinhl;

View File

@@ -300,17 +300,15 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
Mod_LoadStudioModel( mod, buf, &loaded );
break;
case IDSPRITEHEADER:
Mod_LoadSpriteModel( mod, buf, &loaded, 0 );
Mod_LoadSpriteModel( mod, buf, &loaded );
break;
case IDALIASHEADER:
// REFTODO: move server-related code here
loaded = true;
Mod_LoadAliasModel( mod, buf, &loaded );
break;
case Q1BSP_VERSION:
case HLBSP_VERSION:
case QBSP2_VERSION:
Mod_LoadBrushModel( mod, buf, &loaded );
// ref.dllFuncs.Mod_LoadModel( mod_brush, mod, buf, &loaded, 0 );
break;
default:
Mem_Free( buf );
@@ -318,6 +316,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
else Con_Printf( S_ERROR "%s has unknown format\n", tempname );
return NULL;
}
if( loaded )
{
if( world.loading )
@@ -339,6 +338,13 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
#endif
}
if( mod->type == mod_alias )
{
aliashdr_t *hdr = mod->cache.data;
if( hdr ) // clean up temporary pointer after passing the alias model to the renderer
hdr->pposeverts = NULL;
}
if( !loaded )
{
Mod_FreeModel( mod );

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