Compare commits

...

271 Commits

Author SHA1 Message Date
Alibek Omarov
3baeea1253 engine: client: handle hud_utf8 in client.dll's draw character functions, rather than in engine's CL_DrawCharacter 2025-03-12 07:31:18 +03:00
Alibek Omarov
9ba7cc88d9 engine: client: move Con_UtfProcessChar to cl_gameui. It is now deprecated 2025-03-12 07:26:58 +03:00
Alibek Omarov
9ef7759e05 engine: client: rewrite touch control text drawing with utflib and cl_font 2025-03-12 07:26:58 +03:00
Alibek Omarov
232224f52d engine: client: OSK doesn't need unicode conversion, as it only supports basic latin anyway 2025-03-12 07:26:58 +03:00
Alibek Omarov
18d09d80cc engine: client: like GoldSrc, expect UTF-8 encoded strings in pfnDrawString/pfnDrawStringReverse 2025-03-12 06:15:27 +03:00
Alibek Omarov
67f91fc100 engine: client: decode utf-8 string in CL_DrawCenterPrint, as CL_DrawCharacter requires unicode codepoints now 2025-03-12 06:04:35 +03:00
Alibek Omarov
ca22c4123d engine: client: make CL_DrawCharacter accept unicode codepoints, as it was intended to do 2025-03-11 08:23:16 +03:00
Alibek Omarov
8af0e2c8b4 readme: add missing system dependencies on Linux systems [skip ci] 2025-03-08 02:42:28 +03:00
Alibek Omarov
a5191d8948 engine: client: console: simplify Field_DrawInputLine, try to make it safer 2025-03-08 02:35:32 +03:00
Alibek Omarov
b2d8239829 engine: common: net_http: fix decompression for compressed but not chunked files 2025-03-06 19:10:48 +03:00
Alibek Omarov
34322f025b engine: client: limit ticket generator choices to revemu2013 only 2025-03-06 12:35:32 +03:00
Alibek Omarov
3e6b434733 mainui: update 2025-03-05 22:36:41 +03:00
Alibek Omarov
8359cbe76c scripts: waifulib: add flag --enable-limited-debuginfo which enables -gline-tables-only on GCC and Clang compilers
This saves ~30mb of APK size on Android.
2025-03-05 02:19:39 +03:00
Alibek Omarov
0e90e6285e engine: host: use #if instead of #ifdef when checking for extended hl25 structs compile option 2025-03-03 22:59:44 +03:00
Alibek Omarov
2f5840f650 engine: host: add a cvar that indicates whether engine was built with --enable-hl25-extended-structs or not 2025-03-03 22:53:20 +03:00
Alibek Omarov
3b51a554dd mainui: update 2025-03-02 20:20:54 +03:00
Alibek Omarov
5f0880d4a2 engine: client: lower the bandwidth test fragment sizes to 1400 and less, as using 64k, 32k and more is unreliable 2025-03-02 20:20:40 +03:00
Bohdan Shulyar
884a3c66ac client: touch: fix minor typo that prevented editing touch buttons commands 2025-03-02 20:19:58 +03:00
Alibek Omarov
c76752cc5f engine: server: validate uuid in protinfo, it's an md5 string 2025-03-01 22:45:01 +03:00
Alibek Omarov
fc2888e107 engine: server: fix incorrect ID string generation, hashedcdkey is already an MD5 string 2025-03-01 22:27:22 +03:00
Alibek Omarov
674b4c1506 engine: server: reorder sv_client_t struct for better memory efficiency, remove unused fields 2025-03-01 22:07:05 +03:00
Alibek Omarov
cddd50f1e9 engine: server: completely erase sv_client_t on client connect, so we always start from scratch for every user 2025-03-01 22:07:05 +03:00
Alibek Omarov
6c9d5bc1fb engine: server: cleanup penalties and warns for new players 2025-03-01 16:03:39 +03:00
Alibek Omarov
ec23860238 gitmodules: use github mirrors instead of xiph.org's git
It's not really a good idea to hammer upstream git servers with cloning same
data over and over. Besides, it's down right now.
2025-03-01 15:28:55 +03:00
Alibek Omarov
14a2e34b7e mainui: update 2025-03-01 15:21:20 +03:00
Alibek Omarov
29c8818557 engine: server: do not continue processing command if the player was kicked during it (for example, by speedhack prevention) 2025-03-01 14:58:15 +03:00
Andrey Akhmichin
7222830b28 Documentation: supported-mod-list.md: a little remark. 2025-02-28 23:56:28 +03:00
Alibek Omarov
9b0ad7daf0 engine: common: register forgotten net_clockwindow cvar 2025-02-28 22:44:44 +03:00
Alibek Omarov
73729827f4 engine: platform: win32: add forgotten SDL.h include 2025-02-28 21:55:26 +03:00
Alibek Omarov
97fa395a3b engine: platform: win32: fix build by restoring previous win32 header inclusion order 2025-02-28 21:44:22 +03:00
Alibek Omarov
1cef8ea7af Revert "ref: gl: check OES NPOT texture extension in BigGL mode"
This breaks mipmaps on PSVita

This reverts commit 54b0cf9991.
2025-02-28 17:08:27 +03:00
Alibek Omarov
eda4e95607 engine: client: draw version at bottom right in menu, regardless if dev_overview or net_graph are enabled (those only used in-game) 2025-02-28 15:11:24 +03:00
Alibek Omarov
a5f0ca38f1 engine: remove inclusion of SDL headers globally, helps to cleanup code before SDL3 migration 2025-02-28 13:14:47 +03:00
Alibek Omarov
bbbd7711c1 engine: platform: cleanup remnants of disabling vsync while loading mechanism for linux fbdev and dos ports 2025-02-28 12:33:30 +03:00
Alibek Omarov
38e922557d engine: platform: sdl: remove disabling vsync while we're not in game, as this is something users have been complaining a lot
It's not a big deal if level loading will take a few milliseconds more.
2025-02-28 08:27:38 +03:00
Alibek Omarov
4dec1785ed engine: client: touch: fix inverted file extension check 2025-02-28 06:44:21 +03:00
Alibek Omarov
9f77b7dc46 scripts: waifulib: enable HLSDK -mtune only on GCC and Clang, and not on Android 2025-02-26 17:11:10 +03:00
Alibek Omarov
5061a29f86 scripts: waifulib: enable asynchronous-unwind-tables for better stacktraces 2025-02-26 17:10:30 +03:00
Alibek Omarov
cb5dffd554 engine: server: don't bother printing about unsupported connectionless packets if sv_log_outofband is set to 0 2025-02-26 17:06:33 +03:00
Alibek Omarov
4eaa8ab40f android: bump minimum CMake version, so disabling unneeded features in SDL actually works 2025-02-26 14:21:58 +03:00
Alibek Omarov
2a82d265d6 scripts: waifulib: xcompile: add support for Android NDK r27 as well 2025-02-26 12:40:22 +03:00
Alibek Omarov
f2392b5709 scripts: waifulib: xcompile: add support for building on Windows. Drop using shortcut target clang symlinks, as those don't work on Windows at all (they are wrapped into batch files, which can't be invoked like exes) 2025-02-26 12:40:22 +03:00
Alibek Omarov
5620e7ab4c android: fixup CMAKE_LIBRARY_OUTPUT_DIRECTORY on Win32, merge stdout and stderr for waf output 2025-02-26 12:40:22 +03:00
Alibek Omarov
a76236ac5a scripts: waifulib: xcompile: add support for NDK 28, remove setting up custom PREFIX to not mess up installation path 2025-02-26 12:40:22 +03:00
Alibek Omarov
d1c5862bab android: bump NDK version to 28 2025-02-26 12:40:22 +03:00
Alibek Omarov
81400d0b01 android: use xcompile.py's support for Android NDK, fix tabs 2025-02-26 12:40:22 +03:00
Alibek Omarov
a129f13e25 android: enable verbose output for CMake running from Gradle 2025-02-26 12:40:22 +03:00
Alibek Omarov
ec8b4c0a84 android: rework how engine is built, instead of generating CMakeLists, just use included in CMake ExternalProject feature 2025-02-26 12:40:22 +03:00
Alibek Omarov
f1f726822c engine: client: restore cl_cmdrate default value at 30. It wasn't an intentional change. 2025-02-25 19:52:48 +03:00
Alibek Omarov
8982d55392 engine: client: set default rate value to 25000
3500 is barely playable these days. Those who have worse than usual internet
connection, should set appropriate value themselves.
2025-02-25 17:36:43 +03:00
Alibek Omarov
f499286a87 engine: platform: sdl: don't call SDL_GL_SetSwapInterval each frame while we're not in game 2025-02-25 11:52:03 +03:00
Alibek Omarov
a3aaa87147 ref: gl: enable polygon offset for fullbright textures when rendering them in separate from VBO pass 2025-02-25 11:49:31 +03:00
Alibek Omarov
15a6971aca engine: platform: posix: strip path from filename in backtrace 2025-02-25 11:46:57 +03:00
Alibek Omarov
b1eb3390e3 engine: server: let server dll to register it's own showtriggers cvar 2025-02-24 06:41:11 +03:00
Alibek Omarov
74ad504377 engine: client: console: do not let color strings contribute to line length in console 2025-02-24 03:55:13 +03:00
Alibek Omarov
8a0c2577ed engine: platform: sdl: exclude fake game controller found on Android emulator 2025-02-24 03:42:03 +03:00
Alibek Omarov
a060d7aefd wscript: disable large file for 32-bit Android 2025-02-23 16:07:51 +03:00
Alibek Omarov
ccf342f4fe engine: client: fix inconsistent mouse state caused by mis-use of touch_emulate by cs16-client 2025-02-23 07:13:39 +03:00
Alibek Omarov
8b9a40ff1f engine: client: completely refactor touch code, protect button color, improve config output 2025-02-23 07:00:20 +03:00
Alibek Omarov
425cc61c4c engine: client: handle K_ESCAPE in Key_Console, remove special case for it in Key_Event 2025-02-23 06:47:44 +03:00
Alibek Omarov
fe1fd5b024 engine: client: make color array of DrawString functions const 2025-02-23 06:46:22 +03:00
Alibek Omarov
0c8da36a0b filesystem: disallow path traversal in FS_Delete and FS_Rename 2025-02-23 03:13:46 +03:00
Alibek Omarov
2c5030ab45 engine: client: do not save touch_emulate cvar 2025-02-23 02:04:33 +03:00
Alibek Omarov
9decba873b engine: platform: sdl: try to save and restore mouse position during showing or hiding cursor 2025-02-23 02:04:03 +03:00
Alibek Omarov
bda4c45504 engine: client: simplify CL_EDICT_NUM and it's sister, non throwing error, function CL_GetEntityByIndex 2025-02-23 01:51:05 +03:00
Alibek Omarov
f7aa8a0c90 ci: bump SDL2 to 2.32.0. This is the last major upgrade to SDL2 dependency, we should migrate to SDL3 (with sdl2-compat for GoldSrc mods) after that 2025-02-22 18:48:41 +03:00
Alibek Omarov
4c15cceb32 engine: client: deprecate custom id, it is not used meaningfully by anyone 2025-02-20 15:41:17 +03:00
Alibek Omarov
3e4c5beb25 ref: fix another typo made after R_StudioCalcBones refactor 2025-02-18 19:22:06 +03:00
Alibek Omarov
f84d865f4a engine: client: fix crash if server sends new movevars before entities were created
Nothing bad will happen if we skip wave height for world entity for now, but
we might need to handle this situation somehow in the future.
2025-02-17 13:02:21 +03:00
SNMetamorph
2465782a3e engine: platform: sys_win: fixed compiling error 2025-02-15 13:45:22 +03:00
Alibek Omarov
7ba2209124 engine: platform: sdl: set requested timer delay in units of 100ns according to the documentation 2025-02-15 13:08:05 +03:00
Alibek Omarov
af6b434b71 engine: platform: win32: implement nanosleep using waitable timers with high precision 2025-02-15 11:57:41 +03:00
Alibek Omarov
052ea6a8bd engine: platform: introduce for Platform_NanoSleep, to be used for better sleeping in between frames for lowering CPU usage 2025-02-15 10:11:17 +03:00
Alibek Omarov
448dc720ed engine: server: immediately exit from SV_GetChallenge on unknown type addresses 2025-02-15 09:31:20 +03:00
Alibek Omarov
75b15696f8 engine: zone: ensure memheader_t size is always expected 2025-02-15 09:31:20 +03:00
Andrey Akhmichin
7fb113f610 Documentation: opensource-mods.md: add "Delta Particles". 2025-02-15 08:02:44 +03:00
Andrey Akhmichin
0497e00ad2 Documentation: supported-mod-list.md: update. 2025-02-15 08:02:35 +03:00
Alibek Omarov
9c50288bbb engine: server: rewrite challenge generator to something more simple: salted MD5 of an IP address
The idea was taken from ReHLDS project.
2025-02-15 08:01:44 +03:00
Alibek Omarov
c5d4af802c engine: server: even if user set non-integer value for cl_updaterate, clamp it to sv_minupdaterate 2025-02-15 08:01:44 +03:00
Alibek Omarov
340a8b5e0c engine: server: fixes for userinfo change ratelimiting
* Add pentalty earlier
* Increase disallowed timewindow according to penality multiplier
* Allow first change even if it falls into ignore timewindow
2025-02-15 08:01:44 +03:00
Alibek Omarov
bc1b86c19c engine: server: refactor SV_ConnectClient, simplify LAN IP check 2025-02-15 08:01:44 +03:00
Alibek Omarov
b605cf603e common: xash3d_types: make it more compatible for inclusion in SDK 2025-02-15 08:01:44 +03:00
xiaodo
fdc2ed8093 engine: server: pfnClientCommand and pfnQueryClientCvarValue should execute on unspawned player 2025-02-14 20:52:45 +03:00
xiaodo
a27375d1f5 engine: server: cmds: fix kick command incorrect argc 2025-02-14 20:52:45 +03:00
Alibek Omarov
0e2abf9040 engine: platform: always create zeroed buffer for audio 2025-02-14 05:20:40 +03:00
Alibek Omarov
89430400d9 engine: sys_con: only allow names that start with either alphabetic or numerical character for a log file 2025-02-14 01:51:50 +03:00
Alibek Omarov
f1a9d408bf engine: sys_con: check if the next argument after -log starts with minus and ignore it if it does 2025-02-14 00:50:01 +03:00
Alibek Omarov
6529692244 engine: disable timestamps in log file by default, allow changing log file name with -log argument 2025-02-14 00:28:00 +03:00
Alibek Omarov
51d11f8e86 engine: platform: win32: remove unused log variables and checks from Win32 console, sys_con does the job 2025-02-14 00:28:00 +03:00
Alibek Omarov
c5397191e5 engine: client: touch: limit usage of touch_set_stroke and touch_setclientonly only for privileged mode 2025-02-13 20:55:49 +03:00
Alibek Omarov
44426709f7 engine: platform: posix: skip first stack frame when printing stack trace with libbacktrace 2025-02-13 20:43:32 +03:00
Alibek Omarov
2d8f747e84 wscript: disable using system-wide libbacktrace, as it might not support features we need 2025-02-13 19:21:07 +03:00
Alibek Omarov
0dd5a60410 3rdparty: gl4es: update submodule 2025-02-13 02:32:28 +03:00
Alibek Omarov
eec8129be4 3rdparty: extras: update submodule 2025-02-13 02:31:30 +03:00
Alibek Omarov
934c5e018d readme: clarify that chat is for russian speaking people [ci skip] 2025-02-12 18:08:10 +03:00
Alibek Omarov
d658d8cc78 readme: remove builds.sr.ht status, add Telegram chat link, remove stable build link (it's very outdated and not recommended to use) [skip ci] 2025-02-12 17:58:51 +03:00
Alibek Omarov
ca9a3f0491 engine: server: fix out of bounds write in SV_FindTouchedLeafs 2025-02-11 21:15:54 +03:00
Alibek Omarov
1510cb458f public: fix another typo 2025-02-11 21:12:50 +03:00
Andrey Akhmichin
30cabb8107 Documentation: supported-mod-list.md: fix branch name. 2025-02-11 21:10:59 +03:00
Alibek Omarov
64ee956618 engine: fix a typo 2025-02-11 20:06:15 +03:00
Alibek Omarov
39659644bf public: merge calc bone quaternion and position into single function
Expect that only adj and output quaternion can be NULL.
2025-02-11 18:57:08 +03:00
Alibek Omarov
eb09af0b08 ref: gl: avoid generating GL_INVALID_OPERATION if gl_vbo_dlightmode is set to 0 2025-02-11 18:57:08 +03:00
Andrey Akhmichin
91a4ace12c Documentation: supported-mod-list.md: update. 2025-02-11 16:28:40 +03:00
Alibek Omarov
2ad2e46b30 mainui: update 2025-02-10 13:18:59 +03:00
Alibek Omarov
627444279f Revert "common: cvar: make auto descriptions private to cvar subsystem, use them when Cvar_Get is called with NULL description"
This reverts commit ade560c601.
2025-02-10 12:49:05 +03:00
Alibek Omarov
3550bdb30d 3rdparty: mainui: update 2025-02-09 23:14:24 +03:00
Alibek Omarov
c201b895eb common: netadr: force cast uint16_t type to netadrtype_t
So it compiles in C++
2025-02-09 23:13:29 +03:00
Alibek Omarov
72f1ac3780 wscript: ensure system-wide libbacktrace supports threads 2025-02-09 18:29:02 +03:00
Alibek Omarov
d7dc3192de 3rdparty: libbacktrace: fix applying uselib 2025-02-09 18:25:40 +03:00
Alibek Omarov
43ea65fffc ci: upgrade freebsd tasks. 2025-02-09 17:41:01 +03:00
Alibek Omarov
a72d921c12 wscript: add system-wide libbacktrace detection 2025-02-09 17:41:01 +03:00
Alibek Omarov
99b7d71824 wscript: set DEST_SIZEOF_VOID_P with allow 64bit flag 2025-02-09 17:16:17 +03:00
Alibek Omarov
67c73bdcbe engine: server: remove impulse 204, it's not used anywhere
Thanks @tyabus for reminding me about this feature.
2025-02-09 17:16:05 +03:00
Alibek Omarov
8b1dbcf166 ci: remove extra 20s of wait before removing current release and downloading artifacts 2025-02-09 17:02:31 +03:00
Alibek Omarov
5f60095dc4 scripts: flatpak: disable separate debuginfo 2025-02-09 16:54:51 +03:00
Alibek Omarov
c7282b488b 3rdparty: libbacktrace: disable linking zlib, lzma and zstd for now, figure this out later 2025-02-09 16:49:43 +03:00
Alibek Omarov
afa829d996 3rdparty: libbacktrace: don't define POSIX_SOURCE, it breaks build on Mac 2025-02-09 16:41:26 +03:00
Alibek Omarov
c06ea8d915 engine: platform: posix: add printing backtrace to stderr and logfile for libbacktrace backend 2025-02-09 16:41:26 +03:00
Alibek Omarov
bf344282ec android: explicitly set Waf output directory so it doesn't mess with current configuration and places generated files where CMake expects them to be 2025-02-09 16:20:38 +03:00
Alibek Omarov
21f62910ac engine: platform: posix: fix build when glibc execinfo.h is not available, but libbacktrace is still used 2025-02-09 16:20:38 +03:00
Alibek Omarov
54552d93ef Documentation: goldsrc-protocol-support: I am not going to support Dproto 2025-02-09 16:18:21 +03:00
Alibek Omarov
97455e7fd4 engine: platform: sdl: fix build after last PR 2025-02-09 15:56:16 +03:00
Alibek Omarov
6087d43043 3rdparty: libbacktrace: properly disable it on win32, nswitch and psvita 2025-02-09 15:55:12 +03:00
Alibek Omarov
c1a96d3ff1 engine: platform: posix: fix build 2025-02-09 15:51:25 +03:00
Alibek Omarov
e27d20dfa3 android: enable debug symbols for native libraries 2025-02-09 15:49:28 +03:00
Alibek Omarov
890e12ec76 engine: platform: posix: flush stdout/stderr before everything, include build branch 2025-02-09 15:45:44 +03:00
Alibek Omarov
774d2ac28a engine: platform: posix: add libbacktrace support for crash handler 2025-02-09 15:42:28 +03:00
Alibek Omarov
960d724828 3rdparty: libbacktrace: add submodule 2025-02-09 15:40:07 +03:00
Alibek Omarov
32aa1f91bf engine: pass argv0 to crash handler setup, which is required for libbacktrace integration
Fix indentation in crash_posix.c
2025-02-09 15:36:49 +03:00
Alibek Omarov
bd3634c815 wscript: add sanity test for opusfile because some distros don't ship 32-bit binary 2025-02-09 15:34:30 +03:00
Oleg
eda0ac92cc engine: platform: sdl: change behavior when window position is not set 2025-02-09 08:54:31 +03:00
Oleg
546903ea05 engine: platform: sdl: write windows position changes even in fullscreen 2025-02-09 08:54:31 +03:00
Oleg
4975001795 engine: platform: sdl: enumerate video modes for display where window located is instead of display zero 2025-02-09 08:54:31 +03:00
Oleg
a078ad1f51 engine: platform: sdl: fix windows save position for multiple monitors 2025-02-09 08:54:31 +03:00
Oleg
8307f671d4 engine: platform: sdl: let platform decide where to put our fullscreen window 2025-02-09 08:54:31 +03:00
Alibek Omarov
241fab02b1 ref: gl: don't try to free luma and detail texture of water texture, as these fields used by r_ripple 2025-02-08 16:57:20 +03:00
Alibek Omarov
1bfee70477 engine: con_utils: add autocompletion for cvar commands like set, reset and toggle 2025-02-08 16:45:52 +03:00
Alibek Omarov
eb51d17cd2 engine: server: enable sv_zmax clamping back to avoid overflowing zmax value encoded in delta 2025-02-08 16:38:11 +03:00
Alibek Omarov
b5cb0b9f10 ref: gl: add r_dlight_virtual_radius. It potentially fixes ugly dlight cut off on largely scaled textures (or at least allows to tune it)
It also adds a fix found in JoeQuake (which traces back to FitzQuake, in which
it is attributed to LadyHavoc, Darkplaces author) to exactly calculate whether
the light hits the surface, so we don't wrongly enable lighting on a surface by
an increased radius.
2025-02-07 23:07:08 +03:00
Alibek Omarov
a955d1e957 ref: gl: make GL_BuildPolygonFromSurface static, remove one global variable usage (which is unused anyway) 2025-02-07 22:55:38 +03:00
Alibek Omarov
2b2c967e85 engine: add ms3.mentality.rip master server 2025-02-07 19:32:37 +03:00
Alibek Omarov
c48d93e3ce public: use last Git commit date (committer date, to be exact) as more predictable source for build num 2025-02-07 17:51:10 +03:00
Alibek Omarov
8f257cc331 public: add parsing build date from ISO-8601 alike format 2025-02-07 17:47:23 +03:00
Alibek Omarov
151e7fe37b public: crtlib: check for empty buffer in Q_vsnprintf 2025-02-06 21:19:10 +03:00
Alibek Omarov
add02dc6f9 engine: fix potential UB in netadr_t 2025-02-06 20:54:18 +03:00
Alibek Omarov
d4c34abd6e engine: enable writing log even if console hasn't been enabled at the engine startup (it might be enabled later, it might also contain crash data) 2025-02-06 20:03:07 +03:00
Alibek Omarov
1d81e611f0 scripts: gha: use N+1 job count when building PSVita dependencies 2025-02-06 00:32:42 +03:00
Alibek Omarov
6a0038e26a ref: gl: always set texture env mode to GL_MODULATE in TriAPI's RenderMode call
Not sure if this is correct, but it's generally a good idea to restore it to an
expected value.
2025-02-06 00:30:32 +03:00
Alibek Omarov
1d99f65e86 filesystem: when shutting down, clean up gameinfo pointers and total games count 2025-02-05 21:14:08 +03:00
Alibek Omarov
5e524bca60 engine: client: enable half-texel hack for nearest filtering too, if the scaling factor isn't an integer 2025-02-05 20:16:16 +03:00
Alibek Omarov
cf3e56e275 engine: client: add alternative mode for hud_scale, where it scales HUD down to selected resolution with preserving aspect ratio 2025-02-05 19:47:59 +03:00
Alibek Omarov
ade560c601 common: cvar: make auto descriptions private to cvar subsystem, use them when Cvar_Get is called with NULL description
It allows us to not lose engine-side description when client or gameui registers cvar with the same name. In case of
menu it's the only way to get cvar pointer.
2025-02-05 19:11:16 +03:00
Alibek Omarov
62e3ba2126 engine: add cvars to control mounting additional directories
Use existing ui_language cvar for mounting localization folders.
2025-02-05 18:54:28 +03:00
Alibek Omarov
674a4e5883 filesystem: add ability to mount HD, LV, addon and language folders by engine request 2025-02-05 18:24:36 +03:00
Alibek Omarov
f911210b81 public: simplify ctype.h is* functions wrappers for null-terminated strings, add Q_isalpha 2025-02-05 18:21:18 +03:00
Alibek Omarov
14eb07653c engine: client: fix incorrect format in error message in CL_SetLightStyle 2025-02-05 17:41:01 +03:00
Alibek Omarov
54b0cf9991 ref: gl: check OES NPOT texture extension in BigGL mode 2025-02-05 14:00:44 +03:00
Alibek Omarov
3ebcb08a97 ref: gl: add cvar r_large_lightmaps to enable larger lightmap sizes, opt-in, yields better performance with VBO renderer 2025-02-05 13:02:37 +03:00
Alibek Omarov
23940f8590 readme: remove fontconfig from dependencies list, we aren't using it anymore [skip ci] 2025-02-04 21:00:42 +03:00
Alibek Omarov
687fb0123f engine: implement basic gamepad gyroscope calibration
Called on game controller becoming active or by user request.
Exposes current calibration state by read-only console variable.
2025-02-03 13:14:51 +03:00
Alibek Omarov
6c91fdb0cd ref: gl: gl2_shim: fix int vs GLuint 2025-02-02 20:57:37 +03:00
Alibek Omarov
4832232fd6 ci: attempt to fix flatpak upload 2025-02-02 20:31:51 +03:00
Alibek Omarov
185bce0489 engine: common: remove unused D_ enum used for MsgDev in old engine. Make sure all enums and structs here are not anonymous 2025-02-02 20:26:07 +03:00
Alibek Omarov
f460aa63b0 engine: platform: posix: don't forget to print backtrace to stderr too 2025-02-02 19:20:54 +03:00
Alibek Omarov
22f8b6f9c3 engine: platform: enable crash handler for macOS 2025-02-02 18:30:41 +03:00
Alibek Omarov
0cb034afc2 engine: wscript: improve execinfo and GNU backtrace() check 2025-02-02 18:18:26 +03:00
Alibek Omarov
d0464ef602 engine: platform: posix: use glibc-based backtrace implementation for crash handling, if execinfo.h can be found 2025-02-02 18:06:18 +03:00
Alibek Omarov
c3ebb84b97 ci: bump SDL2 to 2.30.12 2025-02-02 08:14:24 +03:00
Alibek Omarov
11742efbc3 engine: fix player move on dedicated servers 2025-02-02 08:08:15 +03:00
Alibek Omarov
95af635ab4 engine: client: add command replaybufferdat to aid in debugging protocol errors by parsing buffer.dat 2025-02-02 05:22:46 +03:00
Alibek Omarov
1abec80191 engine: client: set codepage to 0 if con_charset value is unknown 2025-02-02 02:34:08 +03:00
Alibek Omarov
93ebddfba3 public: utflib: simplify Q_EncodeUTF8 2025-02-02 02:31:56 +03:00
Alibek Omarov
5378494199 wscript: enable main() function for Android port, which was forgotten after last refactoring 2025-02-01 18:26:20 +03:00
Alibek Omarov
1b44d7733e engine: platform: add improved Platform_Vibrate2 function, that allows to control vibration strength 2025-02-01 18:08:53 +03:00
Alibek Omarov
694c630b44 engine: zone: don't error when trying to free NULL pointer, like standard C free() and C++ delete 2025-02-01 17:51:02 +03:00
Alibek Omarov
7df1d4b9e2 engine: platform: sdl: remove useless for us game controller events 2025-01-31 19:48:33 +03:00
Alibek Omarov
b16037eabf engine: drop raw SDL joystick API, always use GameController instead. Implement actually working rumble, ensure we're freeing up all resources related to gamepads 2025-01-31 17:50:19 +03:00
Alibek Omarov
bff7299f9b gha: publish binaries even if flatpak fails 2025-01-31 10:37:41 +03:00
Alibek Omarov
de196b1c58 common: xash3d_types: avoid defining true and false in C23 2025-01-31 10:36:27 +03:00
Alibek Omarov
a0eec8b85d scripts: waifulib: add special_install_path for platform-specific executable formats that create post link stage (was nro_install_path) 2025-01-31 10:25:02 +03:00
Alibek Omarov
c7e8ea2ffa scripts: gha: linux: build smaller SDL2 (without 2D renderer) for Linux as well 2025-01-31 10:02:19 +03:00
Alibek Omarov
1c1cf3d646 scripts: waifulib: psvita: make sce_sys truly optional in apply_vpk 2025-01-31 10:02:19 +03:00
Alibek Omarov
9759b80b78 scripts: waifulib: psvita: set default title id and app name to just test 2025-01-31 09:10:39 +03:00
Alibek Omarov
94b2c0b443 scripts: gha: build render-less SDL2 for PSVita 2025-01-31 09:10:09 +03:00
Alibek Omarov
ff8d17a5a8 scripts: waifulib: psvita: add missing cprogram attributes 2025-01-31 09:04:40 +03:00
Alibek Omarov
aa23196a55 scripts: waifulib: support vpk and nro pass for pure C programs, just in case 2025-01-30 20:51:01 +03:00
Alibek Omarov
83b488c37e wscript: let building client and dedicated server in the same configuration 2025-01-30 20:23:12 +03:00
Alibek Omarov
77abf621d7 ref: gl: make GL_Support and GL_MaxTextureUnits functions inlined 2025-01-30 19:02:53 +03:00
Alibek Omarov
f9d4ac2771 ref: gl: fix ugly seam at the skybox, thanks Spoike for help 2025-01-30 18:53:31 +03:00
Alibek Omarov
f076d84975 engine: platform: android: move dlsym-weak hack from C++ to C 2025-01-30 18:07:35 +03:00
Alibek Omarov
faf0b32a94 ref: gl: fix massive frame drop caused by ripples code rendering same texture multiple times in the frame 2025-01-29 20:15:21 +03:00
Alibek Omarov
feb80e5997 engine: platform: sdl: read gamecontrollerdb.txt from extras.pk3 2025-01-29 13:43:10 +03:00
Alibek Omarov
578a77518f engine: client: fix clearing keyboard buttons caused by typical brain fart 2025-01-29 10:04:47 +03:00
Alibek Omarov
2457ecf226 filesystem: fix recursive basedir possible cyclic dependency when default game directory uses a basedir that's base directory is undefined
That could happen when default game directory depends on base directory that don't have gameinfo.txt.
Because all game directories with liblist.gam automatically have dependency on default game directory, it causes cyclic dependency.
2025-01-29 09:49:29 +03:00
Alibek Omarov
8cd99885f1 filesystem: clean added status for game folders when purging search paths 2025-01-29 09:46:18 +03:00
Alibek Omarov
684e229ac8 engine: client: get rid of absolutely useless bitfields 2025-01-26 23:34:04 +03:00
SNMetamorph
c0f1d8c647 engine: model: fixed incorrect check in Mod_LoadModel 2025-01-26 23:27:18 +03:00
SNMetamorph
c3b8696957 engine: platform: win32: disable initializing console in case of regular game startup 2025-01-26 23:02:24 +03:00
Tom Kidd
3ca413dbab Fixed path calc for extras on Mac 2025-01-26 22:25:08 +03:00
Alibek Omarov
92dc04ff3c engine: client: minor change, add forgotten newline in CL_DeltaEntityGS Host_Error call 2025-01-25 17:51:48 +03:00
Alibek Omarov
ad6db91285 engine: move xashid stuff onto client 2025-01-25 17:51:48 +03:00
David DeGraw
90a0f74087 undo change to mod link 2025-01-25 08:23:04 +03:00
David DeGraw
4f7f5288a1 more nits 2025-01-25 08:23:04 +03:00
David DeGraw
c23b4bfe61 nits 2025-01-25 08:23:04 +03:00
David DeGraw
4780f70ea2 Improve mod installation instructions
Also improved uplink setup and used a better source for mod files.
2025-01-25 08:23:04 +03:00
NightFox
98a04c7764 FIx Matrix*x4_LoadIdentity (xash3d_mathlib.h) 2025-01-25 08:21:21 +03:00
Alibek Omarov
7da9772143 engine: check for macOS bundle in SDL_GetBasePath, and fallback to SDL_GetPrefPath for our directory 2025-01-23 22:58:19 +03:00
Alibek Omarov
f0b29bac1b engine: client: add cl_trace_consistency used to print which resources server wants to check 2025-01-23 13:57:17 +03:00
Alibek Omarov
7b5ff606bd 3rdparty: extras: enable compression of extras.pk3 2025-01-23 13:08:53 +03:00
Alibek Omarov
3e22ee64ae scripts: waifulib: zip: add support for passing compression level on Python 3.7. Exclude PNG files from compression 2025-01-23 13:08:21 +03:00
Alibek Omarov
c86c45503f engine: replace few more Xash3D strings by XASH_ENGINE_NAME macro 2025-01-23 10:33:22 +03:00
Alibek Omarov
ef75a4c28d engine: rename pref path on Mac to Xash3D FWGS by allowing for custom branding through XASH_ENGINE_NAME macro 2025-01-23 10:24:55 +03:00
Alibek Omarov
bccd3f2271 engine: pass launcher's default game directory all the way down to Platform_Init, so we mount correct extras.pk3 on Mac 2025-01-23 10:22:53 +03:00
Tom Kidd
7bbc3e8238 Made modifications for Mac App Bundle
- Looks for game data in SDL pref path (Application Support)
- Sets XASH3D_EXTRAS_PAK1 to SDL base path (Resources dir in App Bundle
- Added option to force search for SDL dylib via pkgconfig on Darwin instead of Framework (option for Mac Source Ports build process)
2025-01-23 10:15:47 +03:00
Alibek Omarov
c34e0c66d9 engine: add fuzzing target for Mod_LoadModel 2025-01-23 10:12:32 +03:00
Alibek Omarov
e5d80878b8 scripts: waifulib: add asan-only build type 2025-01-23 10:11:56 +03:00
Alibek Omarov
1e075d25b7 engine: make LZSS compression optional for 49 protocol, disable it for local clients (singleplayer) 2025-01-22 21:18:19 +03:00
Alibek Omarov
d29e53481d engine: client: remove unused S_StreamAviSamples 2025-01-22 20:01:11 +03:00
Alibek Omarov
d23a2fd2df engine: client: stub AVI_StreamSound RenderAPI call, it is not used in ffmpeg-based video playback code 2025-01-22 20:00:50 +03:00
Alibek Omarov
f6f15cc204 engine: mod_studio: validate studio self-reported length before loading model 2025-01-22 20:00:13 +03:00
Alibek Omarov
4f2249ed8e ref: support loading sprites with truncated palette 2025-01-22 19:24:00 +03:00
Alibek Omarov
9f322df498 engine: imagelib: handle loading truncated palette files, by filling remaining bytes with zeros 2025-01-22 19:21:51 +03:00
Alibek Omarov
b554d7e215 ref: properly handle unloading sprites that aren't loaded completely 2025-01-22 19:20:20 +03:00
Alibek Omarov
719093c10b ref: properly return false to the engine if renderer refuses to load the model for some reason 2025-01-22 19:13:23 +03:00
Alibek Omarov
c2da140ccc engine: model: do not crash if renderer refused to load this model 2025-01-22 19:12:43 +03:00
Alibek Omarov
375998dffb Cleanup xash3d_types.h from engine-specific macros and types 2025-01-22 15:10:18 +03:00
Alibek Omarov
787444f63d engine: simplify sound fx allocation 2025-01-22 14:46:40 +03:00
Alibek Omarov
0c50076ff0 engine: zone: ensure poolcount is zero on Memory_Init 2025-01-22 13:49:51 +03:00
Alibek Omarov
8ce01c38c7 engine: http: ensure we don't write broken decompressed files 2025-01-22 13:49:24 +03:00
Alibek Omarov
cac6206984 engine: client: allocate everything related to sounds in the sound pool 2025-01-22 13:49:02 +03:00
Alibek Omarov
a5c88bdda9 engine: touch: allow smoother migration from old engine touch configs by stripping .tga extension 2025-01-22 13:40:47 +03:00
Alibek Omarov
fc017286a6 engine: base_cmd: slightly faster search based on assumption that list is always ordered 2025-01-22 05:41:52 +03:00
Alibek Omarov
20d4e3e719 engine: fix flexible array member usage in case of null terminated strings
(woops)
2025-01-22 05:41:52 +03:00
Alibek Omarov
4eaa32fc10 engine: whereami: sync with upstream 2025-01-21 20:03:20 +03:00
Alibek Omarov
b7c025b167 filesystem: android: request buffer for Android asset LoadFile implementation
Might be better than asking for random access and then only reading forward.
2025-01-21 19:50:14 +03:00
Alibek Omarov
f29c588e0f filesystem: take code from DarkPlaces to properly read compressed files 2025-01-21 18:47:42 +03:00
Alibek Omarov
2065ef143a engine: server: fix ent_create under PrimeXT 2025-01-21 16:09:56 +03:00
Alibek Omarov
a5c02c85f0 filesystem: wad: get rid of sentinel value at the end of wad_types array 2025-01-21 15:26:06 +03:00
Alibek Omarov
9a8761f1d8 engine: client: remove unused NetAPI_ValueForKey function 2025-01-21 15:17:03 +03:00
Alibek Omarov
273990d292 engine: cmd: store command description in flexible array member 2025-01-21 15:06:08 +03:00
Alibek Omarov
0e27d8717c ref: remove servercount from texture struct, Xash don't use it (and it's also harmful anyway) 2025-01-21 14:36:42 +03:00
Alibek Omarov
8a9b209db0 engine: zone: optimize memory usage a bit by compressing memheader_t better while keeping it efficient
It saves about 40 kilobytes of memory.
2025-01-21 14:04:33 +03:00
Alibek Omarov
232d1f8583 engine: make separate mempools for cmds, cvars and basecmd 2025-01-21 11:26:35 +03:00
Alibek Omarov
6cfa5877a4 engine: base_cmd: decrease base cmd hash size 2025-01-21 11:25:33 +03:00
Alibek Omarov
154df00f94 filesystem: don't create full path to rwdir, as cwd is always equal to rwdir
Fixes updating gameinfo.txt.
2025-01-20 19:53:04 +03:00
Alibek Omarov
c5649c94d5 engine: client: fix delta entity packet flush on GoldSrc protocol
Implement counting playerbytes for more accurate net_graph, even if we're
skipping this delta frame.
2025-01-20 19:38:44 +03:00
Alibek Omarov
a1da10fe38 filesystem: set default values for quick/autosave aged count 2025-01-20 16:06:57 +03:00
Andrey Akhmichin
17a71ffc96 ci: upgrade freebsd tasks. 2025-01-19 04:36:07 +03:00
Andrey Akhmichin
4609fbc0c5 Documentation: supported-mod-list.md: update links. 2025-01-19 04:35:17 +03:00
Andrey Akhmichin
d278d3bdd7 engine: common: fix clang build. 2025-01-19 04:33:06 +03:00
Alibek Omarov
7811b60292 engine: common: fix build for apple and freebsd-15 2025-01-18 10:40:12 +03:00
Alibek Omarov
870fad5606 public: tests: remove Q_colorstr tests 2025-01-18 10:36:11 +03:00
Alibek Omarov
3e93aa459d engine: net_buffer: turn bit write and read masks into predefined arrays, so we don't have to call InitMasks
In future, net_buffer might get moved to libpublic.

Also, get rid of 32-th bit write mask, it's only get used when we're trying to
write zero bits value which is nonsense.
2025-01-18 09:54:11 +03:00
Alibek Omarov
626c5e44f6 engine: client: use existing engine functions for some client API functions 2025-01-18 09:44:21 +03:00
Alibek Omarov
c906aa0106 ref: gl: make DrawGLPoly and R_TextureAnimation private to brush rendering code 2025-01-18 08:39:31 +03:00
Alibek Omarov
0a41b70e44 ref: gl: store ripple texture in texture's fb_texturenum as it's only used for water and water don't have luma 2025-01-18 08:38:43 +03:00
Alibek Omarov
ea338adc46 ref: gl: make GL_FrustumSetPlanme private to the frustum implementation 2025-01-18 08:34:25 +03:00
Alibek Omarov
5fa777578b ref: gl: fix detail texture leak, fix texture leak when texture have default texture set (in which case it still might have other textures set) 2025-01-18 08:33:20 +03:00
Alibek Omarov
5b9db5940b engine: mod_bmodel: don't try to load luma/fullbright texture for water, as no renderers support it anyway, and instead we will use that field for rippletexture 2025-01-18 08:30:59 +03:00
Alibek Omarov
4b1b3aa13c public: remove Q_colorstr, as it's completely useless and checking for color string is easy actually 2025-01-18 08:29:36 +03:00
Alibek Omarov
2d51d23d89 engine: client: don't send commands until ca_active on Xash protocol 2025-01-17 15:06:59 +03:00
Alibek Omarov
b5b6dad39c engine: fix a typo in scroll lock (missing L) 2025-01-15 23:49:13 +03:00
Alibek Omarov
a5619e9960 engine: take keydefs header from Quake-2 source code (client/keys.h) 2025-01-15 23:47:55 +03:00
Alibek Omarov
a75666a3cd engine: common: fix dedicated build by defining SV_GetMaxClients before CL_GetMaxClients stub (that redirects to it)
Also remove CL_Shutdown from dedicated stub lists.
2025-01-14 13:10:02 +03:00
Alibek Omarov
49426721d8 engine: use zero initializers instead of memset 2025-01-14 12:11:27 +03:00
Alibek Omarov
04125284a3 engine: dedicated: make some stubs inlined 2025-01-14 12:10:31 +03:00
Alibek Omarov
1d4f7b2f94 engine: server: slight refactoring, make SV_ModelHandle inlined, move PlayerIsFrozen to sv_client, fix packet loss data type 2025-01-14 12:09:23 +03:00
Alibek Omarov
38c82a3f76 engine: don't bother calculating crc32 for local clients for better performance (thanks @tyabus for the idea) 2025-01-14 11:55:28 +03:00
Alibek Omarov
785632a437 filesystem: minor refactoring in MD5_HashFile, use initializer instead of memset, limit buffer variable scope 2025-01-14 11:36:13 +03:00
Alibek Omarov
4be75af214 engine: client: always write buffer.dat so we will be able to request it from users. Append protocol number to it 2025-01-14 11:31:10 +03:00
Alibek Omarov
dcdca01e86 ref: gl: declare VBO globals static 2025-01-14 11:30:35 +03:00
156 changed files with 6120 additions and 4804 deletions

View File

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

View File

@@ -66,7 +66,7 @@ jobs:
targetos: apple targetos: apple
targetarch: amd64 targetarch: amd64
env: env:
SDL_VERSION: 2.30.11 SDL_VERSION: 2.32.0
GH_CPU_ARCH: ${{ matrix.targetarch }} GH_CPU_ARCH: ${{ matrix.targetarch }}
GH_CROSSCOMPILING: ${{ matrix.cross }} GH_CROSSCOMPILING: ${{ matrix.cross }}
steps: steps:
@@ -87,6 +87,7 @@ jobs:
path: artifacts/* path: artifacts/*
flatpak: flatpak:
runs-on: ubuntu-latest runs-on: ubuntu-latest
continue-on-error: true
strategy: strategy:
matrix: matrix:
include: include:
@@ -100,7 +101,7 @@ jobs:
with: with:
submodules: recursive submodules: recursive
- name: Build flatpak (Compat.i386) - name: Build flatpak (Compat.i386)
uses: FWGS/flatpak-github-actions/flatpak-builder@v6.3 uses: FWGS/flatpak-github-actions/flatpak-builder@v6.3-fix
with: with:
bundle: ${{ matrix.app }}.flatpak bundle: ${{ matrix.app }}.flatpak
manifest-path: scripts/flatpak/${{ matrix.app }}.yml manifest-path: scripts/flatpak/${{ matrix.app }}.yml
@@ -119,7 +120,6 @@ jobs:
--yes \ --yes \
--cleanup-tag \ --cleanup-tag \
--repo "$GITHUB_REPOSITORY" || true --repo "$GITHUB_REPOSITORY" || true
sleep 20s
gh run download "$GITHUB_RUN_ID" \ gh run download "$GITHUB_RUN_ID" \
--dir artifacts/ \ --dir artifacts/ \
--repo "$GITHUB_REPOSITORY" --repo "$GITHUB_REPOSITORY"

9
.gitmodules vendored
View File

@@ -27,10 +27,13 @@
url = https://github.com/FWGS/MultiEmulator url = https://github.com/FWGS/MultiEmulator
[submodule "3rdparty/libogg/libogg"] [submodule "3rdparty/libogg/libogg"]
path = 3rdparty/libogg/libogg path = 3rdparty/libogg/libogg
url = https://gitlab.xiph.org/xiph/ogg.git url = https://github.com/xiph/ogg.git
[submodule "3rdparty/vorbis/vorbis-src"] [submodule "3rdparty/vorbis/vorbis-src"]
path = 3rdparty/vorbis/vorbis-src path = 3rdparty/vorbis/vorbis-src
url = https://gitlab.xiph.org/xiph/vorbis.git url = https://github.com/xiph/vorbis.git
[submodule "3rdparty/opusfile/opusfile"] [submodule "3rdparty/opusfile/opusfile"]
path = 3rdparty/opusfile/opusfile path = 3rdparty/opusfile/opusfile
url = https://gitlab.xiph.org/xiph/opusfile.git url = https://github.com/xiph/opusfile.git
[submodule "3rdparty/libbacktrace/libbacktrace"]
path = 3rdparty/libbacktrace/libbacktrace
url = https://github.com/ianlancetaylor/libbacktrace

View File

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

185
3rdparty/libbacktrace/wscript vendored Normal file
View File

@@ -0,0 +1,185 @@
#! /usr/bin/env python
# encoding: utf-8
from waflib import TaskGen
FRAGMENT_ATOMIC='''int i;
int main(void) {
__atomic_load_n(&i, __ATOMIC_ACQUIRE);
__atomic_store_n(&i, 1, __ATOMIC_RELEASE);
return 0;
}'''
FRAGMENT_SYNC='''int i;
int main (void) {
__sync_bool_compare_and_swap (&i, i, i);
__sync_lock_test_and_set (&i, 1);
__sync_lock_release (&i);
return 0;
}'''
FRAGMENT_GETPAGESIZE='''#include <unistd.h>
int main(void) { return getpagesize() }'''
FRAGMENT_GETEXECNAME='''#include <stdlib.h>
int main(void) { return getexecname() != 0 }'''
FRAGMENT_STRNLEN='''#include <string.h>
int main(int argc, char **argv) { return (int)strnlen(argv[0], 10); }'''
FRAGMENT_DL_ITERATE_PHDR='''#include <%s>
int main(void) { return dl_iterate_phdr(0, 0); }'''
FRAGMENT_FCNTL='''#include <fcntl.h>
int main(void) { return fcntl(0, 0, 0); }'''
FRAGMENT_GETIPINFO='''#include "unwind.h"
struct _Unwind_Context *context;
int ip_before_insn = 0;
int main(void) { return _Unwind_GetIPInfo(context, &ip_before_insn); }'''
FRAGMENT_LOADQUERY='''#include <sys/ldr.h>
#include <sys/debug.h>
int main(void) { return loadquery(0, 0, 0); }'''
FRAGMENT_KERN_PROC='''#include <sys/sysctl.h>
#if !defined(%s) || !defined(KERN_PROC_PATHNAME)
#error
#endif
int main(void) { return 0; }'''
FRAGMENT_LSTAT='''#include <sys/stat.h>
struct stat st;
int main(int argc, char **argv) { return lstat(argv[0], &st); }'''
FRAGMENT_READLINK='''#include <unistd.h>
char buf[100];
int main(int argc, char **argv) { return readlink(argv[0], buf, sizeof(buf)); }'''
def options(opt):
pass
def configure(conf):
# add unsupported platforms here
if conf.env.DEST_OS in ['nswitch', 'psvita', 'dos']:
conf.env.DISABLE_LIBBACKTRACE = True
return
# win32 has it's own dbghelp-based backtrace, that's why we ship PDBs
if conf.env.COMPILER_CC == 'msvc':
conf.env.DISABLE_LIBBACKTRACE = True
return
if not conf.path.find_dir('libbacktrace') or not conf.path.find_dir('libbacktrace/config'):
conf.fatal('Can\'t find libbacktrace submodule. Run `git submodule update --init --recursive`.')
return
if conf.env.DEST_SIZEOF_VOID_P == 8:
conf.define('BACKTRACE_ELF_SIZE', 64)
conf.define('BACKTRACE_XCOFF_SIZE', 64)
else:
conf.define('BACKTRACE_ELF_SIZE', 32)
conf.define('BACKTRACE_XCOFF_SIZE', 32)
conf.define('_ALL_SOURCE', 1)
conf.define('_GNU_SOURCE', 1)
conf.define('_POSIX_PTHREAD_SEMANTICS', 1)
conf.define('_TANDEM_SOURCE', 1)
conf.define('__EXTENSIONS__', 1)
conf.define('_DARWIN_USE_64_BIT_INODE', 1)
conf.define('_LARGE_FILES', 1)
conf.check_large_file(compiler='c', execute=False, mandatory=False) # sets _FILE_OFFSET_BITS
conf.env.CFLAGS_EXTRAFLAGS = conf.filter_cflags(['-funwind-tables', '-g'], [])
if conf.filter_cflags(['-frandom-seed=test'], []):
conf.env.HAVE_FRANDOM_SEED = True
def check_header(hdr):
return {'header_name':hdr, 'msg':'... %s header' % hdr, 'mandatory':False, 'id':hdr}
conf.multicheck(
check_header('dlfcn.h'),
check_header('inttypes.h'),
check_header('link.h'),
check_header('sys/link.h'),
check_header('mach-o/dyld.h'),
check_header('memory.h'),
check_header('stdint.h'),
check_header('stdlib.h'),
check_header('strings.h'),
check_header('string.h'),
check_header('sys/ldr.h'),
check_header('sys/mman.h'),
check_header('sys/stat.h'),
check_header('sys/types.h'),
check_header('tlhelp32.h'),
check_header('unistd.h'),
check_header('windows.h'),
{'fragment':FRAGMENT_ATOMIC, 'msg':'... __atomic extensions', 'define_name':'HAVE_ATOMIC_FUNCTIONS', 'mandatory':False},
{'fragment':FRAGMENT_SYNC, 'msg':'... __sync extensions', 'define_name':'HAVE_SYNC_FUNCTIONS', 'mandatory':False},
{'fragment':FRAGMENT_GETPAGESIZE, 'msg':'... getpagesize function', 'define_name':'HAVE_DECL_GETPAGESIZE', 'mandatory':False},
{'fragment':FRAGMENT_STRNLEN, 'msg':'... strnlen function', 'define_name':'HAVE_DECL_STRNLEN', 'mandatory':False},
{'fragment':FRAGMENT_DL_ITERATE_PHDR % 'link.h', 'msg':'... dl_iterate_phdr function in link.h', 'define_name':'HAVE_DL_ITERATE_PHDR', 'after_tests': ['link.h'], 'mandatory':False},
{'fragment':FRAGMENT_DL_ITERATE_PHDR % 'sys/link.h', 'msg':'... dl_iterate_phdr function in sys/link.h', 'define_name':'HAVE_DL_ITERATE_PHDR', 'after_tests': ['sys/link.h'], 'mandatory':False},
{'fragment':FRAGMENT_FCNTL,'msg':'... fnctl function', 'define_name':'HAVE_FCNTL', 'mandatory':False},
{'fragment':FRAGMENT_GETEXECNAME,'msg':'... getexecname function','define_name':'HAVE_GETEXECNAME', 'mandatory':False},
{'fragment':FRAGMENT_GETIPINFO, 'msg':'... _Unwind_GetIPInfo function', 'define_name':'HAVE_GETIPINFO', 'mandatory':False},
{'fragment':FRAGMENT_KERN_PROC % 'KERN_PROC', 'msg': '... KERN_PROC and KERN_PROC_PATHNAME defines', 'define_name':'HAVE_KERN_PROC', 'mandatory':False},
{'fragment':FRAGMENT_KERN_PROC % 'KERN_PROC_ARGS', 'msg': '... KERN_PROC_ARGS and KERN_PROC_PATHNAME defines', 'define_name':'HAVE_KERN_PROC_ARGS', 'mandatory':False},
{'fragment':FRAGMENT_LOADQUERY, 'msg': '... loadquery function', 'define_name':'HAVE_LOADQUERY', 'mandatory':False},
{'fragment':FRAGMENT_LSTAT, 'msg': '... lstat function', 'define_name':'HAVE_LSTAT', 'mandatory':False},
{'fragment':FRAGMENT_READLINK, 'msg': '... readlink function', 'define_name':'HAVE_READLINK', 'mandatory':False},
# {'lib':'lzma', 'define_name':'HAVE_LIBLZMA', 'uselib_store':'lzma', 'msg':'... lzma library', 'mandatory':False},
# {'lib':'z', 'define_name':'HAVE_ZLIB', 'uselib_store':'z', 'msg':'... zlib library', 'mandatory':False},
# {'lib':'zstd', 'define_name':'HAVE_ZSTD', 'uselib_store':'zstd', 'msg':'... zstd library', 'mandatory':False},
msg='Checking for in parallel'
)
conf.write_config_header()
conf.define('BACKTRACE_SUPPORTED', 1)
conf.define('BACKTRACE_USES_MALLOC', 0)
conf.define('BACKTRACE_SUPPORTS_THREADS', 1)
conf.define('BACKTRACE_SUPPORTS_DATA', conf.env.DEST_BINFMT in ['elf', 'mac-o'])
conf.write_config_header('backtrace-supported.h')
@TaskGen.feature('frandomseed')
@TaskGen.after_method('propagate_uselib_vars')
def process_frandom_seed(ctx):
tasks = getattr(ctx, 'compiled_tasks', [])
for task in tasks:
out = task.outputs[0]
task.env.CFLAGS = list(task.env.CFLAGS) # need a copy
task.env.CFLAGS += ['-frandom-seed=%s' % out.path_from(out.ctx.bldnode)]
def build(bld):
if bld.env.DISABLE_LIBBACKTRACE:
return
# we specifically only want mmap-based allocators because calling malloc is not safe from signal handlers
sources = ['atomic.c', 'dwarf.c', 'fileline.c', 'posix.c', 'print.c', 'sort.c', 'state.c', 'backtrace.c', 'simple.c', 'mmap.c', 'mmapio.c']
if bld.env.DEST_BINFMT == 'pe':
sources += ['pecoff.c']
elif bld.env.DEST_BINFMT == 'mac-o':
sources += ['macho.c']
elif bld.env.DEST_BINFMT == 'elf':
sources += ['elf.c']
else:
sources += ['unknown.c']
task = bld.stlib(
source = ['libbacktrace/' + i for i in sources],
target = 'backtrace',
features = 'frandomseed' if bld.env.HAVE_FRANDOM_SEED else '',
use = 'EXTRAFLAGS lzma z zstd',
includes = '. libbacktrace/',
export_defines = 'HAVE_LIBBACKTRACE=1',
export_includes = 'libbacktrace/'
)

View File

@@ -6,7 +6,7 @@ For connecting to GoldSrc-based servers, use this command:
connect ip:port gs connect ip:port gs
``` ```
But keep in mind, there are requirement for server to be able to accept connections from Xash3D-based clients: it should use Reunion or Dproto. But keep in mind, there are requirement for server to be able to accept connections from Xash3D-based clients: it should use Reunion.
Without this requirement, you will just get "Steam validation rejected" error on connecting. Without this requirement, you will just get "Steam validation rejected" error on connecting.
That is because proper authorization with Steam API is not implemented in engine yet (but we have plans on it). That is because proper authorization with Steam API is not implemented in engine yet (but we have plans on it).

View File

@@ -38,6 +38,9 @@ Uploaded to github by Oleg Cherkasky - https://github.com/gunrunners-paradise/Ct
## Deathmatch Classic ## Deathmatch Classic
Available in Valve's Half-Life repository - https://github.com/ValveSoftware/halflife/tree/master/dmc Available in Valve's Half-Life repository - https://github.com/ValveSoftware/halflife/tree/master/dmc
## Delta Particles
Available on ModDB - https://www.moddb.com/mods/half-life-delta/downloads/delta-particles-full-sources-maps-and-c-code
## Earth Special Forces ## Earth Special Forces
Alpha 2.0 - https://www.gamers-desire.de/details/2830 Alpha 2.0 - https://www.gamers-desire.de/details/2830

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,7 @@
# Xash3D FWGS Engine <img align="right" width="128" height="128" src="https://github.com/FWGS/xash3d-fwgs/raw/master/game_launch/icon-xash-material.png" alt="Xash3D FWGS icon" /> # Xash3D FWGS Engine <img align="right" width="128" height="128" src="https://github.com/FWGS/xash3d-fwgs/raw/master/game_launch/icon-xash-material.png" alt="Xash3D FWGS icon" />
[![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/) \ [![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) \
[![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) [![Discord Server](https://img.shields.io/discord/355697768582610945?logo=Discord&label=International%20Discord%20chat)](http://fwgsdiscord.mentality.rip/) [![Russian speakers Telegram Chat](https://img.shields.io/badge/Russian_speakers_Telegram_chat-gray?logo=Telegram)](https://t.me/flyingwithgauss) \
[![Download Daily Build](https://img.shields.io/badge/downloads-testing-orange)](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous)
Xash3D ([pronounced](https://ipa-reader.com/?text=ks%C9%91%CA%82) `[ksɑʂ]`) FWGS is a game engine, aimed to provide compatibility with Half-Life Engine and extend it, as well as to give game developers well known workflow. Xash3D ([pronounced](https://ipa-reader.com/?text=ks%C9%91%CA%82) `[ksɑʂ]`) FWGS is a game engine, aimed to provide compatibility with Half-Life Engine and extend it, as well as to give game developers well known workflow.
@@ -65,21 +66,21 @@ This repository contains our fork of HLSDK and restored source code for Half-Lif
* Only for 32-bit engine on 64-bit x86 operating system: * Only for 32-bit engine on 64-bit x86 operating system:
* Enable i386 on your system: `$ sudo dpkg --add-architecture i386`. * Enable i386 on your system: `$ sudo dpkg --add-architecture i386`.
* Install `aptitude` ([why?](https://github.com/FWGS/xash3d-fwgs/issues/1828#issuecomment-2415131759)): `$ sudo apt update && sudo apt upgrade && sudo apt install aptitude` * Install `aptitude` ([why?](https://github.com/FWGS/xash3d-fwgs/issues/1828#issuecomment-2415131759)): `$ sudo apt update && sudo apt upgrade && sudo apt install aptitude`
* Install development tools: `$ sudo aptitude --without-recommends install git build-essential gcc-multilib g++-multilib libsdl2-dev:i386 libfontconfig-dev:i386 libfreetype-dev:i386 libopus-dev:i386 libbz2-dev:i386`. * Install development tools: `$ sudo aptitude --without-recommends install git build-essential gcc-multilib g++-multilib libsdl2-dev:i386 libfreetype-dev:i386 libopus-dev:i386 libbz2-dev:i386 libvorbis-dev:i386 libopusfile-dev:i386 libogg-dev:i386`.
* Set PKG_CONFIG_PATH environment variable to point at 32-bit libraries: `$ export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig`. * Set PKG_CONFIG_PATH environment variable to point at 32-bit libraries: `$ export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig`.
* For 64-bit engine on 64-bit x86 and other non-x86 systems: * For 64-bit engine on 64-bit x86 and other non-x86 systems:
* Install development tools: `$ sudo apt install git build-essential python libsdl2-dev libfontconfig-dev libfreetype6-dev libopus-dev libbz2-dev`. * Install development tools: `$ sudo apt install git build-essential python libsdl2-dev libfreetype6-dev libopus-dev libbz2-dev libvorbis-dev libopusfile-dev libogg-dev`.
* Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`. * Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`.
##### RedHat/Fedora ##### RedHat/Fedora
* Only for 32-bit engine on 64-bit x86 operating system: * Only for 32-bit engine on 64-bit x86 operating system:
* Install development tools: `$ sudo dnf install git gcc gcc-c++ glibc-devel.i686 SDL2-devel.i686 opus-devel.i686 fontconfig-devel.i686 freetype-devel.i686 bzip2-devel.i686`. * Install development tools: `$ sudo dnf install git gcc gcc-c++ glibc-devel.i686 SDL2-devel.i686 opus-devel.i686 freetype-devel.i686 bzip2-devel.i686 libvorbis-devel.i686 opusfile-devel.i686 libogg-devel.i686`.
* Set PKG_CONFIG_PATH environment variable to point at 32-bit libraries: `$ export PKG_CONFIG_PATH=/usr/lib/pkgconfig`. * Set PKG_CONFIG_PATH environment variable to point at 32-bit libraries: `$ export PKG_CONFIG_PATH=/usr/lib/pkgconfig`.
* For 64-bit engine on 64-bit x86 and other non-x86 systems: * For 64-bit engine on 64-bit x86 and other non-x86 systems:
* Install development tools: `$ sudo dnf install git gcc gcc-c++ SDL2-devel opus-devel fontconfig-devel freetype-devel bzip2-devel`. * Install development tools: `$ sudo dnf install git gcc gcc-c++ SDL2-devel opus-devel freetype-devel bzip2-devel libvorbis-devel opusfile-devel libogg-devel`.
* Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`. * Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`.

View File

@@ -1,49 +1,39 @@
cmake_minimum_required(VERSION 3.6) cmake_minimum_required(VERSION 3.22)
# Only used to build Android project # Only used to build Android project
project(XASH_ANDROID) project(XASH_ANDROID)
# armeabi-v7a requires cpufeatures library # armeabi-v7a requires cpufeatures library
include(AndroidNdkModules) if(ANDROID)
android_ndk_import_module_cpufeatures() include_directories(${ANDROID_NDK}/sources/android/cpufeatures)
add_library(cpufeatures ${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c)
target_link_libraries(cpufeatures dl)
endif()
find_package(PythonInterp 2.7 REQUIRED) include(FindPython)
get_filename_component(C_COMPILER_ID ${CMAKE_C_COMPILER} NAME_WE)
get_filename_component(CXX_COMPILER_ID ${CMAKE_CXX_COMPILER} NAME_WE)
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
set(BUILD_TYPE "debug") set(BUILD_TYPE "debug")
else() else()
set(BUILD_TYPE "release") set(BUILD_TYPE "release")
list(APPEND WAF_EXTRA_ARGS --enable-poly-opt --enable-lto) list(APPEND WAF_EXTRA_ARGS --enable-poly-opt --enable-lto --enable-limited-debuginfo)
endif() endif()
if(CMAKE_SIZEOF_VOID_P MATCHES "8") if(ANDROID_ABI STREQUAL "x86")
set(64BIT ON CACHE BOOL "" FORCE) # HACKHACK: I don't know why but engine gets built as 64-bit binary here
list(APPEND WAF_EXTRA_ARGS -8) # only required for x86 when testing this cmakelist under linux list(APPEND WAF_EXTRA_ARGS -4)
endif() endif()
set(CMAKE_VERBOSE_MAKEFILE ON) set(CMAKE_VERBOSE_MAKEFILE ON)
set(WAF_CC "${CMAKE_C_COMPILER} --target=${CMAKE_C_COMPILER_TARGET}")
set(WAF_CXX "${CMAKE_CXX_COMPILER} --target=${CMAKE_CXX_COMPILER_TARGET}")
# not cleanest way to get upper directory # not cleanest way to get upper directory
set(ENGINE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../") set(ENGINE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../")
execute_process( set(WAF_CC "${CMAKE_C_COMPILER} --target=${CMAKE_C_COMPILER_TARGET}")
COMMAND ${CMAKE_COMMAND} -E env set(WAF_CXX "${CMAKE_CXX_COMPILER} --target=${CMAKE_CXX_COMPILER_TARGET}")
CC=${WAF_CC} CXX=${WAF_CXX} set(WAF ${Python_EXECUTABLE} ${ENGINE_SOURCE_DIR}waf -t ${ENGINE_SOURCE_DIR} -o ${CMAKE_CURRENT_BINARY_DIR}/xash3d-fwgs)
AR=${CMAKE_AR} STRIP=${CMAKE_STRIP}
${PYTHON_EXECUTABLE} waf configure -T ${BUILD_TYPE} ${WAF_EXTRA_ARGS} cmake
--check-c-compiler=${C_COMPILER_ID} --check-cxx-compiler=${CXX_COMPILER_ID}
-s "${ENGINE_SOURCE_DIR}/SDL" --skip-sdl2-sanity-check --enable-bundled-deps
WORKING_DIRECTORY "${ENGINE_SOURCE_DIR}"
)
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/hlsdk-portable" hlsdk-portable)
# try to build minimal SDL. Enable features as we're gonna use them # try to build minimal SDL. Enable features as we're gonna use them
set(SDL_RENDER OFF) set(SDL_RENDER OFF)
@@ -56,5 +46,50 @@ set(SDL_VULKAN OFF)
set(SDL_OFFSCREEN OFF) set(SDL_OFFSCREEN OFF)
set(SDL_STATIC OFF) set(SDL_STATIC OFF)
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/SDL" SDL) add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/SDL" SDL)
add_subdirectory("${ENGINE_SOURCE_DIR}/" xash3d-fwgs)
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/mainui" mainui) include(ExternalProject)
# gradle passes backslashes to cmake, how does this even work for everybody else?
string(REPLACE "\\" "/" CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
ExternalProject_Add(
Xash3DFWGS
SOURCE_DIR ${ENGINE_SOURCE_DIR}
INSTALL_DIR ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
BUILD_IN_SOURCE TRUE
DEPENDS SDL2
BUILD_ALWAYS TRUE
LOG_CONFIGURE TRUE
LOG_BUILD TRUE
LOG_INSTALL TRUE
LOG_OUTPUT_ON_FAILURE TRUE
LOG_MERGED_STDOUTERR TRUE
# USES_TERMINAL_CONFIGURE TRUE
# USES_TERMINAL_BUILD TRUE
# USES_TERMINAL_INSTALL TRUE
# NOTE: setting up WAFLOCK is important to avoid possible race conditions
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env
ANDROID_NDK=${ANDROID_NDK}
BUILD_CMAKE_LIBRARY_OUTPUT_DIRECTORY=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
WAFLOCK=.lock-waf_android_${ANDROID_ABI}_build
${WAF} configure -T ${BUILD_TYPE} --android=${ANDROID_ABI},,${CMAKE_SYSTEM_VERSION}
-s "${ENGINE_SOURCE_DIR}/3rdparty/SDL" --enable-bundled-deps ${WAF_EXTRA_ARGS}
BUILD_COMMAND ${CMAKE_COMMAND} -E env
WAFLOCK=.lock-waf_android_${ANDROID_ABI}_build
${WAF} build -v
INSTALL_COMMAND ${CMAKE_COMMAND} -E env
WAFLOCK=.lock-waf_android_${ANDROID_ABI}_build
${WAF} install --destdir=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
)
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/hlsdk-portable" hlsdk-portable)
# a1ba: without this, xash3d target will be ignored as nothing depends on it
add_dependencies(client Xash3DFWGS)
add_dependencies(server Xash3DFWGS)

View File

@@ -9,7 +9,7 @@ plugins {
android { android {
namespace = "su.xash.engine" namespace = "su.xash.engine"
ndkVersion = "27.2.12479018" ndkVersion = "28.0.13004108"
defaultConfig { defaultConfig {
applicationId = "su.xash" applicationId = "su.xash"
@@ -96,6 +96,7 @@ android {
packaging { packaging {
jniLibs { jniLibs {
useLegacyPackaging = true useLegacyPackaging = true
keepDebugSymbols.add("**/*.so")
} }
} }
} }
@@ -112,7 +113,7 @@ dependencies {
implementation("androidx.preference:preference-ktx:1.2.1") implementation("androidx.preference:preference-ktx:1.2.1")
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0") implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
implementation("androidx.work:work-runtime-ktx:2.9.0") implementation("androidx.work:work-runtime-ktx:2.9.0")
// implementation "androidx.legacy:legacy-support-v4:1.0.0" // implementation "androidx.legacy:legacy-support-v4:1.0.0"
implementation("com.madgag.spongycastle:prov:1.58.0.0") implementation("com.madgag.spongycastle:prov:1.58.0.0")
implementation("in.dragonbra:javasteam:1.2.0") implementation("in.dragonbra:javasteam:1.2.0")

View File

@@ -21,3 +21,6 @@ kotlin.code.style=official
# resources declared in the library itself and none from the library's dependencies, # resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library # thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true android.nonTransitiveRClass=true
# Enable verbose output for CMake
android.native.buildOutput=verbose

View File

@@ -28,7 +28,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define PORT_ANY -1 #define PORT_ANY -1
typedef enum {NA_LOOPBACK = 1, NA_BROADCAST, NA_IP, NA_IPX, NA_BROADCAST_IPX, NA_IP6, NA_MULTICAST_IP6} netadrtype_t; typedef enum netadrtype_e
{
NA_UNDEFINED = 0,
NA_LOOPBACK,
NA_BROADCAST,
NA_IP,
NA_IPX,
NA_BROADCAST_IPX,
NA_IP6,
NA_MULTICAST_IP6
} netadrtype_t;
/* /*
Original Quake-2 structure: Original Quake-2 structure:
@@ -46,29 +56,60 @@ typedef struct
#pragma pack( push, 1 ) #pragma pack( push, 1 )
typedef struct netadr_s typedef struct netadr_s
{ {
// the reason we do this evil thing, is that when this struct contains IPv6
// address the `type` is 2-byte wide, but when it doesn't `type` must 4-byte
// wide _and_ ip6_0 must be zeroed, to keep it binary compatible.
#if XASH_LITTLE_ENDIAN
uint16_t type;
uint8_t ip6_0[2];
#elif XASH_BIG_ENDIAN
uint8_t ip6_0[2];
uint16_t type;
#else
#error
#endif
union union
{ {
// IPv6 struct // IPv6 struct
uint8_t ip6_1[14];
struct struct
{ {
uint16_t type6;
uint8_t ip6[16];
};
struct
{
uint32_t type; // must be netadrtype_t but will break with short enums
union union
{ {
uint8_t ip[4]; uint8_t ip[4];
uint32_t ip4; // for easier conversions uint32_t ip4; // for easier conversions
}; };
uint8_t ipx[10]; uint8_t ipx[10];
}; };
}; };
uint16_t port; uint16_t port;
} netadr_t; } netadr_t;
#pragma pack( pop ) #pragma pack( pop )
static inline netadrtype_t NET_NetadrType( const netadr_t *a )
{
if( a->type == NA_IP6 || a->type == NA_MULTICAST_IP6 )
return (netadrtype_t)a->type;
if( a->ip6_0[0] || a->ip6_0[1] )
return NA_UNDEFINED;
return (netadrtype_t)a->type;
}
static inline void NET_NetadrSetType( netadr_t *a, netadrtype_t type )
{
if( type == NA_IP6 || type == NA_MULTICAST_IP6 )
{
a->type = type;
return;
}
a->ip6_0[0] = a->ip6_0[1] = 0;
a->type = type;
}
STATIC_CHECK_SIZEOF( netadr_t, 20, 20 ); STATIC_CHECK_SIZEOF( netadr_t, 20, 20 );
#endif // NET_ADR_H #endif // NET_ADR_H

View File

@@ -86,8 +86,4 @@ GNU General Public License for more details.
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
#if defined XASH_SDL && !defined REF_DLL
#include <SDL.h>
#endif
#endif // PORT_H #endif // PORT_H

View File

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

View File

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

View File

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

View File

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

View File

@@ -13,10 +13,12 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
*/ */
#include <ctype.h>
#include "common.h" #include "common.h"
#include "filesystem.h" #include "filesystem.h"
#include "client.h" #include "client.h"
#include "qfont.h" #include "qfont.h"
#include "utflib.h"
qboolean CL_FixedFont( cl_font_t *font ) qboolean CL_FixedFont( cl_font_t *font )
{ {
@@ -173,31 +175,27 @@ static int CL_CalcTabStop( const cl_font_t *font, int x )
return stop; return stop;
} }
int CL_DrawCharacter( float x, float y, int number, rgba_t color, cl_font_t *font, int flags ) static int CL_DrawBitmapCharacter( float x, float y, uint32_t uc, const rgba_t color, const cl_font_t *font, int flags )
{ {
wrect_t *rc; wrect_t *rc;
float w, h; float w, h;
float s1, t1, s2, t2, half = 0.5f; float s1, t1, s2, t2, half = 0.5f;
int texw, texh; int texw, texh;
uint32_t number;
if( !font || !font->valid || y < -font->charHeight ) // bitmap fonts need conversion. Do this and validate the result
if( g_codepage == 1251 )
number = Q_UnicodeToCP1251( uc );
else if( g_codepage == 1252 )
number = Q_UnicodeToCP1252( uc );
else
number = uc;
if( !number || number >= ARRAYSIZE( font->charWidths ))
return 0; return 0;
// check if printable // start rendering
if( number <= 32 ) if( !font->charWidths[number] )
{
if( number == ' ' )
return font->charWidths[' '];
else if( number == '\t' )
return CL_CalcTabStop( font, x );
return 0;
}
if( FBitSet( flags, FONT_DRAW_UTF8 ))
number = Con_UtfProcessChar( number & 255 );
else number &= 255;
if( !number || !font->charWidths[number])
return 0; return 0;
R_GetTextureParms( &texw, &texh, font->hFontTexture ); R_GetTextureParms( &texw, &texh, font->hFontTexture );
@@ -231,29 +229,60 @@ int CL_DrawCharacter( float x, float y, int number, rgba_t color, cl_font_t *fon
return font->charWidths[number]; return font->charWidths[number];
} }
int CL_DrawString( float x, float y, const char *s, rgba_t color, cl_font_t *font, int flags ) static int CL_DrawTrueTypeCharacter( float x, float y, uint32_t uc, const rgba_t color, cl_font_t *font, int flags )
{
// stub
return 0;
}
int CL_DrawCharacter( float x, float y, uint32_t uc, const rgba_t color, const cl_font_t *font, int flags )
{
if( !font || !font->valid || y < -font->charHeight )
return 0;
// check if printable
if( uc <= 32 )
{
if( uc == ' ' )
return font->charWidths[' '];
else if( uc == '\t' )
return CL_CalcTabStop( font, x );
return 0;
}
if( font->type == FONT_TRUETYPE )
return CL_DrawTrueTypeCharacter( x, y, uc, color, font, flags );
return CL_DrawBitmapCharacter( x, y, uc, color, font, flags );
}
int CL_DrawString( float x, float y, const char *s, const rgba_t color, const cl_font_t *font, int flags )
{ {
rgba_t current_color; rgba_t current_color;
int draw_len = 0; int draw_len = 0;
utfstate_t utfstate = { 0 };
if( !font || !font->valid ) if( !font || !font->valid )
return 0; return 0;
if( FBitSet( flags, FONT_DRAW_UTF8 ))
Con_UtfProcessChar( 0 ); // clear utf state
if( !FBitSet( flags, FONT_DRAW_NORENDERMODE )) if( !FBitSet( flags, FONT_DRAW_NORENDERMODE ))
CL_SetFontRendermode( font ); CL_SetFontRendermode( font );
Vector4Copy( color, current_color ); Vector4Copy( color, current_color );
while( *s ) for( ; *s; s++ )
{ {
if( *s == '\n' ) uint32_t uc = (byte)*s;
{
s++;
if( !*s ) if( FBitSet( flags, FONT_DRAW_UTF8 ))
uc = Q_DecodeUTF8( &utfstate, uc );
if( !uc )
continue;
if( uc == '\n' )
{
if( !s[1] ) // ignore newline at end of string if next
break; break;
// some client functions ignore newlines // some client functions ignore newlines
@@ -264,30 +293,29 @@ int CL_DrawString( float x, float y, const char *s, rgba_t color, cl_font_t *fon
} }
if( FBitSet( flags, FONT_DRAW_RESETCOLORONLF )) if( FBitSet( flags, FONT_DRAW_RESETCOLORONLF ))
Vector4Copy( color, current_color ); Vector4Copy( color, current_color );
continue; continue;
} }
if( IsColorString( s )) // check for colorstrings
if( uc == '^' && isdigit( s[1] ))
{ {
// don't copy alpha
if( !FBitSet( flags, FONT_DRAW_FORCECOL )) if( !FBitSet( flags, FONT_DRAW_FORCECOL ))
VectorCopy( g_color_table[ColorIndex(*( s + 1 ))], current_color ); VectorCopy( g_color_table[ColorIndex( s[1] )], current_color );
s += 2; s++;
continue; continue;
} }
// skip setting rendermode, it was changed for this string already // skip setting rendermode, it was changed for this string already
draw_len += CL_DrawCharacter( x + draw_len, y, (byte)*s, current_color, font, flags | FONT_DRAW_NORENDERMODE ); draw_len += CL_DrawCharacter( x + draw_len, y, uc, current_color, font, flags | FONT_DRAW_NORENDERMODE );
s++;
} }
return draw_len; return draw_len;
} }
int CL_DrawStringf( cl_font_t *font, float x, float y, rgba_t color, int flags, const char *fmt, ... ) int CL_DrawStringf( const cl_font_t *font, float x, float y, const rgba_t color, int flags, const char *fmt, ... )
{ {
va_list va; va_list va;
char buf[MAX_VA_STRING]; char buf[MAX_VA_STRING];
@@ -299,20 +327,63 @@ int CL_DrawStringf( cl_font_t *font, float x, float y, rgba_t color, int flags,
return CL_DrawString( x, y, buf, color, font, flags ); return CL_DrawString( x, y, buf, color, font, flags );
} }
void CL_DrawCharacterLen( cl_font_t *font, int number, int *width, int *height ) static int CL_DrawBitmapCharacterLen( const cl_font_t *font, uint32_t uc )
{ {
if( !font || !font->valid ) return; int number;
if( width )
{ if( g_codepage == 1251 )
if( number == '\t' ) number = Q_UnicodeToCP1251( uc );
*width = CL_CalcTabStop( font, 0 ); // at least return max tabstop else if( g_codepage == 1252 )
else *width = font->charWidths[number & 255]; number = Q_UnicodeToCP1252( uc );
} else
if( height ) *height = font->charHeight; number = uc;
if( !number || number >= ARRAYSIZE( font->charWidths ))
return 0;
return font->charWidths[number];
} }
void CL_DrawStringLen( cl_font_t *font, const char *s, int *width, int *height, int flags ) static int CL_DrawTrueTypeCharacterLen( const cl_font_t *font, uint32_t uc )
{ {
// stub
return 0;
}
void CL_DrawCharacterLen( const cl_font_t *font, uint32_t uc, int *width, int *height )
{
if( !font || !font->valid )
return;
if( height )
*height = font->charHeight;
if( width )
{
// basically matches logic of CL_DrawCharacter
if( uc <= 32 )
{
if( uc == ' ' )
*width = font->charWidths[' '];
else if( uc == '\t' )
*width = CL_CalcTabStop( font, 0 ); // at least return max tabstop
else
*width = 0;
}
else if( font->type == FONT_TRUETYPE )
{
*width = CL_DrawTrueTypeCharacterLen( font, uc );
}
else
{
*width = CL_DrawBitmapCharacterLen( font, uc );
}
}
}
void CL_DrawStringLen( const cl_font_t *font, const char *s, int *width, int *height, int flags )
{
utfstate_t utfstate = { 0 };
int draw_len = 0; int draw_len = 0;
if( !font || !font->valid ) if( !font || !font->valid )
@@ -327,54 +398,45 @@ void CL_DrawStringLen( cl_font_t *font, const char *s, int *width, int *height,
if( !COM_CheckString( s )) if( !COM_CheckString( s ))
return; return;
if( FBitSet( flags, FONT_DRAW_UTF8 )) for( ; *s; s++ )
Con_UtfProcessChar( 0 ); // reset utf state
while( *s )
{ {
int number; uint32_t uc = (byte)*s;
int char_width = 0;
if( *s == '\n' ) if( FBitSet( flags, FONT_DRAW_UTF8 ))
uc = Q_DecodeUTF8( &utfstate, uc );
if( !uc )
continue;
if( uc == '\n' )
{ {
// BUG: no check for end string here // BUG: no check for end string here
// but high chances somebody's relying on this // but high chances somebody's relying on this
s++;
draw_len = 0; draw_len = 0;
// some client functions ignore newlines
if( !FBitSet( flags, FONT_DRAW_NOLF )) if( !FBitSet( flags, FONT_DRAW_NOLF ))
{ {
if( height ) if( height )
*height += font->charHeight; *height += font->charHeight;
} }
continue;
} }
else if( *s == '\t' )
// check for colorstrings
if( uc == '^' && isdigit( s[1] ))
{ {
draw_len += CL_CalcTabStop( font, 0 ); // at least return max tabstop
s++; s++;
continue; continue;
} }
if( IsColorString( s )) CL_DrawCharacterLen( font, uc, &char_width, NULL );
draw_len += char_width;
if( width )
{ {
s += 2; if( *width < draw_len )
continue; *width = draw_len;
} }
if( FBitSet( flags, FONT_DRAW_UTF8 ))
number = Con_UtfProcessChar( (byte)*s );
else number = (byte)*s;
if( number )
{
draw_len += font->charWidths[number];
if( width )
{
if( draw_len > *width )
*width = draw_len;
}
}
s++;
} }
} }

View File

@@ -13,6 +13,10 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
*/ */
#if XASH_SDL
#include <SDL.h> // SDL_GetWindowPosition
#endif // XASH_SDL
#include "common.h" #include "common.h"
#include "client.h" #include "client.h"
#include "const.h" #include "const.h"
@@ -29,6 +33,7 @@ GNU General Public License for more details.
#include "vgui_draw.h" #include "vgui_draw.h"
#include "sound.h" // SND_STOP_LOOPING #include "sound.h" // SND_STOP_LOOPING
#include "platform/platform.h" #include "platform/platform.h"
#include "utflib.h"
#define MAX_LINELENGTH 80 #define MAX_LINELENGTH 80
#define MAX_TEXTCHANNELS 8 // must be power of two (GoldSrc uses 4 channels) #define MAX_TEXTCHANNELS 8 // must be power of two (GoldSrc uses 4 channels)
@@ -306,21 +311,22 @@ void SPR_AdjustSize( float *x, float *y, float *w, float *h )
static void SPR_AdjustTexCoords( int texnum, float width, float height, float *s1, float *t1, float *s2, float *t2 ) static void SPR_AdjustTexCoords( int texnum, float width, float height, float *s1, float *t1, float *s2, float *t2 )
{ {
if( REF_GET_PARM( PARM_TEX_FILTERING, texnum )) const qboolean filtering = REF_GET_PARM( PARM_TEX_FILTERING, texnum );
{ const int xremainder = refState.width % clgame.scrInfo.iWidth;
if( refState.width != clgame.scrInfo.iWidth ) const int yremainder = refState.height % clgame.scrInfo.iHeight;
{
// align to texel if scaling
*s1 += 0.5f;
*s2 -= 0.5f;
}
if( refState.height != clgame.scrInfo.iHeight ) if(( filtering || xremainder ) && refState.width != clgame.scrInfo.iWidth )
{ {
// align to texel if scaling // align to texel if scaling
*t1 += 0.5f; *s1 += 0.5f;
*t2 -= 0.5f; *s2 -= 0.5f;
} }
if(( filtering || yremainder ) && refState.height != clgame.scrInfo.iHeight )
{
// align to texel if scaling
*t1 += 0.5f;
*t2 -= 0.5f;
} }
*s1 /= width; *s1 /= width;
@@ -403,8 +409,10 @@ void CL_DrawCenterPrint( void )
char *pText; char *pText;
int i, j, x, y; int i, j, x, y;
int width, lineLength; int width, lineLength;
byte *colorDefault, line[MAX_LINELENGTH]; byte *colorDefault;
uint32_t line[MAX_LINELENGTH];
int charWidth, charHeight; int charWidth, charHeight;
utfstate_t utfstate = { 0 };
if( !clgame.centerPrint.time ) if( !clgame.centerPrint.time )
return; return;
@@ -427,14 +435,19 @@ void CL_DrawCenterPrint( void )
lineLength = 0; lineLength = 0;
width = 0; width = 0;
while( *pText && *pText != '\n' && lineLength < MAX_LINELENGTH ) for( ; *pText && *pText != '\n' && lineLength < MAX_LINELENGTH; pText++ )
{ {
byte c = *pText; byte c = *pText;
line[lineLength] = c; uint32_t uc = Q_DecodeUTF8( &utfstate, c );
CL_DrawCharacterLen( font, c, &charWidth, NULL );
if( !uc )
continue;
line[lineLength] = uc;
CL_DrawCharacterLen( font, uc, &charWidth, NULL );
width += charWidth; width += charWidth;
lineLength++; lineLength++;
pText++;
} }
if( lineLength == MAX_LINELENGTH ) if( lineLength == MAX_LINELENGTH )
@@ -448,7 +461,7 @@ void CL_DrawCenterPrint( void )
for( j = 0; j < lineLength; j++ ) for( j = 0; j < lineLength; j++ )
{ {
if( x >= 0 && y >= 0 && x <= refState.width ) if( x >= 0 && y >= 0 && x <= refState.width )
x += CL_DrawCharacter( x, y, line[j], colorDefault, font, FONT_DRAW_UTF8 | FONT_DRAW_HUD | FONT_DRAW_NORENDERMODE ); x += CL_DrawCharacter( x, y, line[j], colorDefault, font, FONT_DRAW_HUD | FONT_DRAW_NORENDERMODE );
} }
y += charHeight; y += charHeight;
} }
@@ -556,7 +569,7 @@ static void CL_InitTitles( const char *filename )
Q_snprintf( name, sizeof( name ), TEXT_MSGNAME, i ); Q_snprintf( name, sizeof( name ), TEXT_MSGNAME, i );
cl_textmessage[i].pName = _copystring( clgame.mempool, name, __FILE__, __LINE__ ); cl_textmessage[i].pName = copystringpool( clgame.mempool, name );
cl_textmessage[i].pMessage = cl_textbuffer[i]; cl_textmessage[i].pMessage = cl_textbuffer[i];
} }
@@ -1698,7 +1711,12 @@ int GAME_EXPORT CL_GetScreenInfo( SCREENINFO *pscrinfo )
clgame.scrInfo.iSize = sizeof( clgame.scrInfo ); clgame.scrInfo.iSize = sizeof( clgame.scrInfo );
clgame.scrInfo.iFlags = SCRINFO_SCREENFLASH; clgame.scrInfo.iFlags = SCRINFO_SCREENFLASH;
if( scale_factor && scale_factor != 1.0f ) if( hud_scale.value >= 320.0f && hud_scale.value >= hud_scale_minimal_width.value )
{
scale_factor = refState.width / hud_scale.value;
apply_scale_factor = true;
}
else if( scale_factor && scale_factor != 1.0f )
{ {
float scaled_width = (float)refState.width / scale_factor; float scaled_width = (float)refState.width / scale_factor;
if( scaled_width >= hud_scale_minimal_width.value ) if( scaled_width >= hud_scale_minimal_width.value )
@@ -1979,7 +1997,13 @@ static int GAME_EXPORT pfnDrawCharacter( int x, int y, int number, int r, int g,
int flags = FONT_DRAW_HUD; int flags = FONT_DRAW_HUD;
if( hud_utf8.value ) if( hud_utf8.value )
flags |= FONT_DRAW_UTF8; {
static utfstate_t utfstate;
number = Q_DecodeUTF8( &utfstate, number );
if( !number )
return 0;
}
return CL_DrawCharacter( x, y, number, color, &cls.creditsFont, flags ); return CL_DrawCharacter( x, y, number, color, &cls.creditsFont, flags );
} }
@@ -3042,12 +3066,8 @@ pfnDrawString
*/ */
static int GAME_EXPORT pfnDrawString( int x, int y, const char *str, int r, int g, int b ) static int GAME_EXPORT pfnDrawString( int x, int y, const char *str, int r, int g, int b )
{ {
rgba_t color = { r, g, b, 255 }; const rgba_t color = { r, g, b, 255 };
int flags = FONT_DRAW_HUD | FONT_DRAW_NOLF; int flags = FONT_DRAW_HUD | FONT_DRAW_NOLF | FONT_DRAW_UTF8;
if( hud_utf8.value )
SetBits( flags, FONT_DRAW_UTF8 );
return CL_DrawString( x, y, str, color, &cls.creditsFont, flags ); return CL_DrawString( x, y, str, color, &cls.creditsFont, flags );
} }
@@ -3059,13 +3079,10 @@ pfnDrawStringReverse
*/ */
static int GAME_EXPORT pfnDrawStringReverse( int x, int y, const char *str, int r, int g, int b ) static int GAME_EXPORT pfnDrawStringReverse( int x, int y, const char *str, int r, int g, int b )
{ {
rgba_t color = { r, g, b, 255 }; const rgba_t color = { r, g, b, 255 };
int flags = FONT_DRAW_HUD | FONT_DRAW_NOLF; int flags = FONT_DRAW_HUD | FONT_DRAW_NOLF | FONT_DRAW_UTF8;
int width; int width;
if( hud_utf8.value )
SetBits( flags, FONT_DRAW_UTF8 );
CL_DrawStringLen( &cls.creditsFont, str, &width, NULL, flags ); CL_DrawStringLen( &cls.creditsFont, str, &width, NULL, flags );
x -= width; x -= width;
@@ -3348,28 +3365,6 @@ DemoApi implementation
================= =================
*/ */
/*
=================
Demo_IsRecording
=================
*/
static int GAME_EXPORT Demo_IsRecording( void )
{
return cls.demorecording;
}
/*
=================
Demo_IsPlayingback
=================
*/
static int GAME_EXPORT Demo_IsPlayingback( void )
{
return cls.demoplayback;
}
/* /*
================= =================
Demo_IsTimeDemo Demo_IsTimeDemo
@@ -3381,17 +3376,6 @@ static int GAME_EXPORT Demo_IsTimeDemo( void )
return cls.timedemo; return cls.timedemo;
} }
/*
=================
Demo_WriteBuffer
=================
*/
static void GAME_EXPORT Demo_WriteBuffer( int size, byte *buffer )
{
CL_WriteDemoUserMessage( buffer, size );
}
/* /*
================= =================
NetworkApi implementation NetworkApi implementation
@@ -3454,7 +3438,7 @@ static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags,
return; return;
} }
if( remote_address->type == NA_IPX || remote_address->type == NA_BROADCAST_IPX ) if( NET_NetadrType( remote_address ) == NA_IPX || NET_NetadrType( remote_address ) == NA_BROADCAST_IPX )
return; // IPX no longer support return; // IPX no longer support
if( request == NETAPI_REQUEST_SERVERLIST ) if( request == NETAPI_REQUEST_SERVERLIST )
@@ -3577,28 +3561,6 @@ static int GAME_EXPORT NetAPI_CompareAdr( netadr_t *a, netadr_t *b )
return NET_CompareAdr( *a, *b ); return NET_CompareAdr( *a, *b );
} }
/*
=================
NetAPI_StringToAdr
=================
*/
static int GAME_EXPORT NetAPI_StringToAdr( char *s, netadr_t *a )
{
return NET_StringToAdr( s, a );
}
/*
=================
NetAPI_ValueForKey
=================
*/
static const char * GAME_EXPORT NetAPI_ValueForKey( const char *s, const char *key )
{
return Info_ValueForKey( s, key );
}
/* /*
================= =================
NetAPI_RemoveKey NetAPI_RemoveKey
@@ -3795,10 +3757,10 @@ static event_api_t gEventApi =
static demo_api_t gDemoApi = static demo_api_t gDemoApi =
{ {
Demo_IsRecording, (void *)CL_IsRecordDemo,
Demo_IsPlayingback, (void *)CL_IsPlaybackDemo,
Demo_IsTimeDemo, Demo_IsTimeDemo,
Demo_WriteBuffer, CL_WriteDemoUserMessage,
}; };
net_api_t gNetApi = net_api_t gNetApi =
@@ -3810,8 +3772,8 @@ net_api_t gNetApi =
NetAPI_CancelAllRequests, NetAPI_CancelAllRequests,
NetAPI_AdrToString, NetAPI_AdrToString,
NetAPI_CompareAdr, NetAPI_CompareAdr,
NetAPI_StringToAdr, (void *)NET_StringToAdr,
NetAPI_ValueForKey, Info_ValueForKey,
NetAPI_RemoveKey, NetAPI_RemoveKey,
NetAPI_SetValueForKey, NetAPI_SetValueForKey,
}; };

View File

@@ -1324,10 +1324,21 @@ static int pfnIsCvarReadOnly( const char *name )
return FBitSet( cv->flags, FCVAR_READ_ONLY ) ? 1 : 0; return FBitSet( cv->flags, FCVAR_READ_ONLY ) ? 1 : 0;
} }
static int GAME_EXPORT pfnUtfProcessChar( int in )
{
// compatibility export, deprecated, do not use
if( !cls.accept_utf8 ) // incoming character is not a UTF-8 sequence
return in;
// otherwise, decode it and convert to selected codepage
return Con_UtfProcessCharForce( in );
}
static ui_extendedfuncs_t gExtendedfuncs = static ui_extendedfuncs_t gExtendedfuncs =
{ {
pfnEnableTextInput, pfnEnableTextInput,
Con_UtfProcessChar, pfnUtfProcessChar,
Con_UtfMoveLeft, Con_UtfMoveLeft,
Con_UtfMoveRight, Con_UtfMoveRight,
pfnGetRenderers, pfnGetRenderers,

View File

@@ -68,7 +68,7 @@ CVAR_DEFINE_AUTO( hud_scale_minimal_width, "640", FCVAR_ARCHIVE|FCVAR_LATCH, "if
CVAR_DEFINE_AUTO( cl_solid_players, "1", 0, "Make all players not solid (can't traceline them)" ); CVAR_DEFINE_AUTO( cl_solid_players, "1", 0, "Make all players not solid (can't traceline them)" );
CVAR_DEFINE_AUTO( cl_updaterate, "20", FCVAR_USERINFO|FCVAR_ARCHIVE, "refresh rate of server messages" ); CVAR_DEFINE_AUTO( cl_updaterate, "20", FCVAR_USERINFO|FCVAR_ARCHIVE, "refresh rate of server messages" );
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, "30", 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", 0, "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" );
@@ -76,6 +76,7 @@ static CVAR_DEFINE_AUTO( cl_upmax, "1200", FCVAR_ARCHIVE, "max allowed incoming
CVAR_DEFINE_AUTO( cl_lw, "1", FCVAR_ARCHIVE|FCVAR_USERINFO, "enable client weapon predicting" ); CVAR_DEFINE_AUTO( cl_lw, "1", FCVAR_ARCHIVE|FCVAR_USERINFO, "enable client weapon predicting" );
CVAR_DEFINE_AUTO( cl_charset, "utf-8", FCVAR_ARCHIVE, "1-byte charset to use (iconv style)" ); CVAR_DEFINE_AUTO( cl_charset, "utf-8", FCVAR_ARCHIVE, "1-byte charset to use (iconv style)" );
CVAR_DEFINE_AUTO( cl_trace_consistency, "0", FCVAR_ARCHIVE, "enable consistency info tracing (good for developers)" );
CVAR_DEFINE_AUTO( cl_trace_stufftext, "0", FCVAR_ARCHIVE, "enable stufftext (server-to-client console commands) tracing (good for developers)" ); CVAR_DEFINE_AUTO( cl_trace_stufftext, "0", FCVAR_ARCHIVE, "enable stufftext (server-to-client console commands) tracing (good for developers)" );
CVAR_DEFINE_AUTO( cl_trace_messages, "0", FCVAR_ARCHIVE|FCVAR_CHEAT, "enable message names tracing (good for developers)" ); CVAR_DEFINE_AUTO( cl_trace_messages, "0", FCVAR_ARCHIVE|FCVAR_CHEAT, "enable message names tracing (good for developers)" );
CVAR_DEFINE_AUTO( cl_trace_events, "0", FCVAR_ARCHIVE|FCVAR_CHEAT, "enable events tracing (good for developers)" ); CVAR_DEFINE_AUTO( cl_trace_events, "0", FCVAR_ARCHIVE|FCVAR_CHEAT, "enable events tracing (good for developers)" );
@@ -93,11 +94,10 @@ static CVAR_DEFINE_AUTO( name, username, FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_PRIN
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, "25000", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player network rate" );
static CVAR_DEFINE_AUTO( cl_ticket_generator, "revemu2013", FCVAR_ARCHIVE, "you wouldn't steal a car" ); static CVAR_DEFINE_AUTO( cl_ticket_generator, "revemu2013", FCVAR_ARCHIVE, "you wouldn't steal a car" );
client_t cl; client_t cl;
client_static_t cls; client_static_t cls;
clgame_static_t clgame; clgame_static_t clgame;
@@ -147,11 +147,6 @@ qboolean CL_IsRecordDemo( void )
return cls.demorecording; return cls.demorecording;
} }
qboolean CL_IsTimeDemo( void )
{
return cls.timedemo;
}
qboolean CL_DisableVisibility( void ) qboolean CL_DisableVisibility( void )
{ {
return cls.envshot_disable_vis; return cls.envshot_disable_vis;
@@ -598,7 +593,7 @@ CL_CreateCmd
*/ */
static void CL_CreateCmd( void ) static void CL_CreateCmd( void )
{ {
usercmd_t nullcmd, *cmd; usercmd_t nullcmd = { 0 }, *cmd;
runcmd_t *pcmd; runcmd_t *pcmd;
qboolean active; qboolean active;
double accurate_ms; double accurate_ms;
@@ -650,7 +645,6 @@ static void CL_CreateCmd( void )
} }
else else
{ {
memset( &nullcmd, 0, sizeof( nullcmd ));
cmd = &nullcmd; cmd = &nullcmd;
} }
@@ -723,11 +717,20 @@ static void CL_WritePacket( void )
int numbackup, maxbackup, maxcmds; int numbackup, maxbackup, maxcmds;
const connprotocol_t proto = cls.legacymode; const connprotocol_t proto = cls.legacymode;
// FIXME: on Xash protocol we don't send move commands until ca_active
// to prevent outgoing_command outrun incoming_acknowledged
// which is fatal for some buggy mods like TFC
//
// ... but GoldSrc don't have (real) ca_validate state, so we consider
// ca_validate the same as ca_active, otherwise we don't pass validation
// of server-side mods like ReAuthCheck
const connstate_t min_state = proto == PROTO_GOLDSRC ? ca_validate : ca_active;
// don't send anything if playing back a demo // don't send anything if playing back a demo
if( cls.demoplayback || cls.state < ca_connected || cls.state == ca_cinematic ) if( cls.demoplayback || cls.state < ca_connected || cls.state == ca_cinematic )
return; return;
if( cls.state <= ca_connected ) if( cls.state < min_state )
{ {
Netchan_TransmitBits( &cls.netchan, 0, "" ); Netchan_TransmitBits( &cls.netchan, 0, "" );
return; return;
@@ -825,7 +828,7 @@ static void CL_WritePacket( void )
buf.pData[key] = CRC32_BlockSequence( &buf.pData[key + 1], size, cls.netchan.outgoing_sequence ); buf.pData[key] = CRC32_BlockSequence( &buf.pData[key + 1], size, cls.netchan.outgoing_sequence );
COM_Munge( &buf.pData[key + 1], Q_min( size, 255 ), cls.netchan.outgoing_sequence ); COM_Munge( &buf.pData[key + 1], Q_min( size, 255 ), cls.netchan.outgoing_sequence );
} }
else else if( !Host_IsLocalClient( ))
{ {
int size = MSG_GetRealBytesWritten( &buf ) - key - 1; int size = MSG_GetRealBytesWritten( &buf ) - key - 1;
buf.pData[key] = CRC32_BlockSequence( &buf.pData[key + 1], size, cls.netchan.outgoing_sequence ); buf.pData[key] = CRC32_BlockSequence( &buf.pData[key + 1], size, cls.netchan.outgoing_sequence );
@@ -1005,7 +1008,7 @@ static void CL_WriteSteamTicket( sizebuf_t *send )
const char *s; const char *s;
uint32_t crc; uint32_t crc;
char buf[768] = { 0 }; // setti and steamemu return 768 char buf[768] = { 0 }; // setti and steamemu return 768
size_t i = sizeof( buf ); int i = sizeof( buf );
if( !Q_strcmp( cl_ticket_generator.string, "null" )) if( !Q_strcmp( cl_ticket_generator.string, "null" ))
{ {
@@ -1024,24 +1027,7 @@ static void CL_WriteSteamTicket( sizebuf_t *send )
CRC32_Init( &crc ); CRC32_Init( &crc );
CRC32_ProcessBuffer( &crc, s, Q_strlen( s )); CRC32_ProcessBuffer( &crc, s, Q_strlen( s ));
crc = CRC32_Final( crc ); crc = CRC32_Final( crc );
i = GenerateRevEmu2013( buf, s, crc );
if( !Q_stricmp( cl_ticket_generator.string, "revemu2013" ))
i = GenerateRevEmu2013( buf, crc );
else if( !Q_stricmp( cl_ticket_generator.string, "sc2009" ))
i = GenerateSC2009( buf, crc );
else if( !Q_stricmp( cl_ticket_generator.string, "oldrevemu" ))
i = GenerateOldRevEmu( buf, crc );
else if( !Q_stricmp( cl_ticket_generator.string, "steamemu" ))
i = GenerateSteamEmu( buf, crc );
else if( !Q_stricmp( cl_ticket_generator.string, "revemu" ))
i = GenerateRevEmu( buf, crc );
else if( !Q_stricmp( cl_ticket_generator.string, "setti" ))
i = GenerateSetti( buf );
else if( !Q_stricmp( cl_ticket_generator.string, "avsmp" ))
i = GenerateAVSMP( buf, crc, true );
else
Con_Printf( "%s: unknown generator %s, supported are: null, revemu2003, sc2009, oldrevemu, steamemu, revemu, setti, avsmp\n", __func__, cl_ticket_generator.string );
MSG_WriteBytes( send, buf, i ); MSG_WriteBytes( send, buf, i );
} }
@@ -1059,6 +1045,7 @@ static void CL_SendConnectPacket( connprotocol_t proto, int challenge )
const char *key = ID_GetMD5(); const char *key = ID_GetMD5();
netadr_t adr = { 0 }; netadr_t adr = { 0 };
int input_devices; int input_devices;
netadrtype_t adrtype;
protinfo[0] = 0; protinfo[0] = 0;
@@ -1069,14 +1056,16 @@ static void CL_SendConnectPacket( connprotocol_t proto, int challenge )
return; return;
} }
adrtype = NET_NetadrType( &adr );
if( adr.port == 0 ) adr.port = MSG_BigShort( PORT_SERVER ); if( adr.port == 0 ) adr.port = MSG_BigShort( PORT_SERVER );
input_devices = IN_CollectInputDevices(); input_devices = IN_CollectInputDevices();
IN_LockInputDevices( adr.type != NA_LOOPBACK ? true : false ); IN_LockInputDevices( adrtype != NA_LOOPBACK ? true : false );
// GoldSrc doesn't need sv_cheats set to 0, it's handled by svc_goldsrc_sendextrainfo // GoldSrc doesn't need sv_cheats set to 0, it's handled by svc_goldsrc_sendextrainfo
// it also doesn't need useragent string // it also doesn't need useragent string
if( adr.type != NA_LOOPBACK && proto != PROTO_GOLDSRC ) if( adrtype != NA_LOOPBACK && proto != PROTO_GOLDSRC )
{ {
Cvar_SetCheatState(); Cvar_SetCheatState();
Cvar_FullSet( "sv_cheats", "0", FCVAR_READ_ONLY | FCVAR_SERVER ); Cvar_FullSet( "sv_cheats", "0", FCVAR_READ_ONLY | FCVAR_SERVER );
@@ -1176,7 +1165,11 @@ Returns bandwidth test fragment size
*/ */
static int CL_GetTestFragmentSize( void ) static int CL_GetTestFragmentSize( void )
{ {
const int fragmentSizes[CL_TEST_RETRIES] = { 64000, 32000, 10666, 5200, 1400 }; // const int fragmentSizes[CL_TEST_RETRIES] = { 64000, 32000, 10666, 5200, 1400 };
// it turns out, even if we pass the bandwidth test, it doesn't mean we can use such large fragments
// as a temporary solution, use smaller fragment sizes
const int fragmentSizes[CL_TEST_RETRIES] = { 1400, 1200, 1000, 800, 508 };
if( cls.connect_retry >= 0 && cls.connect_retry < CL_TEST_RETRIES ) if( cls.connect_retry >= 0 && cls.connect_retry < CL_TEST_RETRIES )
return bound( FRAGMENT_MIN_SIZE, fragmentSizes[cls.connect_retry], FRAGMENT_MAX_SIZE ); return bound( FRAGMENT_MIN_SIZE, fragmentSizes[cls.connect_retry], FRAGMENT_MAX_SIZE );
else else
@@ -1214,7 +1207,7 @@ static void CL_CheckForResend( void )
cls.signon = 0; cls.signon = 0;
cls.state = ca_connecting; cls.state = ca_connecting;
Q_strncpy( cls.servername, "localhost", sizeof( cls.servername )); Q_strncpy( cls.servername, "localhost", sizeof( cls.servername ));
cls.serveradr.type = NA_LOOPBACK; NET_NetadrSetType( &cls.serveradr, NA_LOOPBACK );
cls.legacymode = PROTO_CURRENT; cls.legacymode = PROTO_CURRENT;
// we don't need a challenge on the localhost // we don't need a challenge on the localhost
@@ -1550,8 +1543,8 @@ static void CL_SendDisconnectMessage( connprotocol_t proto )
MSG_WriteString( &buf, "dropclient\n" ); MSG_WriteString( &buf, "dropclient\n" );
else MSG_WriteString( &buf, "disconnect" ); else MSG_WriteString( &buf, "disconnect" );
if( !cls.netchan.remote_address.type ) if( NET_NetadrType( &cls.netchan.remote_address ) == NA_UNDEFINED )
cls.netchan.remote_address.type = NA_LOOPBACK; NET_NetadrSetType( &cls.netchan.remote_address, NA_LOOPBACK );
// make sure message will be delivered // make sure message will be delivered
Netchan_TransmitBits( &cls.netchan, MSG_GetNumBitsWritten( &buf ), MSG_GetData( &buf )); Netchan_TransmitBits( &cls.netchan, MSG_GetNumBitsWritten( &buf ), MSG_GetData( &buf ));
@@ -1594,6 +1587,9 @@ void CL_SetupNetchanForProtocol( connprotocol_t proto )
} }
break; break;
default: default:
if( !Host_IsLocalClient( ))
SetBits( flags, NETCHAN_USE_LZSS );
cls.extensions = Q_atoi( Info_ValueForKey( Cmd_Argv( 1 ), "ext" )); cls.extensions = Q_atoi( Info_ValueForKey( Cmd_Argv( 1 ), "ext" ));
if( FBitSet( cls.extensions, NET_EXT_SPLITSIZE )) if( FBitSet( cls.extensions, NET_EXT_SPLITSIZE ))
@@ -1717,19 +1713,17 @@ CL_LocalServers_f
*/ */
static void CL_LocalServers_f( void ) static void CL_LocalServers_f( void )
{ {
netadr_t adr; netadr_t adr = { 0 };
memset( &adr, 0, sizeof( adr ));
Con_Printf( "Scanning for servers on the local network area...\n" ); Con_Printf( "Scanning for servers on the local network area...\n" );
NET_Config( true, true ); // allow remote NET_Config( true, true ); // allow remote
// send a broadcast packet // send a broadcast packet
adr.type = NA_BROADCAST; NET_NetadrSetType( &adr, NA_BROADCAST );
adr.port = MSG_BigShort( PORT_SERVER ); adr.port = MSG_BigShort( PORT_SERVER );
Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO" %i", PROTOCOL_VERSION ); Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO" %i", PROTOCOL_VERSION );
adr.type = NA_MULTICAST_IP6; NET_NetadrSetType( &adr, NA_MULTICAST_IP6 );
Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO" %i", PROTOCOL_VERSION ); Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO" %i", PROTOCOL_VERSION );
} }
@@ -2473,18 +2467,18 @@ static void CL_ServerList( netadr_t from, sizebuf_t *msg )
while( MSG_GetNumBitsLeft( msg ) > 8 ) while( MSG_GetNumBitsLeft( msg ) > 8 )
{ {
uint8_t addr[16]; uint8_t addr[16];
netadr_t servadr; netadr_t servadr = { 0 };
if( from.type6 == NA_IP6 ) // IPv6 master server only sends IPv6 addresses if( NET_NetadrType( &from ) == NA_IP6 ) // IPv6 master server only sends IPv6 addresses
{ {
MSG_ReadBytes( msg, addr, sizeof( addr )); MSG_ReadBytes( msg, addr, sizeof( addr ));
NET_IP6BytesToNetadr( &servadr, addr ); NET_IP6BytesToNetadr( &servadr, addr );
servadr.type6 = NA_IP6; NET_NetadrSetType( &servadr, NA_IP6 );
} }
else else
{ {
MSG_ReadBytes( msg, servadr.ip, sizeof( servadr.ip )); // 4 bytes for IP MSG_ReadBytes( msg, servadr.ip, sizeof( servadr.ip )); // 4 bytes for IP
servadr.type = NA_IP; NET_NetadrSetType( &servadr, NA_IP );
} }
servadr.port = MSG_ReadShort( msg ); // 2 bytes for Port servadr.port = MSG_ReadShort( msg ); // 2 bytes for Port
@@ -3132,6 +3126,9 @@ static qboolean CL_ShouldRescanFilesystem( void )
} }
} }
if( FBitSet( fs_mount_lv.flags|fs_mount_hd.flags|fs_mount_addon.flags|fs_mount_l10n.flags|ui_language.flags, FCVAR_CHANGED ))
retval = true;
return retval; return retval;
} }
@@ -3141,7 +3138,7 @@ qboolean CL_PrecacheResources( void )
// if we downloaded new WAD files or any other archives they must be added to searchpath // if we downloaded new WAD files or any other archives they must be added to searchpath
if( CL_ShouldRescanFilesystem( )) if( CL_ShouldRescanFilesystem( ))
g_fsapi.Rescan(); FS_Rescan_f();
// 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 )
@@ -3387,6 +3384,7 @@ static void CL_InitLocal( void )
Cvar_RegisterVariable( &rcon_address ); Cvar_RegisterVariable( &rcon_address );
Cvar_RegisterVariable( &cl_trace_consistency );
Cvar_RegisterVariable( &cl_trace_stufftext ); Cvar_RegisterVariable( &cl_trace_stufftext );
Cvar_RegisterVariable( &cl_trace_messages ); Cvar_RegisterVariable( &cl_trace_messages );
Cvar_RegisterVariable( &cl_trace_events ); Cvar_RegisterVariable( &cl_trace_events );
@@ -3481,6 +3479,8 @@ static void CL_InitLocal( void )
Cmd_AddCommand ("fullserverinfo", CL_FullServerinfo_f, "sent by server when serverinfo changes" ); Cmd_AddCommand ("fullserverinfo", CL_FullServerinfo_f, "sent by server when serverinfo changes" );
Cmd_AddCommand ("upload", CL_BeginUpload_f, "uploading file to the server" ); Cmd_AddCommand ("upload", CL_BeginUpload_f, "uploading file to the server" );
Cmd_AddRestrictedCommand( "replaybufferdat", CL_ReplayBufferDat_f, "development and debugging tool" );
Cmd_AddRestrictedCommand ("quit", CL_Quit_f, "quit from game" ); Cmd_AddRestrictedCommand ("quit", CL_Quit_f, "quit from game" );
Cmd_AddRestrictedCommand ("exit", CL_Quit_f, "quit from game" ); Cmd_AddRestrictedCommand ("exit", CL_Quit_f, "quit from game" );
@@ -3658,6 +3658,8 @@ void CL_Init( void )
if( !CL_LoadProgs( libpath )) if( !CL_LoadProgs( libpath ))
Host_Error( "can't initialize %s: %s\n", libpath, COM_GetLibraryError( )); Host_Error( "can't initialize %s: %s\n", libpath, COM_GetLibraryError( ));
ID_Init();
cls.build_num = 0; cls.build_num = 0;
cls.initialized = true; cls.initialized = true;
cl.maxclients = 1; // allow to drawing player in menu cl.maxclients = 1; // allow to drawing player in menu

View File

@@ -19,6 +19,7 @@ GNU General Public License for more details.
#include "library.h" #include "library.h"
#include "input.h" #include "input.h"
#include "platform/platform.h" #include "platform/platform.h"
#include "utflib.h"
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" );
@@ -58,7 +59,13 @@ static int pfnDrawScaledCharacter( int x, int y, int number, int r, int g, int b
int flags = FONT_DRAW_HUD; int flags = FONT_DRAW_HUD;
if( hud_utf8.value ) if( hud_utf8.value )
SetBits( flags, FONT_DRAW_UTF8 ); {
static utfstate_t utfstate;
number = Q_DecodeUTF8( &utfstate, number );
if( !number )
return 0;
}
if( fabs( g_font_scale - scale ) > 0.1f || if( fabs( g_font_scale - scale ) > 0.1f ||
g_scaled_font.hFontTexture != cls.creditsFont.hFontTexture ) g_scaled_font.hFontTexture != cls.creditsFont.hFontTexture )
@@ -92,6 +99,11 @@ 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 void GAME_EXPORT pfnSetCustomClientID( const char *id )
{
// deprecated
}
static const mobile_engfuncs_t gMobileEngfuncs = static const mobile_engfuncs_t gMobileEngfuncs =
{ {
MOBILITY_API_VERSION, MOBILITY_API_VERSION,
@@ -106,7 +118,7 @@ static const mobile_engfuncs_t gMobileEngfuncs =
pfnDrawScaledCharacter, pfnDrawScaledCharacter,
Sys_Warn, Sys_Warn,
Sys_GetNativeObject, Sys_GetNativeObject,
ID_SetCustomClientID, pfnSetCustomClientID,
pfnParseFileSafe pfnParseFileSafe
}; };

View File

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

View File

@@ -83,7 +83,10 @@ static void CL_ParseNewMovevars( sizebuf_t *msg )
R_SetupSky( clgame.movevars.skyName ); R_SetupSky( clgame.movevars.skyName );
clgame.oldmovevars = clgame.movevars; clgame.oldmovevars = clgame.movevars;
clgame.entities->curstate.scale = clgame.movevars.waveHeight;
// FIXME: set world wave height when entities will be allocated
if( clgame.entities )
clgame.entities->curstate.scale = clgame.movevars.waveHeight;
// keep features an actual! // keep features an actual!
clgame.oldmovevars.features = clgame.movevars.features = host.features; clgame.oldmovevars.features = clgame.movevars.features = host.features;
@@ -91,11 +94,11 @@ static void CL_ParseNewMovevars( sizebuf_t *msg )
typedef struct delta_header_t typedef struct delta_header_t
{ {
qboolean remove : 1; qboolean remove;
qboolean custom : 1; qboolean custom;
qboolean instanced : 1; qboolean instanced;
uint instanced_baseline_index : 6; uint16_t instanced_baseline_index;
uint offset : 6; uint16_t offset;
} delta_header_t; } delta_header_t;
static int CL_ParseDeltaHeader( sizebuf_t *msg, qboolean delta, int oldnum, struct delta_header_t *hdr ) static int CL_ParseDeltaHeader( sizebuf_t *msg, qboolean delta, int oldnum, struct delta_header_t *hdr )
@@ -160,33 +163,47 @@ static int CL_GetEntityDelta( const struct delta_header_t *hdr, int entnum )
return DT_ENTITY_STATE_T; return DT_ENTITY_STATE_T;
} }
static void CL_FlushEntityPacketGS( frame_t *frame, sizebuf_t *msg ) static int CL_FlushEntityPacketGS( frame_t *frame, sizebuf_t *msg )
{ {
int playerbytes = 0, numbase = 0;
frame->valid = false; frame->valid = false;
cl.validsequence = 0; // can't render a frame cl.validsequence = 0; // can't render a frame
// read it all but ignore it // read it all but ignore it
while( 1 ) while( 1 )
{ {
int num = 0; int newnum, bufstart;
entity_state_t from = { 0 }, to; entity_state_t from = { 0 }, to;
delta_header_t hdr; delta_header_t hdr;
qboolean player;
if( MSG_ReadWord( msg ) != 0 ) if( MSG_ReadWord( msg ) != 0 )
{ {
MSG_SeekToBit( msg, -16, SEEK_CUR ); MSG_SeekToBit( msg, -16, SEEK_CUR );
num = CL_ParseDeltaHeader( msg, false, num, &hdr ); numbase = newnum = CL_ParseDeltaHeader( msg, true, numbase, &hdr );
} }
else break; else break;
if( MSG_CheckOverflow( msg )) if( MSG_CheckOverflow( msg ))
Host_Error( "%s: overflow\n", __func__ ); Host_Error( "%s: overflow\n", __func__ );
player = CL_IsPlayerIndex( newnum );
bufstart = MSG_GetNumBytesRead( msg );
if( hdr.remove ) if( hdr.remove )
continue; continue;
Delta_ReadGSFields( msg, CL_GetEntityDelta( &hdr, num ), &from, &to, cl.mtime[0] ); Delta_ReadGSFields( msg, CL_GetEntityDelta( &hdr, newnum ), &from, &to, cl.mtime[0] );
if( player )
playerbytes += MSG_GetNumBytesRead( msg ) - bufstart;
} }
if( MSG_CheckOverflow( msg ))
Host_Error( "%s: overflow\n", __func__ );
return playerbytes;
} }
static void CL_DeltaEntityGS( const delta_header_t *hdr, sizebuf_t *msg, frame_t *frame, int newnum, const entity_state_t *from ) static void CL_DeltaEntityGS( const delta_header_t *hdr, sizebuf_t *msg, frame_t *frame, int newnum, const entity_state_t *from )
@@ -203,7 +220,7 @@ static void CL_DeltaEntityGS( const delta_header_t *hdr, sizebuf_t *msg, frame_t
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 "CL_DeltaEntity: invalid newnum: %d\n", newnum );
Host_Error( "%s: bad delta entity number: %i", __func__, newnum ); Host_Error( "%s: bad delta entity number: %i\n", __func__, newnum );
return; return;
} }
@@ -267,7 +284,7 @@ static void CL_CopyPacketEntity( frame_t *frame, int num, const entity_state_t *
static int CL_ParsePacketEntitiesGS( sizebuf_t *msg, qboolean delta ) static int CL_ParsePacketEntitiesGS( sizebuf_t *msg, qboolean delta )
{ {
frame_t *frame, *oldframe; frame_t *frame, *oldframe;
int oldindex, newnum, oldnum, numbase = 0; int oldindex, oldnum, numbase = 0;
entity_state_t *oldent; entity_state_t *oldent;
int count; int count;
int playerbytes = 0; int playerbytes = 0;
@@ -314,7 +331,7 @@ static int CL_ParsePacketEntitiesGS( sizebuf_t *msg, qboolean delta )
// read it all but ignore it // read it all but ignore it
while( 1 ) while( 1 )
{ {
int bufstart; int bufstart, newnum;
qboolean player; qboolean player;
delta_header_t hdr; delta_header_t hdr;
int val = MSG_ReadWord( msg ); int val = MSG_ReadWord( msg );
@@ -534,7 +551,7 @@ void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
{ {
if( MSG_CheckOverflow( msg )) if( MSG_CheckOverflow( msg ))
{ {
Host_Error( "CL_ParseServerMessage: overflow!\n" ); Host_Error( "%s: overflow!\n", __func__ );
return; return;
} }

View File

@@ -233,6 +233,11 @@ static intptr_t pfnRenderGetParm( int parm, int arg )
return CL_RenderGetParm( parm, arg, true ); return CL_RenderGetParm( parm, arg, true );
} }
static void pfnAVI_StreamSound( void *avi, int entnum, float fvol, float attn, float synctime )
{
return; // stub, use AVI_SetParm and AVI_Think to stream AVI sound
}
static render_api_t gRenderAPI = static render_api_t gRenderAPI =
{ {
pfnRenderGetParm, // GL_RenderGetParm, pfnRenderGetParm, // GL_RenderGetParm,
@@ -265,7 +270,7 @@ static render_api_t gRenderAPI =
NULL, // R_UploadStretchRaw, NULL, // R_UploadStretchRaw,
(void*)AVI_FreeVideo, (void*)AVI_FreeVideo,
(void*)AVI_IsActive, (void*)AVI_IsActive,
S_StreamAviSamples, (void*)pfnAVI_StreamSound,
NULL, NULL,
NULL, NULL,
NULL, // GL_Bind, NULL, // GL_Bind,

View File

@@ -2429,7 +2429,7 @@ void CL_SetLightstyle( int style, const char *s, float f )
if( unlikely( style < 0 || style >= MAX_LIGHTSTYLES )) if( unlikely( style < 0 || style >= MAX_LIGHTSTYLES ))
{ {
Con_Printf( S_WARN "%s: ignored invalid lightstyle id %d\n", style ); Con_Printf( S_WARN "%s: ignored invalid lightstyle id %d\n", __func__, style );
return; return;
} }

View File

@@ -326,8 +326,12 @@ typedef struct
pfnEventHook func; // user-defined function pfnEventHook func; // user-defined function
} cl_user_event_t; } cl_user_event_t;
#define FONT_FIXED 0 enum
#define FONT_VARIABLE 1 {
FONT_FIXED,
FONT_VARIABLE,
FONT_TRUETYPE
};
#define FONT_DRAW_HUD BIT( 0 ) // pass to drawing function to apply hud_scale #define FONT_DRAW_HUD BIT( 0 ) // pass to drawing function to apply hud_scale
#define FONT_DRAW_UTF8 BIT( 1 ) // call UtfProcessChar #define FONT_DRAW_UTF8 BIT( 1 ) // call UtfProcessChar
@@ -688,6 +692,7 @@ extern convar_t r_showtextures;
extern convar_t cl_bmodelinterp; extern convar_t cl_bmodelinterp;
extern convar_t cl_lw; // local weapons extern convar_t cl_lw; // local weapons
extern convar_t cl_charset; extern convar_t cl_charset;
extern convar_t cl_trace_consistency;
extern convar_t cl_trace_stufftext; extern convar_t cl_trace_stufftext;
extern convar_t cl_trace_messages; extern convar_t cl_trace_messages;
extern convar_t cl_trace_events; extern convar_t cl_trace_events;
@@ -736,6 +741,7 @@ void CL_ClearResourceLists( void );
// //
// cl_debug.c // cl_debug.c
// //
void CL_ReplayBufferDat_f( void );
void CL_Parse_Debug( qboolean enable ); void CL_Parse_Debug( qboolean enable );
void CL_Parse_RecordCommand( int cmd, int startoffset ); void CL_Parse_RecordCommand( int cmd, int startoffset );
void CL_ResetFrame( frame_t *frame ); void CL_ResetFrame( frame_t *frame );
@@ -767,7 +773,7 @@ void CL_StartupDemoHeader( void );
void CL_DrawDemoRecording( void ); void CL_DrawDemoRecording( void );
void CL_WriteDemoUserCmd( int cmdnumber ); void CL_WriteDemoUserCmd( int cmdnumber );
void CL_WriteDemoMessage( qboolean startup, int start, sizebuf_t *msg ); void CL_WriteDemoMessage( qboolean startup, int start, sizebuf_t *msg );
void CL_WriteDemoUserMessage( const byte *buffer, size_t size ); void CL_WriteDemoUserMessage( int size, byte *buffer );
qboolean CL_DemoReadMessage( byte *buffer, size_t *length ); qboolean CL_DemoReadMessage( byte *buffer, size_t *length );
void CL_DemoInterpolateAngles( void ); void CL_DemoInterpolateAngles( void );
void CL_CheckStartupDemos( void ); void CL_CheckStartupDemos( void );
@@ -805,11 +811,12 @@ qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float sc
qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float scale, convar_t *rendermode, uint texFlags ); qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float scale, convar_t *rendermode, uint texFlags );
void CL_FreeFont( cl_font_t *font ); void CL_FreeFont( cl_font_t *font );
void CL_SetFontRendermode( cl_font_t *font ); void CL_SetFontRendermode( cl_font_t *font );
int CL_DrawCharacter( float x, float y, int number, rgba_t color, cl_font_t *font, int flags ); int CL_DrawCharacter( float x, float y, uint32_t uc, const rgba_t color, const cl_font_t *font, int flags );
int CL_DrawString( float x, float y, const char *s, rgba_t color, cl_font_t *font, int flags ); void CL_DrawCharacterLen( const cl_font_t *font, uint32_t uc, int *width, int *height );
void CL_DrawCharacterLen( cl_font_t *font, int number, int *width, int *height );
void CL_DrawStringLen( cl_font_t *font, const char *s, int *width, int *height, int flags ); int CL_DrawString( float x, float y, const char *s, const rgba_t color, const cl_font_t *font, int flags );
int CL_DrawStringf( cl_font_t *font, float x, float y, rgba_t color, int flags, const char *fmt, ... ) FORMAT_CHECK( 6 ); int CL_DrawStringf( const cl_font_t *font, float x, float y, const rgba_t color, int flags, const char *fmt, ... ) FORMAT_CHECK( 6 );
void CL_DrawStringLen( const cl_font_t *font, const char *s, int *width, int *height, int flags );
// //
@@ -842,19 +849,21 @@ void CL_EnableScissor( scissor_state_t *scissor, int x, int y, int width, int he
void CL_DisableScissor( scissor_state_t *scissor ); void CL_DisableScissor( scissor_state_t *scissor );
qboolean CL_Scissor( const scissor_state_t *scissor, float *x, float *y, float *width, float *height, float *u0, float *v0, float *u1, float *v1 ); qboolean CL_Scissor( const scissor_state_t *scissor, float *x, float *y, float *width, float *height, float *u0, float *v0, float *u1, float *v1 );
static inline cl_entity_t *CL_EDICT_NUM( int n ) static inline cl_entity_t *CL_EDICT_NUM( int index )
{ {
if( !clgame.entities ) if( !clgame.entities ) // not in game yet
{ {
Host_Error( "%s: clgame.entities is NULL\n", __func__ ); Host_Error( "%s: clgame.entities is NULL\n", __func__ );
return NULL; return NULL;
} }
if(( n >= 0 ) && ( n < clgame.maxEntities )) if( index < 0 || index >= clgame.maxEntities )
return clgame.entities + n; {
Host_Error( "%s: bad number %i\n", __func__, index );
return NULL;
}
Host_Error( "%s: bad number %i\n", __func__, n ); return clgame.entities + index;
return NULL;
} }
static inline cl_entity_t *CL_GetEntityByIndex( int index ) static inline cl_entity_t *CL_GetEntityByIndex( int index )
@@ -865,10 +874,7 @@ static inline cl_entity_t *CL_GetEntityByIndex( int index )
if( index < 0 || index >= clgame.maxEntities ) if( index < 0 || index >= clgame.maxEntities )
return NULL; return NULL;
if( index == 0 ) return clgame.entities + index;
return clgame.entities;
return CL_EDICT_NUM( index );
} }
static inline model_t *CL_ModelHandle( int modelindex ) static inline model_t *CL_ModelHandle( int modelindex )
@@ -878,7 +884,7 @@ static inline model_t *CL_ModelHandle( int modelindex )
static inline qboolean CL_IsThirdPerson( void ) static inline qboolean CL_IsThirdPerson( void )
{ {
return clgame.dllFuncs.CL_IsThirdPerson() ? true : false; return clgame.dllFuncs.CL_IsThirdPerson();
} }
static inline cl_entity_t *CL_GetLocalPlayer( void ) static inline cl_entity_t *CL_GetLocalPlayer( void )
@@ -1089,6 +1095,7 @@ void CL_ReadLineFile_f( void );
// console.c // console.c
// //
extern convar_t con_fontsize; extern convar_t con_fontsize;
extern int g_codepage;
int Con_Visible( void ); int Con_Visible( void );
qboolean Con_FixedFont( void ); qboolean Con_FixedFont( void );
void Con_VidInit( void ); void Con_VidInit( void );
@@ -1099,14 +1106,13 @@ void Con_DrawDebug( void );
void Con_RunConsole( void ); void Con_RunConsole( void );
void Con_DrawConsole( void ); void Con_DrawConsole( void );
void Con_DrawVersion( void ); void Con_DrawVersion( void );
int Con_UtfProcessChar( int in );
int Con_UtfProcessCharForce( int in ); int Con_UtfProcessCharForce( int in );
int Con_UtfMoveLeft( char *str, int pos ); int Con_UtfMoveLeft( char *str, int pos );
int Con_UtfMoveRight( char *str, int pos, int length ); 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 );
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, const 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 );
void Key_Console( int key ); void Key_Console( int key );
@@ -1119,7 +1125,7 @@ void Con_PageUp( int lines );
// //
// s_main.c // s_main.c
// //
void S_StreamAviSamples( void *Avi, int entnum, float fvol, float attn, float synctime ); typedef int sound_t;
void S_StartBackgroundTrack( const char *intro, const char *loop, int position, qboolean fullpath ); void S_StartBackgroundTrack( const char *intro, const char *loop, int position, qboolean fullpath );
void S_StopBackgroundTrack( void ); void S_StopBackgroundTrack( void );
void S_StreamSetPause( int pause ); void S_StreamSetPause( int pause );
@@ -1208,6 +1214,12 @@ void Key_EnableTextInput( qboolean enable, qboolean force );
int Key_ToUpper( int key ); int Key_ToUpper( int key );
void OSK_Draw( void ); void OSK_Draw( void );
//
// identification.c
//
void ID_Init( void );
const char *ID_GetMD5( void );
extern rgba_t g_color_table[8]; extern rgba_t g_color_table[8];
extern triangleapi_t gTriApi; extern triangleapi_t gTriApi;
extern net_api_t gNetApi; extern net_api_t gNetApi;

View File

@@ -34,7 +34,7 @@ static CVAR_DEFINE_AUTO( con_color, "240 180 24", FCVAR_ARCHIVE, "set a custom c
static CVAR_DEFINE_AUTO( scr_drawversion, "1", FCVAR_ARCHIVE, "draw version in menu or screenshots, doesn't affect console" ); static CVAR_DEFINE_AUTO( scr_drawversion, "1", FCVAR_ARCHIVE, "draw version in menu or screenshots, doesn't affect console" );
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; int g_codepage = 0;
static qboolean g_messagemode_privileged = true; static qboolean g_messagemode_privileged = true;
@@ -622,7 +622,7 @@ int Con_UtfProcessCharForce( int in )
// TODO: get rid of global state where possible // TODO: get rid of global state where possible
static utfstate_t state = { 0 }; static utfstate_t state = { 0 };
int ch = Q_DecodeUTF8( &state, in ); uint32_t ch = Q_DecodeUTF8( &state, in );
if( g_codepage == 1251 ) if( g_codepage == 1251 )
return Q_UnicodeToCP1251( ch ); return Q_UnicodeToCP1251( ch );
@@ -632,15 +632,6 @@ int Con_UtfProcessCharForce( int in )
return '?'; // not implemented yet return '?'; // not implemented yet
} }
int GAME_EXPORT Con_UtfProcessChar( int in )
{
if( !cls.accept_utf8 ) // incoming character is not a UTF-8 sequence
return in;
// otherwise, decode it and convert to selected codepage
return Con_UtfProcessCharForce( in );
}
/* /*
================= =================
Con_UtfMoveLeft Con_UtfMoveLeft
@@ -759,7 +750,7 @@ Con_DrawString
client version of routine client version of routine
==================== ====================
*/ */
int Con_DrawString( int x, int y, const char *string, rgba_t setColor ) int Con_DrawString( int x, int y, const char *string, const rgba_t setColor )
{ {
return CL_DrawString( x, y, string, setColor, con.curFont, FONT_DRAW_UTF8 ); return CL_DrawString( x, y, string, setColor, con.curFont, FONT_DRAW_UTF8 );
} }
@@ -843,11 +834,14 @@ If no console is visible, the notify window will pop up.
*/ */
void Con_Print( const char *txt ) void Con_Print( const char *txt )
{ {
static int cr_pending = 0; static qboolean cr_pending = false;
static char buf[MAX_PRINT_MSG]; static qboolean colorstring = false;
qboolean norefresh = false; static char buf[MAX_PRINT_MSG];
static int lastlength = 0; static int lastlength = 0;
static int bufpos = 0; static int bufpos = 0;
static int charpos = 0;
qboolean norefresh = false;
int c, mask = 0; int c, mask = 0;
// client not running // client not running
@@ -873,7 +867,7 @@ void Con_Print( const char *txt )
if( cr_pending ) if( cr_pending )
{ {
Con_DeleteLastLine(); Con_DeleteLastLine();
cr_pending = 0; cr_pending = false;
} }
c = *txt; c = *txt;
@@ -886,23 +880,42 @@ void Con_Print( const char *txt )
{ {
Con_AddLine( buf, bufpos, true ); Con_AddLine( buf, bufpos, true );
lastlength = CON_LINES_LAST().length; lastlength = CON_LINES_LAST().length;
cr_pending = 1; cr_pending = true;
bufpos = 0; bufpos = 0;
charpos = 0;
} }
break; break;
case '\n': case '\n':
Con_AddLine( buf, bufpos, true ); Con_AddLine( buf, bufpos, true );
lastlength = CON_LINES_LAST().length; lastlength = CON_LINES_LAST().length;
bufpos = 0; bufpos = 0;
charpos = 0;
break; break;
default: default:
buf[bufpos++] = c | mask; buf[bufpos++] = c | mask;
if(( bufpos >= sizeof( buf ) - 1 ) || bufpos >= ( con.linewidth - 1 ))
if( IsColorString( txt ))
{
// first color string character
colorstring = true;
}
else if( colorstring )
{
// second color string character
colorstring = false;
}
else
{
// not a color string, move char counter
charpos++;
}
if(( bufpos >= sizeof( buf ) - 1 ) || charpos >= ( con.linewidth - 1 ))
{ {
Con_AddLine( buf, bufpos, true ); Con_AddLine( buf, bufpos, true );
lastlength = CON_LINES_LAST().length; lastlength = CON_LINES_LAST().length;
bufpos = 0; bufpos = 0;
charpos = 0;
} }
break; break;
} }
@@ -918,6 +931,7 @@ void Con_Print( const char *txt )
Con_AddLine( buf, bufpos, lastlength != 0 ); Con_AddLine( buf, bufpos, lastlength != 0 );
lastlength = 0; lastlength = 0;
bufpos = 0; bufpos = 0;
charpos = 0;
} }
// pump messages to avoid window hanging // pump messages to avoid window hanging
@@ -1244,45 +1258,16 @@ static void Field_CharEvent( field_t *edit, int ch )
Field_DrawInputLine Field_DrawInputLine
================== ==================
*/ */
static void Field_DrawInputLine( int x, int y, field_t *edit ) static void Field_DrawInputLine( int x, int y, const field_t *edit )
{ {
int len, cursorChar; int curPos;
int drawLen; char str[MAX_SYSPATH];
int prestep, curPos; const byte *colorDefault = g_color_table[ColorIndex( COLOR_DEFAULT )];
char str[MAX_SYSPATH]; const int prestep = bound( 0, edit->scroll, sizeof( edit->buffer ) - 1 );
byte *colorDefault; const int drawLen = bound( 0, edit->widthInChars, sizeof( str ));
const int cursorCharPos = bound( 0, edit->cursor - prestep, sizeof( str ));
drawLen = edit->widthInChars; Q_strncpy( str, edit->buffer + prestep, drawLen );
len = Q_strlen( edit->buffer ) + 1;
colorDefault = g_color_table[ColorIndex( COLOR_DEFAULT )];
// guarantee that cursor will be visible
if( len <= drawLen )
{
prestep = 0;
}
else
{
if( edit->scroll + drawLen > len )
{
edit->scroll = len - drawLen;
if( edit->scroll < 0 ) edit->scroll = 0;
}
prestep = edit->scroll;
}
if( prestep + drawLen > len )
drawLen = len - prestep;
// extract <drawLen> characters from the field at <prestep>
drawLen = Q_min( drawLen, MAX_SYSPATH - 1 );
memcpy( str, edit->buffer + prestep, drawLen );
str[drawLen] = 0;
// save char for overstrike
cursorChar = str[edit->cursor - prestep];
// draw it // draw it
CL_DrawString( x, y, str, colorDefault, con.curFont, FONT_DRAW_UTF8 ); CL_DrawString( x, y, str, colorDefault, con.curFont, FONT_DRAW_UTF8 );
@@ -1291,7 +1276,7 @@ static void Field_DrawInputLine( int x, int y, field_t *edit )
if((int)( host.realtime * 4 ) & 1 ) return; // off blink if((int)( host.realtime * 4 ) & 1 ) return; // off blink
// calc cursor position // calc cursor position
str[edit->cursor - prestep] = 0; str[cursorCharPos] = 0;
CL_DrawStringLen( con.curFont, str, &curPos, NULL, FONT_DRAW_UTF8 ); CL_DrawStringLen( con.curFont, str, &curPos, NULL, FONT_DRAW_UTF8 );
if( host.key_overstrike ) if( host.key_overstrike )
@@ -1467,6 +1452,16 @@ Handles history and console scrollback
*/ */
void Key_Console( int key ) void Key_Console( int key )
{ {
// exit the console by pressing MINUS on NSwitch
// or both Back(Select)/Start buttons for everyone else
if( key == K_BACK_BUTTON || key == K_START_BUTTON || key == K_ESCAPE )
{
if( cls.state == ca_active && !cl.background )
Key_SetKeyDest( key_game );
else UI_SetActiveMenu( true );
return;
}
// ctrl-L clears screen // ctrl-L clears screen
if( key == 'l' && Key_IsDown( K_CTRL )) if( key == 'l' && Key_IsDown( K_CTRL ))
{ {
@@ -1575,16 +1570,6 @@ void Key_Console( int key )
return; return;
} }
// exit the console by pressing MINUS on NSwitch
// or both Back(Select)/Start buttons for everyone else
if( key == K_BACK_BUTTON || key == K_START_BUTTON )
{
if( cls.state == ca_active && !cl.background )
Key_SetKeyDest( key_game );
else UI_SetActiveMenu( true );
return;
}
// pass to the normal editline routine // pass to the normal editline routine
Field_KeyDownEvent( &con.input, key ); Field_KeyDownEvent( &con.input, key );
} }
@@ -2008,7 +1993,7 @@ void Con_DrawVersion( void )
int start, height = refState.height; int start, height = refState.height;
string curbuild; string curbuild;
if( !scr_drawversion.value || CL_IsDevOverviewMode() == 2 || net_graph.value ) if( !scr_drawversion.value )
return; return;
if( cls.key_dest == key_menu ) if( cls.key_dest == key_menu )
@@ -2020,6 +2005,9 @@ void Con_DrawVersion( void )
{ {
qboolean draw_version; qboolean draw_version;
if( CL_IsDevOverviewMode() == 2 || net_graph.value )
return;
draw_version = cls.scrshot_action == scrshot_normal draw_version = cls.scrshot_action == scrshot_normal
|| cls.scrshot_action == scrshot_snapshot || cls.scrshot_action == scrshot_snapshot
|| host.force_draw_version_time > host.realtime; || host.force_draw_version_time > host.realtime;
@@ -2092,10 +2080,7 @@ void Con_RunConsole( void )
} }
else else
{ {
Con_Printf( S_WARN "Unknown charset %s, defaulting to cp1252", con_charset.string ); g_codepage = 0;
Cvar_DirectSet( &con_charset, "cp1252" );
g_codepage = 1252;
} }
cls.accept_utf8 = !Q_stricmp( cl_charset.string, "utf-8" ); cls.accept_utf8 = !Q_stricmp( cl_charset.string, "utf-8" );

View File

@@ -19,8 +19,8 @@ GNU General Public License for more details.
#if !XASH_WIN32 #if !XASH_WIN32
#include <dirent.h> #include <dirent.h>
#endif #endif
static char id_md5[33]; static char id_md5[33];
static char id_customid[MAX_STRING];
/* /*
========================================================== ==========================================================
@@ -590,28 +590,12 @@ static void ID_Check( void )
const char *ID_GetMD5( void ) const char *ID_GetMD5( void )
{ {
if( id_customid[0] )
return id_customid;
return id_md5; return id_md5;
} }
/*
===============
ID_SetCustomClientID
===============
*/
void GAME_EXPORT ID_SetCustomClientID( const char *id )
{
if( !id )
return;
Q_strncpy( id_customid, id, sizeof( id_customid ) );
}
void ID_Init( void ) void ID_Init( void )
{ {
MD5Context_t hash = {0}; MD5Context_t hash = { 0 };
byte md5[16]; byte md5[16];
int i; int i;
@@ -632,7 +616,7 @@ void ID_Init( void )
#elif XASH_WIN32 #elif XASH_WIN32
{ {
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\\"XASH_ENGINE_NAME"\\", "xash_id", szBuf, MAX_PATH );
sscanf(szBuf, "%016"PRIX64, &id); sscanf(szBuf, "%016"PRIX64, &id);
id ^= SYSTEM_XOR_MASK; id ^= SYSTEM_XOR_MASK;
@@ -686,7 +670,7 @@ void ID_Init( void )
{ {
CHAR Buf[MAX_PATH]; CHAR Buf[MAX_PATH];
sprintf( Buf, "%016"PRIX64, 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\\"XASH_ENGINE_NAME"\\", REG_SZ, "xash_id", Buf, Q_strlen(Buf) );
} }
#else #else
{ {

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -205,9 +205,10 @@ void IN_ToggleClientMouse( int newstate, int oldstate )
} }
} }
static void IN_SetRelativeMouseMode( qboolean set, qboolean verbose ) void IN_SetRelativeMouseMode( qboolean set )
{ {
static qboolean s_bRawInput; static qboolean s_bRawInput;
qboolean verbose = m_grab_debug.value ? true : false;
if( set && !s_bRawInput ) if( set && !s_bRawInput )
{ {
@@ -231,9 +232,10 @@ static void IN_SetRelativeMouseMode( qboolean set, qboolean verbose )
} }
} }
static void IN_SetMouseGrab( qboolean set, qboolean verbose ) void IN_SetMouseGrab( qboolean set )
{ {
static qboolean s_bMouseGrab; static qboolean s_bMouseGrab;
qboolean verbose = m_grab_debug.value ? true : false;
if( set && !s_bMouseGrab ) if( set && !s_bMouseGrab )
{ {
@@ -258,7 +260,7 @@ static void IN_SetMouseGrab( qboolean set, qboolean verbose )
static void IN_CheckMouseState( qboolean active ) static void IN_CheckMouseState( qboolean active )
{ {
qboolean use_raw_input, verbose; qboolean use_raw_input;
#if XASH_WIN32 #if XASH_WIN32
use_raw_input = ( 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;
@@ -266,20 +268,18 @@ static void IN_CheckMouseState( qboolean active )
use_raw_input = 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 )
active = false; active = false;
if( active && use_raw_input && !host.mouse_visible && cls.state == ca_active ) if( active && use_raw_input && !host.mouse_visible && cls.state == ca_active )
IN_SetRelativeMouseMode( true, verbose ); IN_SetRelativeMouseMode( true );
else else
IN_SetRelativeMouseMode( false, verbose ); IN_SetRelativeMouseMode( false );
if( active && !host.mouse_visible && cls.state == ca_active ) if( active && !host.mouse_visible && cls.state == ca_active )
IN_SetMouseGrab( true, verbose ); IN_SetMouseGrab( true );
else else
IN_SetMouseGrab( false, verbose ); IN_SetMouseGrab( false );
} }
/* /*
@@ -332,7 +332,7 @@ static void IN_MouseMove( void )
if( !in_mouseinitialized ) if( !in_mouseinitialized )
return; return;
if( Touch_Emulated( )) if( Touch_WantVisibleCursor( ))
{ {
// touch emulation overrides all input // touch emulation overrides all input
Touch_KeyEvent( 0, 0 ); Touch_KeyEvent( 0, 0 );
@@ -363,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_Emulated( )) if( Touch_WantVisibleCursor( ))
{ {
Touch_KeyEvent( K_MOUSE1 + key, down ); Touch_KeyEvent( K_MOUSE1 + key, down );
} }

View File

@@ -46,6 +46,9 @@ uint IN_CollectInputDevices( void );
void IN_LockInputDevices( qboolean lock ); void IN_LockInputDevices( qboolean lock );
void IN_EngineAppendMove( float frametime, usercmd_t *cmd, qboolean active ); void IN_EngineAppendMove( float frametime, usercmd_t *cmd, qboolean active );
void IN_SetRelativeMouseMode( qboolean set );
void IN_SetMouseGrab( qboolean set );
extern convar_t m_yaw; extern convar_t m_yaw;
extern convar_t m_pitch; extern convar_t m_pitch;
// //
@@ -74,7 +77,6 @@ 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 );
// //
@@ -104,18 +106,21 @@ typedef enum engineAxis_e
JOY_AXIS_NULL JOY_AXIS_NULL
} engineAxis_t; } engineAxis_t;
typedef enum joy_calibration_state_s
{
JOY_NOT_CALIBRATED = 0,
JOY_CALIBRATING,
JOY_FAILED_TO_CALIBRATE,
JOY_CALIBRATED
} joy_calibration_state_t;
qboolean Joy_IsActive( void ); qboolean Joy_IsActive( void );
void Joy_HatMotionEvent( byte hat, byte value ); void Joy_SetCapabilities( qboolean have_gyro );
void Joy_AxisMotionEvent( byte axis, short value ); void Joy_SetCalibrationState( joy_calibration_state_t state );
void Joy_KnownAxisMotionEvent( engineAxis_t engineAxis, short value ); void Joy_AxisMotionEvent( engineAxis_t engineAxis, short value );
void Joy_BallMotionEvent( byte ball, short xrel, short yrel ); void Joy_GyroEvent( vec3_t data );
void Joy_ButtonEvent( byte button, byte down );
void Joy_AddEvent( void );
void Joy_RemoveEvent( void );
void Joy_FinalizeMove( float *fw, float *side, float *dpitch, float *dyaw ); void Joy_FinalizeMove( float *fw, float *side, float *dpitch, float *dyaw );
void Joy_Init( void ); void Joy_Init( void );
void Joy_Shutdown( void ); void Joy_Shutdown( void );
void Joy_EnableTextInput(qboolean enable, qboolean force);
#endif//INPUT_H #endif//INPUT_H

View File

@@ -51,7 +51,7 @@ static const keyname_t keynames[] =
{"CTRL", K_CTRL, "+attack" }, {"CTRL", K_CTRL, "+attack" },
{"SHIFT", K_SHIFT, "+speed" }, {"SHIFT", K_SHIFT, "+speed" },
{"CAPSLOCK", K_CAPSLOCK, "" }, {"CAPSLOCK", K_CAPSLOCK, "" },
{"SCROLLOCK", K_SCROLLOCK, "" }, {"SCROLLOCK", K_SCROLLLOCK, "" },
{"F1", K_F1, "cmd help" }, {"F1", K_F1, "cmd help" },
{"F2", K_F2, "menu_savegame" }, {"F2", K_F2, "menu_savegame" },
{"F3", K_F3, "menu_loadgame" }, {"F3", K_F3, "menu_loadgame" },
@@ -215,7 +215,7 @@ const char *Key_KeynumToString( int keynum )
return "<OUT OF RANGE>"; return "<OUT OF RANGE>";
// check for printable ascii (don't use quote) // check for printable ascii (don't use quote)
if( keynum > 32 && keynum < 127 && keynum != '"' && keynum != ';' && keynum != K_SCROLLOCK ) if( keynum > 32 && keynum < 127 && keynum != '"' && keynum != ';' && keynum != K_SCROLLLOCK )
{ {
tinystr[0] = keynum; tinystr[0] = keynum;
tinystr[1] = 0; tinystr[1] = 0;
@@ -726,18 +726,8 @@ void GAME_EXPORT Key_Event( int key, int down )
return; // handled in client.dll return; // handled in client.dll
} }
break; break;
case key_message: default:
Key_Message( key ); break;
return;
case key_console:
if( cls.state == ca_active && !cl.background )
Key_SetKeyDest( key_game );
else UI_SetActiveMenu( true );
return;
case key_menu:
UI_KeyEvent( key, true );
return;
default: return;
} }
} }
@@ -861,7 +851,9 @@ void GAME_EXPORT Key_ClearStates( void )
for( i = 0; i < 256; i++ ) for( i = 0; i < 256; i++ )
{ {
if( keys[i].down && i < K_MOUSE1 && i > K_MOUSE5 ) if( i >= K_MOUSE1 && i <= K_MOUSE5 )
IN_MouseEvent( i - K_MOUSE1, false );
else
Key_Event( i, false ); Key_Event( i, false );
keys[i].down = 0; keys[i].down = 0;
@@ -869,9 +861,6 @@ void GAME_EXPORT Key_ClearStates( void )
keys[i].gamedown = 0; keys[i].gamedown = 0;
} }
for( i = K_MOUSE1; i < K_MOUSE5; i++ ) // from K_MOUSE1 to K_MOUSE5
IN_MouseEvent( i - K_MOUSE1, false );
if( clgame.hInstance ) if( clgame.hInstance )
clgame.dllFuncs.IN_ClearStates(); clgame.dllFuncs.IN_ClearStates();
} }
@@ -968,6 +957,7 @@ enum
OSK_ENTER, OSK_ENTER,
OSK_SPECKEY_LAST OSK_SPECKEY_LAST
}; };
static const char *osk_keylayout[][4] = static const char *osk_keylayout[][4] =
{ {
{ {
@@ -984,7 +974,7 @@ static const char *osk_keylayout[][4] =
} }
}; };
struct osk_s static struct osk_s
{ {
qboolean enable; qboolean enable;
int curlayout; int curlayout;
@@ -1018,7 +1008,6 @@ static qboolean OSK_KeyEvent( int key, int down )
return false; return false;
} }
switch ( key ) switch ( key )
{ {
case K_ENTER: case K_ENTER:
@@ -1061,10 +1050,6 @@ static qboolean OSK_KeyEvent( int key, int down )
ch = (byte)osk.curbutton.val; ch = (byte)osk.curbutton.val;
// do not pass UTF-8 sequence into the engine, convert it here
if( !cls.accept_utf8 )
ch = Con_UtfProcessCharForce( ch );
if( !ch ) if( !ch )
break; break;
@@ -1108,7 +1093,7 @@ static qboolean OSK_KeyEvent( int key, int down )
/* /*
============= =============
Joy_EnableTextInput OSK_EnableTextInput
Enables built-in IME Enables built-in IME
============= =============
@@ -1199,13 +1184,15 @@ void OSK_Draw( void )
X_STEP * MAX_OSK_ROWS * refState.width, X_STEP * MAX_OSK_ROWS * refState.width,
Y_STEP * MAX_OSK_LINES * refState.height, 100, 100, 100, 100 ); Y_STEP * MAX_OSK_LINES * refState.height, 100, 100, 100, 100 );
OSK_DrawSpecialButton( "-]", X_START, Y_START + Y_STEP * 2, X_STEP, Y_STEP ); OSK_DrawSpecialButton( "-]", X_START, Y_START + Y_STEP * 2, X_STEP, Y_STEP );
OSK_DrawSpecialButton( "<-", X_START + X_STEP * 12, Y_START + Y_STEP * 2, X_STEP, Y_STEP ); OSK_DrawSpecialButton( "<-", X_START + X_STEP * 12, Y_START + Y_STEP * 2, X_STEP, Y_STEP );
OSK_DrawSpecialButton( "sh", X_START, Y_START + Y_STEP * 3, X_STEP, Y_STEP ); OSK_DrawSpecialButton( "sh", X_START, Y_START + Y_STEP * 3, X_STEP, Y_STEP );
OSK_DrawSpecialButton( "en", X_START + X_STEP * 12, Y_START + Y_STEP * 3, X_STEP, Y_STEP ); OSK_DrawSpecialButton( "en", X_START + X_STEP * 12, Y_START + Y_STEP * 3, X_STEP, Y_STEP );
for( y = Y_START, j = 0; j < MAX_OSK_LINES; j++, y += Y_STEP ) for( y = Y_START, j = 0; j < MAX_OSK_LINES; j++, y += Y_STEP )
{
for( x = X_START, i = 0; i < MAX_OSK_ROWS; i++, x += X_STEP ) for( x = X_START, i = 0; i < MAX_OSK_ROWS; i++, x += X_STEP )
OSK_DrawSymbolButton( curlayout[j][i], x, y, X_STEP, Y_STEP ); OSK_DrawSymbolButton( curlayout[j][i], x, y, X_STEP, Y_STEP );
}
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -114,7 +114,6 @@ typedef struct rawchan_s
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;
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[]; // variable sized portable_samplepair_t rawsamples[]; // variable sized
} rawchan_t; } rawchan_t;
@@ -171,6 +170,8 @@ typedef struct
int source; // may be game, menu, etc int source; // may be game, menu, etc
} bg_track_t; } bg_track_t;
typedef int sound_t;
//==================================================================== //====================================================================
#define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS) #define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS)

View File

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

View File

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

View File

@@ -32,6 +32,7 @@ typedef enum base_command_type
typedef void base_command_t; typedef void base_command_t;
void BaseCmd_Init( void ); void BaseCmd_Init( void );
void BaseCmd_Shutdown( 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,
base_command_t **cmd, base_command_t **alias, base_command_t **cvar ); base_command_t **cmd, base_command_t **alias, base_command_t **cvar );

View File

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

View File

@@ -76,23 +76,14 @@ XASH SPECIFIC - sort of hack that works only in Xash3D not in GoldSrc
#define HACKS_RELATED_HLMODS // some HL-mods works differently under Xash and can't be fixed without some hacks at least at current time #define HACKS_RELATED_HLMODS // some HL-mods works differently under Xash and can't be fixed without some hacks at least at current time
enum enum dev_level_e
{ {
DEV_NONE = 0, DEV_NONE = 0,
DEV_NORMAL, DEV_NORMAL,
DEV_EXTENDED DEV_EXTENDED
}; };
enum typedef enum instance_e
{
D_INFO = 1, // "-dev 1", shows various system messages
D_WARN, // "-dev 2", shows not critical system warnings
D_ERROR, // "-dev 3", shows critical warnings
D_REPORT, // "-dev 4", special case for game reports
D_NOTE // "-dev 5", show system notifications for engine developers
};
typedef enum
{ {
HOST_NORMAL, // listen server, singleplayer HOST_NORMAL, // listen server, singleplayer
HOST_DEDICATED, HOST_DEDICATED,
@@ -108,14 +99,14 @@ typedef enum
#include "com_model.h" #include "com_model.h"
#include "com_strings.h" #include "com_strings.h"
#include "crtlib.h" #include "crtlib.h"
#include "cvar.h"
#include "con_nprint.h"
#include "crclib.h"
#include "ref_api.h"
#define FSCALLBACK_OVERRIDE_OPEN #define FSCALLBACK_OVERRIDE_OPEN
#define FSCALLBACK_OVERRIDE_LOADFILE #define FSCALLBACK_OVERRIDE_LOADFILE
#define FSCALLBACK_OVERRIDE_MALLOC_LIKE #define FSCALLBACK_OVERRIDE_MALLOC_LIKE
#include "fscallback.h" #include "fscallback.h"
#include "cvar.h"
#include "con_nprint.h"
#include "crclib.h"
#include "ref_api.h"
// PERFORMANCE INFO // PERFORMANCE INFO
#define MIN_FPS 20.0f // host minimum fps value for maxfps. #define MIN_FPS 20.0f // host minimum fps value for maxfps.
@@ -146,6 +137,11 @@ typedef enum
#define MAX_STATIC_ENTITIES 32 // static entities that moved on the client when level is spawn #define MAX_STATIC_ENTITIES 32 // static entities that moved on the client when level is spawn
#endif #endif
#define MAX_SERVERINFO_STRING 512 // server handles too many settings. expand to 1024?
#define MAX_PRINT_MSG 8192 // how many symbols can handle single call of Con_Printf or Con_DPrintf
#define MAX_TOKEN 2048 // parse token length
#define MAX_USERMSG_LENGTH 2048 // don't modify it's relies on a client-side definitions
#define GameState (&host.game) #define GameState (&host.game)
#define FORCE_DRAW_VERSION_TIME 5.0 // draw version for 5 seconds #define FORCE_DRAW_VERSION_TIME 5.0 // draw version for 5 seconds
@@ -171,6 +167,11 @@ extern convar_t cl_filterstuffcmd;
extern convar_t rcon_password; extern convar_t rcon_password;
extern convar_t hpk_custom_file; extern convar_t hpk_custom_file;
extern convar_t con_gamemaps; extern convar_t con_gamemaps;
extern convar_t fs_mount_lv;
extern convar_t fs_mount_hd;
extern convar_t fs_mount_addon;
extern convar_t fs_mount_l10n;
extern convar_t ui_language; // historically used for UI, but now controls mounted localization directory
#define Mod_AllowMaterials() ( host_allow_materials.value != 0.0f && !FBitSet( host.features, ENGINE_DISABLE_HDTEXTURES )) #define Mod_AllowMaterials() ( host_allow_materials.value != 0.0f && !FBitSet( host.features, ENGINE_DISABLE_HDTEXTURES ))
@@ -189,7 +190,7 @@ GAMEINFO stuff
internal shared gameinfo structure (readonly for engine parts) internal shared gameinfo structure (readonly for engine parts)
======================================================================== ========================================================================
*/ */
typedef enum typedef enum host_status_e
{ {
HOST_INIT = 0, // initalize operations HOST_INIT = 0, // initalize operations
HOST_FRAME, // host running HOST_FRAME, // host running
@@ -200,7 +201,7 @@ typedef enum
HOST_CRASHED // an exception handler called HOST_CRASHED // an exception handler called
} host_status_t; } host_status_t;
typedef enum typedef enum host_state_e
{ {
STATE_RUNFRAME = 0, STATE_RUNFRAME = 0,
STATE_LOAD_LEVEL, STATE_LOAD_LEVEL,
@@ -209,7 +210,7 @@ typedef enum
STATE_GAME_SHUTDOWN, STATE_GAME_SHUTDOWN,
} host_state_t; } host_state_t;
typedef struct typedef struct game_status_e
{ {
host_state_t curstate; host_state_t curstate;
host_state_t nextstate; host_state_t nextstate;
@@ -220,7 +221,7 @@ typedef struct
qboolean newGame; // unload the server.dll before start a new map qboolean newGame; // unload the server.dll before start a new map
} game_status_t; } game_status_t;
typedef enum typedef enum keydest_e
{ {
key_console = 0, key_console = 0,
key_game, key_game,
@@ -228,7 +229,7 @@ typedef enum
key_message key_message
} keydest_t; } keydest_t;
typedef enum typedef enum rdtype_e
{ {
RD_NONE = 0, RD_NONE = 0,
RD_CLIENT, RD_CLIENT,
@@ -238,7 +239,7 @@ typedef enum
#include "net_ws.h" #include "net_ws.h"
// console field // console field
typedef struct typedef struct field_e
{ {
string buffer; string buffer;
int cursor; int cursor;
@@ -256,7 +257,7 @@ typedef struct host_redirect_s
int lines; int lines;
} host_redirect_t; } host_redirect_t;
typedef struct typedef struct soundlist_e
{ {
char name[MAX_QPATH]; char name[MAX_QPATH];
short entnum; short entnum;
@@ -297,7 +298,7 @@ typedef struct host_parm_s
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 instance_t type; // running at
poolhandle_t mempool; // static mempool for misc allocations poolhandle_t mempool; // static mempool for misc allocations
poolhandle_t imagepool; // imagelib mempool poolhandle_t imagepool; // imagelib mempool
poolhandle_t soundpool; // soundlib mempool poolhandle_t soundpool; // soundlib mempool
@@ -414,6 +415,8 @@ byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamediro
MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT; MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
byte *FS_LoadDirectFile( const char *path, fs_offset_t *filesizeptr ) byte *FS_LoadDirectFile( const char *path, fs_offset_t *filesizeptr )
MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT; MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
void FS_Rescan_f( void );
void FS_CheckConfig( void );
// //
// cmd.c // cmd.c
@@ -432,6 +435,7 @@ int Cmd_Argc( void );
const char *Cmd_Args( void ) RETURNS_NONNULL; const char *Cmd_Args( void ) RETURNS_NONNULL;
const char *Cmd_Argv( int arg ) RETURNS_NONNULL; const char *Cmd_Argv( int arg ) RETURNS_NONNULL;
void Cmd_Init( void ); void Cmd_Init( void );
void Cmd_Shutdown( void );
void Cmd_Unlink( int group ); void Cmd_Unlink( int group );
int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd_desc, int flags, const char *funcname ); int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd_desc, int flags, const char *funcname );
@@ -490,7 +494,7 @@ internal sound format
typically expanded to wav buffer typically expanded to wav buffer
======================================================================== ========================================================================
*/ */
typedef enum typedef enum sndformat_e
{ {
WF_UNKNOWN = 0, WF_UNKNOWN = 0,
WF_PCMDATA, WF_PCMDATA,
@@ -501,7 +505,7 @@ typedef enum
} sndformat_t; } sndformat_t;
// wavdata output flags // wavdata output flags
typedef enum typedef enum sndFlags_e
{ {
// wavdata->flags // wavdata->flags
SOUND_LOOPED = BIT( 0 ), // this is looped sound (contain cue markers) SOUND_LOOPED = BIT( 0 ), // this is looped sound (contain cue markers)
@@ -511,29 +515,29 @@ typedef enum
SOUND_RESAMPLE = BIT( 12 ), // resample sound to specified rate SOUND_RESAMPLE = BIT( 12 ), // resample sound to specified rate
} sndFlags_t; } sndFlags_t;
typedef struct typedef struct wavdata_s
{ {
word rate; // num samples per second (e.g. 11025 - 11 khz) size_t size; // for bounds checking
byte width; // resolution - bum bits divided by 8 (8 bit is 1, 16 bit is 2)
byte channels; // num channels (1 - mono, 2 - stereo)
uint loopStart; // offset at this point sound will be looping while playing more than only once uint loopStart; // offset at this point sound will be looping while playing more than only once
uint 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 word rate; // num samples per second (e.g. 11025 - 11 khz)
size_t size; // for bounds checking byte width; // resolution - bum bits divided by 8 (8 bit is 1, 16 bit is 2)
byte channels; // num channels (1 - mono, 2 - stereo)
byte buffer[]; // sound buffer
} wavdata_t; } wavdata_t;
// //
// soundlib // soundlib
// //
typedef struct stream_s stream_t;
void Sound_Init( void ); void Sound_Init( void );
void Sound_Shutdown( void ); void Sound_Shutdown( void );
void FS_FreeSound( wavdata_t *pack ); void FS_FreeSound( wavdata_t *pack );
void FS_FreeStream( stream_t *stream ); 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; 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; stream_t *FS_OpenStream( const char *filename ) MALLOC_LIKE( FS_FreeStream, 1 ) WARN_UNUSED_RESULT;
wavdata_t *FS_StreamInfo( stream_t *stream );
int FS_ReadStream( stream_t *stream, int bytes, void *buffer ); int FS_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 );
@@ -578,11 +582,19 @@ CLIENT / SERVER SYSTEMS
============================================================== ==============================================================
*/ */
#if !XASH_DEDICATED
void CL_Init( void ); void CL_Init( void );
void CL_Shutdown( void ); void CL_Shutdown( void );
void Host_ClientBegin( void ); void Host_ClientBegin( void );
void Host_ClientFrame( void ); void Host_ClientFrame( void );
int CL_Active( void ); int CL_Active( void );
#else
static inline void CL_Init( void ) { }
static inline void CL_Shutdown( void ) { }
static inline void Host_ClientBegin( void ) { Cbuf_Execute(); }
static inline void Host_ClientFrame( void ) { }
static inline int CL_Active( void ) { return 0; }
#endif
void SV_Init( void ); void SV_Init( void );
void SV_Shutdown( const char *finalmsg ); void SV_Shutdown( const char *finalmsg );
@@ -620,6 +632,7 @@ int pfnNumberOfEntities( void );
int pfnIsInGame( void ); int pfnIsInGame( void );
float pfnTime( void ); float pfnTime( void );
#define copystring( s ) _copystring( host.mempool, s, __FILE__, __LINE__ ) #define copystring( s ) _copystring( host.mempool, s, __FILE__, __LINE__ )
#define copystringpool( pool, s ) _copystring( pool, s, __FILE__, __LINE__ )
#define SV_CopyString( s ) _copystring( svgame.stringspool, s, __FILE__, __LINE__ ) #define SV_CopyString( s ) _copystring( svgame.stringspool, s, __FILE__, __LINE__ )
#define freestring( s ) if( s != NULL ) { Mem_Free( s ); s = NULL; } #define freestring( s ) if( s != NULL ) { Mem_Free( s ); s = NULL; }
char *_copystring( poolhandle_t mempool, const char *s, const char *filename, int fileline ); char *_copystring( poolhandle_t mempool, const char *s, const char *filename, int fileline );
@@ -670,6 +683,7 @@ int CSCR_WriteGameCVars( file_t *cfg, const char *scriptfilename );
// //
// hpak.c // hpak.c
// //
const char *COM_ResourceTypeFromIndex( int index );
void HPAK_Init( void ); void HPAK_Init( void );
qboolean HPAK_GetDataPointer( const char *filename, struct resource_s *pRes, byte **buffer, int *size ); qboolean HPAK_GetDataPointer( const char *filename, struct resource_s *pRes, byte **buffer, int *size );
qboolean HPAK_ResourceForHash( const char *filename, byte *hash, struct resource_s *pRes ); qboolean HPAK_ResourceForHash( const char *filename, byte *hash, struct resource_s *pRes );
@@ -703,13 +717,32 @@ typedef enum connprotocol_e
struct physent_s; struct physent_s;
struct sv_client_s; struct sv_client_s;
typedef struct sizebuf_s sizebuf_t; typedef struct sizebuf_s sizebuf_t;
int SV_GetMaxClients( void );
#if !XASH_DEDICATED
qboolean CL_Initialized( void );
qboolean CL_IsInGame( void ); qboolean CL_IsInGame( void );
qboolean CL_IsInConsole( void ); qboolean CL_IsInConsole( void );
qboolean CL_IsIntermission( void ); qboolean CL_IsIntermission( void );
qboolean CL_Initialized( void ); qboolean CL_DisableVisibility( void );
qboolean CL_IsRecordDemo( void );
qboolean CL_IsPlaybackDemo( void );
qboolean UI_CreditsActive( void );
int CL_GetMaxClients( void );
#else
static inline qboolean CL_Initialized( void ) { return false; }
static inline qboolean CL_IsInGame( void ) { return true; } // always true for dedicated
static inline qboolean CL_IsInConsole( void ) { return false; }
static inline qboolean CL_IsIntermission( void ) { return false; }
static inline qboolean CL_DisableVisibility( void ) { return false; }
static inline qboolean CL_IsRecordDemo( void ) { return false; }
static inline qboolean CL_IsPlaybackDemo( void ) { return false; }
static inline qboolean UI_CreditsActive( void ) { return false; }
static inline int CL_GetMaxClients( void ) { return SV_GetMaxClients(); }
#endif
char *CL_Userinfo( void ); char *CL_Userinfo( void );
void CL_CharEvent( int key ); void CL_CharEvent( int key );
qboolean CL_DisableVisibility( void );
byte *COM_LoadFile( const char *filename, int usehunk, int *pLength ) MALLOC_LIKE( free, 1 ); 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 );
@@ -727,13 +760,7 @@ const char *CL_MsgInfo( int cmd );
void SV_DrawDebugTriangles( void ); void SV_DrawDebugTriangles( void );
void SV_DrawOrthoTriangles( void ); void SV_DrawOrthoTriangles( void );
double CL_GetDemoFramerate( void ); double CL_GetDemoFramerate( void );
qboolean UI_CreditsActive( void );
void CL_StopPlayback( void ); void CL_StopPlayback( void );
int CL_GetMaxClients( void );
int SV_GetMaxClients( void );
qboolean CL_IsRecordDemo( void );
qboolean CL_IsTimeDemo( void );
qboolean CL_IsPlaybackDemo( void );
qboolean SV_Initialized( void ); qboolean SV_Initialized( void );
void CL_ProcessFile( qboolean successfully_received, const char *filename ); void CL_ProcessFile( qboolean successfully_received, const char *filename );
int SV_GetSaveComment( const char *savename, char *comment ); int SV_GetSaveComment( const char *savename, char *comment );
@@ -846,13 +873,6 @@ void V_CheckGamma( void );
void V_CheckGammaEnd( void ); void V_CheckGammaEnd( void );
intptr_t V_GetGammaPtr( int parm ); intptr_t V_GetGammaPtr( int parm );
//
// identification.c
//
void ID_Init( void );
const char *ID_GetMD5( void );
void GAME_EXPORT ID_SetCustomClientID( const char *id );
// //
// masterlist.c // masterlist.c
// //

View File

@@ -498,7 +498,6 @@ static qboolean Cmd_GetSoundList( const char *s, char *completedname, int length
return true; return true;
} }
#if !XASH_DEDICATED
/* /*
===================================== =====================================
Cmd_GetItemsList Cmd_GetItemsList
@@ -508,6 +507,7 @@ Prints or complete item classname (weapons only)
*/ */
static qboolean Cmd_GetItemsList( const char *s, char *completedname, int length ) static qboolean Cmd_GetItemsList( const char *s, char *completedname, int length )
{ {
#if !XASH_DEDICATED
search_t *t; search_t *t;
string matchbuf; string matchbuf;
int i, numitems; int i, numitems;
@@ -521,7 +521,7 @@ static qboolean Cmd_GetItemsList( const char *s, char *completedname, int length
Q_strncpy( completedname, matchbuf, length ); Q_strncpy( completedname, matchbuf, length );
if( t->numfilenames == 1 ) return true; if( t->numfilenames == 1 ) return true;
for(i = 0, numitems = 0; i < t->numfilenames; i++) for( i = 0, numitems = 0; i < t->numfilenames; i++ )
{ {
if( Q_stricmp( COM_FileExtension( t->filenames[i] ), "txt" )) if( Q_stricmp( COM_FileExtension( t->filenames[i] ), "txt" ))
continue; continue;
@@ -544,6 +544,8 @@ static qboolean Cmd_GetItemsList( const char *s, char *completedname, int length
} }
} }
return true; return true;
#endif // !XASH_DEDICATED
return false;
} }
/* /*
@@ -555,6 +557,7 @@ Autocomplete for bind command
*/ */
static qboolean Cmd_GetKeysList( const char *s, char *completedname, int length ) static qboolean Cmd_GetKeysList( const char *s, char *completedname, int length )
{ {
#if !XASH_DEDICATED
size_t i, numkeys; size_t i, numkeys;
string keys[256]; string keys[256];
string matchbuf; string matchbuf;
@@ -595,8 +598,9 @@ static qboolean Cmd_GetKeysList( const char *s, char *completedname, int length
} }
return true; return true;
#endif // !XASH_DEDICATED
return false;
} }
#endif // XASH_DEDICATED
/* /*
=============== ===============
@@ -604,13 +608,20 @@ Con_AddCommandToList
=============== ===============
*/ */
static void Con_AddCommandToList( const char *s, const char *unused1, const char *unused2, void *_autocompleteList ) static void Con_AddCommandToList( const char *s, const char *value, const void *ptoggle, void *_autocompleteList )
{ {
con_autocomplete_t *list = (con_autocomplete_t*)_autocompleteList; con_autocomplete_t *list = (con_autocomplete_t*)_autocompleteList;
qboolean toggle = ptoggle != NULL && *(qboolean *)ptoggle;
if( *s == '@' ) return; // never show system cvars or cmds if( *s == '@' ) return; // never show system cvars or cmds
if( list->matchCount >= CON_MAXCMDS ) return; // list is full if( list->matchCount >= CON_MAXCMDS ) return; // list is full
if( toggle )
{
if( Q_strcmp( value, "0" ) && Q_strcmp( value, "1" ))
return; // exclude non-toggable cvars
}
if( Q_strnicmp( s, list->completionString, Q_strlen( list->completionString ) ) ) if( Q_strnicmp( s, list->completionString, Q_strlen( list->completionString ) ) )
return; // no match return; // no match
@@ -634,13 +645,11 @@ Cmd_GetCommandsList
Autocomplete for bind command Autocomplete for bind command
===================================== =====================================
*/ */
static qboolean Cmd_GetCommandsList( const char *s, char *completedname, int length ) static qboolean Cmd_GetCommandsAndCvarsList( const char *s, char *completedname, int length, qboolean cmds, qboolean cvars, qboolean toggle )
{ {
size_t i; size_t i;
string matchbuf; string matchbuf;
con_autocomplete_t list; // local autocomplete list con_autocomplete_t list = { 0 }; // local autocomplete list
memset( &list, 0, sizeof( list ));
list.completionString = s; list.completionString = s;
@@ -652,8 +661,16 @@ static qboolean Cmd_GetCommandsList( const char *s, char *completedname, int len
return false; return false;
// find matching commands and variables // find matching commands and variables
Cmd_LookupCmds( NULL, &list, (setpair_t)Con_AddCommandToList ); if( cvars )
Cvar_LookupVars( 0, NULL, &list, (setpair_t)Con_AddCommandToList ); {
Cvar_LookupVars( 0, &toggle, &list, (setpair_t)Con_AddCommandToList );
}
if( cmds )
{
toggle = false;
Cmd_LookupCmds( &toggle, &list, (setpair_t)Con_AddCommandToList );
}
if( !list.matchCount ) return false; if( !list.matchCount ) return false;
Q_strncpy( matchbuf, list.cmds[0], sizeof( matchbuf )); Q_strncpy( matchbuf, list.cmds[0], sizeof( matchbuf ));
@@ -669,7 +686,7 @@ static qboolean Cmd_GetCommandsList( const char *s, char *completedname, int len
Con_Printf( "%16s\n", matchbuf ); Con_Printf( "%16s\n", matchbuf );
} }
Con_Printf( "\n^3 %i commands found.\n", list.matchCount ); Con_Printf( "\n^3 %i %s found.\n", list.matchCount, cmds ? "commands" : "variables" );
if( completedname && length ) if( completedname && length )
{ {
@@ -691,6 +708,30 @@ static qboolean Cmd_GetCommandsList( const char *s, char *completedname, int len
return true; return true;
} }
/*
=====================================
Cmd_GetCommandsList
Autocomplete for bind command
=====================================
*/
static qboolean Cmd_GetCommandsList( const char *s, char *completedname, int length )
{
return Cmd_GetCommandsAndCvarsList( s, completedname, length, true, true, false );
}
/*
=====================================
Cmd_GetCvarList
Autocomplete for bind command
=====================================
*/
static qboolean Cmd_GetCvarsList( const char *s, char *completedname, int length )
{
qboolean toggle = !Q_stricmp( Cmd_Argv( 0 ), "toggle" );
return Cmd_GetCommandsAndCvarsList( s, completedname, length, false, true, toggle );
}
/* /*
===================================== =====================================
@@ -1010,36 +1051,38 @@ int GAME_EXPORT Cmd_CheckMapsList( int fRefresh )
return Cmd_CheckMapsList_R( fRefresh, true ); return Cmd_CheckMapsList_R( fRefresh, true );
} }
// keep this sorted
static const autocomplete_list_t cmd_list[] = static const autocomplete_list_t cmd_list[] =
{ {
{ "map_background", 1, Cmd_GetMapList }, { "bind", 1, Cmd_GetKeysList },
{ "bind", 2, Cmd_GetCommandsList },
{ "cd", 1, Cmd_GetCDList },
{ "changelevel2", 1, Cmd_GetMapList }, { "changelevel2", 1, Cmd_GetMapList },
{ "changelevel", 1, Cmd_GetMapList }, { "changelevel", 1, Cmd_GetMapList },
{ "playdemo", 1, Cmd_GetDemoList, },
{ "timedemo", 1, Cmd_GetDemoList, },
{ "listdemo", 1, Cmd_GetDemoList, },
{ "playvol", 1, Cmd_GetSoundList },
{ "hpkval", 1, Cmd_GetCustomList },
{ "hpklist", 1, Cmd_GetCustomList },
{ "hpkextract", 1, Cmd_GetCustomList },
{ "entpatch", 1, Cmd_GetMapList },
{ "music", 1, Cmd_GetMusicList, },
{ "movie", 1, Cmd_GetMovieList },
{ "exec", 1, Cmd_GetConfigList },
#if !XASH_DEDICATED
{ "give", 1, Cmd_GetItemsList },
{ "drop", 1, Cmd_GetItemsList }, { "drop", 1, Cmd_GetItemsList },
{ "bind", 1, Cmd_GetKeysList }, { "entpatch", 1, Cmd_GetMapList },
{ "unbind", 1, Cmd_GetKeysList }, { "exec", 1, Cmd_GetConfigList },
{ "bind", 2, Cmd_GetCommandsList },
#endif
{ "game", 1, Cmd_GetGamesList }, { "game", 1, Cmd_GetGamesList },
{ "save", 1, Cmd_GetSavesList }, { "give", 1, Cmd_GetItemsList },
{ "hpkextract", 1, Cmd_GetCustomList },
{ "hpklist", 1, Cmd_GetCustomList },
{ "hpkval", 1, Cmd_GetCustomList },
{ "listdemo", 1, Cmd_GetDemoList, },
{ "load", 1, Cmd_GetSavesList }, { "load", 1, Cmd_GetSavesList },
{ "play", 1, Cmd_GetSoundList },
{ "map", 1, Cmd_GetMapList }, { "map", 1, Cmd_GetMapList },
{ "cd", 1, Cmd_GetCDList }, { "map_background", 1, Cmd_GetMapList },
{ "movie", 1, Cmd_GetMovieList },
{ "mp3", 1, Cmd_GetCDList }, { "mp3", 1, Cmd_GetCDList },
{ "music", 1, Cmd_GetMusicList, },
{ "play", 1, Cmd_GetSoundList },
{ "playdemo", 1, Cmd_GetDemoList, },
{ "playvol", 1, Cmd_GetSoundList },
{ "reset", 1, Cmd_GetCvarsList },
{ "save", 1, Cmd_GetSavesList },
{ "set", 1, Cmd_GetCvarsList },
{ "timedemo", 1, Cmd_GetDemoList },
{ "toggle", 1, Cmd_GetCvarsList },
{ "unbind", 1, Cmd_GetKeysList },
}; };
/* /*
@@ -1160,6 +1203,7 @@ void Con_CompleteCommand( field_t *field )
{ {
field_t temp; field_t temp;
string filename; string filename;
qboolean toggle = false;
qboolean nextcmd; qboolean nextcmd;
int i; int i;
@@ -1194,8 +1238,8 @@ void Con_CompleteCommand( field_t *field )
con.shortestMatch[0] = 0; con.shortestMatch[0] = 0;
// find matching commands and variables // find matching commands and variables
Cmd_LookupCmds( NULL, &con, (setpair_t)Con_AddCommandToList ); Cmd_LookupCmds( &toggle, &con, (setpair_t)Con_AddCommandToList );
Cvar_LookupVars( 0, NULL, &con, (setpair_t)Con_AddCommandToList ); Cvar_LookupVars( 0, &toggle, &con, (setpair_t)Con_AddCommandToList );
if( !con.matchCount ) return; // no matches if( !con.matchCount ) return; // no matches

View File

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

View File

@@ -30,6 +30,8 @@ typedef struct pending_cvar_s
char cv_name[]; char cv_name[];
} pending_cvar_t; } pending_cvar_t;
typedef void (*setpair_t)( const char *key, const void *value, const void *buffer, void *numpairs );
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 );
@@ -52,6 +54,7 @@ void Cvar_Reset( const char *var_name );
void Cvar_SetCheatState( void ); void Cvar_SetCheatState( void );
qboolean Cvar_CommandWithPrivilegeCheck( convar_t *v, qboolean isPrivileged ); qboolean Cvar_CommandWithPrivilegeCheck( convar_t *v, qboolean isPrivileged );
void Cvar_Init( void ); void Cvar_Init( void );
void Cvar_Shutdown( void );
void Cvar_PostFSInit( void ); void Cvar_PostFSInit( void );
void Cvar_Unlink( int group ); void Cvar_Unlink( int group );

View File

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

View File

@@ -1,4 +1,4 @@
/* /*
filesystem.c - game filesystem based on DP fs filesystem.c - game filesystem based on DP fs
Copyright (C) 2003-2006 Mathieu Olivier Copyright (C) 2003-2006 Mathieu Olivier
Copyright (C) 2000-2007 DarkPlaces contributors Copyright (C) 2000-2007 DarkPlaces contributors
@@ -16,11 +16,21 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
*/ */
#if XASH_SDL
#include <SDL.h> // SDL_GetBasePath
#endif
#include <errno.h> #include <errno.h>
#include "common.h" #include "common.h"
#include "library.h" #include "library.h"
#include "platform/platform.h" #include "platform/platform.h"
CVAR_DEFINE_AUTO( fs_mount_hd, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED|FCVAR_LATCH, "mount high definition content folder" );
CVAR_DEFINE_AUTO( fs_mount_lv, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED|FCVAR_LATCH, "mount low violence models content folder" );
CVAR_DEFINE_AUTO( fs_mount_addon, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED|FCVAR_LATCH, "mount addon content folder" );
CVAR_DEFINE_AUTO( fs_mount_l10n, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED|FCVAR_LATCH, "mount localization content folder" );
CVAR_DEFINE_AUTO( ui_language, "english", FCVAR_ARCHIVE|FCVAR_PRIVILEGED|FCVAR_LATCH, "selected game language" );
fs_api_t g_fsapi; fs_api_t g_fsapi;
fs_globals_t *FI; fs_globals_t *FI;
@@ -69,9 +79,23 @@ void *FS_GetNativeObject( const char *obj )
return NULL; return NULL;
} }
static void FS_Rescan_f( void ) void FS_Rescan_f( void )
{ {
FS_Rescan(); uint32_t flags = 0;
// FIXME: VFS shouldn't care about this, allow engine to mount gamedirs
if( fs_mount_lv.value ) SetBits( flags, FS_MOUNT_LV );
if( fs_mount_hd.value ) SetBits( flags, FS_MOUNT_HD );
if( fs_mount_addon.value ) SetBits( flags, FS_MOUNT_ADDON );
if( fs_mount_l10n.value ) SetBits( flags, FS_MOUNT_L10N );
g_fsapi.Rescan( flags, ui_language.string );
ClearBits( fs_mount_lv.flags, FCVAR_CHANGED );
ClearBits( fs_mount_hd.flags, FCVAR_CHANGED );
ClearBits( fs_mount_addon.flags, FCVAR_CHANGED );
ClearBits( fs_mount_l10n.flags, FCVAR_CHANGED );
ClearBits( ui_language.flags, FCVAR_CHANGED );
} }
static void FS_ClearPaths_f( void ) static void FS_ClearPaths_f( void )
@@ -183,14 +207,23 @@ static qboolean FS_DetermineRootDirectory( char *out, size_t size )
#elif XASH_PSVITA #elif XASH_PSVITA
if( PSVita_GetBasePath( out, size )) if( PSVita_GetBasePath( out, size ))
return true; return true;
Sys_Error( "couldn't find Xash3D data directory" ); Sys_Error( "couldn't find %s data directory", XASH_ENGINE_NAME );
return false; return false;
#elif ( XASH_SDL == 2 ) && !XASH_NSWITCH // GetBasePath not impl'd in switch-sdl2 #elif ( XASH_SDL == 2 ) && !XASH_NSWITCH // GetBasePath not impl'd in switch-sdl2
path = SDL_GetBasePath(); path = SDL_GetBasePath();
#if XASH_APPLE
if( path != NULL && Q_stristr( path, ".app" ))
{
SDL_free((void *)path );
path = SDL_GetPrefPath( NULL, XASH_ENGINE_NAME );
}
#endif
if( path != NULL ) if( path != NULL )
{ {
Q_strncpy( out, path, size ); Q_strncpy( out, path, size );
SDL_free(( void *)path ); SDL_free((void *)path );
return true; return true;
} }
@@ -227,6 +260,12 @@ static qboolean FS_DetermineReadOnlyRootDirectory( char *out, size_t size )
return false; return false;
} }
void FS_CheckConfig( void )
{
if( fs_mount_lv.value || fs_mount_hd.value || fs_mount_addon.value || fs_mount_l10n.value )
FS_Rescan_f();
}
/* /*
================ ================
FS_Init FS_Init
@@ -279,6 +318,11 @@ void FS_Init( const char *basedir )
Cmd_AddRestrictedCommand( "fs_clearpaths", FS_ClearPaths_f, "clear filesystem search pathes" ); Cmd_AddRestrictedCommand( "fs_clearpaths", FS_ClearPaths_f, "clear filesystem search pathes" );
Cmd_AddRestrictedCommand( "fs_make_gameinfo", FS_MakeGameInfo_f, "create gameinfo.txt for current running game" ); Cmd_AddRestrictedCommand( "fs_make_gameinfo", FS_MakeGameInfo_f, "create gameinfo.txt for current running game" );
Cvar_RegisterVariable( &fs_mount_hd );
Cvar_RegisterVariable( &fs_mount_lv );
Cvar_RegisterVariable( &fs_mount_addon );
Cvar_RegisterVariable( &fs_mount_l10n );
if( !Sys_GetParmFromCmdLine( "-dll", host.gamedll )) if( !Sys_GetParmFromCmdLine( "-dll", host.gamedll ))
host.gamedll[0] = 0; host.gamedll[0] = 0;

View File

@@ -140,7 +140,8 @@ static void Sys_PrintUsage( const char *exename )
"\nCommon options:\n" "\nCommon options:\n"
O("-dev [level] ", "set log verbosity 0-2") O("-dev [level] ", "set log verbosity 0-2")
O("-log ", "write log to \"engine.log\"") O("-log [file name] ", "write log to \"engine.log\" or [file name] if specified")
O("-logtime ", "enable writing timestamps to the log file")
O("-nowriteconfig ", "disable config save") O("-nowriteconfig ", "disable config save")
O("-noch ", "disable crashhandler") O("-noch ", "disable crashhandler")
#if XASH_WIN32 // !!!! #if XASH_WIN32 // !!!!
@@ -201,7 +202,6 @@ static void Sys_PrintUsage( const char *exename )
O("-daemonize ", "run engine as a daemon") O("-daemonize ", "run engine as a daemon")
#endif #endif
#if XASH_SDL == 2 #if XASH_SDL == 2
O("-sdl_joy_old_api ","use SDL legacy joystick API")
O("-sdl_renderer <n> ","use alternative SDL_Renderer for software") O("-sdl_renderer <n> ","use alternative SDL_Renderer for software")
#endif // XASH_SDL #endif // XASH_SDL
#if XASH_ANDROID && !XASH_SDL #if XASH_ANDROID && !XASH_SDL
@@ -698,17 +698,17 @@ static qboolean Host_Autosleep( double dt, double scale )
static double timewindow; // allocate a time window for sleeps static double timewindow; // allocate a time window for sleeps
static int counter; // for debug static int counter; // for debug
static double realsleeptime; static double realsleeptime;
const double sleeptime = sleep * 0.001; const double sleeptime = sleep * 0.000001;
if( dt < targetframetime * scale ) if( dt < targetframetime * scale )
{ {
// if we have allocated time window, try to sleep // if we have allocated time window, try to sleep
if( timewindow > realsleeptime ) if( timewindow > realsleeptime )
{ {
// Platform_Sleep isn't guaranteed to sleep an exact amount of milliseconds // Platform_Sleep isn't guaranteed to sleep an exact amount of microseconds
// so we measure the real sleep time and use it to decrease the window // so we measure the real sleep time and use it to decrease the window
double t1 = Sys_DoubleTime(), t2; double t1 = Sys_DoubleTime(), t2;
Platform_Sleep( sleep ); // in msec! Platform_NanoSleep( sleep * 1000 ); // in usec!
t2 = Sys_DoubleTime(); t2 = Sys_DoubleTime();
realsleeptime = t2 - t1; realsleeptime = t2 - t1;
@@ -1044,7 +1044,7 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
} }
if( !Sys_CheckParm( "-noch" )) if( !Sys_CheckParm( "-noch" ))
Sys_SetupCrashHandler(); Sys_SetupCrashHandler( argv[0] );
#if XASH_DLL_LOADER #if XASH_DLL_LOADER
host.enabledll = !Sys_CheckParm( "-nodll" ); host.enabledll = !Sys_CheckParm( "-nodll" );
@@ -1131,7 +1131,7 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
#if XASH_DEDICATED #if XASH_DEDICATED
Platform_SetupSigtermHandling(); Platform_SetupSigtermHandling();
#endif #endif
Platform_Init( Host_IsDedicated( ) || developer >= DEV_EXTENDED ); Platform_Init( Host_IsDedicated( ) || developer >= DEV_EXTENDED, basedir );
FS_Init( basedir ); FS_Init( basedir );
Sys_InitLog(); Sys_InitLog();
@@ -1236,6 +1236,14 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
Cvar_Getf( "host_ver", FCVAR_READ_ONLY, "detailed info about this build", "%i " XASH_VERSION " %s %s %s", Q_buildnum(), Q_buildos(), Q_buildarch(), g_buildcommit); Cvar_Getf( "host_ver", FCVAR_READ_ONLY, "detailed info about this build", "%i " XASH_VERSION " %s %s %s", Q_buildnum(), Q_buildos(), Q_buildarch(), g_buildcommit);
Cvar_Getf( "host_lowmemorymode", FCVAR_READ_ONLY, "indicates if engine compiled for low RAM consumption (0 - normal, 1 - low engine limits, 2 - low protocol limits)", "%i", XASH_LOW_MEMORY ); Cvar_Getf( "host_lowmemorymode", FCVAR_READ_ONLY, "indicates if engine compiled for low RAM consumption (0 - normal, 1 - low engine limits, 2 - low protocol limits)", "%i", XASH_LOW_MEMORY );
Cvar_Get( "host_hl25_extended_structs",
#if SUPPORT_HL25_EXTENDED_STRUCTS
"1",
#else
"0",
#endif
FCVAR_READ_ONLY, "indicates if engine was compiled with extended msurface_t struct" );
Mod_Init(); Mod_Init();
NET_Init(); NET_Init();
NET_InitMasters(); NET_InitMasters();
@@ -1256,7 +1264,6 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
CL_Init(); CL_Init();
HTTP_Init(); HTTP_Init();
ID_Init();
SoundList_Init(); SoundList_Init();
if( Host_IsDedicated( )) if( Host_IsDedicated( ))
@@ -1312,6 +1319,7 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
Cmd_RemoveCommand( "setgl" ); Cmd_RemoveCommand( "setgl" );
Cbuf_ExecStuffCmds(); // execute stuffcmds (commandline) Cbuf_ExecStuffCmds(); // execute stuffcmds (commandline)
SCR_CheckStartupVids(); // must be last SCR_CheckStartupVids(); // must be last
FS_CheckConfig();
if( Sys_GetParmFromCmdLine( "-timedemo", demoname )) if( Sys_GetParmFromCmdLine( "-timedemo", demoname ))
Cbuf_AddTextf( "timedemo %s\n", demoname ); Cbuf_AddTextf( "timedemo %s\n", demoname );
@@ -1400,6 +1408,10 @@ void Host_ShutdownWithReason( const char *reason )
Host_FreeCommon(); Host_FreeCommon();
Platform_Shutdown(); Platform_Shutdown();
BaseCmd_Shutdown();
Cmd_Shutdown();
Cvar_Shutdown();
// must be last, console uses this // must be last, console uses this
Mem_FreePool( &host.mempool ); Mem_FreePool( &host.mempool );

View File

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

View File

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

View File

@@ -419,14 +419,21 @@ void NET_InitMasters( void )
Cvar_RegisterVariable( &sv_verbose_heartbeats ); Cvar_RegisterVariable( &sv_verbose_heartbeats );
// keep main master always there { // IPv4-only
NET_AddMaster( MASTERSERVER_ADR, false, false ); NET_AddMaster( "mentality.rip:27010", false, false );
NET_AddMaster( "mentality.rip:27011", false, false ); // testing server, might be offline NET_AddMaster( "ms2.mentality.rip:27010", false, false );
NET_AddMaster( "ms2.mentality.rip:27010", false, false ); // secondary master NET_AddMaster( "ms3.mentality.rip:27010", false, false );
}
NET_AddMaster( "aaaa.mentality.rip:27010", false, true ); // IPv6-only { // IPv6-only
NET_AddMaster( "aaaa.mentality.rip:27011", false, true ); // IPv6-only, testing server, might be offline NET_AddMaster( "aaaa.mentality.rip:27010", false, true );
NET_AddMaster( "aaaa.ms2.mentality.rip:27010", false, false ); // secondary IPv6-only master NET_AddMaster( "aaaa.ms2.mentality.rip:27010", false, true );
}
{ // testing servers, might be offline
NET_AddMaster( "mentality.rip:27011", false, false );
NET_AddMaster( "aaaa.mentality.rip:27011", false, true );
}
NET_LoadMasters( ); NET_LoadMasters( );
} }

View File

@@ -482,7 +482,7 @@ static int Mod_LoadTextureFromWadList( wadlist_t *list, const char *name, rgbdat
return -1; return -1;
} }
static fs_offset_t Mod_CalculateMipTexSize( mip_t *mt, qboolean palette ) static fs_offset_t Mod_CalculateMipTexSize( const mip_t *mt, qboolean palette )
{ {
if( !mt ) if( !mt )
return 0; return 0;
@@ -2359,7 +2359,7 @@ static qboolean Mod_SearchForTextureReplacement( char *out, size_t size, const c
return false; return false;
} }
static void Mod_InitSkyClouds( model_t *mod, mip_t *mt, texture_t *tx, qboolean custom_palette ) static void Mod_InitSkyClouds( model_t *mod, const mip_t *mt, texture_t *tx, qboolean custom_palette )
{ {
#if !XASH_DEDICATED #if !XASH_DEDICATED
rgbdata_t r_temp, *r_sky; rgbdata_t r_temp, *r_sky;
@@ -2516,9 +2516,6 @@ done:
static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureIndex ) static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureIndex )
{ {
texture_t *texture = NULL;
mip_t *mipTex = NULL;
qboolean usesCustomPalette = false;
uint32_t txFlags = 0; uint32_t txFlags = 0;
char texpath[MAX_VA_STRING]; char texpath[MAX_VA_STRING];
char safemtname[16]; // only for external textures char safemtname[16]; // only for external textures
@@ -2526,12 +2523,10 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
// don't load texture data on dedicated server, as there is no renderer. // don't load texture data on dedicated server, as there is no renderer.
// but count the wadusage for automatic precache // but count the wadusage for automatic precache
// texture_t *texture = mod->textures[textureIndex];
// FIXME: for ENGINE_IMPROVED_LINETRACE we need to load textures on server too const mip_t *mipTex = Mod_GetMipTexForTexture( bmod, textureIndex );
// but there is no facility for this yet const qboolean usesCustomPalette = Mod_CalcMipTexUsesCustomPalette( mod, bmod, textureIndex );
texture = mod->textures[textureIndex]; const qboolean iswater = Mod_LooksLikeWaterTexture( mipTex->name );
mipTex = Mod_GetMipTexForTexture( bmod, textureIndex );
usesCustomPalette = Mod_CalcMipTexUsesCustomPalette( mod, bmod, textureIndex );
// check for multi-layered sky texture (quake1 specific) // check for multi-layered sky texture (quake1 specific)
if( bmod->isworld && Q_strncmp( mipTex->name, "sky", 3 ) == 0 && ( mipTex->width / mipTex->height ) == 2 ) if( bmod->isworld && Q_strncmp( mipTex->name, "sky", 3 ) == 0 && ( mipTex->width / mipTex->height ) == 2 )
@@ -2540,11 +2535,13 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
return; return;
} }
// FIXME: for ENGINE_IMPROVED_LINETRACE we need to load textures on server too
// but there is no facility for this yet
if( FBitSet( host.features, ENGINE_IMPROVED_LINETRACE ) && mipTex->name[0] == '{' ) if( FBitSet( host.features, ENGINE_IMPROVED_LINETRACE ) && mipTex->name[0] == '{' )
SetBits( txFlags, TF_KEEP_SOURCE ); // Paranoia2 texture alpha-tracing SetBits( txFlags, TF_KEEP_SOURCE ); // Paranoia2 texture alpha-tracing
// check if this is water to keep the source texture and expand it to RGBA (so ripple effect works) // check if this is water to keep the source texture and expand it to RGBA (so ripple effect works)
if( Mod_LooksLikeWaterTexture( mipTex->name )) if( iswater )
SetBits( txFlags, TF_KEEP_SOURCE | TF_EXPAND_SOURCE ); SetBits( txFlags, TF_KEEP_SOURCE | TF_EXPAND_SOURCE );
// Texture loading order: // Texture loading order:
@@ -2609,8 +2606,13 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
texture->gl_texturenum = R_GetBuiltinTexture( REF_DEFAULT_TEXTURE ); texture->gl_texturenum = R_GetBuiltinTexture( REF_DEFAULT_TEXTURE );
} }
// Check for luma texture
texture->fb_texturenum = 0; texture->fb_texturenum = 0;
// Check for luma texture
// a1ba: ignore for water because fb_texturenum will be used to store ripple texture
if( iswater )
return;
if( load_external ) // external textures will not have TF_HAS_LUMA flag because it set only from WAD images loader if( load_external ) // external textures will not have TF_HAS_LUMA flag because it set only from WAD images loader
{ {
if( Mod_SearchForTextureReplacement( texpath, sizeof( texpath ), mod->name, safemtname, "_luma" )) if( Mod_SearchForTextureReplacement( texpath, sizeof( texpath ), mod->name, safemtname, "_luma" ))

View File

@@ -382,8 +382,7 @@ static void Mod_StudioCalcRotations( int boneused[], int numbones, const byte *p
for( j = numbones - 1; j >= 0; j-- ) for( j = numbones - 1; j >= 0; j-- )
{ {
i = boneused[j]; i = boneused[j];
R_StudioCalcBoneQuaternion( frame, s, &pbone[i], &panim[i], adj, q[i] ); R_StudioCalcBones( frame, s, &pbone[i], &panim[i], adj, pos[i], q[i] );
R_StudioCalcBonePosition( frame, s, &pbone[i], &panim[i], adj, pos[i] );
} }
if( pseqdesc->motiontype & STUDIO_X ) pos[pseqdesc->motionbone][0] = 0.0f; if( pseqdesc->motiontype & STUDIO_X ) pos[pseqdesc->motionbone][0] = 0.0f;
@@ -724,7 +723,7 @@ void Mod_StudioComputeBounds( void *buffer, vec3_t mins, vec3_t maxs, qboolean i
{ {
for( k = 0; k < pseqdesc->numframes; k++ ) for( k = 0; k < pseqdesc->numframes; k++ )
{ {
R_StudioCalcBonePosition( k, 0, &pbones[j], panim, NULL, pos ); R_StudioCalcBones( k, 0, &pbones[j], panim, NULL, pos, NULL );
Mod_StudioBoundVertex( vert_mins, vert_maxs, &bone_count, pos ); Mod_StudioBoundVertex( vert_mins, vert_maxs, &bone_count, pos );
} }
} }
@@ -868,7 +867,7 @@ void Mod_LoadStudioModel( model_t *mod, const void *buffer, qboolean *loaded )
mod->type = mod_studio; mod->type = mod_studio;
phdr = R_StudioLoadHeader( mod, buffer ); phdr = R_StudioLoadHeader( mod, buffer );
if( !phdr ) if( !phdr || phdr->length < sizeof( studiohdr_t )) // garbage value in length
return; // bad model return; // bad model
#if !XASH_DEDICATED #if !XASH_DEDICATED

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -505,11 +505,14 @@ static int HTTP_FileDecompress( httpfile_t *file )
if( zlib_result == Z_OK || zlib_result == Z_STREAM_END ) if( zlib_result == Z_OK || zlib_result == Z_STREAM_END )
{ {
Mem_Free( data_in ); g_fsapi.WriteFile( name, data_out, decompressed_len );
HTTP_FreeFile( file, false );
} }
else HTTP_FreeFile( file, true );
Mem_Free( data_in );
Mem_Free( data_out );
g_fsapi.WriteFile( name, data_out, decompressed_len );
HTTP_FreeFile( file, false );
return 1; return 1;
} }
@@ -841,7 +844,16 @@ static int HTTP_FileProcessStream( httpfile_t *curfile )
if( curfile->downloaded >= curfile->size ) if( curfile->downloaded >= curfile->size )
{ {
HTTP_FreeFile( curfile, false ); // success // chunked files are finalized in FileSaveReceivedData
if( curfile->compressed && !curfile->chunked )
{
curfile->pfn_process = HTTP_FileDecompress;
curfile->success = true;
}
else
{
HTTP_FreeFile( curfile, false ); // success
}
return 0; return 0;
} }
} }

View File

@@ -151,17 +151,24 @@ static inline qboolean NET_IsSocketValid( int socket )
void NET_NetadrToIP6Bytes( uint8_t *ip6, const netadr_t *adr ) void NET_NetadrToIP6Bytes( uint8_t *ip6, const netadr_t *adr )
{ {
memcpy( ip6, adr->ip6, sizeof( adr->ip6 )); memcpy( &ip6[0], adr->ip6_0, 2 );
memcpy( &ip6[2], adr->ip6_1, 14 );
} }
void NET_IP6BytesToNetadr( netadr_t *adr, const uint8_t *ip6 ) void NET_IP6BytesToNetadr( netadr_t *adr, const uint8_t *ip6 )
{ {
memcpy( adr->ip6, ip6, sizeof( adr->ip6 )); memcpy( adr->ip6_0, &ip6[0], 2 );
memcpy( adr->ip6_1, &ip6[2], 14 );
} }
static int NET_NetadrIP6Compare( const netadr_t *a, const netadr_t *b ) static int NET_NetadrIP6Compare( const netadr_t *a, const netadr_t *b )
{ {
return memcmp( a->ip6, b->ip6, sizeof( a->ip6 )); uint8_t ip6_a[16], ip6_b[16];
NET_NetadrToIP6Bytes( ip6_a, a );
NET_NetadrToIP6Bytes( ip6_b, b );
return memcmp( ip6_a, ip6_b, sizeof( ip6_a ));
} }
/* /*
@@ -171,27 +178,29 @@ NET_NetadrToSockadr
*/ */
static void NET_NetadrToSockadr( netadr_t *a, struct sockaddr_storage *s ) static void NET_NetadrToSockadr( netadr_t *a, struct sockaddr_storage *s )
{ {
netadrtype_t type = NET_NetadrType( a );
memset( s, 0, sizeof( *s )); memset( s, 0, sizeof( *s ));
if( a->type == NA_BROADCAST ) if( type == NA_BROADCAST )
{ {
s->ss_family = AF_INET; s->ss_family = AF_INET;
((struct sockaddr_in *)s)->sin_port = a->port; ((struct sockaddr_in *)s)->sin_port = a->port;
((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST; ((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST;
} }
else if( a->type == NA_IP ) else if( type == NA_IP )
{ {
s->ss_family = AF_INET; s->ss_family = AF_INET;
((struct sockaddr_in *)s)->sin_port = a->port; ((struct sockaddr_in *)s)->sin_port = a->port;
((struct sockaddr_in *)s)->sin_addr.s_addr = a->ip4; ((struct sockaddr_in *)s)->sin_addr.s_addr = a->ip4;
} }
else if( a->type6 == NA_IP6 ) else if( type == NA_IP6 )
{ {
s->ss_family = AF_INET6; s->ss_family = AF_INET6;
((struct sockaddr_in6 *)s)->sin6_port = a->port; ((struct sockaddr_in6 *)s)->sin6_port = a->port;
NET_NetadrToIP6Bytes(((struct sockaddr_in6 *)s)->sin6_addr.s6_addr, a ); NET_NetadrToIP6Bytes(((struct sockaddr_in6 *)s)->sin6_addr.s6_addr, a );
} }
else if( a->type6 == NA_MULTICAST_IP6 ) else if( type == NA_MULTICAST_IP6 )
{ {
s->ss_family = AF_INET6; s->ss_family = AF_INET6;
((struct sockaddr_in6 *)s)->sin6_port = a->port; ((struct sockaddr_in6 *)s)->sin6_port = a->port;
@@ -208,13 +217,13 @@ static void NET_SockadrToNetadr( const struct sockaddr_storage *s, netadr_t *a )
{ {
if( s->ss_family == AF_INET ) if( s->ss_family == AF_INET )
{ {
a->type = NA_IP; NET_NetadrSetType( a, NA_IP );
a->ip4 = ((struct sockaddr_in *)s)->sin_addr.s_addr; a->ip4 = ((struct sockaddr_in *)s)->sin_addr.s_addr;
a->port = ((struct sockaddr_in *)s)->sin_port; a->port = ((struct sockaddr_in *)s)->sin_port;
} }
else if( s->ss_family == AF_INET6 ) else if( s->ss_family == AF_INET6 )
{ {
a->type6 = NA_IP6; NET_NetadrSetType( a, NA_IP6 );
NET_IP6BytesToNetadr( a, ((struct sockaddr_in6 *)s)->sin6_addr.s6_addr ); NET_IP6BytesToNetadr( a, ((struct sockaddr_in6 *)s)->sin6_addr.s6_addr );
a->port = ((struct sockaddr_in6 *)s)->sin6_port; a->port = ((struct sockaddr_in6 *)s)->sin6_port;
} }
@@ -549,8 +558,8 @@ qboolean NET_StringToFilterAdr( const char *s, netadr_t *adr, uint *prefixlen )
// try to parse as IPv6 first // try to parse as IPv6 first
if( ParseIPv6Addr( copy, ip6, NULL, NULL )) if( ParseIPv6Addr( copy, ip6, NULL, NULL ))
{ {
NET_NetadrSetType( adr, NA_IP6 );
NET_IP6BytesToNetadr( adr, ip6 ); NET_IP6BytesToNetadr( adr, ip6 );
adr->type6 = NA_IP6;
if( !hasCIDR ) if( !hasCIDR )
*prefixlen = 128; *prefixlen = 128;
@@ -620,7 +629,7 @@ qboolean NET_StringToFilterAdr( const char *s, netadr_t *adr, uint *prefixlen )
adr->ip4 = ntohl( mask ); adr->ip4 = ntohl( mask );
} }
adr->type = NA_IP; NET_NetadrSetType( adr, NA_IP );
} }
return true; return true;
@@ -634,10 +643,11 @@ NET_AdrToString
const char *NET_AdrToString( const netadr_t a ) const char *NET_AdrToString( const netadr_t a )
{ {
static char s[64]; static char s[64];
netadrtype_t type = NET_NetadrType( &a );
if( a.type == NA_LOOPBACK ) if( type == NA_LOOPBACK )
return "loopback"; return "loopback";
if( a.type6 == NA_IP6 || a.type6 == NA_MULTICAST_IP6 ) if( type == NA_IP6 || type == NA_MULTICAST_IP6 )
{ {
uint8_t ip6[16]; uint8_t ip6[16];
@@ -661,10 +671,11 @@ NET_BaseAdrToString
const char *NET_BaseAdrToString( const netadr_t a ) const char *NET_BaseAdrToString( const netadr_t a )
{ {
static char s[64]; static char s[64];
netadrtype_t type = NET_NetadrType( &a );
if( a.type == NA_LOOPBACK ) if( type == NA_LOOPBACK )
return "loopback"; return "loopback";
if( a.type6 == NA_IP6 || a.type6 == NA_MULTICAST_IP6 ) if( type == NA_IP6 || type == NA_MULTICAST_IP6 )
{ {
uint8_t ip6[16]; uint8_t ip6[16];
@@ -689,16 +700,19 @@ Compares without the port
*/ */
qboolean NET_CompareBaseAdr( const netadr_t a, const netadr_t b ) qboolean NET_CompareBaseAdr( const netadr_t a, const netadr_t b )
{ {
if( a.type6 != b.type6 ) netadrtype_t type_a = NET_NetadrType( &a );
netadrtype_t type_b = NET_NetadrType( &b );
if( type_a != type_b )
return false; return false;
if( a.type == NA_LOOPBACK ) if( type_a == NA_LOOPBACK )
return true; return true;
if( a.type == NA_IP ) if( type_a == NA_IP )
return a.ip4 == b.ip4; return a.ip4 == b.ip4;
if( a.type6 == NA_IP6 ) if( type_a == NA_IP6 )
{ {
if( !NET_NetadrIP6Compare( &a, &b )) if( !NET_NetadrIP6Compare( &a, &b ))
return true; return true;
@@ -707,36 +721,6 @@ qboolean NET_CompareBaseAdr( const netadr_t a, const netadr_t b )
return false; return false;
} }
/*
====================
NET_CompareClassBAdr
Compare local masks
====================
*/
qboolean NET_CompareClassBAdr( const netadr_t a, const netadr_t b )
{
if( a.type6 != b.type6 )
return false;
if( a.type == NA_LOOPBACK )
return true;
if( a.type == NA_IP )
{
if( a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] )
return true;
}
// NOTE: we don't check for IPv6 here
// this check is very dumb and only used for LAN restriction
// Actual check is in IsReservedAdr
// for real mask compare use NET_CompareAdrByMask
return false;
}
/* /*
==================== ====================
NET_CompareAdrByMask NET_CompareAdrByMask
@@ -746,10 +730,13 @@ Checks if adr is a part of subnet
*/ */
qboolean NET_CompareAdrByMask( const netadr_t a, const netadr_t b, uint prefixlen ) qboolean NET_CompareAdrByMask( const netadr_t a, const netadr_t b, uint prefixlen )
{ {
if( a.type6 != b.type6 || a.type == NA_LOOPBACK ) netadrtype_t type_a = NET_NetadrType( &a );
netadrtype_t type_b = NET_NetadrType( &b );
if( type_a != type_b || type_a == NA_LOOPBACK )
return false; return false;
if( a.type == NA_IP ) if( type_a == NA_IP )
{ {
uint32_t ipa = htonl( a.ip4 ); uint32_t ipa = htonl( a.ip4 );
uint32_t ipb = htonl( b.ip4 ); uint32_t ipb = htonl( b.ip4 );
@@ -757,7 +744,7 @@ qboolean NET_CompareAdrByMask( const netadr_t a, const netadr_t b, uint prefixle
if(( ipa & (( 0xFFFFFFFFU ) << ( 32 - prefixlen ))) == ipb ) if(( ipa & (( 0xFFFFFFFFU ) << ( 32 - prefixlen ))) == ipb )
return true; return true;
} }
else if( a.type6 == NA_IP6 ) else if( type_a == NA_IP6 )
{ {
uint16_t a_[8], b_[8]; uint16_t a_[8], b_[8];
size_t check = prefixlen / 16; size_t check = prefixlen / 16;
@@ -798,11 +785,13 @@ Check for reserved ip's
*/ */
qboolean NET_IsReservedAdr( netadr_t a ) qboolean NET_IsReservedAdr( netadr_t a )
{ {
if( a.type == NA_LOOPBACK ) netadrtype_t type_a = NET_NetadrType( &a );
if( type_a == NA_LOOPBACK )
return true; return true;
// Following checks was imported from GameNetworkingSockets library // Following checks was imported from GameNetworkingSockets library
if( a.type == NA_IP ) if( type_a == NA_IP )
{ {
if(( a.ip[0] == 10 ) || // 10.x.x.x is reserved if(( a.ip[0] == 10 ) || // 10.x.x.x is reserved
( a.ip[0] == 127 ) || // 127.x.x.x ( a.ip[0] == 127 ) || // 127.x.x.x
@@ -814,7 +803,7 @@ qboolean NET_IsReservedAdr( netadr_t a )
} }
} }
if( a.type6 == NA_IP6 ) if( type_a == NA_IP6 )
{ {
uint8_t ip6[16]; uint8_t ip6[16];
@@ -847,20 +836,23 @@ Compare full address
*/ */
qboolean NET_CompareAdr( const netadr_t a, const netadr_t b ) qboolean NET_CompareAdr( const netadr_t a, const netadr_t b )
{ {
if( a.type6 != b.type6 ) netadrtype_t type_a = NET_NetadrType( &a );
netadrtype_t type_b = NET_NetadrType( &b );
if( type_a != type_b )
return false; return false;
if( a.type == NA_LOOPBACK ) if( type_a == NA_LOOPBACK )
return true; return true;
if( a.type == NA_IP ) if( type_a == NA_IP )
{ {
if( a.ip4 == b.ip4 && a.port == b.port ) if( a.ip4 == b.ip4 && a.port == b.port )
return true; return true;
return false; return false;
} }
if( a.type6 == NA_IP6 ) if( type_a == NA_IP6 )
{ {
if( a.port == b.port && !NET_NetadrIP6Compare( &a, &b )) if( a.port == b.port && !NET_NetadrIP6Compare( &a, &b ))
return true; return true;
@@ -883,9 +875,13 @@ int NET_CompareAdrSort( const void *_a, const void *_b )
{ {
const netadr_t *a = _a, *b = _b; const netadr_t *a = _a, *b = _b;
int porta, portb, portdiff, addrdiff; int porta, portb, portdiff, addrdiff;
netadrtype_t type_a, type_b;
if( a->type6 != b->type6 ) type_a = NET_NetadrType( a );
return bound( -1, (int)a->type6 - (int)b->type6, 1 ); type_b = NET_NetadrType( b );
if( type_a != type_b )
return bound( -1, (int)type_a - (int)type_b, 1 );
porta = ntohs( a->port ); porta = ntohs( a->port );
portb = ntohs( b->port ); portb = ntohs( b->port );
@@ -896,7 +892,7 @@ int NET_CompareAdrSort( const void *_a, const void *_b )
else else
portdiff = 0; portdiff = 0;
switch( a->type6 ) switch( type_a )
{ {
case NA_IP6: case NA_IP6:
if(( addrdiff = NET_NetadrIP6Compare( a, b ))) if(( addrdiff = NET_NetadrIP6Compare( a, b )))
@@ -904,14 +900,7 @@ int NET_CompareAdrSort( const void *_a, const void *_b )
// fallthrough // fallthrough
case NA_MULTICAST_IP6: case NA_MULTICAST_IP6:
return portdiff; return portdiff;
}
// don't check for full type earlier, as it's value depends on v6 address
if( a->type != b->type )
return bound( -1, (int)a->type - (int)b->type, 1 );
switch( a->type )
{
case NA_IP: case NA_IP:
if(( addrdiff = memcmp( a->ip, b->ip, sizeof( a->ipx )))) if(( addrdiff = memcmp( a->ip, b->ip, sizeof( a->ipx ))))
return addrdiff; return addrdiff;
@@ -946,7 +935,7 @@ static qboolean NET_StringToAdrEx( const char *string, netadr_t *adr, int family
if( !Q_stricmp( string, "localhost" ) || !Q_stricmp( string, "loopback" )) if( !Q_stricmp( string, "localhost" ) || !Q_stricmp( string, "loopback" ))
{ {
adr->type = NA_LOOPBACK; NET_NetadrSetType( adr, NA_LOOPBACK );
return true; return true;
} }
@@ -971,7 +960,7 @@ net_gai_state_t NET_StringToAdrNB( const char *string, netadr_t *adr, qboolean v
if( !Q_stricmp( string, "localhost" ) || !Q_stricmp( string, "loopback" )) if( !Q_stricmp( string, "localhost" ) || !Q_stricmp( string, "loopback" ))
{ {
adr->type = NA_LOOPBACK; NET_NetadrSetType( adr, NA_LOOPBACK );
return NET_EAI_OK; return NET_EAI_OK;
} }
@@ -1017,7 +1006,7 @@ static qboolean NET_GetLoopPacket( netsrc_t sock, netadr_t *from, byte *data, si
*length = loop->msgs[i].datalen; *length = loop->msgs[i].datalen;
memset( from, 0, sizeof( *from )); memset( from, 0, sizeof( *from ));
from->type = NA_LOOPBACK; NET_NetadrSetType( from, NA_LOOPBACK );
return true; return true;
} }
@@ -1523,7 +1512,7 @@ static int NET_SendLong( netsrc_t sock, int net_socket, const char *buf, size_t
total_sent += size; total_sent += size;
len -= size; len -= size;
packet_number++; packet_number++;
Platform_Sleep( 1 ); Platform_NanoSleep( 100 * 1000 );
} }
return total_sent; return total_sent;
@@ -1546,19 +1535,20 @@ void NET_SendPacketEx( netsrc_t sock, size_t length, const void *data, netadr_t
int ret; int ret;
struct sockaddr_storage addr = { 0 }; struct sockaddr_storage addr = { 0 };
SOCKET net_socket = 0; SOCKET net_socket = 0;
netadrtype_t type = NET_NetadrType( &to );
if( !net.initialized || to.type == NA_LOOPBACK ) if( !net.initialized || type == NA_LOOPBACK )
{ {
NET_SendLoopPacket( sock, length, data, to ); NET_SendLoopPacket( sock, length, data, to );
return; return;
} }
else if( to.type == NA_BROADCAST || to.type == NA_IP ) else if( type == NA_BROADCAST || type == NA_IP )
{ {
net_socket = net.ip_sockets[sock]; net_socket = net.ip_sockets[sock];
if( !NET_IsSocketValid( net_socket )) if( !NET_IsSocketValid( net_socket ))
return; return;
} }
else if( to.type6 == NA_MULTICAST_IP6 || to.type6 == NA_IP6 ) else if( type == NA_MULTICAST_IP6 || type == NA_IP6 )
{ {
net_socket = net.ip6_sockets[sock]; net_socket = net.ip6_sockets[sock];
if( !NET_IsSocketValid( net_socket )) if( !NET_IsSocketValid( net_socket ))
@@ -1566,7 +1556,7 @@ void NET_SendPacketEx( netsrc_t sock, size_t length, const void *data, netadr_t
} }
else else
{ {
Host_Error( "%s: bad address type %i (%i)\n", __func__, to.type, to.type6 ); Host_Error( "%s: bad address type %i (%i, %i)\n", __func__, to.type, to.ip6_0[0], to.ip6_0[1] );
} }
NET_NetadrToSockadr( &to, &addr ); NET_NetadrToSockadr( &to, &addr );
@@ -1582,7 +1572,7 @@ void NET_SendPacketEx( netsrc_t sock, size_t length, const void *data, netadr_t
return; return;
// some PPP links don't allow broadcasts // some PPP links don't allow broadcasts
if( err == WSAEADDRNOTAVAIL && ( to.type == NA_BROADCAST || to.type6 == NA_MULTICAST_IP6 )) if( err == WSAEADDRNOTAVAIL && ( type == NA_BROADCAST || type == NA_MULTICAST_IP6 ))
return; return;
if( Host_IsDedicated( )) if( Host_IsDedicated( ))
@@ -2037,6 +2027,7 @@ void NET_Init( void )
Cvar_RegisterVariable( &net_fakelag ); Cvar_RegisterVariable( &net_fakelag );
Cvar_RegisterVariable( &net_fakeloss ); Cvar_RegisterVariable( &net_fakeloss );
Cvar_RegisterVariable( &net_resolve_debug ); Cvar_RegisterVariable( &net_resolve_debug );
Cvar_RegisterVariable( &net_clockwindow );
Q_snprintf( cmd, sizeof( cmd ), "%i", PORT_SERVER ); Q_snprintf( cmd, sizeof( cmd ), "%i", PORT_SERVER );
Cvar_FullSet( "hostport", cmd, FCVAR_READ_ONLY ); Cvar_FullSet( "hostport", cmd, FCVAR_READ_ONLY );

View File

@@ -64,7 +64,6 @@ void NET_Config( qboolean net_enable, qboolean changeport );
const char *NET_AdrToString( const netadr_t a ) RETURNS_NONNULL; const char *NET_AdrToString( const netadr_t a ) RETURNS_NONNULL;
const char *NET_BaseAdrToString( const netadr_t a ) RETURNS_NONNULL; const char *NET_BaseAdrToString( const netadr_t a ) RETURNS_NONNULL;
qboolean NET_IsReservedAdr( netadr_t a ); qboolean NET_IsReservedAdr( netadr_t a );
qboolean NET_CompareClassBAdr( const netadr_t a, const netadr_t b );
qboolean NET_StringToAdr( const char *string, netadr_t *adr ); qboolean NET_StringToAdr( const char *string, netadr_t *adr );
qboolean NET_StringToFilterAdr( const char *s, netadr_t *adr, uint *prefixlen ); qboolean NET_StringToFilterAdr( const char *s, netadr_t *adr, uint *prefixlen );
net_gai_state_t NET_StringToAdrNB( const char *string, netadr_t *adr, qboolean v6only ); net_gai_state_t NET_StringToAdrNB( const char *string, netadr_t *adr, qboolean v6only );
@@ -80,7 +79,7 @@ void NET_NetadrToIP6Bytes( uint8_t *ip6, const netadr_t *adr );
static inline qboolean NET_IsLocalAddress( netadr_t adr ) static inline qboolean NET_IsLocalAddress( netadr_t adr )
{ {
return adr.type == NA_LOOPBACK ? true : false; return NET_NetadrType( &adr ) == NA_LOOPBACK;
} }
#if !XASH_DEDICATED #if !XASH_DEDICATED

View File

@@ -69,7 +69,6 @@ GNU General Public License for more details.
// bytes will be stripped by the networking channel layer // bytes will be stripped by the networking channel layer
#define NET_MAX_MESSAGE PAD_NUMBER(( NET_MAX_PAYLOAD + HEADER_BYTES ), 16 ) #define NET_MAX_MESSAGE PAD_NUMBER(( NET_MAX_PAYLOAD + HEADER_BYTES ), 16 )
#define MASTERSERVER_ADR "mentality.rip:27010"
#define MS_SCAN_REQUEST "1\xFF" "0.0.0.0:0\0" #define MS_SCAN_REQUEST "1\xFF" "0.0.0.0:0\0"
#define PORT_MASTER 27010 #define PORT_MASTER 27010
@@ -214,6 +213,7 @@ typedef enum netchan_flags_e
NETCHAN_USE_MUNGE = BIT( 1 ), NETCHAN_USE_MUNGE = BIT( 1 ),
NETCHAN_USE_BZIP2 = BIT( 2 ), NETCHAN_USE_BZIP2 = BIT( 2 ),
NETCHAN_GOLDSRC = BIT( 3 ), NETCHAN_GOLDSRC = BIT( 3 ),
NETCHAN_USE_LZSS = BIT( 4 ), // mutually exclusive with bzip2
} netchan_flags_t; } netchan_flags_t;
// Network Connection Channel // Network Connection Channel
@@ -285,6 +285,7 @@ typedef struct netchan_s
qboolean split; qboolean split;
qboolean use_munge; qboolean use_munge;
qboolean use_bz2; qboolean use_bz2;
qboolean use_lzss;
qboolean gs_netchan; qboolean gs_netchan;
} netchan_t; } netchan_t;

View File

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

View File

@@ -31,15 +31,14 @@ GNU General Public License for more details.
#define XASH_COLORIZE_CONSOLE 0 #define XASH_COLORIZE_CONSOLE 0
#endif #endif
typedef struct { static struct logdata_s {
char title[64]; char title[64];
qboolean log_active; qboolean log_active;
char log_path[MAX_SYSPATH]; qboolean log_time;
FILE *logfile; char log_path[MAX_SYSPATH];
int logfileno; FILE *logfile;
} LogData; int logfileno;
} s_ld;
static LogData s_ld;
void Sys_DestroyConsole( void ) void Sys_DestroyConsole( void )
{ {
@@ -78,14 +77,19 @@ static void Sys_FlushLogfile( void )
void Sys_InitLog( void ) void Sys_InitLog( void )
{ {
const char *mode; const char *mode;
if( Sys_CheckParm( "-log" ) && host.allow_console != 0 ) if( Sys_CheckParm( "-log" ))
{ {
if( !Sys_GetParmFromCmdLine( "-log", s_ld.log_path ) || !isalnum( s_ld.log_path[0] ))
Q_strncpy( s_ld.log_path, "engine.log", sizeof( s_ld.log_path ));
COM_DefaultExtension( s_ld.log_path, ".log", sizeof( s_ld.log_path ));
s_ld.log_active = true; s_ld.log_active = true;
Q_strncpy( s_ld.log_path, "engine.log", sizeof( s_ld.log_path ));
} }
s_ld.log_time = Sys_CheckParm( "-logtime" );
if( host.change_game && host.type != HOST_DEDICATED ) if( host.change_game && host.type != HOST_DEDICATED )
mode = "a"; mode = "a";
else mode = "w"; else mode = "w";
@@ -101,7 +105,7 @@ void Sys_InitLog( void )
if ( !s_ld.logfile ) if ( !s_ld.logfile )
{ {
Con_Reportf( S_ERROR "Sys_InitLog: can't create log file %s: %s\n", s_ld.log_path, strerror( errno )); Con_Reportf( S_ERROR "%s: can't create log file %s: %s\n", __func__, s_ld.log_path, strerror( errno ));
return; return;
} }
@@ -295,17 +299,23 @@ void Sys_PrintLog( const char *pMsg )
// save last char to detect when line was not ended // save last char to detect when line was not ended
lastchar = len > 0 ? pMsg[len - 1] : 0; lastchar = len > 0 ? pMsg[len - 1] : 0;
if( !s_ld.logfile ) // spew to engine.log
return; if( s_ld.logfile )
if( print_time )
{ {
logtime_len = strftime( logtime, sizeof( logtime ), "[%Y:%m:%d|%H:%M:%S] ", crt_tm ); //full time if( s_ld.log_time && print_time )
logtime_len = Q_min( logtime_len, sizeof( logtime ) - 1 ); // just in case {
} logtime_len = strftime( logtime, sizeof( logtime ), "[%Y:%m:%d|%H:%M:%S] ", crt_tm ); //full time
logtime_len = Q_min( logtime_len, sizeof( logtime ) - 1 ); // just in case
}
else
{
logtime[0] = '\0';
logtime_len = 0;
}
Sys_PrintLogfile( s_ld.logfileno, logtime, logtime_len, pMsg, false ); Sys_PrintLogfile( s_ld.logfileno, logtime, logtime_len, pMsg, false );
Sys_FlushLogfile(); Sys_FlushLogfile();
}
} }
/* /*

View File

@@ -41,6 +41,15 @@ NOTE: never change this structure because all dll descriptions in xash code
writes into struct by offsets not names writes into struct by offsets not names
======================================================================== ========================================================================
*/ */
typedef struct dll_info_s
{
const char *name; // name of library
const dllfunc_t *fcts; // list of dll exports
const size_t num_fcts;
qboolean crash; // crash if dll not found
void *link; // hinstance of loading library
} dll_info_t;
extern int error_on_exit; extern int error_on_exit;
double Sys_DoubleTime( void ); double Sys_DoubleTime( void );
char *Sys_GetClipboardData( void ); char *Sys_GetClipboardData( void );

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -142,17 +142,10 @@ static qboolean vsync;
void GL_UpdateSwapInterval( void ) void GL_UpdateSwapInterval( void )
{ {
// disable VSync while level is loading if( FBitSet( gl_vsync.flags, FCVAR_CHANGED ))
if( cls.state < ca_active )
{ {
// setup vsync here ClearBits( gl_vsync.flags, FCVAR_CHANGED );
vsync = false; vsync = gl_vsync.value;
SetBits( gl_vsync->flags, FCVAR_CHANGED );
}
else if( FBitSet( gl_vsync->flags, FCVAR_CHANGED ))
{
ClearBits( gl_vsync->flags, FCVAR_CHANGED );
vsync = true;
} }
} }

View File

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

View File

@@ -161,17 +161,10 @@ void* GL_GetProcAddress( const char *name ) // RenderAPI requirement
void GL_UpdateSwapInterval( void ) void GL_UpdateSwapInterval( void )
{ {
// disable VSync while level is loading if( FBitSet( gl_vsync.flags, FCVAR_CHANGED ))
if( cls.state < ca_active )
{
// setup fb vsync here
fb.vsync = false;
SetBits( gl_vsync.flags, FCVAR_CHANGED );
}
else if( FBitSet( gl_vsync.flags, FCVAR_CHANGED ))
{ {
ClearBits( gl_vsync.flags, FCVAR_CHANGED ); ClearBits( gl_vsync.flags, FCVAR_CHANGED );
fb.vsync = true; fb.vsync = gl_vsync.value;
} }
} }
@@ -281,13 +274,8 @@ void GAME_EXPORT Platform_SetMousePos(int x, int y)
} }
void Platform_Vibrate(float life, char flags) void Platform_Vibrate( float life, char flags )
{ {
} }
int Platform_JoyInit( int numjoy )
{
return 0;
}
#endif #endif

View File

@@ -31,6 +31,7 @@ GNU General Public License for more details.
============================================================================== ==============================================================================
*/ */
double Platform_DoubleTime( void ); double Platform_DoubleTime( void );
void Platform_Sleep( int msec );
void Platform_ShellExecute( const char *path, const char *parms ); void Platform_ShellExecute( const char *path, const char *parms );
void Platform_MessageBox( const char *title, const char *message, qboolean parentMainWindow ); void Platform_MessageBox( const char *title, const char *message, qboolean parentMainWindow );
void Platform_SetStatus( const char *status ); void Platform_SetStatus( const char *status );
@@ -55,7 +56,7 @@ char *Posix_Input( void );
#endif #endif
#if XASH_SDL #if XASH_SDL
void SDLash_Init( void ); void SDLash_Init( const char *basedir );
void SDLash_Shutdown( void ); void SDLash_Shutdown( void );
#endif #endif
@@ -70,6 +71,9 @@ void Android_Shutdown( void );
#endif #endif
#if XASH_WIN32 #if XASH_WIN32
void Win32_Init( qboolean con_showalways );
void Win32_Shutdown( void );
qboolean Win32_NanoSleep( int nsec );
void Wcon_CreateConsole( qboolean con_showalways ); void Wcon_CreateConsole( qboolean con_showalways );
void Wcon_DestroyConsole( void ); void Wcon_DestroyConsole( void );
void Wcon_InitConsoleCommands( void ); void Wcon_InitConsoleCommands( void );
@@ -104,7 +108,7 @@ void Linux_SetTimer( float time );
int Linux_GetProcessID( void ); int Linux_GetProcessID( void );
#endif #endif
static inline void Platform_Init( qboolean con_showalways ) static inline void Platform_Init( qboolean con_showalways, const char *basedir )
{ {
#if XASH_POSIX #if XASH_POSIX
// daemonize as early as possible, because we need to close our file descriptors // daemonize as early as possible, because we need to close our file descriptors
@@ -112,7 +116,7 @@ static inline void Platform_Init( qboolean con_showalways )
#endif #endif
#if XASH_SDL #if XASH_SDL
SDLash_Init( ); SDLash_Init( basedir );
#endif #endif
#if XASH_ANDROID #if XASH_ANDROID
@@ -124,7 +128,7 @@ static inline void Platform_Init( qboolean con_showalways )
#elif XASH_DOS #elif XASH_DOS
DOS_Init( ); DOS_Init( );
#elif XASH_WIN32 #elif XASH_WIN32
Wcon_CreateConsole( con_showalways ); Win32_Init( con_showalways );
#elif XASH_LINUX #elif XASH_LINUX
Linux_Init( ); Linux_Init( );
#endif #endif
@@ -139,7 +143,7 @@ static inline void Platform_Shutdown( void )
#elif XASH_DOS #elif XASH_DOS
DOS_Shutdown( ); DOS_Shutdown( );
#elif XASH_WIN32 #elif XASH_WIN32
Wcon_DestroyConsole( ); Win32_Shutdown( );
#elif XASH_LINUX #elif XASH_LINUX
Linux_Shutdown( ); Linux_Shutdown( );
#endif #endif
@@ -165,24 +169,28 @@ static inline void Platform_SetupSigtermHandling( void )
#endif #endif
} }
static inline void Platform_Sleep( int msec ) static inline qboolean Platform_NanoSleep( int nsec )
{ {
#if XASH_TIMER == TIMER_SDL // SDL2 doesn't have nanosleep, so use low-level functions here
SDL_Delay( msec ); // When this code will be ported to SDL3, use SDL_DelayNS
#elif XASH_TIMER == TIMER_POSIX #if XASH_POSIX
usleep( msec * 1000 ); struct timespec ts = {
#elif XASH_TIMER == TIMER_WIN32 .tv_sec = 0,
Sleep( msec ); .tv_nsec = nsec, // just don't put large numbers here
};
return nanosleep( &ts, NULL ) == 0;
#elif XASH_WIN32
return Win32_NanoSleep( nsec );
#else #else
// stub return false;
#endif #endif
} }
#if XASH_WIN32 || XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD || XASH_ANDROID || XASH_LINUX #if XASH_WIN32 || XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD || XASH_ANDROID || XASH_LINUX || XASH_APPLE
void Sys_SetupCrashHandler( void ); void Sys_SetupCrashHandler( const char *argv0 );
void Sys_RestoreCrashHandler( void ); void Sys_RestoreCrashHandler( void );
#else #else
static inline void Sys_SetupCrashHandler( void ) static inline void Sys_SetupCrashHandler( const char *argv0 )
{ {
} }
@@ -199,7 +207,8 @@ static inline void Sys_RestoreCrashHandler( void )
============================================================================== ==============================================================================
*/ */
void Platform_Vibrate( float life, char flags ); void Platform_Vibrate( float life, char flags ); // left for compatibility
void Platform_Vibrate2( float time, int low_freq, int high_freq, uint flags );
/* /*
============================================================================== ==============================================================================
@@ -209,7 +218,27 @@ void Platform_Vibrate( float life, char flags );
============================================================================== ==============================================================================
*/ */
// Gamepad support // Gamepad support
int Platform_JoyInit( int numjoy ); // returns number of connected gamepads, negative if error #if XASH_SDL
int Platform_JoyInit( void ); // returns number of connected gamepads, negative if error
void Platform_JoyShutdown( void );
void Platform_CalibrateGamepadGyro( void );
#else
static inline int Platform_JoyInit( void )
{
return 0;
}
static inline void Platform_JoyShutdown( void )
{
}
static inline void Platform_CalibrateGamepadGyro( void )
{
}
#endif
// Text input // Text input
void Platform_EnableTextInput( qboolean enable ); void Platform_EnableTextInput( qboolean enable );
key_modifier_t Platform_GetKeyModifiers( void ); key_modifier_t Platform_GetKeyModifiers( void );

View File

@@ -0,0 +1,88 @@
/*
crashhandler.c - advanced crashhandler
Copyright (C) 2016 Mittorn
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
// on Glibc (which potentially might not be only Linux) systems we
// have backtrace() and backtrace_symbols() calls, which replace for us
// platform-specific code
#if HAVE_EXECINFO
#include <execinfo.h>
#include <signal.h>
#include "common.h"
#include "input.h"
void Sys_Crash( int signal, siginfo_t *si, void *context )
{
char message[8192];
int len, logfd, i = 0;
int size;
void *addrs[16];
char **syms;
(void)context;
// flush buffers before writing directly to descriptors
fflush( stdout );
fflush( stderr );
// safe actions first, stack and memory may be corrupted
len = Q_snprintf( message, sizeof( message ), "Ver: " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s-%s, %s-%s)\n",
Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch() );
#if !XASH_FREEBSD && !XASH_NETBSD && !XASH_OPENBSD && !XASH_APPLE // they don't have si_ptr
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p %p\n", signal, si->si_errno, si->si_code, si->si_addr, si->si_ptr );
#else
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p\n", signal, si->si_errno, si->si_code, si->si_addr );
#endif
write( STDERR_FILENO, message, len );
// now get log fd and write trace directly to log
logfd = Sys_LogFileNo();
write( logfd, message, len );
size = backtrace( addrs, sizeof( addrs ) / sizeof( addrs[0] ));
syms = backtrace_symbols( addrs, size );
for( i = 0; i < size && syms; i++ )
{
size_t symlen = Q_strlen( syms[i] );
char ch = '\n';
write( logfd, syms[i], symlen );
write( logfd, &ch, 1 );
write( STDERR_FILENO, syms[i], symlen );
write( STDERR_FILENO, &ch, 1 );
len += Q_snprintf( message + len, sizeof( message ) - len, "%2d: %s\n", i, syms[i] );
}
// put MessageBox as Sys_Error
Msg( "%s\n", message );
#if !XASH_DEDICATED
IN_SetMouseGrab( false );
#endif
host.crashed = true;
Platform_MessageBox( "Xash Error", message, false );
// log saved, now we can try to save configs and close log correctly, it may crash
if( host.type == HOST_NORMAL )
CL_Crashed();
host.status = HOST_CRASHED;
Sys_Quit( "crashed" );
}
#endif // HAVE_EXECINFO

View File

@@ -0,0 +1,188 @@
/*
crashhandler.c - advanced crashhandler
Copyright (C) 2016 Mittorn
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#if HAVE_LIBBACKTRACE
#include <signal.h>
#include "common.h"
#include "backtrace.h"
#include "input.h"
static struct backtrace_state *g_bt_state;
static qboolean enable_libbacktrace;
static void Sys_BacktraceError( void *data, const char *msg, int errnum )
{
if( errnum < 0 )
{
Con_Printf( S_ERROR "no symbol info, no libbacktrace\n" );
return;
}
Con_Printf( S_ERROR "libbacktrace error: %s (%d)\n", msg, errnum );
enable_libbacktrace = false;
}
struct print_data
{
char *message;
size_t message_size;
int len;
int idx;
int logfd;
};
static void Sys_AppendPrint( struct print_data *pd, const char *fmt, ... )
{
va_list va;
int len;
va_start( va, fmt );
len = Q_vsnprintf( pd->message, pd->message_size, fmt, va );
va_end( va );
if( len > 0 )
{
char ch = '\n';
write( pd->logfd, pd->message, len );
write( pd->logfd, &ch, 1 );
write( STDERR_FILENO, pd->message, len );
write( STDERR_FILENO, &ch, 1 );
pd->message += len;
pd->len += len;
pd->message_size -= len;
}
}
static void Sys_BacktracePrintError( void *data, const char *msg, int errnum )
{
struct print_data *pd = data;
Sys_AppendPrint( pd, "%2d: error: %s (%d)\n", pd->idx++, msg, errnum );
}
static void Sys_BacktracePrintSyminfo( void *data, uintptr_t pc, const char *symname, uintptr_t symval, uintptr_t symsize )
{
struct print_data *pd = data;
Dl_info dlinfo = { 0 };
const char *module_name;
if( dladdr((void *)pc, &dlinfo ))
module_name = dlinfo.dli_fname;
else module_name = NULL;
if( symname )
{
if( module_name )
Sys_AppendPrint( pd, "%2d: <%s+%d> (%s)\n", pd->idx++, symname, pc - symval, module_name );
else
Sys_AppendPrint( pd, "%2d: <%s+%d>\n", pd->idx++, symname, pc - symval );
}
else
{
if( module_name )
Sys_AppendPrint( pd, "%2d: %p (%s)\n", pd->idx++, pc, module_name );
else
Sys_AppendPrint( pd, "%2d: %p\n", pd->idx++, pc );
}
}
static int Sys_BacktracePrintFull( void *data, uintptr_t pc, const char *filename, int lineno, const char *function )
{
struct print_data *pd = data;
Dl_info dlinfo = { 0 };
const char *module_name;
if( dladdr((void *)pc, &dlinfo ))
module_name = dlinfo.dli_fname;
else module_name = NULL;
if( filename && lineno >= 0 && function )
{
filename = COM_FileWithoutPath( filename );
if( module_name )
Sys_AppendPrint( pd, "%2d: %s (%s:%d) (%s)\n", pd->idx++, function, filename, lineno, module_name );
else
Sys_AppendPrint( pd, "%2d: %s (%s:%d)\n", pd->idx++, function, filename, lineno );
}
else
{
backtrace_syminfo( g_bt_state, pc, Sys_BacktracePrintSyminfo, Sys_BacktraceError, data );
}
return 0;
}
void Sys_CrashLibbacktrace( int signal, siginfo_t *si, void *context )
{
char message[8192];
int len, logfd;
struct print_data pd = { .idx = 0 };
(void)context;
// flush buffers before writing directly to descriptors
fflush( stdout );
fflush( stderr );
// safe actions first, stack and memory may be corrupted
len = Q_snprintf( message, sizeof( message ), "Ver: " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s-%s, %s-%s)\n",
Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch() );
#if !XASH_FREEBSD && !XASH_NETBSD && !XASH_OPENBSD && !XASH_APPLE // they don't have si_ptr
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p %p\n", signal, si->si_errno, si->si_code, si->si_addr, si->si_ptr );
#else
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p\n", signal, si->si_errno, si->si_code, si->si_addr );
#endif
write( STDERR_FILENO, message, len );
// now get log fd and write trace directly to log
pd.logfd = logfd = Sys_LogFileNo();
write( logfd, message, len );
pd.message = message + len;
pd.message_size = sizeof( message ) - len;
pd.len = 0;
backtrace_full( g_bt_state, 1, Sys_BacktracePrintFull, Sys_BacktracePrintError, &pd );
// put MessageBox as Sys_Error
Msg( "%s\n", message );
#if !XASH_DEDICATED
IN_SetMouseGrab( false );
#endif
host.crashed = true;
Platform_MessageBox( "Xash Error", message, false );
// log saved, now we can try to save configs and close log correctly, it may crash
if( host.type == HOST_NORMAL )
CL_Crashed();
host.status = HOST_CRASHED;
Sys_Quit( "crashed" );
}
qboolean Sys_SetupLibbacktrace( const char *argv0 )
{
enable_libbacktrace = true;
g_bt_state = backtrace_create_state( argv0, true, Sys_BacktraceError, NULL );
return g_bt_state != NULL && enable_libbacktrace;
}
#endif // HAVE_EXECINFO

View File

@@ -18,13 +18,22 @@ GNU General Public License for more details.
// while this is mostly POSIX-compatible functions // while this is mostly POSIX-compatible functions
// the contents of ucontext_t is platform-dependent // the contents of ucontext_t is platform-dependent
// before adding new OS here, check platform.h // before adding new OS here, check platform.h
#if XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD || XASH_ANDROID || XASH_LINUX #define _XOPEN_SOURCE 1 // required for ucontext
#if XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD || XASH_ANDROID || XASH_LINUX || XASH_APPLE
#ifndef XASH_OPENBSD #ifndef XASH_OPENBSD
#include <ucontext.h> #include <ucontext.h>
#endif #endif
#include <signal.h> #include <signal.h>
#include <sys/mman.h> #include <sys/mman.h>
#include "library.h" #include "library.h"
#include "input.h"
void Sys_Crash( int signal, siginfo_t *si, void *context );
void Sys_CrashLibbacktrace( int signal, siginfo_t *si, void *context );
qboolean Sys_SetupLibbacktrace( const char *argv0 );
static struct sigaction oldFilter;
#if !HAVE_EXECINFO
#define STACK_BACKTRACE_STR "Stack backtrace:\n" #define STACK_BACKTRACE_STR "Stack backtrace:\n"
#define STACK_DUMP_STR "Stack dump:\n" #define STACK_DUMP_STR "Stack dump:\n"
@@ -33,27 +42,25 @@ GNU General Public License for more details.
#define STACK_DUMP_STR_LEN ( sizeof( STACK_DUMP_STR ) - 1 ) #define STACK_DUMP_STR_LEN ( sizeof( STACK_DUMP_STR ) - 1 )
#define ALIGN( x, y ) (((uintptr_t) ( x ) + (( y ) - 1 )) & ~(( y ) - 1 )) #define ALIGN( x, y ) (((uintptr_t) ( x ) + (( y ) - 1 )) & ~(( y ) - 1 ))
static struct sigaction oldFilter;
static int Sys_PrintFrame( char *buf, int len, int i, void *addr ) static int Sys_PrintFrame( char *buf, int len, int i, void *addr )
{ {
Dl_info dlinfo; Dl_info dlinfo;
if( len <= 0 ) if( len <= 0 )
return 0; // overflow return 0; // overflow
if( dladdr( addr, &dlinfo )) if( dladdr( addr, &dlinfo ))
{ {
if( dlinfo.dli_sname ) if( dlinfo.dli_sname )
return Q_snprintf( buf, len, "%2d: %p <%s+%lu> (%s)\n", i, addr, dlinfo.dli_sname, return Q_snprintf( buf, len, "%2d: %p <%s+%lu> (%s)\n", i, addr, dlinfo.dli_sname,
(unsigned long)addr - (unsigned long)dlinfo.dli_saddr, dlinfo.dli_fname ); // print symbol, module and address (unsigned long)addr - (unsigned long)dlinfo.dli_saddr, dlinfo.dli_fname ); // print symbol, module and address
return Q_snprintf( buf, len, "%2d: %p (%s)\n", i, addr, dlinfo.dli_fname ); // print module and address return Q_snprintf( buf, len, "%2d: %p (%s)\n", i, addr, dlinfo.dli_fname ); // print module and address
} }
return Q_snprintf( buf, len, "%2d: %p\n", i, addr ); // print only address return Q_snprintf( buf, len, "%2d: %p\n", i, addr ); // print only address
} }
static void Sys_Crash( int signal, siginfo_t *si, void *context) void Sys_Crash( int signal, siginfo_t *si, void *context )
{ {
void *pc = NULL, **bp = NULL, **sp = NULL; // this must be set for every OS! void *pc = NULL, **bp = NULL, **sp = NULL; // this must be set for every OS!
char message[8192]; char message[8192];
@@ -65,6 +72,10 @@ static void Sys_Crash( int signal, siginfo_t *si, void *context)
ucontext_t *ucontext = (ucontext_t*)context; ucontext_t *ucontext = (ucontext_t*)context;
#endif #endif
// flush buffers before writing directly to descriptors
fflush( stdout );
fflush( stderr );
#if XASH_AMD64 #if XASH_AMD64
#if XASH_FREEBSD #if XASH_FREEBSD
pc = (void*)ucontext->uc_mcontext.mc_rip; pc = (void*)ucontext->uc_mcontext.mc_rip;
@@ -112,10 +123,10 @@ static void Sys_Crash( int signal, siginfo_t *si, void *context)
#endif #endif
// safe actions first, stack and memory may be corrupted // safe actions first, stack and memory may be corrupted
len = Q_snprintf( message, sizeof( message ), "Ver: " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s, %s-%s)\n", len = Q_snprintf( message, sizeof( message ), "Ver: " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s-%s, %s-%s)\n",
Q_buildnum(), g_buildcommit, Q_buildos(), Q_buildarch() ); Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch() );
#if !XASH_FREEBSD && !XASH_NETBSD && !XASH_OPENBSD #if !XASH_FREEBSD && !XASH_NETBSD && !XASH_OPENBSD && !XASH_APPLE
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p %p\n", signal, si->si_errno, si->si_code, si->si_addr, si->si_ptr ); len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p %p\n", signal, si->si_errno, si->si_code, si->si_addr, si->si_ptr );
#else #else
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p\n", signal, si->si_errno, si->si_code, si->si_addr ); len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p\n", signal, si->si_errno, si->si_code, si->si_addr );
@@ -123,10 +134,6 @@ static void Sys_Crash( int signal, siginfo_t *si, void *context)
write( STDERR_FILENO, message, len ); write( STDERR_FILENO, message, len );
// flush buffers before writing directly to descriptors
fflush( stdout );
fflush( stderr );
// now get log fd and write trace directly to log // now get log fd and write trace directly to log
logfd = Sys_LogFileNo(); logfd = Sys_LogFileNo();
write( logfd, message, len ); write( logfd, message, len );
@@ -186,8 +193,8 @@ static void Sys_Crash( int signal, siginfo_t *si, void *context)
// put MessageBox as Sys_Error // put MessageBox as Sys_Error
Msg( "%s\n", message ); Msg( "%s\n", message );
#ifdef XASH_SDL #if !XASH_DEDICATED
SDL_SetWindowGrab( host.hWnd, SDL_FALSE ); IN_SetMouseGrab( false );
#endif #endif
host.crashed = true; host.crashed = true;
Platform_MessageBox( "Xash Error", message, false ); Platform_MessageBox( "Xash Error", message, false );
@@ -200,15 +207,27 @@ static void Sys_Crash( int signal, siginfo_t *si, void *context)
Sys_Quit( "crashed" ); Sys_Quit( "crashed" );
} }
void Sys_SetupCrashHandler( void ) #endif // !HAVE_EXECINFO
void Sys_SetupCrashHandler( const char *argv0 )
{ {
struct sigaction act = { 0 }; struct sigaction act = { 0 };
act.sa_sigaction = Sys_Crash; #if HAVE_LIBBACKTRACE
if( Sys_SetupLibbacktrace( argv0 ))
{
act.sa_sigaction = Sys_CrashLibbacktrace;
}
else
#endif
{
act.sa_sigaction = Sys_Crash;
}
act.sa_flags = SA_SIGINFO | SA_ONSTACK; act.sa_flags = SA_SIGINFO | SA_ONSTACK;
sigaction( SIGSEGV, &act, &oldFilter ); sigaction( SIGSEGV, &act, &oldFilter );
sigaction( SIGABRT, &act, &oldFilter ); sigaction( SIGABRT, &act, &oldFilter );
sigaction( SIGBUS, &act, &oldFilter ); sigaction( SIGBUS, &act, &oldFilter );
sigaction( SIGILL, &act, &oldFilter ); sigaction( SIGILL, &act, &oldFilter );
} }
void Sys_RestoreCrashHandler( void ) void Sys_RestoreCrashHandler( void )

View File

@@ -174,5 +174,10 @@ double Platform_DoubleTime( void )
#endif #endif
return (double) ts.tv_sec + (double) ts.tv_nsec/1000000000.0; return (double) ts.tv_sec + (double) ts.tv_nsec/1000000000.0;
} }
void Platform_Sleep( int msec )
{
usleep( msec * 1000 );
}
#endif // XASH_TIMER == TIMER_POSIX #endif // XASH_TIMER == TIMER_POSIX

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
/* /*
vid_sdl.c - SDL input component in_sdl.c - SDL input component
Copyright (C) 2018 a1batross Copyright (C) 2018-2025 a1batross
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@@ -12,7 +12,6 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
*/ */
#if !XASH_DEDICATED
#include <SDL.h> #include <SDL.h>
#include "common.h" #include "common.h"
@@ -24,7 +23,6 @@ GNU General Public License for more details.
#include "sound.h" #include "sound.h"
#include "vid_common.h" #include "vid_common.h"
SDL_Joystick *g_joy = NULL;
#if !SDL_VERSION_ATLEAST( 2, 0, 0 ) #if !SDL_VERSION_ATLEAST( 2, 0, 0 )
#define SDL_WarpMouseInWindow( win, x, y ) SDL_WarpMouse( ( x ), ( y ) ) #define SDL_WarpMouseInWindow( win, x, y ) SDL_WarpMouse( ( x ), ( y ) )
#else #else
@@ -35,6 +33,12 @@ static struct
} cursors; } cursors;
#endif #endif
static struct
{
int x, y;
qboolean pushed;
} in_visible_cursor_pos;
/* /*
============= =============
Platform_GetMousePos Platform_GetMousePos
@@ -126,20 +130,6 @@ void Platform_SetClipboardText( const char *buffer )
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 ) #endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
} }
/*
=============
Platform_Vibrate
=============
*/
void Platform_Vibrate( float time, char flags )
{
#if SDL_VERSION_ATLEAST( 2, 0, 9 )
if( g_joy )
SDL_JoystickRumble( g_joy, 0xFFFF, 0xFFFF, time * 1000.0f );
#endif // SDL_VERSION_ATLEAST( 2, 0, 9 )
}
#if !XASH_PSVITA #if !XASH_PSVITA
/* /*
@@ -157,120 +147,6 @@ void Platform_EnableTextInput( qboolean enable )
#endif // !XASH_PSVITA #endif // !XASH_PSVITA
/*
=============
SDLash_JoyInit_Old
=============
*/
static int SDLash_JoyInit_Old( int numjoy )
{
int num;
int i;
Con_Reportf( "Joystick: SDL\n" );
if( SDL_WasInit( SDL_INIT_JOYSTICK ) != SDL_INIT_JOYSTICK &&
SDL_InitSubSystem( SDL_INIT_JOYSTICK ) )
{
Con_Reportf( "Failed to initialize SDL Joysitck: %s\n", SDL_GetError() );
return 0;
}
if( g_joy )
{
SDL_JoystickClose( g_joy );
}
num = SDL_NumJoysticks();
if( num > 0 )
Con_Reportf( "%i joysticks found:\n", num );
else
{
Con_Reportf( "No joystick found.\n" );
return 0;
}
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
for( i = 0; i < num; i++ )
Con_Reportf( "%i\t: %s\n", i, SDL_JoystickNameForIndex( i ) );
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
Con_Reportf( "Pass +set joy_index N to command line, where N is number, to select active joystick\n" );
g_joy = SDL_JoystickOpen( numjoy );
if( !g_joy )
{
Con_Reportf( "Failed to select joystick: %s\n", SDL_GetError( ) );
return 0;
}
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
Con_Reportf( "Selected joystick: %s\n"
"\tAxes: %i\n"
"\tHats: %i\n"
"\tButtons: %i\n"
"\tBalls: %i\n",
SDL_JoystickName( g_joy ), SDL_JoystickNumAxes( g_joy ), SDL_JoystickNumHats( g_joy ),
SDL_JoystickNumButtons( g_joy ), SDL_JoystickNumBalls( g_joy ) );
SDL_GameControllerEventState( SDL_DISABLE );
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
SDL_JoystickEventState( SDL_ENABLE );
return num;
}
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
/*
=============
SDLash_JoyInit_New
=============
*/
static int SDLash_JoyInit_New( int numjoy )
{
int count, numJoysticks, i;
Con_Reportf( "Joystick: SDL GameController API\n" );
if( SDL_WasInit( SDL_INIT_GAMECONTROLLER ) != SDL_INIT_GAMECONTROLLER &&
SDL_InitSubSystem( SDL_INIT_GAMECONTROLLER ) )
{
Con_Reportf( "Failed to initialize SDL GameController API: %s\n", SDL_GetError() );
return 0;
}
SDL_GameControllerAddMappingsFromFile( "controllermappings.txt" );
count = 0;
numJoysticks = SDL_NumJoysticks();
for ( i = 0; i < numJoysticks; i++ )
if( SDL_IsGameController( i ) )
++count;
return count;
}
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
/*
=============
Platform_JoyInit
=============
*/
int Platform_JoyInit( int numjoy )
{
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
// SDL_Joystick is now an old API
// SDL_GameController is preferred
if( !Sys_CheckParm( "-sdl_joy_old_api" ) )
return SDLash_JoyInit_New(numjoy);
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
return SDLash_JoyInit_Old(numjoy);
}
/* /*
======================== ========================
SDLash_InitCursors SDLash_InitCursors
@@ -333,11 +209,6 @@ void Platform_SetCursorType( VGUI_DefaultCursor type )
{ {
qboolean visible; qboolean visible;
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
if( !cursors.initialized )
return;
#endif
switch( type ) switch( type )
{ {
case dc_user: case dc_user:
@@ -350,7 +221,7 @@ void Platform_SetCursorType( VGUI_DefaultCursor type )
} }
// never disable cursor in touch emulation mode // never disable cursor in touch emulation mode
if( !visible && Touch_Emulated( )) if( !visible && Touch_WantVisibleCursor( ))
return; return;
host.mouse_visible = visible; host.mouse_visible = visible;
@@ -359,11 +230,28 @@ void Platform_SetCursorType( VGUI_DefaultCursor type )
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) #if SDL_VERSION_ATLEAST( 2, 0, 0 )
if( host.mouse_visible ) if( host.mouse_visible )
{ {
SDL_SetCursor( cursors.cursors[type] ); if( cursors.initialized )
SDL_SetCursor( cursors.cursors[type] );
SDL_ShowCursor( true ); SDL_ShowCursor( true );
// restore the last mouse position
if( in_visible_cursor_pos.pushed )
{
SDL_WarpMouseInWindow( host.hWnd, in_visible_cursor_pos.x, in_visible_cursor_pos.y );
in_visible_cursor_pos.pushed = false;
}
} }
else else
{ {
// save last mouse position and warp it to the center
if( !in_visible_cursor_pos.pushed )
{
SDL_GetMouseState( &in_visible_cursor_pos.x, &in_visible_cursor_pos.y );
SDL_WarpMouseInWindow( host.hWnd, host.window_center_x, host.window_center_y );
in_visible_cursor_pos.pushed = true;
}
SDL_ShowCursor( false ); SDL_ShowCursor( false );
} }
#else #else
@@ -418,5 +306,3 @@ key_modifier_t Platform_GetKeyModifiers( void )
return KeyModifier_None; return KeyModifier_None;
#endif #endif
} }
#endif // XASH_DEDICATED

View File

@@ -0,0 +1,403 @@
/*
joy_sdl.c - SDL gamepads
Copyright (C) 2018-2025 a1batross
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include <SDL.h>
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
#include "common.h"
#include "keydefs.h"
#include "input.h"
#include "client.h"
#include "events.h"
static const int g_button_mapping[] =
{
#if XASH_NSWITCH // devkitPro/SDL has inverted Nintendo layout for SDL_GameController
K_B_BUTTON, K_A_BUTTON, K_Y_BUTTON, K_X_BUTTON,
#else
K_A_BUTTON, K_B_BUTTON, K_X_BUTTON, K_Y_BUTTON,
#endif
K_BACK_BUTTON, K_MODE_BUTTON, K_START_BUTTON,
K_LSTICK, K_RSTICK,
K_L1_BUTTON, K_R1_BUTTON,
K_DPAD_UP, K_DPAD_DOWN, K_DPAD_LEFT, K_DPAD_RIGHT,
K_MISC_BUTTON,
K_PADDLE1_BUTTON, K_PADDLE2_BUTTON, K_PADDLE3_BUTTON, K_PADDLE4_BUTTON,
K_TOUCHPAD,
};
// Swap axis to follow default axis binding:
static const engineAxis_t g_axis_mapping[] =
{
JOY_AXIS_SIDE, // SDL_CONTROLLER_AXIS_LEFTX,
JOY_AXIS_FWD, // SDL_CONTROLLER_AXIS_LEFTY,
JOY_AXIS_PITCH, // SDL_CONTROLLER_AXIS_RIGHTX,
JOY_AXIS_YAW, // SDL_CONTROLLER_AXIS_RIGHTY,
JOY_AXIS_LT, // SDL_CONTROLLER_AXIS_TRIGGERLEFT,
JOY_AXIS_RT, // SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
};
static SDL_JoystickID g_current_gamepad_id = -1; // used to send rumble to
static SDL_GameController *g_current_gamepad;
static SDL_GameController **g_gamepads;
static size_t g_num_gamepads;
#define CALIBRATION_TIME 10.0f
static struct
{
float time;
vec3_t data;
vec3_t calibrated_values;
int samples;
} gyrocal;
static void SDLash_RestartCalibration( void )
{
Joy_SetCalibrationState( JOY_NOT_CALIBRATED );
memset( &gyrocal, 0, sizeof( gyrocal ));
gyrocal.time = host.realtime + CALIBRATION_TIME;
Con_Printf( "Starting gyroscope calibration...\n" );
}
static void SDLash_FinalizeCalibration( void )
{
float data_rate = 10.0f; // let's say we're polling at 10Hz?
int min_samples;
#if SDL_VERSION_ATLEAST( 2, 0, 16 )
data_rate = SDL_GameControllerGetSensorDataRate( g_current_gamepad, SDL_SENSOR_GYRO );
if( !data_rate )
data_rate = 10.0f;
#endif
min_samples = Q_rint( CALIBRATION_TIME * data_rate * 0.75f );
// we waited for few seconds and got too few samples
if( gyrocal.samples <= min_samples )
{
Joy_SetCalibrationState( JOY_FAILED_TO_CALIBRATE );
return;
}
VectorScale( gyrocal.data, 1.0f / gyrocal.samples, gyrocal.calibrated_values );
Joy_SetCalibrationState( JOY_CALIBRATED );
Con_Printf( "Calibration done. Result: %f %f %f\n", gyrocal.calibrated_values[0], gyrocal.calibrated_values[1], gyrocal.calibrated_values[2] );
gyrocal.time = 0.0f;
}
static void SDLash_GameControllerAddMappings( const char *name )
{
fs_offset_t len = 0;
byte *p = FS_LoadFile( name, &len, false );
if( !p )
return;
if( len > 0 && len < INT32_MAX ) // function accepts int, SDL3 fixes this
{
SDL_RWops *rwops = SDL_RWFromConstMem( p, (int)len );
SDL_GameControllerAddMappingsFromRW( rwops, true );
}
Mem_Free( p );
}
static void SDLash_SetActiveGameController( SDL_JoystickID id )
{
SDL_GameController *oldgc;
if( g_current_gamepad_id == id )
return;
g_current_gamepad_id = id;
oldgc = g_current_gamepad;
#if SDL_VERSION_ATLEAST( 2, 0, 14 )
SDL_GameControllerSetSensorEnabled( oldgc, SDL_SENSOR_GYRO, SDL_FALSE );
#endif // SDL_VERSION_ATLEAST( 2, 0, 14 )
if( id < 0 )
{
g_current_gamepad = NULL;
Joy_SetCapabilities( false );
Joy_SetCalibrationState( JOY_NOT_CALIBRATED );
}
else
{
qboolean have_gyro = false;
g_current_gamepad = SDL_GameControllerFromInstanceID( id );
#if SDL_VERSION_ATLEAST( 2, 0, 14 )
have_gyro = SDL_GameControllerHasSensor( g_current_gamepad, SDL_SENSOR_GYRO );
if( have_gyro )
{
SDL_GameControllerSetSensorEnabled( g_current_gamepad, SDL_SENSOR_GYRO, SDL_TRUE );
SDLash_RestartCalibration();
}
#endif // SDL_VERSION_ATLEAST( 2, 0, 14 )
Joy_SetCapabilities( have_gyro );
}
}
static void SDLash_GameControllerAdded( int device_index )
{
SDL_GameController *gc;
SDL_GameController **list;
gc = SDL_GameControllerOpen( device_index );
if( !gc )
{
Con_Printf( S_ERROR "SDL_GameControllerOpen: %s\n", SDL_GetError( ));
return;
}
// this "game controller" only exists on Android within emulator and tries to map
// keyboard events into game controller events, which as you can expect, doesn't
// work and I don't understand the intention here. When debugging Xash in Android
// Studio emulator, just enable hardware input passthrough.
#if XASH_ANDROID
if( !Q_strcmp( SDL_GameControllerName( gc ), "qwerty2" ))
{
SDL_GameControllerClose( gc );
return;
}
#endif // XASH_ANDROID
list = Mem_Realloc( host.mempool, g_gamepads, sizeof( *list ) * ( g_num_gamepads + 1 ));
list[g_num_gamepads++] = gc;
g_gamepads = list;
// set as current device if none other set
if( g_current_gamepad_id < 0 )
{
SDL_Joystick *joy = SDL_GameControllerGetJoystick( gc );
if( joy )
SDLash_SetActiveGameController( SDL_JoystickInstanceID( joy ));
}
Con_Printf( "Detected \"%s\" game controller.\nMapping string: %s\n", SDL_GameControllerName( gc ), SDL_GameControllerMapping( gc ));
}
static void SDLash_GameControllerRemoved( SDL_JoystickID id )
{
size_t i;
if( id == g_current_gamepad_id )
SDLash_SetActiveGameController( -1 );
// now close the device
for( i = 0; i < g_num_gamepads; i++ )
{
SDL_GameController *gc = g_gamepads[i];
SDL_Joystick *joy;
if( !gc )
continue;
joy = SDL_GameControllerGetJoystick( gc );
if( !joy )
continue;
if( SDL_JoystickInstanceID( joy ) == id )
{
Con_Printf( "Game controller \"%s\" was disconnected\n", SDL_GameControllerName( gc ));
SDL_GameControllerClose( gc );
g_gamepads[i] = NULL;
}
}
}
static void SDLash_GameControllerSensorUpdate( SDL_ControllerSensorEvent sensor )
{
vec3_t data;
if( sensor.which != g_current_gamepad_id )
return;
if( sensor.sensor != SDL_SENSOR_GYRO )
return;
if( gyrocal.time != 0.0f )
{
if( host.realtime > gyrocal.time )
SDLash_FinalizeCalibration();
VectorAdd( gyrocal.data, sensor.data, gyrocal.data );
gyrocal.samples++;
Joy_SetCalibrationState( JOY_CALIBRATING );
return;
}
VectorSubtract( sensor.data, gyrocal.calibrated_values, data );
Joy_GyroEvent( data );
}
void SDLash_HandleGameControllerEvent( SDL_Event *ev )
{
int x;
switch( ev->type )
{
case SDL_CONTROLLERAXISMOTION:
SDLash_SetActiveGameController( ev->caxis.which );
x = ev->caxis.axis;
if( x >= 0 && x < ARRAYSIZE( g_axis_mapping ))
Joy_AxisMotionEvent( g_axis_mapping[x], ev->caxis.value );
break;
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
SDLash_SetActiveGameController( ev->cbutton.which );
x = ev->cbutton.button;
if( x >= 0 && x < ARRAYSIZE( g_button_mapping ))
Key_Event( g_button_mapping[x], ev->cbutton.state );
break;
case SDL_CONTROLLERDEVICEREMOVED:
SDLash_GameControllerRemoved( ev->cdevice.which );
break;
case SDL_CONTROLLERDEVICEADDED:
SDLash_GameControllerAdded( ev->cdevice.which );
break;
#if SDL_VERSION_ATLEAST( 2, 0, 14 )
case SDL_CONTROLLERSENSORUPDATE:
SDLash_GameControllerSensorUpdate( ev->csensor );
break;
#endif
}
}
void Platform_CalibrateGamepadGyro( void )
{
SDLash_RestartCalibration();
}
void Platform_Vibrate2( float time, int val1, int val2, uint flags )
{
#if SDL_VERSION_ATLEAST( 2, 0, 9 )
SDL_GameController *gc = g_current_gamepad;
Uint32 ms;
if( g_current_gamepad_id < 0 || !gc )
return;
if( val1 < 0 )
val1 = COM_RandomLong( 0x7FFF, 0xFFFF );
if( val2 < 0 )
val2 = COM_RandomLong( 0x7FFF, 0xFFFF );
ms = (Uint32)ceil( time );
SDL_GameControllerRumble( gc, val1, val2, ms );
#endif // SDL_VERSION_ATLEAST( 2, 0, 9 )
}
/*
=============
Platform_Vibrate
=============
*/
void Platform_Vibrate( float time, char flags )
{
Platform_Vibrate2( time, -1, -1, flags );
}
/*
=============
Platform_JoyInit
=============
*/
int Platform_JoyInit( void )
{
int count, numJoysticks, i;
Con_Reportf( "Joystick: SDL GameController API\n" );
if( SDL_WasInit( SDL_INIT_GAMECONTROLLER ) != SDL_INIT_GAMECONTROLLER &&
SDL_InitSubSystem( SDL_INIT_GAMECONTROLLER ))
{
Con_Reportf( "Failed to initialize SDL GameController API: %s\n", SDL_GetError( ));
return 0;
}
SDLash_GameControllerAddMappings( "gamecontrollerdb.txt" ); // shipped in extras.pk3
SDLash_GameControllerAddMappings( "controllermappings.txt" );
count = 0;
numJoysticks = SDL_NumJoysticks();
for ( i = 0; i < numJoysticks; i++ )
{
if( SDL_IsGameController( i ))
++count;
}
return count;
}
/*
=============
Platform_JoyShutdown
=============
*/
void Platform_JoyShutdown( void )
{
size_t i;
SDLash_SetActiveGameController( -1 );
for( i = 0; i < g_num_gamepads; i++ )
{
if( !g_gamepads[i] )
continue;
SDL_GameControllerClose( g_gamepads[i] );
g_gamepads[i] = NULL;
}
Mem_Free( g_gamepads );
g_gamepads = NULL;
g_num_gamepads = 0;
SDL_QuitSubSystem( SDL_INIT_GAMECONTROLLER );
}
#else // SDL_VERSION_ATLEAST( 2, 0, 0 )
void Platform_Vibrate( float time, char flags )
{
}
int Platform_JoyInit( void )
{
return 0;
}
void Platform_JoyShutdown( void )
{
}
#endif

View File

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

View File

@@ -20,9 +20,9 @@ GNU General Public License for more details.
#if XASH_TIMER == TIMER_SDL #if XASH_TIMER == TIMER_SDL
double Platform_DoubleTime( void ) double Platform_DoubleTime( void )
{ {
static longtime_t g_PerformanceFrequency; static Uint64 g_PerformanceFrequency;
static longtime_t g_ClockStart; static Uint64 g_ClockStart;
longtime_t CurrentTime; Uint64 CurrentTime;
if( !g_PerformanceFrequency ) if( !g_PerformanceFrequency )
{ {
@@ -32,6 +32,11 @@ double Platform_DoubleTime( void )
CurrentTime = SDL_GetPerformanceCounter(); CurrentTime = SDL_GetPerformanceCounter();
return (double)( CurrentTime - g_ClockStart ) / (double)( g_PerformanceFrequency ); return (double)( CurrentTime - g_ClockStart ) / (double)( g_PerformanceFrequency );
} }
void Platform_Sleep( int msec )
{
SDL_Delay( msec );
}
#endif // XASH_TIMER == TIMER_SDL #endif // XASH_TIMER == TIMER_SDL
#if XASH_MESSAGEBOX == MSGBOX_SDL #if XASH_MESSAGEBOX == MSGBOX_SDL
@@ -78,8 +83,19 @@ static void SDLCALL SDLash_LogOutputFunction( void *userdata, int category, SDL_
} }
} }
void SDLash_Init( void ) void SDLash_Init( const char *basedir )
{ {
#if XASH_APPLE
char *path = SDL_GetBasePath();
if( path != NULL )
{
char buf[MAX_VA_STRING];
Q_snprintf( buf, sizeof( buf ), "%s%s/extras.pk3", path, basedir );
setenv( "XASH3D_EXTRAS_PAK1", buf, true );
}
#endif
SDL_LogSetOutputFunction( SDLash_LogOutputFunction, NULL ); SDL_LogSetOutputFunction( SDLash_LogOutputFunction, NULL );
if( host_developer.value >= 2 ) if( host_developer.value >= 2 )
@@ -98,8 +114,11 @@ void SDLash_Init( void )
host.type = HOST_DEDICATED; host.type = HOST_DEDICATED;
} }
#if XASH_SDL == 2 #if SDL_MAJOR_VERSION >= 2
SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0"); SDL_SetHint( SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0" );
SDL_SetHint( SDL_HINT_MOUSE_TOUCH_EVENTS, "0" );
SDL_SetHint( SDL_HINT_TOUCH_MOUSE_EVENTS, "0" );
SDL_StopTextInput(); SDL_StopTextInput();
#endif // XASH_SDL == 2 #endif // XASH_SDL == 2

View File

@@ -257,7 +257,8 @@ static void R_InitVideoModes( void )
{ {
char buf[MAX_VA_STRING]; char buf[MAX_VA_STRING];
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) #if SDL_VERSION_ATLEAST( 2, 0, 0 )
int displayIndex = 0; // TODO: handle multiple displays somehow SDL_Point point = { window_xpos.value, window_ypos.value };
int displayIndex = SDL_GetPointDisplayIndex( &point );
int i, modes; int i, modes;
num_vidmodes = 0; num_vidmodes = 0;
@@ -487,13 +488,7 @@ GL_UpdateSwapInterval
void GL_UpdateSwapInterval( void ) void GL_UpdateSwapInterval( void )
{ {
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) #if SDL_VERSION_ATLEAST( 2, 0, 0 )
// disable VSync while level is loading if( FBitSet( gl_vsync.flags, FCVAR_CHANGED ))
if( cls.state < ca_active )
{
SDL_GL_SetSwapInterval( 0 );
SetBits( gl_vsync.flags, FCVAR_CHANGED );
}
else if( FBitSet( gl_vsync.flags, FCVAR_CHANGED ))
{ {
ClearBits( gl_vsync.flags, FCVAR_CHANGED ); ClearBits( gl_vsync.flags, FCVAR_CHANGED );
@@ -735,6 +730,24 @@ static qboolean VID_CreateWindowWithSafeGL( const char *wndname, int xpos, int y
return true; return true;
} }
static qboolean RectFitsInDisplay( const SDL_Rect *rect, const SDL_Rect *display )
{
return rect->x >= display->x
&& rect->y >= display->y
&& rect->x + rect->w <= display->x + display->w
&& rect->y + rect->h <= display->y + display->h;
}
// Function to check if the rectangle fits in any display
static qboolean RectFitsInAnyDisplay( const SDL_Rect *rect, const SDL_Rect *display_rects, int num_displays )
{
for( int i = 0; i < num_displays; i++ )
{
if( RectFitsInDisplay( rect, &display_rects[i] ))
return true; // Rectangle fits in this display
}
return false; // Rectangle does not fit in any display
}
/* /*
================= =================
VID_CreateWindow VID_CreateWindow
@@ -747,6 +760,8 @@ qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
qboolean maximized = vid_maximized.value != 0.0f; qboolean maximized = vid_maximized.value != 0.0f;
Uint32 wndFlags = SDL_WINDOW_SHOWN | SDL_WINDOW_MOUSE_FOCUS; Uint32 wndFlags = SDL_WINDOW_SHOWN | SDL_WINDOW_MOUSE_FOCUS;
int xpos, ypos; int xpos, ypos;
int num_displays = SDL_GetNumVideoDisplays();
SDL_Rect rect = { window_xpos.value, window_ypos.value, width, height };
Q_strncpy( wndname, GI->title, sizeof( wndname )); Q_strncpy( wndname, GI->title, sizeof( wndname ));
@@ -757,35 +772,43 @@ qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
if( window_mode == WINDOW_MODE_WINDOWED ) if( window_mode == WINDOW_MODE_WINDOWED )
{ {
SDL_Rect r; SDL_Rect *display_rects = ( SDL_Rect * )malloc( num_displays * sizeof( SDL_Rect ));
SetBits( wndFlags, SDL_WINDOW_RESIZABLE ); SetBits( wndFlags, SDL_WINDOW_RESIZABLE );
if( maximized ) if( maximized )
SetBits( wndFlags, SDL_WINDOW_MAXIMIZED ); SetBits( wndFlags, SDL_WINDOW_MAXIMIZED );
#if SDL_VERSION_ATLEAST( 2, 0, 5 ) if( !display_rects )
if( SDL_GetDisplayUsableBounds( 0, &r ) < 0 &&
SDL_GetDisplayBounds( 0, &r ) < 0 )
#else
if( SDL_GetDisplayBounds( 0, &r ) < 0 )
#endif
{ {
Con_Reportf( S_ERROR "%s: SDL_GetDisplayBounds failed: %s\n", __func__, SDL_GetError( )); Con_Printf( S_ERROR "Failed to allocate memory for display rects!\n" );
xpos = SDL_WINDOWPOS_CENTERED; xpos = SDL_WINDOWPOS_UNDEFINED;
ypos = SDL_WINDOWPOS_CENTERED; ypos = SDL_WINDOWPOS_UNDEFINED;
} }
else else
{ {
xpos = window_xpos.value; for( int i = 0; i < num_displays; i++ )
ypos = window_ypos.value; {
if( SDL_GetDisplayBounds( i, &display_rects[i] ) != 0 )
// don't create window outside of usable display space {
if( xpos < r.x || xpos + width > r.x + r.w ) Con_Printf( S_ERROR "Failed to get bounds for display %d! SDL_Error: %s\n", i, SDL_GetError());
display_rects[i] = ( SDL_Rect ){ 0, 0, 0, 0 };
}
}
// Check if the rectangle fits in any display
if( !RectFitsInAnyDisplay( &rect, display_rects, num_displays ))
{
// Rectangle doesn't fit in any display, center it
xpos = SDL_WINDOWPOS_CENTERED; xpos = SDL_WINDOWPOS_CENTERED;
if( ypos < r.y || ypos + height > r.y + r.h )
ypos = SDL_WINDOWPOS_CENTERED; ypos = SDL_WINDOWPOS_CENTERED;
Con_Printf( S_ERROR "Rectangle does not fit in any display. Centering window.\n" );
}
else
{
xpos = rect.x;
ypos = rect.y;
}
} }
free( display_rects );
} }
else else
{ {
@@ -795,7 +818,16 @@ qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
else else
SetBits( wndFlags, SDL_WINDOW_FULLSCREEN_DESKTOP ); SetBits( wndFlags, SDL_WINDOW_FULLSCREEN_DESKTOP );
SetBits( wndFlags, SDL_WINDOW_BORDERLESS ); SetBits( wndFlags, SDL_WINDOW_BORDERLESS );
xpos = ypos = 0; if ( window_xpos.value < 0 || window_ypos.value < 0 )
{
xpos = SDL_WINDOWPOS_UNDEFINED;
ypos = SDL_WINDOWPOS_UNDEFINED;
}
else
{
xpos = window_xpos.value;
ypos = window_ypos.value;
}
} }
if( !VID_CreateWindowWithSafeGL( wndname, xpos, ypos, width, height, wndFlags )) if( !VID_CreateWindowWithSafeGL( wndname, xpos, ypos, width, height, wndFlags ))
@@ -1018,7 +1050,8 @@ qboolean R_Init_Video( const int type )
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) #if SDL_VERSION_ATLEAST( 2, 0, 0 )
SDL_DisplayMode displayMode; SDL_DisplayMode displayMode;
SDL_GetCurrentDisplayMode( 0, &displayMode ); SDL_Point point = { window_xpos.value, window_ypos.value };
SDL_GetCurrentDisplayMode( SDL_GetPointDisplayIndex( &point ), &displayMode );
refState.desktopBitsPixel = SDL_BITSPERPIXEL( displayMode.format ); refState.desktopBitsPixel = SDL_BITSPERPIXEL( displayMode.format );
#else #else
refState.desktopBitsPixel = 16; refState.desktopBitsPixel = 16;

View File

@@ -49,10 +49,6 @@ typedef struct
qboolean inputEnabled; qboolean inputEnabled;
qboolean consoleVisible; qboolean consoleVisible;
qboolean attached; qboolean attached;
// log stuff
qboolean log_active;
char log_path[MAX_SYSPATH];
} WinConData; } WinConData;
static WinConData s_wcd; static WinConData s_wcd;
@@ -145,7 +141,7 @@ void Wcon_ShowConsole( qboolean show )
void Wcon_DisableInput( void ) void Wcon_DisableInput( void )
{ {
if( host.type != HOST_DEDICATED ) if( host.type != HOST_DEDICATED || !s_wcd.hWnd )
return; return;
s_wcd.inputEnabled = false; s_wcd.inputEnabled = false;
@@ -469,6 +465,9 @@ print into window console
*/ */
void Wcon_WinPrint( const char *pMsg ) void Wcon_WinPrint( const char *pMsg )
{ {
if( !s_wcd.hWnd )
return;
int nLen; int nLen;
if( s_wcd.consoleTextLen ) if( s_wcd.consoleTextLen )
{ {
@@ -499,29 +498,28 @@ create win32 console
*/ */
void Wcon_CreateConsole( qboolean con_showalways ) void Wcon_CreateConsole( qboolean con_showalways )
{ {
if( Sys_CheckParm( "-log" ))
s_wcd.log_active = true;
if( host.type == HOST_NORMAL ) if( host.type == HOST_NORMAL )
{ {
Q_strncpy( s_wcd.title, XASH_ENGINE_NAME " " XASH_VERSION, sizeof( s_wcd.title )); Q_strncpy( s_wcd.title, XASH_ENGINE_NAME " " XASH_VERSION, sizeof( s_wcd.title ));
Q_strncpy( s_wcd.log_path, "engine.log", sizeof( s_wcd.log_path ));
} }
else // dedicated console else // dedicated console
{ {
Q_strncpy( s_wcd.title, XASH_DEDICATED_SERVER_NAME " " XASH_VERSION, sizeof( s_wcd.title )); Q_strncpy( s_wcd.title, XASH_DEDICATED_SERVER_NAME " " XASH_VERSION, sizeof( s_wcd.title ));
Q_strncpy( s_wcd.log_path, "dedicated.log", sizeof( s_wcd.log_path ));
s_wcd.log_active = true; // always make log
} }
s_wcd.attached = ( AttachConsole( ATTACH_PARENT_PROCESS ) != 0 ); s_wcd.attached = ( AttachConsole( ATTACH_PARENT_PROCESS ) != 0 );
if( s_wcd.attached ) { if( s_wcd.attached )
{
GetConsoleTitle( &s_wcd.previousTitle, sizeof( s_wcd.previousTitle )); GetConsoleTitle( &s_wcd.previousTitle, sizeof( s_wcd.previousTitle ));
s_wcd.previousCodePage = GetConsoleCP(); s_wcd.previousCodePage = GetConsoleCP();
s_wcd.previousOutputCodePage = GetConsoleOutputCP(); s_wcd.previousOutputCodePage = GetConsoleOutputCP();
} }
else { else
AllocConsole(); {
if( host.type != HOST_DEDICATED && host_developer.value == DEV_NONE )
return; // don't initialize console in case of regular game startup, it's useless anyway
else
AllocConsole();
} }
SetConsoleTitle( s_wcd.title ); SetConsoleTitle( s_wcd.title );
@@ -570,7 +568,7 @@ register console commands (dedicated only)
*/ */
void Wcon_InitConsoleCommands( void ) void Wcon_InitConsoleCommands( void )
{ {
if( host.type != HOST_DEDICATED ) if( host.type != HOST_DEDICATED || !s_wcd.hWnd )
return; return;
Cmd_AddCommand( "clear", Wcon_Clear_f, "clear console history" ); Cmd_AddCommand( "clear", Wcon_Clear_f, "clear console history" );
@@ -588,8 +586,6 @@ void Wcon_DestroyConsole( void )
// last text message into console or log // last text message into console or log
Con_Reportf( "%s: Unloading xash.dll\n", __func__ ); Con_Reportf( "%s: Unloading xash.dll\n", __func__ );
Sys_CloseLog( NULL );
if( !s_wcd.attached ) if( !s_wcd.attached )
{ {
if( s_wcd.hWnd ) if( s_wcd.hWnd )
@@ -623,7 +619,7 @@ char *Wcon_Input( void )
DWORD eventsCount; DWORD eventsCount;
static INPUT_RECORD events[1024]; static INPUT_RECORD events[1024];
if( !s_wcd.inputEnabled ) if( !s_wcd.inputEnabled || !s_wcd.hWnd )
return NULL; return NULL;
while( true ) while( true )
@@ -666,7 +662,7 @@ set server status string in console
*/ */
void Platform_SetStatus( const char *pStatus ) void Platform_SetStatus( const char *pStatus )
{ {
if( s_wcd.attached ) if( s_wcd.attached || !s_wcd.hWnd )
return; return;
Q_strncpy( s_wcd.statusLine, pStatus, sizeof( s_wcd.statusLine ) - 1 ); Q_strncpy( s_wcd.statusLine, pStatus, sizeof( s_wcd.statusLine ) - 1 );

View File

@@ -14,11 +14,15 @@ GNU General Public License for more details.
*/ */
#include "platform/platform.h" #include "platform/platform.h"
#include "input.h"
#define DBGHELP 1 // we always enable dbghelp.dll on Windows targets #define DBGHELP 1 // we always enable dbghelp.dll on Windows targets
#if DBGHELP #if XASH_SDL
#include <SDL.h>
#endif // XASH_SDL
#if DBGHELP
#include <winnt.h> #include <winnt.h>
#include <dbghelp.h> #include <dbghelp.h>
#include <psapi.h> #include <psapi.h>
@@ -268,8 +272,8 @@ 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 #if !XASH_DEDICATED
SDL_SetWindowGrab( host.hWnd, SDL_FALSE ); IN_SetMouseGrab( false );
#endif // XASH_SDL #endif // XASH_SDL
#if DBGHELP #if DBGHELP
@@ -318,7 +322,7 @@ static long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo )
return EXCEPTION_CONTINUE_EXECUTION; return EXCEPTION_CONTINUE_EXECUTION;
} }
void Sys_SetupCrashHandler( void ) void Sys_SetupCrashHandler( const char *argv0 )
{ {
SetErrorMode( SEM_FAILCRITICALERRORS ); // no abort/retry/fail errors SetErrorMode( SEM_FAILCRITICALERRORS ); // no abort/retry/fail errors
oldFilter = SetUnhandledExceptionFilter( Sys_Crash ); oldFilter = SetUnhandledExceptionFilter( Sys_Crash );

View File

@@ -18,6 +18,8 @@ GNU General Public License for more details.
#include "server.h" #include "server.h"
#include <shellapi.h> #include <shellapi.h>
HANDLE g_waitable_timer;
#if XASH_TIMER == TIMER_WIN32 #if XASH_TIMER == TIMER_WIN32
double Platform_DoubleTime( void ) double Platform_DoubleTime( void )
{ {
@@ -34,8 +36,74 @@ double Platform_DoubleTime( void )
return (double)( CurrentTime.QuadPart - g_ClockStart.QuadPart ) / (double)( g_PerformanceFrequency.QuadPart ); return (double)( CurrentTime.QuadPart - g_ClockStart.QuadPart ) / (double)( g_PerformanceFrequency.QuadPart );
} }
void Platform_Sleep( int msec )
{
Sleep( msec );
}
#endif // XASH_TIMER == TIMER_WIN32 #endif // XASH_TIMER == TIMER_WIN32
void Win32_Init( qboolean con_showalways )
{
HMODULE hModule = LoadLibrary( "kernel32.dll" );
if( hModule )
{
HANDLE ( __stdcall *pfnCreateWaitableTimerExW)( LPSECURITY_ATTRIBUTES lpTimerAttributes, LPCWSTR lpTimerName, DWORD dwFlags, DWORD dwDesiredAccess );
if(( pfnCreateWaitableTimerExW = (void *)GetProcAddress( hModule, "CreateWaitableTimerExW" )))
{
g_waitable_timer = pfnCreateWaitableTimerExW(
NULL,
NULL,
0x1 /* CREATE_WAITABLE_TIMER_MANUAL_RESET */ | 0x2 /* CREATE_WAITABLE_TIMER_HIGH_RESOLUTION */,
0x0002 /* TIMER_MODIFY_STATE */ | SYNCHRONIZE | DELETE
);
}
FreeLibrary( hModule );
}
#if 0 // FIXME: creates object but doesn't wait for specific time for me on Windows 10, with the code above commented
if( !g_waitable_timer )
g_waitable_timer = CreateWaitableTimer( NULL, TRUE, NULL );
#endif
Wcon_CreateConsole( con_showalways );
}
void Win32_Shutdown( void )
{
Wcon_DestroyConsole( );
if( g_waitable_timer )
{
CloseHandle( g_waitable_timer );
g_waitable_timer = 0;
}
}
qboolean Win32_NanoSleep( int nsec )
{
LARGE_INTEGER ts;
if( !g_waitable_timer )
return false;
ts.QuadPart = -nsec / 100;
if( !SetWaitableTimer( g_waitable_timer, &ts, 0, NULL, NULL, FALSE ))
{
CloseHandle( g_waitable_timer );
g_waitable_timer = 0;
return false;
}
if( WaitForSingleObject( g_waitable_timer, Q_max( 1, nsec / 1000000 )) != WAIT_OBJECT_0 )
return false;
return true;
}
qboolean Platform_DebuggerPresent( void ) qboolean Platform_DebuggerPresent( void )
{ {
return IsDebuggerPresent(); return IsDebuggerPresent();

View File

@@ -348,7 +348,7 @@ typedef struct ref_api_s
void (*Con_NXPrintf)( struct con_nprint_s *info, const char *fmt, ... ) FORMAT_CHECK( 2 ); void (*Con_NXPrintf)( struct con_nprint_s *info, const char *fmt, ... ) FORMAT_CHECK( 2 );
void (*CL_CenterPrint)( const char *s, float y ); void (*CL_CenterPrint)( const char *s, float y );
void (*Con_DrawStringLen)( const char *pText, int *length, int *height ); void (*Con_DrawStringLen)( const char *pText, int *length, int *height );
int (*Con_DrawString)( int x, int y, const char *string, rgba_t setColor ); int (*Con_DrawString)( int x, int y, const char *string, const rgba_t setColor );
void (*CL_DrawCenterPrint)( void ); void (*CL_DrawCenterPrint)( void );
// entity management // entity management

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