Compare commits

..

416 Commits

Author SHA1 Message Date
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
Alibek Omarov
56ba2325c1 engine: client: skip drawing 2D during changelevel before the client was active
* Prevents screen garbage on GPUs with tile-based renderers like Adreno and ImgTec
2024-07-11 09:01:19 +03:00
Alibek Omarov
b77a4ed3a1 engine: client: ignore changelevel for old protocol
* Prevents engine from drawing too early during reconnect to a
  legacy coop server
2024-07-11 08:59:42 +03:00
Alibek Omarov
9b86c3127a engine: properly disconnect from online game when loading local game (save, newgame or a level) 2024-07-10 12:32:33 +03:00
Alibek Omarov
0da7ffe45f engine: client: reset video after last screen update in begin loading plaque. Because update screen supposedly should draw the whole screen now, gl_clear hack shouldn't be required anymore 2024-07-10 11:59:54 +03:00
Alibek Omarov
30b78d9559 mainui: update 2024-07-10 11:32:30 +03:00
Alibek Omarov
c16abc0b85 engine: server: first check for dedicated server in SV_IsSimulating, as CL_Active()/CL_IsInConsole() don't make sense if we're running dedicated server already 2024-07-10 10:35:47 +03:00
Alibek Omarov
708c691cdb engine: fix XASH_DEDICATED check 2024-07-10 10:34:57 +03:00
Alibek Omarov
31c20ac4d8 engine: client: don't call Host_IsDedicated when getting split size for client 2024-07-10 10:34:30 +03:00
Alibek Omarov
1458014a29 engine: remove unused CL_IsInMenu, don't check for Host_IsDedicated in SCR_BeginLoadingPlaque, it's useless 2024-07-10 10:24:22 +03:00
Alibek Omarov
1c84a5c8ad engine: platform: sdl: disable restoring desktop resolution for mobile platforms, as it leads to unwanted window minimize (which correctly implemented by SDL by the way) 2024-07-09 19:52:11 +03:00
Alibek Omarov
6728b843f7 engine: platform: android: use RTLD_NOW in dlopen()
We basically use RTLD_NOW everywhere in the engine these days,
only platform code is behind that
2024-07-09 16:50:37 +03:00
Alibek Omarov
1b55104d51 editorconfig: add IDEA exported config 2024-07-09 16:46:51 +03:00
Alibek Omarov
76978bfd47 scripts: gha: change Android project URL, update Android CLI tools and NDK 2024-07-09 08:56:14 +03:00
Alibek Omarov
6ff3231dab engine: change current working directory before initializing filesystem_stdio 2024-07-09 08:45:27 +03:00
Alibek Omarov
64716e6b42 filesystem: request win32 error string in wide chars and then transform it to UTF-8 using our utflib 2024-07-09 08:25:15 +03:00
Alibek Omarov
a1191eb4ab engine: platform: win32: request error string in wide chars and then transform it to UTF-8 using our utflib 2024-07-09 08:24:58 +03:00
Alibek Omarov
166bed732e engine: crashhandler: few improvements for win32 crashhandler
* Larger message buffer
* Print version at first line
* Tell SDL2 to ungrab mouse
2024-07-08 05:56:20 +03:00
Alibek Omarov
02cb12e4b4 mainui: update 2024-07-08 05:49:24 +03:00
Alibek Omarov
159467ad44 engine: add IPv6 master server 2024-07-07 21:18:02 +03:00
Alibek Omarov
2a006086c5 mainui: update 2024-07-07 06:51:47 +03:00
Alibek Omarov
e0dc1eec93 engine: client: more reliable way to find the payload the netinfo response 2024-07-07 06:49:54 +03:00
Alibek Omarov
ab130ee92c engine: client: fix infostring truncation in NetAPI requests 2024-07-07 06:17:38 +03:00
Alibek Omarov
dabbe09918 engine: add NetAPI flag to send NetAPI requests to old protocol servers 2024-07-07 06:17:15 +03:00
Alibek Omarov
296a7ac11d engine: client: fix NetAPI request sending 2024-07-07 06:16:46 +03:00
Alibek Omarov
6bbf08893e engine: add NetAPI to extended menu API 2024-07-07 03:39:09 +03:00
Alibek Omarov
f8b958738a engine: client: rework NetAPI response parsing 2024-07-07 03:30:34 +03:00
Alibek Omarov
1b4427f13f engine: server: rework NetAPI responses
players list and rules are now actually useful
2024-07-07 03:29:27 +03:00
Alibek Omarov
e55577fd26 engine: get rid of some size constants passed to Info_SetValueForKey, use sizeof instead 2024-07-07 03:02:02 +03:00
Alibek Omarov
c42960ec2a engine: server: mark some cvars and movevars as server cvars, so they get reported in rules query
Bring back sv_contact cvar, as it makes sense to get this from rules query
2024-07-07 03:01:59 +03:00
Alibek Omarov
c033d4b65c engine: server: optimize source query 2024-07-07 02:34:43 +03:00
Alibek Omarov
dc6f03b4e4 engine: server: add function SV_HavePassword that correctly checks whether this server have set up password 2024-07-07 02:10:48 +03:00
Alibek Omarov
b6967a432a engine: add NetAPI flag NET_ERROR_FORBIDDEN 2024-07-07 02:05:25 +03:00
Alibek Omarov
7d0467863c engine: server: add cvar to not expose current player list, or if server has a password 2024-07-07 01:59:56 +03:00
Alibek Omarov
a0b72d3995 engine: server: light sv_query.c refactoring, use Netchan_OutOfBand instead of manually creating out of band packet 2024-07-07 01:55:03 +03:00
Alibek Omarov
5fe4b867f3 engine: server: do not expose some cvars in rules, some of them just don't make sense 2024-07-07 01:51:50 +03:00
Alibek Omarov
40af058406 engine: client: console: add conback.dds by request, don't fail on texture that cannot be loaded 2024-07-06 22:30:05 +03:00
Alibek Omarov
b4376a6a8c engine: client: make a common function for sending out userinfo changes 2024-07-06 06:09:19 +03:00
Alibek Omarov
457422c679 engine: server: fix possible byte overflow when sending sound with attenuation == 4.0f 2024-07-06 05:50:53 +03:00
Alibek Omarov
080eba948f engine: server: fix sound not being overriden when an entity sound came from has an aiment set
This check was added 10+ years ago in 8f6f3fc (viewable in Xash3DArchive) and
probably doesn't make any sense anymore.
2024-07-06 05:32:20 +03:00
Alibek Omarov
eff86defd9 public: fix Q_equal for case when applying epsilon doesn't change the value 2024-07-04 07:55:32 +03:00
Alibek Omarov
fcb463d400 engine: client: flush demoheader before copying it 2024-07-04 07:23:48 +03:00
Alibek Omarov
efee8149e2 filesystem: remove unneeded cast to fs_offset_t in write() call 2024-07-04 07:23:13 +03:00
Alibek Omarov
bc32f37fce public: use Q_strchr in COM_FixSlashes 2024-07-04 06:42:49 +03:00
Alibek Omarov
58bfa247a4 public: add test case for COM_FixSlashes 2024-07-04 06:42:35 +03:00
Alibek Omarov
59b9b31604 public: avoid useless copies in Q_pretifymem 2024-07-04 06:39:18 +03:00
Alibek Omarov
844af709c0 public: simplify Q_colorstr and Q_strnlwr 2024-07-04 06:38:50 +03:00
Alibek Omarov
bb6e2d6885 public: add Q_colorstr and Q_strnlwr tests 2024-07-04 06:38:09 +03:00
Alibek Omarov
6243dc7913 public: simplify Q_ato{i,f} implementation 2024-07-04 06:30:59 +03:00
Alibek Omarov
45c4362ae6 public: add Q_ato{i,f,v} test 2024-07-04 06:29:46 +03:00
Alibek Omarov
a0230b7e00 engine: client: console: minor refactoring, move common NXPrintf code to Con_NXPrintfv 2024-07-04 05:49:33 +03:00
Alibek Omarov
768755c31a engine: client: use Con_Printf instead of Con_Print (which is just printing to console, not the logging) 2024-07-03 04:22:28 +03:00
Alibek Omarov
3088c7f198 scripts: gha: set proper PKG_CONFIG_PATH when building 32-bit SDL 2024-07-02 19:26:39 +03:00
Alibek Omarov
c8469071bf scripts: gha: add remaining wayland dependencies 2024-07-02 19:15:02 +03:00
Alibek Omarov
115fc301b5 scripts: gha: fix installing pulseaudio dependency for 32-bit build 2024-07-02 19:02:54 +03:00
Alibek Omarov
bc449b8e95 scripts: gha: enable JACK in automatic builds 2024-07-02 18:59:13 +03:00
Alibek Omarov
74bbc0fe7e scripts: gha: install pulse, jack and wayland development files for SDL to detect them 2024-07-02 18:58:53 +03:00
Alibek Omarov
c73fa3d7a6 filesystem: fix mounting wads again
Because of the mounting order, VFS fails to automatically find unpacked WADs
2024-06-28 18:00:40 +03:00
Alibek Omarov
5694610478 filesystem: fix writedir being prepended to rodir path when searching for library
* Refactor generating shortName
* Refactor library origin checks
2024-06-27 08:16:56 +03:00
Alibek Omarov
ec107dfba5 filesystem: load on-disk archives like PAK and PK3 through VFS (disk-only for now)
* Track from which archive the file has been opened and provide needed functions for it
2024-06-27 07:31:11 +03:00
Alibek Omarov
64aa476330 editorconfig: add Visual Studio options (generated) 2024-06-27 07:18:10 +03:00
Alibek Omarov
42f6719e8d filesystem: drop direct path hacks for WAD files, let VFS decide how to open WAD archives 2024-06-27 05:55:06 +03:00
Alibek Omarov
244b9dc02b wscript: disable -Wformat=2 back (it wasn't supposed to be pushed anyway) 2024-06-24 20:01:29 +03:00
Alibek Omarov
fe3644a417 engine: client: add simple debugging tool that shows entities number, model and movetype (to be extended) 2024-06-22 08:19:19 +03:00
Alibek Omarov
e18b61e041 Fixes for -Wformat=2 on 64-bit targets 2024-06-22 07:31:37 +03:00
Alibek Omarov
d054782693 engine: client: fix broken legacy demos playing
Fixes: ff4221fbe7 ("engine: client: write correct cls.legacymode/net_protocol value for demos")
2024-06-22 07:30:47 +03:00
Alibek Omarov
d56e53a347 Replace hardcoded functions names by __func__ macro
* while we're here, fix some possible bugs
* and fix -Wformat=2

s/__FUNCTION__/__func__/g

awawawa
2024-06-19 06:53:42 +03:00
Alibek Omarov
3503c721ac engine: client: console: simplify loading console background image 2024-06-19 03:35:28 +03:00
Alibek Omarov
0fab5f07d0 Revert "engine: common: mod_studio: reject models with split textures files that cannot be loaded"
This reverts commit 3256236ba2.
2024-06-18 22:50:06 +03:00
Alibek Omarov
b0d12f8bf9 engine: client: fix build
Forgot to stage these changes two commits ago =/
2024-06-18 00:01:54 +03:00
Alibek Omarov
9fe58aaabc engine: client: send expected cvar not found string for old protocol cvar query 2024-06-17 23:44:05 +03:00
Alibek Omarov
03c8ea14cc engine: client: mute music if not in focus 2024-06-17 20:32:04 +03:00
Alibek Omarov
260edc2a08 ref: gl: try to match texture slot and texture object handle because of buggy games 2024-06-15 19:21:26 +03:00
Alibek Omarov
b41591a527 ref: gl: decreate alphatest value for lightmapped sprites to make them easier to see
With 0.5 they're too tiny
2024-06-15 19:07:17 +03:00
Alibek Omarov
4e9481451b mainui: update 2024-06-15 17:22:52 +03:00
Alibek Omarov
95b48da37d engine: allow to change hardcoded path to custom.hpk 2024-06-15 17:22:26 +03:00
Alibek Omarov
1b36785177 engine: common: hpak: rename hpk_maxsize to hpak_max_size to avoid Valve's defaults
While we're here:
* Increase it to 64 MiB.
* Make it privileged.
* Add hpk_maxsize stub command as a deprecation notice.
2024-06-15 16:55:25 +03:00
Alibek Omarov
8bc76e3d58 engine: host: do not specifically check timedemo or vsync in Host_CalcSleep, because it's already has been checked in Host_CalcFPS 2024-06-15 13:57:12 +03:00
Alibek Omarov
1a5e2b907d engine: client: minor refactoring for cls.demoplayback check 2024-06-15 13:56:25 +03:00
Alibek Omarov
3717e5c2e0 engine: client: simplify server message parsing by moving common code out of protocol-specific parsing funcs 2024-06-15 13:51:02 +03:00
Alibek Omarov
33a1416199 engine: common: net_chan: remove unneeded check for demo and remote address in netchan, as it's handled in client and server already 2024-06-15 13:44:26 +03:00
Alibek Omarov
ff4221fbe7 engine: client: write correct cls.legacymode/net_protocol value for demos 2024-06-15 13:43:18 +03:00
Alibek Omarov
486bca82e8 engine: add quake svc messages names 2024-06-15 11:04:30 +03:00
Alibek Omarov
611d07fc16 engine: client: redefine legacymode from qboolean to an enum with selected protocol. Remove protocol auto-guess hack, it's useless since connect accept accepts protocol string 2024-06-15 10:52:26 +03:00
Alibek Omarov
f7e12586cf engine: platform: sdl: we must notify the engine about the unpressed button when text input was activated 2024-06-15 08:44:19 +03:00
Alibek Omarov
f62aa051c8 engine: common: make netchan cvars static 2024-06-15 08:44:19 +03:00
Alibek Omarov
2b6b898102 engine: client: make some cvars static 2024-06-15 08:44:19 +03:00
Alibek Omarov
1dd0444531 engine: server: comment out unused cvars, make some static 2024-06-15 08:44:19 +03:00
Alibek Omarov
ba9eb01c1f engine: server: replace timeout cvar by sv_timeout cvar for consistency with GoldSrc 2024-06-15 08:44:19 +03:00
Alibek Omarov
73a8144e75 engine: client: reduce console spam about not precached model to dev level 1 2024-06-15 08:44:18 +03:00
Alibek Omarov
6aef422de6 ref: remove unneeded dlight pointer increment 2024-06-15 08:44:18 +03:00
Alibek Omarov
5f4b8b60cb engine: client: make remote print messages more obvious 2024-06-15 08:44:18 +03:00
Alibek Omarov
3256236ba2 engine: common: mod_studio: reject models with split textures files that cannot be loaded 2024-06-14 11:34:42 +03:00
Alibek Omarov
b102727320 engine: client: try to not save passwords to console history 2024-06-14 11:34:37 +03:00
Alibek Omarov
3434005e66 engine: common: make Host_IsLocalGame and Host_IsLocalClient inlined 2024-06-13 01:20:14 +03:00
Alibek Omarov
b3026a7991 engine: client: don't use CL_Active/CL_GetMaxClients wrappers as they are only intended to be either passed to DLL or used in common/server code 2024-06-13 01:19:38 +03:00
Alibek Omarov
0a051832a8 engine: client: do not mute sounds in menu with multiplayer, the bug already been solved different way 2024-06-13 01:07:49 +03:00
Alibek Omarov
2dbafbda02 engine: common: mod_studio: fix NULL mod->cache.data if model has split texture file but none was loaded 2024-06-12 23:37:30 +03:00
Alibek Omarov
240b6fb6f2 engine: fix possible unprivileged config execute with fake extension 2024-06-12 11:16:31 +03:00
Alibek Omarov
4163d3655a engine: reformat and reorder host_parm_s struct, remove now unused host.daemonize and host.enabledll 2024-06-12 11:16:26 +03:00
Alibek Omarov
2c7bf49fc9 engine: host: avoid some of unnecessary double-to-float conversions 2024-06-12 10:20:09 +03:00
Alibek Omarov
739592e50d engine: host: refactoring, reduce usage of global variables a bit 2024-06-12 10:20:09 +03:00
Alibek Omarov
393e31e509 engine: move finding root/readonly directory to FS initialization, remove unused host.rodir, host.rootidr 2024-06-12 10:20:09 +03:00
Alibek Omarov
a1dceacc8f engine: remove unused host.hMutex and host.hInst 2024-06-12 10:20:09 +03:00
Alibek Omarov
cf26c87872 engine: remove unused host.decalList and host.numdecals 2024-06-12 10:20:09 +03:00
Alibek Omarov
21195b3491 engine: increase logo and hpak limits, add cl_logomaxdim cvar to limit decal size (set to 96, default HL logo size is 64) 2024-06-11 07:47:01 +03:00
Alibek Omarov
3f66f6a6a5 ref: null: update to RefAPI 8 2024-06-11 06:30:17 +03:00
Alibek Omarov
daae4f2f80 engine: ref_api: bump RefAPI to version 8 2024-06-11 06:18:09 +03:00
Alibek Omarov
4e2708c1ac engine: bring back texture replacement 2024-06-11 06:16:26 +03:00
Alibek Omarov
d57d8e0d5d ref: soft: fix R_DrawStretchPic and Draw_Fill with OpenMP enabled 2024-06-11 02:07:49 +03:00
Alibek Omarov
9577a6af21 ref: moved VGUI support API implementation to the engine 2024-06-11 02:07:49 +03:00
Alibek Omarov
107a6aed01 ref: move PARM_SURF_SAMPLESIZE handling to the engine 2024-06-11 02:07:49 +03:00
Alibek Omarov
2c2045d413 ref: move PARM_SKY_SPHERE handling to the engine 2024-06-11 02:07:49 +03:00
Alibek Omarov
30fe471d2b ref: move loading skybox into the engine 2024-06-11 02:07:44 +03:00
Alibek Omarov
5ab6979633 ref: move common quake sky cloud loading to the engine 2024-06-10 22:47:39 +03:00
SNMetamorph
ec5e9cb6e3 engine: client: send engine build information to masterserver 2024-06-10 20:53:59 +03:00
Alibek Omarov
f4b4546197 engine: temporarily fix loading studio models with split texture model 2024-06-10 14:57:00 +03:00
Alibek Omarov
f047749e61 engine: move studio model truncation into separate function, disable it by default 2024-06-10 13:34:02 +03:00
Alibek Omarov
87840ce91d engine: fix potential buffer overflow in Mod_StudioTexName
* Model names are 64 bytes wide, adding texture character means we needs 65 byte wide string.
* It never gets stored in memory anyway.
2024-06-10 13:28:01 +03:00
Alibek Omarov
bf31e9f634 engine: fix NO_ASAN macro usage with MSVC 2024-06-09 09:37:16 +03:00
Alibek Omarov
f86d84daed engine: platform: sdl: initialize window name string when building with old SDL 2024-06-09 09:16:45 +03:00
Alibek Omarov
41ed920d35 common: xash3d_types: fix build 2024-06-09 09:16:07 +03:00
Alibek Omarov
df23ddb545 engine: server: fix signed integer overflow in challenge generator 2024-06-09 07:05:24 +03:00
Alibek Omarov
767556ccad engine: temporarily disable ASan in MSG_WriteUBitLong (evil!) 2024-06-09 07:03:59 +03:00
Alibek Omarov
f9dab2ad19 engine: server: rename sv_allow_upload to sv_allowupload for compatibility 2024-06-09 07:02:50 +03:00
Alibek Omarov
66cb3a6120 engine: client: add room_off variable to toggle sound effects processing for GoldSrc compatibility
* Fixes Sven-Coop 4.8 client.
* Declare dsp_off deprecated.
2024-06-09 03:51:43 +03:00
Tuldok
7672a370da engine: Crashhandler support for Windows-on-ARM (arm/arm64) 2024-06-08 21:35:55 +03:00
Alibek Omarov
870e47ed03 engine: ensure character signness when checking for nonprintable characters 2024-06-07 22:22:13 +03:00
Alibek Omarov
32d4bdb80f engine: fix UTF-8 sequence input
Fixes: 2e0fc3e4c1 ("engine: client: do not repeatedly check cl_charset value, use generic Con_UtfProcessChar")
2024-06-07 22:16:32 +03:00
Alibek Omarov
929dfd2c71 mainui: update 2024-06-03 09:04:47 +03:00
Alibek Omarov
f437af6451 mainui: update 2024-06-03 07:57:10 +03:00
Alibek Omarov
413a0fb2e5 engine: client: improve accumulating rounding error, thanks @SNMetamorph for suggestion 2024-06-02 13:09:10 +03:00
Alibek Omarov
793adadb06 mainui: update 2024-06-02 12:51:30 +03:00
Alibek Omarov
999b43b89f engine: implement changing cursor type in gameui 2024-06-02 12:24:14 +03:00
Alibek Omarov
bd60c88c7d ref: soft: fix build with OpenMP under Visual Studio 2024-06-02 11:39:54 +03:00
Alibek Omarov
23b9a2eddf waf.bat: add checks for newer pythons, remove checks for pythons below 2.7 2024-06-02 11:39:54 +03:00
Alibek Omarov
0b57d97c8c vgui_support: update submodule 2024-06-02 11:35:57 +03:00
Alibek Omarov
6255293dd4 engine: fix using OpenMP PHS generation under Visual Studio 2024-06-02 10:34:10 +03:00
Alibek Omarov
04136d95a3 filesystem: fix build warning 2024-06-02 10:33:33 +03:00
Alibek Omarov
40aa29e42a ci: remove freebsd-13-2 task 2024-06-02 10:04:04 +03:00
Alibek Omarov
a709f30da9 engine: soundlib: libmpg: add wrappers on top of libc read & lseek in case they don't match internal mpg123 types
(we better migrate to upstream libmpg at some point)
2024-06-02 09:19:17 +03:00
Alibek Omarov
0796c14e79 engine: client: fix framerate depending player move 2024-06-02 04:15:17 +03:00
Alibek Omarov
a9c0a4be23 engine: server: add cvar to disable bandwidth test on server side 2024-06-01 05:27:35 +03:00
Alibek Omarov
3e1209d3a4 engine: client: do not rely on host.downloadcount when connecting to the server with HTTP enabled
* Replace cl.downloadUrl by cl.http_download
2024-06-01 04:30:21 +03:00
Alibek Omarov
caf14c1b7c engine: soundlib: libmpg: fix the inconsistent use of offset types in lseek() 2024-05-31 03:35:39 +03:00
Alibek Omarov
27f7d2c8d2 engine: common: ban few more executable types for COM_IsSafeFileToDownload 2024-05-31 00:43:28 +03:00
Alibek Omarov
8ee430eda2 engine: common: double check that resource starting with !MD5 doesn't have any extension 2024-05-31 00:42:44 +03:00
Alibek Omarov
484e4cb225 engine: common: net_ws: less verbose HTTP client, fix printing header size in case of an error 2024-05-31 00:07:14 +03:00
Alibek Omarov
b080ad9954 engine: moved link_t helpers to sv_world.c from world.c and made them static 2024-05-30 07:31:03 +03:00
Alibek Omarov
f6625d9188 engine: common: remove unused et_name array 2024-05-30 07:22:21 +03:00
Alibek Omarov
1eb2816bc4 engine: client: manually call FS_Rescan if we downloaded an archive while connecting to server 2024-05-30 06:48:17 +03:00
Alibek Omarov
077be5aaf3 engine: client: only strip DEFAULT_SOUNDPATH from t_sound resources 2024-05-30 06:47:46 +03:00
Alibek Omarov
d59875f114 engine: common: for automatic wad precache to work, we need to count the real wad usage on dedicated 2024-05-30 06:18:15 +03:00
Alibek Omarov
e89191ed39 engine: common: automatically precache wad files required by loaded map
Makes it easier to host server with multiplayer maps and broken .res files.
2024-05-30 05:58:41 +03:00
Alibek Omarov
ea21438637 engine: netchan: append .ztmp extension instead of replacing original extension
* so we don't send wrong file that has same name but different extension

* validate filename size so it won't get truncated in fragbuf_t
2024-05-30 04:50:58 +03:00
Alibek Omarov
0d2e8333e8 common: remove unused boneinfo.h header 2024-05-29 12:25:23 +03:00
Alibek Omarov
338399e622 engine: common: implement PHS calculation like in QuakeWorld/GoldSrc 2024-05-29 05:58:51 +03:00
Alibek Omarov
27cab8aad5 scripts: waifulib: compiler_optimizations: set HAVE_OPENMP=1 define if openmp feature was enabled during the build 2024-05-29 05:41:47 +03:00
Alibek Omarov
1545a49b4c engine: client: only allocate debug hulls polygons when they're requested
* Make the appropriate changes in ref_gl
2024-05-29 05:41:47 +03:00
Alibek Omarov
3ca15250e8 engine: common: use Mod_PointInLeaf in Mod_GetPVSForPoint instead of traversing nodes manually 2024-05-29 05:41:47 +03:00
Alibek Omarov
6cbac51731 engine: common: add function for compressing visdata 2024-05-29 05:41:47 +03:00
Alibek Omarov
e310c666b1 engine: common: add phs flag to Mod_FatPVS, unused currently 2024-05-29 05:41:47 +03:00
Alibek Omarov
677b0170aa engine: server: remove recalculating viewpoint for PVS hack, as it causes issues with inconsistency between real and "restored" view positions 2024-05-29 05:41:47 +03:00
Alibek Omarov
9150b770e4 engine: common: mod_bmodel: add function Mod_DecompressVisTo that will copy fat vis data into the provided buffer 2024-05-29 05:41:47 +03:00
Alibek Omarov
2ad6511c31 public: add Q_memor routine that binary OR's data from src to dst
Supposed to be compiled with optimizations enabled.
2024-05-29 05:41:33 +03:00
Alibek Omarov
0848f28d83 waf: upgrade to latest master 2024-05-26 19:32:14 +03:00
Alibek Omarov
5d9bc950ce wscript: do not load msvc manually, it will be loaded by compiler_{c,cxx} 2024-05-25 22:40:25 +03:00
Alibek Omarov
714da79395 mainui: update 2024-05-25 22:25:33 +03:00
Alibek Omarov
823fe9ebbd waf: upgrade to waf 2.1.1/waifu 1.3.0. Try to fix most optparse->argparse migration issues 2024-05-25 04:58:28 +03:00
Alibek Omarov
4bf72b5383 engine: forbid accessing cvars starting with con_ and scr_ through stufftext
Some stupid servers might mess up with console cvars values.
2024-05-25 02:26:42 +03:00
Alibek Omarov
51945f002b engine: server: check for invoker entity when filtering out host client during entities thinking 2024-05-23 02:06:54 +03:00
Alibek Omarov
bcca9387de engine: server: sv_pmove: always set FEV_NOTHOST for events coming from PMove (like GoldSrc) 2024-05-23 01:51:42 +03:00
Alibek Omarov
b8417fa46d ref: soft: search parent in both entity lists when drawing MOVETYPE_FOLLOW entities
Fixes the issue in Brutal Half-Life beta 2 with invisible scientist skin.

Fixes: 6862b14e59 ("ref: soft: only draw MOVETYPE_FOLLOW studio model if it's parent is visible")
2024-05-19 06:31:46 +03:00
Alibek Omarov
85b0699288 ref: gl: search parent in both entity lists when drawing MOVETYPE_FOLLOW entities
Fixes the issue in Brutal Half-Life beta 2 with invisible scientist skin.

Fixes: dc1d65f621 ("ref: gl: only draw MOVETYPE_FOLLOW studio model if it's parent is visible")
2024-05-19 06:29:22 +03:00
Alibek Omarov
6c03fb0226 engine: client: first attempt to use utflib to replace Con_UtfProcessCharForce calls 2024-05-15 05:25:53 +03:00
Alibek Omarov
a084dea07c public: add functions to convert from Unicode codepoints into CP1251 or CP1252 2024-05-15 05:07:18 +03:00
Alibek Omarov
2e0fc3e4c1 engine: client: do not repeatedly check cl_charset value, use generic Con_UtfProcessChar 2024-05-15 05:06:57 +03:00
Alibek Omarov
24f4d410ce filesystem: take FS_Read improvements from DarkPlaces and proper fix for buffer overflow 2024-05-15 03:43:02 +03:00
Alibek Omarov
052e0445ab engine: client: console: cleanup input buffer from line feed characters before pushing it to the console history 2024-05-15 03:08:22 +03:00
Alibek Omarov
758c908d5a public: add buffer size parameter to COM_RemoveLineFeed 2024-05-15 03:06:57 +03:00
Alibek Omarov
3917c2589d filesystem: fix buffer overflow in FS_Read when we pass single byte buffer to it with one character sitting in ungetc 2024-05-15 02:45:01 +03:00
Alibek Omarov
f4a77308ec engine: soundlib: fix possible buffer overflow in Sound_ConvertUpsample 2024-05-06 15:45:49 +03:00
Alibek Omarov
103b9724f9 scripts: waifulib: compiler_optimizations: fix linking OpenMP 2024-05-06 15:36:26 +03:00
Alibek Omarov
75a315ecf0 engine: client: add optional (compile time for now) setting to reconfigure engine to use 48kHz sounds 2024-05-06 15:10:34 +03:00
Alibek Omarov
63b3b9ef6d engine: client: fix missing upsampling for >32kHz sounds 2024-05-06 15:09:52 +03:00
Alibek Omarov
a6c2cfe89b engine: avoid constants in Q_strncpy third argument, where possible 2024-05-06 14:27:26 +03:00
Alibek Omarov
5120657386 engine: fix possible buffer overflow in S_StreamGetCurrentState 2024-05-06 06:53:22 +03:00
Alibek Omarov
e754de46d1 engine: client: fix buffer overflow in S_FindName 2024-05-06 06:42:47 +03:00
Alibek Omarov
5d718aa0d6 scripts: waifulib: compiler_optimizations: add flag for building with OpenMP (not used anywhere in the engine but let's keep it) 2024-05-06 06:42:15 +03:00
Alibek Omarov
55fcbc8880 engine: soundlib: implement linear interpolation in Sound_ResampleInternal
* split resampling into three functions
* added resampling using SDL_AudioCVT, it's slow, so isn't enabled by default
2024-05-06 06:41:23 +03:00
Alibek Omarov
e19aa001b2 engine: client: ref_common: slight refactoring, reorder ref_state_t 2024-05-06 01:59:50 +03:00
Alibek Omarov
b447ea9c18 engine: client: remove unused fields in client_static_t 2024-05-06 01:59:14 +03:00
Alibek Omarov
13274655d4 engine: client: sound: slight refactoring, removed unused s_listener.velocity 2024-05-06 01:30:06 +03:00
Alibek Omarov
3723ac60ef engine: client: s_mix: _inline -> static 2024-05-06 00:51:32 +03:00
Alibek Omarov
da578f47f1 engine: client: fix sounds being paused in menu and then blasted all at the same time in multiplayer 2024-05-06 00:41:38 +03:00
Alibek Omarov
433e7de686 engine: clean up unused soundlib flags, set SOUND_LOOPED flag on looped sounds 2024-05-05 06:16:57 +03:00
Alibek Omarov
e18e9ae2ea engine: platform: sdl: ignore keyboard events if text mode is active 2024-05-04 11:05:17 +03:00
Alibek Omarov
27d5123a61 mainui: update 2024-05-03 16:55:17 +03:00
Alibek Omarov
89b9f9ffe2 github: update SDL to 2.30.3 2024-05-03 16:04:13 +03:00
Alibek Omarov
a17b8aaa13 public: fix parameter name omitted error for older compilers 2024-05-03 16:01:24 +03:00
Alibek Omarov
e210969612 scripts: gha: build_linux: spew config.log on build failure 2024-05-03 15:57:26 +03:00
Alibek Omarov
1208356b92 ref: gl: gl2_shim: remove unused ALLOCA_H include 2024-05-03 15:53:57 +03:00
Alibek Omarov
d7cd74fe2f wscript: no need to pass PACKAGING into env 2024-05-03 15:45:20 +03:00
Alibek Omarov
31b63e9939 wscript: exclude executing large file test for PSVita 2024-05-03 15:44:35 +03:00
Alibek Omarov
b99c2c2df1 wscript: do not execute test for test for large files 2024-05-03 15:38:35 +03:00
Alibek Omarov
94d3eff9ce engine: host: fix build with Q_strchrnul returning const char * 2024-05-03 15:31:20 +03:00
Alibek Omarov
b78e9961c6 public: fix build on Windows
stristr doesn't exist actually
2024-05-03 15:30:42 +03:00
Alibek Omarov
b0704ca5d6 mainui: update 2024-05-03 06:38:21 +03:00
Alibek Omarov
31c0934108 engine: fix parsing -bugcomp flags, assume bugcomp flags only starts with alphabetic character 2024-05-03 06:28:48 +03:00
Alibek Omarov
37083c8aef ref: soft: mark sw_drawflat and sw_draworder as cheats 2024-05-01 00:52:45 +03:00
Alibek Omarov
af23b0c67b public: crtlib: refactoring with new macros, use system strlcpy/strlcat if possible 2024-04-30 02:20:14 +03:00
Alibek Omarov
a9e83fb9cf wscript: move std defining macros into libpublic's sdk_includes target, so we don't accidentally feed submodules our macros 2024-04-29 05:29:53 +03:00
Alibek Omarov
51126e1691 mainui: update 2024-04-29 05:28:41 +03:00
Alibek Omarov
dd410a2de5 engine: implement small Message Rewrite Facitility that allows to run mods that directly write internal GoldSrc messages 2024-04-28 06:59:18 +03:00
Alibek Omarov
7ccb0b5c02 public: make simple ctype functions inlined 2024-04-28 06:59:18 +03:00
Alibek Omarov
7f3e62e456 public: remove unneeded copy in Q_atov 2024-04-28 06:59:18 +03:00
Alibek Omarov
fcfc29d7ea public: fix variables types in COM_HashKey, they are all supposed to be unsigned integers 2024-04-28 06:59:18 +03:00
Alibek Omarov
2f3429a144 engine: common: base_cmd: use flexible array to store basecmd name 2024-04-28 06:59:18 +03:00
Alibek Omarov
20782693f4 engine: server: rename symbols for svs, sv and SV_DropClient to avoid AMXModX trying to acquire their pointers 2024-04-28 06:59:18 +03:00
Alibek Omarov
0cfb354374 common: add RENAME_SYMBOL macro that renames symbol for compatibility with nasty mods (also reformat this portion, while we're at it) 2024-04-28 06:59:18 +03:00
Alibek Omarov
9be5b7c6c9 engine: physint: empty-define ALLOC_CHECK if not defined by SDK, so this header can be freely moved to another SDK 2024-04-28 06:59:18 +03:00
Alibek Omarov
e7653d2ea6 engine: soundlib: fix searching for a RIFF/WAVE chunks in streams 2024-04-27 10:51:56 +03:00
Alibek Omarov
1494887e29 engine: soundlib: snd_wav: replace strncmp by IsFourCC helper function 2024-04-26 06:29:38 +03:00
Alibek Omarov
42dab2b1a5 engine: soundlib: snd_wav: attempt to fix misleading warning about truncated file 2024-04-26 06:25:18 +03:00
Alibek Omarov
36a0c1fb17 ref: if the entity is opaque, check the renderfx too, it might become translucent 2024-04-26 04:15:21 +03:00
Alibek Omarov
60c6767337 filesystem: copy absolute path to library in FS_FindLibrary for compatibility
Extend fullPath for longer absolute paths.
2024-04-22 04:02:46 +03:00
Alibek Omarov
75451cc7fa engine: client: print correct message names in legacymode 2024-04-22 04:02:46 +03:00
Alibek Omarov
db10035d9d engine: add GoldSrc protocol definitions 2024-04-22 04:02:46 +03:00
245 changed files with 8548 additions and 6330 deletions

View File

@@ -1,15 +1,3 @@
task:
name: freebsd-13-amd64
freebsd_instance:
image_family: freebsd-13-2
setup_script:
- pkg update
- pkg install -y pkgconf git sdl2 python fontconfig opus
- git submodule update --init --recursive
test_script:
- ./scripts/cirrus/build_freebsd.sh dedicated
- ./scripts/cirrus/build_freebsd.sh full
task: task:
name: freebsd-14-amd64 name: freebsd-14-amd64
freebsd_instance: freebsd_instance:

View File

@@ -1,9 +1,365 @@
# EditorConfig is awesome: https://EditorConfig.org # this file is just a suggestion, you might follow it, you might not
root = true root = true
[*] [*]
charset = latin1 charset = utf-8
end_of_line = lf end_of_line = lf
indent_style = tab indent_style = tab
insert_final_newline = true insert_final_newline = true
trim_trailing_whitespace = true trim_trailing_whitespace = true
ij_formatter_off_tag = @formatter:off
ij_formatter_on_tag = @formatter:on
[*.{c++,cc,cpp,cppm,cxx,h,h++,hh,hpp,hxx,inl,ipp,ixx,tlh,tli}]
# Visual C++ Formatting settings
cpp_indent_braces = false
cpp_indent_multi_line_relative_to = innermost_parenthesis
cpp_indent_within_parentheses = indent
cpp_indent_preserve_within_parentheses = true
cpp_indent_case_contents = true
cpp_indent_case_labels = false
cpp_indent_case_contents_when_block = false
cpp_indent_lambda_braces_when_parameter = true
cpp_indent_goto_labels = one_left
cpp_indent_preprocessor = leftmost_column
cpp_indent_access_specifiers = false
cpp_indent_namespace_contents = true
cpp_indent_preserve_comments = false
cpp_new_line_before_open_brace_namespace = new_line
cpp_new_line_before_open_brace_type = new_line
cpp_new_line_before_open_brace_function = new_line
cpp_new_line_before_open_brace_block = new_line
cpp_new_line_before_open_brace_lambda = new_line
cpp_new_line_scope_braces_on_separate_lines = true
cpp_new_line_close_brace_same_line_empty_type = false
cpp_new_line_close_brace_same_line_empty_function = false
cpp_new_line_before_catch = true
cpp_new_line_before_else = true
cpp_new_line_before_while_in_do_while = false
cpp_space_before_function_open_parenthesis = remove
cpp_space_within_parameter_list_parentheses = true
cpp_space_between_empty_parameter_list_parentheses = true
cpp_space_after_keywords_in_control_flow_statements = false
cpp_space_within_control_flow_statement_parentheses = true
cpp_space_before_lambda_open_parenthesis = false
cpp_space_within_cast_parentheses = false
cpp_space_after_cast_close_parenthesis = false
cpp_space_within_expression_parentheses = true
cpp_space_before_block_open_brace = true
cpp_space_between_empty_braces = true
cpp_space_before_initializer_list_open_brace = false
cpp_space_within_initializer_list_braces = true
cpp_space_preserve_in_initializer_list = true
cpp_space_before_open_square_bracket = false
cpp_space_within_square_brackets = false
cpp_space_before_empty_square_brackets = false
cpp_space_between_empty_square_brackets = false
cpp_space_group_square_brackets = true
cpp_space_within_lambda_brackets = false
cpp_space_between_empty_lambda_brackets = false
cpp_space_before_comma = false
cpp_space_after_comma = true
cpp_space_remove_around_member_operators = true
cpp_space_before_inheritance_colon = true
cpp_space_before_constructor_colon = true
cpp_space_remove_before_semicolon = true
cpp_space_after_semicolon = true
cpp_space_remove_around_unary_operator = true
cpp_space_around_binary_operator = insert
cpp_space_around_assignment_operator = insert
cpp_space_pointer_reference_alignment = right
cpp_space_around_ternary_operator = insert
cpp_use_unreal_engine_macro_formatting = true
cpp_wrap_preserve_blocks = one_liners
# IDEA settings
ij_c_add_brief_tag = false
ij_c_add_getter_prefix = true
ij_c_add_setter_prefix = true
ij_c_align_dictionary_pair_values = false
ij_c_align_group_field_declarations = false
ij_c_align_init_list_in_columns = true
ij_c_align_multiline_array_initializer_expression = false
ij_c_align_multiline_assignment = false
ij_c_align_multiline_binary_operation = false
ij_c_align_multiline_chained_methods = false
ij_c_align_multiline_for = true
ij_c_align_multiline_ternary_operation = false
ij_c_array_initializer_comma_on_next_line = false
ij_c_array_initializer_new_line_after_left_brace = false
ij_c_array_initializer_right_brace_on_new_line = false
ij_c_array_initializer_wrap = off
ij_c_assignment_wrap = off
ij_c_binary_operation_sign_on_next_line = false
ij_c_binary_operation_wrap = off
ij_c_blank_lines_after_class_header = 0
ij_c_blank_lines_after_imports = 1
ij_c_blank_lines_around_class = 1
ij_c_blank_lines_around_field = 0
ij_c_blank_lines_around_field_in_interface = 0
ij_c_blank_lines_around_method = 1
ij_c_blank_lines_around_method_in_interface = 1
ij_c_blank_lines_around_namespace = 0
ij_c_blank_lines_around_properties_in_declaration = 0
ij_c_blank_lines_around_properties_in_interface = 0
ij_c_blank_lines_before_imports = 1
ij_c_blank_lines_before_method_body = 0
ij_c_block_brace_placement = next_line
ij_c_block_brace_style = next_line
ij_c_block_comment_at_first_column = true
ij_c_catch_on_new_line = false
ij_c_class_brace_style = next_line
ij_c_class_constructor_init_list_align_multiline = true
ij_c_class_constructor_init_list_comma_on_next_line = false
ij_c_class_constructor_init_list_new_line_after_colon = never
ij_c_class_constructor_init_list_new_line_before_colon = if_long
ij_c_class_constructor_init_list_wrap = normal
ij_c_copy_is_deep = false
ij_c_create_interface_for_categories = true
ij_c_declare_generated_methods = true
ij_c_description_include_member_names = true
ij_c_discharged_short_ternary_operator = false
ij_c_do_not_add_breaks = false
ij_c_do_while_brace_force = never
ij_c_else_on_new_line = false
ij_c_enum_constants_comma_on_next_line = false
ij_c_enum_constants_wrap = off
ij_c_for_brace_force = never
ij_c_for_statement_new_line_after_left_paren = false
ij_c_for_statement_right_paren_on_new_line = false
ij_c_for_statement_wrap = off
ij_c_function_brace_placement = next_line
ij_c_function_call_arguments_align_multiline = true
ij_c_function_call_arguments_align_multiline_pars = false
ij_c_function_call_arguments_comma_on_next_line = false
ij_c_function_call_arguments_new_line_after_lpar = false
ij_c_function_call_arguments_new_line_before_rpar = false
ij_c_function_call_arguments_wrap = normal
ij_c_function_non_top_after_return_type_wrap = normal
ij_c_function_parameters_align_multiline = true
ij_c_function_parameters_align_multiline_pars = false
ij_c_function_parameters_comma_on_next_line = false
ij_c_function_parameters_new_line_after_lpar = false
ij_c_function_parameters_new_line_before_rpar = false
ij_c_function_parameters_wrap = normal
ij_c_function_top_after_return_type_wrap = normal
ij_c_generate_additional_eq_operators = true
ij_c_generate_additional_rel_operators = true
ij_c_generate_class_constructor = true
ij_c_generate_comparison_operators_use_std_tie = false
ij_c_generate_instance_variables_for_properties = ask
ij_c_generate_operators_as_members = true
ij_c_header_guard_style_pattern = ${PROJECT_NAME}_${FILE_NAME}_${EXT}
ij_c_if_brace_force = never
ij_c_in_line_short_ternary_operator = true
ij_c_indent_block_comment = true
ij_c_indent_c_struct_members = 4
ij_c_indent_case_from_switch = true
ij_c_indent_class_members = 4
ij_c_indent_directive_as_code = false
ij_c_indent_implementation_members = 0
ij_c_indent_inside_code_block = 4
ij_c_indent_interface_members = 0
ij_c_indent_interface_members_except_ivars_block = false
ij_c_indent_namespace_members = 4
ij_c_indent_preprocessor_directive = 0
ij_c_indent_visibility_keywords = 0
ij_c_insert_override = true
ij_c_insert_virtual_with_override = false
ij_c_introduce_auto_consts = false
ij_c_introduce_auto_vars = false
ij_c_introduce_const_params = false
ij_c_introduce_const_vars = false
ij_c_introduce_constexpr_consts = false
ij_c_introduce_generate_property = false
ij_c_introduce_generate_synthesize = true
ij_c_introduce_globals_to_header = true
ij_c_introduce_prop_to_private_category = false
ij_c_introduce_static_consts = true
ij_c_introduce_use_ns_types = false
ij_c_ivars_prefix = _
ij_c_ivars_suffix =
ij_c_keep_blank_lines_before_end = 2
ij_c_keep_blank_lines_before_right_brace = 2
ij_c_keep_blank_lines_in_code = 2
ij_c_keep_blank_lines_in_declarations = 2
ij_c_keep_case_expressions_in_one_line = false
ij_c_keep_control_statement_in_one_line = false
ij_c_keep_directive_at_first_column = true
ij_c_keep_first_column_comment = false
ij_c_keep_line_breaks = true
ij_c_keep_nested_namespaces_in_one_line = false
ij_c_keep_simple_blocks_in_one_line = false
ij_c_keep_simple_methods_in_one_line = false
ij_c_keep_structures_in_one_line = false
ij_c_lambda_capture_list_align_multiline = false
ij_c_lambda_capture_list_align_multiline_bracket = false
ij_c_lambda_capture_list_comma_on_next_line = false
ij_c_lambda_capture_list_new_line_after_lbracket = false
ij_c_lambda_capture_list_new_line_before_rbracket = false
ij_c_lambda_capture_list_wrap = off
ij_c_line_comment_add_space = false
ij_c_line_comment_at_first_column = true
ij_c_method_brace_placement = end_of_line
ij_c_method_call_arguments_align_by_colons = true
ij_c_method_call_arguments_align_multiline = false
ij_c_method_call_arguments_special_dictionary_pairs_treatment = true
ij_c_method_call_arguments_wrap = off
ij_c_method_call_chain_wrap = off
ij_c_method_parameters_align_by_colons = true
ij_c_method_parameters_align_multiline = false
ij_c_method_parameters_wrap = off
ij_c_namespace_brace_placement = next_line
ij_c_parentheses_expression_new_line_after_left_paren = false
ij_c_parentheses_expression_right_paren_on_new_line = false
ij_c_place_assignment_sign_on_next_line = false
ij_c_property_nonatomic = true
ij_c_put_ivars_to_implementation = true
ij_c_refactor_compatibility_aliases_and_classes = true
ij_c_refactor_properties_and_ivars = true
ij_c_release_style = ivar
ij_c_retain_object_parameters_in_constructor = true
ij_c_semicolon_after_method_signature = false
ij_c_shift_operation_align_multiline = true
ij_c_shift_operation_wrap = normal
ij_c_show_non_virtual_functions = false
ij_c_space_after_colon = true
ij_c_space_after_colon_in_foreach = true
ij_c_space_after_colon_in_selector = false
ij_c_space_after_comma = true
ij_c_space_after_cup_in_blocks = false
ij_c_space_after_dictionary_literal_colon = true
ij_c_space_after_for_semicolon = true
ij_c_space_after_init_list_colon = true
ij_c_space_after_method_parameter_type_parentheses = false
ij_c_space_after_method_return_type_parentheses = false
ij_c_space_after_pointer_in_declaration = false
ij_c_space_after_quest = true
ij_c_space_after_reference_in_declaration = false
ij_c_space_after_reference_in_rvalue = false
ij_c_space_after_structures_rbrace = true
ij_c_space_after_superclass_colon = true
ij_c_space_after_type_cast = false
ij_c_space_after_visibility_sign_in_method_declaration = true
ij_c_space_before_autorelease_pool_lbrace = true
ij_c_space_before_catch_keyword = true
ij_c_space_before_catch_left_brace = true
ij_c_space_before_catch_parentheses = false
ij_c_space_before_category_parentheses = true
ij_c_space_before_chained_send_message = true
ij_c_space_before_class_left_brace = true
ij_c_space_before_colon = true
ij_c_space_before_colon_in_foreach = true
ij_c_space_before_comma = false
ij_c_space_before_dictionary_literal_colon = true
ij_c_space_before_do_left_brace = true
ij_c_space_before_else_keyword = true
ij_c_space_before_else_left_brace = true
ij_c_space_before_export_lbrace = true
ij_c_space_before_for_left_brace = true
ij_c_space_before_for_parentheses = false
ij_c_space_before_for_semicolon = false
ij_c_space_before_if_left_brace = true
ij_c_space_before_if_parentheses = false
ij_c_space_before_init_list = false
ij_c_space_before_init_list_colon = true
ij_c_space_before_method_call_parentheses = false
ij_c_space_before_method_left_brace = true
ij_c_space_before_method_parentheses = false
ij_c_space_before_namespace_lbrace = true
ij_c_space_before_pointer_in_declaration = true
ij_c_space_before_property_attributes_parentheses = false
ij_c_space_before_protocols_brackets = true
ij_c_space_before_quest = true
ij_c_space_before_reference_in_declaration = true
ij_c_space_before_superclass_colon = true
ij_c_space_before_switch_left_brace = true
ij_c_space_before_switch_parentheses = false
ij_c_space_before_template_call_lt = false
ij_c_space_before_template_declaration_lt = true
ij_c_space_before_try_left_brace = true
ij_c_space_before_while_keyword = true
ij_c_space_before_while_left_brace = true
ij_c_space_before_while_parentheses = false
ij_c_space_between_adjacent_brackets = false
ij_c_space_between_operator_and_punctuator = false
ij_c_space_within_empty_array_initializer_braces = true
ij_c_spaces_around_additive_operators = true
ij_c_spaces_around_assignment_operators = true
ij_c_spaces_around_bitwise_operators = true
ij_c_spaces_around_equality_operators = true
ij_c_spaces_around_lambda_arrow = true
ij_c_spaces_around_logical_operators = true
ij_c_spaces_around_multiplicative_operators = true
ij_c_spaces_around_pm_operators = false
ij_c_spaces_around_relational_operators = true
ij_c_spaces_around_shift_operators = true
ij_c_spaces_around_unary_operator = false
ij_c_spaces_within_array_initializer_braces = true
ij_c_spaces_within_braces = false
ij_c_spaces_within_brackets = false
ij_c_spaces_within_cast_parentheses = false
ij_c_spaces_within_catch_parentheses = true
ij_c_spaces_within_category_parentheses = false
ij_c_spaces_within_empty_braces = false
ij_c_spaces_within_empty_function_call_parentheses = true
ij_c_spaces_within_empty_function_declaration_parentheses = true
ij_c_spaces_within_empty_lambda_capture_list_bracket = false
ij_c_spaces_within_empty_template_call_ltgt = false
ij_c_spaces_within_empty_template_declaration_ltgt = false
ij_c_spaces_within_for_parentheses = true
ij_c_spaces_within_function_call_parentheses = true
ij_c_spaces_within_function_declaration_parentheses = true
ij_c_spaces_within_if_parentheses = true
ij_c_spaces_within_lambda_capture_list_bracket = false
ij_c_spaces_within_method_parameter_type_parentheses = false
ij_c_spaces_within_method_return_type_parentheses = false
ij_c_spaces_within_parentheses = true
ij_c_spaces_within_property_attributes_parentheses = false
ij_c_spaces_within_protocols_brackets = false
ij_c_spaces_within_send_message_brackets = false
ij_c_spaces_within_structured_binding_list_bracket = false
ij_c_spaces_within_switch_parentheses = true
ij_c_spaces_within_template_call_ltgt = false
ij_c_spaces_within_template_declaration_ltgt = false
ij_c_spaces_within_template_double_gt = false
ij_c_spaces_within_while_parentheses = true
ij_c_special_else_if_treatment = true
ij_c_structured_binding_list_align_multiline = false
ij_c_structured_binding_list_align_multiline_bracket = false
ij_c_structured_binding_list_comma_on_next_line = false
ij_c_structured_binding_list_new_line_after_lbracket = false
ij_c_structured_binding_list_new_line_before_rbracket = false
ij_c_structured_binding_list_wrap = off
ij_c_superclass_list_after_colon = never
ij_c_superclass_list_align_multiline = true
ij_c_superclass_list_before_colon = if_long
ij_c_superclass_list_comma_on_next_line = false
ij_c_superclass_list_wrap = on_every_item
ij_c_tag_prefix_of_block_comment = at
ij_c_tag_prefix_of_line_comment = back_slash
ij_c_template_call_arguments_align_multiline = false
ij_c_template_call_arguments_align_multiline_pars = false
ij_c_template_call_arguments_comma_on_next_line = false
ij_c_template_call_arguments_new_line_after_lt = false
ij_c_template_call_arguments_new_line_before_gt = false
ij_c_template_call_arguments_wrap = off
ij_c_template_declaration_function_body_indent = false
ij_c_template_declaration_function_wrap = split_into_lines
ij_c_template_declaration_struct_body_indent = false
ij_c_template_declaration_struct_wrap = split_into_lines
ij_c_template_parameters_align_multiline = false
ij_c_template_parameters_align_multiline_pars = false
ij_c_template_parameters_comma_on_next_line = false
ij_c_template_parameters_new_line_after_lt = false
ij_c_template_parameters_new_line_before_gt = false
ij_c_template_parameters_wrap = off
ij_c_ternary_operation_signs_on_next_line = false
ij_c_ternary_operation_wrap = off
ij_c_type_qualifiers_placement = before
ij_c_use_modern_casts = true
ij_c_use_setters_in_constructor = true
ij_c_while_brace_force = never
ij_c_while_on_new_line = false
ij_c_wrap_property_declaration = off

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 - os: windows-2019 # always use the oldest possible for 32-bit because of older compilers, and better support of certain legacy OSes
targetos: win32 targetos: win32
targetarch: i386 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: env:
SDL_VERSION: 2.28.5 SDL_VERSION: 2.30.3
GH_CPU_ARCH: ${{ matrix.targetarch }} GH_CPU_ARCH: ${{ matrix.targetarch }}
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
- name: Install dependencies - name: Install dependencies
run: bash scripts/gha/deps_${{ matrix.targetos }}.sh run: bash scripts/gha/deps_${{ matrix.targetos }}.sh
- name: Build engine - name: Build engine
env:
FWGS_PFX_PASSWORD: ${{ secrets.FWGS_PFX_PASSWORD }}
run: bash scripts/gha/build_${{ matrix.targetos }}.sh run: bash scripts/gha/build_${{ matrix.targetos }}.sh
- name: Upload engine (artifacts) - name: Upload engine (artifacts)
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: artifact-${{ matrix.targetos }}-${{ matrix.targetarch }} name: artifact-${{ matrix.targetos }}-${{ matrix.targetarch }}
path: artifacts/* path: artifacts/*
flatpak: flatpak:
name: "Flatpak"
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
include: include:
- app: su.xash.Engine.Compat.i386 - app: su.xash.Engine.Compat.i386
container: container:
image: bilelmoussaoui/flatpak-github-actions:freedesktop-22.08 image: bilelmoussaoui/flatpak-github-actions:freedesktop-23.08
options: --privileged options: --privileged
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
- name: Build flatpak (Compat.i386) - name: Build flatpak (Compat.i386)
uses: FWGS/flatpak-github-actions/flatpak-builder@v6.1 uses: FWGS/flatpak-github-actions/flatpak-builder@v6.3
with: with:
bundle: ${{ matrix.app }}.flatpak bundle: ${{ matrix.app }}.flatpak
manifest-path: scripts/flatpak/${{ matrix.app }}.yml 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: release:
name: "Upload releases" name: "Upload releases"
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [build, flatpak] needs: [build, flatpak]
if: ${{ github.event_name == 'push' }} if: ${{ github.event_name == 'push' }}
steps: steps:
- name: Remove old release - name: Remove old release, fetch artifacts, repackage binaries and upload new release
uses: FWGS/delete-tag-and-release@v0.2.1-dev env:
with: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
tag_name: ${{ github.ref_name == 'master' && 'continuous' || format('continuous-{0}', github.ref_name) }} RELEASE_TAG: ${{ 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
run: | run: |
cd artifacts/ gh release delete "$RELEASE_TAG" \
for i in artifact-* su.xash.Engine.*; do --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"/* . mv "$i"/* .
rm -rf "$i" rm -rf "$i"
done done
ls -R . echo "Repackaged artifacts:"
cd ../ ls -R
popd
sleep 20s sleep 20s
- name: Upload new release gh release create "$RELEASE_TAG" artifacts/* \
uses: FWGS/action-gh-release@v0.1.15 --title "Xash3D FWGS Continuous ${{ github.ref_name }} Build" \
with: --target $GITHUB_SHA \
name: Xash3D FWGS Continuous ${{ github.ref_name }} Build --repo "$GITHUB_REPOSITORY" \
tag_name: ${{ github.ref_name == 'master' && 'continuous' || format('continuous-{0}', github.ref_name) }} --prerelease
prerelease: true
token: ${{ secrets.GITHUB_TOKEN }}
files: artifacts/*
draft: false

View File

@@ -13,3 +13,5 @@ When `-bugcomp` is specified with argument, it interpreted as flags separated wi
| Flag | Description | Games that require this flag | | Flag | Description | Games that require this flag |
| ------- | ----------- | ---------------------------- | | ------- | ----------- | ---------------------------- |
| `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 | | `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. | | `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 | | `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 | | `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 ## Note on GoldSrc liblist.gam support

View File

@@ -0,0 +1,40 @@
### HD (external) textures support
Xash3D supports loading texture replacements in TGA format for almost all types of models in the game, except alias models at this time.
Textures are expected to be located at:
* `modfolder/materials/<mapname>` - for a specific map
* `modfolder/materials/common` - common for all maps
* `modfolder/materials/decals` - for decals
* `modfolder/materials/models/<model>` - for models (texture name must match the internal texture name in the model)
Support for high-resolution textures is enabled setting `host_allow_materials` cvar to `1` or in the menu, in "Video options" section.
#### Xash3D FWGS additions
In addition to paths above, Xash3D FWGS checks following paths:
* `modfolder/materials/sprites/<sprite>` - for sprites, except HUD sprites
Also, to check which texture replacements are loaded successfully, failed or weren't found, a mod developer can set `host_allow_materials` cvar value to `2`. The engine will spew log at any developer level in the following format:
```
Looking for <replacement> replacement... <status code> (<path relative to mod directory>)
```
Status codes:
* `OK` - texture replacement file was found and loaded into GPU memory successfully
* `FAIL` - texture file was found but hasn't been parsed or loaded successfully. Refer to engine log for more details.
* `MISS` - texture file wasn't found
Example:
```
Looking for maps/bounce.bsp:!waterblue tex replacement...OK (materials/common/!waterblue.tga)
Looking for maps/bounce.bsp:!waterblue_luma tex replacement...MISS (not found)
Looking for {shot2 decal replacement...MISS (materials/decals/{shot2.tga)
Looking for {shot4 decal replacement...MISS (materials/decals/{shot4.tga)
Looking for {shot3 decal replacement...MISS (materials/decals/{shot3.tga)
Looking for models/gman tex replacement...FAIL (materials/models/gman/GMan_Case1.tga)
Looking for models/gman tex replacement...FAIL (materials/models/gman/inside_1.tga)
```

View File

@@ -19,7 +19,22 @@
- [List of XashXT-based mods](#list-of-xashxt-based-mods) - [List of XashXT-based mods](#list-of-xashxt-based-mods)
- [List of maps for They Hunger](#list-of-maps-for-they-hunger) - [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 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 # List of Half-Life-based mods
Originally this list was written by *Qwertyus*(*Qortez*) 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) 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) 144. [Optimum Fear](https://www.fileplanet.com/7472/0/fileinfo/Optimum-Fear)
145. [Outrun](http://www.moddb.com/mods/outrun) 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) 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/) 148. [P.I.Z.D.E.C.](https://www.runthinkshootlive.com/posts/pizdec/)
149. [pagoda](http://www.moddb.com/mods/pagoda1) 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/) 6. [Catacombs: Part 1](https://www.runthinkshootlive.com/posts/catacombs/)
7. [Cro-man's Office Mappack](http://twhl.info/vault.php?map=5547) 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) 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) 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) 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) 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/) 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) 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) 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) 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/) 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/) 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) 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) 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) 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) 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) 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**) 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) 9. [Soldier](http://www.moddb.com/mods/half-life-soldier)
10. [Solo Operations](http://www.moddb.com/mods/solo-operations) 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) 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/) 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) 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) 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) 55. [Deep](http://twhl.info/vault.php?map=1669)
56. [Desert Attack](http://fyzzer.narod.ru/index.html) 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) 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) 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/) 110. [Hostage](https://www.runthinkshootlive.com/posts/hostage-2/)
111. [House](http://www.artpeter.net/Data/HalfLife/Hl.php) 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*) 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://drive.google.com/file/d/1gOC8zfnUvBxRy8Rr8juNiUNbLYjoZpnn/view?usp=sharing) 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) 114. [In the Kitchen](http://twhl.info/vault.php?map=4314)
115. [Infiltration](https://www.fileplanet.com/7467/0/fileinfo/Infiltration) 115. [Infiltration](https://www.fileplanet.com/7467/0/fileinfo/Infiltration)
116. [Interactivity & Lots of Entities](http://twhl.info/vault.php?map=5744) (link dead!) 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/) \ [![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) [![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. Xash3D FWGS is a heavily modified fork of an original [Xash3D Engine](https://www.moddb.com/engines/xash3d-engine) by Unkle Mike.
@@ -28,7 +28,7 @@ If you like Xash3D FWGS, consider supporting individual engine maintainers. By s
1) Copy engine binaries to some directory. 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. 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). 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. You still needed to copy `valve` directory as all game resources located there.
3) Run the main executable (`xash3d.exe` or AppImage). 3) Run the main executable (`xash3d.exe` or AppImage).
@@ -46,11 +46,11 @@ NOTE: NEVER USE GitHub's ZIP ARCHIVES. GitHub doesn't include external dependenc
### Prerequisites ### 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! 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). 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) #### Windows (Visual Studio)
* Install Visual Studio. * Install Visual Studio.

View File

@@ -1,25 +0,0 @@
/*
boneinfo.h - structure that send delta-compressed bones across network
Copyright (C) 2018 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.
*/
#ifndef BONEINFO_H
#define BONEINFO_H
typedef struct
{
vec3_t angles;
vec3_t origin;
} boneinfo_t;
#endif//BONEINFO_H

View File

@@ -127,14 +127,23 @@ typedef struct
int flags; // sky or slime, no lightmap or 256 subdivision int flags; // sky or slime, no lightmap or 256 subdivision
} mtexinfo_t; } 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 glpoly2_s *next;
struct glpoly_s *chain; struct glpoly2_s *chain;
int numverts; int numverts;
int flags; // for SURF_UNDERWATER int flags; // for SURF_UNDERWATER
float verts[4][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2) #ifdef __cplusplus
} glpoly_t; 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 typedef struct mnode_s
{ {
@@ -173,7 +182,7 @@ struct decal_s
short entityIndex; // Entity this is attached to short entityIndex; // Entity this is attached to
// Xash3D specific // Xash3D specific
vec3_t position; // location of the decal center in world space. 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 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 int light_s, light_t; // gl lightmap coordinates
glpoly_t *polys; // multiple if warped glpoly2_t *polys; // multiple if warped
struct msurface_s *texturechain; struct msurface_s *texturechain;
mtexinfo_t *texinfo; mtexinfo_t *texinfo;
@@ -488,7 +497,8 @@ typedef struct
int flags; int flags;
float size; 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 numposes;
int poseverts; int poseverts;
@@ -531,17 +541,10 @@ typedef struct
#define MAX_MOVIES 8 #define MAX_MOVIES 8
#define MAX_CDTRACKS 32 #define MAX_CDTRACKS 32
#define MAX_CLIENT_SPRITES 512 // SpriteTextures (0-256 hud, 256-512 client) #define MAX_CLIENT_SPRITES 512 // SpriteTextures (0-256 hud, 256-512 client)
#define MAX_EFRAGS 8192 // Arcane Dimensions required
#define MAX_REQUESTS 64 #define MAX_REQUESTS 64
#if ! XASH_64BIT STATIC_CHECK_SIZEOF( mextrasurf_t, 324, 496 );
STATIC_ASSERT( sizeof( mextrasurf_t ) == 324, "mextrasurf_t unexpected size" ); STATIC_CHECK_SIZEOF( decal_t, 60, 88 );
STATIC_ASSERT( sizeof( decal_t ) == 60, "decal_t unexpected size"); STATIC_CHECK_SIZEOF( mfaceinfo_t, 176, 304 );
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
#endif//COM_MODEL_H #endif//COM_MODEL_H

View File

@@ -1,49 +1,122 @@
/*** /*
* cvardef.h - quake cvar definition
* Copyright (c) 1996-2002, Valve LLC. All rights reserved. Copyright (C) 1997-2001 Id Software, Inc.
* Copyright (C) 2024 Alibek Omarov
* 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
#define FCVAR_ARCHIVE (1<<0) // set to cause it to be saved to vars.rc This program is free software; you can redistribute it and/or
#define FCVAR_USERINFO (1<<1) // changes the client's info string modify it under the terms of the GNU General Public License
#define FCVAR_SERVER (1<<2) // notifies players when changed as published by the Free Software Foundation; either version 2
#define FCVAR_EXTDLL (1<<3) // defined by external DLL of the License, or (at your option) any later version.
#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
// Xash3D extensions This program is distributed in the hope that it will be useful,
#define FCVAR_GLCONFIG (1<<12) // write it into <renderer>.cfg(see RefAPI) but WITHOUT ANY WARRANTY; without even the implied warranty of
#define FCVAR_CHANGED (1<<13) // set each time the cvar is changed MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#define FCVAR_GAMEUIDLL (1<<14) // defined by the menu DLL
#define FCVAR_CHEAT (1<<15) // can not be changed if cheats are disabled
// a1ba: let's reuse higher bits for flags extensions from now on See the GNU General Public License for more details.
#define FCVAR_LATCH (1<<30) // notify client what this cvar will be applied only after server restart (but don't does more nothing)
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; // GoldSrc compatibility flags
char *string; FCVAR_ARCHIVE = 1 << 0, // set to cause it to be saved to vars.rc
int flags; FCVAR_USERINFO = 1 << 1, // added to userinfo when changed
float value; FCVAR_SERVER = 1 << 2, // added to serverinfo when changed, will notify clients by default
struct cvar_s *next; FCVAR_EXTDLL = 1 << 3, // defined by server.dll
} cvar_t; 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

@@ -1,5 +1,5 @@
/* /*
features.h - engine features that can be enabled by mod-maker request enginefeatures.h - engine features that can be enabled by mod-maker request
Copyright (C) 2012 Uncle Mike Copyright (C) 2012 Uncle Mike
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@@ -27,6 +27,7 @@ GNU General Public License for more details.
#define ENGINE_COMPUTE_STUDIO_LERP (1<<7) // enable MOVETYPE_STEP lerping back in engine #define ENGINE_COMPUTE_STUDIO_LERP (1<<7) // enable MOVETYPE_STEP lerping back in engine
#define ENGINE_LINEAR_GAMMA_SPACE (1<<8) // disable influence of gamma/brightness cvars to textures/lightmaps, for mods with custom renderer #define ENGINE_LINEAR_GAMMA_SPACE (1<<8) // disable influence of gamma/brightness cvars to textures/lightmaps, for mods with custom renderer
#define ENGINE_DISABLE_HDTEXTURES (1U<<30) // disable support of HD-textures in case custom renderer have separate way to load them
#define ENGINE_STEP_POSHISTORY_LERP (1U<<31) // enable MOVETYPE_STEP interpolation based on position history. Incompatible with ENGINE_COMPUTE_STUDIO_LERP! #define ENGINE_STEP_POSHISTORY_LERP (1U<<31) // enable MOVETYPE_STEP interpolation based on position history. Incompatible with ENGINE_COMPUTE_STUDIO_LERP!
// adjust the mask when features will be added or removed // adjust the mask when features will be added or removed

View File

@@ -30,7 +30,7 @@ GAMEINFO stuff
internal shared gameinfo structure (readonly for engine parts) internal shared gameinfo structure (readonly for engine parts)
======================================================================== ========================================================================
*/ */
typedef struct typedef struct GAMEINFO_s
{ {
// filesystem info // filesystem info
char gamefolder[64]; // used for change game '-game x' char gamefolder[64]; // used for change game '-game x'
@@ -50,4 +50,48 @@ typedef struct
int gamemode; int gamemode;
} GAMEINFO; } 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 #endif//GAMEINFO_H

View File

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

View File

@@ -27,6 +27,7 @@
// Set this flag for things like broadcast requests, etc. where the engine should not // Set this flag for things like broadcast requests, etc. where the engine should not
// kill the request hook after receiving the first response // kill the request hook after receiving the first response
#define FNETAPI_MULTIPLE_RESPONSE ( 1<<0 ) #define FNETAPI_MULTIPLE_RESPONSE ( 1<<0 )
#define FNETAPI_LEGACY_PROTOCOL ( 1<<1 ) // xash3d-fwgs extension
struct net_response_s; struct net_response_s;
typedef void (*net_api_response_func_t) ( struct net_response_s *response ); typedef void (*net_api_response_func_t) ( struct net_response_s *response );
@@ -35,6 +36,7 @@ typedef void (*net_api_response_func_t) ( struct net_response_s *response );
#define NET_ERROR_TIMEOUT ( 1<<0 ) #define NET_ERROR_TIMEOUT ( 1<<0 )
#define NET_ERROR_PROTO_UNSUPPORTED ( 1<<1 ) #define NET_ERROR_PROTO_UNSUPPORTED ( 1<<1 )
#define NET_ERROR_UNDEFINED ( 1<<2 ) #define NET_ERROR_UNDEFINED ( 1<<2 )
#define NET_ERROR_FORBIDDEN ( 1<<3 ) // xash3d-fwgs extension
typedef struct net_adrlist_s typedef struct net_adrlist_s
{ {

View File

@@ -69,6 +69,6 @@ typedef struct netadr_s
} netadr_t; } netadr_t;
#pragma pack( pop ) #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 #endif // NET_ADR_H

View File

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

View File

@@ -70,48 +70,64 @@ typedef uint64_t longtime_t;
#define IsColorString( p ) ( p && *( p ) == '^' && *(( p ) + 1) && *(( p ) + 1) >= '0' && *(( p ) + 1 ) <= '9' ) #define IsColorString( p ) ( p && *( p ) == '^' && *(( p ) + 1) && *(( p ) + 1) >= '0' && *(( p ) + 1 ) <= '9' )
#define ColorIndex( c ) ((( c ) - '0' ) & 7 ) #define ColorIndex( c ) ((( c ) - '0' ) & 7 )
#if defined(__GNUC__) #if defined( __GNUC__ )
#ifdef __i386__ #if defined( __i386__ )
#define EXPORT __attribute__ ((visibility ("default"),force_align_arg_pointer)) #define EXPORT __attribute__(( visibility( "default" ), force_align_arg_pointer ))
#define GAME_EXPORT __attribute((force_align_arg_pointer)) #define GAME_EXPORT __attribute(( force_align_arg_pointer ))
#else #else
#define EXPORT __attribute__ ((visibility ("default"))) #define EXPORT __attribute__(( visibility ( "default" )))
#define GAME_EXPORT #define GAME_EXPORT
#endif #endif
#define _format(x) __attribute__((format(printf, x, x+1)))
#define NORETURN __attribute__((noreturn)) #define MALLOC __attribute__(( malloc ))
#define NONNULL __attribute__((nonnull))
#define ALLOC_CHECK(x) __attribute__((alloc_size(x))) // added in GCC 11
#elif defined(_MSC_VER) #if __GNUC__ >= 11
#define EXPORT __declspec( dllexport ) // might want to set noclone due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116893
#define GAME_EXPORT // but it's easier to not force mismatched-dealloc to error yet
#define _format(x) #define MALLOC_LIKE( x, y ) __attribute__(( malloc( x, y )))
#define NORETURN #else
#define NONNULL #define MALLOC_LIKE( x, y ) MALLOC
#define ALLOC_CHECK(x) #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 #else
#define EXPORT #if defined( _MSC_VER )
#define EXPORT __declspec( dllexport )
#define NO_ASAN __declspec( no_sanitize_address )
#else
#define EXPORT
#define NO_ASAN
#endif
#define GAME_EXPORT #define GAME_EXPORT
#define _format(x)
#define NORETURN #define NORETURN
#define NONNULL #define NONNULL
#define ALLOC_CHECK(x) #define _format( x )
#define ALLOC_CHECK( x )
#define RENAME_SYMBOL( x )
#define MALLOC
#define MALLOC_LIKE( x, y )
#define WARN_UNUSED_RESULT
#endif #endif
#if ( __GNUC__ >= 3 ) #if __GNUC__ >= 3
#define unlikely(x) __builtin_expect(x, 0) #define unlikely( x ) __builtin_expect( x, 0 )
#define likely(x) __builtin_expect(x, 1) #define likely( x ) __builtin_expect( x, 1 )
#elif defined( __has_builtin ) #elif defined( __has_builtin )
#if __has_builtin( __builtin_expect ) #if __has_builtin( __builtin_expect ) // this must be after defined() check
#define unlikely(x) __builtin_expect(x, 0) #define unlikely( x ) __builtin_expect( x, 0 )
#define likely(x) __builtin_expect(x, 1) #define likely( x ) __builtin_expect( x, 1 )
#else
#define unlikely(x) (x)
#define likely(x) (x)
#endif #endif
#else #endif
#define unlikely(x) (x)
#define likely(x) (x) #if !defined( unlikely ) || !defined( likely )
#define unlikely( x ) ( x )
#define likely( x ) ( x )
#endif #endif
#if __STDC_VERSION__ >= 202311L || __cplusplus >= 201103L // C23 or C++ static_assert is a keyword #if __STDC_VERSION__ >= 202311L || __cplusplus >= 201103L // C23 or C++ static_assert is a keyword
@@ -128,6 +144,23 @@ typedef uint64_t longtime_t;
#define STATIC_ASSERT( x, y ) STATIC_ASSERT_2( __LINE__, x, y ) #define STATIC_ASSERT( x, y ) STATIC_ASSERT_2( __LINE__, x, y )
#endif #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
#define XASH_RESTRICT __restrict
#else
#define XASH_RESTRICT // nothing
#endif
#ifdef XASH_BIG_ENDIAN #ifdef XASH_BIG_ENDIAN
#define LittleLong(x) (((int)(((x)&255)<<24)) + ((int)((((x)>>8)&255)<<16)) + ((int)(((x)>>16)&255)<<8) + (((x) >> 24)&255)) #define LittleLong(x) (((int)(((x)&255)<<24)) + ((int)((((x)>>8)&255)<<16)) + ((int)(((x)>>16)&255)<<8) + (((x) >> 24)&255))
#define LittleLongSW(x) (x = LittleLong(x) ) #define LittleLongSW(x) (x = LittleLong(x) )
@@ -158,8 +191,9 @@ _inline float LittleFloat( float f )
#endif #endif
typedef unsigned int dword; typedef unsigned int dword;
typedef unsigned int uint; typedef unsigned int uint;
typedef unsigned long ulong;
typedef char string[MAX_STRING]; typedef char string[MAX_STRING];
typedef struct file_s file_t; // normal file typedef struct file_s file_t; // normal file
typedef struct stream_s stream_t; // sound stream for background music playing typedef struct stream_s stream_t; // sound stream for background music playing

View File

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

View File

@@ -274,6 +274,13 @@ void CL_GenericShot_f( void )
string checkname; string checkname;
int i; 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 ) if( type == scrshot_snapshot )
{ {
fmt = "../%s_%04d.png"; fmt = "../%s_%04d.png";
@@ -349,7 +356,7 @@ void CL_SetSky_f( void )
return; return;
} }
ref.dllFuncs.R_SetupSky( Cmd_Argv( 1 )); R_SetupSky( Cmd_Argv( 1 ));
} }
/* /*

View File

@@ -70,16 +70,17 @@ qboolean CL_CheckFile( sizebuf_t *msg, resource_t *pResource )
return true; return true;
} }
if( cl.downloadUrl[0] ) host.downloadcount++;
if( cl.http_download )
{ {
HTTP_AddDownload( filepath, pResource->nDownloadSize, true ); HTTP_AddDownload( filepath, pResource->nDownloadSize, true );
host.downloadcount++;
return false;
} }
else
MSG_BeginClientCmd( msg, clc_stringcmd ); {
MSG_WriteStringf( msg, "dlfile %s", filepath ); MSG_BeginClientCmd( msg, clc_stringcmd );
host.downloadcount++; MSG_WriteStringf( msg, "dlfile %s", filepath );
}
return false; return false;
} }
@@ -104,7 +105,7 @@ void CL_AddToResourceList( resource_t *pResource, resource_t *pList )
void CL_RemoveFromResourceList( resource_t *pResource ) void CL_RemoveFromResourceList( resource_t *pResource )
{ {
if( pResource->pPrev == NULL || pResource->pNext == NULL ) if( pResource->pPrev == NULL || pResource->pNext == NULL )
Host_Error( "mislinked resource in CL_RemoveFromResourceList\n" ); Host_Error( "mislinked resource in %s\n", __func__ );
if( pResource->pNext == pResource || pResource->pPrev == pResource ) if( pResource->pNext == pResource || pResource->pPrev == pResource )
Host_Error( "attempt to free last entry in list.\n" ); Host_Error( "attempt to free last entry in list.\n" );
@@ -119,7 +120,7 @@ void CL_MoveToOnHandList( resource_t *pResource )
{ {
if( !pResource ) if( !pResource )
{ {
Con_Reportf( "Null resource passed to CL_MoveToOnHandList\n" ); Con_Reportf( "Null resource passed to %s\n", __func__ );
return; return;
} }

View File

@@ -50,7 +50,29 @@ const char *CL_MsgInfo( int cmd )
if( cmd >= 0 && cmd <= svc_lastmsg ) if( cmd >= 0 && cmd <= svc_lastmsg )
{ {
// get engine message name // get engine message name
Q_strncpy( sz, svc_strings[cmd], sizeof( sz )); const char *svc_string = NULL;
switch( cls.legacymode )
{
case PROTO_CURRENT:
svc_string = svc_strings[cmd];
break;
case PROTO_LEGACY:
svc_string = svc_legacy_strings[cmd];
break;
case PROTO_QUAKE:
svc_string = svc_quake_strings[cmd];
break;
case PROTO_GOLDSRC:
svc_string = svc_goldsrc_strings[cmd];
break;
}
// fall back to current protocol strings
if( !svc_string )
svc_string = svc_strings[cmd];
Q_strncpy( sz, svc_string, sizeof( sz ));
} }
else if( cmd > svc_lastmsg && cmd <= ( svc_lastmsg + MAX_USER_MESSAGES )) else if( cmd > svc_lastmsg && cmd <= ( svc_lastmsg + MAX_USER_MESSAGES ))
{ {

View File

@@ -79,7 +79,7 @@ typedef struct
typedef struct typedef struct
{ {
demoentry_t *entries; // track entry info demoentry_t *entries; // track entry info
int numentries; // number of tracks int32_t numentries; // number of tracks
} demodirectory_t; } demodirectory_t;
// add angles // add angles
@@ -109,6 +109,40 @@ struct
static qboolean CL_NextDemo( void ); static qboolean CL_NextDemo( void );
static int CL_GetDemoNetProtocol( connprotocol_t proto )
{
switch( proto )
{
case PROTO_CURRENT:
return PROTOCOL_VERSION;
case PROTO_LEGACY:
return PROTOCOL_LEGACY_VERSION;
case PROTO_QUAKE:
return PROTOCOL_VERSION_QUAKE;
case PROTO_GOLDSRC:
return PROTOCOL_GOLDSRC_VERSION;
}
return PROTOCOL_VERSION;
}
static connprotocol_t CL_GetProtocolFromDemo( int net_protocol )
{
switch( net_protocol )
{
case PROTOCOL_VERSION:
return PROTO_CURRENT;
case PROTOCOL_LEGACY_VERSION:
return PROTO_LEGACY;
case PROTOCOL_VERSION_QUAKE:
return PROTO_QUAKE;
case PROTOCOL_GOLDSRC_VERSION:
return PROTO_GOLDSRC;
}
return PROTO_CURRENT;
}
/* /*
==================== ====================
CL_StartupDemoHeader CL_StartupDemoHeader
@@ -119,12 +153,8 @@ we record a demo on this level
*/ */
void CL_StartupDemoHeader( void ) void CL_StartupDemoHeader( void )
{ {
if( cls.demoheader ) CL_CloseDemoHeader();
{
FS_Close( cls.demoheader );
}
// Note: this is replacing tmpfile()
cls.demoheader = FS_Open( "demoheader.tmp", "w+b", true ); cls.demoheader = FS_Open( "demoheader.tmp", "w+b", true );
if( !cls.demoheader ) if( !cls.demoheader )
@@ -297,10 +327,6 @@ void CL_WriteDemoMessage( qboolean startup, int start, sizebuf_t *msg )
if( !file ) return; if( !file ) return;
// past the start but not recording a demo.
if( !startup && !cls.demorecording )
return;
swlen = MSG_GetNumBytesWritten( msg ) - start; swlen = MSG_GetNumBytesWritten( msg ) - start;
if( swlen <= 0 ) return; if( swlen <= 0 ) return;
@@ -373,7 +399,7 @@ static void CL_WriteDemoHeader( const char *name )
demo.header.id = IDEMOHEADER; demo.header.id = IDEMOHEADER;
demo.header.dem_protocol = DEMO_PROTOCOL; demo.header.dem_protocol = DEMO_PROTOCOL;
demo.header.net_protocol = cls.legacymode ? PROTOCOL_LEGACY_VERSION : PROTOCOL_VERSION; demo.header.net_protocol = CL_GetDemoNetProtocol( cls.legacymode );
demo.header.host_fps = host_maxfps.value ? bound( MIN_FPS, host_maxfps.value, MAX_FPS ) : MAX_FPS; demo.header.host_fps = host_maxfps.value ? bound( MIN_FPS, host_maxfps.value, MAX_FPS ) : MAX_FPS;
Q_strncpy( demo.header.mapname, clgame.mapname, sizeof( demo.header.mapname )); Q_strncpy( demo.header.mapname, clgame.mapname, sizeof( demo.header.mapname ));
Q_strncpy( demo.header.comment, clgame.maptitle, sizeof( demo.header.comment )); Q_strncpy( demo.header.comment, clgame.maptitle, sizeof( demo.header.comment ));
@@ -393,6 +419,7 @@ static void CL_WriteDemoHeader( const char *name )
// finish off the startup info. // finish off the startup info.
CL_WriteDemoCmdHeader( dem_stop, cls.demoheader ); CL_WriteDemoCmdHeader( dem_stop, cls.demoheader );
FS_Flush( cls.demoheader );
// now copy the stuff we cached from the server. // now copy the stuff we cached from the server.
copysize = savepos = FS_Tell( cls.demoheader ); copysize = savepos = FS_Tell( cls.demoheader );
@@ -1119,6 +1146,7 @@ show stats
*/ */
static void CL_FinishTimeDemo( void ) static void CL_FinishTimeDemo( void )
{ {
qboolean temp = host.allow_console;
int frames; int frames;
double time; double time;
@@ -1129,7 +1157,9 @@ static void CL_FinishTimeDemo( void )
time = host.realtime - cls.td_starttime; time = host.realtime - cls.td_starttime;
if( !time ) time = 1.0; 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 ); 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" )) if( Sys_CheckParm( "-timedemo" ))
CL_Quit_f(); CL_Quit_f();
@@ -1418,6 +1448,51 @@ void CL_Record_f( void )
CL_WriteDemoHeader( demopath ); 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 CL_PlayDemo_f
@@ -1438,9 +1513,7 @@ void CL_PlayDemo_f( void )
} }
if( cls.demoplayback ) if( cls.demoplayback )
{
CL_StopPlayback(); CL_StopPlayback();
}
if( cls.demorecording ) if( cls.demorecording )
{ {
@@ -1490,51 +1563,32 @@ void CL_PlayDemo_f( void )
if( neg ) cls.forcetrack = -cls.forcetrack; if( neg ) cls.forcetrack = -cls.forcetrack;
CL_DemoStartPlayback( DEMO_QUAKE1 ); CL_DemoStartPlayback( DEMO_QUAKE1 );
cls.legacymode = PROTO_QUAKE;
return; // quake demo is started return; // quake demo is started
} }
// read in the demo header // read in the demo header
FS_Read( cls.demofile, &demo.header, sizeof( demoheader_t )); if( !CL_ParseDemoHeader( Cmd_Argv( 0 ), filename, cls.demofile, &demo.header, &demo.directory.numentries ))
if( demo.header.id != IDEMOHEADER )
{ {
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(); CL_DemoAborted();
return; return;
} }
// allocate demo entries // 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++ ) 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; demo.entryIndex = 0;
@@ -1544,9 +1598,11 @@ void CL_PlayDemo_f( void )
CL_DemoStartPlayback( DEMO_XASH3D ); CL_DemoStartPlayback( DEMO_XASH3D );
// must be after DemoStartPlayback, as CL_Disconnect_f resets the protocol
cls.legacymode = CL_GetProtocolFromDemo( demo.header.net_protocol );
// g-cont. is this need? // g-cont. is this need?
Q_strncpy( cls.servername, demoname, sizeof( cls.servername )); Q_strncpy( cls.servername, demoname, sizeof( cls.servername ));
cls.legacymode = demo.header.net_protocol == PROTOCOL_LEGACY_VERSION;
// begin a playback demo // begin a playback demo
} }
@@ -1588,7 +1644,7 @@ void CL_StartDemos_f( void )
c = Cmd_Argc() - 1; c = Cmd_Argc() - 1;
if( c > MAX_DEMOS ) if( c > MAX_DEMOS )
{ {
Con_DPrintf( S_WARN "Host_StartDemos: max %i demos in demoloop\n", MAX_DEMOS ); Con_DPrintf( S_WARN "%s: max %i demos in demoloop\n", __func__, MAX_DEMOS );
c = MAX_DEMOS; c = MAX_DEMOS;
} }
@@ -1646,3 +1702,78 @@ void CL_Stop_f( void )
S_StopBackgroundTrack(); 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 efrag_t **lastlink;
static mnode_t *r_pefragtopnode; static mnode_t *r_pefragtopnode;
static vec3_t r_emins, r_emaxs; static vec3_t r_emins, r_emaxs;
static cl_entity_t *r_addent; 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; leaf = (mleaf_t *)node;
// grab an efrag off the free list // grab an efrag off the free list
ef = clgame.free_efrags; ef = cl_efrags;
if( !ef ) if( !ef )
{ ef = CL_AllocEfrags( NUM_EFRAGS_ALLOC );
Con_Printf( S_ERROR "too many efrags!\n" );
return; // no free fragments...
}
clgame.free_efrags = ef->entnext; cl_efrags = ef->entnext;
ef->entity = r_addent; ef->entity = r_addent;
// add the entity link // add the entity link
@@ -133,35 +171,29 @@ R_StoreEfrags
*/ */
void R_StoreEfrags( efrag_t **ppefrag, int framecount ) void R_StoreEfrags( efrag_t **ppefrag, int framecount )
{ {
cl_entity_t *pent; efrag_t *pefrag;
model_t *clmodel; cl_entity_t *pent;
efrag_t *pefrag; model_t *clmodel;
while(( pefrag = *ppefrag ) != NULL ) while(( pefrag = *ppefrag ) != NULL )
{ {
pent = pefrag->entity; pent = pefrag->entity;
clmodel = pent->model; clmodel = pent->model;
switch( clmodel->type ) // how this could happen?
{ if( unlikely( clmodel->type < mod_brush || clmodel->type > mod_studio ))
case mod_alias: continue;
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;
}
}
ppefrag = &pefrag->leafnext; if( pent->visframe != framecount )
break; {
default: if( CL_AddVisibleEntity( pent, ET_FRAGMENTED ))
break; {
// mark that we've recorded this entity for this frame
pent->curstate.messagenum = cl.parsecount;
pent->visframe = framecount;
}
} }
ppefrag = &pefrag->leafnext;
} }
} }

View File

@@ -250,7 +250,7 @@ static particle_t *R_AllocTracer( const vec3_t org, const vec3_t vel, float life
VectorCopy( vel, p->vel ); VectorCopy( vel, p->vel );
p->die = cl.time + life; p->die = cl.time + life;
p->ramp = tracerlength.value; p->ramp = tracerlength.value;
p->color = 4; // select custom color p->color = TRACER_COLORINDEX_DEFAULT; // select custom color
p->packedColor = 255; // alpha p->packedColor = 255; // alpha
return p; return p;
@@ -636,12 +636,24 @@ and all particle trails (if this is a beamfollow)
*/ */
void GAME_EXPORT R_BeamKill( int deadEntity ) void GAME_EXPORT R_BeamKill( int deadEntity )
{ {
cl_entity_t *pDeadEntity; BEAM *beam;
pDeadEntity = R_BeamGetEntity( deadEntity ); for( beam = cl_active_beams; beam; beam = beam->next )
if( !pDeadEntity ) return; {
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 +1106,7 @@ void GAME_EXPORT R_ParticleExplosion2( const vec3_t org, int colorStart, int col
int colorMod = 0, packedColor; int colorMod = 0, packedColor;
particle_t *p; particle_t *p;
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE )) packedColor = Host_IsQuakeCompatible( ) ? 255 : 0; // use old code for blob particles
packedColor = 255; // use old code for blob particles
else packedColor = 0;
for( i = 0; i < 512; i++ ) for( i = 0; i < 512; i++ )
{ {
@@ -1129,9 +1139,7 @@ void GAME_EXPORT R_BlobExplosion( const vec3_t org )
particle_t *p; particle_t *p;
int i, j, packedColor; int i, j, packedColor;
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE )) packedColor = Host_IsQuakeCompatible( ) ? 255 : 0; // use old code for blob particles
packedColor = 255; // use old code for blob particles
else packedColor = 0;
for( i = 0; i < 1024; i++ ) for( i = 0; i < 1024; i++ )
{ {

View File

@@ -192,7 +192,7 @@ void CL_RegisterEvent( int lastnum, const char *szEvName, pfnEventHook func )
ev = clgame.events[lastnum]; ev = clgame.events[lastnum];
// NOTE: ev->index will be set later // NOTE: ev->index will be set later
Q_strncpy( ev->name, szEvName, MAX_QPATH ); Q_strncpy( ev->name, szEvName, sizeof( ev->name ));
ev->func = func; ev->func = func;
} }
@@ -219,7 +219,7 @@ static qboolean CL_FireEvent( event_info_t *ei, int slot )
if( !ev ) if( !ev )
{ {
idx = bound( 1, ei->index, ( MAX_EVENTS - 1 )); idx = bound( 1, ei->index, ( MAX_EVENTS - 1 ));
Con_Reportf( S_ERROR "CL_FireEvent: %s not precached\n", cl.event_precache[idx] ); Con_Reportf( S_ERROR "%s: %s not precached\n", __func__, cl.event_precache[idx] );
break; break;
} }
@@ -244,7 +244,7 @@ static qboolean CL_FireEvent( event_info_t *ei, int slot )
return true; return true;
} }
Con_Reportf( S_ERROR "CL_FireEvent: %s not hooked\n", name ); Con_Reportf( S_ERROR "%s: %s not hooked\n", __func__, name );
break; break;
} }
} }
@@ -497,14 +497,14 @@ void GAME_EXPORT CL_PlaybackEvent( int flags, const edict_t *pInvoker, word even
// first check event for out of bounds // first check event for out of bounds
if( eventindex < 1 || eventindex >= MAX_EVENTS ) if( eventindex < 1 || eventindex >= MAX_EVENTS )
{ {
Con_DPrintf( S_ERROR "CL_PlaybackEvent: invalid eventindex %i\n", eventindex ); Con_DPrintf( S_ERROR "%s: invalid eventindex %i\n", __func__, eventindex );
return; return;
} }
// check event for precached // check event for precached
if( !CL_EventIndex( cl.event_precache[eventindex] )) if( !CL_EventIndex( cl.event_precache[eventindex] ))
{ {
Con_DPrintf( S_ERROR "CL_PlaybackEvent: event %i was not precached\n", eventindex ); Con_DPrintf( S_ERROR "%s: event %i was not precached\n", __func__, eventindex );
return; return;
} }

View File

@@ -95,8 +95,7 @@ static void CL_ResetPositions( cl_entity_t *ent )
ent->current_position = 1; ent->current_position = 1;
memset( ent->ph, 0, sizeof( position_history_t ) * HISTORY_MAX ); memset( ent->ph, 0, sizeof( position_history_t ) * HISTORY_MAX );
memcpy( &ent->ph[1], &store, sizeof( position_history_t )); ent->ph[1] = ent->ph[0] = store;
memcpy( &ent->ph[0], &store, sizeof( position_history_t ));
} }
/* /*
@@ -712,7 +711,7 @@ static void CL_FlushEntityPacket( sizebuf_t *msg )
break; // done break; // done
if( MSG_CheckOverflow( msg )) if( MSG_CheckOverflow( msg ))
Host_Error( "CL_FlushEntityPacket: overflow\n" ); Host_Error( "%s: overflow\n", __func__ );
MSG_ReadDeltaEntity( msg, &from, &to, newnum, CL_IsPlayerIndex( newnum ) ? DELTA_PLAYER : DELTA_ENTITY, cl.mtime[0] ); MSG_ReadDeltaEntity( msg, &from, &to, newnum, CL_IsPlayerIndex( newnum ) ? DELTA_PLAYER : DELTA_ENTITY, cl.mtime[0] );
} }
@@ -740,7 +739,7 @@ static void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_s
if(( newnum < 0 ) || ( newnum >= clgame.maxEntities )) if(( newnum < 0 ) || ( newnum >= clgame.maxEntities ))
{ {
Con_DPrintf( S_ERROR "CL_DeltaEntity: invalid newnum: %d\n", newnum ); Con_DPrintf( S_ERROR "%s: invalid newnum: %d\n", __func__, newnum );
if( has_update ) if( has_update )
MSG_ReadDeltaEntity( msg, old, state, newnum, delta_type, cl.mtime[0] ); MSG_ReadDeltaEntity( msg, old, state, newnum, delta_type, cl.mtime[0] );
return; return;
@@ -752,7 +751,7 @@ static void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_s
if( has_update ) if( has_update )
alive = MSG_ReadDeltaEntity( msg, old, state, newnum, delta_type, cl.mtime[0] ); 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 ) if( !alive )
{ {
@@ -885,7 +884,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
break; // done break; // done
if( MSG_CheckOverflow( msg )) if( MSG_CheckOverflow( msg ))
Host_Error( "CL_ParsePacketEntities: overflow\n" ); Host_Error( "%s: overflow\n", __func__ );
player = CL_IsPlayerIndex( newnum ); player = CL_IsPlayerIndex( newnum );
@@ -955,7 +954,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
} }
if( newframe->num_entities != count && newframe->num_entities != 0 ) if( newframe->num_entities != count && newframe->num_entities != 0 )
Con_Reportf( S_WARN "CL_Parse%sPacketEntities: (%i should be %i)\n", delta ? "Delta" : "", newframe->num_entities, count ); Con_Reportf( S_WARN "%s%s: (%i should be %i)\n", __func__, delta ? "Delta" : "", newframe->num_entities, count );
if( !newframe->valid ) if( !newframe->valid )
return playerbytes; // frame is not valid but message was parsed return playerbytes; // frame is not valid but message was parsed
@@ -1187,7 +1186,7 @@ static void CL_LinkPacketEntities( frame_t *frame )
if( !ent ) if( !ent )
{ {
Con_Reportf( S_ERROR "CL_LinkPacketEntity: bad entity %i\n", state->number ); Con_Reportf( S_ERROR "%s: bad entity %i\n", __func__, state->number );
continue; continue;
} }

View File

@@ -231,7 +231,7 @@ static void CL_InitCDAudio( const char *filename )
if( ++c > MAX_CDTRACKS - 1 ) if( ++c > MAX_CDTRACKS - 1 )
{ {
Con_Reportf( S_WARN "CD_Init: too many tracks %i in %s\n", MAX_CDTRACKS, filename ); Con_Reportf( S_WARN "%s: too many tracks %i in %s\n", __func__, MAX_CDTRACKS, filename );
break; break;
} }
} }
@@ -560,7 +560,19 @@ static void CL_DrawScreenFade( void )
if( !alpha ) if( !alpha )
return; 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 ); ref.dllFuncs.GL_SetRenderMode( kRenderScreenFadeModulate );
@@ -570,11 +582,6 @@ static void CL_DrawScreenFade( void )
(uint16_t)( sf->fadeb * alpha + ( 255 - alpha ) * 255 ) >> 8, (uint16_t)( sf->fadeb * alpha + ( 255 - alpha ) * 255 ) >> 8,
255 ); 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, ref.dllFuncs.R_DrawStretchPic( 0, 0, refState.width, refState.height, 0, 0, 1, 1,
R_GetBuiltinTexture( REF_WHITE_TEXTURE )); R_GetBuiltinTexture( REF_WHITE_TEXTURE ));
@@ -777,14 +784,14 @@ static const char *CL_SoundFromIndex( int index )
if( !hSound ) if( !hSound )
{ {
Con_DPrintf( S_ERROR "CL_SoundFromIndex: invalid sound index %i\n", index ); Con_DPrintf( S_ERROR "%s: invalid sound index %i\n", __func__, index );
return NULL; return NULL;
} }
sfx = S_GetSfxByHandle( hSound ); sfx = S_GetSfxByHandle( hSound );
if( !sfx ) if( !sfx )
{ {
Con_DPrintf( S_ERROR "CL_SoundFromIndex: bad sfx for index %i\n", index ); Con_DPrintf( S_ERROR "%s: bad sfx for index %i\n", __func__, index );
return NULL; return NULL;
} }
@@ -1041,10 +1048,10 @@ void CL_LinkUserMessage( char *pszName, const int svc_num, int iSize )
int i; int i;
if( !pszName || !*pszName ) if( !pszName || !*pszName )
Host_Error( "CL_LinkUserMessage: bad message name\n" ); Host_Error( "%s: bad message name\n", __func__ );
if( svc_num <= svc_lastmsg ) if( svc_num <= svc_lastmsg )
Host_Error( "CL_LinkUserMessage: tried to hook a system message \"%s\"\n", svc_strings[svc_num] ); Host_Error( "%s: tried to hook a system message \"%s\"\n", __func__, svc_strings[svc_num] );
// see if already hooked // see if already hooked
for( i = 0; i < MAX_USER_MESSAGES && clgame.msg[i].name[0]; i++ ) for( i = 0; i < MAX_USER_MESSAGES && clgame.msg[i].name[0]; i++ )
@@ -1061,7 +1068,7 @@ void CL_LinkUserMessage( char *pszName, const int svc_num, int iSize )
if( i == MAX_USER_MESSAGES ) if( i == MAX_USER_MESSAGES )
{ {
Host_Error( "CL_LinkUserMessage: MAX_USER_MESSAGES hit!\n" ); Host_Error( "%s: MAX_USER_MESSAGES hit!\n", __func__ );
return; return;
} }
@@ -1182,7 +1189,7 @@ static qboolean CL_LoadHudSprite( const char *szSpriteName, model_t *m_pSprite,
if( type == SPR_CLIENT || type == SPR_HUDSPRITE ) if( type == SPR_CLIENT || type == SPR_HUDSPRITE )
SetBits( m_pSprite->flags, MODEL_CLIENT ); 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 ) ) if( !FS_FileExists( szSpriteName, false ) )
{ {
@@ -1209,7 +1216,7 @@ static qboolean CL_LoadHudSprite( const char *szSpriteName, model_t *m_pSprite,
ref.dllFuncs.Mod_LoadMapSprite( m_pSprite, buf, size, &loaded ); ref.dllFuncs.Mod_LoadMapSprite( m_pSprite, buf, size, &loaded );
else else
{ {
Mod_LoadSpriteModel( m_pSprite, buf, &loaded, texFlags ); Mod_LoadSpriteModel( m_pSprite, buf, &loaded );
ref.dllFuncs.Mod_ProcessRenderData( m_pSprite, true, buf ); ref.dllFuncs.Mod_ProcessRenderData( m_pSprite, true, buf );
} }
@@ -1242,7 +1249,7 @@ static model_t *CL_LoadSpriteModel( const char *filename, uint type, uint texFla
if( !COM_CheckString( filename )) if( !COM_CheckString( filename ))
{ {
Con_Reportf( S_ERROR "CL_LoadSpriteModel: bad name!\n" ); Con_Reportf( S_ERROR "%s: bad name!\n", __func__ );
return NULL; return NULL;
} }
@@ -1503,12 +1510,12 @@ static void GAME_EXPORT pfnSPR_DrawAdditive( int frame, int x, int y, const wrec
/* /*
========= =========
pfnSPR_GetList SPR_GetList
for parsing half-life scripts - hud.txt etc for parsing half-life scripts - hud.txt etc
========= =========
*/ */
static client_sprite_t *pfnSPR_GetList( char *psz, int *piCount ) static client_sprite_t *SPR_GetList( char *psz, int *piCount )
{ {
cached_spritelist_t *pEntry = &clgame.sprlist[0]; cached_spritelist_t *pEntry = &clgame.sprlist[0];
int slot, index, numSprites = 0; int slot, index, numSprites = 0;
@@ -1534,7 +1541,7 @@ static client_sprite_t *pfnSPR_GetList( char *psz, int *piCount )
if( slot == MAX_CLIENT_SPRITES ) if( slot == MAX_CLIENT_SPRITES )
{ {
Con_Printf( S_ERROR "SPR_GetList: overflow cache!\n" ); Con_Printf( S_ERROR "%s: overflow cache!\n", __func__ );
return NULL; return NULL;
} }
@@ -1743,7 +1750,7 @@ static int GAME_EXPORT pfnHookUserMsg( const char *pszName, pfnUserMsgHook pfn )
if( i == MAX_USER_MESSAGES ) if( i == MAX_USER_MESSAGES )
{ {
Host_Error( "HookUserMsg: MAX_USER_MESSAGES hit!\n" ); Host_Error( "%s: MAX_USER_MESSAGES hit!\n", __func__ );
return 0; return 0;
} }
@@ -2293,7 +2300,7 @@ static void GAME_EXPORT pfnHookEvent( const char *filename, pfnEventHook pfn )
if( !Q_stricmp( name, ev->name ) && ev->func != NULL ) if( !Q_stricmp( name, ev->name ) && ev->func != NULL )
{ {
Con_Reportf( S_WARN "CL_HookEvent: %s already hooked!\n", name ); Con_Reportf( S_WARN "%s: %s already hooked!\n", __func__, name );
return; return;
} }
} }
@@ -2376,7 +2383,7 @@ static int GAME_EXPORT CL_FindModelIndex( const char *m )
if( lasttimewarn < host.realtime ) if( lasttimewarn < host.realtime )
{ {
// tell user about problem (but don't spam console) // tell user about problem (but don't spam console)
Con_Printf( S_ERROR "Could not find index for model %s: not precached\n", filepath ); Con_DPrintf( S_ERROR "Could not find index for model %s: not precached\n", filepath );
lasttimewarn = host.realtime + 1.0f; lasttimewarn = host.realtime + 1.0f;
} }
@@ -2428,8 +2435,8 @@ static void GAME_EXPORT pfnLocalPlayerBounds( int hull, float *mins, float *maxs
{ {
if( hull >= 0 && hull < 4 ) if( hull >= 0 && hull < 4 )
{ {
if( mins ) VectorCopy( clgame.pmove->player_mins[hull], mins ); if( mins ) VectorCopy( host.player_mins[hull], mins );
if( maxs ) VectorCopy( clgame.pmove->player_maxs[hull], maxs ); if( maxs ) VectorCopy( host.player_maxs[hull], maxs );
} }
} }
@@ -2497,9 +2504,17 @@ CL_PushTraceBounds
*/ */
static void GAME_EXPORT CL_PushTraceBounds( int hullnum, const float *mins, const float *maxs ) 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 ); hullnum = bound( 0, hullnum, 3 );
VectorCopy( mins, clgame.pmove->player_mins[hullnum] ); VectorCopy( mins, host.player_mins[hullnum] );
VectorCopy( maxs, clgame.pmove->player_maxs[hullnum] ); VectorCopy( maxs, host.player_maxs[hullnum] );
} }
/* /*
@@ -2510,8 +2525,15 @@ CL_PopTraceBounds
*/ */
static void GAME_EXPORT CL_PopTraceBounds( void ) static void GAME_EXPORT CL_PopTraceBounds( void )
{ {
memcpy( clgame.pmove->player_mins, host.player_mins, sizeof( host.player_mins )); if( !host.trace_bounds_pushed )
memcpy( clgame.pmove->player_maxs, host.player_maxs, sizeof( host.player_maxs )); {
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 ));
} }
/* /*
@@ -2788,10 +2810,10 @@ static void GAME_EXPORT PlayerInfo_SetValueForKey( const char *key, const char *
{ {
Cvar_DirectSet( var, value ); Cvar_DirectSet( var, value );
} }
else if( Info_SetValueForStarKey( cls.userinfo, key, value, MAX_INFO_STRING )) else if( Info_SetValueForStarKey( cls.userinfo, key, value, sizeof( cls.userinfo )))
{ {
// time to update server copy of userinfo // time to update server copy of userinfo
CL_ServerCommand( true, "setinfo \"%s\" \"%s\"\n", key, value ); CL_UpdateInfo( key, value );
} }
} }
@@ -3283,7 +3305,7 @@ Heavy legacy of Quake...
*/ */
void TriColor4fRendermode( float r, float g, float b, float a, int rendermode ) 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; clgame.ds.triRGBA[3] = a / 255.0f;
ref.dllFuncs.Color4f( r, g, b, a ); ref.dllFuncs.Color4f( r, g, b, a );
@@ -3415,16 +3437,15 @@ 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 ) 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; net_request_t *nr = NULL;
string req;
int i; int i;
if( !response ) if( !response )
{ {
Con_DPrintf( S_ERROR "Net_SendRequest: no callbcak specified for request with context %i!\n", context ); Con_DPrintf( S_ERROR "%s: no callbcak specified for request with context %i!\n", __func__, context );
return; return;
} }
if( remote_address->type != NA_IPX && remote_address->type != NA_BROADCAST_IPX ) if( remote_address->type == NA_IPX || remote_address->type == NA_BROADCAST_IPX )
return; // IPX no longer support return; // IPX no longer support
if( request == NETAPI_REQUEST_SERVERLIST ) if( request == NETAPI_REQUEST_SERVERLIST )
@@ -3467,8 +3488,7 @@ static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags,
nr->flags = flags; nr->flags = flags;
// local servers request // local servers request
Q_snprintf( req, sizeof( req ), "netinfo %i %i %i", PROTOCOL_VERSION, context, request ); Netchan_OutOfBandPrint( NS_CLIENT, nr->resp.remote_address, "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 );
} }
/* /*
@@ -3772,7 +3792,7 @@ static demo_api_t gDemoApi =
Demo_WriteBuffer, Demo_WriteBuffer,
}; };
static net_api_t gNetApi = net_api_t gNetApi =
{ {
NetAPI_InitNetworking, NetAPI_InitNetworking,
NetAPI_Status, NetAPI_Status,
@@ -3808,7 +3828,7 @@ static cl_enginefunc_t gEngfuncs =
pfnSPR_DrawAdditive, pfnSPR_DrawAdditive,
SPR_EnableScissor, SPR_EnableScissor,
SPR_DisableScissor, SPR_DisableScissor,
pfnSPR_GetList, SPR_GetList,
CL_FillRGBA, CL_FillRGBA,
CL_GetScreenInfo, CL_GetScreenInfo,
pfnSetCrosshair, pfnSetCrosshair,
@@ -4030,14 +4050,14 @@ qboolean CL_LoadProgs( const char *name )
// trying to get single export // trying to get single export
if(( GetClientAPI = (void *)COM_GetProcAddress( clgame.hInstance, "GetClientAPI" )) != NULL ) if(( GetClientAPI = (void *)COM_GetProcAddress( clgame.hInstance, "GetClientAPI" )) != NULL )
{ {
Con_Reportf( "CL_LoadProgs: found single callback export\n" ); Con_Reportf( "%s: found single callback export\n", __func__ );
// trying to fill interface now // trying to fill interface now
GetClientAPI( &clgame.dllFuncs ); GetClientAPI( &clgame.dllFuncs );
} }
else if(( GetClientAPI = (void *)COM_GetProcAddress( clgame.hInstance, "F" )) != NULL ) else if(( GetClientAPI = (void *)COM_GetProcAddress( clgame.hInstance, "F" )) != NULL )
{ {
Con_Reportf( "CL_LoadProgs: found single callback export (secured client dlls)\n" ); Con_Reportf( "%s: found single callback export (secured client dlls)\n", __func__ );
// trying to fill interface now // trying to fill interface now
CL_GetSecuredClientAPI( GetClientAPI ); CL_GetSecuredClientAPI( GetClientAPI );
@@ -4065,7 +4085,7 @@ qboolean CL_LoadProgs( const char *name )
// functions are cleared before all the extensions are evaluated // functions are cleared before all the extensions are evaluated
if(( *func->func = (void *)COM_GetProcAddress( clgame.hInstance, func->name )) == NULL ) if(( *func->func = (void *)COM_GetProcAddress( clgame.hInstance, func->name )) == NULL )
{ {
Con_Reportf( "CL_LoadProgs: failed to get address of %s proc\n", func->name ); Con_Reportf( "%s: failed to get address of %s proc\n", __func__, func->name );
if( critical_exports ) if( critical_exports )
{ {
@@ -4092,13 +4112,13 @@ qboolean CL_LoadProgs( const char *name )
// functions are cleared before all the extensions are evaluated // functions are cleared before all the extensions are evaluated
// NOTE: new exports can be missed without stop the engine // NOTE: new exports can be missed without stop the engine
if(( *func->func = (void *)COM_GetProcAddress( clgame.hInstance, func->name )) == NULL ) if(( *func->func = (void *)COM_GetProcAddress( clgame.hInstance, func->name )) == NULL )
Con_Reportf( "CL_LoadProgs: failed to get address of %s proc\n", func->name ); Con_Reportf( "%s: failed to get address of %s proc\n", __func__, func->name );
} }
if( !clgame.dllFuncs.pfnInitialize( &gEngfuncs, CLDLL_INTERFACE_VERSION )) if( !clgame.dllFuncs.pfnInitialize( &gEngfuncs, CLDLL_INTERFACE_VERSION ))
{ {
COM_FreeLibrary( clgame.hInstance ); COM_FreeLibrary( clgame.hInstance );
Con_Reportf( "CL_LoadProgs: can't init client API\n" ); Con_Reportf( "%s: can't init client API\n", __func__ );
clgame.hInstance = NULL; clgame.hInstance = NULL;
return false; return false;
} }
@@ -4115,10 +4135,10 @@ qboolean CL_LoadProgs( const char *name )
CL_InitTempEnts (); CL_InitTempEnts ();
if( !R_InitRenderAPI()) // Xash3D extension if( !R_InitRenderAPI()) // Xash3D extension
Con_Reportf( S_WARN "CL_LoadProgs: couldn't get render API\n" ); Con_Reportf( S_WARN "%s: couldn't get render API\n", __func__ );
if( !Mobile_Init() ) // Xash3D FWGS extension: mobile interface if( !Mobile_Init() ) // Xash3D FWGS extension: mobile interface
Con_Reportf( S_WARN "CL_LoadProgs: couldn't get mobility API\n" ); Con_Reportf( S_WARN "%s: couldn't get mobility API\n", __func__ );
CL_InitEdicts( cl.maxclients ); // initailize local player and world CL_InitEdicts( cl.maxclients ); // initailize local player and world
CL_InitClientMove(); // initialize pm_shared CL_InitClientMove(); // initialize pm_shared

View File

@@ -25,6 +25,14 @@ static void UI_UpdateUserinfo( void );
gameui_static_t gameui; 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 ) void UI_UpdateMenu( float realtime )
{ {
if( !gameui.hInstance ) return; if( !gameui.hInstance ) return;
@@ -216,12 +224,14 @@ UI_ShowConnectionWarning
show message box show message box
================= =================
*/ */
void UI_ShowMessageBox( const char *text ) qboolean UI_ShowMessageBox( const char *text )
{ {
if( gameui.dllFuncs2.pfnShowMessageBox ) if( gameui.dllFuncs2.pfnShowMessageBox )
{ {
gameui.dllFuncs2.pfnShowMessageBox( text ); gameui.dllFuncs2.pfnShowMessageBox( text );
return true;
} }
return false;
} }
void UI_ConnectionProgress_Disconnect( void ) void UI_ConnectionProgress_Disconnect( void )
@@ -397,17 +407,21 @@ void Host_Credits( void )
gameui.dllFuncs.pfnFinalCredits(); 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->gamefolder, in->gamefolder, sizeof( out->gamefolder ));
Q_strncpy( out->startmap, in->startmap, sizeof( out->startmap )); Q_strncpy( out->startmap, in->startmap, sizeof( out->startmap ));
Q_strncpy( out->trainmap, in->trainmap, sizeof( out->trainmap )); 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_strncpy( out->title, in->title, sizeof( out->title ));
Q_snprintf( out->version, sizeof( out->version ), "%g", in->version ); 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->game_url, in->game_url, sizeof( out->game_url ));
Q_strncpy( out->update_url, in->update_url, sizeof( out->update_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->type, in->type, sizeof( out->type ));
Q_strncpy( out->date, in->date, sizeof( out->date )); Q_strncpy( out->date, in->date, sizeof( out->date ));
@@ -425,6 +439,31 @@ static void UI_ConvertGameInfo( GAMEINFO *out, gameinfo_t *in )
SetBits( out->flags, GFL_ANIMATED_TITLE ); 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 PIC_DrawGeneric
@@ -492,7 +531,7 @@ static HIMAGE GAME_EXPORT pfnPIC_Load( const char *szPicName, const byte *image_
if( !COM_CheckString( szPicName )) if( !COM_CheckString( szPicName ))
{ {
Con_Reportf( S_ERROR "CL_LoadImage: refusing to load image with empty name\n" ); Con_Reportf( S_ERROR "%s: refusing to load image with empty name\n", __func__ );
return 0; return 0;
} }
@@ -922,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; return 1;
} }
@@ -938,8 +978,26 @@ pfnGetGamesList
*/ */
static GAMEINFO ** GAME_EXPORT pfnGetGamesList( int *numGames ) static GAMEINFO ** GAME_EXPORT pfnGetGamesList( int *numGames )
{ {
if( numGames ) *numGames = FI->numgames; if( numGames )
return gameui.modsInfo; *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;
} }
/* /*
@@ -1011,7 +1069,7 @@ pfnChangeInstance
*/ */
static void GAME_EXPORT pfnChangeInstance( const char *newInstance, const char *szFinalMessage ) static void GAME_EXPORT pfnChangeInstance( const char *newInstance, const char *szFinalMessage )
{ {
Con_Reportf( S_ERROR "ChangeInstance menu call is deprecated!\n" ); Con_Reportf( S_ERROR "%s menu call is deprecated!\n", __func__ );
} }
/* /*
@@ -1097,8 +1155,22 @@ static void GAME_EXPORT pfnCon_DefaultColor( int r, int g, int b )
Con_DefaultColor( r, g, b, true ); Con_DefaultColor( r, g, b, true );
} }
static void GAME_EXPORT pfnSetCursor( void *hCursor )
{
uintptr_t cursor;
if( !gameui.use_extended_api )
return; // ignore original Xash menus
cursor = (uintptr_t)hCursor;
if( cursor < dc_user || cursor > dc_last )
return;
Platform_SetCursorType( cursor );
}
// engine callbacks // engine callbacks
static ui_enginefuncs_t gEngfuncs = static const ui_enginefuncs_t gEngfuncs =
{ {
pfnPIC_Load, pfnPIC_Load,
GL_FreeImage, GL_FreeImage,
@@ -1162,7 +1234,7 @@ static ui_enginefuncs_t gEngfuncs =
pfnKeyGetState, pfnKeyGetState,
pfnMemAlloc, pfnMemAlloc,
pfnMemFree, pfnMemFree,
pfnGetGameInfo, pfnGetOldGameInfo,
pfnGetGamesList, pfnGetGamesList,
pfnGetFilesList, pfnGetFilesList,
SV_GetSaveComment, SV_GetSaveComment,
@@ -1176,7 +1248,7 @@ static ui_enginefuncs_t gEngfuncs =
pfnHostEndGame, pfnHostEndGame,
COM_RandomFloat, COM_RandomFloat,
COM_RandomLong, COM_RandomLong,
IN_SetCursor, pfnSetCursor,
pfnIsMapValid, pfnIsMapValid,
GL_ProcessTexture, GL_ProcessTexture,
COM_CompareFileTime, COM_CompareFileTime,
@@ -1209,6 +1281,28 @@ static char *pfnParseFileSafe( char *data, char *buf, const int size, unsigned i
return COM_ParseFileSafe( data, buf, size, flags, len, NULL ); 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 = static ui_extendedfuncs_t gExtendedfuncs =
{ {
pfnEnableTextInput, pfnEnableTextInput,
@@ -1221,6 +1315,9 @@ static ui_extendedfuncs_t gExtendedfuncs =
NET_AdrToString, NET_AdrToString,
NET_CompareAdrSort, NET_CompareAdrSort,
Sys_GetNativeObject, Sys_GetNativeObject,
&gNetApi,
pfnGetGameInfo,
pfnGetModInfo,
}; };
void UI_UnloadProgs( void ) void UI_UnloadProgs( void )
@@ -1230,6 +1327,7 @@ void UI_UnloadProgs( void )
// deinitialize game // deinitialize game
gameui.dllFuncs.pfnShutdown(); gameui.dllFuncs.pfnShutdown();
Cmd_RemoveCommand( "ui_allowconsole" );
Cvar_FullSet( "host_gameuiloaded", "0", FCVAR_READ_ONLY ); Cvar_FullSet( "host_gameuiloaded", "0", FCVAR_READ_ONLY );
Cvar_Unlink( FCVAR_GAMEUIDLL ); Cvar_Unlink( FCVAR_GAMEUIDLL );
@@ -1280,71 +1378,65 @@ qboolean UI_LoadProgs( void )
if(( GetMenuAPI = (MENUAPI)COM_GetProcAddress( gameui.hInstance, "GetMenuAPI" )) == NULL ) if(( GetMenuAPI = (MENUAPI)COM_GetProcAddress( gameui.hInstance, "GetMenuAPI" )) == NULL )
{ {
COM_FreeLibrary( gameui.hInstance ); COM_FreeLibrary( gameui.hInstance );
Con_Reportf( "UI_LoadProgs: can't init menu API\n" ); Con_Reportf( "%s: can't init menu API\n", __func__ );
gameui.hInstance = NULL; gameui.hInstance = NULL;
return false; return false;
} }
gameui.use_text_api = false; gameui.use_extended_api = false;
// make local copy of engfuncs to prevent overwrite it with user dll // 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" ); gameui.mempool = Mem_AllocPool( "Menu Pool" );
if( !GetMenuAPI( &gameui.dllFuncs, &gpEngfuncs, gameui.globals )) if( !GetMenuAPI( &gameui.dllFuncs, &gpEngfuncs, gameui.globals ))
{ {
COM_FreeLibrary( gameui.hInstance ); COM_FreeLibrary( gameui.hInstance );
Con_Reportf( "UI_LoadProgs: can't init menu API\n" ); Con_Reportf( "%s: can't init menu API\n", __func__ );
Mem_FreePool( &gameui.mempool ); Mem_FreePool( &gameui.mempool );
gameui.hInstance = NULL; gameui.hInstance = NULL;
return false; return false;
} }
// make local copy of engfuncs to prevent overwrite it with user dll // 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 )); memset( &gameui.dllFuncs2, 0, sizeof( gameui.dllFuncs2 ));
// try to initialize new extended API // try to initialize new extended API
if( ( GetExtAPI = (UIEXTENEDEDAPI)COM_GetProcAddress( gameui.hInstance, "GetExtAPI" ) ) ) if( ( GetExtAPI = (UIEXTENEDEDAPI)COM_GetProcAddress( gameui.hInstance, "GetExtAPI" ) ) )
{ {
Con_Reportf( "UI_LoadProgs: extended Menu API found\n" ); Con_Reportf( "%s: extended Menu API found\n", __func__ );
if( GetExtAPI( MENU_EXTENDED_API_VERSION, &gameui.dllFuncs2, &gpExtendedfuncs ) ) if( GetExtAPI( MENU_EXTENDED_API_VERSION, &gameui.dllFuncs2, &gpExtendedfuncs ) )
{ {
Con_Reportf( "UI_LoadProgs: extended Menu API initialized\n" ); Con_Reportf( "%s: extended Menu API initialized\n", __func__ );
gameui.use_text_api = true; gameui.use_extended_api = true;
} }
} }
else // otherwise, fallback to old and deprecated extensions else // otherwise, fallback to old and deprecated extensions
{ {
if( ( GiveTextApi = (UITEXTAPI)COM_GetProcAddress( gameui.hInstance, "GiveTextAPI" ) ) ) if( ( GiveTextApi = (UITEXTAPI)COM_GetProcAddress( gameui.hInstance, "GiveTextAPI" ) ) )
{ {
Con_Reportf( "UI_LoadProgs: extended text API found\n" ); Con_Reportf( "%s: extended text API found\n", __func__ );
Con_Reportf( S_WARN "Text API is deprecated! If you are mod developer, consider moving to Extended Menu API!\n" ); Con_Reportf( S_WARN "Text API is deprecated! If you are mod developer, consider moving to Extended Menu API!\n" );
if( GiveTextApi( &gpExtendedfuncs ) ) // they are binary compatible, so we can just pass extended funcs API to menu if( GiveTextApi( &gpExtendedfuncs ) ) // they are binary compatible, so we can just pass extended funcs API to menu
{ {
Con_Reportf( "UI_LoadProgs: extended text API initialized\n" ); Con_Reportf( "%s: extended text API initialized\n", __func__ );
gameui.use_text_api = true; gameui.use_extended_api = true;
} }
} }
gameui.dllFuncs2.pfnAddTouchButtonToList = (ADDTOUCHBUTTONTOLIST)COM_GetProcAddress( gameui.hInstance, "AddTouchButtonToList" ); gameui.dllFuncs2.pfnAddTouchButtonToList = (ADDTOUCHBUTTONTOLIST)COM_GetProcAddress( gameui.hInstance, "AddTouchButtonToList" );
if( gameui.dllFuncs2.pfnAddTouchButtonToList ) if( gameui.dllFuncs2.pfnAddTouchButtonToList )
{ {
Con_Reportf( "UI_LoadProgs: AddTouchButtonToList call found\n" ); Con_Reportf( "%s: AddTouchButtonToList call found\n", __func__ );
Con_Reportf( S_WARN "AddTouchButtonToList is deprecated! If you are mod developer, consider moving to Extended Menu API!\n" ); Con_Reportf( S_WARN "AddTouchButtonToList is deprecated! If you are mod developer, consider moving to Extended Menu API!\n" );
} }
} }
Cvar_FullSet( "host_gameuiloaded", "1", FCVAR_READ_ONLY ); Cvar_FullSet( "host_gameuiloaded", "1", FCVAR_READ_ONLY );
Cmd_AddRestrictedCommand( "ui_allowconsole", UI_ToggleAllowConsole_f, "unlocks developer console" );
// 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] );
}
UI_ConvertGameInfo( &gameui.gameInfo, FI->GameInfo ); // current gameinfo UI_ConvertGameInfo( &gameui.gameInfo, FI->GameInfo ); // current gameinfo

View File

@@ -31,15 +31,16 @@ GNU General Public License for more details.
#define CL_TEST_RETRIES 5 #define CL_TEST_RETRIES 5
CVAR_DEFINE_AUTO( mp_decals, "300", FCVAR_ARCHIVE, "decals limit in multiplayer" ); CVAR_DEFINE_AUTO( mp_decals, "300", FCVAR_ARCHIVE, "decals limit in multiplayer" );
CVAR_DEFINE_AUTO( dev_overview, "0", 0, "draw level in overview-mode" ); static CVAR_DEFINE_AUTO( dev_overview, "0", 0, "draw level in overview-mode" );
CVAR_DEFINE_AUTO( cl_resend, "6.0", 0, "time to resend connect" ); static CVAR_DEFINE_AUTO( cl_resend, "6.0", 0, "time to resend connect" );
CVAR_DEFINE( cl_allow_download, "cl_allowdownload", "1", FCVAR_ARCHIVE, "allow to downloading resources from the server" ); CVAR_DEFINE( cl_allow_download, "cl_allowdownload", "1", FCVAR_ARCHIVE, "allow to downloading resources from the server" );
CVAR_DEFINE_AUTO( cl_allow_upload, "1", FCVAR_ARCHIVE, "allow to uploading resources to the server" ); static CVAR_DEFINE( cl_allow_upload, "cl_allowupload", "1", FCVAR_ARCHIVE, "allow to uploading resources to the server" );
CVAR_DEFINE_AUTO( cl_download_ingame, "1", FCVAR_ARCHIVE, "allow to downloading resources while client is active" ); CVAR_DEFINE_AUTO( cl_download_ingame, "1", FCVAR_ARCHIVE, "allow to downloading resources while client is active" );
CVAR_DEFINE_AUTO( cl_logofile, "lambda", FCVAR_ARCHIVE, "player logo name" ); static CVAR_DEFINE_AUTO( cl_logofile, "lambda", FCVAR_ARCHIVE, "player logo name" );
CVAR_DEFINE_AUTO( cl_logocolor, "orange", FCVAR_ARCHIVE, "player logo color" ); static CVAR_DEFINE_AUTO( cl_logocolor, "orange", FCVAR_ARCHIVE, "player logo color" );
CVAR_DEFINE_AUTO( cl_logoext, "bmp", FCVAR_ARCHIVE, "temporary cvar to tell engine which logo must be packed" ); static CVAR_DEFINE_AUTO( cl_logoext, "bmp", FCVAR_ARCHIVE, "temporary cvar to tell engine which logo must be packed" );
CVAR_DEFINE_AUTO( cl_test_bandwidth, "1", FCVAR_ARCHIVE, "test network bandwith before connection" ); CVAR_DEFINE_AUTO( cl_logomaxdim, "96", FCVAR_ARCHIVE, "maximum decal dimension" );
static CVAR_DEFINE_AUTO( cl_test_bandwidth, "1", FCVAR_ARCHIVE, "test network bandwith before connection" );
CVAR_DEFINE( cl_draw_particles, "r_drawparticles", "1", FCVAR_CHEAT, "render particles" ); CVAR_DEFINE( cl_draw_particles, "r_drawparticles", "1", FCVAR_CHEAT, "render particles" );
CVAR_DEFINE( cl_draw_tracers, "r_drawtracers", "1", FCVAR_CHEAT, "render tracers" ); CVAR_DEFINE( cl_draw_tracers, "r_drawtracers", "1", FCVAR_CHEAT, "render tracers" );
@@ -48,17 +49,17 @@ CVAR_DEFINE( cl_draw_beams, "r_drawbeams", "1", FCVAR_CHEAT, "render beams" );
static CVAR_DEFINE_AUTO( rcon_address, "", FCVAR_PRIVILEGED, "remote control address" ); static CVAR_DEFINE_AUTO( rcon_address, "", FCVAR_PRIVILEGED, "remote control address" );
CVAR_DEFINE_AUTO( cl_timeout, "60", 0, "connect timeout (in-seconds)" ); CVAR_DEFINE_AUTO( cl_timeout, "60", 0, "connect timeout (in-seconds)" );
CVAR_DEFINE_AUTO( cl_nopred, "0", FCVAR_ARCHIVE|FCVAR_USERINFO, "disable client movement prediction" ); CVAR_DEFINE_AUTO( cl_nopred, "0", FCVAR_ARCHIVE|FCVAR_USERINFO, "disable client movement prediction" );
CVAR_DEFINE_AUTO( cl_nodelta, "0", 0, "disable delta-compression for server messages" ); static CVAR_DEFINE_AUTO( cl_nodelta, "0", 0, "disable delta-compression for server messages" );
CVAR_DEFINE( cl_crosshair, "crosshair", "1", FCVAR_ARCHIVE, "show weapon chrosshair" ); CVAR_DEFINE( cl_crosshair, "crosshair", "1", FCVAR_ARCHIVE, "show weapon chrosshair" );
static CVAR_DEFINE_AUTO( cl_cmdbackup, "10", FCVAR_ARCHIVE, "how many additional history commands are sent" ); static CVAR_DEFINE_AUTO( cl_cmdbackup, "10", FCVAR_ARCHIVE, "how many additional history commands are sent" );
CVAR_DEFINE_AUTO( cl_showerror, "0", FCVAR_ARCHIVE, "show prediction error" ); CVAR_DEFINE_AUTO( cl_showerror, "0", FCVAR_ARCHIVE, "show prediction error" );
CVAR_DEFINE_AUTO( cl_bmodelinterp, "1", FCVAR_ARCHIVE, "enable bmodel interpolation" ); CVAR_DEFINE_AUTO( cl_bmodelinterp, "1", FCVAR_ARCHIVE, "enable bmodel interpolation" );
CVAR_DEFINE_AUTO( cl_lightstyle_lerping, "0", FCVAR_ARCHIVE, "enables animated light lerping (perfomance option)" ); static CVAR_DEFINE_AUTO( cl_lightstyle_lerping, "0", FCVAR_ARCHIVE, "enables animated light lerping (perfomance option)" );
CVAR_DEFINE_AUTO( cl_idealpitchscale, "0.8", 0, "how much to look up/down slopes and stairs when not using freelook" ); CVAR_DEFINE_AUTO( cl_idealpitchscale, "0.8", 0, "how much to look up/down slopes and stairs when not using freelook" );
CVAR_DEFINE_AUTO( cl_nosmooth, "0", FCVAR_ARCHIVE, "disable smooth up stair climbing" ); CVAR_DEFINE_AUTO( cl_nosmooth, "0", FCVAR_ARCHIVE, "disable smooth up stair climbing" );
CVAR_DEFINE_AUTO( cl_smoothtime, "0.1", FCVAR_ARCHIVE, "time to smooth up" ); CVAR_DEFINE_AUTO( cl_smoothtime, "0.1", FCVAR_ARCHIVE, "time to smooth up" );
CVAR_DEFINE_AUTO( cl_clockreset, "0.1", FCVAR_ARCHIVE, "frametime delta maximum value before reset" ); CVAR_DEFINE_AUTO( cl_clockreset, "0.1", FCVAR_ARCHIVE, "frametime delta maximum value before reset" );
CVAR_DEFINE_AUTO( cl_fixtimerate, "7.5", FCVAR_ARCHIVE, "time in msec to client clock adjusting" ); static CVAR_DEFINE_AUTO( cl_fixtimerate, "7.5", FCVAR_ARCHIVE, "time in msec to client clock adjusting" );
CVAR_DEFINE_AUTO( hud_fontscale, "1.0", FCVAR_ARCHIVE|FCVAR_LATCH, "scale hud font texture" ); CVAR_DEFINE_AUTO( hud_fontscale, "1.0", FCVAR_ARCHIVE|FCVAR_LATCH, "scale hud font texture" );
CVAR_DEFINE_AUTO( hud_fontrender, "0", FCVAR_ARCHIVE, "hud font render mode (0: additive, 1: holes, 2: trans)" ); CVAR_DEFINE_AUTO( hud_fontrender, "0", FCVAR_ARCHIVE, "hud font render mode (0: additive, 1: holes, 2: trans)" );
CVAR_DEFINE_AUTO( hud_scale, "0", FCVAR_ARCHIVE|FCVAR_LATCH, "scale hud at current resolution" ); CVAR_DEFINE_AUTO( hud_scale, "0", FCVAR_ARCHIVE|FCVAR_LATCH, "scale hud at current resolution" );
@@ -68,7 +69,7 @@ CVAR_DEFINE_AUTO( cl_updaterate, "20", FCVAR_USERINFO|FCVAR_ARCHIVE, "refresh ra
CVAR_DEFINE_AUTO( cl_showevents, "0", FCVAR_ARCHIVE, "show events playback" ); CVAR_DEFINE_AUTO( cl_showevents, "0", FCVAR_ARCHIVE, "show events playback" );
CVAR_DEFINE_AUTO( cl_cmdrate, "60", FCVAR_ARCHIVE, "Max number of command packets sent to server per second" ); CVAR_DEFINE_AUTO( cl_cmdrate, "60", FCVAR_ARCHIVE, "Max number of command packets sent to server per second" );
CVAR_DEFINE( cl_interp, "ex_interp", "0.1", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "Interpolate object positions starting this many seconds in past" ); CVAR_DEFINE( cl_interp, "ex_interp", "0.1", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "Interpolate object positions starting this many seconds in past" );
CVAR_DEFINE_AUTO( cl_nointerp, "0", FCVAR_CLIENTDLL, "disable interpolation of entities and players" ); CVAR_DEFINE_AUTO( cl_nointerp, "0", 0, "disable interpolation of entities and players" );
static CVAR_DEFINE_AUTO( cl_dlmax, "0", FCVAR_USERINFO|FCVAR_ARCHIVE, "max allowed outcoming fragment size" ); static CVAR_DEFINE_AUTO( cl_dlmax, "0", FCVAR_USERINFO|FCVAR_ARCHIVE, "max allowed outcoming fragment size" );
static CVAR_DEFINE_AUTO( cl_upmax, "1200", FCVAR_ARCHIVE, "max allowed incoming fragment size" ); static CVAR_DEFINE_AUTO( cl_upmax, "1200", FCVAR_ARCHIVE, "max allowed incoming fragment size" );
@@ -86,12 +87,14 @@ CVAR_DEFINE_AUTO( cl_fixmodelinterpolationartifacts, "1", 0, "try to fix up mode
// //
// userinfo // 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( 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( 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" ); 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" ); CVAR_DEFINE_AUTO( rate, "3500", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player network rate" );
client_t cl; client_t cl;
client_static_t cls; client_static_t cls;
clgame_static_t clgame; clgame_static_t clgame;
@@ -115,17 +118,12 @@ qboolean CL_IsInGame( void )
if( host.type == HOST_DEDICATED ) if( host.type == HOST_DEDICATED )
return true; // always active for dedicated servers return true; // always active for dedicated servers
if( cl.background || CL_GetMaxClients() > 1 ) if( cl.background || cl.maxclients > 1 )
return true; // always active for multiplayer or background map return true; // always active for multiplayer or background map
return ( cls.key_dest == key_game ); // active if not menu or console return ( cls.key_dest == key_game ); // active if not menu or console
} }
qboolean CL_IsInMenu( void )
{
return ( cls.key_dest == key_menu );
}
qboolean CL_IsInConsole( void ) qboolean CL_IsInConsole( void )
{ {
return ( cls.key_dest == key_console ); return ( cls.key_dest == key_console );
@@ -222,7 +220,7 @@ An svc_signonnum has been received, perform a client side setup
void CL_SignonReply( void ) void CL_SignonReply( void )
{ {
// g-cont. my favorite message :-) // g-cont. my favorite message :-)
Con_Reportf( "CL_SignonReply: %i\n", cls.signon ); Con_Reportf( "%s: %i\n", __func__, cls.signon );
switch( cls.signon ) switch( cls.signon )
{ {
@@ -587,21 +585,38 @@ CL_CreateCmd
*/ */
static void CL_CreateCmd( void ) static void CL_CreateCmd( void )
{ {
usercmd_t nullcmd, *cmd; usercmd_t nullcmd, *cmd;
runcmd_t *pcmd; runcmd_t *pcmd;
vec3_t angles; qboolean active;
qboolean active; double accurate_ms;
int input_override; vec3_t angles;
int i, ms; 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; return;
// store viewangles in case it's will be freeze // store viewangles in case it's will be freeze
VectorCopy( cl.viewangles, angles ); VectorCopy( cl.viewangles, angles );
ms = bound( 1, host.frametime * 1000, 255 );
input_override = 0; input_override = 0;
// fix rounding error and framerate depending player move
accurate_ms = host.frametime * 1000;
ms = (int)accurate_ms;
cl.frametime_remainder += accurate_ms - ms; // accumulate rounding error each frame
// add a ms if error accumulates enough
if( cl.frametime_remainder >= 1.0 )
{
int ms2 = (int)cl.frametime_remainder;
ms += ms2;
cl.frametime_remainder -= ms2;
}
// ms can't be negative, rely on error accumulation only if FPS > 1000
ms = Q_min( ms, 255 );
CL_SetSolidEntities(); CL_SetSolidEntities();
CL_PushPMStates(); CL_PushPMStates();
CL_SetSolidPlayers( cl.playernum ); CL_SetSolidPlayers( cl.playernum );
@@ -809,7 +824,7 @@ static void CL_WritePacket( void )
from = to; from = to;
if( MSG_CheckOverflow( &buf )) if( MSG_CheckOverflow( &buf ))
Host_Error( "CL_WritePacket: overflowed command buffer (%i bytes)\n", MAX_CMD_BUFFER ); Host_Error( "%s: overflowed command buffer (%i bytes)\n", __func__, MAX_CMD_BUFFER );
} }
// calculate a checksum over the move commands // calculate a checksum over the move commands
@@ -834,7 +849,7 @@ static void CL_WritePacket( void )
} }
if( MSG_CheckOverflow( &buf )) if( MSG_CheckOverflow( &buf ))
Host_Error( "CL_WritePacket: overflowed command buffer (%i bytes)\n", MAX_CMD_BUFFER ); Host_Error( "%s: overflowed command buffer (%i bytes)\n", __func__, MAX_CMD_BUFFER );
// remember outgoing command that we are sending // remember outgoing command that we are sending
cls.lastoutgoingcommand = cls.netchan.outgoing_sequence; cls.lastoutgoingcommand = cls.netchan.outgoing_sequence;
@@ -920,16 +935,16 @@ static void CL_BeginUpload_f( void )
memset( &custResource, 0, sizeof( custResource )); memset( &custResource, 0, sizeof( custResource ));
COM_HexConvert( name + 4, 32, md5 ); COM_HexConvert( name + 4, 32, md5 );
if( HPAK_ResourceForHash( CUSTOM_RES_PATH, md5, &custResource )) if( HPAK_ResourceForHash( hpk_custom_file.string, md5, &custResource ))
{ {
if( memcmp( md5, custResource.rgucMD5_hash, 16 )) if( memcmp( md5, custResource.rgucMD5_hash, 16 ))
{ {
Con_Reportf( "Bogus data retrieved from %s, attempting to delete entry\n", CUSTOM_RES_PATH ); Con_Reportf( "Bogus data retrieved from %s, attempting to delete entry\n", hpk_custom_file.string );
HPAK_RemoveLump( CUSTOM_RES_PATH, &custResource ); HPAK_RemoveLump( hpk_custom_file.string, &custResource );
return; return;
} }
if( HPAK_GetDataPointer( CUSTOM_RES_PATH, &custResource, &buf, &size )) if( HPAK_GetDataPointer( hpk_custom_file.string, &custResource, &buf, &size ))
{ {
byte md5[16]; byte md5[16];
MD5Context_t ctx; MD5Context_t ctx;
@@ -945,7 +960,7 @@ static void CL_BeginUpload_f( void )
Con_Reportf( "Purported: %s\n", MD5_Print( custResource.rgucMD5_hash ) ); Con_Reportf( "Purported: %s\n", MD5_Print( custResource.rgucMD5_hash ) );
Con_Reportf( "Actual : %s\n", MD5_Print( md5 ) ); Con_Reportf( "Actual : %s\n", MD5_Print( md5 ) );
Con_Reportf( "Removing conflicting lump\n" ); Con_Reportf( "Removing conflicting lump\n" );
HPAK_RemoveLump( CUSTOM_RES_PATH, &custResource ); HPAK_RemoveLump( hpk_custom_file.string, &custResource );
return; return;
} }
} }
@@ -1001,7 +1016,7 @@ static void CL_SendConnectPacket( void )
if( !NET_StringToAdr( cls.servername, &adr )) if( !NET_StringToAdr( cls.servername, &adr ))
{ {
Con_Printf( "CL_SendConnectPacket: bad server address\n"); Con_Printf( "%s: bad server address\n", __func__ );
cls.connect_time = 0; cls.connect_time = 0;
return; return;
} }
@@ -1149,7 +1164,7 @@ static void CL_CheckForResend( void )
// only retry so many times before failure. // only retry so many times before failure.
if( cls.connect_retry >= CL_CONNECTION_RETRIES ) if( cls.connect_retry >= CL_CONNECTION_RETRIES )
{ {
Con_DPrintf( S_ERROR "CL_CheckForResend: couldn't connected\n" ); Con_DPrintf( S_ERROR "%s: couldn't connect\n", __func__ );
CL_Disconnect(); CL_Disconnect();
return; return;
} }
@@ -1236,7 +1251,7 @@ static void CL_CreateResourceList( void )
{ {
SetBits( pNewResource->ucFlags, RES_CUSTOM ); SetBits( pNewResource->ucFlags, RES_CUSTOM );
memcpy( pNewResource->rgucMD5_hash, rgucMD5_hash, 16 ); memcpy( pNewResource->rgucMD5_hash, rgucMD5_hash, 16 );
HPAK_AddLump( false, CUSTOM_RES_PATH, pNewResource, NULL, fp ); HPAK_AddLump( false, hpk_custom_file.string, pNewResource, NULL, fp );
} }
} }
@@ -1252,16 +1267,28 @@ CL_Connect_f
static void CL_Connect_f( void ) static void CL_Connect_f( void )
{ {
string server; string server;
qboolean legacyconnect = false; connprotocol_t proto = PROTO_CURRENT;
// hidden hint to connect by using legacy protocol // hint to connect by using legacy protocol
if( Cmd_Argc() == 3 ) if( Cmd_Argc() == 3 )
{ {
legacyconnect = !Q_strcmp( Cmd_Argv( 2 ), "legacy" ); const char *s = Cmd_Argv( 2 );
if( !Q_strcmp( s, "current" ) || !Q_strcmp( s, "49" ))
proto = PROTO_CURRENT;
else if( !Q_strcmp( s, "legacy" ) || !Q_strcmp( s, "48" ))
proto = PROTO_LEGACY;
else
{
// quake protocol only used for demos
// goldsrc protocol is not supported yet
Con_Printf( "Unknown protocol. Supported are: current, legacy\n" );
return;
}
} }
else if( Cmd_Argc() != 2 ) else if( Cmd_Argc() != 2 )
{ {
Con_Printf( S_USAGE "connect <server>\n" ); Con_Printf( S_USAGE "connect <server> [protocol]\n" );
return; return;
} }
@@ -1279,7 +1306,7 @@ static void CL_Connect_f( void )
Key_SetKeyDest( key_console ); Key_SetKeyDest( key_console );
cls.state = ca_connecting; cls.state = ca_connecting;
cls.legacymode = legacyconnect; cls.legacymode = proto;
Q_strncpy( cls.servername, server, sizeof( cls.servername )); Q_strncpy( cls.servername, server, sizeof( cls.servername ));
cls.connect_time = MAX_HEARTBEAT; // CL_CheckForResend() will fire immediately cls.connect_time = MAX_HEARTBEAT; // CL_CheckForResend() will fire immediately
cls.max_fragment_size = FRAGMENT_MAX_SIZE; // guess a we can establish connection with maximum fragment size cls.max_fragment_size = FRAGMENT_MAX_SIZE; // guess a we can establish connection with maximum fragment size
@@ -1425,20 +1452,18 @@ static void CL_SendDisconnectMessage( void )
int CL_GetSplitSize( void ) int CL_GetSplitSize( void )
{ {
int splitsize; int splitsize = (int)cl_dlmax.value;
if( Host_IsDedicated() ) if( !FBitSet( cls.extensions, NET_EXT_SPLITSIZE ))
return 0;
if( !(cls.extensions & NET_EXT_SPLITSIZE) )
return 1400; return 1400;
splitsize = cl_dlmax.value; if(( splitsize < FRAGMENT_MIN_SIZE ) || ( splitsize > FRAGMENT_MAX_SIZE ))
{
if( splitsize < FRAGMENT_MIN_SIZE || splitsize > FRAGMENT_MAX_SIZE )
Cvar_SetValue( "cl_dlmax", FRAGMENT_DEFAULT_SIZE ); Cvar_SetValue( "cl_dlmax", FRAGMENT_DEFAULT_SIZE );
return FRAGMENT_DEFAULT_SIZE;
}
return cl_dlmax.value; return (int)cl_dlmax.value;
} }
/* /*
@@ -1509,7 +1534,7 @@ This is also called on Host_Error, so it shouldn't cause any errors
*/ */
void CL_Disconnect( void ) void CL_Disconnect( void )
{ {
cls.legacymode = false; cls.legacymode = PROTO_CURRENT;
if( cls.state == ca_disconnected ) if( cls.state == ca_disconnected )
return; return;
@@ -1539,7 +1564,7 @@ void CL_Disconnect( void )
cls.signon = 0; cls.signon = 0;
// back to menu in non-developer mode // back to menu in non-developer mode
if( host_developer.value || CL_IsInMenu( )) if( host_developer.value || cls.key_dest == key_menu )
return; return;
UI_SetActiveMenu( true ); UI_SetActiveMenu( true );
@@ -1618,9 +1643,17 @@ static size_t NONNULL CL_BuildMasterServerScanRequest( char *buf, size_t size, u
#ifndef XASH_ALL_SERVERS #ifndef XASH_ALL_SERVERS
Info_SetValueForKey( info, "gamedir", GI->gamefolder, remaining ); Info_SetValueForKey( info, "gamedir", GI->gamefolder, remaining );
#endif #endif
Info_SetValueForKey( info, "clver", XASH_VERSION, remaining ); // let master know about client version // let master know about client version
Info_SetValueForKey( info, "clver", XASH_VERSION, remaining );
Info_SetValueForKey( info, "nat", nat ? "1" : "0", remaining ); Info_SetValueForKey( info, "nat", nat ? "1" : "0", remaining );
Info_SetValueForKey( info, "commit", Q_buildcommit(), remaining );
Info_SetValueForKey( info, "branch", Q_buildbranch(), remaining );
Info_SetValueForKey( info, "os", Q_buildos(), remaining );
Info_SetValueForKey( info, "arch", Q_buildarch(), remaining );
Q_snprintf( temp, sizeof( temp ), "%d", Q_buildnum() );
Info_SetValueForKey( info, "buildnum", temp, remaining );
Q_snprintf( temp, sizeof( temp ), "%x", *key ); Q_snprintf( temp, sizeof( temp ), "%x", *key );
Info_SetValueForKey( info, "key", temp, remaining ); Info_SetValueForKey( info, "key", temp, remaining );
@@ -1688,7 +1721,7 @@ static void CL_Reconnect_f( void )
if( COM_CheckString( cls.servername )) if( COM_CheckString( cls.servername ))
{ {
qboolean legacy = cls.legacymode; connprotocol_t proto = cls.legacymode;
if( cls.state >= ca_connected ) if( cls.state >= ca_connected )
CL_Disconnect(); CL_Disconnect();
@@ -1697,7 +1730,7 @@ static void CL_Reconnect_f( void )
cls.demonum = cls.movienum = -1; // not in the demo loop now cls.demonum = cls.movienum = -1; // not in the demo loop now
cls.state = ca_connecting; cls.state = ca_connecting;
cls.signon = 0; cls.signon = 0;
cls.legacymode = legacy; // don't change protocol cls.legacymode = proto; // don't change protocol
Con_Printf( "reconnecting...\n" ); Con_Printf( "reconnecting...\n" );
} }
@@ -1710,7 +1743,7 @@ CL_FixupColorStringsForInfoString
all the keys and values must be ends with ^7 all the keys and values must be ends with ^7
================= =================
*/ */
static void CL_FixupColorStringsForInfoString( const char *in, char *out ) static void CL_FixupColorStringsForInfoString( const char *in, char *out, size_t len )
{ {
qboolean hasPrefix = false; qboolean hasPrefix = false;
qboolean endOfKeyVal = false; qboolean endOfKeyVal = false;
@@ -1723,7 +1756,7 @@ static void CL_FixupColorStringsForInfoString( const char *in, char *out )
count++; count++;
} }
while( *in && count < MAX_INFO_STRING ) while( *in && count < len )
{ {
if( IsColorString( in )) if( IsColorString( in ))
color = ColorIndex( *(in+1)); color = ColorIndex( *(in+1));
@@ -1794,7 +1827,7 @@ static void CL_ParseStatusMessage( netadr_t from, sizebuf_t *msg )
return; return;
} }
CL_FixupColorStringsForInfoString( s, infostring ); CL_FixupColorStringsForInfoString( s, infostring, sizeof( infostring ));
if( !COM_CheckString( Info_ValueForKey( infostring, "gamedir" ))) if( !COM_CheckString( Info_ValueForKey( infostring, "gamedir" )))
{ {
@@ -1823,52 +1856,87 @@ CL_ParseNETInfoMessage
Handle a reply from a netinfo Handle a reply from a netinfo
================= =================
*/ */
static void CL_ParseNETInfoMessage( netadr_t from, sizebuf_t *msg, const char *s ) static void CL_ParseNETInfoMessage( netadr_t from, const char *s )
{ {
net_request_t *nr; net_request_t *nr = NULL;
static char infostring[MAX_INFO_STRING+8]; static char infostring[MAX_PRINT_MSG];
int i, context, type; int i, context, type;
int errorBits = 0; int errorBits = 0;
const char *val; const char *val;
size_t slen;
context = Q_atoi( Cmd_Argv( 1 )); context = Q_atoi( Cmd_Argv( 1 ));
type = Q_atoi( Cmd_Argv( 2 )); type = Q_atoi( Cmd_Argv( 2 ));
while( *s != '\\' ) s++; // fetching infostring
// check for errors // find request with specified context and type
val = Info_ValueForKey( s, "neterror" );
if( !Q_stricmp( val, "protocol" ))
SetBits( errorBits, NET_ERROR_PROTO_UNSUPPORTED );
else if( !Q_stricmp( val, "undefined" ))
SetBits( errorBits, NET_ERROR_UNDEFINED );
CL_FixupColorStringsForInfoString( s, infostring );
// find a request with specified context
for( i = 0; i < MAX_REQUESTS; i++ ) for( i = 0; i < MAX_REQUESTS; i++ )
{ {
nr = &clgame.net_requests[i]; if( clgame.net_requests[i].resp.context == context && clgame.net_requests[i].resp.type == type )
if( nr->resp.context == context && nr->resp.type == type )
{ {
// setup the answer nr = &clgame.net_requests[i];
nr->resp.response = infostring; break;
nr->resp.remote_address = from;
nr->resp.error = NET_SUCCESS;
nr->resp.ping = host.realtime - nr->timesend;
if( nr->timeout <= host.realtime )
SetBits( nr->resp.error, NET_ERROR_TIMEOUT );
SetBits( nr->resp.error, errorBits ); // misc error bits
nr->pfnFunc( &nr->resp );
if( !FBitSet( nr->flags, FNETAPI_MULTIPLE_RESPONSE ))
memset( nr, 0, sizeof( *nr )); // done
return;
} }
} }
// not found, ignore
if( nr == NULL )
return;
// find the payload
s = Q_strchr( s, ' ' ); // skip netinfo
if( !s )
return;
s = Q_strchr( s + 1, ' ' ); // skip challenge
if( !s )
return;
s = Q_strchr( s + 1, ' ' ); // skip type
if( s )
s++; // skip final whitespace
else if( type != NETAPI_REQUEST_PING ) // ping have no payload, and that's ok
return;
if( s )
{
if( s[0] == '\\' )
{
// check for errors
val = Info_ValueForKey( s, "neterror" );
if( !Q_stricmp( val, "protocol" ))
SetBits( errorBits, NET_ERROR_PROTO_UNSUPPORTED );
else if( !Q_stricmp( val, "undefined" ))
SetBits( errorBits, NET_ERROR_UNDEFINED );
else if( !Q_stricmp( val, "forbidden" ))
SetBits( errorBits, NET_ERROR_FORBIDDEN );
CL_FixupColorStringsForInfoString( s, infostring, sizeof( infostring ));
}
else
{
Q_strncpy( infostring, s, sizeof( infostring ));
}
}
else
{
infostring[0] = 0;
}
// setup the answer
nr->resp.response = infostring;
nr->resp.remote_address = from;
nr->resp.error = NET_SUCCESS;
nr->resp.ping = host.realtime - nr->timesend;
if( nr->timeout <= host.realtime )
SetBits( nr->resp.error, NET_ERROR_TIMEOUT );
SetBits( nr->resp.error, errorBits ); // misc error bits
nr->pfnFunc( &nr->resp );
if( !FBitSet( nr->flags, FNETAPI_MULTIPLE_RESPONSE ))
memset( nr, 0, sizeof( *nr )); // done
} }
/* /*
@@ -1966,7 +2034,6 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
const char *c; const char *c;
char buf[MAX_SYSPATH]; char buf[MAX_SYSPATH];
int len = sizeof( buf ); int len = sizeof( buf );
int dataoffset = 0;
netadr_t servadr; netadr_t servadr;
MSG_Clear( msg ); MSG_Clear( msg );
@@ -1977,7 +2044,7 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
Cmd_TokenizeString( args ); Cmd_TokenizeString( args );
c = Cmd_Argv( 0 ); c = Cmd_Argv( 0 );
Con_Reportf( "CL_ConnectionlessPacket: %s : %s\n", NET_AdrToString( from ), c ); Con_Reportf( "%s: %s : %s\n", __func__, NET_AdrToString( from ), c );
// server connection // server connection
if( !Q_strcmp( c, "client_connect" )) if( !Q_strcmp( c, "client_connect" ))
@@ -2002,7 +2069,7 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
else if( !Q_strcmp( c, "netinfo" )) else if( !Q_strcmp( c, "netinfo" ))
{ {
// server responding to a status broadcast // server responding to a status broadcast
CL_ParseNETInfoMessage( from, msg, args ); CL_ParseNETInfoMessage( from, args );
} }
else if( !Q_strcmp( c, "cmd" )) else if( !Q_strcmp( c, "cmd" ))
{ {
@@ -2023,7 +2090,11 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
else if( !Q_strcmp( c, "print" )) else if( !Q_strcmp( c, "print" ))
{ {
// print command from somewhere // print command from somewhere
Con_Printf( "%s", MSG_ReadString( msg )); char *s = MSG_ReadString( msg );
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, "testpacket" )) else if( !Q_strcmp( c, "testpacket" ))
{ {
@@ -2134,30 +2205,21 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
// a disconnect message from the server, which will happen if the server // a disconnect message from the server, which will happen if the server
// dropped the connection but it is still getting packets from us // dropped the connection but it is still getting packets from us
CL_Disconnect_f(); CL_Disconnect_f();
if( NET_CompareAdr( from, cls.legacyserver ))
{
Cbuf_AddTextf( "connect %s legacy\n", NET_AdrToString( from ));
memset( &cls.legacyserver, 0, sizeof( cls.legacyserver ));
}
} }
else if( !Q_strcmp( c, "errormsg" )) else if( !Q_strcmp( c, "errormsg" ))
{ {
char formatted_msg[MAX_VA_STRING];
if( !CL_IsFromConnectingServer( from )) if( !CL_IsFromConnectingServer( from ))
return; return;
args = MSG_ReadString( msg ); args = MSG_ReadString( msg );
if( !Q_strcmp( args, "Server uses protocol version 48.\n" )) Q_snprintf( formatted_msg, sizeof( formatted_msg ), "^3Server message^7\n%s", args );
{
cls.legacyserver = from; // in case we're in console or it's classic mainui which doesn't support messageboxes
} if( !UI_IsVisible() || !UI_ShowMessageBox( formatted_msg ))
else Msg( "%s\n", formatted_msg );
{
if( UI_IsVisible() )
UI_ShowMessageBox( va("^3Server message^7\n%s", args ) );
Msg( "%s", args );
}
} }
else if( !Q_strcmp( c, "updatemsg" )) else if( !Q_strcmp( c, "updatemsg" ))
{ {
@@ -2271,6 +2333,29 @@ static int CL_GetMessage( byte *data, size_t *length )
return false; return false;
} }
static void CL_ParseNetMessage( sizebuf_t *msg, void (*parsefn)( sizebuf_t * ))
{
cls.starting_count = MSG_GetNumBytesRead( msg ); // updates each frame
CL_Parse_Debug( true ); // begin parsing
parsefn( msg );
cl.frames[cl.parsecountmod].graphdata.msgbytes += MSG_GetNumBytesRead( msg ) - cls.starting_count;
CL_Parse_Debug( false ); // done
// we don't know if it is ok to save a demo message until
// after we have parsed the frame
if( !cls.demoplayback )
{
if( cls.state != ca_active )
CL_WriteDemoMessage( true, cls.starting_count, msg );
if( cls.demorecording && !cls.demowaiting )
CL_WriteDemoMessage( false, cls.starting_count, msg );
}
}
/* /*
================= =================
CL_ReadNetMessage CL_ReadNetMessage
@@ -2279,11 +2364,29 @@ CL_ReadNetMessage
static void CL_ReadNetMessage( void ) static void CL_ReadNetMessage( void )
{ {
size_t curSize; size_t curSize;
void (*parsefn)( sizebuf_t *msg );
switch( cls.legacymode )
{
case PROTO_CURRENT:
parsefn = CL_ParseServerMessage;
break;
case PROTO_LEGACY:
parsefn = CL_ParseLegacyServerMessage;
break;
case PROTO_QUAKE:
parsefn = CL_ParseQuakeMessage;
break;
case PROTO_GOLDSRC:
default:
ASSERT( 0 );
return;
}
while( CL_GetMessage( net_message_buffer, &curSize )) while( CL_GetMessage( net_message_buffer, &curSize ))
{ {
const int split_header = LittleLong( 0xFFFFFFFE ); const int split_header = LittleLong( 0xFFFFFFFE );
if( cls.legacymode && !memcmp( &split_header, net_message_buffer, sizeof( split_header ))) if( cls.legacymode == PROTO_LEGACY && !memcmp( &split_header, net_message_buffer, sizeof( split_header )))
{ {
// Will rewrite existing packet by merged // Will rewrite existing packet by merged
if( !NetSplit_GetLong( &cls.netchan.netsplit, &net_from, net_message_buffer, &curSize ) ) if( !NetSplit_GetLong( &cls.netchan.netsplit, &net_from, net_message_buffer, &curSize ) )
@@ -2302,27 +2405,36 @@ static void CL_ReadNetMessage( void )
// can't be a valid sequenced packet // can't be a valid sequenced packet
if( cls.state < ca_connected ) continue; if( cls.state < ca_connected ) continue;
if( !cls.demoplayback && MSG_GetMaxBytes( &net_message ) < 8 ) if( !cls.demoplayback )
{ {
Con_Printf( S_WARN "CL_ReadPackets: %s:runt packet\n", NET_AdrToString( net_from )); if( MSG_GetMaxBytes( &net_message ) < 8 )
continue; {
Con_Printf( S_WARN "%s: %s:runt packet\n", __func__, NET_AdrToString( net_from ));
continue;
}
// packet from server
if( !NET_CompareAdr( net_from, cls.netchan.remote_address ))
{
Con_DPrintf( S_ERROR "%s: %s:sequenced packet without connection\n", __func__, NET_AdrToString( net_from ));
continue;
}
if( !Netchan_Process( &cls.netchan, &net_message ))
continue; // wasn't accepted for some reason
} }
// packet from server if( cls.state == ca_active )
if( !cls.demoplayback && !NET_CompareAdr( net_from, cls.netchan.remote_address ))
{ {
Con_DPrintf( S_ERROR "CL_ReadPackets: %s:sequenced packet without connection\n", NET_AdrToString( net_from )); cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].valid = false;
continue; cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].choked = false;
}
else
{
CL_ResetFrame( &cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK] );
} }
if( !cls.demoplayback && !Netchan_Process( &cls.netchan, &net_message )) CL_ParseNetMessage( &net_message, parsefn );
continue; // wasn't accepted for some reason
// run special handler for quake demos
if( cls.demoplayback == DEMO_QUAKE1 )
CL_ParseQuakeMessage( &net_message, true );
else if( cls.legacymode ) CL_ParseLegacyServerMessage( &net_message, true );
else CL_ParseServerMessage( &net_message, true );
cl.send_reply = true; cl.send_reply = true;
} }
@@ -2336,7 +2448,7 @@ static void CL_ReadNetMessage( void )
if( Netchan_CopyNormalFragments( &cls.netchan, &net_message, &curSize )) if( Netchan_CopyNormalFragments( &cls.netchan, &net_message, &curSize ))
{ {
MSG_Init( &net_message, "ServerData", net_message_buffer, curSize ); MSG_Init( &net_message, "ServerData", net_message_buffer, curSize );
CL_ParseServerMessage( &net_message, false ); CL_ParseNetMessage( &net_message, parsefn );
} }
if( Netchan_CopyFileFragments( &cls.netchan, &net_message )) if( Netchan_CopyFileFragments( &cls.netchan, &net_message ))
@@ -2479,7 +2591,6 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
{ {
int sound_len = sizeof( DEFAULT_SOUNDPATH ) - 1; int sound_len = sizeof( DEFAULT_SOUNDPATH ) - 1;
byte rgucMD5_hash[16]; byte rgucMD5_hash[16];
const char *pfilename;
resource_t *p; resource_t *p;
if( COM_CheckString( filename ) && successfully_received ) if( COM_CheckString( filename ) && successfully_received )
@@ -2487,10 +2598,10 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
if( filename[0] != '!' ) if( filename[0] != '!' )
Con_Printf( "processing %s\n", filename ); 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 // skip "downloaded/" part to avoid mismatch with needed resources list
filename += 11; filename += sizeof( DEFAULT_DOWNLOADED_DIRECTORY ) - 1;
} }
} }
else if( !successfully_received ) else if( !successfully_received )
@@ -2510,11 +2621,6 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
return; return;
} }
pfilename = filename;
if( !Q_strnicmp( filename, DEFAULT_SOUNDPATH, sound_len ))
pfilename += sound_len;
for( p = cl.resourcesneeded.pNext; p != &cl.resourcesneeded; p = p->pNext ) for( p = cl.resourcesneeded.pNext; p != &cl.resourcesneeded; p = p->pNext )
{ {
if( !Q_strnicmp( filename, "!MD5", 4 )) if( !Q_strnicmp( filename, "!MD5", 4 ))
@@ -2524,18 +2630,20 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
if( !memcmp( p->rgucMD5_hash, rgucMD5_hash, 16 )) if( !memcmp( p->rgucMD5_hash, rgucMD5_hash, 16 ))
break; break;
} }
else if( p->type == t_sound )
{
const char *pfilename = filename;
if( !Q_strnicmp( filename, DEFAULT_SOUNDPATH, sound_len ))
pfilename += sound_len;
if( !Q_stricmp( p->szFileName, pfilename ))
break;
}
else else
{ {
if( p->type == t_generic ) if( !Q_stricmp( p->szFileName, filename ))
{
if( !Q_stricmp( p->szFileName, filename ))
break; break;
}
else
{
if( !Q_stricmp( p->szFileName, pfilename ))
break;
}
} }
} }
@@ -2552,14 +2660,14 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
{ {
if( p->ucFlags & RES_CUSTOM ) if( p->ucFlags & RES_CUSTOM )
{ {
HPAK_AddLump( true, CUSTOM_RES_PATH, p, cls.netchan.tempbuffer, NULL ); HPAK_AddLump( true, hpk_custom_file.string, p, cls.netchan.tempbuffer, NULL );
CL_RegisterCustomization( p ); CL_RegisterCustomization( p );
} }
} }
else else
{ {
Con_Printf( "Downloaded %i bytes for purported %i byte file, ignoring download\n", 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 ) if( cls.netchan.tempbuffer )
@@ -2600,7 +2708,7 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
if( cls.netchan.tempbuffer ) if( cls.netchan.tempbuffer )
{ {
Con_Printf( "Received a decal %s, but didn't find it in resources needed list!\n", pfilename ); Con_Printf( "Received a decal %s, but didn't find it in resources needed list!\n", filename );
Mem_Free( cls.netchan.tempbuffer ); Mem_Free( cls.netchan.tempbuffer );
} }
@@ -2640,6 +2748,29 @@ void CL_ServerCommand( qboolean reliable, const char *fmt, ... )
} }
} }
/*
===============
CL_UpdateInfo
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
{
if( cls.state != ca_active )
return;
MSG_BeginClientCmd( &cls.netchan.message, clc_legacy_userinfo );
MSG_WriteString( &cls.netchan.message, cls.userinfo );
}
}
//============================================================================= //=============================================================================
/* /*
============== ==============
@@ -2654,7 +2785,7 @@ static void CL_SetInfo_f( void )
{ {
Con_Printf( "User info settings:\n" ); Con_Printf( "User info settings:\n" );
Info_Print( cls.userinfo ); Info_Print( cls.userinfo );
Con_Printf( "Total %i symbols\n", Q_strlen( cls.userinfo )); Con_Printf( "Total %zu symbols\n", Q_strlen( cls.userinfo ));
return; return;
} }
@@ -2674,7 +2805,7 @@ static void CL_SetInfo_f( void )
{ {
Cvar_DirectSet( var, Cmd_Argv( 2 )); Cvar_DirectSet( var, Cmd_Argv( 2 ));
} }
else if( Info_SetValueForKey( cls.userinfo, Cmd_Argv( 1 ), Cmd_Argv( 2 ), MAX_INFO_STRING )) else if( Info_SetValueForKey( cls.userinfo, Cmd_Argv( 1 ), Cmd_Argv( 2 ), sizeof( cls.userinfo )))
{ {
// send update only on successfully changed userinfo // send update only on successfully changed userinfo
Cmd_ForwardToServer (); Cmd_ForwardToServer ();
@@ -2690,13 +2821,42 @@ static void CL_Physinfo_f( void )
{ {
Con_Printf( "Phys info settings:\n" ); Con_Printf( "Phys info settings:\n" );
Info_Print( cls.physinfo ); Info_Print( cls.physinfo );
Con_Printf( "Total %i symbols\n", Q_strlen( cls.physinfo )); Con_Printf( "Total %zu symbols\n", Q_strlen( cls.physinfo ));
}
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 );
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 retval;
} }
qboolean CL_PrecacheResources( void ) qboolean CL_PrecacheResources( void )
{ {
resource_t *pRes; resource_t *pRes;
// if we downloaded new WAD files or any other archives they must be added to searchpath
if( CL_ShouldRescanFilesystem( ))
g_fsapi.Rescan();
// NOTE: world need to be loaded as first model // NOTE: world need to be loaded as first model
for( pRes = cl.resourcesonhand.pNext; pRes && pRes != &cl.resourcesonhand; pRes = pRes->pNext ) for( pRes = cl.resourcesonhand.pNext; pRes && pRes != &cl.resourcesonhand; pRes = pRes->pNext )
{ {
@@ -2895,6 +3055,7 @@ static void CL_InitLocal( void )
Cvar_RegisterVariable( &cl_logofile ); Cvar_RegisterVariable( &cl_logofile );
Cvar_RegisterVariable( &cl_logocolor ); Cvar_RegisterVariable( &cl_logocolor );
Cvar_RegisterVariable( &cl_logoext ); Cvar_RegisterVariable( &cl_logoext );
Cvar_RegisterVariable( &cl_logomaxdim );
Cvar_RegisterVariable( &cl_test_bandwidth ); Cvar_RegisterVariable( &cl_test_bandwidth );
Voice_RegisterCvars(); Voice_RegisterCvars();
@@ -2918,8 +3079,9 @@ static void CL_InitLocal( void )
// userinfo // userinfo
Cvar_RegisterVariable( &cl_nopred ); Cvar_RegisterVariable( &cl_nopred );
Q_strncpy( username, Sys_GetCurrentUser(), sizeof( username )); // initialize before registering variable
Cvar_RegisterVariable( &name ); 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( &model );
Cvar_RegisterVariable( &cl_updaterate ); Cvar_RegisterVariable( &cl_updaterate );
Cvar_RegisterVariable( &cl_dlmax ); Cvar_RegisterVariable( &cl_dlmax );
@@ -2995,6 +3157,7 @@ static void CL_InitLocal( void )
Cmd_AddCommand ("demos", CL_Demos_f, "restart looping demos defined by the last startdemos command" ); 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 ("movie", CL_PlayVideo_f, "play a movie" );
Cmd_AddCommand ("stop", CL_Stop_f, "stop playing or recording a demo" ); 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 ("info", NULL, "collect info about local servers with specified protocol" );
Cmd_AddCommand ("escape", CL_Escape_f, "escape from game to menu" ); Cmd_AddCommand ("escape", CL_Escape_f, "escape from game to menu" );
Cmd_AddCommand ("togglemenu", CL_Escape_f, "toggle between game and menu" ); Cmd_AddCommand ("togglemenu", CL_Escape_f, "toggle between game and menu" );
@@ -3190,7 +3353,7 @@ CL_Shutdown
*/ */
void CL_Shutdown( void ) void CL_Shutdown( void )
{ {
Con_Printf( "CL_Shutdown()\n" ); Con_Printf( "%s()\n", __func__ );
if( !host.crashed && cls.initialized ) if( !host.crashed && cls.initialized )
{ {

View File

@@ -20,8 +20,6 @@ GNU General Public License for more details.
#include "input.h" #include "input.h"
#include "platform/platform.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_length, "1.0", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "vibration length" );
static CVAR_DEFINE_AUTO( vibration_enable, "1", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "enable vibration" ); 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 ) static void pfnVibrate( float life, char flags )
{ {
if( !vibration_enable.value ) if( !vibration_enable.value || life < 0.0f )
return; 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 // here goes platform-specific backends
Platform_Vibrate( life * vibration_length.value, flags ); Platform_Vibrate( life * vibration_length.value, flags );
} }
@@ -53,7 +43,7 @@ static void Vibrate_f( void )
return; return;
} }
pfnVibrate( Q_atof( Cmd_Argv(1) ), VIBRATE_NORMAL ); pfnVibrate( Q_atof( Cmd_Argv( 1 )), VIBRATE_NORMAL );
} }
static void pfnEnableTextInput( int enable ) 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 ); return COM_ParseFileSafe( data, buf, size, flags, len, NULL );
} }
static mobile_engfuncs_t gpMobileEngfuncs = static const mobile_engfuncs_t gMobileEngfuncs =
{ {
MOBILITY_API_VERSION, MOBILITY_API_VERSION,
pfnVibrate, pfnVibrate,
@@ -122,21 +112,38 @@ static mobile_engfuncs_t gpMobileEngfuncs =
qboolean Mobile_Init( void ) qboolean Mobile_Init( void )
{ {
qboolean success = false;
pfnMobilityInterface ExportToClient; pfnMobilityInterface ExportToClient;
// find a mobility interface Cmd_AddCommand( "vibrate", Vibrate_f, "Vibrate for specified time");
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");
Cvar_RegisterVariable( &vibration_length ); Cvar_RegisterVariable( &vibration_length );
Cvar_RegisterVariable( &vibration_enable ); 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 ) void Mobile_Shutdown( void )

View File

@@ -188,7 +188,7 @@ void CL_ParseServerTime( sizebuf_t *msg )
cl.mtime[1] = cl.mtime[0]; cl.mtime[1] = cl.mtime[0];
cl.mtime[0] = MSG_ReadFloat( msg ); cl.mtime[0] = MSG_ReadFloat( msg );
if( cls.demoplayback == DEMO_QUAKE1 ) if( cls.legacymode == PROTO_QUAKE )
return; // don't mess the time return; // don't mess the time
if( cl.maxclients == 1 ) if( cl.maxclients == 1 )
@@ -249,9 +249,9 @@ void CL_ParseMovevars( sizebuf_t *msg )
// update sky if changed // update sky if changed
if( Q_strcmp( clgame.oldmovevars.skyName, clgame.movevars.skyName ) && cl.video_prepped ) if( Q_strcmp( clgame.oldmovevars.skyName, clgame.movevars.skyName ) && cl.video_prepped )
ref.dllFuncs.R_SetupSky( clgame.movevars.skyName ); R_SetupSky( clgame.movevars.skyName );
memcpy( &clgame.oldmovevars, &clgame.movevars, sizeof( movevars_t )); clgame.oldmovevars = clgame.movevars;
clgame.entities->curstate.scale = clgame.movevars.waveHeight; clgame.entities->curstate.scale = clgame.movevars.waveHeight;
// keep features an actual! // keep features an actual!
@@ -388,7 +388,6 @@ void CL_ParseStaticDecal( sizebuf_t *msg )
{ {
vec3_t origin; vec3_t origin;
int decalIndex, entityIndex, modelIndex; int decalIndex, entityIndex, modelIndex;
cl_entity_t *ent = NULL;
float scale; float scale;
int flags; int flags;
@@ -458,6 +457,7 @@ void CL_BatchResourceRequest( qboolean initialize )
byte data[MAX_INIT_MSG]; byte data[MAX_INIT_MSG];
resource_t *p, *n; resource_t *p, *n;
sizebuf_t msg; sizebuf_t msg;
qboolean done_downloading = true;
MSG_Init( &msg, "Resource Batch", data, sizeof( data )); MSG_Init( &msg, "Resource Batch", data, sizeof( data ));
@@ -487,20 +487,24 @@ void CL_BatchResourceRequest( qboolean initialize )
case t_model: case t_model:
case t_eventscript: case t_eventscript:
if( !CL_CheckFile( &msg, p )) if( !CL_CheckFile( &msg, p ))
{
done_downloading = false;
break; break;
}
CL_MoveToOnHandList( p ); CL_MoveToOnHandList( p );
break; break;
case t_skin: case t_skin:
CL_MoveToOnHandList( p ); CL_MoveToOnHandList( p );
break; break;
case t_decal: case t_decal:
if( !HPAK_GetDataPointer( CUSTOM_RES_PATH, p, NULL, NULL )) if( !HPAK_GetDataPointer( hpk_custom_file.string, p, NULL, NULL ))
{ {
if( !FBitSet( p->ucFlags, RES_REQUESTED )) if( !FBitSet( p->ucFlags, RES_REQUESTED ))
{ {
MSG_BeginClientCmd( &msg, clc_stringcmd ); MSG_BeginClientCmd( &msg, clc_stringcmd );
MSG_WriteStringf( &msg, "dlfile !MD5%s", MD5_Print( p->rgucMD5_hash ));; MSG_WriteStringf( &msg, "dlfile !MD5%s", MD5_Print( p->rgucMD5_hash ));;
SetBits( p->ucFlags, RES_REQUESTED ); SetBits( p->ucFlags, RES_REQUESTED );
done_downloading = false;
} }
break; break;
} }
@@ -525,11 +529,7 @@ void CL_BatchResourceRequest( qboolean initialize )
if( cls.state != ca_disconnected ) if( cls.state != ca_disconnected )
{ {
if( !cl.downloadUrl[0] && !MSG_GetNumBytesWritten( &msg ) && CL_PrecacheResources( )) if( done_downloading && CL_PrecacheResources( ))
{
CL_RegisterResources( &msg );
}
if( cl.downloadUrl[0] && host.downloadcount == 0 && CL_PrecacheResources( ) )
{ {
CL_RegisterResources( &msg ); CL_RegisterResources( &msg );
} }
@@ -721,7 +721,7 @@ void CL_ParseCustomization( sizebuf_t *msg )
} }
} }
if( HPAK_GetDataPointer( CUSTOM_RES_PATH, pRes, NULL, NULL )) if( HPAK_GetDataPointer( hpk_custom_file.string, pRes, NULL, NULL ))
{ {
qboolean bError = false; qboolean bError = false;
@@ -853,7 +853,7 @@ void CL_ParseServerData( sizebuf_t *msg, qboolean legacy )
int i; int i;
uint32_t mapCRC; uint32_t mapCRC;
HPAK_CheckSize( CUSTOM_RES_PATH ); HPAK_CheckSize( hpk_custom_file.string );
Con_Reportf( "%s packet received.\n", legacy ? "Legacy serverdata" : "Serverdata" ); Con_Reportf( "%s packet received.\n", legacy ? "Legacy serverdata" : "Serverdata" );
@@ -1180,17 +1180,16 @@ CL_ParseBaseline
*/ */
void CL_ParseBaseline( sizebuf_t *msg, qboolean legacy ) void CL_ParseBaseline( sizebuf_t *msg, qboolean legacy )
{ {
int i, newnum; const entity_state_t nullstate = { 0 };
entity_state_t nullstate;
qboolean player;
cl_entity_t *ent;
Delta_InitClient (); // finalize client delta's Delta_InitClient (); // finalize client delta's
memset( &nullstate, 0, sizeof( nullstate ));
while( 1 ) while( 1 )
{ {
cl_entity_t *ent;
qboolean player;
int newnum;
if( legacy ) if( legacy )
{ {
newnum = MSG_ReadWord( msg ); newnum = MSG_ReadWord( msg );
@@ -1203,13 +1202,13 @@ void CL_ParseBaseline( sizebuf_t *msg, qboolean legacy )
player = CL_IsPlayerIndex( newnum ); player = CL_IsPlayerIndex( newnum );
if( newnum >= clgame.maxEntities ) if( newnum >= clgame.maxEntities )
Host_Error( "CL_AllocEdict: no free edicts\n" ); Host_Error( "%s: no free edicts\n", __func__ );
ent = CL_EDICT_NUM( newnum ); ent = CL_EDICT_NUM( newnum );
memset( &ent->prevstate, 0, sizeof( ent->prevstate )); ent->prevstate = nullstate;
ent->index = newnum; ent->index = newnum;
MSG_ReadDeltaEntity( msg, &ent->prevstate, &ent->baseline, newnum, player, 1.0f ); MSG_ReadDeltaEntity( msg, &nullstate, &ent->baseline, newnum, player, 1.0f );
if( legacy ) if( legacy )
{ {
@@ -1219,11 +1218,13 @@ void CL_ParseBaseline( sizebuf_t *msg, qboolean legacy )
if( !legacy ) if( !legacy )
{ {
int i;
cl.instanced_baseline_count = MSG_ReadUBitLong( msg, 6 ); cl.instanced_baseline_count = MSG_ReadUBitLong( msg, 6 );
for( i = 0; i < cl.instanced_baseline_count; i++ ) for( i = 0; i < cl.instanced_baseline_count; i++ )
{ {
newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS ); int newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS );
MSG_ReadDeltaEntity( msg, &nullstate, &cl.instanced_baseline[i], newnum, false, 1.0f ); MSG_ReadDeltaEntity( msg, &nullstate, &cl.instanced_baseline[i], newnum, false, 1.0f );
} }
} }
@@ -1380,7 +1381,7 @@ void CL_UpdateUserinfo( sizebuf_t *msg, qboolean legacy )
slot = MSG_ReadUBitLong( msg, MAX_CLIENT_BITS ); slot = MSG_ReadUBitLong( msg, MAX_CLIENT_BITS );
if( slot >= MAX_CLIENTS ) if( slot >= MAX_CLIENTS )
Host_Error( "CL_ParseServerMessage: svc_updateuserinfo >= MAX_CLIENTS\n" ); Host_Error( "%s: svc_updateuserinfo >= MAX_CLIENTS\n", __func__ );
player = &cl.players[slot]; player = &cl.players[slot];
@@ -1402,7 +1403,7 @@ void CL_UpdateUserinfo( sizebuf_t *msg, qboolean legacy )
if( !legacy ) if( !legacy )
MSG_ReadBytes( msg, player->hashedcdkey, sizeof( player->hashedcdkey )); MSG_ReadBytes( msg, player->hashedcdkey, sizeof( player->hashedcdkey ));
if( slot == cl.playernum ) memcpy( &gameui.playerinfo, player, sizeof( player_info_t )); if( slot == cl.playernum ) gameui.playerinfo = *player;
} }
else else
{ {
@@ -1493,7 +1494,7 @@ void CL_UpdateUserPings( sizebuf_t *msg )
slot = MSG_ReadUBitLong( msg, MAX_CLIENT_BITS ); slot = MSG_ReadUBitLong( msg, MAX_CLIENT_BITS );
if( slot >= MAX_CLIENTS ) if( slot >= MAX_CLIENTS )
Host_Error( "CL_ParseServerMessage: svc_pings > MAX_CLIENTS\n" ); Host_Error( "%s: svc_pings > MAX_CLIENTS\n", __func__ );
player = &cl.players[slot]; player = &cl.players[slot];
player->ping = MSG_ReadUBitLong( msg, 12 ); player->ping = MSG_ReadUBitLong( msg, 12 );
@@ -1645,6 +1646,9 @@ void CL_RegisterResources( sizebuf_t *msg )
CL_ClearWorld (); CL_ClearWorld ();
// load skybox
R_SetupSky( clgame.movevars.skyName );
// tell rendering system we have a new set of models. // tell rendering system we have a new set of models.
ref.dllFuncs.R_NewMap (); ref.dllFuncs.R_NewMap ();
@@ -1718,7 +1722,7 @@ static void CL_ParseConsistencyInfo( sizebuf_t *msg )
} }
if( cl.num_consistency >= MAX_MODELS ) if( cl.num_consistency >= MAX_MODELS )
Host_Error( "CL_CheckConsistency: MAX_MODELS limit exceeded (%d)\n", MAX_MODELS ); Host_Error( "%s: MAX_MODELS limit exceeded (%d)\n", __func__, MAX_MODELS );
pc = &cl.consistency_list[cl.num_consistency]; pc = &cl.consistency_list[cl.num_consistency];
cl.num_consistency++; cl.num_consistency++;
@@ -1840,13 +1844,10 @@ void CL_ParseResLocation( sizebuf_t *msg )
return; return;
} }
while( ( data = COM_ParseFile( data, token, sizeof( token ) ) ) ) while(( data = COM_ParseFile( data, token, sizeof( token ))))
{ {
Con_Reportf( "Adding %s as download location\n", token ); Con_Reportf( "Adding %s as download location\n", token );
cl.http_download = true;
if( !cl.downloadUrl[0] )
Q_strncpy( cl.downloadUrl, token, sizeof( token ) );
HTTP_AddCustomServer( token ); HTTP_AddCustomServer( token );
} }
} }
@@ -1877,8 +1878,12 @@ void CL_ParseHLTV( sizebuf_t *msg )
break; break;
case HLTV_LISTEN: case HLTV_LISTEN:
cls.signon = SIGNONS; cls.signon = SIGNONS;
#if 1
MSG_ReadString( msg );
#else
NET_StringToAdr( MSG_ReadString( msg ), &cls.hltv_listen_address ); NET_StringToAdr( MSG_ReadString( msg ), &cls.hltv_listen_address );
// NET_JoinGroup( cls.netchan.sock, cls.hltv_listen_address ); NET_JoinGroup( cls.netchan.sock, cls.hltv_listen_address );
#endif
SCR_EndLoadingPlaque(); SCR_EndLoadingPlaque();
break; break;
default: default:
@@ -1988,7 +1993,7 @@ Find the client cvar value
and sent it back to the server and sent it back to the server
============== ==============
*/ */
void CL_ParseCvarValue( sizebuf_t *msg, const qboolean ext ) void CL_ParseCvarValue( sizebuf_t *msg, const qboolean ext, const connprotocol_t proto )
{ {
const char *cvarName, *response; const char *cvarName, *response;
convar_t *cvar; convar_t *cvar;
@@ -2011,7 +2016,14 @@ void CL_ParseCvarValue( sizebuf_t *msg, const qboolean ext )
else else
response = cvar->string; response = cvar->string;
} }
else response = "Bad CVAR request"; else if( proto == PROTO_LEGACY )
{
response = "Not Found";
}
else
{
response = "Bad CVAR request";
}
if( ext ) if( ext )
{ {
@@ -2128,7 +2140,7 @@ void CL_ParseUserMessage( sizebuf_t *msg, int svc_num )
if( svc_num <= svc_lastmsg || svc_num > ( MAX_USER_MESSAGES + svc_lastmsg )) if( svc_num <= svc_lastmsg || svc_num > ( MAX_USER_MESSAGES + svc_lastmsg ))
{ {
// out or range // out or range
Host_Error( "CL_ParseUserMessage: illegible server message %d\n", svc_num ); Host_Error( "%s: illegible server message %d\n", __func__, svc_num );
return; return;
} }
@@ -2140,7 +2152,7 @@ void CL_ParseUserMessage( sizebuf_t *msg, int svc_num )
} }
if( i == MAX_USER_MESSAGES ) // probably unregistered if( i == MAX_USER_MESSAGES ) // probably unregistered
Host_Error( "CL_ParseUserMessage: illegible server message %d\n", svc_num ); Host_Error( "%s: illegible server message %d\n", __func__, svc_num );
// NOTE: some user messages handled into engine // NOTE: some user messages handled into engine
if( !Q_strcmp( clgame.msg[i].name, "ScreenShake" )) if( !Q_strcmp( clgame.msg[i].name, "ScreenShake" ))
@@ -2166,7 +2178,7 @@ void CL_ParseUserMessage( sizebuf_t *msg, int svc_num )
if( iSize >= MAX_USERMSG_LENGTH ) if( iSize >= MAX_USERMSG_LENGTH )
{ {
Msg("WTF??? %d %d\n", i, svc_num ); Con_Reportf( "%s: user message %s size limit hit (%d > %d)!\n", __func__, clgame.msg[i].name, iSize, MAX_USERMSG_LENGTH );
return; return;
} }
@@ -2195,7 +2207,7 @@ void CL_ParseUserMessage( sizebuf_t *msg, int svc_num )
} }
else else
{ {
Con_DPrintf( S_ERROR "UserMsg: No pfn %s %d\n", clgame.msg[i].name, clgame.msg[i].number ); Con_DPrintf( S_ERROR "%s: No pfn %s %d\n", __func__, clgame.msg[i].name, clgame.msg[i].number );
clgame.msg[i].func = CL_UserMsgStub; // throw warning only once clgame.msg[i].func = CL_UserMsgStub; // throw warning only once
} }
} }
@@ -2214,36 +2226,19 @@ CL_ParseServerMessage
dispatch messages dispatch messages
===================== =====================
*/ */
void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message ) void CL_ParseServerMessage( sizebuf_t *msg )
{ {
size_t bufStart, playerbytes; size_t bufStart, playerbytes;
int cmd, param1, param2; int cmd, param1, param2;
int old_background; int old_background;
const char *s; const char *s;
cls.starting_count = MSG_GetNumBytesRead( msg ); // updates each frame
CL_Parse_Debug( true ); // begin parsing
if( normal_message )
{
// assume no entity/player update this packet
if( cls.state == ca_active )
{
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].valid = false;
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].choked = false;
}
else
{
CL_ResetFrame( &cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK] );
}
}
// parse the message // parse the message
while( 1 ) while( 1 )
{ {
if( MSG_CheckOverflow( msg )) if( MSG_CheckOverflow( msg ))
{ {
Host_Error( "CL_ParseServerMessage: overflow!\n" ); Host_Error( "%s: overflow!\n", __func__ );
return; return;
} }
@@ -2488,10 +2483,10 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
CL_ParseResLocation( msg ); CL_ParseResLocation( msg );
break; break;
case svc_querycvarvalue: case svc_querycvarvalue:
CL_ParseCvarValue( msg, false ); CL_ParseCvarValue( msg, false, PROTO_CURRENT );
break; break;
case svc_querycvarvalue2: case svc_querycvarvalue2:
CL_ParseCvarValue( msg, true ); CL_ParseCvarValue( msg, true, PROTO_CURRENT );
break; break;
case svc_exec: case svc_exec:
CL_ParseExec( msg ); CL_ParseExec( msg );
@@ -2502,21 +2497,4 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
break; break;
} }
} }
cl.frames[cl.parsecountmod].graphdata.msgbytes += MSG_GetNumBytesRead( msg ) - cls.starting_count;
CL_Parse_Debug( false ); // done
// we don't know if it is ok to save a demo message until
// 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 )
{
CL_WriteDemoMessage( true, cls.starting_count, msg );
}
}
} }

View File

@@ -174,7 +174,7 @@ static void CL_LegacyPrecacheSound( sizebuf_t *msg )
soundIndex = MSG_ReadUBitLong( msg, MAX_SOUND_BITS ); soundIndex = MSG_ReadUBitLong( msg, MAX_SOUND_BITS );
if( soundIndex < 0 || soundIndex >= MAX_SOUNDS ) if( soundIndex < 0 || soundIndex >= MAX_SOUNDS )
Host_Error( "CL_PrecacheSound: bad soundindex %i\n", soundIndex ); Host_Error( "%s: bad soundindex %i\n", __func__, soundIndex );
Q_strncpy( cl.sound_precache[soundIndex], MSG_ReadString( msg ), sizeof( cl.sound_precache[0] )); Q_strncpy( cl.sound_precache[soundIndex], MSG_ReadString( msg ), sizeof( cl.sound_precache[0] ));
@@ -192,9 +192,9 @@ static void CL_LegacyPrecacheModel( sizebuf_t *msg )
modelIndex = MSG_ReadUBitLong( msg, MAX_LEGACY_MODEL_BITS ); modelIndex = MSG_ReadUBitLong( msg, MAX_LEGACY_MODEL_BITS );
if( modelIndex < 0 || modelIndex >= MAX_MODELS ) if( modelIndex < 0 || modelIndex >= MAX_MODELS )
Host_Error( "CL_PrecacheModel: bad modelindex %i\n", modelIndex ); Host_Error( "%s: bad modelindex %i\n", __func__, modelIndex );
Q_strncpy( model, MSG_ReadString( msg ), MAX_STRING ); Q_strncpy( model, MSG_ReadString( msg ), sizeof( model ));
//Q_strncpy( cl.model_precache[modelIndex], BF_ReadString( msg ), sizeof( cl.model_precache[0] )); //Q_strncpy( cl.model_precache[modelIndex], BF_ReadString( msg ), sizeof( cl.model_precache[0] ));
// when we loading map all resources is precached sequentially // when we loading map all resources is precached sequentially
@@ -221,7 +221,7 @@ static void CL_LegacyPrecacheEvent( sizebuf_t *msg )
eventIndex = MSG_ReadUBitLong( msg, MAX_EVENT_BITS ); eventIndex = MSG_ReadUBitLong( msg, MAX_EVENT_BITS );
if( eventIndex < 0 || eventIndex >= MAX_EVENTS ) if( eventIndex < 0 || eventIndex >= MAX_EVENTS )
Host_Error( "CL_PrecacheEvent: bad eventindex %i\n", eventIndex ); Host_Error( "%s: bad eventindex %i\n", __func__, eventIndex );
Q_strncpy( cl.event_precache[eventIndex], MSG_ReadString( msg ), sizeof( cl.event_precache[0] )); Q_strncpy( cl.event_precache[eventIndex], MSG_ReadString( msg ), sizeof( cl.event_precache[0] ));
@@ -256,15 +256,15 @@ static void CL_LegacyParseResourceList( sizebuf_t *msg )
reslist.rescount = MSG_ReadWord( msg ) - 1; reslist.rescount = MSG_ReadWord( msg ) - 1;
if( reslist.rescount > MAX_LEGACY_RESOURCES ) if( reslist.rescount > MAX_LEGACY_RESOURCES )
Host_Error("MAX_RESOURCES reached\n"); Host_Error( "MAX_RESOURCES reached\n" );
for( i = 0; i < reslist.rescount; i++ ) for( i = 0; i < reslist.rescount; i++ )
{ {
reslist.restype[i] = MSG_ReadWord( msg ); reslist.restype[i] = MSG_ReadWord( msg );
Q_strncpy( reslist.resnames[i], MSG_ReadString( msg ), MAX_QPATH ); Q_strncpy( reslist.resnames[i], MSG_ReadString( msg ), sizeof( reslist.resnames[i] ));
} }
if( CL_IsPlaybackDemo() ) if( cls.demoplayback )
return; return;
if( !cl_allow_download.value ) if( !cl_allow_download.value )
@@ -317,36 +317,19 @@ CL_ParseLegacyServerMessage
dispatch messages dispatch messages
===================== =====================
*/ */
void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message ) void CL_ParseLegacyServerMessage( sizebuf_t *msg )
{ {
size_t bufStart, playerbytes; size_t bufStart, playerbytes;
int cmd, param1, param2; int cmd, param1, param2;
int old_background; int old_background;
const char *s; const char *s;
cls.starting_count = MSG_GetNumBytesRead( msg ); // updates each frame
CL_Parse_Debug( true ); // begin parsing
if( normal_message )
{
// assume no entity/player update this packet
if( cls.state == ca_active )
{
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].valid = false;
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].choked = false;
}
else
{
CL_ResetFrame( &cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK] );
}
}
// parse the message // parse the message
while( 1 ) while( 1 )
{ {
if( MSG_CheckOverflow( msg )) if( MSG_CheckOverflow( msg ))
{ {
Host_Error( "CL_ParseServerMessage: overflow!\n" ); Host_Error( "%s: overflow!\n", __func__ );
return; return;
} }
@@ -385,7 +368,9 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message )
{ {
int maxclients = cl.maxclients; int maxclients = cl.maxclients;
cls.changelevel = true; // we can only changelevel in singleplayer
// and singleplayer always runs in current protocol
// cls.changelevel = true;
S_StopAllSounds( true ); S_StopAllSounds( true );
Con_Printf( "Server changing, reconnecting\n" ); Con_Printf( "Server changing, reconnecting\n" );
@@ -612,10 +597,10 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message )
CL_ParseResLocation( msg ); CL_ParseResLocation( msg );
break; break;
case svc_querycvarvalue: case svc_querycvarvalue:
CL_ParseCvarValue( msg, false ); CL_ParseCvarValue( msg, false, PROTO_LEGACY );
break; break;
case svc_querycvarvalue2: case svc_querycvarvalue2:
CL_ParseCvarValue( msg, true ); CL_ParseCvarValue( msg, true, PROTO_LEGACY );
break; break;
default: default:
CL_ParseUserMessage( msg, cmd ); CL_ParseUserMessage( msg, cmd );
@@ -623,23 +608,6 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message )
break; break;
} }
} }
cl.frames[cl.parsecountmod].graphdata.msgbytes += MSG_GetNumBytesRead( msg ) - cls.starting_count;
CL_Parse_Debug( false ); // done
// we don't know if it is ok to save a demo message until
// 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 )
{
CL_WriteDemoMessage( true, cls.starting_count, msg );
}
}
} }
void CL_LegacyPrecache_f( void ) void CL_LegacyPrecache_f( void )
@@ -664,6 +632,9 @@ void CL_LegacyPrecache_f( void )
if( clgame.entities ) if( clgame.entities )
clgame.entities->model = cl.worldmodel; clgame.entities->model = cl.worldmodel;
// load skybox
R_SetupSky( clgame.movevars.skyName );
// tell rendering system we have a new set of models. // tell rendering system we have a new set of models.
ref.dllFuncs.R_NewMap (); ref.dllFuncs.R_NewMap ();
@@ -685,22 +656,10 @@ void CL_LegacyPrecache_f( void )
// Include server count in case server disconnects and changes level during d/l // Include server count in case server disconnects and changes level during d/l
MSG_BeginClientCmd( &cls.netchan.message, clc_stringcmd ); MSG_BeginClientCmd( &cls.netchan.message, clc_stringcmd );
MSG_WriteStringf( &cls.netchan.message, "begin %i", spawncount ); MSG_WriteStringf( &cls.netchan.message, "begin %i", spawncount );
cls.signon = SIGNONS; cls.signon = SIGNONS - 1;
}
void CL_LegacyUpdateInfo( void )
{
if( !cls.legacymode )
return;
if( cls.state != ca_active )
return;
MSG_BeginClientCmd( &cls.netchan.message, clc_legacy_userinfo );
MSG_WriteString( &cls.netchan.message, cls.userinfo );
} }
qboolean CL_LegacyMode( void ) qboolean CL_LegacyMode( void )
{ {
return cls.legacymode; return cls.legacymode == PROTO_LEGACY;
} }

View File

@@ -544,8 +544,8 @@ void GAME_EXPORT CL_SetSolidPlayers( int playernum )
// some fields needs to be override from cls.predicted_players // some fields needs to be override from cls.predicted_players
VectorCopy( player->origin, pe->origin ); VectorCopy( player->origin, pe->origin );
VectorCopy( player->angles, pe->angles ); VectorCopy( player->angles, pe->angles );
VectorCopy( clgame.pmove->player_mins[player->usehull], pe->mins ); VectorCopy( host.player_mins[player->usehull], pe->mins );
VectorCopy( clgame.pmove->player_maxs[player->usehull], pe->maxs ); VectorCopy( host.player_maxs[player->usehull], pe->maxs );
pe->movetype = player->movetype; pe->movetype = player->movetype;
pe->solid = player->solid; pe->solid = player->solid;
} }
@@ -853,7 +853,7 @@ static void CL_SetupPMove( playermove_t *pmove, const local_state_t *from, const
VectorCopy( cd->vuser4, pmove->vuser4 ); VectorCopy( cd->vuser4, pmove->vuser4 );
pmove->cmd = *ucmd; // copy current cmds pmove->cmd = *ucmd; // copy current cmds
Q_strncpy( pmove->physinfo, cls.physinfo, MAX_INFO_STRING ); Q_strncpy( pmove->physinfo, cls.physinfo, sizeof( pmove->physinfo ));
} }
static const void CL_FinishPMove( const playermove_t *pmove, local_state_t *to ) static const void CL_FinishPMove( const playermove_t *pmove, local_state_t *to )

View File

@@ -22,22 +22,24 @@ GNU General Public License for more details.
#include "hltv.h" #include "hltv.h"
#include "input.h" #include "input.h"
#define STAT_HEALTH 0 enum {
#define STAT_FRAGS 1 STAT_HEALTH = 0,
#define STAT_WEAPON 2 STAT_FRAGS,
#define STAT_AMMO 3 STAT_WEAPON,
#define STAT_ARMOR 4 STAT_AMMO,
#define STAT_WEAPONFRAME 5 STAT_ARMOR,
#define STAT_SHELLS 6 STAT_WEAPONFRAME,
#define STAT_NAILS 7 STAT_SHELLS,
#define STAT_ROCKETS 8 STAT_NAILS,
#define STAT_CELLS 9 STAT_ROCKETS,
#define STAT_ACTIVEWEAPON 10 STAT_CELLS,
#define STAT_TOTALSECRETS 11 STAT_ACTIVEWEAPON,
#define STAT_TOTALMONSTERS 12 STAT_TOTALSECRETS,
#define STAT_SECRETS 13 // bumped on client side by svc_foundsecret STAT_TOTALMONSTERS,
#define STAT_MONSTERS 14 // bumped by svc_killedmonster STAT_SECRETS, // bumped on client side by svc_foundsecret
#define MAX_STATS 32 STAT_MONSTERS, // bumped by svc_killedmonster
MAX_STATS = 32,
};
static char cmd_buf[8192]; static char cmd_buf[8192];
static char msg_buf[8192]; static char msg_buf[8192];
@@ -211,7 +213,7 @@ static void CL_ParseQuakeServerInfo( sizebuf_t *msg )
clgame.maxEntities = GI->max_edicts; clgame.maxEntities = GI->max_edicts;
clgame.maxEntities = bound( 600, clgame.maxEntities, MAX_EDICTS ); clgame.maxEntities = bound( 600, clgame.maxEntities, MAX_EDICTS );
clgame.maxModels = MAX_MODELS; clgame.maxModels = MAX_MODELS;
Q_strncpy( clgame.maptitle, MSG_ReadString( msg ), MAX_STRING ); Q_strncpy( clgame.maptitle, MSG_ReadString( msg ), sizeof( clgame.maptitle ));
// Re-init hud video, especially if we changed game directories // Re-init hud video, especially if we changed game directories
clgame.dllFuncs.pfnVidInit(); clgame.dllFuncs.pfnVidInit();
@@ -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.gravity = 800.0f; // quake doesn't write gravity in demos
clgame.movevars.maxvelocity = 2000.0f; clgame.movevars.maxvelocity = 2000.0f;
memcpy( &clgame.oldmovevars, &clgame.movevars, sizeof( movevars_t )); clgame.oldmovevars = clgame.movevars;
} }
/* /*
@@ -620,11 +622,11 @@ static void CL_ParseQuakeDamage( sizebuf_t *msg )
/* /*
=================== ===================
CL_ParseQuakeStaticEntity CL_ParseStaticEntity
=================== ===================
*/ */
static void CL_ParseQuakeStaticEntity( sizebuf_t *msg ) static void CL_ParseStaticEntity( sizebuf_t *msg )
{ {
entity_state_t state; entity_state_t state;
cl_entity_t *ent; cl_entity_t *ent;
@@ -646,7 +648,7 @@ static void CL_ParseQuakeStaticEntity( sizebuf_t *msg )
i = clgame.numStatics; i = clgame.numStatics;
if( i >= MAX_STATIC_ENTITIES ) if( i >= MAX_STATIC_ENTITIES )
{ {
Con_Printf( S_ERROR "CL_ParseStaticEntity: static entities limit exceeded!\n" ); Con_Printf( S_ERROR "%s: static entities limit exceeded!\n", __func__ );
return; return;
} }
@@ -697,7 +699,7 @@ static void CL_ParseQuakeBaseline( sizebuf_t *msg )
newnum = MSG_ReadWord( msg ); // entnum newnum = MSG_ReadWord( msg ); // entnum
if( newnum >= clgame.maxEntities ) if( newnum >= clgame.maxEntities )
Host_Error( "CL_AllocEdict: no free edicts\n" ); Host_Error( "%s: no free edicts\n", __func__ );
// parse baseline // parse baseline
memset( &state, 0, sizeof( state )); memset( &state, 0, sizeof( state ));
@@ -715,8 +717,7 @@ static void CL_ParseQuakeBaseline( sizebuf_t *msg )
ent = CL_EDICT_NUM( newnum ); ent = CL_EDICT_NUM( newnum );
ent->index = newnum; ent->index = newnum;
ent->player = CL_IsPlayerIndex( newnum ); ent->player = CL_IsPlayerIndex( newnum );
memcpy( &ent->baseline, &state, sizeof( entity_state_t )); ent->prevstate = ent->baseline = state;
memcpy( &ent->prevstate, &state, sizeof( entity_state_t ));
} }
/* /*
@@ -778,7 +779,7 @@ static void CL_ParseQuakeSignon( sizebuf_t *msg )
int i = MSG_ReadByte( msg ); int i = MSG_ReadByte( msg );
if( i == 3 ) cls.signon = SIGNONS - 1; if( i == 3 ) cls.signon = SIGNONS - 1;
Con_Reportf( "CL_Signon: %d\n", i ); Con_Reportf( "%s: %d\n", __func__, i );
} }
/* /*
@@ -844,7 +845,7 @@ static void CL_QuakeExecStuff( void )
while( 1 ) while( 1 )
{ {
// skip whitespace up to a /n // skip whitespace up to a /n
while( *text && ((byte)*text) <= ' ' && *text != '\r' && *text != '\n' ) while( *text && ((byte)*text ) <= ' ' && *text != '\r' && *text != '\n' )
text++; text++;
if( *text == '\n' || *text == '\r' ) if( *text == '\n' || *text == '\r' )
@@ -886,38 +887,21 @@ CL_ParseQuakeMessage
================== ==================
*/ */
void CL_ParseQuakeMessage( sizebuf_t *msg, qboolean normal_message ) void CL_ParseQuakeMessage( sizebuf_t *msg )
{ {
int cmd, param1, param2; int cmd, param1, param2;
size_t bufStart; size_t bufStart;
const char *str; const char *str;
cls.starting_count = MSG_GetNumBytesRead( msg ); // updates each frame
CL_Parse_Debug( true ); // begin parsing
// init excise buffer // init excise buffer
MSG_Init( &msg_demo, "UserMsg", msg_buf, sizeof( msg_buf )); MSG_Init( &msg_demo, "UserMsg", msg_buf, sizeof( msg_buf ));
if( normal_message )
{
// assume no entity/player update this packet
if( cls.state == ca_active )
{
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].valid = false;
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].choked = false;
}
else
{
CL_ResetFrame( &cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK] );
}
}
// parse the message // parse the message
while( 1 ) while( 1 )
{ {
if( MSG_CheckOverflow( msg )) if( MSG_CheckOverflow( msg ))
{ {
Host_Error( "CL_ParseServerMessage: overflow!\n" ); Host_Error( "%s: overflow!\n", __func__ );
return; return;
} }
@@ -1022,7 +1006,7 @@ void CL_ParseQuakeMessage( sizebuf_t *msg, qboolean normal_message )
CL_ParseQuakeDamage( msg ); CL_ParseQuakeDamage( msg );
break; break;
case svc_spawnstatic: case svc_spawnstatic:
CL_ParseQuakeStaticEntity( msg ); CL_ParseStaticEntity( msg );
break; break;
case svc_spawnbinary: case svc_spawnbinary:
// never used in Quake // never used in Quake
@@ -1108,14 +1092,11 @@ void CL_ParseQuakeMessage( sizebuf_t *msg, qboolean normal_message )
} }
break; break;
default: default:
Host_Error( "CL_ParseServerMessage: Illegible server message\n" ); Host_Error( "%s: Illegible server message\n", __func__ );
break; break;
} }
} }
cl.frames[cl.parsecountmod].graphdata.msgbytes += MSG_GetNumBytesRead( msg ) - cls.starting_count;
CL_Parse_Debug( false ); // done
// now process packet. // now process packet.
CL_ProcessPacket( &cl.frames[cl.parsecountmod] ); CL_ProcessPacket( &cl.frames[cl.parsecountmod] );

View File

@@ -20,7 +20,7 @@ GNU General Public License for more details.
int R_FatPVS( const vec3_t org, float radius, byte *visbuffer, qboolean merge, qboolean fullvis ) int R_FatPVS( const vec3_t org, float radius, byte *visbuffer, qboolean merge, qboolean fullvis )
{ {
return Mod_FatPVS( org, radius, visbuffer, world.visbytes, merge, fullvis ); return Mod_FatPVS( org, radius, visbuffer, world.visbytes, merge, fullvis, false );
} }
lightstyle_t *CL_GetLightStyle( int number ) lightstyle_t *CL_GetLightStyle( int number )
@@ -170,6 +170,12 @@ intptr_t CL_RenderGetParm( const int parm, const int arg, const qboolean checkRe
return refState.width; return refState.width;
case PARM_SCREEN_HEIGHT: case PARM_SCREEN_HEIGHT:
return refState.height; return refState.height;
case PARM_SKY_SPHERE:
return FBitSet( world.flags, FWORLD_SKYSPHERE ) && !FBitSet( world.flags, FWORLD_CUSTOM_SKYBOX );
case PARM_SURF_SAMPLESIZE:
if( arg >= 0 && arg < cl.worldmodel->numsurfaces )
return Mod_SampleSizeForFace( &cl.worldmodel->surfaces[arg] );
return LM_SAMPLE_SIZE;
default: default:
// indicates call from client.dll // indicates call from client.dll
if( checkRef ) if( checkRef )
@@ -341,7 +347,7 @@ qboolean R_InitRenderAPI( void )
{ {
if( clgame.dllFuncs.pfnGetRenderInterface( CL_RENDER_INTERFACE_VERSION, &gRenderAPI, &clgame.drawFuncs )) if( clgame.dllFuncs.pfnGetRenderInterface( CL_RENDER_INTERFACE_VERSION, &gRenderAPI, &clgame.drawFuncs ))
{ {
Con_Reportf( "CL_LoadProgs: ^2initailized extended RenderAPI ^7ver. %i\n", CL_RENDER_INTERFACE_VERSION ); Con_Reportf( "%s: ^2initailized extended RenderAPI ^7ver. %i\n", __func__, CL_RENDER_INTERFACE_VERSION );
return true; return true;
} }

View File

@@ -24,7 +24,7 @@ CVAR_DEFINE_AUTO( scr_centertime, "2.5", 0, "centerprint hold time" );
CVAR_DEFINE_AUTO( scr_loading, "0", 0, "loading bar progress" ); CVAR_DEFINE_AUTO( scr_loading, "0", 0, "loading bar progress" );
CVAR_DEFINE_AUTO( scr_download, "-1", 0, "downloading bar progress" ); CVAR_DEFINE_AUTO( scr_download, "-1", 0, "downloading bar progress" );
CVAR_DEFINE( scr_viewsize, "viewsize", "120", FCVAR_ARCHIVE, "screen size (quake only)" ); CVAR_DEFINE( scr_viewsize, "viewsize", "120", FCVAR_ARCHIVE, "screen size (quake only)" );
CVAR_DEFINE_AUTO( cl_testlights, "0", 0, "test dynamic lights" ); CVAR_DEFINE_AUTO( cl_testlights, "0", FCVAR_CHEAT, "test dynamic lights" );
CVAR_DEFINE( cl_allow_levelshots, "allow_levelshots", "0", FCVAR_ARCHIVE, "allow engine to use indivdual levelshots instead of 'loading' image" ); CVAR_DEFINE( cl_allow_levelshots, "allow_levelshots", "0", FCVAR_ARCHIVE, "allow engine to use indivdual levelshots instead of 'loading' image" );
CVAR_DEFINE_AUTO( cl_levelshot_name, "*black", 0, "contains path to current levelshot" ); CVAR_DEFINE_AUTO( cl_levelshot_name, "*black", 0, "contains path to current levelshot" );
static CVAR_DEFINE_AUTO( cl_envshot_size, "256", FCVAR_ARCHIVE, "envshot size of cube side" ); static CVAR_DEFINE_AUTO( cl_envshot_size, "256", FCVAR_ARCHIVE, "envshot size of cube side" );
@@ -32,6 +32,7 @@ CVAR_DEFINE_AUTO( v_dark, "0", 0, "starts level from dark screen" );
static CVAR_DEFINE_AUTO( net_speeds, "0", FCVAR_ARCHIVE, "show network packets" ); static CVAR_DEFINE_AUTO( net_speeds, "0", FCVAR_ARCHIVE, "show network packets" );
static CVAR_DEFINE_AUTO( cl_showfps, "0", FCVAR_ARCHIVE, "show client fps" ); static CVAR_DEFINE_AUTO( cl_showfps, "0", FCVAR_ARCHIVE, "show client fps" );
static CVAR_DEFINE_AUTO( cl_showpos, "0", FCVAR_ARCHIVE, "show local player position and velocity" ); static CVAR_DEFINE_AUTO( cl_showpos, "0", FCVAR_ARCHIVE, "show local player position and velocity" );
static CVAR_DEFINE_AUTO( cl_showents, "0", FCVAR_ARCHIVE | FCVAR_CHEAT, "show entities information (largely undone)" );
typedef struct typedef struct
{ {
@@ -122,7 +123,7 @@ void SCR_DrawPos( void )
if( cls.state != ca_active || !cl_showpos.value || cl.background ) if( cls.state != ca_active || !cl_showpos.value || cl.background )
return; return;
ent = CL_GetLocalPlayer(); ent = CL_EDICT_NUM( cl.playernum + 1 );
speed = VectorLength( cl.simvel ); speed = VectorLength( cl.simvel );
Q_snprintf( msg, MAX_SYSPATH, Q_snprintf( msg, MAX_SYSPATH,
@@ -140,6 +141,68 @@ void SCR_DrawPos( void )
Con_DrawString( refState.width / 2, 4, msg, color ); Con_DrawString( refState.width / 2, 4, msg, color );
} }
/*
==============
SCR_DrawEnts
==============
*/
void SCR_DrawEnts( void )
{
rgba_t color = { 255, 255, 255, 255 };
int i;
if( cls.state != ca_active || !cl_showents.value || ( cl.maxclients > 1 && !cls.demoplayback ))
return;
// this probably better hook CL_AddVisibleEntities
// as entities might get added by client.dll
for( i = 0; i < clgame.maxEntities; i++ )
{
const cl_entity_t *ent = &clgame.entities[i];
string msg;
vec3_t screen, pos;
if( ent->curstate.messagenum != cl.parsecount )
continue;
VectorCopy( ent->origin, pos );
if( ent->model != NULL )
{
vec3_t v;
// simple model type filter
if( cl_showents.value > 1 )
{
if( ent->model->type != (modtype_t)( cl_showents.value - 2 ))
continue;
}
VectorAverage( ent->model->mins, ent->model->maxs, v );
VectorAdd( pos, v, pos );
}
if( !ref.dllFuncs.WorldToScreen( pos, screen ))
{
Q_snprintf( msg, sizeof( msg ),
"entity %d\n"
"model %s\n"
"movetype %d\n",
ent->index,
ent->model ? ent->model->name : "(null)",
ent->curstate.movetype );
screen[0] = 0.5f * screen[0] * refState.width;
screen[1] = -0.5f * screen[1] * refState.height;
screen[0] += 0.5f * refState.width;
screen[1] += 0.5f * refState.height;
Con_DrawString( screen[0], screen[1], msg, color );
}
}
}
/* /*
============== ==============
SCR_NetSpeeds SCR_NetSpeeds
@@ -345,7 +408,7 @@ void SCR_MakeScreenShot( void )
SCR_DrawPlaque SCR_DrawPlaque
================ ================
*/ */
static void SCR_DrawPlaque( void ) static qboolean SCR_DrawPlaque( void )
{ {
if(( cl_allow_levelshots.value && !cls.changelevel ) || cl.background ) if(( cl_allow_levelshots.value && !cls.changelevel ) || cl.background )
{ {
@@ -353,7 +416,11 @@ static void SCR_DrawPlaque( void )
ref.dllFuncs.GL_SetRenderMode( kRenderNormal ); ref.dllFuncs.GL_SetRenderMode( kRenderNormal );
ref.dllFuncs.R_DrawStretchPic( 0, 0, refState.width, refState.height, 0, 0, 1, 1, levelshot ); ref.dllFuncs.R_DrawStretchPic( 0, 0, refState.width, refState.height, 0, 0, 1, 1, levelshot );
if( !cl.background ) CL_DrawHUD( CL_LOADING ); if( !cl.background ) CL_DrawHUD( CL_LOADING );
return true;
} }
return false;
} }
/* /*
@@ -363,15 +430,10 @@ SCR_BeginLoadingPlaque
*/ */
void SCR_BeginLoadingPlaque( qboolean is_background ) void SCR_BeginLoadingPlaque( qboolean is_background )
{ {
float oldclear = 0;;
S_StopAllSounds( true ); S_StopAllSounds( true );
cl.audio_prepped = false; // don't play ambients cl.audio_prepped = false; // don't play ambients
cl.video_prepped = false;
if( !Host_IsDedicated() ) if( cls.key_dest == key_menu && !cls.changedemo && !is_background )
oldclear = gl_clear.value;
if( CL_IsInMenu( ) && !cls.changedemo && !is_background )
{ {
UI_SetActiveMenu( false ); UI_SetActiveMenu( false );
if( cls.state == ca_disconnected && !(GameState->curstate == STATE_RUNFRAME && GameState->nextstate != STATE_RUNFRAME) ) if( cls.state == ca_disconnected && !(GameState->curstate == STATE_RUNFRAME && GameState->nextstate != STATE_RUNFRAME) )
@@ -384,18 +446,15 @@ void SCR_BeginLoadingPlaque( qboolean is_background )
if( cls.key_dest == key_console ) if( cls.key_dest == key_console )
return; return;
if( !Host_IsDedicated() )
gl_clear.value = 0.0f;
if( is_background ) IN_MouseSavePos( ); if( is_background ) IN_MouseSavePos( );
cls.draw_changelevel = !is_background; cls.draw_changelevel = !is_background;
SCR_UpdateScreen(); SCR_UpdateScreen();
// set video_prepped after update screen, so engine can draw last remaining frame
cl.video_prepped = false;
cls.disable_screen = host.realtime; cls.disable_screen = host.realtime;
cl.background = is_background; // set right state before svc_serverdata is came cl.background = is_background; // set right state before svc_serverdata is came
if( !Host_IsDedicated() )
gl_clear.value = oldclear;
// SNDDMA_LockSound(); // SNDDMA_LockSound();
} }
@@ -445,7 +504,7 @@ void SCR_TileClear( void )
int i, top, bottom, left, right; int i, top, bottom, left, right;
dirty_t clear; dirty_t clear;
if( scr_viewsize.value >= 120 ) if( likely( scr_viewsize.value >= 120 ))
return; // full screen rendering return; // full screen rendering
// erase rect will be the union of the past three frames // erase rect will be the union of the past three frames
@@ -523,6 +582,8 @@ text to the screen.
*/ */
void SCR_UpdateScreen( void ) void SCR_UpdateScreen( void )
{ {
qboolean screen_redraw = true; // assume screen has been redrawn
if( !V_PreRender( )) return; if( !V_PreRender( )) return;
switch( cls.state ) switch( cls.state )
@@ -533,7 +594,7 @@ void SCR_UpdateScreen( void )
case ca_connecting: case ca_connecting:
case ca_connected: case ca_connected:
case ca_validate: case ca_validate:
SCR_DrawPlaque(); screen_redraw = SCR_DrawPlaque();
break; break;
case ca_active: case ca_active:
Con_RunConsole (); Con_RunConsole ();
@@ -543,11 +604,15 @@ void SCR_UpdateScreen( void )
SCR_DrawCinematic(); SCR_DrawCinematic();
break; break;
default: default:
Host_Error( "SCR_UpdateScreen: bad cls.state\n" ); Host_Error( "%s: bad cls.state\n", __func__ );
break; break;
} }
V_PostRender(); // during changelevel we might have a few frames when we have nothing to draw
// (assuming levelshots are off) and drawing 2d on top of nothing or cleared screen
// is ugly, specifically with Adreno and ImgTec GPUs
if( screen_redraw || !cls.changelevel || !cls.changedemo )
V_PostRender();
} }
/* /*
@@ -753,6 +818,9 @@ void SCR_Init( void )
Cvar_RegisterVariable( &net_speeds ); Cvar_RegisterVariable( &net_speeds );
Cvar_RegisterVariable( &cl_showfps ); Cvar_RegisterVariable( &cl_showfps );
Cvar_RegisterVariable( &cl_showpos ); Cvar_RegisterVariable( &cl_showpos );
#ifdef _DEBUG
Cvar_RegisterVariable( &cl_showents );
#endif // NDEBUG
// register our commands // register our commands
Cmd_AddCommand( "skyname", CL_SetSky_f, "set new skybox by basename" ); Cmd_AddCommand( "skyname", CL_SetSky_f, "set new skybox by basename" );

View File

@@ -1269,6 +1269,73 @@ void GAME_EXPORT R_Sprite_Smoke( TEMPENTITY *pTemp, float scale )
pTemp->entity.curstate.scale = scale; pTemp->entity.curstate.scale = scale;
} }
static void R_Spray_Generic( const char *func, const vec3_t pos, const vec3_t dir, int modelIndex, int count, int speed, int spread, int rendermode, qboolean sprite_spray )
{
model_t *mod = CL_ModelHandle( modelIndex );
float noise = spread / 100.0f;
float znoise = noise * 1.5f;
int i;
znoise = Q_min( 1.0f, znoise );
if( !mod )
{
Con_Reportf( "%s: No model %d!\n", func, modelIndex );
return;
}
for( i = 0; i < count; i++ )
{
TEMPENTITY *tent = CL_TempEntAlloc( pos, mod );
float rand_speed;
vec3_t noise_vec, vout;
if( !tent )
break;
tent->flags |= FTENT_SLOWGRAVITY;
tent->entity.curstate.rendermode = rendermode;
tent->entity.curstate.renderamt = 255;
tent->entity.baseline.renderamt = 255;
tent->entity.curstate.renderfx = kRenderFxNoDissipation;
noise_vec[0] = COM_RandomFloat( -noise, noise );
noise_vec[1] = COM_RandomFloat( -noise, noise );
noise_vec[2] = COM_RandomFloat( 0.0f, znoise );
rand_speed = COM_RandomFloat( speed * 0.8f, speed * 1.2f );
VectorAdd( dir, noise_vec, vout );
VectorScale( vout, rand_speed, tent->entity.baseline.origin );
if( sprite_spray ) // if TE_SPRITE_SPRAY
{
tent->flags |= FTENT_FADEOUT;
tent->fadeSpeed = 2.0f;
tent->entity.curstate.framerate = 0.5f;
tent->die = cl.time + 0.35;
tent->entity.curstate.frame = COM_RandomLong( 0, tent->frameMax ); // frameMax inclusive
}
else
{
tent->flags |= FTENT_COLLIDEWORLD;
if( tent->frameMax > 1 )
{
tent->flags |= FTENT_SPRANIMATE;
tent->entity.curstate.framerate = 10.0f;
tent->die = cl.time + tent->frameMax * 0.1;
}
else
{
tent->entity.curstate.framerate = 1.0f;
tent->die = cl.time + 0.35;
}
tent->entity.curstate.frame = 0.0f;
}
}
}
/* /*
=============== ===============
R_Spray R_Spray
@@ -1278,61 +1345,7 @@ Throws a shower of sprites or models
*/ */
void GAME_EXPORT R_Spray( const vec3_t pos, const vec3_t dir, int modelIndex, int count, int speed, int spread, int rendermode ) void GAME_EXPORT R_Spray( const vec3_t pos, const vec3_t dir, int modelIndex, int count, int speed, int spread, int rendermode )
{ {
TEMPENTITY *pTemp; R_Spray_Generic( __func__, pos, dir, modelIndex, count, speed, spread, rendermode, false );
float noise;
float znoise;
model_t *pmodel;
int i;
if(( pmodel = CL_ModelHandle( modelIndex )) == NULL )
{
Con_Reportf( "No model %d!\n", modelIndex );
return;
}
noise = (float)spread / 100.0f;
// more vertical displacement
znoise = Q_min( 1.0f, noise * 1.5f );
for( i = 0; i < count; i++ )
{
pTemp = CL_TempEntAlloc( pos, pmodel );
if( !pTemp ) return;
pTemp->entity.curstate.rendermode = rendermode;
pTemp->entity.baseline.renderamt = pTemp->entity.curstate.renderamt = 255;
pTemp->entity.curstate.renderfx = kRenderFxNoDissipation;
if( rendermode != kRenderGlow )
{
// spray
pTemp->flags |= FTENT_COLLIDEWORLD | FTENT_SLOWGRAVITY;
if( pTemp->frameMax > 1 )
{
pTemp->flags |= FTENT_COLLIDEWORLD | FTENT_SLOWGRAVITY | FTENT_SPRANIMATE;
pTemp->die = cl.time + (pTemp->frameMax * 0.1f);
pTemp->entity.curstate.framerate = 10;
}
else pTemp->die = cl.time + 0.35f;
}
else
{
// sprite spray
pTemp->entity.curstate.frame = COM_RandomLong( 0, pTemp->frameMax );
pTemp->flags |= FTENT_FADEOUT | FTENT_SLOWGRAVITY;
pTemp->entity.curstate.framerate = 0.5;
pTemp->die = cl.time + 0.35f;
pTemp->fadeSpeed = 2.0;
}
// make the spittle fly the direction indicated, but mix in some noise.
pTemp->entity.baseline.origin[0] = dir[0] + COM_RandomFloat( -noise, noise );
pTemp->entity.baseline.origin[1] = dir[1] + COM_RandomFloat( -noise, noise );
pTemp->entity.baseline.origin[2] = dir[2] + COM_RandomFloat( 0, znoise );
VectorScale( pTemp->entity.baseline.origin, COM_RandomFloat(( speed * 0.8f ), ( speed * 1.2f )), pTemp->entity.baseline.origin );
}
} }
/* /*
@@ -1344,7 +1357,7 @@ Spray of alpha sprites
*/ */
void GAME_EXPORT R_Sprite_Spray( const vec3_t pos, const vec3_t dir, int modelIndex, int count, int speed, int spread ) void GAME_EXPORT R_Sprite_Spray( const vec3_t pos, const vec3_t dir, int modelIndex, int count, int speed, int spread )
{ {
R_Spray( pos, dir, modelIndex, count, speed, spread, kRenderGlow ); R_Spray_Generic( __func__, pos, dir, modelIndex, count, speed, spread, kRenderTransAlpha, true );
} }
/* /*
@@ -1904,7 +1917,7 @@ void CL_ParseTempEntity( sizebuf_t *msg )
// this will probably be fatal anyway // this will probably be fatal anyway
if( iSize > sizeof( pbuf )) if( iSize > sizeof( pbuf ))
Con_Printf( S_ERROR "%s: Temp buffer overflow!\n", __FUNCTION__ ); Con_Printf( S_ERROR "%s: Temp buffer overflow!\n", __func__ );
// parse user message into buffer // parse user message into buffer
MSG_ReadBytes( msg, pbuf, iSize ); MSG_ReadBytes( msg, pbuf, iSize );
@@ -2384,13 +2397,13 @@ void CL_ParseTempEntity( sizebuf_t *msg )
R_UserTracerParticle( pos, pos2, life, color, scale, 0, NULL ); R_UserTracerParticle( pos, pos2, life, color, scale, 0, NULL );
break; break;
default: default:
Con_DPrintf( S_ERROR "ParseTempEntity: illegible TE message %i\n", type ); Con_DPrintf( S_ERROR "%s: illegible TE message %i\n", __func__, type );
break; break;
} }
// throw warning // throw warning
if( MSG_CheckOverflow( &buf )) if( MSG_CheckOverflow( &buf ))
Con_DPrintf( S_WARN "ParseTempEntity: overflow TE message %i\n", type ); Con_DPrintf( S_WARN "%s: overflow TE message %i\n", __func__, type );
} }
@@ -2448,7 +2461,8 @@ void CL_SetLightstyle( int style, const char *s, float f )
} }
} }
Con_Reportf( "Lightstyle %i (%s), interp %s\n", style, ls->pattern, ls->interp ? "Yes" : "No" ); if( ls->length >= 1 )
Con_Reportf( "Lightstyle %i (%s), interp %s\n", style, ls->pattern, ls->interp ? "Yes" : "No" );
} }
/* /*
@@ -2570,31 +2584,43 @@ CL_DecayLights
*/ */
void CL_DecayLights( void ) void CL_DecayLights( void )
{ {
dlight_t *dl; const float time = cl.time;
float time; const float dt = cl.time - cl.oldtime;
int i; int i;
time = cl.time - cl.oldtime; for( i = 0; i < MAX_DLIGHTS; i++ )
for( i = 0, dl = cl_dlights; i < MAX_DLIGHTS; i++, dl++ )
{ {
if( !dl->radius ) continue; dlight_t *dl = &cl_dlights[i];
dl->radius -= time * dl->decay; if( !dl->radius )
if( dl->radius < 0 ) dl->radius = 0; continue;
if( dl->die < cl.time || !dl->radius ) if( dl->die < time )
{
memset( dl, 0, sizeof( *dl ));
continue;
}
dl->radius -= dt * dl->decay;
if( dl->radius <= 0 )
memset( dl, 0, sizeof( *dl )); memset( dl, 0, sizeof( *dl ));
} }
for( i = 0, dl = cl_elights; i < MAX_ELIGHTS; i++, dl++ ) for( i = 0; i < MAX_ELIGHTS; i++ )
{ {
if( !dl->radius ) continue; dlight_t *dl = &cl_elights[i];
dl->radius -= time * dl->decay; if( !dl->radius )
if( dl->radius < 0 ) dl->radius = 0; continue;
if( dl->die < cl.time || !dl->radius ) if( dl->die < time )
{
memset( dl, 0, sizeof( *dl ));
continue;
}
dl->radius -= dt * dl->decay;
if( dl->radius <= 0 )
memset( dl, 0, sizeof( *dl )); memset( dl, 0, sizeof( *dl ));
} }
} }
@@ -2737,7 +2763,12 @@ void CL_AddEntityEffects( cl_entity_t *ent )
if( FBitSet( ent->curstate.effects, EF_BRIGHTLIGHT )) if( FBitSet( ent->curstate.effects, EF_BRIGHTLIGHT ))
R_EntityBrightlight( ent, ent->index /* 1 in GoldSrc */, 400 ); R_EntityBrightlight( ent, ent->index /* 1 in GoldSrc */, 400 );
else if( FBitSet( ent->curstate.effects, EF_DIMLIGHT )) else if( FBitSet( ent->curstate.effects, EF_DIMLIGHT ))
CL_UpdateFlashlight( ent ); {
if( Host_IsQuakeCompatible( ))
R_EntityDimlight( ent, ent->index );
else
CL_UpdateFlashlight( ent );
}
} }
else else
{ {
@@ -2927,16 +2958,26 @@ static void CL_PlayerDecal( int playernum, int customIndex, int entityIndex, flo
{ {
if( !pCust->nUserData1 ) if( !pCust->nUserData1 )
{ {
int sprayTextureIndex;
char decalname[MAX_VA_STRING]; char decalname[MAX_VA_STRING];
int width, height;
Q_snprintf( decalname, sizeof( decalname ), "player%dlogo%d", playernum, customIndex ); Q_snprintf( decalname, sizeof( decalname ), "player%dlogo%d", playernum, customIndex );
sprayTextureIndex = ref.dllFuncs.GL_FindTexture( decalname ); textureIndex = ref.dllFuncs.GL_FindTexture( decalname );
if( sprayTextureIndex != 0 ) if( textureIndex != 0 )
{ ref.dllFuncs.GL_FreeTexture( textureIndex );
ref.dllFuncs.GL_FreeTexture( sprayTextureIndex );
}
pCust->nUserData1 = GL_LoadTextureInternal( decalname, pCust->pInfo, TF_DECAL ); pCust->nUserData1 = GL_LoadTextureInternal( decalname, pCust->pInfo, TF_DECAL );
width = REF_GET_PARM( PARM_TEX_WIDTH, pCust->nUserData1 );
height = REF_GET_PARM( PARM_TEX_HEIGHT, pCust->nUserData1 );
if( width > cl_logomaxdim.value || height > cl_logomaxdim.value )
{
double scale = cl_logomaxdim.value / Q_max( width, height );
width = round( width * scale );
height = round( height * scale );
ref.dllFuncs.R_OverrideTextureSourceSize( pCust->nUserData1, width, height ); // default custom decal from HL1
}
} }
textureIndex = pCust->nUserData1; textureIndex = pCust->nUserData1;
} }
@@ -2981,8 +3022,47 @@ int GAME_EXPORT CL_DecalIndex( int id )
if( cl.decal_index[id] == 0 ) if( cl.decal_index[id] == 0 )
{ {
int gl_texturenum = 0;
Image_SetForceFlags( IL_LOAD_DECAL ); Image_SetForceFlags( IL_LOAD_DECAL );
cl.decal_index[id] = ref.dllFuncs.GL_LoadTexture( host.draw_decals[id], NULL, 0, TF_DECAL );
if( Mod_AllowMaterials( ))
{
string decalname;
if( Q_snprintf( decalname, sizeof( decalname ), "materials/decals/%s.tga", host.draw_decals[id] ) > 0 )
{
if( g_fsapi.FileExists( decalname, false ))
{
gl_texturenum = ref.dllFuncs.GL_LoadTexture( decalname, NULL, 0, TF_DECAL );
if( host_allow_materials.value == 2.0f )
Con_Printf( "Looking for %s decal replacement...%s (%s)\n", host.draw_decals[id], gl_texturenum != 0 ? S_GREEN "OK" : S_RED "FAIL", decalname );
}
else if( host_allow_materials.value == 2.0f )
Con_Printf( "Looking for %s decal replacement..." S_YELLOW "MISS (%s)\n", host.draw_decals[id], decalname );
}
else if( host_allow_materials.value == 2.0f )
Con_Printf( "Looking for %s decal replacement..." S_YELLOW "MISS (overflow)\n", host.draw_decals[id] );
if( gl_texturenum )
{
byte *fin;
Q_snprintf( decalname, sizeof( decalname ), "decals.wad/%s", host.draw_decals[id] );
if(( fin = g_fsapi.LoadFile( decalname, NULL, false )) != NULL )
{
mip_t *mip = (mip_t *)fin;
ref.dllFuncs.R_OverrideTextureSourceSize( gl_texturenum, mip->width, mip->height );
Mem_Free( fin );
}
}
}
if( !gl_texturenum )
gl_texturenum = ref.dllFuncs.GL_LoadTexture( host.draw_decals[id], NULL, 0, TF_DECAL );
cl.decal_index[id] = gl_texturenum;
Image_ClearForceFlags(); Image_ClearForceFlags();
} }
@@ -3009,26 +3089,6 @@ EFRAGS MANAGEMENT
============================================================== ==============================================================
*/ */
efrag_t cl_efrags[MAX_EFRAGS];
/*
==============
CL_ClearEfrags
==============
*/
void CL_ClearEfrags( void )
{
int i;
memset( cl_efrags, 0, sizeof( cl_efrags ));
// allocate the efrags and chain together into a free list
clgame.free_efrags = cl_efrags;
for( i = 0; i < MAX_EFRAGS - 1; i++ )
clgame.free_efrags[i].entnext = &clgame.free_efrags[i+1];
clgame.free_efrags[i].entnext = NULL;
}
/* /*
======================= =======================
R_ClearStaticEntities R_ClearStaticEntities
@@ -3066,4 +3126,3 @@ void CL_ClearEffects( void )
CL_ClearParticles (); CL_ClearParticles ();
CL_ClearLightStyles (); CL_ClearLightStyles ();
} }

View File

@@ -35,7 +35,7 @@ static void V_CalcViewRect( void )
int sb_lines; int sb_lines;
float size; float size;
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE )) if( Host_IsQuakeCompatible( ))
{ {
// intermission is always full screen // intermission is always full screen
if( cl.intermission ) size = 120.0f; if( cl.intermission ) size = 120.0f;
@@ -144,7 +144,9 @@ static void V_SetRefParams( ref_params_t *fd )
VectorCopy( cl.viewangles, fd->cl_viewangles ); VectorCopy( cl.viewangles, fd->cl_viewangles );
fd->health = cl.local.health; fd->health = cl.local.health;
VectorCopy( cl.crosshairangle, fd->crosshairangle ); 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 ); VectorCopy( cl.punchangle, fd->punchangle );
fd->maxclients = cl.maxclients; fd->maxclients = cl.maxclients;
@@ -341,7 +343,7 @@ qboolean V_PreRender( void )
{ {
if(( host.realtime - cls.disable_screen ) > cl_timeout.value ) if(( host.realtime - cls.disable_screen ) > cl_timeout.value )
{ {
Con_Reportf( "V_PreRender: loading plaque timed out\n" ); Con_Reportf( "%s: loading plaque timed out\n", __func__ );
cls.disable_screen = 0.0f; cls.disable_screen = 0.0f;
} }
return false; return false;
@@ -506,7 +508,6 @@ V_PostRender
*/ */
void V_PostRender( void ) void V_PostRender( void )
{ {
static double oldtime;
qboolean draw_2d = false; qboolean draw_2d = false;
ref.dllFuncs.R_AllowFog( false ); ref.dllFuncs.R_AllowFog( false );
@@ -533,6 +534,7 @@ void V_PostRender( void )
SCR_RSpeeds(); SCR_RSpeeds();
SCR_NetSpeeds(); SCR_NetSpeeds();
SCR_DrawPos(); SCR_DrawPos();
SCR_DrawEnts();
SCR_DrawNetGraph(); SCR_DrawNetGraph();
SV_DrawOrthoTriangles(); SV_DrawOrthoTriangles();
CL_DrawDemoRecording(); CL_DrawDemoRecording();

View File

@@ -229,7 +229,7 @@ typedef struct
char serverinfo[MAX_SERVERINFO_STRING]; char serverinfo[MAX_SERVERINFO_STRING];
player_info_t players[MAX_CLIENTS]; // collected info about all other players include himself player_info_t players[MAX_CLIENTS]; // collected info about all other players include himself
double lastresourcecheck; double lastresourcecheck;
string downloadUrl; qboolean http_download;
event_state_t events; event_state_t events;
// predicting stuff but not only... // predicting stuff but not only...
@@ -276,6 +276,8 @@ typedef struct
model_t *worldmodel; // pointer to world model_t *worldmodel; // pointer to world
int lostpackets; // count lost packets and show dialog in menu int lostpackets; // count lost packets and show dialog in menu
double frametime_remainder;
} client_t; } client_t;
/* /*
@@ -307,6 +309,14 @@ typedef enum
CL_CHANGELEVEL, // draw 'loading' during changelevel CL_CHANGELEVEL, // draw 'loading' during changelevel
} scrstate_t; } 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 typedef struct
{ {
char name[32]; char name[32];
@@ -491,7 +501,6 @@ typedef struct
net_request_t net_requests[MAX_REQUESTS]; // no reason to keep more net_request_t net_requests[MAX_REQUESTS]; // no reason to keep more
efrag_t *free_efrags; // linked efrags
cl_entity_t viewent; // viewmodel cl_entity_t viewent; // viewmodel
qboolean client_dll_uses_sdl; qboolean client_dll_uses_sdl;
@@ -508,8 +517,9 @@ typedef struct
player_info_t playerinfo; // local playerinfo player_info_t playerinfo; // local playerinfo
gameui_draw_t ds; // draw2d stuff (menu images) gameui_draw_t ds; // draw2d stuff (menu images)
GAMEINFO gameInfo; // current gameInfo gameinfo2_t gameInfo; // current gameInfo
GAMEINFO *modsInfo[MAX_MODS]; // simplified gameInfo for MainUI gameinfo2_t *modsInfo; // simplified gameInfo for MainUI, allocated by demand
GAMEINFO **oldModsInfo; // simplified gameInfo for older MainUI, allocated by demand
ui_globalvars_t *globals; ui_globalvars_t *globals;
@@ -518,7 +528,7 @@ typedef struct
int logo_yres; int logo_yres;
float logo_length; float logo_length;
qboolean use_text_api; qboolean use_extended_api;
} gameui_static_t; } gameui_static_t;
typedef struct typedef struct
@@ -539,12 +549,8 @@ typedef struct
poolhandle_t mempool; // client premamnent pool: edicts etc poolhandle_t mempool; // client premamnent pool: edicts etc
netadr_t hltv_listen_address;
int signon; // 0 to SIGNONS, for the signon sequence. int signon; // 0 to SIGNONS, for the signon sequence.
int quakePort; // a 16 bit value that allows quake servers
// to work around address translating routers
// g-cont. this port allow many copies of engine in multiplayer game
// connection information // connection information
char servername[MAX_QPATH]; // name of server from original connect char servername[MAX_QPATH]; // name of server from original connect
double connect_time; // for connection retransmits double connect_time; // for connection retransmits
@@ -628,12 +634,14 @@ typedef struct
char internetservers_query[512]; // cached query char internetservers_query[512]; // cached query
uint32_t internetservers_query_len; uint32_t internetservers_query_len;
// legacy mode support // multiprotocol support
qboolean legacymode; // one-way 48 protocol compatibility connprotocol_t legacymode;
netadr_t legacyserver;
int extensions; int extensions;
netadr_t serveradr; netadr_t serveradr;
// do we accept utf8 as input
qboolean accept_utf8;
} client_static_t; } client_static_t;
#ifdef __cplusplus #ifdef __cplusplus
@@ -653,14 +661,11 @@ extern gameui_static_t gameui;
// cvars // cvars
// //
extern convar_t mp_decals; extern convar_t mp_decals;
extern convar_t cl_logofile; extern convar_t cl_logomaxdim;
extern convar_t cl_logocolor;
extern convar_t cl_allow_download; extern convar_t cl_allow_download;
extern convar_t cl_allow_upload;
extern convar_t cl_download_ingame; extern convar_t cl_download_ingame;
extern convar_t cl_nopred; extern convar_t cl_nopred;
extern convar_t cl_timeout; extern convar_t cl_timeout;
extern convar_t cl_nodelta;
extern convar_t cl_interp; extern convar_t cl_interp;
extern convar_t cl_nointerp; extern convar_t cl_nointerp;
extern convar_t cl_showerror; extern convar_t cl_showerror;
@@ -673,13 +678,11 @@ extern convar_t cl_updaterate;
extern convar_t cl_solid_players; extern convar_t cl_solid_players;
extern convar_t cl_idealpitchscale; extern convar_t cl_idealpitchscale;
extern convar_t cl_allow_levelshots; extern convar_t cl_allow_levelshots;
extern convar_t cl_lightstyle_lerping;
extern convar_t cl_draw_particles; extern convar_t cl_draw_particles;
extern convar_t cl_draw_tracers; extern convar_t cl_draw_tracers;
extern convar_t cl_levelshot_name; extern convar_t cl_levelshot_name;
extern convar_t cl_draw_beams; extern convar_t cl_draw_beams;
extern convar_t cl_clockreset; extern convar_t cl_clockreset;
extern convar_t cl_fixtimerate;
extern convar_t hud_fontscale; extern convar_t hud_fontscale;
extern convar_t hud_fontrender; extern convar_t hud_fontrender;
extern convar_t hud_scale; extern convar_t hud_scale;
@@ -781,6 +784,7 @@ void CL_Demos_f( void );
void CL_DeleteDemo_f( void ); void CL_DeleteDemo_f( void );
void CL_Record_f( void ); void CL_Record_f( void );
void CL_Stop_f( void ); void CL_Stop_f( void );
void CL_ListDemo_f( void );
int CL_GetDemoComment( const char *demoname, char *comment ); int CL_GetDemoComment( const char *demoname, char *comment );
// //
@@ -849,14 +853,14 @@ _inline cl_entity_t *CL_EDICT_NUM( int n )
{ {
if( !clgame.entities ) if( !clgame.entities )
{ {
Host_Error( "CL_EDICT_NUM: clgame.entities is NULL\n"); Host_Error( "%s: clgame.entities is NULL\n", __func__ );
return NULL; return NULL;
} }
if(( n >= 0 ) && ( n < clgame.maxEntities )) if(( n >= 0 ) && ( n < clgame.maxEntities ))
return clgame.entities + n; return clgame.entities + n;
Host_Error( "CL_EDICT_NUM: bad number %i\n", n ); Host_Error( "%s: bad number %i\n", __func__, n );
return NULL; return NULL;
} }
@@ -887,8 +891,8 @@ void CL_ParseFileTransferFailed( sizebuf_t *msg );
void CL_ParseHLTV( sizebuf_t *msg ); void CL_ParseHLTV( sizebuf_t *msg );
void CL_ParseDirector( sizebuf_t *msg ); void CL_ParseDirector( sizebuf_t *msg );
void CL_ParseResLocation( sizebuf_t *msg ); void CL_ParseResLocation( sizebuf_t *msg );
void CL_ParseCvarValue( sizebuf_t *msg, const qboolean ext ); void CL_ParseCvarValue( sizebuf_t *msg, const qboolean ext, const connprotocol_t proto );
void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message ); void CL_ParseServerMessage( sizebuf_t *msg );
void CL_ParseTempEntity( sizebuf_t *msg ); void CL_ParseTempEntity( sizebuf_t *msg );
qboolean CL_DispatchUserMessage( const char *pszName, int iSize, void *pbuf ); qboolean CL_DispatchUserMessage( const char *pszName, int iSize, void *pbuf );
qboolean CL_RequestMissingResources( void ); qboolean CL_RequestMissingResources( void );
@@ -904,7 +908,7 @@ int CL_EstimateNeededResources( void );
// //
// cl_parse_48.c // cl_parse_48.c
// //
void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message ); void CL_ParseLegacyServerMessage( sizebuf_t *msg );
void CL_LegacyPrecache_f( void ); void CL_LegacyPrecache_f( void );
// //
@@ -922,6 +926,7 @@ void SCR_NetSpeeds( void );
void SCR_RSpeeds( void ); void SCR_RSpeeds( void );
void SCR_DrawFPS( int height ); void SCR_DrawFPS( int height );
void SCR_DrawPos( void ); void SCR_DrawPos( void );
void SCR_DrawEnts( void );
// //
// cl_netgraph.c // cl_netgraph.c
@@ -963,7 +968,7 @@ void CL_SetIdealPitch( void );
// //
// cl_qparse.c // cl_qparse.c
// //
void CL_ParseQuakeMessage( sizebuf_t *msg, qboolean normal_message ); void CL_ParseQuakeMessage( sizebuf_t *msg );
// //
// cl_frame.c // cl_frame.c
@@ -1056,7 +1061,6 @@ int Con_UtfMoveRight( char *str, int pos, int length );
void Con_DefaultColor( int r, int g, int b, qboolean gameui ); void Con_DefaultColor( int r, int g, int b, qboolean gameui );
cl_font_t *Con_GetCurFont( void ); cl_font_t *Con_GetCurFont( void );
cl_font_t *Con_GetFont( int num ); cl_font_t *Con_GetFont( int num );
void Con_DrawCharacterLen( int number, int *width, int *height );
int Con_DrawString( int x, int y, const char *string, rgba_t setColor ); // legacy, use cl_font.c int Con_DrawString( int x, int y, const char *string, rgba_t setColor ); // legacy, use cl_font.c
void GAME_EXPORT Con_DrawStringLen( const char *pText, int *length, int *height ); // legacy, use cl_font.c void GAME_EXPORT Con_DrawStringLen( const char *pText, int *length, int *height ); // legacy, use cl_font.c
void Con_CharEvent( int key ); void Con_CharEvent( int key );
@@ -1107,7 +1111,7 @@ qboolean UI_MouseInRect( void );
qboolean UI_IsVisible( void ); qboolean UI_IsVisible( void );
void UI_ResetPing( void ); void UI_ResetPing( void );
void UI_ShowUpdateDialog( qboolean preferStore ); void UI_ShowUpdateDialog( qboolean preferStore );
void UI_ShowMessageBox( const char *text ); qboolean UI_ShowMessageBox( const char *text );
void UI_AddTouchButtonToList( const char *name, const char *texture, const char *command, unsigned char *color, int flags ); void UI_AddTouchButtonToList( const char *name, const char *texture, const char *command, unsigned char *color, int flags );
void UI_ConnectionProgress_Disconnect( void ); void UI_ConnectionProgress_Disconnect( void );
void UI_ConnectionProgress_Download( const char *pszFileName, const char *pszServerName, const char *pszServerPath, int iCurrent, int iTotal, const char *comment ); void UI_ConnectionProgress_Download( const char *pszFileName, const char *pszServerName, const char *pszServerPath, int iCurrent, int iTotal, const char *comment );
@@ -1161,5 +1165,7 @@ int Key_ToUpper( int key );
void OSK_Draw( void ); void OSK_Draw( void );
extern rgba_t g_color_table[8]; extern rgba_t g_color_table[8];
extern triangleapi_t gTriApi;
extern net_api_t gNetApi;
#endif//CLIENT_H #endif//CLIENT_H

View File

@@ -21,6 +21,7 @@ GNU General Public License for more details.
#include "qfont.h" #include "qfont.h"
#include "wadfile.h" #include "wadfile.h"
#include "input.h" #include "input.h"
#include "utflib.h"
static CVAR_DEFINE_AUTO( scr_conspeed, "600", FCVAR_ARCHIVE, "console moving speed" ); static CVAR_DEFINE_AUTO( scr_conspeed, "600", FCVAR_ARCHIVE, "console moving speed" );
static CVAR_DEFINE_AUTO( con_notifytime, "3", FCVAR_ARCHIVE, "notify time to live" ); static CVAR_DEFINE_AUTO( con_notifytime, "3", FCVAR_ARCHIVE, "notify time to live" );
@@ -34,7 +35,6 @@ static CVAR_DEFINE_AUTO( scr_drawversion, "1", FCVAR_ARCHIVE, "draw version in m
static CVAR_DEFINE_AUTO( con_oldfont, "0", 0, "use legacy font from gfx.wad, might be missing or broken" ); static CVAR_DEFINE_AUTO( con_oldfont, "0", 0, "use legacy font from gfx.wad, might be missing or broken" );
static int g_codepage = 0; static int g_codepage = 0;
static qboolean g_utf8 = false;
static qboolean g_messagemode_privileged = true; static qboolean g_messagemode_privileged = true;
@@ -610,19 +610,6 @@ static void Con_LoadConchars( void )
con.curFont = &con.chars[fontSize]; con.curFont = &con.chars[fontSize];
} }
// CP1251 table
int table_cp1251[64] = {
0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021,
0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F,
0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x007F, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F,
0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7,
0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407,
0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7,
0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457
};
/* /*
============================ ============================
Con_UtfProcessChar Con_UtfProcessChar
@@ -632,84 +619,28 @@ Convert utf char to current font's single-byte encoding
*/ */
int Con_UtfProcessCharForce( int in ) int Con_UtfProcessCharForce( int in )
{ {
static int m = -1, k = 0; //multibyte state // TODO: get rid of global state where possible
static int uc = 0; //unicode char static utfstate_t state = { 0 };
if( !in ) int ch = Q_DecodeUTF8( &state, in );
{
m = -1;
k = 0;
uc = 0;
return 0;
}
// Get character length if( g_codepage == 1251 )
if(m == -1) return Q_UnicodeToCP1251( ch );
{ if( g_codepage == 1252 )
uc = 0; return Q_UnicodeToCP1252( ch );
if( in >= 0xF8 )
return 0;
else if( in >= 0xF0 )
uc = in & 0x07, m = 3;
else if( in >= 0xE0 )
uc = in & 0x0F, m = 2;
else if( in >= 0xC0 )
uc = in & 0x1F, m = 1;
else if( in <= 0x7F)
return in; //ascii
// return 0 if we need more chars to decode one
k=0;
return 0;
}
// get more chars
else if( k <= m )
{
uc <<= 6;
uc += in & 0x3F;
k++;
}
if( in > 0xBF || m < 0 )
{
m = -1;
return 0;
}
if( k == m )
{
k = m = -1;
if( g_codepage == 1251 )
{
// cp1251 now
if( uc >= 0x0410 && uc <= 0x042F )
return uc - 0x410 + 0xC0;
if( uc >= 0x0430 && uc <= 0x044F )
return uc - 0x430 + 0xE0;
else
{
int i;
for( i = 0; i < 64; i++ )
if( table_cp1251[i] == uc )
return i + 0x80;
}
}
else if( g_codepage == 1252 )
{
if( uc < 255 )
return uc;
}
// not implemented yet return '?'; // not implemented yet
return '?';
}
return 0;
} }
int GAME_EXPORT Con_UtfProcessChar( int in ) int GAME_EXPORT Con_UtfProcessChar( int in )
{ {
if( !g_utf8 ) if( !cls.accept_utf8 ) // incoming character is not a UTF-8 sequence
return in; return in;
else
return Con_UtfProcessCharForce( in ); // otherwise, decode it and convert to selected codepage
return Con_UtfProcessCharForce( in );
} }
/* /*
================= =================
Con_UtfMoveLeft Con_UtfMoveLeft
@@ -719,16 +650,22 @@ get position of previous printful char
*/ */
int Con_UtfMoveLeft( char *str, int pos ) int Con_UtfMoveLeft( char *str, int pos )
{ {
int i, k = 0; utfstate_t state = { 0 };
// int j; int k = 0;
if( !g_utf8 ) int i;
if( !cls.accept_utf8 ) // incoming character is not a UTF-8 sequence
return pos - 1; return pos - 1;
Con_UtfProcessChar( 0 );
if(pos == 1) return 0; if( pos == 1 )
for( i = 0; i < pos-1; i++ ) return 0;
if( Con_UtfProcessChar( (unsigned char)str[i] ) )
k = i+1; for( i = 0; i < pos - 1; i++ )
Con_UtfProcessChar( 0 ); {
if( Q_DecodeUTF8( &state, (byte)str[i] ))
k = i + 1;
}
return k; return k;
} }
@@ -741,17 +678,19 @@ get next of previous printful char
*/ */
int Con_UtfMoveRight( char *str, int pos, int length ) int Con_UtfMoveRight( char *str, int pos, int length )
{ {
utfstate_t state = { 0 };
int i; int i;
if( !g_utf8 )
if( !cls.accept_utf8 ) // incoming character is not a UTF-8 sequence
return pos + 1; return pos + 1;
Con_UtfProcessChar( 0 );
for( i = pos; i <= length; i++ ) for( i = pos; i <= length; i++ )
{ {
if( Con_UtfProcessChar( (unsigned char)str[i] ) ) if( Q_DecodeUTF8( &state, (byte)str[i] ))
return i+1; return i + 1;
} }
Con_UtfProcessChar( 0 );
return pos+1; return pos + 1;
} }
static void Con_DrawCharToConback( int num, const byte *conchars, byte *dest ) static void Con_DrawCharToConback( int num, const byte *conchars, byte *dest )
@@ -908,7 +847,6 @@ void Con_Print( const char *txt )
static char buf[MAX_PRINT_MSG]; static char buf[MAX_PRINT_MSG];
qboolean norefresh = false; qboolean norefresh = false;
static int lastlength = 0; static int lastlength = 0;
static qboolean inupdate;
static int bufpos = 0; static int bufpos = 0;
int c, mask = 0; int c, mask = 0;
@@ -999,6 +937,27 @@ void Con_Print( const char *txt )
} }
} }
/*
================
Con_NXPrintfv
Draw a single debug line with specified height, color and time to live
================
*/
static void Con_NXPrintfv( keydest_t key_dest, const con_nprint_t *info, const char *fmt, va_list va )
{
if( info->index < 0 || info->index >= ARRAYSIZE( con.notify ))
return;
Q_vsnprintf( con.notify[info->index].szNotify, sizeof( con.notify[info->index].szNotify ), fmt, va );
// setup values
con.notify[info->index].key_dest = key_dest;
con.notify[info->index].expire = host.realtime + info->time_to_live;
MakeRGBA( con.notify[info->index].color, (byte)(info->color[0] * 255), (byte)(info->color[1] * 255), (byte)(info->color[2] * 255), 255 );
con.draw_notify = true;
}
/* /*
================ ================
Con_NPrint Con_NPrint
@@ -1009,21 +968,16 @@ Draw a single debug line with specified height
void GAME_EXPORT Con_NPrintf( int idx, const char *fmt, ... ) void GAME_EXPORT Con_NPrintf( int idx, const char *fmt, ... )
{ {
va_list args; va_list args;
con_nprint_t info =
if( idx < 0 || idx >= MAX_DBG_NOTIFY ) {
return; .index = idx,
.time_to_live = 4.0f,
memset( con.notify[idx].szNotify, 0, MAX_STRING ); .color = { 1.0f, 1.0f, 1.0f },
};
va_start( args, fmt ); va_start( args, fmt );
Q_vsnprintf( con.notify[idx].szNotify, MAX_STRING, fmt, args ); Con_NXPrintfv( key_game, &info, fmt, args );
va_end( args ); va_end( args );
// reset values
con.notify[idx].key_dest = key_game;
con.notify[idx].expire = host.realtime + 4.0f;
MakeRGBA( con.notify[idx].color, 255, 255, 255, 255 );
con.draw_notify = true;
} }
/* /*
@@ -1039,20 +993,9 @@ void GAME_EXPORT Con_NXPrintf( con_nprint_t *info, const char *fmt, ... )
if( !info ) return; if( !info ) return;
if( info->index < 0 || info->index >= MAX_DBG_NOTIFY )
return;
memset( con.notify[info->index].szNotify, 0, MAX_STRING );
va_start( args, fmt ); va_start( args, fmt );
Q_vsnprintf( con.notify[info->index].szNotify, MAX_STRING, fmt, args ); Con_NXPrintfv( key_game, info, fmt, args );
va_end( args ); va_end( args );
// setup values
con.notify[info->index].key_dest = key_game;
con.notify[info->index].expire = host.realtime + info->time_to_live;
MakeRGBA( con.notify[info->index].color, (byte)(info->color[0] * 255), (byte)(info->color[1] * 255), (byte)(info->color[2] * 255), 255 );
con.draw_notify = true;
} }
/* /*
@@ -1065,21 +1008,16 @@ Draw a single debug line with specified height (menu version)
void GAME_EXPORT UI_NPrintf( int idx, const char *fmt, ... ) void GAME_EXPORT UI_NPrintf( int idx, const char *fmt, ... )
{ {
va_list args; va_list args;
con_nprint_t info =
if( idx < 0 || idx >= MAX_DBG_NOTIFY ) {
return; .index = idx,
.time_to_live = 4.0f,
memset( con.notify[idx].szNotify, 0, MAX_STRING ); .color = { 1.0f, 1.0f, 1.0f },
};
va_start( args, fmt ); va_start( args, fmt );
Q_vsnprintf( con.notify[idx].szNotify, MAX_STRING, fmt, args ); Con_NXPrintfv( key_menu, &info, fmt, args );
va_end( args ); va_end( args );
// reset values
con.notify[idx].key_dest = key_menu;
con.notify[idx].expire = host.realtime + 4.0f;
MakeRGBA( con.notify[idx].color, 255, 255, 255, 255 );
con.draw_notify = true;
} }
/* /*
@@ -1095,20 +1033,9 @@ void GAME_EXPORT UI_NXPrintf( con_nprint_t *info, const char *fmt, ... )
if( !info ) return; if( !info ) return;
if( info->index < 0 || info->index >= MAX_DBG_NOTIFY )
return;
memset( con.notify[info->index].szNotify, 0, MAX_STRING );
va_start( args, fmt ); va_start( args, fmt );
Q_vsnprintf( con.notify[info->index].szNotify, MAX_STRING, fmt, args ); Con_NXPrintfv( key_menu, info, fmt, args );
va_end( args ); va_end( args );
// setup values
con.notify[info->index].key_dest = key_menu;
con.notify[info->index].expire = host.realtime + info->time_to_live;
MakeRGBA( con.notify[info->index].color, (byte)(info->color[0] * 255), (byte)(info->color[1] * 255), (byte)(info->color[2] * 255), 255 );
con.draw_notify = true;
} }
/* /*
@@ -1138,7 +1065,7 @@ Field_Set
static void Field_Set( field_t *f, const char *string ) static void Field_Set( field_t *f, const char *string )
{ {
f->scroll = 0; f->scroll = 0;
f->cursor = Q_strncpy( f->buffer, string, MAX_STRING ); f->cursor = Q_strncpy( f->buffer, string, sizeof( f->buffer ));
} }
/* /*
@@ -1507,7 +1434,15 @@ static void Con_SaveHistory( con_history_t *self )
f = FS_Open( "console_history.txt", "wb", true ); f = FS_Open( "console_history.txt", "wb", true );
for( i = historyStart; i < self->next; i++ ) for( i = historyStart; i < self->next; i++ )
FS_Printf( f, "%s\n", self->lines[i % CON_HISTORY].buffer ); {
const char *s = self->lines[i % CON_HISTORY].buffer;
// HACKHACK: don't save lines that have something that looks like a password
if( Q_stristr( s, "password" ) || Q_stristr( s, "_pw" ))
continue;
FS_Printf( f, "%s\n", s );
}
FS_Close( f ); FS_Close( f );
} }
@@ -1549,6 +1484,9 @@ void Key_Console( int key )
Con_Printf( ">%s\n", con.input.buffer ); Con_Printf( ">%s\n", con.input.buffer );
// copy line to history buffer // copy line to history buffer
// just in case, remove all CR and LF characters pushing it to the history
// not sure how they get even added in the first place
COM_RemoveLineFeed( con.input.buffer, sizeof( con.input.buffer ));
Con_HistoryAppend( &con.history, &con.input ); Con_HistoryAppend( &con.history, &con.input );
Con_ClearField( &con.input ); Con_ClearField( &con.input );
@@ -1815,7 +1753,7 @@ static void Con_DrawNotify( void )
if( host.allow_console && ( !Cvar_VariableInteger( "cl_background" ) && !Cvar_VariableInteger( "sv_background" ))) 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 ); con_lineinfo_t *l = &CON_LINES( i );
@@ -2157,7 +2095,7 @@ void Con_RunConsole( void )
g_codepage = 1252; g_codepage = 1252;
} }
g_utf8 = !Q_stricmp( cl_charset.string, "utf-8" ); cls.accept_utf8 = !Q_stricmp( cl_charset.string, "utf-8" );
Con_InvalidateFonts(); Con_InvalidateFonts();
Con_LoadConchars(); Con_LoadConchars();
ClearBits( con_charset.flags, FCVAR_CHANGED ); ClearBits( con_charset.flags, FCVAR_CHANGED );
@@ -2195,6 +2133,34 @@ void Con_CharEvent( int key )
} }
} }
static int Con_LoadSimpleConback( const char *name, int flags )
{
const char *paths[] = {
"gfx/shell/%s.dds",
"gfx/shell/%s.bmp",
"gfx/shell/%s.tga",
"cached/%s640",
"cached/%s",
};
size_t i;
for( i = 0; i < ARRAYSIZE( paths ); i++ )
{
string path;
Q_snprintf( path, sizeof( path ), paths[i], name );
if( g_fsapi.FileExists( path, false ))
{
int gl_texturenum = ref.dllFuncs.GL_LoadTexture( path, NULL, 0, flags );
if( gl_texturenum )
return gl_texturenum;
}
}
return 0;
}
/* /*
========= =========
Con_VidInit Con_VidInit
@@ -2217,38 +2183,12 @@ void Con_VidInit( void )
Con_LoadConchars(); Con_LoadConchars();
Con_CheckResize(); Con_CheckResize();
#if XASH_LOW_MEMORY #if XASH_LOW_MEMORY
con.background = R_GetBuiltinTexture( REF_BLACK_TEXTURE ); con.background = R_GetBuiltinTexture( REF_GRAY_TEXTURE );
#else #else
// loading console image // loading console image
if( host.allow_console ) con.background = Con_LoadSimpleConback( host.allow_console ? "conback" : "loading", flags );
{
// trying to load truecolor image first
if( FS_FileExists( "gfx/shell/conback.bmp", false ) || FS_FileExists( "gfx/shell/conback.tga", false ))
con.background = ref.dllFuncs.GL_LoadTexture( "gfx/shell/conback", NULL, 0, flags );
if( !con.background )
{
if( FS_FileExists( "cached/conback640", false ))
con.background = ref.dllFuncs.GL_LoadTexture( "cached/conback640", NULL, 0, flags );
else if( FS_FileExists( "cached/conback", false ))
con.background = ref.dllFuncs.GL_LoadTexture( "cached/conback", NULL, 0, flags );
}
}
else
{
// trying to load truecolor image first
if( FS_FileExists( "gfx/shell/loading.bmp", false ) || FS_FileExists( "gfx/shell/loading.tga", false ))
con.background = ref.dllFuncs.GL_LoadTexture( "gfx/shell/loading", NULL, 0, flags );
if( !con.background )
{
if( FS_FileExists( "cached/loading640", false ))
con.background = ref.dllFuncs.GL_LoadTexture( "cached/loading640", NULL, 0, flags );
else if( FS_FileExists( "cached/loading", false ))
con.background = ref.dllFuncs.GL_LoadTexture( "cached/loading", NULL, 0, flags );
}
}
if( !con.background ) // last chance - quake conback image if( !con.background ) // last chance - quake conback image
{ {

View File

@@ -134,7 +134,7 @@ static void Joy_ProcessTrigger( const engineAxis_t engineAxis, short value )
trigThreshold = joy_lt_threshold.value; trigThreshold = joy_lt_threshold.value;
break; break;
default: default:
Con_Reportf( S_ERROR "Joy_ProcessTrigger: invalid axis = %i", engineAxis ); Con_Reportf( S_ERROR "%s: invalid axis = %i\n", __func__, engineAxis );
break; break;
} }
@@ -205,7 +205,7 @@ static void Joy_ProcessStick( const engineAxis_t engineAxis, short value )
case JOY_AXIS_PITCH: deadzone = joy_pitch_deadzone.value; break; case JOY_AXIS_PITCH: deadzone = joy_pitch_deadzone.value; break;
case JOY_AXIS_YAW: deadzone = joy_yaw_deadzone.value; break; case JOY_AXIS_YAW: deadzone = joy_yaw_deadzone.value; break;
default: default:
Con_Reportf( S_ERROR "Joy_ProcessStick: invalid axis = %i", engineAxis ); Con_Reportf( S_ERROR "%s: invalid axis = %i\n", __func__, engineAxis );
break; break;
} }
@@ -218,7 +218,7 @@ static void Joy_ProcessStick( const engineAxis_t engineAxis, short value )
// fwd/side axis simulate hat movement // fwd/side axis simulate hat movement
if( ( engineAxis == JOY_AXIS_SIDE || engineAxis == JOY_AXIS_FWD ) && if( ( engineAxis == JOY_AXIS_SIDE || engineAxis == JOY_AXIS_FWD ) &&
( CL_IsInMenu() || CL_IsInConsole() ) ) ( cls.key_dest == key_menu || cls.key_dest == key_console ))
{ {
int val = 0; int val = 0;

View File

@@ -142,7 +142,7 @@ static struct touch_s
touchdefaultbutton_t g_DefaultButtons[256]; touchdefaultbutton_t g_DefaultButtons[256];
int g_LastDefaultButton; 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_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_sidezone, "0.06", FCVAR_FILTERABLE, "side touch zone" );
static CVAR_DEFINE_AUTO( touch_pitch, "90", FCVAR_FILTERABLE, "touch pitch sensitivity" ); 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_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_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_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_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 // code looks smaller with it
#define B(x) (button->x) #define B(x) (button->x)
@@ -333,7 +333,7 @@ void Touch_WriteConfig( void )
if( Sys_CheckParm( "-nowriteconfig" ) || !touch.configchanged || !touch.config_loaded ) if( Sys_CheckParm( "-nowriteconfig" ) || !touch.configchanged || !touch.config_loaded )
return; return;
Con_DPrintf( "Touch_WriteConfig(): %s\n", touch_config_file.string ); Con_DPrintf( "%s: %s\n", __func__, touch_config_file.string );
Q_snprintf( newconfigfile, sizeof( newconfigfile ), "%s.new", touch_config_file.string ); Q_snprintf( newconfigfile, sizeof( newconfigfile ), "%s.new", touch_config_file.string );
Q_snprintf( oldconfigfile, sizeof( oldconfigfile ), "%s.bak", touch_config_file.string ); Q_snprintf( oldconfigfile, sizeof( oldconfigfile ), "%s.bak", touch_config_file.string );
@@ -767,14 +767,18 @@ static void Touch_ReloadConfig_f( void )
touch.state = state_none; touch.state = state_none;
if( touch.edit ) if( touch.edit )
touch.edit->finger = -1; touch.edit->finger = -1;
if( touch.selection ) if( touch.selection )
touch.selection->finger = -1; touch.selection->finger = -1;
touch.edit = touch.selection = NULL; touch.edit = touch.selection = NULL;
touch.resize_finger = touch.move_finger = touch.look_finger = touch.wheel_finger = -1; 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 ); Cbuf_AddTextf( "exec \"%s\"\n", touch_config_file.string );
}
else else
{ {
Touch_LoadDefaults_f(); Touch_LoadDefaults_f();
@@ -1010,7 +1014,7 @@ static void Touch_DisableEdit_f( void )
{ {
Cvar_Set( "touch_in_menu", "0" ); Cvar_Set( "touch_in_menu", "0" );
} }
else if( cls.key_dest == key_game ) else if( cls.key_dest == key_game )
Touch_WriteConfig(); Touch_WriteConfig();
} }
@@ -1064,7 +1068,7 @@ void Touch_Init( void )
return; return;
touch.mempool = Mem_AllocPool( "Touch" ); touch.mempool = Mem_AllocPool( "Touch" );
//touch.first = touch.last = NULL; //touch.first = touch.last = NULL;
Con_Printf( "IN_TouchInit()\n"); Con_Printf( "%s()\n", __func__ );
touch.move_finger = touch.resize_finger = touch.look_finger = touch.wheel_finger = -1; touch.move_finger = touch.resize_finger = touch.look_finger = touch.wheel_finger = -1;
touch.state = state_none; touch.state = state_none;
touch.showeditbuttons = true; touch.showeditbuttons = true;
@@ -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( "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( "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( "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( "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.760000, 0.000000, 0.840000, 0.151486, 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.760000, 0.000000, 0.840000, 0.151486, color, 2, 1, 8 ); 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( "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( "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( "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( "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( "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( "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( "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_addbutton", Touch_AddButton_f, "add native touch button" );
Cmd_AddCommand( "touch_removebutton", IN_TouchRemoveButton_f, "remove native touch button" ); Cmd_AddCommand( "touch_removebutton", IN_TouchRemoveButton_f, "remove native touch button" );
@@ -1217,10 +1222,10 @@ static qboolean Touch_IsVisible( touch_button_t *button )
if( FBitSet( button->flags, TOUCH_FL_HIDE )) if( FBitSet( button->flags, TOUCH_FL_HIDE ))
return false; // skip hidden return false; // skip hidden
if( FBitSet( button->flags, TOUCH_FL_SP ) && CL_GetMaxClients() != 1 ) if( FBitSet( button->flags, TOUCH_FL_SP ) && cl.maxclients != 1 )
return false; // skip singleplayer(load, save) buttons in multiplayer return false; // skip singleplayer(load, save) buttons in multiplayer
if( FBitSet( button->flags, TOUCH_FL_MP ) && CL_GetMaxClients() == 1 ) if( FBitSet( button->flags, TOUCH_FL_MP ) && cl.maxclients == 1 )
return false; // skip multiplayer buttons in singleplayer return false; // skip multiplayer buttons in singleplayer
return true; return true;
@@ -2122,7 +2127,7 @@ void Touch_KeyEvent( int key, int down )
float x, y; float x, y;
int finger, xi, yi; int finger, xi, yi;
if( !touch_emulate.value ) if( !Touch_Emulated( ))
{ {
if( touch_enable.value ) if( touch_enable.value )
return; return;
@@ -2163,8 +2168,7 @@ void Touch_KeyEvent( int key, int down )
x = xi / SCR_W; x = xi / SCR_W;
y = yi / SCR_H; y = yi / SCR_H;
Con_DPrintf( "event %d %.2f %.2f %.2f %.2f\n", // Con_DPrintf( "event %d %.2f %.2f %.2f %.2f\n", event, x, y, x - lx, y - ly );
event, x, y, x - lx, y - ly );
IN_TouchEvent( event, finger, x, y, x - lx, y - ly ); IN_TouchEvent( event, finger, x, y, x - lx, y - ly );
@@ -2177,6 +2181,11 @@ qboolean Touch_WantVisibleCursor( void )
return ( touch_enable.value && touch_emulate.value ) || touch.clientonly; 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 ) void Touch_Shutdown( void )
{ {
if( !touch.initialized ) if( !touch.initialized )

View File

@@ -17,6 +17,7 @@ GNU General Public License for more details.
#include "input.h" #include "input.h"
#include "client.h" #include "client.h"
#include "vgui_draw.h" #include "vgui_draw.h"
#include "cursor_type.h"
#if XASH_SDL #if XASH_SDL
#include <SDL.h> #include <SDL.h>
@@ -46,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_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( 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 IN_CollectInputDevices
@@ -115,6 +118,7 @@ static void IN_StartupMouse( void )
Cvar_RegisterVariable( &m_yaw ); Cvar_RegisterVariable( &m_yaw );
Cvar_RegisterVariable( &look_filter ); Cvar_RegisterVariable( &look_filter );
Cvar_RegisterVariable( &m_rawinput ); Cvar_RegisterVariable( &m_rawinput );
Cvar_RegisterVariable( &m_grab_debug );
// You can use -nomouse argument to prevent using mouse from client // You can use -nomouse argument to prevent using mouse from client
// -noenginemouse will disable all mouse input // -noenginemouse will disable all mouse input
@@ -123,11 +127,6 @@ static void IN_StartupMouse( void )
in_mouseinitialized = true; in_mouseinitialized = true;
} }
void GAME_EXPORT IN_SetCursor( void *hCursor )
{
// stub
}
/* /*
=========== ===========
IN_MouseSavePos IN_MouseSavePos
@@ -206,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 void IN_CheckMouseState( qboolean active )
{ {
static qboolean s_bRawInput, s_bMouseGrab; qboolean use_raw_input, verbose;
#if XASH_WIN32 #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 #else
qboolean useRawInput = true; // always use SDL code use_raw_input = true; // always use SDL code
#endif #endif
verbose = m_grab_debug.value ? true : false;
if( m_ignore.value ) if( m_ignore.value )
return; active = false;
if( active && useRawInput && !host.mouse_visible && cls.state == ca_active ) if( active && use_raw_input && !host.mouse_visible && cls.state == ca_active )
{ IN_SetRelativeMouseMode( true, verbose );
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;
}
}
else else
{ IN_SetRelativeMouseMode( false, verbose );
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;
}
}
if( active && !host.mouse_visible && cls.state == ca_active ) if( active && !host.mouse_visible && cls.state == ca_active )
{ IN_SetMouseGrab( true, verbose );
if( !s_bMouseGrab )
{
#if XASH_SDL
SDL_SetWindowGrab( host.hWnd, SDL_TRUE );
#endif
// Con_Printf( "Enable grab\n" );
s_bMouseGrab = true;
}
}
else else
{ IN_SetMouseGrab( false, verbose );
if( s_bMouseGrab )
{
#if XASH_SDL
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
#endif
// Con_Printf( "Disable grab\n" );
s_bMouseGrab = false;
}
}
} }
/* /*
@@ -320,7 +332,7 @@ static void IN_MouseMove( void )
if( !in_mouseinitialized ) if( !in_mouseinitialized )
return; return;
if( touch_emulate.value ) if( Touch_Emulated( ))
{ {
// touch emulation overrides all input // touch emulation overrides all input
Touch_KeyEvent( 0, 0 ); Touch_KeyEvent( 0, 0 );
@@ -351,7 +363,7 @@ void IN_MouseEvent( int key, int down )
else ClearBits( in_mstate, BIT( key )); else ClearBits( in_mstate, BIT( key ));
// touch emulation overrides all input // touch emulation overrides all input
if( touch_emulate.value ) if( Touch_Emulated( ))
{ {
Touch_KeyEvent( K_MOUSE1 + key, down ); Touch_KeyEvent( K_MOUSE1 + key, down );
} }

View File

@@ -40,7 +40,6 @@ void IN_DeactivateMouse( void );
void IN_MouseSavePos( void ); void IN_MouseSavePos( void );
void IN_MouseRestorePos( void ); void IN_MouseRestorePos( void );
void IN_ToggleClientMouse( int newstate, int oldstate ); void IN_ToggleClientMouse( int newstate, int oldstate );
void IN_SetCursor( void *hCursor );
uint IN_CollectInputDevices( void ); uint IN_CollectInputDevices( void );
void IN_LockInputDevices( qboolean lock ); void IN_LockInputDevices( qboolean lock );
@@ -59,7 +58,6 @@ typedef enum
} touchEventType; } touchEventType;
extern convar_t touch_enable; extern convar_t touch_enable;
extern convar_t touch_emulate;
void Touch_Draw( void ); void Touch_Draw( void );
void Touch_SetClientOnly( byte state ); void Touch_SetClientOnly( byte state );
@@ -75,6 +73,7 @@ void Touch_ResetDefaultButtons( void );
int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy ); int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy );
void Touch_KeyEvent( int key, int down ); void Touch_KeyEvent( int key, int down );
qboolean Touch_WantVisibleCursor( void ); qboolean Touch_WantVisibleCursor( void );
qboolean Touch_Emulated( void );
void Touch_NotifyResize( void ); void Touch_NotifyResize( void );
// //

View File

@@ -553,7 +553,7 @@ static void Key_AddKeyCommands( int key, const char *kb, qboolean down )
} }
buttonPtr = button; buttonPtr = button;
while(( kb[i] <= ' ' || kb[i] == ';' ) && kb[i] != 0 ) while((((byte)kb[i]) <= ' ' || kb[i] == ';' ) && kb[i] != 0 )
i++; i++;
} }
@@ -749,10 +749,10 @@ void GAME_EXPORT Key_Event( int key, int down )
if( cls.key_dest == key_menu ) if( cls.key_dest == key_menu )
{ {
// only non printable keys passed // only non printable keys passed
if( !gameui.use_text_api ) if( !gameui.use_extended_api )
Key_EnableTextInput( true, false ); Key_EnableTextInput( true, false );
//pass printable chars for old menus //pass printable chars for old menus
if( !gameui.use_text_api && !host.textmode && down && ( key >= 32 ) && ( key <= 'z' ) ) if( !gameui.use_extended_api && !host.textmode && down && ( key >= 32 ) && ( key <= 'z' ) )
{ {
if( Key_IsDown( K_SHIFT ) ) if( Key_IsDown( K_SHIFT ) )
{ {
@@ -840,7 +840,7 @@ void GAME_EXPORT Key_SetKeyDest( int key_dest )
cls.key_dest = key_message; cls.key_dest = key_message;
break; break;
default: default:
Host_Error( "Key_SetKeyDest: wrong destination (%i)\n", key_dest ); Host_Error( "%s: wrong destination (%i)\n", __func__, key_dest );
break; break;
} }
} }
@@ -1055,18 +1055,16 @@ static qboolean OSK_KeyEvent( int key, int down )
break; break;
} }
if( !Q_stricmp( cl_charset.string, "utf-8" ) ) ch = (byte)osk.curbutton.val;
ch = (unsigned char)osk.curbutton.val;
else // do not pass UTF-8 sequence into the engine, convert it here
ch = Con_UtfProcessCharForce( (unsigned char)osk.curbutton.val ); if( !cls.accept_utf8 )
ch = Con_UtfProcessCharForce( ch );
if( !ch ) if( !ch )
break; break;
Con_CharEvent( ch ); CL_CharEvent( ch );
if( cls.key_dest == key_menu )
UI_CharEvent ( ch );
break; break;
} }
} }
@@ -1121,7 +1119,6 @@ static void OSK_EnableTextInput( qboolean enable, qboolean force )
{ {
osk.curlayout = 0; osk.curlayout = 0;
osk.curbutton.val = osk_keylayout[osk.curlayout][osk.curbutton.y][osk.curbutton.x]; osk.curbutton.val = osk_keylayout[osk.curlayout][osk.curbutton.y][osk.curbutton.x];
} }
} }

View File

@@ -74,7 +74,7 @@ static void free_winding( winding_t *w )
{ {
// simple sentinel by Carmack // simple sentinel by Carmack
if( *(unsigned *)w == 0xDEADC0DE ) if( *(unsigned *)w == 0xDEADC0DE )
Host_Error( "free_winding: freed a freed winding\n" ); Host_Error( "%s: freed a freed winding\n", __func__ );
*(unsigned *)w = 0xDEADC0DE; *(unsigned *)w = 0xDEADC0DE;
free( w ); free( w );
} }
@@ -154,7 +154,7 @@ static winding_t *winding_for_plane( const mplane_t *p )
vup[0] = 1; vup[0] = 1;
break; break;
default: default:
Host_Error( "BaseWindingForPlane: no axis found\n" ); Host_Error( "%s: no axis found\n", __func__ );
return NULL; return NULL;
} }
@@ -685,6 +685,9 @@ void Mod_CreatePolygonsForHull( int hullnum )
if( hullnum < 1 || hullnum > 3 ) if( hullnum < 1 || hullnum > 3 )
return; return;
if( !world.num_hull_models )
Mod_InitDebugHulls( mod ); // FIXME: build hulls for separate bmodels (shells, medkits etc)
Con_Printf( "generating polygons for hull %u...\n", hullnum ); Con_Printf( "generating polygons for hull %u...\n", hullnum );
start = Sys_DoubleTime(); start = Sys_DoubleTime();

View File

@@ -8,7 +8,9 @@
struct ref_state_s ref; struct ref_state_s ref;
ref_globals_t refState; ref_globals_t refState;
CVAR_DEFINE_AUTO( gl_vsync, "0", FCVAR_ARCHIVE, "enable vertical syncronization" ); static const char* r_skyBoxSuffix[SKYBOX_MAX_SIDES] = { "rt", "bk", "lf", "ft", "up", "dn" };
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_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_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" ); CVAR_DEFINE_AUTO( r_decals, "4096", FCVAR_ARCHIVE, "sets the maximum number of decals" );
@@ -49,13 +51,102 @@ void R_GetTextureParms( int *w, int *h, int texnum )
if( h ) *h = REF_GET_PARM( PARM_TEX_HEIGHT, texnum ); if( h ) *h = REF_GET_PARM( PARM_TEX_HEIGHT, texnum );
} }
/* static qboolean CheckSkybox( const char *name, char out[SKYBOX_MAX_SIDES][MAX_STRING] )
================ {
GL_FreeImage static const char *skybox_ext[3] = { "dds", "tga", "bmp" };
static const char *skybox_delim[2] = { "", "_" }; // no space for HL style, underscore for Q1 style
int i;
// search for skybox images
for( i = 0; i < ARRAYSIZE( skybox_ext ); i++ )
{
int j;
for( j = 0; j < ARRAYSIZE( skybox_delim ); j++ )
{
int k, num_checked_sides = 0;
for( k = 0; k < SKYBOX_MAX_SIDES; k++ )
{
char sidename[MAX_VA_STRING];
Q_snprintf( sidename, sizeof( sidename ), "%s%s%s.%s", name, skybox_delim[j], r_skyBoxSuffix[k], skybox_ext[i] );
if( g_fsapi.FileExists( sidename, false ))
{
Q_strncpy( out[k], sidename, sizeof( out[k] ));
num_checked_sides++;
}
}
if( num_checked_sides == SKYBOX_MAX_SIDES )
return true; // image exists
}
}
return false;
}
void R_SetupSky( const char *name )
{
string loadname;
char sidenames[SKYBOX_MAX_SIDES][MAX_STRING];
int skyboxTextures[SKYBOX_MAX_SIDES] = { 0 };
int i, len;
qboolean result;
if( !COM_CheckString( name ))
{
ref.dllFuncs.R_SetupSky( NULL ); // unload skybox
return;
}
Q_snprintf( loadname, sizeof( loadname ), "gfx/env/%s", name );
COM_StripExtension( loadname );
// kill the underline suffix to find them manually later
len = Q_strlen( loadname );
if( loadname[len - 1] == '_' )
loadname[len - 1] = '\0';
result = CheckSkybox( loadname, sidenames );
// to prevent infinite recursion if default skybox was missed
if( !result && Q_stricmp( name, DEFAULT_SKYBOX_NAME ))
{
Con_Reportf( S_WARN "missed or incomplete skybox '%s'\n", name );
R_SetupSky( DEFAULT_SKYBOX_NAME ); // force to default
return;
}
ref.dllFuncs.R_SetupSky( NULL ); // unload skybox
Con_DPrintf( "SKY: " );
for( i = 0; i < SKYBOX_MAX_SIDES; i++ )
{
skyboxTextures[i] = ref.dllFuncs.GL_LoadTexture( sidenames[i], NULL, 0, TF_CLAMP|TF_SKY );
if( !skyboxTextures[i] )
break;
Con_DPrintf( "%s%s%s", name, r_skyBoxSuffix[i], i != 5 ? ", " : ". " );
}
if( i == SKYBOX_MAX_SIDES )
{
SetBits( world.flags, FWORLD_CUSTOM_SKYBOX );
Con_DPrintf( "done\n" );
ref.dllFuncs.R_SetupSky( skyboxTextures );
return; // loaded
}
Con_DPrintf( "^2failed\n" );
for( i = 0; i < SKYBOX_MAX_SIDES; i++ )
{
if( skyboxTextures[i] )
ref.dllFuncs.GL_FreeTexture( skyboxTextures[i] );
}
}
Frees image by name
================
*/
void GAME_EXPORT GL_FreeImage( const char *name ) void GAME_EXPORT GL_FreeImage( const char *name )
{ {
int texnum; int texnum;
@@ -80,6 +171,22 @@ static intptr_t pfnEngineGetParm( int parm, int arg )
return CL_RenderGetParm( parm, arg, false ); // prevent recursion 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 ) static void pfnStudioEvent( const mstudioevent_t *event, const cl_entity_t *e )
{ {
clgame.dllFuncs.pfnStudioEvent( event, e ); clgame.dllFuncs.pfnStudioEvent( event, e );
@@ -91,7 +198,7 @@ static model_t *pfnGetDefaultSprite( enum ref_defaultsprite_e spr )
{ {
case REF_DOT_SPRITE: return cl_sprite_dot; case REF_DOT_SPRITE: return cl_sprite_dot;
case REF_CHROME_SPRITE: return cl_sprite_shell; case REF_CHROME_SPRITE: return cl_sprite_shell;
default: Host_Error( "GetDefaultSprite: unknown sprite %d\n", spr ); default: Host_Error( "%s: unknown sprite %d\n", __func__, spr );
} }
return NULL; return NULL;
} }
@@ -104,7 +211,7 @@ static void *pfnMod_Extradata( int type, model_t *m )
case mod_studio: return Mod_StudioExtradata( m ); case mod_studio: return Mod_StudioExtradata( m );
case mod_sprite: // fallthrough case mod_sprite: // fallthrough
case mod_brush: return NULL; case mod_brush: return NULL;
default: Host_Error( "Mod_Extradata: unknown type %d\n", type ); default: Host_Error( "%s: unknown type %d\n", __func__, type );
} }
return NULL; return NULL;
} }
@@ -194,18 +301,18 @@ static qboolean R_Init_Video_( const int type )
return R_Init_Video( type ); return R_Init_Video( type );
} }
static ref_api_t gEngfuncs = static const ref_api_t gEngfuncs =
{ {
pfnEngineGetParm, pfnEngineGetParm,
(void*)Cvar_Get, pfnCvar_Get,
(void*)Cvar_FindVarExt, (void*)Cvar_FindVarExt,
Cvar_VariableValue, Cvar_VariableValue,
Cvar_VariableString, Cvar_VariableString,
Cvar_SetValue, Cvar_SetValue,
Cvar_Set, Cvar_Set,
Cvar_RegisterVariable, pfnCvar_RegisterVariable,
Cvar_FullSet, pfnCvar_FullSet,
Cmd_AddRefCommand, Cmd_AddRefCommand,
Cmd_RemoveCommand, Cmd_RemoveCommand,
@@ -340,7 +447,7 @@ static void R_UnloadProgs( void )
Cvar_FullSet( "host_refloaded", "0", FCVAR_READ_ONLY ); 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 ); Cmd_Unlink( CMD_REFDLL );
COM_FreeLibrary( ref.hInstance ); COM_FreeLibrary( ref.hInstance );
@@ -376,48 +483,41 @@ static void CL_FillTriAPIFromRef( triangleapi_t *dst, const ref_interface_t *src
static qboolean R_LoadProgs( const char *name ) static qboolean R_LoadProgs( const char *name )
{ {
extern triangleapi_t gTriApi;
static ref_api_t gpEngfuncs; static ref_api_t gpEngfuncs;
REFAPI GetRefAPI; // single export REFAPI GetRefAPI; // single export
if( ref.hInstance ) R_UnloadProgs(); if( ref.hInstance ) R_UnloadProgs();
FS_AllowDirectPaths( true ); FS_AllowDirectPaths( true );
if( !(ref.hInstance = COM_LoadLibrary( name, false, true ) )) if( !( ref.hInstance = COM_LoadLibrary( name, false, true )))
{ {
FS_AllowDirectPaths( false ); FS_AllowDirectPaths( false );
Con_Reportf( "R_LoadProgs: can't load renderer library %s: %s\n", name, COM_GetLibraryError() ); Con_Reportf( "%s: can't load renderer library %s: %s\n", __func__, name, COM_GetLibraryError() );
return false; return false;
} }
FS_AllowDirectPaths( false ); 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 );
Con_Reportf( "R_LoadProgs: can't find GetRefAPI entry point in %s\n", name );
ref.hInstance = NULL;
return false; return false;
} }
// make local copy of engfuncs to prevent overwrite it with user dll // 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 ) 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__ );
Con_Reportf( "R_LoadProgs: can't init renderer API: wrong version\n" );
ref.hInstance = NULL;
return false; return false;
} }
refState.developer = host_developer.value; 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() );
Con_Reportf( "R_LoadProgs: can't init renderer!\n" ); //, ref.dllFuncs.R_GetInitError() );
ref.hInstance = NULL;
return false; return false;
} }
@@ -454,21 +554,19 @@ static void R_GetRendererName( char *dest, size_t size, const char *opt )
{ {
if( !Q_strstr( opt, "." OS_LIB_EXT )) if( !Q_strstr( opt, "." OS_LIB_EXT ))
{ {
const char *format;
#ifdef XASH_INTERNAL_GAMELIBS #ifdef XASH_INTERNAL_GAMELIBS
if( !Q_strcmp( opt, "ref_" )) #define FMT1 "%s"
format = "%s"; #define FMT2 "ref_%s"
else
format = "ref_%s";
#else #else
if( !Q_strcmp( opt, "ref_" )) #define FMT1 OS_LIB_PREFIX "%s." OS_LIB_EXT
format = OS_LIB_PREFIX "%s." OS_LIB_EXT; #define FMT2 OS_LIB_PREFIX "ref_%s." OS_LIB_EXT
else
format = OS_LIB_PREFIX "ref_%s." OS_LIB_EXT;
#endif #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 else
{ {
@@ -580,7 +678,8 @@ static void R_CollectRendererNames( void )
qboolean R_Init( void ) qboolean R_Init( void )
{ {
qboolean success = false; qboolean success = false;
string requested; string requested_cmdline;
string requested_cvar;
Cvar_RegisterVariable( &gl_vsync ); Cvar_RegisterVariable( &gl_vsync );
Cvar_RegisterVariable( &r_showtextures ); Cvar_RegisterVariable( &r_showtextures );
@@ -630,15 +729,16 @@ qboolean R_Init( void )
// 1. Command line `-ref` argument. // 1. Command line `-ref` argument.
// 2. `ref_dll` cvar. // 2. `ref_dll` cvar.
// 3. Detected renderers in `DEFAULT_RENDERERS` order. // 3. Detected renderers in `DEFAULT_RENDERERS` order.
requested[0] = 0; requested_cmdline[0] = 0;
requested_cvar[0] = 0;
if( !success && Sys_GetParmFromCmdLine( "-ref", requested )) if( Sys_GetParmFromCmdLine( "-ref", requested_cmdline ))
success = R_LoadRenderer( requested ); 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 )); Q_strncpy( requested_cvar, r_refdll.string, sizeof( requested_cvar ));
success = R_LoadRenderer( requested ); success = R_LoadRenderer( requested_cvar );
} }
if( !success ) if( !success )
@@ -648,7 +748,10 @@ qboolean R_Init( void )
for( i = 0; i < ref.numRenderers && !success; i++ ) for( i = 0; i < ref.numRenderers && !success; i++ )
{ {
// skip renderer that was requested but failed to load // 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; continue;
success = R_LoadRenderer( ref.shortNames[i] ); success = R_LoadRenderer( ref.shortNames[i] );
@@ -657,7 +760,7 @@ qboolean R_Init( void )
if( !success ) 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; return false;
} }

View File

@@ -18,19 +18,18 @@ GNU General Public License for more details.
#include "ref_api.h" #include "ref_api.h"
#define RP_LOCALCLIENT( e ) ((e) != NULL && (e)->index == ( cl.playernum + 1 ) && e->player ) #define RP_LOCALCLIENT( e ) ((e) != NULL && (e)->index == ( cl.playernum + 1 ) && e->player )
struct ref_state_s struct ref_state_s
{ {
qboolean initialized; HINSTANCE hInstance;
qboolean initialized;
HINSTANCE hInstance; int numRenderers;
ref_interface_t dllFuncs; ref_interface_t dllFuncs;
// depends on build configuration // depends on build configuration
int numRenderers; const char **shortNames;
const char **shortNames; const char **readableNames;
const char **readableNames;
}; };
extern struct ref_state_s ref; extern struct ref_state_s ref;
@@ -45,14 +44,14 @@ void R_GetTextureParms( int *w, int *h, int texnum );
void GL_RenderFrame( const struct ref_viewpass_s *rvp ); void GL_RenderFrame( const struct ref_viewpass_s *rvp );
void R_SetupSky( const char *name );
// common engine and renderer cvars // common engine and renderer cvars
extern convar_t r_decals; extern convar_t r_decals;
extern convar_t r_adjust_fov; extern convar_t r_adjust_fov;
extern convar_t gl_clear; extern convar_t gl_clear;
qboolean R_Init( void ); qboolean R_Init( void );
void R_Shutdown( void ); void R_Shutdown( void );
extern triangleapi_t gTriApi;
#endif // REF_COMMON_H #endif // REF_COMMON_H

View File

@@ -154,7 +154,8 @@ static const sx_preset_t rgsxpre_hlalpha052[] =
static const sx_preset_t *ptable = rgsxpre; static const sx_preset_t *ptable = rgsxpre;
// cvars // cvars
static CVAR_DEFINE_AUTO( dsp_off, "0", FCVAR_ARCHIVE, "disable DSP processing" ); static CVAR_DEFINE_AUTO( dsp_off, "0", FCVAR_ARCHIVE, "disable DSP processing (deprecated)" );
static CVAR_DEFINE_AUTO( room_off, "0", FCVAR_ARCHIVE, "disable DSP processing (GoldSrc compatible cvar)" );
static CVAR_DEFINE_AUTO( dsp_coeff_table, "0", FCVAR_ARCHIVE, "select DSP coefficient table: 0 for release or 1 for alpha 0.52" ); static CVAR_DEFINE_AUTO( dsp_coeff_table, "0", FCVAR_ARCHIVE, "select DSP coefficient table: 0 for release or 1 for alpha 0.52" );
static CVAR_DEFINE_AUTO( room_type, "0", 0, "current room type preset" ); static CVAR_DEFINE_AUTO( room_type, "0", 0, "current room type preset" );
@@ -232,6 +233,7 @@ void SX_Init( void )
sxmod2cur = sxmod2 = 450 * ( idsp_dma_speed / SOUND_11k ); sxmod2cur = sxmod2 = 450 * ( idsp_dma_speed / SOUND_11k );
Cvar_RegisterVariable( &dsp_off ); Cvar_RegisterVariable( &dsp_off );
Cvar_RegisterVariable( &room_off );
Cvar_RegisterVariable( &dsp_coeff_table ); Cvar_RegisterVariable( &dsp_coeff_table );
Cvar_RegisterVariable( &roomwater_type ); Cvar_RegisterVariable( &roomwater_type );
@@ -809,7 +811,7 @@ DSP_Process
*/ */
void DSP_Process( portable_samplepair_t *pbfront, int sampleCount ) void DSP_Process( portable_samplepair_t *pbfront, int sampleCount )
{ {
if( dsp_off.value || !sampleCount ) if( dsp_off.value || room_off.value || !sampleCount )
return; return;
// preset is already installed by CheckNewDspPresets // preset is already installed by CheckNewDspPresets
@@ -843,7 +845,7 @@ CheckNewDspPresets
*/ */
void CheckNewDspPresets( void ) void CheckNewDspPresets( void )
{ {
if( dsp_off.value != 0.0f ) if( dsp_off.value || room_off.value )
return; return;
if( FBitSet( dsp_coeff_table.flags, FCVAR_CHANGED )) if( FBitSet( dsp_coeff_table.flags, FCVAR_CHANGED ))

View File

@@ -52,8 +52,11 @@ void S_SoundList_f( void )
{ {
totalSize += sc->size; totalSize += sc->size;
if( sc->loopStart >= 0 ) Con_Printf( "L" ); if( FBitSet( sc->flags, SOUND_LOOPED ))
else Con_Printf( " " ); Con_Printf( "L" );
else
Con_Printf( " " );
if( sfx->name[0] == '*' || !Q_strncmp( sfx->name, DEFAULT_SOUNDPATH, sizeof( DEFAULT_SOUNDPATH ) - 1 )) if( sfx->name[0] == '*' || !Q_strncmp( sfx->name, DEFAULT_SOUNDPATH, sizeof( DEFAULT_SOUNDPATH ) - 1 ))
Con_Printf( " (%2db) %s : %s\n", sc->width * 8, Q_memprint( sc->size ), sfx->name ); Con_Printf( " (%2db) %s : %s\n", sc->width * 8, Q_memprint( sc->size ), sfx->name );
else Con_Printf( " (%2db) %s : " DEFAULT_SOUNDPATH "%s\n", sc->width * 8, Q_memprint( sc->size ), sfx->name ); else Con_Printf( " (%2db) %s : " DEFAULT_SOUNDPATH "%s\n", sc->width * 8, Q_memprint( sc->size ), sfx->name );
@@ -110,7 +113,7 @@ static wavdata_t *S_CreateDefaultSound( void )
sc->width = 2; sc->width = 2;
sc->channels = 1; sc->channels = 1;
sc->loopStart = -1; sc->loopStart = 0;
sc->rate = SOUND_DMA_SPEED; sc->rate = SOUND_DMA_SPEED;
sc->samples = SOUND_DMA_SPEED; sc->samples = SOUND_DMA_SPEED;
sc->size = sc->samples * sc->width * sc->channels; sc->size = sc->samples * sc->width * sc->channels;
@@ -141,8 +144,8 @@ wavdata_t *S_LoadSound( sfx_t *sfx )
if( Q_stricmp( sfx->name, "*default" )) if( Q_stricmp( sfx->name, "*default" ))
{ {
// load it from disk // load it from disk
if( s_warn_late_precache.value > 0 && CL_Active() ) if( s_warn_late_precache.value > 0 && cls.state == ca_active )
Con_Printf( S_WARN "S_LoadSound: late precache of %s\n", sfx->name ); Con_Printf( S_WARN "%s: late precache of %s\n", __func__, sfx->name );
if( sfx->name[0] == '*' ) if( sfx->name[0] == '*' )
sc = FS_LoadSound( sfx->name + 1, NULL, 0 ); sc = FS_LoadSound( sfx->name + 1, NULL, 0 );
@@ -152,11 +155,11 @@ wavdata_t *S_LoadSound( sfx_t *sfx )
if( !sc ) sc = S_CreateDefaultSound(); if( !sc ) sc = S_CreateDefaultSound();
if( sc->rate < SOUND_11k ) // some bad sounds 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 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_32k ) // some bad sounds 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; sfx->cache = sc;
@@ -218,7 +221,7 @@ sfx_t *S_FindName( const char *pname, int *pfInCache )
sfx = &s_knownSfx[i]; sfx = &s_knownSfx[i];
memset( sfx, 0, sizeof( *sfx )); memset( sfx, 0, sizeof( *sfx ));
if( pfInCache ) *pfInCache = false; if( pfInCache ) *pfInCache = false;
Q_strncpy( sfx->name, name, MAX_STRING ); Q_strncpy( sfx->name, name, sizeof( sfx->name ));
sfx->servercount = cl.servercount; sfx->servercount = cl.servercount;
sfx->hashValue = COM_HashKey( sfx->name, MAX_SFX_HASH ); sfx->hashValue = COM_HashKey( sfx->name, MAX_SFX_HASH );
@@ -377,7 +380,7 @@ S_InitSounds
void S_InitSounds( void ) void S_InitSounds( void )
{ {
// create unused 0-entry // create unused 0-entry
Q_strncpy( s_knownSfx->name, "*default", MAX_QPATH ); Q_strncpy( s_knownSfx->name, "*default", sizeof( s_knownSfx->name ));
s_knownSfx->hashValue = COM_HashKey( s_knownSfx->name, MAX_SFX_HASH ); s_knownSfx->hashValue = COM_HashKey( s_knownSfx->name, MAX_SFX_HASH );
s_knownSfx->hashNext = s_sfxHashList[s_knownSfx->hashValue]; s_knownSfx->hashNext = s_sfxHashList[s_knownSfx->hashValue];
s_sfxHashList[s_knownSfx->hashValue] = s_knownSfx; s_sfxHashList[s_knownSfx->hashValue] = s_knownSfx;

View File

@@ -43,7 +43,7 @@ CVAR_DEFINE_AUTO( s_lerping, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "apply interpo
static CVAR_DEFINE( s_ambient_level, "ambient_level", "0.3", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "volume of environment noises (water and wind)" ); static CVAR_DEFINE( s_ambient_level, "ambient_level", "0.3", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "volume of environment noises (water and wind)" );
static CVAR_DEFINE( s_ambient_fade, "ambient_fade", "1000", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "rate of volume fading when client is moving" ); static CVAR_DEFINE( s_ambient_fade, "ambient_fade", "1000", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "rate of volume fading when client is moving" );
static CVAR_DEFINE_AUTO( s_combine_sounds, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "combine channels with same sounds" ); static CVAR_DEFINE_AUTO( s_combine_sounds, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "combine channels with same sounds" );
static CVAR_DEFINE_AUTO( snd_mute_losefocus, "1", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "silence the audio when game window loses focus" ); CVAR_DEFINE_AUTO( snd_mute_losefocus, "1", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "silence the audio when game window loses focus" );
CVAR_DEFINE_AUTO( s_test, "0", 0, "engine developer cvar for quick testing new features" ); CVAR_DEFINE_AUTO( s_test, "0", 0, "engine developer cvar for quick testing new features" );
CVAR_DEFINE_AUTO( s_samplecount, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "sample count (0 for default value)" ); CVAR_DEFINE_AUTO( s_samplecount, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "sample count (0 for default value)" );
CVAR_DEFINE_AUTO( s_warn_late_precache, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "warn about late precached sounds on client-side" ); CVAR_DEFINE_AUTO( s_warn_late_precache, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "warn about late precached sounds on client-side" );
@@ -328,7 +328,7 @@ channel_t *SND_PickDynamicChannel( int entnum, int channel, sfx_t *sfx, qboolean
// don't restart looping sounds for the same entity // don't restart looping sounds for the same entity
wavdata_t *sc = channels[first_to_die].sfx->cache; wavdata_t *sc = channels[first_to_die].sfx->cache;
if( sc && sc->loopStart != -1 ) if( sc && FBitSet( sc->flags, SOUND_LOOPED ))
{ {
channel_t *ch = &channels[first_to_die]; channel_t *ch = &channels[first_to_die];
@@ -382,7 +382,7 @@ channel_t *SND_PickStaticChannel( const vec3_t pos, sfx_t *sfx )
// no empty slots, alloc a new static sound channel // no empty slots, alloc a new static sound channel
if( total_channels == MAX_CHANNELS ) if( total_channels == MAX_CHANNELS )
{ {
Con_DPrintf( S_ERROR "S_PickStaticChannel: no free channels\n" ); Con_DPrintf( S_ERROR "%s: no free channels\n", __func__ );
return NULL; return NULL;
} }
@@ -503,7 +503,7 @@ static void SND_Spatialize( channel_t *ch )
pSource = ch->sfx->cache; pSource = ch->sfx->cache;
if( ch->use_loop && pSource && pSource->loopStart != -1 ) if( ch->use_loop && pSource && FBitSet( pSource->flags, SOUND_LOOPED ))
looping = true; looping = true;
if( !ch->staticsound ) if( !ch->staticsound )
@@ -524,8 +524,11 @@ static void SND_Spatialize( channel_t *ch )
dist = VectorNormalizeLength( source_vec ); dist = VectorNormalizeLength( source_vec );
dot = DotProduct( s_listener.right, source_vec ); dot = DotProduct( s_listener.right, source_vec );
// don't pan sounds with no attenuation if( !FBitSet( host.bugcomp, BUGCOMP_SPATIALIZE_SOUND_WITH_ATTN_NONE ))
if( ch->dist_mult <= 0.0f ) dot = 0.0f; {
// don't pan sounds with no attenuation
if( ch->dist_mult <= 0.0f ) dot = 0.0f;
}
// fill out channel volumes for single location // fill out channel volumes for single location
S_SpatializeChannel( &ch->leftvol, &ch->rightvol, ch->master_vol, gain, dot, dist * ch->dist_mult ); S_SpatializeChannel( &ch->leftvol, &ch->rightvol, ch->master_vol, gain, dot, dist * ch->dist_mult );
@@ -641,7 +644,7 @@ void S_StartSound( const vec3_t pos, int ent, int chan, sound_t handle, float fv
if( !target_chan->leftvol && !target_chan->rightvol ) if( !target_chan->leftvol && !target_chan->rightvol )
{ {
// looping sounds don't use this optimization because they should stick around until they're killed. // looping sounds don't use this optimization because they should stick around until they're killed.
if( !sfx->cache || sfx->cache->loopStart == -1 ) if( !sfx->cache || !FBitSet( sfx->cache->flags, SOUND_LOOPED ))
{ {
// if this is a streaming sound, play the whole thing. // if this is a streaming sound, play the whole thing.
if( chan != CHAN_STREAM ) if( chan != CHAN_STREAM )
@@ -893,7 +896,7 @@ int S_GetCurrentStaticSounds( soundlist_t *pout, int size )
VectorCopy( channels[i].origin, pout->origin ); VectorCopy( channels[i].origin, pout->origin );
pout->volume = (float)channels[i].master_vol / 255.0f; pout->volume = (float)channels[i].master_vol / 255.0f;
pout->attenuation = channels[i].dist_mult * SND_CLIP_DISTANCE; pout->attenuation = channels[i].dist_mult * SND_CLIP_DISTANCE;
pout->looping = ( channels[i].use_loop && channels[i].sfx->cache->loopStart != -1 ); pout->looping = ( channels[i].use_loop && FBitSet( channels[i].sfx->cache->flags, SOUND_LOOPED ));
pout->pitch = channels[i].basePitch; pout->pitch = channels[i].basePitch;
pout->channel = channels[i].entchannel; pout->channel = channels[i].entchannel;
pout->wordIndex = channels[i].wordIndex; pout->wordIndex = channels[i].wordIndex;
@@ -928,7 +931,7 @@ int S_GetCurrentDynamicSounds( soundlist_t *pout, int size )
if( !channels[i].sfx || !channels[i].sfx->name[0] || !Q_stricmp( channels[i].sfx->name, "*default" )) if( !channels[i].sfx || !channels[i].sfx->name[0] || !Q_stricmp( channels[i].sfx->name, "*default" ))
continue; // don't serialize default sounds continue; // don't serialize default sounds
looped = ( channels[i].use_loop && channels[i].sfx->cache->loopStart != -1 ); looped = ( channels[i].use_loop && FBitSet( channels[i].sfx->cache->flags, SOUND_LOOPED ));
if( channels[i].entchannel == CHAN_STATIC && looped && !Host_IsQuakeCompatible()) if( channels[i].entchannel == CHAN_STATIC && looped && !Host_IsQuakeCompatible())
continue; // never serialize static looped sounds. It will be restoring in game code continue; // never serialize static looped sounds. It will be restoring in game code
@@ -1092,7 +1095,7 @@ rawchan_t *S_FindRawChannel( int entnum, qboolean create )
if( !raw_channels[best] ) if( !raw_channels[best] )
{ {
raw_samples = MAX_RAW_SAMPLES; 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]; ch = raw_channels[best];
@@ -1599,11 +1602,10 @@ void SND_UpdateSound( void )
// release raw-channels that no longer used more than 10 secs // release raw-channels that no longer used more than 10 secs
S_FreeIdleRawChannels(); S_FreeIdleRawChannels();
VectorCopy( cl.simvel, s_listener.velocity );
s_listener.frametime = (cl.time - cl.oldtime); s_listener.frametime = (cl.time - cl.oldtime);
s_listener.waterlevel = cl.local.waterlevel; s_listener.waterlevel = cl.local.waterlevel;
s_listener.active = CL_IsInGame(); s_listener.active = CL_IsInGame();
s_listener.inmenu = CL_IsInMenu(); s_listener.inmenu = cls.key_dest == key_menu;
s_listener.paused = cl.paused; s_listener.paused = cl.paused;
// update general area ambient sound sources // update general area ambient sound sources

View File

@@ -17,30 +17,56 @@ GNU General Public License for more details.
#include "sound.h" #include "sound.h"
#include "client.h" #include "client.h"
#define IPAINTBUFFER 0 enum
#define IROOMBUFFER 1 {
#define ISTREAMBUFFER 2 IPAINTBUFFER = 0,
IROOMBUFFER,
ISTREAMBUFFER,
CPAINTBUFFERS,
};
#define FILTERTYPE_NONE 0 enum
#define FILTERTYPE_LINEAR 1 {
#define FILTERTYPE_CUBIC 2 FILTERTYPE_NONE = 0,
FILTERTYPE_LINEAR,
FILTERTYPE_CUBIC,
};
#define CCHANVOLUMES 2 #define CCHANVOLUMES 2
#define SND_SCALE_BITS 7 #define SND_SCALE_BITS 7
#define SND_SCALE_SHIFT (8 - SND_SCALE_BITS) #define SND_SCALE_SHIFT ( 8 - SND_SCALE_BITS )
#define SND_SCALE_LEVELS (1 << SND_SCALE_BITS) #define SND_SCALE_LEVELS ( 1 << SND_SCALE_BITS )
portable_samplepair_t *g_curpaintbuffer; // sound mixing buffer
portable_samplepair_t streambuffer[(PAINTBUFFER_SIZE+1)]; #define CPAINTFILTERMEM 3
portable_samplepair_t paintbuffer[(PAINTBUFFER_SIZE+1)]; #define CPAINTFILTERS 4 // maximum number of consecutive upsample passes per paintbuffer
portable_samplepair_t roombuffer[(PAINTBUFFER_SIZE+1)];
portable_samplepair_t facingbuffer[(PAINTBUFFER_SIZE+1)];
portable_samplepair_t temppaintbuffer[(PAINTBUFFER_SIZE+1)];
paintbuffer_t paintbuffers[CPAINTBUFFERS];
int snd_scaletable[SND_SCALE_LEVELS][256]; // fixed point stuff for real-time resampling
#define FIX_BITS 28
#define FIX_SCALE ( 1 << FIX_BITS )
#define FIX_MASK (( 1 << FIX_BITS ) - 1 )
#define FIX_FLOAT( a ) ((int)(( a ) * FIX_SCALE ))
#define FIX( a ) (((int)( a )) << FIX_BITS )
#define FIX_INTPART( a ) (((int)( a )) >> FIX_BITS )
#define FIX_FRACPART( a ) (( a ) & FIX_MASK )
typedef struct
{
qboolean factive; // if true, mix to this paintbuffer using flags
portable_samplepair_t *pbuf; // front stereo mix buffer, for 2 or 4 channel mixing
int ifilter; // current filter memory buffer to use for upsampling pass
portable_samplepair_t fltmem[CPAINTFILTERS][CPAINTFILTERMEM];
} paintbuffer_t;
static portable_samplepair_t *g_curpaintbuffer;
static portable_samplepair_t streambuffer[(PAINTBUFFER_SIZE+1)];
static portable_samplepair_t paintbuffer[(PAINTBUFFER_SIZE+1)];
static portable_samplepair_t roombuffer[(PAINTBUFFER_SIZE+1)];
static portable_samplepair_t temppaintbuffer[(PAINTBUFFER_SIZE+1)];
static paintbuffer_t paintbuffers[CPAINTBUFFERS];
static int snd_scaletable[SND_SCALE_LEVELS][256];
void S_InitScaletable( void ) void S_InitScaletable( void )
{ {
int i, j; int i, j;
@@ -67,7 +93,7 @@ static void S_TransferPaintBuffer( int endtime )
dword *pbuf; dword *pbuf;
pbuf = (dword *)dma.buffer; pbuf = (dword *)dma.buffer;
snd_p = (int *)PAINTBUFFER; snd_p = (int *)g_curpaintbuffer;
lpaintedtime = paintedtime; lpaintedtime = paintedtime;
sampleMask = ((dma.samples >> 1) - 1); sampleMask = ((dma.samples >> 1) - 1);
@@ -111,20 +137,20 @@ static void S_TransferPaintBuffer( int endtime )
//=============================================================================== //===============================================================================
// Activate a paintbuffer. All active paintbuffers are mixed in parallel within // Activate a paintbuffer. All active paintbuffers are mixed in parallel within
// MIX_MixChannelsToPaintbuffer, according to flags // MIX_MixChannelsToPaintbuffer, according to flags
_inline void MIX_ActivatePaintbuffer( int ipaintbuffer ) static void MIX_ActivatePaintbuffer( int ipaintbuffer )
{ {
Assert( ipaintbuffer < CPAINTBUFFERS ); Assert( ipaintbuffer < CPAINTBUFFERS );
paintbuffers[ipaintbuffer].factive = true; paintbuffers[ipaintbuffer].factive = true;
} }
_inline void MIX_SetCurrentPaintbuffer( int ipaintbuffer ) static void MIX_SetCurrentPaintbuffer( int ipaintbuffer )
{ {
Assert( ipaintbuffer < CPAINTBUFFERS ); Assert( ipaintbuffer < CPAINTBUFFERS );
g_curpaintbuffer = paintbuffers[ipaintbuffer].pbuf; g_curpaintbuffer = paintbuffers[ipaintbuffer].pbuf;
Assert( g_curpaintbuffer != NULL ); Assert( g_curpaintbuffer != NULL );
} }
_inline int MIX_GetCurrentPaintbufferIndex( void ) static int MIX_GetCurrentPaintbufferIndex( void )
{ {
int i; int i;
@@ -136,7 +162,7 @@ _inline int MIX_GetCurrentPaintbufferIndex( void )
return 0; return 0;
} }
_inline paintbuffer_t *MIX_GetCurrentPaintbufferPtr( void ) static paintbuffer_t *MIX_GetCurrentPaintbufferPtr( void )
{ {
int ipaint = MIX_GetCurrentPaintbufferIndex(); int ipaint = MIX_GetCurrentPaintbufferIndex();
@@ -145,7 +171,7 @@ _inline paintbuffer_t *MIX_GetCurrentPaintbufferPtr( void )
} }
// Don't mix into any paintbuffers // Don't mix into any paintbuffers
_inline void MIX_DeactivateAllPaintbuffers( void ) static void MIX_DeactivateAllPaintbuffers( void )
{ {
int i; int i;
@@ -154,7 +180,7 @@ _inline void MIX_DeactivateAllPaintbuffers( void )
} }
// set upsampling filter indexes back to 0 // set upsampling filter indexes back to 0
_inline void MIX_ResetPaintbufferFilterCounters( void ) static void MIX_ResetPaintbufferFilterCounters( void )
{ {
int i; int i;
@@ -163,13 +189,13 @@ _inline void MIX_ResetPaintbufferFilterCounters( void )
} }
// return pointer to front paintbuffer pbuf, given index // return pointer to front paintbuffer pbuf, given index
_inline portable_samplepair_t *MIX_GetPFrontFromIPaint( int ipaintbuffer ) static portable_samplepair_t *MIX_GetPFrontFromIPaint( int ipaintbuffer )
{ {
Assert( ipaintbuffer < CPAINTBUFFERS ); Assert( ipaintbuffer < CPAINTBUFFERS );
return paintbuffers[ipaintbuffer].pbuf; return paintbuffers[ipaintbuffer].pbuf;
} }
_inline paintbuffer_t *MIX_GetPPaintFromIPaint( int ipaint ) static paintbuffer_t *MIX_GetPPaintFromIPaint( int ipaint )
{ {
Assert( ipaint < CPAINTBUFFERS ); Assert( ipaint < CPAINTBUFFERS );
return &paintbuffers[ipaint]; return &paintbuffers[ipaint];
@@ -523,6 +549,7 @@ static void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate
wavdata_t *pSource; wavdata_t *pSource;
int i, sampleCount; int i, sampleCount;
qboolean bZeroVolume; qboolean bZeroVolume;
qboolean local = Host_IsLocalGame();
// mix each channel into paintbuffer // mix each channel into paintbuffer
ch = channels; ch = channels;
@@ -549,7 +576,7 @@ static void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate
{ {
// play, playvol // play, playvol
} }
else if(( s_listener.inmenu || s_listener.paused ) && !ch->localsound ) else if(( s_listener.inmenu || s_listener.paused ) && !ch->localsound && local )
{ {
// play only local sounds, keep pause for other // play only local sounds, keep pause for other
continue; continue;
@@ -567,6 +594,7 @@ static void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate
// Don't mix sound data for sounds with zero volume. If it's a non-looping sound, // Don't mix sound data for sounds with zero volume. If it's a non-looping sound,
// just remove the sound when its volume goes to zero. // just remove the sound when its volume goes to zero.
bZeroVolume = !ch->leftvol && !ch->rightvol; bZeroVolume = !ch->leftvol && !ch->rightvol;
if( !bZeroVolume ) if( !bZeroVolume )
@@ -576,7 +604,7 @@ static void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate
bZeroVolume = true; bZeroVolume = true;
} }
if( !pSource || ( bZeroVolume && pSource->loopStart == -1 )) if( !pSource || ( bZeroVolume && !FBitSet( pSource->flags, SOUND_LOOPED )))
{ {
if( !pSource ) if( !pSource )
{ {
@@ -629,7 +657,7 @@ static void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate
} }
// pass in index -1...count+2, return pointer to source sample in either paintbuffer or delay buffer // pass in index -1...count+2, return pointer to source sample in either paintbuffer or delay buffer
_inline portable_samplepair_t *S_GetNextpFilter( int i, portable_samplepair_t *pbuffer, portable_samplepair_t *pfiltermem ) static portable_samplepair_t *S_GetNextpFilter( int i, portable_samplepair_t *pbuffer, portable_samplepair_t *pfiltermem )
{ {
// The delay buffer is assumed to precede the paintbuffer by 6 duplicated samples // The delay buffer is assumed to precede the paintbuffer by 6 duplicated samples
if( i == -1 ) return (&(pfiltermem[0])); if( i == -1 ) return (&(pfiltermem[0]));
@@ -838,6 +866,14 @@ static void MIX_MixPaintbuffers( int ibuf1, int ibuf2, int ibuf3, int count, flo
pbuf2 = paintbuffers[ibuf2].pbuf; pbuf2 = paintbuffers[ibuf2].pbuf;
pbuf3 = paintbuffers[ibuf3].pbuf; pbuf3 = paintbuffers[ibuf3].pbuf;
if( !gain )
{
// do not mix buf2 into buf3, just copy
if( pbuf1 != pbuf3 )
memcpy( pbuf3, pbuf1, sizeof( *pbuf1 ) * count );
return;
}
// destination buffer stereo - average n chans down to stereo // destination buffer stereo - average n chans down to stereo
// destination 2ch: // destination 2ch:
@@ -887,7 +923,7 @@ static void S_MixUpsample( int sampleCount, int filtertype )
static void MIX_MixRawSamplesBuffer( int end ) static void MIX_MixRawSamplesBuffer( int end )
{ {
portable_samplepair_t *pbuf, *roombuf, *streambuf; portable_samplepair_t *pbuf, *roombuf, *streambuf;
uint i, j, stop; uint i, j, stop;
roombuf = MIX_GetPFrontFromIPaint( IROOMBUFFER ); roombuf = MIX_GetPFrontFromIPaint( IROOMBUFFER );
streambuf = MIX_GetPFrontFromIPaint( ISTREAMBUFFER ); streambuf = MIX_GetPFrontFromIPaint( ISTREAMBUFFER );
@@ -920,7 +956,11 @@ static void MIX_MixRawSamplesBuffer( int end )
} }
if( ch->entnum > 0 ) 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

@@ -57,6 +57,12 @@ float S_GetMusicVolume( void )
{ {
float scale = 1.0f; float scale = 1.0f;
if( host.status == HOST_NOFOCUS && snd_mute_losefocus.value != 0.0f )
{
// we return zero volume to keep sounds running
return 0.0f;
}
if( !s_listener.inmenu && musicfade.percent != 0 ) if( !s_listener.inmenu && musicfade.percent != 0 )
{ {
scale = bound( 0.0f, musicfade.percent / 100.0f, 1.0f ); scale = bound( 0.0f, musicfade.percent / 100.0f, 1.0f );
@@ -142,7 +148,7 @@ S_StreamGetCurrentState
save\restore code save\restore code
================= =================
*/ */
qboolean S_StreamGetCurrentState( char *currentTrack, char *loopTrack, int *position ) qboolean S_StreamGetCurrentState( char *currentTrack, size_t currentTrackSize, char *loopTrack, size_t loopTrackSize, int *position )
{ {
if( !s_bgTrack.stream ) if( !s_bgTrack.stream )
return false; // not active return false; // not active
@@ -150,15 +156,15 @@ qboolean S_StreamGetCurrentState( char *currentTrack, char *loopTrack, int *posi
if( currentTrack ) if( currentTrack )
{ {
if( s_bgTrack.current[0] ) if( s_bgTrack.current[0] )
Q_strncpy( currentTrack, s_bgTrack.current, MAX_STRING ); Q_strncpy( currentTrack, s_bgTrack.current, currentTrackSize );
else Q_strncpy( currentTrack, "*", MAX_STRING ); // no track else Q_strncpy( currentTrack, "*", currentTrackSize ); // no track
} }
if( loopTrack ) if( loopTrack )
{ {
if( s_bgTrack.loopName[0] ) if( s_bgTrack.loopName[0] )
Q_strncpy( loopTrack, s_bgTrack.loopName, MAX_STRING ); Q_strncpy( loopTrack, s_bgTrack.loopName, loopTrackSize );
else Q_strncpy( loopTrack, "*", MAX_STRING ); // no track else Q_strncpy( loopTrack, "*", loopTrackSize ); // no track
} }
if( position ) if( position )

View File

@@ -27,7 +27,7 @@ int S_ConvertLoopedPosition( wavdata_t *pSource, int samplePosition, qboolean us
// convert to a position within the loop // convert to a position within the loop
// At the end of the loop, we return a short buffer, and subsequent call // At the end of the loop, we return a short buffer, and subsequent call
// will loop back and get the rest of the buffer // will loop back and get the rest of the buffer
if( pSource->loopStart >= 0 && samplePosition >= pSource->samples && use_loop ) if( FBitSet( pSource->flags, SOUND_LOOPED ) && samplePosition >= pSource->samples && use_loop )
{ {
// size of loop // size of loop
int loopSize = pSource->samples - pSource->loopStart; int loopSize = pSource->samples - pSource->loopStart;

View File

@@ -96,7 +96,7 @@ static int S_TrimEnd( const wavdata_t *wav, int end )
if( width == 1 ) 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++ ) 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 ) 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++ ) for( i = 0; i < TRIM_SCAN_MAX && end > 0; i++ )
{ {
@@ -261,7 +261,7 @@ static const char *VOX_GetDirectory( char *szpath, const char *psz, int nsize )
if( len > nsize ) if( len > nsize )
{ {
Con_Printf( "VOX_GetDirectory: invalid directory in: %s\n", psz ); Con_Printf( "%s: invalid directory in: %s\n", __func__, psz );
return NULL; return NULL;
} }
@@ -467,7 +467,7 @@ void VOX_LoadSound( channel_t *ch, const char *pszin )
if( !psz ) if( !psz )
{ {
Con_Printf( "VOX_LoadSound: no sentence named %s\n", pszin ); Con_Printf( "%s: no sentence named %s\n", __func__, pszin );
return; return;
} }
@@ -475,13 +475,13 @@ void VOX_LoadSound( channel_t *ch, const char *pszin )
if( !psz ) if( !psz )
{ {
Con_Printf( "VOX_LoadSound: failed getting directory for %s\n", pszin ); Con_Printf( "%s: failed getting directory for %s\n", __func__, pszin );
return; return;
} }
if( Q_strlen( psz ) >= sizeof( buffer ) ) if( Q_strlen( psz ) >= sizeof( buffer ) )
{ {
Con_Printf( "VOX_LoadSound: sentence is too long %s", psz ); Con_Printf( "%s: sentence is too long %s", __func__, psz );
return; return;
} }

View File

@@ -20,208 +20,181 @@ extern poolhandle_t sndpool;
#include "xash3d_mathlib.h" #include "xash3d_mathlib.h"
// sound engine rate defines #define XASH_AUDIO_CD_QUALITY 1 // some platforms might need this
#define SOUND_DMA_SPEED 44100 // hardware playback rate
#define SOUND_11k 11025 // 11khz sample rate
#define SOUND_16k 16000 // 16khz sample rate
#define SOUND_22k 22050 // 22khz sample rate
#define SOUND_32k 32000 // 32khz sample rate
#define SOUND_44k 44100 // 44khz sample rate
#define DMA_MSEC_PER_SAMPLE ((float)(1000.0 / SOUND_DMA_SPEED))
// fixed point stuff for real-time resampling // sound engine rate defines
#define FIX_BITS 28 #if XASH_AUDIO_CD_QUALITY
#define FIX_SCALE (1 << FIX_BITS) #define SOUND_11k 11025 // 11khz sample rate
#define FIX_MASK ((1 << FIX_BITS)-1) #define SOUND_22k 22050 // 22khz sample rate
#define FIX_FLOAT(a) ((int)((a) * FIX_SCALE)) #define SOUND_44k 44100 // 44khz sample rate
#define FIX(a) (((int)(a)) << FIX_BITS) #else // XASH_AUDIO_CD_QUALITY
#define FIX_INTPART(a) (((int)(a)) >> FIX_BITS) #define SOUND_11k 12000 // 11khz sample rate
#define FIX_FRACTION(a,b) (FIX(a)/(b)) #define SOUND_22k 24000 // 22khz sample rate
#define FIX_FRACPART(a) ((a) & FIX_MASK) #define SOUND_44k 48000 // 44khz sample rate
#endif // XASH_AUDIO_CD_QUALITY
#define SOUND_DMA_SPEED SOUND_44k // hardware playback rate
// NOTE: clipped sound at 32760 to avoid overload // NOTE: clipped sound at 32760 to avoid overload
#define CLIP( x ) (( x ) > 32760 ? 32760 : (( x ) < -32760 ? -32760 : ( x ))) #define CLIP( x ) (( x ) > 32760 ? 32760 : (( x ) < -32760 ? -32760 : ( x )))
#define PAINTBUFFER_SIZE 1024 // 44k: was 512 #define PAINTBUFFER_SIZE 1024 // 44k: was 512
#define PAINTBUFFER (g_curpaintbuffer)
#define CPAINTBUFFERS 3
// sound mixing buffer #define S_RAW_SOUND_IDLE_SEC 10 // time interval for idling raw sound before it's freed
#define CPAINTFILTERMEM 3 #define S_RAW_SOUND_BACKGROUNDTRACK -2
#define CPAINTFILTERS 4 // maximum number of consecutive upsample passes per paintbuffer #define S_RAW_SOUND_SOUNDTRACK -1
#define S_RAW_SAMPLES_PRECISION_BITS 14
#define S_RAW_SOUND_IDLE_SEC 10 // time interval for idling raw sound before it's freed
#define S_RAW_SOUND_BACKGROUNDTRACK -2
#define S_RAW_SOUND_SOUNDTRACK -1
#define S_RAW_SAMPLES_PRECISION_BITS 14
#define CIN_FRAMETIME (1.0f / 30.0f)
typedef struct typedef struct
{ {
int left; int left;
int right; int right;
} portable_samplepair_t; } portable_samplepair_t;
typedef struct
{
qboolean factive; // if true, mix to this paintbuffer using flags
portable_samplepair_t *pbuf; // front stereo mix buffer, for 2 or 4 channel mixing
int ifilter; // current filter memory buffer to use for upsampling pass
portable_samplepair_t fltmem[CPAINTFILTERS][CPAINTFILTERMEM];
} paintbuffer_t;
typedef struct sfx_s typedef struct sfx_s
{ {
char name[MAX_QPATH]; char name[MAX_QPATH];
wavdata_t *cache; wavdata_t *cache;
int servercount; int servercount;
uint hashValue; uint hashValue;
struct sfx_s *hashNext; struct sfx_s *hashNext;
} sfx_t; } sfx_t;
extern portable_samplepair_t paintbuffer[];
extern portable_samplepair_t roombuffer[];
extern portable_samplepair_t temppaintbuffer[];
extern portable_samplepair_t *g_curpaintbuffer;
extern paintbuffer_t paintbuffers[];
// structure used for fading in and out client sound volume. // structure used for fading in and out client sound volume.
typedef struct typedef struct
{ {
float initial_percent; float initial_percent;
float percent; // how far to adjust client's volume down by. float percent; // how far to adjust client's volume down by.
float starttime; // GetHostTime() when we started adjusting volume float starttime; // GetHostTime() when we started adjusting volume
float fadeouttime; // # of seconds to get to faded out state float fadeouttime; // # of seconds to get to faded out state
float holdtime; // # of seconds to hold float holdtime; // # of seconds to hold
float fadeintime; // # of seconds to restore float fadeintime; // # of seconds to restore
} soundfade_t; } soundfade_t;
typedef struct typedef struct
{ {
float percent; float percent;
} musicfade_t; } musicfade_t;
typedef struct snd_format_s typedef struct snd_format_s
{ {
unsigned int speed; uint speed;
unsigned int width; byte width;
unsigned int channels; byte channels;
} snd_format_t; } snd_format_t;
typedef struct typedef struct
{ {
snd_format_t format; snd_format_t format;
int samples; // mono samples in buffer int samples; // mono samples in buffer
int samplepos; // in mono samples int samplepos; // in mono samples
byte *buffer; qboolean initialized; // sound engine is active
qboolean initialized; // sound engine is active byte *buffer;
const char *backendName; const char *backendName;
} dma_t; } dma_t;
#include "vox.h" #include "vox.h"
typedef struct typedef struct
{ {
double sample; double sample;
wavdata_t *pData;
wavdata_t *pData; double forcedEndSample;
double forcedEndSample; qboolean finished;
qboolean finished;
} mixer_t; } mixer_t;
typedef struct rawchan_s typedef struct rawchan_s
{ {
int entnum; int entnum;
int master_vol; int master_vol;
int leftvol; // 0-255 left volume int leftvol; // 0-255 left volume
int rightvol; // 0-255 right volume int rightvol; // 0-255 right volume
float dist_mult; // distance multiplier (attenuation/clipK) float dist_mult; // distance multiplier (attenuation/clipK)
vec3_t origin; // only use if fixed_origin is set vec3_t origin; // only use if fixed_origin is set
volatile uint s_rawend; volatile uint s_rawend;
wavdata_t sound_info; // advance play position float oldtime; // catch time jumps
float oldtime; // catch time jumps wavdata_t sound_info; // advance play position
size_t max_samples; // buffer length size_t max_samples; // buffer length
portable_samplepair_t rawsamples[1]; // variable sized portable_samplepair_t rawsamples[]; // variable sized
} rawchan_t; } rawchan_t;
typedef struct channel_s typedef struct channel_s
{ {
char name[16]; // keept sentence name char name[16]; // keep sentence name
sfx_t *sfx; // sfx number sfx_t *sfx; // sfx number
int leftvol; // 0-255 left volume int leftvol; // 0-255 left volume
int rightvol; // 0-255 right volume int rightvol; // 0-255 right volume
int entnum; // entity soundsource int entnum; // entity soundsource
int entchannel; // sound channel (CHAN_STREAM, CHAN_VOICE, etc.) int entchannel; // sound channel (CHAN_STREAM, CHAN_VOICE, etc.)
vec3_t origin; // only use if fixed_origin is set vec3_t origin; // only use if fixed_origin is set
float dist_mult; // distance multiplier (attenuation/clipK) float dist_mult; // distance multiplier (attenuation/clipK)
int master_vol; // 0-255 master volume int master_vol; // 0-255 master volume
qboolean isSentence; // bit who indicated sentence int basePitch; // base pitch percent (100% is normal pitch playback)
int basePitch; // base pitch percent (100% is normal pitch playback) float pitch; // real-time pitch after any modulation or shift by dynamic data
float pitch; // real-time pitch after any modulation or shift by dynamic data qboolean use_loop; // don't loop default and local sounds
qboolean use_loop; // don't loop default and local sounds qboolean staticsound; // use origin instead of fetching entnum's origin
qboolean staticsound; // use origin instead of fetching entnum's origin qboolean localsound; // it's a local menu sound (not looped, not paused)
qboolean localsound; // it's a local menu sound (not looped, not paused) mixer_t pMixer;
mixer_t pMixer;
// sentence mixer // sentence mixer
int wordIndex; qboolean isSentence; // bit indicating sentence
mixer_t *currentWord; // NULL if sentence is finished int wordIndex;
voxword_t words[CVOXWORDMAX]; mixer_t *currentWord; // NULL if sentence is finished
voxword_t words[CVOXWORDMAX];
} channel_t; } channel_t;
typedef struct typedef struct
{ {
vec3_t origin; // simorg + view_ofs vec3_t origin; // simorg + view_ofs
vec3_t velocity; vec3_t forward;
vec3_t forward; vec3_t right;
vec3_t right; vec3_t up;
vec3_t up;
int entnum; int entnum;
int waterlevel; int waterlevel;
float frametime; // used for sound fade float frametime; // used for sound fade
qboolean active; qboolean active;
qboolean inmenu; // listener in-menu ? qboolean inmenu; // listener in-menu ?
qboolean paused; qboolean paused;
qboolean streaming; // playing AVI-file qboolean streaming; // playing AVI-file
qboolean stream_paused; // pause only background track qboolean stream_paused; // pause only background track
} listener_t; } listener_t;
typedef struct typedef struct
{ {
string current; // a currently playing track string current; // a currently playing track
string loopName; // may be empty string loopName; // may be empty
stream_t *stream; stream_t *stream;
int source; // may be game, menu, etc int source; // may be game, menu, etc
} bg_track_t; } bg_track_t;
//==================================================================== //====================================================================
#define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS) #define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS)
#define MAX_CHANNELS (256 + MAX_DYNAMIC_CHANNELS) // Scourge Of Armagon has too many static sounds on hip2m4.bsp #define MAX_CHANNELS (256 + MAX_DYNAMIC_CHANNELS) // Scourge Of Armagon has too many static sounds on hip2m4.bsp
#define MAX_RAW_CHANNELS 48 #define MAX_RAW_CHANNELS 48
#define MAX_RAW_SAMPLES 8192 #define MAX_RAW_SAMPLES 8192
extern sound_t ambient_sfx[NUM_AMBIENTS]; extern sound_t ambient_sfx[NUM_AMBIENTS];
extern qboolean snd_ambient; extern qboolean snd_ambient;
extern channel_t channels[MAX_CHANNELS]; extern channel_t channels[MAX_CHANNELS];
extern rawchan_t *raw_channels[MAX_RAW_CHANNELS]; extern rawchan_t *raw_channels[MAX_RAW_CHANNELS];
extern int total_channels; extern int total_channels;
extern int paintedtime; extern int paintedtime;
extern int soundtime; extern int soundtime;
extern listener_t s_listener; extern listener_t s_listener;
extern int idsp_room; extern int idsp_room;
extern dma_t dma; extern dma_t dma;
extern convar_t s_musicvolume; extern convar_t s_musicvolume;
extern convar_t s_lerping; extern convar_t s_lerping;
extern convar_t s_test; // cvar to testify new effects extern convar_t s_test; // cvar to test new effects
extern convar_t s_samplecount; extern convar_t s_samplecount;
extern convar_t s_warn_late_precache; extern convar_t s_warn_late_precache;
extern convar_t snd_mute_losefocus;
void S_InitScaletable( void ); void S_InitScaletable( void );
wavdata_t *S_LoadSound( sfx_t *sfx ); wavdata_t *S_LoadSound( sfx_t *sfx );
@@ -292,7 +265,6 @@ void SND_ForceCloseMouth( int entnum );
// //
void S_StreamSoundTrack( void ); void S_StreamSoundTrack( void );
void S_StreamBackgroundTrack( void ); void S_StreamBackgroundTrack( void );
qboolean S_StreamGetCurrentState( char *currentTrack, char *loopTrack, int *position );
void S_PrintBackgroundTrackState( void ); void S_PrintBackgroundTrackState( void );
void S_FadeMusicVolume( float fadePercent ); void S_FadeMusicVolume( float fadePercent );

View File

@@ -250,7 +250,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
if( IsEndOfText( trim )) if( IsEndOfText( trim ))
{ {
Con_Reportf( "TextMessage: unexpected '}' found, line %d\n", lineNumber ); Con_Reportf( "%s: unexpected '}' found, line %d\n", __func__, lineNumber );
return; return;
} }
Q_strncpy( currentName, trim, sizeof( currentName )); Q_strncpy( currentName, trim, sizeof( currentName ));
@@ -263,7 +263,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
// save name on name heap // save name on name heap
if( lastNamePos + length > 32768 ) if( lastNamePos + length > 32768 )
{ {
Con_Reportf( "TextMessage: error while parsing!\n" ); Con_Reportf( "%s: error while parsing!\n", __func__ );
return; return;
} }
@@ -286,7 +286,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
} }
if( IsStartOfText( trim )) if( IsStartOfText( trim ))
{ {
Con_Reportf( "TextMessage: unexpected '{' found, line %d\n", lineNumber ); Con_Reportf( "%s: unexpected '{' found, line %d\n", __func__, lineNumber );
return; return;
} }
break; break;
@@ -302,7 +302,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
} }
} }
Con_Reportf( "TextMessage: parsed %d text messages\n", messageCount ); Con_Reportf( "%s: parsed %d text messages\n", __func__, messageCount );
nameHeapSize = lastNamePos; nameHeapSize = lastNamePos;
textHeapSize = 0; textHeapSize = 0;
@@ -347,7 +347,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
} }
if(( pCurrentText - (char *)clgame.titles ) != ( textHeapSize + nameHeapSize + messageSize )) if(( pCurrentText - (char *)clgame.titles ) != ( textHeapSize + nameHeapSize + messageSize ))
Con_DPrintf( S_ERROR "TextMessage: overflow text message buffer!\n" ); Con_DPrintf( S_ERROR "%s: overflow text message buffer!\n", __func__ );
clgame.numTitles = messageCount; clgame.numTitles = messageCount;
} }

View File

@@ -23,55 +23,182 @@ GNU General Public License for more details.
#include "input.h" #include "input.h"
#include "platform/platform.h" #include "platform/platform.h"
CVAR_DEFINE_AUTO( vgui_utf8, "0", FCVAR_ARCHIVE, "enable utf-8 support for vgui text" ); #define VGUI_MAX_TEXTURES 1024
static void GAME_EXPORT *VGUI_EngineMalloc( size_t size ); typedef struct vgui_static_s
static void GAME_EXPORT VGUI_GetMousePos( int *, int * );
static void GAME_EXPORT VGUI_CursorSelect( VGUI_DefaultCursor );
static byte GAME_EXPORT VGUI_GetColor( int, int );
static int GAME_EXPORT VGUI_UtfProcessChar( int in );
static qboolean GAME_EXPORT VGUI_IsInGame( void );
static struct
{ {
qboolean initialized; qboolean initialized;
vguiapi_t dllFuncs;
VGUI_DefaultCursor cursor; VGUI_DefaultCursor cursor;
vguiapi_t dllFuncs;
int textures[VGUI_MAX_TEXTURES];
int texture_id;
int bound_texture;
byte color[4];
qboolean enable_texture;
HINSTANCE hInstance; HINSTANCE hInstance;
enum VGUI_KeyCode virtualKeyTrans[256]; enum VGUI_KeyCode virtualKeyTrans[256];
} vgui = } vgui_static_t;
{
false, static vgui_static_t vgui = {
{ false, -1
false, // Not initialized yet
NULL, // VGUI_DrawInit,
NULL, // VGUI_DrawShutdown,
NULL, // VGUI_SetupDrawingText,
NULL, // VGUI_SetupDrawingRect,
NULL, // VGUI_SetupDrawingImage,
NULL, // VGUI_BindTexture,
NULL, // VGUI_EnableTexture,
NULL, // VGUI_CreateTexture,
NULL, // VGUI_UploadTexture,
NULL, // VGUI_UploadTextureBlock,
NULL, // VGUI_DrawQuad,
NULL, // VGUI_GetTextureSizes,
NULL, // VGUI_GenerateTexture,
VGUI_EngineMalloc,
VGUI_CursorSelect,
VGUI_GetColor,
VGUI_IsInGame,
Key_EnableTextInput,
VGUI_GetMousePos,
VGUI_UtfProcessChar,
Platform_GetClipboardText,
Platform_SetClipboardText,
Platform_GetKeyModifiers,
},
-1
}; };
static CVAR_DEFINE_AUTO( vgui_utf8, "0", FCVAR_ARCHIVE, "enable utf-8 support for vgui text" );
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 )
{
int i;
for( i = 1; i < vgui.texture_id; i++ )
ref.dllFuncs.GL_FreeTexture( vgui.textures[i] );
}
static int GAME_EXPORT VGUI_GenerateTexture( void )
{
if( ++vgui.texture_id >= VGUI_MAX_TEXTURES )
Host_Error( "%s: VGUI_MAX_TEXTURES limit exceeded\n", __func__ );
return vgui.texture_id;
}
static void GAME_EXPORT VGUI_UploadTexture( int id, const char *buffer, int width, int height )
{
rgbdata_t r_image = { 0 };
char texName[32];
if( id <= 0 || id >= VGUI_MAX_TEXTURES )
{
Con_DPrintf( S_ERROR "%s: bad texture %i. Ignored\n", __func__, id );
return;
}
Q_snprintf( texName, sizeof( texName ), "*vgui%i", id );
r_image.width = width;
r_image.height = height;
r_image.type = PF_RGBA_32;
r_image.size = width * height * 4;
r_image.flags = IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA;
r_image.buffer = (byte*)buffer;
vgui.textures[id] = GL_LoadTextureInternal( texName, &r_image, TF_IMAGE );
}
static void GAME_EXPORT VGUI_CreateTexture( int id, int width, int height )
{
rgbdata_t r_image = { 0 };
char texName[32];
if( id <= 0 || id >= VGUI_MAX_TEXTURES )
{
Con_DPrintf( S_ERROR "%s: bad texture %i. Ignored\n", __func__, id );
return;
}
Q_snprintf( texName, sizeof( texName ), "*vgui%i", id );
r_image.width = width;
r_image.height = height;
r_image.type = PF_RGBA_32;
r_image.size = width * height * 4;
r_image.flags = IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA;
r_image.buffer = NULL;
vgui.textures[id] = GL_LoadTextureInternal( texName, &r_image, TF_IMAGE );
vgui.bound_texture = id;
}
static void GAME_EXPORT VGUI_UploadTextureBlock( int id, int drawX, int drawY, const byte *rgba, int blockWidth, int blockHeight )
{
if( id <= 0 || id >= VGUI_MAX_TEXTURES || vgui.textures[id] == 0 )
{
Con_DPrintf( S_ERROR "%s: bad texture %i. Ignored\n", __func__, id );
return;
}
ref.dllFuncs.VGUI_UploadTextureBlock( drawX, drawY, rgba, blockWidth, blockHeight );
vgui.bound_texture = id;
}
static void GAME_EXPORT VGUI_BindTexture( int id )
{
if( id <= 0 || id >= VGUI_MAX_TEXTURES || !vgui.textures[id] )
id = 1; // NOTE: same as bogus index 2700 in GoldSrc
ref.dllFuncs.GL_Bind( XASH_TEXTURE0, vgui.textures[id] );
vgui.bound_texture = id;
}
static void GAME_EXPORT VGUI_GetTextureSizes( int *w, int *h )
{
int texnum;
if( vgui.bound_texture )
texnum = vgui.textures[vgui.bound_texture];
else
texnum = R_GetBuiltinTexture( REF_DEFAULT_TEXTURE );
R_GetTextureParms( w, h, texnum );
}
static void GAME_EXPORT VGUI_SetupDrawingRect( int *pColor )
{
ref.dllFuncs.VGUI_SetupDrawing( true );
Vector4Set( vgui.color, pColor[0], pColor[1], pColor[2], 255 - pColor[3] );
}
static void GAME_EXPORT VGUI_SetupDrawingText( int *pColor )
{
ref.dllFuncs.VGUI_SetupDrawing( false );
Vector4Set( vgui.color, pColor[0], pColor[1], pColor[2], 255 - pColor[3] );
}
static void GAME_EXPORT VGUI_DrawQuad( const vpoint_t *ul, const vpoint_t *lr )
{
float x, y, w, h;
if( !ul || !lr )
return;
x = ul->point[0];
y = ul->point[1];
w = lr->point[0] - x;
h = lr->point[1] - y;
SPR_AdjustSize( &x, &y, &w, &h );
if( vgui.enable_texture )
{
float s1, s2, t1, t2;
s1 = ul->coord[0];
t1 = ul->coord[1];
s2 = lr->coord[0];
t2 = lr->coord[1];
ref.dllFuncs.Color4ub( vgui.color[0], vgui.color[1], vgui.color[2], vgui.color[3] );
ref.dllFuncs.R_DrawStretchPic( x, y, w, h, s1, t1, s2, t2, vgui.textures[vgui.bound_texture] );
}
else
{
ref.dllFuncs.FillRGBABlend( x, y, w, h, vgui.color[0], vgui.color[1], vgui.color[2], vgui.color[3] );
}
}
static void GAME_EXPORT VGUI_EnableTexture( qboolean enable )
{
vgui.enable_texture = enable;
}
static void GAME_EXPORT *VGUI_EngineMalloc( size_t size ) static void GAME_EXPORT *VGUI_EngineMalloc( size_t size )
{ {
@@ -117,33 +244,46 @@ qboolean VGui_IsActive( void )
return vgui.initialized; return vgui.initialized;
} }
static void VGui_FillAPIFromRef( vguiapi_t *to, const ref_interface_t *from )
{
to->DrawInit = from->VGUI_DrawInit;
to->DrawShutdown = from->VGUI_DrawShutdown;
to->SetupDrawingText = from->VGUI_SetupDrawingText;
to->SetupDrawingRect = from->VGUI_SetupDrawingRect;
to->SetupDrawingImage = from->VGUI_SetupDrawingImage;
to->BindTexture = from->VGUI_BindTexture;
to->EnableTexture = from->VGUI_EnableTexture;
to->CreateTexture = from->VGUI_CreateTexture;
to->UploadTexture = from->VGUI_UploadTexture;
to->UploadTextureBlock = from->VGUI_UploadTextureBlock;
to->DrawQuad = from->VGUI_DrawQuad;
to->GetTextureSizes = from->VGUI_GetTextureSizes;
to->GenerateTexture = from->VGUI_GenerateTexture;
}
void VGui_RegisterCvars( void ) void VGui_RegisterCvars( void )
{ {
Cvar_RegisterVariable( &vgui_utf8 ); Cvar_RegisterVariable( &vgui_utf8 );
} }
static const vguiapi_t gEngfuncs =
{
false, // Not initialized yet
VGUI_DrawInit, // VGUI_DrawInit,
VGUI_DrawShutdown, // VGUI_DrawShutdown,
VGUI_SetupDrawingText, // VGUI_SetupDrawingText,
VGUI_SetupDrawingRect, // VGUI_SetupDrawingRect,
VGUI_SetupDrawingText, // VGUI_SetupDrawingImage, (same as text)
VGUI_BindTexture, // VGUI_BindTexture,
VGUI_EnableTexture, // VGUI_EnableTexture,
VGUI_CreateTexture, // VGUI_CreateTexture,
VGUI_UploadTexture, // VGUI_UploadTexture,
VGUI_UploadTextureBlock, // VGUI_UploadTextureBlock,
VGUI_DrawQuad, // VGUI_DrawQuad,
VGUI_GetTextureSizes, // VGUI_GetTextureSizes,
VGUI_GenerateTexture, // VGUI_GenerateTexture,
VGUI_EngineMalloc,
VGUI_CursorSelect,
VGUI_GetColor,
VGUI_IsInGame,
Key_EnableTextInput,
VGUI_GetMousePos,
VGUI_UtfProcessChar,
Platform_GetClipboardText,
Platform_SetClipboardText,
Platform_GetKeyModifiers,
};
qboolean VGui_LoadProgs( HINSTANCE hInstance ) qboolean VGui_LoadProgs( HINSTANCE hInstance )
{ {
void (*F)( vguiapi_t* ); void (*F)( vguiapi_t* );
qboolean client = hInstance != NULL; qboolean client = hInstance != NULL;
vgui.dllFuncs = gEngfuncs;
// not loading interface from client.dll, load vgui_support.dll instead // not loading interface from client.dll, load vgui_support.dll instead
if( !client ) if( !client )
{ {
@@ -167,7 +307,7 @@ qboolean VGui_LoadProgs( HINSTANCE hInstance )
{ {
if( FS_FileExists( vguiloader, false )) if( FS_FileExists( vguiloader, false ))
Con_Reportf( S_ERROR "Failed to load vgui_support library: %s\n", COM_GetLibraryError() ); Con_Reportf( S_ERROR "Failed to load vgui_support library: %s\n", COM_GetLibraryError() );
else Con_Reportf( "vgui_support: not found\n" ); else Con_Reportf( "%s: not found\n", __func__ );
return false; return false;
} }
@@ -178,16 +318,15 @@ qboolean VGui_LoadProgs( HINSTANCE hInstance )
if( F ) if( F )
{ {
VGui_FillAPIFromRef( &vgui.dllFuncs, &ref.dllFuncs );
F( &vgui.dllFuncs ); F( &vgui.dllFuncs );
vgui.initialized = vgui.dllFuncs.initialized = true; vgui.initialized = vgui.dllFuncs.initialized = true;
Con_Reportf( "vgui_support: initialized legacy API in %s module\n", client ? "client" : "support" ); Con_Reportf( "%s: initialized legacy API in %s module\n", __func__, client ? "client" : "support" );
return true; return true;
} }
Con_Reportf( S_ERROR "Failed to find VGUI support API entry point in %s module\n", client ? "client" : "support" ); Con_Reportf( S_ERROR "%s: Failed to find VGUI support API entry point in %s module\n", __func__, client ? "client" : "support" );
return false; return false;
} }
@@ -233,8 +372,9 @@ void VGui_Shutdown( void )
if( vgui.hInstance ) if( vgui.hInstance )
COM_FreeLibrary( vgui.hInstance ); COM_FreeLibrary( vgui.hInstance );
// drop pointers to now unloaded vgui_support
vgui.dllFuncs = gEngfuncs;
vgui.hInstance = NULL; vgui.hInstance = NULL;
vgui.initialized = false;
} }

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_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_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_width, "width", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen width" );
CVAR_DEFINE( window_height, "height", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen height" ); 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" ); CVAR_DEFINE( window_xpos, "_window_xpos", "-1", FCVAR_RENDERINFO, "window position by horizontal" );
@@ -175,7 +175,7 @@ static void VID_Mode_f( void )
vidmode = R_GetVideoMode( Q_atoi( Cmd_Argv( 1 )) ); vidmode = R_GetVideoMode( Q_atoi( Cmd_Argv( 1 )) );
if( !vidmode ) if( !vidmode )
{ {
Con_Print( S_ERROR "unable to set mode, backend returned null" ); Con_Printf( S_ERROR "unable to set mode, backend returned null" );
return; return;
} }

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 ); 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;
/* /*
=============================================================================== ===============================================================================
@@ -397,7 +402,7 @@ void Voice_RecordStart( void )
if( voice.input_file ) 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.input_file_pos = 0;
voice.start_time = Sys_DoubleTime(); voice.start_time = Sys_DoubleTime();
@@ -591,10 +596,17 @@ void Voice_Idle( double frametime )
{ {
int i; int i;
if( FBitSet( voice_enable.flags, FCVAR_CHANGED ) && !voice_enable.value ) if( FBitSet( voice_enable.flags, FCVAR_CHANGED ))
{ {
Voice_Shutdown(); ClearBits( voice_enable.flags, FCVAR_CHANGED );
return;
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 // update local player status first
@@ -613,6 +625,19 @@ Initialize the voice subsystem
*/ */
qboolean Voice_Init( const char *pszCodecName, int quality, qboolean preinit ) qboolean Voice_Init( const char *pszCodecName, int quality, qboolean preinit )
{ {
if( Q_strcmp( pszCodecName, VOICE_OPUS_CUSTOM_CODEC ))
{
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 ) if( !voice_enable.value )
return false; return false;
@@ -620,13 +645,6 @@ qboolean Voice_Init( const char *pszCodecName, int quality, qboolean preinit )
if( Q_strcmp( pszCodecName, voice.codec ) || voice.quality != quality ) if( Q_strcmp( pszCodecName, voice.codec ) || voice.quality != quality )
{ {
Voice_Shutdown(); 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; voice.autogain.block_size = 128;
if( !Voice_InitCustomMode( )) if( !Voice_InitCustomMode( ))

View File

@@ -31,7 +31,7 @@ typedef struct OpusCustomMode OpusCustomMode;
#define VOICE_PCM_CHANNELS 1 // always mono #define VOICE_PCM_CHANNELS 1 // always mono
// never change these parameters when using opuscustom // never change these parameters when using opuscustom
#define VOICE_OPUS_CUSTOM_SAMPLERATE SOUND_44k #define VOICE_OPUS_CUSTOM_SAMPLERATE 44100
// must follow opus custom requirements // must follow opus custom requirements
// also be divisible with MAX_RAW_SAMPLES // also be divisible with MAX_RAW_SAMPLES
#define VOICE_OPUS_CUSTOM_FRAME_SIZE 1024 #define VOICE_OPUS_CUSTOM_FRAME_SIZE 1024

View File

@@ -16,21 +16,20 @@ GNU General Public License for more details.
#ifndef VOX_H #ifndef VOX_H
#define VOX_H #define VOX_H
#define CVOXWORDMAX 64 #define CVOXWORDMAX 64
#define SENTENCE_INDEX -99999 // unique sentence index
#define SENTENCE_INDEX -99999 // unique sentence index
typedef struct voxword_s typedef struct voxword_s
{ {
int volume; // increase percent, ie: 125 = 125% increase int volume; // increase percent, ie: 125 = 125% increase
int pitch; // pitch shift up percent int pitch; // pitch shift up percent
int start; // offset start of wave percent int start; // offset start of wave percent
int end; // offset end of wave percent int end; // offset end of wave percent
int cbtrim; // end of wave after being trimmed to 'end' int cbtrim; // end of wave after being trimmed to 'end'
int fKeepCached; // 1 if this word was already in cache before sentence referenced it int fKeepCached; // 1 if this word was already in cache before sentence referenced it
int samplefrac; // if pitch shifting, this is position into wav * 256 int samplefrac; // if pitch shifting, this is position into wav * 256
int timecompress; // % of wave to skip during playback (causes no pitch shift) int timecompress; // % of wave to skip during playback (causes no pitch shift)
sfx_t *sfx; // name and cache pointer sfx_t *sfx; // name and cache pointer
} voxword_t; } voxword_t;
struct channel_s; struct channel_s;

View File

@@ -19,13 +19,15 @@ GNU General Public License for more details.
#define HASH_SIZE 128 // 128 * 4 * 4 == 2048 bytes #define HASH_SIZE 128 // 128 * 4 * 4 == 2048 bytes
typedef struct base_command_hashmap_s typedef struct base_command_hashmap_s base_command_hashmap_t;
struct base_command_hashmap_s
{ {
base_command_t *basecmd; // base command: cvar, alias or command base_command_t *basecmd; // base command: cvar, alias or command
const char *name; // key for searching base_command_hashmap_t *next;
base_command_type_e type; // type for faster searching base_command_type_e type; // type for faster searching
struct base_command_hashmap_s *next; char name[1]; // key for searching
} base_command_hashmap_t; };
static base_command_hashmap_t *hashed_cmds[HASH_SIZE]; static base_command_hashmap_t *hashed_cmds[HASH_SIZE];
@@ -124,11 +126,12 @@ void BaseCmd_Insert( base_command_type_e type, base_command_t *basecmd, const ch
{ {
base_command_hashmap_t *elem, *cur, *find; base_command_hashmap_t *elem, *cur, *find;
uint hash = BaseCmd_HashKey( name ); uint hash = BaseCmd_HashKey( name );
size_t len = Q_strlen( name );
elem = Z_Malloc( sizeof( base_command_hashmap_t ) ); elem = Z_Malloc( sizeof( base_command_hashmap_t ) + len );
elem->basecmd = basecmd; elem->basecmd = basecmd;
elem->type = type; elem->type = type;
elem->name = name; Q_strncpy( elem->name, name, len + 1 );
// link the variable in alphanumerical order // link the variable in alphanumerical order
for( cur = NULL, find = hashed_cmds[hash]; for( cur = NULL, find = hashed_cmds[hash];
@@ -159,7 +162,7 @@ void BaseCmd_Remove( base_command_type_e type, const char *name )
if( !i ) if( !i )
{ {
Con_Reportf( S_ERROR "Couldn't find %s in buckets\n", name ); Con_Reportf( S_ERROR "%s: Couldn't find %s in buckets\n", __func__, name );
return; return;
} }

View File

@@ -31,8 +31,6 @@ typedef enum base_command_type
typedef void base_command_t; typedef void base_command_t;
void BaseCmd_Init( void ); void BaseCmd_Init( void );
base_command_t *BaseCmd_Find( base_command_type_e type, const char *name ); base_command_t *BaseCmd_Find( base_command_type_e type, const char *name );
void BaseCmd_FindAll( const char *name, void BaseCmd_FindAll( const char *name,

View File

@@ -86,7 +86,7 @@ static void *Cbuf_GetSpace( cmdbuf_t *buf, int length )
if(( buf->cursize + length ) > buf->maxsize ) if(( buf->cursize + length ) > buf->maxsize )
{ {
buf->cursize = 0; buf->cursize = 0;
Host_Error( "Cbuf_GetSpace: overflow\n" ); Host_Error( "%s: overflow\n", __func__ );
} }
data = buf->data + buf->cursize; data = buf->data + buf->cursize;
@@ -156,7 +156,7 @@ static void Cbuf_InsertTextToBuffer( cmdbuf_t *buf, const char *text )
if(( buf->cursize + l ) >= buf->maxsize ) if(( buf->cursize + l ) >= buf->maxsize )
{ {
Con_Reportf( S_WARN "Cbuf_InsertText: overflow\n" ); Con_Reportf( S_WARN "%s: overflow\n", __func__ );
} }
else else
{ {
@@ -224,7 +224,7 @@ static void Cbuf_ExecuteCommandsFromBuffer( cmdbuf_t *buf, qboolean isPrivileged
if( i >= ( MAX_CMD_LINE - 1 )) if( i >= ( MAX_CMD_LINE - 1 ))
{ {
Con_DPrintf( S_ERROR "Cbuf_Execute: command string owerflow\n" ); Con_DPrintf( S_ERROR "%s: command string owerflow\n", __func__ );
line[0] = 0; line[0] = 0;
} }
else else
@@ -387,7 +387,7 @@ static void Cmd_Echo_f( void )
int i; int i;
for( i = 1; i < Cmd_Argc(); i++ ) for( i = 1; i < Cmd_Argc(); i++ )
Con_Printf( "%s", Cmd_Argv( i )); Con_Printf( "%s ", Cmd_Argv( i ));
Con_Printf( "\n" ); Con_Printf( "\n" );
} }
@@ -640,7 +640,7 @@ void Cmd_TokenizeString( const char *text )
while( 1 ) while( 1 )
{ {
// skip whitespace up to a /n // skip whitespace up to a /n
while( *text && *text <= ' ' && *text != '\r' && *text != '\n' ) while( *text && ((byte)*text ) <= ' ' && *text != '\r' && *text != '\n' )
text++; text++;
if( *text == '\n' || *text == '\r' ) if( *text == '\n' || *text == '\r' )
@@ -682,7 +682,7 @@ static int Cmd_AddCommandEx( const char *funcname, const char *cmd_name, xcomman
if( !COM_CheckString( cmd_name )) if( !COM_CheckString( cmd_name ))
{ {
Con_Reportf( S_ERROR "%s: NULL name\n", funcname ); Con_Reportf( S_ERROR "%s: NULL name\n", funcname );
return 0; return 0;
} }
@@ -728,7 +728,7 @@ Cmd_AddCommand
*/ */
void Cmd_AddCommand( const char *cmd_name, xcommand_t function, const char *cmd_desc ) void Cmd_AddCommand( const char *cmd_name, xcommand_t function, const char *cmd_desc )
{ {
Cmd_AddCommandEx( __FUNCTION__, cmd_name, function, cmd_desc, 0 ); Cmd_AddCommandEx( __func__, cmd_name, function, cmd_desc, 0 );
} }
@@ -739,7 +739,7 @@ Cmd_AddRestrictedCommand
*/ */
void Cmd_AddRestrictedCommand( const char *cmd_name, xcommand_t function, const char *cmd_desc ) void Cmd_AddRestrictedCommand( const char *cmd_name, xcommand_t function, const char *cmd_desc )
{ {
Cmd_AddCommandEx( __FUNCTION__, cmd_name, function, cmd_desc, CMD_PRIVILEGED ); Cmd_AddCommandEx( __func__, cmd_name, function, cmd_desc, CMD_PRIVILEGED );
} }
/* /*
@@ -749,7 +749,7 @@ Cmd_AddServerCommand
*/ */
void GAME_EXPORT Cmd_AddServerCommand( const char *cmd_name, xcommand_t function ) void GAME_EXPORT Cmd_AddServerCommand( const char *cmd_name, xcommand_t function )
{ {
Cmd_AddCommandEx( __FUNCTION__, cmd_name, function, "server command", CMD_SERVERDLL ); Cmd_AddCommandEx( __func__, cmd_name, function, "server command", CMD_SERVERDLL );
} }
/* /*
@@ -767,7 +767,7 @@ int GAME_EXPORT Cmd_AddClientCommand( const char *cmd_name, xcommand_t function
flags |= CMD_PRIVILEGED; flags |= CMD_PRIVILEGED;
} }
return Cmd_AddCommandEx( __FUNCTION__, cmd_name, function, "client command", flags ); return Cmd_AddCommandEx( __func__, cmd_name, function, "client command", flags );
} }
/* /*
@@ -777,7 +777,7 @@ Cmd_AddGameUICommand
*/ */
int GAME_EXPORT Cmd_AddGameUICommand( const char *cmd_name, xcommand_t function ) int GAME_EXPORT Cmd_AddGameUICommand( const char *cmd_name, xcommand_t function )
{ {
return Cmd_AddCommandEx( __FUNCTION__, cmd_name, function, "gameui command", CMD_GAMEUIDLL ); return Cmd_AddCommandEx( __func__, cmd_name, function, "gameui command", CMD_GAMEUIDLL );
} }
/* /*
@@ -787,7 +787,7 @@ Cmd_AddRefCommand
*/ */
int Cmd_AddRefCommand( const char *cmd_name, xcommand_t function, const char *description ) int Cmd_AddRefCommand( const char *cmd_name, xcommand_t function, const char *description )
{ {
return Cmd_AddCommandEx( __FUNCTION__, cmd_name, function, description, CMD_REFDLL ); return Cmd_AddCommandEx( __func__, cmd_name, function, description, CMD_REFDLL );
} }
/* /*
@@ -949,7 +949,7 @@ static void Cmd_Else_f( void )
static qboolean Cmd_ShouldAllowCommand( cmd_t *cmd, qboolean isPrivileged ) static qboolean Cmd_ShouldAllowCommand( cmd_t *cmd, qboolean isPrivileged )
{ {
const char *prefixes[] = { "cl_", "gl_", "r_", "m_", "hud_", "joy_" }; const char *prefixes[] = { "cl_", "gl_", "r_", "m_", "hud_", "joy_", "con_", "scr_" };
int i; int i;
// always allow local commands // always allow local commands
@@ -1015,7 +1015,7 @@ static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPr
*ptoken++ = *text++; *ptoken++ = *text++;
*ptoken = 0; *ptoken = 0;
len += Q_strncpy( pcmd, Cvar_VariableString( token ), MAX_CMD_LINE - len ); len += Q_strncpy( pcmd, Cvar_VariableString( token ), sizeof( token ) - len );
pcmd = command + len; pcmd = command + len;
if( !*text ) break; if( !*text ) break;

View File

@@ -39,9 +39,6 @@ GNU General Public License for more details.
// end game final default message // end game final default message
#define DEFAULT_ENDGAME_MESSAGE "The End" #define DEFAULT_ENDGAME_MESSAGE "The End"
// path to the hash-pak that contain custom player decals
#define CUSTOM_RES_PATH "custom.hpk"
// path to default playermodel in GoldSrc // path to default playermodel in GoldSrc
#define DEFAULT_PLAYER_PATH_HALFLIFE "models/player.mdl" #define DEFAULT_PLAYER_PATH_HALFLIFE "models/player.mdl"
@@ -55,14 +52,20 @@ GNU General Public License for more details.
#define DEFAULT_EXTERNAL_PALETTE "gfx/palette.pal" #define DEFAULT_EXTERNAL_PALETTE "gfx/palette.pal"
// path to folders where placed all sounds // path to sound files
#define DEFAULT_SOUNDPATH "sound/" #define DEFAULT_SOUNDPATH "sound/"
// path store saved games // path to saved games
#define DEFAULT_SAVE_DIRECTORY "save/" #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 // fallback to this skybox
#define DEFAULT_SKYBOX_PATH "gfx/env/desert" #define DEFAULT_SKYBOX_NAME "desert"
// playlist for startup videos // playlist for startup videos
#define DEFAULT_VIDEOLIST_PATH "media/StartupVids.txt" #define DEFAULT_VIDEOLIST_PATH "media/StartupVids.txt"
@@ -75,7 +78,7 @@ GNU General Public License for more details.
#define XASH_ENGINE_NAME "Xash3D FWGS" #define XASH_ENGINE_NAME "Xash3D FWGS"
#define XASH_DEDICATED_SERVER_NAME "XashDS" #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 #define XASH_COMPAT_VERSION "0.99" // version we are based on
#endif//COM_STRINGS_H #endif//COM_STRINGS_H

View File

@@ -25,16 +25,19 @@ GNU General Public License for more details.
static const char *file_exts[] = static const char *file_exts[] =
{ {
"cfg", // ban text files that don't make sense as resource
"lst", "cfg", "lst", "ini", "log",
"exe",
"vbs", // ban Windows code
"com", "exe", "vbs", "com", "bat",
"bat", "dll", "sys", "ps1",
"dll",
"ini", // ban common unix code
"log", // NOTE: in unix anything can be executed as long it has access flag
"sys", "so", "sh", "dylib",
// ban mobile archives
"apk", "ipa",
}; };
#ifdef _DEBUG #ifdef _DEBUG
@@ -900,7 +903,10 @@ qboolean COM_IsSafeFileToDownload( const char *filename )
if( !COM_CheckString( filename )) if( !COM_CheckString( filename ))
return false; return false;
if( !Q_strncmp( filename, "!MD5", 4 )) ext = COM_FileExtension( lwrfilename );
// only allow extensionless files that start with !MD5
if( !Q_strncmp( filename, "!MD5", 4 ) && ext[0] == 0 )
return true; return true;
Q_strnlwr( filename, lwrfilename, sizeof( lwrfilename )); Q_strnlwr( filename, lwrfilename, sizeof( lwrfilename ));
@@ -923,8 +929,6 @@ qboolean COM_IsSafeFileToDownload( const char *filename )
if( Q_strlen( first ) != 4 ) if( Q_strlen( first ) != 4 )
return false; return false;
ext = COM_FileExtension( lwrfilename );
for( i = 0; i < ARRAYSIZE( file_exts ); i++ ) for( i = 0; i < ARRAYSIZE( file_exts ); i++ )
{ {
if( !Q_stricmp( ext, file_exts[i] )) if( !Q_stricmp( ext, file_exts[i] ))
@@ -967,7 +971,7 @@ used by CS:CZ
*/ */
void *GAME_EXPORT pfnSequenceGet( const char *fileName, const char *entryName ) void *GAME_EXPORT pfnSequenceGet( const char *fileName, const char *entryName )
{ {
Msg( "Sequence_Get: file %s, entry %s\n", fileName, entryName ); Msg( "%s: file %s, entry %s\n", __func__, fileName, entryName );
return NULL; return NULL;
} }
@@ -981,7 +985,7 @@ used by CS:CZ
*/ */
void *GAME_EXPORT pfnSequencePickSentence( const char *groupName, int pickMethod, int *picked ) void *GAME_EXPORT pfnSequencePickSentence( const char *groupName, int pickMethod, int *picked )
{ {
Msg( "Sequence_PickSentence: group %s, pickMethod %i\n", groupName, pickMethod ); Msg( "%s: group %s, pickMethod %i\n", __func__, groupName, pickMethod );
return NULL; return NULL;

View File

@@ -112,6 +112,9 @@ typedef enum
#include "con_nprint.h" #include "con_nprint.h"
#include "crclib.h" #include "crclib.h"
#include "ref_api.h" #include "ref_api.h"
#define FSCALLBACK_OVERRIDE_OPEN
#define FSCALLBACK_OVERRIDE_LOADFILE
#define FSCALLBACK_OVERRIDE_MALLOC_LIKE
#include "fscallback.h" #include "fscallback.h"
// PERFORMANCE INFO // PERFORMANCE INFO
@@ -157,13 +160,16 @@ extern convar_t gl_vsync;
extern convar_t scr_loading; extern convar_t scr_loading;
extern convar_t scr_download; extern convar_t scr_download;
extern convar_t cmd_scripting; extern convar_t cmd_scripting;
extern convar_t cl_allow_levelshots; extern convar_t host_allow_materials;
extern convar_t host_developer; extern convar_t host_developer;
extern convar_t host_limitlocal; extern convar_t host_limitlocal;
extern convar_t host_maxfps; extern convar_t host_maxfps;
extern convar_t sys_timescale; extern convar_t sys_timescale;
extern convar_t cl_filterstuffcmd; extern convar_t cl_filterstuffcmd;
extern convar_t rcon_password; extern convar_t rcon_password;
extern convar_t hpk_custom_file;
#define Mod_AllowMaterials() ( host_allow_materials.value != 0.0f && !FBitSet( host.features, ENGINE_DISABLE_HDTEXTURES ))
/* /*
============================================================== ==============================================================
@@ -180,15 +186,6 @@ GAMEINFO stuff
internal shared gameinfo structure (readonly for engine parts) internal shared gameinfo structure (readonly for engine parts)
======================================================================== ========================================================================
*/ */
typedef struct sysinfo_s
{
string exeName; // exe.filename
string rcName; // .rc script name
string basedirName; // name of base directory
string gamedll;
string clientlib;
} sysinfo_t;
typedef enum typedef enum
{ {
HOST_INIT = 0, // initalize operations HOST_INIT = 0, // initalize operations
@@ -275,94 +272,89 @@ typedef enum bugcomp_e
{ {
// reverts fix for pfnPEntityOfEntIndex for bug compatibility with GoldSrc // reverts fix for pfnPEntityOfEntIndex for bug compatibility with GoldSrc
BUGCOMP_PENTITYOFENTINDEX_FLAG = BIT( 0 ), BUGCOMP_PENTITYOFENTINDEX_FLAG = BIT( 0 ),
// 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; } bugcomp_t;
typedef struct host_parm_s typedef struct host_parm_s
{ {
HINSTANCE hInst; // ==== shared through RefAPI's ref_host_t
HANDLE hMutex; double realtime; // host.curtime
double frametime; // time between engine frames
uint features; // custom features that enables by mod-maker request
// ==== shared through RefAPI's ref_host_t
host_status_t status; // global host state host_status_t status; // global host state
game_status_t game; // game manager game_status_t game; // game manager
uint type; // running at uint type; // running at
jmp_buf abortframe; // abort current frame poolhandle_t mempool; // static mempool for misc allocations
dword errorframe; // to prevent multiple host error poolhandle_t imagepool; // imagelib mempool
poolhandle_t mempool; // static mempool for misc allocations poolhandle_t soundpool; // soundlib mempool
string finalmsg; // server shutdown final message string finalmsg; // server shutdown final message
string downloadfile; // filename to be downloading string downloadfile; // filename to be downloading
int downloadcount; // how many files remain to downloading int downloadcount; // how many files remain to downloading
char deferred_cmd[128]; // deferred commands char deferred_cmd[128];// deferred commands
host_redirect_t rd; // remote console
host_redirect_t rd; // remote console
void *hWnd; // main window
// command line parms // command line parms
int argc; char **argv;
char **argv; int argc;
// ==== shared through RefAPI's ref_host_t uint framecount; // global framecount
double realtime; // host.curtime uint errorframe; // to prevent multiple host error
double frametime; // time between engine frames uint32_t bugcomp; // bug compatibility level, for very "special" games
uint features; // custom features that enables by mod-maker request double realframetime; // for some system events, e.g. console animations
// ==== shared through RefAPI's ref_host_t double starttime; // measure time to first frame
double pureframetime; // count of sleeps can be inserted between frames
double force_draw_version_time;
double realframetime; // for some system events, e.g. console animations char draw_decals[MAX_DECALS][MAX_QPATH]; // list of unique decal indexes
vec3_t player_mins[MAX_MAP_HULLS]; // 4 hulls allowed
vec3_t player_maxs[MAX_MAP_HULLS]; // 4 hulls allowed
uint framecount; // global framecount // 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;
// list of unique decal indexes qboolean allow_console; // allow console in dev-mode or multiplayer game
char draw_decals[MAX_DECALS][MAX_QPATH]; qboolean allow_console_init; // initial value to allow the console
qboolean key_overstrike; // key overstrike mode
vec3_t player_mins[MAX_MAP_HULLS]; // 4 hulls allowed qboolean stuffcmds_pending; // should execute stuff commands
vec3_t player_maxs[MAX_MAP_HULLS]; // 4 hulls allowed qboolean allow_cheats; // this host will allow cheating
qboolean change_game; // initialize when game is changed
void* hWnd; // main window qboolean mouse_visible; // vgui override cursor control (never change outside Platform_SetCursorType!)
qboolean allow_console; // allow console in dev-mode or multiplayer game qboolean shutdown_issued; // engine is shutting down
qboolean allow_console_init; // initial value to allow the console qboolean apply_game_config; // when true apply only to game cvars and ignore all other commands
qboolean key_overstrike; // key overstrike mode qboolean apply_opengl_config; // when true apply only to opengl cvars and ignore all other commands
qboolean stuffcmds_pending; // should execute stuff commands qboolean config_executed; // a bit who indicated was config.cfg already executed e.g. from valve.rc
qboolean allow_cheats; // this host will allow cheating qboolean crashed; // set to true if crashed
qboolean con_showalways; // show console always (developer and dedicated) #if XASH_DLL_LOADER
qboolean change_game; // initialize when game is changed qboolean enabledll;
qboolean mouse_visible; // vgui override cursor control (never change outside Platform_SetCursorType!) #endif
qboolean shutdown_issued; // engine is shutting down qboolean textmode;
double force_draw_version_time;
qboolean apply_game_config; // when true apply only to game cvars and ignore all other commands
qboolean apply_opengl_config;// when true apply only to opengl cvars and ignore all other commands
qboolean config_executed; // a bit who indicated was config.cfg already executed e.g. from valve.rc
qboolean crashed; // set to true if crashed
qboolean daemonized;
qboolean enabledll;
qboolean textmode;
// some settings were changed and needs to global update // some settings were changed and needs to global update
qboolean userinfo_changed; qboolean userinfo_changed;
qboolean movevars_changed; qboolean movevars_changed;
qboolean renderinfo_changed; qboolean renderinfo_changed;
char rootdir[MAX_OSPATH]; // member root directory
char rodir[MAX_OSPATH]; // readonly root
char gamefolder[MAX_QPATH]; // it's a default gamefolder
poolhandle_t imagepool; // imagelib mempool
poolhandle_t soundpool; // soundlib mempool
// for IN_MouseMove() easy access // for IN_MouseMove() easy access
int window_center_x; int window_center_x;
int window_center_y; int window_center_y;
string gamedll;
struct decallist_s *decalList; // used for keep decals, when renderer is restarted or changed string clientlib;
int numdecals;
// bug compatibility level, for very "special" games
uint32_t bugcomp;
// measure time to first frame
double starttime;
// count of sleeps can be inserted between frames
double pureframetime;
} host_parm_t; } host_parm_t;
extern host_parm_t host; extern host_parm_t host;
extern sysinfo_t SI;
#define CMD_SERVERDLL BIT( 0 ) // added by server.dll #define CMD_SERVERDLL BIT( 0 ) // added by server.dll
#define CMD_CLIENTDLL BIT( 1 ) // added by client.dll #define CMD_CLIENTDLL BIT( 1 ) // added by client.dll
@@ -373,13 +365,49 @@ extern sysinfo_t SI;
typedef void (*xcommand_t)( void ); 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 // filesystem_engine.c
// //
qboolean FS_LoadProgs( void ); void FS_Init( const char *basedir );
void FS_Init( void );
void FS_Shutdown( void ); void FS_Shutdown( void );
void *FS_GetNativeObject( const char *obj ); 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 // cmd.c
@@ -412,30 +440,6 @@ void Cmd_ExecuteString( const char *text );
void Cmd_ForwardToServer( void ); void Cmd_ForwardToServer( void );
void Cmd_Escape( char *newCommand, const char *oldCommand, int len ); 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 // imagelib
@@ -446,10 +450,10 @@ void Image_Setup( void );
void Image_Init( void ); void Image_Init( void );
void Image_Shutdown( void ); void Image_Shutdown( void );
void Image_AddCmdFlags( uint flags ); 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 ); 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 extern const bpc_desc_t PFDesc[]; // image get pixelformat
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 );
void Image_PaletteHueReplace( byte *palSrc, int newHue, int start, int end, int pal_size ); void Image_PaletteHueReplace( byte *palSrc, int newHue, int start, int end, int pal_size );
@@ -475,14 +479,6 @@ typedef enum
WF_TOTALCOUNT, // must be last WF_TOTALCOUNT, // must be last
} sndformat_t; } sndformat_t;
// soundlib global settings
typedef enum
{
SL_USE_LERPING = BIT(0), // lerping sounds during resample
SL_KEEP_8BIT = BIT(1), // don't expand 8bit sounds automatically up to 16 bit
SL_ALLOW_OVERWRITE = BIT(2), // allow to overwrite stored sounds
} slFlags_t;
// wavdata output flags // wavdata output flags
typedef enum typedef enum
{ {
@@ -491,21 +487,20 @@ typedef enum
SOUND_STREAM = BIT( 1 ), // this is a streaminfo, not a real sound SOUND_STREAM = BIT( 1 ), // this is a streaminfo, not a real sound
// Sound_Process manipulation flags // Sound_Process manipulation flags
SOUND_RESAMPLE = BIT(12), // resample sound to specified rate SOUND_RESAMPLE = BIT( 12 ), // resample sound to specified rate
SOUND_CONVERT16BIT = BIT(13), // change sound resolution from 8 bit to 16
} sndFlags_t; } sndFlags_t;
typedef struct typedef struct
{ {
word rate; // num samples per second (e.g. 11025 - 11 khz) word rate; // num samples per second (e.g. 11025 - 11 khz)
byte width; // resolution - bum bits divided by 8 (8 bit is 1, 16 bit is 2) byte width; // resolution - bum bits divided by 8 (8 bit is 1, 16 bit is 2)
byte channels; // num channels (1 - mono, 2 - stereo) byte channels; // num channels (1 - mono, 2 - stereo)
int loopStart; // offset at this point sound will be looping while playing more than only once uint loopStart; // offset at this point sound will be looping while playing more than only once
int samples; // total samplecount in wav uint samples; // total samplecount in wav
uint type; // compression type uint type; // compression type
uint flags; // misc sound flags uint flags; // misc sound flags
byte *buffer; // sound buffer byte *buffer; // sound buffer
size_t size; // for bounds checking size_t size; // for bounds checking
} wavdata_t; } wavdata_t;
// //
@@ -513,15 +508,15 @@ typedef struct
// //
void Sound_Init( void ); void Sound_Init( void );
void Sound_Shutdown( void ); void Sound_Shutdown( void );
wavdata_t *FS_LoadSound( const char *filename, const byte *buffer, size_t size );
void FS_FreeSound( wavdata_t *pack ); 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 ); wavdata_t *FS_StreamInfo( stream_t *stream );
int FS_ReadStream( stream_t *stream, int bytes, void *buffer ); int FS_ReadStream( stream_t *stream, int bytes, void *buffer );
int FS_SetStreamPos( stream_t *stream, int newpos ); int FS_SetStreamPos( stream_t *stream, int newpos );
int FS_GetStreamPos( stream_t *stream ); int FS_GetStreamPos( stream_t *stream );
void FS_FreeStream( stream_t *stream ); qboolean Sound_Process( wavdata_t **wav, int rate, int width, int channels, uint flags );
qboolean Sound_Process( wavdata_t **wav, int rate, int width, uint flags );
uint Sound_GetApproxWavePlayLen( const char *filepath ); uint Sound_GetApproxWavePlayLen( const char *filepath );
qboolean Sound_SupportedFileFormat( const char *fileext ); qboolean Sound_SupportedFileFormat( const char *fileext );
@@ -540,12 +535,10 @@ void Host_WriteServerConfig( const char *name );
void Host_WriteOpenGLConfig( void ); void Host_WriteOpenGLConfig( void );
void Host_WriteVideoConfig( void ); void Host_WriteVideoConfig( void );
void Host_WriteConfig( void ); void Host_WriteConfig( void );
qboolean Host_IsLocalGame( void );
qboolean Host_IsLocalClient( void );
void Host_ShutdownServer( void ); void Host_ShutdownServer( void );
void Host_Error( const char *error, ... ) _format( 1 ); void Host_Error( const char *error, ... ) _format( 1 );
void Host_ValidateEngineFeatures( uint32_t features ); void Host_ValidateEngineFeatures( uint32_t features );
void Host_Frame( float time ); void Host_Frame( double time );
void Host_Credits( void ); void Host_Credits( void );
// //
@@ -556,7 +549,7 @@ void COM_NewGame( char const *pMapName );
void COM_LoadLevel( char const *pMapName, qboolean background ); void COM_LoadLevel( char const *pMapName, qboolean background );
void COM_LoadGame( char const *pSaveFileName ); void COM_LoadGame( char const *pSaveFileName );
void COM_ChangeLevel( char const *pNewLevel, char const *pLandmarkName, qboolean background ); void COM_ChangeLevel( char const *pNewLevel, char const *pLandmarkName, qboolean background );
void COM_Frame( float time ); void COM_Frame( double time );
/* /*
============================================================== ==============================================================
@@ -587,7 +580,7 @@ qboolean SV_Active( void );
char *COM_MemFgets( byte *pMemFile, int fileSize, int *filePos, char *pBuffer, int bufferSize ); char *COM_MemFgets( byte *pMemFile, int fileSize, int *filePos, char *pBuffer, int bufferSize );
void COM_HexConvert( const char *pszInput, int nInputLength, byte *pOutput ); void COM_HexConvert( const char *pszInput, int nInputLength, byte *pOutput );
int COM_SaveFile( const char *filename, const void *data, int len ); 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 ); qboolean COM_IsSafeFileToDownload( const char *filename );
cvar_t *pfnCVarGetPointer( const char *szVarName ); cvar_t *pfnCVarGetPointer( const char *szVarName );
int pfnDrawConsoleString( int x, int y, char *string ); int pfnDrawConsoleString( int x, int y, char *string );
@@ -682,7 +675,6 @@ struct physent_s;
struct sv_client_s; struct sv_client_s;
typedef struct sizebuf_s sizebuf_t; typedef struct sizebuf_s sizebuf_t;
qboolean CL_IsInGame( void ); qboolean CL_IsInGame( void );
qboolean CL_IsInMenu( void );
qboolean CL_IsInConsole( void ); qboolean CL_IsInConsole( void );
qboolean CL_IsThirdPerson( void ); qboolean CL_IsThirdPerson( void );
qboolean CL_IsIntermission( void ); qboolean CL_IsIntermission( void );
@@ -691,7 +683,7 @@ char *CL_Userinfo( void );
void CL_LegacyUpdateInfo( void ); void CL_LegacyUpdateInfo( void );
void CL_CharEvent( int key ); void CL_CharEvent( int key );
qboolean CL_DisableVisibility( void ); 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_GetFirstFunctionHandle( void );
struct cmd_s *Cmd_GetNextFunctionHandle( struct cmd_s *cmd ); struct cmd_s *Cmd_GetNextFunctionHandle( struct cmd_s *cmd );
struct cmdalias_s *Cmd_AliasGetList( void ); struct cmdalias_s *Cmd_AliasGetList( void );
@@ -700,8 +692,9 @@ void Log_Printf( const char *fmt, ... ) _format( 1 );
void SV_BroadcastCommand( const char *fmt, ... ) _format( 1 ); void SV_BroadcastCommand( const char *fmt, ... ) _format( 1 );
void SV_BroadcastPrintf( struct sv_client_s *ignore, const char *fmt, ... ) _format( 2 ); void SV_BroadcastPrintf( struct sv_client_s *ignore, const char *fmt, ... ) _format( 2 );
void CL_ClearStaticEntities( void ); void CL_ClearStaticEntities( void );
qboolean S_StreamGetCurrentState( char *currentTrack, char *loopTrack, int *position ); qboolean S_StreamGetCurrentState( char *currentTrack, size_t currentTrackSize, char *loopTrack, size_t loopTrackSize, int *position );
void CL_ServerCommand( qboolean reliable, const char *fmt, ... ) _format( 2 ); void CL_ServerCommand( qboolean reliable, const char *fmt, ... ) _format( 2 );
void CL_UpdateInfo( const char *key, const char *value );
void CL_HudMessage( const char *pMessage ); void CL_HudMessage( const char *pMessage );
const char *CL_MsgInfo( int cmd ); const char *CL_MsgInfo( int cmd );
void SV_DrawDebugTriangles( void ); void SV_DrawDebugTriangles( void );
@@ -775,6 +768,18 @@ int COM_CompareFileTime( const char *filename1, const char *filename2, int *iCom
char *va( const char *format, ... ) _format( 1 ); char *va( const char *format, ... ) _format( 1 );
qboolean CRC32_MapFile( dword *crcvalue, const char *filename, qboolean multiplayer ); qboolean CRC32_MapFile( dword *crcvalue, const char *filename, qboolean multiplayer );
static inline qboolean Host_IsLocalGame( void )
{
if( SV_Active( ))
return SV_GetMaxClients() == 1 ? true : false;
return CL_GetMaxClients() == 1 ? true : false;
}
static inline qboolean Host_IsLocalClient( void )
{
return CL_Initialized( ) && SV_Initialized( ) ? true : false;
}
// soundlib shared exports // soundlib shared exports
qboolean S_Init( void ); qboolean S_Init( void );
void S_Shutdown( void ); void S_Shutdown( void );

View File

@@ -465,7 +465,7 @@ static qboolean Cmd_GetSoundList( const char *s, char *completedname, int length
t = FS_Search( va( "%s%s*.*", DEFAULT_SOUNDPATH, s ), true, false ); t = FS_Search( va( "%s%s*.*", DEFAULT_SOUNDPATH, s ), true, false );
if( !t ) return false; if( !t ) return false;
Q_strncpy( matchbuf, t->filenames[0] + sizeof( DEFAULT_SOUNDPATH ) - 1, MAX_STRING ); Q_strncpy( matchbuf, t->filenames[0] + sizeof( DEFAULT_SOUNDPATH ) - 1, sizeof( matchbuf ));
COM_StripExtension( matchbuf ); COM_StripExtension( matchbuf );
if( completedname && length ) if( completedname && length )
Q_strncpy( completedname, matchbuf, length ); Q_strncpy( completedname, matchbuf, length );
@@ -478,7 +478,7 @@ static qboolean Cmd_GetSoundList( const char *s, char *completedname, int length
if( Q_stricmp( ext, "wav" ) && Q_stricmp( ext, "mp3" )) if( Q_stricmp( ext, "wav" ) && Q_stricmp( ext, "mp3" ))
continue; continue;
Q_strncpy( matchbuf, t->filenames[i] + sizeof( DEFAULT_SOUNDPATH ) - 1, MAX_STRING ); Q_strncpy( matchbuf, t->filenames[i] + sizeof( DEFAULT_SOUNDPATH ) - 1, sizeof( matchbuf ));
COM_StripExtension( matchbuf ); COM_StripExtension( matchbuf );
Con_Printf( "%16s\n", matchbuf ); Con_Printf( "%16s\n", matchbuf );
numsounds++; numsounds++;
@@ -585,7 +585,7 @@ static qboolean Cmd_GetKeysList( const char *s, char *completedname, int length
Con_Printf( "%16s\n", matchbuf ); Con_Printf( "%16s\n", matchbuf );
} }
Con_Printf( "\n^3 %lu keys found.\n", numkeys ); Con_Printf( "\n^3 %zu keys found.\n", numkeys );
if( completedname && length ) if( completedname && length )
{ {
@@ -764,14 +764,14 @@ static qboolean Cmd_GetGamesList( const char *s, char *completedname, int length
} }
if( !numgamedirs ) return false; if( !numgamedirs ) return false;
Q_strncpy( matchbuf, gamedirs[0], MAX_STRING ); Q_strncpy( matchbuf, gamedirs[0], sizeof( matchbuf ));
if( completedname && length ) if( completedname && length )
Q_strncpy( completedname, matchbuf, length ); Q_strncpy( completedname, matchbuf, length );
if( numgamedirs == 1 ) return true; if( numgamedirs == 1 ) return true;
for( i = 0; i < numgamedirs; i++ ) for( i = 0; i < numgamedirs; i++ )
{ {
Q_strncpy( matchbuf, gamedirs[i], MAX_STRING ); Q_strncpy( matchbuf, gamedirs[i], sizeof( matchbuf ));
Con_Printf( "%16s\n", matchbuf ); Con_Printf( "%16s\n", matchbuf );
} }
@@ -825,14 +825,14 @@ static qboolean Cmd_GetCDList( const char *s, char *completedname, int length )
} }
if( !numcdcommands ) return false; if( !numcdcommands ) return false;
Q_strncpy( matchbuf, cdcommands[0], MAX_STRING ); Q_strncpy( matchbuf, cdcommands[0], sizeof( matchbuf ));
if( completedname && length ) if( completedname && length )
Q_strncpy( completedname, matchbuf, length ); Q_strncpy( completedname, matchbuf, length );
if( numcdcommands == 1 ) return true; if( numcdcommands == 1 ) return true;
for( i = 0; i < numcdcommands; i++ ) for( i = 0; i < numcdcommands; i++ )
{ {
Q_strncpy( matchbuf, cdcommands[i], MAX_STRING ); Q_strncpy( matchbuf, cdcommands[i], sizeof( matchbuf ));
Con_Printf( "%16s\n", matchbuf ); Con_Printf( "%16s\n", matchbuf );
} }
@@ -901,12 +901,10 @@ static qboolean Cmd_CheckMapsList_R( qboolean fRefresh, qboolean onlyingamedir )
if( f ) if( f )
{ {
qboolean have_spawnpoints = false; qboolean have_spawnpoints = false;
dheader_t *header;
dlump_t entities; dlump_t entities;
memset( buf, 0, MAX_SYSPATH ); memset( buf, 0, MAX_SYSPATH );
FS_Read( f, buf, MAX_SYSPATH ); FS_Read( f, buf, MAX_SYSPATH );
header = (dheader_t *)buf;
// check all the lumps and some other errors // check all the lumps and some other errors
if( !Mod_TestBmodelLumps( f, t->filenames[i], buf, true, &entities )) if( !Mod_TestBmodelLumps( f, t->filenames[i], buf, true, &entities ))
@@ -937,7 +935,7 @@ static qboolean Cmd_CheckMapsList_R( qboolean fRefresh, qboolean onlyingamedir )
char token[MAX_TOKEN]; char token[MAX_TOKEN];
qboolean worldspawn = true; qboolean worldspawn = true;
Q_strncpy( message, "No Title", MAX_STRING ); Q_strncpy( message, "No Title", sizeof( message ));
pfile = ents; pfile = ents;
while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL ) while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL )
@@ -1021,6 +1019,7 @@ autocomplete_list_t cmd_list[] =
{ "changelevel", 1, Cmd_GetMapList }, { "changelevel", 1, Cmd_GetMapList },
{ "playdemo", 1, Cmd_GetDemoList, }, { "playdemo", 1, Cmd_GetDemoList, },
{ "timedemo", 1, Cmd_GetDemoList, }, { "timedemo", 1, Cmd_GetDemoList, },
{ "listdemo", 1, Cmd_GetDemoList, },
{ "playvol", 1, Cmd_GetSoundList }, { "playvol", 1, Cmd_GetSoundList },
{ "hpkval", 1, Cmd_GetCustomList }, { "hpkval", 1, Cmd_GetCustomList },
{ "hpklist", 1, Cmd_GetCustomList }, { "hpklist", 1, Cmd_GetCustomList },
@@ -1203,7 +1202,7 @@ void Con_CompleteCommand( field_t *field )
if( !con.matchCount ) return; // no matches if( !con.matchCount ) return; // no matches
memcpy( &temp, con.completionField, sizeof( field_t ) ); temp = *con.completionField;
// autocomplete second arg // autocomplete second arg
if( (Cmd_Argc() >= 2) || ((Cmd_Argc() == 1) && nextcmd) ) if( (Cmd_Argc() >= 2) || ((Cmd_Argc() == 1) && nextcmd) )
@@ -1397,7 +1396,7 @@ void Host_WriteConfig( void )
f = FS_Open( "config.cfg.new", "w", false ); f = FS_Open( "config.cfg.new", "w", false );
if( f ) if( f )
{ {
Con_Reportf( "Host_WriteConfig()\n" ); Con_Reportf( "%s()\n", __func__ );
FS_Printf( f, "//=======================================================================\n"); FS_Printf( f, "//=======================================================================\n");
FS_Printf( f, "//\t\t\tCopyright XashXT Group & Flying With Gauss %s (C)\n", Q_timestamp( TIME_YEAR_ONLY )); FS_Printf( f, "//\t\t\tCopyright XashXT Group & Flying With Gauss %s (C)\n", Q_timestamp( TIME_YEAR_ONLY ));
FS_Printf( f, "//\t\t\tconfig.cfg - archive of cvars\n" ); FS_Printf( f, "//\t\t\tconfig.cfg - archive of cvars\n" );
@@ -1480,7 +1479,7 @@ void Host_WriteOpenGLConfig( void )
f = FS_Open( va( "%s.new", name ), "w", false ); f = FS_Open( va( "%s.new", name ), "w", false );
if( f ) if( f )
{ {
Con_Reportf( "Host_WriteGLConfig()\n" ); Con_Reportf( "%s()\n", __func__ );
FS_Printf( f, "//=======================================================================\n" ); FS_Printf( f, "//=======================================================================\n" );
FS_Printf( f, "//\t\t\tCopyright XashXT Group & Flying With Gauss %s (C)\n", Q_timestamp( TIME_YEAR_ONLY )); FS_Printf( f, "//\t\t\tCopyright XashXT Group & Flying With Gauss %s (C)\n", Q_timestamp( TIME_YEAR_ONLY ));
FS_Printf( f, "//\t\t %s - archive of renderer implementation cvars\n", name ); FS_Printf( f, "//\t\t %s - archive of renderer implementation cvars\n", name );
@@ -1510,7 +1509,7 @@ void Host_WriteVideoConfig( void )
f = FS_Open( "video.cfg.new", "w", false ); f = FS_Open( "video.cfg.new", "w", false );
if( f ) if( f )
{ {
Con_Reportf( "Host_WriteVideoConfig()\n" ); Con_Reportf( "%s()\n", __func__ );
FS_Printf( f, "//=======================================================================\n" ); FS_Printf( f, "//=======================================================================\n" );
FS_Printf( f, "//\t\t\tCopyright XashXT Group & Flying With Gauss %s (C)\n", Q_timestamp( TIME_YEAR_ONLY )); FS_Printf( f, "//\t\t\tCopyright XashXT Group & Flying With Gauss %s (C)\n", Q_timestamp( TIME_YEAR_ONLY ));
FS_Printf( f, "//\t\tvideo.cfg - archive of renderer variables\n"); FS_Printf( f, "//\t\tvideo.cfg - archive of renderer variables\n");

View File

@@ -80,7 +80,7 @@ static int Sys_ModuleName( HANDLE process, char *name, void *address, int len )
static void Sys_StackTrace( PEXCEPTION_POINTERS pInfo ) static void Sys_StackTrace( PEXCEPTION_POINTERS pInfo )
{ {
char message[1024]; char message[8192]; // match *nix Sys_Crash
int len = 0; int len = 0;
size_t i; size_t i;
HANDLE process = GetCurrentProcess(); HANDLE process = GetCurrentProcess();
@@ -92,7 +92,7 @@ static void Sys_StackTrace( PEXCEPTION_POINTERS pInfo )
STACKFRAME64 stackframe; STACKFRAME64 stackframe;
DWORD image; DWORD image;
memcpy( &context, pInfo->ContextRecord, sizeof( CONTEXT )); context = *pInfo->ContextRecord;
options = SymGetOptions(); options = SymGetOptions();
options |= SYMOPT_DEBUG; options |= SYMOPT_DEBUG;
@@ -129,9 +129,29 @@ static void Sys_StackTrace( PEXCEPTION_POINTERS pInfo )
stackframe.AddrBStore.Mode = AddrModeFlat; stackframe.AddrBStore.Mode = AddrModeFlat;
stackframe.AddrStack.Offset = context.IntSp; stackframe.AddrStack.Offset = context.IntSp;
stackframe.AddrStack.Mode = AddrModeFlat; stackframe.AddrStack.Mode = AddrModeFlat;
#elif _M_ARM
image = IMAGE_FILE_MACHINE_ARMNT;
stackframe.AddrPC.Offset = context.Pc;
stackframe.AddrPC.Mode = AddrModeFlat;
stackframe.AddrFrame.Offset = context.R11;
stackframe.AddrFrame.Mode = AddrModeFlat;
stackframe.AddrStack.Offset = context.Sp;
stackframe.AddrStack.Mode = AddrModeFlat;
#elif _M_ARM64
image = IMAGE_FILE_MACHINE_ARM64;
stackframe.AddrPC.Offset = context.Pc;
stackframe.AddrPC.Mode = AddrModeFlat;
stackframe.AddrFrame.Offset = context.Fp;
stackframe.AddrFrame.Mode = AddrModeFlat;
stackframe.AddrStack.Offset = context.Sp;
stackframe.AddrStack.Mode = AddrModeFlat;
#elif #elif
#error #error
#endif #endif
len = Q_snprintf( message, sizeof( message ), "Ver: " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s, %s-%s)\n",
Q_buildnum(), Q_buildcommit(), Q_buildos(), Q_buildarch() );
len += Q_snprintf( message + len, 1024 - len, "Sys_Crash: address %p, code %p\n", len += Q_snprintf( message + len, 1024 - len, "Sys_Crash: address %p, code %p\n",
pInfo->ExceptionRecord->ExceptionAddress, (void*)pInfo->ExceptionRecord->ExceptionCode ); pInfo->ExceptionRecord->ExceptionAddress, (void*)pInfo->ExceptionRecord->ExceptionCode );
if( SymGetLineFromAddr64( process, (DWORD64)pInfo->ExceptionRecord->ExceptionAddress, &dline, &line ) ) if( SymGetLineFromAddr64( process, (DWORD64)pInfo->ExceptionRecord->ExceptionAddress, &dline, &line ) )
@@ -259,6 +279,10 @@ static long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo )
// check to avoid recursive call // check to avoid recursive call
host.crashed = true; host.crashed = true;
#ifdef XASH_SDL
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
#endif // XASH_SDL
#if DBGHELP #if DBGHELP
Sys_StackTrace( pInfo ); Sys_StackTrace( pInfo );
#else #else
@@ -309,7 +333,6 @@ void Sys_SetupCrashHandler( void )
{ {
SetErrorMode( SEM_FAILCRITICALERRORS ); // no abort/retry/fail errors SetErrorMode( SEM_FAILCRITICALERRORS ); // no abort/retry/fail errors
oldFilter = SetUnhandledExceptionFilter( Sys_Crash ); oldFilter = SetUnhandledExceptionFilter( Sys_Crash );
host.hInst = GetModuleHandle( NULL );
} }
void Sys_RestoreCrashHandler( void ) void Sys_RestoreCrashHandler( void )

View File

@@ -16,6 +16,7 @@ GNU General Public License for more details.
#include "common.h" #include "common.h"
#include "custom.h" #include "custom.h"
#include "ref_common.h" #include "ref_common.h"
#include "hpak.h" // be aware of HPK limits
static rgbdata_t *CustomDecal_LoadImage( const char *path, void *raw, int size ) static rgbdata_t *CustomDecal_LoadImage( const char *path, void *raw, int size )
{ {
@@ -93,7 +94,7 @@ qboolean COM_CreateCustomization( customization_t *pListHead, resource_t *pResou
if( FBitSet( flags, FCUST_FROMHPAK )) if( FBitSet( flags, FCUST_FROMHPAK ))
{ {
if( !HPAK_GetDataPointer( CUSTOM_RES_PATH, pResource, (byte **)&pCust->pBuffer, NULL )) if( !HPAK_GetDataPointer( hpk_custom_file.string, pResource, (byte **)&pCust->pBuffer, NULL ))
bError = true; bError = true;
} }
else else
@@ -115,11 +116,11 @@ qboolean COM_CreateCustomization( customization_t *pListHead, resource_t *pResou
{ {
if( !FBitSet( flags, FCUST_IGNOREINIT )) if( !FBitSet( flags, FCUST_IGNOREINIT ))
{ {
if( pResource->nDownloadSize >= (1 * 1024) && pResource->nDownloadSize <= ( 128 * 1024 )) if( pResource->nDownloadSize >= HPAK_ENTRY_MIN_SIZE && pResource->nDownloadSize <= HPAK_ENTRY_MAX_SIZE )
{ {
pCust->bTranslated = true; pCust->bTranslated = true;
pCust->nUserData1 = 0; pCust->nUserData1 = 0;
pCust->nUserData2 = 1; pCust->nUserData2 = 7;
if( !FBitSet( flags, FCUST_WIPEDATA )) if( !FBitSet( flags, FCUST_WIPEDATA ))
pCust->pInfo = CustomDecal_LoadImage( pResource->szFileName, pCust->pBuffer, pCust->resource.nDownloadSize ); pCust->pInfo = CustomDecal_LoadImage( pResource->szFileName, pCust->pBuffer, pCust->resource.nDownloadSize );

View File

@@ -164,8 +164,7 @@ static qboolean Cvar_UpdateInfo( convar_t *var, const char *value, qboolean noti
return false; // failed to change value return false; // failed to change value
// time to update server copy of userinfo // time to update server copy of userinfo
CL_ServerCommand( true, "setinfo \"%s\" \"%s\"\n", var->name, value ); CL_UpdateInfo( var->name, value );
CL_LegacyUpdateInfo();
} }
#endif #endif
} }
@@ -231,7 +230,7 @@ static const char *Cvar_ValidateString( convar_t *var, const char *value )
if( !COM_CheckStringEmpty( szNew ) ) Q_strncpy( szNew, "empty", sizeof( szNew )); 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; char *szVal = szNew;
int len = 0; int len = 0;
@@ -794,7 +793,7 @@ void GAME_EXPORT Cvar_Set( const char *var_name, const char *value )
if( !var_name ) if( !var_name )
{ {
// there is an error in C code if this happens // there is an error in C code if this happens
Con_Printf( "Cvar_Set: passed NULL variable name\n" ); Con_Printf( "%s: passed NULL variable name\n", __func__ );
return; return;
} }
@@ -803,7 +802,7 @@ void GAME_EXPORT Cvar_Set( const char *var_name, const char *value )
if( !var ) if( !var )
{ {
// there is an error in C code if this happens // there is an error in C code if this happens
Con_Printf( "Cvar_Set: variable '%s' not found\n", var_name ); Con_Printf( "%s: variable '%s' not found\n", __func__, var_name );
return; return;
} }
@@ -848,7 +847,7 @@ float GAME_EXPORT Cvar_VariableValue( const char *var_name )
if( !var_name ) if( !var_name )
{ {
// there is an error in C code if this happens // there is an error in C code if this happens
Con_Printf( "Cvar_VariableValue: passed NULL variable name\n" ); Con_Printf( "%s: passed NULL variable name\n", __func__ );
return 0.0f; return 0.0f;
} }
@@ -885,7 +884,7 @@ const char *Cvar_VariableString( const char *var_name )
if( !var_name ) if( !var_name )
{ {
// there is an error in C code if this happens // there is an error in C code if this happens
Con_Printf( "Cvar_VariableString: passed NULL variable name\n" ); Con_Printf( "%s: passed NULL variable name\n", __func__ );
return ""; return "";
} }
@@ -955,7 +954,7 @@ static void Cvar_SetGL( const char *name, const char *value )
static qboolean Cvar_ShouldSetCvar( convar_t *v, qboolean isPrivileged ) static qboolean Cvar_ShouldSetCvar( convar_t *v, qboolean isPrivileged )
{ {
const char *prefixes[] = { "cl_", "gl_", "m_", "r_", "hud_", "joy_" }; const char *prefixes[] = { "cl_", "gl_", "m_", "r_", "hud_", "joy_", "con_", "scr_" };
int i; int i;
if( isPrivileged ) if( isPrivileged )

View File

@@ -18,45 +18,6 @@ GNU General Public License for more details.
#include "cvardef.h" #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
{
// this part shared with cvar_t
char *name;
char *string;
int flags;
float value;
struct convar_s *next;
// this part unique for convar_t
char *desc; // variable descrition info
char *def_string; // keep pointer to initial value
} convar_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 ); cvar_t *Cvar_GetList( void );
#define Cvar_FindVar( name ) Cvar_FindVarExt( name, 0 ) #define Cvar_FindVar( name ) Cvar_FindVarExt( name, 0 )
convar_t *Cvar_FindVarExt( const char *var_name, int ignore_group ); convar_t *Cvar_FindVarExt( const char *var_name, int ignore_group );
@@ -81,6 +42,5 @@ qboolean Cvar_CommandWithPrivilegeCheck( convar_t *v, qboolean isPrivileged );
void Cvar_Init( void ); void Cvar_Init( void );
void Cvar_PostFSInit( void ); void Cvar_PostFSInit( void );
void Cvar_Unlink( int group ); void Cvar_Unlink( int group );
#endif // REF_DLL
#endif//CVAR_H #endif//CVAR_H

View File

@@ -39,11 +39,6 @@ qboolean CL_IsInGame( void )
return true; // always active for dedicated servers return true; // always active for dedicated servers
} }
qboolean CL_IsInMenu( void )
{
return false;
}
qboolean CL_IsInConsole( void ) qboolean CL_IsInConsole( void )
{ {
return false; return false;

View File

@@ -16,6 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
*/ */
#include <errno.h>
#include "common.h" #include "common.h"
#include "library.h" #include "library.h"
#include "platform/platform.h" #include "platform/platform.h"
@@ -26,6 +27,40 @@ fs_globals_t *FI;
static pfnCreateInterface_t fs_pfnCreateInterface; static pfnCreateInterface_t fs_pfnCreateInterface;
static HINSTANCE fs_hInstance; 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;
len = Q_strlen( pname );
if( len > 0 && pname[len - 1] == '/' )
pname[len - 1] = 0;
}
void *FS_GetNativeObject( const char *obj ) void *FS_GetNativeObject( const char *obj )
{ {
if( fs_pfnCreateInterface ) if( fs_pfnCreateInterface )
@@ -49,7 +84,7 @@ static void FS_Path_f_( void )
FS_Path_f(); FS_Path_f();
} }
static fs_interface_t fs_memfuncs = static const fs_interface_t fs_memfuncs =
{ {
Con_Printf, Con_Printf,
Con_DPrintf, Con_DPrintf,
@@ -80,7 +115,7 @@ static void FS_UnloadProgs( void )
#define FILESYSTEM_STDIO_DLL "filesystem_stdio." OS_LIB_EXT #define FILESYSTEM_STDIO_DLL "filesystem_stdio." OS_LIB_EXT
#endif #endif
qboolean FS_LoadProgs( void ) static qboolean FS_LoadProgs( void )
{ {
const char *name = FILESYSTEM_STDIO_DLL; const char *name = FILESYSTEM_STDIO_DLL;
FSAPI GetFSAPI; FSAPI GetFSAPI;
@@ -89,63 +124,160 @@ qboolean FS_LoadProgs( void )
if( !fs_hInstance ) if( !fs_hInstance )
{ {
Host_Error( "FS_LoadProgs: can't load filesystem library %s: %s\n", name, COM_GetLibraryError() ); Sys_Error( "%s: can't load filesystem library %s: %s\n", __func__, name, COM_GetLibraryError() );
return false; return false;
} }
if( !( GetFSAPI = (FSAPI)COM_GetProcAddress( fs_hInstance, GET_FS_API ))) if( !( GetFSAPI = (FSAPI)COM_GetProcAddress( fs_hInstance, GET_FS_API )))
{ {
FS_UnloadProgs(); FS_UnloadProgs();
Host_Error( "FS_LoadProgs: can't find GetFSAPI entry point in %s\n", name ); Sys_Error( "%s: can't find GetFSAPI entry point in %s\n", __func__, name );
return false; return false;
} }
if( !GetFSAPI( FS_API_VERSION, &g_fsapi, &FI, &fs_memfuncs )) if( GetFSAPI( FS_API_VERSION, &g_fsapi, &FI, &fs_memfuncs ) != FS_API_VERSION )
{ {
FS_UnloadProgs(); FS_UnloadProgs();
Host_Error( "FS_LoadProgs: can't initialize filesystem API: wrong version\n" ); Sys_Error( "%s: can't initialize filesystem API: wrong version\n", __func__ );
return false; return false;
} }
if( !( fs_pfnCreateInterface = (pfnCreateInterface_t)COM_GetProcAddress( fs_hInstance, "CreateInterface" ))) if( !( fs_pfnCreateInterface = (pfnCreateInterface_t)COM_GetProcAddress( fs_hInstance, "CreateInterface" )))
{ {
FS_UnloadProgs(); FS_UnloadProgs();
Host_Error( "FS_LoadProgs: can't find CreateInterface entry point in %s\n", name ); Sys_Error( "%s: can't find CreateInterface entry point in %s\n", __func__, name );
return false; return false;
} }
Con_DPrintf( "FS_LoadProgs: filesystem_stdio successfully loaded\n" ); Con_DPrintf( "%s: filesystem_stdio successfully loaded\n", __func__ );
return true; return true;
} }
static qboolean FS_DetermineRootDirectory( char *out, size_t size )
{
const char *path = getenv( "XASH3D_BASEDIR" );
if( COM_CheckString( path ))
{
Q_strncpy( out, path, size );
return true;
}
#if TARGET_OS_IOS
Q_strncpy( out, IOS_GetDocsDir(), size );
return true;
#elif XASH_ANDROID && XASH_SDL
path = SDL_AndroidGetExternalStoragePath();
if( path != NULL )
{
Q_strncpy( out, path, size );
return true;
}
Sys_Error( "couldn't determine Android external storage path: %s", SDL_GetError( ));
return false;
#elif XASH_PSVITA
if( PSVita_GetBasePath( out, size ))
return true;
Sys_Error( "couldn't find Xash3D data directory" );
return false;
#elif ( XASH_SDL == 2 ) && !XASH_NSWITCH // GetBasePath not impl'd in switch-sdl2
path = SDL_GetBasePath();
if( path != NULL )
{
Q_strncpy( out, path, size );
SDL_free(( void *)path );
return true;
}
#if XASH_POSIX || XASH_WIN32
if( getcwd( out, size ))
return true;
Sys_Error( "couldn't determine current directory: %s, getcwd: %s", SDL_GetError(), strerror( errno ));
#else // !( XASH_POSIX || XASH_WIN32 )
Sys_Error( "couldn't determine current directory: %s", SDL_GetError( ));
#endif // !( XASH_POSIX || XASH_WIN32 )
return false;
#else // generic case
if( getcwd( out, size ))
return true;
Sys_Error( "couldn't determine current directory: %s", strerror( errno ));
return false;
#endif // generic case
}
static qboolean FS_DetermineReadOnlyRootDirectory( char *out, size_t size )
{
const char *env_rodir = getenv( "XASH3D_RODIR" );
if( _Sys_GetParmFromCmdLine( "-rodir", out, size ))
return true;
if( COM_CheckString( env_rodir ))
{
Q_strncpy( out, env_rodir, size );
return true;
}
return false;
}
/* /*
================ ================
FS_Init FS_Init
================ ================
*/ */
void FS_Init( void ) void FS_Init( const char *basedir )
{ {
string gamedir; string gamedir;
char rodir[MAX_OSPATH], rootdir[MAX_OSPATH];
rodir[0] = rootdir[0] = 0;
if( !FS_DetermineRootDirectory( rootdir, sizeof( rootdir )) || !COM_CheckStringEmpty( rootdir ))
{
Sys_Error( "couldn't determine current directory (empty string)" );
return;
}
COM_FixSlashes( rootdir );
COM_StripDirectorySlash( rootdir );
FS_DetermineReadOnlyRootDirectory( rodir, sizeof( rodir ));
COM_FixSlashes( rodir );
COM_StripDirectorySlash( rodir );
if( !Sys_GetParmFromCmdLine( "-game", gamedir ))
{
char *env = getenv( "XASH3D_GAME" );
if( env )
Q_strncpy( gamedir, env, sizeof( gamedir ));
else
Q_strncpy( gamedir, basedir, sizeof( gamedir )); // gamedir == basedir
}
FS_LoadProgs();
// TODO: this function will cause engine to stop in case of fail
// when it will have an option to return string error, restore Sys_Error
// FIXME: why do we call this function before InitStdio?
// because InitStdio immediately scans all available game directories
// and this better be reworked at some point
g_fsapi.SetCurrentDirectory( rootdir );
if( !g_fsapi.InitStdio( true, rootdir, basedir, gamedir, rodir ))
{
Sys_Error( "Can't init filesystem_stdio!\n" );
return;
}
Cmd_AddRestrictedCommand( "fs_rescan", FS_Rescan_f, "rescan filesystem search pathes" ); Cmd_AddRestrictedCommand( "fs_rescan", FS_Rescan_f, "rescan filesystem search pathes" );
Cmd_AddRestrictedCommand( "fs_path", FS_Path_f_, "show filesystem search pathes" ); Cmd_AddRestrictedCommand( "fs_path", FS_Path_f_, "show filesystem search pathes" );
Cmd_AddRestrictedCommand( "fs_clearpaths", FS_ClearPaths_f, "clear filesystem search pathes" ); Cmd_AddRestrictedCommand( "fs_clearpaths", FS_ClearPaths_f, "clear filesystem search pathes" );
if( !Sys_GetParmFromCmdLine( "-game", gamedir )) if( !Sys_GetParmFromCmdLine( "-dll", host.gamedll ))
Q_strncpy( gamedir, SI.basedirName, sizeof( gamedir )); // gamedir == basedir host.gamedll[0] = 0;
if( !FS_InitStdio( true, host.rootdir, SI.basedirName, gamedir, host.rodir )) if( !Sys_GetParmFromCmdLine( "-clientlib", host.clientlib ))
{ host.clientlib[0] = 0;
Host_Error( "Can't init filesystem_stdio!\n" );
return;
}
if( !Sys_GetParmFromCmdLine( "-dll", SI.gamedll ))
SI.gamedll[0] = 0;
if( !Sys_GetParmFromCmdLine( "-clientlib", SI.clientlib ))
SI.clientlib[0] = 0;
} }
/* /*
@@ -158,11 +290,5 @@ void FS_Shutdown( void )
if( g_fsapi.ShutdownStdio ) if( g_fsapi.ShutdownStdio )
g_fsapi.ShutdownStdio(); g_fsapi.ShutdownStdio();
memset( &SI, 0, sizeof( sysinfo_t ));
FS_UnloadProgs(); FS_UnloadProgs();
} }

View File

@@ -18,8 +18,6 @@ GNU General Public License for more details.
#include <SDL.h> #include <SDL.h>
#endif // XASH_SDL #endif // XASH_SDL
#include <stdarg.h> // va_args #include <stdarg.h> // va_args
#include <errno.h> // errno
#include <string.h> // strerror
#if !XASH_WIN32 #if !XASH_WIN32
#include <unistd.h> // fork #include <unistd.h> // fork
#include <sys/types.h> #include <sys/types.h>
@@ -29,7 +27,6 @@ GNU General Public License for more details.
#if XASH_EMSCRIPTEN #if XASH_EMSCRIPTEN
#include <emscripten/emscripten.h> #include <emscripten/emscripten.h>
#endif #endif
#include <errno.h>
#include "common.h" #include "common.h"
#include "base_cmd.h" #include "base_cmd.h"
#include "client.h" #include "client.h"
@@ -45,7 +42,6 @@ GNU General Public License for more details.
pfnChangeGame pChangeGame = NULL; pfnChangeGame pChangeGame = NULL;
host_parm_t host; // host parms host_parm_t host; // host parms
sysinfo_t SI;
#ifdef XASH_ENGINE_TESTS #ifdef XASH_ENGINE_TESTS
struct tests_stats_s tests_stats; struct tests_stats_s tests_stats;
@@ -53,7 +49,7 @@ struct tests_stats_s tests_stats;
CVAR_DEFINE( host_developer, "developer", "0", FCVAR_FILTERABLE, "engine is in development-mode" ); 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_timescale, "1.0", FCVAR_FILTERABLE, "scale frame time" );
CVAR_DEFINE_AUTO( sys_ticrate, "100", 0, "framerate in dedicated mode" ); 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_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_gameloaded, "0", FCVAR_READ_ONLY, "inidcates a loaded game.dll" );
@@ -63,6 +59,7 @@ CVAR_DEFINE( host_maxfps, "fps_max", "72", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "host
static CVAR_DEFINE_AUTO( host_framerate, "0", FCVAR_FILTERABLE, "locks frame timing to this value in seconds" ); static CVAR_DEFINE_AUTO( host_framerate, "0", FCVAR_FILTERABLE, "locks frame timing to this value in seconds" );
static CVAR_DEFINE( host_sleeptime, "sleeptime", "1", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "milliseconds to sleep for each frame. higher values reduce fps accuracy" ); static CVAR_DEFINE( host_sleeptime, "sleeptime", "1", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "milliseconds to sleep for each frame. higher values reduce fps accuracy" );
static CVAR_DEFINE_AUTO( host_sleeptime_debug, "0", 0, "print sleeps between frames" ); static CVAR_DEFINE_AUTO( host_sleeptime_debug, "0", 0, "print sleeps between frames" );
CVAR_DEFINE_AUTO( host_allow_materials, "0", FCVAR_LATCH|FCVAR_ARCHIVE, "allow texture replacements from materials/ folder" );
CVAR_DEFINE( con_gamemaps, "con_mapfilter", "1", FCVAR_ARCHIVE, "when true show only maps in game folder" ); CVAR_DEFINE( con_gamemaps, "con_mapfilter", "1", FCVAR_ARCHIVE, "when true show only maps in game folder" );
typedef struct feature_message_s typedef struct feature_message_s
@@ -75,6 +72,8 @@ typedef struct feature_message_s
static feature_message_t bugcomp_features[] = static feature_message_t bugcomp_features[] =
{ {
{ BUGCOMP_PENTITYOFENTINDEX_FLAG, "pfnPEntityOfEntIndex bugfix revert", "peoei" }, { 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 feature_message_t engine_features[] =
@@ -91,7 +90,7 @@ static feature_message_t engine_features[] =
{ ENGINE_STEP_POSHISTORY_LERP, "MOVETYPE_STEP Position History Based Lerping" }, { ENGINE_STEP_POSHISTORY_LERP, "MOVETYPE_STEP Position History Based Lerping" },
}; };
static void Sys_PrintUsage( void ) static void Sys_PrintUsage( const char *exename )
{ {
string version_str; string version_str;
const char *usage_str; const char *usage_str;
@@ -99,10 +98,14 @@ static void Sys_PrintUsage( void )
Q_snprintf( version_str, sizeof( version_str ), Q_snprintf( version_str, sizeof( version_str ),
XASH_ENGINE_NAME " %i/" XASH_VERSION " (%s-%s build %i)", PROTOCOL_VERSION, Q_buildos(), Q_buildarch(), Q_buildnum( )); XASH_ENGINE_NAME " %i/" XASH_VERSION " (%s-%s build %i)", PROTOCOL_VERSION, Q_buildos(), Q_buildarch(), Q_buildnum( ));
#if XASH_WIN32 #if XASH_MESSAGEBOX != MSGBOX_STDERR
#define XASH_EXE "(xash).exe" #if XASH_WIN32
#define XASH_EXE "(xash).exe"
#else
#define XASH_EXE "(xash)"
#endif
#else #else
#define XASH_EXE "(xash)" #define XASH_EXE "%s"
#endif #endif
#define O( x, y ) " "x" "y"\n" #define O( x, y ) " "x" "y"\n"
@@ -190,7 +193,8 @@ static void Sys_PrintUsage( void )
#if XASH_MESSAGEBOX != MSGBOX_STDERR #if XASH_MESSAGEBOX != MSGBOX_STDERR
Platform_MessageBox( version_str, usage_str, false ); Platform_MessageBox( version_str, usage_str, false );
#else #else
fprintf( stderr, "%s\n%s", version_str, usage_str ); fprintf( stderr, "%s\n", version_str );
fprintf( stderr, usage_str, exename );
#endif #endif
Sys_Quit(); Sys_Quit();
@@ -241,7 +245,7 @@ void Host_ValidateEngineFeatures( uint32_t features )
{ {
uint32_t mask = ENGINE_FEATURES_MASK; uint32_t mask = ENGINE_FEATURES_MASK;
#if !HOST_DEDICATED #if !XASH_DEDICATED
if( !Host_IsDedicated( ) && cls.legacymode ) if( !Host_IsDedicated( ) && cls.legacymode )
mask = ENGINE_LEGACY_FEATURES_MASK; mask = ENGINE_LEGACY_FEATURES_MASK;
#endif #endif
@@ -315,18 +319,6 @@ void Host_EndGame( qboolean abort, const char *message, ... )
if( abort ) Host_AbortCurrentFrame (); if( abort ) Host_AbortCurrentFrame ();
} }
/*
================
Host_AbortCurrentFrame
aborts the current host frame and goes on with the next one
================
*/
void Host_AbortCurrentFrame( void )
{
longjmp( host.abortframe, 1 );
}
/* /*
================== ==================
Host_CalcSleep Host_CalcSleep
@@ -334,14 +326,7 @@ Host_CalcSleep
*/ */
static int Host_CalcSleep( void ) static int Host_CalcSleep( void )
{ {
#ifndef XASH_DEDICATED if( Host_IsDedicated( ))
// never sleep in timedemo for benchmarking purposes
// also don't sleep with vsync for less lag
if( CL_IsTimeDemo( ) || gl_vsync.value )
return 0;
#endif
if( Host_IsDedicated() )
{ {
// let the dedicated server some sleep // let the dedicated server some sleep
return host_sleeptime.value; return host_sleeptime.value;
@@ -423,7 +408,6 @@ static void Host_Exec_f( void )
byte *f; byte *f;
char *txt; char *txt;
fs_offset_t len; fs_offset_t len;
const char *arg;
if( Cmd_Argc() != 2 ) if( Cmd_Argc() != 2 )
{ {
@@ -431,7 +415,8 @@ static void Host_Exec_f( void )
return; return;
} }
arg = Cmd_Argv( 1 ); Q_strncpy( cfgpath, Cmd_Argv( 1 ), sizeof( cfgpath ));
COM_DefaultExtension( cfgpath, ".cfg", sizeof( cfgpath )); // append as default
#ifndef XASH_DEDICATED #ifndef XASH_DEDICATED
if( !Cmd_CurrentCommandIsPrivileged() ) if( !Cmd_CurrentCommandIsPrivileged() )
@@ -451,7 +436,7 @@ static void Host_Exec_f( void )
for( i = 0; i < ARRAYSIZE( unprivilegedWhitelist ); i++ ) for( i = 0; i < ARRAYSIZE( unprivilegedWhitelist ); i++ )
{ {
if( !Q_strcmp( arg, unprivilegedWhitelist[i] )) if( !Q_strcmp( cfgpath, unprivilegedWhitelist[i] ))
{ {
allow = true; allow = true;
break; break;
@@ -460,21 +445,15 @@ static void Host_Exec_f( void )
if( !allow ) if( !allow )
{ {
Con_Printf( "exec %s: not privileged or in whitelist\n", arg ); Con_Printf( "exec %s: not privileged or in whitelist\n", cfgpath );
return; return;
} }
} }
#endif // XASH_DEDICATED #endif // XASH_DEDICATED
if( !Q_stricmp( "game.cfg", arg )) // don't execute game.cfg in singleplayer
{ if( SV_GetMaxClients() == 1 && !Q_stricmp( "game.cfg", cfgpath ))
// don't execute game.cfg in singleplayer return;
if( SV_GetMaxClients() == 1 )
return;
}
Q_strncpy( cfgpath, arg, sizeof( cfgpath ));
COM_DefaultExtension( cfgpath, ".cfg", sizeof( cfgpath )); // append as default
f = FS_LoadFile( cfgpath, &len, false ); f = FS_LoadFile( cfgpath, &len, false );
if( !f ) if( !f )
@@ -483,17 +462,18 @@ static void Host_Exec_f( void )
return; return;
} }
if( !Q_stricmp( "config.cfg", arg )) if( !Q_stricmp( "config.cfg", cfgpath ))
host.config_executed = true; host.config_executed = true;
// adds \n\0 at end of the file // adds \n\0 at end of the file
txt = Z_Calloc( len + 2 ); txt = Z_Calloc( len + 2 );
memcpy( txt, f, len ); memcpy( txt, f, len );
Q_strncat( txt, "\n", len + 2 ); txt[len] = '\n';
txt[len + 1] = '\0';
Mem_Free( f ); Mem_Free( f );
if( !host.apply_game_config ) if( !host.apply_game_config )
Con_Printf( "execing %s\n", arg ); Con_Printf( "execing %s\n", Cmd_Argv( 1 ));
Cbuf_InsertText( txt ); Cbuf_InsertText( txt );
Mem_Free( txt ); Mem_Free( txt );
} }
@@ -528,33 +508,6 @@ static void Host_Minimize_f( void )
#endif #endif
} }
/*
=================
Host_IsLocalGame
singleplayer game detect
=================
*/
qboolean Host_IsLocalGame( void )
{
if( SV_Active( ))
{
return ( SV_GetMaxClients() == 1 ) ? true : false;
}
else
{
return ( CL_GetMaxClients() == 1 ) ? true : false;
}
}
qboolean Host_IsLocalClient( void )
{
// only the local client have the active server
if( CL_Initialized( ) && SV_Initialized( ))
return true;
return false;
}
/* /*
================= =================
Host_RegisterDecal Host_RegisterDecal
@@ -599,10 +552,6 @@ static void Host_InitDecals( void )
int i, num_decals = 0; int i, num_decals = 0;
search_t *t; search_t *t;
// NOTE: only once resource without which engine can't continue work
if( !FS_FileExists( "gfx/conchars", false ))
Sys_Error( "W_LoadWadFile: couldn't load gfx.wad\n" );
memset( host.draw_decals, 0, sizeof( host.draw_decals )); memset( host.draw_decals, 0, sizeof( host.draw_decals ));
// lookup all the decals in decals.wad (basedir, gamedir, falldir) // lookup all the decals in decals.wad (basedir, gamedir, falldir)
@@ -615,7 +564,7 @@ static void Host_InitDecals( void )
} }
if( t ) Mem_Free( t ); if( t ) Mem_Free( t );
Con_Reportf( "InitDecals: %i decals\n", num_decals ); Con_Reportf( "%s: %i decals\n", __func__, num_decals );
} }
/* /*
@@ -647,7 +596,7 @@ static double Host_CalcFPS( void )
{ {
double fps = 0.0; double fps = 0.0;
if( Host_IsDedicated() ) if( Host_IsDedicated( ))
{ {
fps = sys_ticrate.value; fps = sys_ticrate.value;
} }
@@ -760,7 +709,7 @@ Host_FilterTime
Returns false if the time is too short to run a frame Returns false if the time is too short to run a frame
=================== ===================
*/ */
static qboolean Host_FilterTime( float time ) static qboolean Host_FilterTime( double time )
{ {
static double oldtime; static double oldtime;
double dt; double dt;
@@ -790,9 +739,9 @@ static qboolean Host_FilterTime( float time )
Host_Frame Host_Frame
================= =================
*/ */
void Host_Frame( float time ) void Host_Frame( double time )
{ {
double t1, t2; double t1;
// decide the simulation time // decide the simulation time
if( !Host_FilterTime( time )) if( !Host_FilterTime( time ))
@@ -810,11 +759,8 @@ void Host_Frame( float time )
Host_ClientFrame (); // client frame Host_ClientFrame (); // client frame
HTTP_Run(); // both server and client HTTP_Run(); // both server and client
t2 = Sys_DoubleTime();
host.pureframetime = t2 - t1;
host.framecount++; host.framecount++;
host.pureframetime = Sys_DoubleTime() - t1;
} }
/* /*
@@ -837,11 +783,11 @@ void GAME_EXPORT Host_Error( const char *error, ... )
if( host.framecount < 3 ) if( host.framecount < 3 )
{ {
Sys_Error( "Host_InitError: %s", hosterror1 ); Sys_Error( "%sInit: %s", __func__, hosterror1 );
} }
else if( host.framecount == host.errorframe ) else if( host.framecount == host.errorframe )
{ {
Sys_Error( "Host_MultiError: %s", hosterror2 ); Sys_Error( "%sMulti: %s", __func__, hosterror2 );
} }
else else
{ {
@@ -849,7 +795,7 @@ void GAME_EXPORT Host_Error( const char *error, ... )
{ {
UI_SetActiveMenu( false ); UI_SetActiveMenu( false );
Key_SetKeyDest( key_console ); Key_SetKeyDest( key_console );
Con_Printf( "Host_Error: %s", hosterror1 ); Con_Printf( "%s: %s", __func__, hosterror1 );
} }
else Platform_MessageBox( "Host Error", hosterror1, true ); else Platform_MessageBox( "Host Error", hosterror1, true );
} }
@@ -859,12 +805,12 @@ void GAME_EXPORT Host_Error( const char *error, ... )
if( recursive ) if( recursive )
{ {
Con_Printf( "Host_RecursiveError: %s", hosterror2 ); Con_Printf( "%sRecursive: %s", __func__, hosterror2 );
Sys_Error( "%s", hosterror1 ); Sys_Error( "%s", hosterror1 );
} }
recursive = true; recursive = true;
Q_strncpy( hosterror2, hosterror1, MAX_SYSPATH ); Q_strncpy( hosterror2, hosterror1, sizeof( hosterror2 ));
host.errorframe = host.framecount; // to avoid multply calls per frame host.errorframe = host.framecount; // to avoid multply calls per frame
Q_snprintf( host.finalmsg, sizeof( host.finalmsg ), "Server crashed: %s", hosterror1 ); Q_snprintf( host.finalmsg, sizeof( host.finalmsg ), "Server crashed: %s", hosterror1 );
@@ -958,15 +904,15 @@ static void Host_RunTests( int stage )
static uint32_t Host_CheckBugcomp( void ) static uint32_t Host_CheckBugcomp( void )
{ {
const char *prev, *next;
uint32_t flags = 0; uint32_t flags = 0;
string args, arg; string args, arg;
char *prev, *next;
size_t i; size_t i;
if( !Sys_CheckParm( "-bugcomp" )) if( !Sys_CheckParm( "-bugcomp" ))
return 0; return 0;
if( Sys_GetParmFromCmdLine( "-bugcomp", args ) && args[0] != '-' ) if( Sys_GetParmFromCmdLine( "-bugcomp", args ) && isalpha( args[0] ))
{ {
for( prev = args, next = Q_strchrnul( prev, '+' ); ; prev = next + 1, next = Q_strchrnul( prev, '+' )) for( prev = args, next = Q_strchrnul( prev, '+' ); ; prev = next + 1, next = Q_strchrnul( prev, '+' ))
{ {
@@ -1003,40 +949,59 @@ static uint32_t Host_CheckBugcomp( void )
return flags; return flags;
} }
static void Host_DetermineExecutableName( char *out, size_t size )
{
#if XASH_WIN32
char temp[MAX_SYSPATH];
if( GetModuleFileName( NULL, temp, sizeof( temp )))
COM_FileBase( temp, out, size );
#else
if( host.argc > 0 )
COM_FileBase( host.argv[0], out, size );
else
Q_strncpy( out, "xash", size );
#endif
}
/* /*
================= =================
Host_InitCommon Host_InitCommon
================= =================
*/ */
static void Host_InitCommon( int argc, char **argv, const char *progname, qboolean bChangeGame ) static void Host_InitCommon( int argc, char **argv, const char *progname, qboolean bChangeGame, char *exename, size_t exename_size )
{ {
char dev_level[4]; const char *basedir = progname[0] == '#' ? progname + 1 : progname;
int developer = DEFAULT_DEV; char dev_level[4], ticrate[16];
const char *baseDir; int developer = DEFAULT_DEV;
char ticrate[16];
int len, i;
// some commands may turn engine into infinite loop, // some commands may turn engine into infinite loop,
// e.g. xash.exe +game xash -game xash // e.g. xash.exe +game xash -game xash
// so we clear all cmd_args, but leave dbg states as well // so we clear all cmd_args, but leave dbg states as well
Sys_ParseCommandLine( argc, argv ); Sys_ParseCommandLine( argc, argv );
Host_DetermineExecutableName( exename, exename_size );
if( !Sys_CheckParm( "-disablehelp" ) ) if( !Sys_CheckParm( "-disablehelp" ))
{ {
if( Sys_CheckParm( "-help" ) || Sys_CheckParm( "-h" ) || Sys_CheckParm( "--help" ) ) if( Sys_CheckParm( "-help" ) || Sys_CheckParm( "-h" ) || Sys_CheckParm( "--help" ))
{ Sys_PrintUsage( exename );
Sys_PrintUsage();
}
} }
if( !Sys_CheckParm( "-noch" ) ) if( !Sys_CheckParm( "-noch" ))
Sys_SetupCrashHandler(); Sys_SetupCrashHandler();
#if XASH_DLL_LOADER
host.enabledll = !Sys_CheckParm( "-nodll" ); host.enabledll = !Sys_CheckParm( "-nodll" );
#endif
host.change_game = bChangeGame || Sys_CheckParm( "-changegame" ); host.change_game = bChangeGame || Sys_CheckParm( "-changegame" );
host.config_executed = false; host.config_executed = false;
host.status = HOST_INIT; // initialzation started host.status = HOST_INIT; // initialzation started
host.type = HOST_DEDICATED; // predict state
#ifndef XASH_DEDICATED
if( !Sys_CheckParm( "-dedicated" ))
host.type = HOST_NORMAL;
#endif
Memory_Init(); // init memory subsystem Memory_Init(); // init memory subsystem
@@ -1044,11 +1009,6 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
host.allow_console = DEFAULT_ALLOWCONSOLE; host.allow_console = DEFAULT_ALLOWCONSOLE;
// HACKHACK: Quake console is always allowed
// TODO: determine if we are running QWrap more reliable
if( !host.allow_console && ( Sys_CheckParm( "-console" ) || !Q_stricmp( SI.exeName, "quake" )))
host.allow_console = true;
if( Sys_CheckParm( "-dev" )) if( Sys_CheckParm( "-dev" ))
{ {
host.allow_console = true; host.allow_console = true;
@@ -1069,40 +1029,9 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
} }
#endif #endif
host.con_showalways = true; // always enable console for Quake and dedicated
if( !host.allow_console && ( Host_IsDedicated() || Sys_CheckParm( "-console" ) || !Q_strnicmp( exename, "quake", 5 )))
#if XASH_DEDICATED
host.type = HOST_DEDICATED; // predict state
#else
if( Sys_CheckParm("-dedicated") || progname[0] == '#' )
{
host.type = HOST_DEDICATED;
}
else
{
host.type = HOST_NORMAL;
}
#endif
// set default gamedir
if( progname[0] == '#' )
progname++;
Q_strncpy( SI.exeName, progname, sizeof( SI.exeName ));
Q_strncpy( SI.basedirName, progname, sizeof( SI.basedirName ));
if( Host_IsDedicated() )
{
Sys_MergeCommandLine( );
host.allow_console = true; host.allow_console = true;
}
else
{
// don't show console as default
if( developer <= DEV_NORMAL )
host.con_showalways = false;
}
// member console allowing // member console allowing
host.allow_console_init = host.allow_console; host.allow_console_init = host.allow_console;
@@ -1143,99 +1072,23 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
Host_RunTests( 0 ); Host_RunTests( 0 );
#endif #endif
Platform_Init(); Platform_Init( Host_IsDedicated( ) || developer >= DEV_EXTENDED );
FS_Init( basedir );
baseDir = getenv( "XASH3D_BASEDIR" );
if( COM_CheckString( baseDir ) )
{
Q_strncpy( host.rootdir, baseDir, sizeof( host.rootdir ));
}
else
{
#if TARGET_OS_IOS
Q_strncpy( host.rootdir, IOS_GetDocsDir(), sizeof( host.rootdir ));
#elif XASH_ANDROID && XASH_SDL
Q_strncpy( host.rootdir, SDL_AndroidGetExternalStoragePath(), sizeof( host.rootdir ));
#elif XASH_PSVITA
if ( !PSVita_GetBasePath( host.rootdir, sizeof( host.rootdir )))
{
Sys_Error( "couldn't find xash3d data directory" );
host.rootdir[0] = 0;
}
#elif (XASH_SDL == 2) && !XASH_NSWITCH // GetBasePath not impl'd in switch-sdl2
char *szBasePath = SDL_GetBasePath();
if( szBasePath )
{
Q_strncpy( host.rootdir, szBasePath, sizeof( host.rootdir ));
SDL_free( szBasePath );
}
else
{
#if XASH_POSIX || XASH_WIN32
if( !getcwd( host.rootdir, sizeof( host.rootdir )))
Sys_Error( "couldn't determine current directory: %s, getcwd: %s", SDL_GetError(), strerror( errno ));
#else
Sys_Error( "couldn't determine current directory: %s", SDL_GetError() );
#endif
}
#else
if( !getcwd( host.rootdir, sizeof( host.rootdir )))
{
Sys_Error( "couldn't determine current directory: %s", strerror( errno ) );
host.rootdir[0] = 0;
}
#endif
}
#if XASH_WIN32
COM_FixSlashes( host.rootdir );
#endif
len = Q_strlen( host.rootdir );
if( len && host.rootdir[len - 1] == '/' )
host.rootdir[len - 1] = 0;
// get readonly root. The order is: check for arg, then env.
// if still not got it, rodir is disabled.
host.rodir[0] = '\0';
if( !Sys_GetParmFromCmdLine( "-rodir", host.rodir ))
{
char *roDir = getenv( "XASH3D_RODIR" );
if( COM_CheckString( roDir ))
Q_strncpy( host.rodir, roDir, sizeof( host.rodir ));
}
#if XASH_WIN32
COM_FixSlashes( host.rootdir );
#endif
len = Q_strlen( host.rodir );
if( len && host.rodir[len - 1] == '/' )
host.rodir[len - 1] = 0;
if( !COM_CheckStringEmpty( host.rootdir ))
{
Sys_Error( "Changing working directory failed (empty working directory)\n" );
return;
}
FS_LoadProgs();
// TODO: this function will cause engine to stop in case of fail
// when it will have an option to return string error, restore Sys_Error
FS_SetCurrentDirectory( host.rootdir );
FS_Init();
Sys_InitLog(); Sys_InitLog();
// print current developer level to simplify processing users feedback // print current developer level to simplify processing users feedback
if( developer > 0 ) 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(); host.bugcomp = Host_CheckBugcomp();
@@ -1254,39 +1107,14 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
FS_LoadGameInfo( NULL ); FS_LoadGameInfo( NULL );
Cvar_PostFSInit(); Cvar_PostFSInit();
Q_strncpy( host.gamefolder, GI->gamefolder, sizeof( host.gamefolder ));
for( i = 0; i < 3; i++ )
{
const char *rcName;
switch( i )
{
case 0: rcName = SI.basedirName; break; // e.g. valve.rc
case 1: rcName = SI.exeName; break; // e.g. quake.rc
case 2: rcName = host.gamefolder; break; // e.g. game.rc (ran from default launcher)
}
if( FS_FileExists( va( "%s.rc", rcName ), false ))
{
Q_strncpy( SI.rcName, rcName, sizeof( SI.rcName ));
break;
}
}
Image_CheckPaletteQ1 (); Image_CheckPaletteQ1 ();
// NOTE: only once resource without which engine can't continue work
if( !FS_FileExists( "gfx/conchars", false ))
Sys_Error( "%s: couldn't load gfx.wad\n", __func__ );
Host_InitDecals (); // reload decals Host_InitDecals (); // reload decals
// DEPRECATED: by FWGS fork
#if 0
if( GI->secure )
{
// clear all developer levels when game is protected
Cvar_DirectSet( &host_developer, "0" );
host.allow_console_init = false;
host.con_showalways = false;
host.allow_console = false;
}
#endif
HPAK_Init(); HPAK_Init();
IN_Init(); IN_Init();
@@ -1310,13 +1138,13 @@ Host_Main
int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGame, pfnChangeGame func ) int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGame, pfnChangeGame func )
{ {
static double oldtime, newtime; static double oldtime, newtime;
string demoname; string demoname, exename;
host.starttime = Sys_DoubleTime(); host.starttime = Sys_DoubleTime();
pChangeGame = func; // may be NULL pChangeGame = func; // may be NULL
Host_InitCommon( argc, argv, progname, bChangeGame ); Host_InitCommon( argc, argv, progname, bChangeGame, exename, sizeof( exename ));
// init commands and vars // init commands and vars
if( host_developer.value >= DEV_EXTENDED ) if( host_developer.value >= DEV_EXTENDED )
@@ -1326,6 +1154,7 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
Cmd_AddRestrictedCommand ( "crash", Host_Crash_f, "a way to force a bus error for development reasons"); Cmd_AddRestrictedCommand ( "crash", Host_Crash_f, "a way to force a bus error for development reasons");
} }
Cvar_RegisterVariable( &host_allow_materials );
Cvar_RegisterVariable( &host_serverstate ); Cvar_RegisterVariable( &host_serverstate );
Cvar_RegisterVariable( &host_maxfps ); Cvar_RegisterVariable( &host_maxfps );
Cvar_RegisterVariable( &host_framerate ); Cvar_RegisterVariable( &host_framerate );
@@ -1365,21 +1194,25 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
ID_Init(); ID_Init();
SoundList_Init(); SoundList_Init();
if( Host_IsDedicated() ) if( Host_IsDedicated( ))
{ {
#ifdef _WIN32 #ifdef _WIN32
Wcon_InitConsoleCommands (); Wcon_InitConsoleCommands ();
#endif #endif
// disable texture replacements for dedicated
Cvar_FullSet( "host_allow_materials", "0", FCVAR_READ_ONLY );
Cmd_AddRestrictedCommand( "quit", Sys_Quit, "quit the game" ); Cmd_AddRestrictedCommand( "quit", Sys_Quit, "quit the game" );
Cmd_AddRestrictedCommand( "exit", Sys_Quit, "quit the game" ); Cmd_AddRestrictedCommand( "exit", Sys_Quit, "quit the game" );
} }
else Cmd_AddRestrictedCommand( "minimize", Host_Minimize_f, "minimize main window to tray" ); else Cmd_AddRestrictedCommand( "minimize", Host_Minimize_f, "minimize main window to tray" );
HPAK_CheckIntegrity( CUSTOM_RES_PATH );
host.errorframe = 0; host.errorframe = 0;
if( progname[0] == '#' )
progname++;
// post initializations // post initializations
switch( host.type ) switch( host.type )
{ {
@@ -1388,8 +1221,14 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
Wcon_ShowConsole( false ); // hide console Wcon_ShowConsole( false ); // hide console
#endif #endif
// execute startup config and cmdline // execute startup config and cmdline
Cbuf_AddTextf( "exec %s.rc\n", SI.rcName ); if( FS_FileExists( va( "%s.rc", progname ), false )) // e.g. valve.rc
Cbuf_AddTextf( "exec %s.rc", progname );
else if( FS_FileExists( va( "%s.rc", exename ), false )) // e.g. quake.rc
Cbuf_AddTextf( "exec %s.rc", exename );
else if( FS_FileExists( va( "%s.rc", GI->gamefolder ), false )) // e.g. game.rc (ran from default launcher)
Cbuf_AddTextf( "exec %s.rc", GI->gamefolder );
Cbuf_Execute(); Cbuf_Execute();
if( !host.config_executed ) if( !host.config_executed )
{ {
Cbuf_AddText( "exec config.cfg\n" ); Cbuf_AddText( "exec config.cfg\n" );
@@ -1433,6 +1272,9 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
Cbuf_Execute(); Cbuf_Execute();
} }
// check after all configs were executed
HPAK_CheckIntegrity( hpk_custom_file.string );
// main window message loop // main window message loop
while( !host.crashed ) while( !host.crashed )
{ {

View File

@@ -16,6 +16,8 @@ GNU General Public License for more details.
#include "common.h" #include "common.h"
#include "platform/platform.h" #include "platform/platform.h"
static jmp_buf g_abortframe;
void COM_InitHostState( void ) void COM_InitHostState( void )
{ {
memset( GameState, 0, sizeof( game_status_t )); memset( GameState, 0, sizeof( game_status_t ));
@@ -58,6 +60,9 @@ void COM_NewGame( char const *pMapName )
GameState->loadGame = false; GameState->loadGame = false;
GameState->newGame = true; GameState->newGame = true;
if( !SV_Active( ))
CL_Disconnect( ); // disconnect from current online game
SV_ShutdownGame(); // exit from current game SV_ShutdownGame(); // exit from current game
} }
@@ -77,6 +82,9 @@ void COM_LoadLevel( char const *pMapName, qboolean background )
GameState->loadGame = false; GameState->loadGame = false;
GameState->newGame = false; GameState->newGame = false;
if( !SV_Active( ))
CL_Disconnect( ); // disconnect from current online game
SV_ShutdownGame(); // exit from current game SV_ShutdownGame(); // exit from current game
} }
@@ -93,6 +101,9 @@ void COM_LoadGame( char const *pMapName )
GameState->backgroundMap = false; GameState->backgroundMap = false;
GameState->newGame = false; GameState->newGame = false;
GameState->loadGame = true; GameState->loadGame = true;
if( !SV_Active( ))
CL_Disconnect( ); // disconnect from current online game
} }
void COM_ChangeLevel( char const *pNewLevel, char const *pLandmarkName, qboolean background ) void COM_ChangeLevel( char const *pNewLevel, char const *pLandmarkName, qboolean background )
@@ -137,7 +148,7 @@ static void Host_ShutdownGame( void )
} }
} }
static void Host_RunFrame( float time ) static void Host_RunFrame( double time )
{ {
// at this time, we don't need to get events from OS on dedicated // at this time, we don't need to get events from OS on dedicated
#if !XASH_DEDICATED #if !XASH_DEDICATED
@@ -168,11 +179,23 @@ static void Host_RunFrame( float time )
} }
} }
void COM_Frame( float time ) /*
================
Host_AbortCurrentFrame
aborts the current host frame and goes on with the next one
================
*/
void Host_AbortCurrentFrame( void )
{
longjmp( g_abortframe, 1 );
}
void COM_Frame( double time )
{ {
int loopCount = 0; int loopCount = 0;
if( setjmp( host.abortframe )) if( setjmp( g_abortframe ))
return; return;
while( 1 ) while( 1 )

View File

@@ -17,8 +17,6 @@ GNU General Public License for more details.
#include "hpak.h" #include "hpak.h"
#define HPAK_MAX_ENTRIES 0x8000 #define HPAK_MAX_ENTRIES 0x8000
#define HPAK_ENTRY_MIN_SIZE (512)
#define HPAK_ENTRY_MAX_SIZE (128 * 1024)
typedef struct hash_pack_queue_s typedef struct hash_pack_queue_s
{ {
@@ -29,11 +27,17 @@ typedef struct hash_pack_queue_s
struct hash_pack_queue_s *next; struct hash_pack_queue_s *next;
} hash_pack_queue_t; } hash_pack_queue_t;
static CVAR_DEFINE_AUTO( hpk_maxsize, "4", FCVAR_ARCHIVE, "set limit by size for all HPK-files ( 0 - unlimited )" ); static CVAR_DEFINE( hpk_maxsize, "hpk_max_size", "64", FCVAR_ARCHIVE|FCVAR_PRIVILEGED, "set limit by size for all HPK-files in megabytes ( 0 - unlimited )" );
CVAR_DEFINE_AUTO( hpk_custom_file, "custom.hpk", FCVAR_ARCHIVE|FCVAR_PRIVILEGED, "set custom path for players customizations cache file" );
static hash_pack_queue_t *gp_hpak_queue = NULL; static hash_pack_queue_t *gp_hpak_queue = NULL;
static hpak_header_t hash_pack_header; static hpak_header_t hash_pack_header;
static hpak_info_t hash_pack_info; static hpak_info_t hash_pack_info;
static void HPAK_MaxSize_f( void )
{
Con_Printf( S_ERROR "hpk_maxsize is deprecated, use hpk_max_size\n" );
}
static const char *HPAK_TypeFromIndex( int type ) static const char *HPAK_TypeFromIndex( int type )
{ {
switch( type ) switch( type )
@@ -73,7 +77,7 @@ static void HPAK_AddToQueue( const char *name, resource_t *pResource, void *data
if( data != NULL ) memcpy( p->data, data, p->size ); if( data != NULL ) memcpy( p->data, data, p->size );
else if( f != NULL ) FS_Read( f, p->data, p->size ); else if( f != NULL ) FS_Read( f, p->data, p->size );
else Host_Error( "HPAK_AddToQueue: data == NULL.\n" ); else Host_Error( "%s: data == NULL.\n", __func__ );
p->next = gp_hpak_queue; p->next = gp_hpak_queue;
gp_hpak_queue = p; gp_hpak_queue = p;
@@ -116,7 +120,7 @@ static void HPAK_CreatePak( const char *filename, resource_t *pResource, byte *p
fout = FS_Open( pakname, "wb", true ); fout = FS_Open( pakname, "wb", true );
if( !fout ) if( !fout )
{ {
Con_DPrintf( S_ERROR "HPAK_CreatePak: can't write %s.\n", pakname ); Con_DPrintf( S_ERROR "%s: can't write %s.\n", __func__, pakname );
return; return;
} }
@@ -145,7 +149,7 @@ static void HPAK_CreatePak( const char *filename, resource_t *pResource, byte *p
if( memcmp( md5, pResource->rgucMD5_hash, 16 )) if( memcmp( md5, pResource->rgucMD5_hash, 16 ))
{ {
Con_DPrintf( S_ERROR "HPAK_CreatePak: bad checksum for %s. Ignored\n", pakname ); Con_DPrintf( S_ERROR "%s: bad checksum for %s. Ignored\n", __func__, pakname );
return; return;
} }
@@ -246,7 +250,7 @@ void HPAK_AddLump( qboolean bUseQueue, const char *name, resource_t *pResource,
if( memcmp( md5, pResource->rgucMD5_hash, 16 )) if( memcmp( md5, pResource->rgucMD5_hash, 16 ))
{ {
Con_DPrintf( S_ERROR "HPAK_AddLump: bad checksum for %s. Ignored\n", pResource->szFileName ); Con_DPrintf( S_ERROR "%s: bad checksum for %s. Ignored\n", __func__, pResource->szFileName );
return; return;
} }
@@ -275,7 +279,7 @@ void HPAK_AddLump( qboolean bUseQueue, const char *name, resource_t *pResource,
if( !file_dst ) if( !file_dst )
{ {
Con_DPrintf( S_ERROR "HPAK_AddLump: couldn't open %s.\n", srcname ); Con_DPrintf( S_ERROR "%s: couldn't open %s.\n", __func__, srcname );
FS_Close( file_src ); FS_Close( file_src );
return; return;
} }
@@ -286,7 +290,7 @@ void HPAK_AddLump( qboolean bUseQueue, const char *name, resource_t *pResource,
if( hash_pack_header.version != IDHPAK_VERSION ) if( hash_pack_header.version != IDHPAK_VERSION )
{ {
// we don't check the HPAK bit for some reason. // we don't check the HPAK bit for some reason.
Con_DPrintf( S_ERROR "HPAK_AddLump: %s does not have a valid header.\n", srcname ); Con_DPrintf( S_ERROR "%s: %s does not have a valid header.\n", __func__, srcname );
FS_Close( file_src ); FS_Close( file_src );
FS_Close( file_dst ); FS_Close( file_dst );
return; return;
@@ -301,7 +305,7 @@ void HPAK_AddLump( qboolean bUseQueue, const char *name, resource_t *pResource,
if( srcpak.count < 1 || srcpak.count > HPAK_MAX_ENTRIES ) if( srcpak.count < 1 || srcpak.count > HPAK_MAX_ENTRIES )
{ {
Con_DPrintf( S_ERROR "HPAK_AddLump: %s contain too many lumps.\n", srcname ); Con_DPrintf( S_ERROR "%s: %s contain too many lumps.\n", __func__, srcname );
FS_Close( file_src ); FS_Close( file_src );
FS_Close( file_dst ); FS_Close( file_dst );
return; return;
@@ -410,7 +414,7 @@ static qboolean HPAK_Validate( const char *filename, qboolean quiet, qboolean de
FS_Read( f, &hdr, sizeof( hdr )); FS_Read( f, &hdr, sizeof( hdr ));
if( hdr.ident != IDHPAKHEADER || hdr.version != IDHPAK_VERSION ) if( hdr.ident != IDHPAKHEADER || hdr.version != IDHPAK_VERSION )
{ {
Con_DPrintf( S_ERROR "HPAK_ValidatePak: %s does not have a valid HPAK header.\n", pakname ); Con_DPrintf( S_ERROR "%s: %s does not have a valid HPAK header.\n", __func__, pakname );
FS_Close( f ); FS_Close( f );
if( delete ) FS_Delete( pakname ); if( delete ) FS_Delete( pakname );
return false; return false;
@@ -421,7 +425,7 @@ static qboolean HPAK_Validate( const char *filename, qboolean quiet, qboolean de
if( num_lumps < 1 || num_lumps > HPAK_MAX_ENTRIES ) if( num_lumps < 1 || num_lumps > HPAK_MAX_ENTRIES )
{ {
Con_DPrintf( S_ERROR "HPAK_ValidatePak: %s has too many lumps %u.\n", pakname, num_lumps ); Con_DPrintf( S_ERROR "%s: %s has too many lumps %u.\n", __func__, pakname, num_lumps );
FS_Close( f ); FS_Close( f );
if( delete ) FS_Delete( pakname ); if( delete ) FS_Delete( pakname );
return false; return false;
@@ -439,7 +443,7 @@ static qboolean HPAK_Validate( const char *filename, qboolean quiet, qboolean de
if( dataDir[i].disksize < HPAK_ENTRY_MIN_SIZE || dataDir[i].disksize > HPAK_ENTRY_MAX_SIZE ) if( dataDir[i].disksize < HPAK_ENTRY_MIN_SIZE || dataDir[i].disksize > HPAK_ENTRY_MAX_SIZE )
{ {
// odd max size // odd max size
Con_DPrintf( S_ERROR "HPAK_ValidatePak: lump %i has invalid size %s\n", i, Q_pretifymem( dataDir[i].disksize, 2 )); Con_DPrintf( S_ERROR "%s: lump %i has invalid size %s\n", __func__, i, Q_pretifymem( dataDir[i].disksize, 2 ));
Mem_Free( dataDir ); Mem_Free( dataDir );
FS_Close( f ); FS_Close( f );
if( delete ) FS_Delete( pakname ); if( delete ) FS_Delete( pakname );
@@ -467,7 +471,7 @@ static qboolean HPAK_Validate( const char *filename, qboolean quiet, qboolean de
{ {
if( quiet ) if( quiet )
{ {
Con_DPrintf( S_ERROR "HPAK_ValidatePak: %s has invalid checksum.\n", pakname ); Con_DPrintf( S_ERROR "%s: %s has invalid checksum.\n", __func__, pakname );
Mem_Free( dataPak ); Mem_Free( dataPak );
Mem_Free( dataDir ); Mem_Free( dataDir );
FS_Close( f ); FS_Close( f );
@@ -517,7 +521,7 @@ void HPAK_CheckSize( const char *filename )
Q_strncpy( pakname, filename, sizeof( pakname )); Q_strncpy( pakname, filename, sizeof( pakname ));
COM_ReplaceExtension( pakname, ".hpk", sizeof( pakname )); COM_ReplaceExtension( pakname, ".hpk", sizeof( pakname ));
if( FS_FileSize( pakname, false ) > ( maxsize * 1048576 )) if( FS_FileSize( pakname, false ) > ( maxsize * 1024 * 1024 ))
{ {
Con_Printf( "Server: Size of %s > %f MB, deleting.\n", filename, hpk_maxsize.value ); Con_Printf( "Server: Size of %s > %f MB, deleting.\n", filename, hpk_maxsize.value );
Log_Printf( "Server: Size of %s > %f MB, deleting.\n", filename, hpk_maxsize.value ); Log_Printf( "Server: Size of %s > %f MB, deleting.\n", filename, hpk_maxsize.value );
@@ -708,7 +712,7 @@ qboolean HPAK_GetDataPointer( const char *filename, resource_t *pResource, byte
if( directory.count < 1 || directory.count > HPAK_MAX_ENTRIES ) if( directory.count < 1 || directory.count > HPAK_MAX_ENTRIES )
{ {
Con_DPrintf( S_ERROR "HPAK_GetDataPointer: %s has too many lumps %u.\n", filename, directory.count ); Con_DPrintf( S_ERROR "%s: %s has too many lumps %u.\n", __func__, filename, directory.count );
FS_Close( f ); FS_Close( f );
return false; return false;
} }
@@ -1101,7 +1105,9 @@ void HPAK_Init( void )
Cmd_AddRestrictedCommand( "hpkremove", HPAK_Remove_f, "remove specified file from HPK-file" ); Cmd_AddRestrictedCommand( "hpkremove", HPAK_Remove_f, "remove specified file from HPK-file" );
Cmd_AddRestrictedCommand( "hpkval", HPAK_Validate_f, "validate specified HPK-file" ); Cmd_AddRestrictedCommand( "hpkval", HPAK_Validate_f, "validate specified HPK-file" );
Cmd_AddRestrictedCommand( "hpkextract", HPAK_Extract_f, "extract all lumps from specified HPK-file" ); Cmd_AddRestrictedCommand( "hpkextract", HPAK_Extract_f, "extract all lumps from specified HPK-file" );
Cmd_AddRestrictedCommand( "hpk_maxsize", HPAK_MaxSize_f, "deprecation notice for hpk_maxsize" );
Cvar_RegisterVariable( &hpk_maxsize ); Cvar_RegisterVariable( &hpk_maxsize );
Cvar_RegisterVariable( &hpk_custom_file );
gp_hpak_queue = NULL; gp_hpak_queue = NULL;
} }

View File

@@ -17,6 +17,9 @@ GNU General Public License for more details.
#include "custom.h" #include "custom.h"
#define HPAK_ENTRY_MIN_SIZE (512)
#define HPAK_ENTRY_MAX_SIZE (256 * 1024)
/* /*
======================================================================== ========================================================================
.HPK archive format (Hash PAK - HPK) .HPK archive format (Hash PAK - HPK)
@@ -64,7 +67,7 @@ typedef struct dresource_s
} dresource_t; } dresource_t;
#pragma pack( pop ) #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 typedef struct
{ {
@@ -73,6 +76,8 @@ typedef struct
int infotableofs; int infotableofs;
} hpak_header_t; } hpak_header_t;
STATIC_CHECK_SIZEOF( hpak_header_t, 12, 12 );
typedef struct typedef struct
{ {
dresource_t resource; dresource_t resource;
@@ -80,6 +85,8 @@ typedef struct
int disksize; int disksize;
} hpak_lump_t; } hpak_lump_t;
STATIC_CHECK_SIZEOF( hpak_lump_t, 144, 144 );
typedef struct typedef struct
{ {
int count; int count;

View File

@@ -13,6 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
*/ */
#include <inttypes.h>
#include "common.h" #include "common.h"
#include <fcntl.h> #include <fcntl.h>
#if !XASH_WIN32 #if !XASH_WIN32
@@ -104,7 +105,7 @@ static void ID_BloomFilter_f( void )
for( i = 1; i < Cmd_Argc(); i++ ) for( i = 1; i < Cmd_Argc(); i++ )
value |= BloomFilter_ProcessStr( Cmd_Argv( i ) ); value |= BloomFilter_ProcessStr( Cmd_Argv( i ) );
Msg( "%d %016llX\n", BloomFilter_Weight( value ), value ); Msg( "%d %016"PRIX64"\n", BloomFilter_Weight( value ), value );
// test // test
// for( i = 1; i < Cmd_Argc(); i++ ) // for( i = 1; i < Cmd_Argc(); i++ )
@@ -283,7 +284,7 @@ static void ID_TestCPUInfo_f( void )
bloomfilter_t value = 0; bloomfilter_t value = 0;
if( ID_ProcessCPUInfo( &value ) ) if( ID_ProcessCPUInfo( &value ) )
Msg( "Got %016llX\n", value ); Msg( "Got %016"PRIX64"\n", value );
else else
Msg( "Could not get serial\n" ); Msg( "Could not get serial\n" );
} }
@@ -555,7 +556,7 @@ static uint ID_CheckRawId( bloomfilter_t filter )
} }
#endif #endif
#if 0 #if 0
Msg( "ID_CheckRawId: %d\n", count ); Msg( "%s: %d\n", __func__, count );
#endif #endif
return count; return count;
} }
@@ -575,7 +576,7 @@ static void ID_Check( void )
{ {
id = 0; id = 0;
#if 0 #if 0
Msg( "ID_Check(): fail %d\n", weight ); Msg( "%s: fail %d\n", __func__, weight );
#endif #endif
return; return;
} }
@@ -583,7 +584,7 @@ static void ID_Check( void )
if( ID_CheckRawId( id ) < mincount ) if( ID_CheckRawId( id ) < mincount )
id = 0; id = 0;
#if 0 #if 0
Msg( "ID_Check(): success %d\n", weight ); Msg( "%s: success %d\n", __func__, weight );
#endif #endif
} }
@@ -621,7 +622,7 @@ void ID_Init( void )
#endif #endif
#if XASH_ANDROID && !XASH_DEDICATED #if XASH_ANDROID && !XASH_DEDICATED
sscanf( Android_LoadID(), "%016llX", &id ); sscanf( Android_LoadID(), "%016"PRIX64, &id );
if( id ) if( id )
{ {
id ^= SYSTEM_XOR_MASK; id ^= SYSTEM_XOR_MASK;
@@ -633,7 +634,7 @@ void ID_Init( void )
CHAR szBuf[MAX_PATH]; CHAR szBuf[MAX_PATH];
ID_GetKeyData( HKEY_CURRENT_USER, "Software\\Xash3D\\", "xash_id", szBuf, MAX_PATH ); ID_GetKeyData( HKEY_CURRENT_USER, "Software\\Xash3D\\", "xash_id", szBuf, MAX_PATH );
sscanf(szBuf, "%016llX", &id); sscanf(szBuf, "%016"PRIX64, &id);
id ^= SYSTEM_XOR_MASK; id ^= SYSTEM_XOR_MASK;
ID_Check(); ID_Check();
} }
@@ -649,7 +650,7 @@ void ID_Init( void )
cfg = fopen( va( "%s/.xash_id", home ), "r" ); cfg = fopen( va( "%s/.xash_id", home ), "r" );
if( cfg ) if( cfg )
{ {
if( fscanf( cfg, "%016llX", &id ) > 0 ) if( fscanf( cfg, "%016"PRIX64, &id ) > 0 )
{ {
id ^= SYSTEM_XOR_MASK; id ^= SYSTEM_XOR_MASK;
ID_Check(); ID_Check();
@@ -664,7 +665,7 @@ void ID_Init( void )
const char *buf = (const char*) FS_LoadFile( ".xash_id", NULL, false ); const char *buf = (const char*) FS_LoadFile( ".xash_id", NULL, false );
if( buf ) if( buf )
{ {
sscanf( buf, "%016llX", &id ); sscanf( buf, "%016"PRIX64, &id );
id ^= GAME_XOR_MASK; id ^= GAME_XOR_MASK;
ID_Check(); ID_Check();
} }
@@ -680,11 +681,11 @@ void ID_Init( void )
Q_snprintf( &id_md5[i*2], sizeof( id_md5 ) - i * 2, "%02hhx", md5[i] ); Q_snprintf( &id_md5[i*2], sizeof( id_md5 ) - i * 2, "%02hhx", md5[i] );
#if XASH_ANDROID && !XASH_DEDICATED #if XASH_ANDROID && !XASH_DEDICATED
Android_SaveID( va("%016llX", id^SYSTEM_XOR_MASK ) ); Android_SaveID( va("%016"PRIX64, id^SYSTEM_XOR_MASK ) );
#elif XASH_WIN32 #elif XASH_WIN32
{ {
CHAR Buf[MAX_PATH]; CHAR Buf[MAX_PATH];
sprintf( Buf, "%016llX", id^SYSTEM_XOR_MASK ); sprintf( Buf, "%016"PRIX64, id^SYSTEM_XOR_MASK );
ID_SetKeyData( HKEY_CURRENT_USER, "Software\\Xash3D\\", REG_SZ, "xash_id", Buf, Q_strlen(Buf) ); ID_SetKeyData( HKEY_CURRENT_USER, "Software\\Xash3D\\", REG_SZ, "xash_id", Buf, Q_strlen(Buf) );
} }
#else #else
@@ -699,14 +700,14 @@ void ID_Init( void )
cfg = fopen( va( "%s/.xash_id", home ), "w" ); cfg = fopen( va( "%s/.xash_id", home ), "w" );
if( cfg ) if( cfg )
{ {
fprintf( cfg, "%016llX", id^SYSTEM_XOR_MASK ); fprintf( cfg, "%016"PRIX64, id^SYSTEM_XOR_MASK );
fclose( cfg ); fclose( cfg );
} }
} }
} }
#endif #endif
FS_WriteFile( ".xash_id", va("%016llX", id^GAME_XOR_MASK), 16 ); FS_WriteFile( ".xash_id", va("%016"PRIX64, id^GAME_XOR_MASK), 16 );
#if 0 #if 0
Msg("MD5 id: %s\nRAW id:%016llX\n", id_md5, id ); Msg("MD5 id: %s\nRAW id:%016"PRIX64"\n", id_md5, id );
#endif #endif
} }

View File

@@ -103,17 +103,18 @@ typedef struct imglib_s
#define IMAGE_MAXHEIGHT 8192 #define IMAGE_MAXHEIGHT 8192
#define LUMP_MAXWIDTH 1024 // WorldCraft limits #define LUMP_MAXWIDTH 1024 // WorldCraft limits
#define LUMP_MAXHEIGHT 1024 #define LUMP_MAXHEIGHT 1024
#define PLDECAL_MAXWIDTH 512 #define PLDECAL_MAXWIDTH 768 // total of ~2mb uncompressed rgba data
#define PLDECAL_MAXHEIGHT 512 #define PLDECAL_MAXHEIGHT 768
enum enum
{ {
LUMP_NORMAL = 0, // no alpha LUMP_NORMAL = 0, // no alpha
LUMP_MASKED, // 1-bit alpha channel masked texture LUMP_MASKED, // 1-bit alpha channel masked texture
LUMP_GRADIENT, // gradient image (decals) LUMP_GRADIENT, // gradient image (decals)
LUMP_EXTENDED, // bmp images have extened palette with alpha-channel LUMP_EXTENDED, // bmp images have extened palette with alpha-channel
LUMP_HALFLIFE, // get predefined half-life palette LUMP_HALFLIFE, // get predefined half-life palette
LUMP_QUAKE1 // get predefined quake palette LUMP_QUAKE1, // get predefined quake palette
LUMP_TEXGAMMA, // apply texgamma on top of palette, for half-life mips
}; };
enum enum

View File

@@ -35,7 +35,7 @@ qboolean Image_LoadBMP( const char *name, const byte *buffer, fs_offset_t filesi
if( filesize < sizeof( bhdr )) if( filesize < sizeof( bhdr ))
{ {
Con_Reportf( S_ERROR "Image_LoadBMP: %s have incorrect file size %li should be greater than %li (header)\n", name, filesize, sizeof( bhdr ) ); Con_Reportf( S_ERROR "%s: %s have incorrect file size %li should be greater than %zu (header)\n", __func__, name, (long)filesize, sizeof( bhdr ));
return false; return false;
} }
@@ -49,13 +49,13 @@ qboolean Image_LoadBMP( const char *name, const byte *buffer, fs_offset_t filesi
if( memcmp( bhdr.id, "BM", 2 )) if( memcmp( bhdr.id, "BM", 2 ))
{ {
Con_DPrintf( S_ERROR "Image_LoadBMP: only Windows-style BMP files supported (%s)\n", name ); Con_DPrintf( S_ERROR "%s: only Windows-style BMP files supported (%s)\n", __func__, name );
return false; return false;
} }
if(!( bhdr.bitmapHeaderSize == 40 || bhdr.bitmapHeaderSize == 108 || bhdr.bitmapHeaderSize == 124 )) if(!( bhdr.bitmapHeaderSize == 40 || bhdr.bitmapHeaderSize == 108 || bhdr.bitmapHeaderSize == 124 ))
{ {
Con_DPrintf( S_ERROR "Image_LoadBMP: %s have non-standard header size %i\n", name, bhdr.bitmapHeaderSize ); Con_DPrintf( S_ERROR "%s: %s have non-standard header size %i\n", __func__, name, bhdr.bitmapHeaderSize );
return false; return false;
} }
@@ -63,7 +63,7 @@ qboolean Image_LoadBMP( const char *name, const byte *buffer, fs_offset_t filesi
if( bhdr.fileSize != filesize ) if( bhdr.fileSize != filesize )
{ {
// Sweet Half-Life issues. splash.bmp have bogus filesize // Sweet Half-Life issues. splash.bmp have bogus filesize
Con_Reportf( S_WARN "Image_LoadBMP: %s have incorrect file size %li should be %i\n", name, filesize, bhdr.fileSize ); Con_Reportf( S_WARN "%s: %s have incorrect file size %li should be %i\n", __func__, name, (long)filesize, bhdr.fileSize );
} }
// bogus compression? Only non-compressed supported. // bogus compression? Only non-compressed supported.
@@ -71,7 +71,7 @@ qboolean Image_LoadBMP( const char *name, const byte *buffer, fs_offset_t filesi
{ {
if( bhdr.bitsPerPixel != 32 || bhdr.compression != BI_BITFIELDS ) if( bhdr.bitsPerPixel != 32 || bhdr.compression != BI_BITFIELDS )
{ {
Con_DPrintf( S_ERROR "Image_LoadBMP: only uncompressed BMP files supported (%s)\n", name ); Con_DPrintf( S_ERROR "%s: only uncompressed BMP files supported (%s)\n", __func__, name );
return false; return false;
} }
} }
@@ -108,7 +108,7 @@ qboolean Image_LoadBMP( const char *name, const byte *buffer, fs_offset_t filesi
estimatedSize = ( buf_p - buffer ) + cbPalBytes; estimatedSize = ( buf_p - buffer ) + cbPalBytes;
if( filesize < estimatedSize ) if( filesize < estimatedSize )
{ {
Con_Reportf( S_ERROR "Image_LoadBMP: %s have incorrect file size %li should be greater than %li (palette)\n", name, filesize, estimatedSize ); Con_Reportf( S_ERROR "%s: %s have incorrect file size %li should be greater than %li (palette)\n", __func__, name, (long)filesize, (long)estimatedSize );
return false; return false;
} }
@@ -186,7 +186,7 @@ qboolean Image_LoadBMP( const char *name, const byte *buffer, fs_offset_t filesi
image.palette = NULL; image.palette = NULL;
} }
Con_Reportf( S_ERROR "Image_LoadBMP: %s have incorrect file size %li should be greater than %li (pixels)\n", name, filesize, estimatedSize ); Con_Reportf( S_ERROR "%s: %s have incorrect file size %li should be greater than %li (pixels)\n", __func__, name, (long)filesize, (long)estimatedSize );
return false; return false;
} }

View File

@@ -261,7 +261,7 @@ static uint Image_DXTCalcSize( const char *name, dds_t *hdr, size_t filesize )
if( filesize != buffsize ) // main check if( filesize != buffsize ) // main check
{ {
Con_DPrintf( S_WARN "Image_LoadDDS: (%s) probably corrupted (%zu should be %lu)\n", name, buffsize, filesize ); Con_DPrintf( S_WARN "%s: (%s) probably corrupted (%zu should be %zu)\n", __func__, name, buffsize, filesize );
if( buffsize > filesize ) if( buffsize > filesize )
return false; return false;
} }
@@ -300,13 +300,13 @@ qboolean Image_LoadDDS( const char *name, const byte *buffer, fs_offset_t filesi
if( header.dwSize != sizeof( header ) - sizeof( uint )) // size of the structure (minus MagicNum) if( header.dwSize != sizeof( header ) - sizeof( uint )) // size of the structure (minus MagicNum)
{ {
Con_DPrintf( S_ERROR "Image_LoadDDS: (%s) have corrupted header\n", name ); Con_DPrintf( S_ERROR "%s: (%s) have corrupted header\n", __func__, name );
return false; return false;
} }
if( header.dsPixelFormat.dwSize != sizeof( dds_pixf_t )) // size of the structure if( header.dsPixelFormat.dwSize != sizeof( dds_pixf_t )) // size of the structure
{ {
Con_DPrintf( S_ERROR "Image_LoadDDS: (%s) have corrupt pixelformat header\n", name ); Con_DPrintf( S_ERROR "%s: (%s) have corrupt pixelformat header\n", __func__, name );
return false; return false;
} }
@@ -334,7 +334,7 @@ qboolean Image_LoadDDS( const char *name, const byte *buffer, fs_offset_t filesi
if( image.type == PF_UNKNOWN ) if( image.type == PF_UNKNOWN )
{ {
Con_DPrintf( S_ERROR "Image_LoadDDS: (%s) has unrecognized type\n", name ); Con_DPrintf( S_ERROR "%s: (%s) has unrecognized type\n", __func__, name );
return false; return false;
} }

View File

@@ -78,49 +78,49 @@ static qboolean Image_KTX2Parse( const ktx2_header_t *header, const byte *buffer
if( image.type == PF_UNKNOWN ) if( image.type == PF_UNKNOWN )
{ {
Con_DPrintf( S_ERROR "%s: unsupported KTX2 format %d\n", __FUNCTION__, header->vkFormat ); Con_DPrintf( S_ERROR "%s: unsupported KTX2 format %d\n", __func__, header->vkFormat );
return false; return false;
} }
if( !Image_CheckFlag( IL_DDS_HARDWARE ) && ImageCompressed( image.type )) if( !Image_CheckFlag( IL_DDS_HARDWARE ) && ImageCompressed( image.type ))
{ {
Con_DPrintf( S_WARN "%s: has compressed format, but support is not advertized\n", __FUNCTION__ ); Con_DPrintf( S_WARN "%s: has compressed format, but support is not advertized\n", __func__ );
return false; return false;
} }
if( header->levelCount == 0 ) if( header->levelCount == 0 )
{ {
Con_DPrintf( S_ERROR "%s: file has no mip levels\n", __FUNCTION__ ); Con_DPrintf( S_ERROR "%s: file has no mip levels\n", __func__ );
return false; return false;
} }
if( header->pixelDepth > 1 ) if( header->pixelDepth > 1 )
{ {
Con_DPrintf( S_ERROR "%s: unsupported KTX2 pixelDepth %d\n", __FUNCTION__, header->pixelDepth ); Con_DPrintf( S_ERROR "%s: unsupported KTX2 pixelDepth %d\n", __func__, header->pixelDepth );
return false; return false;
} }
if( header->faceCount > 1 ) if( header->faceCount > 1 )
{ {
Con_DPrintf( S_ERROR "%s: unsupported KTX2 faceCount %d\n", __FUNCTION__, header->faceCount ); Con_DPrintf( S_ERROR "%s: unsupported KTX2 faceCount %d\n", __func__, header->faceCount );
return false; return false;
} }
if( header->layerCount > 1 ) if( header->layerCount > 1 )
{ {
Con_DPrintf( S_ERROR "%s: unsupported KTX2 layerCount %d\n", __FUNCTION__, header->layerCount ); Con_DPrintf( S_ERROR "%s: unsupported KTX2 layerCount %d\n", __func__, header->layerCount );
return false; return false;
} }
if( header->supercompressionScheme != 0 ) if( header->supercompressionScheme != 0 )
{ {
Con_DPrintf( S_ERROR "%s: unsupported KTX2 supercompressionScheme %d\n", __FUNCTION__, header->supercompressionScheme ); Con_DPrintf( S_ERROR "%s: unsupported KTX2 supercompressionScheme %d\n", __func__, header->supercompressionScheme );
return false; return false;
} }
if( header->levelCount * sizeof( ktx2_level_t ) + KTX2_LEVELS_OFFSET > filesize ) if( header->levelCount * sizeof( ktx2_level_t ) + KTX2_LEVELS_OFFSET > filesize )
{ {
Con_DPrintf( S_ERROR "%s: file abruptly ends\n", __FUNCTION__ ); Con_DPrintf( S_ERROR "%s: file abruptly ends\n", __func__ );
return false; return false;
} }
@@ -138,7 +138,7 @@ static qboolean Image_KTX2Parse( const ktx2_header_t *header, const byte *buffer
if( mip_size != level.byteLength ) if( mip_size != level.byteLength )
{ {
Con_DPrintf( S_ERROR "%s: mip=%d size mismatch read=%d, but computed=%d\n", Con_DPrintf( S_ERROR "%s: mip=%d size mismatch read=%d, but computed=%d\n",
__FUNCTION__, mip, (int)level.byteLength, mip_size ); __func__, mip, (int)level.byteLength, mip_size );
return false; return false;
} }
@@ -175,7 +175,7 @@ qboolean Image_LoadKTX2( const char *name, const byte *buffer, fs_offset_t files
if( memcmp( buffer, KTX2_IDENTIFIER, KTX2_IDENTIFIER_SIZE ) != 0 ) if( memcmp( buffer, KTX2_IDENTIFIER, KTX2_IDENTIFIER_SIZE ) != 0 )
{ {
Con_DPrintf( S_ERROR "%s: (%s) has invalid identifier\n", __FUNCTION__, name ); Con_DPrintf( S_ERROR "%s: (%s) has invalid identifier\n", __func__, name );
return false; return false;
} }
@@ -196,7 +196,7 @@ qboolean Image_LoadKTX2( const char *name, const byte *buffer, fs_offset_t files
// If KTX2 to imagelib conversion failed, try passing the file as raw data. // If KTX2 to imagelib conversion failed, try passing the file as raw data.
// This is useful for ref_vk which can directly support hundreds of formats which we don't convert to pixformat_t here // This is useful for ref_vk which can directly support hundreds of formats which we don't convert to pixformat_t here
Con_DPrintf( S_WARN "%s: (%s) could not be converted to supported imagelib format, passing as raw KTX2 data\n", __FUNCTION__, name ); Con_DPrintf( S_WARN "%s: (%s) could not be converted to supported imagelib format, passing as raw KTX2 data\n", __func__, name );
// This is a catch-all for ref_vk, which can do this format directly and natively // This is a catch-all for ref_vk, which can do this format directly and natively
image.type = PF_KTX2_RAW; image.type = PF_KTX2_RAW;

View File

@@ -110,7 +110,7 @@ void Image_Reset( void )
image.size = 0; image.size = 0;
} }
static rgbdata_t *ImagePack( void ) static MALLOC_LIKE( FS_FreeImage, 1 ) rgbdata_t *ImagePack( void )
{ {
rgbdata_t *pack; rgbdata_t *pack;
@@ -360,7 +360,7 @@ load_internal:
} }
if( loadname[0] != '#' ) if( loadname[0] != '#' )
Con_Reportf( S_WARN "FS_LoadImage: couldn't load \"%s\"\n", loadname ); Con_Reportf( S_WARN "%s: couldn't load \"%s\"\n", __func__, loadname );
// clear any force flags // clear any force flags
image.force_flags = 0; image.force_flags = 0;
@@ -547,7 +547,7 @@ static void Test_CheckImage( const char *name, rgbdata_t *rgb )
TASSERT( load->size == rgb->size ) TASSERT( load->size == rgb->size )
TASSERT( memcmp(load->buffer, rgb->buffer, rgb->size ) == 0 ) TASSERT( memcmp(load->buffer, rgb->buffer, rgb->size ) == 0 )
Mem_Free( load ); FS_FreeImage( load );
} }
void Test_RunImagelib( void ) void Test_RunImagelib( void )

View File

@@ -63,7 +63,7 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
// check png signature // check png signature
if( memcmp( png_hdr.sign, png_sign, sizeof( png_sign ) ) ) if( memcmp( png_hdr.sign, png_sign, sizeof( png_sign ) ) )
{ {
Con_DPrintf( S_ERROR "Image_LoadPNG: Invalid PNG signature (%s)\n", name ); Con_DPrintf( S_ERROR "%s: Invalid PNG signature (%s)\n", __func__, name );
return false; return false;
} }
@@ -73,14 +73,14 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
// check IHDR chunk length (valid value - 13) // check IHDR chunk length (valid value - 13)
if( png_hdr.ihdr_len != sizeof( png_ihdr_t ) ) if( png_hdr.ihdr_len != sizeof( png_ihdr_t ) )
{ {
Con_DPrintf( S_ERROR "Image_LoadPNG: Invalid IHDR chunk size %u (%s)\n", png_hdr.ihdr_len, name ); Con_DPrintf( S_ERROR "%s: Invalid IHDR chunk size %u (%s)\n", __func__, png_hdr.ihdr_len, name );
return false; return false;
} }
// check IHDR chunk signature // check IHDR chunk signature
if( memcmp( png_hdr.ihdr_sign, ihdr_sign, sizeof( ihdr_sign ) ) ) if( memcmp( png_hdr.ihdr_sign, ihdr_sign, sizeof( ihdr_sign ) ) )
{ {
Con_DPrintf( S_ERROR "Image_LoadPNG: IHDR chunk corrupted (%s)\n", name ); Con_DPrintf( S_ERROR "%s: IHDR chunk corrupted (%s)\n", __func__, name );
return false; return false;
} }
@@ -90,7 +90,7 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
if( png_hdr.ihdr_chunk.height == 0 || png_hdr.ihdr_chunk.width == 0 ) if( png_hdr.ihdr_chunk.height == 0 || png_hdr.ihdr_chunk.width == 0 )
{ {
Con_DPrintf( S_ERROR "Image_LoadPNG: Invalid image size %ux%u (%s)\n", png_hdr.ihdr_chunk.width, png_hdr.ihdr_chunk.height, name ); Con_DPrintf( S_ERROR "%s: Invalid image size %ux%u (%s)\n", __func__, png_hdr.ihdr_chunk.width, png_hdr.ihdr_chunk.height, name );
return false; return false;
} }
@@ -99,7 +99,7 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
if( png_hdr.ihdr_chunk.bitdepth != 8 ) if( png_hdr.ihdr_chunk.bitdepth != 8 )
{ {
Con_DPrintf( S_WARN "Image_LoadPNG: Only 8-bit images is supported (%s)\n", name ); Con_DPrintf( S_WARN "%s: Only 8-bit images is supported (%s)\n", __func__, name );
return false; return false;
} }
@@ -109,31 +109,31 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
|| png_hdr.ihdr_chunk.colortype == PNG_CT_ALPHA || png_hdr.ihdr_chunk.colortype == PNG_CT_ALPHA
|| png_hdr.ihdr_chunk.colortype == PNG_CT_PALLETE ) ) || png_hdr.ihdr_chunk.colortype == PNG_CT_PALLETE ) )
{ {
Con_DPrintf( S_WARN "Image_LoadPNG: Unknown color type %u (%s)\n", png_hdr.ihdr_chunk.colortype, name ); Con_DPrintf( S_WARN "%s: Unknown color type %u (%s)\n", __func__, png_hdr.ihdr_chunk.colortype, name );
return false; return false;
} }
if( png_hdr.ihdr_chunk.compression > 0 ) if( png_hdr.ihdr_chunk.compression > 0 )
{ {
Con_DPrintf( S_ERROR "Image_LoadPNG: Unknown compression method %u (%s)\n", png_hdr.ihdr_chunk.compression, name ); Con_DPrintf( S_ERROR "%s: Unknown compression method %u (%s)\n", __func__, png_hdr.ihdr_chunk.compression, name );
return false; return false;
} }
if( png_hdr.ihdr_chunk.filter > 0 ) if( png_hdr.ihdr_chunk.filter > 0 )
{ {
Con_DPrintf( S_ERROR "Image_LoadPNG: Unknown filter type %u (%s)\n", png_hdr.ihdr_chunk.filter, name ); Con_DPrintf( S_ERROR "%s: Unknown filter type %u (%s)\n", __func__, png_hdr.ihdr_chunk.filter, name );
return false; return false;
} }
if( png_hdr.ihdr_chunk.interlace == 1 ) if( png_hdr.ihdr_chunk.interlace == 1 )
{ {
Con_DPrintf( S_WARN "Image_LoadPNG: Adam7 Interlacing not supported (%s)\n", name ); Con_DPrintf( S_WARN "%s: Adam7 Interlacing not supported (%s)\n", __func__, name );
return false; return false;
} }
if( png_hdr.ihdr_chunk.interlace > 0 ) if( png_hdr.ihdr_chunk.interlace > 0 )
{ {
Con_DPrintf( S_ERROR "Image_LoadPNG: Unknown interlacing type %u (%s)\n", png_hdr.ihdr_chunk.interlace, name ); Con_DPrintf( S_ERROR "%s: Unknown interlacing type %u (%s)\n", __func__, png_hdr.ihdr_chunk.interlace, name );
return false; return false;
} }
@@ -145,7 +145,7 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
// check IHDR chunk CRC // check IHDR chunk CRC
if( ntohl( png_hdr.ihdr_crc32 ) != crc32_check ) if( ntohl( png_hdr.ihdr_crc32 ) != crc32_check )
{ {
Con_DPrintf( S_ERROR "Image_LoadPNG: IHDR chunk has wrong CRC32 sum (%s)\n", name ); Con_DPrintf( S_ERROR "%s: IHDR chunk has wrong CRC32 sum (%s)\n", __func__, name );
return false; return false;
} }
@@ -163,14 +163,14 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
if( chunk_len > INT_MAX ) if( chunk_len > INT_MAX )
{ {
Con_DPrintf( S_ERROR "Image_LoadPNG: Found chunk with wrong size (%s)\n", name ); Con_DPrintf( S_ERROR "%s: Found chunk with wrong size (%s)\n", __func__, name );
if( idat_buf ) Mem_Free( idat_buf ); if( idat_buf ) Mem_Free( idat_buf );
return false; return false;
} }
if( chunk_len > filesize - ( buf_p - buffer )) if( chunk_len > filesize - ( buf_p - buffer ))
{ {
Con_DPrintf( S_ERROR "Image_LoadPNG: Found chunk with size past file size (%s)\n", name ); Con_DPrintf( S_ERROR "%s: Found chunk with size past file size (%s)\n", __func__, name );
if( idat_buf ) Mem_Free( idat_buf ); if( idat_buf ) Mem_Free( idat_buf );
return false; return false;
} }
@@ -216,7 +216,7 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
// check chunk CRC // check chunk CRC
if( ntohl( crc32 ) != crc32_check ) if( ntohl( crc32 ) != crc32_check )
{ {
Con_DPrintf( S_ERROR "Image_LoadPNG: Found chunk with wrong CRC32 sum (%s)\n", name ); Con_DPrintf( S_ERROR "%s: Found chunk with wrong CRC32 sum (%s)\n", __func__, name );
if( idat_buf ) Mem_Free( idat_buf ); if( idat_buf ) Mem_Free( idat_buf );
return false; return false;
} }
@@ -227,27 +227,27 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
if( oldsize == 0 ) if( oldsize == 0 )
{ {
Con_DPrintf( S_ERROR "Image_LoadPNG: Couldn't find IDAT chunks (%s)\n", name ); Con_DPrintf( S_ERROR "%s: Couldn't find IDAT chunks (%s)\n", __func__, name );
return false; return false;
} }
if( png_hdr.ihdr_chunk.colortype == PNG_CT_PALLETE && !pallete ) if( png_hdr.ihdr_chunk.colortype == PNG_CT_PALLETE && !pallete )
{ {
Con_DPrintf( S_ERROR "Image_LoadPNG: PLTE chunk not found (%s)\n", name ); Con_DPrintf( S_ERROR "%s: PLTE chunk not found (%s)\n", __func__, name );
Mem_Free( idat_buf ); Mem_Free( idat_buf );
return false; return false;
} }
if( !has_iend_chunk ) if( !has_iend_chunk )
{ {
Con_DPrintf( S_ERROR "Image_LoadPNG: IEND chunk not found (%s)\n", name ); Con_DPrintf( S_ERROR "%s: IEND chunk not found (%s)\n", __func__, name );
Mem_Free( idat_buf ); Mem_Free( idat_buf );
return false; return false;
} }
if( chunk_len != 0 ) if( chunk_len != 0 )
{ {
Con_DPrintf( S_ERROR "Image_LoadPNG: IEND chunk has wrong size %u (%s)\n", chunk_len, name ); Con_DPrintf( S_ERROR "%s: IEND chunk has wrong size %u (%s)\n", __func__, chunk_len, name );
Mem_Free( idat_buf ); Mem_Free( idat_buf );
return false; return false;
} }
@@ -298,7 +298,7 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
// uncompress image // uncompress image
if( inflateInit2( &stream, MAX_WBITS ) != Z_OK ) if( inflateInit2( &stream, MAX_WBITS ) != Z_OK )
{ {
Con_DPrintf( S_ERROR "Image_LoadPNG: IDAT chunk decompression failed (%s)\n", name ); Con_DPrintf( S_ERROR "%s: IDAT chunk decompression failed (%s)\n", __func__, name );
Mem_Free( uncompressed_buffer ); Mem_Free( uncompressed_buffer );
Mem_Free( idat_buf ); Mem_Free( idat_buf );
return false; return false;
@@ -311,7 +311,7 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
if( ret != Z_OK && ret != Z_STREAM_END ) if( ret != Z_OK && ret != Z_STREAM_END )
{ {
Con_DPrintf( S_ERROR "Image_LoadPNG: IDAT chunk decompression failed (%s)\n", name ); Con_DPrintf( S_ERROR "%s: IDAT chunk decompression failed (%s)\n", __func__, name );
Mem_Free( uncompressed_buffer ); Mem_Free( uncompressed_buffer );
return false; return false;
} }
@@ -351,7 +351,7 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
pixbuf[i] = raw[i] + ( pixbuf[i - pixel_size] >> 1 ); pixbuf[i] = raw[i] + ( pixbuf[i - pixel_size] >> 1 );
break; break;
default: default:
Con_DPrintf( S_ERROR "Image_LoadPNG: Found unknown filter type (%s)\n", name ); Con_DPrintf( S_ERROR "%s: Found unknown filter type (%s)\n", __func__, name );
Mem_Free( uncompressed_buffer ); Mem_Free( uncompressed_buffer );
Mem_Free( image.rgba ); Mem_Free( image.rgba );
return false; return false;
@@ -415,7 +415,7 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
} }
break; break;
default: default:
Con_DPrintf( S_ERROR "Image_LoadPNG: Found unknown filter type (%s)\n", name ); Con_DPrintf( S_ERROR "%s: Found unknown filter type (%s)\n", __func__, name );
Mem_Free( uncompressed_buffer ); Mem_Free( uncompressed_buffer );
Mem_Free( image.rgba ); Mem_Free( image.rgba );
return false; return false;
@@ -650,7 +650,7 @@ qboolean Image_SavePNG( const char *name, rgbdata_t *pix )
// compress image // compress image
if( deflateInit( &stream, Z_BEST_COMPRESSION ) != Z_OK ) if( deflateInit( &stream, Z_BEST_COMPRESSION ) != Z_OK )
{ {
Con_DPrintf( S_ERROR "Image_SavePNG: deflateInit failed (%s)\n", name ); Con_DPrintf( S_ERROR "%s: deflateInit failed (%s)\n", __func__, name );
Mem_Free( filtered_buffer ); Mem_Free( filtered_buffer );
Mem_Free( buffer ); Mem_Free( buffer );
return false; return false;
@@ -663,7 +663,7 @@ qboolean Image_SavePNG( const char *name, rgbdata_t *pix )
if( ret != Z_OK && ret != Z_STREAM_END ) if( ret != Z_OK && ret != Z_STREAM_END )
{ {
Con_DPrintf( S_ERROR "Image_SavePNG: IDAT chunk compression failed (%s)\n", name ); Con_DPrintf( S_ERROR "%s: IDAT chunk compression failed (%s)\n", __func__, name );
Mem_Free( buffer ); Mem_Free( buffer );
return false; return false;
} }

View File

@@ -62,17 +62,17 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
// uncompressed colormapped image // uncompressed colormapped image
if( targa_header.pixel_size != 8 ) if( targa_header.pixel_size != 8 )
{ {
Con_DPrintf( S_ERROR "Image_LoadTGA: (%s) Only 8 bit images supported for type 1 and 9\n", name ); Con_DPrintf( S_ERROR "%s: (%s) Only 8 bit images supported for type 1 and 9\n", __func__, name );
return false; return false;
} }
if( targa_header.colormap_length != 256 ) if( targa_header.colormap_length != 256 )
{ {
Con_DPrintf( S_ERROR "Image_LoadTGA: (%s) Only 8 bit colormaps are supported for type 1 and 9\n", name ); Con_DPrintf( S_ERROR "%s: (%s) Only 8 bit colormaps are supported for type 1 and 9\n", __func__, name );
return false; return false;
} }
if( targa_header.colormap_index ) if( targa_header.colormap_index )
{ {
Con_DPrintf( S_ERROR "Image_LoadTGA: (%s) colormap_index is not supported for type 1 and 9\n", name ); Con_DPrintf( S_ERROR "%s: (%s) colormap_index is not supported for type 1 and 9\n", __func__, name );
return false; return false;
} }
if( targa_header.colormap_size == 24 ) if( targa_header.colormap_size == 24 )
@@ -97,7 +97,7 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
} }
else else
{ {
Con_DPrintf( S_ERROR "Image_LoadTGA: (%s) only 24 and 32 bit colormaps are supported for type 1 and 9\n", name ); Con_DPrintf( S_ERROR "%s: (%s) only 24 and 32 bit colormaps are supported for type 1 and 9\n", __func__, name );
return false; return false;
} }
} }
@@ -106,7 +106,7 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
// uncompressed or RLE compressed RGB // uncompressed or RLE compressed RGB
if( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) if( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 )
{ {
Con_DPrintf( S_ERROR "Image_LoadTGA: (%s) Only 32 or 24 bit images supported for type 2 and 10\n", name ); Con_DPrintf( S_ERROR "%s: (%s) Only 32 or 24 bit images supported for type 2 and 10\n", __func__, name );
return false; return false;
} }
} }
@@ -115,7 +115,7 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
// uncompressed greyscale // uncompressed greyscale
if( targa_header.pixel_size != 8 && targa_header.pixel_size != 16 ) if( targa_header.pixel_size != 8 && targa_header.pixel_size != 16 )
{ {
Con_DPrintf( S_ERROR "Image_LoadTGA: (%s) Only 8 bit images supported for type 3 and 11\n", name ); Con_DPrintf( S_ERROR "%s: (%s) Only 8 bit images supported for type 3 and 11\n", __func__, name );
return false; return false;
} }
} }

View File

@@ -174,8 +174,8 @@ byte *Image_Copy( size_t size )
{ {
byte *out; byte *out;
out = Mem_Malloc( host.imagepool, size ); out = Mem_Realloc( host.imagepool, image.tempbuffer, size );
memcpy( out, image.tempbuffer, size ); image.tempbuffer = NULL;
return out; return out;
} }
@@ -293,9 +293,18 @@ static void Image_SetPalette( const byte *pal, uint *d_table )
case LUMP_NORMAL: case LUMP_NORMAL:
for( i = 0; i < 256; i++ ) for( i = 0; i < 256; i++ )
{ {
rgba[0] = TextureToGamma( pal[i*3+0] ); memcpy( rgba, &pal[i * 3], 3 );
rgba[1] = TextureToGamma( pal[i*3+1] ); rgba[3] = 0xFF;
rgba[2] = TextureToGamma( pal[i*3+2] ); 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; rgba[3] = 0xFF;
memcpy( &uirgba, rgba, sizeof( uirgba )); memcpy( &uirgba, rgba, sizeof( uirgba ));
d_table[i] = uirgba; d_table[i] = uirgba;
@@ -1179,7 +1188,7 @@ byte *Image_FlipInternal( const byte *in, word *srcwidth, word *srcheight, int t
return image.tempbuffer; return image.tempbuffer;
} }
static byte *Image_CreateLumaInternal( byte *fin, int width, int height, int type, int flags ) static byte *Image_MakeLuma( byte *fin, int width, int height, int type, int flags )
{ {
byte *out; byte *out;
int i; int i;
@@ -1197,7 +1206,7 @@ static byte *Image_CreateLumaInternal( byte *fin, int width, int height, int typ
break; break;
default: default:
// another formats does ugly result :( // another formats does ugly result :(
Con_Printf( S_ERROR "Image_MakeLuma: unsupported format %s\n", PFDesc[type].name ); Con_Printf( S_ERROR "%s: unsupported format %s\n", __func__, PFDesc[type].name );
return (byte *)fin; return (byte *)fin;
} }
@@ -1374,20 +1383,20 @@ static qboolean Image_RemapInternal( rgbdata_t *pic, int topColor, int bottomCol
return true; 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; rgbdata_t *pic = *pix;
qboolean result = true; qboolean result = true;
byte *out; byte *out;
// check for buffers // check for buffers
if( !pic || !pic->buffer ) if( unlikely( !pic || !pic->buffer ))
{ {
image.force_flags = 0; image.force_flags = 0;
return false; return false;
} }
if( !flags ) if( unlikely( !flags ))
{ {
// clear any force flags // clear any force flags
image.force_flags = 0; image.force_flags = 0;
@@ -1396,7 +1405,7 @@ qboolean Image_Process(rgbdata_t **pix, int width, int height, uint flags, float
if( FBitSet( flags, IMAGE_MAKE_LUMA )) if( FBitSet( flags, IMAGE_MAKE_LUMA ))
{ {
out = Image_CreateLumaInternal( pic->buffer, pic->width, pic->height, pic->type, pic->flags ); out = Image_MakeLuma( pic->buffer, pic->width, pic->height, pic->type, pic->flags );
if( pic->buffer != out ) memcpy( pic->buffer, image.tempbuffer, pic->size ); if( pic->buffer != out ) memcpy( pic->buffer, image.tempbuffer, pic->size );
ClearBits( pic->flags, IMAGE_HAS_LUMA ); ClearBits( pic->flags, IMAGE_HAS_LUMA );
} }
@@ -1432,7 +1441,7 @@ qboolean Image_Process(rgbdata_t **pix, int width, int height, uint flags, float
pic->width = w, pic->height = h; pic->width = w, pic->height = h;
pic->size = w * h * PFDesc[pic->type].bpp; pic->size = w * h * PFDesc[pic->type].bpp;
Mem_Free( pic->buffer ); // free original image buffer 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 else
{ {

View File

@@ -31,7 +31,7 @@ qboolean Image_LoadPAL( const char *name, const byte *buffer, fs_offset_t filesi
if( filesize != 768 ) if( filesize != 768 )
{ {
Con_DPrintf( S_ERROR "Image_LoadPAL: (%s) have invalid size (%ld should be %d)\n", name, filesize, 768 ); Con_DPrintf( S_ERROR "%s: (%s) have invalid size (%li should be %d)\n", __func__, name, (long)filesize, 768 );
return false; return false;
} }
@@ -427,8 +427,18 @@ qboolean Image_LoadMIP( const char *name, const byte *buffer, fs_offset_t filesi
} }
if( pal_type == PAL_QUAKE1 ) if( pal_type == PAL_QUAKE1 )
{
SetBits( image.flags, IMAGE_QUAKEPAL ); 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 ); Image_GetPaletteLMP( pal, rendermode );

View File

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

View File

@@ -81,8 +81,8 @@ void *COM_FunctionFromName_SR( void *hInstance, const char *pName )
const char *COM_OffsetNameForFunction( void *function ) const char *COM_OffsetNameForFunction( void *function )
{ {
static string sname; static string sname;
Q_snprintf( sname, MAX_STRING, "ofs:%lu", (size_t)((byte*)function - (byte*)svgame.dllFuncs.pfnGameInit) ); Q_snprintf( sname, MAX_STRING, "ofs:%zu", ((byte*)function - (byte*)svgame.dllFuncs.pfnGameInit) );
Con_Reportf( "COM_OffsetNameForFunction %s\n", sname ); Con_Reportf( "%s: %s\n", __func__, sname );
return sname; return sname;
} }
@@ -231,9 +231,9 @@ void COM_GetCommonLibraryPath( ECommonLibraryType eLibType, char *out, size_t si
COM_GenerateClientLibraryPath( "menu", out, size ); COM_GenerateClientLibraryPath( "menu", out, size );
break; break;
case LIBRARY_CLIENT: case LIBRARY_CLIENT:
if( SI.clientlib[0] ) if( COM_CheckStringEmpty( host.clientlib ))
{ {
Q_strncpy( out, SI.clientlib, size ); Q_strncpy( out, host.clientlib, size );
} }
else else
{ {
@@ -241,9 +241,9 @@ void COM_GetCommonLibraryPath( ECommonLibraryType eLibType, char *out, size_t si
} }
break; break;
case LIBRARY_SERVER: case LIBRARY_SERVER:
if( SI.gamedll[0] ) if( COM_CheckStringEmpty( host.gamedll ))
{ {
Q_strncpy( out, SI.gamedll, size ); Q_strncpy( out, host.gamedll, size );
} }
else else
{ {
@@ -359,7 +359,7 @@ static char *COM_GetItaniumName( const char * const in_name )
if( i == MAX_NESTED_NAMESPACES ) if( i == MAX_NESTED_NAMESPACES )
{ {
Con_DPrintf( "%s: too much nested namespaces: %s\n", __FUNCTION__, in_name ); Con_DPrintf( "%s: too much nested namespaces: %s\n", __func__, in_name );
return NULL; return NULL;
} }
@@ -373,7 +373,7 @@ static char *COM_GetItaniumName( const char * const in_name )
return out_name; return out_name;
invalid_format: invalid_format:
Con_DPrintf( "%s: invalid format: %s\n", __FUNCTION__, in_name ); Con_DPrintf( "%s: invalid format: %s\n", __func__, in_name );
return NULL; return NULL;
} }
@@ -421,7 +421,7 @@ char **COM_ConvertToLocalPlatform( EFunctionMangleType to, const char *from, siz
if( i == MAX_NESTED_NAMESPACES ) if( i == MAX_NESTED_NAMESPACES )
{ {
Con_DPrintf( "%s: too much nested namespaces: %s\n", __FUNCTION__, from ); Con_DPrintf( "%s: too much nested namespaces: %s\n", __func__, from );
return NULL; return NULL;
} }

View File

@@ -24,7 +24,8 @@ typedef struct dll_user_s
qboolean custom_loader; // a bit who indicated loader type qboolean custom_loader; // a bit who indicated loader type
qboolean encrypted; // dll is crypted (some client.dll in HL, CS etc) qboolean encrypted; // dll is crypted (some client.dll in HL, CS etc)
char dllName[32]; // for debug messages char dllName[32]; // for debug messages
string fullPath, shortPath; // actual dll paths char fullPath[2048];
string shortPath; // actual dll paths
// ordinals stuff, valid only on Win32 // ordinals stuff, valid only on Win32
word *ordinals; word *ordinals;

View File

@@ -262,7 +262,7 @@ static void NET_AddMaster( const char *addr, qboolean save )
} }
master = Mem_Malloc( host.mempool, sizeof( master_t ) ); master = Mem_Malloc( host.mempool, sizeof( master_t ) );
Q_strncpy( master->address, addr, MAX_STRING ); Q_strncpy( master->address, addr, sizeof( master->address ));
master->sent = false; master->sent = false;
master->save = save; master->save = save;
master->next = NULL; master->next = NULL;
@@ -389,7 +389,7 @@ void NET_SaveMasters( void )
if( !f ) if( !f )
{ {
Con_Reportf( S_ERROR "Couldn't write xashcomm.lst\n" ); Con_Reportf( S_ERROR "Couldn't write xashcomm.lst\n" );
return; return;
} }
@@ -419,6 +419,9 @@ void NET_InitMasters( void )
// keep main master always there // keep main master always there
NET_AddMaster( MASTERSERVER_ADR, false ); NET_AddMaster( MASTERSERVER_ADR, false );
NET_AddMaster( MASTERSERVER_ADR_TEST, false ); NET_AddMaster( "aaaa.mentality.rip:27010", false ); // IPv6-only
NET_AddMaster( "mentality.rip:27011", false ); // testing server, might be offline
NET_AddMaster( "aaaa.mentality.rip:27011", false ); // IPv6-only, testing server, might be offline
NET_LoadMasters( ); 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
}

File diff suppressed because it is too large Load Diff

View File

@@ -33,7 +33,7 @@ GNU General Public License for more details.
#define REFPVS_RADIUS 2.0f // radius for rendering #define REFPVS_RADIUS 2.0f // radius for rendering
#define FATPVS_RADIUS 8.0f // FatPVS use radius smaller than the FatPHS #define FATPVS_RADIUS 8.0f // FatPVS use radius smaller than the FatPHS
#define FATPHS_RADIUS 16.0f #define FATPHS_RADIUS 8.0f // see SV_AddToFatPAS in GoldSrc
#define WORLD_INDEX (1) // world index is always 1 #define WORLD_INDEX (1) // world index is always 1
@@ -74,7 +74,7 @@ typedef struct winding_s
struct winding_s *pair; struct winding_s *pair;
hullnode_t chain; hullnode_t chain;
int numpoints; int numpoints;
vec3_t p[4]; // variable sized vec3_t p[]; // variable sized
} winding_t; } winding_t;
typedef struct typedef struct
@@ -83,6 +83,12 @@ typedef struct
uint num_polys; uint num_polys;
} hull_model_t; } 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 typedef struct world_static_s
{ {
@@ -115,6 +121,12 @@ typedef struct world_static_s
int max_recursion; int max_recursion;
uint32_t version; // BSP version uint32_t version; // BSP version
// Potentially Hearable Set
byte *compressed_phs;
size_t *phsofs;
wadlist_t wadlist;
} world_static_t; } world_static_t;
#ifndef REF_DLL #ifndef REF_DLL
@@ -145,13 +157,18 @@ qboolean Mod_ValidateCRC( const char *name, CRC32_t crc );
void Mod_NeedCRC( const char *name, qboolean needCRC ); void Mod_NeedCRC( const char *name, qboolean needCRC );
void Mod_FreeUnused( void ); void Mod_FreeUnused( void );
//
// mod_alias.c
//
void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *loaded );
// //
// mod_bmodel.c // mod_bmodel.c
// //
void Mod_LoadBrushModel( model_t *mod, const void *buffer, qboolean *loaded ); void Mod_LoadBrushModel( model_t *mod, const void *buffer, qboolean *loaded );
qboolean Mod_TestBmodelLumps( file_t *f, const char *name, const byte *mod_base, qboolean silent, dlump_t *entities ); qboolean Mod_TestBmodelLumps( file_t *f, const char *name, const byte *mod_base, qboolean silent, dlump_t *entities );
qboolean Mod_HeadnodeVisible( mnode_t *node, const byte *visbits, int *lastleaf ); qboolean Mod_HeadnodeVisible( mnode_t *node, const byte *visbits, int *lastleaf );
int Mod_FatPVS( const vec3_t org, float radius, byte *visbuffer, int visbytes, qboolean merge, qboolean fullvis ); int Mod_FatPVS( const vec3_t org, float radius, byte *visbuffer, int visbytes, qboolean merge, qboolean fullvis, qboolean false );
qboolean Mod_BoxVisible( const vec3_t mins, const vec3_t maxs, const byte *visbits ); qboolean Mod_BoxVisible( const vec3_t mins, const vec3_t maxs, const byte *visbits );
int Mod_CheckLump( const char *filename, const int lump, int *lumpsize ); int Mod_CheckLump( const char *filename, const int lump, int *lumpsize );
int Mod_ReadLump( const char *filename, const int lump, void **lumpdata, int *lumpsize ); int Mod_ReadLump( const char *filename, const int lump, void **lumpdata, int *lumpsize );
@@ -190,7 +207,7 @@ void Mod_ClearStudioCache( void );
// //
// mod_sprite.c // 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
#endif//MOD_LOCAL_H #endif//MOD_LOCAL_H

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