mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-05 19:45:05 +08:00
Compare commits
258 Commits
continuous
...
continuous
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65bfff69d0 | ||
|
|
9d8ba03f5e | ||
|
|
778b8ede58 | ||
|
|
f8a1a2ed71 | ||
|
|
b4a7c266b5 | ||
|
|
a488f79852 | ||
|
|
b290046503 | ||
|
|
e8409cee8b | ||
|
|
1d4d355b38 | ||
|
|
dfe12535a5 | ||
|
|
74946100f1 | ||
|
|
9a1717915c | ||
|
|
3691eb6e48 | ||
|
|
3bb7471fd3 | ||
|
|
74e09ddb12 | ||
|
|
6b73d056b2 | ||
|
|
3e7847551a | ||
|
|
91d92935fa | ||
|
|
eff033298a | ||
|
|
3a8f4961bc | ||
|
|
b81f94518a | ||
|
|
96f7f5457d | ||
|
|
498ec6b4f1 | ||
|
|
607e62a1ae | ||
|
|
d41a80bc2c | ||
|
|
643bec4071 | ||
|
|
a7e84230c3 | ||
|
|
c96cf7e22d | ||
|
|
46c61660cf | ||
|
|
f6fecce52b | ||
|
|
54a5947a3c | ||
|
|
521bc675a2 | ||
|
|
845cee2578 | ||
|
|
93ceb0e4ed | ||
|
|
13aab4e59c | ||
|
|
36c2f9e9f2 | ||
|
|
514da0ffa9 | ||
|
|
37b8d5da79 | ||
|
|
b5d602d953 | ||
|
|
c926fee13c | ||
|
|
a675806c91 | ||
|
|
683c4874f8 | ||
|
|
20ced857b4 | ||
|
|
c6c86f9665 | ||
|
|
1e0107944f | ||
|
|
21797f9ac8 | ||
|
|
c800b34cd4 | ||
|
|
1612e2d669 | ||
|
|
26d229c8ca | ||
|
|
9c66e86be1 | ||
|
|
7e9f87de2d | ||
|
|
67737446ac | ||
|
|
dabed4f9eb | ||
|
|
f9b6389248 | ||
|
|
9ec1e259b4 | ||
|
|
0c2d480d89 | ||
|
|
350d8ccb7b | ||
|
|
0c512d0431 | ||
|
|
3bf55c9ea4 | ||
|
|
9994c57796 | ||
|
|
3f724b6b17 | ||
|
|
255773b4de | ||
|
|
5b73a788da | ||
|
|
748b06a00e | ||
|
|
273bccdc9a | ||
|
|
f0a2362da3 | ||
|
|
be8ade23e8 | ||
|
|
6814908d80 | ||
|
|
08dbfc45d3 | ||
|
|
89f9b3df68 | ||
|
|
40c9a2fb82 | ||
|
|
a34c22fb10 | ||
|
|
e161ff0f7a | ||
|
|
fee42eab5a | ||
|
|
2d2e03f235 | ||
|
|
4c3c3529e9 | ||
|
|
7051b844ff | ||
|
|
68377435c8 | ||
|
|
652b1804a8 | ||
|
|
e7e1677786 | ||
|
|
f330aac113 | ||
|
|
dbdd330cf7 | ||
|
|
c448c7b0b1 | ||
|
|
8d7b9c2f01 | ||
|
|
b6a235445a | ||
|
|
9fcd4baa87 | ||
|
|
fb0102eb8e | ||
|
|
9c1afaa372 | ||
|
|
1d1a6badb5 | ||
|
|
2d41c9cb15 | ||
|
|
722cbe1f02 | ||
|
|
8ac2c241c4 | ||
|
|
dd11f73951 | ||
|
|
a443547d4d | ||
|
|
7a795edeb5 | ||
|
|
a8cbfb8dda | ||
|
|
5216cccef4 | ||
|
|
a87f399e68 | ||
|
|
dd310ab851 | ||
|
|
16cc0ca0fe | ||
|
|
83d26ad233 | ||
|
|
d1f9a8f2db | ||
|
|
a2e1071808 | ||
|
|
0aa8a2891c | ||
|
|
c0ceab7513 | ||
|
|
5c90e716cb | ||
|
|
0073225549 | ||
|
|
d03a64602b | ||
|
|
d67a4234cc | ||
|
|
0d37244490 | ||
|
|
6426919cb5 | ||
|
|
0a0d63663a | ||
|
|
71b06801ef | ||
|
|
cfc7b35927 | ||
|
|
76564958d1 | ||
|
|
a464c3dd66 | ||
|
|
bd969f3594 | ||
|
|
fb87d7c0b3 | ||
|
|
a69fc87940 | ||
|
|
e481e1d73e | ||
|
|
6c0eed1b2b | ||
|
|
a6c67fdf9f | ||
|
|
03f838e37e | ||
|
|
e21fa4a910 | ||
|
|
46889ed453 | ||
|
|
882fcc152c | ||
|
|
a41902bd46 | ||
|
|
a6af32dafd | ||
|
|
d6dfb83be7 | ||
|
|
597429cf41 | ||
|
|
5ea074a1fd | ||
|
|
29c9393da3 | ||
|
|
bf6829189e | ||
|
|
a62a9429c9 | ||
|
|
f2c080e736 | ||
|
|
ea55e78855 | ||
|
|
f7c536b81c | ||
|
|
6c40104c66 | ||
|
|
4d7d592918 | ||
|
|
c5e91f299b | ||
|
|
cff276db71 | ||
|
|
30d1492b93 | ||
|
|
f07eea5073 | ||
|
|
fe407fbe00 | ||
|
|
78bc177e05 | ||
|
|
8fb908e3d4 | ||
|
|
d8b261370a | ||
|
|
a2c9ac5b1f | ||
|
|
7f9025e178 | ||
|
|
8647110a10 | ||
|
|
48e44f0057 | ||
|
|
e3934af7d1 | ||
|
|
a5ee631191 | ||
|
|
ce39255ef0 | ||
|
|
5aac5d2a52 | ||
|
|
061b50404d | ||
|
|
279cec5ae9 | ||
|
|
83a5648335 | ||
|
|
a8fc9a4c5a | ||
|
|
6f6ddbce28 | ||
|
|
4cb425d2bb | ||
|
|
bf5fd40d64 | ||
|
|
6bc613bdb4 | ||
|
|
a982562658 | ||
|
|
96a9172e36 | ||
|
|
34d7664342 | ||
|
|
b0a79df86f | ||
|
|
9e107e900c | ||
|
|
8f819a2fde | ||
|
|
3251b68df5 | ||
|
|
3ac8ad9484 | ||
|
|
b9ca0d4563 | ||
|
|
dcb3da53b0 | ||
|
|
e68b19ed1a | ||
|
|
14c7a84482 | ||
|
|
c1d1aa6787 | ||
|
|
bee81e9723 | ||
|
|
1bfb6c560a | ||
|
|
24d6f1788a | ||
|
|
fb95cc9a97 | ||
|
|
b949da291e | ||
|
|
2ecbe5b67e | ||
|
|
6634e0487c | ||
|
|
7d61b5317c | ||
|
|
201258dc9e | ||
|
|
0330569537 | ||
|
|
a1ab84a2ca | ||
|
|
2d79f3ef7a | ||
|
|
99a7e9ad87 | ||
|
|
02b8037f33 | ||
|
|
fc55a685e3 | ||
|
|
b76a75d6b4 | ||
|
|
a251600c8a | ||
|
|
c551aefd77 | ||
|
|
f343f0da41 | ||
|
|
6d318a4102 | ||
|
|
a2b992d865 | ||
|
|
ddf3f2ffdb | ||
|
|
2454e87509 | ||
|
|
0dc44249a2 | ||
|
|
150cbfa4de | ||
|
|
c0b068d81b | ||
|
|
fbc312b6cf | ||
|
|
342e0d3e2e | ||
|
|
202b228691 | ||
|
|
c9c1286803 | ||
|
|
eab98b0eda | ||
|
|
35be80fc21 | ||
|
|
6041bb0a43 | ||
|
|
c7dd9d6437 | ||
|
|
d378878c91 | ||
|
|
4a2f8cafcd | ||
|
|
d254bac16b | ||
|
|
e23b632ce5 | ||
|
|
2f321b1471 | ||
|
|
0265e88d8f | ||
|
|
4114d2f24d | ||
|
|
8124035763 | ||
|
|
96127c6eb0 | ||
|
|
cf65a39b83 | ||
|
|
0341f96b70 | ||
|
|
c95d91cfe3 | ||
|
|
cbd10c6279 | ||
|
|
5df9e57743 | ||
|
|
c178022fb5 | ||
|
|
724c29d711 | ||
|
|
74a2dbeb91 | ||
|
|
5d20d24ebc | ||
|
|
0e2fc277c8 | ||
|
|
1505740b73 | ||
|
|
6bad07b39d | ||
|
|
f85437dfc5 | ||
|
|
c765261db6 | ||
|
|
73087ead2d | ||
|
|
8c88e82709 | ||
|
|
40dd6e0234 | ||
|
|
eb23b226cc | ||
|
|
676526a518 | ||
|
|
7e0bd86b65 | ||
|
|
97489635af | ||
|
|
a9ea3976a7 | ||
|
|
5501ca927a | ||
|
|
a19fb82d66 | ||
|
|
9d032e953f | ||
|
|
38587151a9 | ||
|
|
02d5bab04b | ||
|
|
d8f3e53b1f | ||
|
|
877ed8a92a | ||
|
|
487a652aa8 | ||
|
|
64c5d141af | ||
|
|
16db8a8008 | ||
|
|
b6b14da102 | ||
|
|
a575605c75 | ||
|
|
a205a3e878 | ||
|
|
26ef3e274c | ||
|
|
33be1b7591 | ||
|
|
de19d78571 | ||
|
|
287381d5ca |
22
.cirrus.yml
22
.cirrus.yml
@@ -1,10 +1,10 @@
|
||||
task:
|
||||
name: freebsd-12-amd64
|
||||
freebsd_instance:
|
||||
image_family: freebsd-12-3
|
||||
image_family: freebsd-12-4
|
||||
setup_script:
|
||||
- pkg update
|
||||
- pkg install -y git sdl2 python fontconfig
|
||||
- pkg install -y pkgconf git sdl2 python fontconfig opus
|
||||
- git submodule update --init --recursive
|
||||
test_script:
|
||||
- ./scripts/cirrus/build_freebsd.sh dedicated
|
||||
@@ -13,10 +13,10 @@ task:
|
||||
task:
|
||||
name: freebsd-13-amd64
|
||||
freebsd_instance:
|
||||
image_family: freebsd-13-1
|
||||
image_family: freebsd-13-2
|
||||
setup_script:
|
||||
- pkg update
|
||||
- pkg install -y git sdl2 python fontconfig
|
||||
- pkg install -y pkgconf git sdl2 python fontconfig opus
|
||||
- git submodule update --init --recursive
|
||||
test_script:
|
||||
- ./scripts/cirrus/build_freebsd.sh dedicated
|
||||
@@ -28,7 +28,19 @@ task:
|
||||
image_family: freebsd-14-0-snap
|
||||
setup_script:
|
||||
- pkg update
|
||||
- pkg install -y git sdl2 python fontconfig
|
||||
- pkg install -y pkgconf git sdl2 python fontconfig opus
|
||||
- git submodule update --init --recursive
|
||||
test_script:
|
||||
- ./scripts/cirrus/build_freebsd.sh dedicated
|
||||
- ./scripts/cirrus/build_freebsd.sh full
|
||||
|
||||
task:
|
||||
name: freebsd-15-amd64
|
||||
freebsd_instance:
|
||||
image_family: freebsd-15-0-snap
|
||||
setup_script:
|
||||
- pkg update
|
||||
- pkg install -y pkgconf git sdl2 python fontconfig opus
|
||||
- git submodule update --init --recursive
|
||||
test_script:
|
||||
- ./scripts/cirrus/build_freebsd.sh dedicated
|
||||
|
||||
2
3rdparty/mainui
vendored
2
3rdparty/mainui
vendored
Submodule 3rdparty/mainui updated: d6a54bbf0c...b4bb815420
2
3rdparty/vgui_support
vendored
2
3rdparty/vgui_support
vendored
Submodule 3rdparty/vgui_support updated: 521cf5cb6c...f85d64c149
24
Documentation/donate.md
Normal file
24
Documentation/donate.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Developers donation page
|
||||
|
||||
On this page you can find links where you can support each developer individually, who has provided public sponsorship information.
|
||||
|
||||
### [a1batross](https://github.com/a1batross)
|
||||
|
||||
* Initial Xash3D SDL2/Linux port author, Xash3D FWGS engine maintainer, creator of non-commercial Flying With Gauss organization.
|
||||
* Boosty page: https://boosty.to/a1ba
|
||||
|
||||
### [nekonomicon](https://github.com/nekonomicon)
|
||||
|
||||
* [hlsdk-portable](https://github.com/FWGS/hlsdk-portable), [mdldec](../utils/mdldec), [opensource-mods.md](opensource-mods.md) maintainer and Xash3D FWGS [contributor](https://github.com/FWGS/xash3d-fwgs/commits?author=nekonomicon) (*BSD/clang port, PNG support, etc).
|
||||
* Boosty page: https://boosty.to/nekonomicon
|
||||
|
||||
### [Velaron](https://github.com/Velaron)
|
||||
* [cs16-client](https://github.com/Velaron/cs16-client) & [tf15-client](https://github.com/Velaron/tf15-client) maintainer and Xash3D FWGS [contributor](https://github.com/FWGS/xash3d-fwgs/commits?author=Velaron) (Android port, voice chat, etc).
|
||||
* BuyMeACoffee page: https://www.buymeacoffee.com/velaron
|
||||
|
||||
### [SNMetamorph](https://github.com/SNMetamorph)
|
||||
* [PrimeXT](https://github.com/SNMetamorph/PrimeXT) & [GoldSrc Monitor](https://github.com/SNMetamorph/goldsrc-monitor) maintainer and Xash3D FWGS [contributor](https://github.com/FWGS/xash3d-fwgs/commits?author=SNMetamorph) (Windows port, voice chat, etc).
|
||||
* BTC: `16GAzK3qei5AwBW7sggXp3yNcFHBtdpxXj`
|
||||
* ETH (ERC20): `0xb580eeca9756e3881f9d6d026e28db28eb72a383`
|
||||
* USDT (ERC20): `0xb580eeca9756e3881f9d6d026e28db28eb72a383`
|
||||
* USDC (ERC20): `0xb580eeca9756e3881f9d6d026e28db28eb72a383`
|
||||
@@ -70,9 +70,11 @@ These strings are specific to Xash3D FWGS.
|
||||
|
||||
| Key | Type | Default value | Description |
|
||||
| ----------------------- | ---------- | ------------------------ | ----------- |
|
||||
| `animated_title` | boolean | 0 | Use animated title in main menu (WON Half-Life logo.avi imitation from Half-Life 25-th anniversary update)
|
||||
| `autosave_aged_count` | integer | 2 | Auto saves limit used in saves rotation |
|
||||
| `gamedll_linux` | string | Generated from `gamedll` | Game server DLL for 32-bit x86 Linux (see LibraryNaming.md for details) |
|
||||
| `gamedll_osx` | string | Generated from `gamedll` | Game server DLL for 32-bit x86 macOS (see LibraryNaming.md for details) |
|
||||
| `hd_background` | boolean | 0 | Use HD background for main menu (Half-Life 25-th anniversary update) |
|
||||
| `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 |
|
||||
@@ -88,6 +90,7 @@ The table below defines conversion rules from liblist.gam to gameinfo.txt. Some
|
||||
|
||||
| `liblist.gam` key | `gameinfo.txt` key | Note |
|
||||
| ----------------- | ------------------ | ---- |
|
||||
| `animated_title` | `animated_title` | |
|
||||
| `edicts` | `max_edicts` | |
|
||||
| `fallback_dir` | `fallback_dir` | |
|
||||
| `game` | `title` | |
|
||||
@@ -95,6 +98,7 @@ The table below defines conversion rules from liblist.gam to gameinfo.txt. Some
|
||||
| `gamedll` | `gamedll` | |
|
||||
| `gamedll_linux` | `gamedll_linux` | |
|
||||
| `gamedll_osx` | `gamedll_osx` | |
|
||||
| `hd_background` | `hd_background` | |
|
||||
| `icon` | `icon` | |
|
||||
| `mpentity` | `mp_entity` | |
|
||||
| `mpfilter` | `mp_filter` | |
|
||||
|
||||
@@ -133,22 +133,8 @@ Available in mod archive on ModDB - https://www.moddb.com/mods/overturn
|
||||
## Oz Deathmatch
|
||||
Mirrored on github - https://github.com/nekonomicon/OZDM
|
||||
|
||||
## Spirit of Half-Life
|
||||
[Logic&Trick's](https://github.com/LogicAndTrick) mirror - https://files.logic-and-trick.com/#/Half-Life/Mods/Spirit%20of%20Half-Life
|
||||
|
||||
## Threewave CTF
|
||||
*Unfinished mod by Valve Software*
|
||||
|
||||
Available in Valve's Half-Life repository with Deathmatch Classic sources - https://github.com/ValveSoftware/halflife/tree/master/dmc
|
||||
|
||||
## Trinity Render
|
||||
Available on ModDB: https://www.moddb.com/mods/half-life-episode-two/downloads/trinity-rendering-engine-v308f
|
||||
|
||||
## Tyrian: Ground Assault
|
||||
Available on ModDB: https://www.moddb.com/mods/tyriangroundassault/downloads/tyrianga-v1-0-src
|
||||
|
||||
## Paranoia
|
||||
Available on ModDB: https://www.moddb.com/mods/paranoia/downloads/paranoia-toolkit
|
||||
Available on ModDB - https://www.moddb.com/mods/paranoia/downloads/paranoia-toolkit
|
||||
|
||||
## Paranoia 2: The Savior
|
||||
Prealpha, mirrored on github - https://github.com/a1batross/Paranoia2_ancient
|
||||
@@ -163,12 +149,37 @@ Was found on HLFX - http://hlfx.ru/forum/showthread.php?s=2c892dfc52f72be52a89c3
|
||||
## Ricochet
|
||||
Available in Valve's Half-Life repository - https://github.com/ValveSoftware/halflife/tree/master/ricochet
|
||||
|
||||
## Spirit of Half-Life
|
||||
[Logic&Trick's](https://github.com/LogicAndTrick) mirror - https://files.logic-and-trick.com/#/Half-Life/Mods/Spirit%20of%20Half-Life
|
||||
|
||||
## The Wastes
|
||||
Version 1.5: mirrored on code.idtech.space - https://code.idtech.space/vera/halflife-thewastes-sdk
|
||||
|
||||
## Threewave CTF
|
||||
*Unfinished mod by Valve Software*
|
||||
|
||||
Available in Valve's Half-Life repository with Deathmatch Classic sources - https://github.com/ValveSoftware/halflife/tree/master/dmc
|
||||
|
||||
## Trinity Render
|
||||
Available on ModDB - https://www.moddb.com/mods/half-life-episode-two/downloads/trinity-rendering-engine-v308f
|
||||
|
||||
## Tyrian: Ground Assault
|
||||
Available on ModDB - https://www.moddb.com/mods/tyriangroundassault/downloads/tyrianga-v1-0-src
|
||||
|
||||
## Wasteland
|
||||
Mirrored on code.idtech.space - https://code.idtech.space/vera/halflife-wasteland-sdk
|
||||
|
||||
## Wizard Wars
|
||||
Download page on official site - http://www.thothie.com/ww/
|
||||
|
||||
## XashXT
|
||||
Mirrored on github - https://github.com/a1batross/XashXT_original
|
||||
|
||||
## Xen-Warrior
|
||||
*Source code is a part of Spirit of Half-Life 1.0-1.2 under XENWARRIOR macro*
|
||||
|
||||
[Logic&Trick's](https://github.com/LogicAndTrick) mirror - https://files.logic-and-trick.com/#/Half-Life/Mods/Spirit%20of%20Half-Life
|
||||
|
||||
## Zombie-X
|
||||
Available in mod archive on ModDB - https://www.moddb.com/mods/zombie-x-10-final/downloads/zombie-x-10-dle-beta6-last-version
|
||||
|
||||
@@ -190,12 +201,12 @@ malortie's recreation - https://github.com/malortie/hl-aom
|
||||
Branch **aom** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/aom
|
||||
|
||||
## Afraid of Monsters: Director's cut
|
||||
Reverse-engineered code, branch **aomdc** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/aomdc
|
||||
Reverse-engineered code: branch **aomdc** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/aomdc
|
||||
|
||||
## Azure Sheep
|
||||
malortie's recreation - https://github.com/malortie/hl-asheep
|
||||
|
||||
Reverse-engineered code, branch **asheep** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/asheep
|
||||
Reverse-engineered code: branch **asheep** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/asheep
|
||||
|
||||
## Big Lolly
|
||||
malortie's recreation - https://github.com/malortie/hl-biglolly
|
||||
@@ -217,7 +228,7 @@ Branch **caseclosed** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable
|
||||
Branch **CAd** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/CAd
|
||||
|
||||
## Counter Strike
|
||||
Reverse-engineered code of client part by a1batross - https://github.com/FWGS/cs16-client/tree/v1.32
|
||||
Reverse-engineered code of client part by a1batross - https://github.com/Velaron/cs16-client
|
||||
|
||||
Reverse-engineered code of server part by nagist - https://github.com/nagist/cs16nd
|
||||
|
||||
@@ -232,12 +243,17 @@ Recreation by lostgamer aka nillerusr - https://github.com/LostGamerHL/crack_lif
|
||||
## Escape from the Darkness
|
||||
malortie's recreation - https://github.com/malortie/hl-eftd
|
||||
|
||||
Reverse-engineered code, branch **eftd** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/eftd
|
||||
Reverse-engineered code: branch **eftd** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/eftd
|
||||
|
||||
## Half-Life: Black Guard
|
||||
*This mod uses dlls from Cleaner's Adventures*
|
||||
|
||||
Branch **CAd** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/CAd
|
||||
|
||||
## Half-Life: Blue Shift
|
||||
Unkle Mike's recreation - https://hlfx.ru/forum/showthread.php?s=&threadid=5253
|
||||
|
||||
Reverse-engineered code, branch **bshift** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/bshift
|
||||
Reverse-engineered code: branch **bshift** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/bshift
|
||||
|
||||
## Half-Life: Induction
|
||||
Branch **induction** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/induction
|
||||
@@ -245,12 +261,12 @@ Branch **induction** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/
|
||||
## Half-Life: Opposing Force
|
||||
Recreation by lostgamer aka nillerusr - https://github.com/LostGamerHL/hlsdk-xash3d
|
||||
|
||||
Reverse-engineered code, clean branch **opfor** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/opfor
|
||||
Reverse-engineered code: clean branch **opfor** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/opfor
|
||||
|
||||
Spirit of Half Life: Opposing-Force Edition - https://github.com/Hammermaps-DEV/SOHL-V1.9-Opposing-Force-Edition
|
||||
|
||||
## Half-Life: Rebellion
|
||||
Reverse-engineered code, branch **rebellion** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/rebellion
|
||||
Reverse-engineered code: branch **rebellion** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/rebellion
|
||||
|
||||
## Half-Life: Urbicide
|
||||
Branch **hl_urbicide** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/hl_urbicide
|
||||
@@ -258,7 +274,7 @@ Branch **hl_urbicide** in hlsdk-portable - https://github.com/FWGS/hlsdk-portabl
|
||||
## Half-Life: Visitors
|
||||
malortie's recreation - https://github.com/malortie/hl-visitors
|
||||
|
||||
Reverse-engineered code, branch **visitors** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/visitors
|
||||
Reverse-engineered code: branch **visitors** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/visitors
|
||||
|
||||
## Half-Secret
|
||||
Branch **half-secret** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/half-secret
|
||||
@@ -271,18 +287,18 @@ Branch **noffice** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tr
|
||||
## Poke 646
|
||||
malortie's recreation - https://github.com/malortie/hl-poke646
|
||||
|
||||
Reverse-engineered code, branch **poke646** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/poke646
|
||||
Reverse-engineered code: branch **poke646** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/poke646
|
||||
|
||||
## Poke 646: Vendetta
|
||||
malortie's recreation - https://github.com/malortie/hl-poke646-vendetta
|
||||
|
||||
Reverse-engineered code, branch **poke646_vendetta** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/poke646_vendetta
|
||||
Reverse-engineered code: branch **poke646_vendetta** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/poke646_vendetta
|
||||
|
||||
## Residual Life
|
||||
Reverse-engineered code, branch **residual_point** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/residual_point
|
||||
Reverse-engineered code: branch **residual_point** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/residual_point
|
||||
|
||||
## Residual Point
|
||||
Reverse-engineered code, branch **residual_point** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/residual_point
|
||||
Reverse-engineered code: branch **residual_point** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/residual_point
|
||||
|
||||
## Sewer Beta
|
||||
Branch **sewer_beta** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/sewer_beta
|
||||
@@ -293,12 +309,12 @@ Reverse-engineered code by Velaron - https://github.com/Velaron/tf15-client
|
||||
## The Gate
|
||||
malortie's recreation - https://github.com/malortie/hl-thegate
|
||||
|
||||
Reverse-engineered code, branch **thegate** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/thegate
|
||||
Reverse-engineered code: branch **thegate** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/thegate
|
||||
|
||||
## They Hunger
|
||||
malortie's recreation - https://github.com/malortie/hl-theyhunger
|
||||
|
||||
Reverse-engineered code, branch **theyhunger** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/theyhunger
|
||||
Reverse-engineered code: branch **theyhunger** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/theyhunger
|
||||
|
||||
They Hunger: Tactical - https://www.moddb.com/mods/they-hunger-tactical/downloads/tht-source-code-documentation
|
||||
|
||||
@@ -341,16 +357,22 @@ Branch **half-screwed** in hlsdk-portable - https://github.com/FWGS/hlsdk-portab
|
||||
Port to Linux - https://github.com/fmoraw/NS
|
||||
|
||||
## Spirit of Half-Life
|
||||
Version 1.2, branch **sohl1.2** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/sohl1.2
|
||||
Version 1.2: branch **sohl1.2** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/sohl1.2
|
||||
|
||||
## Swiss Cheese Halloween 2002
|
||||
Just more playable version by malortie - https://github.com/malortie/hl-shall
|
||||
|
||||
Branch **halloween** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/halloween
|
||||
|
||||
## The Wastes
|
||||
Version 1.5: Port to Linux - https://git.mentality.rip/a1batross/halflife-thewastes-sdk
|
||||
|
||||
## Threewave CTF
|
||||
Branch **dmc** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/dmc
|
||||
|
||||
## Xen-Warrior
|
||||
Branch **sohl1.2** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/sohl1.2
|
||||
|
||||
## Zombie-X
|
||||
Branch **zombie-x** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/zombie-x
|
||||
|
||||
|
||||
42
README.md
42
README.md
@@ -1,33 +1,27 @@
|
||||
# Xash3D FWGS Engine
|
||||
# Xash3D FWGS Engine <img align="right" width="128" height="128" src="https://github.com/FWGS/xash3d-fwgs/raw/master/game_launch/icon-xash-material.png" alt="Xash3D FWGS icon" />
|
||||
[](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml) [](https://cirrus-ci.com/github/FWGS/xash3d-fwgs) [](http://fwgsdiscord.mentality.rip/) \
|
||||
[](https://github.com/FWGS/xash3d-fwgs/releases/latest) [](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous)
|
||||
[](https://github.com/FWGS/xash3d-fwgs/releases/latest) [](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous)
|
||||
|
||||
Xash3D FWGS is a fork of Xash3D Engine by Unkle Mike with extended features and crossplatform.
|
||||
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 is a game engine, aimed to provide compatibility with Half-Life Engine,
|
||||
as well as to give game developers well known workflow and extend it.
|
||||
Read more about Xash3D on ModDB: https://www.moddb.com/engines/xash3d-engine
|
||||
```
|
||||
Xash3D FWGS is a heavily modified fork of an original [Xash3D Engine](https://www.moddb.com/engines/xash3d-engine) by Unkle Mike.
|
||||
|
||||
## Donate
|
||||
[](Documentation/donate.md) \
|
||||
If you like Xash3D FWGS, consider supporting individual engine maintainers. By supporting us, you help to continue developing this game engine further. The sponsorship links are available in [documentation](Documentation/donate.md).
|
||||
|
||||
## Fork features
|
||||
* HLSDK 2.4 support.
|
||||
* Crossplatform: supported x86 and ARM on Windows/Linux/BSD/Android. ([see docs for more info](Documentation/ports.md))
|
||||
* Modern compilers support: say no more to MSVC6.
|
||||
* Better multiplayer support: multiple master servers, headless dedicated server.
|
||||
* Mobility API: allows better game integration on mobile devices(vibration, touch controls)
|
||||
* Different input methods: touch, gamepad and classic mouse & keyboard.
|
||||
* Steam Half-Life (HLSDK 2.4) support.
|
||||
* Crossplatform and modern compilers support: supports Windows, Linux, BSD & Android on x86 & ARM and [many more](Documentation/ports.md).
|
||||
* Better multiplayer support: multiple master servers, headless dedicated server, voice chat and IPv6 support.
|
||||
* Multiple renderers support: OpenGL, GLESv1, GLESv2 and Software.
|
||||
* Advanced virtual filesystem: `.pk3` and `.pk3dir` support, compatibility with GoldSrc FS module, fast case-insensitivity emulation for crossplatform.
|
||||
* Mobility API: better game integration on mobile devices (vibration, touch controls)
|
||||
* Different input methods: touch and gamepad in addition to mouse & keyboard.
|
||||
* TrueType font rendering, as a part of mainui_cpp.
|
||||
* Multiple renderers support: OpenGL, GLESv1, GLESv2, Software.
|
||||
* Voice support.
|
||||
* External filesystem module like in GoldSrc engine.
|
||||
* External vgui support module.
|
||||
* PNG image format support.
|
||||
* A set of small improvements, without broken compatibility.
|
||||
|
||||
## Planned fork features
|
||||
* Virtual Reality support and game API.
|
||||
* Vulkan renderer.
|
||||
* External VGUI support module.
|
||||
* PNG & KTX2 image format support.
|
||||
* [A set of small improvements](Documentation/), without broken compatibility.
|
||||
|
||||
## Installation & Running
|
||||
0) Get Xash3D FWGS binaries: you can use [testing](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous) build or you can compile engine from source code.
|
||||
|
||||
@@ -9,7 +9,20 @@ NOTE: number at end of pixelformat name it's a total bitscount e.g. PF_RGB_24 ==
|
||||
========================================================================
|
||||
*/
|
||||
#define ImageRAW( type ) (type == PF_RGBA_32 || type == PF_BGRA_32 || type == PF_RGB_24 || type == PF_BGR_24 || type == PF_LUMINANCE)
|
||||
#define ImageDXT( type ) (type == PF_DXT1 || type == PF_DXT3 || type == PF_DXT5 || type == PF_ATI2 || type == PF_BC6H_SIGNED || type == PF_BC6H_UNSIGNED || type == PF_BC7)
|
||||
#define ImageCompressed( type ) \
|
||||
( type == PF_DXT1 \
|
||||
|| type == PF_DXT3 \
|
||||
|| type == PF_DXT5 \
|
||||
|| type == PF_ATI2 \
|
||||
|| type == PF_BC4_SIGNED \
|
||||
|| type == PF_BC4_UNSIGNED \
|
||||
|| type == PF_BC5_SIGNED \
|
||||
|| type == PF_BC5_UNSIGNED \
|
||||
|| type == PF_BC6H_SIGNED \
|
||||
|| type == PF_BC6H_UNSIGNED \
|
||||
|| type == PF_BC7_UNORM \
|
||||
|| type == PF_BC7_SRGB \
|
||||
|| type == PF_KTX2_RAW )
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@@ -25,9 +38,15 @@ typedef enum
|
||||
PF_DXT3, // s3tc DXT3/BC2 format
|
||||
PF_DXT5, // s3tc DXT5/BC3 format
|
||||
PF_ATI2, // latc ATI2N/BC5 format
|
||||
PF_BC4_SIGNED,
|
||||
PF_BC4_UNSIGNED,
|
||||
PF_BC5_SIGNED,
|
||||
PF_BC5_UNSIGNED,
|
||||
PF_BC6H_SIGNED, // bptc BC6H signed FP16 format
|
||||
PF_BC6H_UNSIGNED, // bptc BC6H unsigned FP16 format
|
||||
PF_BC7, // bptc BC7 format
|
||||
PF_BC7_UNORM, // bptc BC7 format
|
||||
PF_BC7_SRGB,
|
||||
PF_KTX2_RAW, // Raw KTX2 data, used for yet unsupported KTX2 subformats
|
||||
PF_TOTALCOUNT, // must be last
|
||||
} pixformat_t;
|
||||
|
||||
@@ -50,6 +69,7 @@ typedef enum
|
||||
IL_LOAD_DECAL = BIT(5), // special mode for load gradient decals
|
||||
IL_OVERVIEW = BIT(6), // overview required some unque operations
|
||||
IL_LOAD_PLAYER_DECAL = BIT(7), // special mode for player decals
|
||||
IL_KTX2_RAW = BIT(8), // renderer can consume raw KTX2 files (e.g. ref_vk)
|
||||
} ilFlags_t;
|
||||
|
||||
// goes into rgbdata_t->encode
|
||||
|
||||
@@ -189,4 +189,8 @@ Default build-depended cvar and constant values
|
||||
#define DEFAULT_FULLSCREEN "1" // must be a string
|
||||
#endif // DEFAULT_FULLSCREEN
|
||||
|
||||
#ifndef DEFAULT_MAX_EDICTS
|
||||
#define DEFAULT_MAX_EDICTS 1200 // was 900 before HL25
|
||||
#endif // DEFAULT_MAX_EDICTS
|
||||
|
||||
#endif // DEFAULTS_H
|
||||
|
||||
@@ -27,4 +27,16 @@ GNU General Public License for more details.
|
||||
#define ENGINE_COMPUTE_STUDIO_LERP (1<<7) // enable MOVETYPE_STEP lerping back in engine
|
||||
#define ENGINE_LINEAR_GAMMA_SPACE (1<<8) // disable influence of gamma/brightness cvars to textures/lightmaps, for mods with custom renderer
|
||||
|
||||
// adjust the mask when features will be added or removed
|
||||
#define ENGINE_FEATURES_MASK \
|
||||
( ENGINE_WRITE_LARGE_COORD \
|
||||
| ENGINE_QUAKE_COMPATIBLE \
|
||||
| ENGINE_LOAD_DELUXEDATA \
|
||||
| ENGINE_PHYSICS_PUSHER_EXT \
|
||||
| ENGINE_LARGE_LIGHTMAPS \
|
||||
| ENGINE_COMPENSATE_QUAKE_BUG \
|
||||
| ENGINE_IMPROVED_LINETRACE \
|
||||
| ENGINE_COMPUTE_STUDIO_LERP \
|
||||
| ENGINE_LINEAR_GAMMA_SPACE )
|
||||
|
||||
#endif//FEATURES_H
|
||||
|
||||
@@ -19,6 +19,8 @@ GNU General Public License for more details.
|
||||
#define GFL_NOMODELS (1<<0)
|
||||
#define GFL_NOSKILLS (1<<1)
|
||||
#define GFL_RENDER_PICBUTTON_TEXT (1<<2)
|
||||
#define GFL_HD_BACKGROUND (1<<3)
|
||||
#define GFL_ANIMATED_TITLE (1<<4)
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
|
||||
@@ -229,7 +229,7 @@ typedef struct render_api_s
|
||||
void (*R_Reserved0)( void );
|
||||
|
||||
// static allocations
|
||||
void *(*pfnMemAlloc)( size_t cb, const char *filename, const int fileline );
|
||||
void *(*pfnMemAlloc)( size_t cb, const char *filename, const int fileline ) ALLOC_CHECK( 1 );
|
||||
void (*pfnMemFree)( void *mem, const char *filename, const int fileline );
|
||||
|
||||
// engine utils (not related with render API but placed here)
|
||||
|
||||
@@ -57,6 +57,7 @@ typedef uint64_t longtime_t;
|
||||
#define MAX_USERMSG_LENGTH 2048 // don't modify it's relies on a client-side definitions
|
||||
|
||||
#define BIT( n ) ( 1U << ( n ))
|
||||
#define BIT64( n ) ( 1ULL << ( n ))
|
||||
#define GAMMA ( 2.2f ) // Valve Software gamma
|
||||
#define INVGAMMA ( 1.0f / 2.2f ) // back to 1.0
|
||||
#define TEXGAMMA ( 0.9f ) // compensate dim textures
|
||||
@@ -86,16 +87,22 @@ typedef uint64_t longtime_t;
|
||||
#endif
|
||||
#define _format(x) __attribute__((format(printf, x, x+1)))
|
||||
#define NORETURN __attribute__((noreturn))
|
||||
#define NONNULL __attribute__((nonnull))
|
||||
#define ALLOC_CHECK(x) __attribute__((alloc_size(x)))
|
||||
#elif defined(_MSC_VER)
|
||||
#define EXPORT __declspec( dllexport )
|
||||
#define GAME_EXPORT
|
||||
#define _format(x)
|
||||
#define NORETURN
|
||||
#define NONNULL
|
||||
#define ALLOC_CHECK(x)
|
||||
#else
|
||||
#define EXPORT
|
||||
#define GAME_EXPORT
|
||||
#define _format(x)
|
||||
#define NORETURN
|
||||
#define NONNULL
|
||||
#define ALLOC_CHECK(x)
|
||||
#endif
|
||||
|
||||
#if ( __GNUC__ >= 3 )
|
||||
@@ -114,7 +121,7 @@ typedef uint64_t longtime_t;
|
||||
#define likely(x) (x)
|
||||
#endif
|
||||
|
||||
#if defined( static_assert ) // C11 static_assert
|
||||
#if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L // C11 static_assert
|
||||
#define STATIC_ASSERT static_assert
|
||||
#else
|
||||
#define STATIC_ASSERT( x, y ) extern int _static_assert_##__LINE__[( x ) ? 1 : -1]
|
||||
@@ -177,6 +184,7 @@ typedef struct dll_info_s
|
||||
} dll_info_t;
|
||||
|
||||
typedef void (*setpair_t)( const char *key, const void *value, const void *buffer, void *numpairs );
|
||||
typedef void *(*pfnCreateInterface_t)( const char *, int * );
|
||||
|
||||
// config strings are a general means of communication from
|
||||
// the server to all connected clients.
|
||||
|
||||
@@ -85,6 +85,12 @@ void CL_PlayCDTrack_f( void )
|
||||
paused = false;
|
||||
looped = false;
|
||||
}
|
||||
else if( !Q_stricmp( command, "playfile" ))
|
||||
{
|
||||
S_StartBackgroundTrack( pszTrack, NULL, 0, true );
|
||||
paused = false;
|
||||
looped = false;
|
||||
}
|
||||
else if( !Q_stricmp( command, "loop" ))
|
||||
{
|
||||
if( Q_isdigit( pszTrack ))
|
||||
@@ -96,6 +102,12 @@ void CL_PlayCDTrack_f( void )
|
||||
paused = false;
|
||||
looped = true;
|
||||
}
|
||||
else if( !Q_stricmp( command, "loopfile" ))
|
||||
{
|
||||
S_StartBackgroundTrack( pszTrack, pszTrack, 0, true );
|
||||
paused = false;
|
||||
looped = true;
|
||||
}
|
||||
else if( !Q_stricmp( command, "pause" ))
|
||||
{
|
||||
S_StreamSetPause( true );
|
||||
|
||||
@@ -372,7 +372,7 @@ void CL_WriteDemoHeader( const char *name )
|
||||
demo.header.id = IDEMOHEADER;
|
||||
demo.header.dem_protocol = DEMO_PROTOCOL;
|
||||
demo.header.net_protocol = cls.legacymode ? PROTOCOL_LEGACY_VERSION : PROTOCOL_VERSION;
|
||||
demo.header.host_fps = bound( MIN_FPS, host_maxfps.value, MAX_FPS );
|
||||
demo.header.host_fps = host_maxfps.value ? bound( MIN_FPS, host_maxfps.value, MAX_FPS ) : MAX_FPS;
|
||||
Q_strncpy( demo.header.mapname, clgame.mapname, sizeof( demo.header.mapname ));
|
||||
Q_strncpy( demo.header.comment, clgame.maptitle, sizeof( demo.header.comment ));
|
||||
Q_strncpy( demo.header.gamedir, FS_Gamedir(), sizeof( demo.header.gamedir ));
|
||||
@@ -1124,7 +1124,10 @@ void CL_FinishTimeDemo( void )
|
||||
time = host.realtime - cls.td_starttime;
|
||||
if( !time ) time = 1.0;
|
||||
|
||||
Con_Printf( "%i frames %5.3f seconds %5.3f fps\n", frames, time, frames / time );
|
||||
Con_Printf( "timedemo result: %i frames %5.3f seconds %5.3f fps\n", frames, time, frames / time );
|
||||
|
||||
if( Sys_CheckParm( "-timedemo" ))
|
||||
CL_Quit_f();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1109,12 +1109,12 @@ void CL_InitEdicts( int maxclients )
|
||||
clgame.remap_info = (remap_info_t **)Mem_Calloc( clgame.mempool, sizeof( remap_info_t* ) * clgame.maxRemapInfos );
|
||||
}
|
||||
|
||||
ref.dllFuncs.R_ProcessEntData( true );
|
||||
ref.dllFuncs.R_ProcessEntData( true, clgame.entities, clgame.maxEntities );
|
||||
}
|
||||
|
||||
void CL_FreeEdicts( void )
|
||||
{
|
||||
ref.dllFuncs.R_ProcessEntData( false );
|
||||
ref.dllFuncs.R_ProcessEntData( false, NULL, 0 );
|
||||
|
||||
if( clgame.entities )
|
||||
Mem_Free( clgame.entities );
|
||||
@@ -1235,11 +1235,7 @@ static model_t *CL_LoadSpriteModel( const char *filename, uint type, uint texFla
|
||||
{
|
||||
char name[MAX_QPATH];
|
||||
model_t *mod;
|
||||
int i;
|
||||
|
||||
// use high indices for client sprites
|
||||
// for GoldSrc bug-compatibility
|
||||
const int start = type != SPR_HUDSPRITE ? MAX_CLIENT_SPRITES / 2 : 0;
|
||||
int i, start;
|
||||
|
||||
if( !COM_CheckString( filename ))
|
||||
{
|
||||
@@ -1250,7 +1246,7 @@ static model_t *CL_LoadSpriteModel( const char *filename, uint type, uint texFla
|
||||
Q_strncpy( name, filename, sizeof( name ));
|
||||
COM_FixSlashes( name );
|
||||
|
||||
for( i = 0, mod = clgame.sprites + start; i < MAX_CLIENT_SPRITES / 2; i++, mod++ )
|
||||
for( i = 0, mod = clgame.sprites; i < MAX_CLIENT_SPRITES; i++, mod++ )
|
||||
{
|
||||
if( !Q_stricmp( mod->name, name ))
|
||||
{
|
||||
@@ -1267,8 +1263,15 @@ static model_t *CL_LoadSpriteModel( const char *filename, uint type, uint texFla
|
||||
}
|
||||
|
||||
// find a free model slot spot
|
||||
for( i = 0, mod = clgame.sprites + start; i < MAX_CLIENT_SPRITES / 2; i++, mod++ )
|
||||
if( !mod->name[0] ) break; // this is a valid spot
|
||||
// use low indices only for HUD sprites
|
||||
// for GoldSrc bug compatibility
|
||||
start = type == SPR_HUDSPRITE ? 0 : MAX_CLIENT_SPRITES / 2;
|
||||
|
||||
for( i = 0, mod = &clgame.sprites[start]; i < MAX_CLIENT_SPRITES / 2; i++, mod++ )
|
||||
{
|
||||
if( !mod->name[0] )
|
||||
break; // this is a valid spot
|
||||
}
|
||||
|
||||
if( i == MAX_CLIENT_SPRITES / 2 )
|
||||
{
|
||||
@@ -1320,9 +1323,10 @@ HSPRITE pfnSPR_LoadExt( const char *szPicName, uint texFlags )
|
||||
=========
|
||||
pfnSPR_Load
|
||||
|
||||
function exported for support GoldSrc Monitor utility
|
||||
=========
|
||||
*/
|
||||
static HSPRITE GAME_EXPORT pfnSPR_Load( const char *szPicName )
|
||||
HSPRITE EXPORT pfnSPR_Load( const char *szPicName )
|
||||
{
|
||||
model_t *spr;
|
||||
|
||||
@@ -1368,9 +1372,10 @@ static const model_t *CL_GetSpritePointer( HSPRITE hSprite )
|
||||
=========
|
||||
pfnSPR_Frames
|
||||
|
||||
function exported for support GoldSrc Monitor utility
|
||||
=========
|
||||
*/
|
||||
static int GAME_EXPORT pfnSPR_Frames( HSPRITE hPic )
|
||||
int EXPORT pfnSPR_Frames( HSPRITE hPic )
|
||||
{
|
||||
int numFrames = 0;
|
||||
|
||||
@@ -3336,6 +3341,9 @@ static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags,
|
||||
if( remote_address->type != NA_IPX && remote_address->type != NA_BROADCAST_IPX )
|
||||
return; // IPX no longer support
|
||||
|
||||
if( request == NETAPI_REQUEST_SERVERLIST )
|
||||
return; // no support for server list requests
|
||||
|
||||
// find a free request
|
||||
for( i = 0; i < MAX_REQUESTS; i++ )
|
||||
{
|
||||
@@ -3372,28 +3380,9 @@ static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags,
|
||||
nr->resp.remote_address = *remote_address;
|
||||
nr->flags = flags;
|
||||
|
||||
if( request == NETAPI_REQUEST_SERVERLIST )
|
||||
{
|
||||
char fullquery[512];
|
||||
size_t len;
|
||||
|
||||
len = CL_BuildMasterServerScanRequest( fullquery, sizeof( fullquery ), false );
|
||||
|
||||
// make sure that port is specified
|
||||
if( !nr->resp.remote_address.port )
|
||||
nr->resp.remote_address.port = MSG_BigShort( PORT_MASTER );
|
||||
|
||||
// grab the list from the master server
|
||||
NET_SendPacket( NS_CLIENT, len, fullquery, nr->resp.remote_address );
|
||||
clgame.request_type = NET_REQUEST_CLIENT;
|
||||
clgame.master_request = nr; // holds the master request unitl the master acking
|
||||
}
|
||||
else
|
||||
{
|
||||
// local servers request
|
||||
Q_snprintf( req, sizeof( req ), "netinfo %i %i %i", PROTOCOL_VERSION, context, request );
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, nr->resp.remote_address, "%s", req );
|
||||
}
|
||||
// local servers request
|
||||
Q_snprintf( req, sizeof( req ), "netinfo %i %i %i", PROTOCOL_VERSION, context, request );
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, nr->resp.remote_address, "%s", req );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3421,13 +3410,6 @@ static void GAME_EXPORT NetAPI_CancelRequest( int context )
|
||||
nr->pfnFunc( &nr->resp );
|
||||
}
|
||||
|
||||
if( clgame.net_requests[i].resp.type == NETAPI_REQUEST_SERVERLIST && &clgame.net_requests[i] == clgame.master_request )
|
||||
{
|
||||
if( clgame.request_type == NET_REQUEST_CLIENT )
|
||||
clgame.request_type = NET_REQUEST_CANCEL;
|
||||
clgame.master_request = NULL;
|
||||
}
|
||||
|
||||
memset( &clgame.net_requests[i], 0, sizeof( net_request_t ));
|
||||
break;
|
||||
}
|
||||
@@ -3456,8 +3438,6 @@ void GAME_EXPORT NetAPI_CancelAllRequests( void )
|
||||
}
|
||||
|
||||
memset( clgame.net_requests, 0, sizeof( clgame.net_requests ));
|
||||
clgame.request_type = NET_REQUEST_CANCEL;
|
||||
clgame.master_request = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -414,11 +414,15 @@ static void UI_ConvertGameInfo( GAMEINFO *out, gameinfo_t *in )
|
||||
out->gamemode = in->gamemode;
|
||||
|
||||
if( in->nomodels )
|
||||
out->flags |= GFL_NOMODELS;
|
||||
SetBits( out->flags, GFL_NOMODELS );
|
||||
if( in->noskills )
|
||||
out->flags |= GFL_NOSKILLS;
|
||||
SetBits( out->flags, GFL_NOSKILLS );
|
||||
if( in->render_picbutton_text )
|
||||
out->flags |= GFL_RENDER_PICBUTTON_TEXT;
|
||||
SetBits( out->flags, GFL_RENDER_PICBUTTON_TEXT );
|
||||
if( in->hd_background )
|
||||
SetBits( out->flags, GFL_HD_BACKGROUND );
|
||||
if( in->animated_title )
|
||||
SetBits( out->flags, GFL_ANIMATED_TITLE );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -982,28 +986,21 @@ pfnCheckGameDll
|
||||
*/
|
||||
int GAME_EXPORT pfnCheckGameDll( void )
|
||||
{
|
||||
string dllpath;
|
||||
void *hInst;
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
// loading server library drains too many ram
|
||||
// so 512MB iPod Touch cannot even connect to
|
||||
// to servers in cstrike
|
||||
#ifdef XASH_INTERNAL_GAMELIBS
|
||||
return true;
|
||||
#endif
|
||||
#else
|
||||
string dllpath;
|
||||
|
||||
if( svgame.hInstance )
|
||||
return true;
|
||||
|
||||
COM_GetCommonLibraryPath( LIBRARY_SERVER, dllpath, sizeof( dllpath ));
|
||||
|
||||
if(( hInst = COM_LoadLibrary( dllpath, true, false )) != NULL )
|
||||
{
|
||||
COM_FreeLibrary( hInst ); // don't increase linker's reference counter
|
||||
if( FS_FileExists( dllpath, false ))
|
||||
return true;
|
||||
}
|
||||
Con_Reportf( S_WARN "Could not load server library: %s\n", COM_GetLibraryError() );
|
||||
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -34,7 +34,7 @@ GNU General Public License for more details.
|
||||
CVAR_DEFINE_AUTO( mp_decals, "300", FCVAR_ARCHIVE, "decals limit in multiplayer" );
|
||||
CVAR_DEFINE_AUTO( dev_overview, "0", 0, "draw level in overview-mode" );
|
||||
CVAR_DEFINE_AUTO( cl_resend, "6.0", 0, "time to resend connect" );
|
||||
CVAR_DEFINE_AUTO( cl_allow_download, "1", FCVAR_ARCHIVE, "allow to downloading resources from the server" );
|
||||
CVAR_DEFINE( cl_allow_download, "cl_allowdownload", "1", FCVAR_ARCHIVE, "allow to downloading resources from the server" );
|
||||
CVAR_DEFINE_AUTO( cl_allow_upload, "1", FCVAR_ARCHIVE, "allow to uploading resources to the server" );
|
||||
CVAR_DEFINE_AUTO( cl_download_ingame, "1", FCVAR_ARCHIVE, "allow to downloading resources while client is active" );
|
||||
CVAR_DEFINE_AUTO( cl_logofile, "lambda", FCVAR_ARCHIVE, "player logo name" );
|
||||
@@ -87,12 +87,13 @@ static CVAR_DEFINE_AUTO( model, "", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABL
|
||||
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" );
|
||||
static CVAR_DEFINE_AUTO( cl_maxframetime, "0", 0, "set deadline timer for client rendering to catch freezes" );
|
||||
|
||||
client_t cl;
|
||||
client_static_t cls;
|
||||
clgame_static_t clgame;
|
||||
|
||||
void CL_InternetServers_f( void );
|
||||
static void CL_SendMasterServerScanRequest( void );
|
||||
|
||||
//======================================================================
|
||||
int GAME_EXPORT CL_Active( void )
|
||||
@@ -1081,7 +1082,7 @@ void CL_CheckForResend( void )
|
||||
qboolean bandwidthTest;
|
||||
|
||||
if( cls.internetservers_wait )
|
||||
CL_InternetServers_f();
|
||||
CL_SendMasterServerScanRequest();
|
||||
|
||||
// if the local server is running and we aren't then connect
|
||||
if( cls.state == ca_disconnected && SV_Active( ))
|
||||
@@ -1574,10 +1575,10 @@ void CL_LocalServers_f( void )
|
||||
CL_BuildMasterServerScanRequest
|
||||
=================
|
||||
*/
|
||||
size_t CL_BuildMasterServerScanRequest( char *buf, size_t size, qboolean nat )
|
||||
static size_t NONNULL CL_BuildMasterServerScanRequest( char *buf, size_t size, uint32_t *key, qboolean nat, const char *filter )
|
||||
{
|
||||
size_t remaining;
|
||||
char *info;
|
||||
char *info, temp[32];
|
||||
|
||||
if( unlikely( size < sizeof( MS_SCAN_REQUEST )))
|
||||
return 0;
|
||||
@@ -1587,7 +1588,9 @@ size_t CL_BuildMasterServerScanRequest( char *buf, size_t size, qboolean nat )
|
||||
info = buf + sizeof( MS_SCAN_REQUEST ) - 1;
|
||||
remaining = size - sizeof( MS_SCAN_REQUEST );
|
||||
|
||||
info[0] = 0;
|
||||
Q_strncpy( info, filter, remaining );
|
||||
|
||||
*key = COM_RandomLong( 0, 0x7FFFFFFF );
|
||||
|
||||
#ifndef XASH_ALL_SERVERS
|
||||
Info_SetValueForKey( info, "gamedir", GI->gamefolder, remaining );
|
||||
@@ -1595,9 +1598,24 @@ size_t CL_BuildMasterServerScanRequest( char *buf, size_t size, qboolean nat )
|
||||
Info_SetValueForKey( info, "clver", XASH_VERSION, remaining ); // let master know about client version
|
||||
Info_SetValueForKey( info, "nat", nat ? "1" : "0", remaining );
|
||||
|
||||
Q_snprintf( temp, sizeof( temp ), "%x", *key );
|
||||
Info_SetValueForKey( info, "key", temp, remaining );
|
||||
|
||||
return sizeof( MS_SCAN_REQUEST ) + Q_strlen( info );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_SendMasterServerScanRequest
|
||||
=================
|
||||
*/
|
||||
static void CL_SendMasterServerScanRequest( void )
|
||||
{
|
||||
cls.internetservers_wait = NET_SendToMasters( NS_CLIENT,
|
||||
cls.internetservers_query_len, cls.internetservers_query );
|
||||
cls.internetservers_pending = true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_InternetServers_f
|
||||
@@ -1605,26 +1623,24 @@ CL_InternetServers_f
|
||||
*/
|
||||
void CL_InternetServers_f( void )
|
||||
{
|
||||
char fullquery[512];
|
||||
size_t len;
|
||||
qboolean nat = cl_nat.value != 0.0f;
|
||||
uint32_t key;
|
||||
|
||||
len = CL_BuildMasterServerScanRequest( fullquery, sizeof( fullquery ), nat );
|
||||
if( Cmd_Argc( ) > 2 || ( Cmd_Argc( ) == 2 && !Info_IsValid( Cmd_Argv( 1 ))))
|
||||
{
|
||||
Con_Printf( S_USAGE "internetservers [filter]\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
cls.internetservers_query_len = CL_BuildMasterServerScanRequest(
|
||||
cls.internetservers_query, sizeof( cls.internetservers_query ),
|
||||
&cls.internetservers_key, nat, Cmd_Argv( 1 ));
|
||||
|
||||
Con_Printf( "Scanning for servers on the internet area...\n" );
|
||||
|
||||
NET_Config( true, true ); // allow remote
|
||||
|
||||
cls.internetservers_wait = NET_SendToMasters( NS_CLIENT, len, fullquery );
|
||||
cls.internetservers_pending = true;
|
||||
|
||||
if( !cls.internetservers_wait )
|
||||
{
|
||||
// now we clearing the vgui request
|
||||
if( clgame.master_request != NULL )
|
||||
memset( clgame.master_request, 0, sizeof( net_request_t ));
|
||||
clgame.request_type = NET_REQUEST_GAMEUI;
|
||||
}
|
||||
CL_SendMasterServerScanRequest();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2152,6 +2168,25 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
||||
return;
|
||||
}
|
||||
|
||||
// check the extra header
|
||||
if( MSG_ReadByte( msg ) == 0x7f )
|
||||
{
|
||||
uint32_t key = MSG_ReadDword( msg );
|
||||
|
||||
if( cls.internetservers_key != key )
|
||||
{
|
||||
Con_Printf( S_WARN "unexpected server list packet from %s (invalid key)\n", NET_AdrToString( from ));
|
||||
return;
|
||||
}
|
||||
|
||||
MSG_ReadByte( msg ); // reserved byte
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_Printf( S_WARN "invalid server list packet from %s (missing extra header)\n", NET_AdrToString( from ));
|
||||
return;
|
||||
}
|
||||
|
||||
// serverlist got from masterserver
|
||||
while( MSG_GetNumBitsLeft( msg ) > 8 )
|
||||
{
|
||||
@@ -2161,58 +2196,10 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
||||
|
||||
// list is ends here
|
||||
if( !servadr.port )
|
||||
{
|
||||
if( clgame.request_type == NET_REQUEST_CLIENT && clgame.master_request != NULL )
|
||||
{
|
||||
net_request_t *nr = clgame.master_request;
|
||||
net_adrlist_t *list, **prev;
|
||||
|
||||
// setup the answer
|
||||
nr->resp.remote_address = from;
|
||||
nr->resp.error = NET_SUCCESS;
|
||||
nr->resp.ping = host.realtime - nr->timesend;
|
||||
|
||||
if( nr->timeout <= host.realtime )
|
||||
SetBits( nr->resp.error, NET_ERROR_TIMEOUT );
|
||||
|
||||
Con_Printf( "serverlist call: %s\n", NET_AdrToString( from ));
|
||||
nr->pfnFunc( &nr->resp );
|
||||
|
||||
// throw the list, now it will be stored in user area
|
||||
prev = (net_adrlist_t**)&nr->resp.response;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
list = *prev;
|
||||
if( !list ) break;
|
||||
|
||||
// throw out any variables the game created
|
||||
*prev = list->next;
|
||||
Mem_Free( list );
|
||||
}
|
||||
memset( nr, 0, sizeof( *nr )); // done
|
||||
clgame.request_type = NET_REQUEST_CANCEL;
|
||||
clgame.master_request = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if( clgame.request_type == NET_REQUEST_CLIENT && clgame.master_request != NULL )
|
||||
{
|
||||
net_request_t *nr = clgame.master_request;
|
||||
net_adrlist_t *list;
|
||||
|
||||
// adding addresses into list
|
||||
list = Z_Malloc( sizeof( *list ));
|
||||
list->remote_address = servadr;
|
||||
list->next = nr->resp.response;
|
||||
nr->resp.response = list;
|
||||
}
|
||||
else if( clgame.request_type == NET_REQUEST_GAMEUI )
|
||||
{
|
||||
NET_Config( true, false ); // allow remote
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, servadr, "info %i", PROTOCOL_VERSION );
|
||||
}
|
||||
NET_Config( true, false ); // allow remote
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, servadr, "info %i", PROTOCOL_VERSION );
|
||||
}
|
||||
|
||||
if( cls.internetservers_pending )
|
||||
@@ -2261,10 +2248,13 @@ void CL_ReadNetMessage( void )
|
||||
|
||||
while( CL_GetMessage( net_message_buffer, &curSize ))
|
||||
{
|
||||
if( cls.legacymode && *((int *)&net_message_buffer) == 0xFFFFFFFE )
|
||||
const int split_header = LittleLong( 0xFFFFFFFE );
|
||||
if( cls.legacymode && !memcmp( &split_header, net_message_buffer, sizeof( split_header )))
|
||||
{
|
||||
// Will rewrite existing packet by merged
|
||||
if( !NetSplit_GetLong( &cls.netchan.netsplit, &net_from, net_message_buffer, &curSize ) )
|
||||
continue;
|
||||
}
|
||||
|
||||
MSG_Init( &net_message, "ServerData", net_message_buffer, curSize );
|
||||
|
||||
@@ -2341,7 +2331,7 @@ void CL_ReadPackets( void )
|
||||
// decide the simulation time
|
||||
cl.oldtime = cl.time;
|
||||
|
||||
if( cls.demoplayback != DEMO_XASH3D && !cl.paused )
|
||||
if( !cl.paused )
|
||||
cl.time += host.frametime;
|
||||
|
||||
// demo time
|
||||
@@ -2928,6 +2918,7 @@ void CL_InitLocal( void )
|
||||
Cvar_RegisterVariable( &cl_showevents );
|
||||
Cvar_Get( "lastdemo", "", FCVAR_ARCHIVE, "last played demo" );
|
||||
Cvar_RegisterVariable( &ui_renderworld );
|
||||
Cvar_RegisterVariable( &cl_maxframetime );
|
||||
|
||||
// these two added to shut up CS 1.5 about 'unknown' commands
|
||||
Cvar_Get( "lightgamma", "1", FCVAR_ARCHIVE, "ambient lighting level (legacy, unused)" );
|
||||
@@ -3068,6 +3059,8 @@ void Host_ClientFrame( void )
|
||||
{
|
||||
// if client is not active, do nothing
|
||||
if( !cls.initialized ) return;
|
||||
if( cls.key_dest == key_game && cls.state == ca_active && !Con_Visible() )
|
||||
Platform_SetTimer( cl_maxframetime.value );
|
||||
|
||||
// if running the server remotely, send intentions now after
|
||||
// the incoming messages have been read
|
||||
|
||||
@@ -87,15 +87,6 @@ static int pfnDrawScaledCharacter( int x, int y, int number, int r, int g, int b
|
||||
return CL_DrawCharacter( x, y, number, color, &g_scaled_font, flags );
|
||||
}
|
||||
|
||||
static void *pfnGetNativeObject( const char *obj )
|
||||
{
|
||||
if( !obj )
|
||||
return NULL;
|
||||
|
||||
// Backend should consider that obj is case-sensitive
|
||||
return Platform_GetNativeObject( obj );
|
||||
}
|
||||
|
||||
static void pfnTouch_HideButtons( const char *name, byte state )
|
||||
{
|
||||
Touch_HideButtons( name, state, true );
|
||||
@@ -124,7 +115,7 @@ static mobile_engfuncs_t gpMobileEngfuncs =
|
||||
Touch_ResetDefaultButtons,
|
||||
pfnDrawScaledCharacter,
|
||||
Sys_Warn,
|
||||
pfnGetNativeObject,
|
||||
Sys_GetNativeObject,
|
||||
ID_SetCustomClientID,
|
||||
pfnParseFileSafe
|
||||
};
|
||||
|
||||
@@ -904,6 +904,10 @@ void CL_ParseServerData( sizebuf_t *msg, qboolean legacy )
|
||||
background = MSG_ReadOneBit( msg );
|
||||
Q_strncpy( gamefolder, MSG_ReadString( msg ), sizeof( gamefolder ));
|
||||
host.features = (uint)MSG_ReadLong( msg );
|
||||
host.features &= legacy ? ENGINE_LEGACY_FEATURES_MASK : ENGINE_FEATURES_MASK;
|
||||
|
||||
if( !Host_IsLocalGame( ))
|
||||
Host_PrintEngineFeatures( host.features );
|
||||
|
||||
if( !legacy )
|
||||
{
|
||||
@@ -1534,7 +1538,8 @@ void CL_SendConsistencyInfo( sizebuf_t *msg )
|
||||
{
|
||||
case force_exactfile:
|
||||
MD5_HashFile( md5, filename, NULL );
|
||||
pc->value = *(int *)md5;
|
||||
memcpy( &pc->value, md5, sizeof( pc->value ));
|
||||
LittleLongSW( pc->value );
|
||||
|
||||
if( user_changed_diskfile )
|
||||
MSG_WriteUBitLong( msg, 0, 32 );
|
||||
|
||||
@@ -265,8 +265,18 @@ void CL_LegacyParseResourceList( sizebuf_t *msg )
|
||||
}
|
||||
|
||||
if( CL_IsPlaybackDemo() )
|
||||
{
|
||||
return;
|
||||
|
||||
if( !cl_allow_download.value )
|
||||
{
|
||||
Con_DPrintf( "Refusing new resource, cl_allow_download set to 0\n" );
|
||||
reslist.rescount = 0;
|
||||
}
|
||||
|
||||
if( cls.state == ca_active && !cl_download_ingame.value )
|
||||
{
|
||||
Con_DPrintf( "Refusing new resource, cl_download_ingame set to 0\n" );
|
||||
reslist.rescount = 0;
|
||||
}
|
||||
|
||||
HTTP_ResetProcessState();
|
||||
|
||||
@@ -78,7 +78,7 @@ CL_CreateRawTextureFromPixels
|
||||
Convert texture_t struct into mstudiotexture_t prototype
|
||||
====================
|
||||
*/
|
||||
byte *CL_CreateRawTextureFromPixels( texture_t *tx, size_t *size, int topcolor, int bottomcolor )
|
||||
static byte *CL_CreateRawTextureFromPixels( texture_t *tx, size_t *size, int topcolor, int bottomcolor )
|
||||
{
|
||||
static mstudiotexture_t pin;
|
||||
byte *pal;
|
||||
@@ -111,7 +111,7 @@ CL_DuplicateTexture
|
||||
Dupliacte texture with remap pixels
|
||||
====================
|
||||
*/
|
||||
void CL_DuplicateTexture( cl_entity_t *entity, model_t *model, mstudiotexture_t *ptexture, int topcolor, int bottomcolor )
|
||||
static void CL_DuplicateTexture( cl_entity_t *entity, model_t *model, mstudiotexture_t *ptexture, int topcolor, int bottomcolor )
|
||||
{
|
||||
const char *name;
|
||||
texture_t *tx = NULL;
|
||||
@@ -154,7 +154,7 @@ CL_UpdateStudioTexture
|
||||
Update texture top and bottom colors
|
||||
====================
|
||||
*/
|
||||
void CL_UpdateStudioTexture( cl_entity_t *entity, mstudiotexture_t *ptexture, int topcolor, int bottomcolor )
|
||||
static void CL_UpdateStudioTexture( cl_entity_t *entity, mstudiotexture_t *ptexture, int topcolor, int bottomcolor )
|
||||
{
|
||||
rgbdata_t *pic;
|
||||
texture_t *tx = NULL;
|
||||
@@ -215,7 +215,7 @@ CL_UpdateAliasTexture
|
||||
Update texture top and bottom colors
|
||||
====================
|
||||
*/
|
||||
void CL_UpdateAliasTexture( cl_entity_t *entity, unsigned short *texture, int skinnum, int topcolor, int bottomcolor )
|
||||
static void CL_UpdateAliasTexture( cl_entity_t *entity, unsigned short *texture, int skinnum, int topcolor, int bottomcolor )
|
||||
{
|
||||
char texname[MAX_QPATH];
|
||||
rgbdata_t skin, *pic;
|
||||
@@ -247,6 +247,68 @@ void CL_UpdateAliasTexture( cl_entity_t *entity, unsigned short *texture, int sk
|
||||
ref.dllFuncs.GL_ProcessTexture( *texture, -1.0f, topcolor, bottomcolor );
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_FreeRemapInfo
|
||||
|
||||
Release remap info per entity
|
||||
====================
|
||||
*/
|
||||
static void CL_FreeRemapInfo( remap_info_t *info )
|
||||
{
|
||||
int i;
|
||||
|
||||
Assert( info != NULL );
|
||||
|
||||
// release all colormap texture copies
|
||||
for( i = 0; i < info->numtextures; i++ )
|
||||
{
|
||||
if( info->ptexture != NULL )
|
||||
{
|
||||
if( FBitSet( info->ptexture[i].flags, STUDIO_NF_COLORMAP ))
|
||||
ref.dllFuncs.GL_FreeTexture( info->ptexture[i].index );
|
||||
}
|
||||
|
||||
if( info->textures[i] != 0 )
|
||||
ref.dllFuncs.GL_FreeTexture( info->textures[i] );
|
||||
}
|
||||
|
||||
Mem_Free( info ); // release struct
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_UpdateRemapInfo
|
||||
|
||||
Update all remaps per entity
|
||||
====================
|
||||
*/
|
||||
static void CL_UpdateRemapInfo( cl_entity_t *entity, int topcolor, int bottomcolor )
|
||||
{
|
||||
remap_info_t *info;
|
||||
int i;
|
||||
|
||||
i = ( entity == &clgame.viewent ) ? clgame.maxEntities : entity->curstate.number;
|
||||
info = clgame.remap_info[i];
|
||||
if( !info ) return; // no remap info
|
||||
|
||||
if( info->topcolor == topcolor && info->bottomcolor == bottomcolor )
|
||||
return; // values is valid
|
||||
|
||||
for( i = 0; i < info->numtextures; i++ )
|
||||
{
|
||||
if( info->ptexture != NULL )
|
||||
{
|
||||
if( FBitSet( info->ptexture[i].flags, STUDIO_NF_COLORMAP ))
|
||||
CL_UpdateStudioTexture( entity, &info->ptexture[i], topcolor, bottomcolor );
|
||||
}
|
||||
else CL_UpdateAliasTexture( entity, &info->textures[i], i, topcolor, bottomcolor );
|
||||
}
|
||||
|
||||
info->topcolor = topcolor;
|
||||
info->bottomcolor = bottomcolor;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_AllocRemapInfo
|
||||
@@ -255,7 +317,7 @@ Allocate new remap info per entity
|
||||
and make copy of remap textures
|
||||
====================
|
||||
*/
|
||||
void CL_AllocRemapInfo( cl_entity_t *entity, model_t *model, int topcolor, int bottomcolor )
|
||||
static void CL_AllocRemapInfo( cl_entity_t *entity, model_t *model, int topcolor, int bottomcolor )
|
||||
{
|
||||
remap_info_t *info;
|
||||
studiohdr_t *phdr;
|
||||
@@ -362,68 +424,6 @@ void CL_AllocRemapInfo( cl_entity_t *entity, model_t *model, int topcolor, int b
|
||||
info->model = model;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_UpdateRemapInfo
|
||||
|
||||
Update all remaps per entity
|
||||
====================
|
||||
*/
|
||||
void CL_UpdateRemapInfo( cl_entity_t *entity, int topcolor, int bottomcolor )
|
||||
{
|
||||
remap_info_t *info;
|
||||
int i;
|
||||
|
||||
i = ( entity == &clgame.viewent ) ? clgame.maxEntities : entity->curstate.number;
|
||||
info = clgame.remap_info[i];
|
||||
if( !info ) return; // no remap info
|
||||
|
||||
if( info->topcolor == topcolor && info->bottomcolor == bottomcolor )
|
||||
return; // values is valid
|
||||
|
||||
for( i = 0; i < info->numtextures; i++ )
|
||||
{
|
||||
if( info->ptexture != NULL )
|
||||
{
|
||||
if( FBitSet( info->ptexture[i].flags, STUDIO_NF_COLORMAP ))
|
||||
CL_UpdateStudioTexture( entity, &info->ptexture[i], topcolor, bottomcolor );
|
||||
}
|
||||
else CL_UpdateAliasTexture( entity, &info->textures[i], i, topcolor, bottomcolor );
|
||||
}
|
||||
|
||||
info->topcolor = topcolor;
|
||||
info->bottomcolor = bottomcolor;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_FreeRemapInfo
|
||||
|
||||
Release remap info per entity
|
||||
====================
|
||||
*/
|
||||
void CL_FreeRemapInfo( remap_info_t *info )
|
||||
{
|
||||
int i;
|
||||
|
||||
Assert( info != NULL );
|
||||
|
||||
// release all colormap texture copies
|
||||
for( i = 0; i < info->numtextures; i++ )
|
||||
{
|
||||
if( info->ptexture != NULL )
|
||||
{
|
||||
if( FBitSet( info->ptexture[i].flags, STUDIO_NF_COLORMAP ))
|
||||
ref.dllFuncs.GL_FreeTexture( info->ptexture[i].index );
|
||||
}
|
||||
|
||||
if( info->textures[i] != 0 )
|
||||
ref.dllFuncs.GL_FreeTexture( info->textures[i] );
|
||||
}
|
||||
|
||||
Mem_Free( info ); // release struct
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_ClearAllRemaps
|
||||
@@ -446,3 +446,21 @@ void CL_ClearAllRemaps( void )
|
||||
}
|
||||
clgame.remap_info = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CL_EntitySetRemapColors
|
||||
=============
|
||||
*/
|
||||
qboolean CL_EntitySetRemapColors( cl_entity_t *e, model_t *mod, int top, int bottom )
|
||||
{
|
||||
CL_AllocRemapInfo( e, mod, top, bottom );
|
||||
|
||||
if( CL_GetRemapInfoForEntity( e ))
|
||||
{
|
||||
CL_UpdateRemapInfo( e, top, bottom );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -207,6 +207,8 @@ intptr_t CL_RenderGetParm( const int parm, const int arg, const qboolean checkRe
|
||||
return pfnNumberOfEntities();
|
||||
case PARM_NUMMODELS:
|
||||
return cl.nummodels;
|
||||
case PARM_WORLD_VERSION:
|
||||
return world.version;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -726,6 +726,7 @@ void SCR_VidInit( void )
|
||||
|
||||
// restart console size
|
||||
Con_VidInit ();
|
||||
Touch_NotifyResize();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -2665,7 +2665,7 @@ void CL_UpdateFlashlight( cl_entity_t *ent )
|
||||
// update flashlight endpos
|
||||
dl = CL_AllocDlight( ent->index );
|
||||
#if 1
|
||||
hit = CL_GetEntityByIndex( clgame.pmove->visents[trace.ent].info );
|
||||
hit = CL_GetEntityByIndex( clgame.pmove->physents[trace.ent].info );
|
||||
if( hit && hit->model && ( hit->model->type == mod_alias || hit->model->type == mod_studio ))
|
||||
VectorCopy( hit->origin, dl->origin );
|
||||
else VectorCopy( trace.endpos, dl->origin );
|
||||
|
||||
@@ -202,7 +202,6 @@ SCR_PlayCinematic
|
||||
*/
|
||||
qboolean SCR_PlayCinematic( const char *arg )
|
||||
{
|
||||
string path;
|
||||
const char *fullpath;
|
||||
|
||||
fullpath = FS_GetDiskPath( arg, false );
|
||||
|
||||
@@ -549,5 +549,6 @@ void V_PostRender( void )
|
||||
|
||||
SCR_MakeScreenShot();
|
||||
ref.dllFuncs.R_AllowFog( true );
|
||||
Platform_SetTimer( 0.0f );
|
||||
ref.dllFuncs.R_EndFrame();
|
||||
}
|
||||
|
||||
@@ -423,13 +423,6 @@ typedef struct
|
||||
float applied_angle;
|
||||
} screen_shake_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NET_REQUEST_CANCEL = 0, // request was cancelled for some reasons
|
||||
NET_REQUEST_GAMEUI, // called from GameUI
|
||||
NET_REQUEST_CLIENT, // called from Client
|
||||
} net_request_type_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
net_response_t resp;
|
||||
@@ -491,9 +484,7 @@ typedef struct
|
||||
client_textmessage_t *titles; // title messages, not network messages
|
||||
int numTitles;
|
||||
|
||||
net_request_type_t request_type; // filter the requests
|
||||
net_request_t net_requests[MAX_REQUESTS]; // no reason to keep more
|
||||
net_request_t *master_request; // queued master request
|
||||
|
||||
efrag_t *free_efrags; // linked efrags
|
||||
cl_entity_t viewent; // viewmodel
|
||||
@@ -627,7 +618,10 @@ typedef struct
|
||||
file_t *demofile;
|
||||
file_t *demoheader; // contain demo startup info in case we record a demo on this level
|
||||
qboolean internetservers_wait; // internetservers is waiting for dns request
|
||||
qboolean internetservers_pending; // internetservers is waiting for dns request
|
||||
qboolean internetservers_pending; // if true, clean master server pings
|
||||
uint32_t internetservers_key; // compare key to validate master server reply
|
||||
char internetservers_query[512]; // cached query
|
||||
uint32_t internetservers_query_len;
|
||||
|
||||
// legacy mode support
|
||||
qboolean legacymode; // one-way 48 protocol compatibility
|
||||
@@ -765,7 +759,6 @@ int CL_IsDevOverviewMode( void );
|
||||
void CL_PingServers_f( void );
|
||||
void CL_SignonReply( void );
|
||||
void CL_ClearState( void );
|
||||
size_t CL_BuildMasterServerScanRequest( char *buf, size_t size, qboolean nat );
|
||||
|
||||
//
|
||||
// cl_demo.c
|
||||
@@ -1003,9 +996,7 @@ void CL_EmitEntities( void );
|
||||
// cl_remap.c
|
||||
//
|
||||
remap_info_t *CL_GetRemapInfoForEntity( cl_entity_t *e );
|
||||
void CL_AllocRemapInfo( cl_entity_t *entity, model_t *model, int topcolor, int bottomcolor );
|
||||
void CL_FreeRemapInfo( remap_info_t *info );
|
||||
void CL_UpdateRemapInfo( cl_entity_t *ent, int topcolor, int bottomcolor );
|
||||
qboolean CL_EntitySetRemapColors( cl_entity_t *e, model_t *mod, int top, int bottom );
|
||||
void CL_ClearAllRemaps( void );
|
||||
|
||||
//
|
||||
|
||||
@@ -1983,7 +1983,7 @@ void Con_DrawConsole( void )
|
||||
|
||||
if( cls.state == ca_connecting || cls.state == ca_connected )
|
||||
{
|
||||
if( !cl_allow_levelshots.value )
|
||||
if( !cl_allow_levelshots.value && !cls.timedemo )
|
||||
{
|
||||
if(( Cvar_VariableInteger( "cl_background" ) || Cvar_VariableInteger( "sv_background" )) && cls.key_dest != key_console )
|
||||
con.vislines = con.showlines = 0;
|
||||
@@ -1993,7 +1993,7 @@ void Con_DrawConsole( void )
|
||||
{
|
||||
con.showlines = 0;
|
||||
|
||||
if( host_developer.value >= DEV_EXTENDED )
|
||||
if( host_developer.value >= DEV_EXTENDED && !cls.timedemo )
|
||||
Con_DrawNotify(); // draw notify lines
|
||||
}
|
||||
}
|
||||
@@ -2025,7 +2025,7 @@ void Con_DrawConsole( void )
|
||||
{
|
||||
if( con.vislines )
|
||||
Con_DrawSolidConsole( con.vislines );
|
||||
else if( cls.state == ca_active && ( cls.key_dest == key_game || cls.key_dest == key_message ))
|
||||
else if( cls.state == ca_active && ( cls.key_dest == key_game || cls.key_dest == key_message ) && !cls.timedemo )
|
||||
Con_DrawNotify(); // draw notify lines
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -132,6 +132,8 @@ static struct touch_s
|
||||
int whitetexture;
|
||||
int joytexture; // touch indicator
|
||||
qboolean configchanged;
|
||||
float actual_aspect_ratio; // maximum aspect ratio from launch, or aspect ratio when entering editor
|
||||
float config_aspect_ratio; // aspect ratio set by command from config or after entering editor
|
||||
} touch;
|
||||
|
||||
// private to the engine flags
|
||||
@@ -168,13 +170,42 @@ CVAR_DEFINE_AUTO( touch_emulate, "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "emulate
|
||||
#define B(x) (button->x)
|
||||
#define SCR_W ((float)refState.width)
|
||||
#define SCR_H ((float)refState.height)
|
||||
#define TO_SCRN_Y(x) (refState.height * (x))
|
||||
#define TO_SCRN_Y(x) (refState.width * (x) * Touch_AspectRatio())
|
||||
#define TO_SCRN_X(x) (refState.width * (x))
|
||||
|
||||
static void IN_TouchCheckCoords( float *x1, float *y1, float *x2, float *y2 );
|
||||
static void IN_TouchEditClear( void );
|
||||
static void Touch_InitConfig( void );
|
||||
|
||||
void Touch_NotifyResize( void )
|
||||
{
|
||||
if( refState.width && refState.height && ( !touch.configchanged || !touch.actual_aspect_ratio ))
|
||||
{
|
||||
float aspect_ratio = SCR_H/SCR_W;
|
||||
if( aspect_ratio < 0.99 && aspect_ratio > touch.actual_aspect_ratio )
|
||||
touch.actual_aspect_ratio = aspect_ratio;
|
||||
}
|
||||
}
|
||||
|
||||
static inline float Touch_AspectRatio( void )
|
||||
{
|
||||
if( touch.config_aspect_ratio )
|
||||
return touch.config_aspect_ratio;
|
||||
else if( touch.actual_aspect_ratio )
|
||||
return touch.actual_aspect_ratio;
|
||||
else if( refState.width && refState.height )
|
||||
return SCR_H/SCR_W;
|
||||
else
|
||||
return 9.0f / 16.0f;
|
||||
}
|
||||
|
||||
|
||||
static void Touch_ConfigAspectRatio_f( void )
|
||||
{
|
||||
touch.config_aspect_ratio = Q_atof( Cmd_Argv( 1 ));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==========================
|
||||
Touch_ExportButtonToConfig
|
||||
@@ -206,7 +237,7 @@ static inline int Touch_ExportButtonToConfig( file_t *f, touch_button_t *button,
|
||||
|
||||
if( keepAspect )
|
||||
{
|
||||
float aspect = ( B(y2) - B(y1) ) / ( ( B(x2) - B(x1) ) /(SCR_H/SCR_W) );
|
||||
float aspect = ( B(y2) - B(y1) ) / ( ( B(x2) - B(x1) ) /(Touch_AspectRatio()) );
|
||||
FS_Printf( f, " %f\n", aspect );
|
||||
}
|
||||
else FS_Printf( f, "\n" );
|
||||
@@ -271,6 +302,8 @@ qboolean Touch_DumpConfig( const char *name, const char *profilename )
|
||||
FS_Printf( f, "touch_setclientonly 0\n" );
|
||||
FS_Printf( f, "\n// touch buttons\n" );
|
||||
FS_Printf( f, "touch_removeall\n" );
|
||||
FS_Printf( f, "touch_aspectratio %f\n", Touch_AspectRatio());
|
||||
|
||||
|
||||
for( button = touch.list_user.first; button; button = button->next )
|
||||
{
|
||||
@@ -376,7 +409,7 @@ static void Touch_GenerateCode_f( void )
|
||||
if( FBitSet( flags, TOUCH_FL_DEF_HIDE ))
|
||||
SetBits( flags, TOUCH_FL_HIDE );
|
||||
|
||||
aspect = ( B(y2) - B(y1) ) / ( ( B(x2) - B(x1) ) /(SCR_H/SCR_W) );
|
||||
aspect = ( B(y2) - B(y1) ) / ( ( B(x2) - B(x1) ) /(Touch_AspectRatio()) );
|
||||
if( memcmp( &c, &B(color), sizeof( rgba_t ) ) )
|
||||
{
|
||||
Con_Printf( "unsigned char color[] = { %d, %d, %d, %d };\n", B(color[0]), B(color[1]), B(color[2]), B(color[3]) );
|
||||
@@ -549,6 +582,7 @@ static void Touch_RemoveAll_f( void )
|
||||
{
|
||||
IN_TouchEditClear();
|
||||
Touch_ClearList( &touch.list_user );
|
||||
touch.config_aspect_ratio = 0.0f;
|
||||
}
|
||||
|
||||
static void Touch_SetColor( touchbuttonlist_t *list, const char *name, byte *color )
|
||||
@@ -726,6 +760,8 @@ static void Touch_SetCommand_f( void )
|
||||
Con_Printf( S_USAGE "touch_setcommand <name> <command>\n" );
|
||||
}
|
||||
|
||||
static void Touch_LoadDefaults_f( void );
|
||||
|
||||
static void Touch_ReloadConfig_f( void )
|
||||
{
|
||||
touch.state = state_none;
|
||||
@@ -735,8 +771,15 @@ static void Touch_ReloadConfig_f( void )
|
||||
touch.selection->finger = -1;
|
||||
touch.edit = touch.selection = NULL;
|
||||
touch.resize_finger = touch.move_finger = touch.look_finger = touch.wheel_finger = -1;
|
||||
|
||||
Cbuf_AddTextf( "exec %s\n", touch_config_file.string );
|
||||
if( FS_FileExists( touch_config_file.string, true ) )
|
||||
{
|
||||
Cbuf_AddTextf( "exec \"%s\"\n", touch_config_file.string );
|
||||
}
|
||||
else
|
||||
{
|
||||
Touch_LoadDefaults_f();
|
||||
touch.configchanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
static touch_button_t *Touch_AddButton( touchbuttonlist_t *list,
|
||||
@@ -784,7 +827,7 @@ void Touch_AddClientButton( const char *name, const char *texture, const char *c
|
||||
IN_TouchCheckCoords( &x1, &y1, &x2, &y2 );
|
||||
if( round == round_aspect )
|
||||
{
|
||||
y2 = y1 + ( x2 - x1 ) * (SCR_W/SCR_H) * aspect;
|
||||
y2 = y1 + ( x2 - x1 ) / (Touch_AspectRatio()) * aspect;
|
||||
}
|
||||
button = Touch_AddButton( &touch.list_user, name, texture, command, x1, y1, x2, y2, color, true );
|
||||
button->flags |= flags | TOUCH_FL_CLIENT | TOUCH_FL_NOEDIT;
|
||||
@@ -809,7 +852,7 @@ static void Touch_LoadDefaults_f( void )
|
||||
if( g_DefaultButtons[i].texturefile[0] == '#' )
|
||||
y2 = y1 + ( (float)clgame.scrInfo.iCharHeight / (float)clgame.scrInfo.iHeight ) * g_DefaultButtons[i].aspect + touch.swidth*2/SCR_H;
|
||||
else
|
||||
y2 = y1 + ( x2 - x1 ) * (SCR_W/SCR_H) * g_DefaultButtons[i].aspect;
|
||||
y2 = y1 + (( x2 - x1 ) / Touch_AspectRatio()) * g_DefaultButtons[i].aspect;
|
||||
}
|
||||
|
||||
IN_TouchCheckCoords( &x1, &y1, &x2, &y2 );
|
||||
@@ -817,6 +860,7 @@ static void Touch_LoadDefaults_f( void )
|
||||
button->flags |= g_DefaultButtons[i].flags;
|
||||
button->aspect = g_DefaultButtons[i].aspect;
|
||||
}
|
||||
touch.configchanged = true;
|
||||
}
|
||||
|
||||
// Add default button from client
|
||||
@@ -909,7 +953,7 @@ static void Touch_AddButton_f( void )
|
||||
if( aspect )
|
||||
{
|
||||
if( B( texturefile )[0] != '#' )
|
||||
B( y2 ) = B( y1 ) + ( B( x2 ) - B( x1 )) * ( SCR_W / SCR_H ) * aspect;
|
||||
B( y2 ) = B( y1 ) + (( B( x2 ) - B( x1 )) / Touch_AspectRatio() ) * aspect;
|
||||
B( aspect ) = aspect;
|
||||
}
|
||||
}
|
||||
@@ -917,11 +961,39 @@ static void Touch_AddButton_f( void )
|
||||
|
||||
static void Touch_EnableEdit_f( void )
|
||||
{
|
||||
touch_button_t *button;
|
||||
float current_ratio = SCR_H/SCR_W;
|
||||
if( touch.state == state_none )
|
||||
touch.state = state_edit;
|
||||
touch.resize_finger = touch.move_finger = touch.look_finger = touch.wheel_finger = -1;
|
||||
touch.move_button = NULL;
|
||||
touch.configchanged = true;
|
||||
/* try determine the best ratio
|
||||
* User enters editor. Window now have correct size. Need to fix aspect ratio in some cases */
|
||||
// Case A: no config was loaded, touch was generated with lower height, but window was resized higher, reset it to actual size
|
||||
if( touch.actual_aspect_ratio > current_ratio )
|
||||
touch.actual_aspect_ratio = current_ratio;
|
||||
if( !touch.config_aspect_ratio )
|
||||
touch.config_aspect_ratio = touch.actual_aspect_ratio;
|
||||
// Case B: config was loaded, but window may be resized later, so keep y coordinate as is
|
||||
touch.actual_aspect_ratio = current_ratio;
|
||||
// convert coordinates to actual aspect ratio after it was updated
|
||||
if( touch.config_aspect_ratio != touch.actual_aspect_ratio )
|
||||
{
|
||||
for( button = touch.list_user.first; button; button = button->next )
|
||||
{
|
||||
B(y1) /= touch.actual_aspect_ratio / touch.config_aspect_ratio;
|
||||
B(y2) /= touch.actual_aspect_ratio / touch.config_aspect_ratio;
|
||||
|
||||
// clamp positions to make buttons visible by user
|
||||
if( B(y2) > 1.0f )
|
||||
{
|
||||
B(y1) -= B(y2) - 1.0f;
|
||||
B(y2) -= B(y2) - 1.0f;
|
||||
}
|
||||
}
|
||||
touch.config_aspect_ratio = touch.actual_aspect_ratio;
|
||||
}
|
||||
}
|
||||
|
||||
static void Touch_DisableEdit_f( void )
|
||||
@@ -956,7 +1028,7 @@ static void Touch_DeleteProfile_f( void )
|
||||
|
||||
static void Touch_InitEditor( void )
|
||||
{
|
||||
float x = 0.1f * (SCR_H/SCR_W);
|
||||
float x = 0.1f * (Touch_AspectRatio());
|
||||
float y = 0.05f;
|
||||
touch_button_t *temp;
|
||||
rgba_t color;
|
||||
@@ -1051,6 +1123,7 @@ void Touch_Init( void )
|
||||
Cmd_AddRestrictedCommand( "touch_generate_code", Touch_GenerateCode_f, "create code sample for mobility API" );
|
||||
Cmd_AddCommand( "touch_fade", Touch_Fade_f, "start fade animation for selected buttons" );
|
||||
Cmd_AddRestrictedCommand( "touch_toggleselection", Touch_ToggleSelection_f, "toggle vidibility on selected button in editor" );
|
||||
Cmd_AddRestrictedCommand( "touch_aspectratio", Touch_ConfigAspectRatio_f, "set current aspect ratio" );
|
||||
|
||||
// not saved, just runtime state for scripting
|
||||
Cvar_RegisterVariable( &touch_in_menu );
|
||||
@@ -1087,7 +1160,7 @@ void Touch_Init( void )
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 10 )
|
||||
SDL_SetHint( SDL_HINT_MOUSE_TOUCH_EVENTS, "0" );
|
||||
SDL_SetHint( SDL_HINT_TOUCH_MOUSE_EVENTS, "0" );
|
||||
#else
|
||||
#elif defined(SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH)
|
||||
SDL_SetHint( SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1" );
|
||||
#endif
|
||||
|
||||
@@ -1170,9 +1243,9 @@ static void Touch_DrawTexture ( float x1, float y1, float x2, float y2, int text
|
||||
}
|
||||
|
||||
#define GRID_COUNT_X ((int)touch_grid_count.value)
|
||||
#define GRID_COUNT_Y (((int)touch_grid_count.value) * SCR_H / SCR_W)
|
||||
#define GRID_COUNT_Y (((int)touch_grid_count.value) * Touch_AspectRatio())
|
||||
#define GRID_X (1.0f/GRID_COUNT_X)
|
||||
#define GRID_Y (SCR_W/SCR_H/GRID_COUNT_X)
|
||||
#define GRID_Y (1.0f/Touch_AspectRatio()/GRID_COUNT_X)
|
||||
#define GRID_ROUND_X(x) ((float)round( x * GRID_COUNT_X ) / GRID_COUNT_X)
|
||||
#define GRID_ROUND_Y(x) ((float)round( x * GRID_COUNT_Y ) / GRID_COUNT_Y)
|
||||
|
||||
@@ -1250,7 +1323,7 @@ static float Touch_DrawText( float x1, float y1, float x2, float y2, const char
|
||||
{
|
||||
while( *s && ( *s != '\n' ) && ( *s != ';' ) && ( x1 < maxx ) )
|
||||
x1 += Touch_DrawCharacter( x1, y1, *s++, size );
|
||||
y1 += cls.creditsFont.charHeight / 1024.f * size / SCR_H * SCR_W;
|
||||
y1 += cls.creditsFont.charHeight / 1024.f * size / Touch_AspectRatio();
|
||||
|
||||
if( y1 >= maxy )
|
||||
break;
|
||||
@@ -1357,11 +1430,12 @@ void Touch_Draw( void )
|
||||
if( !touch.initialized || ( !touch_enable.value && !touch.clientonly ))
|
||||
return;
|
||||
|
||||
Touch_InitConfig();
|
||||
|
||||
if( cls.key_dest != key_game && !touch_in_menu.value )
|
||||
return;
|
||||
|
||||
Touch_InitConfig();
|
||||
|
||||
|
||||
ref.dllFuncs.GL_SetRenderMode( kRenderTransTexture );
|
||||
|
||||
if( touch.state >= state_edit && touch_grid_enable.value )
|
||||
@@ -1948,6 +2022,8 @@ static int Touch_ControlsEvent( touchEventType type, int fingerID, float x, floa
|
||||
|
||||
int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy )
|
||||
{
|
||||
y *= SCR_H/SCR_W/Touch_AspectRatio();
|
||||
// Con_Printf("%f %f\n", TO_SCRN_X(x), TO_SCRN_Y(y));
|
||||
// simulate menu mouse click
|
||||
if( cls.key_dest != key_game && !touch_in_menu.value )
|
||||
{
|
||||
|
||||
@@ -192,6 +192,10 @@ void IN_ToggleClientMouse( int newstate, int oldstate )
|
||||
#endif
|
||||
}
|
||||
|
||||
// don't leave the user without cursor if they enabled m_ignore
|
||||
if( m_ignore.value )
|
||||
return;
|
||||
|
||||
if( oldstate == key_game )
|
||||
{
|
||||
IN_DeactivateMouse();
|
||||
@@ -212,6 +216,9 @@ void IN_CheckMouseState( qboolean active )
|
||||
qboolean useRawInput = true; // always use SDL code
|
||||
#endif
|
||||
|
||||
if( m_ignore.value )
|
||||
return;
|
||||
|
||||
if( active && useRawInput && !host.mouse_visible && cls.state == ca_active )
|
||||
{
|
||||
if( !s_bRawInput )
|
||||
|
||||
@@ -75,6 +75,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 );
|
||||
void Touch_NotifyResize( void );
|
||||
|
||||
//
|
||||
// in_joy.c
|
||||
|
||||
@@ -659,7 +659,7 @@ static void make_hull_windings( hull_t *hull, hull_model_t *model )
|
||||
Con_Reportf( "%i hull polys\n", model->num_polys );
|
||||
}
|
||||
|
||||
void Mod_InitDebugHulls( void )
|
||||
void Mod_InitDebugHulls( model_t *loadmodel )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ CVAR_DEFINE_AUTO( gl_msaa_samples, "0", FCVAR_GLCONFIG, "samples number for mult
|
||||
CVAR_DEFINE_AUTO( gl_clear, "0", FCVAR_ARCHIVE, "clearing screen after each frame" );
|
||||
CVAR_DEFINE_AUTO( r_showtree, "0", FCVAR_ARCHIVE, "build the graph of visible BSP tree" );
|
||||
static CVAR_DEFINE_AUTO( r_refdll, "", FCVAR_RENDERINFO, "choose renderer implementation, if supported" );
|
||||
static CVAR_DEFINE_AUTO( r_refdll_loaded, "", FCVAR_READ_ONLY, "currently loaded renderer" );
|
||||
|
||||
void R_GetTextureParms( int *w, int *h, int texnum )
|
||||
{
|
||||
@@ -98,24 +99,14 @@ static void *pfnMod_Extradata( int type, model_t *m )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static model_t *pfnMod_GetCurrentLoadingModel( void )
|
||||
{
|
||||
return loadmodel;
|
||||
}
|
||||
|
||||
static void pfnMod_SetCurrentLoadingModel( model_t *m )
|
||||
{
|
||||
loadmodel = m;
|
||||
}
|
||||
|
||||
static void pfnGetPredictedOrigin( vec3_t v )
|
||||
{
|
||||
VectorCopy( cl.simorg, v );
|
||||
}
|
||||
|
||||
static color24 *pfnCL_GetPaletteColor( int color ) // clgame.palette[color]
|
||||
static color24 *pfnCL_GetPaletteColor( void ) // clgame.palette[color]
|
||||
{
|
||||
return &clgame.palette[color];
|
||||
return clgame.palette;
|
||||
}
|
||||
|
||||
static void pfnCL_GetScreenInfo( int *width, int *height ) // clgame.scrInfo, ptrs may be NULL
|
||||
@@ -167,11 +158,6 @@ static int pfnGetStudioModelInterface( int version, struct r_studio_interface_s
|
||||
0;
|
||||
}
|
||||
|
||||
static poolhandle_t pfnImage_GetPool( void )
|
||||
{
|
||||
return host.imagepool;
|
||||
}
|
||||
|
||||
static const bpc_desc_t *pfnImage_GetPFDesc( int idx )
|
||||
{
|
||||
return &PFDesc[idx];
|
||||
@@ -221,6 +207,11 @@ static qboolean R_Init_Video_( const int type )
|
||||
return R_Init_Video( type );
|
||||
}
|
||||
|
||||
static model_t **pfnGetModels( void )
|
||||
{
|
||||
return cl.models;
|
||||
}
|
||||
|
||||
static ref_api_t gEngfuncs =
|
||||
{
|
||||
pfnEngineGetParm,
|
||||
@@ -255,9 +246,7 @@ static ref_api_t gEngfuncs =
|
||||
Con_DrawString,
|
||||
CL_DrawCenterPrint,
|
||||
|
||||
CL_GetLocalPlayer,
|
||||
CL_GetViewModel,
|
||||
CL_GetEntityByIndex,
|
||||
R_BeamGetEntity,
|
||||
CL_GetWaterEntity,
|
||||
CL_AddVisibleEntity,
|
||||
@@ -281,14 +270,10 @@ static ref_api_t gEngfuncs =
|
||||
|
||||
Mod_ForName,
|
||||
pfnMod_Extradata,
|
||||
CL_ModelHandle,
|
||||
pfnMod_GetCurrentLoadingModel,
|
||||
pfnMod_SetCurrentLoadingModel,
|
||||
pfnGetModels,
|
||||
|
||||
CL_EntitySetRemapColors,
|
||||
CL_GetRemapInfoForEntity,
|
||||
CL_AllocRemapInfo,
|
||||
CL_FreeRemapInfo,
|
||||
CL_UpdateRemapInfo,
|
||||
|
||||
CL_ExtraUpdate,
|
||||
Host_Error,
|
||||
@@ -296,7 +281,6 @@ static ref_api_t gEngfuncs =
|
||||
COM_RandomFloat,
|
||||
COM_RandomLong,
|
||||
pfnRefGetScreenFade,
|
||||
CL_TextMessageGet,
|
||||
pfnGetPredictedOrigin,
|
||||
pfnCL_GetPaletteColor,
|
||||
pfnCL_GetScreenInfo,
|
||||
@@ -360,7 +344,6 @@ static ref_api_t gEngfuncs =
|
||||
FS_CopyImage,
|
||||
FS_FreeImage,
|
||||
Image_SetMDLPointer,
|
||||
pfnImage_GetPool,
|
||||
pfnImage_GetPFDesc,
|
||||
|
||||
pfnDrawNormalTriangles,
|
||||
@@ -442,7 +425,7 @@ static qboolean R_LoadProgs( const char *name )
|
||||
// make local copy of engfuncs to prevent overwrite it with user dll
|
||||
memcpy( &gpEngfuncs, &gEngfuncs, sizeof( gpEngfuncs ));
|
||||
|
||||
if( !GetRefAPI( REF_API_VERSION, &ref.dllFuncs, &gpEngfuncs, &refState ))
|
||||
if( GetRefAPI( REF_API_VERSION, &ref.dllFuncs, &gpEngfuncs, &refState ) != REF_API_VERSION )
|
||||
{
|
||||
COM_FreeLibrary( ref.hInstance );
|
||||
Con_Reportf( "R_LoadProgs: can't init renderer API: wrong version\n" );
|
||||
@@ -531,6 +514,7 @@ static qboolean R_LoadRenderer( const char *refopt )
|
||||
return false;
|
||||
}
|
||||
|
||||
Cvar_FullSet( "r_refdll_loaded", refopt, FCVAR_READ_ONLY );
|
||||
Con_Reportf( "Renderer %s initialized\n", refdll );
|
||||
|
||||
return true;
|
||||
@@ -579,6 +563,9 @@ static void R_CollectRendererNames( void )
|
||||
#if XASH_REF_GL4ES_ENABLED
|
||||
"gl4es",
|
||||
#endif
|
||||
#if XASH_REF_GLES3COMPAT_ENABLED
|
||||
"gles3compat",
|
||||
#endif
|
||||
#if XASH_REF_SOFT_ENABLED
|
||||
"soft",
|
||||
#endif
|
||||
@@ -599,6 +586,9 @@ static void R_CollectRendererNames( void )
|
||||
#if XASH_REF_GL4ES_ENABLED
|
||||
"GL4ES",
|
||||
#endif
|
||||
#if XASH_REF_GLES3COMPAT_ENABLED
|
||||
"GLES3 (gl2_shim)"
|
||||
#endif
|
||||
#if XASH_REF_SOFT_ENABLED
|
||||
"Software",
|
||||
#endif
|
||||
@@ -622,6 +612,7 @@ qboolean R_Init( void )
|
||||
Cvar_RegisterVariable( &gl_clear );
|
||||
Cvar_RegisterVariable( &r_showtree );
|
||||
Cvar_RegisterVariable( &r_refdll );
|
||||
Cvar_RegisterVariable( &r_refdll_loaded );
|
||||
|
||||
// cvars that are expected to exist
|
||||
Cvar_Get( "r_speeds", "0", FCVAR_ARCHIVE, "shows renderer speeds" );
|
||||
|
||||
@@ -381,6 +381,7 @@ typedef void (*xcommand_t)( void );
|
||||
qboolean FS_LoadProgs( void );
|
||||
void FS_Init( void );
|
||||
void FS_Shutdown( void );
|
||||
void *FS_GetNativeObject( const char *obj );
|
||||
|
||||
//
|
||||
// cmd.c
|
||||
@@ -421,8 +422,8 @@ void Cmd_Escape( char *newCommand, const char *oldCommand, int len );
|
||||
// zone.c
|
||||
//
|
||||
void Memory_Init( void );
|
||||
void *_Mem_Realloc( poolhandle_t poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline );
|
||||
void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline );
|
||||
void *_Mem_Realloc( poolhandle_t poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline ) ALLOC_CHECK( 3 );
|
||||
void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline ) ALLOC_CHECK( 2 );
|
||||
poolhandle_t _Mem_AllocPool( const char *name, const char *filename, int fileline );
|
||||
void _Mem_FreePool( poolhandle_t *poolptr, const char *filename, int fileline );
|
||||
void _Mem_EmptyPool( poolhandle_t poolptr, const char *filename, int fileline );
|
||||
@@ -551,7 +552,7 @@ qboolean Host_IsLocalGame( void );
|
||||
qboolean Host_IsLocalClient( void );
|
||||
void Host_ShutdownServer( void );
|
||||
void Host_Error( const char *error, ... ) _format( 1 );
|
||||
void Host_PrintEngineFeatures( void );
|
||||
void Host_PrintEngineFeatures( int features );
|
||||
void Host_Frame( float time );
|
||||
void Host_InitDecals( void );
|
||||
void Host_Credits( void );
|
||||
@@ -747,8 +748,6 @@ void SV_ShutdownGame( void );
|
||||
void SV_ExecLoadLevel( void );
|
||||
void SV_ExecLoadGame( void );
|
||||
void SV_ExecChangeLevel( void );
|
||||
qboolean SV_InitGameProgs( void );
|
||||
void SV_FreeGameProgs( void );
|
||||
void CL_WriteMessageHistory( void );
|
||||
void CL_SendCmd( void );
|
||||
void CL_Disconnect( void );
|
||||
@@ -794,7 +793,7 @@ void VID_Init( void );
|
||||
void UI_SetActiveMenu( qboolean fActive );
|
||||
void UI_ShowConnectionWarning( void );
|
||||
void Cmd_Null_f( void );
|
||||
void Rcon_Print( const char *pMsg );
|
||||
void Rcon_Print( host_redirect_t *rd, const char *pMsg );
|
||||
qboolean COM_ParseVector( char **pfile, float *v, size_t size );
|
||||
void COM_NormalizeAngles( vec3_t angles );
|
||||
int COM_FileSize( const char *filename );
|
||||
|
||||
@@ -1423,15 +1423,11 @@ save serverinfo variables into server.cfg (using for dedicated server too)
|
||||
*/
|
||||
void GAME_EXPORT Host_WriteServerConfig( const char *name )
|
||||
{
|
||||
qboolean already_loaded;
|
||||
file_t *f;
|
||||
string newconfigfile;
|
||||
|
||||
Q_snprintf( newconfigfile, MAX_STRING, "%s.new", name );
|
||||
|
||||
// TODO: remove this mechanism, make it safer for now
|
||||
already_loaded = SV_InitGameProgs(); // collect user variables
|
||||
|
||||
// FIXME: move this out until menu parser is done
|
||||
CSCR_LoadDefaultCVars( "settings.scr" );
|
||||
|
||||
@@ -1448,10 +1444,6 @@ void GAME_EXPORT Host_WriteServerConfig( const char *name )
|
||||
Host_FinalizeConfig( f, name );
|
||||
}
|
||||
else Con_DPrintf( S_ERROR "Couldn't write %s.\n", name );
|
||||
|
||||
// don't unload library that wasn't loaded by us
|
||||
if( !already_loaded )
|
||||
SV_FreeGameProgs(); // release progs with all variables
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -320,7 +320,9 @@ void Sys_RestoreCrashHandler( void )
|
||||
|
||||
#elif XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD || XASH_ANDROID || XASH_LINUX
|
||||
// Posix signal handler
|
||||
#ifndef XASH_OPENBSD
|
||||
#include <ucontext.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include <sys/mman.h>
|
||||
#include "library.h"
|
||||
@@ -488,7 +490,7 @@ static void Sys_Crash( int signal, siginfo_t *si, void *context)
|
||||
#ifdef XASH_SDL
|
||||
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
|
||||
#endif
|
||||
MSGBOX( message );
|
||||
Platform_MessageBox( "Xash Error", message, false );
|
||||
|
||||
// log saved, now we can try to save configs and close log correctly, it may crash
|
||||
if( host.type == HOST_NORMAL )
|
||||
|
||||
@@ -1136,8 +1136,6 @@ As Cvar_Set, but also flags it as glconfig
|
||||
*/
|
||||
void Cvar_SetGL_f( void )
|
||||
{
|
||||
convar_t *var;
|
||||
|
||||
if( Cmd_Argc() != 3 )
|
||||
{
|
||||
Con_Printf( S_USAGE "setgl <variable> <value>\n" );
|
||||
|
||||
@@ -23,8 +23,17 @@ GNU General Public License for more details.
|
||||
fs_api_t g_fsapi;
|
||||
fs_globals_t *FI;
|
||||
|
||||
static pfnCreateInterface_t fs_pfnCreateInterface;
|
||||
static HINSTANCE fs_hInstance;
|
||||
|
||||
void *FS_GetNativeObject( const char *obj )
|
||||
{
|
||||
if( fs_pfnCreateInterface )
|
||||
return fs_pfnCreateInterface( obj, NULL );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void FS_Rescan_f( void )
|
||||
{
|
||||
FS_Rescan();
|
||||
@@ -53,7 +62,7 @@ static fs_interface_t fs_memfuncs =
|
||||
_Mem_Realloc,
|
||||
_Mem_Free,
|
||||
|
||||
Platform_GetNativeObject,
|
||||
Sys_GetNativeObject,
|
||||
};
|
||||
|
||||
static void FS_UnloadProgs( void )
|
||||
@@ -98,6 +107,13 @@ qboolean FS_LoadProgs( void )
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !( fs_pfnCreateInterface = (pfnCreateInterface_t)COM_GetProcAddress( fs_hInstance, "CreateInterface" )))
|
||||
{
|
||||
FS_UnloadProgs();
|
||||
Host_Error( "FS_LoadProgs: can't find CreateInterface entry point in %s\n", name );
|
||||
return false;
|
||||
}
|
||||
|
||||
Con_DPrintf( "FS_LoadProgs: filesystem_stdio successfully loaded\n" );
|
||||
|
||||
return true;
|
||||
|
||||
@@ -33,6 +33,7 @@ GNU General Public License for more details.
|
||||
#include "common.h"
|
||||
#include "base_cmd.h"
|
||||
#include "client.h"
|
||||
#include "server.h"
|
||||
#include "netchan.h"
|
||||
#include "protocol.h"
|
||||
#include "mod_local.h"
|
||||
@@ -51,7 +52,7 @@ struct tests_stats_s tests_stats;
|
||||
#endif
|
||||
|
||||
CVAR_DEFINE( host_developer, "developer", "0", FCVAR_FILTERABLE, "engine is in development-mode" );
|
||||
CVAR_DEFINE_AUTO( sys_timescale, "1.0", FCVAR_CHEAT|FCVAR_FILTERABLE, "scale frame time" );
|
||||
CVAR_DEFINE_AUTO( sys_timescale, "1.0", FCVAR_FILTERABLE, "scale frame time" );
|
||||
CVAR_DEFINE_AUTO( sys_ticrate, "100", 0, "framerate in dedicated mode" );
|
||||
|
||||
static CVAR_DEFINE_AUTO( host_serverstate, "0", FCVAR_READ_ONLY, "displays current server state" );
|
||||
@@ -61,6 +62,7 @@ CVAR_DEFINE_AUTO( host_limitlocal, "0", 0, "apply cl_cmdrate and rate to loopbac
|
||||
CVAR_DEFINE( host_maxfps, "fps_max", "72", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "host fps upper limit" );
|
||||
static CVAR_DEFINE_AUTO( host_framerate, "0", FCVAR_FILTERABLE, "locks frame timing to this value in seconds" );
|
||||
static CVAR_DEFINE( host_sleeptime, "sleeptime", "1", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "milliseconds to sleep for each frame. higher values reduce fps accuracy" );
|
||||
static CVAR_DEFINE_AUTO( host_sleeptime_debug, "0", 0, "print sleeps between frames" );
|
||||
CVAR_DEFINE( con_gamemaps, "con_mapfilter", "1", FCVAR_ARCHIVE, "when true show only maps in game folder" );
|
||||
|
||||
void Sys_PrintUsage( void )
|
||||
@@ -127,6 +129,7 @@ void Sys_PrintUsage( void )
|
||||
O("-noenginejoy ", "disable engine builtin joystick support")
|
||||
O("-noenginemouse ", "disable engine builtin mouse support")
|
||||
O("-nosound ", "disable sound output")
|
||||
O("-timedemo ", "run timedemo and exit")
|
||||
#endif
|
||||
|
||||
"\nPlatform-specific options:\n"
|
||||
@@ -137,7 +140,7 @@ void Sys_PrintUsage( void )
|
||||
O("-sdl_joy_old_api ","use SDL legacy joystick API")
|
||||
O("-sdl_renderer <n>","use alternative SDL_Renderer for software")
|
||||
#endif // XASH_SDL
|
||||
#if XASH_ANDROID
|
||||
#if XASH_ANDROID && !XASH_SDL
|
||||
O("-nativeegl ","use native egl implementation. Use if screen does not update or black")
|
||||
#endif // XASH_ANDROID
|
||||
#if XASH_DOS
|
||||
@@ -187,22 +190,27 @@ void Host_ShutdownServer( void )
|
||||
Host_PrintEngineFeatures
|
||||
================
|
||||
*/
|
||||
void Host_PrintEngineFeatures( void )
|
||||
void Host_PrintEngineFeatures( int features )
|
||||
{
|
||||
if( FBitSet( host.features, ENGINE_WRITE_LARGE_COORD ))
|
||||
Con_Reportf( "^3EXT:^7 big world support enabled\n" );
|
||||
const char *features_str[] =
|
||||
{
|
||||
"Big World Support",
|
||||
"Quake Compatibility",
|
||||
"Deluxemap Support",
|
||||
"Improved MOVETYPE_PUSH",
|
||||
"Large Lightmaps",
|
||||
"Stupid Quake Bug Compensation",
|
||||
"Improved Trace Line",
|
||||
"Studio MOVETYPE_STEP Lerping",
|
||||
"Linear Gamma Space"
|
||||
};
|
||||
int i;
|
||||
|
||||
if( FBitSet( host.features, ENGINE_LOAD_DELUXEDATA ))
|
||||
Con_Reportf( "^3EXT:^7 deluxemap support enabled\n" );
|
||||
|
||||
if( FBitSet( host.features, ENGINE_PHYSICS_PUSHER_EXT ))
|
||||
Con_Reportf( "^3EXT:^7 Improved MOVETYPE_PUSH is used\n" );
|
||||
|
||||
if( FBitSet( host.features, ENGINE_LARGE_LIGHTMAPS ))
|
||||
Con_Reportf( "^3EXT:^7 Large lightmaps enabled\n" );
|
||||
|
||||
if( FBitSet( host.features, ENGINE_COMPENSATE_QUAKE_BUG ))
|
||||
Con_Reportf( "^3EXT:^7 Compensate quake bug enabled\n" );
|
||||
for( i = 0; i < ARRAYSIZE( features_str ); i++ )
|
||||
{
|
||||
if( FBitSet( features, BIT( i )))
|
||||
Con_Reportf( "^3EXT:^7 %s is enabled\n", features_str[i] );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -616,6 +624,84 @@ double Host_CalcFPS( void )
|
||||
return fps;
|
||||
}
|
||||
|
||||
static qboolean Host_Autosleep( double dt, double scale )
|
||||
{
|
||||
double targetframetime, fps;
|
||||
int sleep;
|
||||
|
||||
fps = Host_CalcFPS();
|
||||
|
||||
if( fps <= 0 )
|
||||
return true;
|
||||
|
||||
// limit fps to withing tolerable range
|
||||
fps = bound( MIN_FPS, fps, MAX_FPS );
|
||||
|
||||
if( Host_IsDedicated( ))
|
||||
targetframetime = ( 1.0 / ( fps + 1.0 ));
|
||||
else targetframetime = ( 1.0 / fps );
|
||||
|
||||
sleep = Host_CalcSleep();
|
||||
if( sleep == 0 ) // no sleeps between frames, much simpler code
|
||||
{
|
||||
if( dt < targetframetime * scale )
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
static double timewindow; // allocate a time window for sleeps
|
||||
static int counter; // for debug
|
||||
static double realsleeptime;
|
||||
const double sleeptime = sleep * 0.001;
|
||||
|
||||
if( dt < targetframetime * scale )
|
||||
{
|
||||
// if we have allocated time window, try to sleep
|
||||
if( timewindow > realsleeptime )
|
||||
{
|
||||
// Sys_Sleep isn't guaranteed to sleep an exact amount of milliseconds
|
||||
// so we measure the real sleep time and use it to decrease the window
|
||||
double t1 = Sys_DoubleTime(), t2;
|
||||
Sys_Sleep( sleep ); // in msec!
|
||||
t2 = Sys_DoubleTime();
|
||||
realsleeptime = t2 - t1;
|
||||
|
||||
timewindow -= realsleeptime;
|
||||
|
||||
if( host_sleeptime_debug.value )
|
||||
{
|
||||
counter++;
|
||||
|
||||
Con_NPrintf( counter, "%d: %.4f %.4f", counter, timewindow, realsleeptime );
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// if we exhausted this time window, allocate a new one after new frame
|
||||
if( timewindow <= realsleeptime )
|
||||
{
|
||||
double targetsleeptime = targetframetime - host.pureframetime * 2;
|
||||
|
||||
if( targetsleeptime > 0 )
|
||||
timewindow = targetsleeptime;
|
||||
else timewindow = 0;
|
||||
|
||||
realsleeptime = sleeptime; // reset in case CPU was too busy
|
||||
|
||||
if( host_sleeptime_debug.value )
|
||||
{
|
||||
counter = 0;
|
||||
|
||||
Con_NPrintf( 0, "tgt = %.4f, pft = %.4f, wnd = %.4f", targetframetime, host.pureframetime, timewindow );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
Host_FilterTime
|
||||
@@ -626,55 +712,15 @@ Returns false if the time is too short to run a frame
|
||||
qboolean Host_FilterTime( float time )
|
||||
{
|
||||
static double oldtime;
|
||||
double fps, scale = sys_timescale.value;
|
||||
double dt;
|
||||
double scale = sys_timescale.value;
|
||||
|
||||
host.realtime += time * scale;
|
||||
fps = Host_CalcFPS();
|
||||
dt = host.realtime - oldtime;
|
||||
|
||||
// clamp the fps in multiplayer games
|
||||
if( fps != 0.0 )
|
||||
{
|
||||
static int sleeps;
|
||||
double targetframetime;
|
||||
int sleeptime = Host_CalcSleep();
|
||||
|
||||
// limit fps to withing tolerable range
|
||||
fps = bound( MIN_FPS, fps, MAX_FPS );
|
||||
|
||||
if( Host_IsDedicated( ))
|
||||
targetframetime = ( 1.0 / ( fps + 1.0 ));
|
||||
else targetframetime = ( 1.0 / fps );
|
||||
|
||||
if(( host.realtime - oldtime ) < targetframetime * scale )
|
||||
{
|
||||
if( sleeptime > 0 && sleeps > 0 )
|
||||
{
|
||||
Sys_Sleep( sleeptime );
|
||||
sleeps--;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( sleeptime > 0 && sleeps <= 0 )
|
||||
{
|
||||
if( host.status == HOST_FRAME )
|
||||
{
|
||||
// give few sleeps this frame with small margin
|
||||
double targetsleeptime = targetframetime - host.pureframetime * 2;
|
||||
|
||||
// don't sleep if we can't keep up with the framerate
|
||||
if( targetsleeptime > 0 )
|
||||
sleeps = targetsleeptime / ( sleeptime * 0.001 );
|
||||
else sleeps = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// always sleep at least once in minimized/nofocus state
|
||||
sleeps = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( !Host_Autosleep( dt, scale ))
|
||||
return false;
|
||||
|
||||
host.frametime = host.realtime - oldtime;
|
||||
host.realframetime = bound( MIN_FRAMETIME, host.frametime, MAX_FRAMETIME );
|
||||
@@ -754,7 +800,7 @@ void GAME_EXPORT Host_Error( const char *error, ... )
|
||||
Key_SetKeyDest( key_console );
|
||||
Con_Printf( "Host_Error: %s", hosterror1 );
|
||||
}
|
||||
else MSGBOX2( hosterror1 );
|
||||
else Platform_MessageBox( "Host Error", hosterror1, true );
|
||||
}
|
||||
|
||||
// host is shutting down. don't invoke infinite loop
|
||||
@@ -1016,21 +1062,31 @@ void Host_InitCommon( int argc, char **argv, const char *progname, qboolean bCha
|
||||
else
|
||||
{
|
||||
#if TARGET_OS_IOS
|
||||
const char *IOS_GetDocsDir();
|
||||
Q_strncpy( host.rootdir, IOS_GetDocsDir(), sizeof(host.rootdir) );
|
||||
Q_strncpy( host.rootdir, IOS_GetDocsDir(), sizeof( host.rootdir ));
|
||||
#elif XASH_ANDROID && XASH_SDL
|
||||
Q_strncpy( host.rootdir, SDL_AndroidGetExternalStoragePath(), sizeof( host.rootdir ));
|
||||
#elif XASH_PSVITA
|
||||
if ( !PSVita_GetBasePath( host.rootdir, sizeof( host.rootdir ) ) )
|
||||
if ( !PSVita_GetBasePath( host.rootdir, sizeof( host.rootdir )))
|
||||
{
|
||||
Sys_Error( "couldn't find xash3d data directory" );
|
||||
host.rootdir[0] = 0;
|
||||
}
|
||||
#elif (XASH_SDL == 2) && !XASH_NSWITCH // GetBasePath not impl'd in switch-sdl2
|
||||
char *szBasePath;
|
||||
|
||||
if( !( szBasePath = SDL_GetBasePath() ) )
|
||||
char *szBasePath = SDL_GetBasePath();
|
||||
if( szBasePath )
|
||||
{
|
||||
Q_strncpy( host.rootdir, szBasePath, sizeof( host.rootdir ));
|
||||
SDL_free( szBasePath );
|
||||
}
|
||||
else
|
||||
{
|
||||
#if XASH_POSIX || XASH_WIN32
|
||||
if( !getcwd( host.rootdir, sizeof( host.rootdir )))
|
||||
Sys_Error( "couldn't determine current directory: %s, getcwd: %s", SDL_GetError(), strerror( errno ));
|
||||
#else
|
||||
Sys_Error( "couldn't determine current directory: %s", SDL_GetError() );
|
||||
Q_strncpy( host.rootdir, szBasePath, sizeof( host.rootdir ));
|
||||
SDL_free( szBasePath );
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
if( !getcwd( host.rootdir, sizeof( host.rootdir )))
|
||||
{
|
||||
@@ -1149,6 +1205,7 @@ Host_Main
|
||||
int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGame, pfnChangeGame func )
|
||||
{
|
||||
static double oldtime, newtime;
|
||||
string demoname;
|
||||
|
||||
host.starttime = Sys_DoubleTime();
|
||||
|
||||
@@ -1168,6 +1225,7 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
|
||||
Cvar_RegisterVariable( &host_maxfps );
|
||||
Cvar_RegisterVariable( &host_framerate );
|
||||
Cvar_RegisterVariable( &host_sleeptime );
|
||||
Cvar_RegisterVariable( &host_sleeptime_debug );
|
||||
Cvar_RegisterVariable( &host_gameloaded );
|
||||
Cvar_RegisterVariable( &host_clientloaded );
|
||||
Cvar_RegisterVariable( &host_limitlocal );
|
||||
@@ -1245,6 +1303,9 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
|
||||
Cbuf_ExecStuffCmds(); // execute stuffcmds (commandline)
|
||||
SCR_CheckStartupVids(); // must be last
|
||||
|
||||
if( Sys_GetParmFromCmdLine( "-timedemo", demoname ))
|
||||
Cbuf_AddTextf( "timedemo %s\n", demoname );
|
||||
|
||||
oldtime = Sys_DoubleTime() - 0.1;
|
||||
|
||||
if( Host_IsDedicated( ))
|
||||
@@ -1293,6 +1354,7 @@ void EXPORT Host_Shutdown( void )
|
||||
#endif
|
||||
|
||||
SV_Shutdown( "Server shutdown\n" );
|
||||
SV_UnloadProgs();
|
||||
SV_ShutdownFilter();
|
||||
CL_Shutdown();
|
||||
|
||||
|
||||
@@ -142,6 +142,7 @@ void Image_CopyPalette32bit( void );
|
||||
void Image_SetPixelFormat( void );
|
||||
void Image_GetPaletteQ1( void );
|
||||
void Image_GetPaletteHL( void );
|
||||
size_t Image_ComputeSize( int type, int width, int height, int depth );
|
||||
|
||||
//
|
||||
// formats load
|
||||
@@ -156,6 +157,7 @@ qboolean Image_LoadDDS( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
qboolean Image_LoadFNT( const char *name, const byte *buffer, fs_offset_t filesize );
|
||||
qboolean Image_LoadLMP( const char *name, const byte *buffer, fs_offset_t filesize );
|
||||
qboolean Image_LoadPAL( const char *name, const byte *buffer, fs_offset_t filesize );
|
||||
qboolean Image_LoadKTX2( const char *name, const byte *buffer, fs_offset_t filesize );
|
||||
|
||||
//
|
||||
// formats save
|
||||
|
||||
@@ -104,6 +104,13 @@ void Image_DXTGetPixelFormat( dds_t *hdr, dds_header_dxt10_t *headerExt )
|
||||
{
|
||||
switch( headerExt->dxgiFormat )
|
||||
{
|
||||
case DXGI_FORMAT_BC4_TYPELESS:
|
||||
case DXGI_FORMAT_BC4_UNORM:
|
||||
image.type = PF_BC4_UNSIGNED;
|
||||
break;
|
||||
case DXGI_FORMAT_BC4_SNORM:
|
||||
image.type = PF_BC4_SIGNED;
|
||||
break;
|
||||
case DXGI_FORMAT_BC6H_SF16:
|
||||
image.type = PF_BC6H_SIGNED;
|
||||
break;
|
||||
@@ -112,9 +119,20 @@ void Image_DXTGetPixelFormat( dds_t *hdr, dds_header_dxt10_t *headerExt )
|
||||
image.type = PF_BC6H_UNSIGNED;
|
||||
break;
|
||||
case DXGI_FORMAT_BC7_UNORM:
|
||||
case DXGI_FORMAT_BC7_UNORM_SRGB:
|
||||
case DXGI_FORMAT_BC7_TYPELESS:
|
||||
image.type = PF_BC7;
|
||||
image.type = PF_BC7_UNORM;
|
||||
break;
|
||||
case DXGI_FORMAT_BC7_UNORM_SRGB:
|
||||
image.type = PF_BC7_SRGB;
|
||||
break;
|
||||
case DXGI_FORMAT_BC5_TYPELESS:
|
||||
image.type = PF_ATI2;
|
||||
break;
|
||||
case DXGI_FORMAT_BC5_UNORM:
|
||||
image.type = PF_BC5_UNSIGNED;
|
||||
break;
|
||||
case DXGI_FORMAT_BC5_SNORM:
|
||||
image.type = PF_BC5_SIGNED;
|
||||
break;
|
||||
default:
|
||||
image.type = PF_UNKNOWN;
|
||||
@@ -122,7 +140,7 @@ void Image_DXTGetPixelFormat( dds_t *hdr, dds_header_dxt10_t *headerExt )
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
switch( hdr->dsPixelFormat.dwFourCC )
|
||||
{
|
||||
case TYPE_DXT1:
|
||||
@@ -143,6 +161,15 @@ void Image_DXTGetPixelFormat( dds_t *hdr, dds_header_dxt10_t *headerExt )
|
||||
case TYPE_ATI2:
|
||||
image.type = PF_ATI2;
|
||||
break;
|
||||
case TYPE_BC5S:
|
||||
image.type = PF_BC5_SIGNED;
|
||||
break;
|
||||
case TYPE_BC4S:
|
||||
image.type = PF_BC4_SIGNED;
|
||||
break;
|
||||
case TYPE_BC4U:
|
||||
image.type = PF_BC4_UNSIGNED;
|
||||
break;
|
||||
default:
|
||||
image.type = PF_UNKNOWN; // assume error
|
||||
break;
|
||||
@@ -188,27 +215,6 @@ void Image_DXTGetPixelFormat( dds_t *hdr, dds_header_dxt10_t *headerExt )
|
||||
image.num_mips = hdr->dwMipMapCount; // get actual mip count
|
||||
}
|
||||
|
||||
size_t Image_DXTGetLinearSize( int type, int width, int height, int depth )
|
||||
{
|
||||
switch( type )
|
||||
{
|
||||
case PF_DXT1: return ((( width + 3 ) / 4 ) * (( height + 3 ) / 4 ) * depth * 8 );
|
||||
case PF_DXT3:
|
||||
case PF_DXT5:
|
||||
case PF_BC6H_SIGNED:
|
||||
case PF_BC6H_UNSIGNED:
|
||||
case PF_BC7:
|
||||
case PF_ATI2: return ((( width + 3 ) / 4 ) * (( height + 3 ) / 4 ) * depth * 16 );
|
||||
case PF_LUMINANCE: return (width * height * depth);
|
||||
case PF_BGR_24:
|
||||
case PF_RGB_24: return (width * height * depth * 3);
|
||||
case PF_BGRA_32:
|
||||
case PF_RGBA_32: return (width * height * depth * 4);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t Image_DXTCalcMipmapSize( dds_t *hdr )
|
||||
{
|
||||
size_t buffsize = 0;
|
||||
@@ -219,7 +225,7 @@ size_t Image_DXTCalcMipmapSize( dds_t *hdr )
|
||||
{
|
||||
width = Q_max( 1, ( hdr->dwWidth >> i ));
|
||||
height = Q_max( 1, ( hdr->dwHeight >> i ));
|
||||
buffsize += Image_DXTGetLinearSize( image.type, width, height, image.depth );
|
||||
buffsize += Image_ComputeSize( image.type, width, height, image.depth );
|
||||
}
|
||||
|
||||
return buffsize;
|
||||
@@ -255,7 +261,7 @@ uint Image_DXTCalcSize( const char *name, dds_t *hdr, size_t filesize )
|
||||
|
||||
if( filesize != buffsize ) // main check
|
||||
{
|
||||
Con_DPrintf( S_WARN "Image_LoadDDS: (%s) probably corrupted (%i should be %lu)\n", name, buffsize, filesize );
|
||||
Con_DPrintf( S_WARN "Image_LoadDDS: (%s) probably corrupted (%zu should be %lu)\n", name, buffsize, filesize );
|
||||
if( buffsize > filesize )
|
||||
return false;
|
||||
}
|
||||
@@ -268,7 +274,7 @@ void Image_DXTAdjustVolume( dds_t *hdr )
|
||||
if( hdr->dwDepth <= 1 )
|
||||
return;
|
||||
|
||||
hdr->dwLinearSize = Image_DXTGetLinearSize( image.type, hdr->dwWidth, hdr->dwHeight, hdr->dwDepth );
|
||||
hdr->dwLinearSize = Image_ComputeSize( image.type, hdr->dwWidth, hdr->dwHeight, hdr->dwDepth );
|
||||
hdr->dwFlags |= DDS_LINEARSIZE;
|
||||
}
|
||||
|
||||
@@ -323,7 +329,7 @@ qboolean Image_LoadDDS( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
Image_DXTGetPixelFormat( &header, &header2 ); // and image type too :)
|
||||
Image_DXTAdjustVolume( &header );
|
||||
|
||||
if( !Image_CheckFlag( IL_DDS_HARDWARE ) && ImageDXT( image.type ))
|
||||
if( !Image_CheckFlag( IL_DDS_HARDWARE ) && ImageCompressed( image.type ))
|
||||
return false; // silently rejected
|
||||
|
||||
if( image.type == PF_UNKNOWN )
|
||||
@@ -356,8 +362,10 @@ qboolean Image_LoadDDS( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
SetBits( image.flags, IMAGE_HAS_ALPHA );
|
||||
else if( image.type == PF_DXT5 && Image_CheckDXT5Alpha( &header, fin ))
|
||||
SetBits( image.flags, IMAGE_HAS_ALPHA );
|
||||
else if ( image.type == PF_BC7 )
|
||||
SetBits(image.flags, IMAGE_HAS_ALPHA);
|
||||
else if( image.type == PF_BC5_SIGNED || image.type == PF_BC5_UNSIGNED )
|
||||
SetBits( image.flags, IMAGE_HAS_ALPHA );
|
||||
else if( image.type == PF_BC7_UNORM || image.type == PF_BC7_SRGB )
|
||||
SetBits( image.flags, IMAGE_HAS_ALPHA );
|
||||
if( !FBitSet( header.dsPixelFormat.dwFlags, DDS_LUMINANCE ))
|
||||
SetBits( image.flags, IMAGE_HAS_COLOR );
|
||||
break;
|
||||
|
||||
@@ -32,6 +32,9 @@ GNU General Public License for more details.
|
||||
#define TYPE_DX10 (('0'<<24)+('1'<<16)+('X'<<8)+'D') // little-endian "DX10"
|
||||
#define TYPE_ATI1 (('1'<<24)+('I'<<16)+('T'<<8)+'A') // little-endian "ATI1"
|
||||
#define TYPE_ATI2 (('2'<<24)+('I'<<16)+('T'<<8)+'A') // little-endian "ATI2"
|
||||
#define TYPE_BC5S (('S'<<24)+('5'<<16)+('C'<<8)+'B') // little-endian "BC5S"
|
||||
#define TYPE_BC4S (('S'<<24)+('4'<<16)+('C'<<8)+'B') // little-endian "BC4S"
|
||||
#define TYPE_BC4U (('U'<<24)+('4'<<16)+('C'<<8)+'B') // little-endian "BC4U"
|
||||
#define TYPE_RXGB (('B'<<24)+('G'<<16)+('X'<<8)+'R') // little-endian "RXGB" doom3 normalmaps
|
||||
#define TYPE_$ (('\0'<<24)+('\0'<<16)+('\0'<<8)+'$') // little-endian "$"
|
||||
#define TYPE_o (('\0'<<24)+('\0'<<16)+('\0'<<8)+'o') // little-endian "o"
|
||||
@@ -202,7 +205,7 @@ typedef enum
|
||||
DXGI_FORMAT_FORCE_UINT = 0xffffffff
|
||||
} dxgi_format_t;
|
||||
|
||||
typedef enum
|
||||
typedef enum
|
||||
{
|
||||
D3D10_RESOURCE_DIMENSION_UNKNOWN = 0,
|
||||
D3D10_RESOURCE_DIMENSION_BUFFER = 1,
|
||||
|
||||
210
engine/common/imagelib/img_ktx2.c
Normal file
210
engine/common/imagelib/img_ktx2.c
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
img_ktx2.c - ktx2 format load
|
||||
Copyright (C) 2023 Provod
|
||||
|
||||
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 "imagelib.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
#include "img_ktx2.h"
|
||||
|
||||
static void Image_KTX2Format( uint32_t ktx2_format )
|
||||
{
|
||||
switch( ktx2_format )
|
||||
{
|
||||
case KTX2_FORMAT_BC4_UNORM_BLOCK:
|
||||
image.type = PF_BC4_UNSIGNED;
|
||||
// 1 component for ref_gl
|
||||
break;
|
||||
case KTX2_FORMAT_BC4_SNORM_BLOCK:
|
||||
image.type = PF_BC4_SIGNED;
|
||||
// 1 component for ref_gl
|
||||
break;
|
||||
case KTX2_FORMAT_BC5_UNORM_BLOCK:
|
||||
image.type = PF_BC5_UNSIGNED;
|
||||
// 2 components for ref_gl
|
||||
SetBits( image.flags, IMAGE_HAS_ALPHA );
|
||||
break;
|
||||
case KTX2_FORMAT_BC5_SNORM_BLOCK:
|
||||
image.type = PF_BC5_SIGNED;
|
||||
// 2 components for ref_gl
|
||||
SetBits( image.flags, IMAGE_HAS_ALPHA );
|
||||
break;
|
||||
case KTX2_FORMAT_BC6H_UFLOAT_BLOCK:
|
||||
image.type = PF_BC6H_UNSIGNED;
|
||||
// 3 components for ref_gl
|
||||
SetBits( image.flags, IMAGE_HAS_COLOR );
|
||||
break;
|
||||
case KTX2_FORMAT_BC6H_SFLOAT_BLOCK:
|
||||
image.type = PF_BC6H_SIGNED;
|
||||
// 3 components for ref_gl
|
||||
SetBits( image.flags, IMAGE_HAS_COLOR );
|
||||
break;
|
||||
case KTX2_FORMAT_BC7_UNORM_BLOCK:
|
||||
image.type = PF_BC7_UNORM;
|
||||
// 4 components for ref_gl
|
||||
SetBits( image.flags, IMAGE_HAS_COLOR | IMAGE_HAS_ALPHA );
|
||||
break;
|
||||
case KTX2_FORMAT_BC7_SRGB_BLOCK:
|
||||
image.type = PF_BC7_SRGB;
|
||||
// 4 components for ref_gl
|
||||
SetBits( image.flags, IMAGE_HAS_COLOR | IMAGE_HAS_ALPHA );
|
||||
break;
|
||||
default:
|
||||
image.type = PF_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static qboolean Image_KTX2Parse( const ktx2_header_t *header, const byte *buffer, fs_offset_t filesize )
|
||||
{
|
||||
ktx2_index_t index;
|
||||
size_t total_size = 0;
|
||||
size_t max_offset = 0;
|
||||
const byte *const levels_begin = buffer + KTX2_LEVELS_OFFSET;
|
||||
|
||||
// Sets image.type and image.flags
|
||||
Image_KTX2Format( header->vkFormat );
|
||||
|
||||
if( image.type == PF_UNKNOWN )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s: unsupported KTX2 format %d\n", __FUNCTION__, header->vkFormat );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !Image_CheckFlag( IL_DDS_HARDWARE ) && ImageCompressed( image.type ))
|
||||
{
|
||||
Con_DPrintf( S_WARN "%s: has compressed format, but support is not advertized\n", __FUNCTION__ );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( header->levelCount == 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s: file has no mip levels\n", __FUNCTION__ );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( header->pixelDepth > 1 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s: unsupported KTX2 pixelDepth %d\n", __FUNCTION__, header->pixelDepth );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( header->faceCount > 1 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s: unsupported KTX2 faceCount %d\n", __FUNCTION__, header->faceCount );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( header->layerCount > 1 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s: unsupported KTX2 layerCount %d\n", __FUNCTION__, header->layerCount );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( header->supercompressionScheme != 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s: unsupported KTX2 supercompressionScheme %d\n", __FUNCTION__, header->supercompressionScheme );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( header->levelCount * sizeof( ktx2_level_t ) + KTX2_LEVELS_OFFSET > filesize )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s: file abruptly ends\n", __FUNCTION__ );
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy( &index, buffer + KTX2_IDENTIFIER_SIZE + sizeof( ktx2_header_t ), sizeof( index ));
|
||||
|
||||
for( int mip = 0; mip < header->levelCount; ++mip )
|
||||
{
|
||||
const uint32_t width = Q_max( 1, ( header->pixelWidth >> mip ));
|
||||
const uint32_t height = Q_max( 1, ( header->pixelHeight >> mip ));
|
||||
const uint32_t mip_size = Image_ComputeSize( image.type, width, height, image.depth );
|
||||
|
||||
ktx2_level_t level;
|
||||
memcpy( &level, levels_begin + mip * sizeof( level ), sizeof( level ));
|
||||
|
||||
if( mip_size != level.byteLength )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s: mip=%d size mismatch read=%d, but computed=%d\n",
|
||||
__FUNCTION__, mip, (int)level.byteLength, mip_size );
|
||||
return false;
|
||||
}
|
||||
|
||||
total_size += level.byteLength;
|
||||
max_offset = Q_max( max_offset, level.byteLength + level.byteOffset );
|
||||
}
|
||||
|
||||
if( max_offset > filesize )
|
||||
return false;
|
||||
|
||||
image.size = total_size;
|
||||
image.num_mips = header->levelCount;
|
||||
|
||||
image.rgba = Mem_Malloc( host.imagepool, image.size );
|
||||
memcpy( image.rgba, buffer, image.size );
|
||||
|
||||
for( int mip = 0, cursor = 0; mip < header->levelCount; ++mip )
|
||||
{
|
||||
ktx2_level_t level;
|
||||
memcpy( &level, levels_begin + mip * sizeof( level ), sizeof( level ));
|
||||
memcpy( image.rgba + cursor, buffer + level.byteOffset, level.byteLength );
|
||||
cursor += level.byteLength;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
qboolean Image_LoadKTX2( const char *name, const byte *buffer, fs_offset_t filesize )
|
||||
{
|
||||
ktx2_header_t header;
|
||||
|
||||
if( filesize < KTX2_MINIMAL_HEADER_SIZE )
|
||||
return false;
|
||||
|
||||
if( memcmp( buffer, KTX2_IDENTIFIER, KTX2_IDENTIFIER_SIZE ) != 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s: (%s) has invalid identifier\n", __FUNCTION__, name );
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy( &header, buffer + KTX2_IDENTIFIER_SIZE, sizeof( header ));
|
||||
|
||||
image.width = header.pixelWidth;
|
||||
image.height = header.pixelHeight;
|
||||
image.depth = Q_max( 1, header.pixelDepth );
|
||||
image.num_mips = 1;
|
||||
|
||||
ClearBits( image.flags, IMAGE_HAS_COLOR | IMAGE_HAS_ALPHA | IMAGE_HAS_LUMA );
|
||||
|
||||
if( !Image_KTX2Parse( &header, buffer, filesize ))
|
||||
{
|
||||
if( !Image_CheckFlag( IL_KTX2_RAW ))
|
||||
return false;
|
||||
|
||||
// If KTX2 to imagelib conversion failed, try passing the file as raw data.
|
||||
// This is useful for ref_vk which can directly support hundreds of formats which we don't convert to pixformat_t here
|
||||
|
||||
Con_DPrintf( S_WARN "%s: (%s) could not be converted to supported imagelib format, passing as raw KTX2 data\n", __FUNCTION__, name );
|
||||
// This is a catch-all for ref_vk, which can do this format directly and natively
|
||||
image.type = PF_KTX2_RAW;
|
||||
|
||||
image.size = filesize;
|
||||
//image.encode = TODO custom encode type?
|
||||
|
||||
image.rgba = Mem_Malloc( host.imagepool, image.size );
|
||||
memcpy( image.rgba, buffer, image.size );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
79
engine/common/imagelib/img_ktx2.h
Normal file
79
engine/common/imagelib/img_ktx2.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
img_ktx2.h - ktx2 format reference
|
||||
Copyright (C) 2023 Provod
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
#ifndef IMG_KTX2_H
|
||||
#define IMG_KTX2_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define KTX2_IDENTIFIER_SIZE 12
|
||||
#define KTX2_IDENTIFIER "\xABKTX 20\xBB\r\n\x1A\n"
|
||||
|
||||
/*
|
||||
static const char k_ktx2_identifier[KTX2_IDENTIFIER_SIZE] =
|
||||
{
|
||||
'\xAB', 'K', 'T', 'X', ' ', '2', '0', '\xBB', '\r', '\n', '\x1A', '\n'
|
||||
};
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t vkFormat;
|
||||
uint32_t typeSize;
|
||||
uint32_t pixelWidth;
|
||||
uint32_t pixelHeight;
|
||||
uint32_t pixelDepth;
|
||||
uint32_t layerCount;
|
||||
uint32_t faceCount;
|
||||
uint32_t levelCount;
|
||||
uint32_t supercompressionScheme;
|
||||
} ktx2_header_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t dfdByteOffset;
|
||||
uint32_t dfdByteLength;
|
||||
uint32_t kvdByteOffset;
|
||||
uint32_t kvdByteLength;
|
||||
uint64_t sgdByteOffset;
|
||||
uint64_t sgdByteLength;
|
||||
} ktx2_index_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t byteOffset;
|
||||
uint64_t byteLength;
|
||||
uint64_t uncompressedByteLength;
|
||||
} ktx2_level_t;
|
||||
|
||||
#define KTX2_LEVELS_OFFSET ( KTX2_IDENTIFIER_SIZE + sizeof( ktx2_header_t ) + sizeof( ktx2_index_t ))
|
||||
|
||||
#define KTX2_MINIMAL_HEADER_SIZE ( KTX2_LEVELS_OFFSET + sizeof( ktx2_level_t ))
|
||||
|
||||
// These have the same values as enum VkFormat in vulkan_core.h
|
||||
// There are hundreds of formats which can be contained in KTX2.
|
||||
// Below are listed the ones which are supported here. This list can be extended.
|
||||
typedef enum
|
||||
{
|
||||
KTX2_FORMAT_BC4_UNORM_BLOCK = 139,
|
||||
KTX2_FORMAT_BC4_SNORM_BLOCK = 140,
|
||||
KTX2_FORMAT_BC5_UNORM_BLOCK = 141,
|
||||
KTX2_FORMAT_BC5_SNORM_BLOCK = 142,
|
||||
KTX2_FORMAT_BC6H_UFLOAT_BLOCK = 143,
|
||||
KTX2_FORMAT_BC6H_SFLOAT_BLOCK = 144,
|
||||
KTX2_FORMAT_BC7_UNORM_BLOCK = 145,
|
||||
KTX2_FORMAT_BC7_SRGB_BLOCK = 146,
|
||||
} ktx2_format_t;
|
||||
|
||||
#endif // IMG_KTX2_H
|
||||
@@ -105,6 +105,7 @@ static const loadpixformat_t load_game[] =
|
||||
{ "%s%s.%s", "lmp", Image_LoadLMP, IL_HINT_NO }, // hl menu images (cached.wad etc)
|
||||
{ "%s%s.%s", "fnt", Image_LoadFNT, IL_HINT_HL }, // hl console font (fonts.wad etc)
|
||||
{ "%s%s.%s", "pal", Image_LoadPAL, IL_HINT_NO }, // install studio\sprite palette
|
||||
{ "%s%s.%s", "ktx2", Image_LoadKTX2, IL_HINT_NO }, // ktx2 for world and studio models
|
||||
{ NULL, NULL, NULL, IL_HINT_NO }
|
||||
};
|
||||
|
||||
@@ -283,8 +284,10 @@ int Image_ComparePalette( const byte *pal )
|
||||
void Image_SetPalette( const byte *pal, uint *d_table )
|
||||
{
|
||||
byte rgba[4];
|
||||
uint uirgba; // TODO: palette looks byte-swapped on big-endian
|
||||
int i;
|
||||
|
||||
|
||||
// setup palette
|
||||
switch( image.d_rendermode )
|
||||
{
|
||||
@@ -295,7 +298,8 @@ void Image_SetPalette( const byte *pal, uint *d_table )
|
||||
rgba[1] = pal[i*3+1];
|
||||
rgba[2] = pal[i*3+2];
|
||||
rgba[3] = 0xFF;
|
||||
d_table[i] = *(uint *)rgba;
|
||||
memcpy( &uirgba, rgba, sizeof( uirgba ));
|
||||
d_table[i] = uirgba;
|
||||
}
|
||||
break;
|
||||
case LUMP_GRADIENT:
|
||||
@@ -305,7 +309,8 @@ void Image_SetPalette( const byte *pal, uint *d_table )
|
||||
rgba[1] = pal[766];
|
||||
rgba[2] = pal[767];
|
||||
rgba[3] = i;
|
||||
d_table[i] = *(uint *)rgba;
|
||||
memcpy( &uirgba, rgba, sizeof( uirgba ));
|
||||
d_table[i] = uirgba;
|
||||
}
|
||||
break;
|
||||
case LUMP_MASKED:
|
||||
@@ -315,7 +320,8 @@ void Image_SetPalette( const byte *pal, uint *d_table )
|
||||
rgba[1] = pal[i*3+1];
|
||||
rgba[2] = pal[i*3+2];
|
||||
rgba[3] = 0xFF;
|
||||
d_table[i] = *(uint *)rgba;
|
||||
memcpy( &uirgba, rgba, sizeof( uirgba ));
|
||||
d_table[i] = uirgba;
|
||||
}
|
||||
d_table[255] = 0;
|
||||
break;
|
||||
@@ -326,7 +332,8 @@ void Image_SetPalette( const byte *pal, uint *d_table )
|
||||
rgba[1] = pal[i*4+1];
|
||||
rgba[2] = pal[i*4+2];
|
||||
rgba[3] = pal[i*4+3];
|
||||
d_table[i] = *(uint *)rgba;
|
||||
memcpy( &uirgba, rgba, sizeof( uirgba ));
|
||||
d_table[i] = uirgba;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1446,3 +1453,36 @@ qboolean Image_Process(rgbdata_t **pix, int width, int height, uint flags, float
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// This codebase has too many copies of this function:
|
||||
// - ref_gl has one
|
||||
// - ref_vk has one
|
||||
// - ref_soft has one
|
||||
// - many more places probably have one too
|
||||
// TODO figure out how to make it available for ref_*
|
||||
size_t Image_ComputeSize( int type, int width, int height, int depth )
|
||||
{
|
||||
switch( type )
|
||||
{
|
||||
case PF_DXT1:
|
||||
case PF_BC4_SIGNED:
|
||||
case PF_BC4_UNSIGNED:
|
||||
return ((( width + 3 ) / 4 ) * (( height + 3 ) / 4 ) * depth * 8 );
|
||||
case PF_DXT3:
|
||||
case PF_DXT5:
|
||||
case PF_ATI2:
|
||||
case PF_BC5_UNSIGNED:
|
||||
case PF_BC5_SIGNED:
|
||||
case PF_BC6H_SIGNED:
|
||||
case PF_BC6H_UNSIGNED:
|
||||
case PF_BC7_UNORM:
|
||||
case PF_BC7_SRGB: return ((( width + 3 ) / 4 ) * (( height + 3 ) / 4 ) * depth * 16 );
|
||||
case PF_LUMINANCE: return ( width * height * depth );
|
||||
case PF_BGR_24:
|
||||
case PF_RGB_24: return ( width * height * depth * 3 );
|
||||
case PF_BGRA_32:
|
||||
case PF_RGBA_32: return ( width * height * depth * 4 );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -23,15 +23,6 @@ GNU General Public License for more details.
|
||||
|
||||
#if XASH_EMSCRIPTEN
|
||||
#include <emscripten.h>
|
||||
#elif XASH_WIN32
|
||||
extern "C"
|
||||
{
|
||||
// Enable NVIDIA High Performance Graphics while using Integrated Graphics.
|
||||
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
|
||||
|
||||
// Enable AMD High Performance Graphics while using Integrated Graphics.
|
||||
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define E_GAME "XASH3D_GAME" // default env dir to start from
|
||||
@@ -39,6 +30,10 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
||||
#define XASH_GAMEDIR "valve"
|
||||
#endif
|
||||
|
||||
#if XASH_WIN32
|
||||
#error "Single-binary or dedicated builds aren't supported for Windows!"
|
||||
#endif
|
||||
|
||||
static char szGameDir[128]; // safe place to keep gamedir
|
||||
static int szArgc;
|
||||
static char **szArgv;
|
||||
@@ -47,7 +42,7 @@ static void Sys_ChangeGame( const char *progname )
|
||||
{
|
||||
// a1ba: may never be called within engine
|
||||
// if platform supports execv() function
|
||||
Q_strncpy( szGameDir, progname, sizeof( szGameDir ) - 1 );
|
||||
Q_strncpy( szGameDir, progname, sizeof( szGameDir ));
|
||||
Host_Shutdown( );
|
||||
exit( Host_Main( szArgc, szArgv, szGameDir, 1, &Sys_ChangeGame ) );
|
||||
}
|
||||
@@ -88,7 +83,6 @@ _inline int Sys_Start( void )
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if !XASH_WIN32
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
#if XASH_PSVITA
|
||||
@@ -100,36 +94,4 @@ int main( int argc, char **argv )
|
||||
#endif // XASH_PSVITA
|
||||
return Sys_Start();
|
||||
}
|
||||
#else
|
||||
int __stdcall WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdLine, int nShow)
|
||||
{
|
||||
LPWSTR* lpArgv;
|
||||
int ret, i;
|
||||
|
||||
lpArgv = CommandLineToArgvW( GetCommandLineW(), &szArgc );
|
||||
szArgv = ( char** )malloc( (szArgc + 1) * sizeof( char* ));
|
||||
|
||||
for( i = 0; i < szArgc; ++i )
|
||||
{
|
||||
size_t size = wcslen(lpArgv[i]) + 1;
|
||||
|
||||
// just in case, allocate some more memory
|
||||
szArgv[i] = ( char * )malloc( size * sizeof( wchar_t ));
|
||||
wcstombs( szArgv[i], lpArgv[i], size );
|
||||
}
|
||||
szArgv[szArgc] = 0;
|
||||
|
||||
LocalFree( lpArgv );
|
||||
|
||||
ret = Sys_Start();
|
||||
|
||||
for( ; i < szArgc; ++i )
|
||||
free( szArgv[i] );
|
||||
free( szArgv );
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif // XASH_WIN32
|
||||
|
||||
|
||||
#endif
|
||||
#endif // SINGLE_BINARY
|
||||
|
||||
@@ -419,5 +419,6 @@ void NET_InitMasters( void )
|
||||
|
||||
// keep main master always there
|
||||
NET_AddMaster( MASTERSERVER_ADR, false );
|
||||
NET_AddMaster( MASTERSERVER_ADR_TEST, false );
|
||||
NET_LoadMasters( );
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -113,12 +113,13 @@ typedef struct world_static_s
|
||||
// tree visualization stuff
|
||||
int recursion_level;
|
||||
int max_recursion;
|
||||
|
||||
uint32_t version; // BSP version
|
||||
} world_static_t;
|
||||
|
||||
#ifndef REF_DLL
|
||||
extern world_static_t world;
|
||||
extern poolhandle_t com_studiocache;
|
||||
extern model_t *loadmodel;
|
||||
extern convar_t mod_studiocache;
|
||||
extern convar_t r_wadtextures;
|
||||
extern convar_t r_showhull;
|
||||
@@ -156,7 +157,7 @@ int Mod_CheckLump( const char *filename, const int lump, int *lumpsize );
|
||||
int Mod_ReadLump( const char *filename, const int lump, void **lumpdata, int *lumpsize );
|
||||
int Mod_SaveLump( const char *filename, const int lump, void *lumpdata, int lumpsize );
|
||||
mleaf_t *Mod_PointInLeaf( const vec3_t p, mnode_t *node );
|
||||
int Mod_SampleSizeForFace( msurface_t *surf );
|
||||
int Mod_SampleSizeForFace( const msurface_t *surf );
|
||||
byte *Mod_GetPVSForPoint( const vec3_t p );
|
||||
void Mod_UnloadBrushModel( model_t *mod );
|
||||
void Mod_PrintWorldStats_f( void );
|
||||
@@ -164,7 +165,7 @@ void Mod_PrintWorldStats_f( void );
|
||||
//
|
||||
// mod_dbghulls.c
|
||||
//
|
||||
void Mod_InitDebugHulls( void );
|
||||
void Mod_InitDebugHulls( model_t *mod );
|
||||
void Mod_CreatePolygonsForHull( int hullnum );
|
||||
void Mod_ReleaseHullPolygons( void );
|
||||
|
||||
|
||||
@@ -851,11 +851,11 @@ void Mod_LoadStudioModel( model_t *mod, const void *buffer, qboolean *loaded )
|
||||
char poolname[MAX_VA_STRING];
|
||||
studiohdr_t *phdr;
|
||||
|
||||
Q_snprintf( poolname, sizeof( poolname ), "^2%s^7", loadmodel->name );
|
||||
Q_snprintf( poolname, sizeof( poolname ), "^2%s^7", mod->name );
|
||||
|
||||
if( loaded ) *loaded = false;
|
||||
loadmodel->mempool = Mem_AllocPool( poolname );
|
||||
loadmodel->type = mod_studio;
|
||||
mod->mempool = Mem_AllocPool( poolname );
|
||||
mod->type = mod_studio;
|
||||
|
||||
phdr = R_StudioLoadHeader( mod, buffer );
|
||||
if( !phdr ) return; // bad model
|
||||
@@ -886,9 +886,9 @@ void Mod_LoadStudioModel( model_t *mod, const void *buffer, qboolean *loaded )
|
||||
// give space for textures and skinrefs
|
||||
size1 = thdr->numtextures * sizeof( mstudiotexture_t );
|
||||
size2 = thdr->numskinfamilies * thdr->numskinref * sizeof( short );
|
||||
mod->cache.data = Mem_Calloc( loadmodel->mempool, phdr->length + size1 + size2 );
|
||||
memcpy( loadmodel->cache.data, buffer, phdr->length ); // copy main mdl buffer
|
||||
phdr = (studiohdr_t *)loadmodel->cache.data; // get the new pointer on studiohdr
|
||||
mod->cache.data = Mem_Calloc( mod->mempool, phdr->length + size1 + size2 );
|
||||
memcpy( mod->cache.data, buffer, phdr->length ); // copy main mdl buffer
|
||||
phdr = (studiohdr_t *)mod->cache.data; // get the new pointer on studiohdr
|
||||
phdr->numskinfamilies = thdr->numskinfamilies;
|
||||
phdr->numtextures = thdr->numtextures;
|
||||
phdr->numskinref = thdr->numskinref;
|
||||
@@ -905,52 +905,52 @@ void Mod_LoadStudioModel( model_t *mod, const void *buffer, qboolean *loaded )
|
||||
else
|
||||
{
|
||||
// NOTE: don't modify source buffer because it's used for CRC computing
|
||||
loadmodel->cache.data = Mem_Calloc( loadmodel->mempool, phdr->length );
|
||||
memcpy( loadmodel->cache.data, buffer, phdr->length );
|
||||
phdr = (studiohdr_t *)loadmodel->cache.data; // get the new pointer on studiohdr
|
||||
mod->cache.data = Mem_Calloc( mod->mempool, phdr->length );
|
||||
memcpy( mod->cache.data, buffer, phdr->length );
|
||||
phdr = (studiohdr_t *)mod->cache.data; // get the new pointer on studiohdr
|
||||
#if !XASH_DEDICATED
|
||||
ref.dllFuncs.Mod_StudioLoadTextures( mod, phdr );
|
||||
#endif
|
||||
|
||||
// NOTE: we wan't keep raw textures in memory. just cutoff model pointer above texture base
|
||||
loadmodel->cache.data = Mem_Realloc( loadmodel->mempool, loadmodel->cache.data, phdr->texturedataindex );
|
||||
phdr = (studiohdr_t *)loadmodel->cache.data; // get the new pointer on studiohdr
|
||||
mod->cache.data = Mem_Realloc( mod->mempool, mod->cache.data, phdr->texturedataindex );
|
||||
phdr = (studiohdr_t *)mod->cache.data; // get the new pointer on studiohdr
|
||||
phdr->length = phdr->texturedataindex; // update model size
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// just copy model into memory
|
||||
loadmodel->cache.data = Mem_Calloc( loadmodel->mempool, phdr->length );
|
||||
memcpy( loadmodel->cache.data, buffer, phdr->length );
|
||||
mod->cache.data = Mem_Calloc( mod->mempool, phdr->length );
|
||||
memcpy( mod->cache.data, buffer, phdr->length );
|
||||
|
||||
phdr = loadmodel->cache.data;
|
||||
phdr = mod->cache.data;
|
||||
}
|
||||
|
||||
// setup bounding box
|
||||
if( !VectorCompare( vec3_origin, phdr->bbmin ))
|
||||
{
|
||||
// clipping bounding box
|
||||
VectorCopy( phdr->bbmin, loadmodel->mins );
|
||||
VectorCopy( phdr->bbmax, loadmodel->maxs );
|
||||
VectorCopy( phdr->bbmin, mod->mins );
|
||||
VectorCopy( phdr->bbmax, mod->maxs );
|
||||
}
|
||||
else if( !VectorCompare( vec3_origin, phdr->min ))
|
||||
{
|
||||
// movement bounding box
|
||||
VectorCopy( phdr->min, loadmodel->mins );
|
||||
VectorCopy( phdr->max, loadmodel->maxs );
|
||||
VectorCopy( phdr->min, mod->mins );
|
||||
VectorCopy( phdr->max, mod->maxs );
|
||||
}
|
||||
else
|
||||
{
|
||||
// well compute bounds from vertices and round to nearest even values
|
||||
Mod_StudioComputeBounds( phdr, loadmodel->mins, loadmodel->maxs, true );
|
||||
RoundUpHullSize( loadmodel->mins );
|
||||
RoundUpHullSize( loadmodel->maxs );
|
||||
Mod_StudioComputeBounds( phdr, mod->mins, mod->maxs, true );
|
||||
RoundUpHullSize( mod->mins );
|
||||
RoundUpHullSize( mod->maxs );
|
||||
}
|
||||
|
||||
loadmodel->numframes = Mod_StudioBodyVariations( loadmodel );
|
||||
loadmodel->radius = RadiusFromBounds( loadmodel->mins, loadmodel->maxs );
|
||||
loadmodel->flags = phdr->flags; // copy header flags
|
||||
mod->numframes = Mod_StudioBodyVariations( mod );
|
||||
mod->radius = RadiusFromBounds( mod->mins, mod->maxs );
|
||||
mod->flags = phdr->flags; // copy header flags
|
||||
|
||||
if( loaded ) *loaded = true;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ poolhandle_t com_studiocache; // cache for submodels
|
||||
CVAR_DEFINE( mod_studiocache, "r_studiocache", "1", FCVAR_ARCHIVE, "enables studio cache for speedup tracing hitboxes" );
|
||||
CVAR_DEFINE_AUTO( r_wadtextures, "0", 0, "completely ignore textures in the bsp-file if enabled" );
|
||||
CVAR_DEFINE_AUTO( r_showhull, "0", 0, "draw collision hulls 1-3" );
|
||||
model_t *loadmodel;
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
@@ -112,6 +111,7 @@ void Mod_FreeModel( model_t *mod )
|
||||
|
||||
if( mod->type == mod_brush && FBitSet( mod->flags, MODEL_WORLD ) )
|
||||
{
|
||||
world.version = 0;
|
||||
world.shadowdata = NULL;
|
||||
world.deluxedata = NULL;
|
||||
}
|
||||
@@ -287,7 +287,6 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
|
||||
Con_Reportf( "loading %s\n", mod->name );
|
||||
mod->needload = NL_PRESENT;
|
||||
mod->type = mod_bad;
|
||||
loadmodel = mod;
|
||||
|
||||
// call the apropriate loader
|
||||
switch( *(uint *)buf )
|
||||
|
||||
@@ -1087,7 +1087,6 @@ int Delta_TestBaseline( entity_state_t *from, entity_state_t *to, qboolean playe
|
||||
delta_info_t *dt = NULL;
|
||||
delta_t *pField;
|
||||
int i, countBits;
|
||||
int numChanges = 0;
|
||||
|
||||
countBits = MAX_ENTITY_BITS + 2;
|
||||
|
||||
@@ -1121,7 +1120,7 @@ int Delta_TestBaseline( entity_state_t *from, entity_state_t *to, qboolean playe
|
||||
|
||||
if( !Delta_CompareField( pField, from, to, timebase ))
|
||||
{
|
||||
// strings are handled difference
|
||||
// strings are handled differently
|
||||
if( FBitSet( pField->flags, DT_STRING ))
|
||||
countBits += Q_strlen((char *)((byte *)to + pField->offset )) * 8;
|
||||
else countBits += pField->bits;
|
||||
|
||||
@@ -274,8 +274,8 @@ static void NET_NetadrToSockadr( netadr_t *a, struct sockaddr_storage *s )
|
||||
else if( a->type == NA_IP )
|
||||
{
|
||||
((struct sockaddr_in *)s)->sin_family = AF_INET;
|
||||
((struct sockaddr_in *)s)->sin_addr.s_addr = *(uint32_t *)&a->ip;
|
||||
((struct sockaddr_in *)s)->sin_port = a->port;
|
||||
((struct sockaddr_in *)s)->sin_addr.s_addr = a->ip4;
|
||||
}
|
||||
else if( a->type6 == NA_IP6 )
|
||||
{
|
||||
@@ -314,7 +314,7 @@ static void NET_SockadrToNetadr( const struct sockaddr_storage *s, netadr_t *a )
|
||||
if( s->ss_family == AF_INET )
|
||||
{
|
||||
a->type = NA_IP;
|
||||
*(int *)&a->ip = ((struct sockaddr_in *)s)->sin_addr.s_addr;
|
||||
a->ip4 = ((struct sockaddr_in *)s)->sin_addr.s_addr;
|
||||
a->port = ((struct sockaddr_in *)s)->sin_port;
|
||||
}
|
||||
else if( s->ss_family == AF_INET6 )
|
||||
@@ -444,6 +444,7 @@ static void NET_InitializeCriticalSections( void )
|
||||
void NET_ResolveThread( void )
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
qboolean res;
|
||||
|
||||
RESOLVE_DBG( "[resolve thread] starting resolve for " );
|
||||
RESOLVE_DBG( nsthread.hostname );
|
||||
@@ -453,13 +454,14 @@ void NET_ResolveThread( void )
|
||||
RESOLVE_DBG( " with gethostbyname\n" );
|
||||
#endif
|
||||
|
||||
if( NET_GetHostByName( nsthread.hostname, nsthread.family, &addr ))
|
||||
if(( res = NET_GetHostByName( nsthread.hostname, nsthread.family, &addr )))
|
||||
RESOLVE_DBG( "[resolve thread] success\n" );
|
||||
else
|
||||
RESOLVE_DBG( "[resolve thread] failed\n" );
|
||||
mutex_lock( &nsthread.mutexres );
|
||||
nsthread.addr = addr;
|
||||
nsthread.busy = false;
|
||||
nsthread.result = res ? NET_EAI_OK : NET_EAI_NONAME;
|
||||
RESOLVE_DBG( "[resolve thread] returning result\n" );
|
||||
mutex_unlock( &nsthread.mutexres );
|
||||
RESOLVE_DBG( "[resolve thread] exiting thread\n" );
|
||||
@@ -544,6 +546,7 @@ static net_gai_state_t NET_StringToSockaddr( const char *s, struct sockaddr_stor
|
||||
memset( &nsthread.addr, 0, sizeof( nsthread.addr ));
|
||||
|
||||
detach_thread( nsthread.thread );
|
||||
asyncfailed = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2197,6 +2200,8 @@ HTTP downloader
|
||||
=================================================
|
||||
*/
|
||||
|
||||
#define MAX_HTTP_BUFFER_SIZE (BIT( 13 ))
|
||||
|
||||
typedef struct httpserver_s
|
||||
{
|
||||
char host[256];
|
||||
@@ -2237,7 +2242,7 @@ typedef struct httpfile_s
|
||||
qboolean process;
|
||||
|
||||
// query or response
|
||||
char buf[BUFSIZ+1];
|
||||
char buf[MAX_HTTP_BUFFER_SIZE+1];
|
||||
int header_size, query_length, bytes_sent;
|
||||
} httpfile_t;
|
||||
|
||||
@@ -2382,18 +2387,18 @@ process incoming data
|
||||
*/
|
||||
static qboolean HTTP_ProcessStream( httpfile_t *curfile )
|
||||
{
|
||||
char buf[BUFSIZ+1];
|
||||
char buf[sizeof( curfile->buf )];
|
||||
char *begin = 0;
|
||||
int res;
|
||||
|
||||
if( curfile->header_size >= BUFSIZ )
|
||||
if( curfile->header_size >= sizeof( buf ))
|
||||
{
|
||||
Con_Reportf( S_ERROR "Header to big\n");
|
||||
Con_Reportf( S_ERROR "Header too big, the size is %s\n", curfile->header_size );
|
||||
HTTP_FreeFile( curfile, true );
|
||||
return false;
|
||||
}
|
||||
|
||||
while( ( res = recv( curfile->socket, buf, BUFSIZ - curfile->header_size, 0 )) > 0) // if we got there, we are receiving data
|
||||
while( ( res = recv( curfile->socket, buf, sizeof( buf ) - curfile->header_size, 0 )) > 0) // if we got there, we are receiving data
|
||||
{
|
||||
curfile->blocktime = 0;
|
||||
|
||||
@@ -2406,7 +2411,7 @@ static qboolean HTTP_ProcessStream( httpfile_t *curfile )
|
||||
if( begin ) // Got full header
|
||||
{
|
||||
int cutheadersize = begin - curfile->buf + 4; // after that begin of data
|
||||
char *length;
|
||||
char *content_length_line;
|
||||
|
||||
Con_Reportf( "HTTP: Got response!\n" );
|
||||
|
||||
@@ -2425,10 +2430,13 @@ static qboolean HTTP_ProcessStream( httpfile_t *curfile )
|
||||
}
|
||||
|
||||
// print size
|
||||
length = Q_stristr( curfile->buf, "Content-Length: " );
|
||||
if( length )
|
||||
content_length_line = Q_stristr( curfile->buf, "Content-Length: " );
|
||||
if( content_length_line )
|
||||
{
|
||||
int size = Q_atoi( length += 16 );
|
||||
int size;
|
||||
|
||||
content_length_line += sizeof( "Content-Length: " ) - 1;
|
||||
size = Q_atoi( content_length_line );
|
||||
|
||||
Con_Reportf( "HTTP: File size is %d\n", size );
|
||||
|
||||
@@ -2870,6 +2878,10 @@ static void HTTP_AddCustomServer_f( void )
|
||||
{
|
||||
HTTP_AddCustomServer( Cmd_Argv( 1 ));
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_Printf( S_USAGE "http_addcustomserver <url>\n" );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -70,6 +70,7 @@ GNU General Public License for more details.
|
||||
#define NET_MAX_MESSAGE PAD_NUMBER(( NET_MAX_PAYLOAD + HEADER_BYTES ), 16 )
|
||||
|
||||
#define MASTERSERVER_ADR "mentality.rip:27010"
|
||||
#define MASTERSERVER_ADR_TEST "mentality.rip:27011"
|
||||
#define MS_SCAN_REQUEST "1\xFF" "0.0.0.0:0\0"
|
||||
|
||||
#define PORT_MASTER 27010
|
||||
|
||||
@@ -305,6 +305,14 @@ extern const char *clc_strings[clc_lastmsg+1];
|
||||
#define MAX_LEGACY_EDICTS (1 << MAX_LEGACY_ENTITY_BITS) // 4096 edicts
|
||||
#define MIN_LEGACY_EDICTS 30
|
||||
|
||||
// legacy engine features that can be implemented through currently supported features
|
||||
#define ENGINE_LEGACY_FEATURES_MASK \
|
||||
( ENGINE_WRITE_LARGE_COORD \
|
||||
| ENGINE_LOAD_DELUXEDATA \
|
||||
| ENGINE_LARGE_LIGHTMAPS \
|
||||
| ENGINE_COMPENSATE_QUAKE_BUG \
|
||||
| ENGINE_COMPUTE_STUDIO_LERP )
|
||||
|
||||
// Master Server protocol
|
||||
#define MS_SCAN_REQUEST "1\xFF" "0.0.0.0:0\0" // TODO: implement IP filter
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@ void Sys_InitLog( void )
|
||||
s_ld.logfileno = fileno( s_ld.logfile );
|
||||
|
||||
fprintf( s_ld.logfile, "=================================================================================\n" );
|
||||
fprintf( s_ld.logfile, "\t%s (build %i) started at %s\n", s_ld.title, Q_buildnum(), Q_timestamp( TIME_FULL ) );
|
||||
fprintf( s_ld.logfile, "\t%s (build %i commit %s (%s-%s)) started at %s\n", s_ld.title, Q_buildnum(), Q_buildcommit(), Q_buildos(), Q_buildarch(), Q_timestamp( TIME_FULL ) );
|
||||
fprintf( s_ld.logfile, "=================================================================================\n" );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,7 +402,7 @@ void Sys_Warn( const char *format, ... )
|
||||
Msg( "Sys_Warn: %s\n", text );
|
||||
|
||||
if( !Host_IsDedicated() ) // dedicated server should not hang on messagebox
|
||||
MSGBOX(text);
|
||||
Platform_MessageBox( "Xash Warning", text, false );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -446,8 +446,8 @@ void Sys_Error( const char *error, ... )
|
||||
#if XASH_WIN32
|
||||
Wcon_ShowConsole( false );
|
||||
#endif
|
||||
MSGBOX( text );
|
||||
Sys_Print( text );
|
||||
Platform_MessageBox( "Xash Error", text, false );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -562,7 +562,7 @@ void Sys_Print( const char *pMsg )
|
||||
|
||||
Sys_PrintLog( pMsg );
|
||||
|
||||
Rcon_Print( pMsg );
|
||||
Rcon_Print( &host.rd, pMsg );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -649,3 +649,31 @@ qboolean Sys_NewInstance( const char *gamedir )
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_GetNativeObject
|
||||
|
||||
Get platform-specific native object
|
||||
==================
|
||||
*/
|
||||
void *Sys_GetNativeObject( const char *obj )
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
if( !COM_CheckString( obj ))
|
||||
return NULL;
|
||||
|
||||
ptr = FS_GetNativeObject( obj );
|
||||
|
||||
if( ptr )
|
||||
return ptr;
|
||||
|
||||
// Backend should consider that obj is case-sensitive
|
||||
#if XASH_ANDROID
|
||||
ptr = Android_GetNativeObject( obj );
|
||||
#endif // XASH_ANDROID
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@@ -30,9 +30,6 @@ extern "C" {
|
||||
#include "crtlib.h"
|
||||
#include "platform/platform.h"
|
||||
|
||||
#define MSGBOX( x ) Platform_MessageBox( "Xash Error", (x), false )
|
||||
#define MSGBOX2( x ) Platform_MessageBox( "Host Error", (x), true )
|
||||
#define MSGBOX3( x ) Platform_MessageBox( "Host Recursive Error", (x), true )
|
||||
#define ASSERT( exp ) if(!( exp )) Sys_Error( "assert failed at %s:%i\n", __FILE__, __LINE__ )
|
||||
|
||||
/*
|
||||
@@ -70,6 +67,7 @@ void Sys_InitLog( void );
|
||||
void Sys_CloseLog( void );
|
||||
void Sys_Quit( void ) NORETURN;
|
||||
qboolean Sys_NewInstance( const char *gamedir );
|
||||
void *Sys_GetNativeObject( const char *obj );
|
||||
|
||||
//
|
||||
// sys_con.c
|
||||
|
||||
@@ -632,12 +632,14 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
|
||||
else
|
||||
{
|
||||
const char* PATH = getenv("PATH");
|
||||
const char* begin;
|
||||
size_t argv0_length;
|
||||
if (!PATH)
|
||||
break;
|
||||
|
||||
size_t argv0_length = strlen(argv[0]);
|
||||
argv0_length = strlen(argv[0]);
|
||||
|
||||
const char* begin = PATH;
|
||||
begin = PATH;
|
||||
while (1)
|
||||
{
|
||||
const char* separator = strchr(begin, ':');
|
||||
|
||||
@@ -143,7 +143,7 @@ typedef struct ui_enginefuncs_s
|
||||
void *(*pfnKeyGetState)( const char *name ); // for mlook, klook etc
|
||||
|
||||
// engine memory manager
|
||||
void* (*pfnMemAlloc)( size_t cb, const char *filename, const int fileline );
|
||||
void* (*pfnMemAlloc)( size_t cb, const char *filename, const int fileline ) ALLOC_CHECK( 1 );
|
||||
void (*pfnMemFree)( void *mem, const char *filename, const int fileline );
|
||||
|
||||
// collect info from engine
|
||||
|
||||
@@ -86,7 +86,7 @@ typedef struct server_physics_api_s
|
||||
const byte *(*pfnGetTextureData)( unsigned int texnum );
|
||||
|
||||
// static allocations
|
||||
void *(*pfnMemAlloc)( size_t cb, const char *filename, const int fileline );
|
||||
void *(*pfnMemAlloc)( size_t cb, const char *filename, const int fileline ) ALLOC_CHECK( 1 );
|
||||
void (*pfnMemFree)( void *mem, const char *filename, const int fileline );
|
||||
|
||||
// trace & contents
|
||||
|
||||
@@ -32,10 +32,9 @@ struct jnimethods_s
|
||||
JNIEnv *env;
|
||||
jobject activity;
|
||||
jclass actcls;
|
||||
jmethodID getID;
|
||||
jmethodID saveID;
|
||||
jmethodID loadID;
|
||||
jmethodID getKeyboardHeight;
|
||||
jmethodID loadAndroidID;
|
||||
jmethodID getAndroidID;
|
||||
jmethodID saveAndroidID;
|
||||
} jni;
|
||||
|
||||
void Android_Init( void )
|
||||
@@ -43,10 +42,9 @@ void Android_Init( void )
|
||||
jni.env = (JNIEnv *)SDL_AndroidGetJNIEnv();
|
||||
jni.activity = (jobject)SDL_AndroidGetActivity();
|
||||
jni.actcls = (*jni.env)->GetObjectClass( jni.env, jni.activity );
|
||||
jni.loadID = (*jni.env)->GetMethodID( jni.env, jni.actcls, "loadAndroidID", "()Ljava/lang/String;" );
|
||||
jni.getID = (*jni.env)->GetMethodID( jni.env, jni.actcls, "getAndroidID", "()Ljava/lang/String;" );
|
||||
jni.saveID = (*jni.env)->GetMethodID( jni.env, jni.actcls, "saveAndroidID", "(Ljava/lang/String;)V" );
|
||||
jni.getKeyboardHeight = (*jni.env)->GetMethodID( jni.env, jni.actcls, "getKeyboardHeight", "()I" );
|
||||
jni.loadAndroidID = (*jni.env)->GetMethodID( jni.env, jni.actcls, "loadAndroidID", "()Ljava/lang/String;" );
|
||||
jni.getAndroidID = (*jni.env)->GetMethodID( jni.env, jni.actcls, "getAndroidID", "()Ljava/lang/String;" );
|
||||
jni.saveAndroidID = (*jni.env)->GetMethodID( jni.env, jni.actcls, "saveAndroidID", "(Ljava/lang/String;)V" );
|
||||
|
||||
SDL_SetHint( SDL_HINT_ORIENTATIONS, "LandscapeLeft LandscapeRight" );
|
||||
SDL_SetHint( SDL_HINT_JOYSTICK_HIDAPI_STEAM, "1" );
|
||||
@@ -95,7 +93,7 @@ const char *Android_GetAndroidID( void )
|
||||
|
||||
if( COM_CheckString( id ) ) return id;
|
||||
|
||||
resultJNIStr = (*jni.env)->CallObjectMethod( jni.env, jni.activity, jni.getID );
|
||||
resultJNIStr = (*jni.env)->CallObjectMethod( jni.env, jni.activity, jni.getAndroidID );
|
||||
resultCStr = (*jni.env)->GetStringUTFChars( jni.env, resultJNIStr, NULL );
|
||||
Q_strncpy( id, resultCStr, sizeof( id ) );
|
||||
(*jni.env)->ReleaseStringUTFChars( jni.env, resultJNIStr, resultCStr );
|
||||
@@ -114,7 +112,7 @@ const char *Android_LoadID( void )
|
||||
jstring resultJNIStr;
|
||||
const char *resultCStr;
|
||||
|
||||
resultJNIStr = (*jni.env)->CallObjectMethod( jni.env, jni.activity, jni.loadID );
|
||||
resultJNIStr = (*jni.env)->CallObjectMethod( jni.env, jni.activity, jni.loadAndroidID );
|
||||
resultCStr = (*jni.env)->GetStringUTFChars( jni.env, resultJNIStr, NULL );
|
||||
Q_strncpy( id, resultCStr, sizeof( id ) );
|
||||
(*jni.env)->ReleaseStringUTFChars( jni.env, resultJNIStr, resultCStr );
|
||||
@@ -129,7 +127,7 @@ Android_SaveID
|
||||
*/
|
||||
void Android_SaveID( const char *id )
|
||||
{
|
||||
(*jni.env)->CallVoidMethod( jni.env, jni.activity, jni.saveID, (*jni.env)->NewStringUTF( jni.env, id ) );
|
||||
(*jni.env)->CallVoidMethod( jni.env, jni.activity, jni.saveAndroidID, (*jni.env)->NewStringUTF( jni.env, id ) );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -144,14 +142,4 @@ void Platform_ShellExecute( const char *path, const char *parms )
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
Android_GetKeyboardHeight
|
||||
========================
|
||||
*/
|
||||
int Android_GetKeyboardHeight( void )
|
||||
{
|
||||
return (*jni.env)->CallIntMethod( jni.env, jni.activity, jni.getKeyboardHeight );
|
||||
}
|
||||
|
||||
#endif // XASH_DEDICATED
|
||||
|
||||
@@ -13,10 +13,16 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <dlfcn.h>
|
||||
#include <signal.h>
|
||||
#include <ucontext.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include "platform/platform.h"
|
||||
|
||||
static void *g_hsystemd;
|
||||
@@ -103,3 +109,44 @@ void Linux_Shutdown( void )
|
||||
g_hsystemd = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void Linux_TimerHandler( int sig, siginfo_t *si, void *uc )
|
||||
{
|
||||
timer_t *tidp = si->si_value.sival_ptr;
|
||||
int overrun = timer_getoverrun( *tidp );
|
||||
Con_Printf( "Frame too long (overrun %d)!\n", overrun );
|
||||
}
|
||||
|
||||
#define DEBUG_TIMER_SIGNAL SIGRTMIN
|
||||
|
||||
void Linux_SetTimer( float tm )
|
||||
{
|
||||
static timer_t timerid;
|
||||
|
||||
if( !timerid && tm )
|
||||
{
|
||||
struct sigevent sev = { 0 };
|
||||
struct sigaction sa = { 0 };
|
||||
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
sa.sa_sigaction = Linux_TimerHandler;
|
||||
sigaction( DEBUG_TIMER_SIGNAL, &sa, NULL );
|
||||
// this path availiable in POSIX, but may signal wrong thread...
|
||||
// sev.sigev_notify = SIGEV_SIGNAL;
|
||||
sev.sigev_notify = SIGEV_THREAD_ID;
|
||||
sev._sigev_un._tid = gettid();
|
||||
sev.sigev_signo = DEBUG_TIMER_SIGNAL;
|
||||
sev.sigev_value.sival_ptr = &timerid;
|
||||
timer_create( CLOCK_REALTIME, &sev, &timerid );
|
||||
}
|
||||
|
||||
if( timerid )
|
||||
{
|
||||
struct itimerspec its = {0};
|
||||
its.it_value.tv_sec = tm;
|
||||
its.it_value.tv_nsec = 1000000000ULL * fmod( tm, 1.0f );
|
||||
its.it_interval.tv_sec = 0;
|
||||
its.it_interval.tv_nsec = 0;
|
||||
timer_settime( timerid, 0, &its, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,11 @@ void Platform_MessageBox( const char *title, const char *message, qboolean paren
|
||||
qboolean Sys_DebuggerPresent( void ); // optional, see Sys_DebugBreak
|
||||
void Platform_SetStatus( const char *status );
|
||||
|
||||
// legacy iOS port functions
|
||||
#if TARGET_OS_IOS
|
||||
const char *IOS_GetDocsDir( void );
|
||||
#endif // TARGET_OS_IOS
|
||||
|
||||
#if XASH_WIN32 || XASH_LINUX
|
||||
#define XASH_PLATFORM_HAVE_STATUS 1
|
||||
#else
|
||||
@@ -58,7 +63,6 @@ const char *Android_LoadID( void );
|
||||
void Android_SaveID( const char *id );
|
||||
void Android_Init( void );
|
||||
void *Android_GetNativeObject( const char *name );
|
||||
int Android_GetKeyboardHeight( void );
|
||||
#endif
|
||||
|
||||
#if XASH_WIN32
|
||||
@@ -87,6 +91,7 @@ void DOS_Shutdown( void );
|
||||
#if XASH_LINUX
|
||||
void Linux_Init( void );
|
||||
void Linux_Shutdown( void );
|
||||
void Linux_SetTimer( float time );
|
||||
#endif
|
||||
|
||||
static inline void Platform_Init( void )
|
||||
@@ -134,17 +139,6 @@ static inline void Platform_Shutdown( void )
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void *Platform_GetNativeObject( const char *name )
|
||||
{
|
||||
void *ptr = NULL;
|
||||
|
||||
#if XASH_ANDROID
|
||||
ptr = Android_GetNativeObject( name );
|
||||
#endif
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
@@ -153,7 +147,6 @@ static inline void *Platform_GetNativeObject( const char *name )
|
||||
==============================================================================
|
||||
*/
|
||||
void Platform_Vibrate( float life, char flags );
|
||||
void*Platform_GetNativeObject( const char *name );
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
@@ -189,6 +182,13 @@ void Platform_SetClipboardText( const char *buffer );
|
||||
#define SDL_VERSION_ATLEAST( x, y, z ) 0
|
||||
#endif
|
||||
|
||||
static void Platform_SetTimer( float time )
|
||||
{
|
||||
#if XASH_LINUX
|
||||
Linux_SetTimer( time );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ static qboolean SDLash_IsInstanceIDAGameController( SDL_JoystickID joyId )
|
||||
return true;
|
||||
return false;
|
||||
#else
|
||||
if( SDL_GameControllerFromInstanceID( joyId ) )
|
||||
if( SDL_GameControllerFromInstanceID( joyId ) != NULL )
|
||||
return true;
|
||||
return false;
|
||||
#endif
|
||||
@@ -148,7 +148,7 @@ static void SDLash_KeyEvent( SDL_KeyboardEvent key )
|
||||
#else
|
||||
int keynum = key.keysym.sym;
|
||||
#endif
|
||||
qboolean numLock = SDL_GetModState() & KMOD_NUM;
|
||||
qboolean numLock = FBitSet( SDL_GetModState(), KMOD_NUM );
|
||||
|
||||
#if XASH_ANDROID
|
||||
if( keynum == SDL_SCANCODE_VOLUMEUP || keynum == SDL_SCANCODE_VOLUMEDOWN )
|
||||
@@ -159,7 +159,7 @@ static void SDLash_KeyEvent( SDL_KeyboardEvent key )
|
||||
|
||||
if( SDL_IsTextInputActive() && down && cls.key_dest != key_game )
|
||||
{
|
||||
if( SDL_GetModState() & KMOD_CTRL )
|
||||
if( FBitSet( SDL_GetModState(), KMOD_CTRL ))
|
||||
{
|
||||
if( keynum >= SDL_SCANCODE_A && keynum <= SDL_SCANCODE_Z )
|
||||
{
|
||||
@@ -176,7 +176,7 @@ static void SDLash_KeyEvent( SDL_KeyboardEvent key )
|
||||
|
||||
if( isprint( keynum ) )
|
||||
{
|
||||
if( SDL_GetModState() & KMOD_SHIFT )
|
||||
if( FBitSet( SDL_GetModState(), KMOD_SHIFT ))
|
||||
{
|
||||
keynum = Key_ToUpper( keynum );
|
||||
}
|
||||
|
||||
@@ -158,8 +158,8 @@ void *SW_LockBuffer( void )
|
||||
void *pixels;
|
||||
int stride;
|
||||
|
||||
if( SDL_LockTexture(sw.tex, NULL, &pixels, &stride ) )
|
||||
Sys_Error("%s", SDL_GetError());
|
||||
if( SDL_LockTexture(sw.tex, NULL, &pixels, &stride ) < 0 )
|
||||
Sys_Error( "%s: %s", __func__, SDL_GetError( ));
|
||||
return pixels;
|
||||
}
|
||||
|
||||
@@ -272,7 +272,7 @@ static void R_InitVideoModes( void )
|
||||
int j;
|
||||
SDL_DisplayMode mode;
|
||||
|
||||
if( SDL_GetDisplayMode( displayIndex, i, &mode ) )
|
||||
if( SDL_GetDisplayMode( displayIndex, i, &mode ) < 0 )
|
||||
{
|
||||
Msg( "SDL_GetDisplayMode: %s\n", SDL_GetError() );
|
||||
continue;
|
||||
@@ -419,12 +419,16 @@ static qboolean WIN_SetWindowIcon( HICON ico )
|
||||
{
|
||||
SDL_SysWMinfo wminfo;
|
||||
|
||||
if( SDL_GetWindowWMInfo( host.hWnd, &wminfo ))
|
||||
SDL_VERSION( &wminfo.version );
|
||||
|
||||
if( SDL_GetWindowWMInfo( host.hWnd, &wminfo ) == SDL_TRUE )
|
||||
{
|
||||
SendMessage( wminfo.info.win.window, WM_SETICON, ICON_SMALL, (LONG_PTR)ico );
|
||||
SendMessage( wminfo.info.win.window, WM_SETICON, ICON_BIG, (LONG_PTR)ico );
|
||||
return true;
|
||||
}
|
||||
|
||||
Con_Reportf( S_ERROR "%s: %s", __func__, SDL_GetError( ));
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@@ -438,6 +442,25 @@ GL_GetProcAddress
|
||||
void *GL_GetProcAddress( const char *name )
|
||||
{
|
||||
void *func = SDL_GL_GetProcAddress( name );
|
||||
#if !SDL_VERSION_ATLEAST( 2, 0, 6 ) && XASH_POSIX
|
||||
if( !func && Sys_CheckParm( "-egl" ))
|
||||
{
|
||||
/*
|
||||
* SDL2 has broken SDL_GL_GetProcAddress until this commit if using egl:
|
||||
* https://github.com/libsdl-org/SDL/commit/466ba57d42d244e80357e9ad3011c50af30ed225
|
||||
* so call eglGetProcAddress directly
|
||||
* */
|
||||
static void *(*peglGetProcAddress)( const char * );
|
||||
if( !peglGetProcAddress )
|
||||
{
|
||||
void *lib = dlopen( "libEGL.so", RTLD_NOW );
|
||||
if( lib )
|
||||
*(void**)&peglGetProcAddress = dlsym( lib, "eglGetProcAddress" );
|
||||
}
|
||||
if( peglGetProcAddress )
|
||||
func = peglGetProcAddress( name );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if XASH_PSVITA
|
||||
// try to find in main module
|
||||
@@ -473,8 +496,8 @@ void GL_UpdateSwapInterval( void )
|
||||
{
|
||||
ClearBits( gl_vsync.flags, FCVAR_CHANGED );
|
||||
|
||||
if( SDL_GL_SetSwapInterval( gl_vsync.value ) )
|
||||
Con_Reportf( S_ERROR "SDL_GL_SetSwapInterval: %s\n", SDL_GetError( ) );
|
||||
if( SDL_GL_SetSwapInterval( gl_vsync.value ) < 0 )
|
||||
Con_Reportf( S_ERROR "SDL_GL_SetSwapInterval: %s\n", SDL_GetError( ));
|
||||
}
|
||||
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
}
|
||||
@@ -523,7 +546,7 @@ GL_UpdateContext
|
||||
static qboolean GL_UpdateContext( void )
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
if( SDL_GL_MakeCurrent( host.hWnd, glw_state.context ))
|
||||
if( SDL_GL_MakeCurrent( host.hWnd, glw_state.context ) < 0 )
|
||||
{
|
||||
Con_Reportf( S_ERROR "GL_UpdateContext: %s\n", SDL_GetError());
|
||||
return GL_DeleteContext();
|
||||
@@ -580,7 +603,7 @@ static qboolean VID_SetScreenResolution( int width, int height, window_mode_t wi
|
||||
want.w = width;
|
||||
want.h = height;
|
||||
|
||||
if( SDL_GetClosestDisplayMode( 0, &want, &got ) < 0 )
|
||||
if( SDL_GetClosestDisplayMode( 0, &want, &got ) == NULL )
|
||||
{
|
||||
Con_Printf( S_ERROR "%s: SDL_GetClosestDisplayMode: %s", __func__, SDL_GetError( ));
|
||||
return false;
|
||||
@@ -626,14 +649,14 @@ void VID_RestoreScreenResolution( void )
|
||||
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
}
|
||||
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
static void VID_SetWindowIcon( SDL_Window *hWnd )
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
rgbdata_t *icon = NULL;
|
||||
char iconpath[MAX_STRING];
|
||||
#if XASH_WIN32 // ICO support only for Win32
|
||||
const char *localIcoPath;
|
||||
|
||||
#if XASH_WIN32 // ICO support only for Win32
|
||||
if(( localIcoPath = FS_GetDiskPath( GI->iconpath, true )))
|
||||
{
|
||||
HICON ico = (HICON)LoadImage( NULL, localIcoPath, IMAGE_ICON, 0, 0, LR_LOADFROMFILE|LR_DEFAULTSIZE );
|
||||
@@ -666,8 +689,8 @@ static void VID_SetWindowIcon( SDL_Window *hWnd )
|
||||
#if XASH_WIN32 // ICO support only for Win32
|
||||
WIN_SetWindowIcon( LoadIcon( host.hInst, MAKEINTRESOURCE( 101 )));
|
||||
#endif
|
||||
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
}
|
||||
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
|
||||
static qboolean VID_CreateWindowWithSafeGL( const char *wndname, int xpos, int ypos, int w, int h, uint32_t flags )
|
||||
{
|
||||
@@ -785,6 +808,7 @@ qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
|
||||
else VID_RestoreScreenResolution();
|
||||
#endif
|
||||
|
||||
VID_SetWindowIcon( host.hWnd );
|
||||
SDL_ShowWindow( host.hWnd );
|
||||
|
||||
if( glw_state.software )
|
||||
@@ -812,8 +836,13 @@ qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
|
||||
{
|
||||
if( !glw_state.initialized )
|
||||
{
|
||||
if( !GL_CreateContext( ))
|
||||
return false;
|
||||
while( !GL_CreateContext( ))
|
||||
{
|
||||
glw_state.safe++;
|
||||
if(glw_state.safe > SAFE_DONTCARE)
|
||||
return false;
|
||||
GL_SetupAttributes(); // re-choose attributes
|
||||
}
|
||||
|
||||
VID_StartupGamma();
|
||||
}
|
||||
@@ -991,8 +1020,12 @@ qboolean R_Init_Video( const int type )
|
||||
refState.desktopBitsPixel = 16;
|
||||
#endif
|
||||
|
||||
#ifdef SDL_HINT_QTWAYLAND_WINDOW_FLAGS
|
||||
SDL_SetHint( SDL_HINT_QTWAYLAND_WINDOW_FLAGS, "OverridesSystemGestures" );
|
||||
#endif
|
||||
#ifdef SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION
|
||||
SDL_SetHint( SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION, "landscape" );
|
||||
#endif
|
||||
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) && !XASH_WIN32
|
||||
SDL_SetHint( "SDL_VIDEO_X11_XRANDR", "1" );
|
||||
@@ -1018,7 +1051,7 @@ qboolean R_Init_Video( const int type )
|
||||
// refdll can request some attributes
|
||||
GL_SetupAttributes( );
|
||||
|
||||
if( SDL_GL_LoadLibrary( EGL_LIB ) )
|
||||
if( SDL_GL_LoadLibrary( EGL_LIB ) < 0 )
|
||||
{
|
||||
Con_Reportf( S_ERROR "Couldn't initialize OpenGL: %s\n", SDL_GetError());
|
||||
return false;
|
||||
@@ -1057,7 +1090,11 @@ rserr_t R_ChangeDisplaySettings( int width, int height, window_mode_t window_mod
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
SDL_DisplayMode displayMode;
|
||||
|
||||
SDL_GetCurrentDisplayMode( 0, &displayMode );
|
||||
if( SDL_GetCurrentDisplayMode( 0, &displayMode ) < 0 )
|
||||
{
|
||||
Con_Printf( S_ERROR "SDL_GetCurrentDisplayMode: %s", SDL_GetError( ));
|
||||
return rserr_invalid_mode;
|
||||
}
|
||||
|
||||
// check our desktop attributes
|
||||
refState.desktopBitsPixel = SDL_BITSPERPIXEL( displayMode.format );
|
||||
@@ -1086,8 +1123,11 @@ rserr_t R_ChangeDisplaySettings( int width, int height, window_mode_t window_mod
|
||||
VID_RestoreScreenResolution();
|
||||
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
if( SDL_SetWindowFullscreen( host.hWnd, 0 ))
|
||||
if( SDL_SetWindowFullscreen( host.hWnd, 0 ) < 0 )
|
||||
{
|
||||
Con_Printf( S_ERROR "SDL_SetWindowFullscreen: %s", SDL_GetError( ));
|
||||
return rserr_invalid_fullscreen;
|
||||
}
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 5 )
|
||||
SDL_SetWindowResizable( host.hWnd, SDL_TRUE );
|
||||
#endif
|
||||
|
||||
@@ -34,7 +34,11 @@ GNU General Public License for more details.
|
||||
// 2. FS functions are removed, instead we have full fs_api_t
|
||||
// 3. SlerpBones, CalcBonePosition/Quaternion calls were moved to libpublic/mathlib
|
||||
// 4. R_StudioEstimateFrame now has time argument
|
||||
#define REF_API_VERSION 4
|
||||
// 5. Removed GetSomethingByIndex calls, renderers are supposed to cache pointer values
|
||||
// Removed previously unused calls
|
||||
// Simplified remapping calls
|
||||
// GetRefAPI is now expected to return REF_API_VERSION
|
||||
#define REF_API_VERSION 5
|
||||
|
||||
|
||||
#define TF_SKY (TF_SKYSIDE|TF_NOMIPMAP)
|
||||
@@ -257,6 +261,7 @@ typedef enum
|
||||
PARM_LOCAL_GAME = -11,
|
||||
PARM_NUMENTITIES = -12, // local game only
|
||||
PARM_NUMMODELS = -13, // cl.nummodels
|
||||
PARM_WORLD_VERSION = -14,
|
||||
} ref_parm_e;
|
||||
|
||||
typedef struct ref_api_s
|
||||
@@ -299,15 +304,13 @@ typedef struct ref_api_s
|
||||
void (*CL_DrawCenterPrint)( void );
|
||||
|
||||
// entity management
|
||||
struct cl_entity_s *(*GetLocalPlayer)( void );
|
||||
struct cl_entity_s *(*GetViewModel)( void );
|
||||
struct cl_entity_s *(*GetEntityByIndex)( int idx );
|
||||
struct cl_entity_s *(*R_BeamGetEntity)( int index );
|
||||
struct cl_entity_s *(*CL_GetWaterEntity)( const vec3_t p );
|
||||
qboolean (*CL_AddVisibleEntity)( cl_entity_t *ent, int entityType );
|
||||
|
||||
// brushes
|
||||
int (*Mod_SampleSizeForFace)( struct msurface_s *surf );
|
||||
int (*Mod_SampleSizeForFace)( const struct msurface_s *surf );
|
||||
qboolean (*Mod_BoxVisible)( const vec3_t mins, const vec3_t maxs, const byte *visbits );
|
||||
struct world_static_s *(*GetWorld)( void ); // returns &world
|
||||
mleaf_t *(*Mod_PointInLeaf)( const vec3_t p, mnode_t *node );
|
||||
@@ -329,15 +332,11 @@ typedef struct ref_api_s
|
||||
// model management
|
||||
model_t *(*Mod_ForName)( const char *name, qboolean crash, qboolean trackCRC );
|
||||
void *(*Mod_Extradata)( int type, model_t *model );
|
||||
struct model_s *(*pfnGetModelByIndex)( int index ); // CL_ModelHandle
|
||||
struct model_s *(*Mod_GetCurrentLoadingModel)( void ); // loadmodel
|
||||
void (*Mod_SetCurrentLoadingModel)( struct model_s* ); // loadmodel
|
||||
struct model_s **(*pfnGetModels)( void );
|
||||
|
||||
// remap
|
||||
qboolean (*CL_EntitySetRemapColors)( cl_entity_t *e, model_t *mod, int top, int bottom );
|
||||
struct remap_info_s *(*CL_GetRemapInfoForEntity)( cl_entity_t *e );
|
||||
void (*CL_AllocRemapInfo)( cl_entity_t *entity, model_t *model, int topcolor, int bottomcolor );
|
||||
void (*CL_FreeRemapInfo)( struct remap_info_s *info );
|
||||
void (*CL_UpdateRemapInfo)( cl_entity_t *entity, int topcolor, int bottomcolor );
|
||||
|
||||
// utils
|
||||
void (*CL_ExtraUpdate)( void );
|
||||
@@ -346,9 +345,8 @@ typedef struct ref_api_s
|
||||
float (*COM_RandomFloat)( float rmin, float rmax );
|
||||
int (*COM_RandomLong)( int rmin, int rmax );
|
||||
struct screenfade_s *(*GetScreenFade)( void );
|
||||
struct client_textmessage_s *(*pfnTextMessageGet)( const char *pName );
|
||||
void (*GetPredictedOrigin)( vec3_t v );
|
||||
color24 *(*CL_GetPaletteColor)(int color); // clgame.palette[color]
|
||||
color24 *(*CL_GetPaletteColor)( void ); // clgame.palette[color]
|
||||
void (*CL_GetScreenInfo)( int *width, int *height ); // clgame.scrInfo, ptrs may be NULL
|
||||
void (*SetLocalLightLevel)( int level ); // cl.local.light_level
|
||||
int (*Sys_CheckParm)( const char *flag );
|
||||
@@ -364,8 +362,8 @@ typedef struct ref_api_s
|
||||
// memory
|
||||
poolhandle_t (*_Mem_AllocPool)( const char *name, const char *filename, int fileline );
|
||||
void (*_Mem_FreePool)( poolhandle_t *poolptr, const char *filename, int fileline );
|
||||
void *(*_Mem_Alloc)( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline );
|
||||
void *(*_Mem_Realloc)( poolhandle_t poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline );
|
||||
void *(*_Mem_Alloc)( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline ) ALLOC_CHECK( 2 );
|
||||
void *(*_Mem_Realloc)( poolhandle_t poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline ) ALLOC_CHECK( 3 );
|
||||
void (*_Mem_Free)( void *data, const char *filename, int fileline );
|
||||
|
||||
// library management
|
||||
@@ -422,7 +420,6 @@ typedef struct ref_api_s
|
||||
rgbdata_t *(*FS_CopyImage)( rgbdata_t *in );
|
||||
void (*FS_FreeImage)( rgbdata_t *pack );
|
||||
void (*Image_SetMDLPointer)( byte *p );
|
||||
poolhandle_t (*Image_GetPool)( void );
|
||||
const struct bpc_desc_s *(*Image_GetPFDesc)( int idx );
|
||||
|
||||
// client exports
|
||||
@@ -451,6 +448,7 @@ typedef struct ref_interface_s
|
||||
void (*GL_InitExtensions)( void );
|
||||
void (*GL_ClearExtensions)( void );
|
||||
|
||||
// scene rendering
|
||||
void (*R_BeginFrame)( qboolean clearScene );
|
||||
void (*R_RenderScene)( void );
|
||||
void (*R_EndFrame)( void );
|
||||
@@ -465,7 +463,8 @@ typedef struct ref_interface_s
|
||||
|
||||
qboolean (*R_AddEntity)( struct cl_entity_s *clent, int type );
|
||||
void (*CL_AddCustomBeam)( cl_entity_t *pEnvBeam );
|
||||
void (*R_ProcessEntData)( qboolean allocate );
|
||||
void (*R_ProcessEntData)( qboolean allocate, cl_entity_t *entities, unsigned int max_entities );
|
||||
void (*R_Flush)( unsigned int flush_flags );
|
||||
|
||||
// debug
|
||||
void (*R_ShowTextures)( void );
|
||||
@@ -506,7 +505,7 @@ typedef struct ref_interface_s
|
||||
|
||||
// bmodel
|
||||
void (*R_InitSkyClouds)( struct mip_s *mt, struct texture_s *tx, qboolean custom_palette );
|
||||
void (*GL_SubdivideSurface)( msurface_t *fa );
|
||||
void (*GL_SubdivideSurface)( model_t *mod, msurface_t *fa );
|
||||
void (*CL_RunLightStyles)( void );
|
||||
|
||||
// sprites
|
||||
|
||||
@@ -360,7 +360,6 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
qboolean initialized; // sv_init has completed
|
||||
qboolean game_library_loaded; // is game library loaded in SV_InitGame
|
||||
double timestart; // just for profiling
|
||||
|
||||
int maxclients; // server max clients
|
||||
@@ -473,6 +472,8 @@ extern convar_t sv_userinfo_penalty_multiplier;
|
||||
extern convar_t sv_userinfo_penalty_attempts;
|
||||
extern convar_t sv_fullupdate_penalty_time;
|
||||
extern convar_t sv_log_outofband;
|
||||
extern convar_t sv_allow_autoaim;
|
||||
extern convar_t sv_aim;
|
||||
|
||||
//===========================================================
|
||||
//
|
||||
@@ -563,7 +564,7 @@ qboolean SV_IsPlayerIndex( int idx );
|
||||
int SV_CalcPing( sv_client_t *cl );
|
||||
void SV_InitClientMove( void );
|
||||
void SV_UpdateServerInfo( void );
|
||||
void SV_EndRedirect( void );
|
||||
void SV_EndRedirect( host_redirect_t *rd );
|
||||
void SV_RejectConnection( netadr_t from, const char *fmt, ... ) _format( 2 );
|
||||
void SV_GetPlayerCount( int *clients, int *bots );
|
||||
|
||||
|
||||
@@ -639,7 +639,7 @@ void SV_DropClient( sv_client_t *cl, qboolean crash )
|
||||
cl->frames = NULL;
|
||||
|
||||
if( NET_CompareBaseAdr( cl->netchan.remote_address, host.rd.address ))
|
||||
SV_EndRedirect();
|
||||
SV_EndRedirect( &host.rd );
|
||||
|
||||
// throw away any residual garbage in the channel.
|
||||
Netchan_Clear( &cl->netchan );
|
||||
@@ -676,22 +676,19 @@ SVC COMMAND REDIRECT
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
void SV_BeginRedirect( netadr_t adr, rdtype_t target, char *buffer, size_t buffersize, void (*flush))
|
||||
static void SV_BeginRedirect( host_redirect_t *rd, netadr_t adr, rdtype_t target, char *buffer, size_t buffersize, void (*flush))
|
||||
{
|
||||
if( !target || !buffer || !buffersize || !flush )
|
||||
return;
|
||||
|
||||
host.rd.target = target;
|
||||
host.rd.buffer = buffer;
|
||||
host.rd.buffersize = buffersize;
|
||||
host.rd.flush = flush;
|
||||
host.rd.address = adr;
|
||||
host.rd.buffer[0] = 0;
|
||||
if( host.rd.lines == 0 )
|
||||
host.rd.lines = -1;
|
||||
rd->target = target;
|
||||
rd->buffer = buffer;
|
||||
rd->buffersize = buffersize;
|
||||
rd->flush = flush;
|
||||
rd->address = adr;
|
||||
rd->buffer[0] = 0;
|
||||
if( rd->lines == 0 )
|
||||
rd->lines = -1;
|
||||
}
|
||||
|
||||
void SV_FlushRedirect( netadr_t adr, int dest, char *buf )
|
||||
static void SV_FlushRedirect( netadr_t adr, int dest, char *buf )
|
||||
{
|
||||
if( sv.current_client && FBitSet( sv.current_client->flags, FCL_FAKECLIENT ))
|
||||
return;
|
||||
@@ -712,18 +709,18 @@ void SV_FlushRedirect( netadr_t adr, int dest, char *buf )
|
||||
}
|
||||
}
|
||||
|
||||
void SV_EndRedirect( void )
|
||||
void SV_EndRedirect( host_redirect_t *rd )
|
||||
{
|
||||
if( host.rd.lines > 0 )
|
||||
if( rd->lines > 0 )
|
||||
return;
|
||||
|
||||
if( host.rd.flush )
|
||||
host.rd.flush( host.rd.address, host.rd.target, host.rd.buffer );
|
||||
if( rd->flush )
|
||||
rd->flush( rd->address, rd->target, rd->buffer );
|
||||
|
||||
host.rd.target = 0;
|
||||
host.rd.buffer = NULL;
|
||||
host.rd.buffersize = 0;
|
||||
host.rd.flush = NULL;
|
||||
rd->target = RD_NONE;
|
||||
rd->buffer = NULL;
|
||||
rd->buffersize = 0;
|
||||
rd->flush = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -733,24 +730,26 @@ Rcon_Print
|
||||
Print message to rcon buffer and send to rcon redirect target
|
||||
================
|
||||
*/
|
||||
void Rcon_Print( const char *pMsg )
|
||||
void Rcon_Print( host_redirect_t *rd, const char *pMsg )
|
||||
{
|
||||
if( host.rd.target && host.rd.lines && host.rd.flush && host.rd.buffer )
|
||||
size_t len;
|
||||
|
||||
if( !rd->target || !rd->lines || !rd->flush || !rd->buffer )
|
||||
return;
|
||||
|
||||
len = Q_strncat( rd->buffer, pMsg, rd->buffersize );
|
||||
|
||||
if( len && rd->buffer[len - 1] == '\n' )
|
||||
{
|
||||
size_t len = Q_strncat( host.rd.buffer, pMsg, host.rd.buffersize );
|
||||
rd->flush( rd->address, rd->target, rd->buffer );
|
||||
|
||||
if( len && host.rd.buffer[len-1] == '\n' )
|
||||
{
|
||||
host.rd.flush( host.rd.address, host.rd.target, host.rd.buffer );
|
||||
if( rd->lines > 0 )
|
||||
rd->lines--;
|
||||
|
||||
if( host.rd.lines > 0 )
|
||||
host.rd.lines--;
|
||||
rd->buffer[0] = 0;
|
||||
|
||||
host.rd.buffer[0] = 0;
|
||||
|
||||
if( !host.rd.lines )
|
||||
Msg( "End of redirection!\n" );
|
||||
}
|
||||
if( !rd->lines )
|
||||
Msg( "End of redirection!\n" );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1090,7 +1089,7 @@ void SV_RemoteCommand( netadr_t from, sizebuf_t *msg )
|
||||
|
||||
if( Rcon_Validate( ))
|
||||
{
|
||||
SV_BeginRedirect( from, RD_PACKET, outputbuf, sizeof( outputbuf ) - 16, SV_FlushRedirect );
|
||||
SV_BeginRedirect( &host.rd, from, RD_PACKET, outputbuf, sizeof( outputbuf ) - 16, SV_FlushRedirect );
|
||||
|
||||
remaining[0] = 0;
|
||||
for( i = 2; i < Cmd_Argc(); i++ )
|
||||
@@ -1101,7 +1100,7 @@ void SV_RemoteCommand( netadr_t from, sizebuf_t *msg )
|
||||
}
|
||||
Cmd_ExecuteString( remaining );
|
||||
|
||||
SV_EndRedirect();
|
||||
SV_EndRedirect( &host.rd );
|
||||
}
|
||||
else Con_Printf( S_ERROR "Bad rcon_password.\n" );
|
||||
}
|
||||
@@ -1772,6 +1771,9 @@ static qboolean SV_ShouldUpdateUserinfo( sv_client_t *cl )
|
||||
if( FBitSet( cl->flags, FCL_FAKECLIENT ))
|
||||
return allow;
|
||||
|
||||
if( Host_IsLocalGame( ))
|
||||
return allow;
|
||||
|
||||
// start from 1 second
|
||||
if( !cl->userinfo_penalty )
|
||||
cl->userinfo_penalty = sv_userinfo_penalty_time.value;
|
||||
|
||||
@@ -121,8 +121,10 @@ void SV_ParseConsistencyResponse( sv_client_t *cl, sizebuf_t *msg )
|
||||
{
|
||||
value = MSG_ReadUBitLong( msg, 32 );
|
||||
|
||||
LittleLongSW( value );
|
||||
|
||||
// will be compare only first 4 bytes
|
||||
if( value != *(int *)r->rgucMD5_hash )
|
||||
if( memcmp( &value, r->rgucMD5_hash, 4 ))
|
||||
badresindex = idx + 1;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -2385,7 +2385,9 @@ static void GAME_EXPORT pfnGetAimVector( edict_t* ent, float speed, float *rgflR
|
||||
|
||||
// try all possible entities
|
||||
VectorCopy( svgame.globals->v_forward, bestdir );
|
||||
bestdist = Cvar_VariableValue( "sv_aim" );
|
||||
if( sv_allow_autoaim.value )
|
||||
bestdist = sv_aim.value;
|
||||
else bestdist = 0;
|
||||
|
||||
check = EDICT_NUM( 1 ); // start at first client
|
||||
for( i = 1; i < svgame.numEntities; i++, check++ )
|
||||
@@ -3031,7 +3033,7 @@ void SV_SetStringArrayMode( qboolean dynamic )
|
||||
#endif
|
||||
}
|
||||
|
||||
#if XASH_64BIT && !XASH_WIN32 && !XASH_APPLE && !XASH_NSWITCH
|
||||
#if XASH_64BIT && !XASH_WIN32 && !XASH_APPLE && !XASH_NSWITCH && !XASH_ANDROID
|
||||
#define USE_MMAP
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
@@ -4523,7 +4525,7 @@ static qboolean GAME_EXPORT pfnVoice_GetClientListening( int iReceiver, int iSen
|
||||
iReceiver -= 1;
|
||||
iSender -= 1;
|
||||
|
||||
if( iReceiver < 0 || iReceiver >= svs.maxclients || iSender < 0 || iSender > svs.maxclients )
|
||||
if( iReceiver < 0 || iReceiver >= svs.maxclients || iSender < 0 || iSender >= svs.maxclients )
|
||||
return false;
|
||||
|
||||
return (FBitSet( svs.clients[iSender].listeners, BIT( iReceiver )) != 0 );
|
||||
@@ -4540,7 +4542,7 @@ static qboolean GAME_EXPORT pfnVoice_SetClientListening( int iReceiver, int iSen
|
||||
iReceiver -= 1;
|
||||
iSender -= 1;
|
||||
|
||||
if( iReceiver < 0 || iReceiver >= svs.maxclients || iSender < 0 || iSender > svs.maxclients )
|
||||
if( iReceiver < 0 || iReceiver >= svs.maxclients || iSender < 0 || iSender >= svs.maxclients )
|
||||
return false;
|
||||
|
||||
if( bListen ) SetBits( svs.clients[iSender].listeners, BIT( iReceiver ));
|
||||
@@ -4965,12 +4967,6 @@ static qboolean SV_ParseEdict( char **pfile, edict_t *ent )
|
||||
pkvd[i].szValue = copystring( temp );
|
||||
}
|
||||
#endif
|
||||
if( !Q_strcmp( pkvd[i].szKeyName, "light" ))
|
||||
{
|
||||
Mem_Free( pkvd[i].szKeyName );
|
||||
pkvd[i].szKeyName = copystring( "light_level" );
|
||||
}
|
||||
|
||||
if( !pkvd[i].fHandled )
|
||||
{
|
||||
pkvd[i].szClassName = classname;
|
||||
@@ -5130,7 +5126,6 @@ void SV_UnloadProgs( void )
|
||||
|
||||
Mod_ResetStudioAPI ();
|
||||
|
||||
svs.game_library_loaded = false;
|
||||
COM_FreeLibrary( svgame.hInstance );
|
||||
Mem_FreePool( &svgame.mempool );
|
||||
memset( &svgame, 0, sizeof( svgame ));
|
||||
@@ -5148,7 +5143,14 @@ qboolean SV_LoadProgs( const char *name )
|
||||
static playermove_t gpMove;
|
||||
edict_t *e;
|
||||
|
||||
if( svgame.hInstance ) SV_UnloadProgs();
|
||||
if( svgame.hInstance )
|
||||
{
|
||||
#if XASH_WIN32
|
||||
SV_UnloadProgs();
|
||||
#else // XASH_WIN32
|
||||
return true;
|
||||
#endif // XASH_WIN32
|
||||
}
|
||||
|
||||
// fill it in
|
||||
svgame.pmove = &gpMove;
|
||||
|
||||
@@ -706,7 +706,7 @@ qboolean SV_InitGame( void )
|
||||
{
|
||||
string dllpath;
|
||||
|
||||
if( svs.game_library_loaded )
|
||||
if( svgame.hInstance )
|
||||
return true;
|
||||
|
||||
// first initialize?
|
||||
@@ -721,7 +721,6 @@ qboolean SV_InitGame( void )
|
||||
}
|
||||
|
||||
// client frames will be allocated in SV_ClientConnect
|
||||
svs.game_library_loaded = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1042,8 +1041,9 @@ qboolean SV_SpawnServer( const char *mapname, const char *startspot, qboolean ba
|
||||
// force normal player collisions for single player
|
||||
if( svs.maxclients == 1 ) Cvar_SetValue( "sv_clienttrace", 1 );
|
||||
|
||||
// make sure what server name doesn't contain path and extension
|
||||
COM_FileBase( mapname, sv.name, sizeof( sv.name ));
|
||||
// allow loading maps from subdirectories, strip extension anyway
|
||||
Q_strncpy( sv.name, mapname, sizeof( sv.name ));
|
||||
COM_StripExtension( sv.name );
|
||||
|
||||
// precache and static commands can be issued during map initialization
|
||||
Host_SetServerState( ss_loading );
|
||||
@@ -1115,28 +1115,6 @@ int SV_GetMaxClients( void )
|
||||
return svs.maxclients;
|
||||
}
|
||||
|
||||
qboolean SV_InitGameProgs( void )
|
||||
{
|
||||
string dllpath;
|
||||
|
||||
if( svgame.hInstance ) return true; // already loaded
|
||||
|
||||
COM_GetCommonLibraryPath( LIBRARY_SERVER, dllpath, sizeof( dllpath ));
|
||||
|
||||
// just try to initialize
|
||||
SV_LoadProgs( dllpath );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SV_FreeGameProgs( void )
|
||||
{
|
||||
if( svs.initialized ) return; // server is active
|
||||
|
||||
// unload progs (free cvars and commands)
|
||||
SV_UnloadProgs();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SV_ExecLoadLevel
|
||||
|
||||
@@ -23,6 +23,7 @@ CVAR_DEFINE_AUTO( sv_lan, "0", 0, "server is a lan server ( no heartbeat, no aut
|
||||
CVAR_DEFINE_AUTO( sv_lan_rate, "20000.0", 0, "rate for lan server" );
|
||||
CVAR_DEFINE_AUTO( sv_nat, "0", 0, "enable NAT bypass for this server" );
|
||||
CVAR_DEFINE_AUTO( sv_aim, "1", FCVAR_ARCHIVE|FCVAR_SERVER, "auto aiming option" );
|
||||
CVAR_DEFINE_AUTO( sv_allow_autoaim, "0", FCVAR_ARCHIVE|FCVAR_SERVER, "auto aiming option (for HL25 compatibility)" );
|
||||
CVAR_DEFINE_AUTO( sv_unlag, "1", 0, "allow lag compensation on server-side" );
|
||||
CVAR_DEFINE_AUTO( sv_maxunlag, "0.5", 0, "max latency value which can be interpolated (by default ping should not exceed 500 units)" );
|
||||
CVAR_DEFINE_AUTO( sv_unlagpush, "0.0", 0, "interpolation bias for unlag time" );
|
||||
@@ -48,7 +49,8 @@ CVAR_DEFINE_AUTO( sv_send_logos, "1", 0, "send custom decal logo to other player
|
||||
CVAR_DEFINE_AUTO( sv_send_resources, "1", 0, "allow to download missed resources for players" );
|
||||
CVAR_DEFINE_AUTO( sv_logbans, "0", 0, "print into the server log info about player bans" );
|
||||
CVAR_DEFINE_AUTO( sv_allow_upload, "1", FCVAR_SERVER, "allow uploading custom resources on a server" );
|
||||
CVAR_DEFINE_AUTO( sv_allow_download, "1", FCVAR_SERVER, "allow downloading custom resources to the client" );
|
||||
CVAR_DEFINE( sv_allow_download, "sv_allowdownload", "1", FCVAR_SERVER, "allow downloading custom resources to the client" );
|
||||
static CVAR_DEFINE_AUTO( sv_allow_dlfile, "1", 0, "compatibility cvar, does nothing" );
|
||||
CVAR_DEFINE_AUTO( sv_uploadmax, "0.5", FCVAR_SERVER, "max size to upload custom resources (500 kB as default)" );
|
||||
CVAR_DEFINE_AUTO( sv_downloadurl, "", FCVAR_PROTECTED, "location from which clients can download missing files" );
|
||||
CVAR_DEFINE( sv_consistency, "mp_consistency", "1", FCVAR_SERVER, "enbale consistency check in multiplayer" );
|
||||
@@ -884,6 +886,7 @@ void SV_Init( void )
|
||||
Cvar_RegisterVariable( &sv_fps );
|
||||
Cvar_RegisterVariable( &showtriggers );
|
||||
Cvar_RegisterVariable( &sv_aim );
|
||||
Cvar_RegisterVariable( &sv_allow_autoaim );
|
||||
Cvar_RegisterVariable( &deathmatch );
|
||||
Cvar_RegisterVariable( &coop );
|
||||
Cvar_RegisterVariable( &teamplay );
|
||||
@@ -925,6 +928,7 @@ void SV_Init( void )
|
||||
Cvar_RegisterVariable( &sv_unlagsamples );
|
||||
Cvar_RegisterVariable( &sv_allow_upload );
|
||||
Cvar_RegisterVariable( &sv_allow_download );
|
||||
Cvar_RegisterVariable( &sv_allow_dlfile );
|
||||
Cvar_RegisterVariable( &sv_send_logos );
|
||||
Cvar_RegisterVariable( &sv_send_resources );
|
||||
Cvar_RegisterVariable( &sv_uploadmax );
|
||||
@@ -1089,7 +1093,9 @@ void SV_Shutdown( const char *finalmsg )
|
||||
if( CL_IsPlaybackDemo( ))
|
||||
CL_Drop();
|
||||
|
||||
SV_UnloadProgs ();
|
||||
#if XASH_WIN32
|
||||
SV_UnloadProgs();
|
||||
#endif // XASH_WIN32
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1097,7 +1103,7 @@ void SV_Shutdown( const char *finalmsg )
|
||||
Con_Printf( "%s", finalmsg );
|
||||
|
||||
// rcon will be disconnected
|
||||
SV_EndRedirect();
|
||||
SV_EndRedirect( &host.rd );
|
||||
|
||||
if( svs.clients )
|
||||
SV_FinalMessage( finalmsg, false );
|
||||
@@ -1106,7 +1112,10 @@ void SV_Shutdown( const char *finalmsg )
|
||||
NET_MasterShutdown();
|
||||
|
||||
NET_Config( false, false );
|
||||
SV_UnloadProgs ();
|
||||
SV_DeactivateServer();
|
||||
#if XASH_WIN32
|
||||
SV_UnloadProgs();
|
||||
#endif // XASH_WIN32
|
||||
CL_Drop();
|
||||
|
||||
// free current level
|
||||
|
||||
@@ -2139,8 +2139,8 @@ qboolean SV_InitPhysicsAPI( void )
|
||||
if( svgame.physFuncs.SV_CheckFeatures != NULL )
|
||||
{
|
||||
// grab common engine features (it will be shared across the network)
|
||||
host.features = svgame.physFuncs.SV_CheckFeatures();
|
||||
Host_PrintEngineFeatures ();
|
||||
host.features = svgame.physFuncs.SV_CheckFeatures() & ENGINE_FEATURES_MASK;
|
||||
Host_PrintEngineFeatures( host.features );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -80,8 +80,8 @@ static qboolean SV_CopyEdictToPhysEnt( physent_t *pe, edict_t *ed )
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise copy the classname
|
||||
Q_strncpy( pe->name, STRING( ed->v.classname ), sizeof( pe->name ));
|
||||
// otherwise copy the modelname
|
||||
Q_strncpy( pe->name, mod->name, sizeof( pe->name ));
|
||||
}
|
||||
|
||||
pe->model = pe->studiomodel = NULL;
|
||||
|
||||
@@ -36,7 +36,7 @@ static void SV_SourceQuery_Details( netadr_t from )
|
||||
{
|
||||
sizebuf_t buf;
|
||||
char answer[2048];
|
||||
int i, bot_count, client_count;
|
||||
int bot_count, client_count;
|
||||
int is_private = 0;
|
||||
|
||||
SV_GetPlayerCount( &client_count, &bot_count );
|
||||
|
||||
@@ -984,7 +984,10 @@ static void ParseSaveTables( SAVERESTOREDATA *pSaveData, SAVE_HEADER *pHeader, i
|
||||
InitEntityTable( pSaveData, pSaveData->tableCount );
|
||||
|
||||
for( i = 0; i < pSaveData->tableCount; i++ )
|
||||
{
|
||||
svgame.dllFuncs.pfnSaveReadFields( pSaveData, "ETABLE", &pSaveData->pTable[i], gEntityTable, ARRAYSIZE( gEntityTable ));
|
||||
pSaveData->pTable[i].pent = NULL;
|
||||
}
|
||||
|
||||
pSaveData->pBaseData = pSaveData->pCurrentData;
|
||||
pSaveData->size = 0;
|
||||
|
||||
@@ -1475,7 +1475,6 @@ static qboolean SV_RecursiveLightPoint( model_t *model, mnode_t *node, const vec
|
||||
float ds, dt, s, t;
|
||||
int sample_size;
|
||||
msurface_t *surf;
|
||||
mtexinfo_t *tex;
|
||||
mextrasurf_t *info;
|
||||
color24 *lm;
|
||||
vec3_t mid;
|
||||
@@ -1510,7 +1509,6 @@ static qboolean SV_RecursiveLightPoint( model_t *model, mnode_t *node, const vec
|
||||
{
|
||||
int smax, tmax;
|
||||
|
||||
tex = surf->texinfo;
|
||||
info = surf->info;
|
||||
|
||||
if( FBitSet( surf->flags, SURF_DRAWTILED ))
|
||||
|
||||
@@ -37,8 +37,6 @@ def options(opt):
|
||||
def configure(conf):
|
||||
# check for dedicated server build
|
||||
if conf.options.DEDICATED:
|
||||
if conf.env.DEST_OS == 'linux':
|
||||
conf.check_cc(lib='rt')
|
||||
conf.define('XASH_DEDICATED', 1)
|
||||
elif conf.env.DEST_OS == 'dos':
|
||||
conf.options.STATIC = True
|
||||
@@ -49,14 +47,14 @@ def configure(conf):
|
||||
# re-enable undefined reference errors
|
||||
conf.env.CXXFLAGS += ['-Wl,--no-undefined']
|
||||
conf.env.CFLAGS += ['-Wl,--no-undefined']
|
||||
# allow the SDL2 sanity check to complete properly by linking in libstdc++ and lm normally
|
||||
conf.env.LDFLAGS += ['-lstdc++', '-lm']
|
||||
# allow the SDL2 sanity check to complete properly by linking in lm normally
|
||||
conf.env.LDFLAGS += ['-lm']
|
||||
conf.load('sdl2')
|
||||
if not conf.env.HAVE_SDL2:
|
||||
conf.fatal('SDL2 not availiable! Install switch-sdl2!')
|
||||
conf.define('XASH_SDL', 2)
|
||||
# then remove them to avoid them getting linked to shared objects
|
||||
conf.env.LDFLAGS.remove('-lstdc++')
|
||||
conf.env.LIB_SDL2.remove('stdc++') # remove libstdc++ linking from SDL2, we link it later
|
||||
conf.env.LDFLAGS.remove('-lm')
|
||||
elif conf.env.DEST_OS == 'psvita':
|
||||
# allow the SDL2 sanity check to complete properly by linking in some deps missing from the pkg-config file
|
||||
@@ -73,12 +71,9 @@ def configure(conf):
|
||||
# unused, XASH_LINUX without XASH_SDL gives fbdev & alsa support
|
||||
# conf.define('XASH_FBDEV', 1)
|
||||
conf.check_cc( lib = 'asound' )
|
||||
conf.check_cc( lib = 'rt' )
|
||||
elif conf.options.SDL12:
|
||||
conf.define('XASH_SDL', 12)
|
||||
conf.check_cfg(package='sdl', args='--cflags --libs', uselib_store='SDL2' )
|
||||
if conf.env.DEST_OS == 'linux':
|
||||
conf.check_cc( lib='rt' )
|
||||
conf.env.HAVE_SDL2 = True
|
||||
else:
|
||||
conf.load('sdl2')
|
||||
@@ -97,6 +92,9 @@ def configure(conf):
|
||||
if not conf.env.DEST_OS in ['win32', 'android'] and not conf.options.NO_ASYNC_RESOLVE:
|
||||
conf.check_pthreads()
|
||||
|
||||
if conf.env.DEST_OS == 'linux':
|
||||
conf.check_cc(lib='rt')
|
||||
|
||||
if hasattr(conf.options, 'DLLEMU'):
|
||||
conf.define_cond('XASH_DLL_LOADER', conf.options.DLLEMU)
|
||||
|
||||
@@ -189,7 +187,7 @@ def build(bld):
|
||||
# HACK: link in the entirety of libstdc++ so that dynamic libs could use all of it without manual exporting
|
||||
# we can't do this right away because std::filesystem will complain about not having pathconf(),
|
||||
# which we have defined in sys_nswitch.c
|
||||
bld.env.LDFLAGS += ['-Wl,--whole-archive', '-lstdc++', '-Wl,--no-whole-archive', '-lm']
|
||||
bld.env.LDFLAGS += ['-v', '-Wl,--whole-archive', '-lstdc++', '-Wl,--no-whole-archive', '-lm']
|
||||
|
||||
if bld.env.DEST_OS == 'psvita':
|
||||
libs += [ 'VRTLD' ]
|
||||
|
||||
@@ -150,7 +150,10 @@ public:
|
||||
|
||||
void RemoveFile( const char *path, const char *id ) override
|
||||
{
|
||||
FS_Delete( path ); // FS_Delete is aware of slashes
|
||||
char dir[MAX_VA_STRING], fullpath[MAX_VA_STRING];
|
||||
|
||||
Q_snprintf( fullpath, sizeof( fullpath ), "%s/%s", IdToDir( dir, sizeof( dir ), id ), path );
|
||||
FS_Delete( fullpath ); // FS_Delete is aware of slashes
|
||||
}
|
||||
|
||||
void CreateDirHierarchy( const char *path, const char *id ) override
|
||||
@@ -230,6 +233,13 @@ public:
|
||||
return FS_FileTime( p, false );
|
||||
}
|
||||
|
||||
long int GetFileModificationTime( const char *path )
|
||||
{
|
||||
// TODO: properly reverse-engineer this
|
||||
FixupPath( p, path );
|
||||
return FS_FileTime( p, false );
|
||||
}
|
||||
|
||||
void FileTimeToString( char *p, int size, long int time ) override
|
||||
{
|
||||
const time_t curtime = time;
|
||||
|
||||
@@ -40,8 +40,7 @@ public:
|
||||
virtual ~IBaseInterface() {}
|
||||
};
|
||||
|
||||
class IVFileSystem009 : public IBaseInterface
|
||||
{
|
||||
class IVFileSystem009 : public IBaseInterface {
|
||||
public:
|
||||
virtual void Mount() = 0; /* linkage=_ZN11IFileSystem5MountEv */
|
||||
|
||||
@@ -148,8 +147,8 @@ public:
|
||||
virtual FileHandle_t OpenFromCacheForRead(const char *, const char *, const char *) = 0; /* linkage=_ZN11IFileSystem20OpenFromCacheForReadEPKcS1_S1_ */
|
||||
|
||||
virtual void AddSearchPathNoWrite(const char *, const char *) = 0; /* linkage=_ZN11IFileSystem20AddSearchPathNoWriteEPKcS1_ */
|
||||
|
||||
virtual long int GetFileModificationTime(const char *) = 0; /* linkage=_ZN11IFileSystem23GetFileModificationTimeEPKc */
|
||||
};
|
||||
|
||||
#define FILESYSTEM_INTERFACE_VERSION "VFileSystem009" // never change this!
|
||||
|
||||
#endif // VFILESYSTEM009_H
|
||||
|
||||
325
filesystem/android.c
Normal file
325
filesystem/android.c
Normal file
@@ -0,0 +1,325 @@
|
||||
/*
|
||||
android.c - android support for filesystem
|
||||
Copyright (C) 2022 Velaron
|
||||
|
||||
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 "port.h"
|
||||
|
||||
#if XASH_ANDROID
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include STDINT_H
|
||||
#include "filesystem_internal.h"
|
||||
#include "crtlib.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
#include "common/com_strings.h"
|
||||
|
||||
#include <jni.h>
|
||||
#include <android/asset_manager.h>
|
||||
#include <android/asset_manager_jni.h>
|
||||
#include <time.h>
|
||||
|
||||
struct android_assets_s
|
||||
{
|
||||
string package_name;
|
||||
qboolean engine;
|
||||
AAssetManager *asset_manager;
|
||||
AAssetDir *dir;
|
||||
};
|
||||
|
||||
struct jni_methods_s
|
||||
{
|
||||
JNIEnv *env;
|
||||
jobject activity;
|
||||
jclass activity_class;
|
||||
jmethodID getPackageName;
|
||||
jmethodID getCallingPackage;
|
||||
jmethodID getAssetsList;
|
||||
jmethodID getAssets;
|
||||
} jni;
|
||||
|
||||
static void Android_GetAssetManager( android_assets_t *assets )
|
||||
{
|
||||
jobject assetManager;
|
||||
|
||||
assetManager = (*jni.env)->CallObjectMethod( jni.env, jni.activity, jni.getAssets, assets->engine );
|
||||
|
||||
if( assetManager )
|
||||
assets->asset_manager = AAssetManager_fromJava( jni.env, assetManager );
|
||||
else if( assets->engine )
|
||||
Con_Reportf( S_WARN "Couldn't add engine assets!" );
|
||||
}
|
||||
|
||||
static const char *Android_GetPackageName( qboolean engine )
|
||||
{
|
||||
static string pkg;
|
||||
jstring resultJNIStr;
|
||||
const char *resultCStr;
|
||||
|
||||
resultJNIStr = (*jni.env)->CallObjectMethod( jni.env, jni.activity, engine ? jni.getPackageName : jni.getCallingPackage );
|
||||
|
||||
if( !resultJNIStr )
|
||||
return NULL;
|
||||
|
||||
resultCStr = (*jni.env)->GetStringUTFChars( jni.env, resultJNIStr, NULL );
|
||||
Q_strncpy( pkg, resultCStr, sizeof( pkg ));
|
||||
(*jni.env)->ReleaseStringUTFChars( jni.env, resultJNIStr, resultCStr );
|
||||
|
||||
return pkg;
|
||||
}
|
||||
|
||||
static void Android_ListDirectory( stringlist_t *list, const char *path, qboolean engine )
|
||||
{
|
||||
jstring JStr = (*jni.env)->NewStringUTF( jni.env, path );
|
||||
jobjectArray JNIArray = (*jni.env)->CallObjectMethod( jni.env, jni.activity, jni.getAssetsList, engine, JStr );
|
||||
int JNIArraySize = (*jni.env)->GetArrayLength( jni.env, JNIArray );
|
||||
|
||||
for( int i = 0; i < JNIArraySize; i++ )
|
||||
{
|
||||
jstring JNIStr = (*jni.env)->GetObjectArrayElement( jni.env, JNIArray, i );
|
||||
const char *CStr = (*jni.env)->GetStringUTFChars( jni.env, JNIStr, NULL );
|
||||
|
||||
stringlistappend( list, (char *)CStr );
|
||||
(*jni.env)->ReleaseStringUTFChars( jni.env, JNIStr, CStr );
|
||||
}
|
||||
}
|
||||
|
||||
static void FS_CloseAndroidAssets( android_assets_t *assets )
|
||||
{
|
||||
if( assets->dir )
|
||||
AAssetDir_close( assets->dir );
|
||||
|
||||
Mem_Free( assets );
|
||||
}
|
||||
|
||||
static android_assets_t *FS_LoadAndroidAssets( qboolean engine )
|
||||
{
|
||||
android_assets_t *assets = Mem_Calloc( fs_mempool, sizeof( *assets ));
|
||||
|
||||
assets->engine = engine;
|
||||
|
||||
Android_GetAssetManager( assets );
|
||||
if( !assets->asset_manager )
|
||||
{
|
||||
FS_CloseAndroidAssets( assets );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
assets->dir = AAssetManager_openDir( assets->asset_manager, "" );
|
||||
if( !assets->dir )
|
||||
{
|
||||
FS_CloseAndroidAssets( assets );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return assets;
|
||||
}
|
||||
|
||||
static int FS_FileTime_AndroidAssets( searchpath_t *search, const char *filename )
|
||||
{
|
||||
static time_t time;
|
||||
|
||||
if( !time )
|
||||
{
|
||||
struct tm file_tm;
|
||||
|
||||
strptime( __DATE__ " "__TIME__, "%b %d %Y %H:%M:%S", &file_tm );
|
||||
time = mktime( &file_tm );
|
||||
}
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
static int FS_FindFile_AndroidAssets( struct searchpath_s *search, const char *path, char *fixedname, size_t len )
|
||||
{
|
||||
AAsset *assets = AAssetManager_open( search->assets->asset_manager, path, AASSET_MODE_UNKNOWN );
|
||||
|
||||
if( assets )
|
||||
{
|
||||
AAsset_close( assets );
|
||||
|
||||
Q_strncpy( fixedname, path, len );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void FS_PrintInfo_AndroidAssets( searchpath_t *search, char *dst, size_t size )
|
||||
{
|
||||
Q_snprintf( dst, size, "%s", search->assets->package_name );
|
||||
}
|
||||
|
||||
static void FS_Close_AndroidAssets( searchpath_t *search )
|
||||
{
|
||||
FS_CloseAndroidAssets( search->assets );
|
||||
}
|
||||
|
||||
static void FS_Search_AndroidAssets( searchpath_t *search, stringlist_t *list, const char *pattern, int caseinsensitive )
|
||||
{
|
||||
string temp;
|
||||
stringlist_t dirlist;
|
||||
const char *slash, *backslash, *colon, *separator;
|
||||
int basepathlength, dirlistindex, resultlistindex;
|
||||
char *basepath;
|
||||
|
||||
slash = Q_strrchr( pattern, '/' );
|
||||
backslash = Q_strrchr( pattern, '\\' );
|
||||
colon = Q_strrchr( pattern, ':' );
|
||||
|
||||
separator = Q_max( slash, backslash );
|
||||
separator = Q_max( separator, colon );
|
||||
|
||||
basepathlength = separator ? (separator + 1 - pattern) : 0;
|
||||
basepath = Mem_Calloc( fs_mempool, basepathlength + 1 );
|
||||
if( basepathlength )
|
||||
memcpy( basepath, pattern, basepathlength );
|
||||
basepath[basepathlength] = '\0';
|
||||
|
||||
stringlistinit( &dirlist );
|
||||
Android_ListDirectory( &dirlist, basepath, search->assets->engine );
|
||||
|
||||
Q_strncpy( temp, basepath, sizeof( temp ));
|
||||
|
||||
for( dirlistindex = 0; dirlistindex < dirlist.numstrings; dirlistindex++ )
|
||||
{
|
||||
Q_strncpy( &temp[basepathlength], dirlist.strings[dirlistindex], sizeof( temp ) - basepathlength );
|
||||
|
||||
if( matchpattern( temp, (char *)pattern, true ))
|
||||
{
|
||||
for( resultlistindex = 0; resultlistindex < list->numstrings; resultlistindex++ )
|
||||
{
|
||||
if( !Q_strcmp( list->strings[resultlistindex], temp ))
|
||||
break;
|
||||
}
|
||||
|
||||
if( resultlistindex == list->numstrings )
|
||||
stringlistappend( list, temp );
|
||||
}
|
||||
}
|
||||
|
||||
stringlistfreecontents( &dirlist );
|
||||
|
||||
Mem_Free( basepath );
|
||||
}
|
||||
|
||||
static file_t *FS_OpenFile_AndroidAssets( searchpath_t *search, const char *filename, const char *mode, int pack_ind )
|
||||
{
|
||||
file_t *file = Mem_Calloc( fs_mempool, sizeof( *file ));
|
||||
AAsset *assets = AAssetManager_open( search->assets->asset_manager, filename, AASSET_MODE_RANDOM );
|
||||
|
||||
file->handle = AAsset_openFileDescriptor( assets, &file->offset, &file->real_length );
|
||||
|
||||
file->position = 0;
|
||||
file->ungetc = EOF;
|
||||
|
||||
AAsset_close( assets );
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
static byte *FS_LoadAndroidAssetsFile( searchpath_t *search, const char *path, int pack_ind, fs_offset_t *filesize )
|
||||
{
|
||||
byte *buf;
|
||||
off_t size;
|
||||
AAsset *asset;
|
||||
|
||||
if( filesize ) *filesize = 0;
|
||||
|
||||
asset = AAssetManager_open( search->assets->asset_manager, path, AASSET_MODE_RANDOM );
|
||||
if( !asset )
|
||||
return NULL;
|
||||
|
||||
size = AAsset_getLength( asset );
|
||||
|
||||
buf = (byte *)Mem_Malloc( fs_mempool, size + 1 );
|
||||
buf[size] = '\0';
|
||||
|
||||
if( AAsset_read( asset, buf, size ) < 0 )
|
||||
{
|
||||
Mem_Free( buf );
|
||||
AAsset_close( asset );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AAsset_close( asset );
|
||||
|
||||
if( filesize ) *filesize = size;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
searchpath_t *FS_AddAndroidAssets_Fullpath( const char *path, int flags )
|
||||
{
|
||||
searchpath_t *search;
|
||||
android_assets_t *assets = NULL;
|
||||
qboolean engine = true;
|
||||
|
||||
if( FBitSet( flags, FS_STATIC_PATH | FS_CUSTOM_PATH ))
|
||||
return NULL;
|
||||
|
||||
if( FBitSet( flags, FS_GAMEDIR_PATH ) && Q_stricmp( GI->basedir, GI->gamefolder ))
|
||||
engine = false;
|
||||
|
||||
assets = FS_LoadAndroidAssets( engine );
|
||||
|
||||
if( !assets )
|
||||
{
|
||||
Con_Reportf( S_ERROR "%s: unable to load Android assets \"%s\"\n", __FUNCTION__, Android_GetPackageName( engine ));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Q_strncpy( assets->package_name, Android_GetPackageName( engine ), sizeof( assets->package_name ));
|
||||
|
||||
search = Mem_Calloc( fs_mempool, sizeof( *search ));
|
||||
|
||||
Q_strncpy( search->filename, assets->package_name, sizeof( search->filename ));
|
||||
search->assets = assets;
|
||||
search->type = SEARCHPATH_ANDROID_ASSETS;
|
||||
SetBits( search->flags, FS_NOWRITE_PATH | FS_CUSTOM_PATH );
|
||||
|
||||
search->pfnPrintInfo = FS_PrintInfo_AndroidAssets;
|
||||
search->pfnClose = FS_Close_AndroidAssets;
|
||||
search->pfnOpenFile = FS_OpenFile_AndroidAssets;
|
||||
search->pfnFileTime = FS_FileTime_AndroidAssets;
|
||||
search->pfnFindFile = FS_FindFile_AndroidAssets;
|
||||
search->pfnSearch = FS_Search_AndroidAssets;
|
||||
search->pfnLoadFile = FS_LoadAndroidAssetsFile;
|
||||
|
||||
Con_Reportf( "Adding Android assets: %s\n", assets->package_name );
|
||||
|
||||
return search;
|
||||
}
|
||||
|
||||
void FS_InitAndroid( void )
|
||||
{
|
||||
jmethodID getContext;
|
||||
|
||||
jni.env = (JNIEnv *)Sys_GetNativeObject( "JNIEnv" );
|
||||
jni.activity_class = Sys_GetNativeObject( "ActivityClass" );
|
||||
|
||||
getContext = (*jni.env)->GetStaticMethodID( jni.env, jni.activity_class, "getContext", "()Landroid/content/Context;" );
|
||||
jni.activity = (*jni.env)->CallStaticObjectMethod( jni.env, jni.activity_class, getContext );
|
||||
|
||||
jni.getPackageName = (*jni.env)->GetMethodID( jni.env, jni.activity_class, "getPackageName", "()Ljava/lang/String;" );
|
||||
jni.getCallingPackage = (*jni.env)->GetMethodID( jni.env, jni.activity_class, "getCallingPackage", "()Ljava/lang/String;" );
|
||||
jni.getAssetsList = (*jni.env)->GetMethodID( jni.env, jni.activity_class, "getAssetsList", "(ZLjava/lang/String;)[Ljava/lang/String;" );
|
||||
jni.getAssets = (*jni.env)->GetMethodID( jni.env, jni.activity_class, "getAssets", "(Z)Landroid/content/res/AssetManager;" );
|
||||
}
|
||||
|
||||
#endif // XASH_ANDROID
|
||||
@@ -449,7 +449,6 @@ static void FS_Search_DIR( searchpath_t *search, stringlist_t *list, const char
|
||||
|
||||
static int FS_FileTime_DIR( searchpath_t *search, const char *filename )
|
||||
{
|
||||
int time;
|
||||
char path[MAX_SYSPATH];
|
||||
|
||||
Q_snprintf( path, sizeof( path ), "%s%s", search->filename, filename );
|
||||
|
||||
@@ -34,6 +34,7 @@ GNU General Public License for more details.
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "port.h"
|
||||
#include "defaults.h"
|
||||
#include "const.h"
|
||||
#include "crtlib.h"
|
||||
#include "crclib.h"
|
||||
@@ -71,8 +72,10 @@ const fs_archive_t g_archives[] =
|
||||
static const fs_archive_t g_directory_archive =
|
||||
{ NULL, SEARCHPATH_PLAIN, FS_AddDir_Fullpath, false };
|
||||
|
||||
// static const fs_archive_t g_android_archive =
|
||||
// { NULL, SEARCHPATH_ANDROID, FS_AddAndroid_Fullpath, false, false };
|
||||
#ifdef XASH_ANDROID
|
||||
static const fs_archive_t g_android_archive =
|
||||
{ NULL, SEARCHPATH_ANDROID_ASSETS, FS_AddAndroidAssets_Fullpath, false };
|
||||
#endif
|
||||
|
||||
#ifdef XASH_REDUCE_FD
|
||||
static file_t *fs_last_readfile;
|
||||
@@ -154,7 +157,7 @@ void stringlistfreecontents( stringlist_t *list )
|
||||
list->strings = NULL;
|
||||
}
|
||||
|
||||
void stringlistappend( stringlist_t *list, char *text )
|
||||
void stringlistappend( stringlist_t *list, const char *text )
|
||||
{
|
||||
size_t textlen;
|
||||
|
||||
@@ -403,6 +406,10 @@ void FS_AddGameDirectory( const char *dir, uint flags )
|
||||
|
||||
stringlistfreecontents( &list );
|
||||
|
||||
#ifdef XASH_ANDROID
|
||||
FS_AddArchive_Fullpath( &g_android_archive, dir, flags );
|
||||
#endif
|
||||
|
||||
// add the directory to the search path
|
||||
// (unpacked files have the priority over packed files)
|
||||
search = FS_AddArchive_Fullpath( &g_directory_archive, dir, flags );
|
||||
@@ -596,7 +603,7 @@ static void FS_WriteGameInfo( const char *filepath, gameinfo_t *GameInfo )
|
||||
}
|
||||
|
||||
if( GameInfo->noskills )
|
||||
FS_Printf( f, "noskills\t\t\"%i\"\n", GameInfo->nomodels );
|
||||
FS_Printf( f, "noskills\t\t\"%i\"\n", GameInfo->noskills );
|
||||
|
||||
#define SAVE_AGED_COUNT 2 // the default count of quick and auto saves
|
||||
if( GameInfo->quicksave_aged_count != SAVE_AGED_COUNT )
|
||||
@@ -606,6 +613,13 @@ static void FS_WriteGameInfo( const char *filepath, gameinfo_t *GameInfo )
|
||||
FS_Printf( f, "autosave_aged_count\t\t%d\n", GameInfo->autosave_aged_count );
|
||||
#undef SAVE_AGED_COUNT
|
||||
|
||||
// HL25 compatibility
|
||||
if( GameInfo->animated_title )
|
||||
FS_Printf( f, "animated_title\t\t%i\n", GameInfo->animated_title );
|
||||
|
||||
if( GameInfo->hd_background )
|
||||
FS_Printf( f, "hd_background\t\t%i\n", GameInfo->hd_background );
|
||||
|
||||
// always expose our extensions :)
|
||||
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" );
|
||||
@@ -638,7 +652,7 @@ void FS_InitGameInfo( gameinfo_t *GameInfo, const char *gamedir )
|
||||
Q_strncpy( GameInfo->sp_entity, "info_player_start", sizeof( GameInfo->sp_entity ));
|
||||
Q_strncpy( GameInfo->mp_entity, "info_player_deathmatch", sizeof( GameInfo->mp_entity ));
|
||||
|
||||
GameInfo->max_edicts = 900; // default value if not specified
|
||||
GameInfo->max_edicts = DEFAULT_MAX_EDICTS; // default value if not specified
|
||||
GameInfo->max_tents = 500;
|
||||
GameInfo->max_beams = 128;
|
||||
GameInfo->max_particles = 4096;
|
||||
@@ -770,19 +784,30 @@ void FS_ParseGenericGameInfo( gameinfo_t *GameInfo, const char *buf, const qbool
|
||||
else if( !Q_stricmp( token, "secure" ))
|
||||
{
|
||||
pfile = COM_ParseFile( pfile, token, sizeof( token ));
|
||||
GameInfo->secure = Q_atoi( token );
|
||||
GameInfo->secure = Q_atoi( token ) ? true : false;
|
||||
}
|
||||
// valid for both
|
||||
else if( !Q_stricmp( token, "nomodels" ))
|
||||
{
|
||||
pfile = COM_ParseFile( pfile, token, sizeof( token ));
|
||||
GameInfo->nomodels = Q_atoi( token );
|
||||
GameInfo->nomodels = Q_atoi( token ) ? true : false;
|
||||
}
|
||||
else if( !Q_stricmp( token, isGameInfo ? "max_edicts" : "edicts" ))
|
||||
{
|
||||
pfile = COM_ParseFile( pfile, token, sizeof( token ));
|
||||
GameInfo->max_edicts = bound( MIN_EDICTS, Q_atoi( token ), MAX_EDICTS );
|
||||
}
|
||||
// valid for both
|
||||
else if( !Q_stricmp( token, "hd_background" ))
|
||||
{
|
||||
pfile = COM_ParseFile( pfile, token, sizeof( token ));
|
||||
GameInfo->hd_background = Q_atoi( token ) ? true : false;
|
||||
}
|
||||
else if( !Q_stricmp( token, "animated_title" ))
|
||||
{
|
||||
pfile = COM_ParseFile( pfile, token, sizeof( token ));
|
||||
GameInfo->animated_title = Q_atoi( token ) ? true : false;
|
||||
}
|
||||
// only for gameinfo
|
||||
else if( isGameInfo )
|
||||
{
|
||||
@@ -844,17 +869,17 @@ void FS_ParseGenericGameInfo( gameinfo_t *GameInfo, const char *buf, const qbool
|
||||
else if( !Q_stricmp( token, "noskills" ))
|
||||
{
|
||||
pfile = COM_ParseFile( pfile, token, sizeof( token ));
|
||||
GameInfo->noskills = Q_atoi( token );
|
||||
GameInfo->noskills = Q_atoi( token ) ? true : false;
|
||||
}
|
||||
else if( !Q_stricmp( token, "render_picbutton_text" ))
|
||||
{
|
||||
pfile = COM_ParseFile( pfile, token, sizeof( token ));
|
||||
GameInfo->render_picbutton_text = Q_atoi( token );
|
||||
GameInfo->render_picbutton_text = Q_atoi( token ) ? true : false;
|
||||
}
|
||||
else if( !Q_stricmp( token, "internal_vgui_support" ))
|
||||
{
|
||||
pfile = COM_ParseFile( pfile, token, sizeof( token ));
|
||||
GameInfo->internal_vgui_support = Q_atoi( token );
|
||||
GameInfo->internal_vgui_support = Q_atoi( token ) ? true : false;
|
||||
}
|
||||
else if( !Q_stricmp( token, "quicksave_aged_count" ))
|
||||
{
|
||||
@@ -1053,29 +1078,39 @@ static qboolean FS_ParseGameInfo( const char *gamedir, gameinfo_t *GameInfo )
|
||||
roGameInfoTime = FS_SysFileTime( gameinfo_ro );
|
||||
rwGameInfoTime = FS_SysFileTime( gameinfo_path );
|
||||
|
||||
// if rodir's liblist.gam newer than rwdir's gameinfo.txt, then convert it
|
||||
if( roLibListTime > rwGameInfoTime )
|
||||
{
|
||||
haveUpdate = FS_ConvertGameInfo( gamedir, gameinfo_path, liblist_ro );
|
||||
}
|
||||
// if rodir's gameinfo.txt newer than rwdir's gameinfo.txt, just copy the file
|
||||
else if( roGameInfoTime > rwGameInfoTime )
|
||||
{
|
||||
fs_offset_t len;
|
||||
char *afile_ro = (char *)FS_LoadDirectFile( gameinfo_ro, &len );
|
||||
file_t *ro, *rw;
|
||||
fs_offset_t ro_size;
|
||||
|
||||
if( afile_ro )
|
||||
{
|
||||
Con_DPrintf( "Copy rodir %s to rwdir %s\n", gameinfo_ro, gameinfo_path );
|
||||
haveUpdate = true;
|
||||
FS_WriteFile( gameinfo_path, afile_ro, len );
|
||||
Mem_Free( afile_ro );
|
||||
}
|
||||
// read & write as binary to copy the exact file
|
||||
ro = FS_SysOpen( gameinfo_ro, "rb" );
|
||||
rw = FS_SysOpen( gameinfo_path, "wb" );
|
||||
|
||||
FS_Seek( ro, 0, SEEK_END );
|
||||
ro_size = FS_Tell( ro );
|
||||
FS_Seek( ro, 0, SEEK_SET );
|
||||
|
||||
FS_FileCopy( rw, ro, ro_size );
|
||||
|
||||
FS_Close( rw );
|
||||
FS_Close( ro );
|
||||
|
||||
haveUpdate = true;
|
||||
}
|
||||
|
||||
FS_AllowDirectPaths( false );
|
||||
}
|
||||
|
||||
// do not update gameinfo.txt, if it was just copied from rodir's
|
||||
// if user change liblist.gam update the gameinfo.txt
|
||||
if( FS_FileTime( liblist_path, false ) > FS_FileTime( gameinfo_path, false ))
|
||||
if( !haveUpdate && FS_FileTime( liblist_path, false ) > FS_FileTime( gameinfo_path, false ))
|
||||
FS_ConvertGameInfo( gamedir, gameinfo_path, liblist_path );
|
||||
|
||||
// force to create gameinfo for specified game if missing
|
||||
@@ -1386,7 +1421,7 @@ static void _Sys_Error( const char *fmt, ... )
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
static void *_Platform_GetNativeObject_stub( const char *object )
|
||||
static void *Sys_GetNativeObject_stub( const char *object )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -1406,6 +1441,10 @@ qboolean FS_InitStdio( qboolean unused_set_to_true, const char *rootdir, const c
|
||||
|
||||
FS_InitMemory();
|
||||
|
||||
#ifdef XASH_ANDROID
|
||||
FS_InitAndroid();
|
||||
#endif
|
||||
|
||||
Q_strncpy( fs_rootdir, rootdir, sizeof( fs_rootdir ));
|
||||
Q_strncpy( fs_gamedir, gamedir, sizeof( fs_gamedir ));
|
||||
Q_strncpy( fs_basedir, basedir, sizeof( fs_basedir ));
|
||||
@@ -1638,6 +1677,9 @@ file_t *FS_SysOpen( const char *filepath, const char *mode )
|
||||
|
||||
if( file->handle < 0 )
|
||||
{
|
||||
if( errno != ENOENT )
|
||||
Con_Printf( S_ERROR "%s: can't open file %s: %s\n", __func__, filepath, strerror( errno ));
|
||||
|
||||
Mem_Free( file );
|
||||
return NULL;
|
||||
}
|
||||
@@ -2841,7 +2883,7 @@ fs_interface_t g_engfuncs =
|
||||
_Mem_Alloc,
|
||||
_Mem_Realloc,
|
||||
_Mem_Free,
|
||||
_Platform_GetNativeObject_stub
|
||||
Sys_GetNativeObject_stub
|
||||
};
|
||||
|
||||
static qboolean FS_InitInterface( int version, fs_interface_t *engfuncs )
|
||||
@@ -2883,9 +2925,9 @@ static qboolean FS_InitInterface( int version, fs_interface_t *engfuncs )
|
||||
Con_Reportf( "filesystem_stdio: custom memory allocation functions found\n" );
|
||||
}
|
||||
|
||||
if( engfuncs->_Platform_GetNativeObject )
|
||||
if( engfuncs->_Sys_GetNativeObject )
|
||||
{
|
||||
g_engfuncs._Platform_GetNativeObject = engfuncs->_Platform_GetNativeObject;
|
||||
g_engfuncs._Sys_GetNativeObject = engfuncs->_Sys_GetNativeObject;
|
||||
Con_Reportf( "filesystem_stdio: custom platform-specific functions found\n" );
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,8 @@ extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
#define FS_API_VERSION 2 // not stable yet!
|
||||
#define FS_API_CREATEINTERFACE_TAG "XashFileSystem002" // follow FS_API_VERSION!!!
|
||||
#define FS_API_CREATEINTERFACE_TAG "XashFileSystem002" // follow FS_API_VERSION!!!
|
||||
#define FILESYSTEM_INTERFACE_VERSION "VFileSystem009" // never change this!
|
||||
|
||||
// search path flags
|
||||
enum
|
||||
@@ -105,6 +106,10 @@ typedef struct gameinfo_s
|
||||
|
||||
int quicksave_aged_count; // min is 1, max is 99
|
||||
int autosave_aged_count; // min is 1, max is 99
|
||||
|
||||
// HL25 compatibility keys
|
||||
qboolean hd_background;
|
||||
qboolean animated_title;
|
||||
} gameinfo_t;
|
||||
|
||||
typedef enum
|
||||
@@ -205,12 +210,12 @@ typedef struct fs_interface_t
|
||||
// memory
|
||||
poolhandle_t (*_Mem_AllocPool)( const char *name, const char *filename, int fileline );
|
||||
void (*_Mem_FreePool)( poolhandle_t *poolptr, const char *filename, int fileline );
|
||||
void *(*_Mem_Alloc)( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline );
|
||||
void *(*_Mem_Realloc)( poolhandle_t poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline );
|
||||
void *(*_Mem_Alloc)( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline ) ALLOC_CHECK( 2 );
|
||||
void *(*_Mem_Realloc)( poolhandle_t poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline ) ALLOC_CHECK( 3 );
|
||||
void (*_Mem_Free)( void *data, const char *filename, int fileline );
|
||||
|
||||
// platform
|
||||
void *(*_Platform_GetNativeObject)( const char *object );
|
||||
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 );
|
||||
|
||||
@@ -22,6 +22,10 @@ GNU General Public License for more details.
|
||||
#include "xash3d_types.h"
|
||||
#include "filesystem.h"
|
||||
|
||||
#if XASH_ANDROID
|
||||
#include <android/asset_manager.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
@@ -31,6 +35,10 @@ typedef struct dir_s dir_t;
|
||||
typedef struct zip_s zip_t;
|
||||
typedef struct pack_s pack_t;
|
||||
typedef struct wfile_s wfile_t;
|
||||
#if XASH_ANDROID
|
||||
typedef struct android_assets_s android_assets_t;
|
||||
// typedef struct android_saf_s android_saf_t;
|
||||
#endif
|
||||
|
||||
#define FILE_BUFF_SIZE (2048)
|
||||
|
||||
@@ -58,7 +66,8 @@ enum
|
||||
SEARCHPATH_PAK,
|
||||
SEARCHPATH_WAD,
|
||||
SEARCHPATH_ZIP,
|
||||
SEARCHPATH_PK3DIR, // it's actually a plain directory but it must behave like a ZIP archive
|
||||
SEARCHPATH_PK3DIR, // it's actually a plain directory but it must behave like a ZIP archive,
|
||||
SEARCHPATH_ANDROID_ASSETS
|
||||
};
|
||||
|
||||
typedef struct stringlist_s
|
||||
@@ -81,6 +90,9 @@ typedef struct searchpath_s
|
||||
pack_t *pack;
|
||||
wfile_t *wad;
|
||||
zip_t *zip;
|
||||
#if XASH_ANDROID
|
||||
android_assets_t *assets;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct searchpath_s *next;
|
||||
@@ -127,7 +139,7 @@ extern const fs_archive_t g_archives[];
|
||||
#define Con_DPrintf (*g_engfuncs._Con_DPrintf)
|
||||
#define Con_Reportf (*g_engfuncs._Con_Reportf)
|
||||
#define Sys_Error (*g_engfuncs._Sys_Error)
|
||||
#define Platform_GetNativeObject (*g_engfuncs._Platform_GetNativeObject)
|
||||
#define Sys_GetNativeObject (*g_engfuncs._Sys_GetNativeObject)
|
||||
|
||||
//
|
||||
// filesystem.c
|
||||
@@ -179,7 +191,7 @@ qboolean MD5_HashFile( byte digest[16], const char *pszFileName, uint seed[4] );
|
||||
// stringlist ops
|
||||
void stringlistinit( stringlist_t *list );
|
||||
void stringlistfreecontents( stringlist_t *list );
|
||||
void stringlistappend( stringlist_t *list, char *text );
|
||||
void stringlistappend( stringlist_t *list, const char *text );
|
||||
void stringlistsort( stringlist_t *list );
|
||||
void listdirectory( stringlist_t *list, const char *path );
|
||||
|
||||
@@ -225,6 +237,12 @@ searchpath_t *FS_AddDir_Fullpath( const char *path, int flags );
|
||||
qboolean FS_FixFileCase( dir_t *dir, const char *path, char *dst, const size_t len, qboolean createpath );
|
||||
void FS_InitDirectorySearchpath( searchpath_t *search, const char *path, int flags );
|
||||
|
||||
//
|
||||
// android.c
|
||||
//
|
||||
void FS_InitAndroid( void );
|
||||
searchpath_t *FS_AddAndroidAssets_Fullpath( const char *path, int flags );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -334,7 +334,7 @@ searchpath_t *FS_AddPak_Fullpath( const char *pakfile, int flags )
|
||||
{
|
||||
searchpath_t *search;
|
||||
pack_t *pak;
|
||||
int i, errorcode = PAK_LOAD_COULDNT_OPEN;
|
||||
int errorcode = PAK_LOAD_COULDNT_OPEN;
|
||||
|
||||
pak = FS_LoadPackPAK( pakfile, &errorcode );
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ typedef void *HMODULE;
|
||||
|
||||
HMODULE g_hModule;
|
||||
FSAPI g_pfnGetFSAPI;
|
||||
typedef void *(*pfnCreateInterface_t)( const char *, int * );
|
||||
pfnCreateInterface_t g_pfnCreateInterface;
|
||||
fs_api_t g_fs;
|
||||
fs_globals_t *g_nullglobals;
|
||||
|
||||
@@ -10,19 +10,19 @@ def configure(conf):
|
||||
}
|
||||
conf.env.append_unique('CXXFLAGS', conf.get_flags_by_compiler(nortti, conf.env.COMPILER_CC))
|
||||
|
||||
if conf.env.DEST_OS != 'android':
|
||||
if conf.env.cxxshlib_PATTERN.startswith('lib'):
|
||||
conf.env.cxxshlib_PATTERN = conf.env.cxxshlib_PATTERN[3:]
|
||||
if conf.env.DEST_OS == 'android':
|
||||
conf.check_cc(lib='android')
|
||||
elif conf.env.cxxshlib_PATTERN.startswith('lib'): # remove lib prefix for other systems than Android
|
||||
conf.env.cxxshlib_PATTERN = conf.env.cxxshlib_PATTERN[3:]
|
||||
|
||||
def build(bld):
|
||||
bld(name = 'filesystem_includes', export_includes = '.')
|
||||
|
||||
libs = [ 'filesystem_includes' ]
|
||||
libs = [ 'filesystem_includes', 'sdk_includes' ]
|
||||
|
||||
# on PSVita do not link any libraries that are already in the main executable, but add the includes target
|
||||
if bld.env.DEST_OS == 'psvita':
|
||||
libs += [ 'sdk_includes' ]
|
||||
else:
|
||||
libs += [ 'public' ]
|
||||
if bld.env.DEST_OS != 'psvita':
|
||||
libs += [ 'public', 'ANDROID' ]
|
||||
|
||||
bld.shlib(target = 'filesystem_stdio',
|
||||
features = 'cxx seq',
|
||||
|
||||
@@ -129,6 +129,8 @@ struct zip_s
|
||||
zipfile_t *files;
|
||||
};
|
||||
|
||||
// #define ENABLE_CRC_CHECK // known to be buggy because of possible libpublic crc32 bug, disabled
|
||||
|
||||
#ifdef XASH_REDUCE_FD
|
||||
static void FS_EnsureOpenZip( zip_t *zip )
|
||||
{
|
||||
@@ -423,12 +425,13 @@ FS_LoadZIPFile
|
||||
static byte *FS_LoadZIPFile( searchpath_t *search, const char *path, int pack_ind, fs_offset_t *sizeptr )
|
||||
{
|
||||
zipfile_t *file;
|
||||
int index;
|
||||
byte *compressed_buffer = NULL, *decompressed_buffer = NULL;
|
||||
int zlib_result = 0;
|
||||
dword test_crc, final_crc;
|
||||
z_stream decompress_stream;
|
||||
size_t c;
|
||||
#ifdef ENABLE_CRC_CHECK
|
||||
dword test_crc, final_crc;
|
||||
#endif // ENABLE_CRC_CHECK
|
||||
|
||||
if( sizeptr ) *sizeptr = 0;
|
||||
|
||||
@@ -460,7 +463,7 @@ static byte *FS_LoadZIPFile( searchpath_t *search, const char *path, int pack_in
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
#ifdef ENABLE_CRC_CHECK
|
||||
CRC32_Init( &test_crc );
|
||||
CRC32_ProcessBuffer( &test_crc, decompressed_buffer, file->size );
|
||||
|
||||
@@ -472,7 +475,8 @@ static byte *FS_LoadZIPFile( searchpath_t *search, const char *path, int pack_in
|
||||
Mem_Free( decompressed_buffer );
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
#endif // ENABLE_CRC_CHECK
|
||||
|
||||
if( sizeptr ) *sizeptr = file->size;
|
||||
|
||||
FS_EnsureOpenZip( NULL );
|
||||
@@ -516,7 +520,7 @@ static byte *FS_LoadZIPFile( searchpath_t *search, const char *path, int pack_in
|
||||
if( zlib_result == Z_OK || zlib_result == Z_STREAM_END )
|
||||
{
|
||||
Mem_Free( compressed_buffer ); // finaly free compressed buffer
|
||||
#if 0
|
||||
#if ENABLE_CRC_CHECK
|
||||
CRC32_Init( &test_crc );
|
||||
CRC32_ProcessBuffer( &test_crc, decompressed_buffer, file->size );
|
||||
|
||||
@@ -668,7 +672,7 @@ searchpath_t *FS_AddZip_Fullpath( const char *zipfile, int flags )
|
||||
{
|
||||
searchpath_t *search;
|
||||
zip_t *zip;
|
||||
int i, errorcode = ZIP_LOAD_COULDNT_OPEN;
|
||||
int errorcode = ZIP_LOAD_COULDNT_OPEN;
|
||||
|
||||
zip = FS_LoadZip( zipfile, &errorcode );
|
||||
|
||||
|
||||
@@ -21,21 +21,19 @@ def configure(conf):
|
||||
conf.define_cond('XASH_DISABLE_MENU_CHANGEGAME', conf.options.DISABLE_MENU_CHANGEGAME)
|
||||
|
||||
def build(bld):
|
||||
libs = ['sdk_includes']
|
||||
source = ['game.cpp']
|
||||
defines = []
|
||||
|
||||
if bld.env.DEST_OS != 'win32':
|
||||
libs += [ 'DL' ]
|
||||
else:
|
||||
libs += ['USER32', 'SHELL32']
|
||||
if bld.env.DEST_OS == 'win32':
|
||||
source += ['game.rc']
|
||||
|
||||
# Half-Life 25th anniversary update doesn't have server library explicitly linked to libm
|
||||
if bld.env.DEST_OS == 'linux':
|
||||
bld.env.LDFLAGS += ['-Wl,--no-as-needed', '-lm']
|
||||
|
||||
bld(source = source,
|
||||
target = 'xash3d', # hl.exe
|
||||
features = 'c cxx cxxprogram',
|
||||
use = libs,
|
||||
defines = defines,
|
||||
use = 'sdk_includes DL USER32 SHELL32',
|
||||
rpath = bld.env.DEFAULT_RPATH,
|
||||
install_path = bld.env.BINDIR,
|
||||
subsystem = bld.env.MSVC_SUBSYSTEM
|
||||
|
||||
@@ -438,7 +438,10 @@ uint COM_HashKey( const char *string, uint hashSize )
|
||||
unsigned char i;
|
||||
|
||||
while(( i = *string++ ))
|
||||
{
|
||||
i = Q_tolower( i );
|
||||
hashKey = ( hashKey << 5 ) + hashKey + ( i & 0xDF );
|
||||
}
|
||||
|
||||
return hashKey & ( hashSize - 1 );
|
||||
}
|
||||
|
||||
@@ -645,10 +645,10 @@ void COM_ExtractFilePath( const char *path, char *dest )
|
||||
const char *src = path + Q_strlen( path ) - 1;
|
||||
|
||||
// back up until a \ or the start
|
||||
while( src != path && !(*(src - 1) == '\\' || *(src - 1) == '/' ))
|
||||
while( src > path && !(*(src - 1) == '\\' || *(src - 1) == '/' ))
|
||||
src--;
|
||||
|
||||
if( src != path )
|
||||
if( src > path )
|
||||
{
|
||||
memcpy( dest, path, src - path );
|
||||
dest[src - path - 1] = 0; // cutoff backslash
|
||||
|
||||
40
public/tests/test_efp.c
Normal file
40
public/tests/test_efp.c
Normal file
@@ -0,0 +1,40 @@
|
||||
#include <stdlib.h>
|
||||
#include "crtlib.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int Test_ExtractFilePath( void )
|
||||
{
|
||||
char dst[64];
|
||||
const char *strings[] =
|
||||
{
|
||||
"dir/file", "dir",
|
||||
"bark\\meow", "bark",
|
||||
"nopath", "",
|
||||
"knee/deep/in/paths", "knee/deep/in",
|
||||
// yes, it removes the behavior/ even if it might be technically a directory
|
||||
"keep/the/original/func/behavior/", "keep/the/original/func",
|
||||
"backslashes\\are\\annoying\\af", "backslashes\\are\\annoying",
|
||||
"", ""
|
||||
};
|
||||
size_t i;
|
||||
|
||||
for( i = 0; i < sizeof( strings ) / sizeof( strings[0] ); i += 2 )
|
||||
{
|
||||
COM_ExtractFilePath( strings[i], dst );
|
||||
if( Q_strcmp( dst, strings[i+1] ))
|
||||
{
|
||||
printf( "%s %s %s\n", strings[i], strings[i+1], dst );
|
||||
return (i >> 1) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main( void )
|
||||
{
|
||||
if( Test_ExtractFilePath( ))
|
||||
return EXIT_FAILURE;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -12,8 +12,7 @@ def options(opt):
|
||||
return
|
||||
|
||||
def configure(conf):
|
||||
# stub
|
||||
return
|
||||
conf.define('XASH_BUILD_COMMIT', conf.env.GIT_VERSION if conf.env.GIT_VERSION else 'notset')
|
||||
|
||||
def build(bld):
|
||||
bld(name = 'sdk_includes', export_includes = '. ../common ../pm_shared ../engine')
|
||||
@@ -28,6 +27,7 @@ def build(bld):
|
||||
'strings': 'tests/test_strings.c',
|
||||
'build': 'tests/test_build.c',
|
||||
'filebase': 'tests/test_filebase.c',
|
||||
'efp': 'tests/test_efp.c',
|
||||
}
|
||||
|
||||
for i in tests:
|
||||
|
||||
@@ -384,18 +384,6 @@ void VectorsAngles( const vec3_t forward, const vec3_t right, const vec3_t up, v
|
||||
//
|
||||
// bounds operations
|
||||
//
|
||||
/*
|
||||
=================
|
||||
ClearBounds
|
||||
=================
|
||||
*/
|
||||
void ClearBounds( vec3_t mins, vec3_t maxs )
|
||||
{
|
||||
// make bogus range
|
||||
mins[0] = mins[1] = mins[2] = 999999.0f;
|
||||
maxs[0] = maxs[1] = maxs[2] = -999999.0f;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
AddPointToBounds
|
||||
@@ -416,7 +404,7 @@ void AddPointToBounds( const vec3_t v, vec3_t mins, vec3_t maxs )
|
||||
|
||||
/*
|
||||
=================
|
||||
ExpandBounds
|
||||
ExpandBounds (not used anywhere?)
|
||||
=================
|
||||
*/
|
||||
void ExpandBounds( vec3_t mins, vec3_t maxs, float offset )
|
||||
@@ -429,34 +417,6 @@ void ExpandBounds( vec3_t mins, vec3_t maxs, float offset )
|
||||
maxs[2] += offset;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
BoundsIntersect
|
||||
=================
|
||||
*/
|
||||
qboolean BoundsIntersect( const vec3_t mins1, const vec3_t maxs1, const vec3_t mins2, const vec3_t maxs2 )
|
||||
{
|
||||
if( mins1[0] > maxs2[0] || mins1[1] > maxs2[1] || mins1[2] > maxs2[2] )
|
||||
return false;
|
||||
if( maxs1[0] < mins2[0] || maxs1[1] < mins2[1] || maxs1[2] < mins2[2] )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
BoundsAndSphereIntersect
|
||||
=================
|
||||
*/
|
||||
qboolean BoundsAndSphereIntersect( const vec3_t mins, const vec3_t maxs, const vec3_t origin, float radius )
|
||||
{
|
||||
if( mins[0] > origin[0] + radius || mins[1] > origin[1] + radius || mins[2] > origin[2] + radius )
|
||||
return false;
|
||||
if( maxs[0] < origin[0] - radius || maxs[1] < origin[1] - radius || maxs[2] < origin[2] - radius )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
SphereIntersect
|
||||
|
||||
@@ -195,10 +195,32 @@ void AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up
|
||||
void VectorsAngles( const vec3_t forward, const vec3_t right, const vec3_t up, vec3_t angles );
|
||||
void PlaneIntersect( const struct mplane_s *plane, const vec3_t p0, const vec3_t p1, vec3_t out );
|
||||
|
||||
void ClearBounds( vec3_t mins, vec3_t maxs );
|
||||
static inline void ClearBounds( vec3_t mins, vec3_t maxs )
|
||||
{
|
||||
// make bogus range
|
||||
mins[0] = mins[1] = mins[2] = 999999.0f;
|
||||
maxs[0] = maxs[1] = maxs[2] = -999999.0f;
|
||||
}
|
||||
|
||||
static inline qboolean BoundsIntersect( const vec3_t mins1, const vec3_t maxs1, const vec3_t mins2, const vec3_t maxs2 )
|
||||
{
|
||||
if( mins1[0] > maxs2[0] || mins1[1] > maxs2[1] || mins1[2] > maxs2[2] )
|
||||
return false;
|
||||
if( maxs1[0] < mins2[0] || maxs1[1] < mins2[1] || maxs1[2] < mins2[2] )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline qboolean BoundsAndSphereIntersect( const vec3_t mins, const vec3_t maxs, const vec3_t origin, float radius )
|
||||
{
|
||||
if( mins[0] > origin[0] + radius || mins[1] > origin[1] + radius || mins[2] > origin[2] + radius )
|
||||
return false;
|
||||
if( maxs[0] < origin[0] - radius || maxs[1] < origin[1] - radius || maxs[2] < origin[2] - radius )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void AddPointToBounds( const vec3_t v, vec3_t mins, vec3_t maxs );
|
||||
qboolean BoundsIntersect( const vec3_t mins1, const vec3_t maxs1, const vec3_t mins2, const vec3_t maxs2 );
|
||||
qboolean BoundsAndSphereIntersect( const vec3_t mins, const vec3_t maxs, const vec3_t origin, float radius );
|
||||
qboolean SphereIntersect( const vec3_t vSphereCenter, float fSphereRadiusSquared, const vec3_t vLinePt, const vec3_t vLineDir );
|
||||
float RadiusFromBounds( const vec3_t mins, const vec3_t maxs );
|
||||
void ExpandBounds( vec3_t mins, vec3_t maxs, float offset );
|
||||
|
||||
70
ref/gl/gl2_shim/fragment.glsl.inc
Normal file
70
ref/gl/gl2_shim/fragment.glsl.inc
Normal file
@@ -0,0 +1,70 @@
|
||||
"#if VER <= 300\n"
|
||||
"#define layout(x)\n"
|
||||
"#endif\n"
|
||||
"#if VER < 300\n"
|
||||
"#define out attribute\n"
|
||||
"#define in varying\n"
|
||||
"#define texture texture2D\n"
|
||||
"#endif\n"
|
||||
"#if VER >= 130 || VER == 100\n"
|
||||
"precision mediump float;\n"
|
||||
"#endif\n"
|
||||
"#if VER == 100\n"
|
||||
"#define PREC mediump\n"
|
||||
"#else\n"
|
||||
"#define PREC\n"
|
||||
"#endif\n"
|
||||
"#if ATTR_TEXCOORD0\n"
|
||||
"uniform sampler2D uTex0;\n"
|
||||
"#endif\n"
|
||||
"#if ATTR_TEXCOORD1\n"
|
||||
"uniform sampler2D uTex1;\n"
|
||||
"#endif\n"
|
||||
"#if FEAT_ALPHA_TEST\n"
|
||||
"uniform float uAlphaTest;\n"
|
||||
"#endif\n"
|
||||
"#if FEAT_FOG\n"
|
||||
"uniform PREC vec4 uFog;\n"
|
||||
"#endif\n"
|
||||
"uniform PREC vec4 uColor;\n"
|
||||
"#if ATTR_COLOR\n"
|
||||
"in PREC vec4 vColor;\n"
|
||||
"#endif\n"
|
||||
"#if ATTR_TEXCOORD0\n"
|
||||
"in PREC vec2 vTexCoord0;\n"
|
||||
"#endif\n"
|
||||
"#if ATTR_TEXCOORD1\n"
|
||||
"in PREC vec2 vTexCoord1;\n"
|
||||
"#endif\n"
|
||||
"#if ATTR_NORMAL\n"
|
||||
"in PREC vec2 vNormal;\n"
|
||||
"#endif\n"
|
||||
"#if VER >= 300\n"
|
||||
"out vec4 oFragColor;\n"
|
||||
"#else\n"
|
||||
"#define oFragColor gl_FragColor\n"
|
||||
"#endif\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
"#if ATTR_COLOR\n"
|
||||
"PREC vec4 c = vColor;\n"
|
||||
"#else\n"
|
||||
"PREC vec4 c = uColor;\n"
|
||||
"#endif\n"
|
||||
"#if ATTR_TEXCOORD0\n"
|
||||
"c = c * texture(uTex0, vTexCoord0);\n"
|
||||
"#endif\n"
|
||||
"#if ATTR_TEXCOORD1\n"
|
||||
"c = c * texture(uTex1, vTexCoord1);\n"
|
||||
"#endif\n"
|
||||
"#if FEAT_ALPHA_TEST\n"
|
||||
"if(c.a <= uAlphaTest)\n"
|
||||
"discard;\n"
|
||||
"#endif\n"
|
||||
"#if FEAT_FOG\n"
|
||||
"float fogDist = gl_FragCoord.z / gl_FragCoord.w;\n"
|
||||
"float fogRate = clamp(exp(-uFog.w * fogDist), 0.0, 1.0);\n"
|
||||
"c.rgb = mix(uFog.rgb, c.rgb, fogRate);\n"
|
||||
"#endif\n"
|
||||
"oFragColor = c;\n"
|
||||
"}\n"
|
||||
1770
ref/gl/gl2_shim/gl2_shim.c
Normal file
1770
ref/gl/gl2_shim/gl2_shim.c
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user