mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-05 11:35:05 +08:00
Compare commits
136 Commits
continuous
...
continuous
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ca7f19067e | ||
|
|
380a9f7a6f | ||
|
|
a6c7b67d0d | ||
|
|
c13c1f2577 | ||
|
|
151405618f | ||
|
|
70e11cc309 | ||
|
|
7619824d80 | ||
|
|
f3d181b5ee | ||
|
|
55055a70f0 | ||
|
|
22d3ba674e | ||
|
|
ac487a2133 | ||
|
|
4da3a14adc | ||
|
|
69ec810ed0 | ||
|
|
2df01316ce | ||
|
|
3a67aefee2 | ||
|
|
d114dffcb4 | ||
|
|
7bb5d9a67a | ||
|
|
a6b1e57ae1 | ||
|
|
c70c13eb5c | ||
|
|
d905ea354e | ||
|
|
99cec81894 | ||
|
|
5d5bccf1bb | ||
|
|
6fcf0a77af | ||
|
|
e7477c0abf | ||
|
|
85540855c3 | ||
|
|
2dc220b42f | ||
|
|
2d6cadbf1b | ||
|
|
340871e03a | ||
|
|
e222a74960 | ||
|
|
ab499d5095 | ||
|
|
a5f7027229 | ||
|
|
bf5cf897e2 | ||
|
|
d33c1af549 | ||
|
|
677464d04d | ||
|
|
d2d6ed8bd4 | ||
|
|
bd2a44dbdd | ||
|
|
e9ee4beb9f | ||
|
|
3b3f057f6f | ||
|
|
a9dec51e59 | ||
|
|
257312ad7c | ||
|
|
6ee8a2dfa7 | ||
|
|
75c5e9cfa7 | ||
|
|
1a94f2b585 | ||
|
|
f0b4c42c68 | ||
|
|
9be061735f | ||
|
|
6bfa525080 | ||
|
|
8fcaf18897 | ||
|
|
f558cde266 | ||
|
|
b508a33f5d | ||
|
|
b4db99006b | ||
|
|
8994f079a5 | ||
|
|
b2d184cfa5 | ||
|
|
92dc92379f | ||
|
|
2a6862ceb9 | ||
|
|
4c569e1d5f | ||
|
|
4420ffd49e | ||
|
|
fb7f57cf6a | ||
|
|
8be3bdac5d | ||
|
|
2785376bd3 | ||
|
|
d6e77e531d | ||
|
|
e686b1410d | ||
|
|
2c23a1e0a0 | ||
|
|
47eb9e8c8f | ||
|
|
712b354421 | ||
|
|
18ef4922de | ||
|
|
274f9d5846 | ||
|
|
f6fa085fe4 | ||
|
|
9ab0f04ba5 | ||
|
|
fb7854f1ef | ||
|
|
1086c31503 | ||
|
|
3a47248a09 | ||
|
|
71a333261b | ||
|
|
5ea2e295c1 | ||
|
|
1fc7547a53 | ||
|
|
a7d63649f8 | ||
|
|
2f26fcdc2a | ||
|
|
107d4cdd61 | ||
|
|
52f9aad4d0 | ||
|
|
7bb5175084 | ||
|
|
dd570b616b | ||
|
|
943a30af04 | ||
|
|
eabed60e56 | ||
|
|
f793413a79 | ||
|
|
f4a3b8571d | ||
|
|
da6586b847 | ||
|
|
4a5f34089d | ||
|
|
90da9659d1 | ||
|
|
2e30acf611 | ||
|
|
5554d13f7f | ||
|
|
a5ef33b302 | ||
|
|
9a2588f7eb | ||
|
|
cac5852e68 | ||
|
|
d52d50e283 | ||
|
|
6911da8581 | ||
|
|
e70f9a67b8 | ||
|
|
173aa7333a | ||
|
|
2396b2d4db | ||
|
|
6120c0daec | ||
|
|
790f9bde54 | ||
|
|
7a469fb481 | ||
|
|
d4a2011a59 | ||
|
|
9165832caf | ||
|
|
d274a5c13c | ||
|
|
e6bd15c68b | ||
|
|
38bef99f98 | ||
|
|
95ff9e7165 | ||
|
|
2fddbdddee | ||
|
|
465e812ed9 | ||
|
|
3b1fb79a85 | ||
|
|
0f8f35b415 | ||
|
|
a133b1c2a9 | ||
|
|
fa74acb5f0 | ||
|
|
836b4c358f | ||
|
|
982e32d108 | ||
|
|
024a335505 | ||
|
|
963cbf61e4 | ||
|
|
6d98d2c7c3 | ||
|
|
64726f13e1 | ||
|
|
85dfaaa2c2 | ||
|
|
42a915b04a | ||
|
|
42a8aa6c66 | ||
|
|
56464d3291 | ||
|
|
aed96ee753 | ||
|
|
a937320c65 | ||
|
|
a81a0cb059 | ||
|
|
5af9511505 | ||
|
|
14ae9b312d | ||
|
|
2d3e5c2e0b | ||
|
|
17950fec3e | ||
|
|
2009140da8 | ||
|
|
2a394eee62 | ||
|
|
09a7585643 | ||
|
|
a09084ceba | ||
|
|
147e5dceff | ||
|
|
3510afd30b | ||
|
|
d3586c2143 |
72
.github/workflows/c-cpp.yml
vendored
72
.github/workflows/c-cpp.yml
vendored
@@ -43,80 +43,82 @@ jobs:
|
||||
- os: windows-2019 # always use the oldest possible for 32-bit because of older compilers, and better support of certain legacy OSes
|
||||
targetos: win32
|
||||
targetarch: i386
|
||||
- os: macos-14 # in GitHub documentation, it's an ARM64 machine
|
||||
targetos: apple
|
||||
targetarch: arm64
|
||||
- os: macos-12 # in GitHub documentation, it's an x86 machine
|
||||
targetos: apple
|
||||
targetarch: amd64
|
||||
env:
|
||||
SDL_VERSION: 2.30.3
|
||||
GH_CPU_ARCH: ${{ matrix.targetarch }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install dependencies
|
||||
run: bash scripts/gha/deps_${{ matrix.targetos }}.sh
|
||||
- name: Build engine
|
||||
env:
|
||||
FWGS_PFX_PASSWORD: ${{ secrets.FWGS_PFX_PASSWORD }}
|
||||
run: bash scripts/gha/build_${{ matrix.targetos }}.sh
|
||||
- name: Upload engine (artifacts)
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: artifact-${{ matrix.targetos }}-${{ matrix.targetarch }}
|
||||
path: artifacts/*
|
||||
flatpak:
|
||||
name: "Flatpak"
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- app: su.xash.Engine.Compat.i386
|
||||
container:
|
||||
image: bilelmoussaoui/flatpak-github-actions:freedesktop-22.08
|
||||
image: bilelmoussaoui/flatpak-github-actions:freedesktop-23.08
|
||||
options: --privileged
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build flatpak (Compat.i386)
|
||||
uses: FWGS/flatpak-github-actions/flatpak-builder@v6.1
|
||||
uses: FWGS/flatpak-github-actions/flatpak-builder@v6.3
|
||||
with:
|
||||
bundle: ${{ matrix.app }}.flatpak
|
||||
manifest-path: scripts/flatpak/${{ matrix.app }}.yml
|
||||
- name: Upload engine (artifacts)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: artifact-${{ matrix.targetos }}-${{ matrix.targetarch }}
|
||||
path: artifacts/*
|
||||
release:
|
||||
name: "Upload releases"
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build, flatpak]
|
||||
if: ${{ github.event_name == 'push' }}
|
||||
steps:
|
||||
- name: Remove old release
|
||||
uses: FWGS/delete-tag-and-release@v0.2.1-dev
|
||||
with:
|
||||
tag_name: ${{ github.ref_name == 'master' && 'continuous' || format('continuous-{0}', github.ref_name) }}
|
||||
delete_release: true
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Fetch artifacts
|
||||
uses: actions/download-artifact@v3.0.1
|
||||
with:
|
||||
path: artifacts/
|
||||
- name: Repackage binaries and allow GitHub to process removed release for few seconds
|
||||
- name: Remove old release, fetch artifacts, repackage binaries and upload new release
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
RELEASE_TAG: ${{ github.ref_name == 'master' && 'continuous' || format('continuous-{0}', github.ref_name) }}
|
||||
run: |
|
||||
cd artifacts/
|
||||
for i in artifact-* su.xash.Engine.*; do
|
||||
gh release delete "$RELEASE_TAG" \
|
||||
--yes \
|
||||
--cleanup-tag \
|
||||
--repo "$GITHUB_REPOSITORY" || true
|
||||
sleep 20s
|
||||
gh run download "$GITHUB_RUN_ID" \
|
||||
--dir artifacts/ \
|
||||
--repo "$GITHUB_REPOSITORY"
|
||||
pushd artifacts/
|
||||
echo "Found artifacts:"
|
||||
ls
|
||||
for i in $(find -mindepth 1 -maxdepth 1 -type d); do
|
||||
mv "$i"/* .
|
||||
rm -rf "$i"
|
||||
done
|
||||
ls -R .
|
||||
cd ../
|
||||
echo "Repackaged artifacts:"
|
||||
ls -R
|
||||
popd
|
||||
sleep 20s
|
||||
- name: Upload new release
|
||||
uses: FWGS/action-gh-release@v0.1.15
|
||||
with:
|
||||
name: Xash3D FWGS Continuous ${{ github.ref_name }} Build
|
||||
tag_name: ${{ github.ref_name == 'master' && 'continuous' || format('continuous-{0}', github.ref_name) }}
|
||||
prerelease: true
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
files: artifacts/*
|
||||
draft: false
|
||||
gh release create "$RELEASE_TAG" artifacts/* \
|
||||
--title "Xash3D FWGS Continuous ${{ github.ref_name }} Build" \
|
||||
--target $GITHUB_SHA \
|
||||
--repo "$GITHUB_REPOSITORY" \
|
||||
--prerelease
|
||||
|
||||
2
3rdparty/extras/xash-extras
vendored
2
3rdparty/extras/xash-extras
vendored
Submodule 3rdparty/extras/xash-extras updated: 853f633be1...f4ff263d42
2
3rdparty/mainui
vendored
2
3rdparty/mainui
vendored
Submodule 3rdparty/mainui updated: f0c11b141f...ad333f6152
@@ -78,6 +78,7 @@ These strings are specific to Xash3D FWGS.
|
||||
| `internal_vgui_support` | boolean | 0 | Only for programmers! Required to be set as 1 for PrimeXT!<br>When set to 1, the engine will not load vgui_support DLL, as VGUI support is done (or intentionally ignored) on the game side. |
|
||||
| `render_picbutton_text` | boolean | 0 | When set to 1, the UI will not use prerendered `btns_main.bmp` and dynamically render them instead |
|
||||
| `quicksave_aged_count` | integer | 2 | Quick saves limit used in saves rotation |
|
||||
| `demomap` | string | Empty string | The name of the demo chapter map (Half-Life Uplink) |
|
||||
|
||||
## Note on GoldSrc liblist.gam support
|
||||
|
||||
|
||||
@@ -19,7 +19,22 @@
|
||||
- [List of XashXT-based mods](#list-of-xashxt-based-mods)
|
||||
- [List of maps for They Hunger](#list-of-maps-for-they-hunger)
|
||||
- [List of games and mods with custom gamedll](#list-of-games-and-mods-with-custom-gamedll)
|
||||
- [List of mods for Counter Strike(Android only)](#list-of-mods-for-counter-strike)
|
||||
- [List of mods for Counter Strike](#list-of-mods-for-counter-strike)
|
||||
- [List of supported mods from mobile_hacks branch of HLSDK Portable by FWGS](#list-of-supported-mods-from-mobile_hacks-branch-of-hlsdk-portable-by-fwgs)
|
||||
|
||||
# List of supported mods from mobile_hacks branch of HLSDK Portable by FWGS
|
||||
1. [Afraid of Monsters](https://www.moddb.com/mods/afraid-of-monsters/downloads/afraid-of-monsters-v1)
|
||||
2. [Big Lolly](https://www.moddb.com/mods/big-lolly)
|
||||
3. [Half-Life: Blue Shift](https://store.steampowered.com/app/130/HalfLife_Blue_Shift/)
|
||||
4. [Half-Secret](https://www.moddb.com/mods/half-secret)
|
||||
5. [Case Closed](https://www.moddb.com/mods/caseclosed)
|
||||
6. [Bloody Pizza - Vendetta](https://www.moddb.com/games/half-life/addons/bloody-pizza-vendetta)
|
||||
7. [Borderlands](https://www.moddb.com/games/half-life/addons/borderlands-v04)
|
||||
8. [Half-Life: Induction](https://www.moddb.com/mods/half-life-induction/downloads/half-life-induction-12)
|
||||
9. [Redemption/Absolute Redemption](https://www.moddb.com/mods/absolute-redemption)
|
||||
10. [Sewer beta](https://www.moddb.com/games/half-life/addons/sewer-beta)
|
||||
11. [Times of Troubles](https://www.moddb.com/mods/times-of-troubles)
|
||||
12. [Half-Life: Urbicide](https://www.moddb.com/mods/half-life-urbicide)
|
||||
|
||||
# List of Half-Life-based mods
|
||||
Originally this list was written by *Qwertyus*(*Qortez*)
|
||||
@@ -176,7 +191,7 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
|
||||
143. [Operation: Nova](http://www.moddb.com/mods/half-life-operation-nova) (there is an inner bug with an M60 machinegun on a map with Osprey: it can be activated and used if you are staying in front of it, not behind it)
|
||||
144. [Optimum Fear](https://www.fileplanet.com/7472/0/fileinfo/Optimum-Fear)
|
||||
145. [Outrun](http://www.moddb.com/mods/outrun)
|
||||
146. [Outwards (Day One)](https://drive.google.com/file/d/1mjQ8wUazYbwTq9Ocg0Vs0raq4avbTRne/view?usp=sharing)
|
||||
146. [Outwards (Day One)](https://web.archive.org/web/20161026104825/http://visgi.info/maps/)
|
||||
147. [Overhaul Pack](http://www.moddb.com/mods/half-life-overhaul-pack) (Just HD pack for Half-Life)
|
||||
148. [P.I.Z.D.E.C.](https://www.runthinkshootlive.com/posts/pizdec/)
|
||||
149. [pagoda](http://www.moddb.com/mods/pagoda1)
|
||||
@@ -282,7 +297,7 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
|
||||
6. [Catacombs: Part 1](https://www.runthinkshootlive.com/posts/catacombs/)
|
||||
7. [Cro-man's Office Mappack](http://twhl.info/vault.php?map=5547)
|
||||
8. [Half-Life Episode Two Demo Alpha v1.0](http://hl.loess.ru/?mod=451)
|
||||
9. [Hazardous-Course (first version of Hazardous-Course 2)](https://drive.google.com/file/d/16djJZSpNWKyScSxSyMqX-u_S-2i400rl/view?usp=sharing)
|
||||
9. [Hazardous-Course (first version of Hazardous-Course 2)](https://web.archive.org/web/20110512012317/http://www.richmans-maps.ch.vu/)
|
||||
10. [High Tech v0.2](http://hl.loess.ru/?mod=499)
|
||||
11. [HL Shadows, Part 1](https://www.fileplanet.com/7466/0/fileinfo/'HL-Shadows',-Part-1)
|
||||
12. [HLNewEnd](http://twhl.info/vault.php?map=2275)
|
||||
@@ -305,11 +320,11 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
|
||||
29. [Shortcut v1.0 Beta](https://www.runthinkshootlive.com/posts/shortcut/)
|
||||
30. [Stoka](https://www.ceskemody.cz/mapy.php?lng=1&clanek=222&razeni_hra=1&pn=stoka)
|
||||
31. [Striker's Compo 26](http://twhl.info/vault.php?map=5190) (buggy)
|
||||
32. [Technology Test 2](https://drive.google.com/file/d/1LfldzsMIN5j07bgtNkfY5v0Xl0S9de_G/view?usp=sharing)
|
||||
32. [Technology Test 2](https://web.archive.org/web/20110512012317/http://www.richmans-maps.ch.vu/)
|
||||
33. [The Gate Playable Demo](https://www.fileplanet.com/116347/110000/fileinfo/The-Gate-Playable-Demo)
|
||||
34. [They are Back](https://www.runthinkshootlive.com/posts/they-are-back/)
|
||||
35. [Tiefseelabor( Deep Sea Laboratory )](https://www.runthinkshootlive.com/posts/deep-sea-laboratory/)
|
||||
36. [Time-Shift](https://drive.google.com/file/d/1pK1s-2SIlSMQHVRPMLdC_94wTa__8_DX/view?usp=sharing)
|
||||
36. [Time-Shift](https://web.archive.org/web/20110512012317/http://www.richmans-maps.ch.vu/)
|
||||
37. [Train Single Beta](https://cs-mapping.com.ua/forum/showthread.php?t=36394) (Remove **gfx.wad** from **TrainSingle** folder)
|
||||
38. [WAR: The Killer Beta 0.1](http://www.moddb.com/mods/war)
|
||||
39. [White Force Beta( Residual Point prototype )](http://www.moddb.com/mods/hl-residual-point/downloads/white-force-beta-2002)
|
||||
@@ -379,7 +394,7 @@ Mods:
|
||||
5. [Half-Life Baby v1.4](http://www.moddb.com/games/half-life/addons/half-life-baby) (it's an unfinished but playable mod; after installing of the mod open **liblist.gam** or **gameinfo.txt** file in the mod's folder and correct the line **gamedll "..\hlbaby\dlls\hl.dll"** for **gamedll "dlls\hl.dll"**, otherwise you'll not be able to start a game)
|
||||
6. [Half-Secret](http://www.moddb.com/mods/half-secret) (this mod has custom **weapon_snark** code)
|
||||
7. [Induction](http://www.moddb.com/mods/half-life-induction) (this mod has new item - **item_flashlight**)
|
||||
8. [Lost in Black Mesa(first version without HLFX)](https://drive.google.com/file/d/1bEnm_AxJs-ly8hTEZIQBw_v2BsXdSiGa/view?usp=sharing)
|
||||
8. [Lost in Black Mesa(first version without HLFX)](https://web.archive.org/web/20160407041812/http://half-life.ru/forum/showthread.php?threadid=13959) (download links dead!)
|
||||
9. [Soldier](http://www.moddb.com/mods/half-life-soldier)
|
||||
10. [Solo Operations](http://www.moddb.com/mods/solo-operations)
|
||||
11. [The Blood v1.1](http://hl.loess.ru/?mods=&search=The+Blood) (there are some inner bugs in the mod, but they don't interfere with a game progress)
|
||||
@@ -440,7 +455,7 @@ Mods:
|
||||
51. [Data-base](https://www.runthinkshootlive.com/posts/database/)
|
||||
52. [de_dust2_azabetfeN](https://cs-mapping.com.ua/forum/showthread.php?t=36394) (remove **cl_dlls** & **dlls** folders from inside of mod's directory before you start the game)
|
||||
53. [De-railed](http://twhl.info/competitions.php?results=7)
|
||||
54. [Dead Shift Beta](http://www.moddb.com/mods/dead-shift) - [Demo 1](https://www.gamewatcher.com/mods/half-life-mod/dead-shift-1-0-beta) & [Demo 2](https://drive.google.com/file/d/1uHvr8xONogTTNOy-8X6G4ehFV6Eawvbq/view?usp=sharing)
|
||||
54. [Dead Shift Beta](http://www.moddb.com/mods/dead-shift) - [Demo 1](https://www.gamewatcher.com/mods/half-life-mod/dead-shift-1-0-beta) & [Demo 2](https://web.archive.org/web/20151030005310/http://www.gamefront.com/files/13532512)
|
||||
55. [Deep](http://twhl.info/vault.php?map=1669)
|
||||
56. [Desert Attack](http://fyzzer.narod.ru/index.html)
|
||||
57. [Desert Combat Demo](https://www.fileplanet.com/190487/190000/fileinfo/Half-Life---Desert-Combat-Mod) (despite a big file size there's only one small unfinished map)
|
||||
@@ -498,8 +513,8 @@ Mods:
|
||||
109. [Hospital](https://gamebanana.com/maps/167446) (you need to edit **liblist.gam** file in the mod's folder - delete *gamedll & type* strings from it before you start to play)
|
||||
110. [Hostage](https://www.runthinkshootlive.com/posts/hostage-2/)
|
||||
111. [House](http://www.artpeter.net/Data/HalfLife/Hl.php)
|
||||
112. [Impulse 101 Fun - The Train](https://drive.google.com/file/d/1jAuMCCmREH0mfAEAscqaG8FQGa2uNknb/view?usp=sharing) (map from *TWHL* by *Archie* aka *The Hunter*)
|
||||
113. [In America](https://drive.google.com/file/d/1gOC8zfnUvBxRy8Rr8juNiUNbLYjoZpnn/view?usp=sharing)
|
||||
112. [Impulse 101 Fun - The Train](http://web.archive.org/web/20070305075816/http://www.twhl.co.za/mapvault/2817.zip) (map from *TWHL* by *Archie* aka *The Hunter*)
|
||||
113. [In America](https://web.archive.org/web/20170221213409/http://www.lambda-force.org/load/half_life/karty/half_life_in_america/18-1-0-476)
|
||||
114. [In the Kitchen](http://twhl.info/vault.php?map=4314)
|
||||
115. [Infiltration](https://www.fileplanet.com/7467/0/fileinfo/Infiltration)
|
||||
116. [Interactivity & Lots of Entities](http://twhl.info/vault.php?map=5744) (link dead!)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
[](https://builds.sr.ht/~a1batross/xash3d-fwgs?) [](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)
|
||||
|
||||
Xash3D FWGS is a game engine, aimed to provide compatibility with Half-Life Engine and extend it, as well as to give game developers well known workflow.
|
||||
Xash3D (pronounced `[ksɑʂ]`) FWGS is a game engine, aimed to provide compatibility with Half-Life Engine and extend it, as well as to give game developers well known workflow.
|
||||
|
||||
Xash3D FWGS is a heavily modified fork of an original [Xash3D Engine](https://www.moddb.com/engines/xash3d-engine) by Unkle Mike.
|
||||
|
||||
@@ -28,7 +28,7 @@ If you like Xash3D FWGS, consider supporting individual engine maintainers. By s
|
||||
1) Copy engine binaries to some directory.
|
||||
2) Copy `valve` directory from [Half-Life](https://store.steampowered.com/app/70/HalfLife/) to directory with engine binaries.
|
||||
If your CPU is NOT x86 compatible or you're running 64-bit version of the engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-portable).
|
||||
This repository contains our fork of HLSDK and restored source code for some of the mods. Not all of them, of course.
|
||||
This repository contains our fork of HLSDK and restored source code for Half-Life expansions and some mods.
|
||||
You still needed to copy `valve` directory as all game resources located there.
|
||||
3) Run the main executable (`xash3d.exe` or AppImage).
|
||||
|
||||
@@ -46,11 +46,11 @@ NOTE: NEVER USE GitHub's ZIP ARCHIVES. GitHub doesn't include external dependenc
|
||||
|
||||
### Prerequisites
|
||||
|
||||
If your CPU is x86 compatible, we are building 32-bit code by default. This was done to maintain compatibility with Steam releases of Half-Life and based on it's engine games.
|
||||
If your CPU is x86 compatible and you're on Windows or Linux, we are building 32-bit code by default. This was done to maintain compatibility with Steam releases of Half-Life and based on it's engine games.
|
||||
Even if Xash3D FWGS does support targetting 64-bit, you can't load games without recompiling them from source code!
|
||||
|
||||
If your CPU is NOT x86 compatible or you decided build 64-bit version of engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-portable).
|
||||
This repository contains our fork of HLSDK and restored source code for some of the mods. Not all of them, of course.
|
||||
This repository contains our fork of HLSDK and restored source code for Half-Life expansions and some mods.
|
||||
|
||||
#### Windows (Visual Studio)
|
||||
* Install Visual Studio.
|
||||
|
||||
@@ -127,14 +127,23 @@ typedef struct
|
||||
int flags; // sky or slime, no lightmap or 256 subdivision
|
||||
} mtexinfo_t;
|
||||
|
||||
typedef struct glpoly_s
|
||||
// a1ba: changed size to avoid undefined behavior. Check your allocations if you take this header!
|
||||
// For example:
|
||||
// before: malloc( sizeof( glpoly_t ) + ( numverts - 4 ) * VERTEXSIZE * sizeof( float ))
|
||||
// after (C): malloc( sizeof( glpoly_t ) + numverts * VERTEXSIZE * sizeof( float ))
|
||||
// after (C++): malloc( sizeof( glpoly_t ) + ( numverts - 1 ) * VERTEXSIZE * sizeof( float ))
|
||||
typedef struct glpoly2_s
|
||||
{
|
||||
struct glpoly_s *next;
|
||||
struct glpoly_s *chain;
|
||||
struct glpoly2_s *next;
|
||||
struct glpoly2_s *chain;
|
||||
int numverts;
|
||||
int flags; // for SURF_UNDERWATER
|
||||
float verts[4][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2)
|
||||
} glpoly_t;
|
||||
#ifdef __cplusplus
|
||||
float verts[1][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2)
|
||||
#else
|
||||
float verts[][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2)
|
||||
#endif
|
||||
} glpoly2_t;
|
||||
|
||||
typedef struct mnode_s
|
||||
{
|
||||
@@ -173,7 +182,7 @@ struct decal_s
|
||||
short entityIndex; // Entity this is attached to
|
||||
// Xash3D specific
|
||||
vec3_t position; // location of the decal center in world space.
|
||||
glpoly_t *polys; // precomputed decal vertices
|
||||
glpoly2_t *polys; // precomputed decal vertices
|
||||
intptr_t reserved[4]; // just for future expansions or mod-makers
|
||||
};
|
||||
|
||||
@@ -246,7 +255,7 @@ struct msurface_s
|
||||
|
||||
int light_s, light_t; // gl lightmap coordinates
|
||||
|
||||
glpoly_t *polys; // multiple if warped
|
||||
glpoly2_t *polys; // multiple if warped
|
||||
struct msurface_s *texturechain;
|
||||
|
||||
mtexinfo_t *texinfo;
|
||||
@@ -488,7 +497,8 @@ typedef struct
|
||||
int flags;
|
||||
float size;
|
||||
|
||||
int reserved[8]; // VBO offsets
|
||||
const trivertex_t **pposeverts; // only valid during loading, used to build GL mesh
|
||||
intptr_t reserved[7]; // VBO offsets
|
||||
|
||||
int numposes;
|
||||
int poseverts;
|
||||
@@ -531,7 +541,6 @@ typedef struct
|
||||
#define MAX_MOVIES 8
|
||||
#define MAX_CDTRACKS 32
|
||||
#define MAX_CLIENT_SPRITES 512 // SpriteTextures (0-256 hud, 256-512 client)
|
||||
#define MAX_EFRAGS 8192 // Arcane Dimensions required
|
||||
#define MAX_REQUESTS 64
|
||||
|
||||
#if ! XASH_64BIT
|
||||
|
||||
@@ -30,7 +30,7 @@ GAMEINFO stuff
|
||||
internal shared gameinfo structure (readonly for engine parts)
|
||||
========================================================================
|
||||
*/
|
||||
typedef struct
|
||||
typedef struct GAMEINFO_s
|
||||
{
|
||||
// filesystem info
|
||||
char gamefolder[64]; // used for change game '-game x'
|
||||
@@ -50,4 +50,48 @@ typedef struct
|
||||
int gamemode;
|
||||
} GAMEINFO;
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
|
||||
Extended GameInfo struct introduced in Xash3D FWGS
|
||||
|
||||
GAMEINFO can't be reliably extended, as nor engine, nor menu can't be
|
||||
sure about struct size. By adding struct versioning, we can check the
|
||||
presense for extra fields.
|
||||
========================================================================
|
||||
*/
|
||||
|
||||
#define GAMEINFO_VERSION 2
|
||||
|
||||
typedef enum gametype_e
|
||||
{
|
||||
GAME_NORMAL,
|
||||
GAME_SINGLEPLAYER_ONLY,
|
||||
GAME_MULTIPLAYER_ONLY,
|
||||
} gametype_t;
|
||||
|
||||
typedef struct gameinfo2_s
|
||||
{
|
||||
int gi_version; // should be set to desired struct version, e.g. GAMEINFO_VERSION
|
||||
|
||||
// filesystem info
|
||||
char gamefolder[64]; // used for change game
|
||||
char startmap[64]; // map to start singleplayer game from
|
||||
char trainmap[64]; // map to start hazardous course from (if specified)
|
||||
char demomap[64]; // map to start demo chapter from (if specified)
|
||||
char title[64]; // game title
|
||||
char iconpath[64]; // path to game icon
|
||||
char version[16]; // game version (optional)
|
||||
uint32_t flags; // gameinfo flags, extended to fit more flags
|
||||
|
||||
// mod info
|
||||
char game_url[256]; // link to a developer's site
|
||||
char update_url[256]; // link to updates page
|
||||
char type[64]; // single, toolkit, multiplayer, etc
|
||||
char date[64]; // release date
|
||||
uint64_t size; // size in bytes
|
||||
|
||||
gametype_t gamemode;
|
||||
} gameinfo2_t;
|
||||
|
||||
#endif//GAMEINFO_H
|
||||
|
||||
@@ -79,7 +79,7 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
demoentry_t *entries; // track entry info
|
||||
int numentries; // number of tracks
|
||||
int32_t numentries; // number of tracks
|
||||
} demodirectory_t;
|
||||
|
||||
// add angles
|
||||
@@ -327,10 +327,6 @@ void CL_WriteDemoMessage( qboolean startup, int start, sizebuf_t *msg )
|
||||
|
||||
if( !file ) return;
|
||||
|
||||
// past the start but not recording a demo.
|
||||
if( !startup && !cls.demorecording )
|
||||
return;
|
||||
|
||||
swlen = MSG_GetNumBytesWritten( msg ) - start;
|
||||
if( swlen <= 0 ) return;
|
||||
|
||||
@@ -1150,6 +1146,7 @@ show stats
|
||||
*/
|
||||
static void CL_FinishTimeDemo( void )
|
||||
{
|
||||
qboolean temp = host.allow_console;
|
||||
int frames;
|
||||
double time;
|
||||
|
||||
@@ -1160,7 +1157,9 @@ static void CL_FinishTimeDemo( void )
|
||||
time = host.realtime - cls.td_starttime;
|
||||
if( !time ) time = 1.0;
|
||||
|
||||
host.allow_console = true;
|
||||
Con_Printf( "timedemo result: %i frames %5.3f seconds %5.3f fps\n", frames, time, frames / time );
|
||||
host.allow_console = temp;
|
||||
|
||||
if( Sys_CheckParm( "-timedemo" ))
|
||||
CL_Quit_f();
|
||||
@@ -1449,6 +1448,51 @@ void CL_Record_f( void )
|
||||
CL_WriteDemoHeader( demopath );
|
||||
}
|
||||
|
||||
static qboolean CL_ParseDemoHeader( const char *callee, const char *filename, file_t *f, demoheader_t *hdr, int32_t *numentries )
|
||||
{
|
||||
if( FS_Read( f, hdr, sizeof( *hdr )) != sizeof( *hdr ) || hdr->id != IDEMOHEADER )
|
||||
{
|
||||
Con_Printf( S_ERROR "%s: %s is not in supported format or not a demo file\n", callee, filename );
|
||||
return false;
|
||||
}
|
||||
|
||||
// force null terminate strings
|
||||
hdr->mapname[sizeof( hdr->mapname ) - 1] = 0;
|
||||
hdr->comment[sizeof( hdr->comment ) - 1] = 0;
|
||||
hdr->gamedir[sizeof( hdr->gamedir ) - 1] = 0;
|
||||
|
||||
if( hdr->dem_protocol != DEMO_PROTOCOL )
|
||||
{
|
||||
Con_Printf( S_ERROR "%s: demo protocol outdated (%i should be %i)\n",
|
||||
callee, hdr->net_protocol, DEMO_PROTOCOL );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( hdr->net_protocol != PROTOCOL_VERSION && hdr->net_protocol != PROTOCOL_LEGACY_VERSION )
|
||||
{
|
||||
Con_Printf( S_ERROR "%s: net protocol outdated (%i should be %i or %i)\n",
|
||||
callee, hdr->net_protocol, PROTOCOL_VERSION, PROTOCOL_LEGACY_VERSION );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( FS_Seek( f, hdr->directory_offset, SEEK_SET ) < 0
|
||||
|| FS_Read( f, numentries, sizeof( *numentries )) != sizeof( *numentries ))
|
||||
{
|
||||
Con_Printf( S_ERROR "%s: can't find directory offset in %s, demo file corrupted\n",
|
||||
callee, filename );
|
||||
return false;
|
||||
}
|
||||
|
||||
if(( *numentries < 1 ) || ( *numentries > 1024 ))
|
||||
{
|
||||
Con_Printf( S_ERROR "%s: demo have bogus # of directory entries: %i\n",
|
||||
callee, *numentries );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_PlayDemo_f
|
||||
@@ -1469,9 +1513,7 @@ void CL_PlayDemo_f( void )
|
||||
}
|
||||
|
||||
if( cls.demoplayback )
|
||||
{
|
||||
CL_StopPlayback();
|
||||
}
|
||||
|
||||
if( cls.demorecording )
|
||||
{
|
||||
@@ -1520,53 +1562,33 @@ void CL_PlayDemo_f( void )
|
||||
}
|
||||
|
||||
if( neg ) cls.forcetrack = -cls.forcetrack;
|
||||
cls.legacymode = PROTO_QUAKE;
|
||||
CL_DemoStartPlayback( DEMO_QUAKE1 );
|
||||
cls.legacymode = PROTO_QUAKE;
|
||||
return; // quake demo is started
|
||||
}
|
||||
|
||||
// read in the demo header
|
||||
FS_Read( cls.demofile, &demo.header, sizeof( demoheader_t ));
|
||||
|
||||
if( demo.header.id != IDEMOHEADER )
|
||||
if( !CL_ParseDemoHeader( Cmd_Argv( 0 ), filename, cls.demofile, &demo.header, &demo.directory.numentries ))
|
||||
{
|
||||
Con_Printf( S_ERROR "%s is not a demo file\n", demoname );
|
||||
CL_DemoAborted();
|
||||
return;
|
||||
}
|
||||
|
||||
if( demo.header.dem_protocol != DEMO_PROTOCOL )
|
||||
{
|
||||
Con_Printf( S_ERROR "playdemo: demo protocol outdated (%i should be %i)\n", demo.header.dem_protocol, DEMO_PROTOCOL );
|
||||
CL_DemoAborted();
|
||||
return;
|
||||
}
|
||||
|
||||
if( demo.header.net_protocol != PROTOCOL_VERSION &&
|
||||
demo.header.net_protocol != PROTOCOL_LEGACY_VERSION )
|
||||
{
|
||||
Con_Printf( S_ERROR "playdemo: net protocol outdated (%i should be %i)\n", demo.header.net_protocol, PROTOCOL_VERSION );
|
||||
CL_DemoAborted();
|
||||
return;
|
||||
}
|
||||
|
||||
// now read in the directory structure.
|
||||
FS_Seek( cls.demofile, demo.header.directory_offset, SEEK_SET );
|
||||
FS_Read( cls.demofile, &demo.directory.numentries, sizeof( int ));
|
||||
|
||||
if( demo.directory.numentries < 1 || demo.directory.numentries > 1024 )
|
||||
{
|
||||
Con_Printf( S_ERROR "demo had bogus # of directory entries: %i\n", demo.directory.numentries );
|
||||
CL_DemoAborted();
|
||||
return;
|
||||
}
|
||||
|
||||
// allocate demo entries
|
||||
demo.directory.entries = Mem_Malloc( cls.mempool, sizeof( demoentry_t ) * demo.directory.numentries );
|
||||
demo.directory.entries = Mem_Malloc( cls.mempool, sizeof( *demo.directory.entries ) * demo.directory.numentries );
|
||||
|
||||
for( i = 0; i < demo.directory.numentries; i++ )
|
||||
{
|
||||
FS_Read( cls.demofile, &demo.directory.entries[i], sizeof( demoentry_t ));
|
||||
demoentry_t *entry = &demo.directory.entries[i];
|
||||
|
||||
if( FS_Read( cls.demofile, entry, sizeof( *entry )) != sizeof( *entry ))
|
||||
{
|
||||
Con_Printf( S_ERROR "%s: demo entry %i of %s corrupted", Cmd_Argv( 0 ), i, filename );
|
||||
CL_DemoAborted();
|
||||
return;
|
||||
}
|
||||
|
||||
entry->description[sizeof( entry->description ) - 1] = 0;
|
||||
}
|
||||
|
||||
demo.entryIndex = 0;
|
||||
@@ -1680,3 +1702,78 @@ void CL_Stop_f( void )
|
||||
S_StopBackgroundTrack();
|
||||
}
|
||||
}
|
||||
|
||||
void CL_ListDemo_f( void )
|
||||
{
|
||||
demoheader_t hdr;
|
||||
int32_t num_entries;
|
||||
file_t *f;
|
||||
char filename[MAX_QPATH];
|
||||
char demoname[MAX_QPATH];
|
||||
int i;
|
||||
|
||||
if( Cmd_Argc() < 2 )
|
||||
{
|
||||
Con_Printf( S_USAGE "%s <demoname>\n", Cmd_Argv( 0 ));
|
||||
return;
|
||||
}
|
||||
|
||||
Q_strncpy( demoname, Cmd_Argv( 1 ), sizeof( demoname ));
|
||||
COM_StripExtension( demoname );
|
||||
Q_snprintf( filename, sizeof( filename ), "%s.dem", demoname );
|
||||
|
||||
f = FS_Open( filename, "rb", true );
|
||||
if( !f )
|
||||
{
|
||||
Con_Printf( S_ERROR "couldn't open %s\n", filename );
|
||||
return;
|
||||
}
|
||||
|
||||
if( !CL_ParseDemoHeader( Cmd_Argv( 0 ), filename, f, &hdr, &num_entries ))
|
||||
{
|
||||
FS_Close( f );
|
||||
return;
|
||||
}
|
||||
|
||||
Con_Printf( "Demo contents for %s:\n"
|
||||
"\tProtocol: %i net/%i demo\n"
|
||||
"\tFPS: %g\n"
|
||||
"\tMap: %s\n"
|
||||
"\tComment: %s\n"
|
||||
"\tGame: %s\n",
|
||||
filename, hdr.net_protocol, hdr.dem_protocol, hdr.host_fps, hdr.mapname,
|
||||
hdr.comment, hdr.gamedir );
|
||||
|
||||
for( i = 0; i < num_entries; i++ )
|
||||
{
|
||||
demoentry_t entry;
|
||||
|
||||
Con_Printf( "Demo entry #%i:\n", i );
|
||||
|
||||
if( FS_Read( f, &entry, sizeof( entry )) != sizeof( entry ))
|
||||
{
|
||||
Con_Printf( S_ERROR "can't read demo entry\n" );
|
||||
FS_Close( f );
|
||||
return;
|
||||
}
|
||||
|
||||
entry.description[sizeof( entry.description ) - 1] = 0;
|
||||
|
||||
if( entry.entrytype == DEMO_STARTUP )
|
||||
{
|
||||
// startup entries don't have anything useful
|
||||
Con_Printf( "\tEntry type: " S_YELLOW "startup" S_DEFAULT "\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_Printf( "\tEntry type: " S_GREEN "normal" S_DEFAULT " (%i)\n"
|
||||
"\tEntry playback time/frames: %.2f seconds/%i frames\n"
|
||||
"\tEntry flags: 0x%x\n"
|
||||
"\tEntry description: %s\n",
|
||||
entry.entrytype, entry.playback_time, entry.playback_frames,
|
||||
entry.flags, entry.description );
|
||||
}
|
||||
}
|
||||
|
||||
FS_Close( f );
|
||||
}
|
||||
|
||||
@@ -28,10 +28,51 @@ GNU General Public License for more details.
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
#define NUM_EFRAGS_ALLOC 64 // alloc 64 efrags (1-2kb each alloc)
|
||||
|
||||
static efrag_t **lastlink;
|
||||
static mnode_t *r_pefragtopnode;
|
||||
static vec3_t r_emins, r_emaxs;
|
||||
static cl_entity_t *r_addent;
|
||||
static int cl_efrags_num;
|
||||
static efrag_t *cl_efrags;
|
||||
|
||||
static efrag_t *CL_AllocEfrags( int num )
|
||||
{
|
||||
int i;
|
||||
efrag_t *efrags;
|
||||
|
||||
if( !cl.worldmodel )
|
||||
{
|
||||
Host_Error( "%s: called with NULL world\n", __func__ );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( num == 0 )
|
||||
return NULL;
|
||||
|
||||
// set world to be the owner, so it will get automatically cleaned up
|
||||
efrags = Mem_Calloc( cl.worldmodel->mempool, sizeof( *efrags ) * num );
|
||||
|
||||
// initialize linked list
|
||||
for( i = 0; i < num - 1; i++ )
|
||||
efrags[i].entnext = &efrags[i + 1];
|
||||
|
||||
cl_efrags_num += num;
|
||||
|
||||
return efrags;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
CL_ClearEfrags
|
||||
==============
|
||||
*/
|
||||
void CL_ClearEfrags( void )
|
||||
{
|
||||
cl_efrags_num = 0;
|
||||
cl_efrags = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
@@ -56,14 +97,11 @@ static void R_SplitEntityOnNode( mnode_t *node )
|
||||
leaf = (mleaf_t *)node;
|
||||
|
||||
// grab an efrag off the free list
|
||||
ef = clgame.free_efrags;
|
||||
ef = cl_efrags;
|
||||
if( !ef )
|
||||
{
|
||||
Con_Printf( S_ERROR "too many efrags!\n" );
|
||||
return; // no free fragments...
|
||||
}
|
||||
ef = CL_AllocEfrags( NUM_EFRAGS_ALLOC );
|
||||
|
||||
clgame.free_efrags = ef->entnext;
|
||||
cl_efrags = ef->entnext;
|
||||
ef->entity = r_addent;
|
||||
|
||||
// add the entity link
|
||||
@@ -133,35 +171,29 @@ R_StoreEfrags
|
||||
*/
|
||||
void R_StoreEfrags( efrag_t **ppefrag, int framecount )
|
||||
{
|
||||
cl_entity_t *pent;
|
||||
model_t *clmodel;
|
||||
efrag_t *pefrag;
|
||||
efrag_t *pefrag;
|
||||
cl_entity_t *pent;
|
||||
model_t *clmodel;
|
||||
|
||||
while(( pefrag = *ppefrag ) != NULL )
|
||||
{
|
||||
pent = pefrag->entity;
|
||||
clmodel = pent->model;
|
||||
|
||||
switch( clmodel->type )
|
||||
{
|
||||
case mod_alias:
|
||||
case mod_brush:
|
||||
case mod_studio:
|
||||
case mod_sprite:
|
||||
if( pent->visframe != framecount )
|
||||
{
|
||||
if( CL_AddVisibleEntity( pent, ET_FRAGMENTED ))
|
||||
{
|
||||
// mark that we've recorded this entity for this frame
|
||||
pent->curstate.messagenum = cl.parsecount;
|
||||
pent->visframe = framecount;
|
||||
}
|
||||
}
|
||||
// how this could happen?
|
||||
if( unlikely( clmodel->type < mod_brush || clmodel->type > mod_studio ))
|
||||
continue;
|
||||
|
||||
ppefrag = &pefrag->leafnext;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if( pent->visframe != framecount )
|
||||
{
|
||||
if( CL_AddVisibleEntity( pent, ET_FRAGMENTED ))
|
||||
{
|
||||
// mark that we've recorded this entity for this frame
|
||||
pent->curstate.messagenum = cl.parsecount;
|
||||
pent->visframe = framecount;
|
||||
}
|
||||
}
|
||||
|
||||
ppefrag = &pefrag->leafnext;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -636,12 +636,24 @@ and all particle trails (if this is a beamfollow)
|
||||
*/
|
||||
void GAME_EXPORT R_BeamKill( int deadEntity )
|
||||
{
|
||||
cl_entity_t *pDeadEntity;
|
||||
BEAM *beam;
|
||||
|
||||
pDeadEntity = R_BeamGetEntity( deadEntity );
|
||||
if( !pDeadEntity ) return;
|
||||
for( beam = cl_active_beams; beam; beam = beam->next )
|
||||
{
|
||||
if( FBitSet( beam->flags, FBEAM_STARTENTITY ) && beam->startEntity == deadEntity )
|
||||
{
|
||||
if( beam->type != TE_BEAMFOLLOW )
|
||||
beam->die = cl.time;
|
||||
|
||||
CL_KillDeadBeams( pDeadEntity );
|
||||
ClearBits( beam->flags, FBEAM_STARTENTITY );
|
||||
}
|
||||
|
||||
if( FBitSet( beam->flags, FBEAM_ENDENTITY ) && beam->endEntity == deadEntity )
|
||||
{
|
||||
beam->die = cl.time;
|
||||
ClearBits( beam->flags, FBEAM_ENDENTITY );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1094,9 +1106,7 @@ void GAME_EXPORT R_ParticleExplosion2( const vec3_t org, int colorStart, int col
|
||||
int colorMod = 0, packedColor;
|
||||
particle_t *p;
|
||||
|
||||
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
||||
packedColor = 255; // use old code for blob particles
|
||||
else packedColor = 0;
|
||||
packedColor = Host_IsQuakeCompatible( ) ? 255 : 0; // use old code for blob particles
|
||||
|
||||
for( i = 0; i < 512; i++ )
|
||||
{
|
||||
@@ -1129,9 +1139,7 @@ void GAME_EXPORT R_BlobExplosion( const vec3_t org )
|
||||
particle_t *p;
|
||||
int i, j, packedColor;
|
||||
|
||||
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
||||
packedColor = 255; // use old code for blob particles
|
||||
else packedColor = 0;
|
||||
packedColor = Host_IsQuakeCompatible( ) ? 255 : 0; // use old code for blob particles
|
||||
|
||||
for( i = 0; i < 1024; i++ )
|
||||
{
|
||||
|
||||
@@ -95,8 +95,7 @@ static void CL_ResetPositions( cl_entity_t *ent )
|
||||
ent->current_position = 1;
|
||||
|
||||
memset( ent->ph, 0, sizeof( position_history_t ) * HISTORY_MAX );
|
||||
memcpy( &ent->ph[1], &store, sizeof( position_history_t ));
|
||||
memcpy( &ent->ph[0], &store, sizeof( position_history_t ));
|
||||
ent->ph[1] = ent->ph[0] = store;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -752,7 +751,7 @@ static void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_s
|
||||
|
||||
if( has_update )
|
||||
alive = MSG_ReadDeltaEntity( msg, old, state, newnum, delta_type, cl.mtime[0] );
|
||||
else memcpy( state, old, sizeof( entity_state_t ));
|
||||
else *state = *old;
|
||||
|
||||
if( !alive )
|
||||
{
|
||||
|
||||
@@ -560,7 +560,19 @@ static void CL_DrawScreenFade( void )
|
||||
if( !alpha )
|
||||
return;
|
||||
|
||||
if( FBitSet( sf->fadeFlags, FFADE_MODULATE ))
|
||||
if( !FBitSet( sf->fadeFlags, FFADE_MODULATE ))
|
||||
{
|
||||
ref.dllFuncs.GL_SetRenderMode( kRenderTransTexture );
|
||||
ref.dllFuncs.Color4ub( sf->fader, sf->fadeg, sf->fadeb, alpha );
|
||||
}
|
||||
else if( Host_IsQuakeCompatible( ))
|
||||
{
|
||||
// Quake Wrapper and Quake Remake use FFADE_MODULATE for item pickups
|
||||
// so hack the check here
|
||||
ref.dllFuncs.GL_SetRenderMode( kRenderTransAdd );
|
||||
ref.dllFuncs.Color4ub( sf->fader, sf->fadeg, sf->fadeb, alpha );
|
||||
}
|
||||
else
|
||||
{
|
||||
ref.dllFuncs.GL_SetRenderMode( kRenderScreenFadeModulate );
|
||||
|
||||
@@ -570,11 +582,6 @@ static void CL_DrawScreenFade( void )
|
||||
(uint16_t)( sf->fadeb * alpha + ( 255 - alpha ) * 255 ) >> 8,
|
||||
255 );
|
||||
}
|
||||
else
|
||||
{
|
||||
ref.dllFuncs.GL_SetRenderMode( kRenderTransTexture );
|
||||
ref.dllFuncs.Color4ub( sf->fader, sf->fadeg, sf->fadeb, alpha );
|
||||
}
|
||||
|
||||
ref.dllFuncs.R_DrawStretchPic( 0, 0, refState.width, refState.height, 0, 0, 1, 1,
|
||||
R_GetBuiltinTexture( REF_WHITE_TEXTURE ));
|
||||
@@ -1182,7 +1189,7 @@ static qboolean CL_LoadHudSprite( const char *szSpriteName, model_t *m_pSprite,
|
||||
if( type == SPR_CLIENT || type == SPR_HUDSPRITE )
|
||||
SetBits( m_pSprite->flags, MODEL_CLIENT );
|
||||
|
||||
m_pSprite->numtexinfo = texFlags; // store texFlags into numtexinfo
|
||||
m_pSprite->numtexinfo = texFlags; // store texFlags for renderer into numtexinfo
|
||||
|
||||
if( !FS_FileExists( szSpriteName, false ) )
|
||||
{
|
||||
@@ -1209,7 +1216,7 @@ static qboolean CL_LoadHudSprite( const char *szSpriteName, model_t *m_pSprite,
|
||||
ref.dllFuncs.Mod_LoadMapSprite( m_pSprite, buf, size, &loaded );
|
||||
else
|
||||
{
|
||||
Mod_LoadSpriteModel( m_pSprite, buf, &loaded, texFlags );
|
||||
Mod_LoadSpriteModel( m_pSprite, buf, &loaded );
|
||||
ref.dllFuncs.Mod_ProcessRenderData( m_pSprite, true, buf );
|
||||
}
|
||||
|
||||
@@ -2428,8 +2435,8 @@ static void GAME_EXPORT pfnLocalPlayerBounds( int hull, float *mins, float *maxs
|
||||
{
|
||||
if( hull >= 0 && hull < 4 )
|
||||
{
|
||||
if( mins ) VectorCopy( clgame.pmove->player_mins[hull], mins );
|
||||
if( maxs ) VectorCopy( clgame.pmove->player_maxs[hull], maxs );
|
||||
if( mins ) VectorCopy( host.player_mins[hull], mins );
|
||||
if( maxs ) VectorCopy( host.player_maxs[hull], maxs );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2497,9 +2504,17 @@ CL_PushTraceBounds
|
||||
*/
|
||||
static void GAME_EXPORT CL_PushTraceBounds( int hullnum, const float *mins, const float *maxs )
|
||||
{
|
||||
if( !host.trace_bounds_pushed )
|
||||
{
|
||||
memcpy( host.player_mins_backup, host.player_mins, sizeof( host.player_mins_backup ));
|
||||
memcpy( host.player_maxs_backup, host.player_maxs, sizeof( host.player_maxs_backup ));
|
||||
|
||||
host.trace_bounds_pushed = true;
|
||||
}
|
||||
|
||||
hullnum = bound( 0, hullnum, 3 );
|
||||
VectorCopy( mins, clgame.pmove->player_mins[hullnum] );
|
||||
VectorCopy( maxs, clgame.pmove->player_maxs[hullnum] );
|
||||
VectorCopy( mins, host.player_mins[hullnum] );
|
||||
VectorCopy( maxs, host.player_maxs[hullnum] );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2510,8 +2525,15 @@ CL_PopTraceBounds
|
||||
*/
|
||||
static void GAME_EXPORT CL_PopTraceBounds( void )
|
||||
{
|
||||
memcpy( clgame.pmove->player_mins, host.player_mins, sizeof( host.player_mins ));
|
||||
memcpy( clgame.pmove->player_maxs, host.player_maxs, sizeof( host.player_maxs ));
|
||||
if( !host.trace_bounds_pushed )
|
||||
{
|
||||
Con_Reportf( S_ERROR "%s called without push!\n", __func__ );
|
||||
return;
|
||||
}
|
||||
|
||||
host.trace_bounds_pushed = false;
|
||||
memcpy( host.player_mins, host.player_mins_backup, sizeof( host.player_mins ));
|
||||
memcpy( host.player_maxs, host.player_maxs_backup, sizeof( host.player_maxs ));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3283,7 +3305,7 @@ Heavy legacy of Quake...
|
||||
*/
|
||||
void TriColor4fRendermode( float r, float g, float b, float a, int rendermode )
|
||||
{
|
||||
if( clgame.ds.renderMode == kRenderTransAlpha )
|
||||
if( rendermode == kRenderTransAlpha )
|
||||
{
|
||||
clgame.ds.triRGBA[3] = a / 255.0f;
|
||||
ref.dllFuncs.Color4f( r, g, b, a );
|
||||
@@ -3415,7 +3437,6 @@ NetAPI_SendRequest
|
||||
static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags, double timeout, netadr_t *remote_address, net_api_response_func_t response )
|
||||
{
|
||||
net_request_t *nr = NULL;
|
||||
string req;
|
||||
int i;
|
||||
|
||||
if( !response )
|
||||
@@ -3467,8 +3488,7 @@ static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags,
|
||||
nr->flags = flags;
|
||||
|
||||
// local servers request
|
||||
Q_snprintf( req, sizeof( req ), "netinfo %i %i %i", FBitSet( flags, FNETAPI_LEGACY_PROTOCOL ) ? PROTOCOL_LEGACY_VERSION : PROTOCOL_VERSION, context, request );
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, nr->resp.remote_address, "%s", req );
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, nr->resp.remote_address, "netinfo %i %i %i", FBitSet( flags, FNETAPI_LEGACY_PROTOCOL ) ? PROTOCOL_LEGACY_VERSION : PROTOCOL_VERSION, context, request );
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -25,6 +25,14 @@ static void UI_UpdateUserinfo( void );
|
||||
|
||||
gameui_static_t gameui;
|
||||
|
||||
static void UI_ToggleAllowConsole_f( void )
|
||||
{
|
||||
host.allow_console = host.allow_console_init = true;
|
||||
|
||||
if( gameui.globals )
|
||||
gameui.globals->developer = true;
|
||||
}
|
||||
|
||||
void UI_UpdateMenu( float realtime )
|
||||
{
|
||||
if( !gameui.hInstance ) return;
|
||||
@@ -399,17 +407,21 @@ void Host_Credits( void )
|
||||
gameui.dllFuncs.pfnFinalCredits();
|
||||
}
|
||||
|
||||
static void UI_ConvertGameInfo( GAMEINFO *out, gameinfo_t *in )
|
||||
static void UI_ConvertGameInfo( gameinfo2_t *out, const gameinfo_t *in )
|
||||
{
|
||||
out->gi_version = GAMEINFO_VERSION;
|
||||
|
||||
Q_strncpy( out->gamefolder, in->gamefolder, sizeof( out->gamefolder ));
|
||||
Q_strncpy( out->startmap, in->startmap, sizeof( out->startmap ));
|
||||
Q_strncpy( out->trainmap, in->trainmap, sizeof( out->trainmap ));
|
||||
Q_strncpy( out->demomap, in->demomap, sizeof( out->demomap ));
|
||||
Q_strncpy( out->title, in->title, sizeof( out->title ));
|
||||
Q_snprintf( out->version, sizeof( out->version ), "%g", in->version );
|
||||
Q_strncpy( out->iconpath, in->iconpath, sizeof( out->iconpath ));
|
||||
|
||||
Q_strncpy( out->game_url, in->game_url, sizeof( out->game_url ));
|
||||
Q_strncpy( out->update_url, in->update_url, sizeof( out->update_url ));
|
||||
Q_strncpy( out->size, Q_pretifymem( in->size, 0 ), sizeof( out->size ));
|
||||
out->size = in->size;
|
||||
Q_strncpy( out->type, in->type, sizeof( out->type ));
|
||||
Q_strncpy( out->date, in->date, sizeof( out->date ));
|
||||
|
||||
@@ -427,6 +439,31 @@ static void UI_ConvertGameInfo( GAMEINFO *out, gameinfo_t *in )
|
||||
SetBits( out->flags, GFL_ANIMATED_TITLE );
|
||||
}
|
||||
|
||||
static void UI_ToOldGameInfo( GAMEINFO *out, const gameinfo2_t *in )
|
||||
{
|
||||
Q_strncpy( out->gamefolder, in->gamefolder, sizeof( out->gamefolder ));
|
||||
Q_strncpy( out->startmap, in->startmap, sizeof( out->startmap ));
|
||||
Q_strncpy( out->trainmap, in->trainmap, sizeof( out->trainmap ));
|
||||
Q_strncpy( out->title, in->title, sizeof( out->title ));
|
||||
Q_strncpy( out->version, in->version, sizeof( out->version ));
|
||||
out->flags = in->flags & 0xFFFF;
|
||||
Q_strncpy( out->game_url, in->game_url, sizeof( out->game_url ));
|
||||
Q_strncpy( out->update_url, in->update_url, sizeof( out->update_url ));
|
||||
Q_strncpy( out->size, Q_memprint( in->size ), sizeof( out->size ));
|
||||
Q_strncpy( out->type, in->type, sizeof( out->type ));
|
||||
Q_strncpy( out->date, in->date, sizeof( out->date ));
|
||||
out->gamemode = in->gamemode;
|
||||
}
|
||||
|
||||
static void UI_GetModsInfo( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
gameui.modsInfo = Mem_Calloc( gameui.mempool, sizeof( *gameui.modsInfo ) * FI->numgames );
|
||||
for( i = 0; i < FI->numgames; i++ )
|
||||
UI_ConvertGameInfo( &gameui.modsInfo[i], FI->games[i] );
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
PIC_DrawGeneric
|
||||
@@ -924,11 +961,12 @@ pfnGetGameInfo
|
||||
|
||||
=========
|
||||
*/
|
||||
static int GAME_EXPORT pfnGetGameInfo( GAMEINFO *pgameinfo )
|
||||
static int GAME_EXPORT pfnGetOldGameInfo( GAMEINFO *pgameinfo )
|
||||
{
|
||||
if( !pgameinfo ) return 0;
|
||||
if( !pgameinfo )
|
||||
return 0;
|
||||
|
||||
*pgameinfo = gameui.gameInfo;
|
||||
UI_ToOldGameInfo( pgameinfo, &gameui.gameInfo );
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -940,8 +978,26 @@ pfnGetGamesList
|
||||
*/
|
||||
static GAMEINFO ** GAME_EXPORT pfnGetGamesList( int *numGames )
|
||||
{
|
||||
if( numGames ) *numGames = FI->numgames;
|
||||
return gameui.modsInfo;
|
||||
if( numGames )
|
||||
*numGames = FI->numgames;
|
||||
|
||||
if( !gameui.oldModsInfo )
|
||||
{
|
||||
int i;
|
||||
|
||||
if( !gameui.modsInfo )
|
||||
UI_GetModsInfo();
|
||||
|
||||
// first allocate array of pointers
|
||||
gameui.oldModsInfo = Mem_Calloc( gameui.mempool, sizeof( *gameui.oldModsInfo ) * FI->numgames );
|
||||
for( i = 0; i < FI->numgames; i++ )
|
||||
{
|
||||
gameui.oldModsInfo[i] = Mem_Calloc( gameui.mempool, sizeof( *gameui.oldModsInfo[i] ));
|
||||
UI_ToOldGameInfo( gameui.oldModsInfo[i], &gameui.modsInfo[i] );
|
||||
}
|
||||
}
|
||||
|
||||
return gameui.oldModsInfo;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1114,7 +1170,7 @@ static void GAME_EXPORT pfnSetCursor( void *hCursor )
|
||||
}
|
||||
|
||||
// engine callbacks
|
||||
static ui_enginefuncs_t gEngfuncs =
|
||||
static const ui_enginefuncs_t gEngfuncs =
|
||||
{
|
||||
pfnPIC_Load,
|
||||
GL_FreeImage,
|
||||
@@ -1178,7 +1234,7 @@ static ui_enginefuncs_t gEngfuncs =
|
||||
pfnKeyGetState,
|
||||
pfnMemAlloc,
|
||||
pfnMemFree,
|
||||
pfnGetGameInfo,
|
||||
pfnGetOldGameInfo,
|
||||
pfnGetGamesList,
|
||||
pfnGetFilesList,
|
||||
SV_GetSaveComment,
|
||||
@@ -1225,6 +1281,28 @@ static char *pfnParseFileSafe( char *data, char *buf, const int size, unsigned i
|
||||
return COM_ParseFileSafe( data, buf, size, flags, len, NULL );
|
||||
}
|
||||
|
||||
static gameinfo2_t *pfnGetGameInfo( int gi_version )
|
||||
{
|
||||
if( gi_version != gameui.gameInfo.gi_version )
|
||||
return NULL;
|
||||
|
||||
return &gameui.gameInfo;
|
||||
}
|
||||
|
||||
static gameinfo2_t *pfnGetModInfo( int gi_version, int i )
|
||||
{
|
||||
if( i < 0 || i >= FI->numgames )
|
||||
return NULL;
|
||||
|
||||
if( !gameui.modsInfo )
|
||||
UI_GetModsInfo();
|
||||
|
||||
if( gi_version != gameui.modsInfo[i].gi_version )
|
||||
return NULL;
|
||||
|
||||
return &gameui.modsInfo[i];
|
||||
}
|
||||
|
||||
static ui_extendedfuncs_t gExtendedfuncs =
|
||||
{
|
||||
pfnEnableTextInput,
|
||||
@@ -1238,6 +1316,8 @@ static ui_extendedfuncs_t gExtendedfuncs =
|
||||
NET_CompareAdrSort,
|
||||
Sys_GetNativeObject,
|
||||
&gNetApi,
|
||||
pfnGetGameInfo,
|
||||
pfnGetModInfo,
|
||||
};
|
||||
|
||||
void UI_UnloadProgs( void )
|
||||
@@ -1247,6 +1327,7 @@ void UI_UnloadProgs( void )
|
||||
// deinitialize game
|
||||
gameui.dllFuncs.pfnShutdown();
|
||||
|
||||
Cmd_RemoveCommand( "ui_allowconsole" );
|
||||
Cvar_FullSet( "host_gameuiloaded", "0", FCVAR_READ_ONLY );
|
||||
|
||||
Cvar_Unlink( FCVAR_GAMEUIDLL );
|
||||
@@ -1306,7 +1387,7 @@ qboolean UI_LoadProgs( void )
|
||||
gameui.use_extended_api = false;
|
||||
|
||||
// make local copy of engfuncs to prevent overwrite it with user dll
|
||||
memcpy( &gpEngfuncs, &gEngfuncs, sizeof( gpEngfuncs ));
|
||||
gpEngfuncs = gEngfuncs;
|
||||
|
||||
gameui.mempool = Mem_AllocPool( "Menu Pool" );
|
||||
|
||||
@@ -1320,7 +1401,7 @@ qboolean UI_LoadProgs( void )
|
||||
}
|
||||
|
||||
// make local copy of engfuncs to prevent overwrite it with user dll
|
||||
memcpy( &gpExtendedfuncs, &gExtendedfuncs, sizeof( gExtendedfuncs ));
|
||||
gpExtendedfuncs = gExtendedfuncs;
|
||||
memset( &gameui.dllFuncs2, 0, sizeof( gameui.dllFuncs2 ));
|
||||
|
||||
// try to initialize new extended API
|
||||
@@ -1355,13 +1436,7 @@ qboolean UI_LoadProgs( void )
|
||||
}
|
||||
|
||||
Cvar_FullSet( "host_gameuiloaded", "1", FCVAR_READ_ONLY );
|
||||
|
||||
// setup gameinfo
|
||||
for( i = 0; i < FI->numgames; i++ )
|
||||
{
|
||||
gameui.modsInfo[i] = Mem_Calloc( gameui.mempool, sizeof( GAMEINFO ));
|
||||
UI_ConvertGameInfo( gameui.modsInfo[i], FI->games[i] );
|
||||
}
|
||||
Cmd_AddRestrictedCommand( "ui_allowconsole", UI_ToggleAllowConsole_f, "unlocks developer console" );
|
||||
|
||||
UI_ConvertGameInfo( &gameui.gameInfo, FI->GameInfo ); // current gameinfo
|
||||
|
||||
|
||||
@@ -87,12 +87,14 @@ CVAR_DEFINE_AUTO( cl_fixmodelinterpolationartifacts, "1", 0, "try to fix up mode
|
||||
//
|
||||
// userinfo
|
||||
//
|
||||
static CVAR_DEFINE_AUTO( name, "player", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_PRINTABLEONLY|FCVAR_FILTERABLE, "player name" );
|
||||
static char username[32];
|
||||
static CVAR_DEFINE_AUTO( name, username, FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_PRINTABLEONLY|FCVAR_FILTERABLE, "player name" );
|
||||
static CVAR_DEFINE_AUTO( model, "", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player model ('player' is a singleplayer model)" );
|
||||
static CVAR_DEFINE_AUTO( topcolor, "0", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player top color" );
|
||||
static CVAR_DEFINE_AUTO( bottomcolor, "0", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player bottom color" );
|
||||
CVAR_DEFINE_AUTO( rate, "3500", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player network rate" );
|
||||
|
||||
|
||||
client_t cl;
|
||||
client_static_t cls;
|
||||
clgame_static_t clgame;
|
||||
@@ -2345,14 +2347,11 @@ static void CL_ParseNetMessage( sizebuf_t *msg, void (*parsefn)( sizebuf_t * ))
|
||||
// after we have parsed the frame
|
||||
if( !cls.demoplayback )
|
||||
{
|
||||
if( cls.demorecording && !cls.demowaiting )
|
||||
{
|
||||
CL_WriteDemoMessage( false, cls.starting_count, msg );
|
||||
}
|
||||
else if( cls.state != ca_active )
|
||||
{
|
||||
if( cls.state != ca_active )
|
||||
CL_WriteDemoMessage( true, cls.starting_count, msg );
|
||||
}
|
||||
|
||||
if( cls.demorecording && !cls.demowaiting )
|
||||
CL_WriteDemoMessage( false, cls.starting_count, msg );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2592,7 +2591,6 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
|
||||
{
|
||||
int sound_len = sizeof( DEFAULT_SOUNDPATH ) - 1;
|
||||
byte rgucMD5_hash[16];
|
||||
const char *pfilename;
|
||||
resource_t *p;
|
||||
|
||||
if( COM_CheckString( filename ) && successfully_received )
|
||||
@@ -2600,10 +2598,10 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
|
||||
if( filename[0] != '!' )
|
||||
Con_Printf( "processing %s\n", filename );
|
||||
|
||||
if( !Q_strnicmp( filename, "downloaded/", 11 ))
|
||||
if( !Q_strnicmp( filename, DEFAULT_DOWNLOADED_DIRECTORY, sizeof( DEFAULT_DOWNLOADED_DIRECTORY ) - 1 ))
|
||||
{
|
||||
// skip "downloaded/" part to avoid mismatch with needed resources list
|
||||
filename += 11;
|
||||
filename += sizeof( DEFAULT_DOWNLOADED_DIRECTORY ) - 1;
|
||||
}
|
||||
}
|
||||
else if( !successfully_received )
|
||||
@@ -2669,7 +2667,7 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
|
||||
else
|
||||
{
|
||||
Con_Printf( "Downloaded %i bytes for purported %i byte file, ignoring download\n",
|
||||
cls.netchan.tempbuffersize, p->nDownloadSize );
|
||||
cls.netchan.tempbuffersize, p->nDownloadSize );
|
||||
}
|
||||
|
||||
if( cls.netchan.tempbuffer )
|
||||
@@ -2829,19 +2827,26 @@ static void CL_Physinfo_f( void )
|
||||
static qboolean CL_ShouldRescanFilesystem( void )
|
||||
{
|
||||
resource_t *res;
|
||||
qboolean retval = false;
|
||||
|
||||
for( res = cl.resourcesonhand.pNext; res && res != &cl.resourcesonhand; res = res->pNext )
|
||||
{
|
||||
if( res->type == t_generic )
|
||||
{
|
||||
const char *ext = COM_FileExtension( res->szFileName );
|
||||
// TODO: query supported archives format from fs_stdio
|
||||
// TODO: query if was already opened
|
||||
if( !Q_stricmp( ext, "wad" ) || !Q_stricmp( ext, "pk3" ) || !Q_stricmp( ext, "pak" ))
|
||||
return true;
|
||||
|
||||
if( !g_fsapi.IsArchiveExtensionSupported( ext, IAES_ONLY_REAL_ARCHIVES ))
|
||||
continue;
|
||||
|
||||
if( FBitSet( res->ucExtraFlags, RES_EXTRA_ARCHIVE_CHECKED ))
|
||||
continue;
|
||||
|
||||
SetBits( res->ucExtraFlags, RES_EXTRA_ARCHIVE_CHECKED );
|
||||
retval = true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
qboolean CL_PrecacheResources( void )
|
||||
@@ -3074,8 +3079,9 @@ static void CL_InitLocal( void )
|
||||
|
||||
// userinfo
|
||||
Cvar_RegisterVariable( &cl_nopred );
|
||||
Q_strncpy( username, Sys_GetCurrentUser(), sizeof( username )); // initialize before registering variable
|
||||
Cvar_RegisterVariable( &name );
|
||||
Cvar_DirectSet( &name, Sys_GetCurrentUser( ));
|
||||
Cvar_Get( "ui_username", username, FCVAR_READ_ONLY|FCVAR_PRIVILEGED, "default user name" );
|
||||
Cvar_RegisterVariable( &model );
|
||||
Cvar_RegisterVariable( &cl_updaterate );
|
||||
Cvar_RegisterVariable( &cl_dlmax );
|
||||
@@ -3151,6 +3157,7 @@ static void CL_InitLocal( void )
|
||||
Cmd_AddCommand ("demos", CL_Demos_f, "restart looping demos defined by the last startdemos command" );
|
||||
Cmd_AddCommand ("movie", CL_PlayVideo_f, "play a movie" );
|
||||
Cmd_AddCommand ("stop", CL_Stop_f, "stop playing or recording a demo" );
|
||||
Cmd_AddCommand( "listdemo", CL_ListDemo_f, "list demo entries" );
|
||||
Cmd_AddCommand ("info", NULL, "collect info about local servers with specified protocol" );
|
||||
Cmd_AddCommand ("escape", CL_Escape_f, "escape from game to menu" );
|
||||
Cmd_AddCommand ("togglemenu", CL_Escape_f, "toggle between game and menu" );
|
||||
|
||||
@@ -20,8 +20,6 @@ GNU General Public License for more details.
|
||||
#include "input.h"
|
||||
#include "platform/platform.h"
|
||||
|
||||
static mobile_engfuncs_t *gMobileEngfuncs;
|
||||
|
||||
static CVAR_DEFINE_AUTO( vibration_length, "1.0", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "vibration length" );
|
||||
static CVAR_DEFINE_AUTO( vibration_enable, "1", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "enable vibration" );
|
||||
|
||||
@@ -30,17 +28,9 @@ static float g_font_scale;
|
||||
|
||||
static void pfnVibrate( float life, char flags )
|
||||
{
|
||||
if( !vibration_enable.value )
|
||||
if( !vibration_enable.value || life < 0.0f )
|
||||
return;
|
||||
|
||||
if( life < 0.0f )
|
||||
{
|
||||
Con_Reportf( S_WARN "Negative vibrate time: %f\n", life );
|
||||
return;
|
||||
}
|
||||
|
||||
//Con_Reportf( "Vibrate: %f %d\n", life, flags );
|
||||
|
||||
// here goes platform-specific backends
|
||||
Platform_Vibrate( life * vibration_length.value, flags );
|
||||
}
|
||||
@@ -53,7 +43,7 @@ static void Vibrate_f( void )
|
||||
return;
|
||||
}
|
||||
|
||||
pfnVibrate( Q_atof( Cmd_Argv(1) ), VIBRATE_NORMAL );
|
||||
pfnVibrate( Q_atof( Cmd_Argv( 1 )), VIBRATE_NORMAL );
|
||||
}
|
||||
|
||||
static void pfnEnableTextInput( int enable )
|
||||
@@ -102,7 +92,7 @@ static char *pfnParseFileSafe( char *data, char *buf, const int size, unsigned i
|
||||
return COM_ParseFileSafe( data, buf, size, flags, len, NULL );
|
||||
}
|
||||
|
||||
static mobile_engfuncs_t gpMobileEngfuncs =
|
||||
static const mobile_engfuncs_t gMobileEngfuncs =
|
||||
{
|
||||
MOBILITY_API_VERSION,
|
||||
pfnVibrate,
|
||||
@@ -122,21 +112,38 @@ static mobile_engfuncs_t gpMobileEngfuncs =
|
||||
|
||||
qboolean Mobile_Init( void )
|
||||
{
|
||||
qboolean success = false;
|
||||
pfnMobilityInterface ExportToClient;
|
||||
|
||||
// find a mobility interface
|
||||
ExportToClient = COM_GetProcAddress( clgame.hInstance, MOBILITY_CLIENT_EXPORT );
|
||||
gMobileEngfuncs = &gpMobileEngfuncs;
|
||||
|
||||
if( ExportToClient && !ExportToClient( gMobileEngfuncs ) )
|
||||
success = true;
|
||||
|
||||
Cmd_AddCommand( "vibrate", (xcommand_t)Vibrate_f, "Vibrate for specified time");
|
||||
Cmd_AddCommand( "vibrate", Vibrate_f, "Vibrate for specified time");
|
||||
Cvar_RegisterVariable( &vibration_length );
|
||||
Cvar_RegisterVariable( &vibration_enable );
|
||||
|
||||
return success;
|
||||
// find mobility interface
|
||||
if(( ExportToClient = COM_GetProcAddress( clgame.hInstance, MOBILITY_CLIENT_EXPORT )))
|
||||
{
|
||||
static mobile_engfuncs_t mobile_engfuncs; // keep a copy, don't let user change engine pointers
|
||||
|
||||
mobile_engfuncs = gMobileEngfuncs;
|
||||
|
||||
if( !ExportToClient( &mobile_engfuncs ))
|
||||
{
|
||||
Con_Reportf( "%s: ^2initailized extended MobilityAPI ^7ver. %i\n", __func__, MOBILITY_API_VERSION );
|
||||
return true;
|
||||
}
|
||||
|
||||
// make sure that mobile functions are cleared
|
||||
#if 1
|
||||
// some SDKs define export as returning void, breaking the contract
|
||||
// ignore result for now...
|
||||
return true;
|
||||
#else
|
||||
memset( &mobile_engfuncs, 0, sizeof( mobile_engfuncs ));
|
||||
|
||||
return false; // just tell user about problems
|
||||
#endif
|
||||
}
|
||||
|
||||
return true; // mobile interface is missed
|
||||
}
|
||||
|
||||
void Mobile_Shutdown( void )
|
||||
|
||||
@@ -251,7 +251,7 @@ void CL_ParseMovevars( sizebuf_t *msg )
|
||||
if( Q_strcmp( clgame.oldmovevars.skyName, clgame.movevars.skyName ) && cl.video_prepped )
|
||||
R_SetupSky( clgame.movevars.skyName );
|
||||
|
||||
memcpy( &clgame.oldmovevars, &clgame.movevars, sizeof( movevars_t ));
|
||||
clgame.oldmovevars = clgame.movevars;
|
||||
clgame.entities->curstate.scale = clgame.movevars.waveHeight;
|
||||
|
||||
// keep features an actual!
|
||||
@@ -1403,7 +1403,7 @@ void CL_UpdateUserinfo( sizebuf_t *msg, qboolean legacy )
|
||||
if( !legacy )
|
||||
MSG_ReadBytes( msg, player->hashedcdkey, sizeof( player->hashedcdkey ));
|
||||
|
||||
if( slot == cl.playernum ) memcpy( &gameui.playerinfo, player, sizeof( player_info_t ));
|
||||
if( slot == cl.playernum ) gameui.playerinfo = *player;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -656,7 +656,7 @@ void CL_LegacyPrecache_f( void )
|
||||
// Include server count in case server disconnects and changes level during d/l
|
||||
MSG_BeginClientCmd( &cls.netchan.message, clc_stringcmd );
|
||||
MSG_WriteStringf( &cls.netchan.message, "begin %i", spawncount );
|
||||
cls.signon = SIGNONS;
|
||||
cls.signon = SIGNONS - 1;
|
||||
}
|
||||
|
||||
qboolean CL_LegacyMode( void )
|
||||
|
||||
@@ -544,8 +544,8 @@ void GAME_EXPORT CL_SetSolidPlayers( int playernum )
|
||||
// some fields needs to be override from cls.predicted_players
|
||||
VectorCopy( player->origin, pe->origin );
|
||||
VectorCopy( player->angles, pe->angles );
|
||||
VectorCopy( clgame.pmove->player_mins[player->usehull], pe->mins );
|
||||
VectorCopy( clgame.pmove->player_maxs[player->usehull], pe->maxs );
|
||||
VectorCopy( host.player_mins[player->usehull], pe->mins );
|
||||
VectorCopy( host.player_maxs[player->usehull], pe->maxs );
|
||||
pe->movetype = player->movetype;
|
||||
pe->solid = player->solid;
|
||||
}
|
||||
|
||||
@@ -22,22 +22,24 @@ GNU General Public License for more details.
|
||||
#include "hltv.h"
|
||||
#include "input.h"
|
||||
|
||||
#define STAT_HEALTH 0
|
||||
#define STAT_FRAGS 1
|
||||
#define STAT_WEAPON 2
|
||||
#define STAT_AMMO 3
|
||||
#define STAT_ARMOR 4
|
||||
#define STAT_WEAPONFRAME 5
|
||||
#define STAT_SHELLS 6
|
||||
#define STAT_NAILS 7
|
||||
#define STAT_ROCKETS 8
|
||||
#define STAT_CELLS 9
|
||||
#define STAT_ACTIVEWEAPON 10
|
||||
#define STAT_TOTALSECRETS 11
|
||||
#define STAT_TOTALMONSTERS 12
|
||||
#define STAT_SECRETS 13 // bumped on client side by svc_foundsecret
|
||||
#define STAT_MONSTERS 14 // bumped by svc_killedmonster
|
||||
#define MAX_STATS 32
|
||||
enum {
|
||||
STAT_HEALTH = 0,
|
||||
STAT_FRAGS,
|
||||
STAT_WEAPON,
|
||||
STAT_AMMO,
|
||||
STAT_ARMOR,
|
||||
STAT_WEAPONFRAME,
|
||||
STAT_SHELLS,
|
||||
STAT_NAILS,
|
||||
STAT_ROCKETS,
|
||||
STAT_CELLS,
|
||||
STAT_ACTIVEWEAPON,
|
||||
STAT_TOTALSECRETS,
|
||||
STAT_TOTALMONSTERS,
|
||||
STAT_SECRETS, // bumped on client side by svc_foundsecret
|
||||
STAT_MONSTERS, // bumped by svc_killedmonster
|
||||
MAX_STATS = 32,
|
||||
};
|
||||
|
||||
static char cmd_buf[8192];
|
||||
static char msg_buf[8192];
|
||||
@@ -328,7 +330,7 @@ static void CL_ParseQuakeServerInfo( sizebuf_t *msg )
|
||||
clgame.movevars.gravity = 800.0f; // quake doesn't write gravity in demos
|
||||
clgame.movevars.maxvelocity = 2000.0f;
|
||||
|
||||
memcpy( &clgame.oldmovevars, &clgame.movevars, sizeof( movevars_t ));
|
||||
clgame.oldmovevars = clgame.movevars;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -715,8 +717,7 @@ static void CL_ParseQuakeBaseline( sizebuf_t *msg )
|
||||
ent = CL_EDICT_NUM( newnum );
|
||||
ent->index = newnum;
|
||||
ent->player = CL_IsPlayerIndex( newnum );
|
||||
memcpy( &ent->baseline, &state, sizeof( entity_state_t ));
|
||||
memcpy( &ent->prevstate, &state, sizeof( entity_state_t ));
|
||||
ent->prevstate = ent->baseline = state;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -2448,7 +2448,8 @@ void CL_SetLightstyle( int style, const char *s, float f )
|
||||
}
|
||||
}
|
||||
|
||||
Con_Reportf( "Lightstyle %i (%s), interp %s\n", style, ls->pattern, ls->interp ? "Yes" : "No" );
|
||||
if( ls->length >= 1 )
|
||||
Con_Reportf( "Lightstyle %i (%s), interp %s\n", style, ls->pattern, ls->interp ? "Yes" : "No" );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2570,31 +2571,43 @@ CL_DecayLights
|
||||
*/
|
||||
void CL_DecayLights( void )
|
||||
{
|
||||
dlight_t *dl;
|
||||
float time;
|
||||
const float time = cl.time;
|
||||
const float dt = cl.time - cl.oldtime;
|
||||
int i;
|
||||
|
||||
time = cl.time - cl.oldtime;
|
||||
|
||||
for( i = 0, dl = cl_dlights; i < MAX_DLIGHTS; i++, dl++ )
|
||||
for( i = 0; i < MAX_DLIGHTS; i++ )
|
||||
{
|
||||
if( !dl->radius ) continue;
|
||||
dlight_t *dl = &cl_dlights[i];
|
||||
|
||||
dl->radius -= time * dl->decay;
|
||||
if( dl->radius < 0 ) dl->radius = 0;
|
||||
if( !dl->radius )
|
||||
continue;
|
||||
|
||||
if( dl->die < cl.time || !dl->radius )
|
||||
if( dl->die < time )
|
||||
{
|
||||
memset( dl, 0, sizeof( *dl ));
|
||||
continue;
|
||||
}
|
||||
|
||||
dl->radius -= dt * dl->decay;
|
||||
if( dl->radius <= 0 )
|
||||
memset( dl, 0, sizeof( *dl ));
|
||||
}
|
||||
|
||||
for( i = 0, dl = cl_elights; i < MAX_ELIGHTS; i++, dl++ )
|
||||
for( i = 0; i < MAX_ELIGHTS; i++ )
|
||||
{
|
||||
if( !dl->radius ) continue;
|
||||
dlight_t *dl = &cl_elights[i];
|
||||
|
||||
dl->radius -= time * dl->decay;
|
||||
if( dl->radius < 0 ) dl->radius = 0;
|
||||
if( !dl->radius )
|
||||
continue;
|
||||
|
||||
if( dl->die < cl.time || !dl->radius )
|
||||
if( dl->die < time )
|
||||
{
|
||||
memset( dl, 0, sizeof( *dl ));
|
||||
continue;
|
||||
}
|
||||
|
||||
dl->radius -= dt * dl->decay;
|
||||
if( dl->radius <= 0 )
|
||||
memset( dl, 0, sizeof( *dl ));
|
||||
}
|
||||
}
|
||||
@@ -2737,7 +2750,12 @@ void CL_AddEntityEffects( cl_entity_t *ent )
|
||||
if( FBitSet( ent->curstate.effects, EF_BRIGHTLIGHT ))
|
||||
R_EntityBrightlight( ent, ent->index /* 1 in GoldSrc */, 400 );
|
||||
else if( FBitSet( ent->curstate.effects, EF_DIMLIGHT ))
|
||||
CL_UpdateFlashlight( ent );
|
||||
{
|
||||
if( Host_IsQuakeCompatible( ))
|
||||
R_EntityDimlight( ent, ent->index );
|
||||
else
|
||||
CL_UpdateFlashlight( ent );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3058,26 +3076,6 @@ EFRAGS MANAGEMENT
|
||||
|
||||
==============================================================
|
||||
*/
|
||||
efrag_t cl_efrags[MAX_EFRAGS];
|
||||
|
||||
/*
|
||||
==============
|
||||
CL_ClearEfrags
|
||||
==============
|
||||
*/
|
||||
void CL_ClearEfrags( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
memset( cl_efrags, 0, sizeof( cl_efrags ));
|
||||
|
||||
// allocate the efrags and chain together into a free list
|
||||
clgame.free_efrags = cl_efrags;
|
||||
for( i = 0; i < MAX_EFRAGS - 1; i++ )
|
||||
clgame.free_efrags[i].entnext = &clgame.free_efrags[i+1];
|
||||
clgame.free_efrags[i].entnext = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
=======================
|
||||
R_ClearStaticEntities
|
||||
|
||||
@@ -35,7 +35,7 @@ static void V_CalcViewRect( void )
|
||||
int sb_lines;
|
||||
float size;
|
||||
|
||||
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
||||
if( Host_IsQuakeCompatible( ))
|
||||
{
|
||||
// intermission is always full screen
|
||||
if( cl.intermission ) size = 120.0f;
|
||||
@@ -144,7 +144,9 @@ static void V_SetRefParams( ref_params_t *fd )
|
||||
VectorCopy( cl.viewangles, fd->cl_viewangles );
|
||||
fd->health = cl.local.health;
|
||||
VectorCopy( cl.crosshairangle, fd->crosshairangle );
|
||||
fd->viewsize = scr_viewsize.value;
|
||||
if( Host_IsQuakeCompatible( ))
|
||||
fd->viewsize = scr_viewsize.value;
|
||||
else fd->viewsize = 120.0f;
|
||||
|
||||
VectorCopy( cl.punchangle, fd->punchangle );
|
||||
fd->maxclients = cl.maxclients;
|
||||
|
||||
@@ -501,7 +501,6 @@ typedef struct
|
||||
|
||||
net_request_t net_requests[MAX_REQUESTS]; // no reason to keep more
|
||||
|
||||
efrag_t *free_efrags; // linked efrags
|
||||
cl_entity_t viewent; // viewmodel
|
||||
|
||||
qboolean client_dll_uses_sdl;
|
||||
@@ -518,8 +517,9 @@ typedef struct
|
||||
player_info_t playerinfo; // local playerinfo
|
||||
|
||||
gameui_draw_t ds; // draw2d stuff (menu images)
|
||||
GAMEINFO gameInfo; // current gameInfo
|
||||
GAMEINFO *modsInfo[MAX_MODS]; // simplified gameInfo for MainUI
|
||||
gameinfo2_t gameInfo; // current gameInfo
|
||||
gameinfo2_t *modsInfo; // simplified gameInfo for MainUI, allocated by demand
|
||||
GAMEINFO **oldModsInfo; // simplified gameInfo for older MainUI, allocated by demand
|
||||
|
||||
ui_globalvars_t *globals;
|
||||
|
||||
@@ -784,6 +784,7 @@ void CL_Demos_f( void );
|
||||
void CL_DeleteDemo_f( void );
|
||||
void CL_Record_f( void );
|
||||
void CL_Stop_f( void );
|
||||
void CL_ListDemo_f( void );
|
||||
int CL_GetDemoComment( const char *demoname, char *comment );
|
||||
|
||||
//
|
||||
|
||||
@@ -1753,7 +1753,7 @@ static void Con_DrawNotify( void )
|
||||
|
||||
if( host.allow_console && ( !Cvar_VariableInteger( "cl_background" ) && !Cvar_VariableInteger( "sv_background" )))
|
||||
{
|
||||
for( i = CON_LINES_COUNT - con.num_times; i < CON_LINES_COUNT; i++ )
|
||||
for( i = Q_max( 0, CON_LINES_COUNT - con.num_times ); i < CON_LINES_COUNT; i++ )
|
||||
{
|
||||
con_lineinfo_t *l = &CON_LINES( i );
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ static struct touch_s
|
||||
touchdefaultbutton_t g_DefaultButtons[256];
|
||||
int g_LastDefaultButton;
|
||||
|
||||
static CVAR_DEFINE_AUTO( touch_in_menu, "0", FCVAR_FILTERABLE, "draw touch in menu (for internal use only)" );
|
||||
static CVAR_DEFINE_AUTO( touch_in_menu, "0", FCVAR_PRIVILEGED, "draw touch in menu (for internal use only)" );
|
||||
static CVAR_DEFINE_AUTO( touch_forwardzone, "0.06", FCVAR_FILTERABLE, "forward touch zone" );
|
||||
static CVAR_DEFINE_AUTO( touch_sidezone, "0.06", FCVAR_FILTERABLE, "side touch zone" );
|
||||
static CVAR_DEFINE_AUTO( touch_pitch, "90", FCVAR_FILTERABLE, "touch pitch sensitivity" );
|
||||
@@ -163,8 +163,8 @@ static CVAR_DEFINE_AUTO( touch_dpad_radius, "1.0", FCVAR_FILTERABLE, "dpad radiu
|
||||
static CVAR_DEFINE_AUTO( touch_joy_radius, "1.0", FCVAR_FILTERABLE, "joy radius multiplier" );
|
||||
static CVAR_DEFINE_AUTO( touch_move_indicator, "0.0", FCVAR_FILTERABLE, "indicate move events (0 to disable)" );
|
||||
static CVAR_DEFINE_AUTO( touch_joy_texture, "touch_default/joy", FCVAR_FILTERABLE, "texture for move indicator");
|
||||
static CVAR_DEFINE_AUTO( touch_emulate, "0", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "emulate touch with mouse" );
|
||||
CVAR_DEFINE_AUTO( touch_enable, DEFAULT_TOUCH_ENABLE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable touch controls" );
|
||||
CVAR_DEFINE_AUTO( touch_emulate, "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "emulate touch with mouse" );
|
||||
|
||||
// code looks smaller with it
|
||||
#define B(x) (button->x)
|
||||
@@ -767,14 +767,18 @@ static void Touch_ReloadConfig_f( void )
|
||||
touch.state = state_none;
|
||||
if( touch.edit )
|
||||
touch.edit->finger = -1;
|
||||
|
||||
if( touch.selection )
|
||||
touch.selection->finger = -1;
|
||||
|
||||
touch.edit = touch.selection = NULL;
|
||||
touch.resize_finger = touch.move_finger = touch.look_finger = touch.wheel_finger = -1;
|
||||
if( FS_FileExists( touch_config_file.string, true ) )
|
||||
{
|
||||
|
||||
if( touch_in_menu.value )
|
||||
Cvar_DirectSet( &touch_in_menu, "0" );
|
||||
|
||||
if( FS_FileExists( touch_config_file.string, true ))
|
||||
Cbuf_AddTextf( "exec \"%s\"\n", touch_config_file.string );
|
||||
}
|
||||
else
|
||||
{
|
||||
Touch_LoadDefaults_f();
|
||||
@@ -1010,7 +1014,7 @@ static void Touch_DisableEdit_f( void )
|
||||
{
|
||||
Cvar_Set( "touch_in_menu", "0" );
|
||||
}
|
||||
else if( cls.key_dest == key_game )
|
||||
else if( cls.key_dest == key_game )
|
||||
Touch_WriteConfig();
|
||||
}
|
||||
|
||||
@@ -1087,18 +1091,19 @@ void Touch_Init( void )
|
||||
Touch_AddDefaultButton( "jump", "touch_default/jump", "+jump", 0.880000, 0.227228, 1.000000, 0.454457, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "attack", "touch_default/shoot", "+attack", 0.760000, 0.530200, 0.880000, 0.757428, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "attack2", "touch_default/shoot_alt", "+attack2", 0.760000, 0.302971, 0.880000, 0.530200, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "loadquick", "touch_default/load", "loadquick", 0.680000, 0.000000, 0.760000, 0.151486, color, 2, 1, 16 );
|
||||
Touch_AddDefaultButton( "savequick", "touch_default/save", "savequick", 0.760000, 0.000000, 0.840000, 0.151486, color, 2, 1, 16 );
|
||||
Touch_AddDefaultButton( "messagemode", "touch_default/keyboard", "messagemode", 0.760000, 0.000000, 0.840000, 0.151486, color, 2, 1, 8 );
|
||||
Touch_AddDefaultButton( "loadquick", "touch_default/load", "loadquick", 0.760000, 0.000000, 0.840000, 0.142222, color, 2, 1, 16 );
|
||||
Touch_AddDefaultButton( "savequick", "touch_default/save", "savequick", 0.840000, 0.000000, 0.920000, 0.142222, color, 2, 1, 16 );
|
||||
Touch_AddDefaultButton( "messagemode", "touch_default/keyboard", "messagemode", 0.840000, 0.000000, 0.920000, 0.142222, color, 2, 1, 8 );
|
||||
Touch_AddDefaultButton( "reload", "touch_default/reload", "+reload", 0.000000, 0.302971, 0.120000, 0.530200, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "flashlight", "touch_default/flash_light_filled", "impulse 100", 0.920000, 0.000000, 1.000000, 0.151486, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "scores", "touch_default/map", "+showscores", 0.680000, 0.000000, 0.760000, 0.151486, color, 2, 1, 8 );
|
||||
Touch_AddDefaultButton( "scores", "touch_default/map", "+showscores", 0.760000, 0.000000, 0.840000, 0.142222, color, 2, 1, 8 );
|
||||
Touch_AddDefaultButton( "show_numbers", "touch_default/show_weapons", "exec touch_default/numbers.cfg", 0.440000, 0.833171, 0.520000, 0.984656, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "duck", "touch_default/crouch", "+duck", 0.880000, 0.757428, 1.000000, 0.984656, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "tduck", "touch_default/tduck", ";+duck", 0.560000, 0.833171, 0.620000, 0.946785, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "edit", "touch_default/settings", "touch_enableedit", 0.420000, 0.000000, 0.500000, 0.151486, color, 2, 1, 32 );
|
||||
Touch_AddDefaultButton( "menu", "touch_default/menu", "escape", 0.000000, 0.833171, 0.080000, 0.984656, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "spray", "touch_default/spray", "impulse 201", 0.840000, 0.000000, 0.920000, 0.151486, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "spray", "touch_default/spray", "impulse 201", 0.680000, 0.000000, 0.760000, 0.142222, color, 2, 1, 8 );
|
||||
Touch_AddDefaultButton( "voicechat", "touch_default/microphone", "+voicerecord", 0.780000, 0.817778, 0.860000, 0.960000, color, 2, 1, 8 );
|
||||
|
||||
Cmd_AddCommand( "touch_addbutton", Touch_AddButton_f, "add native touch button" );
|
||||
Cmd_AddCommand( "touch_removebutton", IN_TouchRemoveButton_f, "remove native touch button" );
|
||||
@@ -2122,7 +2127,7 @@ void Touch_KeyEvent( int key, int down )
|
||||
float x, y;
|
||||
int finger, xi, yi;
|
||||
|
||||
if( !touch_emulate.value )
|
||||
if( !Touch_Emulated( ))
|
||||
{
|
||||
if( touch_enable.value )
|
||||
return;
|
||||
@@ -2176,6 +2181,11 @@ qboolean Touch_WantVisibleCursor( void )
|
||||
return ( touch_enable.value && touch_emulate.value ) || touch.clientonly;
|
||||
}
|
||||
|
||||
qboolean Touch_Emulated( void )
|
||||
{
|
||||
return touch_emulate.value || touch_in_menu.value;
|
||||
}
|
||||
|
||||
void Touch_Shutdown( void )
|
||||
{
|
||||
if( !touch.initialized )
|
||||
|
||||
@@ -47,6 +47,8 @@ static CVAR_DEFINE_AUTO( cl_forwardspeed, "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL
|
||||
static CVAR_DEFINE_AUTO( cl_backspeed, "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL | FCVAR_FILTERABLE, "Default back move speed" );
|
||||
static CVAR_DEFINE_AUTO( cl_sidespeed, "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL | FCVAR_FILTERABLE, "Default side move speed" );
|
||||
|
||||
static CVAR_DEFINE_AUTO( m_grab_debug, "0", FCVAR_PRIVILEGED, "show debug messages on mouse state change" );
|
||||
|
||||
/*
|
||||
================
|
||||
IN_CollectInputDevices
|
||||
@@ -116,6 +118,7 @@ static void IN_StartupMouse( void )
|
||||
Cvar_RegisterVariable( &m_yaw );
|
||||
Cvar_RegisterVariable( &look_filter );
|
||||
Cvar_RegisterVariable( &m_rawinput );
|
||||
Cvar_RegisterVariable( &m_grab_debug );
|
||||
|
||||
// You can use -nomouse argument to prevent using mouse from client
|
||||
// -noenginemouse will disable all mouse input
|
||||
@@ -202,68 +205,81 @@ void IN_ToggleClientMouse( int newstate, int oldstate )
|
||||
}
|
||||
}
|
||||
|
||||
static void IN_SetRelativeMouseMode( qboolean set, qboolean verbose )
|
||||
{
|
||||
static qboolean s_bRawInput;
|
||||
|
||||
if( set && !s_bRawInput )
|
||||
{
|
||||
#if XASH_SDL == 2
|
||||
SDL_GetRelativeMouseState( NULL, NULL );
|
||||
SDL_SetRelativeMouseMode( SDL_TRUE );
|
||||
#endif
|
||||
s_bRawInput = true;
|
||||
if( verbose )
|
||||
Con_Printf( "%s: true\n", __func__ );
|
||||
}
|
||||
else if( !set && s_bRawInput )
|
||||
{
|
||||
#if XASH_SDL == 2
|
||||
SDL_GetRelativeMouseState( NULL, NULL );
|
||||
SDL_SetRelativeMouseMode( SDL_FALSE );
|
||||
#endif
|
||||
s_bRawInput = false;
|
||||
if( verbose )
|
||||
Con_Printf( "%s: false\n", __func__ );
|
||||
}
|
||||
}
|
||||
|
||||
static void IN_SetMouseGrab( qboolean set, qboolean verbose )
|
||||
{
|
||||
static qboolean s_bMouseGrab;
|
||||
|
||||
if( set && !s_bMouseGrab )
|
||||
{
|
||||
#if XASH_SDL
|
||||
SDL_SetWindowGrab( host.hWnd, SDL_TRUE );
|
||||
#endif
|
||||
s_bMouseGrab = true;
|
||||
if( verbose )
|
||||
Con_Printf( "%s: true\n", __func__ );
|
||||
}
|
||||
else if( !set && s_bMouseGrab )
|
||||
{
|
||||
#if XASH_SDL
|
||||
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
|
||||
#endif
|
||||
|
||||
s_bMouseGrab = false;
|
||||
if( verbose )
|
||||
Con_Printf( "%s: false\n", __func__ );
|
||||
}
|
||||
}
|
||||
|
||||
static void IN_CheckMouseState( qboolean active )
|
||||
{
|
||||
static qboolean s_bRawInput, s_bMouseGrab;
|
||||
qboolean use_raw_input, verbose;
|
||||
|
||||
#if XASH_WIN32
|
||||
qboolean useRawInput = ( m_rawinput.value && clgame.client_dll_uses_sdl ) || clgame.dllFuncs.pfnLookEvent != NULL;
|
||||
use_raw_input = ( m_rawinput.value && clgame.client_dll_uses_sdl ) || clgame.dllFuncs.pfnLookEvent != NULL;
|
||||
#else
|
||||
qboolean useRawInput = true; // always use SDL code
|
||||
use_raw_input = true; // always use SDL code
|
||||
#endif
|
||||
|
||||
verbose = m_grab_debug.value ? true : false;
|
||||
|
||||
if( m_ignore.value )
|
||||
return;
|
||||
active = false;
|
||||
|
||||
if( active && useRawInput && !host.mouse_visible && cls.state == ca_active )
|
||||
{
|
||||
if( !s_bRawInput )
|
||||
{
|
||||
#if XASH_SDL == 2
|
||||
SDL_GetRelativeMouseState( NULL, NULL );
|
||||
SDL_SetRelativeMouseMode( SDL_TRUE );
|
||||
#endif
|
||||
|
||||
// Con_Printf( "Enable relative mode\n" );
|
||||
s_bRawInput = true;
|
||||
}
|
||||
}
|
||||
if( active && use_raw_input && !host.mouse_visible && cls.state == ca_active )
|
||||
IN_SetRelativeMouseMode( true, verbose );
|
||||
else
|
||||
{
|
||||
if( s_bRawInput )
|
||||
{
|
||||
#if XASH_SDL == 2
|
||||
SDL_GetRelativeMouseState( NULL, NULL );
|
||||
SDL_SetRelativeMouseMode( SDL_FALSE );
|
||||
#endif
|
||||
// Con_Printf( "Disable relative mode\n" );
|
||||
s_bRawInput = false;
|
||||
}
|
||||
}
|
||||
IN_SetRelativeMouseMode( false, verbose );
|
||||
|
||||
if( active && !host.mouse_visible && cls.state == ca_active )
|
||||
{
|
||||
if( !s_bMouseGrab )
|
||||
{
|
||||
#if XASH_SDL
|
||||
SDL_SetWindowGrab( host.hWnd, SDL_TRUE );
|
||||
#endif
|
||||
// Con_Printf( "Enable grab\n" );
|
||||
s_bMouseGrab = true;
|
||||
}
|
||||
}
|
||||
IN_SetMouseGrab( true, verbose );
|
||||
else
|
||||
{
|
||||
if( s_bMouseGrab )
|
||||
{
|
||||
#if XASH_SDL
|
||||
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
|
||||
#endif
|
||||
|
||||
// Con_Printf( "Disable grab\n" );
|
||||
s_bMouseGrab = false;
|
||||
}
|
||||
}
|
||||
IN_SetMouseGrab( false, verbose );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -316,7 +332,7 @@ static void IN_MouseMove( void )
|
||||
if( !in_mouseinitialized )
|
||||
return;
|
||||
|
||||
if( touch_emulate.value )
|
||||
if( Touch_Emulated( ))
|
||||
{
|
||||
// touch emulation overrides all input
|
||||
Touch_KeyEvent( 0, 0 );
|
||||
@@ -347,7 +363,7 @@ void IN_MouseEvent( int key, int down )
|
||||
else ClearBits( in_mstate, BIT( key ));
|
||||
|
||||
// touch emulation overrides all input
|
||||
if( touch_emulate.value )
|
||||
if( Touch_Emulated( ))
|
||||
{
|
||||
Touch_KeyEvent( K_MOUSE1 + key, down );
|
||||
}
|
||||
|
||||
@@ -58,7 +58,6 @@ typedef enum
|
||||
} touchEventType;
|
||||
|
||||
extern convar_t touch_enable;
|
||||
extern convar_t touch_emulate;
|
||||
|
||||
void Touch_Draw( void );
|
||||
void Touch_SetClientOnly( byte state );
|
||||
@@ -74,6 +73,7 @@ void Touch_ResetDefaultButtons( void );
|
||||
int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy );
|
||||
void Touch_KeyEvent( int key, int down );
|
||||
qboolean Touch_WantVisibleCursor( void );
|
||||
qboolean Touch_Emulated( void );
|
||||
void Touch_NotifyResize( void );
|
||||
|
||||
//
|
||||
|
||||
@@ -10,7 +10,7 @@ ref_globals_t refState;
|
||||
|
||||
static const char* r_skyBoxSuffix[SKYBOX_MAX_SIDES] = { "rt", "bk", "lf", "ft", "up", "dn" };
|
||||
|
||||
CVAR_DEFINE_AUTO( gl_vsync, "0", FCVAR_ARCHIVE, "enable vertical syncronization" );
|
||||
CVAR_DEFINE_AUTO( gl_vsync, "1", FCVAR_ARCHIVE, "enable vertical syncronization" );
|
||||
CVAR_DEFINE_AUTO( r_showtextures, "0", FCVAR_CHEAT, "show all uploaded textures" );
|
||||
CVAR_DEFINE_AUTO( r_adjust_fov, "1", FCVAR_ARCHIVE, "making FOV adjustment for wide-screens" );
|
||||
CVAR_DEFINE_AUTO( r_decals, "4096", FCVAR_ARCHIVE, "sets the maximum number of decals" );
|
||||
@@ -285,7 +285,7 @@ static qboolean R_Init_Video_( const int type )
|
||||
return R_Init_Video( type );
|
||||
}
|
||||
|
||||
static ref_api_t gEngfuncs =
|
||||
static const ref_api_t gEngfuncs =
|
||||
{
|
||||
pfnEngineGetParm,
|
||||
|
||||
@@ -491,7 +491,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 ));
|
||||
gpEngfuncs = gEngfuncs;
|
||||
|
||||
if( GetRefAPI( REF_API_VERSION, &ref.dllFuncs, &gpEngfuncs, &refState ) != REF_API_VERSION )
|
||||
{
|
||||
@@ -544,21 +544,19 @@ static void R_GetRendererName( char *dest, size_t size, const char *opt )
|
||||
{
|
||||
if( !Q_strstr( opt, "." OS_LIB_EXT ))
|
||||
{
|
||||
const char *format;
|
||||
|
||||
#ifdef XASH_INTERNAL_GAMELIBS
|
||||
if( !Q_strcmp( opt, "ref_" ))
|
||||
format = "%s";
|
||||
else
|
||||
format = "ref_%s";
|
||||
#define FMT1 "%s"
|
||||
#define FMT2 "ref_%s"
|
||||
#else
|
||||
if( !Q_strcmp( opt, "ref_" ))
|
||||
format = OS_LIB_PREFIX "%s." OS_LIB_EXT;
|
||||
else
|
||||
format = OS_LIB_PREFIX "ref_%s." OS_LIB_EXT;
|
||||
#define FMT1 OS_LIB_PREFIX "%s." OS_LIB_EXT
|
||||
#define FMT2 OS_LIB_PREFIX "ref_%s." OS_LIB_EXT
|
||||
#endif
|
||||
Q_snprintf( dest, size, format, opt );
|
||||
|
||||
if( !Q_strncmp( opt, "ref_", 4 ))
|
||||
Q_snprintf( dest, size, FMT1, opt );
|
||||
else
|
||||
Q_snprintf( dest, size, FMT2, opt );
|
||||
#undef FMT1
|
||||
#undef FMT2
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -636,6 +634,9 @@ static void R_CollectRendererNames( void )
|
||||
#endif
|
||||
#if XASH_REF_SOFT_ENABLED
|
||||
"soft",
|
||||
#endif
|
||||
#if XASH_REF_NULL_ENABLED
|
||||
"null",
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -659,6 +660,9 @@ static void R_CollectRendererNames( void )
|
||||
#endif
|
||||
#if XASH_REF_SOFT_ENABLED
|
||||
"Software",
|
||||
#endif
|
||||
#if XASH_REF_NULL_ENABLED
|
||||
"Null Renderer",
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -155,11 +155,11 @@ wavdata_t *S_LoadSound( sfx_t *sfx )
|
||||
if( !sc ) sc = S_CreateDefaultSound();
|
||||
|
||||
if( sc->rate < SOUND_11k ) // some bad sounds
|
||||
Sound_Process( &sc, SOUND_11k, sc->width, SOUND_RESAMPLE );
|
||||
Sound_Process( &sc, SOUND_11k, sc->width, sc->channels, SOUND_RESAMPLE );
|
||||
else if( sc->rate > SOUND_11k && sc->rate < SOUND_22k ) // some bad sounds
|
||||
Sound_Process( &sc, SOUND_22k, sc->width, SOUND_RESAMPLE );
|
||||
Sound_Process( &sc, SOUND_22k, sc->width, sc->channels, SOUND_RESAMPLE );
|
||||
else if( sc->rate > SOUND_22k && sc->rate < SOUND_44k ) // some bad sounds
|
||||
Sound_Process( &sc, SOUND_44k, sc->width, SOUND_RESAMPLE );
|
||||
Sound_Process( &sc, SOUND_44k, sc->width, sc->channels, SOUND_RESAMPLE );
|
||||
|
||||
sfx->cache = sc;
|
||||
|
||||
|
||||
@@ -1092,7 +1092,7 @@ rawchan_t *S_FindRawChannel( int entnum, qboolean create )
|
||||
if( !raw_channels[best] )
|
||||
{
|
||||
raw_samples = MAX_RAW_SAMPLES;
|
||||
raw_channels[best] = Mem_Calloc( sndpool, sizeof( *ch ) + sizeof( portable_samplepair_t ) * ( raw_samples - 1 ));
|
||||
raw_channels[best] = Mem_Calloc( sndpool, sizeof( *ch ) + sizeof( portable_samplepair_t ) * raw_samples );
|
||||
}
|
||||
|
||||
ch = raw_channels[best];
|
||||
|
||||
@@ -923,7 +923,7 @@ static void S_MixUpsample( int sampleCount, int filtertype )
|
||||
static void MIX_MixRawSamplesBuffer( int end )
|
||||
{
|
||||
portable_samplepair_t *pbuf, *roombuf, *streambuf;
|
||||
uint i, j, stop;
|
||||
uint i, j, stop;
|
||||
|
||||
roombuf = MIX_GetPFrontFromIPaint( IROOMBUFFER );
|
||||
streambuf = MIX_GetPFrontFromIPaint( ISTREAMBUFFER );
|
||||
@@ -956,7 +956,11 @@ static void MIX_MixRawSamplesBuffer( int end )
|
||||
}
|
||||
|
||||
if( ch->entnum > 0 )
|
||||
SND_MoveMouthRaw( ch, &ch->rawsamples[paintedtime & ( ch->max_samples - 1 )], stop - paintedtime );
|
||||
{
|
||||
int pos = paintedtime & ( ch->max_samples - 1 );
|
||||
|
||||
SND_MoveMouthRaw( ch, &ch->rawsamples[pos], bound( 0, ch->max_samples - pos, stop - paintedtime ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ static int S_TrimEnd( const wavdata_t *wav, int end )
|
||||
|
||||
if( width == 1 )
|
||||
{
|
||||
const int8_t *data = (const int8_t *)&wav->buffer[channels * width * end];
|
||||
const int8_t *data = (const int8_t *)&wav->buffer[channels * width * ( end - 1 )];
|
||||
|
||||
for( i = 0; i < TRIM_SCAN_MAX && end > 0; i++ )
|
||||
{
|
||||
@@ -109,7 +109,7 @@ static int S_TrimEnd( const wavdata_t *wav, int end )
|
||||
}
|
||||
else if( width == 2 )
|
||||
{
|
||||
const int16_t *data = (const int16_t *)&wav->buffer[channels * width * end];
|
||||
const int16_t *data = (const int16_t *)&wav->buffer[channels * width * ( end - 1 )];
|
||||
|
||||
for( i = 0; i < TRIM_SCAN_MAX && end > 0; i++ )
|
||||
{
|
||||
|
||||
@@ -116,7 +116,7 @@ typedef struct rawchan_s
|
||||
float oldtime; // catch time jumps
|
||||
wavdata_t sound_info; // advance play position
|
||||
size_t max_samples; // buffer length
|
||||
portable_samplepair_t rawsamples[1]; // variable sized
|
||||
portable_samplepair_t rawsamples[]; // variable sized
|
||||
} rawchan_t;
|
||||
|
||||
typedef struct channel_s
|
||||
|
||||
@@ -50,7 +50,9 @@ static CVAR_DEFINE_AUTO( vgui_utf8, "0", FCVAR_ARCHIVE, "enable utf-8 support fo
|
||||
static void GAME_EXPORT VGUI_DrawInit( void )
|
||||
{
|
||||
memset( vgui.textures, 0, sizeof( vgui.textures ));
|
||||
memset( vgui.color, 0, sizeof( vgui.color ));
|
||||
vgui.texture_id = vgui.bound_texture = 0;
|
||||
vgui.enable_texture = true;
|
||||
}
|
||||
|
||||
static void GAME_EXPORT VGUI_DrawShutdown( void )
|
||||
@@ -280,7 +282,7 @@ qboolean VGui_LoadProgs( HINSTANCE hInstance )
|
||||
void (*F)( vguiapi_t* );
|
||||
qboolean client = hInstance != NULL;
|
||||
|
||||
memcpy( &vgui.dllFuncs, &gEngfuncs, sizeof( vgui.dllFuncs ));
|
||||
vgui.dllFuncs = gEngfuncs;
|
||||
|
||||
// not loading interface from client.dll, load vgui_support.dll instead
|
||||
if( !client )
|
||||
@@ -371,7 +373,7 @@ void VGui_Shutdown( void )
|
||||
COM_FreeLibrary( vgui.hInstance );
|
||||
|
||||
// drop pointers to now unloaded vgui_support
|
||||
memcpy( &vgui.dllFuncs, &gEngfuncs, sizeof( vgui.dllFuncs ));
|
||||
vgui.dllFuncs = gEngfuncs;
|
||||
vgui.hInstance = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ static CVAR_DEFINE_AUTO( vid_scale, "1.0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "p
|
||||
|
||||
CVAR_DEFINE_AUTO( vid_highdpi, "1", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "enable High-DPI mode" );
|
||||
CVAR_DEFINE_AUTO( vid_maximized, "0", FCVAR_RENDERINFO, "window maximized state, read-only" );
|
||||
CVAR_DEFINE( vid_fullscreen, "fullscreen", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "fullscreen state (0 windowed, 1 fullscreen, 2 borderless)" );
|
||||
CVAR_DEFINE( vid_fullscreen, "fullscreen", DEFAULT_FULLSCREEN, FCVAR_RENDERINFO|FCVAR_VIDRESTART, "fullscreen state (0 windowed, 1 fullscreen, 2 borderless)" );
|
||||
CVAR_DEFINE( window_width, "width", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen width" );
|
||||
CVAR_DEFINE( window_height, "height", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen height" );
|
||||
CVAR_DEFINE( window_xpos, "_window_xpos", "-1", FCVAR_RENDERINFO, "window position by horizontal" );
|
||||
|
||||
@@ -32,6 +32,11 @@ CVAR_DEFINE_AUTO( voice_inputfromfile, "0", FCVAR_PRIVILEGED, "input voice from
|
||||
|
||||
static void Voice_ApplyGainAdjust( int16_t *samples, int count, float scale );
|
||||
|
||||
// in case user enabled voice after connection
|
||||
// can't keep in `voice` struct because it gets zeroed on shutdown
|
||||
static string voice_codec_init;
|
||||
static int voice_quality_init;
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
@@ -397,7 +402,7 @@ void Voice_RecordStart( void )
|
||||
|
||||
if( voice.input_file )
|
||||
{
|
||||
Sound_Process( &voice.input_file, voice.samplerate, voice.width, SOUND_RESAMPLE );
|
||||
Sound_Process( &voice.input_file, voice.samplerate, voice.width, VOICE_PCM_CHANNELS, SOUND_RESAMPLE );
|
||||
voice.input_file_pos = 0;
|
||||
|
||||
voice.start_time = Sys_DoubleTime();
|
||||
@@ -591,10 +596,17 @@ void Voice_Idle( double frametime )
|
||||
{
|
||||
int i;
|
||||
|
||||
if( FBitSet( voice_enable.flags, FCVAR_CHANGED ) && !voice_enable.value )
|
||||
if( FBitSet( voice_enable.flags, FCVAR_CHANGED ))
|
||||
{
|
||||
Voice_Shutdown();
|
||||
return;
|
||||
ClearBits( voice_enable.flags, FCVAR_CHANGED );
|
||||
|
||||
if( voice_enable.value )
|
||||
{
|
||||
if( cls.state == ca_active && COM_CheckString( voice_codec_init ) && voice_quality_init != 0 )
|
||||
Voice_Init( voice_codec_init, voice_quality_init, false );
|
||||
}
|
||||
else
|
||||
Voice_Shutdown();
|
||||
}
|
||||
|
||||
// update local player status first
|
||||
@@ -613,6 +625,19 @@ Initialize the voice subsystem
|
||||
*/
|
||||
qboolean Voice_Init( const char *pszCodecName, int quality, qboolean preinit )
|
||||
{
|
||||
if( Q_strcmp( pszCodecName, VOICE_OPUS_CUSTOM_CODEC ))
|
||||
{
|
||||
Con_Printf( S_ERROR "Server requested unsupported codec: %s\n", pszCodecName );
|
||||
|
||||
// reset saved codec name, we won't enable voice for this connection
|
||||
voice_codec_init[0] = 0;
|
||||
voice_quality_init = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
Q_strncpy( voice_codec_init, pszCodecName, sizeof( voice_codec_init ));
|
||||
voice_quality_init = quality;
|
||||
|
||||
if( !voice_enable.value )
|
||||
return false;
|
||||
|
||||
@@ -620,13 +645,6 @@ qboolean Voice_Init( const char *pszCodecName, int quality, qboolean preinit )
|
||||
if( Q_strcmp( pszCodecName, voice.codec ) || voice.quality != quality )
|
||||
{
|
||||
Voice_Shutdown();
|
||||
|
||||
if( Q_strcmp( pszCodecName, VOICE_OPUS_CUSTOM_CODEC ))
|
||||
{
|
||||
Con_Printf( S_ERROR "Server requested unsupported codec: %s\n", pszCodecName );
|
||||
return false;
|
||||
}
|
||||
|
||||
voice.autogain.block_size = 128;
|
||||
|
||||
if( !Voice_InitCustomMode( ))
|
||||
|
||||
@@ -52,12 +52,18 @@ GNU General Public License for more details.
|
||||
|
||||
#define DEFAULT_EXTERNAL_PALETTE "gfx/palette.pal"
|
||||
|
||||
// path to folders where placed all sounds
|
||||
// path to sound files
|
||||
#define DEFAULT_SOUNDPATH "sound/"
|
||||
|
||||
// path store saved games
|
||||
// path to saved games
|
||||
#define DEFAULT_SAVE_DIRECTORY "save/"
|
||||
|
||||
// path to download games
|
||||
#define DEFAULT_DOWNLOADED_DIRECTORY "downloaded/"
|
||||
|
||||
// path to user mod directory
|
||||
#define DEFAULT_CUSTOM_DIRECTORY "custom/"
|
||||
|
||||
// fallback to this skybox
|
||||
#define DEFAULT_SKYBOX_NAME "desert"
|
||||
|
||||
@@ -72,7 +78,7 @@ GNU General Public License for more details.
|
||||
|
||||
#define XASH_ENGINE_NAME "Xash3D FWGS"
|
||||
#define XASH_DEDICATED_SERVER_NAME "XashDS"
|
||||
#define XASH_VERSION "0.20" // engine current version
|
||||
#define XASH_VERSION "0.21" // engine current version
|
||||
#define XASH_COMPAT_VERSION "0.99" // version we are based on
|
||||
|
||||
#endif//COM_STRINGS_H
|
||||
|
||||
@@ -314,6 +314,11 @@ typedef struct host_parm_s
|
||||
vec3_t player_mins[MAX_MAP_HULLS]; // 4 hulls allowed
|
||||
vec3_t player_maxs[MAX_MAP_HULLS]; // 4 hulls allowed
|
||||
|
||||
// for CL_{Push,Pop}TraceBounds
|
||||
vec3_t player_mins_backup[MAX_MAP_HULLS];
|
||||
vec3_t player_maxs_backup[MAX_MAP_HULLS];
|
||||
qboolean trace_bounds_pushed;
|
||||
|
||||
qboolean allow_console; // allow console in dev-mode or multiplayer game
|
||||
qboolean allow_console_init; // initial value to allow the console
|
||||
qboolean key_overstrike; // key overstrike mode
|
||||
@@ -492,7 +497,7 @@ int FS_ReadStream( stream_t *stream, int bytes, void *buffer );
|
||||
int FS_SetStreamPos( stream_t *stream, int newpos );
|
||||
int FS_GetStreamPos( stream_t *stream );
|
||||
void FS_FreeStream( stream_t *stream );
|
||||
qboolean Sound_Process( wavdata_t **wav, int rate, int width, uint flags );
|
||||
qboolean Sound_Process( wavdata_t **wav, int rate, int width, int channels, uint flags );
|
||||
uint Sound_GetApproxWavePlayLen( const char *filepath );
|
||||
qboolean Sound_SupportedFileFormat( const char *fileext );
|
||||
|
||||
|
||||
@@ -1019,6 +1019,7 @@ autocomplete_list_t cmd_list[] =
|
||||
{ "changelevel", 1, Cmd_GetMapList },
|
||||
{ "playdemo", 1, Cmd_GetDemoList, },
|
||||
{ "timedemo", 1, Cmd_GetDemoList, },
|
||||
{ "listdemo", 1, Cmd_GetDemoList, },
|
||||
{ "playvol", 1, Cmd_GetSoundList },
|
||||
{ "hpkval", 1, Cmd_GetCustomList },
|
||||
{ "hpklist", 1, Cmd_GetCustomList },
|
||||
@@ -1201,7 +1202,7 @@ void Con_CompleteCommand( field_t *field )
|
||||
|
||||
if( !con.matchCount ) return; // no matches
|
||||
|
||||
memcpy( &temp, con.completionField, sizeof( field_t ) );
|
||||
temp = *con.completionField;
|
||||
|
||||
// autocomplete second arg
|
||||
if( (Cmd_Argc() >= 2) || ((Cmd_Argc() == 1) && nextcmd) )
|
||||
|
||||
@@ -92,7 +92,7 @@ static void Sys_StackTrace( PEXCEPTION_POINTERS pInfo )
|
||||
STACKFRAME64 stackframe;
|
||||
DWORD image;
|
||||
|
||||
memcpy( &context, pInfo->ContextRecord, sizeof( CONTEXT ));
|
||||
context = *pInfo->ContextRecord;
|
||||
|
||||
options = SymGetOptions();
|
||||
options |= SYMOPT_DEBUG;
|
||||
|
||||
@@ -59,7 +59,7 @@ static void FS_Path_f_( void )
|
||||
FS_Path_f();
|
||||
}
|
||||
|
||||
static fs_interface_t fs_memfuncs =
|
||||
static const fs_interface_t fs_memfuncs =
|
||||
{
|
||||
Con_Printf,
|
||||
Con_DPrintf,
|
||||
@@ -221,7 +221,13 @@ void FS_Init( const char *basedir )
|
||||
COM_StripDirectorySlash( rodir );
|
||||
|
||||
if( !Sys_GetParmFromCmdLine( "-game", gamedir ))
|
||||
Q_strncpy( gamedir, basedir, sizeof( gamedir )); // gamedir == basedir
|
||||
{
|
||||
char *env = getenv( "XASH3D_GAME" );
|
||||
if( env )
|
||||
Q_strncpy( gamedir, env, sizeof( gamedir ));
|
||||
else
|
||||
Q_strncpy( gamedir, basedir, sizeof( gamedir )); // gamedir == basedir
|
||||
}
|
||||
|
||||
FS_LoadProgs();
|
||||
|
||||
|
||||
@@ -1028,8 +1028,8 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
|
||||
}
|
||||
#endif
|
||||
|
||||
// always enable console for Quake
|
||||
if( !host.allow_console && ( Sys_CheckParm( "-console" ) || !Q_strnicmp( exename, "quake", 5 )))
|
||||
// always enable console for Quake and dedicated
|
||||
if( !host.allow_console && ( Host_IsDedicated() || Sys_CheckParm( "-console" ) || !Q_strnicmp( exename, "quake", 5 )))
|
||||
host.allow_console = true;
|
||||
|
||||
// member console allowing
|
||||
@@ -1078,7 +1078,16 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
|
||||
|
||||
// print current developer level to simplify processing users feedback
|
||||
if( developer > 0 )
|
||||
Con_Printf( "Developer level: ^3%i\n", developer );
|
||||
{
|
||||
int i;
|
||||
|
||||
Con_Printf( "Program args: " S_YELLOW );
|
||||
for( i = 0; i < host.argc; i++ )
|
||||
Con_Printf( "%s ", host.argv[i] );
|
||||
Con_Printf( S_DEFAULT "\n" );
|
||||
|
||||
Con_Printf( "Developer level: " S_YELLOW "%i" S_DEFAULT "\n", developer );
|
||||
}
|
||||
|
||||
host.bugcomp = Host_CheckBugcomp();
|
||||
|
||||
|
||||
@@ -76,6 +76,8 @@ typedef struct
|
||||
int infotableofs;
|
||||
} hpak_header_t;
|
||||
|
||||
STATIC_ASSERT( sizeof( hpak_header_t ) == 12, "invalid hpak_header_t size" );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
dresource_t resource;
|
||||
@@ -83,6 +85,8 @@ typedef struct
|
||||
int disksize;
|
||||
} hpak_lump_t;
|
||||
|
||||
STATIC_ASSERT( sizeof( hpak_lump_t ) == 144, "invalid hpak_lump_t size" );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int count;
|
||||
|
||||
@@ -108,12 +108,13 @@ typedef struct imglib_s
|
||||
|
||||
enum
|
||||
{
|
||||
LUMP_NORMAL = 0, // no alpha
|
||||
LUMP_MASKED, // 1-bit alpha channel masked texture
|
||||
LUMP_GRADIENT, // gradient image (decals)
|
||||
LUMP_EXTENDED, // bmp images have extened palette with alpha-channel
|
||||
LUMP_HALFLIFE, // get predefined half-life palette
|
||||
LUMP_QUAKE1 // get predefined quake palette
|
||||
LUMP_NORMAL = 0, // no alpha
|
||||
LUMP_MASKED, // 1-bit alpha channel masked texture
|
||||
LUMP_GRADIENT, // gradient image (decals)
|
||||
LUMP_EXTENDED, // bmp images have extened palette with alpha-channel
|
||||
LUMP_HALFLIFE, // get predefined half-life palette
|
||||
LUMP_QUAKE1, // get predefined quake palette
|
||||
LUMP_TEXGAMMA, // apply texgamma on top of palette, for half-life mips
|
||||
};
|
||||
|
||||
enum
|
||||
|
||||
@@ -174,8 +174,8 @@ byte *Image_Copy( size_t size )
|
||||
{
|
||||
byte *out;
|
||||
|
||||
out = Mem_Malloc( host.imagepool, size );
|
||||
memcpy( out, image.tempbuffer, size );
|
||||
out = Mem_Realloc( host.imagepool, image.tempbuffer, size );
|
||||
image.tempbuffer = NULL;
|
||||
|
||||
return out;
|
||||
}
|
||||
@@ -293,9 +293,18 @@ static void Image_SetPalette( const byte *pal, uint *d_table )
|
||||
case LUMP_NORMAL:
|
||||
for( i = 0; i < 256; i++ )
|
||||
{
|
||||
rgba[0] = TextureToGamma( pal[i*3+0] );
|
||||
rgba[1] = TextureToGamma( pal[i*3+1] );
|
||||
rgba[2] = TextureToGamma( pal[i*3+2] );
|
||||
memcpy( rgba, &pal[i * 3], 3 );
|
||||
rgba[3] = 0xFF;
|
||||
memcpy( &uirgba, rgba, sizeof( uirgba ));
|
||||
d_table[i] = uirgba;
|
||||
}
|
||||
break;
|
||||
case LUMP_TEXGAMMA:
|
||||
for( i = 0; i < 256; i++ )
|
||||
{
|
||||
rgba[0] = TextureToGamma( pal[i * 3 + 0] );
|
||||
rgba[1] = TextureToGamma( pal[i * 3 + 1] );
|
||||
rgba[2] = TextureToGamma( pal[i * 3 + 2] );
|
||||
rgba[3] = 0xFF;
|
||||
memcpy( &uirgba, rgba, sizeof( uirgba ));
|
||||
d_table[i] = uirgba;
|
||||
@@ -1374,20 +1383,20 @@ static qboolean Image_RemapInternal( rgbdata_t *pic, int topColor, int bottomCol
|
||||
return true;
|
||||
}
|
||||
|
||||
qboolean Image_Process(rgbdata_t **pix, int width, int height, uint flags, float reserved )
|
||||
qboolean Image_Process( rgbdata_t **pix, int width, int height, uint flags, float reserved )
|
||||
{
|
||||
rgbdata_t *pic = *pix;
|
||||
qboolean result = true;
|
||||
byte *out;
|
||||
|
||||
// check for buffers
|
||||
if( !pic || !pic->buffer )
|
||||
if( unlikely( !pic || !pic->buffer ))
|
||||
{
|
||||
image.force_flags = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !flags )
|
||||
if( unlikely( !flags ))
|
||||
{
|
||||
// clear any force flags
|
||||
image.force_flags = 0;
|
||||
@@ -1432,7 +1441,7 @@ qboolean Image_Process(rgbdata_t **pix, int width, int height, uint flags, float
|
||||
pic->width = w, pic->height = h;
|
||||
pic->size = w * h * PFDesc[pic->type].bpp;
|
||||
Mem_Free( pic->buffer ); // free original image buffer
|
||||
pic->buffer = Image_Copy( pic->size ); // unzone buffer (don't touch image.tempbuffer)
|
||||
pic->buffer = Image_Copy( pic->size ); // unzone buffer
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -427,8 +427,18 @@ qboolean Image_LoadMIP( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
}
|
||||
|
||||
if( pal_type == PAL_QUAKE1 )
|
||||
{
|
||||
SetBits( image.flags, IMAGE_QUAKEPAL );
|
||||
rendermode = LUMP_NORMAL;
|
||||
|
||||
// if texture was converted from quake to half-life with no palette changes
|
||||
// then applying texgamma might make it too dark or even outright broken
|
||||
rendermode = LUMP_NORMAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// half-life mips need texgamma applied
|
||||
rendermode = LUMP_TEXGAMMA;
|
||||
}
|
||||
}
|
||||
|
||||
Image_GetPaletteLMP( pal, rendermode );
|
||||
|
||||
@@ -23,9 +23,8 @@ GNU General Public License for more details.
|
||||
#include "build.h"
|
||||
#include "common.h"
|
||||
|
||||
#define E_GAME "XASH3D_GAME" // default env dir to start from
|
||||
#ifndef XASH_GAMEDIR
|
||||
#define XASH_GAMEDIR "valve"
|
||||
#define XASH_GAMEDIR "valve" // !!! Replace with your default (base) game directory !!!
|
||||
#endif
|
||||
|
||||
#if XASH_WIN32
|
||||
@@ -47,12 +46,7 @@ static void Sys_ChangeGame( const char *progname )
|
||||
|
||||
static int Sys_Start( void )
|
||||
{
|
||||
const char *game = getenv( E_GAME );
|
||||
|
||||
if( !game )
|
||||
game = XASH_GAMEDIR;
|
||||
|
||||
Q_strncpy( szGameDir, game, sizeof( szGameDir ));
|
||||
Q_strncpy( szGameDir, XASH_GAMEDIR, sizeof( szGameDir ));
|
||||
|
||||
#if XASH_EMSCRIPTEN
|
||||
#ifdef EMSCRIPTEN_LIB_FS
|
||||
@@ -73,7 +67,7 @@ static int Sys_Start( void )
|
||||
IOS_LaunchDialog();
|
||||
#endif
|
||||
|
||||
return Host_Main( szArgc, szArgv, game, 0, Sys_ChangeGame );
|
||||
return Host_Main( szArgc, szArgv, szGameDir, 0, Sys_ChangeGame );
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
|
||||
241
engine/common/mod_alias.c
Normal file
241
engine/common/mod_alias.c
Normal file
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
mod_alias.c - alias model loading
|
||||
Copyright (C) 2010 Uncle Mike
|
||||
Copyright (C) 2024 Alibek Omarov
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "alias.h"
|
||||
#if !XASH_DEDICATED
|
||||
#include "ref_common.h"
|
||||
#endif // XASH_DEDICATED
|
||||
#include "mod_local.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
|
||||
static int g_posenum = 0;
|
||||
static const trivertex_t *g_poseverts[MAXALIASFRAMES];
|
||||
|
||||
static const void *Mod_LoadAliasFrame( const daliasframe_t *pdaliasframe, maliasframedesc_t *frame, const aliashdr_t *aliashdr )
|
||||
{
|
||||
const trivertex_t *pinframe;
|
||||
int i;
|
||||
|
||||
Q_strncpy( frame->name, pdaliasframe->name, sizeof( frame->name ));
|
||||
frame->firstpose = g_posenum;
|
||||
frame->numposes = 1;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
frame->bboxmin.v[i] = pdaliasframe->bboxmin.v[i];
|
||||
frame->bboxmax.v[i] = pdaliasframe->bboxmax.v[i];
|
||||
}
|
||||
|
||||
pinframe = (const trivertex_t *)(pdaliasframe + 1);
|
||||
|
||||
g_poseverts[g_posenum] = pinframe;
|
||||
g_posenum++;
|
||||
|
||||
pinframe += aliashdr->numverts;
|
||||
|
||||
return (void *)pinframe;
|
||||
}
|
||||
|
||||
static const void *Mod_LoadAliasGroup( const daliasgroup_t *pingroup, maliasframedesc_t *frame, const aliashdr_t *aliashdr )
|
||||
{
|
||||
const daliasinterval_t *pin_intervals;
|
||||
const void *ptemp;
|
||||
int i, numframes;
|
||||
|
||||
frame->firstpose = g_posenum;
|
||||
frame->numposes = numframes = pingroup->numframes;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
frame->bboxmin.v[i] = pingroup->bboxmin.v[i];
|
||||
frame->bboxmax.v[i] = pingroup->bboxmax.v[i];
|
||||
}
|
||||
|
||||
pin_intervals = (const daliasinterval_t *)(pingroup + 1);
|
||||
|
||||
// all the intervals are always equal 0.1 so we don't care about them
|
||||
frame->interval = pin_intervals->interval;
|
||||
pin_intervals += numframes;
|
||||
ptemp = (void *)pin_intervals;
|
||||
|
||||
for( i = 0; i < numframes; i++ )
|
||||
{
|
||||
g_poseverts[g_posenum] = (const trivertex_t *)((const daliasframe_t *)ptemp + 1);
|
||||
ptemp = g_poseverts[g_posenum] + aliashdr->numverts;
|
||||
g_posenum++;
|
||||
}
|
||||
|
||||
return ptemp;
|
||||
}
|
||||
|
||||
static void Mod_CalcAliasBounds( model_t *mod, const aliashdr_t *aliashdr )
|
||||
{
|
||||
int i, j, k;
|
||||
float radius;
|
||||
float dist;
|
||||
vec3_t v;
|
||||
|
||||
ClearBounds( mod->mins, mod->maxs );
|
||||
radius = 0.0f;
|
||||
|
||||
// process verts
|
||||
for( i = 0; i < aliashdr->numposes; i++ )
|
||||
{
|
||||
for( j = 0; j < aliashdr->numverts; j++ )
|
||||
{
|
||||
for( k = 0; k < 3; k++ )
|
||||
v[k] = g_poseverts[i][j].v[k] * aliashdr->scale[k] + aliashdr->scale_origin[k];
|
||||
|
||||
AddPointToBounds( v, mod->mins, mod->maxs );
|
||||
dist = DotProduct( v, v );
|
||||
|
||||
if( radius < dist )
|
||||
radius = dist;
|
||||
}
|
||||
}
|
||||
|
||||
mod->radius = sqrt( radius );
|
||||
}
|
||||
|
||||
static const void *Mod_LoadAllSkins( model_t *mod, int numskins, const daliasskintype_t *pskintype, const aliashdr_t *aliashdr )
|
||||
{
|
||||
int i, size;
|
||||
|
||||
if(( numskins < 1 ) || ( numskins > MAX_SKINS ))
|
||||
Host_Error( "%s: Invalid # of skins: %d\n", __func__, numskins );
|
||||
|
||||
size = aliashdr->skinwidth * aliashdr->skinheight;
|
||||
|
||||
// just skipping textures, renderer will take care of them later
|
||||
for( i = 0; i < numskins; i++ )
|
||||
{
|
||||
if( pskintype->type == ALIAS_SKIN_SINGLE )
|
||||
{
|
||||
const byte *ptexture = (const byte *)&pskintype[1];
|
||||
|
||||
pskintype = (const daliasskintype_t *)( ptexture + size );
|
||||
}
|
||||
else
|
||||
{
|
||||
const daliasskingroup_t *pinskingroup = (const daliasskingroup_t *)&pskintype[1];
|
||||
const daliasskininterval_t *pinskinintervals = (const daliasskininterval_t *)&pinskingroup[1];
|
||||
const byte *ptexture = (const byte *)&pinskinintervals[pinskingroup->numskins];
|
||||
|
||||
pskintype = (const daliasskintype_t *)( ptexture + size );
|
||||
}
|
||||
}
|
||||
|
||||
return pskintype;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
Mod_LoadAliasModel
|
||||
|
||||
load alias model
|
||||
====================
|
||||
*/
|
||||
void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *loaded )
|
||||
{
|
||||
const daliasframetype_t *pframetype;
|
||||
const daliasskintype_t *pskintype;
|
||||
const dtriangle_t *pintriangles;
|
||||
const daliashdr_t *pinmodel;
|
||||
const stvert_t *pinstverts;
|
||||
aliashdr_t *m_pAliasHeader;
|
||||
size_t size;
|
||||
char poolname[MAX_VA_STRING];
|
||||
int i;
|
||||
|
||||
if( loaded ) *loaded = false;
|
||||
pinmodel = (const daliashdr_t *)buffer;
|
||||
i = pinmodel->version;
|
||||
|
||||
if( i != ALIAS_VERSION )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s has wrong version number (%i should be %i)\n", mod->name, i, ALIAS_VERSION );
|
||||
return;
|
||||
}
|
||||
|
||||
if( pinmodel->numverts <= 0 || pinmodel->numtris <= 0 || pinmodel->numframes <= 0 )
|
||||
return; // how is it possible to make that?
|
||||
|
||||
Q_snprintf( poolname, sizeof( poolname ), "^2%s^7", mod->name );
|
||||
mod->mempool = Mem_AllocPool( poolname );
|
||||
|
||||
size = sizeof( aliashdr_t ) + (pinmodel->numframes - 1) * sizeof( maliasframedesc_t );
|
||||
mod->cache.data = m_pAliasHeader = Mem_Calloc( mod->mempool, size );
|
||||
|
||||
// endian-adjust and copy the data, starting with the alias model header
|
||||
m_pAliasHeader->numverts = pinmodel->numverts;
|
||||
|
||||
if( m_pAliasHeader->numverts > MAXALIASVERTS )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "model %s has too many vertices\n", mod->name );
|
||||
return;
|
||||
}
|
||||
|
||||
mod->flags = pinmodel->flags; // share effects flags
|
||||
m_pAliasHeader->boundingradius = pinmodel->boundingradius;
|
||||
m_pAliasHeader->numskins = pinmodel->numskins;
|
||||
m_pAliasHeader->skinwidth = pinmodel->skinwidth;
|
||||
m_pAliasHeader->skinheight = pinmodel->skinheight;
|
||||
m_pAliasHeader->numtris = pinmodel->numtris;
|
||||
mod->numframes = m_pAliasHeader->numframes = pinmodel->numframes;
|
||||
m_pAliasHeader->size = pinmodel->size;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
m_pAliasHeader->scale[i] = pinmodel->scale[i];
|
||||
m_pAliasHeader->scale_origin[i] = pinmodel->scale_origin[i];
|
||||
m_pAliasHeader->eyeposition[i] = pinmodel->eyeposition[i];
|
||||
}
|
||||
|
||||
// load the skins
|
||||
pskintype = (const daliasskintype_t *)&pinmodel[1];
|
||||
pskintype = Mod_LoadAllSkins( mod, m_pAliasHeader->numskins, pskintype, m_pAliasHeader );
|
||||
// will be done at renderer side...
|
||||
|
||||
// load base s and t vertices
|
||||
pinstverts = (const stvert_t *)pskintype;
|
||||
// will be done at renderer side...
|
||||
|
||||
// load triangle lists
|
||||
pintriangles = (const dtriangle_t *)&pinstverts[m_pAliasHeader->numverts];
|
||||
// will be done at renderer side
|
||||
|
||||
// load the frames
|
||||
pframetype = (const daliasframetype_t *)&pintriangles[m_pAliasHeader->numtris];
|
||||
m_pAliasHeader->pposeverts = g_poseverts; // store the pointer to be accessed by renderer
|
||||
g_posenum = 0;
|
||||
|
||||
for( i = 0; i < m_pAliasHeader->numframes; i++ )
|
||||
{
|
||||
aliasframetype_t frametype = pframetype->type;
|
||||
|
||||
if( frametype == ALIAS_SINGLE )
|
||||
pframetype = (const daliasframetype_t *)Mod_LoadAliasFrame((const daliasframe_t *)&pframetype[1], &m_pAliasHeader->frames[i], m_pAliasHeader );
|
||||
else pframetype = (const daliasframetype_t *)Mod_LoadAliasGroup(( const daliasgroup_t *)&pframetype[1], &m_pAliasHeader->frames[i], m_pAliasHeader );
|
||||
}
|
||||
|
||||
m_pAliasHeader->numposes = g_posenum;
|
||||
Mod_CalcAliasBounds( mod, m_pAliasHeader );
|
||||
mod->type = mod_alias;
|
||||
|
||||
if( loaded ) *loaded = true; // done
|
||||
}
|
||||
@@ -74,7 +74,7 @@ typedef struct winding_s
|
||||
struct winding_s *pair;
|
||||
hullnode_t chain;
|
||||
int numpoints;
|
||||
vec3_t p[4]; // variable sized
|
||||
vec3_t p[]; // variable sized
|
||||
} winding_t;
|
||||
|
||||
typedef struct
|
||||
@@ -149,6 +149,11 @@ qboolean Mod_ValidateCRC( const char *name, CRC32_t crc );
|
||||
void Mod_NeedCRC( const char *name, qboolean needCRC );
|
||||
void Mod_FreeUnused( void );
|
||||
|
||||
//
|
||||
// mod_alias.c
|
||||
//
|
||||
void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *loaded );
|
||||
|
||||
//
|
||||
// mod_bmodel.c
|
||||
//
|
||||
@@ -194,7 +199,7 @@ void Mod_ClearStudioCache( void );
|
||||
//
|
||||
// mod_sprite.c
|
||||
//
|
||||
void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, uint texFlags );
|
||||
void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded );
|
||||
#endif
|
||||
|
||||
#endif//MOD_LOCAL_H
|
||||
|
||||
@@ -30,7 +30,7 @@ Mod_LoadSpriteModel
|
||||
load sprite model
|
||||
====================
|
||||
*/
|
||||
void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, uint texFlags )
|
||||
void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded )
|
||||
{
|
||||
dsprite_q1_t *pinq1;
|
||||
dsprite_hl_t *pinhl;
|
||||
|
||||
@@ -300,17 +300,15 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
|
||||
Mod_LoadStudioModel( mod, buf, &loaded );
|
||||
break;
|
||||
case IDSPRITEHEADER:
|
||||
Mod_LoadSpriteModel( mod, buf, &loaded, 0 );
|
||||
Mod_LoadSpriteModel( mod, buf, &loaded );
|
||||
break;
|
||||
case IDALIASHEADER:
|
||||
// REFTODO: move server-related code here
|
||||
loaded = true;
|
||||
Mod_LoadAliasModel( mod, buf, &loaded );
|
||||
break;
|
||||
case Q1BSP_VERSION:
|
||||
case HLBSP_VERSION:
|
||||
case QBSP2_VERSION:
|
||||
Mod_LoadBrushModel( mod, buf, &loaded );
|
||||
// ref.dllFuncs.Mod_LoadModel( mod_brush, mod, buf, &loaded, 0 );
|
||||
break;
|
||||
default:
|
||||
Mem_Free( buf );
|
||||
@@ -318,6 +316,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
|
||||
else Con_Printf( S_ERROR "%s has unknown format\n", tempname );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( loaded )
|
||||
{
|
||||
if( world.loading )
|
||||
@@ -339,6 +338,13 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
|
||||
#endif
|
||||
}
|
||||
|
||||
if( mod->type == mod_alias )
|
||||
{
|
||||
aliashdr_t *hdr = mod->cache.data;
|
||||
if( hdr ) // clean up temporary pointer after passing the alias model to the renderer
|
||||
hdr->pposeverts = NULL;
|
||||
}
|
||||
|
||||
if( !loaded )
|
||||
{
|
||||
Mod_FreeModel( mod );
|
||||
|
||||
@@ -395,15 +395,11 @@ qboolean MSG_WriteBytes( sizebuf_t *sb, const void *pBuf, int nBytes )
|
||||
|
||||
qboolean MSG_WriteString( sizebuf_t *sb, const char *pStr )
|
||||
{
|
||||
if( pStr )
|
||||
{
|
||||
do
|
||||
{
|
||||
MSG_WriteChar( sb, (signed char)*pStr );
|
||||
pStr++;
|
||||
} while( *( pStr - 1 ));
|
||||
}
|
||||
else MSG_WriteChar( sb, 0 );
|
||||
int len = Q_strlen( pStr );
|
||||
|
||||
if( len )
|
||||
MSG_WriteBytes( sb, pStr, len + 1 );
|
||||
else MSG_WriteByte( sb, 0 );
|
||||
|
||||
return !sb->bOverflow;
|
||||
}
|
||||
@@ -411,13 +407,22 @@ qboolean MSG_WriteString( sizebuf_t *sb, const char *pStr )
|
||||
qboolean MSG_WriteStringf( sizebuf_t *sb, const char *format, ... )
|
||||
{
|
||||
va_list va;
|
||||
int len;
|
||||
char buf[MAX_VA_STRING];
|
||||
|
||||
va_start( va, format );
|
||||
Q_vsnprintf( buf, sizeof( buf ), format, va );
|
||||
len = Q_vsnprintf( buf, sizeof( buf ), format, va );
|
||||
va_end( va );
|
||||
|
||||
return MSG_WriteString( sb, buf );
|
||||
if( len < 0 )
|
||||
{
|
||||
Host_Error( "%s: snprintf overflow!\n", __func__ );
|
||||
return false;
|
||||
}
|
||||
|
||||
MSG_WriteBytes( sb, buf, len + 1 );
|
||||
|
||||
return !sb->bOverflow;
|
||||
}
|
||||
|
||||
int MSG_ReadOneBit( sizebuf_t *sb )
|
||||
@@ -629,9 +634,7 @@ float MSG_ReadFloat( sizebuf_t *sb )
|
||||
{
|
||||
float ret;
|
||||
|
||||
Assert( sizeof( ret ) == 4 );
|
||||
|
||||
MSG_ReadBits( sb, &ret, 32 );
|
||||
MSG_ReadBits( sb, &ret, sizeof( ret ) << 3 );
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -694,3 +697,160 @@ void MSG_ExciseBits( sizebuf_t *sb, int startbit, int bitstoremove )
|
||||
MSG_SeekToBit( sb, startbit, SEEK_SET );
|
||||
sb->nDataBits -= bitstoremove;
|
||||
}
|
||||
|
||||
#ifdef XASH_ENGINE_TESTS
|
||||
#include "tests.h"
|
||||
|
||||
static const void *g_testbuf = "asdf\xba\xa1\xba\xa1\xed\xc8\x15\x7a";
|
||||
static const size_t g_testbuf_bits = (( 4 + 4 + 2 + 1 ) << 3 ) + 4;
|
||||
|
||||
static void Test_Buffer_BitByte( void )
|
||||
{
|
||||
TASSERT_EQi( BitByte( 0 ), 0 );
|
||||
TASSERT_EQi( BitByte( 1 ), 1 );
|
||||
TASSERT_EQi( BitByte( 8 ), 1 );
|
||||
TASSERT_EQi( BitByte( 9 ), 2 );
|
||||
}
|
||||
|
||||
static void Test_Buffer_Write( void )
|
||||
{
|
||||
sizebuf_t sb;
|
||||
char testdata[0x100] = { 0 };
|
||||
|
||||
MSG_Init( &sb, __func__, testdata, sizeof( testdata ));
|
||||
TASSERT_EQi( sb.iCurBit, 0 );
|
||||
TASSERT_EQi( sb.nDataBits, sizeof( testdata ) << 3 );
|
||||
TASSERT_EQi( sb.pData, testdata );
|
||||
TASSERT_EQi( sb.bOverflow, false );
|
||||
|
||||
MSG_WriteBytes( &sb, "asdf", 4 );
|
||||
TASSERT_EQi( sb.bOverflow, false );
|
||||
TASSERT_EQi( sb.iCurBit, 32 );
|
||||
|
||||
MSG_WriteDword( &sb, 0xa1baa1ba );
|
||||
TASSERT_EQi( sb.bOverflow, false );
|
||||
TASSERT_EQi( sb.iCurBit, 64 );
|
||||
|
||||
MSG_WriteShort( &sb, -0x3713 );
|
||||
TASSERT_EQi( sb.bOverflow, false );
|
||||
TASSERT_EQi( sb.iCurBit, 80 );
|
||||
|
||||
MSG_WriteOneBit( &sb, 1 );
|
||||
TASSERT_EQi( sb.bOverflow, false );
|
||||
TASSERT_EQi( sb.iCurBit, 81 );
|
||||
|
||||
MSG_WriteOneBit( &sb, 0 );
|
||||
TASSERT_EQi( sb.bOverflow, false );
|
||||
TASSERT_EQi( sb.iCurBit, 82 );
|
||||
|
||||
MSG_WriteOneBit( &sb, 1 );
|
||||
TASSERT_EQi( sb.bOverflow, false );
|
||||
TASSERT_EQi( sb.iCurBit, 83 );
|
||||
|
||||
MSG_WriteOneBit( &sb, 0 );
|
||||
TASSERT_EQi( sb.bOverflow, false );
|
||||
TASSERT_EQi( sb.iCurBit, 84 );
|
||||
|
||||
MSG_WriteByte( &sb, 0xa1 );
|
||||
TASSERT_EQi( sb.bOverflow, false );
|
||||
TASSERT_EQi( sb.iCurBit, 92 );
|
||||
|
||||
TASSERT_EQi( MSG_GetNumBitsWritten( &sb ), g_testbuf_bits );
|
||||
TASSERT_EQi( MSG_GetNumBytesWritten( &sb ), BitByte( g_testbuf_bits ));
|
||||
TASSERT_EQi( MSG_GetRealBytesWritten( &sb ), g_testbuf_bits >> 3 );
|
||||
|
||||
// if tests fails here on big endian, it's possible due to endian issues
|
||||
TASSERT( !memcmp( sb.pData, g_testbuf, g_testbuf_bits >> 3 ));
|
||||
|
||||
// must check last 4 bits separately because we never care about uninitialized bits
|
||||
MSG_SeekToBit( &sb, g_testbuf_bits & ~7, SEEK_SET );
|
||||
TASSERT_EQi( sb.iCurBit, 88 );
|
||||
TASSERT_EQi( MSG_ReadUBitLong( &sb, 4 ), 0xa );
|
||||
}
|
||||
|
||||
static void Test_Buffer_Read( void )
|
||||
{
|
||||
sizebuf_t sb;
|
||||
char buf[4];
|
||||
|
||||
MSG_StartReading( &sb, (void *)g_testbuf, -1, 0, g_testbuf_bits );
|
||||
TASSERT_EQi( sb.iCurBit, 0 );
|
||||
TASSERT_EQi( sb.nDataBits, g_testbuf_bits );
|
||||
TASSERT_EQi( sb.pData, g_testbuf );
|
||||
TASSERT_EQi( sb.bOverflow, false );
|
||||
|
||||
MSG_ReadBytes( &sb, buf, 4 );
|
||||
TASSERT( !memcmp( buf, "asdf", 4 ));
|
||||
TASSERT_EQi( sb.iCurBit, 32 );
|
||||
TASSERT_EQi( sb.bOverflow, false );
|
||||
|
||||
TASSERT_EQi( MSG_ReadWord( &sb ), 0xa1ba );
|
||||
TASSERT_EQi( sb.iCurBit, 48 );
|
||||
TASSERT_EQi( sb.bOverflow, false );
|
||||
|
||||
TASSERT_EQi( MSG_ReadDword( &sb ), 0xc8eda1baU );
|
||||
TASSERT_EQi( sb.iCurBit, 80 );
|
||||
TASSERT_EQi( sb.bOverflow, false );
|
||||
|
||||
TASSERT_EQi( MSG_ReadOneBit( &sb ), 1 );
|
||||
TASSERT_EQi( sb.iCurBit, 81 );
|
||||
TASSERT_EQi( sb.bOverflow, false );
|
||||
|
||||
TASSERT_EQi( MSG_ReadOneBit( &sb ), 0 );
|
||||
TASSERT_EQi( sb.iCurBit, 82 );
|
||||
TASSERT_EQi( sb.bOverflow, false );
|
||||
|
||||
TASSERT_EQi( MSG_ReadOneBit( &sb ), 1 );
|
||||
TASSERT_EQi( sb.iCurBit, 83 );
|
||||
TASSERT_EQi( sb.bOverflow, false );
|
||||
|
||||
TASSERT_EQi( MSG_ReadOneBit( &sb ), 0 );
|
||||
TASSERT_EQi( sb.iCurBit, 84 );
|
||||
TASSERT_EQi( sb.bOverflow, false );
|
||||
|
||||
TASSERT_EQi( MSG_ReadByte( &sb ), 0xa1 );
|
||||
TASSERT_EQi( sb.iCurBit, 92 );
|
||||
TASSERT_EQi( sb.bOverflow, false );
|
||||
|
||||
TASSERT_EQi( MSG_Overflow( &sb, 1 ), true );
|
||||
TASSERT_EQi( sb.bOverflow, true );
|
||||
}
|
||||
|
||||
static void Test_Buffer_ExciseBits( void )
|
||||
{
|
||||
sizebuf_t sb;
|
||||
char testdata[0x100];
|
||||
|
||||
memcpy( testdata, g_testbuf, BitByte( g_testbuf_bits ));
|
||||
|
||||
MSG_StartWriting( &sb, testdata, 0, 0, g_testbuf_bits );
|
||||
MSG_ExciseBits( &sb, 8, 28 );
|
||||
|
||||
TASSERT_EQi( MSG_CheckOverflow( &sb ), false );
|
||||
TASSERT_EQi( MSG_GetMaxBits( &sb ), 64 );
|
||||
TASSERT( !memcmp( MSG_GetData( &sb ), "a\x1b\xaa\x1b\xda\x8e\x5c\xa1", 8 ));
|
||||
|
||||
memcpy( testdata, g_testbuf, BitByte( g_testbuf_bits ));
|
||||
|
||||
MSG_StartWriting( &sb, testdata, 0, 0, g_testbuf_bits );
|
||||
MSG_ExciseBits( &sb, 16, 32 );
|
||||
|
||||
TASSERT_EQi( MSG_CheckOverflow( &sb ), false );
|
||||
TASSERT_EQi( MSG_GetMaxBits( &sb ), g_testbuf_bits - 32 );
|
||||
TASSERT( !memcmp( MSG_GetData( &sb ), "as\xba\xa1\xed\xc8\x15", 7 ));
|
||||
|
||||
MSG_SeekToBit( &sb, 7 << 3, SEEK_SET );
|
||||
TASSERT_EQi( MSG_ReadUBitLong( &sb, 4 ), 0xa );
|
||||
}
|
||||
|
||||
void Test_RunBuffer( void )
|
||||
{
|
||||
MSG_InitMasks();
|
||||
|
||||
TRUN( Test_Buffer_BitByte( ));
|
||||
TRUN( Test_Buffer_Write( ));
|
||||
TRUN( Test_Buffer_Read( ));
|
||||
TRUN( Test_Buffer_ExciseBits( ));
|
||||
}
|
||||
|
||||
#endif // XASH_ENGINE_TESTS
|
||||
|
||||
@@ -379,7 +379,6 @@ static void Netchan_ClearFragbufs( fragbuf_t **ppbuf )
|
||||
while( buf )
|
||||
{
|
||||
n = buf->next;
|
||||
Mem_Free( buf->frag_message_buf );
|
||||
Mem_Free( buf );
|
||||
buf = n;
|
||||
}
|
||||
@@ -458,22 +457,21 @@ Netchan_OutOfBand
|
||||
Sends an out-of-band datagram
|
||||
================
|
||||
*/
|
||||
void Netchan_OutOfBand( int net_socket, netadr_t adr, int length, byte *data )
|
||||
void Netchan_OutOfBand( int net_socket, netadr_t adr, int len, byte *data )
|
||||
{
|
||||
byte send_buf[MAX_PRINT_MSG];
|
||||
sizebuf_t send;
|
||||
byte buf[MAX_PRINT_MSG + 4] = { 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
// write the packet header
|
||||
MSG_Init( &send, "SequencePacket", send_buf, sizeof( send_buf ));
|
||||
if( CL_IsPlaybackDemo( ))
|
||||
return;
|
||||
|
||||
MSG_WriteLong( &send, NET_HEADER_OUTOFBANDPACKET ); // -1 sequence means out of band
|
||||
MSG_WriteBytes( &send, data, length );
|
||||
|
||||
if( !CL_IsPlaybackDemo( ))
|
||||
if( len > sizeof( buf ) - 4 )
|
||||
{
|
||||
// send the datagram
|
||||
NET_SendPacket( net_socket, MSG_GetNumBytesWritten( &send ), MSG_GetData( &send ), adr );
|
||||
Host_Error( "%s: overflow!\n", __func__ );
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy( &buf[4], data, len );
|
||||
NET_SendPacket( net_socket, len + 4, buf, adr );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -483,16 +481,26 @@ Netchan_OutOfBandPrint
|
||||
Sends a text message in an out-of-band datagram
|
||||
================
|
||||
*/
|
||||
void Netchan_OutOfBandPrint( int net_socket, netadr_t adr, const char *format, ... )
|
||||
void Netchan_OutOfBandPrint( int net_socket, netadr_t adr, const char *fmt, ... )
|
||||
{
|
||||
char string[MAX_PRINT_MSG];
|
||||
va_list argptr;
|
||||
va_list va;
|
||||
byte buf[MAX_PRINT_MSG + 4] = { 0xff, 0xff, 0xff, 0xff };
|
||||
int len;
|
||||
|
||||
va_start( argptr, format );
|
||||
Q_vsnprintf( string, sizeof( string ) - 1, format, argptr );
|
||||
va_end( argptr );
|
||||
if( CL_IsPlaybackDemo( ))
|
||||
return;
|
||||
|
||||
Netchan_OutOfBand( net_socket, adr, Q_strlen( string ), (byte *)string );
|
||||
va_start( va, fmt );
|
||||
len = Q_vsnprintf( &buf[4], sizeof( buf ) - 4, fmt, va );
|
||||
va_end( va );
|
||||
|
||||
if( len < 0 )
|
||||
{
|
||||
Host_Error( "%s: snprintf overflow!\n", __func__ );
|
||||
return;
|
||||
}
|
||||
|
||||
NET_SendPacket( net_socket, len + 4, buf, adr );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -505,8 +513,7 @@ static fragbuf_t *Netchan_AllocFragbuf( int fragment_size )
|
||||
{
|
||||
fragbuf_t *buf;
|
||||
|
||||
buf = (fragbuf_t *)Mem_Calloc( net_mempool, sizeof( fragbuf_t ));
|
||||
buf->frag_message_buf = (byte *)Mem_Calloc( net_mempool, fragment_size );
|
||||
buf = (fragbuf_t *)Mem_Calloc( net_mempool, sizeof( fragbuf_t ) + fragment_size );
|
||||
MSG_Init( &buf->frag_message, "Frag Message", buf->frag_message_buf, fragment_size );
|
||||
|
||||
return buf;
|
||||
@@ -520,7 +527,7 @@ Netchan_AddFragbufToTail
|
||||
*/
|
||||
static void Netchan_AddFragbufToTail( fragbufwaiting_t *wait, fragbuf_t *buf )
|
||||
{
|
||||
fragbuf_t *p;
|
||||
fragbuf_t *p;
|
||||
|
||||
buf->next = NULL;
|
||||
wait->fragbufcount++;
|
||||
@@ -1168,7 +1175,7 @@ qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg )
|
||||
if( filename[0] != '!' )
|
||||
{
|
||||
string temp_filename;
|
||||
Q_snprintf( temp_filename, sizeof( temp_filename ), "downloaded/%s", filename );
|
||||
Q_snprintf( temp_filename, sizeof( temp_filename ), DEFAULT_DOWNLOADED_DIRECTORY "%s", filename );
|
||||
Q_strncpy( filename, temp_filename, sizeof( filename ));
|
||||
}
|
||||
|
||||
|
||||
@@ -1209,7 +1209,7 @@ static void NET_AddToLagged( netsrc_t sock, packetlag_t *list, packetlag_t *pack
|
||||
packet->data = pStart;
|
||||
packet->size = length;
|
||||
packet->receivedtime = timestamp;
|
||||
memcpy( &packet->from, from, sizeof( netadr_t ));
|
||||
packet->from = *from;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1321,7 +1321,7 @@ static qboolean NET_LagPacket( qboolean newdata, netsrc_t sock, netadr_t *from,
|
||||
|
||||
// delivery packet from fake lag queue
|
||||
memcpy( data, pPacket->data, pPacket->size );
|
||||
memcpy( &net_from, &pPacket->from, sizeof( netadr_t ));
|
||||
net_from = pPacket->from;
|
||||
*length = pPacket->size;
|
||||
|
||||
if( pPacket->data )
|
||||
@@ -2282,7 +2282,7 @@ static void HTTP_FreeFile( httpfile_t *file, qboolean error )
|
||||
|
||||
file->socket = -1;
|
||||
|
||||
Q_snprintf( incname, 256, "downloaded/%s.incomplete", file->path );
|
||||
Q_snprintf( incname, sizeof( incname ), DEFAULT_DOWNLOADED_DIRECTORY "%s.incomplete", file->path );
|
||||
if( error )
|
||||
{
|
||||
// Switch to next fastdl server if present
|
||||
@@ -2308,7 +2308,7 @@ static void HTTP_FreeFile( httpfile_t *file, qboolean error )
|
||||
// Success, rename and process file
|
||||
char name[256];
|
||||
|
||||
Q_snprintf( name, 256, "downloaded/%s", file->path );
|
||||
Q_snprintf( name, sizeof( name ), DEFAULT_DOWNLOADED_DIRECTORY "%s", file->path );
|
||||
FS_Rename( incname, name );
|
||||
|
||||
if( file->process )
|
||||
@@ -2527,7 +2527,7 @@ void HTTP_Run( void )
|
||||
}
|
||||
|
||||
Con_Reportf( "HTTP: Starting download %s from %s\n", curfile->path, curfile->server->host );
|
||||
Q_snprintf( name, sizeof( name ), "downloaded/%s.incomplete", curfile->path );
|
||||
Q_snprintf( name, sizeof( name ), DEFAULT_DOWNLOADED_DIRECTORY "%s.incomplete", curfile->path );
|
||||
|
||||
curfile->file = FS_Open( name, "wb", true );
|
||||
|
||||
|
||||
@@ -184,13 +184,13 @@ typedef struct fragbuf_s
|
||||
struct fragbuf_s *next; // next buffer in chain
|
||||
int bufferid; // id of this buffer
|
||||
sizebuf_t frag_message; // message buffer where raw data is stored
|
||||
byte *frag_message_buf; // the actual data sits here
|
||||
qboolean isfile; // is this a file buffer?
|
||||
qboolean isbuffer; // is this file buffer from memory ( custom decal, etc. ).
|
||||
qboolean iscompressed; // is compressed file, we should using filename.ztmp
|
||||
char filename[MAX_OSPATH]; // name of the file to save out on remote host
|
||||
int foffset; // offset in file from which to read data
|
||||
int size; // size of data to read at that offset
|
||||
byte frag_message_buf[]; // the actual data sits here (flexible)
|
||||
} fragbuf_t;
|
||||
|
||||
// Waiting list of fragbuf chains
|
||||
|
||||
@@ -186,7 +186,7 @@ hull_t *PM_HullForBsp( physent_t *pe, playermove_t *pmove, float *offset )
|
||||
Assert( hull != NULL );
|
||||
|
||||
// calculate an offset value to center the origin
|
||||
VectorSubtract( hull->clip_mins, pmove->player_mins[pmove->usehull], offset );
|
||||
VectorSubtract( hull->clip_mins, host.player_mins[pmove->usehull], offset );
|
||||
VectorAdd( offset, pe->origin, offset );
|
||||
|
||||
return hull;
|
||||
@@ -203,7 +203,7 @@ static hull_t *PM_HullForStudio( physent_t *pe, playermove_t *pmove, int *numhit
|
||||
{
|
||||
vec3_t size;
|
||||
|
||||
VectorSubtract( pmove->player_maxs[pmove->usehull], pmove->player_mins[pmove->usehull], size );
|
||||
VectorSubtract( host.player_maxs[pmove->usehull], host.player_mins[pmove->usehull], size );
|
||||
VectorScale( size, 0.5f, size );
|
||||
|
||||
return Mod_HullForStudio( pe->studiomodel, pe->frame, pe->sequence, pe->angles, pe->origin, size, pe->controller, pe->blending, numhitboxes, NULL );
|
||||
@@ -379,8 +379,8 @@ pmtrace_t PM_PlayerTraceExt( playermove_t *pmove, vec3_t start, vec3_t end, int
|
||||
|
||||
if( pe->solid == SOLID_CUSTOM )
|
||||
{
|
||||
VectorCopy( pmove->player_mins[pmove->usehull], mins );
|
||||
VectorCopy( pmove->player_maxs[pmove->usehull], maxs );
|
||||
VectorCopy( host.player_mins[pmove->usehull], mins );
|
||||
VectorCopy( host.player_maxs[pmove->usehull], maxs );
|
||||
VectorClear( offset );
|
||||
}
|
||||
else if( pe->model )
|
||||
@@ -401,8 +401,8 @@ pmtrace_t PM_PlayerTraceExt( playermove_t *pmove, vec3_t start, vec3_t end, int
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorSubtract( pe->mins, pmove->player_maxs[pmove->usehull], mins );
|
||||
VectorSubtract( pe->maxs, pmove->player_mins[pmove->usehull], maxs );
|
||||
VectorSubtract( pe->mins, host.player_maxs[pmove->usehull], mins );
|
||||
VectorSubtract( pe->maxs, host.player_mins[pmove->usehull], maxs );
|
||||
|
||||
hull = PM_HullForBox( mins, maxs );
|
||||
VectorCopy( pe->origin, offset );
|
||||
@@ -410,8 +410,8 @@ pmtrace_t PM_PlayerTraceExt( playermove_t *pmove, vec3_t start, vec3_t end, int
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorSubtract( pe->mins, pmove->player_maxs[pmove->usehull], mins );
|
||||
VectorSubtract( pe->maxs, pmove->player_mins[pmove->usehull], maxs );
|
||||
VectorSubtract( pe->mins, host.player_maxs[pmove->usehull], mins );
|
||||
VectorSubtract( pe->maxs, host.player_mins[pmove->usehull], maxs );
|
||||
|
||||
hull = PM_HullForBox( mins, maxs );
|
||||
VectorCopy( pe->origin, offset );
|
||||
@@ -442,7 +442,7 @@ pmtrace_t PM_PlayerTraceExt( playermove_t *pmove, vec3_t start, vec3_t end, int
|
||||
|
||||
if( transform_bbox )
|
||||
{
|
||||
World_TransformAABB( matrix, pmove->player_mins[pmove->usehull], pmove->player_maxs[pmove->usehull], mins, maxs );
|
||||
World_TransformAABB( matrix, host.player_mins[pmove->usehull], host.player_maxs[pmove->usehull], mins, maxs );
|
||||
VectorSubtract( hull->clip_mins, mins, offset ); // calc new local offset
|
||||
|
||||
for( j = 0; j < 3; j++ )
|
||||
@@ -569,8 +569,8 @@ int PM_TestPlayerPosition( playermove_t *pmove, vec3_t pos, pmtrace_t *ptrace, p
|
||||
|
||||
if( pe->solid == SOLID_CUSTOM )
|
||||
{
|
||||
VectorCopy( pmove->player_mins[pmove->usehull], mins );
|
||||
VectorCopy( pmove->player_maxs[pmove->usehull], maxs );
|
||||
VectorCopy( host.player_mins[pmove->usehull], mins );
|
||||
VectorCopy( host.player_maxs[pmove->usehull], maxs );
|
||||
VectorClear( offset );
|
||||
}
|
||||
else if( pe->model )
|
||||
@@ -584,8 +584,8 @@ int PM_TestPlayerPosition( playermove_t *pmove, vec3_t pos, pmtrace_t *ptrace, p
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorSubtract( pe->mins, pmove->player_maxs[pmove->usehull], mins );
|
||||
VectorSubtract( pe->maxs, pmove->player_mins[pmove->usehull], maxs );
|
||||
VectorSubtract( pe->mins, host.player_maxs[pmove->usehull], mins );
|
||||
VectorSubtract( pe->maxs, host.player_mins[pmove->usehull], maxs );
|
||||
|
||||
hull = PM_HullForBox( mins, maxs );
|
||||
VectorCopy( pe->origin, offset );
|
||||
@@ -611,7 +611,7 @@ int PM_TestPlayerPosition( playermove_t *pmove, vec3_t pos, pmtrace_t *ptrace, p
|
||||
|
||||
if( transform_bbox )
|
||||
{
|
||||
World_TransformAABB( matrix, pmove->player_mins[pmove->usehull], pmove->player_maxs[pmove->usehull], mins, maxs );
|
||||
World_TransformAABB( matrix, host.player_mins[pmove->usehull], host.player_maxs[pmove->usehull], mins, maxs );
|
||||
VectorSubtract( hull->clip_mins, mins, offset ); // calc new local offset
|
||||
|
||||
for( j = 0; j < 3; j++ )
|
||||
|
||||
@@ -90,8 +90,8 @@ static byte *Sound_Copy( size_t size )
|
||||
{
|
||||
byte *out;
|
||||
|
||||
out = Mem_Malloc( host.soundpool, size );
|
||||
memcpy( out, sound.tempbuffer, size );
|
||||
out = Mem_Realloc( host.soundpool, sound.tempbuffer, size );
|
||||
sound.tempbuffer = NULL;
|
||||
|
||||
return out;
|
||||
}
|
||||
@@ -133,346 +133,275 @@ uint GAME_EXPORT Sound_GetApproxWavePlayLen( const char *filepath )
|
||||
return msecs;
|
||||
}
|
||||
|
||||
static qboolean Sound_ConvertNoResample( wavdata_t *sc, int inwidth, int outwidth, int outcount )
|
||||
#define SOUND_FORMATCONVERT_BOILERPLATE( resamplemacro ) \
|
||||
if( inwidth == 1 ) \
|
||||
{ \
|
||||
const int8_t *data = (const int8_t *)sc->buffer; \
|
||||
if( outwidth == 1 ) \
|
||||
{ \
|
||||
int8_t *outdata = (int8_t *)sound.tempbuffer; \
|
||||
resamplemacro( 1 ) \
|
||||
} \
|
||||
else if( outwidth == 2 ) \
|
||||
{ \
|
||||
int16_t *outdata = (int16_t *)sound.tempbuffer; \
|
||||
resamplemacro( 256 ) \
|
||||
} \
|
||||
else \
|
||||
return false; \
|
||||
} \
|
||||
else if( inwidth == 2 ) \
|
||||
{ \
|
||||
const int16_t *data = (const int16_t *)sc->buffer; \
|
||||
if( outwidth == 1 ) \
|
||||
{ \
|
||||
int8_t *outdata = (int8_t *)sound.tempbuffer; \
|
||||
resamplemacro( 1 / 256.0 ) \
|
||||
} \
|
||||
else if( outwidth == 2 ) \
|
||||
{ \
|
||||
int16_t *outdata = (int16_t *)sound.tempbuffer; \
|
||||
resamplemacro( 1 ) \
|
||||
} \
|
||||
else \
|
||||
return false; \
|
||||
} \
|
||||
else \
|
||||
return false; \
|
||||
|
||||
|
||||
#define SOUND_CONVERTNORESAMPLE_BOILERPLATE( multiplier ) \
|
||||
if( inchannels == 1 ) \
|
||||
{ \
|
||||
if( outchannels == 1 ) \
|
||||
{ \
|
||||
for( i = 0; i < outcount * outchannels; i++ ) \
|
||||
outdata[i] = data[i] * ( multiplier ); \
|
||||
} \
|
||||
else if( outchannels == 2 ) \
|
||||
{ \
|
||||
for( i = 0; i < outcount; i++ ) \
|
||||
{ \
|
||||
outdata[i * 2 + 0] = data[i] * ( multiplier ); \
|
||||
outdata[i * 2 + 1] = data[i] * ( multiplier ); \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
return false; \
|
||||
} \
|
||||
else if( inchannels == 2 ) \
|
||||
{ \
|
||||
if( outchannels == 1 ) \
|
||||
{ \
|
||||
for( i = 0; i < outcount; i++ ) \
|
||||
outdata[i] = ( data[i * 2 + 0] + data[i * 2 + 1] ) * ( multiplier ) / 2; \
|
||||
} \
|
||||
else if( outchannels == 2 ) \
|
||||
{ \
|
||||
for( i = 0; i < outcount * outchannels; i++ ) \
|
||||
outdata[i] = data[i] * ( multiplier ); \
|
||||
} \
|
||||
else \
|
||||
return false; \
|
||||
} \
|
||||
else \
|
||||
return false; \
|
||||
|
||||
#define SOUND_CONVERTDOWNSAMPLE_BOILERPLATE( multiplier ) \
|
||||
if( inchannels == 1 ) \
|
||||
{ \
|
||||
if( outchannels == 1 ) \
|
||||
{ \
|
||||
for( i = 0; i < outcount; i++ ) \
|
||||
{ \
|
||||
double j = stepscale * i; \
|
||||
outdata[i] = data[(int)j] * ( multiplier ); \
|
||||
} \
|
||||
} \
|
||||
else if( outchannels == 2 ) \
|
||||
{ \
|
||||
for( i = 0; i < outcount; i++ ) \
|
||||
{ \
|
||||
double j = stepscale * i;\
|
||||
outdata[i * 2 + 0] = data[(int)j] * ( multiplier ); \
|
||||
outdata[i * 2 + 1] = data[(int)j] * ( multiplier ); \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
return false; \
|
||||
} \
|
||||
else if( inchannels == 2 ) \
|
||||
{ \
|
||||
if( outchannels == 1 ) \
|
||||
{ \
|
||||
for( i = 0; i < outcount; i++ ) \
|
||||
{ \
|
||||
double j = stepscale * i; \
|
||||
outdata[i] = ( data[((int)j) * 2 + 0] + data[((int)j) * 2 + 1] ) * ( multiplier ) / 2; \
|
||||
} \
|
||||
} \
|
||||
else if( outchannels == 2 ) \
|
||||
{ \
|
||||
for( i = 0; i < outcount; i++ ) \
|
||||
{ \
|
||||
double j = stepscale * i; \
|
||||
outdata[i * 2 + 0] = data[((int)j) * 2 + 0] * ( multiplier ); \
|
||||
outdata[i * 2 + 1] = data[((int)j) * 2 + 1] * ( multiplier ); \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
return false; \
|
||||
} \
|
||||
else \
|
||||
return false; \
|
||||
|
||||
|
||||
#define SOUND_CONVERTUPSAMPLE_BOILERPLATE( multiplier ) \
|
||||
if( inchannels == 1 ) \
|
||||
{ \
|
||||
if( outchannels == 1 ) \
|
||||
{ \
|
||||
for( i = 0; i < outcount; i++ ) \
|
||||
{ \
|
||||
double j = stepscale * i; \
|
||||
outdata[i] = data[(int)j] * ( multiplier ); \
|
||||
if( j != (int)j && j < incount ) \
|
||||
{ \
|
||||
double frac = ( j - (int)j ) * ( multiplier ); \
|
||||
outdata[i] += (data[(int)j+1] - data[(int)j]) * frac; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
else if( outchannels == 2 ) \
|
||||
{ \
|
||||
for( i = 0; i < outcount; i++ ) \
|
||||
{ \
|
||||
double j = stepscale * i; \
|
||||
outdata[i * 2 + 0] = data[(int)j] * ( multiplier ); \
|
||||
if( j != (int)j && j < incount ) \
|
||||
{ \
|
||||
double frac = ( j - (int)j ) * ( multiplier ); \
|
||||
outdata[i * 2 + 0] += (data[(int)j+1] - data[(int)j]) * frac; \
|
||||
} \
|
||||
outdata[i * 2 + 1] = outdata[i * 2 + 0]; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
return false; \
|
||||
} \
|
||||
else if( inchannels == 2 ) \
|
||||
{ \
|
||||
if( outchannels == 1 ) \
|
||||
{ \
|
||||
for( i = 0; i < outcount; i++ ) \
|
||||
{ \
|
||||
double j = stepscale * i; \
|
||||
outdata[i] = ( data[((int)j) * 2 + 0] + data[((int)j) * 2 + 1] ) * ( multiplier ) / 2; \
|
||||
if( j != (int)j && j < incount ) \
|
||||
{ \
|
||||
double frac = ( j - (int)j ) * ( multiplier ) / 2; \
|
||||
outdata[i] += (data[((int)j + 1 ) * 2 + 0] - data[((int)j) * 2 + 0]) * frac; \
|
||||
outdata[i] += (data[((int)j + 1 ) * 2 + 1] - data[((int)j) * 2 + 1]) * frac; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
else if( outchannels == 2 ) \
|
||||
{ \
|
||||
for( i = 0; i < outcount; i++ ) \
|
||||
{ \
|
||||
double j = stepscale * i; \
|
||||
outdata[i*2+0] = data[((int)j)*2+0] * ( multiplier ); \
|
||||
outdata[i*2+1] = data[((int)j)*2+1] * ( multiplier ); \
|
||||
if( j != (int)j && j < incount ) \
|
||||
{ \
|
||||
double frac = ( j - (int)j ) * ( multiplier ); \
|
||||
outdata[i*2+0] += (data[((int)j+1)*2+0] - data[((int)j)*2+0]) * frac; \
|
||||
outdata[i*2+1] += (data[((int)j+1)*2+1] - data[((int)j)*2+1]) * frac; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
return false; \
|
||||
} \
|
||||
else \
|
||||
return false; \
|
||||
|
||||
static qboolean Sound_ConvertNoResample( wavdata_t *sc, int inwidth, int inchannels, int outwidth, int outchannels, int outcount )
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if( inwidth == 1 && outwidth == 2 ) // S8 to S16
|
||||
{
|
||||
for( i = 0; i < outcount * sc->channels; i++ )
|
||||
((int16_t*)sound.tempbuffer)[i] = ((int8_t *)sc->buffer)[i] * 256;
|
||||
return true;
|
||||
}
|
||||
// I could write a generic case here but I also want to make it easier for compiler
|
||||
// to unroll these for-loops
|
||||
|
||||
if( inwidth == 2 && outwidth == 1 ) // S16 to S8
|
||||
{
|
||||
for( i = 0; i < outcount * sc->channels; i++ )
|
||||
((int8_t*)sound.tempbuffer)[i] = ((int16_t *)sc->buffer)[i] / 256;
|
||||
return true;
|
||||
}
|
||||
SOUND_FORMATCONVERT_BOILERPLATE( SOUND_CONVERTNORESAMPLE_BOILERPLATE )
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static qboolean Sound_ConvertDownsample( wavdata_t *sc, int inwidth, int outwidth, int outcount, double stepscale )
|
||||
static qboolean Sound_ConvertDownsample( wavdata_t *sc, int inwidth, int inchannels, int outwidth, int outchannels, int outcount, double stepscale )
|
||||
{
|
||||
size_t i;
|
||||
double j;
|
||||
|
||||
if( inwidth == 1 && outwidth == 1 )
|
||||
{
|
||||
int8_t *data = (int8_t *)sc->buffer;
|
||||
SOUND_FORMATCONVERT_BOILERPLATE( SOUND_CONVERTDOWNSAMPLE_BOILERPLATE )
|
||||
|
||||
if( outwidth == 1 )
|
||||
{
|
||||
int8_t *outdata = (int8_t *)sound.tempbuffer;
|
||||
|
||||
if( sc->channels == 2 )
|
||||
{
|
||||
for( i = 0; i < outcount; i++ )
|
||||
{
|
||||
j = stepscale * i;
|
||||
outdata[i*2+0] = data[((int)j)*2+0];
|
||||
outdata[i*2+1] = data[((int)j)*2+1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = 0; i < outcount; i++ )
|
||||
{
|
||||
j = stepscale * i;
|
||||
outdata[i] = data[(int)j];
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if( outwidth == 2 )
|
||||
{
|
||||
int16_t *outdata = (int16_t *)sound.tempbuffer;
|
||||
|
||||
if( sc->channels == 2 )
|
||||
{
|
||||
for( i = 0; i < outcount; i++ )
|
||||
{
|
||||
j = stepscale * i;
|
||||
outdata[i*2+0] = data[((int)j)*2+0] * 256;
|
||||
outdata[i*2+1] = data[((int)j)*2+1] * 256;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = 0; i < outcount; i++ )
|
||||
{
|
||||
j = stepscale * i;
|
||||
outdata[i] = data[(int)j] * 256;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if( inwidth == 2 )
|
||||
{
|
||||
int16_t *data = (int16_t *)sc->buffer;
|
||||
|
||||
if( outwidth == 1 )
|
||||
{
|
||||
int8_t *outdata = (int8_t *)sound.tempbuffer;
|
||||
|
||||
if( sc->channels == 2 )
|
||||
{
|
||||
for( i = 0; i < outcount; i++ )
|
||||
{
|
||||
j = stepscale * i;
|
||||
outdata[i*2+0] = data[((int)j)*2+0] / 256;
|
||||
outdata[i*2+1] = data[((int)j)*2+1] / 256;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = 0; i < outcount; i++ )
|
||||
{
|
||||
j = stepscale * i;
|
||||
outdata[i] = data[(int)j] / 256;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if( outwidth == 2 )
|
||||
{
|
||||
int16_t *outdata = (int16_t *)sound.tempbuffer;
|
||||
|
||||
if( sc->channels == 2 )
|
||||
{
|
||||
for( i = 0; i < outcount; i++ )
|
||||
{
|
||||
j = stepscale * i;
|
||||
outdata[i*2+0] = data[((int)j)*2+0];
|
||||
outdata[i*2+1] = data[((int)j)*2+1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = 0; i < outcount; i++ )
|
||||
{
|
||||
j = stepscale * i;
|
||||
outdata[i] = data[(int)j];
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static qboolean Sound_ConvertUpsample( wavdata_t *sc, int inwidth, int outwidth, int outcount, int incount, double stepscale )
|
||||
static qboolean Sound_ConvertUpsample( wavdata_t *sc, int inwidth, int inchannels, int incount, int outwidth, int outchannels, int outcount, double stepscale )
|
||||
{
|
||||
size_t i;
|
||||
double j;
|
||||
double frac;
|
||||
|
||||
incount--; // to not go past last sample while interpolating
|
||||
|
||||
if( inwidth == 1 )
|
||||
{
|
||||
int8_t *data = (int8_t *)sc->buffer;
|
||||
SOUND_FORMATCONVERT_BOILERPLATE( SOUND_CONVERTUPSAMPLE_BOILERPLATE )
|
||||
|
||||
if( outwidth == 1 )
|
||||
{
|
||||
int8_t *outdata = (int8_t *)sound.tempbuffer;
|
||||
|
||||
if( sc->channels == 2 )
|
||||
{
|
||||
for( i = 0; i < outcount; i++ )
|
||||
{
|
||||
j = stepscale * i;
|
||||
outdata[i*2+0] = data[((int)j)*2+0];
|
||||
outdata[i*2+1] = data[((int)j)*2+1];
|
||||
if( j != (int)j && j < incount )
|
||||
{
|
||||
frac = j - (int)j;
|
||||
outdata[i*2+0] += (data[((int)j+1)*2+0] - data[((int)j)*2+0]) * frac;
|
||||
outdata[i*2+1] += (data[((int)j+1)*2+1] - data[((int)j)*2+1]) * frac;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = 0; i < outcount; i++ )
|
||||
{
|
||||
j = stepscale * i;
|
||||
outdata[i] = data[(int)j];
|
||||
if( j != (int)j && j < incount )
|
||||
{
|
||||
frac = j - (int)j;
|
||||
outdata[i] += (data[(int)j+1] - data[(int)j]) * frac;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if( outwidth == 2 )
|
||||
{
|
||||
int16_t *outdata = (int16_t *)sound.tempbuffer;
|
||||
|
||||
if( sc->channels == 2 )
|
||||
{
|
||||
for( i = 0; i < outcount; i++ )
|
||||
{
|
||||
j = stepscale * i;
|
||||
outdata[i*2+0] = data[((int)j)*2+0] * 256;
|
||||
outdata[i*2+1] = data[((int)j)*2+1] * 256;
|
||||
if( j != (int)j && j < incount )
|
||||
{
|
||||
frac = ( j - (int)j ) * 256;
|
||||
outdata[i*2+0] += (data[((int)j+1)*2+0] - data[((int)j)*2+0]) * frac;
|
||||
outdata[i*2+1] += (data[((int)j+1)*2+1] - data[((int)j)*2+1]) * frac;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = 0; i < outcount; i++ )
|
||||
{
|
||||
j = stepscale * i;
|
||||
outdata[i] = data[(int)j] * 256;
|
||||
if( j != (int)j && j < incount )
|
||||
{
|
||||
frac = ( j - (int)j ) * 256;
|
||||
outdata[i] += (data[(int)j+1] - data[(int)j]) * frac;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if( inwidth == 2 )
|
||||
{
|
||||
int16_t *data = (int16_t *)sc->buffer;
|
||||
|
||||
if( outwidth == 1 )
|
||||
{
|
||||
int8_t *outdata = (int8_t *)sound.tempbuffer;
|
||||
|
||||
if( sc->channels == 2 )
|
||||
{
|
||||
for( i = 0; i < outcount; i++ )
|
||||
{
|
||||
j = stepscale * i;
|
||||
outdata[i*2+0] = data[((int)j)*2+0] / 256;
|
||||
outdata[i*2+1] = data[((int)j)*2+1] / 256;
|
||||
if( j != (int)j && j < incount )
|
||||
{
|
||||
frac = ( j - (int)j ) / 256;
|
||||
outdata[i*2+0] += (data[((int)j+1)*2+0] - data[((int)j)*2+0]) * frac;
|
||||
outdata[i*2+1] += (data[((int)j+1)*2+1] - data[((int)j)*2+1]) * frac;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = 0; i < outcount; i++ )
|
||||
{
|
||||
j = stepscale * i;
|
||||
outdata[i] = data[(int)j] / 256;
|
||||
if( j != (int)j && j < incount )
|
||||
{
|
||||
frac = ( j - (int)j ) / 256;
|
||||
outdata[i] += (data[(int)j+1] - data[(int)j]) * frac;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if( outwidth == 2 )
|
||||
{
|
||||
int16_t *outdata = (int16_t *)sound.tempbuffer;
|
||||
|
||||
if( sc->channels == 2 )
|
||||
{
|
||||
for( i = 0; i < outcount; i++ )
|
||||
{
|
||||
j = stepscale * i;
|
||||
outdata[i*2+0] = data[((int)j)*2+0];
|
||||
outdata[i*2+1] = data[((int)j)*2+1];
|
||||
if( j != (int)j && j < incount )
|
||||
{
|
||||
frac = j - (int)j;
|
||||
outdata[i*2+0] += (data[((int)j+1)*2+0] - data[((int)j)*2+0]) * frac;
|
||||
outdata[i*2+1] += (data[((int)j+1)*2+1] - data[((int)j)*2+1]) * frac;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = 0; i < outcount; i++ )
|
||||
{
|
||||
j = stepscale * i;
|
||||
outdata[i] = data[(int)j];
|
||||
if( j != (int)j && j < incount )
|
||||
{
|
||||
frac = j - (int)j;
|
||||
outdata[i] += (data[(int)j+1] - data[(int)j]) * frac;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#undef SOUND_FORMATCONVERT_BOILERPLATE
|
||||
#undef SOUND_CONVERTNORESAMPLE_BOILERPLATE
|
||||
#undef SOUND_CONVERTDOWNSAMPLE_BOILERPLATE
|
||||
#undef SOUND_CONVERTUPSAMPLE_BOILERPLATE
|
||||
|
||||
/*
|
||||
================
|
||||
Sound_ResampleInternal
|
||||
|
||||
We need convert sound to signed even if nothing to resample
|
||||
================
|
||||
*/
|
||||
static qboolean Sound_ResampleInternal( wavdata_t *sc, int inrate, int inwidth, int outrate, int outwidth )
|
||||
static qboolean Sound_ResampleInternal( wavdata_t *sc, int outrate, int outwidth, int outchannels )
|
||||
{
|
||||
const size_t oldsize = sc->size;
|
||||
const int inrate = sc->rate;
|
||||
const int inwidth = sc->width;
|
||||
const int inchannels = sc->channels;
|
||||
const int incount = sc->samples;
|
||||
qboolean handled = false;
|
||||
double stepscale;
|
||||
double t1, t2;
|
||||
int outcount, incount = sc->samples;
|
||||
int outcount;
|
||||
|
||||
if( inrate == outrate && inwidth == outwidth )
|
||||
if( inrate == outrate && inwidth == outwidth && inchannels == outchannels )
|
||||
return false;
|
||||
|
||||
t1 = Sys_DoubleTime();
|
||||
|
||||
stepscale = (double)inrate / outrate; // this is usually 0.5, 1, or 2
|
||||
outcount = sc->samples / stepscale;
|
||||
sc->size = outcount * outwidth * sc->channels;
|
||||
sc->size = outcount * outwidth * outchannels;
|
||||
sc->channels = outchannels;
|
||||
|
||||
sc->samples = outcount;
|
||||
if( FBitSet( sc->flags, SOUND_LOOPED ))
|
||||
sc->loopStart = sc->loopStart / stepscale;
|
||||
|
||||
#if 0 && XASH_SDL // slow but somewhat accurate
|
||||
#if 0 && XASH_SDL // slow but somewhat accurate (wasn't updated to channel manipulation!!!)
|
||||
{
|
||||
const SDL_AudioFormat infmt = inwidth == 1 ? AUDIO_S8 : AUDIO_S16;
|
||||
const SDL_AudioFormat outfmt = outwidth == 1 ? AUDIO_S8 : AUDIO_S16;
|
||||
SDL_AudioCVT cvt;
|
||||
|
||||
// SDL_AudioCVT does conversion in place, original buffer is used for it
|
||||
if( SDL_BuildAudioCVT( &cvt, infmt, sc->channels, inrate, outfmt, sc->channels, outrate ) > 0 && cvt.needed )
|
||||
if( SDL_BuildAudioCVT( &cvt, infmt, inchannels, inrate, outfmt, outchannels, outrate ) > 0 && cvt.needed )
|
||||
{
|
||||
sc->buffer = (byte *)Mem_Realloc( host.soundpool, sc->buffer, oldsize * cvt.len_mult );
|
||||
cvt.len = oldsize;
|
||||
@@ -493,23 +422,23 @@ static qboolean Sound_ResampleInternal( wavdata_t *sc, int inrate, int inwidth,
|
||||
sound.tempbuffer = (byte *)Mem_Realloc( host.soundpool, sound.tempbuffer, sc->size );
|
||||
|
||||
if( inrate == outrate ) // no resampling, just copy data
|
||||
handled = Sound_ConvertNoResample( sc, inwidth, outwidth, outcount );
|
||||
handled = Sound_ConvertNoResample( sc, inwidth, inchannels, outwidth, outchannels, outcount );
|
||||
else if( inrate > outrate ) // fast case, usually downsample but is also ok for upsampling
|
||||
handled = Sound_ConvertDownsample( sc, inwidth, outwidth, outcount, stepscale );
|
||||
handled = Sound_ConvertDownsample( sc, inwidth, inchannels, outwidth, outchannels, outcount, stepscale );
|
||||
else // upsample case, w/ interpolation
|
||||
handled = Sound_ConvertUpsample( sc, inwidth, outwidth, outcount, incount, stepscale );
|
||||
handled = Sound_ConvertUpsample( sc, inwidth, inchannels, incount, outwidth, outchannels, outcount, stepscale );
|
||||
|
||||
t2 = Sys_DoubleTime();
|
||||
|
||||
if( handled )
|
||||
{
|
||||
if( t2 - t1 > 0.01f ) // critical, report to mod developer
|
||||
Con_Printf( S_WARN "%s: from [%d bit %d Hz] to [%d bit %d Hz] (took %.3fs)\n", __func__, inwidth * 8, inrate, outwidth * 8, outrate, t2 - t1 );
|
||||
Con_Printf( S_WARN "%s: from [%d bit %d Hz %dch] to [%d bit %d Hz %dch] (took %.3fs)\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels, t2 - t1 );
|
||||
else
|
||||
Con_Reportf( "%s: from [%d bit %d Hz] to [%d bit %d Hz] (took %.3fs)\n", __func__, inwidth * 8, inrate, outwidth * 8, outrate, t2 - t1 );
|
||||
Con_Reportf( "%s: from [%d bit %d Hz %dch] to [%d bit %d Hz %dch] (took %.3fs)\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels, t2 - t1 );
|
||||
}
|
||||
else
|
||||
Con_Printf( S_ERROR "%s: unsupported from [%d bit %d Hz] to [%d bit %d Hz]\n", __func__, inwidth * 8, inrate, outwidth * 8, outrate );
|
||||
Con_Printf( S_ERROR "%s: unsupported from [%d bit %d Hz %dch] to [%d bit %d Hz %dch]\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels );
|
||||
|
||||
sc->rate = outrate;
|
||||
sc->width = outwidth;
|
||||
@@ -517,23 +446,23 @@ static qboolean Sound_ResampleInternal( wavdata_t *sc, int inrate, int inwidth,
|
||||
return handled;
|
||||
}
|
||||
|
||||
qboolean Sound_Process( wavdata_t **wav, int rate, int width, uint flags )
|
||||
qboolean Sound_Process( wavdata_t **wav, int rate, int width, int channels, uint flags )
|
||||
{
|
||||
wavdata_t *snd = *wav;
|
||||
qboolean result = true;
|
||||
|
||||
// check for buffers
|
||||
if( !snd || !snd->buffer )
|
||||
if( unlikely( !snd || !snd->buffer ))
|
||||
return false;
|
||||
|
||||
if( FBitSet( flags, SOUND_RESAMPLE ) && ( width > 0 || rate > 0 ))
|
||||
if( likely( FBitSet( flags, SOUND_RESAMPLE ) && ( width > 0 || rate > 0 || channels > 0 )))
|
||||
{
|
||||
result = Sound_ResampleInternal( snd, snd->rate, snd->width, rate, width );
|
||||
result = Sound_ResampleInternal( snd, rate, width, channels );
|
||||
|
||||
if( result )
|
||||
{
|
||||
Mem_Free( snd->buffer ); // free original image buffer
|
||||
snd->buffer = Sound_Copy( snd->size ); // unzone buffer (don't touch sound.tempbuffer)
|
||||
snd->buffer = Sound_Copy( snd->size ); // unzone buffer
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -241,14 +241,14 @@ qboolean Sound_LoadWAV( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
// get cue chunk
|
||||
FindChunk( name, "cue " );
|
||||
|
||||
if( iff_dataPtr )
|
||||
if( iff_dataPtr && iff_end - iff_dataPtr >= 36 )
|
||||
{
|
||||
iff_dataPtr += 32;
|
||||
sound.loopstart = GetLittleLong();
|
||||
SetBits( sound.flags, SOUND_LOOPED );
|
||||
FindNextChunk( name, "LIST" ); // if the next chunk is a LIST chunk, look for a cue length marker
|
||||
|
||||
if( iff_dataPtr )
|
||||
if( iff_dataPtr && iff_end - iff_dataPtr >= 32 )
|
||||
{
|
||||
if( IsFourCC( iff_dataPtr + 28, "mark" ))
|
||||
{
|
||||
|
||||
@@ -199,20 +199,20 @@ static void Sys_WriteEscapeSequenceForColorcode( int fd, int c )
|
||||
{
|
||||
static const char *q3ToAnsi[ 8 ] =
|
||||
{
|
||||
"\033[30m", // COLOR_BLACK
|
||||
"\033[31m", // COLOR_RED
|
||||
"\033[32m", // COLOR_GREEN
|
||||
"\033[33m", // COLOR_YELLOW
|
||||
"\033[34m", // COLOR_BLUE
|
||||
"\033[36m", // COLOR_CYAN
|
||||
"\033[35m", // COLOR_MAGENTA
|
||||
"\033[1;30m", // COLOR_BLACK
|
||||
"\033[1;31m", // COLOR_RED
|
||||
"\033[1;32m", // COLOR_GREEN
|
||||
"\033[1;33m", // COLOR_YELLOW
|
||||
"\033[1;34m", // COLOR_BLUE
|
||||
"\033[1;36m", // COLOR_CYAN
|
||||
"\033[1;35m", // COLOR_MAGENTA
|
||||
"\033[0m", // COLOR_WHITE
|
||||
};
|
||||
const char *esc = q3ToAnsi[c];
|
||||
|
||||
if( c == 7 )
|
||||
write( fd, esc, 4 );
|
||||
else write( fd, esc, 5 );
|
||||
else write( fd, esc, 7 );
|
||||
}
|
||||
#else
|
||||
static void Sys_WriteEscapeSequenceForColorcode( int fd, int c ) {}
|
||||
@@ -297,6 +297,7 @@ void Sys_PrintLog( const char *pMsg )
|
||||
const struct tm *crt_tm;
|
||||
char logtime[32] = "";
|
||||
static char lastchar;
|
||||
size_t len;
|
||||
|
||||
time( &crt_time );
|
||||
crt_tm = localtime( &crt_time );
|
||||
@@ -307,10 +308,12 @@ void Sys_PrintLog( const char *pMsg )
|
||||
// spew to stdout
|
||||
Sys_PrintStdout( logtime, pMsg );
|
||||
|
||||
len = Q_strlen( pMsg );
|
||||
|
||||
if( !s_ld.logfile )
|
||||
{
|
||||
// save last char to detect when line was not ended
|
||||
lastchar = pMsg[Q_strlen( pMsg ) - 1];
|
||||
lastchar = len > 0 ? pMsg[len - 1] : 0;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -318,7 +321,7 @@ void Sys_PrintLog( const char *pMsg )
|
||||
strftime( logtime, sizeof( logtime ), "[%Y:%m:%d|%H:%M:%S] ", crt_tm ); //full time
|
||||
|
||||
// save last char to detect when line was not ended
|
||||
lastchar = pMsg[Q_strlen( pMsg ) - 1];
|
||||
lastchar = len > 0 ? pMsg[len - 1] : 0;
|
||||
|
||||
Sys_PrintLogfile( s_ld.logfileno, logtime, pMsg, false );
|
||||
Sys_FlushLogfile();
|
||||
@@ -331,6 +334,21 @@ CONSOLE PRINT
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
static void Con_Printfv( qboolean debug, const char *szFmt, va_list args )
|
||||
{
|
||||
static char buffer[MAX_PRINT_MSG];
|
||||
qboolean add_newline;
|
||||
|
||||
add_newline = Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args ) < 0;
|
||||
|
||||
if( debug && !Q_strcmp( buffer, "0\n" ))
|
||||
return; // hlrally spam
|
||||
|
||||
Sys_Print( buffer );
|
||||
if( add_newline )
|
||||
Sys_Print( "\n" );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Con_Printf
|
||||
@@ -339,20 +357,14 @@ Con_Printf
|
||||
*/
|
||||
void GAME_EXPORT Con_Printf( const char *szFmt, ... )
|
||||
{
|
||||
static char buffer[MAX_PRINT_MSG];
|
||||
va_list args;
|
||||
qboolean add_newline;
|
||||
va_list args;
|
||||
|
||||
if( !host.allow_console )
|
||||
return;
|
||||
|
||||
va_start( args, szFmt );
|
||||
add_newline = Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args ) < 0;
|
||||
Con_Printfv( false, szFmt, args );
|
||||
va_end( args );
|
||||
|
||||
Sys_Print( buffer );
|
||||
if( add_newline )
|
||||
Sys_Print( "\n" );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -363,23 +375,14 @@ Con_DPrintf
|
||||
*/
|
||||
void GAME_EXPORT Con_DPrintf( const char *szFmt, ... )
|
||||
{
|
||||
static char buffer[MAX_PRINT_MSG];
|
||||
va_list args;
|
||||
qboolean add_newline;
|
||||
va_list args;
|
||||
|
||||
if( host_developer.value < DEV_NORMAL )
|
||||
return;
|
||||
|
||||
va_start( args, szFmt );
|
||||
add_newline = Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args ) < 0;
|
||||
Con_Printfv( true, szFmt, args );
|
||||
va_end( args );
|
||||
|
||||
if( buffer[0] == '0' && buffer[1] == '\n' && buffer[2] == '\0' )
|
||||
return; // hlrally spam
|
||||
|
||||
Sys_Print( buffer );
|
||||
if( add_newline )
|
||||
Sys_Print( "\n" );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -390,20 +393,14 @@ Con_Reportf
|
||||
*/
|
||||
void Con_Reportf( const char *szFmt, ... )
|
||||
{
|
||||
static char buffer[MAX_PRINT_MSG];
|
||||
va_list args;
|
||||
qboolean add_newline;
|
||||
va_list args;
|
||||
|
||||
if( host_developer.value < DEV_EXTENDED )
|
||||
return;
|
||||
|
||||
va_start( args, szFmt );
|
||||
add_newline = Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args ) < 0;
|
||||
Con_Printfv( false, szFmt, args );
|
||||
va_end( args );
|
||||
|
||||
Sys_Print( buffer );
|
||||
if( add_newline )
|
||||
Sys_Print( "\n" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -72,15 +72,28 @@ Sys_DebugBreak
|
||||
*/
|
||||
void Sys_DebugBreak( void )
|
||||
{
|
||||
#if XASH_SDL
|
||||
int was_grabbed = host.hWnd != NULL && SDL_GetWindowGrab( host.hWnd );
|
||||
#endif
|
||||
|
||||
if( !Sys_DebuggerPresent( ))
|
||||
return;
|
||||
|
||||
#if XASH_SDL
|
||||
if( was_grabbed ) // so annoying...
|
||||
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
|
||||
#endif // XASH_SDL
|
||||
|
||||
#if _MSC_VER
|
||||
if( Sys_DebuggerPresent( ))
|
||||
__debugbreak();
|
||||
__debugbreak();
|
||||
#else // !_MSC_VER
|
||||
if( Sys_DebuggerPresent( ))
|
||||
{
|
||||
INLINE_RAISE( SIGINT );
|
||||
INLINE_NANOSLEEP1(); // sometimes signal comes with delay, let it interrupt nanosleep
|
||||
}
|
||||
INLINE_RAISE( SIGINT );
|
||||
INLINE_NANOSLEEP1(); // sometimes signal comes with delay, let it interrupt nanosleep
|
||||
#endif // !_MSC_VER
|
||||
|
||||
#if XASH_SDL
|
||||
if( was_grabbed )
|
||||
SDL_SetWindowGrab( host.hWnd, SDL_TRUE );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -78,20 +78,6 @@ void Sys_InitLog( void );
|
||||
void Sys_PrintLog( const char *pMsg );
|
||||
int Sys_LogFileNo( void );
|
||||
|
||||
//
|
||||
// con_win.c
|
||||
//
|
||||
#if XASH_WIN32
|
||||
void Wcon_InitConsoleCommands( void );
|
||||
void Wcon_ShowConsole( qboolean show );
|
||||
void Wcon_CreateConsole( void );
|
||||
void Wcon_DestroyConsole( void );
|
||||
void Wcon_DisableInput( void );
|
||||
char *Wcon_Input( void );
|
||||
void Wcon_WinPrint( const char *pMsg );
|
||||
void Wcon_SetStatus( const char *pStatus );
|
||||
#endif
|
||||
|
||||
// text messages
|
||||
#define Msg Con_Printf
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ void Test_RunVOX( void );
|
||||
void Test_RunIPFilter( void );
|
||||
void Test_RunGamma( void );
|
||||
void Test_RunDelta( void );
|
||||
void Test_RunBuffer( void );
|
||||
|
||||
#define TEST_LIST_0 \
|
||||
Test_RunLibCommon(); \
|
||||
@@ -47,6 +48,7 @@ void Test_RunDelta( void );
|
||||
Test_RunCmd(); \
|
||||
Test_RunCvar(); \
|
||||
Test_RunIPFilter(); \
|
||||
Test_RunBuffer(); \
|
||||
Test_RunDelta();
|
||||
|
||||
#define TEST_LIST_0_CLIENT \
|
||||
|
||||
@@ -241,6 +241,21 @@ void _Mem_Free( void *data, const char *filename, int fileline )
|
||||
Mem_FreeBlock((memheader_t *)((byte *)data - sizeof( memheader_t )), filename, fileline );
|
||||
}
|
||||
|
||||
static void Mem_MigratePool( poolhandle_t newpoolptr, memheader_t *mem, const char *filename, int fileline )
|
||||
{
|
||||
mempool_t *oldpool = Mem_FindPool( mem->poolptr );
|
||||
mempool_t *newpool = Mem_FindPool( newpoolptr );
|
||||
|
||||
// dettach allocation from one pool and reattach it to new pool
|
||||
// might be made into public function at some point
|
||||
|
||||
Mem_PoolUnlinkAlloc( oldpool, mem );
|
||||
Mem_PoolSubtract( oldpool, mem->size );
|
||||
|
||||
Mem_PoolLinkAlloc( newpool, mem );
|
||||
Mem_PoolAdd( newpool, mem->size );
|
||||
}
|
||||
|
||||
void *_Mem_Realloc( poolhandle_t poolptr, void *data, size_t size, qboolean clear, const char *filename, int fileline )
|
||||
{
|
||||
memheader_t *mem;
|
||||
@@ -262,15 +277,12 @@ void *_Mem_Realloc( poolhandle_t poolptr, void *data, size_t size, qboolean clea
|
||||
|
||||
mem = (memheader_t *)((byte *)data - sizeof( memheader_t ));
|
||||
|
||||
if( !Mem_CheckAllocHeader( "Mem_Realloc", mem, filename, fileline ))
|
||||
if( !Mem_CheckAllocHeader( __func__, mem, filename, fileline ))
|
||||
return NULL;
|
||||
|
||||
if( unlikely( mem->poolptr != poolptr ))
|
||||
{
|
||||
Sys_Error( "%s: pool migration is not allowed (alloc at %s:%i, realloc at %s:%i)\n",
|
||||
__func__, Mem_CheckFilename( mem->filename ), mem->fileline, filename, fileline );
|
||||
return NULL;
|
||||
}
|
||||
// migrate pool if requested, even if no reallocation needed
|
||||
if( mem->poolptr != poolptr )
|
||||
Mem_MigratePool( poolptr, mem, filename, fileline );
|
||||
|
||||
oldsize = mem->size;
|
||||
if( size == oldsize )
|
||||
@@ -439,7 +451,7 @@ void _Mem_Check( const char *filename, int fileline )
|
||||
|
||||
for( i = 0, pool = poolchain; i < poolcount; i++, pool++ )
|
||||
for( mem = pool->chain; mem; mem = mem->next )
|
||||
Mem_CheckAllocHeader( "Mem_CheckSentinels", mem, filename, fileline );
|
||||
Mem_CheckAllocHeader( __func__, mem, filename, fileline );
|
||||
}
|
||||
|
||||
void Mem_PrintStats( void )
|
||||
|
||||
@@ -53,6 +53,10 @@ typedef struct resourceinfo_s
|
||||
#define RES_ALWAYS (1<<5) // Download always even if available on client
|
||||
#define RES_CHECKFILE (1<<7) // Check file on client
|
||||
|
||||
// this archive was already mounted after rescan
|
||||
// only makes sense for archives and on client
|
||||
#define RES_EXTRA_ARCHIVE_CHECKED BIT( 0 )
|
||||
|
||||
typedef struct resource_s
|
||||
{
|
||||
char szFileName[64]; // File name to download/precache.
|
||||
@@ -67,6 +71,7 @@ typedef struct resource_s
|
||||
// if it's a custom resource.
|
||||
|
||||
unsigned char rguc_reserved[32]; // For future expansion
|
||||
unsigned short ucExtraFlags; // fwgs extension, doesn't change the size of struct because of compiler padding
|
||||
struct resource_s *pNext; // Next in chain.
|
||||
struct resource_s *pPrev;
|
||||
} resource_t;
|
||||
@@ -90,4 +95,12 @@ typedef struct customization_s
|
||||
#define FCUST_WIPEDATA ( 1<<1 )
|
||||
#define FCUST_IGNOREINIT ( 1<<2 )
|
||||
|
||||
#if !XASH_64BIT
|
||||
STATIC_ASSERT( sizeof( customization_t ) == 164, "invalid customization_t size, broken API" );
|
||||
STATIC_ASSERT( sizeof( resource_t ) == 136, "invalid resource_t size, broken API" );
|
||||
#else
|
||||
STATIC_ASSERT( sizeof( customization_t ) == 192, "invalid customization_t size, broken API" );
|
||||
STATIC_ASSERT( sizeof( resource_t ) == 144, "invalid resource_t size, broken API" );
|
||||
#endif
|
||||
|
||||
#endif // CUSTOM_H
|
||||
|
||||
@@ -218,6 +218,10 @@ typedef struct ui_extendedfuncs_s {
|
||||
int (*pfnCompareAdr)( const void *a, const void *b ); // netadr_t
|
||||
void *(*pfnGetNativeObject)( const char *name );
|
||||
struct net_api_s *pNetAPI;
|
||||
|
||||
// new mods info
|
||||
gameinfo2_t *(*pfnGetGameInfo)( int gi_version ); // might return NULL if gi_version is unsupported
|
||||
gameinfo2_t *(*pfnGetModInfo)( int gi_version, int mod_index ); // continiously call it until it returns null
|
||||
} ui_extendedfuncs_t;
|
||||
|
||||
// deprecated export from old engine
|
||||
|
||||
@@ -71,6 +71,11 @@ void Android_Shutdown( void );
|
||||
#if XASH_WIN32
|
||||
void Wcon_CreateConsole( qboolean con_showalways );
|
||||
void Wcon_DestroyConsole( void );
|
||||
void Wcon_InitConsoleCommands( void );
|
||||
void Wcon_ShowConsole( qboolean show );
|
||||
void Wcon_DisableInput( void );
|
||||
char *Wcon_Input( void );
|
||||
void Wcon_WinPrint( const char *pMsg );
|
||||
#endif
|
||||
|
||||
#if XASH_NSWITCH
|
||||
|
||||
@@ -46,6 +46,7 @@ extern void *__aeabi_idivmod;
|
||||
extern void *__aeabi_uidivmod;
|
||||
extern void *__aeabi_d2ulz;
|
||||
extern void *__aeabi_ul2d;
|
||||
extern void *__aeabi_ul2f;
|
||||
|
||||
static const vrtld_export_t aux_exports[] =
|
||||
{
|
||||
@@ -55,6 +56,7 @@ static const vrtld_export_t aux_exports[] =
|
||||
VRTLD_EXPORT_SYMBOL( __aeabi_uidivmod ),
|
||||
VRTLD_EXPORT_SYMBOL( __aeabi_uidiv ),
|
||||
VRTLD_EXPORT_SYMBOL( __aeabi_ul2d ),
|
||||
VRTLD_EXPORT_SYMBOL( __aeabi_ul2f ),
|
||||
VRTLD_EXPORT_SYMBOL( _impure_ptr ),
|
||||
VRTLD_EXPORT_SYMBOL( ctime ),
|
||||
VRTLD_EXPORT_SYMBOL( vasprintf ),
|
||||
|
||||
@@ -350,7 +350,7 @@ void Platform_SetCursorType( VGUI_DefaultCursor type )
|
||||
}
|
||||
|
||||
// never disable cursor in touch emulation mode
|
||||
if( !visible && touch_emulate.value )
|
||||
if( !visible && Touch_Emulated( ))
|
||||
return;
|
||||
|
||||
host.mouse_visible = visible;
|
||||
|
||||
@@ -47,10 +47,13 @@ qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *
|
||||
if( sw.renderer )
|
||||
{
|
||||
unsigned int format = SDL_GetWindowPixelFormat( host.hWnd );
|
||||
SDL_RenderSetLogicalSize(sw.renderer, refState.width, refState.height);
|
||||
SDL_RenderSetLogicalSize( sw.renderer, refState.width, refState.height );
|
||||
|
||||
if( sw.tex )
|
||||
{
|
||||
SDL_DestroyTexture( sw.tex );
|
||||
sw.tex = NULL;
|
||||
}
|
||||
|
||||
// guess
|
||||
if( format == SDL_PIXELFORMAT_UNKNOWN )
|
||||
@@ -63,20 +66,16 @@ qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *
|
||||
|
||||
// we can only copy fast 16 or 32 bits
|
||||
// SDL_Renderer does not allow zero-copy, so 24 bits will be ineffective
|
||||
if( !( SDL_BYTESPERPIXEL(format) == 2 || SDL_BYTESPERPIXEL(format) == 4 ) )
|
||||
if( SDL_BYTESPERPIXEL( format ) != 2 && SDL_BYTESPERPIXEL( format ) != 4 )
|
||||
format = SDL_PIXELFORMAT_RGBA8888;
|
||||
|
||||
sw.tex = SDL_CreateTexture(sw.renderer, format,
|
||||
SDL_TEXTUREACCESS_STREAMING,
|
||||
width, height);
|
||||
sw.tex = SDL_CreateTexture( sw.renderer, format, SDL_TEXTUREACCESS_STREAMING, width, height );
|
||||
|
||||
// fallback
|
||||
if( !sw.tex && format != SDL_PIXELFORMAT_RGBA8888 )
|
||||
{
|
||||
format = SDL_PIXELFORMAT_RGBA8888;
|
||||
sw.tex = SDL_CreateTexture(sw.renderer, format,
|
||||
SDL_TEXTUREACCESS_STREAMING,
|
||||
width, height);
|
||||
sw.tex = SDL_CreateTexture( sw.renderer, format, SDL_TEXTUREACCESS_STREAMING, width, height );
|
||||
}
|
||||
|
||||
if( !sw.tex )
|
||||
@@ -89,25 +88,26 @@ qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *
|
||||
void *pixels;
|
||||
int pitch;
|
||||
|
||||
if( !SDL_LockTexture(sw.tex, NULL, &pixels, &pitch ) )
|
||||
if( !SDL_LockTexture( sw.tex, NULL, &pixels, &pitch ))
|
||||
{
|
||||
int bits;
|
||||
uint amask;
|
||||
|
||||
// lock successfull, release
|
||||
SDL_UnlockTexture(sw.tex);
|
||||
SDL_UnlockTexture( sw.tex );
|
||||
|
||||
// enough for building blitter tables
|
||||
SDL_PixelFormatEnumToMasks( format, &bits, r, g, b, &amask );
|
||||
*bpp = SDL_BYTESPERPIXEL(format);
|
||||
*bpp = SDL_BYTESPERPIXEL( format );
|
||||
*stride = pitch / *bpp;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// fallback to surf
|
||||
SDL_DestroyTexture(sw.tex);
|
||||
SDL_DestroyTexture( sw.tex );
|
||||
sw.tex = NULL;
|
||||
SDL_DestroyRenderer(sw.renderer);
|
||||
SDL_DestroyRenderer( sw.renderer );
|
||||
sw.renderer = NULL;
|
||||
}
|
||||
}
|
||||
@@ -126,7 +126,7 @@ qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *
|
||||
// if it is failed, it is not possible to draw with SDL in REF_SOFTWARE mode
|
||||
if( !sw.win )
|
||||
{
|
||||
Sys_Warn("failed to initialize software output, try enable sw_glblit");
|
||||
Sys_Warn( "failed to initialize software output, try running with -glblit flag" );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -141,9 +141,10 @@ qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *
|
||||
{
|
||||
sw.surf = SDL_CreateRGBSurfaceWithFormat( 0, width, height, 16, SDL_PIXELFORMAT_RGB565 );
|
||||
if( !sw.surf )
|
||||
Sys_Error(SDL_GetError());
|
||||
Sys_Error( "%s: %s", __func__, SDL_GetError( ));
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
// we can't create ref_soft buffer
|
||||
@@ -640,9 +641,17 @@ void VID_RestoreScreenResolution( void )
|
||||
switch((window_mode_t)vid_fullscreen.value )
|
||||
{
|
||||
case WINDOW_MODE_WINDOWED:
|
||||
// TODO: this line is from very old SDL video backend
|
||||
// figure out why we need it, because in windowed mode we
|
||||
// always have borders
|
||||
SDL_SetWindowBordered( host.hWnd, SDL_TRUE );
|
||||
break;
|
||||
default:
|
||||
case WINDOW_MODE_BORDERLESS:
|
||||
// in borderless fullscreen we don't change screen resolution, so no-op
|
||||
break;
|
||||
case WINDOW_MODE_FULLSCREEN:
|
||||
// TODO: we might want to not minimize window if current desktop mode
|
||||
// and window mode are the same
|
||||
SDL_MinimizeWindow( host.hWnd );
|
||||
SDL_SetWindowFullscreen( host.hWnd, 0 );
|
||||
break;
|
||||
@@ -1180,14 +1189,8 @@ qboolean VID_SetMode( void )
|
||||
}
|
||||
#endif
|
||||
|
||||
if( !FBitSet( vid_fullscreen.flags, FCVAR_CHANGED ))
|
||||
Cvar_DirectSet( &vid_fullscreen, DEFAULT_FULLSCREEN );
|
||||
else
|
||||
ClearBits( vid_fullscreen.flags, FCVAR_CHANGED );
|
||||
|
||||
SetBits( gl_vsync.flags, FCVAR_CHANGED );
|
||||
|
||||
window_mode = bound( 0, vid_fullscreen.value, WINDOW_MODE_COUNT - 1 );
|
||||
SetBits( gl_vsync.flags, FCVAR_CHANGED );
|
||||
|
||||
if(( err = R_ChangeDisplaySettings( iScreenWidth, iScreenHeight, window_mode )) == rserr_ok )
|
||||
{
|
||||
|
||||
@@ -5198,7 +5198,7 @@ qboolean SV_LoadProgs( const char *name )
|
||||
gEngfuncs.pfnPEntityOfEntIndex = pfnPEntityOfEntIndexBroken;
|
||||
|
||||
// make local copy of engfuncs to prevent overwrite it with bots.dll
|
||||
memcpy( &gpEngfuncs, &gEngfuncs, sizeof( gpEngfuncs ));
|
||||
gpEngfuncs = gEngfuncs;
|
||||
|
||||
GetEntityAPI = (APIFUNCTION)COM_GetProcAddress( svgame.hInstance, "GetEntityAPI" );
|
||||
GetEntityAPI2 = (APIFUNCTION2)COM_GetProcAddress( svgame.hInstance, "GetEntityAPI2" );
|
||||
|
||||
@@ -236,7 +236,7 @@ void SV_UpdateMovevars( qboolean initialize )
|
||||
if( initialize ) return; // too early
|
||||
|
||||
if( MSG_WriteDeltaMovevars( &sv.reliable_datagram, &svgame.oldmovevars, &svgame.movevars ))
|
||||
memcpy( &svgame.oldmovevars, &svgame.movevars, sizeof( movevars_t )); // oldstate changed
|
||||
svgame.oldmovevars = svgame.movevars; // oldstate changed
|
||||
|
||||
host.movevars_changed = false;
|
||||
}
|
||||
|
||||
@@ -199,8 +199,8 @@ static qboolean SV_TestEntityPosition( edict_t *ent, edict_t *blocker )
|
||||
{
|
||||
// to avoid falling through tracktrain update client mins\maxs here
|
||||
if( FBitSet( ent->v.flags, FL_DUCKING ))
|
||||
SV_SetMinMaxSize( ent, svgame.pmove->player_mins[1], svgame.pmove->player_maxs[1], true );
|
||||
else SV_SetMinMaxSize( ent, svgame.pmove->player_mins[0], svgame.pmove->player_maxs[0], true );
|
||||
SV_SetMinMaxSize( ent, host.player_mins[1], host.player_maxs[1], true );
|
||||
else SV_SetMinMaxSize( ent, host.player_mins[0], host.player_maxs[0], true );
|
||||
}
|
||||
|
||||
trace = SV_Move( ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, MOVE_NORMAL, ent, monsterClip );
|
||||
|
||||
@@ -671,7 +671,7 @@ static void SV_FinishPMove( playermove_t *pmove, sv_client_t *cl )
|
||||
clent->v.angles[YAW] = clent->v.v_angle[YAW];
|
||||
}
|
||||
|
||||
SV_SetMinMaxSize( clent, pmove->player_mins[pmove->usehull], pmove->player_maxs[pmove->usehull], false );
|
||||
SV_SetMinMaxSize( clent, host.player_mins[pmove->usehull], host.player_maxs[pmove->usehull], false );
|
||||
|
||||
// all next calls ignore footstep sounds
|
||||
pmove->runfuncs = false;
|
||||
|
||||
@@ -32,6 +32,9 @@ def options(opt):
|
||||
grp.add_option('--enable-engine-fuzz', action = 'store_true', dest = 'ENGINE_FUZZ', default = False,
|
||||
help = 'add LLVM libFuzzer [default: %(default)s]' )
|
||||
|
||||
grp.add_option('--enable-ffmpeg', action = 'store_true', dest = 'FFMPEG', default = False,
|
||||
help = '') # hidden option, does nothing
|
||||
|
||||
opt.load('sdl2')
|
||||
|
||||
def configure(conf):
|
||||
|
||||
@@ -58,7 +58,7 @@ static inline const char *IdToDir( char *dir, size_t size, const char *id )
|
||||
|
||||
if( !Q_strcmp( id, "GAMEDOWNLOAD" ))
|
||||
{
|
||||
Q_snprintf( dir, size, "%s/downloaded", GI->gamefolder );
|
||||
Q_snprintf( dir, size, "%s/" DEFAULT_DOWNLOADED_DIRECTORY , GI->gamefolder );
|
||||
return dir;
|
||||
}
|
||||
|
||||
@@ -531,9 +531,9 @@ extern "C" void EXPORT *CreateInterface( const char *interface, int *retval )
|
||||
|
||||
if( !Q_strcmp( interface, FS_API_CREATEINTERFACE_TAG ))
|
||||
{
|
||||
static fs_api_t copy = { 0 }; // return a copy, to disallow overriding
|
||||
static fs_api_t copy; // return a copy, to disallow overriding
|
||||
|
||||
memcpy( ©, &g_api, sizeof( copy ));
|
||||
copy = g_api;
|
||||
|
||||
if( retval )
|
||||
*retval = 0;
|
||||
|
||||
@@ -21,15 +21,14 @@ GNU General Public License for more details.
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#if XASH_WIN32
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#elif XASH_DOS4GW
|
||||
#include <direct.h>
|
||||
#include <errno.h>
|
||||
#else
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
@@ -61,10 +60,10 @@ static char fs_gamedir[MAX_SYSPATH]; // game current directory
|
||||
// so raw WADs takes precedence over WADs included into PAKs and PK3s
|
||||
const fs_archive_t g_archives[] =
|
||||
{
|
||||
{ "pak", SEARCHPATH_PAK, FS_AddPak_Fullpath, true },
|
||||
{ "pk3", SEARCHPATH_ZIP, FS_AddZip_Fullpath, true },
|
||||
{ "pk3dir", SEARCHPATH_PK3DIR, FS_AddDir_Fullpath, true },
|
||||
{ "wad", SEARCHPATH_WAD, FS_AddWad_Fullpath, false },
|
||||
{ "pak", SEARCHPATH_PAK, FS_AddPak_Fullpath, true, true },
|
||||
{ "pk3", SEARCHPATH_ZIP, FS_AddZip_Fullpath, true, true },
|
||||
{ "pk3dir", SEARCHPATH_PK3DIR, FS_AddDir_Fullpath, true, false },
|
||||
{ "wad", SEARCHPATH_WAD, FS_AddWad_Fullpath, false, true },
|
||||
{ NULL }, // end marker
|
||||
};
|
||||
|
||||
@@ -619,6 +618,9 @@ static void FS_WriteGameInfo( const char *filepath, gameinfo_t *GameInfo )
|
||||
FS_Printf( f, "internal_vgui_support\t\t%s\n", GameInfo->internal_vgui_support ? "1" : "0" );
|
||||
FS_Printf( f, "render_picbutton_text\t\t%s\n", GameInfo->render_picbutton_text ? "1" : "0" );
|
||||
|
||||
if( COM_CheckStringEmpty( GameInfo->demomap ))
|
||||
FS_Printf( f, "demomap\t\t\"%s\"\n", GameInfo->demomap );
|
||||
|
||||
FS_Close( f ); // all done
|
||||
}
|
||||
|
||||
@@ -879,9 +881,21 @@ static void FS_ParseGenericGameInfo( gameinfo_t *GameInfo, const char *buf, cons
|
||||
pfile = COM_ParseFile( pfile, token, sizeof( token ));
|
||||
GameInfo->autosave_aged_count = bound( 2, Q_atoi( token ), 99 );
|
||||
}
|
||||
else if( !Q_stricmp( token, "demomap" ))
|
||||
{
|
||||
pfile = COM_ParseFile( pfile, GameInfo->demomap, sizeof( GameInfo->demomap ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// demomap only valid for gameinfo.txt but HL1 after 25th anniversary update
|
||||
// comes with demo chapter. Set the demomap here.
|
||||
if( !COM_CheckStringEmpty( GameInfo->demomap ))
|
||||
{
|
||||
if( !Q_stricmp( GameInfo->title, "Half-Life" )) // original check from GameUI
|
||||
Q_strncpy( GameInfo->demomap, "hldemo1", sizeof( GameInfo->demomap ));
|
||||
}
|
||||
|
||||
if( !found_linux || !found_osx )
|
||||
{
|
||||
// just replace extension from dll to so/dylib
|
||||
@@ -897,9 +911,18 @@ static void FS_ParseGenericGameInfo( gameinfo_t *GameInfo, const char *buf, cons
|
||||
}
|
||||
|
||||
// make sure what gamedir is really exist
|
||||
// a1ba: why we are doing this???
|
||||
Q_snprintf( token, sizeof( token ), "%s/%s", fs_rootdir, GameInfo->falldir );
|
||||
if( !FS_SysFolderExists( token ))
|
||||
GameInfo->falldir[0] = '\0';
|
||||
{
|
||||
if( COM_CheckStringEmpty( fs_rodir ))
|
||||
{
|
||||
Q_snprintf( token, sizeof( token ), "%s/%s", fs_rodir, GameInfo->falldir );
|
||||
if( !FS_SysFolderExists( token ))
|
||||
GameInfo->falldir[0] = 0;
|
||||
}
|
||||
else GameInfo->falldir[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1174,14 +1197,14 @@ void FS_AddGameHierarchy( const char *dir, uint flags )
|
||||
|
||||
if( isGameDir )
|
||||
{
|
||||
Q_snprintf( buf, sizeof( buf ), "%s/downloaded/", dir );
|
||||
Q_snprintf( buf, sizeof( buf ), "%s/" DEFAULT_DOWNLOADED_DIRECTORY, dir );
|
||||
FS_AddGameDirectory( buf, FS_NOWRITE_PATH | FS_CUSTOM_PATH );
|
||||
}
|
||||
Q_snprintf( buf, sizeof( buf ), "%s/", dir );
|
||||
FS_AddGameDirectory( buf, flags );
|
||||
if( isGameDir )
|
||||
{
|
||||
Q_snprintf( buf, sizeof( buf ), "%s/custom/", dir );
|
||||
Q_snprintf( buf, sizeof( buf ), "%s/" DEFAULT_CUSTOM_DIRECTORY, dir );
|
||||
FS_AddGameDirectory( buf, FS_NOWRITE_PATH | FS_CUSTOM_PATH );
|
||||
}
|
||||
}
|
||||
@@ -1369,9 +1392,9 @@ static qboolean FS_FindLibrary( const char *dllname, qboolean directpath, fs_dll
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_snprintf( dllInfo->fullPath, sizeof( dllInfo->fullPath ), "%s%s", search->filename, dllInfo->shortPath );
|
||||
Q_snprintf( dllInfo->fullPath, sizeof( dllInfo->fullPath ), "%s", dllInfo->shortPath );
|
||||
#if XASH_WIN32 && XASH_X86 // a1ba: custom loader is non-portable (I just don't want to touch it)
|
||||
Con_Printf( S_WARN "%s: loading libraries from archives is deprecated and will be removed in the future\n", __func__ );
|
||||
Con_Printf( S_WARN "%s: loading libraries from archives is non portable and might fail on other platforms\n", __func__ );
|
||||
dllInfo->custom_loader = true;
|
||||
#else
|
||||
Con_Printf( S_WARN "%s: loading libraries from archives is unsupported on this platform\n", __func__ );
|
||||
@@ -2653,19 +2676,9 @@ return NULL for file in pack
|
||||
const char *FS_GetDiskPath( const char *name, qboolean gamedironly )
|
||||
{
|
||||
static char diskpath[MAX_SYSPATH];
|
||||
char fullpath[MAX_SYSPATH];
|
||||
searchpath_t *search;
|
||||
|
||||
search = FS_FindFile( name, NULL, fullpath, sizeof( fullpath ), gamedironly );
|
||||
|
||||
if( search )
|
||||
{
|
||||
if( search->type != SEARCHPATH_PLAIN ) // file in pack or wad
|
||||
return NULL;
|
||||
|
||||
Q_snprintf( diskpath, sizeof( diskpath ), "%s/%s", search->filename, fullpath );
|
||||
if( FS_GetFullDiskPath( diskpath, sizeof( diskpath ), name, gamedironly ))
|
||||
return diskpath;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -2687,7 +2700,7 @@ qboolean FS_GetFullDiskPath( char *buffer, size_t size, const char *name, qboole
|
||||
|
||||
if( search && search->type == SEARCHPATH_PLAIN )
|
||||
{
|
||||
Q_snprintf( buffer, size, "%s/%s", search->filename, temp );
|
||||
Q_snprintf( buffer, size, "%s%s", search->filename, temp );
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2931,6 +2944,25 @@ static const char *FS_ArchivePath( file_t *f )
|
||||
return "plain";
|
||||
}
|
||||
|
||||
static qboolean FS_IsArchiveExtensionSupported( const char *ext, uint flags )
|
||||
{
|
||||
int i;
|
||||
|
||||
if( ext == NULL )
|
||||
return false;
|
||||
|
||||
for( i = 0; i < ( sizeof( g_archives ) / sizeof( g_archives[0] )) - 1; i++ )
|
||||
{
|
||||
if( FBitSet( flags, IAES_ONLY_REAL_ARCHIVES ) && !g_archives[i].real_archive )
|
||||
continue;
|
||||
|
||||
if( !Q_stricmp( ext, g_archives[i].ext ))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void FS_InitMemory( void )
|
||||
{
|
||||
fs_mempool = Mem_AllocPool( "FileSystem Pool" );
|
||||
@@ -2951,7 +2983,7 @@ fs_interface_t g_engfuncs =
|
||||
Sys_GetNativeObject_stub
|
||||
};
|
||||
|
||||
static qboolean FS_InitInterface( int version, fs_interface_t *engfuncs )
|
||||
static qboolean FS_InitInterface( int version, const fs_interface_t *engfuncs )
|
||||
{
|
||||
// to be extended in future interface revisions
|
||||
if( version != FS_API_VERSION )
|
||||
@@ -2999,7 +3031,7 @@ static qboolean FS_InitInterface( int version, fs_interface_t *engfuncs )
|
||||
return true;
|
||||
}
|
||||
|
||||
fs_api_t g_api =
|
||||
const fs_api_t g_api =
|
||||
{
|
||||
FS_InitStdio,
|
||||
FS_ShutdownStdio,
|
||||
@@ -3059,6 +3091,8 @@ fs_api_t g_api =
|
||||
|
||||
FS_GetFullDiskPath,
|
||||
FS_LoadFileMalloc,
|
||||
|
||||
FS_IsArchiveExtensionSupported,
|
||||
};
|
||||
|
||||
int EXPORT GetFSAPI( int version, fs_api_t *api, fs_globals_t **globals, fs_interface_t *engfuncs );
|
||||
@@ -3067,7 +3101,7 @@ int EXPORT GetFSAPI( int version, fs_api_t *api, fs_globals_t **globals, fs_inte
|
||||
if( engfuncs && !FS_InitInterface( version, engfuncs ))
|
||||
return 0;
|
||||
|
||||
memcpy( api, &g_api, sizeof( *api ));
|
||||
*api = g_api;
|
||||
*globals = &FI;
|
||||
|
||||
return FS_API_VERSION;
|
||||
|
||||
@@ -25,6 +25,7 @@ GNU General Public License for more details.
|
||||
#include "xash3d_types.h"
|
||||
#include "const.h"
|
||||
#include "com_model.h"
|
||||
#include "gameinfo.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
@@ -50,6 +51,13 @@ enum
|
||||
FS_GAMEDIRONLY_SEARCH_FLAGS = FS_GAMEDIR_PATH | FS_CUSTOM_PATH | FS_GAMERODIR_PATH
|
||||
};
|
||||
|
||||
// IsArchiveExtensionSupported flags
|
||||
enum
|
||||
{
|
||||
// excludes directories and pk3dir, i.e. archives that cannot be represented as a single file
|
||||
IAES_ONLY_REAL_ARCHIVES = BIT( 0 ),
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int numfilenames;
|
||||
@@ -111,14 +119,9 @@ typedef struct gameinfo_s
|
||||
// HL25 compatibility keys
|
||||
qboolean hd_background;
|
||||
qboolean animated_title;
|
||||
} gameinfo_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GAME_NORMAL,
|
||||
GAME_SINGLEPLAYER_ONLY,
|
||||
GAME_MULTIPLAYER_ONLY
|
||||
} gametype_t;
|
||||
char demomap[MAX_QPATH];
|
||||
} gameinfo_t;
|
||||
|
||||
typedef struct fs_dllinfo_t
|
||||
{
|
||||
@@ -135,8 +138,6 @@ typedef struct fs_globals_t
|
||||
int numgames;
|
||||
} fs_globals_t;
|
||||
|
||||
typedef void (*fs_event_callback_t)( const char *path );
|
||||
|
||||
typedef struct fs_api_t
|
||||
{
|
||||
qboolean (*InitStdio)( qboolean unused_set_to_true, const char *rootdir, const char *basedir, const char *gamedir, const char *rodir );
|
||||
@@ -199,6 +200,9 @@ typedef struct fs_api_t
|
||||
|
||||
// like LoadFile but returns pointer that can be free'd using standard library function
|
||||
byte *(*LoadFileMalloc)( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly );
|
||||
|
||||
// queries supported archive formats
|
||||
qboolean (*IsArchiveExtensionSupported)( const char *ext, uint flags );
|
||||
} fs_api_t;
|
||||
|
||||
typedef struct fs_interface_t
|
||||
@@ -221,7 +225,7 @@ typedef struct fs_interface_t
|
||||
void *(*_Sys_GetNativeObject)( const char *object );
|
||||
} fs_interface_t;
|
||||
|
||||
typedef int (*FSAPI)( int version, fs_api_t *api, fs_globals_t **globals, fs_interface_t *interface );
|
||||
typedef int (*FSAPI)( int version, fs_api_t *api, fs_globals_t **globals, const fs_interface_t *interface );
|
||||
#define GET_FS_API "GetFSAPI"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -114,6 +114,7 @@ typedef struct fs_archive_s
|
||||
int type;
|
||||
FS_ADDARCHIVE_FULLPATH pfnAddArchive_Fullpath;
|
||||
qboolean load_wads; // load wads from this archive
|
||||
qboolean real_archive;
|
||||
} fs_archive_t;
|
||||
|
||||
extern fs_globals_t FI;
|
||||
@@ -123,7 +124,7 @@ extern fs_interface_t g_engfuncs;
|
||||
extern qboolean fs_ext_path;
|
||||
extern char fs_rodir[MAX_SYSPATH];
|
||||
extern char fs_rootdir[MAX_SYSPATH];
|
||||
extern fs_api_t g_api;
|
||||
extern const fs_api_t g_api;
|
||||
extern const fs_archive_t g_archives[];
|
||||
|
||||
#define GI FI.GameInfo
|
||||
|
||||
@@ -69,7 +69,7 @@ struct pack_s
|
||||
{
|
||||
file_t *handle;
|
||||
int numfiles;
|
||||
dpackfile_t files[1]; // flexible
|
||||
dpackfile_t files[]; // flexible
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -150,7 +150,7 @@ static pack_t *FS_LoadPackPAK( const char *packfile, int *error )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pack = (pack_t *)Mem_Calloc( fs_mempool, sizeof( pack_t ) + sizeof( dpackfile_t ) * ( numpackfiles - 1 ));
|
||||
pack = (pack_t *)Mem_Calloc( fs_mempool, sizeof( pack_t ) + sizeof( dpackfile_t ) * numpackfiles );
|
||||
FS_Seek( packhandle, header.dirofs, SEEK_SET );
|
||||
|
||||
if( header.dirlen != FS_Read( packhandle, (void *)pack->files, header.dirlen ))
|
||||
|
||||
@@ -57,6 +57,15 @@ static int TestNoInit( void )
|
||||
p = g_fs.LoadDirectFile( "hehe", NULL );
|
||||
if( p ) free( p );
|
||||
|
||||
if( !g_fs.IsArchiveExtensionSupported( "pk3", 0 )) return 0;
|
||||
if( !g_fs.IsArchiveExtensionSupported( "wad", 0 )) return 0;
|
||||
if( !g_fs.IsArchiveExtensionSupported( "pak", 0 )) return 0;
|
||||
if( !g_fs.IsArchiveExtensionSupported( "pk3dir", 0 )) return 0;
|
||||
|
||||
if( !g_fs.IsArchiveExtensionSupported( "pk3", IAES_ONLY_REAL_ARCHIVES )) return 0;
|
||||
if( g_fs.IsArchiveExtensionSupported( "pk3dir", IAES_ONLY_REAL_ARCHIVES )) return 0;
|
||||
if( g_fs.IsArchiveExtensionSupported( "vpk", 0)) return 0;
|
||||
|
||||
g_fs.FileExists( "asdcv", 0 );
|
||||
g_fs.FileTime( "zxcasdfd", 0 );
|
||||
g_fs.FileSize( "asdqwe", 1 );
|
||||
|
||||
@@ -125,7 +125,7 @@ struct zip_s
|
||||
{
|
||||
file_t *handle;
|
||||
int numfiles;
|
||||
zipfile_t files[1]; // flexible
|
||||
zipfile_t files[]; // flexible
|
||||
};
|
||||
|
||||
// #define ENABLE_CRC_CHECK // known to be buggy because of possible libpublic crc32 bug, disabled
|
||||
@@ -285,7 +285,7 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
|
||||
FS_Seek( zip->handle, header_eocd.central_directory_offset, SEEK_SET );
|
||||
|
||||
// Calc count of files in archive
|
||||
zip = (zip_t *)Mem_Realloc( fs_mempool, zip, sizeof( *zip ) + sizeof( *info ) * ( header_eocd.total_central_directory_record - 1 ));
|
||||
zip = (zip_t *)Mem_Realloc( fs_mempool, zip, sizeof( *zip ) + sizeof( *info ) * header_eocd.total_central_directory_record );
|
||||
info = zip->files;
|
||||
|
||||
for( i = 0; i < header_eocd.total_central_directory_record; i++ )
|
||||
|
||||
@@ -44,9 +44,8 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
||||
#error // port me!
|
||||
#endif
|
||||
|
||||
#define E_GAME "XASH3D_GAME" // default env dir to start from
|
||||
#ifndef XASH_GAMEDIR
|
||||
#define XASH_GAMEDIR "valve"
|
||||
#define XASH_GAMEDIR "valve" // !!! Replace with your default (base) game directory !!!
|
||||
#endif
|
||||
|
||||
typedef void (*pfnChangeGame)( const char *progname );
|
||||
@@ -151,7 +150,6 @@ _inline int Sys_Start( void )
|
||||
{
|
||||
int ret;
|
||||
pfnChangeGame changeGame = NULL;
|
||||
const char *game = getenv( E_GAME );
|
||||
|
||||
#if XASH_SAILFISH
|
||||
const char *home = getenv( "HOME" );
|
||||
@@ -166,10 +164,7 @@ _inline int Sys_Start( void )
|
||||
#endif // XASH_AURORAOS
|
||||
#endif // XASH_SAILFISH
|
||||
|
||||
if( !game )
|
||||
game = XASH_GAMEDIR;
|
||||
|
||||
strncpy( szGameDir, game, sizeof( szGameDir ) - 1 );
|
||||
strncpy( szGameDir, XASH_GAMEDIR, sizeof( szGameDir ) - 1 );
|
||||
|
||||
Sys_LoadEngine();
|
||||
|
||||
|
||||
@@ -686,15 +686,19 @@ void COM_FixSlashes( char *pname )
|
||||
/*
|
||||
============
|
||||
COM_PathSlashFix
|
||||
|
||||
ensure directory path always ends on forward slash
|
||||
============
|
||||
*/
|
||||
void COM_PathSlashFix( char *path )
|
||||
{
|
||||
size_t len;
|
||||
size_t len = Q_strlen( path );
|
||||
|
||||
len = Q_strlen( path );
|
||||
|
||||
if( path[len - 1] != '\\' && path[len - 1] != '/' )
|
||||
if( path[len - 1] == '\\' )
|
||||
{
|
||||
path[len - 1] = '/';
|
||||
}
|
||||
else if( path[len - 1] != '/' )
|
||||
{
|
||||
path[len] = '/';
|
||||
path[len + 1] = '\0';
|
||||
|
||||
@@ -71,7 +71,11 @@ def configure(conf):
|
||||
conf.env.DEFINES_export = list(conf.env.EXPORT_DEFINES_LIST)
|
||||
|
||||
# check platform-specific header name for alloca(3)
|
||||
if conf.simple_check(ALLOCA_TEST % 'alloca.h', msg='alloca in alloca.h'):
|
||||
if conf.env.DEST_OS == 'win32':
|
||||
# don't waste time on Win32, it's documented to be always in malloc.h.
|
||||
# (plus test can fail because alloca is underscore-prefixed, e.g. _alloca)
|
||||
conf.export_define('ALLOCA_H', '<malloc.h>')
|
||||
elif conf.simple_check(ALLOCA_TEST % 'alloca.h', msg='alloca in alloca.h'):
|
||||
conf.export_define('ALLOCA_H', '<alloca.h>')
|
||||
elif conf.simple_check(ALLOCA_TEST % 'malloc.h', msg='alloca in malloc.h'):
|
||||
conf.export_define('ALLOCA_H', '<malloc.h>')
|
||||
|
||||
@@ -52,15 +52,10 @@ ALIAS MODEL DISPLAY LIST GENERATION
|
||||
*/
|
||||
static qboolean m_fDoRemap;
|
||||
static aliashdr_t *m_pAliasHeader;
|
||||
static trivertex_t *g_poseverts[MAXALIASFRAMES];
|
||||
static dtriangle_t g_triangles[MAXALIASTRIS];
|
||||
static stvert_t g_stverts[MAXALIASVERTS];
|
||||
static int g_used[8192];
|
||||
|
||||
// a pose is a single set of vertexes. a frame may be
|
||||
// an animating sequence of poses
|
||||
static int g_posenum;
|
||||
|
||||
// the command list holds counts and s/t values that are valid for
|
||||
// every frame
|
||||
static int g_commands[8192];
|
||||
@@ -324,7 +319,7 @@ static void GL_MakeAliasModelDisplayLists( model_t *m )
|
||||
for( i = 0; i < m_pAliasHeader->numposes; i++ )
|
||||
{
|
||||
for( j = 0; j < g_numorder; j++ )
|
||||
*verts++ = g_poseverts[i][g_vertexorder[j]];
|
||||
*verts++ = m_pAliasHeader->pposeverts[i][g_vertexorder[j]];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,85 +330,14 @@ ALIAS MODELS
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
/*
|
||||
=================
|
||||
Mod_LoadAliasFrame
|
||||
=================
|
||||
*/
|
||||
static void *Mod_LoadAliasFrame( void *pin, maliasframedesc_t *frame )
|
||||
{
|
||||
daliasframe_t *pdaliasframe;
|
||||
trivertex_t *pinframe;
|
||||
int i;
|
||||
|
||||
pdaliasframe = (daliasframe_t *)pin;
|
||||
|
||||
Q_strncpy( frame->name, pdaliasframe->name, sizeof( frame->name ));
|
||||
frame->firstpose = g_posenum;
|
||||
frame->numposes = 1;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
frame->bboxmin.v[i] = pdaliasframe->bboxmin.v[i];
|
||||
frame->bboxmax.v[i] = pdaliasframe->bboxmax.v[i];
|
||||
}
|
||||
|
||||
pinframe = (trivertex_t *)(pdaliasframe + 1);
|
||||
|
||||
g_poseverts[g_posenum] = (trivertex_t *)pinframe;
|
||||
pinframe += m_pAliasHeader->numverts;
|
||||
g_posenum++;
|
||||
|
||||
return (void *)pinframe;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_LoadAliasGroup
|
||||
=================
|
||||
*/
|
||||
static void *Mod_LoadAliasGroup( void *pin, maliasframedesc_t *frame )
|
||||
{
|
||||
daliasgroup_t *pingroup;
|
||||
int i, numframes;
|
||||
daliasinterval_t *pin_intervals;
|
||||
void *ptemp;
|
||||
|
||||
pingroup = (daliasgroup_t *)pin;
|
||||
numframes = pingroup->numframes;
|
||||
|
||||
frame->firstpose = g_posenum;
|
||||
frame->numposes = numframes;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
frame->bboxmin.v[i] = pingroup->bboxmin.v[i];
|
||||
frame->bboxmax.v[i] = pingroup->bboxmax.v[i];
|
||||
}
|
||||
|
||||
pin_intervals = (daliasinterval_t *)(pingroup + 1);
|
||||
|
||||
// all the intervals are always equal 0.1 so we don't care about them
|
||||
frame->interval = pin_intervals->interval;
|
||||
pin_intervals += numframes;
|
||||
ptemp = (void *)pin_intervals;
|
||||
|
||||
for( i = 0; i < numframes; i++ )
|
||||
{
|
||||
g_poseverts[g_posenum] = (trivertex_t *)((daliasframe_t *)ptemp + 1);
|
||||
ptemp = (trivertex_t *)((daliasframe_t *)ptemp + 1) + m_pAliasHeader->numverts;
|
||||
g_posenum++;
|
||||
}
|
||||
|
||||
return ptemp;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Mod_CreateSkinData
|
||||
===============
|
||||
*/
|
||||
static rgbdata_t *Mod_CreateSkinData( model_t *mod, byte *data, int width, int height )
|
||||
static rgbdata_t *Mod_CreateSkinData( model_t *mod, const byte *data, int width, int height )
|
||||
{
|
||||
static rgbdata_t skin;
|
||||
char name[MAX_QPATH];
|
||||
@@ -426,7 +350,7 @@ static rgbdata_t *Mod_CreateSkinData( model_t *mod, byte *data, int width, int h
|
||||
skin.flags = IMAGE_HAS_COLOR|IMAGE_QUAKEPAL;
|
||||
skin.encode = DXT_ENCODE_DEFAULT;
|
||||
skin.numMips = 1;
|
||||
skin.buffer = data;
|
||||
skin.buffer = (byte *)data;
|
||||
skin.palette = (byte *)tr.palette;
|
||||
skin.size = width * height;
|
||||
|
||||
@@ -475,67 +399,68 @@ static rgbdata_t *Mod_CreateSkinData( model_t *mod, byte *data, int width, int h
|
||||
return gEngfuncs.FS_CopyImage( &skin );
|
||||
}
|
||||
|
||||
static void *Mod_LoadSingleSkin( model_t *loadmodel, daliasskintype_t *pskintype, int skinnum, int size )
|
||||
static const void *Mod_LoadSingleSkin( model_t *loadmodel, const daliasskintype_t *pskintype, int skinnum, int size )
|
||||
{
|
||||
string name, lumaname;
|
||||
string checkname;
|
||||
rgbdata_t *pic;
|
||||
const byte *ptexture = (const byte *)&pskintype[1];
|
||||
rgbdata_t *pic;
|
||||
string name, lumaname, checkname;
|
||||
|
||||
Q_snprintf( name, sizeof( name ), "%s:frame%i", loadmodel->name, skinnum );
|
||||
Q_snprintf( lumaname, sizeof( lumaname ), "%s:luma%i", loadmodel->name, skinnum );
|
||||
Q_snprintf( checkname, sizeof( checkname ), "%s_%i.tga", loadmodel->name, skinnum );
|
||||
if( !gEngfuncs.fsapi->FileExists( checkname, false ) || ( pic = gEngfuncs.FS_LoadImage( checkname, NULL, 0 )) == NULL )
|
||||
pic = Mod_CreateSkinData( loadmodel, (byte *)(pskintype + 1), m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
|
||||
pic = Mod_CreateSkinData( loadmodel, ptexture, m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
|
||||
|
||||
m_pAliasHeader->gl_texturenum[skinnum][0] =
|
||||
m_pAliasHeader->gl_texturenum[skinnum][1] =
|
||||
m_pAliasHeader->gl_texturenum[skinnum][2] =
|
||||
m_pAliasHeader->gl_texturenum[skinnum][3] = GL_LoadTextureInternal( name, pic, 0 );
|
||||
m_pAliasHeader->gl_texturenum[skinnum][1] =
|
||||
m_pAliasHeader->gl_texturenum[skinnum][2] =
|
||||
m_pAliasHeader->gl_texturenum[skinnum][3] = GL_LoadTextureInternal( name, pic, 0 );
|
||||
gEngfuncs.FS_FreeImage( pic );
|
||||
|
||||
if( R_GetTexture( m_pAliasHeader->gl_texturenum[skinnum][0] )->flags & TF_HAS_LUMA )
|
||||
if( FBitSet( R_GetTexture( m_pAliasHeader->gl_texturenum[skinnum][0] )->flags, TF_HAS_LUMA ))
|
||||
{
|
||||
pic = Mod_CreateSkinData( NULL, (byte *)(pskintype + 1), m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
|
||||
Q_snprintf( lumaname, sizeof( lumaname ), "%s:luma%i", loadmodel->name, skinnum );
|
||||
|
||||
pic = Mod_CreateSkinData( NULL, ptexture, m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
|
||||
m_pAliasHeader->fb_texturenum[skinnum][0] =
|
||||
m_pAliasHeader->fb_texturenum[skinnum][1] =
|
||||
m_pAliasHeader->fb_texturenum[skinnum][2] =
|
||||
m_pAliasHeader->fb_texturenum[skinnum][3] = GL_LoadTextureInternal( lumaname, pic, TF_MAKELUMA );
|
||||
m_pAliasHeader->fb_texturenum[skinnum][1] =
|
||||
m_pAliasHeader->fb_texturenum[skinnum][2] =
|
||||
m_pAliasHeader->fb_texturenum[skinnum][3] = GL_LoadTextureInternal( lumaname, pic, TF_MAKELUMA );
|
||||
gEngfuncs.FS_FreeImage( pic );
|
||||
}
|
||||
|
||||
return ((byte *)(pskintype + 1) + size);
|
||||
return ptexture + size;
|
||||
}
|
||||
|
||||
static void *Mod_LoadGroupSkin( model_t *loadmodel, daliasskintype_t *pskintype, int skinnum, int size )
|
||||
static const void *Mod_LoadGroupSkin( model_t *loadmodel, const daliasskintype_t *pskintype, int skinnum, int size )
|
||||
{
|
||||
daliasskininterval_t *pinskinintervals;
|
||||
daliasskingroup_t *pinskingroup;
|
||||
string name, lumaname;
|
||||
rgbdata_t *pic;
|
||||
int i, j;
|
||||
const daliasskininterval_t *pinskinintervals;
|
||||
const daliasskingroup_t *pinskingroup;
|
||||
const byte *ptexture;
|
||||
rgbdata_t *pic;
|
||||
string name, lumaname;
|
||||
int i, j;
|
||||
|
||||
// animating skin group. yuck.
|
||||
pskintype++;
|
||||
pinskingroup = (daliasskingroup_t *)pskintype;
|
||||
pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
|
||||
pskintype = (void *)(pinskinintervals + pinskingroup->numskins);
|
||||
pinskingroup = (const daliasskingroup_t *)&pskintype[1];
|
||||
pinskinintervals = (const daliasskininterval_t *)(&pinskingroup[1]);
|
||||
ptexture = (const byte *)&pinskinintervals[pinskingroup->numskins];
|
||||
|
||||
for( i = 0; i < pinskingroup->numskins; i++ )
|
||||
{
|
||||
Q_snprintf( name, sizeof( name ), "%s_%i_%i", loadmodel->name, skinnum, i );
|
||||
pic = Mod_CreateSkinData( loadmodel, (byte *)(pskintype), m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
|
||||
pic = Mod_CreateSkinData( loadmodel, ptexture, m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
|
||||
m_pAliasHeader->gl_texturenum[skinnum][i & 3] = GL_LoadTextureInternal( name, pic, 0 );
|
||||
gEngfuncs.FS_FreeImage( pic );
|
||||
|
||||
if( R_GetTexture( m_pAliasHeader->gl_texturenum[skinnum][i & 3] )->flags & TF_HAS_LUMA )
|
||||
if( FBitSet( R_GetTexture( m_pAliasHeader->gl_texturenum[skinnum][i & 3] )->flags, TF_HAS_LUMA ))
|
||||
{
|
||||
Q_snprintf( lumaname, sizeof( lumaname ), "%s_%i_%i_luma", loadmodel->name, skinnum, i );
|
||||
pic = Mod_CreateSkinData( NULL, (byte *)(pskintype), m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
|
||||
pic = Mod_CreateSkinData( NULL, ptexture, m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
|
||||
m_pAliasHeader->fb_texturenum[skinnum][i & 3] = GL_LoadTextureInternal( lumaname, pic, TF_MAKELUMA );
|
||||
gEngfuncs.FS_FreeImage( pic );
|
||||
}
|
||||
|
||||
pskintype = (daliasskintype_t *)((byte *)(pskintype) + size);
|
||||
ptexture += size;
|
||||
}
|
||||
|
||||
for( j = i; i < 4; i++ )
|
||||
@@ -544,7 +469,7 @@ static void *Mod_LoadGroupSkin( model_t *loadmodel, daliasskintype_t *pskintype,
|
||||
m_pAliasHeader->fb_texturenum[skinnum][i & 3] = m_pAliasHeader->fb_texturenum[skinnum][i - j];
|
||||
}
|
||||
|
||||
return pskintype;
|
||||
return ptexture;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -552,66 +477,25 @@ static void *Mod_LoadGroupSkin( model_t *loadmodel, daliasskintype_t *pskintype,
|
||||
Mod_LoadAllSkins
|
||||
===============
|
||||
*/
|
||||
static void *Mod_LoadAllSkins( model_t *mod, int numskins, daliasskintype_t *pskintype )
|
||||
static const void *Mod_LoadAllSkins( model_t *mod, int numskins, const daliasskintype_t *pskintype )
|
||||
{
|
||||
int i, size;
|
||||
|
||||
if( numskins < 1 || numskins > MAX_SKINS )
|
||||
gEngfuncs.Host_Error( "%s: Invalid # of skins: %d\n", __func__, numskins );
|
||||
|
||||
size = m_pAliasHeader->skinwidth * m_pAliasHeader->skinheight;
|
||||
|
||||
// TODO: texture replacement support here
|
||||
|
||||
for( i = 0; i < numskins; i++ )
|
||||
{
|
||||
if( pskintype->type == ALIAS_SKIN_SINGLE )
|
||||
{
|
||||
pskintype = (daliasskintype_t *)Mod_LoadSingleSkin( mod, pskintype, i, size );
|
||||
}
|
||||
pskintype = Mod_LoadSingleSkin( mod, pskintype, i, size );
|
||||
else
|
||||
{
|
||||
pskintype = (daliasskintype_t *)Mod_LoadGroupSkin( mod, pskintype, i, size );
|
||||
}
|
||||
pskintype = Mod_LoadGroupSkin( mod, pskintype, i, size );
|
||||
}
|
||||
|
||||
return (void *)pskintype;
|
||||
return pskintype;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
/*
|
||||
=================
|
||||
Mod_CalcAliasBounds
|
||||
=================
|
||||
*/
|
||||
static void Mod_CalcAliasBounds( model_t *mod )
|
||||
{
|
||||
int i, j, k;
|
||||
float radius;
|
||||
float dist;
|
||||
vec3_t v;
|
||||
|
||||
ClearBounds( mod->mins, mod->maxs );
|
||||
radius = 0.0f;
|
||||
|
||||
// process verts
|
||||
for( i = 0; i < m_pAliasHeader->numposes; i++ )
|
||||
{
|
||||
for( j = 0; j < m_pAliasHeader->numverts; j++ )
|
||||
{
|
||||
for( k = 0; k < 3; k++ )
|
||||
v[k] = g_poseverts[i][j].v[k] * m_pAliasHeader->scale[k] + m_pAliasHeader->scale_origin[k];
|
||||
|
||||
AddPointToBounds( v, mod->mins, mod->maxs );
|
||||
dist = DotProduct( v, v );
|
||||
|
||||
if( radius < dist )
|
||||
radius = dist;
|
||||
}
|
||||
}
|
||||
|
||||
mod->radius = sqrt( radius );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
@@ -620,111 +504,34 @@ Mod_LoadAliasModel
|
||||
*/
|
||||
void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *loaded )
|
||||
{
|
||||
daliashdr_t *pinmodel;
|
||||
stvert_t *pinstverts;
|
||||
dtriangle_t *pintriangles;
|
||||
daliasframetype_t *pframetype;
|
||||
daliasskintype_t *pskintype;
|
||||
int i, j, size;
|
||||
char poolname[MAX_VA_STRING];
|
||||
const daliasskintype_t *pskintype;
|
||||
const dtriangle_t *pintriangles;
|
||||
const daliashdr_t *pinmodel;
|
||||
const stvert_t *pinstverts;
|
||||
|
||||
if( loaded ) *loaded = false;
|
||||
pinmodel = (daliashdr_t *)buffer;
|
||||
i = pinmodel->version;
|
||||
|
||||
if( i != ALIAS_VERSION )
|
||||
{
|
||||
gEngfuncs.Con_DPrintf( S_ERROR "%s has wrong version number (%i should be %i)\n", mod->name, i, ALIAS_VERSION );
|
||||
return;
|
||||
}
|
||||
|
||||
if( pinmodel->numverts <= 0 || pinmodel->numtris <= 0 || pinmodel->numframes <= 0 )
|
||||
return; // how to possible is make that?
|
||||
|
||||
Q_snprintf( poolname, sizeof( poolname ), "^2%s^7", mod->name );
|
||||
mod->mempool = Mem_AllocPool( poolname );
|
||||
|
||||
// allocate space for a working header, plus all the data except the frames,
|
||||
// skin and group info
|
||||
size = sizeof( aliashdr_t ) + (pinmodel->numframes - 1) * sizeof( maliasframedesc_t );
|
||||
|
||||
m_pAliasHeader = Mem_Calloc( mod->mempool, size );
|
||||
mod->flags = pinmodel->flags; // share effects flags
|
||||
|
||||
// endian-adjust and copy the data, starting with the alias model header
|
||||
m_pAliasHeader->boundingradius = pinmodel->boundingradius;
|
||||
m_pAliasHeader->numskins = pinmodel->numskins;
|
||||
m_pAliasHeader->skinwidth = pinmodel->skinwidth;
|
||||
m_pAliasHeader->skinheight = pinmodel->skinheight;
|
||||
m_pAliasHeader->numverts = pinmodel->numverts;
|
||||
m_pAliasHeader->numtris = pinmodel->numtris;
|
||||
m_pAliasHeader->numframes = pinmodel->numframes;
|
||||
|
||||
if( m_pAliasHeader->numverts > MAXALIASVERTS )
|
||||
{
|
||||
gEngfuncs.Con_DPrintf( S_ERROR "model %s has too many vertices\n", mod->name );
|
||||
return;
|
||||
}
|
||||
|
||||
m_pAliasHeader->size = pinmodel->size;
|
||||
// mod->synctype = pinmodel->synctype;
|
||||
mod->numframes = m_pAliasHeader->numframes;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
m_pAliasHeader->scale[i] = pinmodel->scale[i];
|
||||
m_pAliasHeader->scale_origin[i] = pinmodel->scale_origin[i];
|
||||
m_pAliasHeader->eyeposition[i] = pinmodel->eyeposition[i];
|
||||
}
|
||||
pinmodel = (const daliashdr_t *)buffer;
|
||||
m_pAliasHeader = mod->cache.data;
|
||||
if( !m_pAliasHeader ) return;
|
||||
|
||||
// load the skins
|
||||
pskintype = (daliasskintype_t *)&pinmodel[1];
|
||||
pskintype = (const daliasskintype_t *)&pinmodel[1];
|
||||
pskintype = Mod_LoadAllSkins( mod, m_pAliasHeader->numskins, pskintype );
|
||||
|
||||
// load base s and t vertices
|
||||
pinstverts = (stvert_t *)pskintype;
|
||||
|
||||
for( i = 0; i < m_pAliasHeader->numverts; i++ )
|
||||
{
|
||||
g_stverts[i].onseam = pinstverts[i].onseam;
|
||||
g_stverts[i].s = pinstverts[i].s;
|
||||
g_stverts[i].t = pinstverts[i].t;
|
||||
}
|
||||
pinstverts = (const stvert_t *)pskintype;
|
||||
memset( g_stverts, 0, sizeof( g_stverts ));
|
||||
memcpy( g_stverts, pinstverts, sizeof( g_stverts[0] ) * m_pAliasHeader->numverts );
|
||||
|
||||
// load triangle lists
|
||||
pintriangles = (dtriangle_t *)&pinstverts[m_pAliasHeader->numverts];
|
||||
|
||||
for( i = 0; i < m_pAliasHeader->numtris; i++ )
|
||||
{
|
||||
g_triangles[i].facesfront = pintriangles[i].facesfront;
|
||||
|
||||
for( j = 0; j < 3; j++ )
|
||||
g_triangles[i].vertindex[j] = pintriangles[i].vertindex[j];
|
||||
}
|
||||
|
||||
// load the frames
|
||||
pframetype = (daliasframetype_t *)&pintriangles[m_pAliasHeader->numtris];
|
||||
g_posenum = 0;
|
||||
|
||||
for( i = 0; i < m_pAliasHeader->numframes; i++ )
|
||||
{
|
||||
aliasframetype_t frametype = pframetype->type;
|
||||
|
||||
if( frametype == ALIAS_SINGLE )
|
||||
pframetype = (daliasframetype_t *)Mod_LoadAliasFrame( pframetype + 1, &m_pAliasHeader->frames[i] );
|
||||
else pframetype = (daliasframetype_t *)Mod_LoadAliasGroup( pframetype + 1, &m_pAliasHeader->frames[i] );
|
||||
}
|
||||
|
||||
m_pAliasHeader->numposes = g_posenum;
|
||||
|
||||
Mod_CalcAliasBounds( mod );
|
||||
mod->type = mod_alias;
|
||||
pintriangles = (const dtriangle_t *)&pinstverts[m_pAliasHeader->numverts];
|
||||
memset( g_triangles, 0, sizeof( g_triangles ));
|
||||
memcpy( g_triangles, pintriangles, sizeof( g_triangles[0] ) * m_pAliasHeader->numtris );
|
||||
|
||||
// build the draw lists
|
||||
GL_MakeAliasModelDisplayLists( mod );
|
||||
|
||||
// move the complete, relocatable alias model to the cache
|
||||
mod->cache.data = m_pAliasHeader;
|
||||
m_pAliasHeader = NULL;
|
||||
|
||||
if( loaded ) *loaded = true; // done
|
||||
}
|
||||
|
||||
@@ -422,7 +422,7 @@ static const char *R_GetConfigName( void )
|
||||
return "opengl";
|
||||
}
|
||||
|
||||
static ref_interface_t gReffuncs =
|
||||
static const ref_interface_t gReffuncs =
|
||||
{
|
||||
R_Init,
|
||||
R_Shutdown,
|
||||
@@ -569,8 +569,8 @@ int EXPORT GetRefAPI( int version, ref_interface_t *funcs, ref_api_t *engfuncs,
|
||||
return 0;
|
||||
|
||||
// fill in our callbacks
|
||||
memcpy( funcs, &gReffuncs, sizeof( ref_interface_t ));
|
||||
memcpy( &gEngfuncs, engfuncs, sizeof( ref_api_t ));
|
||||
*funcs = gReffuncs;
|
||||
gEngfuncs = *engfuncs;
|
||||
gpGlobals = globals;
|
||||
|
||||
gp_cl = (ref_client_t *)ENGINE_GET_PARM( PARM_GET_CLIENT_PTR );
|
||||
|
||||
@@ -492,10 +492,10 @@ R_DecalCreatePoly
|
||||
creates mesh for decal on first rendering
|
||||
====================
|
||||
*/
|
||||
static glpoly_t *R_DecalCreatePoly( decalinfo_t *decalinfo, decal_t *pdecal, msurface_t *surf )
|
||||
static glpoly2_t *R_DecalCreatePoly( decalinfo_t *decalinfo, decal_t *pdecal, msurface_t *surf )
|
||||
{
|
||||
int lnumverts;
|
||||
glpoly_t *poly;
|
||||
glpoly2_t *poly;
|
||||
float *v;
|
||||
int i;
|
||||
|
||||
@@ -507,7 +507,7 @@ static glpoly_t *R_DecalCreatePoly( decalinfo_t *decalinfo, decal_t *pdecal, msu
|
||||
|
||||
// allocate glpoly
|
||||
// REFTODO: com_studiocache pool!
|
||||
poly = Mem_Calloc( r_temppool, sizeof( glpoly_t ) + ( lnumverts - 4 ) * VERTEXSIZE * sizeof( float ));
|
||||
poly = Mem_Calloc( r_temppool, sizeof( glpoly2_t ) + lnumverts * VERTEXSIZE * sizeof( float ));
|
||||
poly->next = pdecal->polys;
|
||||
poly->flags = surf->flags;
|
||||
pdecal->polys = poly;
|
||||
@@ -829,7 +829,7 @@ void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos
|
||||
// triangles the same way.
|
||||
float *R_DecalSetupVerts( decal_t *pDecal, msurface_t *surf, int texture, int *outCount )
|
||||
{
|
||||
glpoly_t *p = pDecal->polys;
|
||||
glpoly2_t *p = pDecal->polys;
|
||||
int i, count;
|
||||
float *v, *v2;
|
||||
|
||||
|
||||
@@ -433,7 +433,7 @@ void R_DrawWaterSurfaces( void );
|
||||
void R_DrawBrushModel( cl_entity_t *e );
|
||||
void GL_SubdivideSurface( model_t *mod, msurface_t *fa );
|
||||
void GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa );
|
||||
void DrawGLPoly( glpoly_t *p, float xScale, float yScale );
|
||||
void DrawGLPoly( glpoly2_t *p, float xScale, float yScale );
|
||||
texture_t *R_TextureAnimation( msurface_t *s );
|
||||
void GL_SetupFogColorForSurfaces( void );
|
||||
void R_DrawAlphaTextureChains( void );
|
||||
@@ -538,8 +538,6 @@ void R_RunViewmodelEvents( void );
|
||||
void R_DrawViewModel( void );
|
||||
int R_GetSpriteTexture( const struct model_s *m_pSpriteModel, int frame );
|
||||
void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, float scale );
|
||||
void R_RemoveEfrags( struct cl_entity_s *ent );
|
||||
void R_AddEfrags( struct cl_entity_s *ent );
|
||||
void R_DecalRemoveAll( int texture );
|
||||
int R_CreateDecalList( decallist_t *pList );
|
||||
void R_ClearAllDecals( void );
|
||||
|
||||
@@ -281,7 +281,6 @@ void CL_DrawParticlesExternal( const ref_viewpass_t *rvp, qboolean trans_pass, f
|
||||
{
|
||||
ref_instance_t oldRI = RI;
|
||||
|
||||
memcpy( &oldRI, &RI, sizeof( ref_instance_t ));
|
||||
R_SetupRefParams( rvp );
|
||||
R_SetupFrustum();
|
||||
R_SetupGL( false ); // don't touch GL-states
|
||||
@@ -290,5 +289,5 @@ void CL_DrawParticlesExternal( const ref_viewpass_t *rvp, qboolean trans_pass, f
|
||||
gEngfuncs.CL_DrawEFX( frametime, trans_pass );
|
||||
|
||||
// restore internal state
|
||||
memcpy( &RI, &oldRI, sizeof( ref_instance_t ));
|
||||
RI = oldRI;
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ static void SubdividePolygon_r( model_t *loadmodel, msurface_t *warpface, int nu
|
||||
int i, j, k, f, b;
|
||||
float sample_size;
|
||||
vec3_t mins, maxs;
|
||||
glpoly_t *poly;
|
||||
glpoly2_t *poly;
|
||||
|
||||
if( numverts > ( SUBDIVIDE_SIZE - 4 ))
|
||||
gEngfuncs.Host_Error( "%s: too many vertexes on face ( %i )\n", __func__, numverts );
|
||||
@@ -196,7 +196,7 @@ static void SubdividePolygon_r( model_t *loadmodel, msurface_t *warpface, int nu
|
||||
ClearBits( warpface->flags, SURF_DRAWTURB_QUADS );
|
||||
|
||||
// add a point in the center to help keep warp valid
|
||||
poly = Mem_Calloc( loadmodel->mempool, sizeof( glpoly_t ) + (numverts - 4) * VERTEXSIZE * sizeof( float ));
|
||||
poly = Mem_Calloc( loadmodel->mempool, sizeof( glpoly2_t ) + numverts * VERTEXSIZE * sizeof( float ));
|
||||
poly->next = warpface->polys;
|
||||
poly->flags = warpface->flags;
|
||||
warpface->polys = poly;
|
||||
@@ -302,7 +302,7 @@ void GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa )
|
||||
float sample_size;
|
||||
texture_t *tex;
|
||||
gl_texture_t *glt;
|
||||
glpoly_t *poly;
|
||||
glpoly2_t *poly;
|
||||
|
||||
if( !mod || !fa->texinfo || !fa->texinfo->texture )
|
||||
return; // bad polygon ?
|
||||
@@ -328,7 +328,7 @@ void GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa )
|
||||
fa->polys = NULL;
|
||||
|
||||
// quake simple models (healthkits etc) need to be reconstructed their polys because LM coords has changed after the map change
|
||||
poly = Mem_Realloc( mod->mempool, poly, sizeof( glpoly_t ) + ( lnumverts - 4 ) * VERTEXSIZE * sizeof( float ));
|
||||
poly = Mem_Realloc( mod->mempool, poly, sizeof( glpoly2_t ) + lnumverts * VERTEXSIZE * sizeof( float ));
|
||||
poly->next = fa->polys;
|
||||
poly->flags = fa->flags;
|
||||
fa->polys = poly;
|
||||
@@ -773,7 +773,7 @@ static void R_BuildLightMap( msurface_t *surf, byte *dest, int stride, qboolean
|
||||
DrawGLPoly
|
||||
================
|
||||
*/
|
||||
void DrawGLPoly( glpoly_t *p, float xScale, float yScale )
|
||||
void DrawGLPoly( glpoly2_t *p, float xScale, float yScale )
|
||||
{
|
||||
float *v;
|
||||
float sOffset, sy;
|
||||
@@ -851,7 +851,7 @@ DrawGLPolyChain
|
||||
Render lightmaps
|
||||
================
|
||||
*/
|
||||
static void DrawGLPolyChain( glpoly_t *p, float soffset, float toffset )
|
||||
static void DrawGLPolyChain( glpoly2_t *p, float soffset, float toffset )
|
||||
{
|
||||
qboolean dynamic = true;
|
||||
|
||||
@@ -1855,6 +1855,7 @@ void R_GenerateVBO( void )
|
||||
int k, len = 0;
|
||||
vboarray_t *vbo;
|
||||
uint maxindex = 0;
|
||||
double t1, t2, t3;
|
||||
|
||||
R_ClearVBO();
|
||||
|
||||
@@ -1865,6 +1866,8 @@ void R_GenerateVBO( void )
|
||||
return;
|
||||
}
|
||||
|
||||
t1 = gEngfuncs.pfnTime();
|
||||
|
||||
// save in config if enabled manually
|
||||
if( r_vbo.value )
|
||||
r_vbo.flags |= FCVAR_ARCHIVE;
|
||||
@@ -1914,7 +1917,7 @@ void R_GenerateVBO( void )
|
||||
vbotex->vboarray = vbo;
|
||||
// generate new array and new vbotexture node
|
||||
vbo->array = Mem_Calloc( vbos.mempool, sizeof( vbovertex_t ) * vbo->array_len );
|
||||
gEngfuncs.Con_Printf( "%s: allocated array of %d verts, texture %d, lm %d\n", __func__, vbo->array_len, j, k );
|
||||
gEngfuncs.Con_Printf( S_NOTE "%s: allocated array of %d verts, texture %d, lm %d\n", __func__, vbo->array_len, j, k );
|
||||
vbo->next = Mem_Calloc( vbos.mempool, sizeof( vboarray_t ) );
|
||||
vbo = vbo->next;
|
||||
vbotex->next = Mem_Calloc( vbos.mempool, sizeof( vbotexture_t ) );
|
||||
@@ -1942,7 +1945,9 @@ void R_GenerateVBO( void )
|
||||
|
||||
// allocate last array
|
||||
vbo->array = Mem_Calloc( vbos.mempool, sizeof( vbovertex_t ) * vbo->array_len );
|
||||
gEngfuncs.Con_Printf( "%s: allocated array of %d verts\n", __func__, vbo->array_len );
|
||||
|
||||
t2 = gEngfuncs.pfnTime();
|
||||
gEngfuncs.Con_Printf( S_NOTE "%s: allocated array of %d verts in %.3g seconds\n", __func__, vbo->array_len, t2 - t1 );
|
||||
|
||||
// switch to list begin
|
||||
vbo = vbos.arraylist;
|
||||
@@ -2057,6 +2062,10 @@ void R_GenerateVBO( void )
|
||||
// reset state
|
||||
pglBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
|
||||
mtst.tmu_gl = XASH_TEXTURE0;
|
||||
|
||||
t3 = gEngfuncs.pfnTime();
|
||||
|
||||
gEngfuncs.Con_Reportf( S_NOTE "%s: uploaded VBOs in %.3g seconds, %.3g seconds total\n", __func__, t3 - t2, t3 - t1 );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3518,7 +3527,7 @@ static void R_DrawTriangleOutlines( void )
|
||||
{
|
||||
int i, j;
|
||||
msurface_t *surf;
|
||||
glpoly_t *p;
|
||||
glpoly2_t *p;
|
||||
float *v;
|
||||
|
||||
if( !gl_wireframe.value )
|
||||
|
||||
@@ -54,7 +54,7 @@ static const byte *R_SpriteLoadFrame( model_t *mod, const void *pin, mspritefram
|
||||
char texname[128];
|
||||
int bytes = 1;
|
||||
|
||||
memcpy( &pinframe, pin, sizeof(dspriteframe_t));
|
||||
memcpy( &pinframe, pin, sizeof( dspriteframe_t ));
|
||||
|
||||
if( sprite_version == SPRITE_VERSION_32 )
|
||||
bytes = 4;
|
||||
|
||||
@@ -3389,7 +3389,8 @@ static int R_StudioDrawPlayer( int flags, entity_state_t *pplayer )
|
||||
|
||||
if( flags & STUDIO_RENDER )
|
||||
{
|
||||
if( cl_himodels->value && RI.currentmodel != RI.currententity->model )
|
||||
// change body if it's a menu entity
|
||||
if( cl_himodels->value && ( RI.currentmodel != RI.currententity->model || !RI.drawWorld ))
|
||||
{
|
||||
// show highest resolution multiplayer model
|
||||
RI.currententity->curstate.body = 255;
|
||||
|
||||
@@ -60,6 +60,7 @@ void TriRenderMode( int mode )
|
||||
break;
|
||||
case kRenderGlow:
|
||||
case kRenderTransAdd:
|
||||
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
pglBlendFunc( GL_SRC_ALPHA, GL_ONE );
|
||||
pglEnable( GL_BLEND );
|
||||
pglDepthMask( GL_FALSE );
|
||||
|
||||
@@ -283,13 +283,13 @@ R_AddSkyBoxSurface
|
||||
void R_AddSkyBoxSurface( msurface_t *fa )
|
||||
{
|
||||
vec3_t verts[MAX_CLIP_VERTS];
|
||||
glpoly_t *p;
|
||||
glpoly2_t *p;
|
||||
float *v;
|
||||
int i;
|
||||
|
||||
if( FBitSet( tr.world->flags, FWORLD_SKYSPHERE ) && fa->polys && !FBitSet( tr.world->flags, FWORLD_CUSTOM_SKYBOX ))
|
||||
{
|
||||
glpoly_t *p = fa->polys;
|
||||
glpoly2_t *p = fa->polys;
|
||||
|
||||
// draw the sky poly
|
||||
pglBegin( GL_POLYGON );
|
||||
@@ -415,7 +415,7 @@ static void R_CloudVertex( float s, float t, int axis, vec3_t v )
|
||||
R_CloudTexCoord
|
||||
=============
|
||||
*/
|
||||
static void R_CloudTexCoord( vec3_t v, float speed, float *s, float *t )
|
||||
static void R_CloudTexCoord( const vec3_t v, float speed, float *s, float *t )
|
||||
{
|
||||
float length, speedscale;
|
||||
vec3_t dir;
|
||||
@@ -438,17 +438,17 @@ static void R_CloudTexCoord( vec3_t v, float speed, float *s, float *t )
|
||||
R_CloudDrawPoly
|
||||
===============
|
||||
*/
|
||||
static void R_CloudDrawPoly( glpoly_t *p )
|
||||
static void R_CloudDrawPoly( const float *verts )
|
||||
{
|
||||
const float *v;
|
||||
float s, t;
|
||||
float *v;
|
||||
int i;
|
||||
|
||||
GL_SetRenderMode( kRenderNormal );
|
||||
GL_Bind( XASH_TEXTURE0, tr.solidskyTexture );
|
||||
|
||||
pglBegin( GL_QUADS );
|
||||
for( i = 0, v = p->verts[0]; i < 4; i++, v += VERTEXSIZE )
|
||||
for( i = 0, v = verts; i < 4; i++, v += VERTEXSIZE )
|
||||
{
|
||||
R_CloudTexCoord( v, 8.0f, &s, &t );
|
||||
pglTexCoord2f( s, t );
|
||||
@@ -460,7 +460,7 @@ static void R_CloudDrawPoly( glpoly_t *p )
|
||||
GL_Bind( XASH_TEXTURE0, tr.alphaskyTexture );
|
||||
|
||||
pglBegin( GL_QUADS );
|
||||
for( i = 0, v = p->verts[0]; i < 4; i++, v += VERTEXSIZE )
|
||||
for( i = 0, v = verts; i < 4; i++, v += VERTEXSIZE )
|
||||
{
|
||||
R_CloudTexCoord( v, 16.0f, &s, &t );
|
||||
pglTexCoord2f( s, t );
|
||||
@@ -479,10 +479,10 @@ R_CloudRenderSide
|
||||
static void R_CloudRenderSide( int axis )
|
||||
{
|
||||
vec3_t verts[4];
|
||||
float final_verts[4][VERTEXSIZE];
|
||||
float di, qi, dj, qj;
|
||||
vec3_t vup, vright;
|
||||
vec3_t temp, temp2;
|
||||
glpoly_t p[1];
|
||||
int i, j;
|
||||
|
||||
R_CloudVertex( -1.0f, -1.0f, axis, verts[0] );
|
||||
@@ -493,7 +493,6 @@ static void R_CloudRenderSide( int axis )
|
||||
VectorSubtract( verts[2], verts[3], vup );
|
||||
VectorSubtract( verts[2], verts[1], vright );
|
||||
|
||||
p->numverts = 4;
|
||||
di = SKYCLOUDS_QUALITY;
|
||||
qi = 1.0f / di;
|
||||
dj = (axis < 4) ? di * 2 : di; //subdivide vertically more than horizontally on skybox sides
|
||||
@@ -512,17 +511,17 @@ static void R_CloudRenderSide( int axis )
|
||||
VectorScale( vright, qi * i, temp );
|
||||
VectorScale( vup, qj * j, temp2 );
|
||||
VectorAdd( temp, temp2, temp );
|
||||
VectorAdd( verts[0], temp, p->verts[0] );
|
||||
VectorAdd( verts[0], temp, final_verts[0] );
|
||||
|
||||
VectorScale( vup, qj, temp );
|
||||
VectorAdd( p->verts[0], temp, p->verts[1] );
|
||||
VectorAdd( final_verts[0], temp, final_verts[1] );
|
||||
|
||||
VectorScale( vright, qi, temp );
|
||||
VectorAdd( p->verts[1], temp, p->verts[2] );
|
||||
VectorAdd( final_verts[1], temp, final_verts[2] );
|
||||
|
||||
VectorAdd( p->verts[0], temp, p->verts[3] );
|
||||
VectorAdd( final_verts[0], temp, final_verts[3] );
|
||||
|
||||
R_CloudDrawPoly( p );
|
||||
R_CloudDrawPoly( final_verts[0] );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -570,7 +569,7 @@ void EmitWaterPolys( msurface_t *warp, qboolean reverse )
|
||||
{
|
||||
float *v, nv, waveHeight;
|
||||
float s, t, os, ot;
|
||||
glpoly_t *p;
|
||||
glpoly2_t *p;
|
||||
int i;
|
||||
|
||||
const qboolean useQuads = FBitSet( warp->flags, SURF_DRAWTURB_QUADS ) && glConfig.context == CONTEXT_TYPE_GL;
|
||||
|
||||
@@ -441,7 +441,7 @@ static void VGUI_UploadTextureBlock( int drawX, int drawY, const byte *rgba, int
|
||||
;
|
||||
}
|
||||
|
||||
static ref_interface_t gReffuncs =
|
||||
static const ref_interface_t gReffuncs =
|
||||
{
|
||||
.R_Init = R_Init,
|
||||
.R_Shutdown = R_SimpleStub,
|
||||
@@ -588,8 +588,8 @@ int EXPORT GetRefAPI( int version, ref_interface_t *funcs, ref_api_t *engfuncs,
|
||||
return 0;
|
||||
|
||||
// fill in our callbacks
|
||||
memcpy( funcs, &gReffuncs, sizeof( ref_interface_t ));
|
||||
memcpy( &gEngfuncs, engfuncs, sizeof( ref_api_t ));
|
||||
*funcs = gReffuncs;
|
||||
gEngfuncs = *engfuncs;
|
||||
gpGlobals = globals;
|
||||
|
||||
return REF_API_VERSION;
|
||||
|
||||
@@ -416,7 +416,7 @@ static void* GAME_EXPORT R_GetProcAddress( const char *name )
|
||||
return gEngfuncs.GL_GetProcAddress( name );
|
||||
}
|
||||
|
||||
static ref_interface_t gReffuncs =
|
||||
static const ref_interface_t gReffuncs =
|
||||
{
|
||||
R_Init,
|
||||
R_Shutdown,
|
||||
@@ -563,8 +563,8 @@ int EXPORT GetRefAPI( int version, ref_interface_t *funcs, ref_api_t *engfuncs,
|
||||
return 0;
|
||||
|
||||
// fill in our callbacks
|
||||
memcpy( funcs, &gReffuncs, sizeof( ref_interface_t ));
|
||||
memcpy( &gEngfuncs, engfuncs, sizeof( ref_api_t ));
|
||||
*funcs = gReffuncs;
|
||||
gEngfuncs = *engfuncs;
|
||||
gpGlobals = globals;
|
||||
|
||||
gp_cl = (ref_client_t *)ENGINE_GET_PARM( PARM_GET_CLIENT_PTR );
|
||||
|
||||
@@ -511,10 +511,10 @@ R_DecalCreatePoly
|
||||
creates mesh for decal on first rendering
|
||||
====================
|
||||
*/
|
||||
static glpoly_t *R_DecalCreatePoly( decalinfo_t *decalinfo, decal_t *pdecal, msurface_t *surf )
|
||||
static glpoly2_t *R_DecalCreatePoly( decalinfo_t *decalinfo, decal_t *pdecal, msurface_t *surf )
|
||||
{
|
||||
int lnumverts;
|
||||
glpoly_t *poly;
|
||||
glpoly2_t *poly;
|
||||
float *v;
|
||||
int i;
|
||||
|
||||
@@ -527,7 +527,7 @@ static glpoly_t *R_DecalCreatePoly( decalinfo_t *decalinfo, decal_t *pdecal, msu
|
||||
|
||||
// allocate glpoly
|
||||
// REFTODO: com_studiocache pool!
|
||||
poly = Mem_Calloc( r_temppool, sizeof( glpoly_t ) + ( lnumverts - 4 ) * VERTEXSIZE * sizeof( float ));
|
||||
poly = Mem_Calloc( r_temppool, sizeof( glpoly2_t ) + lnumverts * VERTEXSIZE * sizeof( float ));
|
||||
poly->next = pdecal->polys;
|
||||
poly->flags = surf->flags;
|
||||
pdecal->polys = poly;
|
||||
@@ -853,7 +853,7 @@ void GAME_EXPORT R_DecalShoot( int textureIndex, int entityIndex, int modelIndex
|
||||
// triangles the same way.
|
||||
float * GAME_EXPORT R_DecalSetupVerts( decal_t *pDecal, msurface_t *surf, int texture, int *outCount )
|
||||
{
|
||||
glpoly_t *p = pDecal->polys;
|
||||
glpoly2_t *p = pDecal->polys;
|
||||
int i, count;
|
||||
float *v, *v2;
|
||||
|
||||
|
||||
@@ -622,9 +622,9 @@ static void R_BuildBlendMaps( void )
|
||||
#endif
|
||||
}
|
||||
|
||||
void R_AllocScreen( void );
|
||||
static qboolean R_AllocScreen( void );
|
||||
|
||||
void R_InitBlit( qboolean glblit )
|
||||
qboolean R_InitBlit( qboolean glblit )
|
||||
{
|
||||
R_BuildBlendMaps();
|
||||
|
||||
@@ -646,10 +646,11 @@ void R_InitBlit( qboolean glblit )
|
||||
swblit.pUnlockBuffer = gEngfuncs.SW_UnlockBuffer;
|
||||
swblit.pCreateBuffer = gEngfuncs.SW_CreateBuffer;
|
||||
}
|
||||
R_AllocScreen();
|
||||
|
||||
return R_AllocScreen();
|
||||
}
|
||||
|
||||
void R_AllocScreen( void )
|
||||
static qboolean R_AllocScreen( void )
|
||||
{
|
||||
int w, h;
|
||||
|
||||
@@ -661,12 +662,20 @@ void R_AllocScreen( void )
|
||||
R_InitCaches();
|
||||
|
||||
if( swblit.rotate )
|
||||
w = gpGlobals->height, h = gpGlobals->width;
|
||||
{
|
||||
w = gpGlobals->height;
|
||||
h = gpGlobals->width;
|
||||
}
|
||||
else
|
||||
h = gpGlobals->height, w = gpGlobals->width;
|
||||
{
|
||||
w = gpGlobals->width;
|
||||
h = gpGlobals->height;
|
||||
}
|
||||
|
||||
if( !swblit.pCreateBuffer( w, h, &swblit.stride, &swblit.bpp,
|
||||
&swblit.rmask, &swblit.gmask, &swblit.bmask ))
|
||||
return false;
|
||||
|
||||
swblit.pCreateBuffer( w, h, &swblit.stride, &swblit.bpp,
|
||||
&swblit.rmask, &swblit.gmask, &swblit.bmask);
|
||||
R_BuildScreenMap();
|
||||
vid.width = gpGlobals->width;
|
||||
vid.height = gpGlobals->height;
|
||||
@@ -674,10 +683,12 @@ void R_AllocScreen( void )
|
||||
if( d_pzbuffer )
|
||||
free( d_pzbuffer );
|
||||
d_pzbuffer = malloc( vid.width*vid.height*2 + 64 );
|
||||
|
||||
if( vid.buffer )
|
||||
free( vid.buffer );
|
||||
|
||||
vid.buffer = malloc( vid.width * vid.height*sizeof( pixel_t ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void R_BlitScreen( void )
|
||||
|
||||
@@ -500,7 +500,7 @@ void R_DrawWaterSurfaces( void );
|
||||
void R_DrawBrushModel( cl_entity_t *e );
|
||||
void GL_SubdivideSurface( msurface_t *fa );
|
||||
void GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa );
|
||||
void DrawGLPoly( glpoly_t *p, float xScale, float yScale );
|
||||
void DrawGLPoly( glpoly2_t *p, float xScale, float yScale );
|
||||
texture_t *R_TextureAnimation( msurface_t *s );
|
||||
void GL_SetupFogColorForSurfaces( void );
|
||||
void R_DrawAlphaTextureChains( void );
|
||||
@@ -622,8 +622,6 @@ void R_RunViewmodelEvents( void );
|
||||
void R_DrawViewModel( void );
|
||||
int R_GetSpriteTexture( const struct model_s *m_pSpriteModel, int frame );
|
||||
void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, float scale );
|
||||
void R_RemoveEfrags( struct cl_entity_s *ent );
|
||||
void R_AddEfrags( struct cl_entity_s *ent );
|
||||
void R_DecalRemoveAll( int texture );
|
||||
int R_CreateDecalList( decallist_t *pList );
|
||||
void R_ClearAllDecals( void );
|
||||
@@ -1175,7 +1173,7 @@ void R_DrawBrushModel(cl_entity_t *pent);
|
||||
//
|
||||
void R_InitCaches (void);
|
||||
void R_BlitScreen( void );
|
||||
void R_InitBlit( qboolean gl );
|
||||
qboolean R_InitBlit( qboolean gl );
|
||||
qboolean R_SetDisplayTransform( ref_screen_rotation_t rotate, int offset_x, int offset_y, float scale_x, float scale_y );
|
||||
|
||||
//
|
||||
|
||||
@@ -1898,7 +1898,11 @@ qboolean GAME_EXPORT R_Init( void )
|
||||
tr.palette = (color24 *)ENGINE_GET_PARM( PARM_GET_PALETTE_PTR );
|
||||
tr.viewent = (cl_entity_t *)ENGINE_GET_PARM( PARM_GET_VIEWENT_PTR );
|
||||
|
||||
R_InitBlit( glblit );
|
||||
if( !R_InitBlit( glblit ))
|
||||
{
|
||||
gEngfuncs.R_Free_Video();
|
||||
return false;
|
||||
}
|
||||
|
||||
R_InitImages();
|
||||
// init draw stack
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user