Compare commits

...

147 Commits

Author SHA1 Message Date
Alibek Omarov
3f81af50af engine: platform: allow querying window type through R_GetWindowHandle 2025-05-24 21:28:09 +05:00
TheEVolk
735f4e2bcb ref_api: make handle as argument and use type request input 2025-05-24 20:47:28 +05:00
TheEVolk
9ebeb520fa engine: platform: refactor R_GetWindowHandle to return a struct instead of a pointer 2025-05-24 20:47:28 +05:00
TheEVolk
dd52840a97 ref_api: update REF_API_VERSION to 10 and document R_GetWindowHandle addition 2025-05-24 20:47:28 +05:00
TheEVolk
4ce03662d9 ref_api: R_GetWindowHandle method 2025-05-24 20:47:28 +05:00
Andrey Akhmichin
20320d8dfa Documentation: not-supported-mod-list-and-reasons-why.md: update. 2025-05-24 20:45:28 +05:00
Alibek Omarov
f2ecdad5bb engine: disable clipnodes remapping for non-extended formats and QBSP2 2025-05-24 20:43:44 +05:00
Alibek Omarov
298842be32 engine: fix clipnodes limit check based on BSP version 2025-05-24 17:43:01 +05:00
Alibek Omarov
15544cde26 engine: common: fix typo in aguirRe nickname [skip ci] 2025-05-21 17:43:05 +05:00
Alibek Omarov
a4ad537e59 engine: server: minor refactoring 2025-05-20 20:24:42 +05:00
Alibek Omarov
7ba48e00bc 3rdparty: libbacktrace: sort entries in config.h to keep it the same between reconfigurations
Multicheck parallel nature caused config.h entries to be sorted randomly and
libbacktrace recompiled on every occasion.
2025-05-20 15:25:39 +05:00
Alibek Omarov
bb620d1265 engine: client: set cl_upmax to 508 by default 2025-05-20 14:35:29 +05:00
SNMetamorph
32e6f37c7e engine: server: fixed incorrect printing of IPv6 address in "status" command 2025-05-12 14:11:09 +03:00
Alibek Omarov
8f95535390 engine: server: fix a typo that prevented "status" command from executing by spawned player 2025-05-12 11:37:11 +03:00
Alibek Omarov
b2444f2480 engine: restore SDL2 include path 2025-05-11 18:01:17 +03:00
Alibek Omarov
37d6d75e69 engine: platform: sdl3: add system and input SDL3 platform implementation 2025-05-11 17:35:13 +03:00
Alibek Omarov
97bdd9dba0 engine: port occasional SDL2 calls to SDL3, no platform yet 2025-05-11 16:18:10 +03:00
Alibek Omarov
ffc8bf30d7 engine: platform: make most input platform functions optional, patch fbdev/evdev to compile 2025-05-11 16:14:36 +03:00
Alibek Omarov
8209a8a681 engine: platform: move mouse grab enabling and querying functions to SDL platform code 2025-05-11 16:09:57 +03:00
Alibek Omarov
34beb9666b engine: soundlib: drop SDL-based resampler 2025-05-11 15:27:50 +03:00
Alibek Omarov
6ccafbe297 engine: platform: move Host_Minimize_f into platform code 2025-05-11 15:24:52 +03:00
Andrey Akhmichin
a479099804 utils: mdldec: write all GoldSource-compatible motion-types with "-m" option. 2025-05-11 03:40:57 +03:00
Alibek Omarov
94791d3cb6 engine: allow downloading files that have multiple dots in filename. Also disallow everything that has nonprintable characters. 2025-05-06 21:16:06 +03:00
Alibek Omarov
6555562e78 engine: common: fix building tests 2025-05-06 21:15:28 +03:00
Alibek Omarov
de790d6f59 Revert "engine: server: increased sv_connect_timeout to a half a minute"
This reverts commit 3fca1bb4d5.
2025-05-06 20:22:20 +03:00
Alibek Omarov
cff0df60a9 engine: server: also bump timeouts for connected clients during changelevel in server activation 2025-05-06 20:19:17 +03:00
Alibek Omarov
c8b8e19ed3 engine: server: fix time out on change level 2025-05-06 20:11:41 +03:00
Alibek Omarov
2106556dec engine: server: limit status and build info commands only to spawned clients 2025-05-06 19:50:51 +03:00
Alibek Omarov
7221bd6049 engine: server: small refactoring 2025-05-06 19:50:26 +03:00
Alibek Omarov
ded38020d3 engine: server: add new client state cs_spawning, to ensure that client cannot spawn before it has an entity 2025-05-06 19:37:54 +03:00
Alibek Omarov
c6251174df engine: server: don't let unspawned player execute ent tools commands or send voice data 2025-05-06 19:02:32 +03:00
Alibek Omarov
177c132969 engine: common: fix incorrect argument name, which also fixes build with compilers that enforce C23 2025-05-06 19:00:18 +03:00
Alibek Omarov
3fca1bb4d5 engine: server: increased sv_connect_timeout to a half a minute 2025-05-06 16:28:29 +03:00
Alibek Omarov
321e28c810 scripts: waifulib: sdl2: fix SDL3 sanity test 2025-05-05 18:51:01 +03:00
Alibek Omarov
7fda58561f engine: platform: sdl2: remove SDL1.2 code, as it's now moved into it's own separate directory 2025-05-05 05:56:23 +03:00
Alibek Omarov
0cbb62b329 engine: platform: try to restore SDL1.2 support (only ref_soft is tested, ref_gl doesn't work) 2025-05-05 05:44:31 +03:00
Alibek Omarov
aa2e5eb3cc engine: platform: move SDL2 support code into sdl2 subdirectory. Change XASH_SDL macro value from 12 to 1 for SDL1.2 2025-05-05 05:15:10 +03:00
Alibek Omarov
3d26ba1ed8 engine: client: always pass a valid pointer to usercmd_t in ref_params_t to prevent crassh when client.dll reads them during demo playback 2025-05-05 03:40:18 +03:00
Alibek Omarov
47c4844024 engine: platform: sdl: enable building with SDL as old as 2.0.8, it should satisfy everybody masturbating to old software 2025-04-30 17:45:05 +03:00
Alibek Omarov
d457d7d093 filesystem: archive mounting refactoring 2025-04-28 22:28:30 +03:00
Vladimir
43364ec2e9 defaults: enable touch for psvita & nswitch (#2143) 2025-04-27 14:39:58 +03:00
Alibek Omarov
14127c26f5 scripts: gha: don't put dedicated binary in full client tarballs 2025-04-24 23:41:26 +03:00
Alibek Omarov
291f24a611 scripts: cirrus: build dedicated server alongside full client for slightly faster builds 2025-04-24 23:33:59 +03:00
Alibek Omarov
1abb16638f scripts: gha: build dedicated server alongside full client for slightly faster builds 2025-04-24 23:33:59 +03:00
Alibek Omarov
3e41e389c5 engine: lib_common: do not take generic GNU/Linux rules for library naming on Android 2025-04-24 21:53:03 +03:00
Alibek Omarov
5aca143eba engine: disable Android-specific library loader under Termux 2025-04-24 21:46:43 +03:00
Alibek Omarov
60fa855d47 filesystem: wscript: strip lib prefix on Termux too 2025-04-24 21:42:20 +03:00
Alibek Omarov
22661fd446 public: define XASH_TERMUX if __TERMUX__ is defined. Do not enable XASH_MOBILE_PLATFORM for it 2025-04-24 21:40:35 +03:00
Alibek Omarov
61d8d5e12b wscript: detect if we're compiling from Termux 2025-04-24 21:39:46 +03:00
Alibek Omarov
a7f3c04baa engine: platform: android: hide SDL calls under XASH_SDL macro 2025-04-24 21:39:46 +03:00
Alibek Omarov
296e642f09 wscript: look for libm when compiling for Android on Android device itself (e.g. Termux) 2025-04-24 20:52:55 +03:00
Alibek Omarov
75eb1f1e8b filesystem: android: make failing to find JNI env non-fatal 2025-04-24 20:52:18 +03:00
Alibek Omarov
8f4a45baaa engine: platform: win32: set IMAGEHLP_LINE64 structure size as required in dbghelp docs on MSDN 2025-04-21 20:33:30 +03:00
Alibek Omarov
18aac5fd3d readme: update 2025-04-21 20:12:55 +03:00
Alibek Omarov
ca6ca8450b engine: platform: sdl: load .ico file with wide function allowing for icons to be loaded from non-latin game directory 2025-04-21 20:09:39 +03:00
Alibek Omarov
6ecaea3102 engine: system: convert Windows username to utf8 2025-04-21 19:56:49 +03:00
Alibek Omarov
fa47ca0d2d engine: system: make a copy of pw_name just in case 2025-04-21 19:56:23 +03:00
Alibek Omarov
8ce3b4ac93 engine: client: identification: use wide CreateProcess call, ensure that process terminated and it's handles are closed 2025-04-21 19:38:10 +03:00
Alibek Omarov
a7ba705277 engine: platform: win32: make output similar to libbacktrace-based crashhandler, general improvements and refactoring 2025-04-21 18:54:39 +03:00
Alibek Omarov
85a4d296f5 Documentation: not-supported-mod-list-and-reasons-why: clarify that we don't know why Arrange Mod doesn't work on Xash yet [skip ci] 2025-04-21 17:06:11 +03:00
Andrey Akhmichin
4dd8d89459 Documentation: not-supported-mod-list-and-reasons-why.md: update [skip ci] 2025-04-21 17:04:19 +03:00
Alibek Omarov
c564cc96c7 engine: get rid of host.crashed field, as it's a complete duplicate of host.status 2025-04-21 16:59:44 +03:00
Alibek Omarov
0e54200f34 engine: platform: win32: move saving minidumps before showing stacktrace messagebox 2025-04-21 16:58:43 +03:00
Alibek Omarov
fa75c33390 engine: platform: win32: do not set parent window for stacktrace print window 2025-04-21 16:57:27 +03:00
Alibek Omarov
36cb3b2d89 engine: fix incompatible int size when casting pointer to int 2025-04-21 15:54:32 +03:00
Andrey Akhmichin
2f3b03d27a Documentation: opensource-mods.md: add "Counter-Life". 2025-04-20 10:23:53 +03:00
SNMetamorph
f0deac206b Documentation: added initial revision of touch controls configuring guide
Thanks to VladislavKZ and archer for helping with information gathering.
2025-04-18 17:24:44 +03:00
Alibek Omarov
5d0e473cf1 3rdparty: maintui: update 2025-04-16 14:52:46 +03:00
Alibek Omarov
2174fe6d21 ci: update to ubuntu-22.04 2025-04-15 21:04:48 +03:00
Alibek Omarov
5d1e207337 3rdparty: maintui: update 2025-04-15 21:00:38 +03:00
Alibek Omarov
87c209f1f9 engine: server: drop clients that do not continue connecting after smaller timeout 2025-04-15 20:54:27 +03:00
SNMetamorph
ed5ea002d7 Documentation: donate: updated details, changed layout 2025-04-15 18:07:59 +03:00
Alibek Omarov
149593fea5 engine: server: hide Cmd_ForwardToServer call under XASH_DEDICATED just in case, fixes build with debug 2025-04-11 00:34:10 +03:00
Alibek Omarov
8c0f1d65ba 3rdparty: maintui: update 2025-04-10 23:56:55 +03:00
Alibek Omarov
bbf6f1c7b8 scripts: gha: fix generating sources.list on different ubuntu version 2025-04-10 23:37:36 +03:00
Alibek Omarov
3b61e0bbd6 ci: thanks github, ubuntu-latest isn't actually latest 2025-04-10 23:07:39 +03:00
Alibek Omarov
8d2986bc74 3rdparty: maintui: update 2025-04-10 23:02:48 +03:00
Alibek Omarov
27a8adad22 ci: compile risc-v port on ubuntu-latest for newer compilers 2025-04-10 22:48:41 +03:00
Alibek Omarov
64e774377b scripts: gha: fix ppc64el rust target 2025-04-10 22:48:17 +03:00
Alibek Omarov
8ff469d466 3rdparty: maintui: update 2025-04-10 22:26:13 +03:00
Alibek Omarov
a20e961892 scripts: gha: install i686-pc-windows-msvc rust target for cross-compiling 32-bit maintui 2025-04-10 22:02:13 +03:00
Alibek Omarov
8ba30a1c09 scripts: gha: add Rust target for crosscompiling 2025-04-10 20:01:03 +03:00
Alibek Omarov
d570d6d6da scripts: gha: enable building maintui on supported platforms (win32, linux and apple) 2025-04-10 19:21:09 +03:00
Alibek Omarov
882b573e70 wscript: build maintui alongside mainui_cpp, so both could be used and shipped 2025-04-10 19:21:09 +03:00
Andrey Akhmichin
54657c149b utils: mdldec: use separate options for sequences and textures. 2025-04-10 14:57:11 +05:00
Alibek Omarov
9054b11ebd engine: client: let loading custom menu dll with -menulib command line switch 2025-04-09 17:35:36 +03:00
Alibek Omarov
71d31330f9 filesystem: dir: fix possible null dereference 2025-04-05 14:03:24 +05:00
SNMetamorph
ea29699633 scripts: gha: psvita: pinned cmake version to 3.28.3 2025-04-05 12:45:45 +05:00
Andrey Akhmichin
ccb8d611c6 public: add getopt implementation from NetBSD libc. 2025-04-02 12:07:41 +03:00
Andrey Akhmichin
f4d98c056e utils: mdldec: handle unknown options. 2025-04-02 12:07:41 +03:00
Andrey Akhmichin
779adcd838 utils: mdldec: bump version to 1.2. 2025-04-02 12:07:41 +03:00
Andrey Akhmichin
16e2ce0aeb utils: mdldec: avoid brackets. 2025-04-02 12:07:41 +03:00
Andrey Akhmichin
7bfcd4cef0 utils: mdldec: add options to:
- disable log output.
 - use separate directories for smd and texture files.
 - avoid to write paranoia 2 motion types.
 - ignore filesize checks.
 - enable UV coords shifting.
 - show decompiler version.
 - show help.
2025-04-02 12:07:41 +03:00
Andrey Akhmichin
c298635728 utils: mdldec: Makefile: update. 2025-04-02 12:07:41 +03:00
Andrey Akhmichin
92e976952e utils: mdldec: fix UV coords shifting yet again. 2025-04-02 12:07:41 +03:00
Denis Drakhnia
a85bd0c864 maintui: first blood 2025-04-01 14:46:27 +03:00
Alibek Omarov
0a5f175431 mainui: update 2025-03-31 19:18:39 +03:00
Alibek Omarov
da6402ccc2 common: xash3d_types: disable PFN_RETURNS_NONNULL attribute for MCST lcc 2025-03-31 19:14:22 +03:00
Alibek Omarov
9d1b03d119 scripts: gha: build for e2k-8c on GitHub Actions machines 2025-03-31 19:07:47 +03:00
Alibek Omarov
6cf0d7a871 scripts: gha: linux: fix enabling stb_truetype in mainui_cpp 2025-03-31 18:20:23 +03:00
SNMetamorph
d5a6a7ae60 scripts: gha: made voice chat enabled by default for PS Vita platform 2025-03-30 20:24:38 +03:00
SNMetamorph
185374f99f engine: platform: psvita: explicitly exported symbol rintf
This is required for cs16client port for PS Vita.
2025-03-30 20:24:38 +03:00
SNMetamorph
b9072e4642 Documentation: slightly updated PS Vita port installation instructions 2025-03-30 20:24:38 +03:00
yumirak
06e5895d7a engine: client: fix TE_BLOODSPRITE behaviour to GoldSrc 2025-03-26 22:00:10 +03:00
Alibek Omarov
ac5be8156b Revert "wscript: force -Wuninitialized to error"
This reverts commit e615ff0e7f.
2025-03-25 19:10:13 +03:00
Alibek Omarov
8c12a8baed mainui: update 2025-03-25 19:02:00 +03:00
Alibek Omarov
e615ff0e7f wscript: force -Wuninitialized to error 2025-03-25 17:11:51 +03:00
Alibek Omarov
2e8fa60e96 engine: client: don't allow downscaling HUD when using hud_scale's fixed resolution mode 2025-03-25 17:07:05 +03:00
Alibek Omarov
a8ba9124dd engine: server: fix -Wmaybe-uninitialized 2025-03-25 17:07:05 +03:00
Alibek Omarov
f6e8a68b22 engine: imagelib: img_png: fix -Wmaybe-uninitialized 2025-03-25 17:07:05 +03:00
Alibek Omarov
706cc16a86 ref: fix -Wmaybe-uninitialized 2025-03-25 17:06:59 +03:00
Alibek Omarov
a9fd508e47 engine: common: fix reading maybe uninitialized crt_tm variable 2025-03-25 17:04:35 +03:00
Alibek Omarov
90bd72d481 ref: gl: disable blend after we're done drawing sprite "lightmap"
Fixes translucent brush model on renderfx2.bsp (https://twhl.info/vault/view/6933)
which so happened to draw after agrunt sprite, that has "lightmap" enabled
2025-03-25 00:52:11 +03:00
Alibek Omarov
a2a3978de7 engine: server: fix erasing physinfo on client connect, when it was already set by game logic on save restore
Fixes issue when player loses long-jump in Half-Life on save load or level transition.
2025-03-24 23:22:19 +03:00
Andrey Akhmichin
ea70989fd2 utils: mdldec: Fix resource names validity checks. 2025-03-24 01:24:31 +03:00
Andrey Akhmichin
091228bcb3 Documentation: supported-mod-list.md: update. 2025-03-24 01:24:25 +03:00
Alibek Omarov
9c49253388 filesystem: allow symlinks when using listdirectory with dirs_only = true
Should fix special setups when game directories are actually symlinks
2025-03-20 20:31:44 +03:00
Alibek Omarov
eea804a4bf engine: server: improve server op status command output 2025-03-20 05:47:24 +03:00
Alibek Omarov
ecbfdb82f4 engine: server: add requested server command status. Only expose client input devices for now, as everything else might be considered sensitive information 2025-03-20 05:46:49 +03:00
Alibek Omarov
a1950ec7b0 engine: server: tiny refactoring, make SV_CalcPing pointer to client const 2025-03-20 05:44:23 +03:00
Alibek Omarov
6b56e13b60 engine: make local ipv4 address private to net_ws, acquire local addresses with GetLocalAddress function 2025-03-20 05:39:02 +03:00
Alibek Omarov
d93bee0cbc engine: minor refactoring, rename ref_state_t fields to snake case, rename readable names to shorter (no pun intended) long names 2025-03-20 03:11:17 +03:00
Alibek Omarov
5009db6aac engine: client: make renderer loading failure less scary for the user 2025-03-20 03:06:05 +03:00
Alibek Omarov
c389736c2f android: do not crash on Browse button if activity wasn't found 2025-03-20 02:44:37 +03:00
Alibek Omarov
66bdca63ee ref: gl: upload skybox texture object with >= 5800 name only with GL compatibility context, it's not needed on GLES 2025-03-17 08:32:06 +03:00
SNMetamorph
d3f455649e engine: client: implemented xashid for PS Vita platform 2025-03-16 21:34:32 +03:00
SNMetamorph
17ff80d85d engine: platform: psvita: implemented function for getting PSID 2025-03-16 21:34:32 +03:00
SNMetamorph
407d0aa291 engine: wscript: enabled linking library SceLibKernel_stub on PS Vita 2025-03-16 21:34:32 +03:00
Alibek Omarov
d13429a287 game_launch: explicitly call wide or ascii Win32 API function calls 2025-03-16 20:41:57 +03:00
Alibek Omarov
a84204fc75 engine: partial fix to explicitly call ascii or wide Win32 API function calls 2025-03-16 20:41:57 +03:00
SNMetamorph
292ace2d26 engine: client: fixed SQB in CL_ParseEvent & CL_ParseReliableEvent 2025-03-16 20:31:14 +03:00
Alibek Omarov
68a1fbdc2b engine: platform: win32: use widechar versions of LoadLibrary, which fixes loading engine if path contains non-latin characters 2025-03-16 03:16:02 +03:00
Alibek Omarov
d68f29737a public: crtlib: use Q_rint instead of round in Q_pretifymem, so we don't have to link libm when we don't need it 2025-03-16 01:01:13 +03:00
Alibek Omarov
a34edbd8e8 wscript: ok, let's disable format-nonliteral for now 2025-03-15 20:01:47 +03:00
Alibek Omarov
71e2d4ecd4 engine: client: fix another case of format-nonliteral 2025-03-15 19:52:24 +03:00
Alibek Omarov
25656b532a engine: platform: posix: fix a typo 2025-03-15 19:52:00 +03:00
Alibek Omarov
1a791e8556 engine: soundlib: get rid of useless formatstring, which is always the same for all types 2025-03-15 19:36:34 +03:00
Alibek Omarov
ccd31c6b27 engine: imagelib: get rid of useless formatstring, which is always the same for all types 2025-03-15 19:29:11 +03:00
Alibek Omarov
6aeedf201c ref: gl: update dlight texture in case if BLOCK_SIZE changes between maps (going from QBSP to BSP2 or toggling r_large_lightmaps cvar) 2025-03-15 19:23:49 +03:00
Alibek Omarov
c9f8bdfcb0 ref: gl: allow updating texture with NULL data by calling TexImage instead of TexSubImage 2025-03-15 19:20:36 +03:00
Alibek Omarov
3cf4901ad2 engine: fix another case of format-nonliteral 2025-03-15 18:23:38 +03:00
Alibek Omarov
92de3ebc58 wscript: disable format-nonliteral for Clang, it's buggy there 2025-03-15 14:20:11 +03:00
Alibek Omarov
7aa9f23590 public: crtlib: fix Q_pretifymem so it compiles with -Wformat-nonliteral 2025-03-15 14:19:47 +03:00
Alibek Omarov
3d999269eb engine: net_ws: make net6_local global static, as it's not used outside of this translation unit 2025-03-15 01:24:59 +03:00
Alibek Omarov
1e8e4825fa engine: fix remaining -Wformat=2 and force it to -Werror 2025-03-15 01:24:59 +03:00
Alibek Omarov
91bc372811 mainui: update 2025-03-15 01:24:59 +03:00
Alibek Omarov
f9df96d70e engine: server: fix server strings deduplication on 64-bit systems 2025-03-15 01:24:59 +03:00
147 changed files with 4193 additions and 1531 deletions

View File

@@ -7,8 +7,7 @@ task:
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2 libbacktrace - 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
- ./scripts/cirrus/build_freebsd.sh full
task: task:
name: freebsd-15-amd64 name: freebsd-15-amd64
@@ -19,5 +18,4 @@ task:
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2 libbacktrace - 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
- ./scripts/cirrus/build_freebsd.sh full

View File

@@ -15,35 +15,39 @@ jobs:
include: include:
# Linux build specifically want oldest Ubuntu as possible # Linux build specifically want oldest Ubuntu as possible
# to be crossdistribution compatible, otherwise use ubuntu-latest # to be crossdistribution compatible, otherwise use ubuntu-latest
- os: ubuntu-20.04 - os: ubuntu-22.04
targetos: linux targetos: linux
targetarch: amd64 targetarch: amd64
- os: ubuntu-20.04 - os: ubuntu-22.04
targetos: linux targetos: linux
targetarch: i386 targetarch: i386
- os: ubuntu-20.04 - os: ubuntu-22.04
targetos: linux targetos: linux
targetarch: arm64 targetarch: arm64
cross: true cross: true
- os: ubuntu-20.04 - os: ubuntu-22.04
targetos: linux targetos: linux
targetarch: armhf targetarch: armhf
cross: true cross: true
- os: ubuntu-20.04 - os: ubuntu-24.04 # riscv64 would benefit from having latest compilers
targetos: linux targetos: linux
targetarch: riscv64 targetarch: riscv64
cross: true cross: true
- os: ubuntu-20.04 - os: ubuntu-22.04
targetos: linux targetos: linux
targetarch: ppc64el targetarch: ppc64el
cross: true cross: true
# - os: ubuntu-aarch64-20.04 # - os: ubuntu-aarch64-22.04
# targetos: linux # targetos: linux
# targetarch: aarch64 # targetarch: aarch64
- os: ubuntu-20.04 - os: ubuntu-latest
targetos: linux
targetarch: e2k-8c
cross: true
- os: ubuntu-latest
targetos: android targetos: android
targetarch: multiarch targetarch: multiarch
# - os: ubuntu-20.04 # - os: ubuntu-22.04
# targetos: motomagx # targetos: motomagx
# targetarch: armv6 # targetarch: armv6

3
.gitmodules vendored
View File

@@ -37,3 +37,6 @@
[submodule "3rdparty/libbacktrace/libbacktrace"] [submodule "3rdparty/libbacktrace/libbacktrace"]
path = 3rdparty/libbacktrace/libbacktrace path = 3rdparty/libbacktrace/libbacktrace
url = https://github.com/ianlancetaylor/libbacktrace url = https://github.com/ianlancetaylor/libbacktrace
[submodule "3rdparty/maintui"]
path = 3rdparty/maintui
url = https://github.com/numas13/xash3d-maintui.git

View File

@@ -2,6 +2,7 @@
# encoding: utf-8 # encoding: utf-8
from waflib import TaskGen from waflib import TaskGen
from waflib.Tools.c_config import DEFKEYS
FRAGMENT_ATOMIC='''int i; FRAGMENT_ATOMIC='''int i;
int main(void) { int main(void) {
@@ -138,6 +139,8 @@ def configure(conf):
msg='Checking for in parallel' msg='Checking for in parallel'
) )
conf.env[DEFKEYS].sort()
conf.write_config_header() conf.write_config_header()
conf.define('BACKTRACE_SUPPORTED', 1) conf.define('BACKTRACE_SUPPORTED', 1)

1
3rdparty/maintui vendored Submodule

Submodule 3rdparty/maintui added at 0b6ee5b2d8

View File

@@ -2,23 +2,27 @@
On this page you can find links where you can support each developer individually, who has provided public sponsorship information. On this page you can find links where you can support each developer individually, who has provided public sponsorship information.
### [a1batross](https://github.com/a1batross) ## [a1batross](https://github.com/a1batross)
* Initial Xash3D SDL2/Linux port author, Xash3D FWGS engine maintainer, creator of non-commercial Flying With Gauss organization. Initial Xash3D SDL2/Linux port author, Xash3D FWGS engine maintainer, creator of non-commercial Flying With Gauss organization.
* Boosty page: https://boosty.to/a1ba
### [nekonomicon](https://github.com/nekonomicon) * [Boosty page](https://boosty.to/a1ba)
* [hlsdk-portable](https://github.com/FWGS/hlsdk-portable), [mdldec](../utils/mdldec), [opensource-mods.md](opensource-mods.md) maintainer and Xash3D FWGS [contributor](https://github.com/FWGS/xash3d-fwgs/commits?author=nekonomicon) (*BSD/clang port, PNG support, etc). ## [nekonomicon](https://github.com/nekonomicon)
* Boosty page: https://boosty.to/nekonomicon
### [Velaron](https://github.com/Velaron) [hlsdk-portable](https://github.com/FWGS/hlsdk-portable), [mdldec](../utils/mdldec), [opensource-mods.md](opensource-mods.md) maintainer and Xash3D FWGS [contributor](https://github.com/FWGS/xash3d-fwgs/commits?author=nekonomicon) (*BSD/clang port, PNG support, etc).
* [cs16-client](https://github.com/Velaron/cs16-client) & [tf15-client](https://github.com/Velaron/tf15-client) maintainer and Xash3D FWGS [contributor](https://github.com/FWGS/xash3d-fwgs/commits?author=Velaron) (Android port, voice chat, etc).
* BuyMeACoffee page: https://www.buymeacoffee.com/velaron
### [SNMetamorph](https://github.com/SNMetamorph) * [Boosty page](https://boosty.to/nekonomicon)
* [PrimeXT](https://github.com/SNMetamorph/PrimeXT) & [GoldSrc Monitor](https://github.com/SNMetamorph/goldsrc-monitor) maintainer and Xash3D FWGS [contributor](https://github.com/FWGS/xash3d-fwgs/commits?author=SNMetamorph) (Windows port, voice chat, etc).
* BTC: `16GAzK3qei5AwBW7sggXp3yNcFHBtdpxXj` ## [Velaron](https://github.com/Velaron)
* ETH (ERC20): `0xb580eeca9756e3881f9d6d026e28db28eb72a383`
* USDT (ERC20): `0xb580eeca9756e3881f9d6d026e28db28eb72a383` [cs16-client](https://github.com/Velaron/cs16-client) & [tf15-client](https://github.com/Velaron/tf15-client) maintainer and Xash3D FWGS [contributor](https://github.com/FWGS/xash3d-fwgs/commits?author=Velaron) (Android port, voice chat, etc).
* USDC (ERC20): `0xb580eeca9756e3881f9d6d026e28db28eb72a383`
* [BuyMeACoffee page](https://www.buymeacoffee.com/velaron)
## [SNMetamorph](https://github.com/SNMetamorph)
[PrimeXT](https://github.com/SNMetamorph/PrimeXT) & [GoldSrc Monitor](https://github.com/SNMetamorph/goldsrc-monitor) maintainer and Xash3D FWGS [contributor](https://github.com/FWGS/xash3d-fwgs/commits?author=SNMetamorph) (Windows port, voice chat, etc).
* [Boosty page](https://boosty.to/snmetamorph)
* [Other donation methods](https://snmetamorph.github.io/donate)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 400 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@@ -2,10 +2,19 @@
|Name |Version |Why not working |What was made for that |Name |Version |Why not working |What was made for that
|---- |------- |--------------- |---------------------- |---- |------- |--------------- |----------------------
|Blue Shift |The latest steam release |Uses vgui2 library which xash3d does not support |Recreated source code here: https://github.com/FWGS/hlsdk-xash3d/tree/bshift |Area 51 |Update 1 |Uses outdated BSP31 map format and custom HLFX SDK libraries. |You can try [this tool](https://hlfx.ru/forum/showthread.php?threadid=5250) to convert maps but there no warranty if it works.
|Counter Strike |1.6(The latest steam release) |Uses vgui2 library which xash3d does not support |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface |Arrange Mod: Rebirth |v150 |No idea yet. |
|Counter Strike: Condition Zero |The latest steam release |Uses vgui2 library which xash3d does not support |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface |Blue Shift |The latest steam release |Uses vgui2 library which xash3d does not support. |Recreated source code here: https://github.com/FWGS/hlsdk-xash3d/tree/bshift.
|Counter Strike: Condition Zero - Deleted scenes |The latest steam release |Uses vgui2 library which xash3d does not support |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface |Counter Strike |Beta 6.5- |Uses an old WON HL 1.0.0.16- interface. |
|Day of Defeat |The latest steam release |Uses vgui2 library which xash3d does not support |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface | |1.4 |Has encrypted blob instead of normal client.dll. |You can try [this tool](https://aluigi.altervista.org/papers/hldlldec.zip) to decrypt client.dll but there no warranty if it works.
|Sven-Coop |5.0+ |Uses custom GoldSrc engine | | |1.5 |Has encrypted blob instead of normal client.dll. |Decrypted blob here: https://csm.dev/threads/cs-1-5-client-dll-decrypted-patched-for-usage.38845.
| |1.6(The latest steam release) |Uses vgui2 library which xash3d does not support. |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface. Recreated Client Source Code here: https://github.com/Velaron/cs16-client.
|Counter Strike: Condition Zero |The latest steam release |Uses vgui2 library which xash3d does not support. |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface. Recreated Client Source Code here: https://github.com/Velaron/cs16-client.
|Counter Strike: Condition Zero - Deleted scenes |The latest steam release |Uses vgui2 library which xash3d does not support. Uses new sequences code on engine-side that was never used in any other mods before. |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface.
|Day of Defeat |The latest steam release |Uses vgui2 library which xash3d does not support. |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface.
|Half-Life: Extended |Day One demo |Uses many hooks to GoldSource engine and version check. |Just wait new version or use more old version.
|Icon of Hell |Beta 0.99 |Uses outdated BSP31 map format and paranoia 2 libraries. |You can try [this tool](https://hlfx.ru/forum/showthread.php?threadid=5250) to convert maps and use Paranoia 2: The Savior 1.51 libraries but there no warranty if it works.
|Paranoia 2: The Savior |All builds older 1.51 |Uses an old renderer interface and engine features. |
|Rebellion |1.0 |Uses an old WON HL 1.0.0.16- interface. |Recreated source code here: https://github.com/FWGS/hlsdk-xash3d/tree/rebellion.
|Sven-Coop |5.0+ |Uses custom GoldSrc engine. |
|Time Shadows |Beta 0.1 |Uses Direct3D renderer. |

View File

@@ -32,6 +32,9 @@ Version 1.9 mirrored on github - https://github.com/solidi/hl-mods/tree/master/c
## Cold Ice Ressurection ## Cold Ice Ressurection
Mirrored on github - https://github.com/solidi/hl-mods/tree/master/cir Mirrored on github - https://github.com/solidi/hl-mods/tree/master/cir
## Counter-Life
Available on ModDB - https://www.moddb.com/mods/counter-life/downloads/cl-version-1-source-code
## Cthulhu ## Cthulhu
Uploaded to github by Oleg Cherkasky - https://github.com/gunrunners-paradise/Cthulhu-HLmod-SDK Uploaded to github by Oleg Cherkasky - https://github.com/gunrunners-paradise/Cthulhu-HLmod-SDK

View File

@@ -2,11 +2,14 @@
### Prerequisites ### Prerequisites
1. Make sure your PSVita is [set up to run homebrew applications](https://vita.hacks.guide/). 1. Make sure your PSVita is [set up to run homebrew applications](https://vita.hacks.guide/).
2. Install [kubridge](https://github.com/TheOfficialFloW/kubridge/releases/) by copying `kubridge.suprx` to your taiHEN plugins folder (usually `ux0:/tai`) and add it to your `config.txt`, for example: 2. Install [kubridge](https://github.com/TheOfficialFloW/kubridge/releases/). It is recommended to use kubridge version `0.1`, because other versions aren't tested, we don't know are they suitable or not.
Worth to notice, we got reports that automatic plugins management app EasyPlugin have issues with installing kubridge plugin, so it's better to install it manually: by copying `kubridge.suprx` to your taiHEN plugins folder (usually `ux0:/tai`, but could be `ur0:/tai`) and add it to your `config.txt`, for example:
``` ```
*KERNEL *KERNEL
ux0:tai/kubridge.skprx ux0:tai/kubridge.skprx
``` ```
3. Install `libshacccg.suprx` by following [this guide](https://cimmerian.gitbook.io/vita-troubleshooting-guide/shader-compiler/extract-libshacccg.suprx). 3. Install `libshacccg.suprx` by following [this guide](https://cimmerian.gitbook.io/vita-troubleshooting-guide/shader-compiler/extract-libshacccg.suprx).
### Installation ### Installation

View File

@@ -982,27 +982,33 @@ Support for other platforms may be available later.
To run this mod on specific platforms you may be need to compile libraries from **eftd** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable). To run this mod on specific platforms you may be need to compile libraries from **eftd** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
19. **[Half-Life: Blue Shift](https://store.steampowered.com/app/130/HalfLife_Blue_Shift/)** 19. **[Gang Wars](https://www.moddb.com/mods/gangwars)**
To run this mod on specific platforms you may be need to compile libraries from **bshift** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
20. **[Half-Life: Decay](https://www.moddb.com/mods/half-life-decay)**
Currently, you can compile mod libraries for x86 Linux from **pc-decay2** branch [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
Support for other platforms may be available later.
21. **[Half-Life: Echoes](https://www.moddb.com/mods/half-life-echoes)**
To run this mod on specific platforms you may be need to compile libraries from **echoes** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
22. **[Half-Life: Field Intensity](https://www.moddb.com/mods/field-intensity)**
This mod already supports x86 Linux. This mod already supports x86 Linux.
Support for other platforms may be available later. Support for other platforms may be available later.
23. **Half-Life: Gravgun** (unfinished) by *mittorn*, *a1batross* and *Solexid* 20. **[Half-Life: Blue Shift](https://store.steampowered.com/app/130/HalfLife_Blue_Shift/)**
To run this mod on specific platforms you may be need to compile libraries from **bshift** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
21. **[Half-Life: Decay](https://www.moddb.com/mods/half-life-decay)**
Currently, you can compile mod libraries for x86 Linux from **decay-pc** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
Support for other platforms may be available later.
22. **[Half-Life: Echoes](https://www.moddb.com/mods/half-life-echoes)**
To run this mod on specific platforms you may be need to compile libraries from **echoes** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
23. **[Half-Life: Field Intensity](https://www.moddb.com/mods/field-intensity)**
This mod already supports x86 Linux.
Support for other platforms may be available later.
24. **Half-Life: Gravgun** (unfinished) by *mittorn*, *a1batross* and *Solexid*
*Support temporary abandoned* *Support temporary abandoned*
@@ -1012,163 +1018,163 @@ Currently, MSVC is not supported, use MinGW if you need build for Windows.
Mod files: [1](http://mittorn.fwgs.ru/coop-entpatches/), [2](http://mittorn.fwgs.ru/ggm/), [3](https://github.com/nillerusr/gravgun-extras). Mod files: [1](http://mittorn.fwgs.ru/coop-entpatches/), [2](http://mittorn.fwgs.ru/ggm/), [3](https://github.com/nillerusr/gravgun-extras).
24. **[Half-Life: Induction 1.2](https://www.moddb.com/mods/half-life-induction)** 25. **[Half-Life: Induction 1.2](https://www.moddb.com/mods/half-life-induction)**
To run this mod on specific platforms you may be need to compile libraries from **induction_1.2** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable). To run this mod on specific platforms you may be need to compile libraries from **induction_1.2** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
25. **[Half-Life: Invasion](https://www.moddb.com/mods/half-life-invasion)** 26. **[Half-Life: Invasion](https://www.moddb.com/mods/half-life-invasion)**
This mod supports x86 Linux. This mod supports x86 Linux.
Support for other platforms may be available later. Support for other platforms may be available later.
26. **[Half-Life: Intense Force](https://www.moddb.com/downloads/intense-force)** 27. **[Half-Life: Intense Force](https://www.moddb.com/downloads/intense-force)**
This mod already supports x86 Linux. This mod already supports x86 Linux.
To run this mod on specific platforms you may be need to compile libraries from **intense_force** branch of [halflife-featureful](https://github.com/FreeSlave/halflife-featureful). To run this mod on specific platforms you may be need to compile libraries from **intense_force** branch of [halflife-featureful](https://github.com/FreeSlave/halflife-featureful).
27. **[Half-Life: Opposing Force](https://store.steampowered.com/app/50/HalfLife_Opposing_Force/)** 28. **[Half-Life: Opposing Force](https://store.steampowered.com/app/50/HalfLife_Opposing_Force/)**
Steam version already supports x86 Linux. Steam version already supports x86 Linux.
To run this mod on specific platforms you may be need to compile libraries from **opfor** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable). To run this mod on specific platforms you may be need to compile libraries from **opfor** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
28. **[Half-Life: Quest mod](https://csm.dev/threads/half-life-the-quest-mod-isxodniki.38030/)** 29. **[Half-Life: Quest mod](https://csm.dev/threads/half-life-the-quest-mod-isxodniki.38030/)**
To run this mod on specific platforms you may be need to compile libraries from **sci** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable). To run this mod on specific platforms you may be need to compile libraries from **sci** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
29. **[Half-Life: TopDown](https://www.moddb.com/mods/half-life-top-downs)** 30. **[Half-Life: TopDown](https://www.moddb.com/mods/half-life-top-downs)**
To run this mod on specific platforms you may be need to compile libraries from **topdown** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable). To run this mod on specific platforms you may be need to compile libraries from **topdown** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
30. **[Half-Life: Urbicide](https://www.moddb.com/mods/half-life-urbicide)** 31. **[Half-Life: Urbicide](https://www.moddb.com/mods/half-life-urbicide)**
To run this mod on specific platforms you may be need to compile libraries from **hl_urbicide** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable). To run this mod on specific platforms you may be need to compile libraries from **hl_urbicide** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
31. **[Half-Life: Visitors](https://www.moddb.com/mods/half-life-visitors)** 32. **[Half-Life: Visitors](https://www.moddb.com/mods/half-life-visitors)**
To run this mod on specific platforms you may be need to compile libraries from **visitors** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable). To run this mod on specific platforms you may be need to compile libraries from **visitors** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
32. **[Half-Rats: Parasomnia](https://www.moddb.com/mods/half-rats-parasomnia/downloads/half-rats-parasomnia-v10b-steamlinux)** 33. **[Half-Rats: Parasomnia](https://www.moddb.com/mods/half-rats-parasomnia/downloads/half-rats-parasomnia-v10b-steamlinux)**
This mod already supports x86 Linux. This mod already supports x86 Linux.
Support for other platforms may be available later. Support for other platforms may be available later.
33. **[Half-Screwed: Death and Rebirth](https://www.moddb.com/mods/half-screwed)** 34. **[Half-Screwed: Death and Rebirth](https://www.moddb.com/mods/half-screwed)**
To run this mod on specific platforms you may be need to compile libraries from **half-screwed** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable). To run this mod on specific platforms you may be need to compile libraries from **half-screwed** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
34. **[Half-Secret](https://www.moddb.com/mods/half-secret)** 35. **[Half-Secret](https://www.moddb.com/mods/half-secret)**
To run this mod on specific platforms you may be need to compile libraries from **half-secret** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable). To run this mod on specific platforms you may be need to compile libraries from **half-secret** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
35. **[Natural Selection](https://www.moddb.com/mods/natural-selection)** 36. **[Natural Selection](https://www.moddb.com/mods/natural-selection)**
This mod already supports x86 Linux. This mod already supports x86 Linux.
Support for other platforms may be available later. Support for other platforms may be available later.
36. **[Night at the Office](https://www.moddb.com/mods/night-at-the-office)** 37. **[Night at the Office](https://www.moddb.com/mods/night-at-the-office)**
To run this mod on specific platforms you may be need to compile libraries from **noffice** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable). To run this mod on specific platforms you may be need to compile libraries from **noffice** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
37. **[Paranoia](https://www.moddb.com/mods/paranoia)** 38. **[Paranoia](https://www.moddb.com/mods/paranoia)**
*Support temporary abandoned* *Support temporary abandoned*
[Source code](https://github.com/FWGS/paranoia_toolkit). [Source code](https://github.com/FWGS/paranoia_toolkit).
38. **[Poke646](https://poke646.com/)** 39. **[Poke646](https://poke646.com/)**
To run this mod on specific platforms you may be need to compile libraries from **poke646** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable). To run this mod on specific platforms you may be need to compile libraries from **poke646** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
39. **[Poke646: Vendetta](https://poke646.com/)** 40. **[Poke646: Vendetta](https://poke646.com/)**
To run this mod on specific platforms you may be need to compile libraries from **poke646_vendetta** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable). To run this mod on specific platforms you may be need to compile libraries from **poke646_vendetta** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
40. [PrimeXT](https://snmetamorph.github.io/PrimeXT/) 41. [PrimeXT](https://snmetamorph.github.io/PrimeXT/)
[Source code](https://github.com/SNMetamorph/PrimeXT) [Source code](https://github.com/SNMetamorph/PrimeXT)
41. **[Quake Remake](https://www.moddb.com/games/quake-remake)** 42. **[Quake Remake](https://www.moddb.com/games/quake-remake)**
*Support was fully abandoned due Quake Wrapper release.* *Support was fully abandoned due Quake Wrapper release.*
[Actual source code](https://github.com/FWGS/quakeremake) [Actual source code](https://github.com/FWGS/quakeremake)
42. **[Rebellion](https://www.moddb.com/mods/rebellion1)** 43. **[Rebellion](https://www.moddb.com/mods/rebellion1)**
To run this mod on specific platforms you may be need to compile libraries from **rebellion** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable). To run this mod on specific platforms you may be need to compile libraries from **rebellion** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
43. **[Residual Life](https://www.moddb.com/mods/hl-residual-life)** 44. **[Residual Life](https://www.moddb.com/mods/hl-residual-life)**
To run this mod on specific platforms you may be need to compile libraries from **residual_point** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable). To run this mod on specific platforms you may be need to compile libraries from **residual_point** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
44. **[Residual Point](https://www.moddb.com/mods/hl-residual-point)** 45. **[Residual Point](https://www.moddb.com/mods/hl-residual-point)**
To run this mod on specific platforms you may be need to compile libraries from **residual_point** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable). To run this mod on specific platforms you may be need to compile libraries from **residual_point** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
45. **[Ricochet](https://store.steampowered.com/app/60/Ricochet/)** 46. **[Ricochet](https://store.steampowered.com/app/60/Ricochet/)**
This mod already supports x86 Linux. This mod already supports x86 Linux.
Support for other platforms may be available later. Support for other platforms may be available later.
46. [Sewer](https://www.moddb.com/games/half-life/addons/sewer-beta) 47. [Sewer](https://www.moddb.com/games/half-life/addons/sewer-beta)
To run this mod on specific platforms you may be need to compile libraries from **sewer_beta** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable). To run this mod on specific platforms you may be need to compile libraries from **sewer_beta** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
47. [Spirit of Half-Life 1.2](https://www.moddb.com/mods/spirit-of-half-life) 48. [Spirit of Half-Life 1.2](https://www.moddb.com/mods/spirit-of-half-life)
To run this mod on specific platforms you may be need to compile libraries from **sohl1.2** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable). To run this mod on specific platforms you may be need to compile libraries from **sohl1.2** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
48. **[Swiss Cheese Halloween](https://www.moddb.com/mods/half-life-halloween-mod)** 49. **[Swiss Cheese Halloween](https://www.moddb.com/mods/half-life-halloween-mod)**
To run this mod on specific platforms you may be need to compile libraries from **halloween** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable). To run this mod on specific platforms you may be need to compile libraries from **halloween** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
49. **[Team Fortress Classic](https://store.steampowered.com/app/20/Team_Fortress_Classic/)** 50. **[Team Fortress Classic](https://store.steampowered.com/app/20/Team_Fortress_Classic/)**
This mod already supports x86 Linux. This mod already supports x86 Linux.
Currently, only source code of [client part](https://github.com/Velaron/tf15-client) is available. Currently, only source code of [client part](https://github.com/Velaron/tf15-client) is available.
50. **[The Gate](https://www.moddb.com/mods/the-gate)** 51. **[The Gate](https://www.moddb.com/mods/the-gate)**
To run this mod on specific platforms you may be need to compile libraries from **thegate** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable). To run this mod on specific platforms you may be need to compile libraries from **thegate** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
51. **[They Hunger: Trilogy](https://www.moddb.com/mods/they-hunger)** 52. **[They Hunger: Trilogy](https://www.moddb.com/mods/they-hunger)**
To run this mod on specific platforms you may be need to compile libraries from **theyhunger** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable). To run this mod on specific platforms you may be need to compile libraries from **theyhunger** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
52. **[ThreeWave CTF](https://www.moddb.com/games/deathmatch-classic/downloads/threewave-ctf)** 53. **[ThreeWave CTF](https://www.moddb.com/games/deathmatch-classic/downloads/threewave-ctf)**
To run this mod on specific platforms you may be need to compile libraries from **dmc** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable). To run this mod on specific platforms you may be need to compile libraries from **dmc** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
53. **[Times of Troubles](https://www.moddb.com/mods/times-of-troubles)** 54. **[Times of Troubles](https://www.moddb.com/mods/times-of-troubles)**
To run this mod on specific platforms you may be need to compile libraries from **tot** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable). To run this mod on specific platforms you may be need to compile libraries from **tot** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
54. [XashXT](https://csm.dev/threads/xashxt-0-65-rev-4-release-stable.38319/) 55. [XashXT](https://csm.dev/threads/xashxt-0-65-rev-4-release-stable.38319/)
*Support was fully abandoned due PrimeXT development* *Support was fully abandoned due PrimeXT development*
[Source code](https://github.com/FWGS/XashXT-FWGS/) [Source code](https://github.com/FWGS/XashXT-FWGS/)
55. **[X-Half-Life DeathMatch](https://www.moddb.com/mods/xdm)** 56. **[X-Half-Life DeathMatch](https://www.moddb.com/mods/xdm)**
This mod already supports x86 Linux. This mod already supports x86 Linux.
Support for other platforms may be available later. Support for other platforms may be available later.
56. **[Xen-Warrior](https://www.moddb.com/mods/xen-warrior)** 57. **[Xen-Warrior](https://www.moddb.com/mods/xen-warrior)**
To run this mod on specific platforms you may be need to compile libraries from **sohl1.2** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable). To run this mod on specific platforms you may be need to compile libraries from **sohl1.2** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
Don't forget to enable XENWARRIOR build option!!! Don't forget to enable XENWARRIOR build option!!!
57. [Zombie-X](https://www.moddb.com/mods/zombie-x-10-final) 58. [Zombie-X](https://www.moddb.com/mods/zombie-x-10-final)
To run this mod on specific platforms you may be need to compile libraries from **zombie-x** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable). To run this mod on specific platforms you may be need to compile libraries from **zombie-x** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).

View File

@@ -0,0 +1,149 @@
# Touch controls configuring
## Introduction
Thanks to mittorn, we have the ability to fully customize the controls in Xash3D. The new config allows you to not only add and change control buttons, but also create custom menus. There is also a built-in visual editor available, which simplifies the customization process without the need for manual file editing.
## Editor mode usage
1. Launch Xash3D and start the game.
2. To enter the edit mode, click on the gear icon (command `touch_enableedit`).
3. In the edit mode, the grid is displayed. The number of cells can be changed with the command `touch_grid_count` (default is 50). The grid can be disabled with the command `touch_grid_enable 0`.
*Touch controls layout editor*
![](images/editor.jpg)
*Touch profiles window*
![](images/touch-profiles.jpg)
*Touch buttons parameters window*
![](images/touch-buttons.jpg)
## Layout editor features
* **Moving buttons**: click on a button, drag it to the desired location, and release.
* **Resizing buttons**: place your first finger on the top left corner of the button, and use your second finger to resize it.
* **Hiding/showing buttons**: select the button (it will turn red), then use the menu:
* **Close**: closes the editing mode (`touch_disableedit`).
* **Reset**: resets the button to its default values.
* **Hide/Show**: hides or shows the button (`touch_hide <name>` / `touch_show <name>`).
## Working with configuration files / console
All changes made in the visual editor are automatically saved to the touch profile file. The files are located in the `touch_profiles` folder inside game directory. The file name depends on the selected profile.
### Common commands in configuration files
```
// Comment: lines starting with // are ignored.
// Swipe zones for movement. Specify how far you need to swipe to speed up.
// The default values are set to be optimal for a small swipe to immediately walk quickly.
touch_forwardzone "0.060000" ; touch_sidezone "0.060000"
// Sensitivity settings (pitch - horizontal, yaw - vertical).
touch_pitch ; touch_yaw
// Grid settings (see above).
touch_grid_count ; touch_grid_enable
// Draws a border around the button.
touch_set_stroke <thickness> <c> <v> <e> <t>
(<r> - red; <g> - green; <b> - blue; <a> - alpha/transparency)
// Show (1) or hide (0) client buttons.
touch_setclientonly
// Removes all buttons from the screen.
touch_removeall
// Shows all available buttons in the configuration file.
touch_list
// Saves the config after editing. You can specify a new file name.
touch_config_file command.cfg
```
*The full list of buttons in the standard `touch.cfg` file, displayed in the console when using `touch_list`.*
![](images/example2.jpg)
## Adding new buttons
To add a new button, use the console command:
```
touch_addbutton "digits" "touch/key_1.png" "toggle_digits" 0.340000 0.782222 0.400000 0.888889 255 255 255 100 0
```
### Parameters of `touch_addbutton` command
| Parameter | Description |
| --- | --- |
| `"digits"` | Unique name of the button. |
| `"touch/key_1.png"` | Path to the icon file (`.png` format). If the icon is not needed, leave `""`. |
| `"toggle_digits"` | Command to execute after clicking (for example, `"buy"` for purchase). |
| `0.340000` | X coordinate of the upper-left corner of the button. |
| `0.782222` | Y coordinate of the upper-left corner of the button. |
| `0.400000` | X coordinate of the lower-right corner of the button. |
| `0.888889` | Y coordinate of the lower-right corner of the button. |
| `255 255 255` | Button color in RGB format. |
| `100` | Button transparency (0 - fully transparent, 255 - fully opaque). |
| `0` | Flags (see next section). |
## List of flags
Flags define the behavior of the button. Their values are powers of two:
| Flag | Value | Description |
| --- | --- | --- |
| `TOUCH_FL_HIDE` | 1 | Hides the button (not displayed in the game, but visible in the editor). |
| `TOUCH_FL_NOEDIT` | 2 | Disables editing of the button in the editor. |
| `TOUCH_FL_CLIENT` | 4 | The button is client-side (not saved in the main control file). |
| `TOUCH_FL_MP` | 8 | The button is displayed only in multiplayer. |
| `TOUCH_FL_SP` | 16 | The button is displayed only in singleplayer. |
| `TOUCH_FL_DEF_SHOW` | 32 | The button is always displayed on startup. |
| `TOUCH_FL_DEF_HIDE` | 64 | The button is always hidden on startup. |
| `TOUCH_FL_DRAW_ADDITIVE` | 128 | The button colors are added together in blend mode. |
| `TOUCH_FL_STROKE` | 256 | Enables outline stroke around the button. |
Flags can be combined by adding their values together. For example, `5 = 1 + 4` is the combination of `TOUCH_FL_HIDE` and `TOUCH_FL_CLIENT` flags, which is a hidden client button.
*In the image below, the `spray`, `scores`, `messagemode` buttons are displayed simultaneously with the flag 8 and `loadquick`, `savequick` with the flag 16, and each is displayed in the corresponding game mode.*
![](images/example1.jpg)
## Useful commands
* `touch_hide <pattern>`: hides buttons by pattern.
* `touch_setcommand`: changes the command bound to a button.
* `touch_settexture`: quickly changes the button image.
* `touch_setcolor`: sets the button color.
* `touch_exportconfig`: exports the current configuration, including aspect ratio.
## Usage examples
* `touch_hide menu*` hides all buttons with names starting with `menu`.
* `touch_setcolor "attack" 255 160 0 128` changes the color of the primary fire button from opaque white to translucent orange, similar to the color of the HUD in Half-Life.
*Result of executing this command*
![](images/example3.jpg)
* Example of adding a new button with a custom icon (the `lastinv` command is used - quick change between weapons)
![](images/example4.jpg)
*View of this button in layout editor*
![](images/example5.jpg)
## Tips
* To prevent the `look` and `move` buttons from interfering with editing other elements, place them before the others in the configuration file.
* And vice versa, to make a button appear on top of others, place it at the end of the configuration file.
* You can assign commands to buttons that change other buttons, see the previous section "Usage examples".
* After editing each parameter of each individual button in the Touch Buttons section, do not forget to press Save, otherwise the applied parameters will not be saved.
* To create your own icon for the button, you can use any graphics editor (for Android, Photo Editor by iudesk is suitable). Saving conditions:
* Image format - `.png` with transparency (e.g. alpha channel)
* Aspect ratio / size - 1:1 / 256x256
* Path to the icons location - `touch/gfx` inside game directory.
### Additional links
* [Handy palette for selecting color in RGB format](https://www.rapidtables.com/web/color/RGB_Color.html)

View File

@@ -44,7 +44,7 @@ For additional info, run Xash3D with `-help` command line key.
## Build instructions ## Build instructions
We are using Waf build system. If you have some Waf-related questions, I recommend you to read [Waf Book](https://waf.io/book/). We are using Waf build system. If you have some Waf-related questions, I recommend you to read [Waf Book](https://waf.io/book/).
NOTE: NEVER USE GitHub's ZIP ARCHIVES. GitHub doesn't include external dependencies we're using! **NOTE: NEVER USE GitHub's ZIP ARCHIVES. GitHub doesn't include external dependencies we're using!**
### Prerequisites ### Prerequisites
If your CPU is x86 compatible and you're on Windows or Linux, we are building 32-bit code by default. This was done to maintain compatibility with Steam releases of Half-Life and based on it's engine games. If your CPU is x86 compatible and you're on Windows or Linux, we are building 32-bit code by default. This was done to maintain compatibility with Steam releases of Half-Life and based on it's engine games.

View File

@@ -2,6 +2,7 @@ package su.xash.engine.ui.library
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Intent import android.content.Intent
import android.content.ActivityNotFoundException
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
@@ -10,6 +11,7 @@ import android.view.MenuInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast
import androidx.core.view.MenuProvider import androidx.core.view.MenuProvider
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
@@ -73,11 +75,16 @@ class LibraryFragment : Fragment(), MenuProvider {
override fun onMenuItemSelected(menuItem: MenuItem): Boolean { override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
when (menuItem.itemId) { when (menuItem.itemId) {
R.id.action_browse -> { R.id.action_browse -> {
startActivity( try {
Intent(Intent.ACTION_VIEW).setDataAndType( startActivity(
null, "vnd.android.document/directory" Intent(Intent.ACTION_VIEW).setDataAndType(
null, "vnd.android.document/directory"
)
) )
) }
catch(e: ActivityNotFoundException) {
Toast.makeText(getActivity(), R.string.library_fragment_no_file_manager, Toast.LENGTH_LONG).show()
}
} }
R.id.action_install -> { R.id.action_install -> {
@@ -91,4 +98,4 @@ class LibraryFragment : Fragment(), MenuProvider {
return false return false
} }
} }

View File

@@ -33,4 +33,5 @@
<string name="preferences_client_package">Client package</string> <string name="preferences_client_package">Client package</string>
<string name="preferences_server_package">Server package</string> <string name="preferences_server_package">Server package</string>
<string name="preferences_use_icons">Use icons instead of backgrounds</string> <string name="preferences_use_icons">Use icons instead of backgrounds</string>
</resources> <string name="library_fragment_no_file_manager">File manager is missing</string>
</resources>

View File

@@ -140,13 +140,13 @@ Default build-depended cvar and constant values
// Platform overrides // Platform overrides
#if XASH_NSWITCH #if XASH_NSWITCH
#define DEFAULT_TOUCH_ENABLE "0" #define DEFAULT_TOUCH_ENABLE "1"
#define DEFAULT_M_IGNORE "1" #define DEFAULT_M_IGNORE "1"
#define DEFAULT_MODE_WIDTH 1280 #define DEFAULT_MODE_WIDTH 1280
#define DEFAULT_MODE_HEIGHT 720 #define DEFAULT_MODE_HEIGHT 720
#define DEFAULT_ALLOWCONSOLE 1 #define DEFAULT_ALLOWCONSOLE 1
#elif XASH_PSVITA #elif XASH_PSVITA
#define DEFAULT_TOUCH_ENABLE "0" #define DEFAULT_TOUCH_ENABLE "1"
#define DEFAULT_M_IGNORE "1" #define DEFAULT_M_IGNORE "1"
#define DEFAULT_MODE_WIDTH 960 #define DEFAULT_MODE_WIDTH 960
#define DEFAULT_MODE_HEIGHT 544 #define DEFAULT_MODE_HEIGHT 544
@@ -158,7 +158,7 @@ Default build-depended cvar and constant values
#define DEFAULT_M_IGNORE "1" #define DEFAULT_M_IGNORE "1"
#endif // !XASH_MOBILE_PLATFORM && !XASH_NSWITCH #endif // !XASH_MOBILE_PLATFORM && !XASH_NSWITCH
#if XASH_ANDROID || XASH_IOS || XASH_EMSCRIPTEN #if (XASH_ANDROID && !XASH_TERMUX) || XASH_IOS || XASH_EMSCRIPTEN
// this means that libraries are provided with engine, but not in game data // this means that libraries are provided with engine, but not in game data
// You need add library loading code to library.c when adding new platform // You need add library loading code to library.c when adding new platform
#define XASH_INTERNAL_GAMELIBS #define XASH_INTERNAL_GAMELIBS

View File

@@ -91,8 +91,10 @@ typedef int qboolean;
#define NORETURN __attribute__(( noreturn )) #define NORETURN __attribute__(( noreturn ))
#define NONNULL __attribute__(( nonnull )) #define NONNULL __attribute__(( nonnull ))
#define RETURNS_NONNULL __attribute__(( returns_nonnull )) #define RETURNS_NONNULL __attribute__(( returns_nonnull ))
#if __clang__ #if __clang__ || __MCST__
#define PFN_RETURNS_NONNULL // clang has bugged returns_nonnull for functions pointers, it's ignored and generates a warning about objective-c? O_o // clang has bugged returns_nonnull for functions pointers, it's ignored and generates a warning about objective-c? O_o
// lcc doesn't support it at all
#define PFN_RETURNS_NONNULL
#else #else
#define PFN_RETURNS_NONNULL RETURNS_NONNULL #define PFN_RETURNS_NONNULL RETURNS_NONNULL
#endif #endif

View File

@@ -152,19 +152,6 @@ void CL_PlayCDTrack_f( void )
else Con_Printf( "%s: unknown command %s\n", Cmd_Argv( 0 ), command ); else Con_Printf( "%s: unknown command %s\n", Cmd_Argv( 0 ), command );
} }
/*
==================
CL_ScreenshotGetName
==================
*/
static qboolean CL_ScreenshotGetName( const char *fmt, int lastnum, char *filename, size_t size )
{
if( lastnum < 0 || lastnum > 9999 )
return false;
return Q_snprintf( filename, size, fmt, clgame.mapname, lastnum ) > 0;
}
/* /*
============================================================================== ==============================================================================
@@ -270,7 +257,6 @@ void CL_GenericShot_f( void )
case scrshot_normal: case scrshot_normal:
case scrshot_snapshot: case scrshot_snapshot:
{ {
const char *fmt;
string checkname; string checkname;
int i; int i;
@@ -282,15 +268,18 @@ void CL_GenericShot_f( void )
} }
if( type == scrshot_snapshot ) if( type == scrshot_snapshot )
{
fmt = "../%s_%04d.png";
FS_AllowDirectPaths( true ); FS_AllowDirectPaths( true );
}
else fmt = "scrshots/%s_shot%04d.png";
for( i = 0; i < 9999; i++ ) for( i = 0; i < 9999; i++ )
{ {
if( !CL_ScreenshotGetName( fmt, i, checkname, sizeof( checkname ))) int ret;
if( type == scrshot_snapshot )
ret = Q_snprintf( checkname, sizeof( checkname ), "../%s_%04d.png", clgame.mapname, i );
else
ret = Q_snprintf( checkname, sizeof( checkname ), "scrshots/%s_shot%04d.png", clgame.mapname, i );
if( ret <= 0 )
{ {
Con_Printf( S_ERROR "unable to write %s\n", argv0 ); Con_Printf( S_ERROR "unable to write %s\n", argv0 );
FS_AllowDirectPaths( false ); FS_AllowDirectPaths( false );

View File

@@ -642,9 +642,7 @@ static void CL_ReadDemoUserCmd( qboolean discard )
pcmd->sendsize = 1; pcmd->sendsize = 1;
// always delta'ing from null // always delta'ing from null
cl.cmd = &pcmd->cmd; MSG_ReadDeltaUsercmd( &buf, &nullcmd, &pcmd->cmd );
MSG_ReadDeltaUsercmd( &buf, &nullcmd, cl.cmd );
// make sure what interp info contain angles from different frames // make sure what interp info contain angles from different frames
// or lerping will stop working // or lerping will stop working
@@ -656,13 +654,16 @@ static void CL_ReadDemoUserCmd( qboolean discard )
// record update // record update
a->starttime = demo.timestamp; a->starttime = demo.timestamp;
VectorCopy( cl.cmd->viewangles, a->viewangles ); VectorCopy( pcmd->cmd.viewangles, a->viewangles );
demo.lasttime = demo.timestamp; demo.lasttime = demo.timestamp;
} }
// NOTE: we need to have the current outgoing sequence correct // NOTE: we need to have the current outgoing sequence correct
// so we can do prediction correctly during playback // so we can do prediction correctly during playback
cls.netchan.outgoing_sequence = outgoing_sequence; cls.netchan.outgoing_sequence = outgoing_sequence;
// save last usercmd
cl.cmd = pcmd->cmd;
} }
} }
@@ -1145,8 +1146,7 @@ void CL_DemoInterpolateAngles( void )
QuaternionSlerp( q2, q1, frac, q ); QuaternionSlerp( q2, q1, frac, q );
QuaternionAngle( q, cl.viewangles ); QuaternionAngle( q, cl.viewangles );
} }
else if( cl.cmd != NULL ) else VectorCopy( cl.cmd.viewangles, cl.viewangles );
VectorCopy( cl.cmd->viewangles, cl.viewangles );
} }
/* /*

View File

@@ -405,7 +405,11 @@ void CL_ParseReliableEvent( sizebuf_t *msg, connprotocol_t proto )
} }
if( args.entindex > 0 && args.entindex <= cl.maxclients ) if( args.entindex > 0 && args.entindex <= cl.maxclients )
args.angles[PITCH] *= -3.0f; {
args.angles[PITCH] *= 3.0f;
if( !FBitSet( host.features, ENGINE_COMPENSATE_QUAKE_BUG ))
args.angles[PITCH] = -args.angles[PITCH];
}
CL_QueueEvent( FEV_RELIABLE|FEV_SERVER, event_index, delay, &args ); CL_QueueEvent( FEV_RELIABLE|FEV_SERVER, event_index, delay, &args );
} }
@@ -477,7 +481,9 @@ void CL_ParseEvent( sizebuf_t *msg, connprotocol_t proto )
if( state->number > 0 && state->number <= cl.maxclients ) if( state->number > 0 && state->number <= cl.maxclients )
{ {
args.angles[PITCH] *= -3.0f; args.angles[PITCH] *= 3.0f;
if( !FBitSet( host.features, ENGINE_COMPENSATE_QUAKE_BUG ))
args.angles[PITCH] = -args.angles[PITCH];
CL_CalcPlayerVelocity( state->number, args.velocity ); CL_CalcPlayerVelocity( state->number, args.velocity );
args.ducking = ( state->usehull == 1 ); args.ducking = ( state->usehull == 1 );
} }
@@ -487,7 +493,11 @@ void CL_ParseEvent( sizebuf_t *msg, connprotocol_t proto )
if( args.entindex != 0 ) if( args.entindex != 0 )
{ {
if( args.entindex > 0 && args.entindex <= cl.maxclients ) if( args.entindex > 0 && args.entindex <= cl.maxclients )
args.angles[PITCH] /= -3.0f; {
args.angles[PITCH] /= 3.0f;
if( !FBitSet( host.features, ENGINE_COMPENSATE_QUAKE_BUG ))
args.angles[PITCH] = -args.angles[PITCH];
}
} }
} }

View File

@@ -13,8 +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 #if XASH_SDL == 2
#include <SDL.h> // SDL_GetWindowPosition #include <SDL.h> // SDL_GetWindowPosition
#elif XASH_SDL == 3
#include <SDL3/SDL.h> // SDL_GetWindowPosition
#endif // XASH_SDL #endif // XASH_SDL
#include "common.h" #include "common.h"
@@ -1688,7 +1690,7 @@ get actual screen info
*/ */
int GAME_EXPORT CL_GetScreenInfo( SCREENINFO *pscrinfo ) int GAME_EXPORT CL_GetScreenInfo( SCREENINFO *pscrinfo )
{ {
qboolean apply_scale_factor = false; qboolean apply_scale_factor = false; // we don't want floating point inaccuracies
float scale_factor = hud_scale.value; float scale_factor = hud_scale.value;
if( FBitSet( hud_fontscale.flags, FCVAR_CHANGED )) if( FBitSet( hud_fontscale.flags, FCVAR_CHANGED ))
@@ -1706,7 +1708,7 @@ int GAME_EXPORT CL_GetScreenInfo( SCREENINFO *pscrinfo )
if( hud_scale.value >= 320.0f && hud_scale.value >= hud_scale_minimal_width.value ) if( hud_scale.value >= 320.0f && hud_scale.value >= hud_scale_minimal_width.value )
{ {
scale_factor = refState.width / hud_scale.value; scale_factor = refState.width / hud_scale.value;
apply_scale_factor = true; apply_scale_factor = scale_factor > 1.0f;
} }
else if( scale_factor && scale_factor != 1.0f ) else if( scale_factor && scale_factor != 1.0f )
{ {
@@ -2083,6 +2085,7 @@ GetWindowCenterX
static int GAME_EXPORT pfnGetWindowCenterX( void ) static int GAME_EXPORT pfnGetWindowCenterX( void )
{ {
int x = 0; int x = 0;
#if XASH_WIN32 #if XASH_WIN32
if( m_ignore.value ) if( m_ignore.value )
{ {
@@ -2092,7 +2095,7 @@ static int GAME_EXPORT pfnGetWindowCenterX( void )
} }
#endif #endif
#if XASH_SDL == 2 #if XASH_SDL >= 2
SDL_GetWindowPosition( host.hWnd, &x, NULL ); SDL_GetWindowPosition( host.hWnd, &x, NULL );
#endif #endif
@@ -2108,6 +2111,7 @@ GetWindowCenterY
static int GAME_EXPORT pfnGetWindowCenterY( void ) static int GAME_EXPORT pfnGetWindowCenterY( void )
{ {
int y = 0; int y = 0;
#if XASH_WIN32 #if XASH_WIN32
if( m_ignore.value ) if( m_ignore.value )
{ {
@@ -2117,7 +2121,7 @@ static int GAME_EXPORT pfnGetWindowCenterY( void )
} }
#endif #endif
#if XASH_SDL == 2 #if XASH_SDL >= 2
SDL_GetWindowPosition( host.hWnd, NULL, &y ); SDL_GetWindowPosition( host.hWnd, NULL, &y );
#endif #endif
@@ -3410,7 +3414,7 @@ static void GAME_EXPORT NetAPI_Status( net_status_t *status )
status->latency = (connected) ? cl.frames[cl.parsecountmod].latency : 0.0; status->latency = (connected) ? cl.frames[cl.parsecountmod].latency : 0.0;
status->remote_address = cls.netchan.remote_address; status->remote_address = cls.netchan.remote_address;
status->packet_loss = packet_loss; status->packet_loss = packet_loss;
status->local_address = net_local; NET_GetLocalAddress( &status->local_address, NULL ); // NetAPI doesn't know about IPv6
status->rate = rate.value; status->rate = rate.value;
} }

View File

@@ -1273,16 +1273,16 @@ static void pfnEnableTextInput( int enable )
Key_EnableTextInput( enable, false ); Key_EnableTextInput( enable, false );
} }
static int pfnGetRenderers( unsigned int num, char *shortName, size_t size1, char *readableName, size_t size2 ) static int pfnGetRenderers( unsigned int num, char *short_name, size_t size1, char *long_name, size_t size2 )
{ {
if( num >= ref.numRenderers ) if( num >= ref.num_renderers )
return 0; return 0;
if( shortName && size1 ) if( short_name && size1 )
Q_strncpy( shortName, ref.shortNames[num], size1 ); Q_strncpy( short_name, ref.short_names[num], size1 );
if( readableName && size2 ) if( long_name && size2 )
Q_strncpy( readableName, ref.readableNames[num], size2 ); Q_strncpy( long_name, ref.long_names[num], size2 );
return 1; return 1;
} }

View File

@@ -72,7 +72,7 @@ CVAR_DEFINE_AUTO( cl_cmdrate, "30", FCVAR_ARCHIVE, "Max number of command packet
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" );
static CVAR_DEFINE_AUTO( cl_upmax, "1200", FCVAR_ARCHIVE, "max allowed incoming fragment size" ); static CVAR_DEFINE_AUTO( cl_upmax, "508", FCVAR_ARCHIVE, "max allowed incoming fragment size" );
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)" );
@@ -673,7 +673,7 @@ static void CL_CreateCmd( void )
} }
// demo always have commands so don't overwrite them // demo always have commands so don't overwrite them
if( !cls.demoplayback ) cl.cmd = &pcmd->cmd; if( !cls.demoplayback ) cl.cmd = pcmd->cmd;
// predict all unacknowledged movements // predict all unacknowledged movements
CL_PredictMovement( false ); CL_PredictMovement( false );
@@ -3677,7 +3677,7 @@ void CL_Shutdown( void )
{ {
Con_Printf( "%s()\n", __func__ ); Con_Printf( "%s()\n", __func__ );
if( !host.crashed && cls.initialized ) if( host.status != HOST_CRASHED && cls.initialized )
{ {
Host_WriteOpenGLConfig (); Host_WriteOpenGLConfig ();
Host_WriteVideoConfig (); Host_WriteVideoConfig ();

View File

@@ -973,7 +973,7 @@ void CL_MoveSpectatorCamera( void )
CL_SetUpPlayerPrediction( false, true ); CL_SetUpPlayerPrediction( false, true );
CL_SetSolidPlayers( cl.playernum ); CL_SetSolidPlayers( cl.playernum );
CL_RunUsercmd( &cls.spectator_state, &cls.spectator_state, cl.cmd, true, &time, (uint)( time * 100.0 )); CL_RunUsercmd( &cls.spectator_state, &cls.spectator_state, &cl.cmd, true, &time, (uint)( time * 100.0 ));
VectorCopy( cls.spectator_state.client.velocity, cl.simvel ); VectorCopy( cls.spectator_state.client.velocity, cl.simvel );
VectorCopy( cls.spectator_state.client.origin, cl.simorg ); VectorCopy( cls.spectator_state.client.origin, cl.simorg );

View File

@@ -955,7 +955,6 @@ void GAME_EXPORT R_BloodSprite( const vec3_t org, int colorIndex, int modelIndex
if( pTemp->entity.curstate.frame > 8.0f ) if( pTemp->entity.curstate.frame > 8.0f )
pTemp->entity.curstate.frame = pTemp->frameMax; pTemp->entity.curstate.frame = pTemp->frameMax;
pTemp->entity.baseline.origin[2] += COM_RandomFloat( 4.0f, 16.0f ) * size;
pTemp->entity.angles[2] = COM_RandomFloat( 0.0f, 360.0f ); pTemp->entity.angles[2] = COM_RandomFloat( 0.0f, 360.0f );
pTemp->bounceFactor = 0.0f; pTemp->bounceFactor = 0.0f;
} }

View File

@@ -165,7 +165,7 @@ static void V_SetRefParams( ref_params_t *fd )
// get pointers to movement vars and user cmd // get pointers to movement vars and user cmd
fd->movevars = &clgame.movevars; fd->movevars = &clgame.movevars;
fd->cmd = cl.cmd; fd->cmd = &cl.cmd;
// setup viewport // setup viewport
fd->viewport[0] = clgame.viewport[0]; fd->viewport[0] = clgame.viewport[0];

View File

@@ -234,7 +234,7 @@ typedef struct
cl_local_data_t local; cl_local_data_t local;
// player final info // player final info
usercmd_t *cmd; // cl.commands[outgoing_sequence].cmd usercmd_t cmd; // cl.commands[outgoing_sequence].cmd
vec3_t viewangles; vec3_t viewangles;
vec3_t viewheight; vec3_t viewheight;
vec3_t punchangle; vec3_t punchangle;

View File

@@ -2132,20 +2132,31 @@ void Con_CharEvent( int key )
static int Con_LoadSimpleConback( const char *name, int flags ) static int Con_LoadSimpleConback( const char *name, int flags )
{ {
const char *paths[] = { int i;
"gfx/shell/%s.dds",
"gfx/shell/%s.bmp",
"gfx/shell/%s.tga",
"cached/%s640",
"cached/%s",
};
size_t i;
for( i = 0; i < ARRAYSIZE( paths ); i++ ) for( i = 0; i < 5; i++ )
{ {
string path; string path;
Q_snprintf( path, sizeof( path ), paths[i], name ); switch( i )
{
case 0:
Q_snprintf( path, sizeof( path ), "gfx/shell/%s.dds", name );
break;
case 1:
Q_snprintf( path, sizeof( path ), "gfx/shell/%s.bmp", name );
break;
case 2:
Q_snprintf( path, sizeof( path ), "gfx/shell/%s.tga", name );
break;
case 3:
Q_snprintf( path, sizeof( path ), "cached/%s640", name );
break;
case 4:
Q_snprintf( path, sizeof( path ), "cached/%s", name );
break;
}
if( g_fsapi.FileExists( path, false )) if( g_fsapi.FileExists( path, false ))
{ {
int gl_texturenum = ref.dllFuncs.GL_LoadTexture( path, NULL, 0, flags ); int gl_texturenum = ref.dllFuncs.GL_LoadTexture( path, NULL, 0, flags );

View File

@@ -365,10 +365,10 @@ static int ID_GetKeyData( HKEY hRootKey, char *subKey, char *value, LPBYTE data,
{ {
HKEY hKey; HKEY hKey;
if( RegOpenKeyEx( hRootKey, subKey, 0, KEY_QUERY_VALUE, &hKey ) != ERROR_SUCCESS ) if( RegOpenKeyExA( hRootKey, subKey, 0, KEY_QUERY_VALUE, &hKey ) != ERROR_SUCCESS )
return 0; return 0;
if( RegQueryValueEx( hKey, value, NULL, NULL, data, &cbData ) != ERROR_SUCCESS ) if( RegQueryValueExA( hKey, value, NULL, NULL, data, &cbData ) != ERROR_SUCCESS )
{ {
RegCloseKey( hKey ); RegCloseKey( hKey );
return 0; return 0;
@@ -377,13 +377,14 @@ static int ID_GetKeyData( HKEY hRootKey, char *subKey, char *value, LPBYTE data,
RegCloseKey( hKey ); RegCloseKey( hKey );
return 1; return 1;
} }
static int ID_SetKeyData( HKEY hRootKey, char *subKey, DWORD dwType, char *value, LPBYTE data, DWORD cbData)
static int ID_SetKeyData( HKEY hRootKey, char *subKey, DWORD dwType, char *value, LPBYTE data, DWORD cbData )
{ {
HKEY hKey; HKEY hKey;
if( RegCreateKey( hRootKey, subKey, &hKey ) != ERROR_SUCCESS ) if( RegCreateKeyA( hRootKey, subKey, &hKey ) != ERROR_SUCCESS )
return 0; return 0;
if( RegSetValueEx( hKey, value, 0, dwType, data, cbData ) != ERROR_SUCCESS ) if( RegSetValueExA( hKey, value, 0, dwType, data, cbData ) != ERROR_SUCCESS )
{ {
RegCloseKey( hKey ); RegCloseKey( hKey );
return 0; return 0;
@@ -395,7 +396,7 @@ static int ID_SetKeyData( HKEY hRootKey, char *subKey, DWORD dwType, char *value
#define BUFSIZE 4096 #define BUFSIZE 4096
static int ID_RunWMIC(char *buffer, const char *cmdline) static int ID_RunWMIC( char *buffer, const wchar_t *cmdline )
{ {
HANDLE g_IN_Rd = NULL; HANDLE g_IN_Rd = NULL;
HANDLE g_IN_Wr = NULL; HANDLE g_IN_Wr = NULL;
@@ -403,75 +404,92 @@ static int ID_RunWMIC(char *buffer, const char *cmdline)
HANDLE g_OUT_Wr = NULL; HANDLE g_OUT_Wr = NULL;
DWORD dwRead; DWORD dwRead;
BOOL bSuccess = FALSE; BOOL bSuccess = FALSE;
SECURITY_ATTRIBUTES saAttr; wchar_t *cmdline_copy;
STARTUPINFO si = {0}; PROCESS_INFORMATION pi = { 0 };
SECURITY_ATTRIBUTES saAttr =
PROCESS_INFORMATION pi = {0}; {
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); .nLength = sizeof( SECURITY_ATTRIBUTES ),
saAttr.bInheritHandle = TRUE; .bInheritHandle = TRUE,
saAttr.lpSecurityDescriptor = NULL; .lpSecurityDescriptor = NULL,
};
CreatePipe( &g_IN_Rd, &g_IN_Wr, &saAttr, 0 ); CreatePipe( &g_IN_Rd, &g_IN_Wr, &saAttr, 0 );
CreatePipe( &g_OUT_Rd, &g_OUT_Wr, &saAttr, 0 ); CreatePipe( &g_OUT_Rd, &g_OUT_Wr, &saAttr, 0 );
SetHandleInformation( g_IN_Wr, HANDLE_FLAG_INHERIT, 0 ); SetHandleInformation( g_IN_Wr, HANDLE_FLAG_INHERIT, 0 );
si.cb = sizeof(STARTUPINFO); STARTUPINFO si =
si.dwFlags = STARTF_USESTDHANDLES; {
si.hStdInput = g_IN_Rd; .cb = sizeof( STARTUPINFO ),
si.hStdOutput = g_OUT_Wr; .dwFlags = STARTF_USESTDHANDLES,
si.hStdError = g_OUT_Wr; .hStdInput = g_IN_Rd,
si.wShowWindow = SW_HIDE; .hStdOutput = g_OUT_Wr,
si.dwFlags |= STARTF_USESTDHANDLES; .hStdError = g_OUT_Wr,
.wShowWindow = SW_HIDE,
.dwFlags = STARTF_USESTDHANDLES,
};
CreateProcess( NULL, (char*)cmdline, NULL, NULL, true, CREATE_NO_WINDOW , NULL, NULL, &si, &pi ); cmdline_copy = malloc( wcslen( cmdline ) * sizeof( *cmdline_copy ));
CloseHandle( g_OUT_Wr ); if( !CreateProcessW( NULL, cmdline_copy, NULL, NULL, true, CREATE_NO_WINDOW, NULL, NULL, &si, &pi ))
CloseHandle( g_IN_Wr ); goto err;
WaitForSingleObject( pi.hProcess, 500 ); WaitForSingleObject( pi.hProcess, 500 );
bSuccess = ReadFile( g_OUT_Rd, buffer, BUFSIZE, &dwRead, NULL ); bSuccess = ReadFile( g_OUT_Rd, buffer, BUFSIZE, &dwRead, NULL );
buffer[BUFSIZE-1] = 0; buffer[BUFSIZE-1] = 0;
TerminateProcess( pi.hProcess, 0 );
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
err:
CloseHandle( g_IN_Wr );
CloseHandle( g_OUT_Wr );
CloseHandle( g_IN_Rd ); CloseHandle( g_IN_Rd );
CloseHandle( g_OUT_Rd ); CloseHandle( g_OUT_Rd );
free( cmdline_copy );
return bSuccess; return bSuccess;
} }
static int ID_ProcessWMIC( bloomfilter_t *value, const char *cmdline ) static int ID_ProcessWMIC( bloomfilter_t *value, const wchar_t *cmdline )
{ {
char buffer[BUFSIZE], token[BUFSIZE], *pbuf; char buffer[BUFSIZE], token[BUFSIZE], *pbuf;
int count = 0; int count = 0;
if( !ID_RunWMIC( buffer, cmdline ) ) if( !ID_RunWMIC( buffer, cmdline ))
return 0; return 0;
pbuf = COM_ParseFile( buffer, token, sizeof( token )); // Header pbuf = COM_ParseFile( buffer, token, sizeof( token )); // Header
while( pbuf = COM_ParseFile( pbuf, token, sizeof( token ) ) ) while( pbuf = COM_ParseFile( pbuf, token, sizeof( token )))
{ {
if( !ID_VerifyHEX( token ) ) if( !ID_VerifyHEX( token ))
continue; continue;
*value |= BloomFilter_ProcessStr( token ); *value |= BloomFilter_ProcessStr( token );
count ++; count++;
} }
return count; return count;
} }
static int ID_CheckWMIC( bloomfilter_t value, const char *cmdline ) static int ID_CheckWMIC( bloomfilter_t value, const wchar_t *cmdline )
{ {
char buffer[BUFSIZE], token[BUFSIZE], *pbuf; char buffer[BUFSIZE], token[BUFSIZE], *pbuf;
int count = 0; int count = 0;
if( !ID_RunWMIC( buffer, cmdline ) ) if( !ID_RunWMIC( buffer, cmdline ))
return 0; return 0;
pbuf = COM_ParseFile( buffer, token, sizeof( token )); // Header pbuf = COM_ParseFile( buffer, token, sizeof( token )); // Header
while( pbuf = COM_ParseFile( pbuf, token, sizeof( token ) ) ) while( pbuf = COM_ParseFile( pbuf, token, sizeof( token )))
{ {
bloomfilter_t filter; bloomfilter_t filter;
if( !ID_VerifyHEX( token ) ) if( !ID_VerifyHEX( token ))
continue; continue;
filter = BloomFilter_ProcessStr( token ); filter = BloomFilter_ProcessStr( token );
@@ -487,6 +505,10 @@ static int ID_CheckWMIC( bloomfilter_t value, const char *cmdline )
char *IOS_GetUDID( void ); char *IOS_GetUDID( void );
#endif #endif
#if XASH_PSVITA
int PSVita_GetPSID( char *buf, const size_t buflen );
#endif
static bloomfilter_t ID_GenerateRawId( void ) static bloomfilter_t ID_GenerateRawId( void )
{ {
bloomfilter_t value = 0; bloomfilter_t value = 0;
@@ -508,14 +530,22 @@ static bloomfilter_t ID_GenerateRawId( void )
count += ID_ProcessNetDevices( &value ); count += ID_ProcessNetDevices( &value );
#endif #endif
#if XASH_WIN32 #if XASH_WIN32
count += ID_ProcessWMIC( &value, "wmic path win32_physicalmedia get SerialNumber " ); count += ID_ProcessWMIC( &value, L"wmic path win32_physicalmedia get SerialNumber " );
count += ID_ProcessWMIC( &value, "wmic bios get serialnumber " ); count += ID_ProcessWMIC( &value, L"wmic bios get serialnumber " );
#endif #endif
#if XASH_IOS #if XASH_IOS
{ {
value |= BloomFilter_ProcessStr(IOS_GetUDID()); value |= BloomFilter_ProcessStr(IOS_GetUDID());
count ++; count ++;
} }
#endif
#if XASH_PSVITA
{
char data[16];
PSVita_GetPSID( data, sizeof( data ));
value |= BloomFilter_Process( data, sizeof( data ));
count ++;
}
#endif #endif
return value; return value;
} }
@@ -544,8 +574,8 @@ static uint ID_CheckRawId( bloomfilter_t filter )
#endif #endif
#if XASH_WIN32 #if XASH_WIN32
count += ID_CheckWMIC( filter, "wmic path win32_physicalmedia get SerialNumber" ); count += ID_CheckWMIC( filter, L"wmic path win32_physicalmedia get SerialNumber" );
count += ID_CheckWMIC( filter, "wmic bios get serialnumber" ); count += ID_CheckWMIC( filter, L"wmic bios get serialnumber" );
#endif #endif
#if XASH_IOS #if XASH_IOS
@@ -555,6 +585,15 @@ static uint ID_CheckRawId( bloomfilter_t filter )
value = 0; value = 0;
} }
#endif #endif
#if XASH_PSVITA
{
char data[16];
PSVita_GetPSID( data, sizeof( data ));
value = BloomFilter_Process( data, sizeof( data ));
count += (filter & value) == value;
value = 0;
}
#endif
#if 0 #if 0
Msg( "%s: %d\n", __func__, count ); Msg( "%s: %d\n", __func__, count );
#endif #endif

View File

@@ -13,16 +13,17 @@ 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 == 2
#include <SDL.h>
#elif XASH_SDL == 3
#include <SDL3/SDL.h>
#endif
#include "common.h" #include "common.h"
#include "input.h" #include "input.h"
#include "client.h" #include "client.h"
#include "vgui_draw.h" #include "vgui_draw.h"
#include "cursor_type.h" #include "cursor_type.h"
#if XASH_SDL
#include <SDL.h>
#endif
#include "platform/platform.h" #include "platform/platform.h"
void* in_mousecursor; void* in_mousecursor;
@@ -212,20 +213,29 @@ void IN_SetRelativeMouseMode( qboolean set )
if( set && !s_bRawInput ) if( set && !s_bRawInput )
{ {
#if XASH_SDL == 2 #if XASH_SDL >= 2
SDL_GetRelativeMouseState( NULL, NULL ); SDL_GetRelativeMouseState( NULL, NULL );
#if XASH_SDL == 2
SDL_SetRelativeMouseMode( SDL_TRUE ); SDL_SetRelativeMouseMode( SDL_TRUE );
#endif #else // XASH_SDL != 2
SDL_SetWindowRelativeMouseMode( host.hWnd, true );
#endif // XASH_SDL != 2
#endif // XASH_SDL >= 2
s_bRawInput = true; s_bRawInput = true;
if( verbose ) if( verbose )
Con_Printf( "%s: true\n", __func__ ); Con_Printf( "%s: true\n", __func__ );
} }
else if( !set && s_bRawInput ) else if( !set && s_bRawInput )
{ {
#if XASH_SDL == 2 #if XASH_SDL >= 2
SDL_GetRelativeMouseState( NULL, NULL ); SDL_GetRelativeMouseState( NULL, NULL );
#if XASH_SDL == 2
SDL_SetRelativeMouseMode( SDL_FALSE ); SDL_SetRelativeMouseMode( SDL_FALSE );
#endif #else // XASH_SDL != 2
SDL_SetWindowRelativeMouseMode( host.hWnd, false );
#endif // XASH_SDL != 2
#endif // XASH_SDL >= 2
s_bRawInput = false; s_bRawInput = false;
if( verbose ) if( verbose )
Con_Printf( "%s: false\n", __func__ ); Con_Printf( "%s: false\n", __func__ );
@@ -239,18 +249,15 @@ void IN_SetMouseGrab( qboolean set )
if( set && !s_bMouseGrab ) if( set && !s_bMouseGrab )
{ {
#if XASH_SDL Platform_SetMouseGrab( true );
SDL_SetWindowGrab( host.hWnd, SDL_TRUE );
#endif
s_bMouseGrab = true; s_bMouseGrab = true;
if( verbose ) if( verbose )
Con_Printf( "%s: true\n", __func__ ); Con_Printf( "%s: true\n", __func__ );
} }
else if( !set && s_bMouseGrab ) else if( !set && s_bMouseGrab )
{ {
#if XASH_SDL Platform_SetMouseGrab( false );
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
#endif
s_bMouseGrab = false; s_bMouseGrab = false;
if( verbose ) if( verbose )

View File

@@ -433,6 +433,8 @@ static const ref_api_t gEngfuncs =
&clgame.drawFuncs, &clgame.drawFuncs,
&g_fsapi, &g_fsapi,
R_GetWindowHandle,
}; };
static void R_UnloadProgs( void ) static void R_UnloadProgs( void )
@@ -572,7 +574,7 @@ static void R_GetRendererName( char *dest, size_t size, const char *opt )
} }
} }
static qboolean R_LoadRenderer( const char *refopt ) static qboolean R_LoadRenderer( const char *refopt, qboolean quiet )
{ {
string refdll; string refdll;
@@ -583,7 +585,8 @@ static qboolean R_LoadRenderer( const char *refopt )
if( !R_LoadProgs( refdll )) if( !R_LoadProgs( refdll ))
{ {
R_Shutdown(); R_Shutdown();
Sys_Warn( S_ERROR "Can't initialize %s renderer!\n", refdll ); if( !quiet )
Sys_Warn( S_ERROR "Can't initialize %s renderer!\n", refdll );
return false; return false;
} }
@@ -622,7 +625,7 @@ static void SetFullscreenModeFromCommandLine( void )
static void R_CollectRendererNames( void ) static void R_CollectRendererNames( void )
{ {
// ordering is important! // ordering is important!
static const char *shortNames[] = static const char *short_names[] =
{ {
#if XASH_REF_GL_ENABLED #if XASH_REF_GL_ENABLED
"gl", "gl",
@@ -645,7 +648,7 @@ static void R_CollectRendererNames( void )
}; };
// ordering is important here too! // ordering is important here too!
static const char *readableNames[ARRAYSIZE( shortNames )] = static const char *long_names[ARRAYSIZE( short_names )] =
{ {
#if XASH_REF_GL_ENABLED #if XASH_REF_GL_ENABLED
"OpenGL", "OpenGL",
@@ -667,9 +670,9 @@ static void R_CollectRendererNames( void )
#endif #endif
}; };
ref.numRenderers = ARRAYSIZE( shortNames ); ref.num_renderers = ARRAYSIZE( short_names );
ref.shortNames = shortNames; ref.short_names = short_names;
ref.readableNames = readableNames; ref.long_names = long_names;
} }
qboolean R_Init( void ) qboolean R_Init( void )
@@ -730,28 +733,44 @@ qboolean R_Init( void )
requested_cvar[0] = 0; requested_cvar[0] = 0;
if( Sys_GetParmFromCmdLine( "-ref", requested_cmdline )) if( Sys_GetParmFromCmdLine( "-ref", requested_cmdline ))
success = R_LoadRenderer( requested_cmdline ); success = R_LoadRenderer( requested_cmdline, false );
if( !success && COM_CheckString( r_refdll.string ) && Q_stricmp( requested_cmdline, r_refdll.string )) if( !success && COM_CheckString( r_refdll.string ) && Q_stricmp( requested_cmdline, r_refdll.string ))
{ {
Q_strncpy( requested_cvar, r_refdll.string, sizeof( requested_cvar )); Q_strncpy( requested_cvar, r_refdll.string, sizeof( requested_cvar ));
success = R_LoadRenderer( requested_cvar );
// do not show scary messages to user if renderer set in config cannot be loaded
// as game data could be copied from one platform to another, where this renderer
// might not be supported (ref_gl on Android for example)
success = R_LoadRenderer( requested_cvar, !host_developer.value );
} }
if( !success ) if( !success )
{ {
int i; int i;
for( i = 0; i < ref.numRenderers && !success; i++ ) for( i = 0; i < ref.num_renderers; i++ )
{ {
// skip renderer that was requested but failed to load // skip renderer that was requested but failed to load
if( !Q_strcmp( requested_cmdline, ref.shortNames[i] )) if( !Q_strcmp( requested_cmdline, ref.short_names[i] ))
continue; continue;
if( !Q_strcmp( requested_cvar, ref.shortNames[i] )) if( !Q_strcmp( requested_cvar, ref.short_names[i] ))
continue; continue;
success = R_LoadRenderer( ref.shortNames[i] ); // do not show bruteforcing attempts, however, warn user about falling back
// to software mode
if( !Q_strcmp( "soft", ref.short_names[i] ) && !host_developer.value )
Sys_Warn( "Can't initialize any hardware accelerated renderer. Falling back to software rendering...\n" );
success = R_LoadRenderer( ref.short_names[i], !host_developer.value );
if( success )
{
// remember last valid renderer
Cvar_DirectSet( &r_refdll, ref.short_names[i] );
break;
}
} }
} }

View File

@@ -24,12 +24,12 @@ struct ref_state_s
{ {
HINSTANCE hInstance; HINSTANCE hInstance;
qboolean initialized; qboolean initialized;
int numRenderers; int num_renderers;
ref_interface_t dllFuncs; ref_interface_t dllFuncs;
// depends on build configuration // depends on build configuration
const char **shortNames; const char **short_names;
const char **readableNames; const char **long_names;
}; };
extern struct ref_state_s ref; extern struct ref_state_s ref;

View File

@@ -56,12 +56,10 @@ loading and unpack to wav any known sound
*/ */
wavdata_t *FS_LoadSound( const char *filename, const byte *buffer, size_t size ) wavdata_t *FS_LoadSound( const char *filename, const byte *buffer, size_t size )
{ {
const char *ext = COM_FileExtension( filename ); const char *ext = COM_FileExtension( filename );
string path, loadname; string loadname;
qboolean anyformat = true; qboolean anyformat = true;
fs_offset_t filesize = 0; const loadwavfmt_t *format;
const loadwavfmt_t *format;
byte *f;
Sound_Reset(); // clear old sounddata Sound_Reset(); // clear old sounddata
Q_strncpy( loadname, filename, sizeof( loadname )); Q_strncpy( loadname, filename, sizeof( loadname ));
@@ -70,7 +68,7 @@ wavdata_t *FS_LoadSound( const char *filename, const byte *buffer, size_t size )
{ {
// we needs to compare file extension with list of supported formats // we needs to compare file extension with list of supported formats
// and be sure what is real extension, not a filename with dot // and be sure what is real extension, not a filename with dot
for( format = sound.loadformats; format && format->formatstring; format++ ) for( format = sound.loadformats; format && format->ext; format++ )
{ {
if( !Q_stricmp( format->ext, ext )) if( !Q_stricmp( format->ext, ext ))
{ {
@@ -86,28 +84,42 @@ wavdata_t *FS_LoadSound( const char *filename, const byte *buffer, size_t size )
goto load_internal; goto load_internal;
// now try all the formats in the selected list // now try all the formats in the selected list
for( format = sound.loadformats; format && format->formatstring; format++) for( format = sound.loadformats; format && format->ext; format++)
{ {
if( anyformat || !Q_stricmp( ext, format->ext )) if( anyformat || !Q_stricmp( ext, format->ext ))
{ {
Q_snprintf( path, sizeof( path ), qboolean success = false;
format->formatstring, loadname, "", format->ext ); fs_offset_t filesize = 0;
byte *f;
string path;
Q_snprintf( path, sizeof( path ), DEFAULT_SOUNDPATH "%s.%s", loadname, format->ext );
f = FS_LoadFile( path, &filesize, false ); f = FS_LoadFile( path, &filesize, false );
if( f && filesize > 0 ) if( f && filesize > 0 )
{ {
if( format->loadfunc( path, f, filesize )) success = format->loadfunc( path, f, filesize );
{ Mem_Free( f ); // release buffer
Mem_Free(f); // release buffer
return SoundPack(); // loaded
}
else Mem_Free(f); // release buffer
} }
if( success )
return SoundPack(); // loaded
Q_snprintf( path, sizeof( path ), "%s.%s", loadname, format->ext );
f = FS_LoadFile( path, &filesize, false );
if( f && filesize > 0 )
{
success = format->loadfunc( path, f, filesize );
Mem_Free( f ); // release buffer
}
if( success )
return SoundPack();
} }
} }
load_internal: load_internal:
for( format = sound.loadformats; format && format->formatstring; format++ ) for( format = sound.loadformats; format && format->ext; format++ )
{ {
if( anyformat || !Q_stricmp( ext, format->ext )) if( anyformat || !Q_stricmp( ext, format->ext ))
{ {
@@ -148,7 +160,7 @@ open and reading basic info from sound stream
stream_t *FS_OpenStream( const char *filename ) stream_t *FS_OpenStream( const char *filename )
{ {
const char *ext = COM_FileExtension( filename ); const char *ext = COM_FileExtension( filename );
string path, loadname; string loadname;
qboolean anyformat = true; qboolean anyformat = true;
const streamfmt_t *format; const streamfmt_t *format;
stream_t *stream = NULL; stream_t *stream = NULL;
@@ -160,7 +172,7 @@ stream_t *FS_OpenStream( const char *filename )
{ {
// we needs to compare file extension with list of supported formats // we needs to compare file extension with list of supported formats
// and be sure what is real extension, not a filename with dot // and be sure what is real extension, not a filename with dot
for( format = sound.streamformat; format && format->formatstring; format++ ) for( format = sound.streamformat; format && format->ext; format++ )
{ {
if( !Q_stricmp( format->ext, ext )) if( !Q_stricmp( format->ext, ext ))
{ {
@@ -172,12 +184,13 @@ stream_t *FS_OpenStream( const char *filename )
} }
// now try all the formats in the selected list // now try all the formats in the selected list
for( format = sound.streamformat; format && format->formatstring; format++) for( format = sound.streamformat; format && format->ext; format++)
{ {
if( anyformat || !Q_stricmp( ext, format->ext )) if( anyformat || !Q_stricmp( ext, format->ext ))
{ {
Q_snprintf( path, sizeof( path ), string path;
format->formatstring, loadname, "", format->ext );
Q_snprintf( path, sizeof( path ), "%s.%s", loadname, format->ext );
if(( stream = format->openfunc( path )) != NULL ) if(( stream = format->openfunc( path )) != NULL )
{ {

View File

@@ -251,7 +251,7 @@ static void LZSS_BuildHash( lzss_state_t *state, const byte *source )
{ {
lzss_list_t *list; lzss_list_t *list;
lzss_node_t *node; lzss_node_t *node;
unsigned int targetindex = (uint)source & ( state->window_size - 1 ); unsigned int targetindex = (uintptr_t)source & ( state->window_size - 1 );
node = &state->hash_node[targetindex]; node = &state->hash_node[targetindex];
@@ -900,7 +900,7 @@ float GAME_EXPORT pfnTime( void )
qboolean COM_IsSafeFileToDownload( const char *filename ) qboolean COM_IsSafeFileToDownload( const char *filename )
{ {
char lwrfilename[4096]; char lwrfilename[4096];
const char *first, *last; const char *last;
const char *ext; const char *ext;
size_t len; size_t len;
int i; int i;
@@ -934,25 +934,27 @@ qboolean COM_IsSafeFileToDownload( const char *filename )
return true; return true;
} }
for( i = 0; i < len; i++ )
{
if( !isprint( filename[i] ))
return false;
}
Q_strnlwr( filename, lwrfilename, sizeof( lwrfilename )); Q_strnlwr( filename, lwrfilename, sizeof( lwrfilename ));
ext = COM_FileExtension( lwrfilename ); ext = COM_FileExtension( lwrfilename );
if( Q_strpbrk( lwrfilename, "\\:~" ) || Q_strstr( lwrfilename, ".." ) ) if( Q_strpbrk( lwrfilename, "\\:~" ) || Q_strstr( lwrfilename, ".." ))
return false; return false;
if( lwrfilename[0] == '/' ) if( lwrfilename[0] == '/' )
return false; return false;
first = Q_strchr( lwrfilename, '.' );
last = Q_strrchr( lwrfilename, '.' ); last = Q_strrchr( lwrfilename, '.' );
if( first == NULL || last == NULL ) if( last == NULL )
return false; return false;
if( first != last ) if( Q_strlen( last ) != 4 )
return false;
if( Q_strlen( first ) != 4 )
return false; return false;
for( i = 0; i < ARRAYSIZE( file_exts ); i++ ) for( i = 0; i < ARRAYSIZE( file_exts ); i++ )
@@ -1131,6 +1133,7 @@ void Test_RunCommon( void )
{ {
Msg( "Checking COM_IsSafeFileToDownload...\n" ); Msg( "Checking COM_IsSafeFileToDownload...\n" );
TASSERT_EQi( COM_IsSafeFileToDownload( "models/bsg_props/[hl-lab.ru]bush.mdl" ), true );
TASSERT_EQi( COM_IsSafeFileToDownload( "!MD5AAB5E8B307672DA86FBD10AC302BC732" ), true ); TASSERT_EQi( COM_IsSafeFileToDownload( "!MD5AAB5E8B307672DA86FBD10AC302BC732" ), true );
TASSERT_EQi( COM_IsSafeFileToDownload( "!MD56f1ffd8c96bd64c9c27955309f6ecfe6" ), false ); TASSERT_EQi( COM_IsSafeFileToDownload( "!MD56f1ffd8c96bd64c9c27955309f6ecfe6" ), false );
TASSERT_EQi( COM_IsSafeFileToDownload( "!MD5AAB5E8B307672DA86FBD10AC302B.exe" ), false ); TASSERT_EQi( COM_IsSafeFileToDownload( "!MD5AAB5E8B307672DA86FBD10AC302B.exe" ), false );

View File

@@ -342,7 +342,6 @@ typedef struct host_parm_s
qboolean apply_game_config; // when true apply only to game cvars and ignore all other commands qboolean apply_game_config; // when true apply only to game cvars and ignore all other commands
qboolean apply_opengl_config; // when true apply only to opengl cvars and ignore all other commands qboolean apply_opengl_config; // when true apply only to opengl cvars and ignore all other commands
qboolean config_executed; // a bit who indicated was config.cfg already executed e.g. from valve.rc qboolean config_executed; // a bit who indicated was config.cfg already executed e.g. from valve.rc
qboolean crashed; // set to true if crashed
#if XASH_DLL_LOADER #if XASH_DLL_LOADER
qboolean enabledll; qboolean enabledll;
#endif #endif
@@ -358,6 +357,7 @@ typedef struct host_parm_s
int window_center_y; int window_center_y;
string gamedll; string gamedll;
string clientlib; string clientlib;
string menulib;
} host_parm_t; } host_parm_t;
extern host_parm_t host; extern host_parm_t host;
@@ -790,7 +790,7 @@ void Con_NPrintf( int idx, const char *fmt, ... ) FORMAT_CHECK( 2 );
void Con_NXPrintf( con_nprint_t *info, const char *fmt, ... ) FORMAT_CHECK( 2 ); void Con_NXPrintf( con_nprint_t *info, const char *fmt, ... ) FORMAT_CHECK( 2 );
void UI_NPrintf( int idx, const char *fmt, ... ) FORMAT_CHECK( 2 ); void UI_NPrintf( int idx, const char *fmt, ... ) FORMAT_CHECK( 2 );
void UI_NXPrintf( con_nprint_t *info, const char *fmt, ... ) FORMAT_CHECK( 2 ); void UI_NXPrintf( con_nprint_t *info, const char *fmt, ... ) FORMAT_CHECK( 2 );
const char *Info_ValueForKey( const char *s, const char *key ); const char *Info_ValueForKey( const char *s, const char *key ) RETURNS_NONNULL NONNULL;
void Info_RemovePrefixedKeys( char *start, char prefix ); void Info_RemovePrefixedKeys( char *start, char prefix );
qboolean Info_RemoveKey( char *s, const char *key ); qboolean Info_RemoveKey( char *s, const char *key );
qboolean Info_SetValueForKey( char *s, const char *key, const char *value, int maxsize ); qboolean Info_SetValueForKey( char *s, const char *key, const char *value, int maxsize );

View File

@@ -153,7 +153,7 @@ static qboolean Cvar_UpdateInfo( convar_t *var, const char *value, qboolean noti
{ {
if( FBitSet( var->flags, FCVAR_USERINFO )) if( FBitSet( var->flags, FCVAR_USERINFO ))
{ {
if ( Host_IsDedicated() ) if( Host_IsDedicated() )
{ {
// g-cont. this is a very strange behavior... // g-cont. this is a very strange behavior...
char *info = SV_Serverinfo(); char *info = SV_Serverinfo();
@@ -432,8 +432,9 @@ convar_t *Cvar_Get( const char *name, const char *value, int flags, const char *
if( COM_CheckStringEmpty( var->desc )) if( COM_CheckStringEmpty( var->desc ))
{ {
// directly set value // directly set value
freestring( var->string ); size_t len = Q_strlen( value ) + 1;
var->string = copystringpool( cvar_pool, value ); var->string = Mem_Realloc( cvar_pool, var->string, len );
Q_strncpy( var->string, value, len );
var->value = Q_atof( var->string ); var->value = Q_atof( var->string );
SetBits( var->flags, flags ); SetBits( var->flags, flags );
@@ -449,11 +450,14 @@ convar_t *Cvar_Get( const char *name, const char *value, int flags, const char *
if( FBitSet( var->flags, FCVAR_ALLOCATED ) && Q_strcmp( var_desc, var->desc )) if( FBitSet( var->flags, FCVAR_ALLOCATED ) && Q_strcmp( var_desc, var->desc ))
{ {
size_t len = Q_strlen( var_desc ) + 1;
if( !FBitSet( flags, FCVAR_GLCONFIG )) if( !FBitSet( flags, FCVAR_GLCONFIG ))
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 ); var->desc = Mem_Realloc( cvar_pool, var->desc, len );
var->desc = copystringpool( cvar_pool, var_desc ); Q_strncpy( var->desc, var_desc, len );
} }
return var; return var;
@@ -602,9 +606,10 @@ Cvar_Set2
static convar_t *Cvar_Set2( const char *var_name, const char *value ) static convar_t *Cvar_Set2( const char *var_name, const char *value )
{ {
convar_t *var; convar_t *var;
const char *pszValue;
qboolean dll_variable = false; qboolean dll_variable = false;
qboolean force = false; qboolean force = false;
const char *fixed_string;
size_t fixed_string_len;
if( !Cvar_ValidateVarName( var_name, false )) if( !Cvar_ValidateVarName( var_name, false ))
{ {
@@ -668,19 +673,20 @@ static convar_t *Cvar_Set2( const char *var_name, const char *value )
return var; return var;
} }
pszValue = Cvar_ValidateString( var, value ); fixed_string = Cvar_ValidateString( var, value );
// nothing to change // nothing to change
if( !Q_strcmp( pszValue, var->string )) if( !Q_strcmp( fixed_string, var->string ))
return var; return var;
// fill it cls.userinfo, svs.serverinfo // fill it cls.userinfo, svs.serverinfo
if( !Cvar_UpdateInfo( var, pszValue, true )) if( !Cvar_UpdateInfo( var, fixed_string, true ))
return var; return var;
// and finally changed the cvar itself // and finally change the cvar itself
freestring( var->string ); fixed_string_len = Q_strlen( fixed_string ) + 1;
var->string = copystringpool( cvar_pool, pszValue ); var->string = Mem_Realloc( cvar_pool, var->string, fixed_string_len );
Q_strncpy( var->string, fixed_string, fixed_string_len );
var->value = Q_atof( var->string ); var->value = Q_atof( var->string );
// tell engine about changes // tell engine about changes
@@ -697,7 +703,8 @@ way to change value for many cvars
*/ */
void GAME_EXPORT Cvar_DirectSet( convar_t *var, const char *value ) void GAME_EXPORT Cvar_DirectSet( convar_t *var, const char *value )
{ {
const char *pszValue; const char *fixed_string;
size_t fixed_string_len;
if( unlikely( !var )) return; // ??? if( unlikely( !var )) return; // ???
@@ -727,19 +734,20 @@ void GAME_EXPORT Cvar_DirectSet( convar_t *var, const char *value )
value = var->def_string; // reset to default value value = var->def_string; // reset to default value
} }
pszValue = Cvar_ValidateString( var, value ); fixed_string = Cvar_ValidateString( var, value );
// nothing to change // nothing to change
if( !Q_strcmp( pszValue, var->string )) if( !Q_strcmp( fixed_string, var->string ))
return; return;
// fill it cls.userinfo, svs.serverinfo // fill it cls.userinfo, svs.serverinfo
if( !Cvar_UpdateInfo( var, pszValue, true )) if( !Cvar_UpdateInfo( var, fixed_string, true ))
return; return;
// and finally changed the cvar itself // and finally change the cvar itself
freestring( var->string ); fixed_string_len = Q_strlen( fixed_string ) + 1;
var->string = copystringpool( cvar_pool, pszValue ); var->string = Mem_Realloc( cvar_pool, var->string, fixed_string_len );
Q_strncpy( var->string, fixed_string, fixed_string_len );
var->value = Q_atof( var->string ); var->value = Q_atof( var->string );
// tell engine about changes // tell engine about changes
@@ -773,7 +781,8 @@ can set any protected cvars
*/ */
void Cvar_FullSet( const char *var_name, const char *value, int flags ) void Cvar_FullSet( const char *var_name, const char *value, int flags )
{ {
convar_t *var = Cvar_FindVar( var_name ); convar_t *var = Cvar_FindVar( var_name );
size_t len = Q_strlen( value ) + 1;
if( !var ) if( !var )
{ {
@@ -781,8 +790,8 @@ void Cvar_FullSet( const char *var_name, const char *value, int flags )
return; return;
} }
freestring( var->string ); var->string = Mem_Realloc( cvar_pool, var->string, len );
var->string = copystringpool( cvar_pool, value ); Q_strncpy( var->string, value, len );
var->value = Q_atof( var->string ); var->value = Q_atof( var->string );
SetBits( var->flags, flags ); SetBits( var->flags, flags );

View File

@@ -16,8 +16,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 #if XASH_SDL == 2
#include <SDL.h> // SDL_GetBasePath #include <SDL.h> // SDL_GetBasePath
#elif XASH_SDL == 3
#include <SDL3/SDL.h>
#endif #endif
#include <errno.h> #include <errno.h>
@@ -209,7 +211,7 @@ static qboolean FS_DetermineRootDirectory( char *out, size_t size )
return true; return true;
Sys_Error( "couldn't find %s data directory", XASH_ENGINE_NAME ); 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 XASH_APPLE
@@ -328,6 +330,9 @@ void FS_Init( const char *basedir )
if( !Sys_GetParmFromCmdLine( "-clientlib", host.clientlib )) if( !Sys_GetParmFromCmdLine( "-clientlib", host.clientlib ))
host.clientlib[0] = 0; host.clientlib[0] = 0;
if( !Sys_GetParmFromCmdLine( "-menulib", host.menulib ))
host.menulib[0] = 0;
} }
/* /*

View File

@@ -14,9 +14,6 @@ GNU General Public License for more details.
*/ */
#include "build.h" #include "build.h"
#ifdef XASH_SDL
#include <SDL.h>
#endif // XASH_SDL
#include <stdarg.h> // va_args #include <stdarg.h> // va_args
#if !XASH_WIN32 #if !XASH_WIN32
#include <unistd.h> // fork #include <unistd.h> // fork
@@ -177,6 +174,7 @@ static void Sys_PrintUsage( const char *exename )
O("-dll <path> ", "override server DLL path") O("-dll <path> ", "override server DLL path")
#if !XASH_DEDICATED #if !XASH_DEDICATED
O("-clientlib <path> ", "override client DLL path") O("-clientlib <path> ", "override client DLL path")
O("-menulib <path> ", "override menu DLL path")
O("-console ", "run engine with console enabled") O("-console ", "run engine with console enabled")
O("-toconsole ", "run engine witn console open") O("-toconsole ", "run engine witn console open")
O("-oldfont ", "enable unused Quake font in Half-Life") O("-oldfont ", "enable unused Quake font in Half-Life")
@@ -541,13 +539,6 @@ static void Host_MemStats_f( void )
} }
} }
static void Host_Minimize_f( void )
{
#ifdef XASH_SDL
if( host.hWnd ) SDL_MinimizeWindow( host.hWnd );
#endif
}
/* /*
================= =================
Host_RegisterDecal Host_RegisterDecal
@@ -1278,7 +1269,7 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
Cmd_AddRestrictedCommand( "quit", Sys_Quit_f, "quit the game" ); Cmd_AddRestrictedCommand( "quit", Sys_Quit_f, "quit the game" );
Cmd_AddRestrictedCommand( "exit", Sys_Quit_f, "quit the game" ); Cmd_AddRestrictedCommand( "exit", Sys_Quit_f, "quit the game" );
} }
else Cmd_AddRestrictedCommand( "minimize", Host_Minimize_f, "minimize main window to tray" ); else Cmd_AddRestrictedCommand( "minimize", Platform_Minimize_f, "minimize main window to tray" );
host.errorframe = 0; host.errorframe = 0;
@@ -1354,7 +1345,7 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
#endif // XASH_ANDROID #endif // XASH_ANDROID
// main window message loop // main window message loop
while( !host.crashed ) while( host.status != HOST_CRASHED )
{ {
newtime = Sys_DoubleTime (); newtime = Sys_DoubleTime ();
COM_Frame( newtime - oldtime ); COM_Frame( newtime - oldtime );

View File

@@ -220,7 +220,7 @@ void HPAK_AddLump( qboolean bUseQueue, const char *name, resource_t *pResource,
if( pResource->nDownloadSize < HPAK_ENTRY_MIN_SIZE || pResource->nDownloadSize > HPAK_ENTRY_MAX_SIZE ) if( pResource->nDownloadSize < HPAK_ENTRY_MIN_SIZE || pResource->nDownloadSize > HPAK_ENTRY_MAX_SIZE )
{ {
Con_Printf( S_ERROR "%s: invalid size %s\n", name, Q_pretifymem( pResource->nDownloadSize, 2 )); Con_Printf( S_ERROR "%s: invalid size %s\n", name, Q_memprint( pResource->nDownloadSize ));
return; return;
} }
@@ -441,7 +441,7 @@ static qboolean HPAK_Validate( const char *filename, qboolean quiet, qboolean de
if( dataDir[i].disksize < HPAK_ENTRY_MIN_SIZE || dataDir[i].disksize > HPAK_ENTRY_MAX_SIZE ) if( dataDir[i].disksize < HPAK_ENTRY_MIN_SIZE || dataDir[i].disksize > HPAK_ENTRY_MAX_SIZE )
{ {
// odd max size // odd max size
Con_DPrintf( S_ERROR "%s: lump %i has invalid size %s\n", __func__, i, Q_pretifymem( dataDir[i].disksize, 2 )); Con_DPrintf( S_ERROR "%s: lump %i has invalid size %s\n", __func__, i, Q_memprint( dataDir[i].disksize ));
Mem_Free( dataDir ); Mem_Free( dataDir );
FS_Close( f ); FS_Close( f );
if( delete ) FS_Delete( pakname ); if( delete ) FS_Delete( pakname );
@@ -462,7 +462,7 @@ static qboolean HPAK_Validate( const char *filename, qboolean quiet, qboolean de
if( !quiet ) if( !quiet )
{ {
Con_Printf( "%i: %s %s %s: ", i, COM_ResourceTypeFromIndex( pRes->type ), Con_Printf( "%i: %s %s %s: ", i, COM_ResourceTypeFromIndex( pRes->type ),
Q_pretifymem( pRes->nDownloadSize, 2 ), pRes->szFileName ); Q_memprint( pRes->nDownloadSize ), pRes->szFileName );
} }
if( memcmp( md5, pRes->rgucMD5_hash, 0x10 )) if( memcmp( md5, pRes->rgucMD5_hash, 0x10 ))

View File

@@ -45,7 +45,6 @@ typedef enum
typedef struct loadformat_s typedef struct loadformat_s
{ {
const char *formatstring;
const char *ext; const char *ext;
qboolean (*loadfunc)( const char *name, const byte *buffer, fs_offset_t filesize ); qboolean (*loadfunc)( const char *name, const byte *buffer, fs_offset_t filesize );
image_hint_t hint; image_hint_t hint;
@@ -53,7 +52,6 @@ typedef struct loadformat_s
typedef struct saveformat_s typedef struct saveformat_s
{ {
const char *formatstring;
const char *ext; const char *ext;
qboolean (*savefunc)( const char *name, rgbdata_t *pix ); qboolean (*savefunc)( const char *name, rgbdata_t *pix );
} savepixformat_t; } savepixformat_t;

View File

@@ -211,7 +211,7 @@ static const loadpixformat_t *Image_GetLoadFormatForExtension( const char *ext )
if( !COM_CheckStringEmpty( ext )) if( !COM_CheckStringEmpty( ext ))
return NULL; return NULL;
for( format = image.loadformats; format->formatstring; format++ ) for( format = image.loadformats; format->ext; format++ )
{ {
if( !Q_stricmp( ext, format->ext )) if( !Q_stricmp( ext, format->ext ))
return format; return format;
@@ -237,7 +237,7 @@ static qboolean Image_ProbeLoadBuffer( const loadpixformat_t *fmt, const char *n
// bruteforce all loaders // bruteforce all loaders
if( !fmt ) if( !fmt )
{ {
for( fmt = image.loadformats; fmt->formatstring; fmt++ ) for( fmt = image.loadformats; fmt->ext; fmt++ )
{ {
if( Image_ProbeLoadBuffer_( fmt, name, buf, size, override_hint )) if( Image_ProbeLoadBuffer_( fmt, name, buf, size, override_hint ))
return true; return true;
@@ -256,7 +256,7 @@ static qboolean Image_ProbeLoad_( const loadpixformat_t *fmt, const char *name,
string path; string path;
byte *f; byte *f;
Q_snprintf( path, sizeof( path ), fmt->formatstring, name, suffix, fmt->ext ); Q_snprintf( path, sizeof( path ), "%s%s.%s", name, suffix, fmt->ext );
f = FS_LoadFile( path, &filesize, false ); f = FS_LoadFile( path, &filesize, false );
if( f ) if( f )
@@ -274,7 +274,7 @@ static qboolean Image_ProbeLoad( const loadpixformat_t *fmt, const char *name, c
if( !fmt ) if( !fmt )
{ {
// bruteforce all formats to allow implicit extension // bruteforce all formats to allow implicit extension
for( fmt = image.loadformats; fmt->formatstring; fmt++ ) for( fmt = image.loadformats; fmt->ext; fmt++ )
{ {
if( Image_ProbeLoad_( fmt, name, suffix, override_hint )) if( Image_ProbeLoad_( fmt, name, suffix, override_hint ))
return true; return true;
@@ -417,14 +417,13 @@ qboolean FS_SaveImage( const char *filename, rgbdata_t *pix )
picBuffer = pix->buffer; picBuffer = pix->buffer;
// save all sides seperately // save all sides seperately
for( format = image.saveformats; format && format->formatstring; format++ ) for( format = image.saveformats; format && format->ext; format++ )
{ {
if( !Q_stricmp( ext, format->ext )) if( !Q_stricmp( ext, format->ext ))
{ {
for( i = 0; i < 6; i++ ) for( i = 0; i < 6; i++ )
{ {
Q_snprintf( path, sizeof( path ), Q_snprintf( path, sizeof( path ), "%s%s.%s", savename, box[i].suf, format->ext );
format->formatstring, savename, box[i].suf, format->ext );
if( !format->savefunc( path, pix )) break; // there were errors if( !format->savefunc( path, pix )) break; // there were errors
pix->buffer += pix->size; // move pointer pix->buffer += pix->size; // move pointer
} }
@@ -442,12 +441,11 @@ qboolean FS_SaveImage( const char *filename, rgbdata_t *pix )
} }
else else
{ {
for( format = image.saveformats; format && format->formatstring; format++ ) for( format = image.saveformats; format && format->ext; format++ )
{ {
if( !Q_stricmp( ext, format->ext )) if( !Q_stricmp( ext, format->ext ))
{ {
Q_snprintf( path, sizeof( path ), Q_snprintf( path, sizeof( path ), "%s.%s", savename, format->ext );
format->formatstring, savename, "", format->ext );
if( format->savefunc( path, pix )) if( format->savefunc( path, pix ))
{ {
// clear any force flags // clear any force flags

View File

@@ -46,7 +46,7 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
short p, a, b, c, pa, pb, pc; short p, a, b, c, pa, pb, pc;
byte *buf_p, *pixbuf, *raw, *prior, *idat_buf = NULL, *uncompressed_buffer = NULL; byte *buf_p, *pixbuf, *raw, *prior, *idat_buf = NULL, *uncompressed_buffer = NULL;
byte *pallete = NULL, *trns = NULL; byte *pallete = NULL, *trns = NULL;
uint chunk_len, trns_len, plte_len, crc32, crc32_check, oldsize = 0, newsize = 0, rowsize; uint chunk_len, trns_len = 0, plte_len = 0, crc32, crc32_check, oldsize = 0, newsize = 0, rowsize;
uint uncompressed_size, pixel_size, pixel_count, i, y, filter_type, chunk_sign, r_alpha, g_alpha, b_alpha; uint uncompressed_size, pixel_size, pixel_count, i, y, filter_type, chunk_sign, r_alpha, g_alpha, b_alpha;
qboolean has_iend_chunk = false; qboolean has_iend_chunk = false;
z_stream stream = {0}; z_stream stream = {0};

View File

@@ -90,23 +90,23 @@ static byte palette_hl[768] =
// stub // stub
static const loadpixformat_t load_null[] = static const loadpixformat_t load_null[] =
{ {
{ NULL, NULL, NULL, IL_HINT_NO } { NULL, NULL, IL_HINT_NO }
}; };
static const loadpixformat_t load_game[] = static const loadpixformat_t load_game[] =
{ {
{ "%s%s.%s", "dds", Image_LoadDDS, IL_HINT_NO }, // dds for world and studio models { "dds", Image_LoadDDS, IL_HINT_NO }, // dds for world and studio models
{ "%s%s.%s", "bmp", Image_LoadBMP, IL_HINT_NO }, // WON menu images { "bmp", Image_LoadBMP, IL_HINT_NO }, // WON menu images
{ "%s%s.%s", "tga", Image_LoadTGA, IL_HINT_NO }, // hl vgui menus { "tga", Image_LoadTGA, IL_HINT_NO }, // hl vgui menus
{ "%s%s.%s", "png", Image_LoadPNG, IL_HINT_NO }, // NightFire 007 menus { "png", Image_LoadPNG, IL_HINT_NO }, // NightFire 007 menus
{ "%s%s.%s", "mip", Image_LoadMIP, IL_HINT_NO }, // hl textures from wad or buffer { "mip", Image_LoadMIP, IL_HINT_NO }, // hl textures from wad or buffer
{ "%s%s.%s", "mdl", Image_LoadMDL, IL_HINT_HL }, // hl studio model skins { "mdl", Image_LoadMDL, IL_HINT_HL }, // hl studio model skins
{ "%s%s.%s", "spr", Image_LoadSPR, IL_HINT_HL }, // hl sprite frames { "spr", Image_LoadSPR, IL_HINT_HL }, // hl sprite frames
{ "%s%s.%s", "lmp", Image_LoadLMP, IL_HINT_NO }, // hl menu images (cached.wad etc) { "lmp", Image_LoadLMP, IL_HINT_NO }, // hl menu images (cached.wad etc)
{ "%s%s.%s", "fnt", Image_LoadFNT, IL_HINT_HL }, // hl console font (fonts.wad etc) { "fnt", Image_LoadFNT, IL_HINT_HL }, // hl console font (fonts.wad etc)
{ "%s%s.%s", "pal", Image_LoadPAL, IL_HINT_NO }, // install studio\sprite palette { "pal", Image_LoadPAL, IL_HINT_NO }, // install studio\sprite palette
{ "%s%s.%s", "ktx2", Image_LoadKTX2, IL_HINT_NO }, // ktx2 for world and studio models { "ktx2", Image_LoadKTX2, IL_HINT_NO }, // ktx2 for world and studio models
{ NULL, NULL, NULL, IL_HINT_NO } { NULL, NULL, IL_HINT_NO }
}; };
/* /*
@@ -119,16 +119,16 @@ static const loadpixformat_t load_game[] =
// stub // stub
static const savepixformat_t save_null[] = static const savepixformat_t save_null[] =
{ {
{ NULL, NULL, NULL } { NULL, NULL }
}; };
// Xash3D normal instance // Xash3D normal instance
static const savepixformat_t save_game[] = static const savepixformat_t save_game[] =
{ {
{ "%s%s.%s", "tga", Image_SaveTGA }, // tga screenshots { "tga", Image_SaveTGA }, // tga screenshots
{ "%s%s.%s", "bmp", Image_SaveBMP }, // bmp levelshots or screenshots { "bmp", Image_SaveBMP }, // bmp levelshots or screenshots
{ "%s%s.%s", "png", Image_SavePNG }, // png screenshots { "png", Image_SavePNG }, // png screenshots
{ NULL, NULL, NULL } { NULL, NULL }
}; };
void Image_Setup( void ) void Image_Setup( void )

View File

@@ -32,7 +32,7 @@ qboolean Image_LoadPAL( const char *name, const byte *buffer, fs_offset_t filesi
if( filesize > sizeof( pal )) if( filesize > sizeof( pal ))
{ {
Con_DPrintf( S_ERROR "%s: (%s) have invalid size (%li should be less or equal than %d)\n", __func__, name, (long)filesize, sizeof( pal )); Con_DPrintf( S_ERROR "%s: (%s) have invalid size (%li should be less or equal than %zu)\n", __func__, name, (long)filesize, sizeof( pal ));
return false; return false;
} }
else if( filesize < sizeof( pal ) && buffer != NULL ) else if( filesize < sizeof( pal ) && buffer != NULL )

View File

@@ -128,9 +128,9 @@ dll_user_t *FS_FindLibrary( const char *dllname, qboolean directpath )
static void COM_GenerateCommonLibraryName( const char *name, const char *ext, char *out, size_t size ) static void COM_GenerateCommonLibraryName( const char *name, const char *ext, char *out, size_t size )
{ {
#if ( XASH_WIN32 || XASH_LINUX || XASH_APPLE ) && XASH_X86 #if ( XASH_WIN32 || ( XASH_LINUX && !XASH_ANDROID ) || XASH_APPLE ) && XASH_X86
Q_snprintf( out, size, "%s.%s", name, ext ); Q_snprintf( out, size, "%s.%s", name, ext );
#elif ( XASH_WIN32 || XASH_LINUX || XASH_APPLE ) #elif XASH_WIN32 || ( XASH_LINUX && !XASH_ANDROID ) || XASH_APPLE
Q_snprintf( out, size, "%s_%s.%s", name, Q_buildarch(), ext ); Q_snprintf( out, size, "%s_%s.%s", name, Q_buildarch(), ext );
#else #else
Q_snprintf( out, size, "%s_%s_%s.%s", name, Q_buildos(), Q_buildarch(), ext ); Q_snprintf( out, size, "%s_%s_%s.%s", name, Q_buildos(), Q_buildarch(), ext );
@@ -185,16 +185,12 @@ static void COM_GenerateServerLibraryPath( char *out, size_t size )
{ {
#ifdef XASH_INTERNAL_GAMELIBS // assuming library loader knows where to get libraries #ifdef XASH_INTERNAL_GAMELIBS // assuming library loader knows where to get libraries
Q_strncpy( out, "server", size ); Q_strncpy( out, "server", size );
#elif ( XASH_WIN32 || XASH_LINUX || XASH_APPLE ) && XASH_X86 #elif XASH_X86 && XASH_WIN32
#if XASH_WIN32
Q_strncpy( out, GI->game_dll, size ); Q_strncpy( out, GI->game_dll, size );
#elif XASH_APPLE #elif XASH_X86 && XASH_APPLE
Q_strncpy( out, GI->game_dll_osx, size ); Q_strncpy( out, GI->game_dll_osx, size );
#else // XASH_LINUX #elif XASH_X86 && XASH_LINUX && !XASH_ANDROID
Q_strncpy( out, GI->game_dll_linux, size ); Q_strncpy( out, GI->game_dll_linux, size );
#endif
#else #else
string dllpath; string dllpath;
const char *ext; const char *ext;
@@ -203,7 +199,7 @@ static void COM_GenerateServerLibraryPath( char *out, size_t size )
Q_strncpy( dllpath, GI->game_dll, sizeof( dllpath ) ); Q_strncpy( dllpath, GI->game_dll, sizeof( dllpath ) );
#elif XASH_APPLE #elif XASH_APPLE
Q_strncpy( dllpath, GI->game_dll_osx, sizeof( dllpath ) ); Q_strncpy( dllpath, GI->game_dll_osx, sizeof( dllpath ) );
#else // XASH_APPLE #else
Q_strncpy( dllpath, GI->game_dll_linux, sizeof( dllpath ) ); Q_strncpy( dllpath, GI->game_dll_linux, sizeof( dllpath ) );
#endif #endif
@@ -228,7 +224,14 @@ void COM_GetCommonLibraryPath( ECommonLibraryType eLibType, char *out, size_t si
switch( eLibType ) switch( eLibType )
{ {
case LIBRARY_GAMEUI: case LIBRARY_GAMEUI:
COM_GenerateClientLibraryPath( "menu", out, size ); if( COM_CheckStringEmpty( host.menulib ))
{
Q_strncpy( out, host.menulib, size );
}
else
{
COM_GenerateClientLibraryPath( "menu", out, size );
}
break; break;
case LIBRARY_CLIENT: case LIBRARY_CLIENT:
if( COM_CheckStringEmpty( host.clientlib )) if( COM_CheckStringEmpty( host.clientlib ))

View File

@@ -129,10 +129,11 @@ typedef struct
dclipnode32_t *clipnodes_out; // temporary 32-bit array to hold clipnodes dclipnode32_t *clipnodes_out; // temporary 32-bit array to hold clipnodes
// misc stuff // misc stuff
int lightmap_samples; // samples per lightmap (1 or 3) int lightmap_samples; // samples per lightmap (1 or 3)
int version; // model version int version; // model version
qboolean isworld; qboolean isworld;
qboolean isbsp30ext; qboolean isbsp30ext;
qboolean need_clipnode_remap; // try to fit 32-bit clipnodes into 16-bit types
} dbspmodel_t; } dbspmodel_t;
typedef struct typedef struct
@@ -1579,8 +1580,8 @@ static void CountClipNodes16_r( mclipnode16_t *src, hull_t *hull, int nodenum )
// leaf? // leaf?
if( nodenum < 0 ) return; if( nodenum < 0 ) return;
if( hull->lastclipnode == MAX_MAP_CLIPNODES ) if( hull->lastclipnode == MAX_MAP_CLIPNODES_HLBSP )
Host_Error( "MAX_MAP_CLIPNODES limit exceeded\n" ); Host_Error( "%s: MAX_MAP_CLIPNODES_HLBSP limit exceeded\n", __func__ );
hull->lastclipnode++; hull->lastclipnode++;
CountClipNodes16_r( src, hull, src[nodenum].children[0] ); CountClipNodes16_r( src, hull, src[nodenum].children[0] );
@@ -1592,25 +1593,25 @@ static void CountClipNodes32_r( mclipnode32_t *src, hull_t *hull, int nodenum )
// leaf? // leaf?
if( nodenum < 0 ) return; if( nodenum < 0 ) return;
if( hull->lastclipnode == MAX_MAP_CLIPNODES ) if( hull->lastclipnode == MAX_MAP_CLIPNODES_BSP2 )
Host_Error( "MAX_MAP_CLIPNODES limit exceeded\n" ); Host_Error( "%s: MAX_MAP_CLIPNODES_BSP2 limit exceeded\n", __func__ );
hull->lastclipnode++; hull->lastclipnode++;
CountClipNodes32_r( src, hull, src[nodenum].children[0] ); CountClipNodes32_r( src, hull, src[nodenum].children[0] );
CountClipNodes32_r( src, hull, src[nodenum].children[1] ); CountClipNodes32_r( src, hull, src[nodenum].children[1] );
} }
static void CountDClipNodes_r( dclipnode32_t *src, hull_t *hull, int nodenum ) static void CountDClipNodes_r( dclipnode32_t *src, hull_t *hull, int nodenum, const int max_clipnodes )
{ {
// leaf? // leaf?
if( nodenum < 0 ) return; if( nodenum < 0 ) return;
if( hull->lastclipnode == MAX_MAP_CLIPNODES ) if( hull->lastclipnode == max_clipnodes )
Host_Error( "MAX_MAP_CLIPNODES limit exceeded\n" ); Host_Error( "%s: MAX_MAP_CLIPNODES (%d) limit exceeded\n", __func__, max_clipnodes );
hull->lastclipnode++; hull->lastclipnode++;
CountDClipNodes_r( src, hull, src[nodenum].children[0] ); CountDClipNodes_r( src, hull, src[nodenum].children[0], max_clipnodes );
CountDClipNodes_r( src, hull, src[nodenum].children[1] ); CountDClipNodes_r( src, hull, src[nodenum].children[1], max_clipnodes );
} }
/* /*
@@ -1628,8 +1629,17 @@ static int RemapClipNodes_r( dbspmodel_t *bmod, dclipnode32_t *srcnodes, hull_t
return nodenum; return nodenum;
// emit a clipnode // emit a clipnode
if( hull->lastclipnode == MAX_MAP_CLIPNODES ) if( bmod->version == QBSP2_VERSION )
Host_Error( "MAX_MAP_CLIPNODES limit exceeded\n" ); {
if( hull->lastclipnode == MAX_MAP_CLIPNODES_BSP2 )
Host_Error( "%s: MAX_MAP_CLIPNODES_BSP2 limit exceeded\n", __func__ );
}
else
{
if( hull->lastclipnode == MAX_MAP_CLIPNODES_HLBSP )
Host_Error( "%s: MAX_MAP_CLIPNODES_HLBSP limit exceeded\n", __func__ );
}
src = srcnodes + nodenum; src = srcnodes + nodenum;
c = hull->lastclipnode; c = hull->lastclipnode;
@@ -1725,19 +1735,9 @@ static void Mod_MakeHull0( model_t *mod, const dbspmodel_t *bmod )
Mod_SetupHull Mod_SetupHull
================= =================
*/ */
static void Mod_SetupHull( dbspmodel_t *bmod, model_t *mod, poolhandle_t mempool, int headnode, int hullnum ) static void Mod_SetupHull( dbspmodel_t *bmod, model_t *mod, int headnode, int hullnum, model_t *world )
{ {
hull_t *hull = &mod->hulls[hullnum]; hull_t *hull = &mod->hulls[hullnum];
// assume no hull
hull->firstclipnode = hull->lastclipnode = 0;
hull->planes = NULL; // hull is missed
if(( headnode == -1 ) || ( hullnum != 1 && headnode == 0 ))
return; // hull missed
if( headnode >= mod->numclipnodes )
return; // ZHLT weird empty hulls
switch( hullnum ) switch( hullnum )
{ {
@@ -1761,13 +1761,75 @@ static void Mod_SetupHull( dbspmodel_t *bmod, model_t *mod, poolhandle_t mempool
if( VectorIsNull( hull->clip_mins ) && VectorIsNull( hull->clip_maxs )) if( VectorIsNull( hull->clip_mins ) && VectorIsNull( hull->clip_maxs ))
return; // no hull specified return; // no hull specified
CountDClipNodes_r( bmod->clipnodes_out, hull, headnode ); // assume no hull
hull->firstclipnode = hull->lastclipnode = 0;
hull->planes = NULL; // hull is missed
if( headnode >= mod->numclipnodes )
return; // ZHLT weird empty hulls
// take a simpler route if we don't need clipnodes remapping
if( !bmod->need_clipnode_remap )
{
hull->planes = mod->planes;
// some map "optimizers" (you know who you are!) put -1 here
hull->firstclipnode = Q_max( 0, headnode );
hull->lastclipnode = mod->numclipnodes - 1;
// only allocate clipnodes array for the base model, only for first hull
if( mod == world && hullnum == 1 )
{
int i;
if( bmod->version == QBSP2_VERSION )
{
hull->clipnodes32 = Mem_Malloc( world->mempool, sizeof( *hull->clipnodes32 ) * mod->numclipnodes );
for( i = 0; i < mod->numclipnodes; i++ )
{
hull->clipnodes32[i].planenum = bmod->clipnodes_out[i].planenum;
hull->clipnodes32[i].children[0] = bmod->clipnodes_out[i].children[0];
hull->clipnodes32[i].children[1] = bmod->clipnodes_out[i].children[1];
}
}
else
{
hull->clipnodes16 = Mem_Malloc( world->mempool, sizeof( *hull->clipnodes16 ) * mod->numclipnodes );
for( i = 0; i < mod->numclipnodes; i++ )
{
hull->clipnodes16[i].planenum = bmod->clipnodes_out[i].planenum;
hull->clipnodes16[i].children[0] = bmod->clipnodes_out[i].children[0];
hull->clipnodes16[i].children[1] = bmod->clipnodes_out[i].children[1];
}
}
}
else
{
if( bmod->version == QBSP2_VERSION )
hull->clipnodes32 = world->hulls[1].clipnodes32;
else
hull->clipnodes16 = world->hulls[1].clipnodes16;
}
return;
}
if(( headnode == -1 ) || ( hullnum != 1 && headnode == 0 ))
return; // hull missed
// fit array to real count // fit array to real count
if( bmod->version == QBSP2_VERSION ) if( bmod->version == QBSP2_VERSION )
hull->clipnodes32 = Mem_Malloc( mempool, sizeof( *hull->clipnodes32 ) * hull->lastclipnode ); {
CountDClipNodes_r( bmod->clipnodes_out, hull, headnode, MAX_MAP_CLIPNODES_BSP2 );
hull->clipnodes32 = Mem_Malloc( world->mempool, sizeof( *hull->clipnodes32 ) * hull->lastclipnode );
}
else else
hull->clipnodes16 = Mem_Malloc( mempool, sizeof( *hull->clipnodes16 ) * hull->lastclipnode ); {
CountDClipNodes_r( bmod->clipnodes_out, hull, headnode, MAX_MAP_CLIPNODES_HLBSP );
hull->clipnodes16 = Mem_Malloc( world->mempool, sizeof( *hull->clipnodes16 ) * hull->lastclipnode );
}
hull->planes = mod->planes; // share planes hull->planes = mod->planes; // share planes
hull->lastclipnode = 0; // restart counting hull->lastclipnode = 0; // restart counting
@@ -1851,28 +1913,19 @@ for embedded submodels
*/ */
static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod ) static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod )
{ {
qboolean colored = false; const qboolean colored = FBitSet( mod->flags, MODEL_COLORED_LIGHTING ) ? true : false;
qboolean qbsp2 = false; const qboolean qbsp2 = FBitSet( mod->flags, MODEL_QBSP2 ) ? true : false;
poolhandle_t mempool;
char *ents;
dmodel_t *bm;
const char *name = mod->name; const char *name = mod->name;
int i, j; model_t *world = mod; // submodels might want to share hulls
int i;
ents = mod->entities;
mempool = mod->mempool;
if( FBitSet( mod->flags, MODEL_COLORED_LIGHTING ))
colored = true;
if( FBitSet( mod->flags, MODEL_QBSP2 ))
qbsp2 = true;
mod->numframes = 2; // regular and alternate animation mod->numframes = 2; // regular and alternate animation
// set up the submodels // set up the submodels
for( i = 0; i < mod->numsubmodels; i++ ) for( i = 0; i < mod->numsubmodels; i++ )
{ {
bm = &mod->submodels[i]; dmodel_t *bm = &mod->submodels[i];
int j;
// hull 0 is just shared across all bmodels // hull 0 is just shared across all bmodels
mod->hulls[0].firstclipnode = bm->headnode[0]; mod->hulls[0].firstclipnode = bm->headnode[0];
@@ -1886,7 +1939,7 @@ static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod )
// but hulls1-3 is build individually for a each given submodel // but hulls1-3 is build individually for a each given submodel
for( j = 1; j < MAX_MAP_HULLS; j++ ) for( j = 1; j < MAX_MAP_HULLS; j++ )
Mod_SetupHull( bmod, mod, mempool, bm->headnode[j], j ); Mod_SetupHull( bmod, mod, bm->headnode[j], j, world );
mod->firstmodelsurface = bm->firstface; mod->firstmodelsurface = bm->firstface;
mod->nummodelsurfaces = bm->numfaces; mod->nummodelsurfaces = bm->numfaces;
@@ -1907,7 +1960,7 @@ static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod )
char temp[MAX_VA_STRING]; char temp[MAX_VA_STRING];
Q_snprintf( temp, sizeof( temp ), "*%i", i ); Q_snprintf( temp, sizeof( temp ), "*%i", i );
Mod_FindModelOrigin( ents, temp, bm->origin ); Mod_FindModelOrigin( world->entities, temp, bm->origin );
// mark models that have origin brushes // mark models that have origin brushes
if( !VectorIsNull( bm->origin )) if( !VectorIsNull( bm->origin ))
@@ -3434,7 +3487,12 @@ static void Mod_LoadClipnodes( model_t *mod, dbspmodel_t *bmod )
if(( bmod->version == QBSP2_VERSION ) || ( bmod->version == HLBSP_VERSION && bmod->isbsp30ext && bmod->numclipnodes >= MAX_MAP_CLIPNODES_HLBSP )) if(( bmod->version == QBSP2_VERSION ) || ( bmod->version == HLBSP_VERSION && bmod->isbsp30ext && bmod->numclipnodes >= MAX_MAP_CLIPNODES_HLBSP ))
{ {
dclipnode32_t *in = bmod->clipnodes32; dclipnode32_t *in = bmod->clipnodes32;
// bsp30ext allows for extended total amount of clipnodes, but the limit is still 16-bit per submodel
// therefore we need to remap them
if( bmod->version == HLBSP_VERSION )
bmod->need_clipnode_remap = true;
for( i = 0; i < bmod->numclipnodes; i++, out++, in++ ) for( i = 0; i < bmod->numclipnodes; i++, out++, in++ )
{ {
@@ -3454,7 +3512,7 @@ static void Mod_LoadClipnodes( model_t *mod, dbspmodel_t *bmod )
out->children[0] = (unsigned short)in->children[0]; out->children[0] = (unsigned short)in->children[0];
out->children[1] = (unsigned short)in->children[1]; out->children[1] = (unsigned short)in->children[1];
// Arguire QBSP 'broken' clipnodes // aguirRe QBSP 'broken' clipnodes
if( out->children[0] >= bmod->numclipnodes ) if( out->children[0] >= bmod->numclipnodes )
out->children[0] -= 65536; out->children[0] -= 65536;
if( out->children[1] >= bmod->numclipnodes ) if( out->children[1] >= bmod->numclipnodes )

View File

@@ -169,7 +169,7 @@ void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *loaded );
// //
void Mod_LoadBrushModel( model_t *mod, const void *buffer, qboolean *loaded ); void Mod_LoadBrushModel( model_t *mod, const void *buffer, qboolean *loaded );
qboolean Mod_TestBmodelLumps( file_t *f, const char *name, const byte *mod_base, qboolean silent, dlump_t *entities ); qboolean Mod_TestBmodelLumps( file_t *f, const char *name, const byte *mod_base, qboolean silent, dlump_t *entities );
int Mod_FatPVS( const vec3_t org, float radius, byte *visbuffer, int visbytes, qboolean merge, qboolean fullvis, qboolean false ); int Mod_FatPVS( const vec3_t org, float radius, byte *visbuffer, int visbytes, qboolean merge, qboolean fullvis, qboolean phs );
qboolean Mod_BoxVisible( const vec3_t mins, const vec3_t maxs, const byte *visbits ); qboolean Mod_BoxVisible( const vec3_t mins, const vec3_t maxs, const byte *visbits );
int Mod_CheckLump( const char *filename, const int lump, int *lumpsize ); int Mod_CheckLump( const char *filename, const int lump, int *lumpsize );
int Mod_ReadLump( const char *filename, const int lump, void **lumpdata, int *lumpsize ); int Mod_ReadLump( const char *filename, const int lump, void **lumpdata, int *lumpsize );

View File

@@ -618,7 +618,7 @@ qboolean MSG_ReadBits( sizebuf_t *sb, void *pOutData, 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 )
{ {
*pOut = (byte)MSG_ReadUBitLong( sb, 8 ); *pOut = (byte)MSG_ReadUBitLong( sb, 8 );
++pOut; ++pOut;
@@ -873,7 +873,7 @@ static void Test_Buffer_Write( void )
MSG_Init( &sb, __func__, testdata, sizeof( testdata )); MSG_Init( &sb, __func__, testdata, sizeof( testdata ));
TASSERT_EQi( sb.iCurBit, 0 ); TASSERT_EQi( sb.iCurBit, 0 );
TASSERT_EQi( sb.nDataBits, sizeof( testdata ) << 3 ); TASSERT_EQi( sb.nDataBits, sizeof( testdata ) << 3 );
TASSERT_EQi( sb.pData, testdata ); TASSERT_EQp( sb.pData, (void *)testdata );
TASSERT_EQi( sb.bOverflow, false ); TASSERT_EQi( sb.bOverflow, false );
MSG_WriteBytes( &sb, "asdf", 4 ); MSG_WriteBytes( &sb, "asdf", 4 );
@@ -929,7 +929,7 @@ static void Test_Buffer_Read( void )
MSG_StartReading( &sb, (void *)g_testbuf, -1, 0, g_testbuf_bits ); MSG_StartReading( &sb, (void *)g_testbuf, -1, 0, g_testbuf_bits );
TASSERT_EQi( sb.iCurBit, 0 ); TASSERT_EQi( sb.iCurBit, 0 );
TASSERT_EQi( sb.nDataBits, g_testbuf_bits ); TASSERT_EQi( sb.nDataBits, g_testbuf_bits );
TASSERT_EQi( sb.pData, g_testbuf ); TASSERT_EQp( sb.pData, (void *)g_testbuf );
TASSERT_EQi( sb.bOverflow, false ); TASSERT_EQi( sb.bOverflow, false );
MSG_ReadBytes( &sb, buf, 4 ); MSG_ReadBytes( &sb, buf, 4 );

View File

@@ -121,7 +121,7 @@ static CVAR_DEFINE_AUTO( net_resolve_debug, "0", FCVAR_PRIVILEGED, "print resolv
CVAR_DEFINE( net_clockwindow, "clockwindow", "0.5", FCVAR_PRIVILEGED, "timewindow to execute client moves" ); CVAR_DEFINE( net_clockwindow, "clockwindow", "0.5", FCVAR_PRIVILEGED, "timewindow to execute client moves" );
netadr_t net_local; netadr_t net_local;
netadr_t net6_local; static netadr_t net6_local;
// cvars equivalents for IPv6 // cvars equivalents for IPv6
static CVAR_DEFINE( net_ip6name, "ip6", "localhost", FCVAR_PRIVILEGED, "network ip6 address" ); static CVAR_DEFINE( net_ip6name, "ip6", "localhost", FCVAR_PRIVILEGED, "network ip6 address" );
@@ -1791,12 +1791,12 @@ static void NET_OpenIP( qboolean change_port, int *sockets, const char *net_ifac
/* /*
================ ================
NET_GetLocalAddress NET_DetermineLocalAddress
Returns the servers' ip address as a string. Returns the servers' ip address as a string.
================ ================
*/ */
static void NET_GetLocalAddress( void ) static void NET_DetermineLocalAddress( void )
{ {
char hostname[512]; char hostname[512];
char buff[512]; char buff[512];
@@ -1910,7 +1910,7 @@ void NET_Config( qboolean multiplayer, qboolean changeport )
// get our local address, if possible // get our local address, if possible
if( bFirst ) if( bFirst )
{ {
NET_GetLocalAddress(); NET_DetermineLocalAddress();
bFirst = false; bFirst = false;
} }
} }
@@ -2006,6 +2006,32 @@ static void NET_ClearLagData( qboolean bClient, qboolean bServer )
if( bServer ) NET_ClearLaggedList( &net.lagdata[NS_SERVER] ); if( bServer ) NET_ClearLaggedList( &net.lagdata[NS_SERVER] );
} }
/*
====================
NET_GetLocalAddress
get local server addresses
====================
*/
void NET_GetLocalAddress( netadr_t *ip4, netadr_t *ip6 )
{
if( ip4 )
{
if( net.allow_ip )
*ip4 = net_local;
else
memset( ip4, 0, sizeof( *ip4 ));
}
if( ip6 )
{
if( net.allow_ip6 )
*ip6 = net6_local;
else
memset( ip6, 0, sizeof( *ip6 ));
}
}
/* /*
==================== ====================
NET_Init NET_Init

View File

@@ -82,6 +82,8 @@ static inline qboolean NET_IsLocalAddress( netadr_t adr )
return NET_NetadrType( &adr ) == NA_LOOPBACK; return NET_NetadrType( &adr ) == NA_LOOPBACK;
} }
void NET_GetLocalAddress( netadr_t *ip4, netadr_t *ip6 );
#if !XASH_DEDICATED #if !XASH_DEDICATED
int CL_GetSplitSize( void ); int CL_GetSplitSize( void );
#endif #endif

View File

@@ -290,8 +290,6 @@ typedef struct netchan_s
} netchan_t; } netchan_t;
extern netadr_t net_from; extern netadr_t net_from;
extern netadr_t net_local;
extern netadr_t net6_local;
extern sizebuf_t net_message; extern sizebuf_t net_message;
extern byte net_message_buffer[NET_MAX_MESSAGE]; extern byte net_message_buffer[NET_MAX_MESSAGE];
extern convar_t sv_lan; extern convar_t sv_lan;

View File

@@ -14,9 +14,6 @@ GNU General Public License for more details.
*/ */
#include "soundlib.h" #include "soundlib.h"
#if XASH_SDL
#include <SDL_audio.h>
#endif // XASH_SDL
// global sound variables // global sound variables
sndlib_t sound; sndlib_t sound;
@@ -31,19 +28,15 @@ sndlib_t sound;
static const loadwavfmt_t load_game[] = static const loadwavfmt_t load_game[] =
{ {
#ifndef XASH_DEDICATED #ifndef XASH_DEDICATED
{ DEFAULT_SOUNDPATH "%s%s.%s", "wav", Sound_LoadWAV }, { "wav", Sound_LoadWAV },
{ "%s%s.%s", "wav", Sound_LoadWAV }, { "mp3", Sound_LoadMPG },
{ DEFAULT_SOUNDPATH "%s%s.%s", "mp3", Sound_LoadMPG }, { "ogg", Sound_LoadOggVorbis },
{ "%s%s.%s", "mp3", Sound_LoadMPG }, { "opus", Sound_LoadOggOpus },
{ DEFAULT_SOUNDPATH "%s%s.%s", "ogg", Sound_LoadOggVorbis },
{ "%s%s.%s", "ogg", Sound_LoadOggVorbis },
{ DEFAULT_SOUNDPATH "%s%s.%s", "opus", Sound_LoadOggOpus },
{ "%s%s.%s", "opus", Sound_LoadOggOpus },
#else // we only need extensions #else // we only need extensions
{ NULL, "wav" }, { "wav" },
{ NULL, "mp3" }, { "mp3" },
{ NULL, "ogg" }, { "ogg" },
{ NULL, "opus" }, { "opus" },
#endif #endif
{ NULL }, { NULL },
}; };
@@ -58,15 +51,15 @@ static const loadwavfmt_t load_game[] =
static const streamfmt_t stream_game[] = static const streamfmt_t stream_game[] =
{ {
#ifndef XASH_DEDICATED #ifndef XASH_DEDICATED
{ "%s%s.%s", "mp3", Stream_OpenMPG, Stream_ReadMPG, Stream_SetPosMPG, Stream_GetPosMPG, Stream_FreeMPG }, { "mp3", Stream_OpenMPG, Stream_ReadMPG, Stream_SetPosMPG, Stream_GetPosMPG, Stream_FreeMPG },
{ "%s%s.%s", "wav", Stream_OpenWAV, Stream_ReadWAV, Stream_SetPosWAV, Stream_GetPosWAV, Stream_FreeWAV }, { "wav", Stream_OpenWAV, Stream_ReadWAV, Stream_SetPosWAV, Stream_GetPosWAV, Stream_FreeWAV },
{ "%s%s.%s", "ogg", Stream_OpenOggVorbis, Stream_ReadOggVorbis, Stream_SetPosOggVorbis, Stream_GetPosOggVorbis, Stream_FreeOggVorbis }, { "ogg", Stream_OpenOggVorbis, Stream_ReadOggVorbis, Stream_SetPosOggVorbis, Stream_GetPosOggVorbis, Stream_FreeOggVorbis },
{ "%s%s.%s", "opus", Stream_OpenOggOpus, Stream_ReadOggOpus, Stream_SetPosOggOpus, Stream_GetPosOggOpus, Stream_FreeOggOpus }, { "opus", Stream_OpenOggOpus, Stream_ReadOggOpus, Stream_SetPosOggOpus, Stream_GetPosOggOpus, Stream_FreeOggOpus },
#else // we only need extensions #else // we only need extensions
{ NULL, "mp3" }, { "mp3" },
{ NULL, "wav" }, { "wav" },
{ NULL, "ogg" }, { "ogg" },
{ NULL, "opus" }, { "opus" },
#endif #endif
{ NULL }, { NULL },
}; };
@@ -388,31 +381,6 @@ static qboolean Sound_ResampleInternal( wavdata_t *sc, int outrate, int outwidth
if( FBitSet( sc->flags, SOUND_LOOPED )) if( FBitSet( sc->flags, SOUND_LOOPED ))
sc->loopStart = sc->loopStart / stepscale; sc->loopStart = sc->loopStart / stepscale;
#if 0 && XASH_SDL // slow but somewhat accurate (wasn't updated to channel manipulation!!!)
{
const SDL_AudioFormat infmt = inwidth == 1 ? AUDIO_S8 : AUDIO_S16;
const SDL_AudioFormat outfmt = outwidth == 1 ? AUDIO_S8 : AUDIO_S16;
SDL_AudioCVT cvt;
// SDL_AudioCVT does conversion in place, original buffer is used for it
if( SDL_BuildAudioCVT( &cvt, infmt, inchannels, inrate, outfmt, outchannels, outrate ) > 0 && cvt.needed )
{
sc->buffer = (byte *)Mem_Realloc( host.soundpool, sc->buffer, oldsize * cvt.len_mult );
cvt.len = oldsize;
cvt.buf = sc->buffer;
if( !SDL_ConvertAudio( &cvt ))
{
t2 = Sys_DoubleTime();
Con_Reportf( "Sound_Resample: from [%d bit %d Hz] to [%d bit %d Hz] (took %.3fs through SDL)\n", inwidth * 8, inrate, outwidth * 8, outrate, t2 - t1 );
sc->rate = outrate;
sc->width = outwidth;
return false; // HACKHACK: return false so Sound_Process won't reallocate buffer
}
}
}
#endif
sound.tempbuffer = (byte *)Mem_Realloc( host.soundpool, sound.tempbuffer, sc->size ); sound.tempbuffer = (byte *)Mem_Realloc( host.soundpool, sound.tempbuffer, sc->size );
if( inrate == outrate ) // no resampling, just copy data if( inrate == outrate ) // no resampling, just copy data
@@ -481,7 +449,7 @@ qboolean Sound_SupportedFileFormat( const char *fileext )
const loadwavfmt_t *format; const loadwavfmt_t *format;
if( COM_CheckStringEmpty( fileext )) if( COM_CheckStringEmpty( fileext ))
{ {
for( format = sound.loadformats; format && format->formatstring; format++ ) for( format = sound.loadformats; format && format->ext; format++ )
{ {
if( !Q_stricmp( format->ext, fileext )) if( !Q_stricmp( format->ext, fileext ))
return true; return true;

View File

@@ -23,14 +23,12 @@ GNU General Public License for more details.
typedef struct loadwavfmt_s typedef struct loadwavfmt_s
{ {
const char *formatstring;
const char *ext; const char *ext;
qboolean (*loadfunc)( const char *name, const byte *buffer, fs_offset_t filesize ); qboolean (*loadfunc)( const char *name, const byte *buffer, fs_offset_t filesize );
} loadwavfmt_t; } loadwavfmt_t;
typedef struct streamfmt_s typedef struct streamfmt_s
{ {
const char *formatstring;
const char *ext; const char *ext;
stream_t *(*openfunc)( const char *filename ); stream_t *(*openfunc)( const char *filename );

View File

@@ -271,7 +271,7 @@ void Sys_PrintLog( const char *pMsg )
const struct tm *crt_tm; const struct tm *crt_tm;
char logtime[32] = ""; char logtime[32] = "";
static char lastchar; static char lastchar;
qboolean print_time = true; qboolean print_time = false;
size_t len, logtime_len = 0; size_t len, logtime_len = 0;
if( !lastchar || lastchar == '\n' ) if( !lastchar || lastchar == '\n' )
@@ -279,11 +279,9 @@ void Sys_PrintLog( const char *pMsg )
if( time( &crt_time ) >= 0 ) if( time( &crt_time ) >= 0 )
{ {
crt_tm = localtime( &crt_time ); crt_tm = localtime( &crt_time );
if( crt_tm == NULL ) print_time = crt_tm != NULL;
print_time = false;
} }
} }
else print_time = false;
if( print_time ) if( print_time )
{ {

View File

@@ -1,5 +1,5 @@
/* /*
sys_win.c - platform dependent code sys_win.c - platform dependent code (which haven't moved to platform dir yet)
Copyright (C) 2011 Uncle Mike Copyright (C) 2011 Uncle Mike
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,10 @@ GNU General Public License for more details.
#include <intrin.h> #include <intrin.h>
#endif #endif
#ifdef XASH_SDL #if XASH_SDL == 2
#include <SDL.h> #include <SDL.h>
#elif XASH_SDL == 3
#include <SDL3/SDL.h>
#endif #endif
#if XASH_POSIX #if XASH_POSIX
@@ -72,17 +74,16 @@ Sys_DebugBreak
*/ */
void Sys_DebugBreak( void ) void Sys_DebugBreak( void )
{ {
#if XASH_SDL qboolean was_grabbed = false;
int was_grabbed = host.hWnd != NULL && SDL_GetWindowGrab( host.hWnd );
#endif
if( !Sys_DebuggerPresent( )) if( !Sys_DebuggerPresent( ))
return; return;
#if XASH_SDL if( host.hWnd ) // so annoying
if( was_grabbed ) // so annoying... {
SDL_SetWindowGrab( host.hWnd, SDL_FALSE ); was_grabbed = Platform_GetMouseGrab();
#endif // XASH_SDL Platform_SetMouseGrab( false );
}
#if _MSC_VER #if _MSC_VER
__debugbreak(); __debugbreak();
@@ -91,10 +92,8 @@ void Sys_DebugBreak( void )
INLINE_NANOSLEEP1(); // sometimes signal comes with delay, let it interrupt nanosleep INLINE_NANOSLEEP1(); // sometimes signal comes with delay, let it interrupt nanosleep
#endif // !_MSC_VER #endif // !_MSC_VER
#if XASH_SDL
if( was_grabbed ) if( was_grabbed )
SDL_SetWindowGrab( host.hWnd, SDL_TRUE ); Platform_SetMouseGrab( true );
#endif
} }
#if !XASH_DEDICATED #if !XASH_DEDICATED
@@ -126,23 +125,34 @@ returns username for current profile
*/ */
const char *Sys_GetCurrentUser( void ) const char *Sys_GetCurrentUser( void )
{ {
// TODO: move to platform
#if XASH_WIN32 #if XASH_WIN32
static string s_userName; static wchar_t sw_userName[MAX_STRING];
unsigned long size = sizeof( s_userName ); DWORD size = ARRAYSIZE( sw_userName );
if( GetUserName( s_userName, &size )) if( GetUserNameW( sw_userName, &size ) && sw_userName[0] != 0 )
{
static char s_userName[MAX_STRING * 4];
// set length to -1, so it will null terminate
WideCharToMultiByte( CP_UTF8, 0, sw_userName, -1, s_userName, sizeof( s_userName ), NULL, NULL );
return s_userName; return s_userName;
}
#elif XASH_PSVITA #elif XASH_PSVITA
static string username; static string username;
sceAppUtilSystemParamGetString( SCE_SYSTEM_PARAM_ID_USERNAME, username, sizeof( username ) - 1 ); sceAppUtilSystemParamGetString( SCE_SYSTEM_PARAM_ID_USERNAME, username, sizeof( username ) - 1 );
if( COM_CheckStringEmpty( username )) if( COM_CheckStringEmpty( username ))
return username; return username;
#elif XASH_POSIX && !XASH_ANDROID && !XASH_NSWITCH #elif XASH_POSIX && !XASH_ANDROID && !XASH_NSWITCH
uid_t uid = geteuid(); static string username;
struct passwd *pw = getpwuid( uid ); struct passwd *pw = getpwuid( geteuid( ));
if( pw ) // POSIX standard says pw _might_ point to static area, so let's make a copy
return pw->pw_name; if( pw && COM_CheckString( pw->pw_name ))
{
Q_strncpy( username, pw->pw_name, sizeof( username ));
return username;
}
#endif #endif
return "Player"; return "Player";
} }
@@ -393,7 +403,7 @@ void Sys_Error( const char *error, ... )
if( !Host_IsDedicated() ) if( !Host_IsDedicated() )
{ {
#if XASH_SDL == 2 #if XASH_SDL >= 2
if( host.hWnd ) SDL_HideWindow( host.hWnd ); if( host.hWnd ) SDL_HideWindow( host.hWnd );
#endif #endif
#if XASH_WIN32 #if XASH_WIN32

View File

@@ -27,6 +27,8 @@ extern struct tests_stats_s tests_stats;
_TASSERT( !(exp), Msg( S_ERROR "assert failed at %s:%i\n", __FILE__, __LINE__ ) ) _TASSERT( !(exp), Msg( S_ERROR "assert failed at %s:%i\n", __FILE__, __LINE__ ) )
#define TASSERT_EQi( val1, val2 ) \ #define TASSERT_EQi( val1, val2 ) \
_TASSERT( ( val1 ) != ( val2 ), Msg( S_ERROR "assert failed at %s:%i, \"%d\" != \"%d\"\n", __FILE__, __LINE__, val1, val2 )) _TASSERT( ( val1 ) != ( val2 ), Msg( S_ERROR "assert failed at %s:%i, \"%d\" != \"%d\"\n", __FILE__, __LINE__, val1, val2 ))
#define TASSERT_EQp( val1, val2 ) \
_TASSERT( ( val1 ) != ( val2 ), Msg( S_ERROR "assert failed at %s:%i, \"%p\" != \"%p\"\n", __FILE__, __LINE__, val1, val2 ))
#define TASSERT_STR( str1, str2 ) \ #define TASSERT_STR( str1, str2 ) \
_TASSERT( Q_strcmp(( str1 ), ( str2 )), Msg( S_ERROR "assert failed at %s:%i, \"%s\" != \"%s\"\n", __FILE__, __LINE__, ( str1 ), ( str2 ))) _TASSERT( Q_strcmp(( str1 ), ( str2 )), Msg( S_ERROR "assert failed at %s:%i, \"%s\" != \"%s\"\n", __FILE__, __LINE__, ( str1 ), ( str2 )))

View File

@@ -210,7 +210,7 @@ typedef struct ui_extendedfuncs_s {
// new engine extended api start here // new engine extended api start here
// returns 1 if there are more in list, otherwise 0 // returns 1 if there are more in list, otherwise 0
int (*pfnGetRenderers)( unsigned int num, char *shortName, size_t size1, char *readableName, size_t size2 ); int (*pfnGetRenderers)( unsigned int num, char *short_name, size_t size1, char *long_name, size_t size2 );
double (*pfnDoubleTime)( void ); double (*pfnDoubleTime)( void );
char *(*pfnParseFile)( char *data, char *buf, const int size, unsigned int flags, int *len ); char *(*pfnParseFile)( char *data, char *buf, const int size, unsigned int flags, int *len );

View File

@@ -13,9 +13,6 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
*/ */
#include "platform/platform.h" #include "platform/platform.h"
#if !defined(XASH_DEDICATED)
#include "input.h" #include "input.h"
#include "client.h" #include "client.h"
#include "sound.h" #include "sound.h"
@@ -25,7 +22,9 @@ GNU General Public License for more details.
#include <android/log.h> #include <android/log.h>
#include <jni.h> #include <jni.h>
#if XASH_SDL
#include <SDL.h> #include <SDL.h>
#endif // XASH_SDL
struct jnimethods_s struct jnimethods_s
{ {
@@ -39,6 +38,9 @@ struct jnimethods_s
void Android_Init( void ) void Android_Init( void )
{ {
memset( &jni, 0, sizeof( jni ));
#if XASH_SDL
jni.env = (JNIEnv *)SDL_AndroidGetJNIEnv(); jni.env = (JNIEnv *)SDL_AndroidGetJNIEnv();
jni.activity = (jobject)SDL_AndroidGetActivity(); jni.activity = (jobject)SDL_AndroidGetActivity();
jni.actcls = (*jni.env)->GetObjectClass( jni.env, jni.activity ); jni.actcls = (*jni.env)->GetObjectClass( jni.env, jni.activity );
@@ -51,6 +53,7 @@ void Android_Init( void )
SDL_SetHint( SDL_HINT_ANDROID_BLOCK_ON_PAUSE, "0" ); SDL_SetHint( SDL_HINT_ANDROID_BLOCK_ON_PAUSE, "0" );
SDL_SetHint( SDL_HINT_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO, "0" ); SDL_SetHint( SDL_HINT_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO, "0" );
SDL_SetHint( SDL_HINT_ANDROID_TRAP_BACK_BUTTON, "1" ); SDL_SetHint( SDL_HINT_ANDROID_TRAP_BACK_BUTTON, "1" );
#endif // !XASH_SDL
} }
/* /*
@@ -134,5 +137,3 @@ void Platform_ShellExecute( const char *path, const char *parms )
SDL_OpenURL( path ); SDL_OpenURL( path );
#endif #endif
} }
#endif // XASH_DEDICATED

View File

@@ -17,7 +17,10 @@ GNU General Public License for more details.
#ifndef ANDROID_LIB_H #ifndef ANDROID_LIB_H
#define ANDROID_LIB_H #define ANDROID_LIB_H
#if !XASH_TERMUX
#define Platform_POSIX_LoadLibrary( x ) ANDROID_LoadLibrary(( x )) #define Platform_POSIX_LoadLibrary( x ) ANDROID_LoadLibrary(( x ))
#endif // !XASH_TERMUX
#define Platform_POSIX_GetProcAddress( x, y ) ANDROID_GetProcAddress(( x ), ( y )) #define Platform_POSIX_GetProcAddress( x, y ) ANDROID_GetProcAddress(( x ), ( y ))
void *ANDROID_LoadLibrary( const char *dllname ); void *ANDROID_LoadLibrary( const char *dllname );

View File

@@ -80,27 +80,11 @@ void Platform_RunEvents( void )
} }
void GAME_EXPORT Platform_GetMousePos( int *x, int *y )
{
*x = *y = 0;
}
void GAME_EXPORT Platform_SetMousePos(int x, int y)
{
}
void Platform_EnableTextInput( qboolean enable ) void Platform_EnableTextInput( qboolean enable )
{ {
keystate.chars = enable; keystate.chars = enable;
} }
void Platform_PreCreateMove( void )
{
}
void Platform_MouseMove( float *x, float *y ) void Platform_MouseMove( float *x, float *y )
{ {
static int lx,ly; static int lx,ly;

View File

@@ -15,24 +15,11 @@ GNU General Public License for more details.
#include "platform/platform.h" #include "platform/platform.h"
#include <dos.h> #include <dos.h>
void Platform_GetClipboardText( char *buffer, size_t size )
{
}
void Platform_SetClipboardText( const char *buffer, size_t size )
{
}
void Platform_Vibrate(float life, char flags)
{
}
void Platform_ShellExecute( const char *path, const char *parms ) void Platform_ShellExecute( const char *path, const char *parms )
{ {
} }
volatile int ticks=0; volatile int ticks=0;
#if XASH_TIMER == TIMER_DOS #if XASH_TIMER == TIMER_DOS

View File

@@ -27,6 +27,11 @@ GNU General Public License for more details.
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
void Platform_Minimize_f( void )
{
// stub
}
/* /*
======================== ========================
Android_SwapBuffers Android_SwapBuffers
@@ -538,4 +543,9 @@ qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *
return true; return true;
} }
ref_window_type_t R_GetWindowHandle( void **handle, ref_window_type_t type )
{
return REF_WINDOW_TYPE_NULL;
}
#endif #endif

View File

@@ -179,7 +179,7 @@ void Evdev_Autodetect_f( void )
for( i = 0; i < evdev.devices; i++ ) for( i = 0; i < evdev.devices; i++ )
{ {
if( !Q_strncmp( evdev.paths[i], path, sizeof( evdev.paths[i] )) if( !Q_strncmp( evdev.paths[i], path, sizeof( evdev.paths[i] )))
goto next; goto next;
} }

View File

@@ -28,6 +28,11 @@ struct fb_s
#define DEFAULT_FBDEV "/dev/fb0" #define DEFAULT_FBDEV "/dev/fb0"
void Platform_Minimize_f( void )
{
// stub
}
/* /*
======================== ========================
Android_SwapBuffers Android_SwapBuffers
@@ -60,7 +65,7 @@ qboolean R_Init_Video( const int type )
if( fb.fd < 0 ) if( fb.fd < 0 )
{ {
Con_Printf( S_ERROR, "failed to open framebuffer device: %s\n", strerror(errno)); Con_Printf( S_ERROR "failed to open framebuffer device: %s\n", strerror(errno));
} }
if( Sys_CheckParm( "-ttygfx" ) ) if( Sys_CheckParm( "-ttygfx" ) )
@@ -129,7 +134,7 @@ rserr_t R_ChangeDisplaySettings( int width, int height, window_mode_t window_mod
Con_Reportf( "%s: forced resolution to %dx%d)\n", __func__, width, height ); Con_Reportf( "%s: forced resolution to %dx%d)\n", __func__, width, height );
VID_SetDisplayTransform( &render_w, &render_h ); VID_SetDisplayTransform( &render_w, &render_h );
R_SaveVideoMode( width, height, render_w, render_h ); R_SaveVideoMode( width, height, render_w, render_h, false );
return rserr_ok; return rserr_ok;
} }
@@ -241,41 +246,9 @@ qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *
return true; return true;
} }
// unrelated stubs ref_window_type_t R_GetWindowHandle( void **handle, ref_window_type_t type )
void Platform_GetClipboardText( char *buffer, size_t size )
{ {
return REF_WINDOW_TYPE_NULL;
} }
void Platform_SetClipboardText( const char *buffer, size_t size )
{
}
void Platform_PreCreateMove( void )
{
}
// will be implemented later
void Platform_RunEvents( void )
{
}
void GAME_EXPORT Platform_GetMousePos( int *x, int *y )
{
*x = *y = 0;
}
void GAME_EXPORT Platform_SetMousePos(int x, int y)
{
}
void Platform_Vibrate( float life, char flags )
{
}
#endif #endif

View File

@@ -58,6 +58,7 @@ char *Posix_Input( void );
#if XASH_SDL #if XASH_SDL
void SDLash_Init( const char *basedir ); void SDLash_Init( const char *basedir );
void SDLash_Shutdown( void ); void SDLash_Shutdown( void );
void SDLash_NanoSleep( int nsec );
#endif #endif
#if XASH_ANDROID #if XASH_ANDROID
@@ -171,9 +172,11 @@ static inline void Platform_SetupSigtermHandling( void )
static inline qboolean Platform_NanoSleep( int nsec ) static inline qboolean Platform_NanoSleep( int nsec )
{ {
#if XASH_SDL == 3
SDLash_NanoSleep( nsec );
return true;
// SDL2 doesn't have nanosleep, so use low-level functions here // SDL2 doesn't have nanosleep, so use low-level functions here
// When this code will be ported to SDL3, use SDL_DelayNS #elif XASH_POSIX
#if XASH_POSIX
struct timespec ts = { struct timespec ts = {
.tv_sec = 0, .tv_sec = 0,
.tv_nsec = nsec, // just don't put large numbers here .tv_nsec = nsec, // just don't put large numbers here
@@ -207,8 +210,13 @@ static inline void Sys_RestoreCrashHandler( void )
============================================================================== ==============================================================================
*/ */
#if XASH_SDL >= 2
void Platform_Vibrate( float life, char flags ); // left for compatibility void Platform_Vibrate( float life, char flags ); // left for compatibility
void Platform_Vibrate2( float time, int low_freq, int high_freq, uint flags ); void Platform_Vibrate2( float time, int low_freq, int high_freq, uint flags );
#else
static inline void Platform_Vibrate( float life, char flags ) {}
static inline void Platform_Vibrate2( float time, int low_freq, int high_freq, uint flags ) {}
#endif
/* /*
============================================================================== ==============================================================================
@@ -217,51 +225,58 @@ void Platform_Vibrate2( float time, int low_freq, int high_freq, uint flags );
============================================================================== ==============================================================================
*/ */
// Gamepad support #if XASH_SDL // only SDL based backends implements these functions
#if XASH_SDL void Platform_PreCreateMove( void );
void GAME_EXPORT Platform_GetMousePos( int *x, int *y );
void GAME_EXPORT Platform_SetMousePos( int x, int y );
qboolean Platform_GetMouseGrab( void );
void Platform_SetMouseGrab( qboolean enable );
void Platform_SetCursorType( VGUI_DefaultCursor type );
int Platform_GetClipboardText( char *buffer, size_t size );
void Platform_SetClipboardText( const char *buffer );
#else
static inline void Platform_PreCreateMove( void ) { }
static inline void GAME_EXPORT Platform_SetMousePos( int x, int y ) { }
static inline void Platform_SetMouseGrab( qboolean enable ) { }
static inline void Platform_SetCursorType( VGUI_DefaultCursor type ) { }
static inline int Platform_GetClipboardText( char *buffer, size_t size ) { return 0; }
static inline void Platform_SetClipboardText( const char *buffer ) { }
static inline qboolean Platform_GetMouseGrab( void ) { return false; }
static inline void GAME_EXPORT Platform_GetMousePos( int *x, int *y )
{
if( x ) *x = 0;
if( y ) *y = 0;
}
#endif
#if XASH_SDL || XASH_DOS
void Platform_RunEvents( void );
void Platform_MouseMove( float *x, float *y );
#else
static inline void Platform_RunEvents( void ) { }
static inline void Platform_MouseMove( float *x, float *y )
{
if( x ) *x = 0.0f;
if( y ) *y = 0.0f;
}
#endif
#if XASH_SDL >= 2 || XASH_PSVITA || XASH_DOS || XASH_USE_EVDEV
void Platform_EnableTextInput( qboolean enable );
#else
static inline void Platform_EnableTextInput( qboolean enable ) { }
#endif
#if XASH_SDL >= 2
int Platform_JoyInit( void ); // returns number of connected gamepads, negative if error int Platform_JoyInit( void ); // returns number of connected gamepads, negative if error
void Platform_JoyShutdown( void ); void Platform_JoyShutdown( void );
void Platform_CalibrateGamepadGyro( 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
void Platform_EnableTextInput( qboolean enable );
key_modifier_t Platform_GetKeyModifiers( void ); key_modifier_t Platform_GetKeyModifiers( void );
// System events #else
void Platform_RunEvents( void ); static inline int Platform_JoyInit( void ) { return 0; }
// Mouse static inline void Platform_JoyShutdown( void ) { }
void Platform_GetMousePos( int *x, int *y ); static inline void Platform_CalibrateGamepadGyro( void ) { }
void Platform_SetMousePos( int x, int y ); static inline key_modifier_t Platform_GetKeyModifiers( void ) { return KeyModifier_None; }
void Platform_PreCreateMove( void );
void Platform_MouseMove( float *x, float *y );
void Platform_SetCursorType( VGUI_DefaultCursor type );
// Clipboard
int Platform_GetClipboardText( char *buffer, size_t size );
void Platform_SetClipboardText( const char *buffer );
#if XASH_SDL == 12
#define SDL_SetWindowGrab( wnd, state ) SDL_WM_GrabInput( (state) )
#define SDL_MinimizeWindow( wnd ) SDL_WM_IconifyWindow()
#define SDL_IsTextInputActive() host.textmode
#endif
#if !XASH_SDL
#define SDL_VERSION_ATLEAST( x, y, z ) 0
#endif #endif
static inline void Platform_SetTimer( float time ) static inline void Platform_SetTimer( float time )
@@ -314,7 +329,8 @@ void GL_SwapBuffers( void );
void *SW_LockBuffer( void ); void *SW_LockBuffer( void );
void SW_UnlockBuffer( void ); void SW_UnlockBuffer( void );
qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b ); qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b );
void Platform_Minimize_f( void );
qboolean R_GetWindowHandle( void **handle, int type );
// //
// in_evdev.c // in_evdev.c

View File

@@ -74,13 +74,12 @@ void Sys_Crash( int signal, siginfo_t *si, void *context )
#if !XASH_DEDICATED #if !XASH_DEDICATED
IN_SetMouseGrab( false ); IN_SetMouseGrab( false );
#endif #endif
host.crashed = true; host.status = HOST_CRASHED;
Platform_MessageBox( "Xash Error", message, false ); Platform_MessageBox( "Xash Error", message, false );
// log saved, now we can try to save configs and close log correctly, it may crash // log saved, now we can try to save configs and close log correctly, it may crash
if( host.type == HOST_NORMAL ) if( host.type == HOST_NORMAL )
CL_Crashed(); CL_Crashed();
host.status = HOST_CRASHED;
Sys_Quit( "crashed" ); Sys_Quit( "crashed" );
} }

View File

@@ -167,13 +167,12 @@ void Sys_CrashLibbacktrace( int signal, siginfo_t *si, void *context )
#if !XASH_DEDICATED #if !XASH_DEDICATED
IN_SetMouseGrab( false ); IN_SetMouseGrab( false );
#endif #endif
host.crashed = true; host.status = HOST_CRASHED;
Platform_MessageBox( "Xash Error", message, false ); Platform_MessageBox( "Xash Error", message, false );
// log saved, now we can try to save configs and close log correctly, it may crash // log saved, now we can try to save configs and close log correctly, it may crash
if( host.type == HOST_NORMAL ) if( host.type == HOST_NORMAL )
CL_Crashed(); CL_Crashed();
host.status = HOST_CRASHED;
Sys_Quit( "crashed" ); Sys_Quit( "crashed" );
} }

View File

@@ -196,13 +196,12 @@ void Sys_Crash( int signal, siginfo_t *si, void *context )
#if !XASH_DEDICATED #if !XASH_DEDICATED
IN_SetMouseGrab( false ); IN_SetMouseGrab( false );
#endif #endif
host.crashed = true; host.status = HOST_CRASHED;
Platform_MessageBox( "Xash Error", message, false ); Platform_MessageBox( "Xash Error", message, false );
// log saved, now we can try to save configs and close log correctly, it may crash // log saved, now we can try to save configs and close log correctly, it may crash
if( host.type == HOST_NORMAL ) if( host.type == HOST_NORMAL )
CL_Crashed(); CL_Crashed();
host.status = HOST_CRASHED;
Sys_Quit( "crashed" ); Sys_Quit( "crashed" );
} }

View File

@@ -149,7 +149,7 @@ void Posix_Daemonize( void )
static void Posix_SigtermCallback( int signal ) static void Posix_SigtermCallback( int signal )
{ {
string reason; string reason;
Con_Printf( reason, sizeof( reason ), "caught signal %d", signal ); Q_snprintf( reason, sizeof( reason ), "caught signal %d", signal );
Sys_Quit( reason ); Sys_Quit( reason );
} }

View File

@@ -14,6 +14,7 @@ GNU General Public License for more details.
*/ */
#include "platform/platform.h" #include "platform/platform.h"
#include "xash3d_mathlib.h"
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@@ -74,6 +75,7 @@ static const vrtld_export_t aux_exports[] =
VRTLD_EXPORT_SYMBOL( stpcpy ), VRTLD_EXPORT_SYMBOL( stpcpy ),
VRTLD_EXPORT_SYMBOL( rand ), VRTLD_EXPORT_SYMBOL( rand ),
VRTLD_EXPORT_SYMBOL( srand ), VRTLD_EXPORT_SYMBOL( srand ),
VRTLD_EXPORT_SYMBOL( rintf ),
VRTLD_EXPORT_SYMBOL( sceGxmMapMemory ), // needed by vgl_shim VRTLD_EXPORT_SYMBOL( sceGxmMapMemory ), // needed by vgl_shim
VRTLD_EXPORT( "dlopen", vrtld_dlopen ), VRTLD_EXPORT( "dlopen", vrtld_dlopen ),
VRTLD_EXPORT( "dlclose", vrtld_dlclose ), VRTLD_EXPORT( "dlclose", vrtld_dlclose ),
@@ -201,3 +203,19 @@ qboolean PSVita_GetBasePath( char *buf, const size_t buflen )
return false; return false;
} }
int PSVita_GetPSID( char *buf, const size_t buflen )
{
SceKernelOpenPsId id;
const int datasize = Q_min( buflen, sizeof( id ));
if( sceKernelGetOpenPsId( &id ) < 0 )
{
return 0;
}
else
{
memcpy( buf, &id.id[0], datasize );
return datasize;
}
}

View File

@@ -0,0 +1,354 @@
/*
host_sdl1.c - SDL event system handlers
Copyright (C) 2015-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>
#include <ctype.h>
#include "common.h"
#include "keydefs.h"
#include "input.h"
#include "client.h"
#include "vgui_draw.h"
#include "platform_sdl1.h"
#include "sound.h"
#include "vid_common.h"
#define SDL_SCANCODE_A SDLK_a
#define SDL_SCANCODE_Z SDLK_z
#define SDL_SCANCODE_1 SDLK_1
#define SDL_SCANCODE_9 SDLK_9
#define SDL_SCANCODE_F1 SDLK_F1
#define SDL_SCANCODE_F12 SDLK_F12
#define SDL_SCANCODE_GRAVE SDLK_BACKQUOTE
#define SDL_SCANCODE_0 SDLK_0
#define SDL_SCANCODE_BACKSLASH SDLK_BACKSLASH
#define SDL_SCANCODE_LEFTBRACKET SDLK_LEFTBRACKET
#define SDL_SCANCODE_RIGHTBRACKET SDLK_RIGHTBRACKET
#define SDL_SCANCODE_EQUALS SDLK_EQUALS
#define SDL_SCANCODE_MINUS SDLK_MINUS
#define SDL_SCANCODE_TAB SDLK_TAB
#define SDL_SCANCODE_RETURN SDLK_RETURN
#define SDL_SCANCODE_ESCAPE SDLK_ESCAPE
#define SDL_SCANCODE_SPACE SDLK_SPACE
#define SDL_SCANCODE_BACKSPACE SDLK_BACKSPACE
#define SDL_SCANCODE_UP SDLK_UP
#define SDL_SCANCODE_LEFT SDLK_LEFT
#define SDL_SCANCODE_DOWN SDLK_DOWN
#define SDL_SCANCODE_RIGHT SDLK_RIGHT
#define SDL_SCANCODE_LALT SDLK_LALT
#define SDL_SCANCODE_RALT SDLK_RALT
#define SDL_SCANCODE_LCTRL SDLK_LCTRL
#define SDL_SCANCODE_RCTRL SDLK_RCTRL
#define SDL_SCANCODE_LSHIFT SDLK_LSHIFT
#define SDL_SCANCODE_RSHIFT SDLK_RSHIFT
#define SDL_SCANCODE_LGUI SDLK_LMETA
#define SDL_SCANCODE_RGUI SDLK_RMETA
#define SDL_SCANCODE_INSERT SDLK_INSERT
#define SDL_SCANCODE_DELETE SDLK_DELETE
#define SDL_SCANCODE_PAGEDOWN SDLK_PAGEDOWN
#define SDL_SCANCODE_PAGEUP SDLK_PAGEUP
#define SDL_SCANCODE_HOME SDLK_HOME
#define SDL_SCANCODE_END SDLK_END
#define SDL_SCANCODE_KP_1 SDLK_KP1
#define SDL_SCANCODE_KP_2 SDLK_KP2
#define SDL_SCANCODE_KP_3 SDLK_KP3
#define SDL_SCANCODE_KP_4 SDLK_KP4
#define SDL_SCANCODE_KP_5 SDLK_KP5
#define SDL_SCANCODE_KP_6 SDLK_KP6
#define SDL_SCANCODE_KP_7 SDLK_KP7
#define SDL_SCANCODE_KP_8 SDLK_KP8
#define SDL_SCANCODE_KP_9 SDLK_KP9
#define SDL_SCANCODE_KP_0 SDLK_KP0
#define SDL_SCANCODE_KP_PERIOD SDLK_KP_PERIOD
#define SDL_SCANCODE_KP_ENTER SDLK_KP_ENTER
#define SDL_SCANCODE_KP_PLUS SDLK_KP_PLUS
#define SDL_SCANCODE_KP_MINUS SDLK_KP_MINUS
#define SDL_SCANCODE_KP_DIVIDE SDLK_KP_DIVIDE
#define SDL_SCANCODE_KP_MULTIPLY SDLK_KP_MULTIPLY
#define SDL_SCANCODE_NUMLOCKCLEAR SDLK_NUMLOCK
#define SDL_SCANCODE_CAPSLOCK SDLK_CAPSLOCK
#define SDL_SCANCODE_SLASH SDLK_SLASH
#define SDL_SCANCODE_PERIOD SDLK_PERIOD
#define SDL_SCANCODE_SEMICOLON SDLK_SEMICOLON
#define SDL_SCANCODE_APOSTROPHE SDLK_QUOTE
#define SDL_SCANCODE_COMMA SDLK_COMMA
#define SDL_SCANCODE_PRINTSCREEN SDLK_PRINT
#define SDL_SCANCODE_UNKNOWN SDLK_UNKNOWN
#define SDL_GetScancodeName( x ) "unknown"
/*
=============
SDLash_KeyEvent
=============
*/
static void SDLash_KeyEvent( SDL_KeyboardEvent key )
{
int down = key.state != SDL_RELEASED;
int keynum = key.keysym.sym;
if( host.textmode && down )
{
// this is how engine understands ctrl+c, ctrl+v and other hotkeys
if( cls.key_dest != key_game && FBitSet( SDL_GetModState(), KMOD_CTRL ))
{
if( keynum >= SDL_SCANCODE_A && keynum <= SDL_SCANCODE_Z )
{
keynum = keynum - SDL_SCANCODE_A + 1;
CL_CharEvent( keynum );
}
return;
}
if( keynum >= SDLK_KP0 && keynum <= SDLK_KP9 )
keynum -= SDLK_KP0 + '0';
if( isprint( keynum ))
{
if( FBitSet( SDL_GetModState(), KMOD_SHIFT ))
keynum = Key_ToUpper( keynum );
CL_CharEvent( keynum );
}
}
#define DECLARE_KEY_RANGE( min, max, repl ) \
if( keynum >= (min) && keynum <= (max) ) \
{ \
keynum = keynum - (min) + (repl); \
}
DECLARE_KEY_RANGE( SDL_SCANCODE_A, SDL_SCANCODE_Z, 'a' )
else DECLARE_KEY_RANGE( SDL_SCANCODE_1, SDL_SCANCODE_9, '1' )
else DECLARE_KEY_RANGE( SDL_SCANCODE_F1, SDL_SCANCODE_F12, K_F1 )
else
{
qboolean numLock = FBitSet( SDL_GetModState(), KMOD_NUM );
switch( keynum )
{
case SDL_SCANCODE_GRAVE: keynum = '`'; break;
case SDL_SCANCODE_0: keynum = '0'; break;
case SDL_SCANCODE_BACKSLASH: keynum = '\\'; break;
case SDL_SCANCODE_LEFTBRACKET: keynum = '['; break;
case SDL_SCANCODE_RIGHTBRACKET: keynum = ']'; break;
case SDL_SCANCODE_EQUALS: keynum = '='; break;
case SDL_SCANCODE_MINUS: keynum = '-'; break;
case SDL_SCANCODE_TAB: keynum = K_TAB; break;
case SDL_SCANCODE_RETURN: keynum = K_ENTER; break;
case SDL_SCANCODE_ESCAPE: keynum = K_ESCAPE; break;
case SDL_SCANCODE_SPACE: keynum = K_SPACE; break;
case SDL_SCANCODE_BACKSPACE: keynum = K_BACKSPACE; break;
case SDL_SCANCODE_UP: keynum = K_UPARROW; break;
case SDL_SCANCODE_LEFT: keynum = K_LEFTARROW; break;
case SDL_SCANCODE_DOWN: keynum = K_DOWNARROW; break;
case SDL_SCANCODE_RIGHT: keynum = K_RIGHTARROW; break;
case SDL_SCANCODE_LALT:
case SDL_SCANCODE_RALT: keynum = K_ALT; break;
case SDL_SCANCODE_LCTRL:
case SDL_SCANCODE_RCTRL: keynum = K_CTRL; break;
case SDL_SCANCODE_LSHIFT:
case SDL_SCANCODE_RSHIFT: keynum = K_SHIFT; break;
case SDL_SCANCODE_LGUI:
case SDL_SCANCODE_RGUI: keynum = K_WIN; break;
case SDL_SCANCODE_INSERT: keynum = K_INS; break;
case SDL_SCANCODE_DELETE: keynum = K_DEL; break;
case SDL_SCANCODE_PAGEDOWN: keynum = K_PGDN; break;
case SDL_SCANCODE_PAGEUP: keynum = K_PGUP; break;
case SDL_SCANCODE_HOME: keynum = K_HOME; break;
case SDL_SCANCODE_END: keynum = K_END; break;
case SDL_SCANCODE_KP_1: keynum = numLock ? '1' : K_KP_END; break;
case SDL_SCANCODE_KP_2: keynum = numLock ? '2' : K_KP_DOWNARROW; break;
case SDL_SCANCODE_KP_3: keynum = numLock ? '3' : K_KP_PGDN; break;
case SDL_SCANCODE_KP_4: keynum = numLock ? '4' : K_KP_LEFTARROW; break;
case SDL_SCANCODE_KP_5: keynum = numLock ? '5' : K_KP_5; break;
case SDL_SCANCODE_KP_6: keynum = numLock ? '6' : K_KP_RIGHTARROW; break;
case SDL_SCANCODE_KP_7: keynum = numLock ? '7' : K_KP_HOME; break;
case SDL_SCANCODE_KP_8: keynum = numLock ? '8' : K_KP_UPARROW; break;
case SDL_SCANCODE_KP_9: keynum = numLock ? '9' : K_KP_PGUP; break;
case SDL_SCANCODE_KP_0: keynum = numLock ? '0' : K_KP_INS; break;
case SDL_SCANCODE_KP_PERIOD: keynum = K_KP_DEL; break;
case SDL_SCANCODE_KP_ENTER: keynum = K_KP_ENTER; break;
case SDL_SCANCODE_KP_PLUS: keynum = K_KP_PLUS; break;
case SDL_SCANCODE_KP_MINUS: keynum = K_KP_MINUS; break;
case SDL_SCANCODE_KP_DIVIDE: keynum = K_KP_SLASH; break;
case SDL_SCANCODE_KP_MULTIPLY: keynum = '*'; break;
case SDL_SCANCODE_NUMLOCKCLEAR: keynum = K_KP_NUMLOCK; break;
case SDL_SCANCODE_CAPSLOCK: keynum = K_CAPSLOCK; break;
case SDL_SCANCODE_SLASH: keynum = '/'; break;
case SDL_SCANCODE_PERIOD: keynum = '.'; break;
case SDL_SCANCODE_SEMICOLON: keynum = ';'; break;
case SDL_SCANCODE_APOSTROPHE: keynum = '\''; break;
case SDL_SCANCODE_COMMA: keynum = ','; break;
case SDL_SCANCODE_PRINTSCREEN:
{
host.force_draw_version_time = host.realtime + FORCE_DRAW_VERSION_TIME;
break;
}
case SDL_SCANCODE_UNKNOWN:
{
if( down ) Con_Reportf( "%s: Unknown scancode\n", __func__ );
return;
}
default:
if( down ) Con_Reportf( "%s: Unknown key: %s = %i\n", __func__, SDL_GetScancodeName( keynum ), keynum );
return;
}
}
#undef DECLARE_KEY_RANGE
Key_Event( keynum, down );
}
/*
=============
SDLash_MouseEvent
=============
*/
static void SDLash_MouseEvent( SDL_MouseButtonEvent button )
{
int down;
if( button.state == SDL_RELEASED )
down = 0;
else
down = 1;
switch( button.button )
{
case SDL_BUTTON_LEFT:
IN_MouseEvent( 0, down );
break;
case SDL_BUTTON_RIGHT:
IN_MouseEvent( 1, down );
break;
case SDL_BUTTON_MIDDLE:
IN_MouseEvent( 2, down );
break;
case SDL_BUTTON_X1:
IN_MouseEvent( 3, down );
break;
case SDL_BUTTON_X2:
IN_MouseEvent( 4, down );
break;
case SDL_BUTTON_WHEELUP:
IN_MWheelEvent( -1 );
break;
case SDL_BUTTON_WHEELDOWN:
IN_MWheelEvent( 1 );
break;
default:
Con_Printf( "Unknown mouse button ID: %d\n", button.button );
}
}
static void SDLash_ActiveEvent( int gain )
{
if( gain )
{
host.status = HOST_FRAME;
if( cls.key_dest == key_game )
IN_ActivateMouse( );
host.force_draw_version_time = host.realtime + FORCE_DRAW_VERSION_TIME;
if( vid_fullscreen.value == WINDOW_MODE_FULLSCREEN )
VID_SetMode();
}
else
{
host.status = HOST_NOFOCUS;
if( cls.key_dest == key_game )
{
Key_ClearStates();
IN_DeactivateMouse();
}
host.force_draw_version_time = host.realtime + 2.0;
VID_RestoreScreenResolution();
}
}
/*
=============
SDLash_EventFilter
=============
*/
static void SDLash_EventHandler( SDL_Event *event )
{
switch ( event->type )
{
/* Mouse events */
case SDL_MOUSEMOTION:
if( host.mouse_visible )
SDL_GetRelativeMouseState( NULL, NULL );
break;
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEBUTTONDOWN:
SDLash_MouseEvent( event->button );
break;
/* Keyboard events */
case SDL_KEYDOWN:
case SDL_KEYUP:
SDLash_KeyEvent( event->key );
break;
case SDL_QUIT:
Sys_Quit( "caught SDL_QUIT" );
break;
case SDL_VIDEORESIZE:
VID_SaveWindowSize( event->resize.w, event->resize.h, false );
break;
case SDL_ACTIVEEVENT:
SDLash_ActiveEvent( event->active.gain );
break;
}
}
/*
=============
SDLash_RunEvents
=============
*/
void Platform_RunEvents( void )
{
SDL_Event event;
while( host.status != HOST_CRASHED && !host.shutdown_issued && SDL_PollEvent( &event ) )
SDLash_EventHandler( &event );
}
/*
========================
Platform_PreCreateMove
this should disable mouse look on client when m_ignore enabled
TODO: kill mouse in win32 clients too
========================
*/
void Platform_PreCreateMove( void )
{
if( m_ignore.value )
{
SDL_GetRelativeMouseState( NULL, NULL );
SDL_ShowCursor( SDL_TRUE );
}
}

View File

@@ -0,0 +1,154 @@
/*
in_sdl1.c - SDL input component
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>
#include "common.h"
#include "keydefs.h"
#include "input.h"
#include "client.h"
#include "vgui_draw.h"
#include "platform_sdl1.h"
#include "sound.h"
#include "vid_common.h"
#define SDL_WarpMouseInWindow( win, x, y ) SDL_WarpMouse( ( x ), ( y ) )
/*
=============
Platform_GetMousePos
=============
*/
void GAME_EXPORT Platform_GetMousePos( int *x, int *y )
{
SDL_GetMouseState( x, y );
if( x && window_width.value && window_width.value != refState.width )
{
float factor = refState.width / window_width.value;
*x = *x * factor;
}
if( y && window_height.value && window_height.value != refState.height )
{
float factor = refState.height / window_height.value;
*y = *y * factor;
}
}
/*
=============
Platform_SetMousePos
============
*/
void GAME_EXPORT Platform_SetMousePos( int x, int y )
{
SDL_WarpMouseInWindow( host.hWnd, x, y );
}
/*
========================
Platform_MouseMove
========================
*/
void Platform_MouseMove( float *x, float *y )
{
int m_x, m_y;
SDL_GetRelativeMouseState( &m_x, &m_y );
*x = (float)m_x;
*y = (float)m_y;
}
/*
=============
Platform_GetClipobardText
=============
*/
int Platform_GetClipboardText( char *buffer, size_t size )
{
buffer[0] = 0;
return 0;
}
/*
=============
Platform_SetClipobardText
=============
*/
void Platform_SetClipboardText( const char *buffer )
{
}
/*
========================
Platform_SetCursorType
========================
*/
void Platform_SetCursorType( VGUI_DefaultCursor type )
{
qboolean visible;
switch( type )
{
case dc_user:
case dc_none:
visible = false;
break;
default:
visible = true;
break;
}
// never disable cursor in touch emulation mode
if( !visible && Touch_WantVisibleCursor( ))
return;
host.mouse_visible = visible;
VGui_UpdateInternalCursorState( type );
if( host.mouse_visible )
{
SDL_ShowCursor( true );
}
else
{
SDL_ShowCursor( false );
}
}
/*
========================
Platform_GetMouseGrab
========================
*/
qboolean Platform_GetMouseGrab( void )
{
return SDL_WM_GrabInput( SDL_GRAB_QUERY ) != SDL_GRAB_OFF;
}
/*
========================
Platform_SetMouseGrab
========================
*/
void Platform_SetMouseGrab( qboolean enable )
{
SDL_WM_GrabInput( enable ? SDL_GRAB_ON : SDL_GRAB_OFF );
}

View File

@@ -0,0 +1,37 @@
/*
platform_sdl1.h - SDL backend internal header
Copyright (C) 2015-2018 a1batross
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
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.
*/
#pragma once
#ifndef KEYWRAPPER_H
#define KEYWRAPPER_H
#ifdef XASH_SDL
#include "platform.h"
// window management
void VID_RestoreScreenResolution( void );
qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode );
void VID_DestroyWindow( void );
void GL_InitExtensions( void );
qboolean GL_DeleteContext( void );
void VID_SaveWindowSize( int width, int height, qboolean maximized );
//
// joy_sdl.c
//
void SDLash_HandleGameControllerEvent( SDL_Event *ev );
#endif // XASH_SDL
#endif // KEYWRAPPER_H

View File

@@ -0,0 +1,268 @@
/*
s_sdl1.c - sound hardware output
Copyright (C) 2009 Uncle Mike
Copyright (C) 2025 Xash3D FWGS contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "common.h"
#include "platform.h"
#if XASH_SOUND == SOUND_SDL
#include "sound.h"
#include "voice.h"
#include <SDL.h>
#include <stdlib.h>
#define SAMPLE_16BIT_SHIFT 1
#define SECONDARY_BUFFER_SIZE 0x10000
#define SDL_GetCurrentAudioDriver() "legacysdl"
#define SDL_OpenAudioDevice( a, b, c, d, e ) SDL_OpenAudio( ( c ), ( d ) )
#define SDL_CloseAudioDevice( a ) SDL_CloseAudio()
#define SDL_PauseAudioDevice( a, b ) SDL_PauseAudio( ( b ) )
#define SDL_LockAudioDevice( x ) SDL_LockAudio()
#define SDL_UnlockAudioDevice( x ) SDL_UnlockAudio()
#define SDLash_IsAudioError( x ) (( x ) != 0)
/*
=======================================================================
Global variables. Must be visible to window-procedure function
so it can unlock and free the data block after it has been played.
=======================================================================
*/
static int sdl_dev;
static char sdl_backend_name[32];
static void SDL_SoundCallback( void *userdata, Uint8 *stream, int len )
{
const int size = dma.samples << 1;
int pos;
int wrapped;
if( !dma.buffer )
{
memset( stream, 0, len );
return;
}
pos = dma.samplepos << 1;
if( pos >= size )
pos = dma.samplepos = 0;
wrapped = pos + len - size;
if( wrapped < 0 )
{
memcpy( stream, dma.buffer + pos, len );
dma.samplepos += len >> 1;
}
else
{
int remaining = size - pos;
memcpy( stream, dma.buffer + pos, remaining );
memcpy( stream + remaining, dma.buffer, wrapped );
dma.samplepos = wrapped >> 1;
}
if( dma.samplepos >= size )
dma.samplepos = 0;
}
/*
==================
SNDDMA_Init
Try to find a sound device to mix for.
Returns false if nothing is found.
==================
*/
qboolean SNDDMA_Init( void )
{
SDL_AudioSpec desired, obtained;
int samplecount;
const char *driver = NULL;
// reinitialize SDL with our driver just in case
if( SDL_WasInit( SDL_INIT_AUDIO ))
SDL_QuitSubSystem( SDL_INIT_AUDIO );
if( SDL_InitSubSystem( SDL_INIT_AUDIO ))
{
Con_Reportf( S_ERROR "Audio: SDL: %s \n", SDL_GetError( ) );
return false;
}
memset( &desired, 0, sizeof( desired ) );
desired.freq = SOUND_DMA_SPEED;
desired.format = AUDIO_S16LSB;
desired.samples = 1024;
desired.channels = 2;
desired.callback = SDL_SoundCallback;
sdl_dev = SDL_OpenAudioDevice( NULL, 0, &desired, &obtained, 0 );
if( SDLash_IsAudioError( sdl_dev ))
{
Con_Printf( "Couldn't open SDL audio: %s\n", SDL_GetError( ) );
return false;
}
if( obtained.format != AUDIO_S16LSB )
{
Con_Printf( "SDL audio format %d unsupported.\n", obtained.format );
goto fail;
}
if( obtained.channels != 1 && obtained.channels != 2 )
{
Con_Printf( "SDL audio channels %d unsupported.\n", obtained.channels );
goto fail;
}
dma.format.speed = obtained.freq;
dma.format.channels = obtained.channels;
dma.format.width = 2;
samplecount = s_samplecount.value;
if( !samplecount )
samplecount = 0x8000;
dma.samples = samplecount * obtained.channels;
dma.buffer = Mem_Calloc( sndpool, dma.samples * 2 );
dma.samplepos = 0;
Con_Printf( "Using SDL audio driver: %s @ %d Hz\n", SDL_GetCurrentAudioDriver( ), obtained.freq );
Q_snprintf( sdl_backend_name, sizeof( sdl_backend_name ), "SDL" );
dma.initialized = true;
dma.backendName = sdl_backend_name;
SNDDMA_Activate( true );
return true;
fail:
SNDDMA_Shutdown( );
return false;
}
/*
==============
SNDDMA_BeginPainting
Makes sure dma.buffer is valid
===============
*/
void SNDDMA_BeginPainting( void )
{
SDL_LockAudioDevice( sdl_dev );
}
/*
==============
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
Also unlocks the dsound buffer
===============
*/
void SNDDMA_Submit( void )
{
SDL_UnlockAudioDevice( sdl_dev );
}
/*
==============
SNDDMA_Shutdown
Reset the sound device for exiting
===============
*/
void SNDDMA_Shutdown( void )
{
Con_Printf( "Shutting down audio.\n" );
dma.initialized = false;
if( sdl_dev )
{
SNDDMA_Activate( false );
SDL_CloseAudioDevice( sdl_dev );
}
if( SDL_WasInit( SDL_INIT_AUDIO ))
SDL_QuitSubSystem( SDL_INIT_AUDIO );
if( dma.buffer )
{
Mem_Free( dma.buffer );
dma.buffer = NULL;
}
}
/*
===========
SNDDMA_Activate
Called when the main window gains or loses focus.
The window have been destroyed and recreated
between a deactivate and an activate.
===========
*/
void SNDDMA_Activate( qboolean active )
{
if( !dma.initialized )
return;
SDL_PauseAudioDevice( sdl_dev, !active );
}
/*
===========
VoiceCapture_Init
===========
*/
qboolean VoiceCapture_Init( void )
{
return false;
}
/*
===========
VoiceCapture_Activate
===========
*/
qboolean VoiceCapture_Activate( qboolean activate )
{
return false;
}
/*
===========
VoiceCapture_Lock
===========
*/
qboolean VoiceCapture_Lock( qboolean lock )
{
return false;
}
/*
==========
VoiceCapture_Shutdown
==========
*/
void VoiceCapture_Shutdown( void )
{
}
#endif // XASH_SOUND == SOUND_SDL

View File

@@ -0,0 +1,61 @@
/*
sys_sdl1.c - SDL1 system utils
Copyright (C) 2018 a1batross
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
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>
#include "platform.h"
#include "platform_sdl1.h"
#if XASH_TIMER == TIMER_SDL
double Platform_DoubleTime( void )
{
static Uint64 g_PerformanceFrequency;
static Uint64 g_ClockStart;
Uint64 CurrentTime;
if( !g_PerformanceFrequency )
{
g_PerformanceFrequency = SDL_GetPerformanceFrequency();
g_ClockStart = SDL_GetPerformanceCounter();
}
CurrentTime = SDL_GetPerformanceCounter();
return (double)( CurrentTime - g_ClockStart ) / (double)( g_PerformanceFrequency );
}
void Platform_Sleep( int msec )
{
SDL_Delay( msec );
}
#endif // XASH_TIMER == TIMER_SDL
#if XASH_MESSAGEBOX == MSGBOX_SDL
void Platform_MessageBox( const char *title, const char *message, qboolean parentMainWindow )
{
SDL_ShowSimpleMessageBox( SDL_MESSAGEBOX_ERROR, title, message, parentMainWindow ? host.hWnd : NULL );
}
#endif // XASH_MESSAGEBOX == MSGBOX_SDL
void SDLash_Init( const char *basedir )
{
if( SDL_Init( SDL_INIT_TIMER | SDL_INIT_VIDEO ))
{
Sys_Warn( "SDL_Init failed: %s", SDL_GetError() );
host.type = HOST_DEDICATED;
}
}
void SDLash_Shutdown( void )
{
SDL_Quit();
}

View File

@@ -0,0 +1,535 @@
/*
vid_sdl1.c - SDL vid component
Copyright (C) 2018 a1batross
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
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>
#include "common.h"
#include "client.h"
#include "vid_common.h"
#include "platform_sdl1.h"
static vidmode_t *vidmodes = NULL;
static int num_vidmodes = 0;
static void GL_SetupAttributes( void );
struct
{
int prev_width, prev_height;
} sdlState = { 640, 480 };
struct
{
int width, height;
SDL_Surface *surf;
SDL_Surface *win;
} sw;
void Platform_Minimize_f( void )
{
SDL_WM_IconifyWindow();
}
qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b )
{
sw.width = width;
sw.height = height;
sw.win = SDL_GetVideoSurface();
// sdl will create renderer if hw framebuffer unavailiable, so cannot fallback here
// if it is failed, it is not possible to draw with SDL in REF_SOFTWARE mode
if( !sw.win )
{
Sys_Warn( "failed to initialize software output, try running with -glblit flag" );
return false;
}
*bpp = sw.win->format->BytesPerPixel;
*r = sw.win->format->Rmask;
*g = sw.win->format->Gmask;
*b = sw.win->format->Bmask;
*stride = sw.win->pitch / sw.win->format->BytesPerPixel;
return true;
}
void *SW_LockBuffer( void )
{
sw.win = SDL_GetVideoSurface();
// prevent buffer overrun
if( !sw.win || sw.win->w < sw.width || sw.win->h < sw.height )
return NULL;
// real window pixels (x11 shm region, dma buffer, etc)
// or SDL_Renderer texture if not supported
SDL_LockSurface( sw.win );
return sw.win->pixels;
}
void SW_UnlockBuffer( void )
{
// already blitted
SDL_UnlockSurface( sw.win );
SDL_Flip( host.hWnd );
}
int R_MaxVideoModes( void )
{
return num_vidmodes;
}
vidmode_t *R_GetVideoMode( int num )
{
if( !vidmodes || num < 0 || num >= R_MaxVideoModes() )
{
return NULL;
}
return vidmodes + num;
}
static void R_InitVideoModes( void )
{
char buf[MAX_VA_STRING];
SDL_Rect **modes;
int len = 0, i = 0, j;
modes = SDL_ListModes( NULL, SDL_FULLSCREEN );
if( !modes || modes == (void*)-1 )
return;
for( len = 0; modes[len]; len++ );
vidmodes = Mem_Malloc( host.mempool, len * sizeof( vidmode_t ) );
// from smallest to largest
for( ; i < len; i++ )
{
SDL_Rect *mode = modes[len - i - 1];
for( j = 0; j < num_vidmodes; j++ )
{
if( mode->w == vidmodes[j].width &&
mode->h == vidmodes[j].height )
{
break;
}
}
if( j != num_vidmodes )
continue;
vidmodes[num_vidmodes].width = mode->w;
vidmodes[num_vidmodes].height = mode->h;
Q_snprintf( buf, sizeof( buf ), "%ix%i", mode->w, mode->h );
vidmodes[num_vidmodes].desc = copystring( buf );
num_vidmodes++;
}
}
static void R_FreeVideoModes( void )
{
int i;
if( !vidmodes )
return;
for( i = 0; i < num_vidmodes; i++ )
Mem_Free( (char*)vidmodes[i].desc );
Mem_Free( vidmodes );
vidmodes = NULL;
}
/*
=================
GL_GetProcAddress
=================
*/
void *GL_GetProcAddress( const char *name )
{
void *func = SDL_GL_GetProcAddress( name );
if( !func )
Con_Reportf( S_ERROR "%s failed for %s\n", __func__, name );
return func;
}
/*
===============
GL_UpdateSwapInterval
===============
*/
void GL_UpdateSwapInterval( void )
{
}
/*
=================
GL_DeleteContext
always return false
=================
*/
qboolean GL_DeleteContext( void )
{
return false;
}
/*
=================
GL_CreateContext
=================
*/
static qboolean GL_CreateContext( void )
{
return true;
}
/*
=================
GL_UpdateContext
=================
*/
static qboolean GL_UpdateContext( void )
{
return true;
}
void VID_SaveWindowSize( int width, int height, qboolean maximized )
{
int render_w = width, render_h = height;
VID_SetDisplayTransform( &render_w, &render_h );
R_SaveVideoMode( width, height, render_w, render_h, maximized );
}
static qboolean VID_SetScreenResolution( int width, int height, window_mode_t window_mode )
{
VID_SaveWindowSize( width, height, true );
return true;
}
void VID_RestoreScreenResolution( void )
{
}
static qboolean VID_CreateWindowWithSafeGL( const char *wndname, int xpos, int ypos, int w, int h, uint32_t flags )
{
while( glw_state.safe >= SAFE_NO && glw_state.safe < SAFE_LAST )
{
host.hWnd = sw.surf = SDL_SetVideoMode( w, h, 16, flags );
// we have window, exit loop
if( host.hWnd )
break;
Con_Reportf( S_ERROR "%s: couldn't create '%s' with safegl level %d: %s\n", __func__, wndname, glw_state.safe, SDL_GetError());
glw_state.safe++;
if( !gl_msaa_samples.value && glw_state.safe == SAFE_NOMSAA )
glw_state.safe++; // no need to skip msaa, if we already disabled it
GL_SetupAttributes(); // re-choose attributes
// try again create window
}
// window creation has failed...
if( glw_state.safe >= SAFE_LAST )
return false;
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
=================
*/
qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
{
string wndname;
Uint32 flags = 0;
Q_strncpy( wndname, GI->title, sizeof( wndname ));
if( window_mode != WINDOW_MODE_WINDOWED )
SetBits( flags, SDL_FULLSCREEN|SDL_HWSURFACE );
if( !glw_state.software )
SetBits( flags, SDL_OPENGL );
if( !VID_CreateWindowWithSafeGL( wndname, 0, 0, width, height, flags ))
return false;
VID_SaveWindowSize( width, height, false );
return true;
}
/*
=================
VID_DestroyWindow
=================
*/
void VID_DestroyWindow( void )
{
GL_DeleteContext();
VID_RestoreScreenResolution();
if( host.hWnd )
host.hWnd = NULL;
if( refState.fullScreen )
refState.fullScreen = false;
}
/*
==================
GL_SetupAttributes
==================
*/
static void GL_SetupAttributes( void )
{
ref.dllFuncs.GL_SetupAttributes( glw_state.safe );
}
void GL_SwapBuffers( void )
{
SDL_Flip( host.hWnd );
}
int GL_SetAttribute( int attr, int val )
{
switch( attr )
{
#define MAP_REF_API_ATTRIBUTE_TO_SDL( name ) case REF_##name: return SDL_GL_SetAttribute( SDL_##name, val );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_RED_SIZE );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_GREEN_SIZE );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_BLUE_SIZE );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_ALPHA_SIZE );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_DOUBLEBUFFER );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_DEPTH_SIZE );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_STENCIL_SIZE );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_MULTISAMPLEBUFFERS );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_MULTISAMPLESAMPLES );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_ACCELERATED_VISUAL );
#undef MAP_REF_API_ATTRIBUTE_TO_SDL
}
return -1;
}
int GL_GetAttribute( int attr, int *val )
{
switch( attr )
{
#define MAP_REF_API_ATTRIBUTE_TO_SDL( name ) case REF_##name: return SDL_GL_GetAttribute( SDL_##name, val );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_RED_SIZE );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_GREEN_SIZE );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_BLUE_SIZE );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_ALPHA_SIZE );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_DOUBLEBUFFER );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_DEPTH_SIZE );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_STENCIL_SIZE );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_MULTISAMPLEBUFFERS );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_MULTISAMPLESAMPLES );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_ACCELERATED_VISUAL );
#undef MAP_REF_API_ATTRIBUTE_TO_SDL
}
return 0;
}
/*
==================
R_Init_Video
==================
*/
qboolean R_Init_Video( const int type )
{
string safe;
qboolean retval;
refState.desktopBitsPixel = 16;
switch( type )
{
case REF_SOFTWARE:
glw_state.software = true;
break;
case REF_GL:
if( !glw_state.safe && Sys_GetParmFromCmdLine( "-safegl", safe ) )
glw_state.safe = bound( SAFE_NO, Q_atoi( safe ), SAFE_DONTCARE );
// refdll can request some attributes
GL_SetupAttributes( );
if( SDL_GL_LoadLibrary( NULL ) < 0 )
{
Con_Reportf( S_ERROR "Couldn't initialize OpenGL: %s\n", SDL_GetError());
return false;
}
break;
default:
Host_Error( "Can't initialize unknown context type %d!\n", type );
break;
}
if( !(retval = VID_SetMode()) )
{
return retval;
}
switch( type )
{
case REF_GL:
// refdll also can check extensions
ref.dllFuncs.GL_InitExtensions();
break;
case REF_SOFTWARE:
default:
break;
}
R_InitVideoModes();
host.renderinfo_changed = false;
return true;
}
rserr_t R_ChangeDisplaySettings( int width, int height, window_mode_t window_mode )
{
refState.fullScreen = window_mode != WINDOW_MODE_WINDOWED;
Con_Reportf( "%s: Setting video mode to %dx%d %s\n", __func__, width, height, refState.fullScreen ? "fullscreen" : "windowed" );
if( !host.hWnd )
{
if( !VID_CreateWindow( width, height, window_mode ))
return rserr_invalid_mode;
}
else if( refState.fullScreen )
{
if( !VID_SetScreenResolution( width, height, window_mode ))
return rserr_invalid_fullscreen;
}
else
{
VID_RestoreScreenResolution();
VID_SaveWindowSize( width, height, true );
}
return rserr_ok;
}
/*
==================
VID_SetMode
Set the described video mode
==================
*/
qboolean VID_SetMode( void )
{
int iScreenWidth, iScreenHeight;
rserr_t err;
window_mode_t window_mode;
iScreenWidth = Cvar_VariableInteger( "width" );
iScreenHeight = Cvar_VariableInteger( "height" );
if( iScreenWidth < VID_MIN_WIDTH ||
iScreenHeight < VID_MIN_HEIGHT ) // trying to get resolution automatically by default
{
iScreenWidth = 320;
iScreenHeight = 240;
}
window_mode = bound( 0, vid_fullscreen.value, WINDOW_MODE_COUNT - 1 );
SetBits( gl_vsync.flags, FCVAR_CHANGED );
if(( err = R_ChangeDisplaySettings( iScreenWidth, iScreenHeight, window_mode )) == rserr_ok )
{
sdlState.prev_width = iScreenWidth;
sdlState.prev_height = iScreenHeight;
}
else
{
if( err == rserr_invalid_fullscreen )
{
Cvar_DirectSet( &vid_fullscreen, "0" );
Con_Reportf( S_ERROR "%s: fullscreen unavailable in this mode\n", __func__ );
Sys_Warn( "fullscreen unavailable in this mode!" );
if(( err = R_ChangeDisplaySettings( iScreenWidth, iScreenHeight, WINDOW_MODE_WINDOWED )) == rserr_ok )
return true;
}
else if( err == rserr_invalid_mode )
{
Con_Reportf( S_ERROR "%s: invalid mode\n", __func__ );
Sys_Warn( "invalid mode, engine will run in %dx%d", sdlState.prev_width, sdlState.prev_height );
}
// try setting it back to something safe
if(( err = R_ChangeDisplaySettings( sdlState.prev_width, sdlState.prev_height, WINDOW_MODE_WINDOWED )) != rserr_ok )
{
Con_Reportf( S_ERROR "%s: could not revert to safe mode\n", __func__ );
Sys_Warn( "could not revert to safe mode!" );
return false;
}
}
return true;
}
ref_window_type_t R_GetWindowHandle( void **handle, ref_window_type_t type )
{
return REF_WINDOW_TYPE_NULL;
}
/*
==================
R_Free_Video
==================
*/
void R_Free_Video( void )
{
GL_DeleteContext ();
VID_DestroyWindow ();
R_FreeVideoModes();
ref.dllFuncs.GL_ClearExtensions();
}

View File

@@ -1,6 +1,6 @@
/* /*
events.c - SDL event system handlers host_sdl2.c - SDL event system handlers
Copyright (C) 2015-2017 a1batross Copyright (C) 2015-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 defined( XASH_SDL ) && !XASH_DEDICATED
#include <SDL.h> #include <SDL.h>
#include <ctype.h> #include <ctype.h>
@@ -21,75 +20,10 @@ GNU General Public License for more details.
#include "input.h" #include "input.h"
#include "client.h" #include "client.h"
#include "vgui_draw.h" #include "vgui_draw.h"
#include "events.h" #include "platform_sdl2.h"
#include "sound.h" #include "sound.h"
#include "vid_common.h" #include "vid_common.h"
#if !SDL_VERSION_ATLEAST( 2, 0, 0 )
#define SDL_SCANCODE_A SDLK_a
#define SDL_SCANCODE_Z SDLK_z
#define SDL_SCANCODE_1 SDLK_1
#define SDL_SCANCODE_9 SDLK_9
#define SDL_SCANCODE_F1 SDLK_F1
#define SDL_SCANCODE_F12 SDLK_F12
#define SDL_SCANCODE_GRAVE SDLK_BACKQUOTE
#define SDL_SCANCODE_0 SDLK_0
#define SDL_SCANCODE_BACKSLASH SDLK_BACKSLASH
#define SDL_SCANCODE_LEFTBRACKET SDLK_LEFTBRACKET
#define SDL_SCANCODE_RIGHTBRACKET SDLK_RIGHTBRACKET
#define SDL_SCANCODE_EQUALS SDLK_EQUALS
#define SDL_SCANCODE_MINUS SDLK_MINUS
#define SDL_SCANCODE_TAB SDLK_TAB
#define SDL_SCANCODE_RETURN SDLK_RETURN
#define SDL_SCANCODE_ESCAPE SDLK_ESCAPE
#define SDL_SCANCODE_SPACE SDLK_SPACE
#define SDL_SCANCODE_BACKSPACE SDLK_BACKSPACE
#define SDL_SCANCODE_UP SDLK_UP
#define SDL_SCANCODE_LEFT SDLK_LEFT
#define SDL_SCANCODE_DOWN SDLK_DOWN
#define SDL_SCANCODE_RIGHT SDLK_RIGHT
#define SDL_SCANCODE_LALT SDLK_LALT
#define SDL_SCANCODE_RALT SDLK_RALT
#define SDL_SCANCODE_LCTRL SDLK_LCTRL
#define SDL_SCANCODE_RCTRL SDLK_RCTRL
#define SDL_SCANCODE_LSHIFT SDLK_LSHIFT
#define SDL_SCANCODE_RSHIFT SDLK_RSHIFT
#define SDL_SCANCODE_LGUI SDLK_LMETA
#define SDL_SCANCODE_RGUI SDLK_RMETA
#define SDL_SCANCODE_INSERT SDLK_INSERT
#define SDL_SCANCODE_DELETE SDLK_DELETE
#define SDL_SCANCODE_PAGEDOWN SDLK_PAGEDOWN
#define SDL_SCANCODE_PAGEUP SDLK_PAGEUP
#define SDL_SCANCODE_HOME SDLK_HOME
#define SDL_SCANCODE_END SDLK_END
#define SDL_SCANCODE_KP_1 SDLK_KP1
#define SDL_SCANCODE_KP_2 SDLK_KP2
#define SDL_SCANCODE_KP_3 SDLK_KP3
#define SDL_SCANCODE_KP_4 SDLK_KP4
#define SDL_SCANCODE_KP_5 SDLK_KP5
#define SDL_SCANCODE_KP_6 SDLK_KP6
#define SDL_SCANCODE_KP_7 SDLK_KP7
#define SDL_SCANCODE_KP_8 SDLK_KP8
#define SDL_SCANCODE_KP_9 SDLK_KP9
#define SDL_SCANCODE_KP_0 SDLK_KP0
#define SDL_SCANCODE_KP_PERIOD SDLK_KP_PERIOD
#define SDL_SCANCODE_KP_ENTER SDLK_KP_ENTER
#define SDL_SCANCODE_KP_PLUS SDLK_KP_PLUS
#define SDL_SCANCODE_KP_MINUS SDLK_KP_MINUS
#define SDL_SCANCODE_KP_DIVIDE SDLK_KP_DIVIDE
#define SDL_SCANCODE_KP_MULTIPLY SDLK_KP_MULTIPLY
#define SDL_SCANCODE_NUMLOCKCLEAR SDLK_NUMLOCK
#define SDL_SCANCODE_CAPSLOCK SDLK_CAPSLOCK
#define SDL_SCANCODE_SLASH SDLK_SLASH
#define SDL_SCANCODE_PERIOD SDLK_PERIOD
#define SDL_SCANCODE_SEMICOLON SDLK_SEMICOLON
#define SDL_SCANCODE_APOSTROPHE SDLK_QUOTE
#define SDL_SCANCODE_COMMA SDLK_COMMA
#define SDL_SCANCODE_PRINTSCREEN SDLK_PRINT
#define SDL_SCANCODE_UNKNOWN SDLK_UNKNOWN
#define SDL_GetScancodeName( x ) "unknown"
#endif
/* /*
============= =============
SDLash_KeyEvent SDLash_KeyEvent
@@ -99,11 +33,7 @@ SDLash_KeyEvent
static void SDLash_KeyEvent( SDL_KeyboardEvent key ) static void SDLash_KeyEvent( SDL_KeyboardEvent key )
{ {
int down = key.state != SDL_RELEASED; int down = key.state != SDL_RELEASED;
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
int keynum = key.keysym.scancode; int keynum = key.keysym.scancode;
#else
int keynum = key.keysym.sym;
#endif
#if XASH_ANDROID #if XASH_ANDROID
if( keynum == SDL_SCANCODE_VOLUMEUP || keynum == SDL_SCANCODE_VOLUMEDOWN ) if( keynum == SDL_SCANCODE_VOLUMEUP || keynum == SDL_SCANCODE_VOLUMEDOWN )
@@ -126,24 +56,11 @@ static void SDLash_KeyEvent( SDL_KeyboardEvent key )
return; return;
} }
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
// ignore printable keys, they are coming through SDL_TEXTINPUT // ignore printable keys, they are coming through SDL_TEXTINPUT
if(( keynum >= SDL_SCANCODE_A && keynum <= SDL_SCANCODE_Z ) if(( keynum >= SDL_SCANCODE_A && keynum <= SDL_SCANCODE_Z )
|| ( keynum >= SDL_SCANCODE_1 && keynum <= SDL_SCANCODE_0 ) || ( keynum >= SDL_SCANCODE_1 && keynum <= SDL_SCANCODE_0 )
|| ( keynum >= SDL_SCANCODE_KP_1 && keynum <= SDL_SCANCODE_KP_0 )) || ( keynum >= SDL_SCANCODE_KP_1 && keynum <= SDL_SCANCODE_KP_0 ))
return; return;
#else
if( keynum >= SDLK_KP0 && keynum <= SDLK_KP9 )
keynum -= SDLK_KP0 + '0';
if( isprint( keynum ))
{
if( FBitSet( SDL_GetModState(), KMOD_SHIFT ))
keynum = Key_ToUpper( keynum );
CL_CharEvent( keynum );
}
#endif
} }
#define DECLARE_KEY_RANGE( min, max, repl ) \ #define DECLARE_KEY_RANGE( min, max, repl ) \
@@ -222,7 +139,6 @@ static void SDLash_KeyEvent( SDL_KeyboardEvent key )
} }
case SDL_SCANCODE_PAUSE: keynum = K_PAUSE; break; case SDL_SCANCODE_PAUSE: keynum = K_PAUSE; break;
case SDL_SCANCODE_SCROLLLOCK: keynum = K_SCROLLLOCK; break; case SDL_SCANCODE_SCROLLLOCK: keynum = K_SCROLLLOCK; break;
#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
case SDL_SCANCODE_MUTE: case SDL_SCANCODE_MUTE:
@@ -232,7 +148,6 @@ static void SDLash_KeyEvent( SDL_KeyboardEvent key )
case SDL_SCANCODE_BRIGHTNESSUP: case SDL_SCANCODE_BRIGHTNESSUP:
case SDL_SCANCODE_SELECT: case SDL_SCANCODE_SELECT:
return; return;
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
case SDL_SCANCODE_UNKNOWN: case SDL_SCANCODE_UNKNOWN:
{ {
if( down ) Con_Reportf( "%s: Unknown scancode\n", __func__ ); if( down ) Con_Reportf( "%s: Unknown scancode\n", __func__ );
@@ -259,10 +174,8 @@ static void SDLash_MouseEvent( SDL_MouseButtonEvent button )
{ {
int down; int down;
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
if( button.which == SDL_TOUCH_MOUSEID ) if( button.which == SDL_TOUCH_MOUSEID )
return; return;
#endif
if( button.state == SDL_RELEASED ) if( button.state == SDL_RELEASED )
down = 0; down = 0;
@@ -288,14 +201,6 @@ static void SDLash_MouseEvent( SDL_MouseButtonEvent button )
case SDL_BUTTON_X2: case SDL_BUTTON_X2:
IN_MouseEvent( 4, down ); IN_MouseEvent( 4, down );
break; break;
#if ! SDL_VERSION_ATLEAST( 2, 0, 0 )
case SDL_BUTTON_WHEELUP:
IN_MWheelEvent( -1 );
break;
case SDL_BUTTON_WHEELDOWN:
IN_MWheelEvent( 1 );
break;
#endif // ! SDL_VERSION_ATLEAST( 2, 0, 0 )
default: default:
Con_Printf( "Unknown mouse button ID: %d\n", button.button ); Con_Printf( "Unknown mouse button ID: %d\n", button.button );
} }
@@ -307,7 +212,6 @@ SDLash_InputEvent
============= =============
*/ */
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
static void SDLash_InputEvent( SDL_TextInputEvent input ) static void SDLash_InputEvent( SDL_TextInputEvent input )
{ {
const char *text; const char *text;
@@ -328,7 +232,6 @@ static void SDLash_InputEvent( SDL_TextInputEvent input )
CL_CharEvent( ch ); CL_CharEvent( ch );
} }
} }
#endif // SDL_VERSION_AT_LEAST( 2, 0, 0 )
static void SDLash_ActiveEvent( int gain ) static void SDLash_ActiveEvent( int gain )
{ {
@@ -394,7 +297,6 @@ static void SDLash_EventHandler( SDL_Event *event )
case SDL_QUIT: case SDL_QUIT:
Sys_Quit( "caught SDL_QUIT" ); Sys_Quit( "caught SDL_QUIT" );
break; break;
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
case SDL_MOUSEWHEEL: case SDL_MOUSEWHEEL:
IN_MWheelEvent( event->wheel.y ); IN_MWheelEvent( event->wheel.y );
break; break;
@@ -464,10 +366,12 @@ static void SDLash_EventHandler( SDL_Event *event )
case SDL_CONTROLLERBUTTONUP: case SDL_CONTROLLERBUTTONUP:
case SDL_CONTROLLERDEVICEADDED: case SDL_CONTROLLERDEVICEADDED:
case SDL_CONTROLLERDEVICEREMOVED: case SDL_CONTROLLERDEVICEREMOVED:
#if SDL_VERSION_ATLEAST( 2, 0, 14 )
case SDL_CONTROLLERTOUCHPADDOWN: case SDL_CONTROLLERTOUCHPADDOWN:
case SDL_CONTROLLERTOUCHPADMOTION: case SDL_CONTROLLERTOUCHPADMOTION:
case SDL_CONTROLLERTOUCHPADUP: case SDL_CONTROLLERTOUCHPADUP:
case SDL_CONTROLLERSENSORUPDATE: case SDL_CONTROLLERSENSORUPDATE:
#endif
SDLash_HandleGameControllerEvent( event ); SDLash_HandleGameControllerEvent( event );
break; break;
@@ -528,14 +432,6 @@ static void SDLash_EventHandler( SDL_Event *event )
default: default:
break; break;
} }
#else
case SDL_VIDEORESIZE:
VID_SaveWindowSize( event->resize.w, event->resize.h );
break;
case SDL_ACTIVEEVENT:
SDLash_ActiveEvent( event->active.gain );
break;
#endif
} }
} }
@@ -549,7 +445,7 @@ void Platform_RunEvents( void )
{ {
SDL_Event event; SDL_Event event;
while( !host.crashed && !host.shutdown_issued && SDL_PollEvent( &event ) ) while( host.status != HOST_CRASHED && !host.shutdown_issued && SDL_PollEvent( &event ) )
SDLash_EventHandler( &event ); SDLash_EventHandler( &event );
#if XASH_PSVITA #if XASH_PSVITA
@@ -573,5 +469,3 @@ void Platform_PreCreateMove( void )
SDL_ShowCursor( SDL_TRUE ); SDL_ShowCursor( SDL_TRUE );
} }
} }
#endif // defined( XASH_SDL ) && !XASH_DEDICATED

View File

@@ -19,19 +19,15 @@ GNU General Public License for more details.
#include "input.h" #include "input.h"
#include "client.h" #include "client.h"
#include "vgui_draw.h" #include "vgui_draw.h"
#include "events.h" #include "platform_sdl2.h"
#include "sound.h" #include "sound.h"
#include "vid_common.h" #include "vid_common.h"
#if !SDL_VERSION_ATLEAST( 2, 0, 0 )
#define SDL_WarpMouseInWindow( win, x, y ) SDL_WarpMouse( ( x ), ( y ) )
#else
static struct static struct
{ {
qboolean initialized; qboolean initialized;
SDL_Cursor *cursors[dc_last]; SDL_Cursor *cursors[dc_last];
} cursors; } cursors;
#endif
static struct static struct
{ {
@@ -95,7 +91,6 @@ Platform_GetClipobardText
*/ */
int Platform_GetClipboardText( char *buffer, size_t size ) int Platform_GetClipboardText( char *buffer, size_t size )
{ {
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
int textLength; int textLength;
char *sdlbuffer = SDL_GetClipboardText(); char *sdlbuffer = SDL_GetClipboardText();
@@ -111,10 +106,6 @@ int Platform_GetClipboardText( char *buffer, size_t size )
} }
SDL_free( sdlbuffer ); SDL_free( sdlbuffer );
return textLength; return textLength;
#else // SDL_VERSION_ATLEAST( 2, 0, 0 )
buffer[0] = 0;
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
return 0;
} }
/* /*
@@ -125,9 +116,7 @@ Platform_SetClipobardText
*/ */
void Platform_SetClipboardText( const char *buffer ) void Platform_SetClipboardText( const char *buffer )
{ {
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
SDL_SetClipboardText( buffer ); SDL_SetClipboardText( buffer );
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
} }
#if !XASH_PSVITA #if !XASH_PSVITA
@@ -140,9 +129,7 @@ SDLash_EnableTextInput
*/ */
void Platform_EnableTextInput( qboolean enable ) void Platform_EnableTextInput( qboolean enable )
{ {
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
enable ? SDL_StartTextInput() : SDL_StopTextInput(); enable ? SDL_StartTextInput() : SDL_StopTextInput();
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
} }
#endif // !XASH_PSVITA #endif // !XASH_PSVITA
@@ -155,7 +142,6 @@ SDLash_InitCursors
*/ */
void SDLash_InitCursors( void ) void SDLash_InitCursors( void )
{ {
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
if( cursors.initialized ) if( cursors.initialized )
SDLash_FreeCursors(); SDLash_FreeCursors();
@@ -174,7 +160,6 @@ void SDLash_InitCursors( void )
cursors.cursors[dc_no] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO); cursors.cursors[dc_no] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO);
cursors.cursors[dc_hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND); cursors.cursors[dc_hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);
cursors.initialized = true; cursors.initialized = true;
#endif
} }
/* /*
@@ -185,7 +170,6 @@ SDLash_FreeCursors
*/ */
void SDLash_FreeCursors( void ) void SDLash_FreeCursors( void )
{ {
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
int i = 0; int i = 0;
for( ; i < ARRAYSIZE( cursors.cursors ); i++ ) for( ; i < ARRAYSIZE( cursors.cursors ); i++ )
@@ -196,7 +180,6 @@ void SDLash_FreeCursors( void )
} }
cursors.initialized = false; cursors.initialized = false;
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
} }
/* /*
@@ -227,7 +210,6 @@ void Platform_SetCursorType( VGUI_DefaultCursor type )
host.mouse_visible = visible; host.mouse_visible = visible;
VGui_UpdateInternalCursorState( type ); VGui_UpdateInternalCursorState( type );
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
if( host.mouse_visible ) if( host.mouse_visible )
{ {
if( cursors.initialized ) if( cursors.initialized )
@@ -254,16 +236,26 @@ void Platform_SetCursorType( VGUI_DefaultCursor type )
SDL_ShowCursor( false ); SDL_ShowCursor( false );
} }
#else }
if( host.mouse_visible )
{ /*
SDL_ShowCursor( true ); ========================
} Platform_GetMouseGrab
else ========================
{ */
SDL_ShowCursor( false ); qboolean Platform_GetMouseGrab( void )
} {
#endif return SDL_GetWindowGrab( host.hWnd );
}
/*
========================
Platform_SetMouseGrab
========================
*/
void Platform_SetMouseGrab( qboolean enable )
{
SDL_SetWindowGrab( host.hWnd, enable );
} }
/* /*
@@ -274,7 +266,6 @@ Platform_GetKeyModifiers
*/ */
key_modifier_t Platform_GetKeyModifiers( void ) key_modifier_t Platform_GetKeyModifiers( void )
{ {
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
SDL_Keymod modFlags; SDL_Keymod modFlags;
key_modifier_t resultFlags; key_modifier_t resultFlags;
@@ -302,7 +293,4 @@ key_modifier_t Platform_GetKeyModifiers( void )
SetBits( resultFlags, KeyModifier_LeftSuper ); SetBits( resultFlags, KeyModifier_LeftSuper );
return resultFlags; return resultFlags;
#else
return KeyModifier_None;
#endif
} }

View File

@@ -14,12 +14,11 @@ GNU General Public License for more details.
*/ */
#include <SDL.h> #include <SDL.h>
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
#include "common.h" #include "common.h"
#include "keydefs.h" #include "keydefs.h"
#include "input.h" #include "input.h"
#include "client.h" #include "client.h"
#include "events.h" #include "platform_sdl2.h"
static const int g_button_mapping[] = static const int g_button_mapping[] =
{ {
@@ -121,18 +120,16 @@ static void SDLash_GameControllerAddMappings( const char *name )
static void SDLash_SetActiveGameController( SDL_JoystickID id ) static void SDLash_SetActiveGameController( SDL_JoystickID id )
{ {
SDL_GameController *oldgc;
if( g_current_gamepad_id == id ) if( g_current_gamepad_id == id )
return; return;
g_current_gamepad_id = id;
oldgc = g_current_gamepad;
#if SDL_VERSION_ATLEAST( 2, 0, 14 ) #if SDL_VERSION_ATLEAST( 2, 0, 14 )
SDL_GameControllerSetSensorEnabled( oldgc, SDL_SENSOR_GYRO, SDL_FALSE ); // going to change active controller, disable gyro events in old
SDL_GameControllerSetSensorEnabled( g_current_gamepad, SDL_SENSOR_GYRO, SDL_FALSE );
#endif // SDL_VERSION_ATLEAST( 2, 0, 14 ) #endif // SDL_VERSION_ATLEAST( 2, 0, 14 )
g_current_gamepad_id = id;
if( id < 0 ) if( id < 0 )
{ {
g_current_gamepad = NULL; g_current_gamepad = NULL;
@@ -231,6 +228,7 @@ static void SDLash_GameControllerRemoved( SDL_JoystickID id )
} }
} }
#if SDL_VERSION_ATLEAST( 2, 0, 14 )
static void SDLash_GameControllerSensorUpdate( SDL_ControllerSensorEvent sensor ) static void SDLash_GameControllerSensorUpdate( SDL_ControllerSensorEvent sensor )
{ {
vec3_t data; vec3_t data;
@@ -256,6 +254,7 @@ static void SDLash_GameControllerSensorUpdate( SDL_ControllerSensorEvent sensor
VectorSubtract( sensor.data, gyrocal.calibrated_values, data ); VectorSubtract( sensor.data, gyrocal.calibrated_values, data );
Joy_GyroEvent( data ); Joy_GyroEvent( data );
} }
#endif
void SDLash_HandleGameControllerEvent( SDL_Event *ev ) void SDLash_HandleGameControllerEvent( SDL_Event *ev )
{ {
@@ -385,19 +384,3 @@ void Platform_JoyShutdown( void )
SDL_QuitSubSystem( SDL_INIT_GAMECONTROLLER ); 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

@@ -1,5 +1,5 @@
/* /*
events.h - SDL backend internal header platform_sdl2.h - SDL backend internal header
Copyright (C) 2015-2018 a1batross Copyright (C) 2015-2018 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
@@ -18,7 +18,7 @@ GNU General Public License for more details.
#define KEYWRAPPER_H #define KEYWRAPPER_H
#ifdef XASH_SDL #ifdef XASH_SDL
#include "platform/platform.h" #include "platform.h"
// window management // window management
void VID_RestoreScreenResolution( void ); void VID_RestoreScreenResolution( void );

View File

@@ -14,7 +14,7 @@ GNU General Public License for more details.
*/ */
#include "common.h" #include "common.h"
#include "platform/platform.h" #include "platform.h"
#if XASH_SOUND == SOUND_SDL #if XASH_SOUND == SOUND_SDL
#include "sound.h" #include "sound.h"
@@ -26,17 +26,7 @@ GNU General Public License for more details.
#define SAMPLE_16BIT_SHIFT 1 #define SAMPLE_16BIT_SHIFT 1
#define SECONDARY_BUFFER_SIZE 0x10000 #define SECONDARY_BUFFER_SIZE 0x10000
#if ! SDL_VERSION_ATLEAST( 2, 0, 0 )
#define SDL_GetCurrentAudioDriver() "legacysdl"
#define SDL_OpenAudioDevice( a, b, c, d, e ) SDL_OpenAudio( ( c ), ( d ) )
#define SDL_CloseAudioDevice( a ) SDL_CloseAudio()
#define SDL_PauseAudioDevice( a, b ) SDL_PauseAudio( ( b ) )
#define SDL_LockAudioDevice( x ) SDL_LockAudio()
#define SDL_UnlockAudioDevice( x ) SDL_UnlockAudio()
#define SDLash_IsAudioError( x ) (( x ) != 0)
#else
#define SDLash_IsAudioError( x ) (( x ) == 0) #define SDLash_IsAudioError( x ) (( x ) == 0)
#endif
/* /*
======================================================================= =======================================================================
@@ -55,14 +45,6 @@ static void SDL_SoundCallback( void *userdata, Uint8 *stream, int len )
int pos; int pos;
int wrapped; int wrapped;
#if ! SDL_VERSION_ATLEAST( 2, 0, 0 )
if( !dma.buffer )
{
memset( stream, 0, len );
return;
}
#endif
pos = dma.samplepos << 1; pos = dma.samplepos << 1;
if( pos >= size ) if( pos >= size )
pos = dma.samplepos = 0; pos = dma.samplepos = 0;

View File

@@ -14,8 +14,8 @@ GNU General Public License for more details.
*/ */
#include <SDL.h> #include <SDL.h>
#include "platform/platform.h" #include "platform.h"
#include "events.h" #include "platform_sdl2.h"
#if XASH_TIMER == TIMER_SDL #if XASH_TIMER == TIMER_SDL
double Platform_DoubleTime( void ) double Platform_DoubleTime( void )
@@ -116,7 +116,10 @@ void SDLash_Init( const char *basedir )
#if SDL_MAJOR_VERSION >= 2 #if SDL_MAJOR_VERSION >= 2
SDL_SetHint( SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0" ); SDL_SetHint( SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0" );
#ifdef SDL_HINT_MOUSE_TOUCH_EVENTS
SDL_SetHint( SDL_HINT_MOUSE_TOUCH_EVENTS, "0" ); SDL_SetHint( SDL_HINT_MOUSE_TOUCH_EVENTS, "0" );
#endif // SDL_HINT_MOUSE_TOUCH_EVENTS
SDL_SetHint( SDL_HINT_TOUCH_MOUSE_EVENTS, "0" ); SDL_SetHint( SDL_HINT_TOUCH_MOUSE_EVENTS, "0" );
SDL_StopTextInput(); SDL_StopTextInput();

View File

@@ -12,12 +12,13 @@ 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 <SDL_config.h>
#include <SDL_syswm.h>
#include "common.h" #include "common.h"
#include "client.h" #include "client.h"
#include "vid_common.h" #include "vid_common.h"
#include "platform/sdl/events.h" #include "platform_sdl2.h"
static vidmode_t *vidmodes = NULL; static vidmode_t *vidmodes = NULL;
static int num_vidmodes = 0; static int num_vidmodes = 0;
@@ -29,21 +30,24 @@ struct
struct struct
{ {
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_Renderer *renderer; SDL_Renderer *renderer;
SDL_Texture *tex; SDL_Texture *tex;
#endif
int width, height; int width, height;
SDL_Surface *surf; SDL_Surface *surf;
SDL_Surface *win; SDL_Surface *win;
} sw; } sw;
void Platform_Minimize_f( void )
{
if( host.hWnd )
SDL_MinimizeWindow( host.hWnd );
}
qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b ) qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b )
{ {
sw.width = width; sw.width = width;
sw.height = height; sw.height = height;
#if SDL_VERSION_ATLEAST(2, 0, 0)
if( sw.renderer ) if( sw.renderer )
{ {
unsigned int format = SDL_GetWindowPixelFormat( host.hWnd ); unsigned int format = SDL_GetWindowPixelFormat( host.hWnd );
@@ -111,16 +115,10 @@ qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *
sw.renderer = NULL; sw.renderer = NULL;
} }
} }
#endif
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
if( !sw.renderer ) if( !sw.renderer )
{ {
sw.win = SDL_GetWindowSurface( host.hWnd ); sw.win = SDL_GetWindowSurface( host.hWnd );
#else // SDL_VERSION_ATLEAST( 2, 0, 0 )
{
sw.win = SDL_GetVideoSurface();
#endif
// sdl will create renderer if hw framebuffer unavailiable, so cannot fallback here // sdl will create renderer if hw framebuffer unavailiable, so cannot fallback here
// if it is failed, it is not possible to draw with SDL in REF_SOFTWARE mode // if it is failed, it is not possible to draw with SDL in REF_SOFTWARE mode
@@ -153,7 +151,6 @@ qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *
void *SW_LockBuffer( void ) void *SW_LockBuffer( void )
{ {
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
if( sw.renderer ) if( sw.renderer )
{ {
void *pixels; void *pixels;
@@ -168,22 +165,17 @@ void *SW_LockBuffer( void )
sw.win = SDL_GetWindowSurface( host.hWnd ); sw.win = SDL_GetWindowSurface( host.hWnd );
//if( !sw.win ) //if( !sw.win )
//SDL_GetWindowSurface( host.hWnd ); //SDL_GetWindowSurface( host.hWnd );
#else // SDL_VERSION_ATLEAST( 2, 0, 0 )
sw.win = SDL_GetVideoSurface();
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
// prevent buffer overrun // prevent buffer overrun
if( !sw.win || sw.win->w < sw.width || sw.win->h < sw.height ) if( !sw.win || sw.win->w < sw.width || sw.win->h < sw.height )
return NULL; return NULL;
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
if( sw.surf ) if( sw.surf )
{ {
SDL_LockSurface( sw.surf ); SDL_LockSurface( sw.surf );
return sw.surf->pixels; return sw.surf->pixels;
} }
else else
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
{ {
// real window pixels (x11 shm region, dma buffer, etc) // real window pixels (x11 shm region, dma buffer, etc)
// or SDL_Renderer texture if not supported // or SDL_Renderer texture if not supported
@@ -194,7 +186,6 @@ void *SW_LockBuffer( void )
void SW_UnlockBuffer( void ) void SW_UnlockBuffer( void )
{ {
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
if( sw.renderer ) if( sw.renderer )
{ {
SDL_Rect src, dst; SDL_Rect src, dst;
@@ -226,16 +217,11 @@ void SW_UnlockBuffer( void )
SDL_BlitSurface( sw.surf, &src, sw.win, &dst ); SDL_BlitSurface( sw.surf, &src, sw.win, &dst );
return; return;
} }
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
// already blitted // already blitted
SDL_UnlockSurface( sw.win ); SDL_UnlockSurface( sw.win );
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
SDL_UpdateWindowSurface( host.hWnd ); SDL_UpdateWindowSurface( host.hWnd );
#else // SDL_VERSION_ATLEAST( 2, 0, 0 )
SDL_Flip( host.hWnd );
#endif
} }
int R_MaxVideoModes( void ) int R_MaxVideoModes( void )
@@ -256,9 +242,12 @@ vidmode_t *R_GetVideoMode( int num )
static void R_InitVideoModes( void ) 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, 24, 0 )
SDL_Point point = { window_xpos.value, window_ypos.value }; SDL_Point point = { window_xpos.value, window_ypos.value };
int displayIndex = SDL_GetPointDisplayIndex( &point ); int displayIndex = SDL_GetPointDisplayIndex( &point );
#else
int displayIndex = 0;
#endif
int i, modes; int i, modes;
num_vidmodes = 0; num_vidmodes = 0;
@@ -301,43 +290,6 @@ static void R_InitVideoModes( void )
num_vidmodes++; num_vidmodes++;
} }
#else // SDL_VERSION_ATLEAST( 2, 0, 0 )
SDL_Rect **modes;
int len = 0, i = 0, j;
modes = SDL_ListModes( NULL, SDL_FULLSCREEN );
if( !modes || modes == (void*)-1 )
return;
for( len = 0; modes[len]; len++ );
vidmodes = Mem_Malloc( host.mempool, len * sizeof( vidmode_t ) );
// from smallest to largest
for( ; i < len; i++ )
{
SDL_Rect *mode = modes[len - i - 1];
for( j = 0; j < num_vidmodes; j++ )
{
if( mode->w == vidmodes[j].width &&
mode->h == vidmodes[j].height )
{
break;
}
}
if( j != num_vidmodes )
continue;
vidmodes[num_vidmodes].width = mode->w;
vidmodes[num_vidmodes].height = mode->h;
Q_snprintf( buf, sizeof( buf ), "%ix%i", mode->w, mode->h );
vidmodes[num_vidmodes].desc = copystring( buf );
num_vidmodes++;
}
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
} }
@@ -370,7 +322,7 @@ static void WIN_SetDPIAwareness( void )
BOOL ( __stdcall *pSetProcessDPIAware )( void ); BOOL ( __stdcall *pSetProcessDPIAware )( void );
BOOL bSuccess = FALSE; BOOL bSuccess = FALSE;
if( ( hModule = LoadLibrary( "shcore.dll" ) ) ) if( ( hModule = LoadLibraryW( L"shcore.dll" ) ) )
{ {
if( ( pSetProcessDpiAwareness = (void*)GetProcAddress( hModule, "SetProcessDpiAwareness" ) ) ) if( ( pSetProcessDpiAwareness = (void*)GetProcAddress( hModule, "SetProcessDpiAwareness" ) ) )
{ {
@@ -395,7 +347,7 @@ static void WIN_SetDPIAwareness( void )
{ {
Con_Reportf( "%s: Trying SetProcessDPIAware...\n", __func__ ); Con_Reportf( "%s: Trying SetProcessDPIAware...\n", __func__ );
if( ( hModule = LoadLibrary( "user32.dll" ) ) ) if( ( hModule = LoadLibraryW( L"user32.dll" ) ) )
{ {
if( ( pSetProcessDPIAware = ( void* )GetProcAddress( hModule, "SetProcessDPIAware" ) ) ) if( ( pSetProcessDPIAware = ( void* )GetProcAddress( hModule, "SetProcessDPIAware" ) ) )
{ {
@@ -416,14 +368,13 @@ static void WIN_SetDPIAwareness( void )
} }
} }
#include <SDL_syswm.h>
static qboolean WIN_SetWindowIcon( HICON ico ) static qboolean WIN_SetWindowIcon( HICON ico )
{ {
SDL_SysWMinfo wminfo; SDL_SysWMinfo wminfo;
SDL_VERSION( &wminfo.version ); SDL_VERSION( &wminfo.version );
if( SDL_GetWindowWMInfo( host.hWnd, &wminfo ) == SDL_TRUE ) if( SDL_GetWindowWMInfo( host.hWnd, &wminfo ) == SDL_TRUE && wminfo.info.subsystem == SDL_SYSWM_WINDOWS )
{ {
SendMessage( wminfo.info.win.window, WM_SETICON, ICON_SMALL, (LONG_PTR)ico ); SendMessage( wminfo.info.win.window, WM_SETICON, ICON_SMALL, (LONG_PTR)ico );
SendMessage( wminfo.info.win.window, WM_SETICON, ICON_BIG, (LONG_PTR)ico ); SendMessage( wminfo.info.win.window, WM_SETICON, ICON_BIG, (LONG_PTR)ico );
@@ -487,7 +438,6 @@ GL_UpdateSwapInterval
*/ */
void GL_UpdateSwapInterval( void ) void GL_UpdateSwapInterval( void )
{ {
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
if( FBitSet( gl_vsync.flags, FCVAR_CHANGED )) if( FBitSet( gl_vsync.flags, FCVAR_CHANGED ))
{ {
ClearBits( gl_vsync.flags, FCVAR_CHANGED ); ClearBits( gl_vsync.flags, FCVAR_CHANGED );
@@ -495,7 +445,6 @@ void GL_UpdateSwapInterval( void )
if( SDL_GL_SetSwapInterval( gl_vsync.value ) < 0 ) if( SDL_GL_SetSwapInterval( gl_vsync.value ) < 0 )
Con_Reportf( S_ERROR "SDL_GL_SetSwapInterval: %s\n", SDL_GetError( )); Con_Reportf( S_ERROR "SDL_GL_SetSwapInterval: %s\n", SDL_GetError( ));
} }
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
} }
/* /*
@@ -507,13 +456,11 @@ always return false
*/ */
qboolean GL_DeleteContext( void ) qboolean GL_DeleteContext( void )
{ {
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
if( glw_state.context ) if( glw_state.context )
{ {
SDL_GL_DeleteContext(glw_state.context); SDL_GL_DeleteContext(glw_state.context);
glw_state.context = NULL; glw_state.context = NULL;
} }
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
return false; return false;
} }
@@ -524,13 +471,11 @@ GL_CreateContext
*/ */
static qboolean GL_CreateContext( void ) static qboolean GL_CreateContext( void )
{ {
#if SDL_VERSION_ATLEAST(2, 0, 0)
if( ( glw_state.context = SDL_GL_CreateContext( host.hWnd ) ) == NULL) if( ( glw_state.context = SDL_GL_CreateContext( host.hWnd ) ) == NULL)
{ {
Con_Reportf( S_ERROR "%s: %s\n", __func__, SDL_GetError( )); Con_Reportf( S_ERROR "%s: %s\n", __func__, SDL_GetError( ));
return GL_DeleteContext(); return GL_DeleteContext();
} }
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
return true; return true;
} }
@@ -541,13 +486,11 @@ GL_UpdateContext
*/ */
static qboolean GL_UpdateContext( void ) static qboolean GL_UpdateContext( void )
{ {
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
if( SDL_GL_MakeCurrent( host.hWnd, glw_state.context ) < 0 ) if( SDL_GL_MakeCurrent( host.hWnd, glw_state.context ) < 0 )
{ {
Con_Reportf( S_ERROR "%s: %s\n", __func__, SDL_GetError( )); Con_Reportf( S_ERROR "%s: %s\n", __func__, SDL_GetError( ));
return GL_DeleteContext(); return GL_DeleteContext();
} }
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
return true; return true;
} }
@@ -555,12 +498,10 @@ void VID_SaveWindowSize( int width, int height, qboolean maximized )
{ {
int render_w = width, render_h = height; int render_w = width, render_h = height;
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
if( !glw_state.software ) if( !glw_state.software )
SDL_GL_GetDrawableSize( host.hWnd, &render_w, &render_h ); SDL_GL_GetDrawableSize( host.hWnd, &render_w, &render_h );
else else
SDL_RenderSetLogicalSize( sw.renderer, width, height ); SDL_RenderSetLogicalSize( sw.renderer, width, height );
#endif
VID_SetDisplayTransform( &render_w, &render_h ); VID_SetDisplayTransform( &render_w, &render_h );
R_SaveVideoMode( width, height, render_w, render_h, maximized ); R_SaveVideoMode( width, height, render_w, render_h, maximized );
@@ -568,7 +509,6 @@ void VID_SaveWindowSize( int width, int height, qboolean maximized )
static qboolean VID_SetScreenResolution( int width, int height, window_mode_t window_mode ) static qboolean VID_SetScreenResolution( int width, int height, window_mode_t window_mode )
{ {
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
SDL_DisplayMode got; SDL_DisplayMode got;
Uint32 wndFlags = 0; Uint32 wndFlags = 0;
@@ -621,9 +561,6 @@ static qboolean VID_SetScreenResolution( int width, int height, window_mode_t wi
SDL_SetWindowSize( host.hWnd, got.w, got.h ); SDL_SetWindowSize( host.hWnd, got.w, got.h );
VID_SaveWindowSize( got.w, got.h, true ); VID_SaveWindowSize( got.w, got.h, true );
#else
VID_SaveWindowSize( width, height, true );
#endif
return true; return true;
} }
@@ -632,7 +569,7 @@ void VID_RestoreScreenResolution( void )
// on mobile platform fullscreen is designed to be always on // on mobile platform fullscreen is designed to be always on
// and code below minimizes our window if we're in full screen // and code below minimizes our window if we're in full screen
// don't do that on mobile devices // don't do that on mobile devices
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) && !XASH_MOBILE_PLATFORM #if !XASH_MOBILE_PLATFORM
switch((window_mode_t)vid_fullscreen.value ) switch((window_mode_t)vid_fullscreen.value )
{ {
case WINDOW_MODE_WINDOWED: case WINDOW_MODE_WINDOWED:
@@ -651,23 +588,33 @@ void VID_RestoreScreenResolution( void )
SDL_SetWindowFullscreen( host.hWnd, 0 ); SDL_SetWindowFullscreen( host.hWnd, 0 );
break; break;
} }
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 ) #endif // !XASH_MOBILE_PLATFORM
} }
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
static void VID_SetWindowIcon( SDL_Window *hWnd ) static void VID_SetWindowIcon( SDL_Window *hWnd )
{ {
rgbdata_t *icon = NULL; rgbdata_t *icon = NULL;
char iconpath[MAX_STRING]; char iconpath[MAX_STRING];
#if XASH_WIN32 // ICO support only for Win32 #if XASH_WIN32 // ICO support only for Win32
const char *localIcoPath; const char *disk_iconpath = FS_GetDiskPath( GI->iconpath, true );
HINSTANCE hInst = GetModuleHandle( NULL );
if(( localIcoPath = FS_GetDiskPath( GI->iconpath, true ))) if( disk_iconpath )
{ {
HICON ico = (HICON)LoadImage( NULL, localIcoPath, IMAGE_ICON, 0, 0, LR_LOADFROMFILE|LR_DEFAULTSIZE ); int len = MultiByteToWideChar( CP_UTF8, 0, disk_iconpath, -1, NULL, 0 );
if( ico && WIN_SetWindowIcon( ico ))
return; if( len >= 0 )
{
wchar_t *path = malloc( len * sizeof( *path ));
HICON ico;
MultiByteToWideChar( CP_UTF8, 0, disk_iconpath, -1, path, len );
ico = (HICON)LoadImageW( NULL, path, IMAGE_ICON, 0, 0, LR_LOADFROMFILE|LR_DEFAULTSIZE );
free( path );
if( ico && WIN_SetWindowIcon( ico ))
return;
}
} }
#endif // XASH_WIN32 #endif // XASH_WIN32
@@ -679,34 +626,29 @@ static void VID_SetWindowIcon( SDL_Window *hWnd )
{ {
SDL_Surface *surface = SDL_CreateRGBSurfaceFrom( icon->buffer, SDL_Surface *surface = SDL_CreateRGBSurfaceFrom( icon->buffer,
icon->width, icon->height, 32, 4 * icon->width, icon->width, icon->height, 32, 4 * icon->width,
0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 ); 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 );
FS_FreeImage( icon );
if( surface ) if( surface )
{ {
SDL_SetWindowIcon( host.hWnd, surface ); SDL_SetWindowIcon( host.hWnd, surface );
SDL_FreeSurface( surface ); SDL_FreeSurface( surface );
FS_FreeImage( icon );
return; return;
} }
FS_FreeImage( icon );
} }
#if XASH_WIN32 // ICO support only for Win32 #if XASH_WIN32 // ICO support only for Win32
WIN_SetWindowIcon( LoadIcon( hInst, MAKEINTRESOURCE( 101 ))); WIN_SetWindowIcon( LoadIcon( GetModuleHandle( NULL ), MAKEINTRESOURCE( 101 )));
#endif #endif
} }
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
static qboolean VID_CreateWindowWithSafeGL( const char *wndname, int xpos, int ypos, int w, int h, uint32_t flags ) static qboolean VID_CreateWindowWithSafeGL( const char *wndname, int xpos, int ypos, int w, int h, uint32_t flags )
{ {
while( glw_state.safe >= SAFE_NO && glw_state.safe < SAFE_LAST ) while( glw_state.safe >= SAFE_NO && glw_state.safe < SAFE_LAST )
{ {
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
host.hWnd = SDL_CreateWindow( wndname, xpos, ypos, w, h, flags ); host.hWnd = SDL_CreateWindow( wndname, xpos, ypos, w, h, flags );
#else
host.hWnd = sw.surf = SDL_SetVideoMode( width, height, 16, flags );
#endif
// we have window, exit loop // we have window, exit loop
if( host.hWnd ) if( host.hWnd )
break; break;
@@ -756,7 +698,6 @@ VID_CreateWindow
qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode ) qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
{ {
string wndname; string wndname;
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
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;
@@ -773,7 +714,7 @@ 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 *display_rects = ( SDL_Rect * )malloc( num_displays * sizeof( SDL_Rect )); 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 );
@@ -885,21 +826,6 @@ qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
return false; return false;
} }
#else // SDL_VERSION_ATLEAST( 2, 0, 0 )
Uint32 flags = 0;
Q_strncpy( wndname, GI->title, sizeof( wndname ));
if( window_mode != WINDOW_MODE_WINDOWED )
SetBits( flags, SDL_FULLSCREEN|SDL_HWSURFACE );
if( !glw_state.software )
SetBits( flags, SDL_OPENGL );
if( !VID_CreateWindowWithSafeGL( wndname, xpos, ypos, width, height, wndFlags ))
return false;
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
VID_SaveWindowSize( width, height, maximized ); VID_SaveWindowSize( width, height, maximized );
return true; return true;
@@ -917,9 +843,7 @@ void VID_DestroyWindow( void )
VID_RestoreScreenResolution(); VID_RestoreScreenResolution();
if( host.hWnd ) if( host.hWnd )
{ {
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
SDL_DestroyWindow ( host.hWnd ); SDL_DestroyWindow ( host.hWnd );
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
host.hWnd = NULL; host.hWnd = NULL;
} }
@@ -936,20 +860,14 @@ GL_SetupAttributes
*/ */
static void GL_SetupAttributes( void ) static void GL_SetupAttributes( void )
{ {
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
SDL_GL_ResetAttributes(); SDL_GL_ResetAttributes();
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
ref.dllFuncs.GL_SetupAttributes( glw_state.safe ); ref.dllFuncs.GL_SetupAttributes( glw_state.safe );
} }
void GL_SwapBuffers( void ) void GL_SwapBuffers( void )
{ {
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
SDL_GL_SwapWindow( host.hWnd ); SDL_GL_SwapWindow( host.hWnd );
#else // SDL_VERSION_ATLEAST( 2, 0, 0 )
SDL_Flip( host.hWnd );
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
} }
int GL_SetAttribute( int attr, int val ) int GL_SetAttribute( int attr, int val )
@@ -967,7 +885,6 @@ int GL_SetAttribute( int attr, int val )
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_MULTISAMPLEBUFFERS ); MAP_REF_API_ATTRIBUTE_TO_SDL( GL_MULTISAMPLEBUFFERS );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_MULTISAMPLESAMPLES ); MAP_REF_API_ATTRIBUTE_TO_SDL( GL_MULTISAMPLESAMPLES );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_ACCELERATED_VISUAL ); MAP_REF_API_ATTRIBUTE_TO_SDL( GL_ACCELERATED_VISUAL );
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_CONTEXT_MAJOR_VERSION ); MAP_REF_API_ATTRIBUTE_TO_SDL( GL_CONTEXT_MAJOR_VERSION );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_CONTEXT_MINOR_VERSION ); MAP_REF_API_ATTRIBUTE_TO_SDL( GL_CONTEXT_MINOR_VERSION );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_CONTEXT_EGL ); MAP_REF_API_ATTRIBUTE_TO_SDL( GL_CONTEXT_EGL );
@@ -978,12 +895,11 @@ int GL_SetAttribute( int attr, int val )
#ifdef SDL_HINT_OPENGL_ES_DRIVER #ifdef SDL_HINT_OPENGL_ES_DRIVER
if( val == REF_GL_CONTEXT_PROFILE_ES ) if( val == REF_GL_CONTEXT_PROFILE_ES )
{ {
SDL_SetHint(SDL_HINT_OPENGL_ES_DRIVER, "1"); SDL_SetHint( SDL_HINT_OPENGL_ES_DRIVER, "1" );
SDL_SetHint( "SDL_VIDEO_X11_FORCE_EGL", "1" ); SDL_SetHint( "SDL_VIDEO_X11_FORCE_EGL", "1" );
} }
#endif // SDL_HINT_OPENGL_ES_DRIVER #endif // SDL_HINT_OPENGL_ES_DRIVER
return SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, val ); return SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, val );
#endif
#if SDL_VERSION_ATLEAST( 2, 0, 4 ) #if SDL_VERSION_ATLEAST( 2, 0, 4 )
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_CONTEXT_RELEASE_BEHAVIOR ); MAP_REF_API_ATTRIBUTE_TO_SDL( GL_CONTEXT_RELEASE_BEHAVIOR );
#endif #endif
@@ -1012,7 +928,6 @@ int GL_GetAttribute( int attr, int *val )
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_MULTISAMPLEBUFFERS ); MAP_REF_API_ATTRIBUTE_TO_SDL( GL_MULTISAMPLEBUFFERS );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_MULTISAMPLESAMPLES ); MAP_REF_API_ATTRIBUTE_TO_SDL( GL_MULTISAMPLESAMPLES );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_ACCELERATED_VISUAL ); MAP_REF_API_ATTRIBUTE_TO_SDL( GL_ACCELERATED_VISUAL );
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_CONTEXT_MAJOR_VERSION ); MAP_REF_API_ATTRIBUTE_TO_SDL( GL_CONTEXT_MAJOR_VERSION );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_CONTEXT_MINOR_VERSION ); MAP_REF_API_ATTRIBUTE_TO_SDL( GL_CONTEXT_MINOR_VERSION );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_CONTEXT_EGL ); MAP_REF_API_ATTRIBUTE_TO_SDL( GL_CONTEXT_EGL );
@@ -1020,7 +935,6 @@ int GL_GetAttribute( int attr, int *val )
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_SHARE_WITH_CURRENT_CONTEXT ); MAP_REF_API_ATTRIBUTE_TO_SDL( GL_SHARE_WITH_CURRENT_CONTEXT );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_FRAMEBUFFER_SRGB_CAPABLE ); MAP_REF_API_ATTRIBUTE_TO_SDL( GL_FRAMEBUFFER_SRGB_CAPABLE );
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_CONTEXT_PROFILE_MASK ); MAP_REF_API_ATTRIBUTE_TO_SDL( GL_CONTEXT_PROFILE_MASK );
#endif
#if SDL_VERSION_ATLEAST( 2, 0, 4 ) #if SDL_VERSION_ATLEAST( 2, 0, 4 )
MAP_REF_API_ATTRIBUTE_TO_SDL( GL_CONTEXT_RELEASE_BEHAVIOR ); MAP_REF_API_ATTRIBUTE_TO_SDL( GL_CONTEXT_RELEASE_BEHAVIOR );
#endif #endif
@@ -1047,16 +961,17 @@ qboolean R_Init_Video( const int type )
{ {
string safe; string safe;
qboolean retval; qboolean retval;
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
SDL_DisplayMode displayMode; SDL_DisplayMode displayMode;
#if SDL_VERSION_ATLEAST( 2, 24, 0 )
SDL_Point point = { window_xpos.value, window_ypos.value }; SDL_Point point = { window_xpos.value, window_ypos.value };
SDL_GetCurrentDisplayMode( SDL_GetPointDisplayIndex( &point ), &displayMode ); int displayIndex = SDL_GetPointDisplayIndex( &point );
refState.desktopBitsPixel = SDL_BITSPERPIXEL( displayMode.format );
#else #else
refState.desktopBitsPixel = 16; int displayIndex = 0;
SDL_GetCurrentDisplayMode( displayIndex, &displayMode );
#endif #endif
refState.desktopBitsPixel = SDL_BITSPERPIXEL( displayMode.format );
#ifdef SDL_HINT_QTWAYLAND_WINDOW_FLAGS #ifdef SDL_HINT_QTWAYLAND_WINDOW_FLAGS
SDL_SetHint( SDL_HINT_QTWAYLAND_WINDOW_FLAGS, "OverridesSystemGestures" ); SDL_SetHint( SDL_HINT_QTWAYLAND_WINDOW_FLAGS, "OverridesSystemGestures" );
#endif #endif
@@ -1064,12 +979,12 @@ qboolean R_Init_Video( const int type )
SDL_SetHint( SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION, "landscape" ); SDL_SetHint( SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION, "landscape" );
#endif #endif
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) && !XASH_WIN32 #if !XASH_WIN32
SDL_SetHint( "SDL_VIDEO_X11_XRANDR", "1" ); SDL_SetHint( "SDL_VIDEO_X11_XRANDR", "1" );
SDL_SetHint( "SDL_VIDEO_X11_XVIDMODE", "1" ); SDL_SetHint( "SDL_VIDEO_X11_XVIDMODE", "1" );
if( Sys_CheckParm( "-egl" ) ) if( Sys_CheckParm( "-egl" ) )
SDL_SetHint( "SDL_VIDEO_X11_FORCE_EGL", "1" ); SDL_SetHint( "SDL_VIDEO_X11_FORCE_EGL", "1" );
#endif #endif // !XASH_WIN32
// must be initialized before creating window // must be initialized before creating window
#if XASH_WIN32 #if XASH_WIN32
@@ -1124,7 +1039,6 @@ qboolean R_Init_Video( const int type )
rserr_t R_ChangeDisplaySettings( int width, int height, window_mode_t window_mode ) rserr_t R_ChangeDisplaySettings( int width, int height, window_mode_t window_mode )
{ {
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
SDL_DisplayMode displayMode; SDL_DisplayMode displayMode;
if( SDL_GetCurrentDisplayMode( 0, &displayMode ) < 0 ) if( SDL_GetCurrentDisplayMode( 0, &displayMode ) < 0 )
@@ -1140,7 +1054,6 @@ rserr_t R_ChangeDisplaySettings( int width, int height, window_mode_t window_mod
width = displayMode.w; width = displayMode.w;
height = displayMode.h; height = displayMode.h;
} }
#endif
refState.fullScreen = window_mode != WINDOW_MODE_WINDOWED; refState.fullScreen = window_mode != WINDOW_MODE_WINDOWED;
Con_Reportf( "%s: Setting video mode to %dx%d %s\n", __func__, width, height, refState.fullScreen ? "fullscreen" : "windowed" ); Con_Reportf( "%s: Setting video mode to %dx%d %s\n", __func__, width, height, refState.fullScreen ? "fullscreen" : "windowed" );
@@ -1159,7 +1072,6 @@ rserr_t R_ChangeDisplaySettings( int width, int height, window_mode_t window_mod
{ {
VID_RestoreScreenResolution(); VID_RestoreScreenResolution();
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
if( SDL_SetWindowFullscreen( host.hWnd, 0 ) < 0 ) if( SDL_SetWindowFullscreen( host.hWnd, 0 ) < 0 )
{ {
Con_Printf( S_ERROR "SDL_SetWindowFullscreen: %s", SDL_GetError( )); Con_Printf( S_ERROR "SDL_SetWindowFullscreen: %s", SDL_GetError( ));
@@ -1170,7 +1082,6 @@ rserr_t R_ChangeDisplaySettings( int width, int height, window_mode_t window_mod
#endif #endif
SDL_SetWindowBordered( host.hWnd, SDL_TRUE ); SDL_SetWindowBordered( host.hWnd, SDL_TRUE );
SDL_SetWindowSize( host.hWnd, width, height ); SDL_SetWindowSize( host.hWnd, width, height );
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
VID_SaveWindowSize( width, height, true ); VID_SaveWindowSize( width, height, true );
} }
@@ -1197,7 +1108,6 @@ qboolean VID_SetMode( void )
if( iScreenWidth < VID_MIN_WIDTH || if( iScreenWidth < VID_MIN_WIDTH ||
iScreenHeight < VID_MIN_HEIGHT ) // trying to get resolution automatically by default iScreenHeight < VID_MIN_HEIGHT ) // trying to get resolution automatically by default
{ {
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
#if !defined( DEFAULT_MODE_WIDTH ) || !defined( DEFAULT_MODE_HEIGHT ) #if !defined( DEFAULT_MODE_WIDTH ) || !defined( DEFAULT_MODE_HEIGHT )
SDL_DisplayMode mode; SDL_DisplayMode mode;
@@ -1209,10 +1119,6 @@ qboolean VID_SetMode( void )
iScreenWidth = DEFAULT_MODE_WIDTH; iScreenWidth = DEFAULT_MODE_WIDTH;
iScreenHeight = DEFAULT_MODE_HEIGHT; iScreenHeight = DEFAULT_MODE_HEIGHT;
#endif #endif
#else // SDL_VERSION_ATLEAST( 2, 0, 0 )
iScreenWidth = 320;
iScreenHeight = 240;
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
} }
#if XASH_MOBILE_PLATFORM #if XASH_MOBILE_PLATFORM
@@ -1259,6 +1165,69 @@ qboolean VID_SetMode( void )
return true; return true;
} }
ref_window_type_t R_GetWindowHandle( void **handle, ref_window_type_t type )
{
SDL_SysWMinfo wmInfo;
if( type == REF_WINDOW_TYPE_SDL )
{
if( handle )
*handle = (void *)host.hWnd;
return REF_WINDOW_TYPE_SDL;
}
SDL_VERSION( &wmInfo.version );
if( SDL_GetWindowWMInfo( host.hWnd, &wmInfo ))
return REF_WINDOW_TYPE_NULL;
switch( wmInfo.info.subsystem )
{
case SDL_SYSWM_WINDOWS:
if( !type || type == REF_WINDOW_TYPE_WIN32 )
{
#ifdef SDL_VIDEO_DRIVER_WINDOWS
if( handle )
*handle = (void *)wmInfo.info.win.window;
return REF_WINDOW_TYPE_WIN32;
#endif // SDL_VIDEO_DRIVER_WINDOWS
}
break;
case SDL_SYSWM_X11:
if( !type || type == REF_WINDOW_TYPE_X11 )
{
#ifdef SDL_VIDEO_DRIVER_X11
if( handle )
*handle = (void *)(uintptr_t)wmInfo.info.x11.window;
return REF_WINDOW_TYPE_X11;
#endif // SDL_VIDEO_DRIVER_X11
}
break;
case SDL_SYSWM_COCOA:
if( !type || type == REF_WINDOW_TYPE_MACOS )
{
#ifdef SDL_VIDEO_DRIVER_COCOA
if( handle )
*handle = (void *)wmInfo.info.cocoa.window;
return REF_WINDOW_TYPE_MACOS;
#endif // SDL_VIDEO_DRIVER_COCOA
}
break;
case SDL_SYSWM_WAYLAND:
if( !type || type == REF_WINDOW_TYPE_WAYLAND )
{
#ifdef SDL_VIDEO_DRIVER_WAYLAND
if( handle )
*handle = (void *)wmInfo.info.wl.surface;
return REF_WINDOW_TYPE_WAYLAND;
#endif // SDL_VIDEO_DRIVER_WAYLAND
}
break;
}
return REF_WINDOW_TYPE_NULL;
}
/* /*
================== ==================
R_Free_Video R_Free_Video
@@ -1274,5 +1243,3 @@ void R_Free_Video( void )
ref.dllFuncs.GL_ClearExtensions(); ref.dllFuncs.GL_ClearExtensions();
} }
#endif // XASH_DEDICATED

View File

@@ -0,0 +1,215 @@
/*
platform_sdl3.h - SDL3 platform definitions
Copyright (C) 2025 Er2off
Copyright (C) 2025 Alibek Omarov
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "platform_sdl3.h"
#include "eiface.h" // ARRAYSIZE
#include "vid_common.h" // window_{width,height}
#include "client.h" // refState
#include "input.h" // Touch_WantVisibleCursor
#include "vgui_draw.h" // VGui_UpdateInternalCursorState
static struct
{
qboolean initialized;
SDL_Cursor *cursors[dc_last];
} cursors;
static struct
{
float x, y;
qboolean pushed;
} in_visible_cursor_pos;
void SDLash_InitCursors( void )
{
if( cursors.initialized )
SDLash_FreeCursors();
// load up all default cursors
cursors.cursors[dc_none] = NULL;
cursors.cursors[dc_arrow] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_DEFAULT );
cursors.cursors[dc_ibeam] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_TEXT );
cursors.cursors[dc_hourglass] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_WAIT );
cursors.cursors[dc_crosshair] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_CROSSHAIR );
cursors.cursors[dc_up] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_DEFAULT );
cursors.cursors[dc_sizenwse] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_NWSE_RESIZE );
cursors.cursors[dc_sizenesw] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_NESW_RESIZE );
cursors.cursors[dc_sizewe] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_EW_RESIZE );
cursors.cursors[dc_sizens] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_NS_RESIZE );
cursors.cursors[dc_sizeall] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_MOVE );
cursors.cursors[dc_no] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_NOT_ALLOWED );
cursors.cursors[dc_hand] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_POINTER );
cursors.initialized = true;
}
void SDLash_FreeCursors( void )
{
if( !cursors.initialized )
return;
for( int i = 0; i < ARRAYSIZE( cursors.cursors ); i++ )
{
if( cursors.cursors[i] )
{
SDL_DestroyCursor( cursors.cursors[i] );
cursors.cursors[i] = NULL;
}
}
cursors.initialized = false;
}
qboolean Platform_GetMouseGrab( void )
{
return SDL_GetWindowMouseGrab( host.hWnd );
}
void Platform_SetMouseGrab( qboolean enable )
{
SDL_SetWindowMouseGrab( host.hWnd, enable );
}
void Platform_MouseMove( float *x, float *y )
{
SDL_GetRelativeMouseState( x, y );
}
void GAME_EXPORT Platform_SetMousePos( int x, int y )
{
SDL_WarpMouseInWindow( host.hWnd, x, y );
}
void GAME_EXPORT Platform_GetMousePos( int *x, int *y )
{
float m_x = 0.0f, m_y = 0.0f;
SDL_GetMouseState( &m_x, &m_y );
if( x )
{
if( window_width.value && window_width.value != refState.width )
{
float factor = refState.width / window_width.value;
*x = m_x * factor;
}
else *x = m_x;
}
if( y )
{
if( window_height.value && window_height.value != refState.height )
{
float factor = refState.height / window_height.value;
*y = m_y * factor;
}
else *y = m_y;
}
}
void Platform_SetCursorType( VGUI_DefaultCursor type )
{
qboolean visible = type != dc_user && type != dc_none;
// never disable cursor in touch emulation mode
if( !visible && Touch_WantVisibleCursor( ))
return;
host.mouse_visible = visible;
VGui_UpdateInternalCursorState( type );
if( visible )
{
if( cursors.initialized )
SDL_SetCursor( cursors.cursors[type] );
SDL_ShowCursor();
// 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
{
// 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_HideCursor();
}
}
void Platform_EnableTextInput( qboolean enable )
{
enable ? SDL_StartTextInput( host.hWnd ) : SDL_StopTextInput( host.hWnd );
}
int Platform_GetClipboardText( char *buffer, size_t size )
{
int len;
char *text = SDL_GetClipboardText();
if( !text )
return 0;
if( buffer && size > 0 )
len = Q_strncpy( buffer, text, size );
else
len = Q_strlen( text );
SDL_free( text );
return len;
}
void Platform_SetClipboardText( const char *buffer )
{
SDL_SetClipboardText( buffer );
}
key_modifier_t Platform_GetKeyModifiers( void )
{
SDL_Keymod mod_flags = SDL_GetModState();
key_modifier_t result_flags = KeyModifier_None;
if( FBitSet( mod_flags, SDL_KMOD_LCTRL ))
SetBits( result_flags, KeyModifier_LeftCtrl );
if( FBitSet( mod_flags, SDL_KMOD_RCTRL ))
SetBits( result_flags, KeyModifier_RightCtrl );
if( FBitSet( mod_flags, SDL_KMOD_RSHIFT ))
SetBits( result_flags, KeyModifier_RightShift );
if( FBitSet( mod_flags, SDL_KMOD_LSHIFT ))
SetBits( result_flags, KeyModifier_LeftShift );
if( FBitSet( mod_flags, SDL_KMOD_LALT ))
SetBits( result_flags, KeyModifier_LeftAlt );
if( FBitSet( mod_flags, SDL_KMOD_RALT ))
SetBits( result_flags, KeyModifier_RightAlt );
if( FBitSet( mod_flags, SDL_KMOD_NUM ))
SetBits( result_flags, KeyModifier_NumLock );
if( FBitSet( mod_flags, SDL_KMOD_CAPS ))
SetBits( result_flags, KeyModifier_CapsLock );
if( FBitSet( mod_flags, SDL_KMOD_RGUI ))
SetBits( result_flags, KeyModifier_RightSuper );
if( FBitSet( mod_flags, SDL_KMOD_LGUI ))
SetBits( result_flags, KeyModifier_LeftSuper );
return result_flags;
}

View File

@@ -0,0 +1,28 @@
/*
platform_sdl3.h - SDL3 platform definitions
Copyright (C) 2025 Er2off
Copyright (C) 2025 Alibek Omarov
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#ifndef PLATFORM_SDL3_H
#define PLATFORM_SDL3_H
#include <SDL3/SDL.h>
#include "platform/platform.h"
//
// in_sdl3.c
//
void SDLash_InitCursors( void );
void SDLash_FreeCursors( void );
#endif // PLATFORM_SDL3_H

View File

@@ -0,0 +1,121 @@
/*
platform_sdl3.h - SDL3 platform definitions
Copyright (C) 2025 Er2off
Copyright (C) 2025 Alibek Omarov
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "platform_sdl3.h"
#include "common.h"
#if XASH_TIMER == TIMER_SDL
double Platform_DoubleTime( void )
{
static Uint64 g_PerformanceFrequency;
static Uint64 g_ClockStart;
Uint64 CurrentTime;
if( !g_PerformanceFrequency )
{
g_PerformanceFrequency = SDL_GetPerformanceFrequency();
g_ClockStart = SDL_GetPerformanceCounter();
return 0.0;
}
CurrentTime = SDL_GetPerformanceCounter();
return (double)( CurrentTime - g_ClockStart ) / (double)( g_PerformanceFrequency );
}
void Platform_Sleep( int msec )
{
SDL_Delay( msec );
}
#endif // XASH_TIMER == TIMER_SDL
#if XASH_MESSAGEBOX == MSGBOX_SDL
void Platform_MessageBox( const char *title, const char *message, qboolean parentMainWindow )
{
SDL_ShowSimpleMessageBox( SDL_MESSAGEBOX_ERROR, title, message, parentMainWindow ? host.hWnd : NULL );
}
#endif
void SDLash_NanoSleep( int nsec )
{
SDL_DelayNS( nsec );
}
static const char *SDLash_CategoryToString( int category )
{
switch( category )
{
case SDL_LOG_CATEGORY_APPLICATION: return "App";
case SDL_LOG_CATEGORY_ERROR: return "Error";
case SDL_LOG_CATEGORY_ASSERT: return "Assert";
case SDL_LOG_CATEGORY_SYSTEM: return "System";
case SDL_LOG_CATEGORY_AUDIO: return "Audio";
case SDL_LOG_CATEGORY_VIDEO: return "Video";
case SDL_LOG_CATEGORY_RENDER: return "Render";
case SDL_LOG_CATEGORY_INPUT: return "Input";
case SDL_LOG_CATEGORY_TEST: return "Test";
case SDL_LOG_CATEGORY_GPU: return "GPU";
default: return "Unknown";
}
}
static void SDLCALL SDLash_LogOutputFunction( void *userdata, int category, SDL_LogPriority priority, const char *message )
{
switch( priority )
{
case SDL_LOG_PRIORITY_CRITICAL:
case SDL_LOG_PRIORITY_ERROR:
Con_Printf( S_ERROR S_BLUE "SDL" S_DEFAULT ": [%s] %s\n", SDLash_CategoryToString( category ), message );
break;
case SDL_LOG_PRIORITY_WARN:
Con_DPrintf( S_WARN S_BLUE "SDL" S_DEFAULT ": [%s] %s\n", SDLash_CategoryToString( category ), message );
break;
case SDL_LOG_PRIORITY_INFO:
Con_Reportf( S_NOTE S_BLUE "SDL" S_DEFAULT ": [%s] %s\n", SDLash_CategoryToString( category ), message );
break;
default:
Con_Reportf( S_BLUE "SDL" S_DEFAULT ": [%s] %s\n", SDLash_CategoryToString( category ), message );
break;
}
}
void SDLash_Init( const char *basedir )
{
SDL_SetLogOutputFunction( SDLash_LogOutputFunction, NULL );
if( host_developer.value >= 2 )
SDL_SetLogPriorities( SDL_LOG_PRIORITY_VERBOSE );
else if( host_developer.value >= 1 )
SDL_SetLogPriorities( SDL_LOG_PRIORITY_WARN );
else
SDL_SetLogPriorities( SDL_LOG_PRIORITY_ERROR );
if( !SDL_Init( SDL_INIT_VIDEO | SDL_INIT_EVENTS ))
{
Sys_Warn( "SDL_Init failed: %s", SDL_GetError( ));
host.type = HOST_DEDICATED;
}
SDL_SetHint( SDL_HINT_MOUSE_TOUCH_EVENTS, "0" );
SDL_SetHint( SDL_HINT_TOUCH_MOUSE_EVENTS, "0" );
SDLash_InitCursors();
}
void SDLash_Shutdown( void )
{
SDLash_FreeCursors();
SDL_Quit();
}

View File

@@ -34,23 +34,20 @@ typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR;
static int Sys_ModuleName( HANDLE process, char *name, void *address, int len ) static int Sys_ModuleName( HANDLE process, char *name, void *address, int len )
{ {
DWORD_PTR baseAddress = 0;
static HMODULE *moduleArray; static HMODULE *moduleArray;
static unsigned int moduleCount; static unsigned int moduleCount;
LPBYTE moduleArrayBytes;
DWORD bytesRequired; DWORD bytesRequired;
int i;
if( len < 3 ) if( len < 3 )
return 0; return 0;
if( !moduleArray && EnumProcessModules( process, NULL, 0, &bytesRequired ) ) if( !moduleArray && EnumProcessModules( process, NULL, 0, &bytesRequired ))
{ {
if ( bytesRequired ) if( bytesRequired )
{ {
moduleArrayBytes = (LPBYTE)LocalAlloc( LPTR, bytesRequired ); LPBYTE moduleArrayBytes = (LPBYTE)LocalAlloc( LPTR, bytesRequired );
if( moduleArrayBytes && EnumProcessModules( process, (HMODULE *)moduleArrayBytes, bytesRequired, &bytesRequired ) ) if( moduleArrayBytes && EnumProcessModules( process, (HMODULE *)moduleArrayBytes, bytesRequired, &bytesRequired ))
{ {
moduleCount = bytesRequired / sizeof( HMODULE ); moduleCount = bytesRequired / sizeof( HMODULE );
moduleArray = (HMODULE *)moduleArrayBytes; moduleArray = (HMODULE *)moduleArrayBytes;
@@ -58,144 +55,154 @@ static int Sys_ModuleName( HANDLE process, char *name, void *address, int len )
} }
} }
for( i = 0; i < moduleCount; i++ ) for( int i = 0; i < moduleCount; i++ )
{ {
MODULEINFO info; MODULEINFO info;
GetModuleInformation( process, moduleArray[i], &info, sizeof(MODULEINFO) ); GetModuleInformation( process, moduleArray[i], &info, sizeof( MODULEINFO ));
if( ( address > info.lpBaseOfDll ) && if( address > info.lpBaseOfDll && (DWORD64)address < (DWORD64)info.lpBaseOfDll + (DWORD64)info.SizeOfImage )
( (DWORD64)address < (DWORD64)info.lpBaseOfDll + (DWORD64)info.SizeOfImage ) )
return GetModuleBaseName( process, moduleArray[i], name, len ); return GetModuleBaseName( process, moduleArray[i], name, len );
} }
return Q_snprintf( name, len, "???" ); return Q_snprintf( name, len, "???" );
} }
static void Sys_StackTrace( PEXCEPTION_POINTERS pInfo ) static void Sys_StackTrace( PEXCEPTION_POINTERS pInfo )
{ {
char message[8192]; // match *nix Sys_Crash char message[8192]; // match *nix Sys_Crash
int len = 0; HANDLE process = GetCurrentProcess();
size_t i; HANDLE thread = GetCurrentThread();
HANDLE process = GetCurrentProcess(); DWORD dline = 0;
HANDLE thread = GetCurrentThread(); DWORD options = SymGetOptions();
IMAGEHLP_LINE64 line; CONTEXT context = *pInfo->ContextRecord;
DWORD dline = 0; IMAGEHLP_LINE64 line = { .SizeOfStruct = sizeof( IMAGEHLP_LINE64 ), };
DWORD options;
CONTEXT context;
STACKFRAME64 stackframe;
DWORD image;
context = *pInfo->ContextRecord; SetBits( options, SYMOPT_DEBUG | SYMOPT_LOAD_LINES );
options = SymGetOptions();
options |= SYMOPT_DEBUG;
options |= SYMOPT_LOAD_LINES;
SymSetOptions( options ); SymSetOptions( options );
SymInitialize( process, NULL, TRUE ); SymInitialize( process, NULL, TRUE );
ZeroMemory( &stackframe, sizeof( STACKFRAME64 ));
#ifdef _M_IX86 #ifdef _M_IX86
image = IMAGE_FILE_MACHINE_I386; DWORD image = IMAGE_FILE_MACHINE_I386;
stackframe.AddrPC.Offset = context.Eip; STACKFRAME64 stackframe =
stackframe.AddrPC.Mode = AddrModeFlat; {
stackframe.AddrFrame.Offset = context.Ebp; .AddrPC.Offset = context.Eip,
stackframe.AddrFrame.Mode = AddrModeFlat; .AddrPC.Mode = AddrModeFlat,
stackframe.AddrStack.Offset = context.Esp; .AddrFrame.Offset = context.Ebp,
stackframe.AddrStack.Mode = AddrModeFlat; .AddrFrame.Mode = AddrModeFlat,
.AddrStack.Offset = context.Esp,
.AddrStack.Mode = AddrModeFlat,
};
#elif _M_X64 #elif _M_X64
image = IMAGE_FILE_MACHINE_AMD64; DWORD image = IMAGE_FILE_MACHINE_AMD64;
stackframe.AddrPC.Offset = context.Rip; STACKFRAME64 stackframe =
stackframe.AddrPC.Mode = AddrModeFlat; {
stackframe.AddrFrame.Offset = context.Rsp; .AddrPC.Offset = context.Rip,
stackframe.AddrFrame.Mode = AddrModeFlat; .AddrPC.Mode = AddrModeFlat,
stackframe.AddrStack.Offset = context.Rsp; .AddrFrame.Offset = context.Rsp,
stackframe.AddrStack.Mode = AddrModeFlat; .AddrFrame.Mode = AddrModeFlat,
.AddrStack.Offset = context.Rsp,
.AddrStack.Mode = AddrModeFlat,
};
#elif _M_IA64 #elif _M_IA64
image = IMAGE_FILE_MACHINE_IA64; DWORD image = IMAGE_FILE_MACHINE_IA64;
stackframe.AddrPC.Offset = context.StIIP; STACKFRAME64 stackframe =
stackframe.AddrPC.Mode = AddrModeFlat; {
stackframe.AddrFrame.Offset = context.IntSp; .AddrPC.Offset = context.StIIP,
stackframe.AddrFrame.Mode = AddrModeFlat; .AddrPC.Mode = AddrModeFlat,
stackframe.AddrBStore.Offset = context.RsBSP; .AddrFrame.Offset = context.IntSp,
stackframe.AddrBStore.Mode = AddrModeFlat; .AddrFrame.Mode = AddrModeFlat,
stackframe.AddrStack.Offset = context.IntSp; .AddrBStore.Offset = context.RsBSP,
stackframe.AddrStack.Mode = AddrModeFlat; .AddrBStore.Mode = AddrModeFlat,
.AddrStack.Offset = context.IntSp,
.AddrStack.Mode = AddrModeFlat,
};
#elif _M_ARM #elif _M_ARM
image = IMAGE_FILE_MACHINE_ARMNT; DWORD image = IMAGE_FILE_MACHINE_ARMNT;
stackframe.AddrPC.Offset = context.Pc; STACKFRAME64 stackframe =
stackframe.AddrPC.Mode = AddrModeFlat; {
stackframe.AddrFrame.Offset = context.R11; .AddrPC.Offset = context.Pc,
stackframe.AddrFrame.Mode = AddrModeFlat; .AddrPC.Mode = AddrModeFlat,
stackframe.AddrStack.Offset = context.Sp; .AddrFrame.Offset = context.R11,
stackframe.AddrStack.Mode = AddrModeFlat; .AddrFrame.Mode = AddrModeFlat,
.AddrStack.Offset = context.Sp,
.AddrStack.Mode = AddrModeFlat,
};
#elif _M_ARM64 #elif _M_ARM64
image = IMAGE_FILE_MACHINE_ARM64; DWORD image = IMAGE_FILE_MACHINE_ARM64;
stackframe.AddrPC.Offset = context.Pc; STACKFRAME64 stackframe =
stackframe.AddrPC.Mode = AddrModeFlat; {
stackframe.AddrFrame.Offset = context.Fp; .AddrPC.Offset = context.Pc,
stackframe.AddrFrame.Mode = AddrModeFlat; .AddrPC.Mode = AddrModeFlat,
stackframe.AddrStack.Offset = context.Sp; .AddrFrame.Offset = context.Fp,
stackframe.AddrStack.Mode = AddrModeFlat; .AddrFrame.Mode = AddrModeFlat,
.AddrStack.Offset = context.Sp,
.AddrStack.Mode = AddrModeFlat,
};
#elif #elif
#error #error
#endif #endif
len = Q_snprintf( message, sizeof( message ), "Ver: " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s, %s-%s)\n", int 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());
len += Q_snprintf( message + len, 1024 - len, "Sys_Crash: address %p, code %p\n", len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: address %p, code %p\n",
pInfo->ExceptionRecord->ExceptionAddress, (void*)pInfo->ExceptionRecord->ExceptionCode ); pInfo->ExceptionRecord->ExceptionAddress, (void*)pInfo->ExceptionRecord->ExceptionCode );
if( SymGetLineFromAddr64( process, (DWORD64)pInfo->ExceptionRecord->ExceptionAddress, &dline, &line ) )
if( SymGetLineFromAddr64( process, (DWORD64)pInfo->ExceptionRecord->ExceptionAddress, &dline, &line ))
{ {
len += Q_snprintf(message + len, 1024 - len, "Exception: %s:%d:%d\n", len += Q_snprintf( message + len, sizeof( message ) - len, "Exception: %s:%d:%d\n",
(char*)line.FileName, (int)line.LineNumber, (int)dline); COM_FileWithoutPath((char*)line.FileName ), (int)line.LineNumber, (int)dline );
} }
if( SymGetLineFromAddr64( process, stackframe.AddrPC.Offset, &dline, &line ) )
if( SymGetLineFromAddr64( process, stackframe.AddrPC.Offset, &dline, &line ))
{ {
len += Q_snprintf(message + len, 1024 - len,"PC: %s:%d:%d\n", len += Q_snprintf( message + len, sizeof( message ) - len, "PC: %s:%d:%d\n",
(char*)line.FileName, (int)line.LineNumber, (int)dline); COM_FileWithoutPath((char*)line.FileName ), (int)line.LineNumber, (int)dline );
} }
if( SymGetLineFromAddr64( process, stackframe.AddrFrame.Offset, &dline, &line ) )
if( SymGetLineFromAddr64( process, stackframe.AddrFrame.Offset, &dline, &line ))
{ {
len += Q_snprintf(message + len, 1024 - len,"Frame: %s:%d:%d\n", len += Q_snprintf( message + len, sizeof( message ) - len, "Frame: %s:%d:%d\n",
(char*)line.FileName, (int)line.LineNumber, (int)dline); COM_FileWithoutPath((char*)line.FileName ), (int)line.LineNumber, (int)dline );
} }
for( i = 0; i < 25; i++ )
for( size_t i = 0; i < 25; i++ )
{ {
char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; char buffer[sizeof( SYMBOL_INFO ) + MAX_SYM_NAME * sizeof( TCHAR )];
PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer; PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
BOOL result = StackWalk64( BOOL result = StackWalk64( image, process, thread,
image, process, thread,
&stackframe, &context, NULL, &stackframe, &context, NULL,
SymFunctionTableAccess64, SymGetModuleBase64, NULL); SymFunctionTableAccess64, SymGetModuleBase64, NULL );
DWORD64 displacement = 0; DWORD64 displacement = 0;
if( !result ) if( !result )
break; break;
symbol->SizeOfStruct = sizeof(SYMBOL_INFO); symbol->SizeOfStruct = sizeof( SYMBOL_INFO );
symbol->MaxNameLen = MAX_SYM_NAME; symbol->MaxNameLen = MAX_SYM_NAME;
len += Q_snprintf( message + len, 1024 - len, "% 2d %p", len += Q_snprintf( message + len, sizeof( message ) - len, "%2d: %p",
i, (void*)stackframe.AddrPC.Offset ); i, (void*)stackframe.AddrPC.Offset );
if( SymFromAddr( process, stackframe.AddrPC.Offset, &displacement, symbol ) ) if( SymFromAddr( process, stackframe.AddrPC.Offset, &displacement, symbol ))
{ {
len += Q_snprintf( message + len, 1024 - len, " %s ", symbol->Name ); len += Q_snprintf( message + len, sizeof( message ) - len, " %s ", symbol->Name );
} }
if( SymGetLineFromAddr64( process, stackframe.AddrPC.Offset, &dline, &line ) )
if( SymGetLineFromAddr64( process, stackframe.AddrPC.Offset, &dline, &line ))
{ {
len += Q_snprintf(message + len, 1024 - len,"(%s:%d:%d) ", len += Q_snprintf( message + len, sizeof( message ) - len,"(%s:%d:%d) ",
(char*)line.FileName, (int)line.LineNumber, (int)dline); COM_FileWithoutPath((char*)line.FileName ), (int)line.LineNumber, (int)dline );
} }
len += Q_snprintf( message + len, 1024 - len, "(");
len += Sys_ModuleName( process, message + len, (void*)stackframe.AddrPC.Offset, 1024 - len ); len += Q_snprintf( message + len, sizeof( message ) - len, "(" );
len += Q_snprintf( message + len, 1024 - len, ")\n"); len += Sys_ModuleName( process, message + len, (void*)stackframe.AddrPC.Offset, sizeof( message ) - len );
len += Q_snprintf( message + len, sizeof( message ) - len, ")\n" );
} }
#if XASH_SDL == 2 #if XASH_SDL == 2
if( host.type != HOST_DEDICATED ) // let system to restart server automaticly if( host.type != HOST_DEDICATED ) // let system to restart server automaticly
SDL_ShowSimpleMessageBox( SDL_MESSAGEBOX_ERROR, "Sys_Crash", message, host.hWnd ); SDL_ShowSimpleMessageBox( SDL_MESSAGEBOX_ERROR, "Sys_Crash", message, NULL );
#endif #endif
Sys_PrintLog( message ); Sys_PrintLog( message );
@@ -227,34 +234,34 @@ static void Sys_GetMinidumpFileName( const char *processName, char *mdmpFileName
currentLocalTime->tm_sec ); currentLocalTime->tm_sec );
} }
static qboolean Sys_WriteMinidump(PEXCEPTION_POINTERS exceptionInfo, MINIDUMP_TYPE minidumpType) static qboolean Sys_WriteMinidump( PEXCEPTION_POINTERS exceptionInfo, MINIDUMP_TYPE minidumpType )
{ {
HRESULT errorCode;
string processName; string processName;
string mdmpFileName; string mdmpFileName;
MINIDUMP_EXCEPTION_INFORMATION minidumpInfo;
Sys_GetProcessName( processName, sizeof( processName )); Sys_GetProcessName( processName, sizeof( processName ));
Sys_GetMinidumpFileName( processName, mdmpFileName, sizeof( mdmpFileName )); Sys_GetMinidumpFileName( processName, mdmpFileName, sizeof( mdmpFileName ));
SetLastError( NOERROR ); SetLastError( NOERROR );
HANDLE fileHandle = CreateFile( HANDLE fileHandle = CreateFile( mdmpFileName, GENERIC_WRITE, FILE_SHARE_WRITE,
mdmpFileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
errorCode = HRESULT_FROM_WIN32( GetLastError( )); HRESULT errorCode = HRESULT_FROM_WIN32( GetLastError( ));
if( !SUCCEEDED( errorCode )) { if( !SUCCEEDED( errorCode ))
{
CloseHandle( fileHandle ); CloseHandle( fileHandle );
return false; return false;
} }
minidumpInfo.ThreadId = GetCurrentThreadId(); MINIDUMP_EXCEPTION_INFORMATION minidumpInfo =
minidumpInfo.ExceptionPointers = exceptionInfo; {
minidumpInfo.ClientPointers = FALSE; .ThreadId = GetCurrentThreadId(),
.ExceptionPointers = exceptionInfo,
.ClientPointers = FALSE
};
qboolean status = MiniDumpWriteDump( qboolean status = MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(), fileHandle,
GetCurrentProcess(), GetCurrentProcessId(), fileHandle, minidumpType, &minidumpInfo, NULL, NULL);
minidumpType, &minidumpInfo, NULL, NULL);
CloseHandle( fileHandle ); CloseHandle( fileHandle );
return status; return status;
@@ -270,13 +277,31 @@ static long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo )
if( host.status != HOST_CRASHED ) if( host.status != HOST_CRASHED )
{ {
// check to avoid recursive call // check to avoid recursive call
host.crashed = true; host.status = HOST_CRASHED;
#if !XASH_DEDICATED #if !XASH_DEDICATED
IN_SetMouseGrab( false ); IN_SetMouseGrab( false );
#endif // XASH_SDL #endif // XASH_SDL
#if DBGHELP #if DBGHELP
if( Sys_CheckParm( "-minidumps" ))
{
int minidumpFlags = MiniDumpWithDataSegs |
MiniDumpWithCodeSegs |
MiniDumpWithHandleData |
MiniDumpWithFullMemory |
MiniDumpWithFullMemoryInfo |
MiniDumpWithIndirectlyReferencedMemory |
MiniDumpWithThreadInfo |
MiniDumpWithModuleHeaders;
if( !Sys_WriteMinidump( pInfo, (MINIDUMP_TYPE)minidumpFlags ))
{
// fallback method, create minidump with minimal info in it
Sys_WriteMinidump( pInfo, MiniDumpWithDataSegs );
}
}
Sys_StackTrace( pInfo ); Sys_StackTrace( pInfo );
#else #else
Sys_Warn( "Sys_Crash: call %p at address %p", pInfo->ExceptionRecord->ExceptionAddress, pInfo->ExceptionRecord->ExceptionCode ); Sys_Warn( "Sys_Crash: call %p at address %p", pInfo->ExceptionRecord->ExceptionAddress, pInfo->ExceptionRecord->ExceptionCode );
@@ -284,37 +309,16 @@ static long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo )
if( host.type == HOST_NORMAL ) if( host.type == HOST_NORMAL )
CL_Crashed(); // tell client about crash CL_Crashed(); // tell client about crash
else host.status = HOST_CRASHED;
#if DBGHELP if( host_developer.value <= 0 )
if( Sys_CheckParm( "-minidumps" )) {
{ // no reason to call debugger in release build - just exit
int minidumpFlags = ( Sys_Quit( "crashed" );
MiniDumpWithDataSegs | return EXCEPTION_CONTINUE_EXECUTION;
MiniDumpWithCodeSegs | }
MiniDumpWithHandleData |
MiniDumpWithFullMemory |
MiniDumpWithFullMemoryInfo |
MiniDumpWithIndirectlyReferencedMemory |
MiniDumpWithThreadInfo |
MiniDumpWithModuleHeaders);
if( !Sys_WriteMinidump( pInfo, (MINIDUMP_TYPE)minidumpFlags )) { // all other states keep unchanged to let debugger find bug
// fallback method, create minidump with minimal info in it Sys_DestroyConsole();
Sys_WriteMinidump( pInfo, MiniDumpWithDataSegs );
}
}
#endif
if( host_developer.value <= 0 )
{
// no reason to call debugger in release build - just exit
Sys_Quit( "crashed" );
return EXCEPTION_CONTINUE_EXECUTION;
}
// all other states keep unchanged to let debugger find bug
Sys_DestroyConsole();
} }
if( oldFilter ) if( oldFilter )

View File

@@ -18,6 +18,14 @@ GNU General Public License for more details.
#if XASH_LIB == LIB_WIN32 #if XASH_LIB == LIB_WIN32
#include "lib_win.h" #include "lib_win.h"
static const wchar_t *FS_PathToWideChar( const char *path )
{
static wchar_t pathBuffer[MAX_PATH];
MultiByteToWideChar( CP_UTF8, 0, path, -1, pathBuffer, MAX_PATH );
return pathBuffer;
}
static DWORD GetOffsetByRVA( DWORD rva, PIMAGE_NT_HEADERS nt_header ) static DWORD GetOffsetByRVA( DWORD rva, PIMAGE_NT_HEADERS nt_header )
{ {
int i = 0; int i = 0;
@@ -375,7 +383,7 @@ static void ListMissingModules( dll_user_t *hInst )
HMODULE hMod; HMODULE hMod;
const char *importName = (const char *)CALCULATE_ADDRESS( data, GetOffsetByRVA( importDesc->Name, peHeader ) ); const char *importName = (const char *)CALCULATE_ADDRESS( data, GetOffsetByRVA( importDesc->Name, peHeader ) );
hMod = LoadLibraryEx( importName, NULL, LOAD_LIBRARY_AS_DATAFILE ); hMod = LoadLibraryExW( FS_PathToWideChar( importName ), NULL, LOAD_LIBRARY_AS_DATAFILE );
if ( !hMod ) if ( !hMod )
{ {
Q_snprintf( buf, sizeof( buf ), "%s not found!", importName ); Q_snprintf( buf, sizeof( buf ), "%s not found!", importName );
@@ -470,7 +478,7 @@ void *COM_LoadLibrary( const char *dllname, int build_ordinals_table, qboolean d
else else
#endif #endif
{ {
hInst->hInstance = LoadLibrary( hInst->fullPath ); hInst->hInstance = LoadLibraryW( FS_PathToWideChar( hInst->fullPath ));
} }
if( !hInst->hInstance ) if( !hInst->hInstance )

View File

@@ -45,7 +45,7 @@ void Platform_Sleep( int msec )
void Win32_Init( qboolean con_showalways ) void Win32_Init( qboolean con_showalways )
{ {
HMODULE hModule = LoadLibrary( "kernel32.dll" ); HMODULE hModule = LoadLibraryW( L"kernel32.dll" );
if( hModule ) if( hModule )
{ {
HANDLE ( __stdcall *pfnCreateWaitableTimerExW)( LPSECURITY_ATTRIBUTES lpTimerAttributes, LPCWSTR lpTimerName, DWORD dwFlags, DWORD dwDesiredAccess ); HANDLE ( __stdcall *pfnCreateWaitableTimerExW)( LPSECURITY_ATTRIBUTES lpTimerAttributes, LPCWSTR lpTimerName, DWORD dwFlags, DWORD dwDesiredAccess );
@@ -114,13 +114,13 @@ void Platform_ShellExecute( const char *path, const char *parms )
if( !Q_strcmp( path, GENERIC_UPDATE_PAGE ) || !Q_strcmp( path, PLATFORM_UPDATE_PAGE )) if( !Q_strcmp( path, GENERIC_UPDATE_PAGE ) || !Q_strcmp( path, PLATFORM_UPDATE_PAGE ))
path = DEFAULT_UPDATE_PAGE; path = DEFAULT_UPDATE_PAGE;
ShellExecute( NULL, "open", path, parms, NULL, SW_SHOW ); ShellExecuteA( NULL, "open", path, parms, NULL, SW_SHOW );
} }
#if XASH_MESSAGEBOX == MSGBOX_WIN32 #if XASH_MESSAGEBOX == MSGBOX_WIN32
void Platform_MessageBox( const char *title, const char *message, qboolean parentMainWindow ) void Platform_MessageBox( const char *title, const char *message, qboolean parentMainWindow )
{ {
MessageBox( parentMainWindow ? host.hWnd : NULL, message, title, MB_OK|MB_SETFOREGROUND|MB_ICONSTOP ); MessageBoxA( parentMainWindow ? host.hWnd : NULL, message, title, MB_OK|MB_SETFOREGROUND|MB_ICONSTOP );
} }
#endif // XASH_MESSAGEBOX == MSGBOX_WIN32 #endif // XASH_MESSAGEBOX == MSGBOX_WIN32

View File

@@ -57,7 +57,8 @@ GNU General Public License for more details.
// CL_RunLightStyles now accepts lightstyles array. // CL_RunLightStyles now accepts lightstyles array.
// Removed R_DrawTileClear and Mod_LoadMapSprite, as they're implemented on engine side // Removed R_DrawTileClear and Mod_LoadMapSprite, as they're implemented on engine side
// Removed FillRGBABlend. Now FillRGBA accepts rendermode parameter. // Removed FillRGBABlend. Now FillRGBA accepts rendermode parameter.
#define REF_API_VERSION 9 // 10. Added R_GetWindowHandle to retrieve platform-specific window object.
#define REF_API_VERSION 10
#define TF_SKY (TF_SKYSIDE|TF_NOMIPMAP|TF_ALLOW_NEAREST) #define TF_SKY (TF_SKYSIDE|TF_NOMIPMAP|TF_ALLOW_NEAREST)
#define TF_FONT (TF_NOMIPMAP|TF_CLAMP|TF_ALLOW_NEAREST) #define TF_FONT (TF_NOMIPMAP|TF_CLAMP|TF_ALLOW_NEAREST)
@@ -103,6 +104,16 @@ typedef enum
DEMO_QUAKE1 DEMO_QUAKE1
} demo_mode; } demo_mode;
typedef enum ref_window_type_e
{
REF_WINDOW_TYPE_NULL = 0,
REF_WINDOW_TYPE_WIN32, // HWND
REF_WINDOW_TYPE_X11, // Display*
REF_WINDOW_TYPE_WAYLAND, // wl_display*
REF_WINDOW_TYPE_MACOS, // NSWindow*
REF_WINDOW_TYPE_SDL, // SDL_Window*
} ref_window_type_t;
typedef struct typedef struct
{ {
msurface_t *surf; msurface_t *surf;
@@ -467,6 +478,9 @@ typedef struct ref_api_s
// filesystem exports // filesystem exports
fs_api_t *fsapi; fs_api_t *fsapi;
// for abstracting the engine's rendering
ref_window_type_t (*R_GetWindowHandle)( void **handle, ref_window_type_t type );
} ref_api_t; } ref_api_t;
struct mip_s; struct mip_s;

View File

@@ -94,6 +94,7 @@ typedef enum
cs_free = 0, // can be reused for a new connection cs_free = 0, // can be reused for a new connection
cs_zombie, // client has been disconnected, but don't reuse connection for a couple seconds cs_zombie, // client has been disconnected, but don't reuse connection for a couple seconds
cs_connected, // has been assigned to a sv_client_t, but not in game yet cs_connected, // has been assigned to a sv_client_t, but not in game yet
cs_spawning, // put in game, but not spawned yet
cs_spawned // client is fully in game cs_spawned // client is fully in game
} cl_state_t; } cl_state_t;
@@ -491,7 +492,7 @@ get model by handle
*/ */
static inline model_t *GAME_EXPORT SV_ModelHandle( int modelindex ) static inline model_t *GAME_EXPORT SV_ModelHandle( int modelindex )
{ {
if( modelindex < 0 || modelindex >= MAX_MODELS ) if( unlikely( modelindex < 0 || modelindex >= MAX_MODELS ))
return NULL; return NULL;
return sv.models[modelindex]; return sv.models[modelindex];
} }
@@ -540,7 +541,7 @@ void SV_ExecuteClientMessage( sv_client_t *cl, sizebuf_t *msg );
void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg ); void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg );
edict_t *SV_FakeConnect( const char *netname ); edict_t *SV_FakeConnect( const char *netname );
void SV_BuildReconnect( sizebuf_t *msg ); void SV_BuildReconnect( sizebuf_t *msg );
int SV_CalcPing( sv_client_t *cl ); int SV_CalcPing( const sv_client_t *cl );
void SV_UpdateServerInfo( void ); void SV_UpdateServerInfo( void );
void SV_EndRedirect( host_redirect_t *rd ); void SV_EndRedirect( host_redirect_t *rd );
void SV_RejectConnection( netadr_t from, const char *fmt, ... ) FORMAT_CHECK( 2 ); void SV_RejectConnection( netadr_t from, const char *fmt, ... ) FORMAT_CHECK( 2 );

View File

@@ -307,6 +307,7 @@ static void SV_ConnectClient( netadr_t from )
{ {
char userinfo[MAX_INFO_STRING]; char userinfo[MAX_INFO_STRING];
char protinfo[MAX_INFO_STRING]; char protinfo[MAX_INFO_STRING];
char physinfo[MAX_INFO_STRING];
client_frame_t *frames; client_frame_t *frames;
sv_client_t *newcl = NULL; sv_client_t *newcl = NULL;
int qport, version; int qport, version;
@@ -415,13 +416,16 @@ static void SV_ConnectClient( netadr_t from )
frames = Mem_Realloc( host.mempool, newcl->frames, sizeof( client_frame_t ) * SV_UPDATE_BACKUP ); frames = Mem_Realloc( host.mempool, newcl->frames, sizeof( client_frame_t ) * SV_UPDATE_BACKUP );
memset( frames, 0, sizeof( client_frame_t ) * SV_UPDATE_BACKUP ); memset( frames, 0, sizeof( client_frame_t ) * SV_UPDATE_BACKUP );
SV_ClearResourceLists( newcl ); SV_ClearResourceLists( newcl );
memcpy( physinfo, newcl->physinfo, sizeof( physinfo ));
memset( newcl, 0, sizeof( *newcl )); memset( newcl, 0, sizeof( *newcl ));
// a1ba: preserve physinfo as it's set by game logic, before client connect!
memcpy( newcl->physinfo, physinfo, sizeof( newcl->physinfo ));
newcl->edict = EDICT_NUM(( newcl - svs.clients ) + 1 ); newcl->edict = EDICT_NUM(( newcl - svs.clients ) + 1 );
newcl->frames = frames; newcl->frames = frames;
newcl->userid = g_userid++; // create unique userid newcl->userid = g_userid++; // create unique userid
newcl->state = cs_connected; newcl->state = cs_connected; // now expect "spawn" command
newcl->extensions = FBitSet( extensions, NET_EXT_SPLITSIZE ); newcl->extensions = FBitSet( extensions, NET_EXT_SPLITSIZE );
Q_strncpy( newcl->useragent, protinfo, sizeof( newcl->useragent )); Q_strncpy( newcl->useragent, protinfo, sizeof( newcl->useragent ));
@@ -1087,7 +1091,7 @@ SV_CalcPing
recalc ping on current client recalc ping on current client
=================== ===================
*/ */
int SV_CalcPing( sv_client_t *cl ) int SV_CalcPing( const sv_client_t *cl )
{ {
float ping = 0; float ping = 0;
int i, count; int i, count;
@@ -1882,20 +1886,6 @@ static void SV_UserinfoChanged( sv_client_t *cl )
ent->v.netname = MAKE_STRING( cl->name ); ent->v.netname = MAKE_STRING( cl->name );
} }
/*
==================
SV_UpdateUserinfo_f
==================
*/
static qboolean SV_UpdateUserinfo_f( sv_client_t *cl )
{
Q_strncpy( cl->userinfo, Cmd_Argv( 1 ), sizeof( cl->userinfo ));
if( cl->state >= cs_connected )
SetBits( cl->flags, FCL_RESEND_USERINFO ); // needs for update client info
return true;
}
/* /*
================== ==================
SV_SetInfo_f SV_SetInfo_f
@@ -2149,6 +2139,8 @@ static qboolean SV_Spawn_f( sv_client_t *cl )
SV_PutClientInServer( cl ); SV_PutClientInServer( cl );
cl->state = cs_spawning;
// if we are paused, tell the clients // if we are paused, tell the clients
if( sv.paused ) if( sv.paused )
{ {
@@ -2166,7 +2158,8 @@ SV_Begin_f
*/ */
static qboolean SV_Begin_f( sv_client_t *cl ) static qboolean SV_Begin_f( sv_client_t *cl )
{ {
if( cl->state != cs_connected ) // make sure client has passed connection process correctly
if( cl->state != cs_spawning )
return false; return false;
// now client is spawned // now client is spawned
@@ -2183,11 +2176,94 @@ SV_SendBuildInfo_f
*/ */
static qboolean SV_SendBuildInfo_f( sv_client_t *cl ) static qboolean SV_SendBuildInfo_f( sv_client_t *cl )
{ {
if( cl->state != cs_spawned )
return false;
SV_ClientPrintf( cl, "Server running " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s, %s-%s)\n", SV_ClientPrintf( cl, "Server running " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s, %s-%s)\n",
Q_buildnum(), g_buildcommit, Q_buildos(), Q_buildarch() ); Q_buildnum(), g_buildcommit, Q_buildos(), Q_buildarch() );
return true; return true;
} }
/*
==================
SV_ClientStatus_f
==================
*/
static qboolean SV_ClientStatus_f( sv_client_t *cl )
{
netadr_t ip4, ip6;
vec3_t origin = { 0 };
int clients, bots, i;
if( cl->state != cs_spawned )
return false;
NET_GetLocalAddress( &ip4, &ip6 );
if( cl->edict )
VectorCopy( cl->edict->v.origin, origin );
SV_GetPlayerCount( &clients, &bots );
SV_ClientPrintf( cl,
"hostname: %s\n"
"version: %i/%s %d\n",
hostname.string,
PROTOCOL_VERSION, XASH_VERSION, Q_buildnum( ));
if( ip4.type == NA_IP )
SV_ClientPrintf( cl, "tcp/ip: %s\n", NET_AdrToString( ip4 ));
if( ip6.type == NA_IP6 )
SV_ClientPrintf( cl, "tcp/ipv6: %s\n", NET_AdrToString( ip6 ));
SV_ClientPrintf( cl,
"map:\t%s at %d x, %d y, %d z\n"
"players: %i active (%i max)\n"
"# score ping dev playtime name\n",
sv.name, (int)origin[0], (int)origin[1], (int)origin[2],
clients, svs.maxclients );
for( i = 0; i < svs.maxclients; i++ )
{
const sv_client_t *pcl = &svs.clients[i];
int j = 0;
int input_devices;
const char *s;
char devices[8];
if( pcl->state != cs_spawned )
continue;
if( FBitSet( pcl->flags, FCL_FAKECLIENT ))
s = "Bot ";
else
s = va( "%i", SV_CalcPing( pcl ));
input_devices = Q_atoi( Info_ValueForKey( pcl->useragent, "d" ));
if( FBitSet( input_devices, INPUT_DEVICE_MOUSE ))
devices[j++] = 'm';
if( FBitSet( input_devices, INPUT_DEVICE_TOUCH ))
devices[j++] = 't';
if( FBitSet( input_devices, INPUT_DEVICE_JOYSTICK ))
devices[j++] = 'j';
if( FBitSet( input_devices, INPUT_DEVICE_VR ))
devices[j++] = 'v';
if( j == 0 )
Q_strncpy( devices, "n/a", sizeof( devices ));
else
devices[j++] = 0;
SV_ClientPrintf( cl,
"%2i %5i %4s %4s %g %s\n",
i, (int)pcl->edict->v.frags, s, devices, host.realtime - pcl->netchan.connect_time, pcl->name );
}
return true;
}
/* /*
================== ==================
SV_GetCrossEnt SV_GetCrossEnt
@@ -2969,32 +3045,33 @@ static qboolean SV_EntGetVars_f( sv_client_t *cl )
return true; return true;
} }
// keep it sorted
static const ucmd_t ucmds[] = static const ucmd_t ucmds[] =
{ {
{ "new", SV_New_f },
{ "god", SV_Godmode_f },
{ "kill", SV_Kill_f },
{ "begin", SV_Begin_f },
{ "spawn", SV_Spawn_f },
{ "pause", SV_Pause_f },
{ "noclip", SV_Noclip_f },
{ "setinfo", SV_SetInfo_f },
{ "sendres", SV_SendRes_f },
{ "notarget", SV_Notarget_f },
{ "info", SV_ShowServerinfo_f },
{ "dlfile", SV_DownloadFile_f },
{ "disconnect", SV_Disconnect_f },
{ "userinfo", SV_UpdateUserinfo_f },
{ "_sv_build_info", SV_SendBuildInfo_f }, { "_sv_build_info", SV_SendBuildInfo_f },
{ "begin", SV_Begin_f },
{ "disconnect", SV_Disconnect_f },
{ "dlfile", SV_DownloadFile_f },
{ "god", SV_Godmode_f },
{ "info", SV_ShowServerinfo_f },
{ "kill", SV_Kill_f },
{ "new", SV_New_f },
{ "noclip", SV_Noclip_f },
{ "notarget", SV_Notarget_f },
{ "pause", SV_Pause_f },
{ "sendres", SV_SendRes_f },
{ "setinfo", SV_SetInfo_f },
{ "spawn", SV_Spawn_f },
{ "status", SV_ClientStatus_f },
}; };
static const ucmd_t enttoolscmds[] = static const ucmd_t enttoolscmds[] =
{ {
{ "ent_list", SV_EntList_f },
{ "ent_info", SV_EntInfo_f },
{ "ent_fire", SV_EntFire_f },
{ "ent_create", SV_EntCreate_f }, { "ent_create", SV_EntCreate_f },
{ "ent_fire", SV_EntFire_f },
{ "ent_getvars", SV_EntGetVars_f }, { "ent_getvars", SV_EntGetVars_f },
{ "ent_info", SV_EntInfo_f },
{ "ent_list", SV_EntList_f },
}; };
/* /*
@@ -3010,41 +3087,37 @@ static void SV_ExecuteClientCommand( sv_client_t *cl, const char *s )
for( i = 0; i < ARRAYSIZE( ucmds ); i++ ) for( i = 0; i < ARRAYSIZE( ucmds ); i++ )
{ {
const ucmd_t *u = &ucmds[i]; if( !Q_strcmp( Cmd_Argv( 0 ), ucmds[i].name ))
if( !Q_strcmp( Cmd_Argv( 0 ), u->name ))
{ {
if( !u->func( cl )) if( !ucmds[i].func( cl ))
Con_Printf( "'%s' is not valid from the console\n", u->name ); Con_Printf( "'%s' is not valid from the console\n", ucmds[i].name );
else else
Con_Reportf( "ucmd->%s()\n", u->name ); Con_Reportf( "ucmd->%s()\n", ucmds[i].name );
return; return;
} }
} }
if( sv_enttools_enable.value > 0.0f && !sv.background )
{
for( i = 0; i < ARRAYSIZE( enttoolscmds ); i++ )
{
const ucmd_t *u = &enttoolscmds[i];
if( !Q_strcmp( Cmd_Argv( 0 ), u->name ))
{
Con_Reportf( "enttools->%s(): %s\n", u->name, s );
Log_Printf( "\"%s<%i><%s><>\" performed: %s\n", Info_ValueForKey( cl->userinfo, "name" ),
cl->userid, SV_GetClientIDString( cl ), s );
if( u->func )
u->func( cl );
return;
}
}
}
if( sv.state == ss_active ) if( sv.state == ss_active )
{ {
qboolean fullupdate = !Q_strcmp( Cmd_Argv( 0 ), "fullupdate" ); qboolean fullupdate;
if( cl->state == cs_spawned && sv_enttools_enable.value > 0.0f && !sv.background )
{
for( i = 0; i < ARRAYSIZE( enttoolscmds ); i++ )
{
if( !Q_strcmp( Cmd_Argv( 0 ), enttoolscmds[i].name ))
{
Con_Reportf( "enttools->%s(): %s\n", enttoolscmds[i].name, s );
Log_Printf( "\"%s<%i><%s><>\" performed: %s\n", Info_ValueForKey( cl->userinfo, "name" ),
cl->userid, SV_GetClientIDString( cl ), s );
enttoolscmds[i].func( cl );
return;
}
}
}
fullupdate = !Q_strcmp( Cmd_Argv( 0 ), "fullupdate" );
if( fullupdate ) if( fullupdate )
{ {
@@ -3474,7 +3547,7 @@ static void SV_ParseVoiceData( sv_client_t *cl, sizebuf_t *msg )
MSG_ReadBytes( msg, received, size ); MSG_ReadBytes( msg, received, size );
if( !sv_voiceenable.value || svs.maxclients <= 1 ) if( !sv_voiceenable.value || svs.maxclients <= 1 || cl->state != cs_spawned )
return; return;
for( i = 0, cur = svs.clients; i < svs.maxclients; i++, cur++ ) for( i = 0, cur = svs.clients; i < svs.maxclients; i++, cur++ )

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