Compare commits

...

163 Commits

Author SHA1 Message Date
Alibek Omarov
3fb92e22fd Documentation: extensions: add documentation piece for lightmapped water 2024-08-26 21:28:06 +03:00
Alibek Omarov
7364765d62 ref: gl: implement reading engine's world flag and extra info for lightmapped water
* Rename gl_litwater to gl_litwater_force because it doesn't affect maps that declare
  litwater support
2024-08-26 21:27:13 +03:00
Alibek Omarov
b64329d1ee engine: add _litwater worldspawn key to allow mod developers to declare lightmapped water support 2024-08-26 17:10:06 +03:00
Alibek Omarov
ff1d3c4257 ref: gl: add cvars to scale and set minimum light for lightmapped water 2024-08-25 23:15:39 +03:00
Alibek Omarov
d418fb5f28 ref: gl: don't draw water backfaces when drawing lightmapped water 2024-08-25 22:30:12 +03:00
Alibek Omarov
62d7959843 ref: gl: move EmitWaterPolys to gl_rsurf and make it static. Slight refactoring, don't set SURF_DRAWTURB_QUADS if context isn't OpenGL 2024-08-25 19:19:03 +03:00
Alibek Omarov
980f356fe9 ref: gl: discard surfaces that don't have lightmaps in one place, remove unneeded checks 2024-08-25 18:56:46 +03:00
Alibek Omarov
83194ca0f5 ref: gl: support lightmapped water on transparent brushes 2024-08-22 23:13:34 +03:00
Alibek Omarov
d23968b12e ref: gl: add lightmapped water rendering, including wavy water 2024-08-22 23:13:08 +03:00
Alibek Omarov
5034b860c8 ref: gl: split lightmap chain handling from R_RenderBrushPoly 2024-08-22 23:08:52 +03:00
Alibek Omarov
5a708f90c6 ref: gl: build lightmap texcoords for subdivided SURF_DRAWTURB surface 2024-08-22 23:00:38 +03:00
Alibek Omarov
4118ac2561 ref: gl: add cvar gl_litwater to enable lightmapped water 2024-08-22 21:42:04 +03:00
Alibek Omarov
5777431577 engine: common: insert spaces between arguments in echo command 2024-08-22 16:45:42 +03:00
Alibek Omarov
cd86f80203 engine: common: make MSG_WriteOneBit inlined, as it's usually called with literal argument 2024-08-22 12:51:47 +03:00
Alibek Omarov
8c885d3f37 mainui: update 2024-08-22 12:50:01 +03:00
Alibek Omarov
dddb46a6d0 mainui: update 2024-08-21 18:14:21 +03:00
Alibek Omarov
6b0f378c5b engine: client: ensure requested (but failed) renderer won't be loaded twice 2024-08-21 12:18:06 +03:00
Alibek Omarov
9dd7f37d42 Revert "engine: client: add missing ref_null to R_CollectRendererNames"
This reverts commit 69ec810ed0.
2024-08-21 12:18:06 +03:00
Alibek Omarov
9f10fb6472 engine: client: ensure RefDll cvars have FCVAR_REFDLL flag, clean up them automatically. Don't unload failed renderer, it will be done in R_UnloadProgs 2024-08-21 12:18:06 +03:00
Alibek Omarov
64dbccb9bd engine: platform: sdl: do not call SDL_VideoQuit in R_Free_Video, as one failed renderer will shut down whole SDL video subsystem 2024-08-21 12:18:06 +03:00
Alibek Omarov
9a432a5a13 common: rewrite cvardef.h from scratch based on Quake definitions
* unify cvar.h and cvardef.h, enable private definitions only for refdll and engine

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

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

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

View File

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

View File

@@ -0,0 +1,19 @@
## Lightmapped water
Xash3D FWGS supports lightmapped water, as an extension. It adds three new cvars and new worldspawn key values.
### For level designers:
If you're a level designer and intend to make your level to have lightmapped water, you can put these keyvalues to worldspawn entity description (always first entity in entities list):
| Key | Value | Description |
| ---------------------- | ------- | ----------- |
| `_litwater` | integer | Set to any non-zero value to enable lightmapped water. Overrides `gl_litwater_force` cvar value. |
| `_litwater_minlight` | integer | Minimal lightmap value water surface will receive. Helps to avoid too dark areas when water isn't properly lit. If not set, defaults to zero. |
| `_litwater_scale` | float | Scales up lightmap value for water surfaces. If not set, defaults to 1.0. |
### For players:
Some of the maps already have computed lightmap for water surfaces and sometimes water has been properly lit but the support hasn't been declared by the level designer.
As a player, you can enable it in `Video options` menu or through console with `gl_litwater_force` cvar. There are also `gl_litwater_minlight` and `gl_litwater_scale` cvars that function similar to keys above. The default values has been set to `192` and `1.25` respectively to slightly avoid issues with maps that wasn't intended to have lightmapped water.

View File

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

View File

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

View File

@@ -2,7 +2,7 @@
[![builds.sr.ht status](https://builds.sr.ht/~a1batross/xash3d-fwgs.svg)](https://builds.sr.ht/~a1batross/xash3d-fwgs?) [![GitHub Actions Status](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml/badge.svg)](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml) [![FreeBSD Build Status](https://img.shields.io/cirrus/github/FWGS/xash3d-fwgs?label=freebsd%20build)](https://cirrus-ci.com/github/FWGS/xash3d-fwgs) [![Discord Server](https://img.shields.io/discord/355697768582610945.svg)](http://fwgsdiscord.mentality.rip/) \
[![Download Stable](https://img.shields.io/badge/download-stable-yellow)](https://github.com/FWGS/xash3d-fwgs/releases/latest) [![Download Testing](https://img.shields.io/badge/downloads-testing-orange)](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous)
Xash3D FWGS is a game engine, aimed to provide compatibility with Half-Life Engine and extend it, as well as to give game developers well known workflow.
Xash3D (pronounced `[ksɑʂ]`) FWGS is a game engine, aimed to provide compatibility with Half-Life Engine and extend it, as well as to give game developers well known workflow.
Xash3D FWGS is a heavily modified fork of an original [Xash3D Engine](https://www.moddb.com/engines/xash3d-engine) by Unkle Mike.
@@ -28,7 +28,7 @@ If you like Xash3D FWGS, consider supporting individual engine maintainers. By s
1) Copy engine binaries to some directory.
2) Copy `valve` directory from [Half-Life](https://store.steampowered.com/app/70/HalfLife/) to directory with engine binaries.
If your CPU is NOT x86 compatible or you're running 64-bit version of the engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-portable).
This repository contains our fork of HLSDK and restored source code for some of the mods. Not all of them, of course.
This repository contains our fork of HLSDK and restored source code for Half-Life expansions and some mods.
You still needed to copy `valve` directory as all game resources located there.
3) Run the main executable (`xash3d.exe` or AppImage).
@@ -46,11 +46,11 @@ NOTE: NEVER USE GitHub's ZIP ARCHIVES. GitHub doesn't include external dependenc
### Prerequisites
If your CPU is x86 compatible, we are building 32-bit code by default. This was done to maintain compatibility with Steam releases of Half-Life and based on it's engine games.
If your CPU is x86 compatible and you're on Windows or Linux, we are building 32-bit code by default. This was done to maintain compatibility with Steam releases of Half-Life and based on it's engine games.
Even if Xash3D FWGS does support targetting 64-bit, you can't load games without recompiling them from source code!
If your CPU is NOT x86 compatible or you decided build 64-bit version of engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-portable).
This repository contains our fork of HLSDK and restored source code for some of the mods. Not all of them, of course.
This repository contains our fork of HLSDK and restored source code for Half-Life expansions and some mods.
#### Windows (Visual Studio)
* Install Visual Studio.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -130,6 +130,15 @@ typedef uint64_t longtime_t;
#define STATIC_ASSERT( x, y ) STATIC_ASSERT_2( __LINE__, x, y )
#endif
// at least, statically check size of some public structures
#if XASH_64BIT
#define STATIC_CHECK_SIZEOF( type, size32, size64 ) \
STATIC_ASSERT( sizeof( type ) == size64, #type " unexpected size" )
#else
#define STATIC_CHECK_SIZEOF( type, size32, size64 ) \
STATIC_ASSERT( sizeof( type ) == size32, #type " unexpected size" )
#endif
#if !defined( __cplusplus ) && __STDC_VERSION__ >= 199101L // not C++ and C99 or newer
#define XASH_RESTRICT restrict
#elif _MSC_VER || __GNUC__ || __clang__ // compiler-specific extensions

View File

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

View File

@@ -79,7 +79,7 @@ typedef struct
typedef struct
{
demoentry_t *entries; // track entry info
int numentries; // number of tracks
int32_t numentries; // number of tracks
} demodirectory_t;
// add angles
@@ -327,10 +327,6 @@ void CL_WriteDemoMessage( qboolean startup, int start, sizebuf_t *msg )
if( !file ) return;
// past the start but not recording a demo.
if( !startup && !cls.demorecording )
return;
swlen = MSG_GetNumBytesWritten( msg ) - start;
if( swlen <= 0 ) return;
@@ -1150,6 +1146,7 @@ show stats
*/
static void CL_FinishTimeDemo( void )
{
qboolean temp = host.allow_console;
int frames;
double time;
@@ -1160,7 +1157,9 @@ static void CL_FinishTimeDemo( void )
time = host.realtime - cls.td_starttime;
if( !time ) time = 1.0;
host.allow_console = true;
Con_Printf( "timedemo result: %i frames %5.3f seconds %5.3f fps\n", frames, time, frames / time );
host.allow_console = temp;
if( Sys_CheckParm( "-timedemo" ))
CL_Quit_f();
@@ -1449,6 +1448,51 @@ void CL_Record_f( void )
CL_WriteDemoHeader( demopath );
}
static qboolean CL_ParseDemoHeader( const char *callee, const char *filename, file_t *f, demoheader_t *hdr, int32_t *numentries )
{
if( FS_Read( f, hdr, sizeof( *hdr )) != sizeof( *hdr ) || hdr->id != IDEMOHEADER )
{
Con_Printf( S_ERROR "%s: %s is not in supported format or not a demo file\n", callee, filename );
return false;
}
// force null terminate strings
hdr->mapname[sizeof( hdr->mapname ) - 1] = 0;
hdr->comment[sizeof( hdr->comment ) - 1] = 0;
hdr->gamedir[sizeof( hdr->gamedir ) - 1] = 0;
if( hdr->dem_protocol != DEMO_PROTOCOL )
{
Con_Printf( S_ERROR "%s: demo protocol outdated (%i should be %i)\n",
callee, hdr->net_protocol, DEMO_PROTOCOL );
return false;
}
if( hdr->net_protocol != PROTOCOL_VERSION && hdr->net_protocol != PROTOCOL_LEGACY_VERSION )
{
Con_Printf( S_ERROR "%s: net protocol outdated (%i should be %i or %i)\n",
callee, hdr->net_protocol, PROTOCOL_VERSION, PROTOCOL_LEGACY_VERSION );
return false;
}
if( FS_Seek( f, hdr->directory_offset, SEEK_SET ) < 0
|| FS_Read( f, numentries, sizeof( *numentries )) != sizeof( *numentries ))
{
Con_Printf( S_ERROR "%s: can't find directory offset in %s, demo file corrupted\n",
callee, filename );
return false;
}
if(( *numentries < 1 ) || ( *numentries > 1024 ))
{
Con_Printf( S_ERROR "%s: demo have bogus # of directory entries: %i\n",
callee, *numentries );
return false;
}
return true;
}
/*
====================
CL_PlayDemo_f
@@ -1469,9 +1513,7 @@ void CL_PlayDemo_f( void )
}
if( cls.demoplayback )
{
CL_StopPlayback();
}
if( cls.demorecording )
{
@@ -1520,53 +1562,33 @@ void CL_PlayDemo_f( void )
}
if( neg ) cls.forcetrack = -cls.forcetrack;
cls.legacymode = PROTO_QUAKE;
CL_DemoStartPlayback( DEMO_QUAKE1 );
cls.legacymode = PROTO_QUAKE;
return; // quake demo is started
}
// read in the demo header
FS_Read( cls.demofile, &demo.header, sizeof( demoheader_t ));
if( demo.header.id != IDEMOHEADER )
if( !CL_ParseDemoHeader( Cmd_Argv( 0 ), filename, cls.demofile, &demo.header, &demo.directory.numentries ))
{
Con_Printf( S_ERROR "%s is not a demo file\n", demoname );
CL_DemoAborted();
return;
}
if( demo.header.dem_protocol != DEMO_PROTOCOL )
{
Con_Printf( S_ERROR "playdemo: demo protocol outdated (%i should be %i)\n", demo.header.dem_protocol, DEMO_PROTOCOL );
CL_DemoAborted();
return;
}
if( demo.header.net_protocol != PROTOCOL_VERSION &&
demo.header.net_protocol != PROTOCOL_LEGACY_VERSION )
{
Con_Printf( S_ERROR "playdemo: net protocol outdated (%i should be %i)\n", demo.header.net_protocol, PROTOCOL_VERSION );
CL_DemoAborted();
return;
}
// now read in the directory structure.
FS_Seek( cls.demofile, demo.header.directory_offset, SEEK_SET );
FS_Read( cls.demofile, &demo.directory.numentries, sizeof( int ));
if( demo.directory.numentries < 1 || demo.directory.numentries > 1024 )
{
Con_Printf( S_ERROR "demo had bogus # of directory entries: %i\n", demo.directory.numentries );
CL_DemoAborted();
return;
}
// allocate demo entries
demo.directory.entries = Mem_Malloc( cls.mempool, sizeof( demoentry_t ) * demo.directory.numentries );
demo.directory.entries = Mem_Malloc( cls.mempool, sizeof( *demo.directory.entries ) * demo.directory.numentries );
for( i = 0; i < demo.directory.numentries; i++ )
{
FS_Read( cls.demofile, &demo.directory.entries[i], sizeof( demoentry_t ));
demoentry_t *entry = &demo.directory.entries[i];
if( FS_Read( cls.demofile, entry, sizeof( *entry )) != sizeof( *entry ))
{
Con_Printf( S_ERROR "%s: demo entry %i of %s corrupted", Cmd_Argv( 0 ), i, filename );
CL_DemoAborted();
return;
}
entry->description[sizeof( entry->description ) - 1] = 0;
}
demo.entryIndex = 0;
@@ -1680,3 +1702,78 @@ void CL_Stop_f( void )
S_StopBackgroundTrack();
}
}
void CL_ListDemo_f( void )
{
demoheader_t hdr;
int32_t num_entries;
file_t *f;
char filename[MAX_QPATH];
char demoname[MAX_QPATH];
int i;
if( Cmd_Argc() < 2 )
{
Con_Printf( S_USAGE "%s <demoname>\n", Cmd_Argv( 0 ));
return;
}
Q_strncpy( demoname, Cmd_Argv( 1 ), sizeof( demoname ));
COM_StripExtension( demoname );
Q_snprintf( filename, sizeof( filename ), "%s.dem", demoname );
f = FS_Open( filename, "rb", true );
if( !f )
{
Con_Printf( S_ERROR "couldn't open %s\n", filename );
return;
}
if( !CL_ParseDemoHeader( Cmd_Argv( 0 ), filename, f, &hdr, &num_entries ))
{
FS_Close( f );
return;
}
Con_Printf( "Demo contents for %s:\n"
"\tProtocol: %i net/%i demo\n"
"\tFPS: %g\n"
"\tMap: %s\n"
"\tComment: %s\n"
"\tGame: %s\n",
filename, hdr.net_protocol, hdr.dem_protocol, hdr.host_fps, hdr.mapname,
hdr.comment, hdr.gamedir );
for( i = 0; i < num_entries; i++ )
{
demoentry_t entry;
Con_Printf( "Demo entry #%i:\n", i );
if( FS_Read( f, &entry, sizeof( entry )) != sizeof( entry ))
{
Con_Printf( S_ERROR "can't read demo entry\n" );
FS_Close( f );
return;
}
entry.description[sizeof( entry.description ) - 1] = 0;
if( entry.entrytype == DEMO_STARTUP )
{
// startup entries don't have anything useful
Con_Printf( "\tEntry type: " S_YELLOW "startup" S_DEFAULT "\n" );
}
else
{
Con_Printf( "\tEntry type: " S_GREEN "normal" S_DEFAULT " (%i)\n"
"\tEntry playback time/frames: %.2f seconds/%i frames\n"
"\tEntry flags: 0x%x\n"
"\tEntry description: %s\n",
entry.entrytype, entry.playback_time, entry.playback_frames,
entry.flags, entry.description );
}
}
FS_Close( f );
}

View File

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

View File

@@ -636,12 +636,24 @@ and all particle trails (if this is a beamfollow)
*/
void GAME_EXPORT R_BeamKill( int deadEntity )
{
cl_entity_t *pDeadEntity;
BEAM *beam;
pDeadEntity = R_BeamGetEntity( deadEntity );
if( !pDeadEntity ) return;
for( beam = cl_active_beams; beam; beam = beam->next )
{
if( FBitSet( beam->flags, FBEAM_STARTENTITY ) && beam->startEntity == deadEntity )
{
if( beam->type != TE_BEAMFOLLOW )
beam->die = cl.time;
CL_KillDeadBeams( pDeadEntity );
ClearBits( beam->flags, FBEAM_STARTENTITY );
}
if( FBitSet( beam->flags, FBEAM_ENDENTITY ) && beam->endEntity == deadEntity )
{
beam->die = cl.time;
ClearBits( beam->flags, FBEAM_ENDENTITY );
}
}
}
/*
@@ -1094,9 +1106,7 @@ void GAME_EXPORT R_ParticleExplosion2( const vec3_t org, int colorStart, int col
int colorMod = 0, packedColor;
particle_t *p;
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
packedColor = 255; // use old code for blob particles
else packedColor = 0;
packedColor = Host_IsQuakeCompatible( ) ? 255 : 0; // use old code for blob particles
for( i = 0; i < 512; i++ )
{
@@ -1129,9 +1139,7 @@ void GAME_EXPORT R_BlobExplosion( const vec3_t org )
particle_t *p;
int i, j, packedColor;
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
packedColor = 255; // use old code for blob particles
else packedColor = 0;
packedColor = Host_IsQuakeCompatible( ) ? 255 : 0; // use old code for blob particles
for( i = 0; i < 1024; i++ )
{

View File

@@ -95,8 +95,7 @@ static void CL_ResetPositions( cl_entity_t *ent )
ent->current_position = 1;
memset( ent->ph, 0, sizeof( position_history_t ) * HISTORY_MAX );
memcpy( &ent->ph[1], &store, sizeof( position_history_t ));
memcpy( &ent->ph[0], &store, sizeof( position_history_t ));
ent->ph[1] = ent->ph[0] = store;
}
/*
@@ -752,7 +751,7 @@ static void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_s
if( has_update )
alive = MSG_ReadDeltaEntity( msg, old, state, newnum, delta_type, cl.mtime[0] );
else memcpy( state, old, sizeof( entity_state_t ));
else *state = *old;
if( !alive )
{

View File

@@ -560,7 +560,19 @@ static void CL_DrawScreenFade( void )
if( !alpha )
return;
if( FBitSet( sf->fadeFlags, FFADE_MODULATE ))
if( !FBitSet( sf->fadeFlags, FFADE_MODULATE ))
{
ref.dllFuncs.GL_SetRenderMode( kRenderTransTexture );
ref.dllFuncs.Color4ub( sf->fader, sf->fadeg, sf->fadeb, alpha );
}
else if( Host_IsQuakeCompatible( ))
{
// Quake Wrapper and Quake Remake use FFADE_MODULATE for item pickups
// so hack the check here
ref.dllFuncs.GL_SetRenderMode( kRenderTransAdd );
ref.dllFuncs.Color4ub( sf->fader, sf->fadeg, sf->fadeb, alpha );
}
else
{
ref.dllFuncs.GL_SetRenderMode( kRenderScreenFadeModulate );
@@ -570,11 +582,6 @@ static void CL_DrawScreenFade( void )
(uint16_t)( sf->fadeb * alpha + ( 255 - alpha ) * 255 ) >> 8,
255 );
}
else
{
ref.dllFuncs.GL_SetRenderMode( kRenderTransTexture );
ref.dllFuncs.Color4ub( sf->fader, sf->fadeg, sf->fadeb, alpha );
}
ref.dllFuncs.R_DrawStretchPic( 0, 0, refState.width, refState.height, 0, 0, 1, 1,
R_GetBuiltinTexture( REF_WHITE_TEXTURE ));
@@ -1182,7 +1189,7 @@ static qboolean CL_LoadHudSprite( const char *szSpriteName, model_t *m_pSprite,
if( type == SPR_CLIENT || type == SPR_HUDSPRITE )
SetBits( m_pSprite->flags, MODEL_CLIENT );
m_pSprite->numtexinfo = texFlags; // store texFlags into numtexinfo
m_pSprite->numtexinfo = texFlags; // store texFlags for renderer into numtexinfo
if( !FS_FileExists( szSpriteName, false ) )
{
@@ -1209,7 +1216,7 @@ static qboolean CL_LoadHudSprite( const char *szSpriteName, model_t *m_pSprite,
ref.dllFuncs.Mod_LoadMapSprite( m_pSprite, buf, size, &loaded );
else
{
Mod_LoadSpriteModel( m_pSprite, buf, &loaded, texFlags );
Mod_LoadSpriteModel( m_pSprite, buf, &loaded );
ref.dllFuncs.Mod_ProcessRenderData( m_pSprite, true, buf );
}
@@ -2428,8 +2435,8 @@ static void GAME_EXPORT pfnLocalPlayerBounds( int hull, float *mins, float *maxs
{
if( hull >= 0 && hull < 4 )
{
if( mins ) VectorCopy( clgame.pmove->player_mins[hull], mins );
if( maxs ) VectorCopy( clgame.pmove->player_maxs[hull], maxs );
if( mins ) VectorCopy( host.player_mins[hull], mins );
if( maxs ) VectorCopy( host.player_maxs[hull], maxs );
}
}
@@ -2497,9 +2504,17 @@ CL_PushTraceBounds
*/
static void GAME_EXPORT CL_PushTraceBounds( int hullnum, const float *mins, const float *maxs )
{
if( !host.trace_bounds_pushed )
{
memcpy( host.player_mins_backup, host.player_mins, sizeof( host.player_mins_backup ));
memcpy( host.player_maxs_backup, host.player_maxs, sizeof( host.player_maxs_backup ));
host.trace_bounds_pushed = true;
}
hullnum = bound( 0, hullnum, 3 );
VectorCopy( mins, clgame.pmove->player_mins[hullnum] );
VectorCopy( maxs, clgame.pmove->player_maxs[hullnum] );
VectorCopy( mins, host.player_mins[hullnum] );
VectorCopy( maxs, host.player_maxs[hullnum] );
}
/*
@@ -2510,8 +2525,15 @@ CL_PopTraceBounds
*/
static void GAME_EXPORT CL_PopTraceBounds( void )
{
memcpy( clgame.pmove->player_mins, host.player_mins, sizeof( host.player_mins ));
memcpy( clgame.pmove->player_maxs, host.player_maxs, sizeof( host.player_maxs ));
if( !host.trace_bounds_pushed )
{
Con_Reportf( S_ERROR "%s called without push!\n", __func__ );
return;
}
host.trace_bounds_pushed = false;
memcpy( host.player_mins, host.player_mins_backup, sizeof( host.player_mins ));
memcpy( host.player_maxs, host.player_maxs_backup, sizeof( host.player_maxs ));
}
/*
@@ -3283,7 +3305,7 @@ Heavy legacy of Quake...
*/
void TriColor4fRendermode( float r, float g, float b, float a, int rendermode )
{
if( clgame.ds.renderMode == kRenderTransAlpha )
if( rendermode == kRenderTransAlpha )
{
clgame.ds.triRGBA[3] = a / 255.0f;
ref.dllFuncs.Color4f( r, g, b, a );
@@ -3415,7 +3437,6 @@ NetAPI_SendRequest
static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags, double timeout, netadr_t *remote_address, net_api_response_func_t response )
{
net_request_t *nr = NULL;
string req;
int i;
if( !response )
@@ -3467,8 +3488,7 @@ static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags,
nr->flags = flags;
// local servers request
Q_snprintf( req, sizeof( req ), "netinfo %i %i %i", FBitSet( flags, FNETAPI_LEGACY_PROTOCOL ) ? PROTOCOL_LEGACY_VERSION : PROTOCOL_VERSION, context, request );
Netchan_OutOfBandPrint( NS_CLIENT, nr->resp.remote_address, "%s", req );
Netchan_OutOfBandPrint( NS_CLIENT, nr->resp.remote_address, "netinfo %i %i %i", FBitSet( flags, FNETAPI_LEGACY_PROTOCOL ) ? PROTOCOL_LEGACY_VERSION : PROTOCOL_VERSION, context, request );
}
/*

View File

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

View File

@@ -87,12 +87,14 @@ CVAR_DEFINE_AUTO( cl_fixmodelinterpolationartifacts, "1", 0, "try to fix up mode
//
// userinfo
//
static CVAR_DEFINE_AUTO( name, "player", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_PRINTABLEONLY|FCVAR_FILTERABLE, "player name" );
static char username[32];
static CVAR_DEFINE_AUTO( name, username, FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_PRINTABLEONLY|FCVAR_FILTERABLE, "player name" );
static CVAR_DEFINE_AUTO( model, "", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player model ('player' is a singleplayer model)" );
static CVAR_DEFINE_AUTO( topcolor, "0", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player top color" );
static CVAR_DEFINE_AUTO( bottomcolor, "0", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player bottom color" );
CVAR_DEFINE_AUTO( rate, "3500", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player network rate" );
client_t cl;
client_static_t cls;
clgame_static_t clgame;
@@ -2345,14 +2347,11 @@ static void CL_ParseNetMessage( sizebuf_t *msg, void (*parsefn)( sizebuf_t * ))
// after we have parsed the frame
if( !cls.demoplayback )
{
if( cls.demorecording && !cls.demowaiting )
{
CL_WriteDemoMessage( false, cls.starting_count, msg );
}
else if( cls.state != ca_active )
{
if( cls.state != ca_active )
CL_WriteDemoMessage( true, cls.starting_count, msg );
}
if( cls.demorecording && !cls.demowaiting )
CL_WriteDemoMessage( false, cls.starting_count, msg );
}
}
@@ -2592,7 +2591,6 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
{
int sound_len = sizeof( DEFAULT_SOUNDPATH ) - 1;
byte rgucMD5_hash[16];
const char *pfilename;
resource_t *p;
if( COM_CheckString( filename ) && successfully_received )
@@ -2600,10 +2598,10 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
if( filename[0] != '!' )
Con_Printf( "processing %s\n", filename );
if( !Q_strnicmp( filename, "downloaded/", 11 ))
if( !Q_strnicmp( filename, DEFAULT_DOWNLOADED_DIRECTORY, sizeof( DEFAULT_DOWNLOADED_DIRECTORY ) - 1 ))
{
// skip "downloaded/" part to avoid mismatch with needed resources list
filename += 11;
filename += sizeof( DEFAULT_DOWNLOADED_DIRECTORY ) - 1;
}
}
else if( !successfully_received )
@@ -2669,7 +2667,7 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
else
{
Con_Printf( "Downloaded %i bytes for purported %i byte file, ignoring download\n",
cls.netchan.tempbuffersize, p->nDownloadSize );
cls.netchan.tempbuffersize, p->nDownloadSize );
}
if( cls.netchan.tempbuffer )
@@ -2829,19 +2827,26 @@ static void CL_Physinfo_f( void )
static qboolean CL_ShouldRescanFilesystem( void )
{
resource_t *res;
qboolean retval = false;
for( res = cl.resourcesonhand.pNext; res && res != &cl.resourcesonhand; res = res->pNext )
{
if( res->type == t_generic )
{
const char *ext = COM_FileExtension( res->szFileName );
// TODO: query supported archives format from fs_stdio
// TODO: query if was already opened
if( !Q_stricmp( ext, "wad" ) || !Q_stricmp( ext, "pk3" ) || !Q_stricmp( ext, "pak" ))
return true;
if( !g_fsapi.IsArchiveExtensionSupported( ext, IAES_ONLY_REAL_ARCHIVES ))
continue;
if( FBitSet( res->ucExtraFlags, RES_EXTRA_ARCHIVE_CHECKED ))
continue;
SetBits( res->ucExtraFlags, RES_EXTRA_ARCHIVE_CHECKED );
retval = true;
}
}
return false;
return retval;
}
qboolean CL_PrecacheResources( void )
@@ -3074,8 +3079,9 @@ static void CL_InitLocal( void )
// userinfo
Cvar_RegisterVariable( &cl_nopred );
Q_strncpy( username, Sys_GetCurrentUser(), sizeof( username )); // initialize before registering variable
Cvar_RegisterVariable( &name );
Cvar_DirectSet( &name, Sys_GetCurrentUser( ));
Cvar_Get( "ui_username", username, FCVAR_READ_ONLY|FCVAR_PRIVILEGED, "default user name" );
Cvar_RegisterVariable( &model );
Cvar_RegisterVariable( &cl_updaterate );
Cvar_RegisterVariable( &cl_dlmax );
@@ -3151,6 +3157,7 @@ static void CL_InitLocal( void )
Cmd_AddCommand ("demos", CL_Demos_f, "restart looping demos defined by the last startdemos command" );
Cmd_AddCommand ("movie", CL_PlayVideo_f, "play a movie" );
Cmd_AddCommand ("stop", CL_Stop_f, "stop playing or recording a demo" );
Cmd_AddCommand( "listdemo", CL_ListDemo_f, "list demo entries" );
Cmd_AddCommand ("info", NULL, "collect info about local servers with specified protocol" );
Cmd_AddCommand ("escape", CL_Escape_f, "escape from game to menu" );
Cmd_AddCommand ("togglemenu", CL_Escape_f, "toggle between game and menu" );

View File

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

View File

@@ -251,7 +251,7 @@ void CL_ParseMovevars( sizebuf_t *msg )
if( Q_strcmp( clgame.oldmovevars.skyName, clgame.movevars.skyName ) && cl.video_prepped )
R_SetupSky( clgame.movevars.skyName );
memcpy( &clgame.oldmovevars, &clgame.movevars, sizeof( movevars_t ));
clgame.oldmovevars = clgame.movevars;
clgame.entities->curstate.scale = clgame.movevars.waveHeight;
// keep features an actual!
@@ -1403,7 +1403,7 @@ void CL_UpdateUserinfo( sizebuf_t *msg, qboolean legacy )
if( !legacy )
MSG_ReadBytes( msg, player->hashedcdkey, sizeof( player->hashedcdkey ));
if( slot == cl.playernum ) memcpy( &gameui.playerinfo, player, sizeof( player_info_t ));
if( slot == cl.playernum ) gameui.playerinfo = *player;
}
else
{

View File

@@ -656,7 +656,7 @@ void CL_LegacyPrecache_f( void )
// Include server count in case server disconnects and changes level during d/l
MSG_BeginClientCmd( &cls.netchan.message, clc_stringcmd );
MSG_WriteStringf( &cls.netchan.message, "begin %i", spawncount );
cls.signon = SIGNONS;
cls.signon = SIGNONS - 1;
}
qboolean CL_LegacyMode( void )

View File

@@ -544,8 +544,8 @@ void GAME_EXPORT CL_SetSolidPlayers( int playernum )
// some fields needs to be override from cls.predicted_players
VectorCopy( player->origin, pe->origin );
VectorCopy( player->angles, pe->angles );
VectorCopy( clgame.pmove->player_mins[player->usehull], pe->mins );
VectorCopy( clgame.pmove->player_maxs[player->usehull], pe->maxs );
VectorCopy( host.player_mins[player->usehull], pe->mins );
VectorCopy( host.player_maxs[player->usehull], pe->maxs );
pe->movetype = player->movetype;
pe->solid = player->solid;
}

View File

@@ -22,22 +22,24 @@ GNU General Public License for more details.
#include "hltv.h"
#include "input.h"
#define STAT_HEALTH 0
#define STAT_FRAGS 1
#define STAT_WEAPON 2
#define STAT_AMMO 3
#define STAT_ARMOR 4
#define STAT_WEAPONFRAME 5
#define STAT_SHELLS 6
#define STAT_NAILS 7
#define STAT_ROCKETS 8
#define STAT_CELLS 9
#define STAT_ACTIVEWEAPON 10
#define STAT_TOTALSECRETS 11
#define STAT_TOTALMONSTERS 12
#define STAT_SECRETS 13 // bumped on client side by svc_foundsecret
#define STAT_MONSTERS 14 // bumped by svc_killedmonster
#define MAX_STATS 32
enum {
STAT_HEALTH = 0,
STAT_FRAGS,
STAT_WEAPON,
STAT_AMMO,
STAT_ARMOR,
STAT_WEAPONFRAME,
STAT_SHELLS,
STAT_NAILS,
STAT_ROCKETS,
STAT_CELLS,
STAT_ACTIVEWEAPON,
STAT_TOTALSECRETS,
STAT_TOTALMONSTERS,
STAT_SECRETS, // bumped on client side by svc_foundsecret
STAT_MONSTERS, // bumped by svc_killedmonster
MAX_STATS = 32,
};
static char cmd_buf[8192];
static char msg_buf[8192];
@@ -328,7 +330,7 @@ static void CL_ParseQuakeServerInfo( sizebuf_t *msg )
clgame.movevars.gravity = 800.0f; // quake doesn't write gravity in demos
clgame.movevars.maxvelocity = 2000.0f;
memcpy( &clgame.oldmovevars, &clgame.movevars, sizeof( movevars_t ));
clgame.oldmovevars = clgame.movevars;
}
/*
@@ -715,8 +717,7 @@ static void CL_ParseQuakeBaseline( sizebuf_t *msg )
ent = CL_EDICT_NUM( newnum );
ent->index = newnum;
ent->player = CL_IsPlayerIndex( newnum );
memcpy( &ent->baseline, &state, sizeof( entity_state_t ));
memcpy( &ent->prevstate, &state, sizeof( entity_state_t ));
ent->prevstate = ent->baseline = state;
}
/*

View File

@@ -2448,7 +2448,8 @@ void CL_SetLightstyle( int style, const char *s, float f )
}
}
Con_Reportf( "Lightstyle %i (%s), interp %s\n", style, ls->pattern, ls->interp ? "Yes" : "No" );
if( ls->length >= 1 )
Con_Reportf( "Lightstyle %i (%s), interp %s\n", style, ls->pattern, ls->interp ? "Yes" : "No" );
}
/*
@@ -2570,31 +2571,43 @@ CL_DecayLights
*/
void CL_DecayLights( void )
{
dlight_t *dl;
float time;
const float time = cl.time;
const float dt = cl.time - cl.oldtime;
int i;
time = cl.time - cl.oldtime;
for( i = 0, dl = cl_dlights; i < MAX_DLIGHTS; i++, dl++ )
for( i = 0; i < MAX_DLIGHTS; i++ )
{
if( !dl->radius ) continue;
dlight_t *dl = &cl_dlights[i];
dl->radius -= time * dl->decay;
if( dl->radius < 0 ) dl->radius = 0;
if( !dl->radius )
continue;
if( dl->die < cl.time || !dl->radius )
if( dl->die < time )
{
memset( dl, 0, sizeof( *dl ));
continue;
}
dl->radius -= dt * dl->decay;
if( dl->radius <= 0 )
memset( dl, 0, sizeof( *dl ));
}
for( i = 0, dl = cl_elights; i < MAX_ELIGHTS; i++, dl++ )
for( i = 0; i < MAX_ELIGHTS; i++ )
{
if( !dl->radius ) continue;
dlight_t *dl = &cl_elights[i];
dl->radius -= time * dl->decay;
if( dl->radius < 0 ) dl->radius = 0;
if( !dl->radius )
continue;
if( dl->die < cl.time || !dl->radius )
if( dl->die < time )
{
memset( dl, 0, sizeof( *dl ));
continue;
}
dl->radius -= dt * dl->decay;
if( dl->radius <= 0 )
memset( dl, 0, sizeof( *dl ));
}
}
@@ -2737,7 +2750,12 @@ void CL_AddEntityEffects( cl_entity_t *ent )
if( FBitSet( ent->curstate.effects, EF_BRIGHTLIGHT ))
R_EntityBrightlight( ent, ent->index /* 1 in GoldSrc */, 400 );
else if( FBitSet( ent->curstate.effects, EF_DIMLIGHT ))
CL_UpdateFlashlight( ent );
{
if( Host_IsQuakeCompatible( ))
R_EntityDimlight( ent, ent->index );
else
CL_UpdateFlashlight( ent );
}
}
else
{
@@ -3058,26 +3076,6 @@ EFRAGS MANAGEMENT
==============================================================
*/
efrag_t cl_efrags[MAX_EFRAGS];
/*
==============
CL_ClearEfrags
==============
*/
void CL_ClearEfrags( void )
{
int i;
memset( cl_efrags, 0, sizeof( cl_efrags ));
// allocate the efrags and chain together into a free list
clgame.free_efrags = cl_efrags;
for( i = 0; i < MAX_EFRAGS - 1; i++ )
clgame.free_efrags[i].entnext = &clgame.free_efrags[i+1];
clgame.free_efrags[i].entnext = NULL;
}
/*
=======================
R_ClearStaticEntities

View File

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

View File

@@ -501,7 +501,6 @@ typedef struct
net_request_t net_requests[MAX_REQUESTS]; // no reason to keep more
efrag_t *free_efrags; // linked efrags
cl_entity_t viewent; // viewmodel
qboolean client_dll_uses_sdl;
@@ -518,8 +517,9 @@ typedef struct
player_info_t playerinfo; // local playerinfo
gameui_draw_t ds; // draw2d stuff (menu images)
GAMEINFO gameInfo; // current gameInfo
GAMEINFO *modsInfo[MAX_MODS]; // simplified gameInfo for MainUI
gameinfo2_t gameInfo; // current gameInfo
gameinfo2_t *modsInfo; // simplified gameInfo for MainUI, allocated by demand
GAMEINFO **oldModsInfo; // simplified gameInfo for older MainUI, allocated by demand
ui_globalvars_t *globals;
@@ -784,6 +784,7 @@ void CL_Demos_f( void );
void CL_DeleteDemo_f( void );
void CL_Record_f( void );
void CL_Stop_f( void );
void CL_ListDemo_f( void );
int CL_GetDemoComment( const char *demoname, char *comment );
//

View File

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

View File

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

View File

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

View File

@@ -58,7 +58,6 @@ typedef enum
} touchEventType;
extern convar_t touch_enable;
extern convar_t touch_emulate;
void Touch_Draw( void );
void Touch_SetClientOnly( byte state );
@@ -74,6 +73,7 @@ void Touch_ResetDefaultButtons( void );
int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy );
void Touch_KeyEvent( int key, int down );
qboolean Touch_WantVisibleCursor( void );
qboolean Touch_Emulated( void );
void Touch_NotifyResize( void );
//

View File

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

View File

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

View File

@@ -1092,7 +1092,7 @@ rawchan_t *S_FindRawChannel( int entnum, qboolean create )
if( !raw_channels[best] )
{
raw_samples = MAX_RAW_SAMPLES;
raw_channels[best] = Mem_Calloc( sndpool, sizeof( *ch ) + sizeof( portable_samplepair_t ) * ( raw_samples - 1 ));
raw_channels[best] = Mem_Calloc( sndpool, sizeof( *ch ) + sizeof( portable_samplepair_t ) * raw_samples );
}
ch = raw_channels[best];

View File

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

View File

@@ -96,7 +96,7 @@ static int S_TrimEnd( const wavdata_t *wav, int end )
if( width == 1 )
{
const int8_t *data = (const int8_t *)&wav->buffer[channels * width * end];
const int8_t *data = (const int8_t *)&wav->buffer[channels * width * ( end - 1 )];
for( i = 0; i < TRIM_SCAN_MAX && end > 0; i++ )
{
@@ -109,7 +109,7 @@ static int S_TrimEnd( const wavdata_t *wav, int end )
}
else if( width == 2 )
{
const int16_t *data = (const int16_t *)&wav->buffer[channels * width * end];
const int16_t *data = (const int16_t *)&wav->buffer[channels * width * ( end - 1 )];
for( i = 0; i < TRIM_SCAN_MAX && end > 0; i++ )
{

View File

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

View File

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

View File

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

View File

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

View File

@@ -387,7 +387,7 @@ static void Cmd_Echo_f( void )
int i;
for( i = 1; i < Cmd_Argc(); i++ )
Con_Printf( "%s", Cmd_Argv( i ));
Con_Printf( "%s ", Cmd_Argv( i ));
Con_Printf( "\n" );
}

View File

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

View File

@@ -314,6 +314,11 @@ typedef struct host_parm_s
vec3_t player_mins[MAX_MAP_HULLS]; // 4 hulls allowed
vec3_t player_maxs[MAX_MAP_HULLS]; // 4 hulls allowed
// for CL_{Push,Pop}TraceBounds
vec3_t player_mins_backup[MAX_MAP_HULLS];
vec3_t player_maxs_backup[MAX_MAP_HULLS];
qboolean trace_bounds_pushed;
qboolean allow_console; // allow console in dev-mode or multiplayer game
qboolean allow_console_init; // initial value to allow the console
qboolean key_overstrike; // key overstrike mode
@@ -492,7 +497,7 @@ int FS_ReadStream( stream_t *stream, int bytes, void *buffer );
int FS_SetStreamPos( stream_t *stream, int newpos );
int FS_GetStreamPos( stream_t *stream );
void FS_FreeStream( stream_t *stream );
qboolean Sound_Process( wavdata_t **wav, int rate, int width, uint flags );
qboolean Sound_Process( wavdata_t **wav, int rate, int width, int channels, uint flags );
uint Sound_GetApproxWavePlayLen( const char *filepath );
qboolean Sound_SupportedFileFormat( const char *fileext );

View File

@@ -1019,6 +1019,7 @@ autocomplete_list_t cmd_list[] =
{ "changelevel", 1, Cmd_GetMapList },
{ "playdemo", 1, Cmd_GetDemoList, },
{ "timedemo", 1, Cmd_GetDemoList, },
{ "listdemo", 1, Cmd_GetDemoList, },
{ "playvol", 1, Cmd_GetSoundList },
{ "hpkval", 1, Cmd_GetCustomList },
{ "hpklist", 1, Cmd_GetCustomList },
@@ -1201,7 +1202,7 @@ void Con_CompleteCommand( field_t *field )
if( !con.matchCount ) return; // no matches
memcpy( &temp, con.completionField, sizeof( field_t ) );
temp = *con.completionField;
// autocomplete second arg
if( (Cmd_Argc() >= 2) || ((Cmd_Argc() == 1) && nextcmd) )

View File

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

View File

@@ -230,7 +230,7 @@ static const char *Cvar_ValidateString( convar_t *var, const char *value )
if( !COM_CheckStringEmpty( szNew ) ) Q_strncpy( szNew, "empty", sizeof( szNew ));
}
if( FBitSet( var->flags, FCVAR_NOEXTRAWHITEPACE ))
if( FBitSet( var->flags, FCVAR_NOEXTRAWHITESPACE ))
{
char *szVal = szNew;
int len = 0;

View File

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

View File

@@ -59,7 +59,7 @@ static void FS_Path_f_( void )
FS_Path_f();
}
static fs_interface_t fs_memfuncs =
static const fs_interface_t fs_memfuncs =
{
Con_Printf,
Con_DPrintf,
@@ -221,7 +221,13 @@ void FS_Init( const char *basedir )
COM_StripDirectorySlash( rodir );
if( !Sys_GetParmFromCmdLine( "-game", gamedir ))
Q_strncpy( gamedir, basedir, sizeof( gamedir )); // gamedir == basedir
{
char *env = getenv( "XASH3D_GAME" );
if( env )
Q_strncpy( gamedir, env, sizeof( gamedir ));
else
Q_strncpy( gamedir, basedir, sizeof( gamedir )); // gamedir == basedir
}
FS_LoadProgs();

View File

@@ -1028,8 +1028,8 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
}
#endif
// always enable console for Quake
if( !host.allow_console && ( Sys_CheckParm( "-console" ) || !Q_strnicmp( exename, "quake", 5 )))
// always enable console for Quake and dedicated
if( !host.allow_console && ( Host_IsDedicated() || Sys_CheckParm( "-console" ) || !Q_strnicmp( exename, "quake", 5 )))
host.allow_console = true;
// member console allowing
@@ -1078,7 +1078,16 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
// print current developer level to simplify processing users feedback
if( developer > 0 )
Con_Printf( "Developer level: ^3%i\n", developer );
{
int i;
Con_Printf( "Program args: " S_YELLOW );
for( i = 0; i < host.argc; i++ )
Con_Printf( "%s ", host.argv[i] );
Con_Printf( S_DEFAULT "\n" );
Con_Printf( "Developer level: " S_YELLOW "%i" S_DEFAULT "\n", developer );
}
host.bugcomp = Host_CheckBugcomp();

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

View File

@@ -1677,9 +1677,10 @@ static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod )
// mark models that have origin brushes
if( !VectorIsNull( bm->origin ))
SetBits( mod->flags, MODEL_HAS_ORIGIN );
#ifdef HACKS_RELATED_HLMODS
// c2a1 doesn't have origin brush it's just placed at center of the level
if( !Q_stricmp( name, "maps/c2a1.bsp" ) && ( i == 11 ))
if( i == 11 && !Q_stricmp( name, "maps/c2a1.bsp" ))
SetBits( mod->flags, MODEL_HAS_ORIGIN );
#endif
}
@@ -1835,6 +1836,8 @@ static void Mod_LoadEntities( model_t *mod, dbspmodel_t *bmod )
world.generator[0] = '\0';
world.compiler[0] = '\0';
world.message[0] = '\0';
world.litwater_minlight = -1;
world.litwater_scale = -1.0f;
bmod->wadlist.count = 0;
// parse all the wads for loading textures in right ordering
@@ -1893,6 +1896,15 @@ static void Mod_LoadEntities( model_t *mod, dbspmodel_t *bmod )
Q_strncpy( world.compiler, token, sizeof( world.compiler ));
else if( !Q_stricmp( keyname, "generator" ) || !Q_stricmp( keyname, "_generator" ))
Q_strncpy( world.generator, token, sizeof( world.generator ));
else if( !Q_stricmp( keyname, "_litwater" ))
{
if( Q_atoi( token ) != 0 )
SetBits( world.flags, FWORLD_HAS_LITWATER );
}
else if( !Q_stricmp( keyname, "_litwater_minlight" ))
world.litwater_minlight = Q_atoi( token );
else if( !Q_stricmp( keyname, "_litwater_scale" ))
world.litwater_scale = Q_atof( token );
}
return; // all done
}

View File

@@ -74,7 +74,7 @@ typedef struct winding_s
struct winding_s *pair;
hullnode_t chain;
int numpoints;
vec3_t p[4]; // variable sized
vec3_t p[]; // variable sized
} winding_t;
typedef struct
@@ -119,6 +119,10 @@ typedef struct world_static_s
// Potentially Hearable Set
byte *compressed_phs;
size_t *phsofs;
// lightmapped water extra info
float litwater_scale;
int litwater_minlight;
} world_static_t;
#ifndef REF_DLL
@@ -149,6 +153,11 @@ qboolean Mod_ValidateCRC( const char *name, CRC32_t crc );
void Mod_NeedCRC( const char *name, qboolean needCRC );
void Mod_FreeUnused( void );
//
// mod_alias.c
//
void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *loaded );
//
// mod_bmodel.c
//
@@ -194,7 +203,7 @@ void Mod_ClearStudioCache( void );
//
// mod_sprite.c
//
void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, uint texFlags );
void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded );
#endif
#endif//MOD_LOCAL_H

View File

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

View File

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

View File

@@ -160,17 +160,6 @@ void MSG_InitMasks( void )
ExtraMasks[maskBit] = (uint)BIT( maskBit ) - 1;
}
void MSG_WriteOneBit( sizebuf_t *sb, int nValue )
{
if( !MSG_Overflow( sb, 1 ))
{
if( nValue ) sb->pData[sb->iCurBit>>3] |= BIT( sb->iCurBit & 7 );
else sb->pData[sb->iCurBit>>3] &= ~BIT( sb->iCurBit & 7 );
sb->iCurBit++;
}
}
void MSG_WriteUBitLong( sizebuf_t *sb, uint curData, int numbits )
{
Assert( numbits >= 0 && numbits <= 32 );
@@ -395,15 +384,11 @@ qboolean MSG_WriteBytes( sizebuf_t *sb, const void *pBuf, int nBytes )
qboolean MSG_WriteString( sizebuf_t *sb, const char *pStr )
{
if( pStr )
{
do
{
MSG_WriteChar( sb, (signed char)*pStr );
pStr++;
} while( *( pStr - 1 ));
}
else MSG_WriteChar( sb, 0 );
int len = Q_strlen( pStr );
if( len )
MSG_WriteBytes( sb, pStr, len + 1 );
else MSG_WriteByte( sb, 0 );
return !sb->bOverflow;
}
@@ -411,13 +396,22 @@ qboolean MSG_WriteString( sizebuf_t *sb, const char *pStr )
qboolean MSG_WriteStringf( sizebuf_t *sb, const char *format, ... )
{
va_list va;
int len;
char buf[MAX_VA_STRING];
va_start( va, format );
Q_vsnprintf( buf, sizeof( buf ), format, va );
len = Q_vsnprintf( buf, sizeof( buf ), format, va );
va_end( va );
return MSG_WriteString( sb, buf );
if( len < 0 )
{
Host_Error( "%s: snprintf overflow!\n", __func__ );
return false;
}
MSG_WriteBytes( sb, buf, len + 1 );
return !sb->bOverflow;
}
int MSG_ReadOneBit( sizebuf_t *sb )
@@ -629,9 +623,7 @@ float MSG_ReadFloat( sizebuf_t *sb )
{
float ret;
Assert( sizeof( ret ) == 4 );
MSG_ReadBits( sb, &ret, 32 );
MSG_ReadBits( sb, &ret, sizeof( ret ) << 3 );
return ret;
}
@@ -694,3 +686,160 @@ void MSG_ExciseBits( sizebuf_t *sb, int startbit, int bitstoremove )
MSG_SeekToBit( sb, startbit, SEEK_SET );
sb->nDataBits -= bitstoremove;
}
#ifdef XASH_ENGINE_TESTS
#include "tests.h"
static const void *g_testbuf = "asdf\xba\xa1\xba\xa1\xed\xc8\x15\x7a";
static const size_t g_testbuf_bits = (( 4 + 4 + 2 + 1 ) << 3 ) + 4;
static void Test_Buffer_BitByte( void )
{
TASSERT_EQi( BitByte( 0 ), 0 );
TASSERT_EQi( BitByte( 1 ), 1 );
TASSERT_EQi( BitByte( 8 ), 1 );
TASSERT_EQi( BitByte( 9 ), 2 );
}
static void Test_Buffer_Write( void )
{
sizebuf_t sb;
char testdata[0x100] = { 0 };
MSG_Init( &sb, __func__, testdata, sizeof( testdata ));
TASSERT_EQi( sb.iCurBit, 0 );
TASSERT_EQi( sb.nDataBits, sizeof( testdata ) << 3 );
TASSERT_EQi( sb.pData, testdata );
TASSERT_EQi( sb.bOverflow, false );
MSG_WriteBytes( &sb, "asdf", 4 );
TASSERT_EQi( sb.bOverflow, false );
TASSERT_EQi( sb.iCurBit, 32 );
MSG_WriteDword( &sb, 0xa1baa1ba );
TASSERT_EQi( sb.bOverflow, false );
TASSERT_EQi( sb.iCurBit, 64 );
MSG_WriteShort( &sb, -0x3713 );
TASSERT_EQi( sb.bOverflow, false );
TASSERT_EQi( sb.iCurBit, 80 );
MSG_WriteOneBit( &sb, 1 );
TASSERT_EQi( sb.bOverflow, false );
TASSERT_EQi( sb.iCurBit, 81 );
MSG_WriteOneBit( &sb, 0 );
TASSERT_EQi( sb.bOverflow, false );
TASSERT_EQi( sb.iCurBit, 82 );
MSG_WriteOneBit( &sb, 1 );
TASSERT_EQi( sb.bOverflow, false );
TASSERT_EQi( sb.iCurBit, 83 );
MSG_WriteOneBit( &sb, 0 );
TASSERT_EQi( sb.bOverflow, false );
TASSERT_EQi( sb.iCurBit, 84 );
MSG_WriteByte( &sb, 0xa1 );
TASSERT_EQi( sb.bOverflow, false );
TASSERT_EQi( sb.iCurBit, 92 );
TASSERT_EQi( MSG_GetNumBitsWritten( &sb ), g_testbuf_bits );
TASSERT_EQi( MSG_GetNumBytesWritten( &sb ), BitByte( g_testbuf_bits ));
TASSERT_EQi( MSG_GetRealBytesWritten( &sb ), g_testbuf_bits >> 3 );
// if tests fails here on big endian, it's possible due to endian issues
TASSERT( !memcmp( sb.pData, g_testbuf, g_testbuf_bits >> 3 ));
// must check last 4 bits separately because we never care about uninitialized bits
MSG_SeekToBit( &sb, g_testbuf_bits & ~7, SEEK_SET );
TASSERT_EQi( sb.iCurBit, 88 );
TASSERT_EQi( MSG_ReadUBitLong( &sb, 4 ), 0xa );
}
static void Test_Buffer_Read( void )
{
sizebuf_t sb;
char buf[4];
MSG_StartReading( &sb, (void *)g_testbuf, -1, 0, g_testbuf_bits );
TASSERT_EQi( sb.iCurBit, 0 );
TASSERT_EQi( sb.nDataBits, g_testbuf_bits );
TASSERT_EQi( sb.pData, g_testbuf );
TASSERT_EQi( sb.bOverflow, false );
MSG_ReadBytes( &sb, buf, 4 );
TASSERT( !memcmp( buf, "asdf", 4 ));
TASSERT_EQi( sb.iCurBit, 32 );
TASSERT_EQi( sb.bOverflow, false );
TASSERT_EQi( MSG_ReadWord( &sb ), 0xa1ba );
TASSERT_EQi( sb.iCurBit, 48 );
TASSERT_EQi( sb.bOverflow, false );
TASSERT_EQi( MSG_ReadDword( &sb ), 0xc8eda1baU );
TASSERT_EQi( sb.iCurBit, 80 );
TASSERT_EQi( sb.bOverflow, false );
TASSERT_EQi( MSG_ReadOneBit( &sb ), 1 );
TASSERT_EQi( sb.iCurBit, 81 );
TASSERT_EQi( sb.bOverflow, false );
TASSERT_EQi( MSG_ReadOneBit( &sb ), 0 );
TASSERT_EQi( sb.iCurBit, 82 );
TASSERT_EQi( sb.bOverflow, false );
TASSERT_EQi( MSG_ReadOneBit( &sb ), 1 );
TASSERT_EQi( sb.iCurBit, 83 );
TASSERT_EQi( sb.bOverflow, false );
TASSERT_EQi( MSG_ReadOneBit( &sb ), 0 );
TASSERT_EQi( sb.iCurBit, 84 );
TASSERT_EQi( sb.bOverflow, false );
TASSERT_EQi( MSG_ReadByte( &sb ), 0xa1 );
TASSERT_EQi( sb.iCurBit, 92 );
TASSERT_EQi( sb.bOverflow, false );
TASSERT_EQi( MSG_Overflow( &sb, 1 ), true );
TASSERT_EQi( sb.bOverflow, true );
}
static void Test_Buffer_ExciseBits( void )
{
sizebuf_t sb;
char testdata[0x100];
memcpy( testdata, g_testbuf, BitByte( g_testbuf_bits ));
MSG_StartWriting( &sb, testdata, 0, 0, g_testbuf_bits );
MSG_ExciseBits( &sb, 8, 28 );
TASSERT_EQi( MSG_CheckOverflow( &sb ), false );
TASSERT_EQi( MSG_GetMaxBits( &sb ), 64 );
TASSERT( !memcmp( MSG_GetData( &sb ), "a\x1b\xaa\x1b\xda\x8e\x5c\xa1", 8 ));
memcpy( testdata, g_testbuf, BitByte( g_testbuf_bits ));
MSG_StartWriting( &sb, testdata, 0, 0, g_testbuf_bits );
MSG_ExciseBits( &sb, 16, 32 );
TASSERT_EQi( MSG_CheckOverflow( &sb ), false );
TASSERT_EQi( MSG_GetMaxBits( &sb ), g_testbuf_bits - 32 );
TASSERT( !memcmp( MSG_GetData( &sb ), "as\xba\xa1\xed\xc8\x15", 7 ));
MSG_SeekToBit( &sb, 7 << 3, SEEK_SET );
TASSERT_EQi( MSG_ReadUBitLong( &sb, 4 ), 0xa );
}
void Test_RunBuffer( void )
{
MSG_InitMasks();
TRUN( Test_Buffer_BitByte( ));
TRUN( Test_Buffer_Write( ));
TRUN( Test_Buffer_Read( ));
TRUN( Test_Buffer_ExciseBits( ));
}
#endif // XASH_ENGINE_TESTS

View File

@@ -173,7 +173,17 @@ void MSG_InitMasks( void ); // called once at startup engine
void MSG_ExciseBits( sizebuf_t *sb, int startbit, int bitstoremove );
// Bit-write functions
void MSG_WriteOneBit( sizebuf_t *sb, int nValue );
static inline void MSG_WriteOneBit( sizebuf_t *sb, int nValue )
{
if( !MSG_Overflow( sb, 1 ))
{
if( nValue ) sb->pData[sb->iCurBit>>3] |= BIT( sb->iCurBit & 7 );
else sb->pData[sb->iCurBit>>3] &= ~BIT( sb->iCurBit & 7 );
sb->iCurBit++;
}
}
NO_ASAN void MSG_WriteUBitLong( sizebuf_t *sb, uint curData, int numbits );
void MSG_WriteSBitLong( sizebuf_t *sb, int data, int numbits );
void MSG_WriteBitLong( sizebuf_t *sb, uint data, int numbits, qboolean bSigned );

View File

@@ -379,7 +379,6 @@ static void Netchan_ClearFragbufs( fragbuf_t **ppbuf )
while( buf )
{
n = buf->next;
Mem_Free( buf->frag_message_buf );
Mem_Free( buf );
buf = n;
}
@@ -458,22 +457,21 @@ Netchan_OutOfBand
Sends an out-of-band datagram
================
*/
void Netchan_OutOfBand( int net_socket, netadr_t adr, int length, byte *data )
void Netchan_OutOfBand( int net_socket, netadr_t adr, int len, byte *data )
{
byte send_buf[MAX_PRINT_MSG];
sizebuf_t send;
byte buf[MAX_PRINT_MSG + 4] = { 0xff, 0xff, 0xff, 0xff };
// write the packet header
MSG_Init( &send, "SequencePacket", send_buf, sizeof( send_buf ));
if( CL_IsPlaybackDemo( ))
return;
MSG_WriteLong( &send, NET_HEADER_OUTOFBANDPACKET ); // -1 sequence means out of band
MSG_WriteBytes( &send, data, length );
if( !CL_IsPlaybackDemo( ))
if( len > sizeof( buf ) - 4 )
{
// send the datagram
NET_SendPacket( net_socket, MSG_GetNumBytesWritten( &send ), MSG_GetData( &send ), adr );
Host_Error( "%s: overflow!\n", __func__ );
return;
}
memcpy( &buf[4], data, len );
NET_SendPacket( net_socket, len + 4, buf, adr );
}
/*
@@ -483,16 +481,26 @@ Netchan_OutOfBandPrint
Sends a text message in an out-of-band datagram
================
*/
void Netchan_OutOfBandPrint( int net_socket, netadr_t adr, const char *format, ... )
void Netchan_OutOfBandPrint( int net_socket, netadr_t adr, const char *fmt, ... )
{
char string[MAX_PRINT_MSG];
va_list argptr;
va_list va;
byte buf[MAX_PRINT_MSG + 4] = { 0xff, 0xff, 0xff, 0xff };
int len;
va_start( argptr, format );
Q_vsnprintf( string, sizeof( string ) - 1, format, argptr );
va_end( argptr );
if( CL_IsPlaybackDemo( ))
return;
Netchan_OutOfBand( net_socket, adr, Q_strlen( string ), (byte *)string );
va_start( va, fmt );
len = Q_vsnprintf( &buf[4], sizeof( buf ) - 4, fmt, va );
va_end( va );
if( len < 0 )
{
Host_Error( "%s: snprintf overflow!\n", __func__ );
return;
}
NET_SendPacket( net_socket, len + 4, buf, adr );
}
/*
@@ -505,8 +513,7 @@ static fragbuf_t *Netchan_AllocFragbuf( int fragment_size )
{
fragbuf_t *buf;
buf = (fragbuf_t *)Mem_Calloc( net_mempool, sizeof( fragbuf_t ));
buf->frag_message_buf = (byte *)Mem_Calloc( net_mempool, fragment_size );
buf = (fragbuf_t *)Mem_Calloc( net_mempool, sizeof( fragbuf_t ) + fragment_size );
MSG_Init( &buf->frag_message, "Frag Message", buf->frag_message_buf, fragment_size );
return buf;
@@ -520,7 +527,7 @@ Netchan_AddFragbufToTail
*/
static void Netchan_AddFragbufToTail( fragbufwaiting_t *wait, fragbuf_t *buf )
{
fragbuf_t *p;
fragbuf_t *p;
buf->next = NULL;
wait->fragbufcount++;
@@ -1168,7 +1175,7 @@ qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg )
if( filename[0] != '!' )
{
string temp_filename;
Q_snprintf( temp_filename, sizeof( temp_filename ), "downloaded/%s", filename );
Q_snprintf( temp_filename, sizeof( temp_filename ), DEFAULT_DOWNLOADED_DIRECTORY "%s", filename );
Q_strncpy( filename, temp_filename, sizeof( filename ));
}

View File

@@ -1209,7 +1209,7 @@ static void NET_AddToLagged( netsrc_t sock, packetlag_t *list, packetlag_t *pack
packet->data = pStart;
packet->size = length;
packet->receivedtime = timestamp;
memcpy( &packet->from, from, sizeof( netadr_t ));
packet->from = *from;
}
/*
@@ -1321,7 +1321,7 @@ static qboolean NET_LagPacket( qboolean newdata, netsrc_t sock, netadr_t *from,
// delivery packet from fake lag queue
memcpy( data, pPacket->data, pPacket->size );
memcpy( &net_from, &pPacket->from, sizeof( netadr_t ));
net_from = pPacket->from;
*length = pPacket->size;
if( pPacket->data )
@@ -2282,7 +2282,7 @@ static void HTTP_FreeFile( httpfile_t *file, qboolean error )
file->socket = -1;
Q_snprintf( incname, 256, "downloaded/%s.incomplete", file->path );
Q_snprintf( incname, sizeof( incname ), DEFAULT_DOWNLOADED_DIRECTORY "%s.incomplete", file->path );
if( error )
{
// Switch to next fastdl server if present
@@ -2308,7 +2308,7 @@ static void HTTP_FreeFile( httpfile_t *file, qboolean error )
// Success, rename and process file
char name[256];
Q_snprintf( name, 256, "downloaded/%s", file->path );
Q_snprintf( name, sizeof( name ), DEFAULT_DOWNLOADED_DIRECTORY "%s", file->path );
FS_Rename( incname, name );
if( file->process )
@@ -2527,7 +2527,7 @@ void HTTP_Run( void )
}
Con_Reportf( "HTTP: Starting download %s from %s\n", curfile->path, curfile->server->host );
Q_snprintf( name, sizeof( name ), "downloaded/%s.incomplete", curfile->path );
Q_snprintf( name, sizeof( name ), DEFAULT_DOWNLOADED_DIRECTORY "%s.incomplete", curfile->path );
curfile->file = FS_Open( name, "wb", true );

View File

@@ -184,13 +184,13 @@ typedef struct fragbuf_s
struct fragbuf_s *next; // next buffer in chain
int bufferid; // id of this buffer
sizebuf_t frag_message; // message buffer where raw data is stored
byte *frag_message_buf; // the actual data sits here
qboolean isfile; // is this a file buffer?
qboolean isbuffer; // is this file buffer from memory ( custom decal, etc. ).
qboolean iscompressed; // is compressed file, we should using filename.ztmp
char filename[MAX_OSPATH]; // name of the file to save out on remote host
int foffset; // offset in file from which to read data
int size; // size of data to read at that offset
byte frag_message_buf[]; // the actual data sits here (flexible)
} fragbuf_t;
// Waiting list of fragbuf chains

View File

@@ -186,7 +186,7 @@ hull_t *PM_HullForBsp( physent_t *pe, playermove_t *pmove, float *offset )
Assert( hull != NULL );
// calculate an offset value to center the origin
VectorSubtract( hull->clip_mins, pmove->player_mins[pmove->usehull], offset );
VectorSubtract( hull->clip_mins, host.player_mins[pmove->usehull], offset );
VectorAdd( offset, pe->origin, offset );
return hull;
@@ -203,7 +203,7 @@ static hull_t *PM_HullForStudio( physent_t *pe, playermove_t *pmove, int *numhit
{
vec3_t size;
VectorSubtract( pmove->player_maxs[pmove->usehull], pmove->player_mins[pmove->usehull], size );
VectorSubtract( host.player_maxs[pmove->usehull], host.player_mins[pmove->usehull], size );
VectorScale( size, 0.5f, size );
return Mod_HullForStudio( pe->studiomodel, pe->frame, pe->sequence, pe->angles, pe->origin, size, pe->controller, pe->blending, numhitboxes, NULL );
@@ -379,8 +379,8 @@ pmtrace_t PM_PlayerTraceExt( playermove_t *pmove, vec3_t start, vec3_t end, int
if( pe->solid == SOLID_CUSTOM )
{
VectorCopy( pmove->player_mins[pmove->usehull], mins );
VectorCopy( pmove->player_maxs[pmove->usehull], maxs );
VectorCopy( host.player_mins[pmove->usehull], mins );
VectorCopy( host.player_maxs[pmove->usehull], maxs );
VectorClear( offset );
}
else if( pe->model )
@@ -401,8 +401,8 @@ pmtrace_t PM_PlayerTraceExt( playermove_t *pmove, vec3_t start, vec3_t end, int
}
else
{
VectorSubtract( pe->mins, pmove->player_maxs[pmove->usehull], mins );
VectorSubtract( pe->maxs, pmove->player_mins[pmove->usehull], maxs );
VectorSubtract( pe->mins, host.player_maxs[pmove->usehull], mins );
VectorSubtract( pe->maxs, host.player_mins[pmove->usehull], maxs );
hull = PM_HullForBox( mins, maxs );
VectorCopy( pe->origin, offset );
@@ -410,8 +410,8 @@ pmtrace_t PM_PlayerTraceExt( playermove_t *pmove, vec3_t start, vec3_t end, int
}
else
{
VectorSubtract( pe->mins, pmove->player_maxs[pmove->usehull], mins );
VectorSubtract( pe->maxs, pmove->player_mins[pmove->usehull], maxs );
VectorSubtract( pe->mins, host.player_maxs[pmove->usehull], mins );
VectorSubtract( pe->maxs, host.player_mins[pmove->usehull], maxs );
hull = PM_HullForBox( mins, maxs );
VectorCopy( pe->origin, offset );
@@ -442,7 +442,7 @@ pmtrace_t PM_PlayerTraceExt( playermove_t *pmove, vec3_t start, vec3_t end, int
if( transform_bbox )
{
World_TransformAABB( matrix, pmove->player_mins[pmove->usehull], pmove->player_maxs[pmove->usehull], mins, maxs );
World_TransformAABB( matrix, host.player_mins[pmove->usehull], host.player_maxs[pmove->usehull], mins, maxs );
VectorSubtract( hull->clip_mins, mins, offset ); // calc new local offset
for( j = 0; j < 3; j++ )
@@ -569,8 +569,8 @@ int PM_TestPlayerPosition( playermove_t *pmove, vec3_t pos, pmtrace_t *ptrace, p
if( pe->solid == SOLID_CUSTOM )
{
VectorCopy( pmove->player_mins[pmove->usehull], mins );
VectorCopy( pmove->player_maxs[pmove->usehull], maxs );
VectorCopy( host.player_mins[pmove->usehull], mins );
VectorCopy( host.player_maxs[pmove->usehull], maxs );
VectorClear( offset );
}
else if( pe->model )
@@ -584,8 +584,8 @@ int PM_TestPlayerPosition( playermove_t *pmove, vec3_t pos, pmtrace_t *ptrace, p
}
else
{
VectorSubtract( pe->mins, pmove->player_maxs[pmove->usehull], mins );
VectorSubtract( pe->maxs, pmove->player_mins[pmove->usehull], maxs );
VectorSubtract( pe->mins, host.player_maxs[pmove->usehull], mins );
VectorSubtract( pe->maxs, host.player_mins[pmove->usehull], maxs );
hull = PM_HullForBox( mins, maxs );
VectorCopy( pe->origin, offset );
@@ -611,7 +611,7 @@ int PM_TestPlayerPosition( playermove_t *pmove, vec3_t pos, pmtrace_t *ptrace, p
if( transform_bbox )
{
World_TransformAABB( matrix, pmove->player_mins[pmove->usehull], pmove->player_maxs[pmove->usehull], mins, maxs );
World_TransformAABB( matrix, host.player_mins[pmove->usehull], host.player_maxs[pmove->usehull], mins, maxs );
VectorSubtract( hull->clip_mins, mins, offset ); // calc new local offset
for( j = 0; j < 3; j++ )

View File

@@ -25,8 +25,7 @@ typedef struct did3v2_header_s
uint8_t flags;
uint32_t length; // size of extended header, padding and frames
} did3v2_header_t;
STATIC_ASSERT( sizeof( did3v2_header_t ) == 10,
"invalid did3v2_header_t size" );
STATIC_CHECK_SIZEOF( did3v2_header_t, 10, 10 );
typedef struct did3v2_extended_header_s
{
@@ -34,8 +33,7 @@ typedef struct did3v2_extended_header_s
uint8_t flags_length;
uint8_t flags[1];
} did3v2_extended_header_t;
STATIC_ASSERT( sizeof( did3v2_extended_header_t ) == 6,
"invalid did3v2_extended_header_t size" );
STATIC_CHECK_SIZEOF( did3v2_extended_header_t, 6, 6 );
typedef struct did3v2_frame_s
{
@@ -43,8 +41,7 @@ typedef struct did3v2_frame_s
uint32_t length;
uint8_t flags[2];
} did3v2_frame_t;
STATIC_ASSERT( sizeof( did3v2_frame_t ) == 10,
"invalid did3v2_frame_t size" );
STATIC_CHECK_SIZEOF( did3v2_frame_t, 10, 10 );
#pragma pack( pop )
typedef enum did3v2_header_flags_e

View File

@@ -90,8 +90,8 @@ static byte *Sound_Copy( size_t size )
{
byte *out;
out = Mem_Malloc( host.soundpool, size );
memcpy( out, sound.tempbuffer, size );
out = Mem_Realloc( host.soundpool, sound.tempbuffer, size );
sound.tempbuffer = NULL;
return out;
}
@@ -133,346 +133,275 @@ uint GAME_EXPORT Sound_GetApproxWavePlayLen( const char *filepath )
return msecs;
}
static qboolean Sound_ConvertNoResample( wavdata_t *sc, int inwidth, int outwidth, int outcount )
#define SOUND_FORMATCONVERT_BOILERPLATE( resamplemacro ) \
if( inwidth == 1 ) \
{ \
const int8_t *data = (const int8_t *)sc->buffer; \
if( outwidth == 1 ) \
{ \
int8_t *outdata = (int8_t *)sound.tempbuffer; \
resamplemacro( 1 ) \
} \
else if( outwidth == 2 ) \
{ \
int16_t *outdata = (int16_t *)sound.tempbuffer; \
resamplemacro( 256 ) \
} \
else \
return false; \
} \
else if( inwidth == 2 ) \
{ \
const int16_t *data = (const int16_t *)sc->buffer; \
if( outwidth == 1 ) \
{ \
int8_t *outdata = (int8_t *)sound.tempbuffer; \
resamplemacro( 1 / 256.0 ) \
} \
else if( outwidth == 2 ) \
{ \
int16_t *outdata = (int16_t *)sound.tempbuffer; \
resamplemacro( 1 ) \
} \
else \
return false; \
} \
else \
return false; \
#define SOUND_CONVERTNORESAMPLE_BOILERPLATE( multiplier ) \
if( inchannels == 1 ) \
{ \
if( outchannels == 1 ) \
{ \
for( i = 0; i < outcount * outchannels; i++ ) \
outdata[i] = data[i] * ( multiplier ); \
} \
else if( outchannels == 2 ) \
{ \
for( i = 0; i < outcount; i++ ) \
{ \
outdata[i * 2 + 0] = data[i] * ( multiplier ); \
outdata[i * 2 + 1] = data[i] * ( multiplier ); \
} \
} \
else \
return false; \
} \
else if( inchannels == 2 ) \
{ \
if( outchannels == 1 ) \
{ \
for( i = 0; i < outcount; i++ ) \
outdata[i] = ( data[i * 2 + 0] + data[i * 2 + 1] ) * ( multiplier ) / 2; \
} \
else if( outchannels == 2 ) \
{ \
for( i = 0; i < outcount * outchannels; i++ ) \
outdata[i] = data[i] * ( multiplier ); \
} \
else \
return false; \
} \
else \
return false; \
#define SOUND_CONVERTDOWNSAMPLE_BOILERPLATE( multiplier ) \
if( inchannels == 1 ) \
{ \
if( outchannels == 1 ) \
{ \
for( i = 0; i < outcount; i++ ) \
{ \
double j = stepscale * i; \
outdata[i] = data[(int)j] * ( multiplier ); \
} \
} \
else if( outchannels == 2 ) \
{ \
for( i = 0; i < outcount; i++ ) \
{ \
double j = stepscale * i;\
outdata[i * 2 + 0] = data[(int)j] * ( multiplier ); \
outdata[i * 2 + 1] = data[(int)j] * ( multiplier ); \
} \
} \
else \
return false; \
} \
else if( inchannels == 2 ) \
{ \
if( outchannels == 1 ) \
{ \
for( i = 0; i < outcount; i++ ) \
{ \
double j = stepscale * i; \
outdata[i] = ( data[((int)j) * 2 + 0] + data[((int)j) * 2 + 1] ) * ( multiplier ) / 2; \
} \
} \
else if( outchannels == 2 ) \
{ \
for( i = 0; i < outcount; i++ ) \
{ \
double j = stepscale * i; \
outdata[i * 2 + 0] = data[((int)j) * 2 + 0] * ( multiplier ); \
outdata[i * 2 + 1] = data[((int)j) * 2 + 1] * ( multiplier ); \
} \
} \
else \
return false; \
} \
else \
return false; \
#define SOUND_CONVERTUPSAMPLE_BOILERPLATE( multiplier ) \
if( inchannels == 1 ) \
{ \
if( outchannels == 1 ) \
{ \
for( i = 0; i < outcount; i++ ) \
{ \
double j = stepscale * i; \
outdata[i] = data[(int)j] * ( multiplier ); \
if( j != (int)j && j < incount ) \
{ \
double frac = ( j - (int)j ) * ( multiplier ); \
outdata[i] += (data[(int)j+1] - data[(int)j]) * frac; \
} \
} \
} \
else if( outchannels == 2 ) \
{ \
for( i = 0; i < outcount; i++ ) \
{ \
double j = stepscale * i; \
outdata[i * 2 + 0] = data[(int)j] * ( multiplier ); \
if( j != (int)j && j < incount ) \
{ \
double frac = ( j - (int)j ) * ( multiplier ); \
outdata[i * 2 + 0] += (data[(int)j+1] - data[(int)j]) * frac; \
} \
outdata[i * 2 + 1] = outdata[i * 2 + 0]; \
} \
} \
else \
return false; \
} \
else if( inchannels == 2 ) \
{ \
if( outchannels == 1 ) \
{ \
for( i = 0; i < outcount; i++ ) \
{ \
double j = stepscale * i; \
outdata[i] = ( data[((int)j) * 2 + 0] + data[((int)j) * 2 + 1] ) * ( multiplier ) / 2; \
if( j != (int)j && j < incount ) \
{ \
double frac = ( j - (int)j ) * ( multiplier ) / 2; \
outdata[i] += (data[((int)j + 1 ) * 2 + 0] - data[((int)j) * 2 + 0]) * frac; \
outdata[i] += (data[((int)j + 1 ) * 2 + 1] - data[((int)j) * 2 + 1]) * frac; \
} \
} \
} \
else if( outchannels == 2 ) \
{ \
for( i = 0; i < outcount; i++ ) \
{ \
double j = stepscale * i; \
outdata[i*2+0] = data[((int)j)*2+0] * ( multiplier ); \
outdata[i*2+1] = data[((int)j)*2+1] * ( multiplier ); \
if( j != (int)j && j < incount ) \
{ \
double frac = ( j - (int)j ) * ( multiplier ); \
outdata[i*2+0] += (data[((int)j+1)*2+0] - data[((int)j)*2+0]) * frac; \
outdata[i*2+1] += (data[((int)j+1)*2+1] - data[((int)j)*2+1]) * frac; \
} \
} \
} \
else \
return false; \
} \
else \
return false; \
static qboolean Sound_ConvertNoResample( wavdata_t *sc, int inwidth, int inchannels, int outwidth, int outchannels, int outcount )
{
size_t i;
if( inwidth == 1 && outwidth == 2 ) // S8 to S16
{
for( i = 0; i < outcount * sc->channels; i++ )
((int16_t*)sound.tempbuffer)[i] = ((int8_t *)sc->buffer)[i] * 256;
return true;
}
// I could write a generic case here but I also want to make it easier for compiler
// to unroll these for-loops
if( inwidth == 2 && outwidth == 1 ) // S16 to S8
{
for( i = 0; i < outcount * sc->channels; i++ )
((int8_t*)sound.tempbuffer)[i] = ((int16_t *)sc->buffer)[i] / 256;
return true;
}
SOUND_FORMATCONVERT_BOILERPLATE( SOUND_CONVERTNORESAMPLE_BOILERPLATE )
return false;
return true;
}
static qboolean Sound_ConvertDownsample( wavdata_t *sc, int inwidth, int outwidth, int outcount, double stepscale )
static qboolean Sound_ConvertDownsample( wavdata_t *sc, int inwidth, int inchannels, int outwidth, int outchannels, int outcount, double stepscale )
{
size_t i;
double j;
if( inwidth == 1 && outwidth == 1 )
{
int8_t *data = (int8_t *)sc->buffer;
SOUND_FORMATCONVERT_BOILERPLATE( SOUND_CONVERTDOWNSAMPLE_BOILERPLATE )
if( outwidth == 1 )
{
int8_t *outdata = (int8_t *)sound.tempbuffer;
if( sc->channels == 2 )
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i*2+0] = data[((int)j)*2+0];
outdata[i*2+1] = data[((int)j)*2+1];
}
}
else
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i] = data[(int)j];
}
}
return true;
}
if( outwidth == 2 )
{
int16_t *outdata = (int16_t *)sound.tempbuffer;
if( sc->channels == 2 )
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i*2+0] = data[((int)j)*2+0] * 256;
outdata[i*2+1] = data[((int)j)*2+1] * 256;
}
}
else
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i] = data[(int)j] * 256;
}
}
return true;
}
}
if( inwidth == 2 )
{
int16_t *data = (int16_t *)sc->buffer;
if( outwidth == 1 )
{
int8_t *outdata = (int8_t *)sound.tempbuffer;
if( sc->channels == 2 )
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i*2+0] = data[((int)j)*2+0] / 256;
outdata[i*2+1] = data[((int)j)*2+1] / 256;
}
}
else
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i] = data[(int)j] / 256;
}
}
return true;
}
if( outwidth == 2 )
{
int16_t *outdata = (int16_t *)sound.tempbuffer;
if( sc->channels == 2 )
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i*2+0] = data[((int)j)*2+0];
outdata[i*2+1] = data[((int)j)*2+1];
}
}
else
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i] = data[(int)j];
}
}
return true;
}
}
return false;
return true;
}
static qboolean Sound_ConvertUpsample( wavdata_t *sc, int inwidth, int outwidth, int outcount, int incount, double stepscale )
static qboolean Sound_ConvertUpsample( wavdata_t *sc, int inwidth, int inchannels, int incount, int outwidth, int outchannels, int outcount, double stepscale )
{
size_t i;
double j;
double frac;
incount--; // to not go past last sample while interpolating
if( inwidth == 1 )
{
int8_t *data = (int8_t *)sc->buffer;
SOUND_FORMATCONVERT_BOILERPLATE( SOUND_CONVERTUPSAMPLE_BOILERPLATE )
if( outwidth == 1 )
{
int8_t *outdata = (int8_t *)sound.tempbuffer;
if( sc->channels == 2 )
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i*2+0] = data[((int)j)*2+0];
outdata[i*2+1] = data[((int)j)*2+1];
if( j != (int)j && j < incount )
{
frac = j - (int)j;
outdata[i*2+0] += (data[((int)j+1)*2+0] - data[((int)j)*2+0]) * frac;
outdata[i*2+1] += (data[((int)j+1)*2+1] - data[((int)j)*2+1]) * frac;
}
}
}
else
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i] = data[(int)j];
if( j != (int)j && j < incount )
{
frac = j - (int)j;
outdata[i] += (data[(int)j+1] - data[(int)j]) * frac;
}
}
}
return true;
}
if( outwidth == 2 )
{
int16_t *outdata = (int16_t *)sound.tempbuffer;
if( sc->channels == 2 )
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i*2+0] = data[((int)j)*2+0] * 256;
outdata[i*2+1] = data[((int)j)*2+1] * 256;
if( j != (int)j && j < incount )
{
frac = ( j - (int)j ) * 256;
outdata[i*2+0] += (data[((int)j+1)*2+0] - data[((int)j)*2+0]) * frac;
outdata[i*2+1] += (data[((int)j+1)*2+1] - data[((int)j)*2+1]) * frac;
}
}
}
else
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i] = data[(int)j] * 256;
if( j != (int)j && j < incount )
{
frac = ( j - (int)j ) * 256;
outdata[i] += (data[(int)j+1] - data[(int)j]) * frac;
}
}
}
return true;
}
}
if( inwidth == 2 )
{
int16_t *data = (int16_t *)sc->buffer;
if( outwidth == 1 )
{
int8_t *outdata = (int8_t *)sound.tempbuffer;
if( sc->channels == 2 )
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i*2+0] = data[((int)j)*2+0] / 256;
outdata[i*2+1] = data[((int)j)*2+1] / 256;
if( j != (int)j && j < incount )
{
frac = ( j - (int)j ) / 256;
outdata[i*2+0] += (data[((int)j+1)*2+0] - data[((int)j)*2+0]) * frac;
outdata[i*2+1] += (data[((int)j+1)*2+1] - data[((int)j)*2+1]) * frac;
}
}
}
else
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i] = data[(int)j] / 256;
if( j != (int)j && j < incount )
{
frac = ( j - (int)j ) / 256;
outdata[i] += (data[(int)j+1] - data[(int)j]) * frac;
}
}
}
return true;
}
if( outwidth == 2 )
{
int16_t *outdata = (int16_t *)sound.tempbuffer;
if( sc->channels == 2 )
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i*2+0] = data[((int)j)*2+0];
outdata[i*2+1] = data[((int)j)*2+1];
if( j != (int)j && j < incount )
{
frac = j - (int)j;
outdata[i*2+0] += (data[((int)j+1)*2+0] - data[((int)j)*2+0]) * frac;
outdata[i*2+1] += (data[((int)j+1)*2+1] - data[((int)j)*2+1]) * frac;
}
}
}
else
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i] = data[(int)j];
if( j != (int)j && j < incount )
{
frac = j - (int)j;
outdata[i] += (data[(int)j+1] - data[(int)j]) * frac;
}
}
}
return true;
}
}
return false;
return true;
}
#undef SOUND_FORMATCONVERT_BOILERPLATE
#undef SOUND_CONVERTNORESAMPLE_BOILERPLATE
#undef SOUND_CONVERTDOWNSAMPLE_BOILERPLATE
#undef SOUND_CONVERTUPSAMPLE_BOILERPLATE
/*
================
Sound_ResampleInternal
We need convert sound to signed even if nothing to resample
================
*/
static qboolean Sound_ResampleInternal( wavdata_t *sc, int inrate, int inwidth, int outrate, int outwidth )
static qboolean Sound_ResampleInternal( wavdata_t *sc, int outrate, int outwidth, int outchannels )
{
const size_t oldsize = sc->size;
const int inrate = sc->rate;
const int inwidth = sc->width;
const int inchannels = sc->channels;
const int incount = sc->samples;
qboolean handled = false;
double stepscale;
double t1, t2;
int outcount, incount = sc->samples;
int outcount;
if( inrate == outrate && inwidth == outwidth )
if( inrate == outrate && inwidth == outwidth && inchannels == outchannels )
return false;
t1 = Sys_DoubleTime();
stepscale = (double)inrate / outrate; // this is usually 0.5, 1, or 2
outcount = sc->samples / stepscale;
sc->size = outcount * outwidth * sc->channels;
sc->size = outcount * outwidth * outchannels;
sc->channels = outchannels;
sc->samples = outcount;
if( FBitSet( sc->flags, SOUND_LOOPED ))
sc->loopStart = sc->loopStart / stepscale;
#if 0 && XASH_SDL // slow but somewhat accurate
#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, sc->channels, inrate, outfmt, sc->channels, outrate ) > 0 && cvt.needed )
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;
@@ -493,23 +422,23 @@ static qboolean Sound_ResampleInternal( wavdata_t *sc, int inrate, int inwidth,
sound.tempbuffer = (byte *)Mem_Realloc( host.soundpool, sound.tempbuffer, sc->size );
if( inrate == outrate ) // no resampling, just copy data
handled = Sound_ConvertNoResample( sc, inwidth, outwidth, outcount );
handled = Sound_ConvertNoResample( sc, inwidth, inchannels, outwidth, outchannels, outcount );
else if( inrate > outrate ) // fast case, usually downsample but is also ok for upsampling
handled = Sound_ConvertDownsample( sc, inwidth, outwidth, outcount, stepscale );
handled = Sound_ConvertDownsample( sc, inwidth, inchannels, outwidth, outchannels, outcount, stepscale );
else // upsample case, w/ interpolation
handled = Sound_ConvertUpsample( sc, inwidth, outwidth, outcount, incount, stepscale );
handled = Sound_ConvertUpsample( sc, inwidth, inchannels, incount, outwidth, outchannels, outcount, stepscale );
t2 = Sys_DoubleTime();
if( handled )
{
if( t2 - t1 > 0.01f ) // critical, report to mod developer
Con_Printf( S_WARN "%s: from [%d bit %d Hz] to [%d bit %d Hz] (took %.3fs)\n", __func__, inwidth * 8, inrate, outwidth * 8, outrate, t2 - t1 );
Con_Printf( S_WARN "%s: from [%d bit %d Hz %dch] to [%d bit %d Hz %dch] (took %.3fs)\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels, t2 - t1 );
else
Con_Reportf( "%s: from [%d bit %d Hz] to [%d bit %d Hz] (took %.3fs)\n", __func__, inwidth * 8, inrate, outwidth * 8, outrate, t2 - t1 );
Con_Reportf( "%s: from [%d bit %d Hz %dch] to [%d bit %d Hz %dch] (took %.3fs)\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels, t2 - t1 );
}
else
Con_Printf( S_ERROR "%s: unsupported from [%d bit %d Hz] to [%d bit %d Hz]\n", __func__, inwidth * 8, inrate, outwidth * 8, outrate );
Con_Printf( S_ERROR "%s: unsupported from [%d bit %d Hz %dch] to [%d bit %d Hz %dch]\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels );
sc->rate = outrate;
sc->width = outwidth;
@@ -517,23 +446,23 @@ static qboolean Sound_ResampleInternal( wavdata_t *sc, int inrate, int inwidth,
return handled;
}
qboolean Sound_Process( wavdata_t **wav, int rate, int width, uint flags )
qboolean Sound_Process( wavdata_t **wav, int rate, int width, int channels, uint flags )
{
wavdata_t *snd = *wav;
qboolean result = true;
// check for buffers
if( !snd || !snd->buffer )
if( unlikely( !snd || !snd->buffer ))
return false;
if( FBitSet( flags, SOUND_RESAMPLE ) && ( width > 0 || rate > 0 ))
if( likely( FBitSet( flags, SOUND_RESAMPLE ) && ( width > 0 || rate > 0 || channels > 0 )))
{
result = Sound_ResampleInternal( snd, snd->rate, snd->width, rate, width );
result = Sound_ResampleInternal( snd, rate, width, channels );
if( result )
{
Mem_Free( snd->buffer ); // free original image buffer
snd->buffer = Sound_Copy( snd->size ); // unzone buffer (don't touch sound.tempbuffer)
snd->buffer = Sound_Copy( snd->size ); // unzone buffer
}
}

View File

@@ -241,14 +241,14 @@ qboolean Sound_LoadWAV( const char *name, const byte *buffer, fs_offset_t filesi
// get cue chunk
FindChunk( name, "cue " );
if( iff_dataPtr )
if( iff_dataPtr && iff_end - iff_dataPtr >= 36 )
{
iff_dataPtr += 32;
sound.loopstart = GetLittleLong();
SetBits( sound.flags, SOUND_LOOPED );
FindNextChunk( name, "LIST" ); // if the next chunk is a LIST chunk, look for a cue length marker
if( iff_dataPtr )
if( iff_dataPtr && iff_end - iff_dataPtr >= 32 )
{
if( IsFourCC( iff_dataPtr + 28, "mark" ))
{

View File

@@ -199,20 +199,20 @@ static void Sys_WriteEscapeSequenceForColorcode( int fd, int c )
{
static const char *q3ToAnsi[ 8 ] =
{
"\033[30m", // COLOR_BLACK
"\033[31m", // COLOR_RED
"\033[32m", // COLOR_GREEN
"\033[33m", // COLOR_YELLOW
"\033[34m", // COLOR_BLUE
"\033[36m", // COLOR_CYAN
"\033[35m", // COLOR_MAGENTA
"\033[1;30m", // COLOR_BLACK
"\033[1;31m", // COLOR_RED
"\033[1;32m", // COLOR_GREEN
"\033[1;33m", // COLOR_YELLOW
"\033[1;34m", // COLOR_BLUE
"\033[1;36m", // COLOR_CYAN
"\033[1;35m", // COLOR_MAGENTA
"\033[0m", // COLOR_WHITE
};
const char *esc = q3ToAnsi[c];
if( c == 7 )
write( fd, esc, 4 );
else write( fd, esc, 5 );
else write( fd, esc, 7 );
}
#else
static void Sys_WriteEscapeSequenceForColorcode( int fd, int c ) {}
@@ -297,6 +297,7 @@ void Sys_PrintLog( const char *pMsg )
const struct tm *crt_tm;
char logtime[32] = "";
static char lastchar;
size_t len;
time( &crt_time );
crt_tm = localtime( &crt_time );
@@ -307,10 +308,12 @@ void Sys_PrintLog( const char *pMsg )
// spew to stdout
Sys_PrintStdout( logtime, pMsg );
len = Q_strlen( pMsg );
if( !s_ld.logfile )
{
// save last char to detect when line was not ended
lastchar = pMsg[Q_strlen( pMsg ) - 1];
lastchar = len > 0 ? pMsg[len - 1] : 0;
return;
}
@@ -318,7 +321,7 @@ void Sys_PrintLog( const char *pMsg )
strftime( logtime, sizeof( logtime ), "[%Y:%m:%d|%H:%M:%S] ", crt_tm ); //full time
// save last char to detect when line was not ended
lastchar = pMsg[Q_strlen( pMsg ) - 1];
lastchar = len > 0 ? pMsg[len - 1] : 0;
Sys_PrintLogfile( s_ld.logfileno, logtime, pMsg, false );
Sys_FlushLogfile();
@@ -331,6 +334,21 @@ CONSOLE PRINT
=============================================================================
*/
static void Con_Printfv( qboolean debug, const char *szFmt, va_list args )
{
static char buffer[MAX_PRINT_MSG];
qboolean add_newline;
add_newline = Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args ) < 0;
if( debug && !Q_strcmp( buffer, "0\n" ))
return; // hlrally spam
Sys_Print( buffer );
if( add_newline )
Sys_Print( "\n" );
}
/*
=============
Con_Printf
@@ -339,20 +357,14 @@ Con_Printf
*/
void GAME_EXPORT Con_Printf( const char *szFmt, ... )
{
static char buffer[MAX_PRINT_MSG];
va_list args;
qboolean add_newline;
va_list args;
if( !host.allow_console )
return;
va_start( args, szFmt );
add_newline = Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args ) < 0;
Con_Printfv( false, szFmt, args );
va_end( args );
Sys_Print( buffer );
if( add_newline )
Sys_Print( "\n" );
}
/*
@@ -363,23 +375,14 @@ Con_DPrintf
*/
void GAME_EXPORT Con_DPrintf( const char *szFmt, ... )
{
static char buffer[MAX_PRINT_MSG];
va_list args;
qboolean add_newline;
va_list args;
if( host_developer.value < DEV_NORMAL )
return;
va_start( args, szFmt );
add_newline = Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args ) < 0;
Con_Printfv( true, szFmt, args );
va_end( args );
if( buffer[0] == '0' && buffer[1] == '\n' && buffer[2] == '\0' )
return; // hlrally spam
Sys_Print( buffer );
if( add_newline )
Sys_Print( "\n" );
}
/*
@@ -390,20 +393,14 @@ Con_Reportf
*/
void Con_Reportf( const char *szFmt, ... )
{
static char buffer[MAX_PRINT_MSG];
va_list args;
qboolean add_newline;
va_list args;
if( host_developer.value < DEV_EXTENDED )
return;
va_start( args, szFmt );
add_newline = Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args ) < 0;
Con_Printfv( false, szFmt, args );
va_end( args );
Sys_Print( buffer );
if( add_newline )
Sys_Print( "\n" );
}

View File

@@ -72,15 +72,28 @@ Sys_DebugBreak
*/
void Sys_DebugBreak( void )
{
#if XASH_SDL
int was_grabbed = host.hWnd != NULL && SDL_GetWindowGrab( host.hWnd );
#endif
if( !Sys_DebuggerPresent( ))
return;
#if XASH_SDL
if( was_grabbed ) // so annoying...
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
#endif // XASH_SDL
#if _MSC_VER
if( Sys_DebuggerPresent( ))
__debugbreak();
__debugbreak();
#else // !_MSC_VER
if( Sys_DebuggerPresent( ))
{
INLINE_RAISE( SIGINT );
INLINE_NANOSLEEP1(); // sometimes signal comes with delay, let it interrupt nanosleep
}
INLINE_RAISE( SIGINT );
INLINE_NANOSLEEP1(); // sometimes signal comes with delay, let it interrupt nanosleep
#endif // !_MSC_VER
#if XASH_SDL
if( was_grabbed )
SDL_SetWindowGrab( host.hWnd, SDL_TRUE );
#endif
}

View File

@@ -78,20 +78,6 @@ void Sys_InitLog( void );
void Sys_PrintLog( const char *pMsg );
int Sys_LogFileNo( void );
//
// con_win.c
//
#if XASH_WIN32
void Wcon_InitConsoleCommands( void );
void Wcon_ShowConsole( qboolean show );
void Wcon_CreateConsole( void );
void Wcon_DestroyConsole( void );
void Wcon_DisableInput( void );
char *Wcon_Input( void );
void Wcon_WinPrint( const char *pMsg );
void Wcon_SetStatus( const char *pStatus );
#endif
// text messages
#define Msg Con_Printf

View File

@@ -40,6 +40,7 @@ void Test_RunVOX( void );
void Test_RunIPFilter( void );
void Test_RunGamma( void );
void Test_RunDelta( void );
void Test_RunBuffer( void );
#define TEST_LIST_0 \
Test_RunLibCommon(); \
@@ -47,6 +48,7 @@ void Test_RunDelta( void );
Test_RunCmd(); \
Test_RunCvar(); \
Test_RunIPFilter(); \
Test_RunBuffer(); \
Test_RunDelta();
#define TEST_LIST_0_CLIENT \

View File

@@ -241,6 +241,21 @@ void _Mem_Free( void *data, const char *filename, int fileline )
Mem_FreeBlock((memheader_t *)((byte *)data - sizeof( memheader_t )), filename, fileline );
}
static void Mem_MigratePool( poolhandle_t newpoolptr, memheader_t *mem, const char *filename, int fileline )
{
mempool_t *oldpool = Mem_FindPool( mem->poolptr );
mempool_t *newpool = Mem_FindPool( newpoolptr );
// dettach allocation from one pool and reattach it to new pool
// might be made into public function at some point
Mem_PoolUnlinkAlloc( oldpool, mem );
Mem_PoolSubtract( oldpool, mem->size );
Mem_PoolLinkAlloc( newpool, mem );
Mem_PoolAdd( newpool, mem->size );
}
void *_Mem_Realloc( poolhandle_t poolptr, void *data, size_t size, qboolean clear, const char *filename, int fileline )
{
memheader_t *mem;
@@ -262,15 +277,12 @@ void *_Mem_Realloc( poolhandle_t poolptr, void *data, size_t size, qboolean clea
mem = (memheader_t *)((byte *)data - sizeof( memheader_t ));
if( !Mem_CheckAllocHeader( "Mem_Realloc", mem, filename, fileline ))
if( !Mem_CheckAllocHeader( __func__, mem, filename, fileline ))
return NULL;
if( unlikely( mem->poolptr != poolptr ))
{
Sys_Error( "%s: pool migration is not allowed (alloc at %s:%i, realloc at %s:%i)\n",
__func__, Mem_CheckFilename( mem->filename ), mem->fileline, filename, fileline );
return NULL;
}
// migrate pool if requested, even if no reallocation needed
if( mem->poolptr != poolptr )
Mem_MigratePool( poolptr, mem, filename, fileline );
oldsize = mem->size;
if( size == oldsize )
@@ -439,7 +451,7 @@ void _Mem_Check( const char *filename, int fileline )
for( i = 0, pool = poolchain; i < poolcount; i++, pool++ )
for( mem = pool->chain; mem; mem = mem->next )
Mem_CheckAllocHeader( "Mem_CheckSentinels", mem, filename, fileline );
Mem_CheckAllocHeader( __func__, mem, filename, fileline );
}
void Mem_PrintStats( void )

View File

@@ -53,6 +53,10 @@ typedef struct resourceinfo_s
#define RES_ALWAYS (1<<5) // Download always even if available on client
#define RES_CHECKFILE (1<<7) // Check file on client
// this archive was already mounted after rescan
// only makes sense for archives and on client
#define RES_EXTRA_ARCHIVE_CHECKED BIT( 0 )
typedef struct resource_s
{
char szFileName[64]; // File name to download/precache.
@@ -67,6 +71,7 @@ typedef struct resource_s
// if it's a custom resource.
unsigned char rguc_reserved[32]; // For future expansion
unsigned short ucExtraFlags; // fwgs extension, doesn't change the size of struct because of compiler padding
struct resource_s *pNext; // Next in chain.
struct resource_s *pPrev;
} resource_t;
@@ -90,4 +95,7 @@ typedef struct customization_s
#define FCUST_WIPEDATA ( 1<<1 )
#define FCUST_IGNOREINIT ( 1<<2 )
STATIC_CHECK_SIZEOF( customization_t, 164, 192 );
STATIC_CHECK_SIZEOF( resource_t, 136, 144 );
#endif // CUSTOM_H

View File

@@ -218,6 +218,10 @@ typedef struct ui_extendedfuncs_s {
int (*pfnCompareAdr)( const void *a, const void *b ); // netadr_t
void *(*pfnGetNativeObject)( const char *name );
struct net_api_s *pNetAPI;
// new mods info
gameinfo2_t *(*pfnGetGameInfo)( int gi_version ); // might return NULL if gi_version is unsupported
gameinfo2_t *(*pfnGetModInfo)( int gi_version, int mod_index ); // continiously call it until it returns null
} ui_extendedfuncs_t;
// deprecated export from old engine

View File

@@ -71,6 +71,11 @@ void Android_Shutdown( void );
#if XASH_WIN32
void Wcon_CreateConsole( qboolean con_showalways );
void Wcon_DestroyConsole( void );
void Wcon_InitConsoleCommands( void );
void Wcon_ShowConsole( qboolean show );
void Wcon_DisableInput( void );
char *Wcon_Input( void );
void Wcon_WinPrint( const char *pMsg );
#endif
#if XASH_NSWITCH

View File

@@ -46,6 +46,7 @@ extern void *__aeabi_idivmod;
extern void *__aeabi_uidivmod;
extern void *__aeabi_d2ulz;
extern void *__aeabi_ul2d;
extern void *__aeabi_ul2f;
static const vrtld_export_t aux_exports[] =
{
@@ -55,6 +56,7 @@ static const vrtld_export_t aux_exports[] =
VRTLD_EXPORT_SYMBOL( __aeabi_uidivmod ),
VRTLD_EXPORT_SYMBOL( __aeabi_uidiv ),
VRTLD_EXPORT_SYMBOL( __aeabi_ul2d ),
VRTLD_EXPORT_SYMBOL( __aeabi_ul2f ),
VRTLD_EXPORT_SYMBOL( _impure_ptr ),
VRTLD_EXPORT_SYMBOL( ctime ),
VRTLD_EXPORT_SYMBOL( vasprintf ),

View File

@@ -350,7 +350,7 @@ void Platform_SetCursorType( VGUI_DefaultCursor type )
}
// never disable cursor in touch emulation mode
if( !visible && touch_emulate.value )
if( !visible && Touch_Emulated( ))
return;
host.mouse_visible = visible;

View File

@@ -47,10 +47,13 @@ qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *
if( sw.renderer )
{
unsigned int format = SDL_GetWindowPixelFormat( host.hWnd );
SDL_RenderSetLogicalSize(sw.renderer, refState.width, refState.height);
SDL_RenderSetLogicalSize( sw.renderer, refState.width, refState.height );
if( sw.tex )
{
SDL_DestroyTexture( sw.tex );
sw.tex = NULL;
}
// guess
if( format == SDL_PIXELFORMAT_UNKNOWN )
@@ -63,20 +66,16 @@ qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *
// we can only copy fast 16 or 32 bits
// SDL_Renderer does not allow zero-copy, so 24 bits will be ineffective
if( !( SDL_BYTESPERPIXEL(format) == 2 || SDL_BYTESPERPIXEL(format) == 4 ) )
if( SDL_BYTESPERPIXEL( format ) != 2 && SDL_BYTESPERPIXEL( format ) != 4 )
format = SDL_PIXELFORMAT_RGBA8888;
sw.tex = SDL_CreateTexture(sw.renderer, format,
SDL_TEXTUREACCESS_STREAMING,
width, height);
sw.tex = SDL_CreateTexture( sw.renderer, format, SDL_TEXTUREACCESS_STREAMING, width, height );
// fallback
if( !sw.tex && format != SDL_PIXELFORMAT_RGBA8888 )
{
format = SDL_PIXELFORMAT_RGBA8888;
sw.tex = SDL_CreateTexture(sw.renderer, format,
SDL_TEXTUREACCESS_STREAMING,
width, height);
sw.tex = SDL_CreateTexture( sw.renderer, format, SDL_TEXTUREACCESS_STREAMING, width, height );
}
if( !sw.tex )
@@ -89,25 +88,26 @@ qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *
void *pixels;
int pitch;
if( !SDL_LockTexture(sw.tex, NULL, &pixels, &pitch ) )
if( !SDL_LockTexture( sw.tex, NULL, &pixels, &pitch ))
{
int bits;
uint amask;
// lock successfull, release
SDL_UnlockTexture(sw.tex);
SDL_UnlockTexture( sw.tex );
// enough for building blitter tables
SDL_PixelFormatEnumToMasks( format, &bits, r, g, b, &amask );
*bpp = SDL_BYTESPERPIXEL(format);
*bpp = SDL_BYTESPERPIXEL( format );
*stride = pitch / *bpp;
return true;
}
// fallback to surf
SDL_DestroyTexture(sw.tex);
SDL_DestroyTexture( sw.tex );
sw.tex = NULL;
SDL_DestroyRenderer(sw.renderer);
SDL_DestroyRenderer( sw.renderer );
sw.renderer = NULL;
}
}
@@ -126,7 +126,7 @@ qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *
// 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 enable sw_glblit");
Sys_Warn( "failed to initialize software output, try running with -glblit flag" );
return false;
}
@@ -141,9 +141,10 @@ qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *
{
sw.surf = SDL_CreateRGBSurfaceWithFormat( 0, width, height, 16, SDL_PIXELFORMAT_RGB565 );
if( !sw.surf )
Sys_Error(SDL_GetError());
Sys_Error( "%s: %s", __func__, SDL_GetError( ));
}
#endif
return true;
}
// we can't create ref_soft buffer
@@ -640,9 +641,17 @@ void VID_RestoreScreenResolution( void )
switch((window_mode_t)vid_fullscreen.value )
{
case WINDOW_MODE_WINDOWED:
// TODO: this line is from very old SDL video backend
// figure out why we need it, because in windowed mode we
// always have borders
SDL_SetWindowBordered( host.hWnd, SDL_TRUE );
break;
default:
case WINDOW_MODE_BORDERLESS:
// in borderless fullscreen we don't change screen resolution, so no-op
break;
case WINDOW_MODE_FULLSCREEN:
// TODO: we might want to not minimize window if current desktop mode
// and window mode are the same
SDL_MinimizeWindow( host.hWnd );
SDL_SetWindowFullscreen( host.hWnd, 0 );
break;
@@ -1006,9 +1015,10 @@ qboolean R_Init_Video( const int type )
{
string safe;
qboolean retval;
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
SDL_DisplayMode displayMode;
SDL_GetCurrentDisplayMode(0, &displayMode);
SDL_GetCurrentDisplayMode( 0, &displayMode );
refState.desktopBitsPixel = SDL_BITSPERPIXEL( displayMode.format );
#else
refState.desktopBitsPixel = 16;
@@ -1086,7 +1096,7 @@ rserr_t R_ChangeDisplaySettings( int width, int height, window_mode_t window_mod
if( SDL_GetCurrentDisplayMode( 0, &displayMode ) < 0 )
{
Con_Printf( S_ERROR "SDL_GetCurrentDisplayMode: %s", SDL_GetError( ));
Con_Printf( S_ERROR "SDL_GetCurrentDisplayMode: %s\n", SDL_GetError( ));
return rserr_invalid_mode;
}
@@ -1180,14 +1190,8 @@ qboolean VID_SetMode( void )
}
#endif
if( !FBitSet( vid_fullscreen.flags, FCVAR_CHANGED ))
Cvar_DirectSet( &vid_fullscreen, DEFAULT_FULLSCREEN );
else
ClearBits( vid_fullscreen.flags, FCVAR_CHANGED );
SetBits( gl_vsync.flags, FCVAR_CHANGED );
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 )
{
@@ -1236,10 +1240,6 @@ void R_Free_Video( void )
R_FreeVideoModes();
ref.dllFuncs.GL_ClearExtensions();
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
SDL_VideoQuit();
#endif
}
#endif // XASH_DEDICATED

View File

@@ -80,10 +80,11 @@ GNU General Public License for more details.
#define MODEL_CLIENT BIT( 30 ) // client sprite
// goes into world.flags
#define FWORLD_SKYSPHERE BIT( 0 )
#define FWORLD_CUSTOM_SKYBOX BIT( 1 )
#define FWORLD_WATERALPHA BIT( 2 )
#define FWORLD_HAS_DELUXEMAP BIT( 3 )
#define FWORLD_SKYSPHERE BIT( 0 )
#define FWORLD_CUSTOM_SKYBOX BIT( 1 )
#define FWORLD_WATERALPHA BIT( 2 )
#define FWORLD_HAS_DELUXEMAP BIT( 3 )
#define FWORLD_HAS_LITWATER BIT( 4 )
// special rendermode for screenfade modulate
// (probably will be expanded at some point)

View File

@@ -3064,7 +3064,7 @@ void SV_SetStringArrayMode( qboolean dynamic )
#endif
}
#if XASH_64BIT && !XASH_WIN32 && !XASH_APPLE && !XASH_NSWITCH && !XASH_ANDROID
#if XASH_AMD64 && XASH_LINUX && !XASH_ANDROID
#define USE_MMAP
#include <sys/mman.h>
#endif
@@ -5198,7 +5198,7 @@ qboolean SV_LoadProgs( const char *name )
gEngfuncs.pfnPEntityOfEntIndex = pfnPEntityOfEntIndexBroken;
// make local copy of engfuncs to prevent overwrite it with bots.dll
memcpy( &gpEngfuncs, &gEngfuncs, sizeof( gpEngfuncs ));
gpEngfuncs = gEngfuncs;
GetEntityAPI = (APIFUNCTION)COM_GetProcAddress( svgame.hInstance, "GetEntityAPI" );
GetEntityAPI2 = (APIFUNCTION2)COM_GetProcAddress( svgame.hInstance, "GetEntityAPI2" );

View File

@@ -236,7 +236,7 @@ void SV_UpdateMovevars( qboolean initialize )
if( initialize ) return; // too early
if( MSG_WriteDeltaMovevars( &sv.reliable_datagram, &svgame.oldmovevars, &svgame.movevars ))
memcpy( &svgame.oldmovevars, &svgame.movevars, sizeof( movevars_t )); // oldstate changed
svgame.oldmovevars = svgame.movevars; // oldstate changed
host.movevars_changed = false;
}

View File

@@ -199,8 +199,8 @@ static qboolean SV_TestEntityPosition( edict_t *ent, edict_t *blocker )
{
// to avoid falling through tracktrain update client mins\maxs here
if( FBitSet( ent->v.flags, FL_DUCKING ))
SV_SetMinMaxSize( ent, svgame.pmove->player_mins[1], svgame.pmove->player_maxs[1], true );
else SV_SetMinMaxSize( ent, svgame.pmove->player_mins[0], svgame.pmove->player_maxs[0], true );
SV_SetMinMaxSize( ent, host.player_mins[1], host.player_maxs[1], true );
else SV_SetMinMaxSize( ent, host.player_mins[0], host.player_maxs[0], true );
}
trace = SV_Move( ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, MOVE_NORMAL, ent, monsterClip );

View File

@@ -671,7 +671,7 @@ static void SV_FinishPMove( playermove_t *pmove, sv_client_t *cl )
clent->v.angles[YAW] = clent->v.v_angle[YAW];
}
SV_SetMinMaxSize( clent, pmove->player_mins[pmove->usehull], pmove->player_maxs[pmove->usehull], false );
SV_SetMinMaxSize( clent, host.player_mins[pmove->usehull], host.player_maxs[pmove->usehull], false );
// all next calls ignore footstep sounds
pmove->runfuncs = false;

View File

@@ -72,7 +72,7 @@ typedef struct
int32_t version; // current version 2
} dsprite_t;
STATIC_ASSERT( sizeof( dsprite_t ) == 8, "invalid dsprite_t size" );
STATIC_CHECK_SIZEOF( dsprite_t, 8, 8 );
typedef struct
{
@@ -86,7 +86,7 @@ typedef struct
uint32_t synctype; // animation synctype, was synctype_t
} dsprite_q1_t;
STATIC_ASSERT( sizeof( dsprite_q1_t ) == 36, "invalid dsprite_q1_t size" );
STATIC_CHECK_SIZEOF( dsprite_q1_t, 36, 36 );
typedef struct
{
@@ -101,7 +101,7 @@ typedef struct
uint32_t synctype; // animation synctype, was synctype_t
} dsprite_hl_t;
STATIC_ASSERT( sizeof( dsprite_hl_t ) == 40, "invalid dsprite_hl_t size" );
STATIC_CHECK_SIZEOF( dsprite_hl_t, 40, 40 );
typedef struct
{
@@ -110,27 +110,27 @@ typedef struct
int32_t height;
} dspriteframe_t;
STATIC_ASSERT( sizeof( dspriteframe_t ) == 16, "invalid dspriteframe_t size" );
STATIC_CHECK_SIZEOF( dspriteframe_t, 16, 16 );
typedef struct
{
int32_t numframes;
} dspritegroup_t;
STATIC_ASSERT( sizeof( dspritegroup_t ) == 4, "invalid dspritegroup_t size" );
STATIC_CHECK_SIZEOF( dspritegroup_t, 4, 4 );
typedef struct
{
float interval;
} dspriteinterval_t;
STATIC_ASSERT( sizeof( dspriteinterval_t ) == 4, "invalid dspriteinterval_t size" );
STATIC_CHECK_SIZEOF( dspriteinterval_t, 4, 4 );
typedef struct
{
uint32_t type; // was frametype_t
} dframetype_t;
STATIC_ASSERT( sizeof( dframetype_t ) == 4, "invalid dframetype_t size" );
STATIC_CHECK_SIZEOF( dframetype_t, 4, 4 );
#endif//SPRITE_H

View File

@@ -32,6 +32,9 @@ def options(opt):
grp.add_option('--enable-engine-fuzz', action = 'store_true', dest = 'ENGINE_FUZZ', default = False,
help = 'add LLVM libFuzzer [default: %(default)s]' )
grp.add_option('--enable-ffmpeg', action = 'store_true', dest = 'FFMPEG', default = False,
help = '') # hidden option, does nothing
opt.load('sdl2')
def configure(conf):
@@ -107,6 +110,8 @@ def configure(conf):
conf.env.append_unique('CFLAGS', '-fsanitize=fuzzer-no-link')
conf.env.append_unique('LINKFLAGS', '-fsanitize=fuzzer')
conf.define('ENGINE_DLL', 1)
conf.define_cond('XASH_ENGINE_TESTS', conf.env.ENGINE_TESTS)
conf.define_cond('XASH_STATIC_LIBS', conf.env.STATIC_LINKING)
conf.define_cond('XASH_CUSTOM_SWAP', conf.options.CUSTOM_SWAP)

View File

@@ -58,7 +58,7 @@ static inline const char *IdToDir( char *dir, size_t size, const char *id )
if( !Q_strcmp( id, "GAMEDOWNLOAD" ))
{
Q_snprintf( dir, size, "%s/downloaded", GI->gamefolder );
Q_snprintf( dir, size, "%s/" DEFAULT_DOWNLOADED_DIRECTORY , GI->gamefolder );
return dir;
}
@@ -531,9 +531,9 @@ extern "C" void EXPORT *CreateInterface( const char *interface, int *retval )
if( !Q_strcmp( interface, FS_API_CREATEINTERFACE_TAG ))
{
static fs_api_t copy = { 0 }; // return a copy, to disallow overriding
static fs_api_t copy; // return a copy, to disallow overriding
memcpy( &copy, &g_api, sizeof( copy ));
copy = g_api;
if( retval )
*retval = 0;

View File

@@ -21,15 +21,14 @@ GNU General Public License for more details.
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <errno.h>
#if XASH_WIN32
#include <direct.h>
#include <io.h>
#elif XASH_DOS4GW
#include <direct.h>
#include <errno.h>
#else
#include <dirent.h>
#include <errno.h>
#endif
#include <stdio.h>
#include <stdarg.h>
@@ -61,10 +60,10 @@ static char fs_gamedir[MAX_SYSPATH]; // game current directory
// so raw WADs takes precedence over WADs included into PAKs and PK3s
const fs_archive_t g_archives[] =
{
{ "pak", SEARCHPATH_PAK, FS_AddPak_Fullpath, true },
{ "pk3", SEARCHPATH_ZIP, FS_AddZip_Fullpath, true },
{ "pk3dir", SEARCHPATH_PK3DIR, FS_AddDir_Fullpath, true },
{ "wad", SEARCHPATH_WAD, FS_AddWad_Fullpath, false },
{ "pak", SEARCHPATH_PAK, FS_AddPak_Fullpath, true, true },
{ "pk3", SEARCHPATH_ZIP, FS_AddZip_Fullpath, true, true },
{ "pk3dir", SEARCHPATH_PK3DIR, FS_AddDir_Fullpath, true, false },
{ "wad", SEARCHPATH_WAD, FS_AddWad_Fullpath, false, true },
{ NULL }, // end marker
};
@@ -619,6 +618,9 @@ static void FS_WriteGameInfo( const char *filepath, gameinfo_t *GameInfo )
FS_Printf( f, "internal_vgui_support\t\t%s\n", GameInfo->internal_vgui_support ? "1" : "0" );
FS_Printf( f, "render_picbutton_text\t\t%s\n", GameInfo->render_picbutton_text ? "1" : "0" );
if( COM_CheckStringEmpty( GameInfo->demomap ))
FS_Printf( f, "demomap\t\t\"%s\"\n", GameInfo->demomap );
FS_Close( f ); // all done
}
@@ -879,9 +881,21 @@ static void FS_ParseGenericGameInfo( gameinfo_t *GameInfo, const char *buf, cons
pfile = COM_ParseFile( pfile, token, sizeof( token ));
GameInfo->autosave_aged_count = bound( 2, Q_atoi( token ), 99 );
}
else if( !Q_stricmp( token, "demomap" ))
{
pfile = COM_ParseFile( pfile, GameInfo->demomap, sizeof( GameInfo->demomap ));
}
}
}
// demomap only valid for gameinfo.txt but HL1 after 25th anniversary update
// comes with demo chapter. Set the demomap here.
if( !COM_CheckStringEmpty( GameInfo->demomap ))
{
if( !Q_stricmp( GameInfo->title, "Half-Life" )) // original check from GameUI
Q_strncpy( GameInfo->demomap, "hldemo1", sizeof( GameInfo->demomap ));
}
if( !found_linux || !found_osx )
{
// just replace extension from dll to so/dylib
@@ -897,9 +911,18 @@ static void FS_ParseGenericGameInfo( gameinfo_t *GameInfo, const char *buf, cons
}
// make sure what gamedir is really exist
// a1ba: why we are doing this???
Q_snprintf( token, sizeof( token ), "%s/%s", fs_rootdir, GameInfo->falldir );
if( !FS_SysFolderExists( token ))
GameInfo->falldir[0] = '\0';
{
if( COM_CheckStringEmpty( fs_rodir ))
{
Q_snprintf( token, sizeof( token ), "%s/%s", fs_rodir, GameInfo->falldir );
if( !FS_SysFolderExists( token ))
GameInfo->falldir[0] = 0;
}
else GameInfo->falldir[0] = 0;
}
}
/*
@@ -1174,14 +1197,14 @@ void FS_AddGameHierarchy( const char *dir, uint flags )
if( isGameDir )
{
Q_snprintf( buf, sizeof( buf ), "%s/downloaded/", dir );
Q_snprintf( buf, sizeof( buf ), "%s/" DEFAULT_DOWNLOADED_DIRECTORY, dir );
FS_AddGameDirectory( buf, FS_NOWRITE_PATH | FS_CUSTOM_PATH );
}
Q_snprintf( buf, sizeof( buf ), "%s/", dir );
FS_AddGameDirectory( buf, flags );
if( isGameDir )
{
Q_snprintf( buf, sizeof( buf ), "%s/custom/", dir );
Q_snprintf( buf, sizeof( buf ), "%s/" DEFAULT_CUSTOM_DIRECTORY, dir );
FS_AddGameDirectory( buf, FS_NOWRITE_PATH | FS_CUSTOM_PATH );
}
}
@@ -1369,9 +1392,9 @@ static qboolean FS_FindLibrary( const char *dllname, qboolean directpath, fs_dll
}
else
{
Q_snprintf( dllInfo->fullPath, sizeof( dllInfo->fullPath ), "%s%s", search->filename, dllInfo->shortPath );
Q_snprintf( dllInfo->fullPath, sizeof( dllInfo->fullPath ), "%s", dllInfo->shortPath );
#if XASH_WIN32 && XASH_X86 // a1ba: custom loader is non-portable (I just don't want to touch it)
Con_Printf( S_WARN "%s: loading libraries from archives is deprecated and will be removed in the future\n", __func__ );
Con_Printf( S_WARN "%s: loading libraries from archives is non portable and might fail on other platforms\n", __func__ );
dllInfo->custom_loader = true;
#else
Con_Printf( S_WARN "%s: loading libraries from archives is unsupported on this platform\n", __func__ );
@@ -2653,19 +2676,9 @@ return NULL for file in pack
const char *FS_GetDiskPath( const char *name, qboolean gamedironly )
{
static char diskpath[MAX_SYSPATH];
char fullpath[MAX_SYSPATH];
searchpath_t *search;
search = FS_FindFile( name, NULL, fullpath, sizeof( fullpath ), gamedironly );
if( search )
{
if( search->type != SEARCHPATH_PLAIN ) // file in pack or wad
return NULL;
Q_snprintf( diskpath, sizeof( diskpath ), "%s/%s", search->filename, fullpath );
if( FS_GetFullDiskPath( diskpath, sizeof( diskpath ), name, gamedironly ))
return diskpath;
}
return NULL;
}
@@ -2687,7 +2700,7 @@ qboolean FS_GetFullDiskPath( char *buffer, size_t size, const char *name, qboole
if( search && search->type == SEARCHPATH_PLAIN )
{
Q_snprintf( buffer, size, "%s/%s", search->filename, temp );
Q_snprintf( buffer, size, "%s%s", search->filename, temp );
return true;
}
@@ -2931,6 +2944,25 @@ static const char *FS_ArchivePath( file_t *f )
return "plain";
}
static qboolean FS_IsArchiveExtensionSupported( const char *ext, uint flags )
{
int i;
if( ext == NULL )
return false;
for( i = 0; i < ( sizeof( g_archives ) / sizeof( g_archives[0] )) - 1; i++ )
{
if( FBitSet( flags, IAES_ONLY_REAL_ARCHIVES ) && !g_archives[i].real_archive )
continue;
if( !Q_stricmp( ext, g_archives[i].ext ))
return true;
}
return false;
}
void FS_InitMemory( void )
{
fs_mempool = Mem_AllocPool( "FileSystem Pool" );
@@ -2951,7 +2983,7 @@ fs_interface_t g_engfuncs =
Sys_GetNativeObject_stub
};
static qboolean FS_InitInterface( int version, fs_interface_t *engfuncs )
static qboolean FS_InitInterface( int version, const fs_interface_t *engfuncs )
{
// to be extended in future interface revisions
if( version != FS_API_VERSION )
@@ -2999,7 +3031,7 @@ static qboolean FS_InitInterface( int version, fs_interface_t *engfuncs )
return true;
}
fs_api_t g_api =
const fs_api_t g_api =
{
FS_InitStdio,
FS_ShutdownStdio,
@@ -3059,6 +3091,8 @@ fs_api_t g_api =
FS_GetFullDiskPath,
FS_LoadFileMalloc,
FS_IsArchiveExtensionSupported,
};
int EXPORT GetFSAPI( int version, fs_api_t *api, fs_globals_t **globals, fs_interface_t *engfuncs );
@@ -3067,7 +3101,7 @@ int EXPORT GetFSAPI( int version, fs_api_t *api, fs_globals_t **globals, fs_inte
if( engfuncs && !FS_InitInterface( version, engfuncs ))
return 0;
memcpy( api, &g_api, sizeof( *api ));
*api = g_api;
*globals = &FI;
return FS_API_VERSION;

View File

@@ -25,6 +25,7 @@ GNU General Public License for more details.
#include "xash3d_types.h"
#include "const.h"
#include "com_model.h"
#include "gameinfo.h"
#ifdef __cplusplus
extern "C"
@@ -50,6 +51,13 @@ enum
FS_GAMEDIRONLY_SEARCH_FLAGS = FS_GAMEDIR_PATH | FS_CUSTOM_PATH | FS_GAMERODIR_PATH
};
// IsArchiveExtensionSupported flags
enum
{
// excludes directories and pk3dir, i.e. archives that cannot be represented as a single file
IAES_ONLY_REAL_ARCHIVES = BIT( 0 ),
};
typedef struct
{
int numfilenames;
@@ -111,14 +119,9 @@ typedef struct gameinfo_s
// HL25 compatibility keys
qboolean hd_background;
qboolean animated_title;
} gameinfo_t;
typedef enum
{
GAME_NORMAL,
GAME_SINGLEPLAYER_ONLY,
GAME_MULTIPLAYER_ONLY
} gametype_t;
char demomap[MAX_QPATH];
} gameinfo_t;
typedef struct fs_dllinfo_t
{
@@ -135,8 +138,6 @@ typedef struct fs_globals_t
int numgames;
} fs_globals_t;
typedef void (*fs_event_callback_t)( const char *path );
typedef struct fs_api_t
{
qboolean (*InitStdio)( qboolean unused_set_to_true, const char *rootdir, const char *basedir, const char *gamedir, const char *rodir );
@@ -199,6 +200,9 @@ typedef struct fs_api_t
// like LoadFile but returns pointer that can be free'd using standard library function
byte *(*LoadFileMalloc)( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly );
// queries supported archive formats
qboolean (*IsArchiveExtensionSupported)( const char *ext, uint flags );
} fs_api_t;
typedef struct fs_interface_t
@@ -221,7 +225,7 @@ typedef struct fs_interface_t
void *(*_Sys_GetNativeObject)( const char *object );
} fs_interface_t;
typedef int (*FSAPI)( int version, fs_api_t *api, fs_globals_t **globals, fs_interface_t *interface );
typedef int (*FSAPI)( int version, fs_api_t *api, fs_globals_t **globals, const fs_interface_t *interface );
#define GET_FS_API "GetFSAPI"
#ifdef __cplusplus

View File

@@ -114,6 +114,7 @@ typedef struct fs_archive_s
int type;
FS_ADDARCHIVE_FULLPATH pfnAddArchive_Fullpath;
qboolean load_wads; // load wads from this archive
qboolean real_archive;
} fs_archive_t;
extern fs_globals_t FI;
@@ -123,7 +124,7 @@ extern fs_interface_t g_engfuncs;
extern qboolean fs_ext_path;
extern char fs_rodir[MAX_SYSPATH];
extern char fs_rootdir[MAX_SYSPATH];
extern fs_api_t g_api;
extern const fs_api_t g_api;
extern const fs_archive_t g_archives[];
#define GI FI.GameInfo

View File

@@ -69,7 +69,7 @@ struct pack_s
{
file_t *handle;
int numfiles;
dpackfile_t files[1]; // flexible
dpackfile_t files[]; // flexible
};
/*
@@ -150,7 +150,7 @@ static pack_t *FS_LoadPackPAK( const char *packfile, int *error )
return NULL;
}
pack = (pack_t *)Mem_Calloc( fs_mempool, sizeof( pack_t ) + sizeof( dpackfile_t ) * ( numpackfiles - 1 ));
pack = (pack_t *)Mem_Calloc( fs_mempool, sizeof( pack_t ) + sizeof( dpackfile_t ) * numpackfiles );
FS_Seek( packhandle, header.dirofs, SEEK_SET );
if( header.dirlen != FS_Read( packhandle, (void *)pack->files, header.dirlen ))

View File

@@ -57,6 +57,15 @@ static int TestNoInit( void )
p = g_fs.LoadDirectFile( "hehe", NULL );
if( p ) free( p );
if( !g_fs.IsArchiveExtensionSupported( "pk3", 0 )) return 0;
if( !g_fs.IsArchiveExtensionSupported( "wad", 0 )) return 0;
if( !g_fs.IsArchiveExtensionSupported( "pak", 0 )) return 0;
if( !g_fs.IsArchiveExtensionSupported( "pk3dir", 0 )) return 0;
if( !g_fs.IsArchiveExtensionSupported( "pk3", IAES_ONLY_REAL_ARCHIVES )) return 0;
if( g_fs.IsArchiveExtensionSupported( "pk3dir", IAES_ONLY_REAL_ARCHIVES )) return 0;
if( g_fs.IsArchiveExtensionSupported( "vpk", 0)) return 0;
g_fs.FileExists( "asdcv", 0 );
g_fs.FileTime( "zxcasdfd", 0 );
g_fs.FileSize( "asdqwe", 1 );

View File

@@ -125,7 +125,7 @@ struct zip_s
{
file_t *handle;
int numfiles;
zipfile_t files[1]; // flexible
zipfile_t files[]; // flexible
};
// #define ENABLE_CRC_CHECK // known to be buggy because of possible libpublic crc32 bug, disabled
@@ -285,7 +285,7 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
FS_Seek( zip->handle, header_eocd.central_directory_offset, SEEK_SET );
// Calc count of files in archive
zip = (zip_t *)Mem_Realloc( fs_mempool, zip, sizeof( *zip ) + sizeof( *info ) * ( header_eocd.total_central_directory_record - 1 ));
zip = (zip_t *)Mem_Realloc( fs_mempool, zip, sizeof( *zip ) + sizeof( *info ) * header_eocd.total_central_directory_record );
info = zip->files;
for( i = 0; i < header_eocd.total_central_directory_record; i++ )

View File

@@ -44,9 +44,8 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
#error // port me!
#endif
#define E_GAME "XASH3D_GAME" // default env dir to start from
#ifndef XASH_GAMEDIR
#define XASH_GAMEDIR "valve"
#define XASH_GAMEDIR "valve" // !!! Replace with your default (base) game directory !!!
#endif
typedef void (*pfnChangeGame)( const char *progname );
@@ -151,7 +150,6 @@ _inline int Sys_Start( void )
{
int ret;
pfnChangeGame changeGame = NULL;
const char *game = getenv( E_GAME );
#if XASH_SAILFISH
const char *home = getenv( "HOME" );
@@ -166,10 +164,7 @@ _inline int Sys_Start( void )
#endif // XASH_AURORAOS
#endif // XASH_SAILFISH
if( !game )
game = XASH_GAMEDIR;
strncpy( szGameDir, game, sizeof( szGameDir ) - 1 );
strncpy( szGameDir, XASH_GAMEDIR, sizeof( szGameDir ) - 1 );
Sys_LoadEngine();

View File

@@ -686,15 +686,19 @@ void COM_FixSlashes( char *pname )
/*
============
COM_PathSlashFix
ensure directory path always ends on forward slash
============
*/
void COM_PathSlashFix( char *path )
{
size_t len;
size_t len = Q_strlen( path );
len = Q_strlen( path );
if( path[len - 1] != '\\' && path[len - 1] != '/' )
if( path[len - 1] == '\\' )
{
path[len - 1] = '/';
}
else if( path[len - 1] != '/' )
{
path[len] = '/';
path[len + 1] = '\0';

View File

@@ -71,7 +71,11 @@ def configure(conf):
conf.env.DEFINES_export = list(conf.env.EXPORT_DEFINES_LIST)
# check platform-specific header name for alloca(3)
if conf.simple_check(ALLOCA_TEST % 'alloca.h', msg='alloca in alloca.h'):
if conf.env.DEST_OS == 'win32':
# don't waste time on Win32, it's documented to be always in malloc.h.
# (plus test can fail because alloca is underscore-prefixed, e.g. _alloca)
conf.export_define('ALLOCA_H', '<malloc.h>')
elif conf.simple_check(ALLOCA_TEST % 'alloca.h', msg='alloca in alloca.h'):
conf.export_define('ALLOCA_H', '<alloca.h>')
elif conf.simple_check(ALLOCA_TEST % 'malloc.h', msg='alloca in malloc.h'):
conf.export_define('ALLOCA_H', '<malloc.h>')

View File

@@ -52,15 +52,10 @@ ALIAS MODEL DISPLAY LIST GENERATION
*/
static qboolean m_fDoRemap;
static aliashdr_t *m_pAliasHeader;
static trivertex_t *g_poseverts[MAXALIASFRAMES];
static dtriangle_t g_triangles[MAXALIASTRIS];
static stvert_t g_stverts[MAXALIASVERTS];
static int g_used[8192];
// a pose is a single set of vertexes. a frame may be
// an animating sequence of poses
static int g_posenum;
// the command list holds counts and s/t values that are valid for
// every frame
static int g_commands[8192];
@@ -324,7 +319,7 @@ static void GL_MakeAliasModelDisplayLists( model_t *m )
for( i = 0; i < m_pAliasHeader->numposes; i++ )
{
for( j = 0; j < g_numorder; j++ )
*verts++ = g_poseverts[i][g_vertexorder[j]];
*verts++ = m_pAliasHeader->pposeverts[i][g_vertexorder[j]];
}
}
@@ -335,85 +330,14 @@ ALIAS MODELS
==============================================================================
*/
/*
=================
Mod_LoadAliasFrame
=================
*/
static void *Mod_LoadAliasFrame( void *pin, maliasframedesc_t *frame )
{
daliasframe_t *pdaliasframe;
trivertex_t *pinframe;
int i;
pdaliasframe = (daliasframe_t *)pin;
Q_strncpy( frame->name, pdaliasframe->name, sizeof( frame->name ));
frame->firstpose = g_posenum;
frame->numposes = 1;
for( i = 0; i < 3; i++ )
{
frame->bboxmin.v[i] = pdaliasframe->bboxmin.v[i];
frame->bboxmax.v[i] = pdaliasframe->bboxmax.v[i];
}
pinframe = (trivertex_t *)(pdaliasframe + 1);
g_poseverts[g_posenum] = (trivertex_t *)pinframe;
pinframe += m_pAliasHeader->numverts;
g_posenum++;
return (void *)pinframe;
}
/*
=================
Mod_LoadAliasGroup
=================
*/
static void *Mod_LoadAliasGroup( void *pin, maliasframedesc_t *frame )
{
daliasgroup_t *pingroup;
int i, numframes;
daliasinterval_t *pin_intervals;
void *ptemp;
pingroup = (daliasgroup_t *)pin;
numframes = pingroup->numframes;
frame->firstpose = g_posenum;
frame->numposes = numframes;
for( i = 0; i < 3; i++ )
{
frame->bboxmin.v[i] = pingroup->bboxmin.v[i];
frame->bboxmax.v[i] = pingroup->bboxmax.v[i];
}
pin_intervals = (daliasinterval_t *)(pingroup + 1);
// all the intervals are always equal 0.1 so we don't care about them
frame->interval = pin_intervals->interval;
pin_intervals += numframes;
ptemp = (void *)pin_intervals;
for( i = 0; i < numframes; i++ )
{
g_poseverts[g_posenum] = (trivertex_t *)((daliasframe_t *)ptemp + 1);
ptemp = (trivertex_t *)((daliasframe_t *)ptemp + 1) + m_pAliasHeader->numverts;
g_posenum++;
}
return ptemp;
}
/*
===============
Mod_CreateSkinData
===============
*/
static rgbdata_t *Mod_CreateSkinData( model_t *mod, byte *data, int width, int height )
static rgbdata_t *Mod_CreateSkinData( model_t *mod, const byte *data, int width, int height )
{
static rgbdata_t skin;
char name[MAX_QPATH];
@@ -426,7 +350,7 @@ static rgbdata_t *Mod_CreateSkinData( model_t *mod, byte *data, int width, int h
skin.flags = IMAGE_HAS_COLOR|IMAGE_QUAKEPAL;
skin.encode = DXT_ENCODE_DEFAULT;
skin.numMips = 1;
skin.buffer = data;
skin.buffer = (byte *)data;
skin.palette = (byte *)tr.palette;
skin.size = width * height;
@@ -475,67 +399,68 @@ static rgbdata_t *Mod_CreateSkinData( model_t *mod, byte *data, int width, int h
return gEngfuncs.FS_CopyImage( &skin );
}
static void *Mod_LoadSingleSkin( model_t *loadmodel, daliasskintype_t *pskintype, int skinnum, int size )
static const void *Mod_LoadSingleSkin( model_t *loadmodel, const daliasskintype_t *pskintype, int skinnum, int size )
{
string name, lumaname;
string checkname;
rgbdata_t *pic;
const byte *ptexture = (const byte *)&pskintype[1];
rgbdata_t *pic;
string name, lumaname, checkname;
Q_snprintf( name, sizeof( name ), "%s:frame%i", loadmodel->name, skinnum );
Q_snprintf( lumaname, sizeof( lumaname ), "%s:luma%i", loadmodel->name, skinnum );
Q_snprintf( checkname, sizeof( checkname ), "%s_%i.tga", loadmodel->name, skinnum );
if( !gEngfuncs.fsapi->FileExists( checkname, false ) || ( pic = gEngfuncs.FS_LoadImage( checkname, NULL, 0 )) == NULL )
pic = Mod_CreateSkinData( loadmodel, (byte *)(pskintype + 1), m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
pic = Mod_CreateSkinData( loadmodel, ptexture, m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
m_pAliasHeader->gl_texturenum[skinnum][0] =
m_pAliasHeader->gl_texturenum[skinnum][1] =
m_pAliasHeader->gl_texturenum[skinnum][2] =
m_pAliasHeader->gl_texturenum[skinnum][3] = GL_LoadTextureInternal( name, pic, 0 );
m_pAliasHeader->gl_texturenum[skinnum][1] =
m_pAliasHeader->gl_texturenum[skinnum][2] =
m_pAliasHeader->gl_texturenum[skinnum][3] = GL_LoadTextureInternal( name, pic, 0 );
gEngfuncs.FS_FreeImage( pic );
if( R_GetTexture( m_pAliasHeader->gl_texturenum[skinnum][0] )->flags & TF_HAS_LUMA )
if( FBitSet( R_GetTexture( m_pAliasHeader->gl_texturenum[skinnum][0] )->flags, TF_HAS_LUMA ))
{
pic = Mod_CreateSkinData( NULL, (byte *)(pskintype + 1), m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
Q_snprintf( lumaname, sizeof( lumaname ), "%s:luma%i", loadmodel->name, skinnum );
pic = Mod_CreateSkinData( NULL, ptexture, m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
m_pAliasHeader->fb_texturenum[skinnum][0] =
m_pAliasHeader->fb_texturenum[skinnum][1] =
m_pAliasHeader->fb_texturenum[skinnum][2] =
m_pAliasHeader->fb_texturenum[skinnum][3] = GL_LoadTextureInternal( lumaname, pic, TF_MAKELUMA );
m_pAliasHeader->fb_texturenum[skinnum][1] =
m_pAliasHeader->fb_texturenum[skinnum][2] =
m_pAliasHeader->fb_texturenum[skinnum][3] = GL_LoadTextureInternal( lumaname, pic, TF_MAKELUMA );
gEngfuncs.FS_FreeImage( pic );
}
return ((byte *)(pskintype + 1) + size);
return ptexture + size;
}
static void *Mod_LoadGroupSkin( model_t *loadmodel, daliasskintype_t *pskintype, int skinnum, int size )
static const void *Mod_LoadGroupSkin( model_t *loadmodel, const daliasskintype_t *pskintype, int skinnum, int size )
{
daliasskininterval_t *pinskinintervals;
daliasskingroup_t *pinskingroup;
string name, lumaname;
rgbdata_t *pic;
int i, j;
const daliasskininterval_t *pinskinintervals;
const daliasskingroup_t *pinskingroup;
const byte *ptexture;
rgbdata_t *pic;
string name, lumaname;
int i, j;
// animating skin group. yuck.
pskintype++;
pinskingroup = (daliasskingroup_t *)pskintype;
pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
pskintype = (void *)(pinskinintervals + pinskingroup->numskins);
pinskingroup = (const daliasskingroup_t *)&pskintype[1];
pinskinintervals = (const daliasskininterval_t *)(&pinskingroup[1]);
ptexture = (const byte *)&pinskinintervals[pinskingroup->numskins];
for( i = 0; i < pinskingroup->numskins; i++ )
{
Q_snprintf( name, sizeof( name ), "%s_%i_%i", loadmodel->name, skinnum, i );
pic = Mod_CreateSkinData( loadmodel, (byte *)(pskintype), m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
pic = Mod_CreateSkinData( loadmodel, ptexture, m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
m_pAliasHeader->gl_texturenum[skinnum][i & 3] = GL_LoadTextureInternal( name, pic, 0 );
gEngfuncs.FS_FreeImage( pic );
if( R_GetTexture( m_pAliasHeader->gl_texturenum[skinnum][i & 3] )->flags & TF_HAS_LUMA )
if( FBitSet( R_GetTexture( m_pAliasHeader->gl_texturenum[skinnum][i & 3] )->flags, TF_HAS_LUMA ))
{
Q_snprintf( lumaname, sizeof( lumaname ), "%s_%i_%i_luma", loadmodel->name, skinnum, i );
pic = Mod_CreateSkinData( NULL, (byte *)(pskintype), m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
pic = Mod_CreateSkinData( NULL, ptexture, m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
m_pAliasHeader->fb_texturenum[skinnum][i & 3] = GL_LoadTextureInternal( lumaname, pic, TF_MAKELUMA );
gEngfuncs.FS_FreeImage( pic );
}
pskintype = (daliasskintype_t *)((byte *)(pskintype) + size);
ptexture += size;
}
for( j = i; i < 4; i++ )
@@ -544,7 +469,7 @@ static void *Mod_LoadGroupSkin( model_t *loadmodel, daliasskintype_t *pskintype,
m_pAliasHeader->fb_texturenum[skinnum][i & 3] = m_pAliasHeader->fb_texturenum[skinnum][i - j];
}
return pskintype;
return ptexture;
}
/*
@@ -552,66 +477,25 @@ static void *Mod_LoadGroupSkin( model_t *loadmodel, daliasskintype_t *pskintype,
Mod_LoadAllSkins
===============
*/
static void *Mod_LoadAllSkins( model_t *mod, int numskins, daliasskintype_t *pskintype )
static const void *Mod_LoadAllSkins( model_t *mod, int numskins, const daliasskintype_t *pskintype )
{
int i, size;
if( numskins < 1 || numskins > MAX_SKINS )
gEngfuncs.Host_Error( "%s: Invalid # of skins: %d\n", __func__, numskins );
size = m_pAliasHeader->skinwidth * m_pAliasHeader->skinheight;
// TODO: texture replacement support here
for( i = 0; i < numskins; i++ )
{
if( pskintype->type == ALIAS_SKIN_SINGLE )
{
pskintype = (daliasskintype_t *)Mod_LoadSingleSkin( mod, pskintype, i, size );
}
pskintype = Mod_LoadSingleSkin( mod, pskintype, i, size );
else
{
pskintype = (daliasskintype_t *)Mod_LoadGroupSkin( mod, pskintype, i, size );
}
pskintype = Mod_LoadGroupSkin( mod, pskintype, i, size );
}
return (void *)pskintype;
return pskintype;
}
//=========================================================================
/*
=================
Mod_CalcAliasBounds
=================
*/
static void Mod_CalcAliasBounds( model_t *mod )
{
int i, j, k;
float radius;
float dist;
vec3_t v;
ClearBounds( mod->mins, mod->maxs );
radius = 0.0f;
// process verts
for( i = 0; i < m_pAliasHeader->numposes; i++ )
{
for( j = 0; j < m_pAliasHeader->numverts; j++ )
{
for( k = 0; k < 3; k++ )
v[k] = g_poseverts[i][j].v[k] * m_pAliasHeader->scale[k] + m_pAliasHeader->scale_origin[k];
AddPointToBounds( v, mod->mins, mod->maxs );
dist = DotProduct( v, v );
if( radius < dist )
radius = dist;
}
}
mod->radius = sqrt( radius );
}
/*
=================
@@ -620,111 +504,34 @@ Mod_LoadAliasModel
*/
void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *loaded )
{
daliashdr_t *pinmodel;
stvert_t *pinstverts;
dtriangle_t *pintriangles;
daliasframetype_t *pframetype;
daliasskintype_t *pskintype;
int i, j, size;
char poolname[MAX_VA_STRING];
const daliasskintype_t *pskintype;
const dtriangle_t *pintriangles;
const daliashdr_t *pinmodel;
const stvert_t *pinstverts;
if( loaded ) *loaded = false;
pinmodel = (daliashdr_t *)buffer;
i = pinmodel->version;
if( i != ALIAS_VERSION )
{
gEngfuncs.Con_DPrintf( S_ERROR "%s has wrong version number (%i should be %i)\n", mod->name, i, ALIAS_VERSION );
return;
}
if( pinmodel->numverts <= 0 || pinmodel->numtris <= 0 || pinmodel->numframes <= 0 )
return; // how to possible is make that?
Q_snprintf( poolname, sizeof( poolname ), "^2%s^7", mod->name );
mod->mempool = Mem_AllocPool( poolname );
// allocate space for a working header, plus all the data except the frames,
// skin and group info
size = sizeof( aliashdr_t ) + (pinmodel->numframes - 1) * sizeof( maliasframedesc_t );
m_pAliasHeader = Mem_Calloc( mod->mempool, size );
mod->flags = pinmodel->flags; // share effects flags
// endian-adjust and copy the data, starting with the alias model header
m_pAliasHeader->boundingradius = pinmodel->boundingradius;
m_pAliasHeader->numskins = pinmodel->numskins;
m_pAliasHeader->skinwidth = pinmodel->skinwidth;
m_pAliasHeader->skinheight = pinmodel->skinheight;
m_pAliasHeader->numverts = pinmodel->numverts;
m_pAliasHeader->numtris = pinmodel->numtris;
m_pAliasHeader->numframes = pinmodel->numframes;
if( m_pAliasHeader->numverts > MAXALIASVERTS )
{
gEngfuncs.Con_DPrintf( S_ERROR "model %s has too many vertices\n", mod->name );
return;
}
m_pAliasHeader->size = pinmodel->size;
// mod->synctype = pinmodel->synctype;
mod->numframes = m_pAliasHeader->numframes;
for( i = 0; i < 3; i++ )
{
m_pAliasHeader->scale[i] = pinmodel->scale[i];
m_pAliasHeader->scale_origin[i] = pinmodel->scale_origin[i];
m_pAliasHeader->eyeposition[i] = pinmodel->eyeposition[i];
}
pinmodel = (const daliashdr_t *)buffer;
m_pAliasHeader = mod->cache.data;
if( !m_pAliasHeader ) return;
// load the skins
pskintype = (daliasskintype_t *)&pinmodel[1];
pskintype = (const daliasskintype_t *)&pinmodel[1];
pskintype = Mod_LoadAllSkins( mod, m_pAliasHeader->numskins, pskintype );
// load base s and t vertices
pinstverts = (stvert_t *)pskintype;
for( i = 0; i < m_pAliasHeader->numverts; i++ )
{
g_stverts[i].onseam = pinstverts[i].onseam;
g_stverts[i].s = pinstverts[i].s;
g_stverts[i].t = pinstverts[i].t;
}
pinstverts = (const stvert_t *)pskintype;
memset( g_stverts, 0, sizeof( g_stverts ));
memcpy( g_stverts, pinstverts, sizeof( g_stverts[0] ) * m_pAliasHeader->numverts );
// load triangle lists
pintriangles = (dtriangle_t *)&pinstverts[m_pAliasHeader->numverts];
for( i = 0; i < m_pAliasHeader->numtris; i++ )
{
g_triangles[i].facesfront = pintriangles[i].facesfront;
for( j = 0; j < 3; j++ )
g_triangles[i].vertindex[j] = pintriangles[i].vertindex[j];
}
// load the frames
pframetype = (daliasframetype_t *)&pintriangles[m_pAliasHeader->numtris];
g_posenum = 0;
for( i = 0; i < m_pAliasHeader->numframes; i++ )
{
aliasframetype_t frametype = pframetype->type;
if( frametype == ALIAS_SINGLE )
pframetype = (daliasframetype_t *)Mod_LoadAliasFrame( pframetype + 1, &m_pAliasHeader->frames[i] );
else pframetype = (daliasframetype_t *)Mod_LoadAliasGroup( pframetype + 1, &m_pAliasHeader->frames[i] );
}
m_pAliasHeader->numposes = g_posenum;
Mod_CalcAliasBounds( mod );
mod->type = mod_alias;
pintriangles = (const dtriangle_t *)&pinstverts[m_pAliasHeader->numverts];
memset( g_triangles, 0, sizeof( g_triangles ));
memcpy( g_triangles, pintriangles, sizeof( g_triangles[0] ) * m_pAliasHeader->numtris );
// build the draw lists
GL_MakeAliasModelDisplayLists( mod );
// move the complete, relocatable alias model to the cache
mod->cache.data = m_pAliasHeader;
m_pAliasHeader = NULL;
if( loaded ) *loaded = true; // done
}

View File

@@ -422,7 +422,7 @@ static const char *R_GetConfigName( void )
return "opengl";
}
static ref_interface_t gReffuncs =
static const ref_interface_t gReffuncs =
{
R_Init,
R_Shutdown,
@@ -569,8 +569,8 @@ int EXPORT GetRefAPI( int version, ref_interface_t *funcs, ref_api_t *engfuncs,
return 0;
// fill in our callbacks
memcpy( funcs, &gReffuncs, sizeof( ref_interface_t ));
memcpy( &gEngfuncs, engfuncs, sizeof( ref_api_t ));
*funcs = gReffuncs;
gEngfuncs = *engfuncs;
gpGlobals = globals;
gp_cl = (ref_client_t *)ENGINE_GET_PARM( PARM_GET_CLIENT_PTR );

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