mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-06 03:54:52 +08:00
Compare commits
20 Commits
continuous
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46add4784b | ||
|
|
fe62e61aa4 | ||
|
|
de74ce9767 | ||
|
|
8c89579c35 | ||
|
|
18dddaf1a5 | ||
|
|
d3bcdc6c06 | ||
|
|
c0a40f6e03 | ||
|
|
e3e459bb67 | ||
|
|
badda6c585 | ||
|
|
db68b7c6e7 | ||
|
|
841b2bcf5a | ||
|
|
a5fb74eb8f | ||
|
|
31d44f85a7 | ||
|
|
24f8525fad | ||
|
|
04fbe1a356 | ||
|
|
ecda80fb9a | ||
|
|
9f14c48787 | ||
|
|
8b15bc9a96 | ||
|
|
e6913c9ce2 | ||
|
|
b4495238d9 |
2
3rdparty/gl4es/gl4es
vendored
2
3rdparty/gl4es/gl4es
vendored
Submodule 3rdparty/gl4es/gl4es updated: 1543ec5074...81547d9867
2
3rdparty/library_suffix
vendored
2
3rdparty/library_suffix
vendored
Submodule 3rdparty/library_suffix updated: a35ac9c12e...e9fc14307b
2
3rdparty/mainui
vendored
2
3rdparty/mainui
vendored
Submodule 3rdparty/mainui updated: 510c30c51a...8843994b3e
2
3rdparty/nanogl
vendored
2
3rdparty/nanogl
vendored
Submodule 3rdparty/nanogl updated: 6c8aeca5e6...7f654d2de2
@@ -1,53 +1,55 @@
|
|||||||
## If you are reporting bugs
|
## If you are reporting bugs
|
||||||
|
|
||||||
1. Check you are using latest version. You can build latest Xash3D FWGS for yourself, look to README.md.
|
1. Check that you are using the latest version. To build the latest Xash3D FWGS, look at README.md.
|
||||||
2. Check open issues is your bug is already reported and closed issues if it reported and fixed. Don't send bug if it's already reported.
|
2. Check the open issues to make sure your bug is not already reported and closed issues if it reported and fixed. Don't send a bug if it's already been reported.
|
||||||
3. Re-run engine with `-dev 2 -log` arguments, reproduce bug and post engine.log which can be found in your working directory.
|
3. Re-run engine with `-dev 2 -log` arguments, then reproduce the bug and post `engine.log` which can be found in your working directory.
|
||||||
3. Describe steps to reproduce bug.
|
3. Describe the steps to reproduce the bug.
|
||||||
4. Describe which OS and architecture you are using.
|
4. Describe which OS and architecture you are using.
|
||||||
6. Attach screenshot if it will help clarify the situation.
|
6. Attach a screenshot if it will help clarify the situation.
|
||||||
|
|
||||||
## If you are contributing code
|
## If you are contributing code
|
||||||
|
|
||||||
### Which branch?
|
### Which branch?
|
||||||
|
|
||||||
* We recommend using `master` branch.
|
* We recommend using the `master` branch.
|
||||||
|
|
||||||
### Third-party libraries
|
### Third-party libraries
|
||||||
|
|
||||||
* Philosophy of any Xash Project by Uncle Mike: don't be bloated. We follow it too.
|
* The philosophy of any Xash Project by Uncle Mike: don't be bloated. We follow it too.
|
||||||
* Adding new library is allowed only if there is a REAL reason to use it. It's will be nice, if you will leave a possibility to remove new dependency at build-time.
|
* Adding new libraries are allowed only if there is a REAL reason to use it. It will be nice, if you leave a possibility to remove the new dependency at build-time.
|
||||||
* Adding new dependencies for Waf Build System is not welcomed.
|
* Adding new dependencies for the Waf Build System is not welcomed.
|
||||||
|
|
||||||
### Portability level
|
### Portability level
|
||||||
|
|
||||||
* Xash3D have it's own crt library. It's recommended to use it. It most cases it's just a wrappers around standart C library.
|
* Xash3D has it's own crt library. It's recommended to use it. In most cases it's just a wrapper around the standard C library.
|
||||||
* If your feature need platform-specific code, move it to `engine/platform` and try to implement to every supported OS and every supported compiler or at least leave a stubs.
|
* If your feature needs platform-specific code, move it to `engine/platform` and try to implement every supported OS and every supported compiler or at least leave a stub.
|
||||||
* You must put it under appopriate macro. It's a rule: Xash3D FWGS must compile everywhere. For list of platforms we support, refer to public/build.h file.
|
* You must put it under the appropriate macro. It's a rule: Xash3D FWGS must compile everywhere. For list of platforms we support, refer to `public/build.h`.
|
||||||
|
|
||||||
### Code style
|
### Code style
|
||||||
|
|
||||||
* This project uses mixed Quake's and HLSDK's C/C++ code style convention.
|
* This project uses a mix of Quake's and HLSDK's C/C++ code style convention.
|
||||||
* In short:
|
* In short:
|
||||||
* Use spaces in parenthesis, but not when two parentheses are consecutive.
|
* Use spaces in parenthesis, but not when two parentheses are consecutive.
|
||||||
* Only tabs for indentation.
|
* Use only tabs for indentation.
|
||||||
* Any brace must have it's own line.
|
* Any brace must have it's own line.
|
||||||
* Short blocks, if statements and loops on single line are allowed.
|
* Use short blocks, if statements and loops on single line are allowed.
|
||||||
* Prefer generic utilities from libpublic over rolling your own.
|
* Prefer generic utilities from libpublic over rolling your own.
|
||||||
* Avoid magic numbers.
|
* Avoid magic numbers.
|
||||||
* While macros are powerful, it's better to avoid overusing them.
|
* While macros are powerful, it's better to avoid overusing them.
|
||||||
* If you unsure, try to mimic code style from anywhere else of engine source code.
|
* If you are unsure, try to mimic the code style from anywhere else in the engine source code.
|
||||||
* **ANY** commit message should start from declaring a tags, in format:
|
* **ANY** commit message should start from declaring tags, in the format:
|
||||||
|
|
||||||
`tag: added some bugs`
|
`tag: added some bugs`
|
||||||
|
|
||||||
`tag: subtag: fixed some features`
|
`tag: subtag: fixed some features`
|
||||||
|
|
||||||
Tags can be any: subsystem, simple feature name or even just a filename, without extension.
|
The tags can be a:
|
||||||
Just keep them always same, it helps keep history clean and commit messages short.
|
* subsystem
|
||||||
|
* simple feature name or even just a filename, without the extension.
|
||||||
|
Just always keep them the same because it helps keep the commit history clean and messages short.
|
||||||
|
|
||||||
## LLM-based tools usage.
|
## LLM-based tools usage.
|
||||||
|
|
||||||
While we wouldn't recommend using any LLM-based (also misleadingly called AI) tools, we understand that they are here to stay.
|
While we wouldn't recommend using any LLM-based (also misleadingly called AI) tools, we understand that they are here to stay.
|
||||||
|
|
||||||
Whether you're reporting bug or contributing the code, you take complete authorship and responsibility over provided content and the same rules will apply to you as for everybody else, so validate the bug report or the patch before sending it.
|
Whether you're reporting a bug or contributing to the code, you will take complete authorship and responsibility over the provided content, and the same rules will apply to you as for everybody else, so validate the bug report or the patch it before sending it.
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ Mirrored on github - https://github.com/solidi/hl-mods/tree/master/cir
|
|||||||
## Counter-Life
|
## Counter-Life
|
||||||
Available on ModDB - https://www.moddb.com/mods/counter-life/downloads/cl-version-1-source-code
|
Available on ModDB - https://www.moddb.com/mods/counter-life/downloads/cl-version-1-source-code
|
||||||
|
|
||||||
|
## Crack-Life Anniversary Campaign
|
||||||
|
Available on ModDB - https://www.moddb.com/mods/crack-life/downloads/crack-life-anniversary-campaign-sdk
|
||||||
|
|
||||||
## Cthulhu
|
## Cthulhu
|
||||||
Uploaded to github by Oleg Cherkasky - https://github.com/gunrunners-paradise/Cthulhu-HLmod-SDK
|
Uploaded to github by Oleg Cherkasky - https://github.com/gunrunners-paradise/Cthulhu-HLmod-SDK
|
||||||
|
|
||||||
@@ -62,11 +65,14 @@ Available on GamerLab - http://gamer-lab.com/eng/code_mods_goldsrc/Half-Life_2D_
|
|||||||
## Gang Wars
|
## Gang Wars
|
||||||
Mirrored on github - https://github.com/nekonomicon/gw1.45src
|
Mirrored on github - https://github.com/nekonomicon/gw1.45src
|
||||||
|
|
||||||
## Go-mod
|
## Go-Mod
|
||||||
Versions 2.0 and 3.0, available in mod archives on ModDB - https://www.moddb.com/mods/go-mod/downloads
|
Versions 2.0 and 3.0, available in mod archives on ModDB - https://www.moddb.com/mods/go-mod/downloads
|
||||||
|
|
||||||
Version 3.0, mirrored on github - https://github.com/nekonomicon/Go-mod30
|
Version 3.0, mirrored on github - https://github.com/nekonomicon/Go-mod30
|
||||||
|
|
||||||
|
## Go-Mod: Reborn
|
||||||
|
Official github repository - https://github.com/LambdaLuke87/Go-Mod-Reborn-Lite-Build
|
||||||
|
|
||||||
## GT mod
|
## GT mod
|
||||||
Available on GamerLab - http://gamer-lab.com/eng/code_mods_goldsrc/GT_mod_(Polnie_ishodniki)
|
Available on GamerLab - http://gamer-lab.com/eng/code_mods_goldsrc/GT_mod_(Polnie_ishodniki)
|
||||||
|
|
||||||
@@ -85,12 +91,21 @@ Available on ModDB - https://www.moddb.com/mods/half-life-echoes
|
|||||||
## Half-Life: Expanded Arsenal
|
## Half-Life: Expanded Arsenal
|
||||||
Available on ModDB - https://www.moddb.com/mods/half-life-expanded-arsenal
|
Available on ModDB - https://www.moddb.com/mods/half-life-expanded-arsenal
|
||||||
|
|
||||||
|
## Half-Life: Featureful
|
||||||
|
Branch **featureful** in halflife-featureful - https://github.com/FreeSlave/halflife-featureful
|
||||||
|
|
||||||
## Half-Life: Field Intensity
|
## Half-Life: Field Intensity
|
||||||
Branch **field_intensity_1.7** in halflife-featureful - https://github.com/FreeSlave/halflife-featureful/tree/field_intensity_1.7
|
Branch **field_intensity_1.7** in halflife-featureful - https://github.com/FreeSlave/halflife-featureful/tree/field_intensity_1.7
|
||||||
|
|
||||||
## Half-Life: Gravgun mod
|
## Half-Life: Gravgun mod
|
||||||
Branch **gravgun** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/gravgun
|
Branch **gravgun** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/gravgun
|
||||||
|
|
||||||
|
## Half-Life: Induction
|
||||||
|
Version 1.4: Branch **induction** in halflife-featureful - https://github.com/FreeSlave/halflife-featureful/tree/induction
|
||||||
|
|
||||||
|
## Half-Life: Insecure
|
||||||
|
Version 1.5 is available on ModDB - https://www.moddb.com/mods/half-life-insecure/downloads/half-life-insecure-map-tools-and-source-code-ver-15
|
||||||
|
|
||||||
## Half-Life: Invasion
|
## Half-Life: Invasion
|
||||||
Official github repository - https://github.com/jlecorre/hlinvasion
|
Official github repository - https://github.com/jlecorre/hlinvasion
|
||||||
|
|
||||||
@@ -100,6 +115,13 @@ Mirrored on github - https://github.com/solidi/hl-mods/tree/master/pong
|
|||||||
## Half-Life: Quest Mode
|
## Half-Life: Quest Mode
|
||||||
Available on cs-mapping.com.ua - https://old.cs-mapping.com.ua/forum/showthread.php?t=38030
|
Available on cs-mapping.com.ua - https://old.cs-mapping.com.ua/forum/showthread.php?t=38030
|
||||||
|
|
||||||
|
## Half-Life: Sum
|
||||||
|
Original Version: Branch **sum_orig** in halflife-featureful - https://github.com/FreeSlave/halflife-featureful/tree/sum_orig
|
||||||
|
|
||||||
|
Version 2022: Branch **sum_2022** in halflife-featureful - https://github.com/FreeSlave/halflife-featureful/tree/sum_2022
|
||||||
|
|
||||||
|
Current Version: Branch **sum** in halflife-featureful - https://github.com/FreeSlave/halflife-featureful/tree/sum
|
||||||
|
|
||||||
## Half-Life: Top-Down
|
## Half-Life: Top-Down
|
||||||
Official gitlab repository - https://gitlab.com/Sockman/hltopdown
|
Official gitlab repository - https://gitlab.com/Sockman/hltopdown
|
||||||
|
|
||||||
@@ -109,6 +131,9 @@ Official github repository - https://github.com/Fograin/hl-subsmod-ex
|
|||||||
## Half-Life: Rally
|
## Half-Life: Rally
|
||||||
Official gitlab repository - https://gitlab.com/hlrally/src
|
Official gitlab repository - https://gitlab.com/hlrally/src
|
||||||
|
|
||||||
|
## Half-Life: Reprocessing
|
||||||
|
Official github repository - https://github.com/EgorYak/ReprocessingSourceCode
|
||||||
|
|
||||||
## Half-Life: RXT
|
## Half-Life: RXT
|
||||||
Available on ModDB - https://www.moddb.com/mods/half-life-rxt/downloads/rxt-source-code-v57
|
Available on ModDB - https://www.moddb.com/mods/half-life-rxt/downloads/rxt-source-code-v57
|
||||||
|
|
||||||
@@ -147,6 +172,9 @@ Mirrored on github (Includes maps and models source files) - https://github.com/
|
|||||||
## Ingram Chillin' Mod
|
## Ingram Chillin' Mod
|
||||||
Official SourceForge repository - https://sourceforge.net/projects/icm-hl/
|
Official SourceForge repository - https://sourceforge.net/projects/icm-hl/
|
||||||
|
|
||||||
|
## Intense Force
|
||||||
|
Branch **intense_force** in halflife-featureful - https://github.com/FreeSlave/halflife-featureful/tree/intense_force
|
||||||
|
|
||||||
## Master Sword
|
## Master Sword
|
||||||
Official github repository of Master Sword Classic - https://github.com/BerntA/MasterSwordClassic
|
Official github repository of Master Sword Classic - https://github.com/BerntA/MasterSwordClassic
|
||||||
|
|
||||||
@@ -189,6 +217,9 @@ Available in Valve's Half-Life repository - https://github.com/ValveSoftware/hal
|
|||||||
## Spirit of Half-Life
|
## Spirit of Half-Life
|
||||||
[Logic&Trick's](https://github.com/LogicAndTrick) mirror - https://files.logic-and-trick.com/#/Half-Life/Mods/Spirit%20of%20Half-Life
|
[Logic&Trick's](https://github.com/LogicAndTrick) mirror - https://files.logic-and-trick.com/#/Half-Life/Mods/Spirit%20of%20Half-Life
|
||||||
|
|
||||||
|
## The Last Bullet
|
||||||
|
Official github repository - https://github.com/GT-Project-Cat/The-Last-Bullet-Updated-Code
|
||||||
|
|
||||||
## The Wastes
|
## The Wastes
|
||||||
Version 1.5: mirrored on code.idtech.space - https://code.idtech.space/vera/halflife-thewastes-sdk
|
Version 1.5: mirrored on code.idtech.space - https://code.idtech.space/vera/halflife-thewastes-sdk
|
||||||
|
|
||||||
@@ -212,6 +243,19 @@ Download page on official site - http://www.thothie.com/ww/
|
|||||||
## Wrong Door
|
## Wrong Door
|
||||||
Available on ModDB - https://www.moddb.com/mods/wrong-door/downloads/wrong-door-sdk
|
Available on ModDB - https://www.moddb.com/mods/wrong-door/downloads/wrong-door-sdk
|
||||||
|
|
||||||
|
## XDM
|
||||||
|
*This mod is opensource but access to source code is always rebus*
|
||||||
|
|
||||||
|
How to get sources of version 3.0.4.3:
|
||||||
|
|
||||||
|
Download SFX-archive from ModDB - https://www.moddb.com/mods/xdm/downloads/xdm3043
|
||||||
|
|
||||||
|
Extract it.
|
||||||
|
|
||||||
|
Open client.dll in HEX-editor and patch header - change `Win!` to `Rar!`
|
||||||
|
|
||||||
|
Extract it using unrar - password `iamtheone`
|
||||||
|
|
||||||
## XashXT
|
## XashXT
|
||||||
Mirrored on github - https://github.com/a1batross/XashXT_original
|
Mirrored on github - https://github.com/a1batross/XashXT_original
|
||||||
|
|
||||||
@@ -220,6 +264,12 @@ Mirrored on github - https://github.com/a1batross/XashXT_original
|
|||||||
|
|
||||||
[Logic&Trick's](https://github.com/LogicAndTrick) mirror - https://files.logic-and-trick.com/#/Half-Life/Mods/Spirit%20of%20Half-Life
|
[Logic&Trick's](https://github.com/LogicAndTrick) mirror - https://files.logic-and-trick.com/#/Half-Life/Mods/Spirit%20of%20Half-Life
|
||||||
|
|
||||||
|
## Yet another PS2 Half-Life port
|
||||||
|
Official github repository - https://github.com/supadupaplex/ya-ps2hl-dll
|
||||||
|
|
||||||
|
## Zombie Panic!
|
||||||
|
Official github repository - https://github.com/Monochrome-Inc/ZombiePanic-HL
|
||||||
|
|
||||||
## Zombie-X
|
## Zombie-X
|
||||||
Available in mod archive on ModDB - https://www.moddb.com/mods/zombie-x-10-final/downloads/zombie-x-10-dle-beta6-last-version
|
Available in mod archive on ModDB - https://www.moddb.com/mods/zombie-x-10-final/downloads/zombie-x-10-dle-beta6-last-version
|
||||||
|
|
||||||
@@ -301,7 +351,7 @@ Unkle Mike's recreation - https://hlfx.ru/forum/showthread.php?s=&threadid=5253
|
|||||||
Reverse-engineered code: branch **bshift** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/bshift
|
Reverse-engineered code: branch **bshift** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/bshift
|
||||||
|
|
||||||
## Half-Life: Induction
|
## Half-Life: Induction
|
||||||
Branch **induction** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/induction
|
Version 1.0-1.2: Branch **induction_1.2** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/induction_1.2
|
||||||
|
|
||||||
## Half-Life: Opposing Force
|
## Half-Life: Opposing Force
|
||||||
Recreation by lostgamer aka nillerusr - https://github.com/LostGamerHL/hlsdk-xash3d
|
Recreation by lostgamer aka nillerusr - https://github.com/LostGamerHL/hlsdk-xash3d
|
||||||
@@ -375,6 +425,9 @@ Branch **aghl** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/
|
|||||||
## Bubblemod
|
## Bubblemod
|
||||||
Branch **bubblemod** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/bubblemod
|
Branch **bubblemod** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/bubblemod
|
||||||
|
|
||||||
|
## Counter-Life
|
||||||
|
Branch **counter-life** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/counter-life
|
||||||
|
|
||||||
## Deathmatch Classic
|
## Deathmatch Classic
|
||||||
Deathmatch Classic: Adrenaline Gamer Edition - https://github.com/martinwebrant/agmod/tree/master/src/dmc
|
Deathmatch Classic: Adrenaline Gamer Edition - https://github.com/martinwebrant/agmod/tree/master/src/dmc
|
||||||
|
|
||||||
@@ -388,6 +441,9 @@ Branch **delta_particles** in hlsdk-portable - https://github.com/FWGS/hlsdk-por
|
|||||||
## Half-Life: Echoes
|
## Half-Life: Echoes
|
||||||
Branch **echoes** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/echoes
|
Branch **echoes** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/echoes
|
||||||
|
|
||||||
|
## Half-Life: Insecure
|
||||||
|
Branch **insecure** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/insecure
|
||||||
|
|
||||||
## Half-Life: Invasion
|
## Half-Life: Invasion
|
||||||
Port to HLSDK 2.4 by malortie - https://github.com/HL1-Mods-Reimplementations-and-Ports/hl-invasion
|
Port to HLSDK 2.4 by malortie - https://github.com/HL1-Mods-Reimplementations-and-Ports/hl-invasion
|
||||||
|
|
||||||
@@ -421,6 +477,8 @@ Branch **dmc** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/d
|
|||||||
## Xen-Warrior
|
## Xen-Warrior
|
||||||
Branch **sohl1.2** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/sohl1.2
|
Branch **sohl1.2** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/sohl1.2
|
||||||
|
|
||||||
|
## Yet another PS2 Half-Life port
|
||||||
|
Branch **ps2hl** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/ps2hl
|
||||||
|
|
||||||
## Zombie-X
|
## Zombie-X
|
||||||
Branch **zombie-x** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/zombie-x
|
Branch **zombie-x** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/zombie-x
|
||||||
|
|
||||||
|
|||||||
@@ -892,6 +892,8 @@ Currently, fresh Xash3D FWGS builds for Android, PS Vita and Nintendo Switch use
|
|||||||
## List of games and mods with custom gamedll
|
## List of games and mods with custom gamedll
|
||||||
For mods from this category - first of all place mod folder beside **valve** folder.
|
For mods from this category - first of all place mod folder beside **valve** folder.
|
||||||
|
|
||||||
|
NOTE: Precompiled libraries for some mods from this category may be already available for your platform in [hlsdk-mega-build](https://github.com/FWGS/hlsdk-mega-build) and this mods may be launch on Android out-of-the-box.
|
||||||
|
|
||||||
1. **[Absolute Redemption](https://www.moddb.com/mods/absolute-redemption)**
|
1. **[Absolute Redemption](https://www.moddb.com/mods/absolute-redemption)**
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **redemption** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **redemption** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
@@ -950,7 +952,11 @@ This mod already supports x86 Linux.
|
|||||||
|
|
||||||
Support for other platforms may be available later.
|
Support for other platforms may be available later.
|
||||||
|
|
||||||
14. **[Counter Strike 1.6](https://store.steampowered.com/app/10/CounterStrike/)**
|
14. **[Counter-Life](https://www.moddb.com/mods/counter-life)**
|
||||||
|
|
||||||
|
To run this mod on specific platforms you may be need to compile libraries from **counter-life** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
|
15. **[Counter Strike 1.6](https://store.steampowered.com/app/10/CounterStrike/)**
|
||||||
|
|
||||||
On x86 you may be need to compile client part.
|
On x86 you may be need to compile client part.
|
||||||
|
|
||||||
@@ -962,57 +968,65 @@ Client: https://github.com/Velaron/cs16-client/
|
|||||||
|
|
||||||
Server: https://github.com/rehlds/ReGameDLL_CS
|
Server: https://github.com/rehlds/ReGameDLL_CS
|
||||||
|
|
||||||
15. **[Crack-Life](https://www.moddb.com/mods/crack-life/downloads/crack-life)**
|
16. **[Crack-Life](https://www.moddb.com/mods/crack-life/downloads/crack-life)**
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **cracklife** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **cracklife** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
16. **[Crack-Life: Campaign Mode](https://www.moddb.com/mods/crack-life/downloads/crack-life-campaign-mode)**
|
17. **[Crack-Life: Campaign Mode](https://www.moddb.com/mods/crack-life/downloads/crack-life-campaign-mode)**
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **clcampaign** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **clcampaign** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
17. **[Deathmatch Classic](https://store.steampowered.com/app/40/Deathmatch_Classic/)**
|
18. **[Deathmatch Classic](https://store.steampowered.com/app/40/Deathmatch_Classic/)**
|
||||||
|
|
||||||
Steam version already supports x86 Linux.
|
Steam version already supports x86 Linux.
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **dmc** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **dmc** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
18. **[Delta Particles](https://www.moddb.com/mods/half-life-delta)**
|
19. **[Delta Particles](https://www.moddb.com/mods/half-life-delta)**
|
||||||
|
|
||||||
This mod already supports x86 Linux.
|
This mod already supports x86 Linux.
|
||||||
|
|
||||||
Support for other platforms may be available later.
|
To run this mod on specific platforms you may be need to compile libraries from **delta_particles** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
19. **[Escape from the Darkness](https://www.moddb.com/mods/escape-from-the-darkness)**
|
20. **[Escape from the Darkness](https://www.moddb.com/mods/escape-from-the-darkness)**
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **eftd** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **eftd** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
20. **[Gang Wars](https://www.moddb.com/mods/gangwars)**
|
21. **[Gang Wars](https://www.moddb.com/mods/gangwars)**
|
||||||
|
|
||||||
This mod already supports x86 Linux.
|
This mod already supports x86 Linux.
|
||||||
|
|
||||||
Support for other platforms may be available later.
|
Support for other platforms may be available later.
|
||||||
|
|
||||||
21. **[Half-Life: Blue Shift](https://store.steampowered.com/app/130/HalfLife_Blue_Shift/)**
|
22. **[Half-Life: Blue Shift](https://store.steampowered.com/app/130/HalfLife_Blue_Shift/)**
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **bshift** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **bshift** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
22. **[Half-Life: Decay](https://www.moddb.com/mods/half-life-decay)**
|
23. **[Half-Life: Decay](https://www.moddb.com/mods/half-life-decay)**
|
||||||
|
|
||||||
Currently, you can compile mod libraries for x86 Linux from **decay-pc** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
Currently, you can compile mod libraries for x86 Linux from **decay-pc** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
Support for other platforms may be available later.
|
Support for other platforms may be available later.
|
||||||
|
|
||||||
23. **[Half-Life: Echoes](https://www.moddb.com/mods/half-life-echoes)**
|
24. **[Half-Life: Echoes](https://www.moddb.com/mods/half-life-echoes)**
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **echoes** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **echoes** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
24. **[Half-Life: Field Intensity](https://www.moddb.com/mods/field-intensity)**
|
25. [Half-Life: Featureful](https://freeslave.github.io/halflife-featureful/)
|
||||||
|
|
||||||
|
*It's modding SDK*
|
||||||
|
|
||||||
This mod already supports x86 Linux.
|
This mod already supports x86 Linux.
|
||||||
|
|
||||||
Support for other platforms may be available later.
|
To run this mod on specific platforms you may be need to compile libraries from **featureful** branch of [halflife-featureful](https://github.com/FreeSlave/halflife-featureful).
|
||||||
|
|
||||||
25. **Half-Life: Gravgun** (unfinished) by *mittorn*, *a1batross* and *Solexid*
|
26. **[Half-Life: Field Intensity](https://www.moddb.com/mods/field-intensity)**
|
||||||
|
|
||||||
|
This mod already supports x86 Linux.
|
||||||
|
|
||||||
|
To run this mod on specific platforms you may be need to compile libraries from **field_intensity_1.7** branch of [halflife-featureful](https://github.com/FreeSlave/halflife-featureful).
|
||||||
|
|
||||||
|
27. **Half-Life: Gravgun** (unfinished) by *mittorn*, *a1batross* and *Solexid*
|
||||||
|
|
||||||
*Support temporary abandoned*
|
*Support temporary abandoned*
|
||||||
|
|
||||||
@@ -1022,163 +1036,197 @@ Currently, MSVC is not supported, use MinGW if you need build for Windows.
|
|||||||
|
|
||||||
Mod files: [1](http://mittorn.fwgs.ru/coop-entpatches/), [2](http://mittorn.fwgs.ru/ggm/), [3](https://github.com/nillerusr/gravgun-extras).
|
Mod files: [1](http://mittorn.fwgs.ru/coop-entpatches/), [2](http://mittorn.fwgs.ru/ggm/), [3](https://github.com/nillerusr/gravgun-extras).
|
||||||
|
|
||||||
26. **[Half-Life: Induction 1.2](https://www.moddb.com/mods/half-life-induction)**
|
28. **[Half-Life: Induction 1.2](https://www.moddb.com/mods/half-life-induction)**
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **induction_1.2** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **induction_1.2** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
27. **[Half-Life: Invasion](https://www.moddb.com/mods/half-life-invasion)**
|
29. **[Half-Life: Induction 1.4](https://www.moddb.com/mods/half-life-induction)**
|
||||||
|
|
||||||
This mod supports x86 Linux.
|
This mod already supports x86 Linux.
|
||||||
|
|
||||||
Support for other platforms may be available later.
|
To run this mod on specific platforms you may be need to compile libraries from **induction** branch of [halflife-featureful](https://github.com/FreeSlave/halflife-featureful).
|
||||||
|
|
||||||
28. **[Half-Life: Intense Force](https://www.moddb.com/downloads/intense-force)**
|
30. **[Half-Life: Insecure](https://www.moddb.com/mods/half-life-insecure)**
|
||||||
|
|
||||||
|
To run this mod on specific platforms you may be need to compile libraries from **insecure** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
|
31. **[Half-Life: Intense Force](https://www.moddb.com/downloads/intense-force)**
|
||||||
|
|
||||||
This mod already supports x86 Linux.
|
This mod already supports x86 Linux.
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **intense_force** branch of [halflife-featureful](https://github.com/FreeSlave/halflife-featureful).
|
To run this mod on specific platforms you may be need to compile libraries from **intense_force** branch of [halflife-featureful](https://github.com/FreeSlave/halflife-featureful).
|
||||||
|
|
||||||
29. **[Half-Life: Opposing Force](https://store.steampowered.com/app/50/HalfLife_Opposing_Force/)**
|
32. **[Half-Life: Invasion](https://www.moddb.com/mods/half-life-invasion)**
|
||||||
|
|
||||||
|
This mod supports x86 Linux.
|
||||||
|
|
||||||
|
Support for other platforms may be available later.
|
||||||
|
|
||||||
|
33. **[Half-Life: Opposing Force](https://store.steampowered.com/app/50/HalfLife_Opposing_Force/)**
|
||||||
|
|
||||||
Steam version already supports x86 Linux.
|
Steam version already supports x86 Linux.
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **opfor** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **opfor** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
30. **[Half-Life: Quest mod](https://csm.dev/threads/half-life-the-quest-mod-isxodniki.38030/)**
|
34. **[Half-Life: Quest mod](https://csm.dev/threads/half-life-the-quest-mod-isxodniki.38030/)**
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **sci** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **sci** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
31. **[Half-Life: TopDown](https://www.moddb.com/mods/half-life-top-downs)**
|
35. **[Half-Life: Sum](https://www.moddb.com/mods/half-life-sum)**
|
||||||
|
|
||||||
|
This mod already supports x86 Linux.
|
||||||
|
|
||||||
|
To run this mod on specific platforms you may be need to compile libraries from **sum** branch of [halflife-featureful](https://github.com/FreeSlave/halflife-featureful).
|
||||||
|
|
||||||
|
36. **[Half-Life: TopDown](https://www.moddb.com/mods/half-life-top-downs)**
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **topdown** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **topdown** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
32. **[Half-Life: Urbicide](https://www.moddb.com/mods/half-life-urbicide)**
|
37. **[Half-Life: Urbicide](https://www.moddb.com/mods/half-life-urbicide)**
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **hl_urbicide** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **hl_urbicide** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
33. **[Half-Life: Visitors](https://www.moddb.com/mods/half-life-visitors)**
|
38. **[Half-Life: Visitors](https://www.moddb.com/mods/half-life-visitors)**
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **visitors** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **visitors** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
34. **[Half-Rats: Parasomnia](https://www.moddb.com/mods/half-rats-parasomnia/downloads/half-rats-parasomnia-v10b-steamlinux)**
|
39. **[Half-Rats: Parasomnia](https://www.moddb.com/mods/half-rats-parasomnia/downloads/half-rats-parasomnia-v10b-steamlinux)**
|
||||||
|
|
||||||
This mod already supports x86 Linux.
|
This mod already supports x86 Linux.
|
||||||
|
|
||||||
Support for other platforms may be available later.
|
Support for other platforms may be available later.
|
||||||
|
|
||||||
35. **[Half-Screwed: Death and Rebirth](https://www.moddb.com/mods/half-screwed)**
|
40. **[Half-Screwed: Death and Rebirth](https://www.moddb.com/mods/half-screwed)**
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **half-screwed** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **half-screwed** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
36. **[Half-Secret](https://www.moddb.com/mods/half-secret)**
|
41. **[Half-Secret](https://www.moddb.com/mods/half-secret)**
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **half-secret** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **half-secret** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
37. **[Natural Selection](https://www.moddb.com/mods/natural-selection)**
|
42. **[Mortal Kombat](https://www.moddb.com/mods/hl-mortal-kombat)**
|
||||||
|
|
||||||
|
This mod already supports Android and x86 Linux.
|
||||||
|
|
||||||
|
43. **[Natural Selection](https://www.moddb.com/mods/natural-selection)**
|
||||||
|
|
||||||
This mod already supports x86 Linux.
|
This mod already supports x86 Linux.
|
||||||
|
|
||||||
Support for other platforms may be available later.
|
Support for other platforms may be available later.
|
||||||
|
|
||||||
38. **[Night at the Office](https://www.moddb.com/mods/night-at-the-office)**
|
44. **[Night at the Office](https://www.moddb.com/mods/night-at-the-office)**
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **noffice** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **noffice** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
39. **[Paranoia](https://www.moddb.com/mods/paranoia)**
|
45. **[Paranoia](https://www.moddb.com/mods/paranoia)**
|
||||||
|
|
||||||
*Support temporary abandoned*
|
*Support temporary abandoned*
|
||||||
|
|
||||||
[Source code](https://github.com/FWGS/paranoia_toolkit).
|
[Source code](https://github.com/FWGS/paranoia_toolkit).
|
||||||
|
|
||||||
40. **[Poke646](https://poke646.com/)**
|
46. **[Poke646](https://poke646.com/)**
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **poke646** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **poke646** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
41. **[Poke646: Vendetta](https://poke646.com/)**
|
47. **[Poke646: Vendetta](https://poke646.com/)**
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **poke646_vendetta** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **poke646_vendetta** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
42. [PrimeXT](https://snmetamorph.github.io/PrimeXT/)
|
48. [PrimeXT](https://snmetamorph.github.io/PrimeXT/)
|
||||||
|
|
||||||
|
*It's modding SDK*
|
||||||
|
|
||||||
[Source code](https://github.com/SNMetamorph/PrimeXT)
|
[Source code](https://github.com/SNMetamorph/PrimeXT)
|
||||||
|
|
||||||
43. **[Quake Remake](https://www.moddb.com/games/quake-remake)**
|
49. **[Quake Remake](https://www.moddb.com/games/quake-remake)**
|
||||||
|
|
||||||
*Support was fully abandoned due Quake Wrapper release.*
|
*Support was fully abandoned due Quake Wrapper release.*
|
||||||
|
|
||||||
[Actual source code](https://github.com/FWGS/quakeremake)
|
[Actual source code](https://github.com/FWGS/quakeremake)
|
||||||
|
|
||||||
44. **[Rebellion](https://www.moddb.com/mods/rebellion1)**
|
50. **[Rebellion](https://www.moddb.com/mods/rebellion1)**
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **rebellion** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **rebellion** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
45. **[Residual Life](https://www.moddb.com/mods/hl-residual-life)**
|
51. **[Residual Life](https://www.moddb.com/mods/hl-residual-life)**
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **residual_point** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **residual_point** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
46. **[Residual Point](https://www.moddb.com/mods/hl-residual-point)**
|
52. **[Residual Point](https://www.moddb.com/mods/hl-residual-point)**
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **residual_point** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **residual_point** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
47. **[Ricochet](https://store.steampowered.com/app/60/Ricochet/)**
|
53. **[Ricochet](https://store.steampowered.com/app/60/Ricochet/)**
|
||||||
|
|
||||||
This mod already supports x86 Linux.
|
This mod already supports x86 Linux.
|
||||||
|
|
||||||
Support for other platforms may be available later.
|
Support for other platforms may be available later.
|
||||||
|
|
||||||
48. [Sewer](https://www.moddb.com/games/half-life/addons/sewer-beta)
|
54. [Sewer](https://www.moddb.com/games/half-life/addons/sewer-beta)
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **sewer_beta** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **sewer_beta** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
49. [Spirit of Half-Life 1.2](https://www.moddb.com/mods/spirit-of-half-life)
|
55. [Spirit of Half-Life 1.2](https://www.moddb.com/mods/spirit-of-half-life)
|
||||||
|
|
||||||
|
*It's modding SDK*
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **sohl1.2** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **sohl1.2** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
50. **[Swiss Cheese Halloween](https://www.moddb.com/mods/half-life-halloween-mod)**
|
56. **[Swiss Cheese Halloween](https://www.moddb.com/mods/half-life-halloween-mod)**
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **halloween** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **halloween** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
51. **[Team Fortress Classic](https://store.steampowered.com/app/20/Team_Fortress_Classic/)**
|
57. **[Team Fortress Classic](https://store.steampowered.com/app/20/Team_Fortress_Classic/)**
|
||||||
|
|
||||||
This mod already supports x86 Linux.
|
This mod already supports x86 Linux.
|
||||||
|
|
||||||
Currently, only source code of [client part](https://github.com/Velaron/tf15-client) is available.
|
Currently, only source code of [client part](https://github.com/Velaron/tf15-client) is available.
|
||||||
|
|
||||||
52. **[The Gate](https://www.moddb.com/mods/the-gate)**
|
58. **[The Gate](https://www.moddb.com/mods/the-gate)**
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **thegate** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **thegate** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
53. **[They Hunger: Trilogy](https://www.moddb.com/mods/they-hunger)**
|
59. **[The Last Bullet](https://www.moddb.com/mods/the-last-bullet-update)**
|
||||||
|
|
||||||
|
To run this mod on specific platforms you may be need to compile libraries from **fwgs** branch of [The-Last-Bullet-Updated-Code](https://github.com/GT-Project-Cat/The-Last-Bullet-Updated-Code).
|
||||||
|
|
||||||
|
60. **[They Hunger: Trilogy](https://www.moddb.com/mods/they-hunger)**
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **theyhunger** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **theyhunger** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
54. **[ThreeWave CTF](https://www.moddb.com/games/deathmatch-classic/downloads/threewave-ctf)**
|
61. **[ThreeWave CTF](https://www.moddb.com/games/deathmatch-classic/downloads/threewave-ctf)**
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **dmc** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **dmc** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
55. **[Times of Troubles](https://www.moddb.com/mods/times-of-troubles)**
|
62. **[Times of Troubles](https://www.moddb.com/mods/times-of-troubles)**
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **tot** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **tot** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
56. [XashXT](https://csm.dev/threads/xashxt-0-65-rev-4-release-stable.38319/)
|
63. [XashXT](https://csm.dev/threads/xashxt-0-65-rev-4-release-stable.38319/)
|
||||||
|
|
||||||
|
*It's modding SDK*
|
||||||
|
|
||||||
*Support was fully abandoned due PrimeXT development*
|
*Support was fully abandoned due PrimeXT development*
|
||||||
|
|
||||||
[Source code](https://github.com/FWGS/XashXT-FWGS/)
|
[Source code](https://github.com/FWGS/XashXT-FWGS/)
|
||||||
|
|
||||||
57. **[X-Half-Life DeathMatch](https://www.moddb.com/mods/xdm)**
|
64. **[X-Half-Life DeathMatch](https://www.moddb.com/mods/xdm)**
|
||||||
|
|
||||||
This mod already supports x86 Linux.
|
This mod already supports x86 Linux.
|
||||||
|
|
||||||
Support for other platforms may be available later.
|
Support for other platforms may be available later.
|
||||||
|
|
||||||
58. **[Xen-Warrior](https://www.moddb.com/mods/xen-warrior)**
|
65. **[Xen-Warrior](https://www.moddb.com/mods/xen-warrior)**
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **sohl1.2** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **sohl1.2** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
Don't forget to enable XENWARRIOR build option!!!
|
Don't forget to enable XENWARRIOR build option!!!
|
||||||
|
|
||||||
59. [Zombie-X](https://www.moddb.com/mods/zombie-x-10-final)
|
66. **[Yet another PS2 Half-Life port](https://www.moddb.com/mods/yet-another-ps2-half-life-pc-port)**
|
||||||
|
|
||||||
|
To run this mod on specific platforms you may be need to compile libraries from **ps2hl** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
|
67. [Zombie-X](https://www.moddb.com/mods/zombie-x-10-final)
|
||||||
|
|
||||||
To run this mod on specific platforms you may be need to compile libraries from **zombie-x** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
To run this mod on specific platforms you may be need to compile libraries from **zombie-x** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
|
||||||
|
|
||||||
|
|||||||
@@ -706,9 +706,6 @@ static void R_CollectRendererNames( void )
|
|||||||
#if XASH_REF_GLES3COMPAT_ENABLED
|
#if XASH_REF_GLES3COMPAT_ENABLED
|
||||||
"gles3compat",
|
"gles3compat",
|
||||||
#endif
|
#endif
|
||||||
#if XASH_REF_DX2_ENABLED
|
|
||||||
"dx2",
|
|
||||||
#endif
|
|
||||||
#if XASH_REF_SOFT_ENABLED
|
#if XASH_REF_SOFT_ENABLED
|
||||||
"soft",
|
"soft",
|
||||||
#endif
|
#endif
|
||||||
@@ -732,9 +729,6 @@ static void R_CollectRendererNames( void )
|
|||||||
#if XASH_REF_GLES3COMPAT_ENABLED
|
#if XASH_REF_GLES3COMPAT_ENABLED
|
||||||
"GLES3 (gl2_shim)",
|
"GLES3 (gl2_shim)",
|
||||||
#endif
|
#endif
|
||||||
#if XASH_REF_DX2_ENABLED
|
|
||||||
"DirectX 2",
|
|
||||||
#endif
|
|
||||||
#if XASH_REF_SOFT_ENABLED
|
#if XASH_REF_SOFT_ENABLED
|
||||||
"Software",
|
"Software",
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -15,14 +15,13 @@ GNU General Public License for more details.
|
|||||||
|
|
||||||
#include "build.h"
|
#include "build.h"
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#if XASH_LINUX
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#if !XASH_WIN32
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#else
|
|
||||||
#include <io.h>
|
|
||||||
#endif
|
#endif
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
|
#include "platform/platform.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==========================================================
|
==========================================================
|
||||||
@@ -97,8 +96,6 @@ IDENTIFICATION
|
|||||||
#define MAXBITS_GEN 30
|
#define MAXBITS_GEN 30
|
||||||
#define MAXBITS_CHECK MAXBITS_GEN + 6
|
#define MAXBITS_CHECK MAXBITS_GEN + 6
|
||||||
|
|
||||||
static qboolean ID_ProcessFile( bloomfilter_t *value, const char *path );
|
|
||||||
|
|
||||||
static void ID_BloomFilter_f( void )
|
static void ID_BloomFilter_f( void )
|
||||||
{
|
{
|
||||||
bloomfilter_t value = 0;
|
bloomfilter_t value = 0;
|
||||||
@@ -203,84 +200,6 @@ static qboolean ID_ProcessCPUInfo( bloomfilter_t *value )
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static qboolean ID_ValidateNetDevice( const char *dev )
|
|
||||||
{
|
|
||||||
const char *prefix = "/sys/class/net";
|
|
||||||
|
|
||||||
// These devices are fake, their mac address is generated each boot, while assign_type is 0
|
|
||||||
if( !Q_strnicmp( dev, "ccmni", sizeof( "ccmni" ) ) ||
|
|
||||||
!Q_strnicmp( dev, "ifb", sizeof( "ifb" ) ) )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
byte *pfile = FS_LoadDirectFile( va( "%s/%s/addr_assign_type", prefix, dev ), NULL );
|
|
||||||
|
|
||||||
// if NULL, it may be old kernel
|
|
||||||
if( pfile )
|
|
||||||
{
|
|
||||||
int assignType = Q_atoi( (char*)pfile );
|
|
||||||
|
|
||||||
Mem_Free( pfile );
|
|
||||||
|
|
||||||
// check is MAC address is constant
|
|
||||||
if( assignType != 0 )
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ID_ProcessNetDevices( bloomfilter_t *value )
|
|
||||||
{
|
|
||||||
const char *prefix = "/sys/class/net";
|
|
||||||
DIR *dir;
|
|
||||||
struct dirent *entry;
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
if( !( dir = opendir( prefix ) ) )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
while( ( entry = readdir( dir ) ) && BloomFilter_Weight( *value ) < MAXBITS_GEN )
|
|
||||||
{
|
|
||||||
if( !Q_strcmp( entry->d_name, "." ) || !Q_strcmp( entry->d_name, ".." ) )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if( !ID_ValidateNetDevice( entry->d_name ) )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
count += ID_ProcessFile( value, va( "%s/%s/address", prefix, entry->d_name ) );
|
|
||||||
}
|
|
||||||
closedir( dir );
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ID_CheckNetDevices( bloomfilter_t value )
|
|
||||||
{
|
|
||||||
const char *prefix = "/sys/class/net";
|
|
||||||
|
|
||||||
DIR *dir;
|
|
||||||
struct dirent *entry;
|
|
||||||
int count = 0;
|
|
||||||
bloomfilter_t filter = 0;
|
|
||||||
|
|
||||||
if( !( dir = opendir( prefix ) ) )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
while( ( entry = readdir( dir ) ) )
|
|
||||||
{
|
|
||||||
if( !Q_strcmp( entry->d_name, "." ) || !Q_strcmp( entry->d_name, ".." ) )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if( !ID_ValidateNetDevice( entry->d_name ) )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if( ID_ProcessFile( &filter, va( "%s/%s/address", prefix, entry->d_name ) ) )
|
|
||||||
count += ( value & filter ) == filter, filter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir( dir );
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ID_TestCPUInfo_f( void )
|
static void ID_TestCPUInfo_f( void )
|
||||||
{
|
{
|
||||||
bloomfilter_t value = 0;
|
bloomfilter_t value = 0;
|
||||||
@@ -291,8 +210,6 @@ static void ID_TestCPUInfo_f( void )
|
|||||||
Msg( "Could not get serial\n" );
|
Msg( "Could not get serial\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static qboolean ID_ProcessFile( bloomfilter_t *value, const char *path )
|
static qboolean ID_ProcessFile( bloomfilter_t *value, const char *path )
|
||||||
{
|
{
|
||||||
int fd = open( path, O_RDONLY );
|
int fd = open( path, O_RDONLY );
|
||||||
@@ -322,7 +239,6 @@ static qboolean ID_ProcessFile( bloomfilter_t *value, const char *path )
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !XASH_WIN32
|
|
||||||
static int ID_ProcessFiles( bloomfilter_t *value, const char *prefix, const char *postfix )
|
static int ID_ProcessFiles( bloomfilter_t *value, const char *prefix, const char *postfix )
|
||||||
{
|
{
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
@@ -365,7 +281,94 @@ static int ID_CheckFiles( bloomfilter_t value, const char *prefix, const char *p
|
|||||||
closedir( dir );
|
closedir( dir );
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
#else
|
#endif // XASH_LINUX
|
||||||
|
|
||||||
|
#if XASH_POSIX
|
||||||
|
#define MAX_NETDEVICES 16
|
||||||
|
|
||||||
|
static qboolean ID_IsReservedMAC( uint64_t mac )
|
||||||
|
{
|
||||||
|
byte first = ( mac >> 40 ) & 0xff;
|
||||||
|
|
||||||
|
// no address at all
|
||||||
|
if( mac == 0 )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// group and local bits of the first octet, see https://www.rfc-editor.org/rfc/rfc9542#section-2.1.1
|
||||||
|
if( FBitSet( first, 0x01 ) || FBitSet( first, 0x02 ))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// IANA OUI, see https://www.iana.org/assignments/ethernet-numbers/ethernet-numbers.xhtml and https://www.rfc-editor.org/rfc/rfc9568#section-7.3
|
||||||
|
if(( mac >> 24 ) == 0x00005e )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ID_FormatMAC( char *out, size_t size, uint64_t mac )
|
||||||
|
{
|
||||||
|
// format exactly like /sys/class/net/ */address contents, so ids generated by older versions stay valid
|
||||||
|
Q_snprintf( out, size, "%02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||||
|
(uint)(( mac >> 40 ) & 0xffu ),
|
||||||
|
(uint)(( mac >> 32 ) & 0xffu ),
|
||||||
|
(uint)(( mac >> 24 ) & 0xffu ),
|
||||||
|
(uint)(( mac >> 16 ) & 0xffu ),
|
||||||
|
(uint)(( mac >> 8 ) & 0xffu ),
|
||||||
|
(uint)( mac & 0xffu ));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ID_ProcessNetDevices( bloomfilter_t *value )
|
||||||
|
{
|
||||||
|
uint64_t macs[MAX_NETDEVICES];
|
||||||
|
int total = Posix_GetNetDeviceAddresses( macs, MAX_NETDEVICES );
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for( int i = 0; i < total && BloomFilter_Weight( *value ) < MAXBITS_GEN; i++ )
|
||||||
|
{
|
||||||
|
char buf[32];
|
||||||
|
|
||||||
|
if( ID_IsReservedMAC( macs[i] ))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ID_FormatMAC( buf, sizeof( buf ), macs[i] );
|
||||||
|
|
||||||
|
if( !ID_VerifyHEX( buf ))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
*value |= BloomFilter_ProcessStr( buf );
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ID_CheckNetDevices( bloomfilter_t value )
|
||||||
|
{
|
||||||
|
uint64_t macs[MAX_NETDEVICES];
|
||||||
|
int total = Posix_GetNetDeviceAddresses( macs, MAX_NETDEVICES );
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for( int i = 0; i < total; i++ )
|
||||||
|
{
|
||||||
|
char buf[32];
|
||||||
|
|
||||||
|
if( ID_IsReservedMAC( macs[i] ))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ID_FormatMAC( buf, sizeof( buf ), macs[i] );
|
||||||
|
|
||||||
|
if( !ID_VerifyHEX( buf ))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bloomfilter_t filter = BloomFilter_ProcessStr( buf );
|
||||||
|
count += ( value & filter ) == filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
#endif // XASH_POSIX
|
||||||
|
|
||||||
|
#if XASH_WIN32
|
||||||
static int ID_GetKeyData( HKEY hRootKey, char *subKey, char *value, LPBYTE data, DWORD cbData )
|
static int ID_GetKeyData( HKEY hRootKey, char *subKey, char *value, LPBYTE data, DWORD cbData )
|
||||||
{
|
{
|
||||||
HKEY hKey;
|
HKEY hKey;
|
||||||
@@ -539,6 +542,17 @@ static bloomfilter_t ID_GenerateRawId( void )
|
|||||||
|
|
||||||
count += ID_ProcessCPUInfo( &value );
|
count += ID_ProcessCPUInfo( &value );
|
||||||
count += ID_ProcessFiles( &value, "/sys/block", "device/cid" );
|
count += ID_ProcessFiles( &value, "/sys/block", "device/cid" );
|
||||||
|
#endif
|
||||||
|
#if XASH_OSX
|
||||||
|
char buf[64];
|
||||||
|
|
||||||
|
if( Apple_GetSerialNumber( buf, sizeof( buf )))
|
||||||
|
{
|
||||||
|
value |= BloomFilter_ProcessStr( buf );
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if XASH_POSIX
|
||||||
count += ID_ProcessNetDevices( &value );
|
count += ID_ProcessNetDevices( &value );
|
||||||
#endif
|
#endif
|
||||||
#if XASH_WIN32
|
#if XASH_WIN32
|
||||||
@@ -587,12 +601,26 @@ static uint ID_CheckRawId( bloomfilter_t filter )
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif // !XASH_ANDROID
|
#endif // !XASH_ANDROID
|
||||||
count += ID_CheckNetDevices( filter );
|
|
||||||
count += ID_CheckFiles( filter, "/sys/block", "device/cid" );
|
count += ID_CheckFiles( filter, "/sys/block", "device/cid" );
|
||||||
if( ID_ProcessCPUInfo( &value ) )
|
if( ID_ProcessCPUInfo( &value ) )
|
||||||
count += (filter & value) == value;
|
count += (filter & value) == value;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if XASH_OSX
|
||||||
|
char buf[64];
|
||||||
|
|
||||||
|
if( Apple_GetSerialNumber( buf, sizeof( buf )))
|
||||||
|
{
|
||||||
|
value = BloomFilter_ProcessStr( buf );
|
||||||
|
count += (filter & value) == value;
|
||||||
|
value = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if XASH_POSIX
|
||||||
|
count += ID_CheckNetDevices( filter );
|
||||||
|
#endif
|
||||||
|
|
||||||
#if XASH_WIN32
|
#if XASH_WIN32
|
||||||
count += ID_CheckWMIC( filter, L"wmic path win32_physicalmedia get SerialNumber" );
|
count += ID_CheckWMIC( filter, L"wmic path win32_physicalmedia get SerialNumber" );
|
||||||
count += ID_CheckWMIC( filter, L"wmic bios get serialnumber" );
|
count += ID_CheckWMIC( filter, L"wmic bios get serialnumber" );
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ typedef struct
|
|||||||
{
|
{
|
||||||
void *context; // handle to GL rendering context
|
void *context; // handle to GL rendering context
|
||||||
ref_safegl_context_t safe;
|
ref_safegl_context_t safe;
|
||||||
ref_graphic_apis_t type;
|
qboolean software;
|
||||||
} glwstate_t;
|
} glwstate_t;
|
||||||
|
|
||||||
extern glwstate_t glw_state;
|
extern glwstate_t glw_state;
|
||||||
|
|||||||
@@ -731,69 +731,77 @@ Image_SaveWAD
|
|||||||
*/
|
*/
|
||||||
qboolean Image_SaveWAD( const char *name, rgbdata_t *pix )
|
qboolean Image_SaveWAD( const char *name, rgbdata_t *pix )
|
||||||
{
|
{
|
||||||
byte *mip1_data = NULL, *mip2_data = NULL, *mip3_data = NULL;
|
|
||||||
byte grad_palette[256 * 3];
|
|
||||||
file_t *f;
|
|
||||||
dwadinfo_t header =
|
|
||||||
{
|
|
||||||
.ident = IDWAD3HEADER,
|
|
||||||
.numlumps = 1,
|
|
||||||
};
|
|
||||||
mip_t miptex;
|
|
||||||
long infotableofs;
|
|
||||||
dlumpinfo_t lump;
|
|
||||||
fs_offset_t pad;
|
|
||||||
qboolean result = false;
|
|
||||||
int lump_type = ( pix->flags & IMAGE_GRADIENT_DECAL ) ? TYP_PALETTE : TYP_MIPTEX;
|
|
||||||
short palette_size = 256;
|
|
||||||
int infotableofs32 = 0;
|
|
||||||
|
|
||||||
if( !pix || !pix->buffer )
|
if( !pix || !pix->buffer )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const byte *palette = pix->palette ? pix->palette : (const byte *)image.palette;
|
const int lump_type = ( pix->flags & IMAGE_GRADIENT_DECAL ) ? TYP_PALETTE : TYP_MIPTEX;
|
||||||
|
|
||||||
int m0size = pix->width * pix->height;
|
int m0size = pix->width * pix->height;
|
||||||
int m1size = m0size / 4;
|
int m1size = m0size / 4;
|
||||||
int m2size = m0size / 16;
|
int m2size = m0size / 16;
|
||||||
int m3size = m0size / 64;
|
int m3size = m0size / 64;
|
||||||
|
|
||||||
mip1_data = (byte *)Mem_Malloc( host.imagepool, m1size );
|
byte *mip1_data = Mem_Malloc( host.imagepool, m1size );
|
||||||
mip2_data = (byte *)Mem_Malloc( host.imagepool, m2size );
|
byte *mip2_data = Mem_Malloc( host.imagepool, m2size );
|
||||||
mip3_data = (byte *)Mem_Malloc( host.imagepool, m3size );
|
byte *mip3_data = Mem_Malloc( host.imagepool, m3size );
|
||||||
if( !mip1_data || !mip2_data || !mip3_data )
|
if( !mip1_data || !mip2_data || !mip3_data ) // Mem_Malloc never returns NULL, but keep this check anyway
|
||||||
goto cleanup;
|
{
|
||||||
|
Mem_Free( mip1_data );
|
||||||
|
Mem_Free( mip2_data );
|
||||||
|
Mem_Free( mip3_data );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Image_GenerateMipmaps( pix->buffer, pix->width, pix->height, mip1_data, mip2_data, mip3_data );
|
Image_GenerateMipmaps( pix->buffer, pix->width, pix->height, mip1_data, mip2_data, mip3_data );
|
||||||
|
|
||||||
memset( &miptex, 0, sizeof( mip_t ));
|
file_t *f = FS_Open( name, "wb", false );
|
||||||
Q_strncpy( miptex.name, "{LOGO", sizeof( miptex.name ));
|
|
||||||
miptex.width = pix->width;
|
|
||||||
miptex.height = pix->height;
|
|
||||||
miptex.offsets[0] = sizeof( mip_t );
|
|
||||||
miptex.offsets[1] = miptex.offsets[0] + m0size;
|
|
||||||
miptex.offsets[2] = miptex.offsets[1] + m1size;
|
|
||||||
miptex.offsets[3] = miptex.offsets[2] + m2size;
|
|
||||||
|
|
||||||
f = FS_Open( name, "wb", false );
|
|
||||||
if( !f )
|
if( !f )
|
||||||
goto cleanup;
|
{
|
||||||
|
Mem_Free( mip1_data );
|
||||||
|
Mem_Free( mip2_data );
|
||||||
|
Mem_Free( mip3_data );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
le_struct_swap( dwadinfo_swap, &header );
|
{
|
||||||
FS_Write( f, &header, sizeof( header ));
|
dwadinfo_t header =
|
||||||
|
{
|
||||||
|
.ident = IDWAD3HEADER,
|
||||||
|
.numlumps = 1,
|
||||||
|
};
|
||||||
|
le_struct_swap( dwadinfo_swap, &header );
|
||||||
|
FS_Write( f, &header, sizeof( header ));
|
||||||
|
}
|
||||||
|
|
||||||
|
mip_t miptex = {
|
||||||
|
.name = "{LOGO",
|
||||||
|
.width = pix->width,
|
||||||
|
.height = pix->height,
|
||||||
|
.offsets[0] = sizeof( mip_t ),
|
||||||
|
.offsets[1] = sizeof( mip_t ) + m0size,
|
||||||
|
.offsets[2] = sizeof( mip_t ) + m0size + m1size,
|
||||||
|
.offsets[3] = sizeof( mip_t ) + m0size + m1size + m2size,
|
||||||
|
};
|
||||||
le_struct_swap( mip_swap, &miptex );
|
le_struct_swap( mip_swap, &miptex );
|
||||||
FS_Write( f, &miptex, sizeof( mip_t ));
|
FS_Write( f, &miptex, sizeof( mip_t ));
|
||||||
le_struct_swap( mip_swap, &miptex );
|
le_struct_swap( mip_swap, &miptex );
|
||||||
|
|
||||||
FS_Write( f, pix->buffer, m0size );
|
FS_Write( f, pix->buffer, m0size );
|
||||||
FS_Write( f, mip1_data, m1size );
|
FS_Write( f, mip1_data, m1size );
|
||||||
FS_Write( f, mip2_data, m2size );
|
FS_Write( f, mip2_data, m2size );
|
||||||
FS_Write( f, mip3_data, m3size );
|
FS_Write( f, mip3_data, m3size );
|
||||||
palette_size = LittleShort( palette_size );
|
|
||||||
FS_Write( f, &palette_size, sizeof( short ));
|
{
|
||||||
|
short palette_size = LittleShort( 256 );
|
||||||
|
FS_Write( f, &palette_size, sizeof( short ));
|
||||||
|
}
|
||||||
|
|
||||||
|
const byte *palette = pix->palette ? pix->palette : (const byte *)image.palette;
|
||||||
|
|
||||||
if( lump_type == TYP_PALETTE )
|
if( lump_type == TYP_PALETTE )
|
||||||
{
|
{
|
||||||
const byte *frontColorPtr = palette + 255 * 3;
|
const byte *frontColorPtr = palette + 255 * 3;
|
||||||
|
byte grad_palette[256 * 3];
|
||||||
for( int i = 0; i < 256; ++i )
|
for( int i = 0; i < 256; ++i )
|
||||||
{
|
{
|
||||||
float t = i / 255.0f;
|
float t = i / 255.0f;
|
||||||
@@ -809,34 +817,37 @@ qboolean Image_SaveWAD( const char *name, rgbdata_t *pix )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// padding up to a multiple of 4
|
// padding up to a multiple of 4
|
||||||
pad = (( FS_Tell( f ) + 3 ) & ~3 ) - FS_Tell( f );
|
fs_offset_t pad = (( FS_Tell( f ) + 3 ) & ~3 ) - FS_Tell( f );
|
||||||
for( int i = 0; i < pad; ++i )
|
for( int i = 0; i < pad; ++i )
|
||||||
FS_Write( f, (const void *)&(char){0}, 1 );
|
{
|
||||||
|
byte x = 0;
|
||||||
|
FS_Write( f, &x, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
infotableofs = FS_Tell( f );
|
fs_offset_t infotableofs = FS_Tell( f );
|
||||||
memset( &lump, 0, sizeof( lump ));
|
|
||||||
lump.filepos = sizeof( dwadinfo_t );
|
{
|
||||||
lump.disksize = (int)( miptex.offsets[3] + m3size + sizeof( short ) + 256 * 3 );
|
dlumpinfo_t lump =
|
||||||
lump.size = lump.disksize;
|
{
|
||||||
lump.type = (char)lump_type;
|
.filepos = sizeof( dwadinfo_t ),
|
||||||
lump.attribs = 0;
|
.disksize = (int)( miptex.offsets[3] + m3size + sizeof( short ) + 256 * 3 ),
|
||||||
Q_strncpy( lump.name, "tempdecal", sizeof( lump.name ));
|
.size = (int)( miptex.offsets[3] + m3size + sizeof( short ) + 256 * 3 ),
|
||||||
le_struct_swap( dlumpinfo_swap, &lump );
|
.type = (char)lump_type,
|
||||||
FS_Write( f, &lump, sizeof( lump ));
|
.attribs = 0,
|
||||||
|
.name = "tempdecal",
|
||||||
|
};
|
||||||
|
le_struct_swap( dlumpinfo_swap, &lump );
|
||||||
|
FS_Write( f, &lump, sizeof( lump ));
|
||||||
|
}
|
||||||
|
|
||||||
FS_Seek( f, offsetof( dwadinfo_t, infotableofs ), SEEK_SET );
|
FS_Seek( f, offsetof( dwadinfo_t, infotableofs ), SEEK_SET );
|
||||||
infotableofs32 = LittleLong((int)infotableofs );
|
int infotableofs32 = LittleLong((int)infotableofs );
|
||||||
FS_Write( f, &infotableofs32, sizeof( int ));
|
FS_Write( f, &infotableofs32, sizeof( int ));
|
||||||
|
|
||||||
FS_Close( f );
|
FS_Close( f );
|
||||||
result = true;
|
|
||||||
|
|
||||||
cleanup:
|
Mem_Free( mip1_data );
|
||||||
if( mip1_data )
|
Mem_Free( mip2_data );
|
||||||
Mem_Free( mip1_data );
|
Mem_Free( mip3_data );
|
||||||
if( mip2_data )
|
return true;
|
||||||
Mem_Free( mip2_data );
|
|
||||||
if( mip3_data )
|
|
||||||
Mem_Free( mip3_data );
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|||||||
50
engine/platform/apple/id_apple.c
Normal file
50
engine/platform/apple/id_apple.c
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
id_apple.c - macOS hardware serial id source
|
||||||
|
Copyright (C) 2026 Xash3D FWGS Contributors
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "platform/platform.h"
|
||||||
|
#include <AvailabilityMacros.h>
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
#include <IOKit/IOKitLib.h>
|
||||||
|
|
||||||
|
// kIOMasterPortDefault was renamed to kIOMainPortDefault in macOS 12 SDK
|
||||||
|
#if MAC_OS_X_VERSION_MIN_REQUIRED < 120000
|
||||||
|
#define kIOMainPortDefault kIOMasterPortDefault
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static qboolean Apple_GetPlatformExpertProperty( CFStringRef key, char *out, size_t size )
|
||||||
|
{
|
||||||
|
io_service_t service = IOServiceGetMatchingService( kIOMainPortDefault, IOServiceMatching( "IOPlatformExpertDevice" ));
|
||||||
|
|
||||||
|
if( !service )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
qboolean ret = false;
|
||||||
|
CFTypeRef prop = IORegistryEntryCreateCFProperty( service, key, kCFAllocatorDefault, 0 );
|
||||||
|
|
||||||
|
if( prop )
|
||||||
|
{
|
||||||
|
if( CFGetTypeID( prop ) == CFStringGetTypeID() && CFStringGetCString( (CFStringRef)prop, out, size, kCFStringEncodingUTF8 ))
|
||||||
|
ret = true;
|
||||||
|
CFRelease( prop );
|
||||||
|
}
|
||||||
|
|
||||||
|
IOObjectRelease( service );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean Apple_GetSerialNumber( char *out, size_t size )
|
||||||
|
{
|
||||||
|
return Apple_GetPlatformExpertProperty( CFSTR( "IOPlatformSerialNumber" ), out, size );
|
||||||
|
}
|
||||||
@@ -69,6 +69,12 @@ void IOS_LaunchDialog( void );
|
|||||||
void Posix_Daemonize( void );
|
void Posix_Daemonize( void );
|
||||||
void Posix_SetupSigtermHandling( void );
|
void Posix_SetupSigtermHandling( void );
|
||||||
char *Posix_Input( void );
|
char *Posix_Input( void );
|
||||||
|
// returns the number of stable network device MAC addresses, each packed into low 48 bits
|
||||||
|
int Posix_GetNetDeviceAddresses( uint64_t *addresses, int max );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if XASH_OSX
|
||||||
|
qboolean Apple_GetSerialNumber( char *out, size_t size );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if XASH_SDL
|
#if XASH_SDL
|
||||||
|
|||||||
141
engine/platform/posix/id_posix.c
Normal file
141
engine/platform/posix/id_posix.c
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
id_posix.c - network device enumeration for unique id generation
|
||||||
|
Copyright (C) 2026 Xash3D FWGS contributors
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "platform/platform.h"
|
||||||
|
|
||||||
|
#if XASH_LINUX
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static qboolean Posix_ValidateNetDevice( const char *dev )
|
||||||
|
{
|
||||||
|
const char *prefix = "/sys/class/net";
|
||||||
|
|
||||||
|
// These devices are fake, their mac address is generated each boot, while assign_type is 0
|
||||||
|
if( !Q_strnicmp( dev, "ccmni", sizeof( "ccmni" ) - 1 ) || !Q_strnicmp( dev, "ifb", sizeof( "ifb" ) - 1 ))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
byte *pfile = FS_LoadDirectFile( va( "%s/%s/addr_assign_type", prefix, dev ), NULL );
|
||||||
|
|
||||||
|
// if NULL, it may be old kernel
|
||||||
|
if( pfile )
|
||||||
|
{
|
||||||
|
int assignType = Q_atoi( (char*)pfile );
|
||||||
|
|
||||||
|
Mem_Free( pfile );
|
||||||
|
|
||||||
|
// check is MAC address is constant
|
||||||
|
if( assignType != 0 )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Posix_GetNetDeviceAddresses( uint64_t *addresses, int max )
|
||||||
|
{
|
||||||
|
const char *prefix = "/sys/class/net";
|
||||||
|
DIR *dir = opendir( prefix );
|
||||||
|
struct dirent *entry;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
if( !dir )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while(( entry = readdir( dir )) && count < max )
|
||||||
|
{
|
||||||
|
if( !Q_strcmp( entry->d_name, "." ) || !Q_strcmp( entry->d_name, ".." ))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( !Posix_ValidateNetDevice( entry->d_name ))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int fd = open( va( "%s/%s/address", prefix, entry->d_name ), O_RDONLY );
|
||||||
|
|
||||||
|
if( fd < 0 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
char buffer[64];
|
||||||
|
int ret = read( fd, buffer, sizeof( buffer ) - 1 );
|
||||||
|
|
||||||
|
close( fd );
|
||||||
|
|
||||||
|
if( ret <= 0 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
buffer[ret] = 0;
|
||||||
|
|
||||||
|
uint mac[6];
|
||||||
|
char term = 0;
|
||||||
|
|
||||||
|
if( sscanf( buffer, "%02x:%02x:%02x:%02x:%02x:%02x%c", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5], &term ) < 6 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// skip malformed or long address devices, we only need MAC addresses and they're always 48-bit
|
||||||
|
if( term != '\n' && term != '\0' )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
addresses[count] = ((uint64_t)mac[0] << 40) | ((uint64_t)mac[1] << 32) | ((uint64_t)mac[2] << 24) | ((uint64_t)mac[3] << 16) | ((uint64_t)mac[4] << 8) | (uint64_t)mac[5];
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir( dir );
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
#elif XASH_APPLE || XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <ifaddrs.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/if_dl.h>
|
||||||
|
|
||||||
|
int Posix_GetNetDeviceAddresses( uint64_t *addresses, int max )
|
||||||
|
{
|
||||||
|
struct ifaddrs *ifaddr;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
if( getifaddrs( &ifaddr ) < 0 )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for( struct ifaddrs *ifa = ifaddr; ifa != NULL && count < max; ifa = ifa->ifa_next )
|
||||||
|
{
|
||||||
|
if( !ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_LINK )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( FBitSet( ifa->ifa_flags, IFF_LOOPBACK | IFF_POINTOPOINT ))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const struct sockaddr_dl *sdl = (const struct sockaddr_dl *)ifa->ifa_addr;
|
||||||
|
|
||||||
|
if( sdl->sdl_alen != 6 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const byte *mac = (const byte *)LLADDR( sdl );
|
||||||
|
|
||||||
|
addresses[count] = ((uint64_t)mac[0] << 40) | ((uint64_t)mac[1] << 32) | ((uint64_t)mac[2] << 24) | ((uint64_t)mac[3] << 16) | ((uint64_t)mac[4] << 8) | (uint64_t)mac[5];
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
freeifaddrs( ifaddr );
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int Posix_GetNetDeviceAddresses( uint64_t *addresses, int max )
|
||||||
|
{
|
||||||
|
Con_Reportf( S_WARN "%s: implement me!\n", __func__ );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -285,7 +285,7 @@ qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
|
|||||||
if( window_mode != WINDOW_MODE_WINDOWED )
|
if( window_mode != WINDOW_MODE_WINDOWED )
|
||||||
SetBits( flags, SDL_FULLSCREEN|SDL_HWSURFACE );
|
SetBits( flags, SDL_FULLSCREEN|SDL_HWSURFACE );
|
||||||
|
|
||||||
if( glw_state.type == REF_GL )
|
if( !glw_state.software )
|
||||||
SetBits( flags, SDL_OPENGL );
|
SetBits( flags, SDL_OPENGL );
|
||||||
|
|
||||||
if( !VID_CreateWindowWithSafeGL( wndname, 0, 0, width, height, flags ))
|
if( !VID_CreateWindowWithSafeGL( wndname, 0, 0, width, height, flags ))
|
||||||
@@ -381,10 +381,10 @@ qboolean R_Init_Video( ref_graphic_apis_t type )
|
|||||||
|
|
||||||
refState.desktopBitsPixel = 16;
|
refState.desktopBitsPixel = 16;
|
||||||
|
|
||||||
glw_state.type = type;
|
|
||||||
switch( type )
|
switch( type )
|
||||||
{
|
{
|
||||||
case REF_SOFTWARE:
|
case REF_SOFTWARE:
|
||||||
|
glw_state.software = true;
|
||||||
break;
|
break;
|
||||||
case REF_GL:
|
case REF_GL:
|
||||||
if( !glw_state.safe && Sys_GetParmFromCmdLine( "-safegl", safe ) )
|
if( !glw_state.safe && Sys_GetParmFromCmdLine( "-safegl", safe ) )
|
||||||
@@ -399,8 +399,6 @@ qboolean R_Init_Video( ref_graphic_apis_t type )
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case REF_D3D:
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
Host_Error( "Can't initialize unknown context type %d!\n", type );
|
Host_Error( "Can't initialize unknown context type %d!\n", type );
|
||||||
break;
|
break;
|
||||||
@@ -419,7 +417,6 @@ qboolean R_Init_Video( ref_graphic_apis_t type )
|
|||||||
ref.dllFuncs.GL_InitExtensions();
|
ref.dllFuncs.GL_InitExtensions();
|
||||||
break;
|
break;
|
||||||
case REF_SOFTWARE:
|
case REF_SOFTWARE:
|
||||||
case REF_D3D:
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -359,7 +359,7 @@ void GL_UpdateSwapInterval( void )
|
|||||||
{
|
{
|
||||||
ClearBits( gl_vsync.flags, FCVAR_CHANGED );
|
ClearBits( gl_vsync.flags, FCVAR_CHANGED );
|
||||||
|
|
||||||
if( glw_state.context && SDL_GL_SetSwapInterval( gl_vsync.value ) < 0 )
|
if( SDL_GL_SetSwapInterval( gl_vsync.value ) < 0 )
|
||||||
Con_Reportf( S_ERROR "SDL_GL_SetSwapInterval: %s\n", SDL_GetError( ));
|
Con_Reportf( S_ERROR "SDL_GL_SetSwapInterval: %s\n", SDL_GetError( ));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -386,7 +386,7 @@ static void VID_GetWindowSizeInPixels( SDL_Window *window, SDL_Renderer *rendere
|
|||||||
#if SDL_VERSION_ATLEAST( 2, 26, 0 )
|
#if SDL_VERSION_ATLEAST( 2, 26, 0 )
|
||||||
SDL_GetWindowSizeInPixels( window, w, h );
|
SDL_GetWindowSizeInPixels( window, w, h );
|
||||||
#else
|
#else
|
||||||
if( glw_state.type != REF_GL )
|
if( glw_state.software )
|
||||||
SDL_GetRendererOutputSize( renderer, w, h );
|
SDL_GetRendererOutputSize( renderer, w, h );
|
||||||
else
|
else
|
||||||
SDL_GL_GetDrawableSize( window, w, h );
|
SDL_GL_GetDrawableSize( window, w, h );
|
||||||
@@ -669,7 +669,7 @@ static rserr_t VID_CreateWindow( const int input_width, const int input_height,
|
|||||||
SetBits( flags, SDL_WINDOW_ALLOW_HIGHDPI );
|
SetBits( flags, SDL_WINDOW_ALLOW_HIGHDPI );
|
||||||
#endif // !XASH_WIN32
|
#endif // !XASH_WIN32
|
||||||
|
|
||||||
if( glw_state.type == REF_GL )
|
if( !glw_state.software )
|
||||||
SetBits( flags, SDL_WINDOW_OPENGL );
|
SetBits( flags, SDL_WINDOW_OPENGL );
|
||||||
|
|
||||||
if( vid_maximized.value )
|
if( vid_maximized.value )
|
||||||
@@ -681,7 +681,7 @@ static rserr_t VID_CreateWindow( const int input_width, const int input_height,
|
|||||||
|
|
||||||
if( !host.hWnd )
|
if( !host.hWnd )
|
||||||
{
|
{
|
||||||
err = (glw_state.type == REF_GL) ? rserr_invalid_context : rserr_unknown;
|
err = glw_state.software ? rserr_unknown : rserr_invalid_context;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -698,7 +698,7 @@ static rserr_t VID_CreateWindow( const int input_width, const int input_height,
|
|||||||
SDL_ShowWindow( host.hWnd );
|
SDL_ShowWindow( host.hWnd );
|
||||||
SDL_RaiseWindow( host.hWnd );
|
SDL_RaiseWindow( host.hWnd );
|
||||||
|
|
||||||
if( glw_state.type == REF_SOFTWARE )
|
if( glw_state.software )
|
||||||
{
|
{
|
||||||
char cmd[64];
|
char cmd[64];
|
||||||
|
|
||||||
@@ -720,7 +720,7 @@ static rserr_t VID_CreateWindow( const int input_width, const int input_height,
|
|||||||
Con_Printf( "SDL_Renderer %s initialized\n", info.name );
|
Con_Printf( "SDL_Renderer %s initialized\n", info.name );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( glw_state.type == REF_GL )
|
else
|
||||||
{
|
{
|
||||||
glw_state.context = SDL_GL_CreateContext( host.hWnd );
|
glw_state.context = SDL_GL_CreateContext( host.hWnd );
|
||||||
|
|
||||||
@@ -917,10 +917,10 @@ qboolean R_Init_Video( ref_graphic_apis_t type )
|
|||||||
SDL_SetHint( SDL_HINT_VIDEO_X11_XRANDR, "1" );
|
SDL_SetHint( SDL_HINT_VIDEO_X11_XRANDR, "1" );
|
||||||
SDL_SetHint( SDL_HINT_VIDEO_X11_XVIDMODE, "1" );
|
SDL_SetHint( SDL_HINT_VIDEO_X11_XVIDMODE, "1" );
|
||||||
|
|
||||||
glw_state.type = type;
|
|
||||||
switch( type )
|
switch( type )
|
||||||
{
|
{
|
||||||
case REF_SOFTWARE:
|
case REF_SOFTWARE:
|
||||||
|
glw_state.software = true;
|
||||||
break;
|
break;
|
||||||
case REF_GL:
|
case REF_GL:
|
||||||
if( !glw_state.safe && Sys_GetParmFromCmdLine( "-safegl", safe ) )
|
if( !glw_state.safe && Sys_GetParmFromCmdLine( "-safegl", safe ) )
|
||||||
@@ -935,8 +935,6 @@ qboolean R_Init_Video( ref_graphic_apis_t type )
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case REF_D3D:
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
Host_Error( "Can't initialize unknown context type %d!\n", type );
|
Host_Error( "Can't initialize unknown context type %d!\n", type );
|
||||||
break;
|
break;
|
||||||
@@ -952,7 +950,6 @@ qboolean R_Init_Video( ref_graphic_apis_t type )
|
|||||||
ref.dllFuncs.GL_InitExtensions();
|
ref.dllFuncs.GL_InitExtensions();
|
||||||
break;
|
break;
|
||||||
case REF_SOFTWARE:
|
case REF_SOFTWARE:
|
||||||
case REF_D3D:
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ static qboolean VID_CreateWindow( const int input_width, const int input_height,
|
|||||||
SDL_Rect rect = { SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, input_width, input_height };
|
SDL_Rect rect = { SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, input_width, input_height };
|
||||||
Uint32 flags = SDL_WINDOW_RESIZABLE;
|
Uint32 flags = SDL_WINDOW_RESIZABLE;
|
||||||
|
|
||||||
if( glw_state.type == REF_GL )
|
if( !glw_state.software )
|
||||||
SetBits( flags, SDL_WINDOW_OPENGL );
|
SetBits( flags, SDL_WINDOW_OPENGL );
|
||||||
|
|
||||||
// probe true fullscreen first, if it fails, try borderless next
|
// probe true fullscreen first, if it fails, try borderless next
|
||||||
@@ -168,12 +168,12 @@ static qboolean VID_CreateWindow( const int input_width, const int input_height,
|
|||||||
|
|
||||||
VID_SetWindowIcon( host.hWnd );
|
VID_SetWindowIcon( host.hWnd );
|
||||||
|
|
||||||
if( glw_state.type == REF_SOFTWARE )
|
if( glw_state.software )
|
||||||
{
|
{
|
||||||
// no support yet
|
// no support yet
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if ( glw_state.type == REF_GL )
|
else
|
||||||
{
|
{
|
||||||
glw_state.context = SDL_GL_CreateContext( host.hWnd );
|
glw_state.context = SDL_GL_CreateContext( host.hWnd );
|
||||||
|
|
||||||
@@ -337,10 +337,10 @@ qboolean R_Init_Video( ref_graphic_apis_t type )
|
|||||||
if( Sys_CheckParm( "-egl" ))
|
if( Sys_CheckParm( "-egl" ))
|
||||||
Con_Printf( S_WARN "%s: -egl option is deprecated\n", __func__ );
|
Con_Printf( S_WARN "%s: -egl option is deprecated\n", __func__ );
|
||||||
|
|
||||||
glw_state.type = type;
|
|
||||||
switch( type )
|
switch( type )
|
||||||
{
|
{
|
||||||
case REF_SOFTWARE:
|
case REF_SOFTWARE:
|
||||||
|
glw_state.software = true;
|
||||||
break;
|
break;
|
||||||
case REF_GL:
|
case REF_GL:
|
||||||
{
|
{
|
||||||
@@ -357,8 +357,6 @@ qboolean R_Init_Video( ref_graphic_apis_t type )
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case REF_D3D:
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
Host_Error( "Can't initialize unknown context type %d!\n", type );
|
Host_Error( "Can't initialize unknown context type %d!\n", type );
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -705,4 +705,23 @@ int SV_LightForEntity( edict_t *pEdict );
|
|||||||
//
|
//
|
||||||
void SV_SourceQuery_HandleConnnectionlessPacket( const char *c, netadr_t from, sizebuf_t *msg );
|
void SV_SourceQuery_HandleConnnectionlessPacket( const char *c, netadr_t from, sizebuf_t *msg );
|
||||||
|
|
||||||
|
static inline qboolean SV_CheckGroupOp( int op, int groupinfo, int mask )
|
||||||
|
{
|
||||||
|
if( op == GROUP_OP_AND && !FBitSet( groupinfo, mask ))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( op == GROUP_OP_NAND && FBitSet( groupinfo, mask ))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline qboolean SV_CheckGroupTrace( const edict_t *e1, const edict_t *e2 )
|
||||||
|
{
|
||||||
|
if( e1->v.groupinfo && e2->v.groupinfo )
|
||||||
|
return SV_CheckGroupOp( svs.groupop, e1->v.groupinfo, e2->v.groupinfo );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#endif//SERVER_H
|
#endif//SERVER_H
|
||||||
|
|||||||
@@ -435,14 +435,8 @@ static int SV_Multicast( int dest, const vec3_t origin, const edict_t *ent, qboo
|
|||||||
if( filter && cl == sv.current_client && FBitSet( sv.current_client->flags, FCL_PREDICT_MOVEMENT ))
|
if( filter && cl == sv.current_client && FBitSet( sv.current_client->flags, FCL_PREDICT_MOVEMENT ))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( SV_IsValidEdict( ent ) && ent->v.groupinfo && cl->edict->v.groupinfo )
|
if( SV_IsValidEdict( ent ) && !SV_CheckGroupTrace( ent, cl->edict ))
|
||||||
{
|
continue;
|
||||||
if( svs.groupop == GROUP_OP_AND && !FBitSet( cl->edict->v.groupinfo, ent->v.groupinfo ))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if( svs.groupop == GROUP_OP_NAND && FBitSet( cl->edict->v.groupinfo, ent->v.groupinfo ))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !SV_CheckClientVisiblity( cl, mask ))
|
if( !SV_CheckClientVisiblity( cl, mask ))
|
||||||
continue;
|
continue;
|
||||||
@@ -4123,14 +4117,8 @@ void GAME_EXPORT SV_PlaybackEventFull( int flags, const edict_t *pInvoker, word
|
|||||||
if( cl->state != cs_spawned || !cl->edict || FBitSet( cl->flags, FCL_FAKECLIENT ))
|
if( cl->state != cs_spawned || !cl->edict || FBitSet( cl->flags, FCL_FAKECLIENT ))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( SV_IsValidEdict( pInvoker ) && pInvoker->v.groupinfo && cl->edict->v.groupinfo )
|
if( SV_IsValidEdict( pInvoker ) && !SV_CheckGroupTrace( pInvoker, cl->edict ))
|
||||||
{
|
continue;
|
||||||
if( svs.groupop == GROUP_OP_AND && !FBitSet( cl->edict->v.groupinfo, pInvoker->v.groupinfo ))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if( svs.groupop == GROUP_OP_NAND && FBitSet( cl->edict->v.groupinfo, pInvoker->v.groupinfo ))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( SV_IsValidEdict( pInvoker ))
|
if( SV_IsValidEdict( pInvoker ))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -60,6 +60,47 @@ Utility functions
|
|||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
SV_CheckVelocity
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
void SV_CheckVelocity( edict_t *ent )
|
||||||
|
{
|
||||||
|
float wishspd;
|
||||||
|
float maxspd;
|
||||||
|
|
||||||
|
// bound velocity
|
||||||
|
for( int i = 0; i < 3; i++ )
|
||||||
|
{
|
||||||
|
if( IS_NAN( ent->v.velocity[i] ))
|
||||||
|
{
|
||||||
|
if( sv_check_errors.value )
|
||||||
|
Con_Printf( "Got a NaN velocity on %s\n", SV_GetString( ent->v.classname ));
|
||||||
|
ent->v.velocity[i] = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( IS_NAN( ent->v.origin[i] ))
|
||||||
|
{
|
||||||
|
if( sv_check_errors.value )
|
||||||
|
Con_Printf( "Got a NaN origin on %s\n", SV_GetString( ent->v.classname ));
|
||||||
|
ent->v.origin[i] = 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wishspd = DotProduct( ent->v.velocity, ent->v.velocity );
|
||||||
|
maxspd = sv_maxvelocity.value * sv_maxvelocity.value * 1.73f; // half-diagonal
|
||||||
|
|
||||||
|
if( wishspd > maxspd )
|
||||||
|
{
|
||||||
|
wishspd = sqrt( wishspd );
|
||||||
|
if( sv_check_errors.value )
|
||||||
|
Con_Printf( "Got a velocity too high on %s ( %.2f > %.2f )\n", SV_GetString( ent->v.classname ), wishspd, sqrt( maxspd ));
|
||||||
|
wishspd = sv_maxvelocity.value / wishspd;
|
||||||
|
VectorScale( ent->v.velocity, wishspd, ent->v.velocity );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
================
|
================
|
||||||
SV_CheckAllEnts
|
SV_CheckAllEnts
|
||||||
@@ -110,47 +151,6 @@ static void SV_CheckAllEnts( void )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
SV_CheckVelocity
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void SV_CheckVelocity( edict_t *ent )
|
|
||||||
{
|
|
||||||
float wishspd;
|
|
||||||
float maxspd;
|
|
||||||
|
|
||||||
// bound velocity
|
|
||||||
for( int i = 0; i < 3; i++ )
|
|
||||||
{
|
|
||||||
if( IS_NAN( ent->v.velocity[i] ))
|
|
||||||
{
|
|
||||||
if( sv_check_errors.value )
|
|
||||||
Con_Printf( "Got a NaN velocity on %s\n", SV_GetString( ent->v.classname ));
|
|
||||||
ent->v.velocity[i] = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( IS_NAN( ent->v.origin[i] ))
|
|
||||||
{
|
|
||||||
if( sv_check_errors.value )
|
|
||||||
Con_Printf( "Got a NaN origin on %s\n", SV_GetString( ent->v.classname ));
|
|
||||||
ent->v.origin[i] = 0.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wishspd = DotProduct( ent->v.velocity, ent->v.velocity );
|
|
||||||
maxspd = sv_maxvelocity.value * sv_maxvelocity.value * 1.73f; // half-diagonal
|
|
||||||
|
|
||||||
if( wishspd > maxspd )
|
|
||||||
{
|
|
||||||
wishspd = sqrt( wishspd );
|
|
||||||
if( sv_check_errors.value )
|
|
||||||
Con_Printf( "Got a velocity too high on %s ( %.2f > %.2f )\n", SV_GetString( ent->v.classname ), wishspd, sqrt( maxspd ));
|
|
||||||
wishspd = sv_maxvelocity.value / wishspd;
|
|
||||||
VectorScale( ent->v.velocity, wishspd, ent->v.velocity );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
================
|
================
|
||||||
SV_UpdateBaseVelocity
|
SV_UpdateBaseVelocity
|
||||||
@@ -158,26 +158,20 @@ SV_UpdateBaseVelocity
|
|||||||
*/
|
*/
|
||||||
void SV_UpdateBaseVelocity( edict_t *ent )
|
void SV_UpdateBaseVelocity( edict_t *ent )
|
||||||
{
|
{
|
||||||
if( ent->v.flags & FL_ONGROUND )
|
if( !FBitSet( ent->v.flags, FL_ONGROUND ))
|
||||||
{
|
return;
|
||||||
edict_t *groundentity = ent->v.groundentity;
|
|
||||||
|
|
||||||
if( SV_IsValidEdict( groundentity ))
|
const edict_t *groundentity = ent->v.groundentity;
|
||||||
{
|
|
||||||
// On conveyor belt that's moving?
|
|
||||||
if( groundentity->v.flags & FL_CONVEYOR )
|
|
||||||
{
|
|
||||||
vec3_t new_basevel;
|
|
||||||
|
|
||||||
VectorScale( groundentity->v.movedir, groundentity->v.speed, new_basevel );
|
if( !SV_IsValidEdict( groundentity ) || !FBitSet( groundentity->v.flags, FL_CONVEYOR ))
|
||||||
if( ent->v.flags & FL_BASEVELOCITY )
|
return;
|
||||||
VectorAdd( new_basevel, ent->v.basevelocity, new_basevel );
|
|
||||||
|
|
||||||
ent->v.flags |= FL_BASEVELOCITY;
|
if( FBitSet( ent->v.flags, FL_BASEVELOCITY ))
|
||||||
VectorCopy( new_basevel, ent->v.basevelocity );
|
VectorMA( ent->v.basevelocity, groundentity->v.speed, groundentity->v.movedir, ent->v.basevelocity );
|
||||||
}
|
else
|
||||||
}
|
VectorScale( groundentity->v.movedir, groundentity->v.speed, ent->v.basevelocity );
|
||||||
}
|
|
||||||
|
ent->v.flags |= FL_BASEVELOCITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -189,18 +183,15 @@ returns true if the entity is in solid currently
|
|||||||
*/
|
*/
|
||||||
static qboolean SV_TestEntityPosition( edict_t *ent, edict_t *blocker )
|
static qboolean SV_TestEntityPosition( edict_t *ent, edict_t *blocker )
|
||||||
{
|
{
|
||||||
qboolean monsterClip = FBitSet( ent->v.flags, FL_MONSTERCLIP ) ? true : false;
|
|
||||||
trace_t trace;
|
|
||||||
|
|
||||||
if( FBitSet( ent->v.flags, FL_CLIENT|FL_FAKECLIENT ))
|
if( FBitSet( ent->v.flags, FL_CLIENT|FL_FAKECLIENT ))
|
||||||
{
|
{
|
||||||
// to avoid falling through tracktrain update client mins\maxs here
|
// to avoid falling through tracktrain update client mins\maxs here
|
||||||
if( FBitSet( ent->v.flags, FL_DUCKING ))
|
int hull = FBitSet( ent->v.flags, FL_DUCKING ) ? 1 : 0;
|
||||||
SV_SetMinMaxSize( ent, host.player_mins[1], host.player_maxs[1], true );
|
SV_SetMinMaxSize( ent, host.player_mins[hull], host.player_maxs[hull], 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 );
|
qboolean monsterClip = FBitSet( ent->v.flags, FL_MONSTERCLIP ) ? true : false;
|
||||||
|
trace_t trace = SV_Move( ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, MOVE_NORMAL, ent, monsterClip );
|
||||||
|
|
||||||
if( SV_IsValidEdict( blocker ) && SV_IsValidEdict( trace.ent ))
|
if( SV_IsValidEdict( blocker ) && SV_IsValidEdict( trace.ent ))
|
||||||
{
|
{
|
||||||
@@ -212,6 +203,25 @@ static qboolean SV_TestEntityPosition( edict_t *ent, edict_t *blocker )
|
|||||||
return trace.startsolid;
|
return trace.startsolid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static qboolean SV_TryThink( edict_t *ent, double frametime, double time )
|
||||||
|
{
|
||||||
|
float thinktime = ent->v.nextthink;
|
||||||
|
if( thinktime <= 0.0f || thinktime > ( time + frametime ))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// don't let things stay in the past.
|
||||||
|
// it is possible to start that way
|
||||||
|
// by a trigger with a local time.
|
||||||
|
if( thinktime < time )
|
||||||
|
thinktime = time;
|
||||||
|
|
||||||
|
ent->v.nextthink = 0.0f;
|
||||||
|
svgame.globals->time = thinktime;
|
||||||
|
svgame.dllFuncs.pfnThink( ent );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=============
|
=============
|
||||||
SV_RunThink
|
SV_RunThink
|
||||||
@@ -224,21 +234,10 @@ Returns false if the entity removed itself.
|
|||||||
*/
|
*/
|
||||||
static qboolean SV_RunThink( edict_t *ent )
|
static qboolean SV_RunThink( edict_t *ent )
|
||||||
{
|
{
|
||||||
float thinktime;
|
|
||||||
|
|
||||||
if( !FBitSet( ent->v.flags, FL_KILLME ))
|
if( !FBitSet( ent->v.flags, FL_KILLME ))
|
||||||
{
|
{
|
||||||
thinktime = ent->v.nextthink;
|
if( !SV_TryThink( ent, sv.frametime, sv.time ))
|
||||||
if( thinktime <= 0.0f || thinktime > (sv.time + sv.frametime))
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if( thinktime < sv.time )
|
|
||||||
thinktime = sv.time; // don't let things stay in the past.
|
|
||||||
// it is possible to start that way
|
|
||||||
// by a trigger with a local time.
|
|
||||||
ent->v.nextthink = 0.0f;
|
|
||||||
svgame.globals->time = thinktime;
|
|
||||||
svgame.dllFuncs.pfnThink( ent );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( FBitSet( ent->v.flags, FL_KILLME ))
|
if( FBitSet( ent->v.flags, FL_KILLME ))
|
||||||
@@ -259,25 +258,13 @@ Returns false if the entity removed itself.
|
|||||||
*/
|
*/
|
||||||
qboolean SV_PlayerRunThink( edict_t *ent, float frametime, double time )
|
qboolean SV_PlayerRunThink( edict_t *ent, float frametime, double time )
|
||||||
{
|
{
|
||||||
float thinktime;
|
|
||||||
|
|
||||||
if( svgame.physFuncs.SV_PlayerThink )
|
if( svgame.physFuncs.SV_PlayerThink )
|
||||||
return svgame.physFuncs.SV_PlayerThink( ent, frametime, time );
|
return svgame.physFuncs.SV_PlayerThink( ent, frametime, time );
|
||||||
|
|
||||||
if( !FBitSet( ent->v.flags, FL_KILLME|FL_DORMANT ))
|
if( !FBitSet( ent->v.flags, FL_KILLME|FL_DORMANT ))
|
||||||
{
|
{
|
||||||
thinktime = ent->v.nextthink;
|
if( !SV_TryThink( ent, frametime, time ))
|
||||||
if( thinktime <= 0.0f || thinktime > (time + frametime))
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if( thinktime < time )
|
|
||||||
thinktime = time; // don't let things stay in the past.
|
|
||||||
// it is possible to start that way
|
|
||||||
// by a trigger with a local time.
|
|
||||||
|
|
||||||
ent->v.nextthink = 0.0f;
|
|
||||||
svgame.globals->time = thinktime;
|
|
||||||
svgame.dllFuncs.pfnThink( ent );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( FBitSet( ent->v.flags, FL_KILLME ))
|
if( FBitSet( ent->v.flags, FL_KILLME ))
|
||||||
@@ -297,17 +284,11 @@ void SV_Impact( edict_t *e1, edict_t *e2, trace_t *trace )
|
|||||||
{
|
{
|
||||||
svgame.globals->time = sv.time;
|
svgame.globals->time = sv.time;
|
||||||
|
|
||||||
if(( e1->v.flags|e2->v.flags ) & FL_KILLME )
|
if( FBitSet( e1->v.flags|e2->v.flags, FL_KILLME ))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( e1->v.groupinfo && e2->v.groupinfo )
|
if( !SV_CheckGroupTrace( e1, e2 ))
|
||||||
{
|
return;
|
||||||
if( svs.groupop == GROUP_OP_AND && !FBitSet( e1->v.groupinfo, e2->v.groupinfo ))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if( svs.groupop == GROUP_OP_NAND && FBitSet( e1->v.groupinfo, e2->v.groupinfo ))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( e1->v.solid != SOLID_NOT )
|
if( e1->v.solid != SOLID_NOT )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -205,10 +205,7 @@ static void SV_AddLinksToPmove( areanode_t *node, const vec3_t pmove_mins, const
|
|||||||
|
|
||||||
if( check->v.groupinfo != 0 )
|
if( check->v.groupinfo != 0 )
|
||||||
{
|
{
|
||||||
if( svs.groupop == GROUP_OP_AND && !FBitSet( check->v.groupinfo, pl->v.groupinfo ))
|
if( !SV_CheckGroupOp( svs.groupop, check->v.groupinfo, pl->v.groupinfo ))
|
||||||
continue;
|
|
||||||
|
|
||||||
if( svs.groupop == GROUP_OP_NAND && FBitSet( check->v.groupinfo, pl->v.groupinfo ))
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -977,9 +974,9 @@ void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd, int random_seed )
|
|||||||
// touch other objects
|
// touch other objects
|
||||||
for( int i = 0; i < svgame.pmove->numtouch; i++ )
|
for( int i = 0; i < svgame.pmove->numtouch; i++ )
|
||||||
{
|
{
|
||||||
pmtrace_t *pmtrace = &svgame.pmove->touchindex[i];
|
pmtrace_t *pmtrace = &svgame.pmove->touchindex[i];
|
||||||
edict_t *touch = SV_EdictNum( svgame.pmove->physents[pmtrace->ent].info );
|
edict_t *touch = SV_EdictNum( svgame.pmove->physents[pmtrace->ent].info );
|
||||||
trace_t trace;
|
trace_t trace;
|
||||||
|
|
||||||
VectorCopy( pmtrace->deltavelocity, clent->v.velocity );
|
VectorCopy( pmtrace->deltavelocity, clent->v.velocity );
|
||||||
PM_ConvertTrace( &trace, pmtrace, touch );
|
PM_ConvertTrace( &trace, pmtrace, touch );
|
||||||
|
|||||||
@@ -522,14 +522,8 @@ static void SV_TouchLinks( edict_t *ent, areanode_t *node )
|
|||||||
if( touch == ent || touch->v.solid != SOLID_TRIGGER ) // disabled ?
|
if( touch == ent || touch->v.solid != SOLID_TRIGGER ) // disabled ?
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( touch->v.groupinfo && ent->v.groupinfo )
|
if( !SV_CheckGroupTrace( touch, ent ))
|
||||||
{
|
continue;
|
||||||
if( svs.groupop == GROUP_OP_AND && !FBitSet( touch->v.groupinfo, ent->v.groupinfo ))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if( svs.groupop == GROUP_OP_NAND && FBitSet( touch->v.groupinfo, ent->v.groupinfo ))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !BoundsIntersect( ent->v.absmin, ent->v.absmax, touch->v.absmin, touch->v.absmax ))
|
if( !BoundsIntersect( ent->v.absmin, ent->v.absmax, touch->v.absmin, touch->v.absmax ))
|
||||||
continue;
|
continue;
|
||||||
@@ -725,10 +719,7 @@ static void SV_WaterLinks( const vec3_t origin, int *pCont, areanode_t *node )
|
|||||||
|
|
||||||
if( touch->v.groupinfo )
|
if( touch->v.groupinfo )
|
||||||
{
|
{
|
||||||
if( svs.groupop == GROUP_OP_AND && !FBitSet( touch->v.groupinfo, svs.groupmask ))
|
if( !SV_CheckGroupOp( svs.groupop, touch->v.groupinfo, svs.groupmask ))
|
||||||
continue;
|
|
||||||
|
|
||||||
if( svs.groupop == GROUP_OP_NAND && FBitSet( touch->v.groupinfo, svs.groupmask ))
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1101,14 +1092,8 @@ static qboolean SV_ClipToEntity( edict_t *touch, moveclip_t *clip )
|
|||||||
trace_t trace;
|
trace_t trace;
|
||||||
model_t *mod;
|
model_t *mod;
|
||||||
|
|
||||||
if( touch->v.groupinfo && SV_IsValidEdict( clip->passedict ) && clip->passedict->v.groupinfo != 0 )
|
if( SV_IsValidEdict( clip->passedict ) && !SV_CheckGroupTrace( touch, clip->passedict ))
|
||||||
{
|
return true;
|
||||||
if( svs.groupop == GROUP_OP_AND && !FBitSet( touch->v.groupinfo, clip->passedict->v.groupinfo ))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if( svs.groupop == GROUP_OP_NAND && FBitSet( touch->v.groupinfo, clip->passedict->v.groupinfo ))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( touch == clip->passedict || touch->v.solid == SOLID_NOT )
|
if( touch == clip->passedict || touch->v.solid == SOLID_NOT )
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -26,7 +26,12 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
frameworks = ['Foundation', 'UIKit', 'QuartzCore', 'GameController', 'SystemConfiguration', 'CFNetwork', 'AVFoundation', 'CoreGraphics']
|
def get_frameworks(env):
|
||||||
|
if env.IOS:
|
||||||
|
return ['Foundation', 'UIKit', 'QuartzCore', 'GameController', 'SystemConfiguration', 'CFNetwork', 'AVFoundation', 'CoreGraphics']
|
||||||
|
if env.DEST_OS == 'darwin':
|
||||||
|
return ['IOKit', 'CoreFoundation']
|
||||||
|
return []
|
||||||
|
|
||||||
@TaskGen.extension('.m')
|
@TaskGen.extension('.m')
|
||||||
def m_hook(self, node):
|
def m_hook(self, node):
|
||||||
@@ -124,9 +129,8 @@ def configure(conf):
|
|||||||
if not conf.env.DEST_OS in ['win32', 'android']:
|
if not conf.env.DEST_OS in ['win32', 'android']:
|
||||||
conf.check_pthreads(mode='c')
|
conf.check_pthreads(mode='c')
|
||||||
|
|
||||||
if conf.env.IOS:
|
for i in get_frameworks(conf.env):
|
||||||
for i in frameworks :
|
conf.check(features='c cprogram', framework=i, uselib_store=i, msg='Checking for %s framework' % i)
|
||||||
conf.check(features='c cprogram', framework=i, uselib_store=i, msg='Checking for %s framework' % i)
|
|
||||||
|
|
||||||
conf.define('ENGINE_DLL', 1)
|
conf.define('ENGINE_DLL', 1)
|
||||||
|
|
||||||
@@ -179,6 +183,8 @@ def build(bld):
|
|||||||
source += bld.path.ant_glob('platform/ios/*.c')
|
source += bld.path.ant_glob('platform/ios/*.c')
|
||||||
source += bld.path.ant_glob('platform/ios/*.m')
|
source += bld.path.ant_glob('platform/ios/*.m')
|
||||||
includes += bld.path.ant_glob('platform/ios')
|
includes += bld.path.ant_glob('platform/ios')
|
||||||
|
elif bld.env.DEST_OS == 'darwin':
|
||||||
|
source += bld.path.ant_glob('platform/apple/*.c')
|
||||||
|
|
||||||
# include sources for optional features
|
# include sources for optional features
|
||||||
if bld.get_define('XASH_CUSTOM_SWAP'):
|
if bld.get_define('XASH_CUSTOM_SWAP'):
|
||||||
@@ -206,6 +212,7 @@ def build(bld):
|
|||||||
]
|
]
|
||||||
else: # POSIX
|
else: # POSIX
|
||||||
libs += ['M', 'RT', 'PTHREAD', 'ASOUND', 'HAIKU', 'MAGX', 'LOG', 'SOCKET']
|
libs += ['M', 'RT', 'PTHREAD', 'ASOUND', 'HAIKU', 'MAGX', 'LOG', 'SOCKET']
|
||||||
|
libs += get_frameworks(bld.env)
|
||||||
if not bld.env.STATIC:
|
if not bld.env.STATIC:
|
||||||
libs += ['DL']
|
libs += ['DL']
|
||||||
|
|
||||||
@@ -274,7 +281,6 @@ def build(bld):
|
|||||||
install_path = bld.env.LIBDIR
|
install_path = bld.env.LIBDIR
|
||||||
|
|
||||||
if bld.env.IOS:
|
if bld.env.IOS:
|
||||||
libs += frameworks
|
|
||||||
defines += ['XASH_SDLMAIN=1']
|
defines += ['XASH_SDLMAIN=1']
|
||||||
|
|
||||||
if bld.env.DEST_OS in ['nswitch', 'psvita', 'emscripten']:
|
if bld.env.DEST_OS in ['nswitch', 'psvita', 'emscripten']:
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
// dllmain.cpp : Defines the entry point for the DLL application.
|
|
||||||
#include "windows.h"
|
|
||||||
|
|
||||||
BOOL APIENTRY DllMain( HMODULE hModule,
|
|
||||||
DWORD ul_reason_for_call,
|
|
||||||
LPVOID lpReserved
|
|
||||||
)
|
|
||||||
{
|
|
||||||
switch (ul_reason_for_call)
|
|
||||||
{
|
|
||||||
case DLL_PROCESS_ATTACH:
|
|
||||||
case DLL_THREAD_ATTACH:
|
|
||||||
case DLL_THREAD_DETACH:
|
|
||||||
case DLL_PROCESS_DETACH:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,481 +0,0 @@
|
|||||||
/*
|
|
||||||
r_context.c -- dx2 renderer context
|
|
||||||
Copyright (C) 2023-2024 a1batross
|
|
||||||
Copyright (C) 2025-2026 lewa_j
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define INITGUID
|
|
||||||
#include "r_local.h"
|
|
||||||
#include "xash3d_mathlib.h"
|
|
||||||
#include "crtlib.h"
|
|
||||||
#include "r_studioint.h"
|
|
||||||
|
|
||||||
//#pragma comment(lib, "ddraw.lib")
|
|
||||||
//TODO COM_GetProcAddress
|
|
||||||
|
|
||||||
|
|
||||||
static void R_SimpleStub( void )
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void R_SimpleStubInt( int unused )
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void R_SimpleStubUInt( unsigned int unused )
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *R_GetConfigName( void )
|
|
||||||
{
|
|
||||||
return "ref_dx2";
|
|
||||||
}
|
|
||||||
|
|
||||||
static qboolean R_SetDisplayTransform( ref_screen_rotation_t rotate, int offset_x, int offset_y, float scale_x, float scale_y )
|
|
||||||
{
|
|
||||||
qboolean ret = true;
|
|
||||||
|
|
||||||
tr.rotation = rotate;
|
|
||||||
|
|
||||||
if( offset_x || offset_y )
|
|
||||||
{
|
|
||||||
gEngfuncs.Con_Printf("offset transform not supported\n");
|
|
||||||
ret = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( scale_x != 1.0f || scale_y != 1.0f )
|
|
||||||
{
|
|
||||||
gEngfuncs.Con_Printf("scale transform not supported\n");
|
|
||||||
ret = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GL_BackendStartFrame( void )
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void GL_BackendEndFrame( void )
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void GL_SetRenderMode( int mode )
|
|
||||||
{
|
|
||||||
dxc.renderMode = mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void R_ProcessEntData( qboolean allocate, cl_entity_t *entities, unsigned int max_entities )
|
|
||||||
{
|
|
||||||
if (!allocate)
|
|
||||||
{
|
|
||||||
tr.draw_list->num_solid_entities = 0;
|
|
||||||
tr.draw_list->num_trans_entities = 0;
|
|
||||||
tr.draw_list->num_beam_entities = 0;
|
|
||||||
|
|
||||||
tr.max_entities = 0;
|
|
||||||
tr.entities = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tr.max_entities = max_entities;
|
|
||||||
tr.entities = entities;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gEngfuncs.drawFuncs->R_ProcessEntData)
|
|
||||||
gEngfuncs.drawFuncs->R_ProcessEntData(allocate);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void R_SetupSky( int *skytextures )
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
static qboolean VID_ScreenShot( const char *filename, int shot_type )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static qboolean VID_CubemapShot( const char *base, uint size, const float *vieworg, qboolean skyshot )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static colorVec R_LightPoint( const float *p )
|
|
||||||
{
|
|
||||||
colorVec c = { 0 };
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, float scale )
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int R_CreateDecalList( struct decallist_s *pList )
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static float R_StudioEstimateFrame( cl_entity_t *e, mstudioseqdesc_t *pseqdesc, double time )
|
|
||||||
{
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void R_StudioLerpMovement( cl_entity_t *e, double time, vec3_t origin, vec3_t angles )
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
static qboolean R_StudioFillAPI( struct engine_studio_api_s *api, struct r_studio_interface_s *pDefaultDraw )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static r_studio_interface_t *pStudioDraw;
|
|
||||||
|
|
||||||
static void R_StudioSetDrawInterface( struct r_studio_interface_s *pDraw )
|
|
||||||
{
|
|
||||||
pStudioDraw = pDraw;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void R_SetSkyCloudsTextures( int solidskyTexture, int alphaskyTexture )
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CL_RunLightStyles( lightstyle_t *ls )
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static qboolean Mod_ProcessRenderData( model_t *mod, qboolean create, const byte *buffer, size_t buffersize )
|
|
||||||
{
|
|
||||||
gEngfuncs.Con_Printf("Mod_ProcessRenderData(%p(%s), %d, %p, %zu)\n", mod, mod->name, create, buffer, buffersize);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Mod_StudioLoadTextures( model_t *mod, void *data )
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CL_DrawParticles( double frametime, particle_t *particles, float partsize )
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CL_DrawTracers( double frametime, particle_t *tracers )
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CL_DrawBeams( int fTrans, BEAM *beams )
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
static intptr_t RefGetParm( int parm, int arg )
|
|
||||||
{
|
|
||||||
dx_texture_t *glt;
|
|
||||||
|
|
||||||
switch (parm)
|
|
||||||
{
|
|
||||||
case PARM_TEX_WIDTH:
|
|
||||||
glt = R_GetTexture(arg);
|
|
||||||
return glt->width;
|
|
||||||
case PARM_TEX_HEIGHT:
|
|
||||||
glt = R_GetTexture(arg);
|
|
||||||
return glt->height;
|
|
||||||
case PARM_TEX_SRC_WIDTH:
|
|
||||||
glt = R_GetTexture(arg);
|
|
||||||
return glt->srcWidth;
|
|
||||||
case PARM_TEX_SRC_HEIGHT:
|
|
||||||
glt = R_GetTexture(arg);
|
|
||||||
return glt->srcHeight;
|
|
||||||
case PARM_TEX_GLFORMAT:
|
|
||||||
glt = R_GetTexture(arg);
|
|
||||||
return 0;
|
|
||||||
case PARM_TEX_ENCODE:
|
|
||||||
glt = R_GetTexture(arg);
|
|
||||||
return 0;
|
|
||||||
case PARM_TEX_MIPCOUNT:
|
|
||||||
glt = R_GetTexture(arg);
|
|
||||||
return glt->numMips;
|
|
||||||
case PARM_TEX_DEPTH:
|
|
||||||
glt = R_GetTexture(arg);
|
|
||||||
return 1;
|
|
||||||
#if 0
|
|
||||||
case PARM_TEX_SKYBOX:
|
|
||||||
Assert(arg >= 0 && arg < 6);
|
|
||||||
return tr.skyboxTextures[arg];
|
|
||||||
#endif
|
|
||||||
case PARM_TEX_SKYTEXNUM:
|
|
||||||
return tr.skytexturenum;
|
|
||||||
#if 0
|
|
||||||
case PARM_TEX_LIGHTMAP:
|
|
||||||
arg = bound(0, arg, MAX_LIGHTMAPS - 1);
|
|
||||||
return tr.lightmapTextures[arg];
|
|
||||||
#endif
|
|
||||||
case PARM_TEX_TARGET:
|
|
||||||
glt = R_GetTexture(arg);
|
|
||||||
return 0;
|
|
||||||
case PARM_TEX_TEXNUM:
|
|
||||||
glt = R_GetTexture(arg);
|
|
||||||
return arg;
|
|
||||||
case PARM_TEX_FLAGS:
|
|
||||||
glt = R_GetTexture(arg);
|
|
||||||
return glt->flags;
|
|
||||||
#if 0
|
|
||||||
case PARM_TEX_MEMORY:
|
|
||||||
return GL_TexMemory();
|
|
||||||
case PARM_ACTIVE_TMU:
|
|
||||||
return glState.activeTMU;
|
|
||||||
#endif
|
|
||||||
case PARM_LIGHTSTYLEVALUE:
|
|
||||||
arg = bound(0, arg, MAX_LIGHTSTYLES - 1);
|
|
||||||
return g_lightstylevalue[arg];
|
|
||||||
#if 0
|
|
||||||
case PARM_MAX_IMAGE_UNITS:
|
|
||||||
return GL_MaxTextureUnits();
|
|
||||||
case PARM_REBUILD_GAMMA:
|
|
||||||
return glConfig.softwareGammaUpdate;
|
|
||||||
case PARM_GL_CONTEXT_TYPE:
|
|
||||||
return glConfig.context;
|
|
||||||
case PARM_GLES_WRAPPER:
|
|
||||||
return glConfig.wrapper;
|
|
||||||
#endif
|
|
||||||
case PARM_STENCIL_ACTIVE:
|
|
||||||
return 0;//No stencil in dx2
|
|
||||||
case PARM_TEX_FILTERING:
|
|
||||||
return 0;
|
|
||||||
#if 0
|
|
||||||
if (arg < 0)
|
|
||||||
return gl_texture_nearest.value == 0.0f;
|
|
||||||
|
|
||||||
return GL_TextureFilteringEnabled(R_GetTexture(arg));
|
|
||||||
#endif
|
|
||||||
case PARM_GET_STUDIO_HDR:
|
|
||||||
//return (intptr_t)R_StudioGetHeader();
|
|
||||||
return 0;
|
|
||||||
default:
|
|
||||||
return (*gEngfuncs.EngineGetParm)(parm, arg);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void GL_Bind( int tmu, unsigned int texnum )
|
|
||||||
{
|
|
||||||
const dx_texture_t *texture;
|
|
||||||
|
|
||||||
// missed or invalid texture?
|
|
||||||
if( texnum <= 0 || texnum >= MAX_TEXTURES )
|
|
||||||
{
|
|
||||||
if( texnum != 0 )
|
|
||||||
gEngfuncs.Con_DPrintf( S_ERROR "%s: invalid texturenum %d\n", __func__, texnum );
|
|
||||||
texnum = tr.defaultTexture;
|
|
||||||
}
|
|
||||||
|
|
||||||
texture = R_GetTexture( texnum );
|
|
||||||
|
|
||||||
//if( dxc.currentTexture == texture->d3dHandle )
|
|
||||||
// return;
|
|
||||||
|
|
||||||
dxc.currentTexture = texture->d3dHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
static qboolean R_SpeedsMessage( char *out, size_t size )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void R_NewMap( void )
|
|
||||||
{
|
|
||||||
tr.worldmodel = gp_cl->models[1];
|
|
||||||
|
|
||||||
// clear out efrags in case the level hasn't been reloaded
|
|
||||||
for( int i = 0; i < tr.worldmodel->numleafs; i++ )
|
|
||||||
tr.worldmodel->leafs[i+1].efrags = NULL;
|
|
||||||
|
|
||||||
tr.skytexturenum = -1;
|
|
||||||
|
|
||||||
// clearing texture chains
|
|
||||||
for( int i = 0; i < tr.worldmodel->numtextures; i++ )
|
|
||||||
{
|
|
||||||
if( !tr.worldmodel->textures[i] )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
texture_t *tx = tr.worldmodel->textures[i];
|
|
||||||
|
|
||||||
if( !Q_strncmp( tx->name, "sky", 3 ) && tx->width == ( tx->height * 2 ))
|
|
||||||
tr.skytexturenum = i;
|
|
||||||
|
|
||||||
tx->texturechain = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
GL_BuildLightmaps();
|
|
||||||
|
|
||||||
if( gEngfuncs.drawFuncs->R_NewMap != NULL )
|
|
||||||
gEngfuncs.drawFuncs->R_NewMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Color4f( float r, float g, float b, float a )
|
|
||||||
{
|
|
||||||
Vector4Set(dxc.currentColor, r, g, b, a);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Color4ub( unsigned char r, unsigned char g, unsigned char b, unsigned char a )
|
|
||||||
{
|
|
||||||
Vector4Set(dxc.currentColor, r/255.f, g/255.f, b/255.f, a/255.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Vertex3fv( const float *worldPnt )
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Vertex3f( float x, float y, float z )
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CullFace( TRICULLSTYLE mode )
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void VGUI_SetupDrawing( qboolean rect )
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void R_FillRenderAPI( render_api_t *api )
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void R_FillTriAPI( triangleapi_t *api )
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ref_interface_t gReffuncs =
|
|
||||||
{
|
|
||||||
.R_Init = R_Init,
|
|
||||||
.R_Shutdown = R_Shutdown,
|
|
||||||
.R_GetConfigName = R_GetConfigName,
|
|
||||||
.R_SetDisplayTransform = R_SetDisplayTransform,
|
|
||||||
|
|
||||||
.GL_SetupAttributes = GL_SetupAttributes,
|
|
||||||
.GL_InitExtensions = GL_InitExtensions,
|
|
||||||
.GL_ClearExtensions = GL_ClearExtensions,
|
|
||||||
|
|
||||||
.R_GammaChanged = R_GammaChanged,
|
|
||||||
.R_BeginFrame = R_BeginFrame,
|
|
||||||
.R_RenderScene = R_RenderScene,
|
|
||||||
.R_EndFrame = R_EndFrame,
|
|
||||||
.R_PushScene = R_SimpleStub,
|
|
||||||
.R_PopScene = R_SimpleStub,
|
|
||||||
.GL_BackendStartFrame = GL_BackendStartFrame,
|
|
||||||
.GL_BackendEndFrame = GL_BackendEndFrame,
|
|
||||||
|
|
||||||
.R_ClearScreen = R_SimpleStub,
|
|
||||||
.R_AllowFog = R_AllowFog,
|
|
||||||
.GL_SetRenderMode = GL_SetRenderMode,
|
|
||||||
|
|
||||||
.R_AddEntity = R_AddEntity,
|
|
||||||
.R_ProcessEntData = R_ProcessEntData,
|
|
||||||
|
|
||||||
.R_ShowTextures = R_ShowTextures,
|
|
||||||
|
|
||||||
.R_GetTextureOriginalBuffer = R_GetTextureOriginalBuffer,
|
|
||||||
.GL_LoadTextureFromBuffer = GL_LoadTextureFromBuffer,
|
|
||||||
.GL_ProcessTexture = GL_ProcessTexture,
|
|
||||||
.R_SetupSky = R_SetupSky,
|
|
||||||
|
|
||||||
.R_Set2DMode = R_Set2DMode,
|
|
||||||
.R_DrawStretchPic = R_DrawStretchPic,
|
|
||||||
.FillRGBA = FillRGBA,
|
|
||||||
.WorldToScreen = WorldToScreen,
|
|
||||||
|
|
||||||
.VID_ScreenShot = VID_ScreenShot,
|
|
||||||
.VID_CubemapShot = VID_CubemapShot,
|
|
||||||
|
|
||||||
.R_LightPoint = R_LightPoint,
|
|
||||||
|
|
||||||
.R_DecalShoot = R_DecalShoot,
|
|
||||||
.R_DecalRemoveAll = R_SimpleStubInt,
|
|
||||||
.R_CreateDecalList = R_CreateDecalList,
|
|
||||||
.R_ClearAllDecals = R_SimpleStub,
|
|
||||||
|
|
||||||
.R_StudioEstimateFrame = R_StudioEstimateFrame,
|
|
||||||
.R_StudioLerpMovement = R_StudioLerpMovement,
|
|
||||||
.R_StudioFillAPI = R_StudioFillAPI,
|
|
||||||
.R_StudioSetDrawInterface = R_StudioSetDrawInterface,
|
|
||||||
|
|
||||||
.R_SetSkyCloudsTextures = R_SetSkyCloudsTextures,
|
|
||||||
.GL_SubdivideSurface = GL_SubdivideSurface,
|
|
||||||
.CL_RunLightStyles = CL_RunLightStyles,
|
|
||||||
|
|
||||||
.Mod_ProcessRenderData = Mod_ProcessRenderData,
|
|
||||||
.Mod_StudioLoadTextures = Mod_StudioLoadTextures,
|
|
||||||
|
|
||||||
.CL_DrawParticles = CL_DrawParticles,
|
|
||||||
.CL_DrawTracers = CL_DrawTracers,
|
|
||||||
.CL_DrawBeams = CL_DrawBeams,
|
|
||||||
|
|
||||||
.RefGetParm = RefGetParm,
|
|
||||||
|
|
||||||
.R_GetDetailScaleForTexture = R_GetDetailScaleForTexture,
|
|
||||||
.R_SetDetailScaleForTexture = R_SetDetailScaleForTexture,
|
|
||||||
|
|
||||||
.GL_CreateTexture = GL_CreateTexture,
|
|
||||||
.GL_FindTexture = GL_FindTexture,
|
|
||||||
.GL_TextureName = GL_TextureName,
|
|
||||||
.GL_TextureData = GL_TextureData,
|
|
||||||
.GL_LoadTexture = GL_LoadTexture,
|
|
||||||
.GL_FreeTexture = GL_FreeTexture,
|
|
||||||
.R_OverrideTextureSourceSize = R_OverrideTextureSourceSize,
|
|
||||||
.GL_UpdateTexture = GL_UpdateTexture,
|
|
||||||
|
|
||||||
.GL_Bind = GL_Bind,
|
|
||||||
|
|
||||||
.GL_RenderFrame = R_RenderFrame,
|
|
||||||
.GL_OrthoBounds = GL_OrthoBounds,
|
|
||||||
.R_SpeedsMessage = R_SpeedsMessage,
|
|
||||||
.Mod_GetCurrentVis = Mod_GetCurrentVis,
|
|
||||||
.R_NewMap = R_NewMap,
|
|
||||||
.R_ClearScene = R_ClearScene,
|
|
||||||
|
|
||||||
.TriRenderMode = R_SimpleStubInt,
|
|
||||||
.Begin = R_SimpleStubInt,
|
|
||||||
.End = R_SimpleStub,
|
|
||||||
.Color4f = Color4f,
|
|
||||||
.Color4ub = Color4ub,
|
|
||||||
.Vertex3fv = Vertex3fv,
|
|
||||||
.Vertex3f = Vertex3f,
|
|
||||||
.CullFace = CullFace,
|
|
||||||
|
|
||||||
.R_FillRenderAPI = R_FillRenderAPI,
|
|
||||||
.R_FillTriAPI = R_FillTriAPI,
|
|
||||||
|
|
||||||
.VGUI_SetupDrawing = VGUI_SetupDrawing,
|
|
||||||
};
|
|
||||||
|
|
||||||
559
ref/dx2/r_d3d.c
559
ref/dx2/r_d3d.c
@@ -1,559 +0,0 @@
|
|||||||
/*
|
|
||||||
r_d3d.c -- dx2 renderer d3d related code
|
|
||||||
Copyright (C) 2025-2026 lewa_j
|
|
||||||
|
|
||||||
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 "r_local.h"
|
|
||||||
#include "xash3d_mathlib.h"
|
|
||||||
|
|
||||||
CVAR_DEFINE_AUTO( r_novis, "0", 0, "ignore vis information (perfomance test)" );
|
|
||||||
CVAR_DEFINE_AUTO( r_nocull, "0", 0, "ignore frustrum culling (perfomance test)" );
|
|
||||||
CVAR_DEFINE_AUTO( r_lockpvs, "0", FCVAR_CHEAT, "lockpvs area at current point (pvs test)" );
|
|
||||||
CVAR_DEFINE_AUTO( r_lockfrustum, "0", FCVAR_CHEAT, "lock frustrum area at current point (cull test)" );
|
|
||||||
|
|
||||||
dx_globals_t tr;
|
|
||||||
dx_context_t dxc;
|
|
||||||
|
|
||||||
const char *dxResultToStr( HRESULT r )
|
|
||||||
{
|
|
||||||
if( r == DD_OK )
|
|
||||||
return "DD_OK";
|
|
||||||
if( r == DDERR_INVALIDPARAMS )
|
|
||||||
return "DDERR_INVALIDPARAMS";
|
|
||||||
if( r == DDERR_INVALIDOBJECT )
|
|
||||||
return "DDERR_INVALIDOBJECT";
|
|
||||||
if( r == DDERR_UNSUPPORTED )
|
|
||||||
return "DDERR_UNSUPPORTED";
|
|
||||||
if( r == DDERR_NOCOOPERATIVELEVELSET )
|
|
||||||
return "DDERR_NOCOOPERATIVELEVELSET";
|
|
||||||
if( r == DDERR_INVALIDCAPS )
|
|
||||||
return "DDERR_INVALIDCAPS";
|
|
||||||
if( r == DDERR_INCOMPATIBLEPRIMARY )
|
|
||||||
return "DDERR_INCOMPATIBLEPRIMARY";
|
|
||||||
if( r == DDERR_NOEXCLUSIVEMODE )
|
|
||||||
return "DDERR_NOEXCLUSIVEMODE";
|
|
||||||
if( r == DDERR_NOFLIPHW )
|
|
||||||
return "DDERR_NOFLIPHW";
|
|
||||||
if( r == DDERR_OUTOFVIDEOMEMORY )
|
|
||||||
return "DDERR_OUTOFVIDEOMEMORY";
|
|
||||||
if( r == DDERR_PRIMARYSURFACEALREADYEXISTS )
|
|
||||||
return "DDERR_PRIMARYSURFACEALREADYEXISTS";
|
|
||||||
if( r == DDERR_UNSUPPORTEDMODE )
|
|
||||||
return "DDERR_UNSUPPORTEDMODE";
|
|
||||||
if( r == DDERR_NOTFOUND )
|
|
||||||
return "DDERR_NOTFOUND";
|
|
||||||
if( r == DDERR_INVALIDRECT )
|
|
||||||
return "DDERR_INVALIDRECT";
|
|
||||||
|
|
||||||
if( r == D3DERR_VIEWPORTDATANOTSET )
|
|
||||||
return "D3DERR_VIEWPORTDATANOTSET";
|
|
||||||
if( r == D3DERR_VIEWPORTHASNODEVICE )
|
|
||||||
return "D3DERR_VIEWPORTHASNODEVICE";
|
|
||||||
if( r == D3DERR_SURFACENOTINVIDMEM )
|
|
||||||
return "D3DERR_SURFACENOTINVIDMEM";
|
|
||||||
|
|
||||||
return "UNKNOWN";
|
|
||||||
}
|
|
||||||
|
|
||||||
static qboolean DD_CreatePrimarySurface( void )
|
|
||||||
{
|
|
||||||
DDSURFACEDESC ddsd = { 0 };
|
|
||||||
memset(&ddsd, 0, sizeof(ddsd));
|
|
||||||
ddsd.dwSize = sizeof(ddsd);
|
|
||||||
ddsd.dwFlags = DDSD_CAPS;
|
|
||||||
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
|
|
||||||
|
|
||||||
DXCheck(IDirectDraw_CreateSurface(dxc.pdd, &ddsd, &dxc.pddsPrimary, NULL));
|
|
||||||
printf("IDirectDraw::CreateSurface(PRIMARY) %p\n", dxc.pddsPrimary);
|
|
||||||
if (!dxc.pddsPrimary)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
DXCheck(IDirectDraw_CreateClipper(dxc.pdd, 0, &dxc.pddClipper, NULL));
|
|
||||||
gEngfuncs.Con_Printf("IDirectDraw::CreateClipper %p\n", dxc.pddClipper);
|
|
||||||
if (!dxc.pddClipper)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
DXCheck(IDirectDrawClipper_SetHWnd(dxc.pddClipper, 0, dxc.window));
|
|
||||||
DXCheck(IDirectDrawSurface_SetClipper(dxc.pddsPrimary, dxc.pddClipper));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static qboolean DD_CreateBackSurface( void )
|
|
||||||
{
|
|
||||||
DDCAPS ddcaps =
|
|
||||||
{
|
|
||||||
.dwSize = sizeof(ddcaps)
|
|
||||||
};
|
|
||||||
DDCAPS helcaps =
|
|
||||||
{
|
|
||||||
.dwSize = sizeof(helcaps)
|
|
||||||
};
|
|
||||||
DXCheck(IDirectDraw_GetCaps(dxc.pdd, &ddcaps, &helcaps));
|
|
||||||
gEngfuncs.Con_Printf("IDirectDraw::GetCaps\n");
|
|
||||||
gEngfuncs.Con_Printf("ZBUFFER: %s\n", (ddcaps.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) ? "- ^2enabled" : "- ^1failed");
|
|
||||||
if (ddcaps.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
|
|
||||||
gEngfuncs.Con_Printf("ZBufferBitDepths: 0x%X\n", ddcaps.dwZBufferBitDepths);
|
|
||||||
if (helcaps.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
|
|
||||||
gEngfuncs.Con_Printf("HEL ZBufferBitDepths: 0x%X\n", helcaps.dwZBufferBitDepths);
|
|
||||||
|
|
||||||
DDSURFACEDESC ddsd = { 0 };
|
|
||||||
memset(&ddsd, 0, sizeof(ddsd));
|
|
||||||
ddsd.dwSize = sizeof(ddsd);
|
|
||||||
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
|
|
||||||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY;
|
|
||||||
ddsd.dwWidth = dxc.windowWidth;
|
|
||||||
ddsd.dwHeight = dxc.windowHeight;
|
|
||||||
|
|
||||||
DXCheck(IDirectDraw_CreateSurface(dxc.pdd, &ddsd, &dxc.pddsBack, NULL));
|
|
||||||
gEngfuncs.Con_Printf("IDirectDraw::CreateSurface(BACK) %p\n", dxc.pddsBack);
|
|
||||||
if (!dxc.pddsBack)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
DXCheck(IDirectDraw_CreateClipper(dxc.pdd, 0, &dxc.pddBackClipper, NULL));
|
|
||||||
gEngfuncs.Con_Printf("IDirectDraw::CreateClipper(BACK) %p\n", dxc.pddBackClipper);
|
|
||||||
if (!dxc.pddBackClipper)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
struct region_t
|
|
||||||
{
|
|
||||||
RGNDATAHEADER rdh;
|
|
||||||
RECT rect;
|
|
||||||
} region;
|
|
||||||
region.rdh.dwSize = sizeof(region.rdh);
|
|
||||||
region.rdh.iType = RDH_RECTANGLES;
|
|
||||||
region.rdh.nCount = 1;
|
|
||||||
region.rdh.nRgnSize = sizeof(RECT);
|
|
||||||
region.rdh.rcBound.left = 0;
|
|
||||||
region.rdh.rcBound.top = 0;
|
|
||||||
region.rdh.rcBound.right = dxc.windowWidth;
|
|
||||||
region.rdh.rcBound.bottom = dxc.windowHeight;
|
|
||||||
memcpy(®ion.rect, ®ion.rdh.rcBound, sizeof(region.rdh.rcBound));
|
|
||||||
|
|
||||||
DXCheck(IDirectDrawClipper_SetClipList(dxc.pddBackClipper, (RGNDATA *)®ion, 0));
|
|
||||||
DXCheck(IDirectDrawSurface_SetClipper(dxc.pddsBack, dxc.pddBackClipper));
|
|
||||||
|
|
||||||
int bitDepths = ddcaps.dwZBufferBitDepths;
|
|
||||||
if (!bitDepths)
|
|
||||||
bitDepths = helcaps.dwZBufferBitDepths;
|
|
||||||
if( (ddcaps.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) && bitDepths )
|
|
||||||
{
|
|
||||||
memset(&ddsd, 0, sizeof(ddsd));
|
|
||||||
ddsd.dwSize = sizeof(ddsd);
|
|
||||||
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_ZBUFFERBITDEPTH;
|
|
||||||
ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
|
|
||||||
ddsd.dwWidth = dxc.windowWidth;
|
|
||||||
ddsd.dwHeight = dxc.windowHeight;
|
|
||||||
ddsd.dwZBufferBitDepth = 16;
|
|
||||||
if(bitDepths & DDBD_16 )
|
|
||||||
ddsd.dwZBufferBitDepth = 16;
|
|
||||||
else if(bitDepths & DDBD_24 )
|
|
||||||
ddsd.dwZBufferBitDepth = 24;
|
|
||||||
else if(bitDepths & DDBD_32 )
|
|
||||||
ddsd.dwZBufferBitDepth = 32;
|
|
||||||
DXCheck(IDirectDraw_CreateSurface(dxc.pdd, &ddsd, &dxc.pddsZBuffer, NULL));
|
|
||||||
gEngfuncs.Con_Printf("IDirectDraw::CreateSurface(ZBUFFER %dbit) %p\n", ddsd.dwZBufferBitDepth, dxc.pddsZBuffer);
|
|
||||||
if( !dxc.pddsZBuffer )
|
|
||||||
return false;
|
|
||||||
DXCheck(IDirectDrawSurface_AddAttachedSurface(dxc.pddsBack, dxc.pddsZBuffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static qboolean D3D_Init( void )
|
|
||||||
{
|
|
||||||
DXCheck(IDirectDraw_QueryInterface(dxc.pdd, &IID_IDirect3D, (void**)&dxc.pd3d));
|
|
||||||
gEngfuncs.Con_Printf("IDirectDraw::QueryInterface(IID_IDirect3D) %p\n", dxc.pd3d);
|
|
||||||
|
|
||||||
if( !dxc.pd3d )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
DXCheck(IDirect3D_CreateViewport(dxc.pd3d, &dxc.viewport, NULL));
|
|
||||||
gEngfuncs.Con_Printf("IDirect3D::CreateViewport %p\n", dxc.viewport);
|
|
||||||
|
|
||||||
if( !dxc.viewport )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static qboolean D3D_InitDevice( void )
|
|
||||||
{
|
|
||||||
if( !dxc.pd3d )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
D3DFINDDEVICESEARCH search = { 0 };
|
|
||||||
memset(&search, 0, sizeof(search));
|
|
||||||
search.dwSize = sizeof(search);
|
|
||||||
search.dwFlags = D3DFDS_COLORMODEL;
|
|
||||||
search.dcmColorModel = D3DCOLOR_RGB;
|
|
||||||
#if 0
|
|
||||||
search.dwFlags |= D3DFDS_HARDWARE;
|
|
||||||
search.bHardware = FALSE;
|
|
||||||
#endif
|
|
||||||
D3DFINDDEVICERESULT result = { 0 };
|
|
||||||
memset(&result, 0, sizeof(result));
|
|
||||||
result.dwSize = sizeof(result);
|
|
||||||
|
|
||||||
DXCheck(IDirect3D_FindDevice(dxc.pd3d, &search, &result));
|
|
||||||
DXCheck(IDirectDrawSurface_QueryInterface(dxc.pddsBack, &result.guid, (void**)&dxc.pd3dd));
|
|
||||||
gEngfuncs.Con_Printf("IDirectDrawSurface::QueryInterface(IDirect3DDevice) %p\n", dxc.pd3dd);
|
|
||||||
gEngfuncs.Con_Printf("DeviceZBufferBitDepth: 0x%X\n", result.ddHwDesc.dwDeviceZBufferBitDepth);
|
|
||||||
gEngfuncs.Con_Printf("SW DeviceZBufferBitDepth: 0x%X\n", result.ddSwDesc.dwDeviceZBufferBitDepth);
|
|
||||||
|
|
||||||
if( !dxc.pd3dd )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
D3DDEVICEDESC d3ddesc =
|
|
||||||
{
|
|
||||||
.dwSize = sizeof(d3ddesc)
|
|
||||||
};
|
|
||||||
D3DDEVICEDESC held3ddesc =
|
|
||||||
{
|
|
||||||
.dwSize = sizeof(held3ddesc)
|
|
||||||
};
|
|
||||||
DXCheck(IDirect3DDevice_GetCaps(dxc.pd3dd, &d3ddesc, &held3ddesc));
|
|
||||||
gEngfuncs.Con_Printf("IDirect3DDevice::GetCaps\n");
|
|
||||||
gEngfuncs.Con_Printf("DeviceZBufferBitDepth: 0x%X\n", result.ddHwDesc.dwDeviceZBufferBitDepth);
|
|
||||||
gEngfuncs.Con_Printf("HEL DeviceZBufferBitDepth: 0x%X\n", result.ddSwDesc.dwDeviceZBufferBitDepth);
|
|
||||||
|
|
||||||
D3DEXECUTEBUFFERDESC ebd = { 0 };
|
|
||||||
memset(&ebd, 0, sizeof(ebd));
|
|
||||||
ebd.dwSize = sizeof(ebd);
|
|
||||||
ebd.dwFlags = D3DDEB_BUFSIZE;
|
|
||||||
ebd.dwBufferSize = 1024 * 64;
|
|
||||||
DXCheck(IDirect3DDevice_CreateExecuteBuffer(dxc.pd3dd, &ebd, &dxc.pd3deb, NULL));
|
|
||||||
gEngfuncs.Con_Printf("IDirect3DDevice::CreateExecuteBuffer %p\n", dxc.pd3deb);
|
|
||||||
|
|
||||||
if (!dxc.pd3deb)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!dxc.viewport)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
DXCheck(IDirect3DDevice_AddViewport(dxc.pd3dd, dxc.viewport));
|
|
||||||
|
|
||||||
DDSURFACEDESC desc = { 0 };
|
|
||||||
memset(&desc, 0, sizeof(desc));
|
|
||||||
desc.dwSize = sizeof(desc);
|
|
||||||
desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
|
|
||||||
DXCheck(IDirectDrawSurface_GetSurfaceDesc(dxc.pddsBack, &desc));
|
|
||||||
|
|
||||||
D3DVIEWPORT viewport = { 0 };
|
|
||||||
viewport.dwSize = sizeof(viewport);
|
|
||||||
viewport.dwX = 0;
|
|
||||||
viewport.dwY = 0;
|
|
||||||
viewport.dwWidth = desc.dwWidth;
|
|
||||||
viewport.dwHeight = desc.dwHeight;
|
|
||||||
viewport.dvScaleX = 0.5 * viewport.dwWidth;
|
|
||||||
viewport.dvScaleY = 0.5f * viewport.dwHeight;
|
|
||||||
viewport.dvMaxX = 1;
|
|
||||||
viewport.dvMaxY = 1;
|
|
||||||
viewport.dvMinZ = 0;
|
|
||||||
viewport.dvMaxZ = 1;
|
|
||||||
DXCheck(IDirect3DViewport_SetViewport(dxc.viewport, &viewport));
|
|
||||||
|
|
||||||
DXCheck(IDirect3DDevice_CreateMatrix(dxc.pd3dd, &dxc.mtxWorld));
|
|
||||||
DXCheck(IDirect3DDevice_CreateMatrix(dxc.pd3dd, &dxc.mtxProjection));
|
|
||||||
|
|
||||||
//set transform state
|
|
||||||
{
|
|
||||||
d3dEBContext_t ebc = { 0 };
|
|
||||||
if (!D3D_StartExecuteBuffer(&ebc))
|
|
||||||
return false;
|
|
||||||
void *cur = ebc.data;
|
|
||||||
|
|
||||||
D3D_PutInstruction(&cur, D3DOP_STATETRANSFORM, sizeof(D3DSTATE), 2);
|
|
||||||
D3D_PutTransformState(&cur, D3DTRANSFORMSTATE_WORLD, dxc.mtxWorld);
|
|
||||||
D3D_PutTransformState(&cur, D3DTRANSFORMSTATE_PROJECTION, dxc.mtxProjection);
|
|
||||||
|
|
||||||
D3D_PutInstruction(&cur, D3DOP_STATERENDER, sizeof(D3DSTATE), 2);
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_ZENABLE, FALSE);
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_ZWRITEENABLE, FALSE);
|
|
||||||
|
|
||||||
D3D_PutInstruction(&cur, D3DOP_EXIT, 0, 0);
|
|
||||||
|
|
||||||
ebc.vertCount = 0;
|
|
||||||
ebc.insOffset = 0;
|
|
||||||
ebc.insLength = ((char *)cur - (char *)ebc.data);
|
|
||||||
|
|
||||||
if (!D3D_EndExecuteBuffer(&ebc))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
DXCheck(IDirect3DDevice_BeginScene(dxc.pd3dd));
|
|
||||||
DXCheck(IDirect3DDevice_Execute(dxc.pd3dd, ebc.pd3deb, dxc.viewport, D3DEXECUTE_CLIPPED));
|
|
||||||
DXCheck(IDirect3DDevice_EndScene(dxc.pd3dd));
|
|
||||||
|
|
||||||
D3D_ReleaseExecuteBuffer(&ebc);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
qboolean R_Init( void )
|
|
||||||
{
|
|
||||||
memset(&dxc, 0, sizeof(dxc));
|
|
||||||
|
|
||||||
gEngfuncs.Cvar_RegisterVariable( &r_novis );
|
|
||||||
gEngfuncs.Cvar_RegisterVariable( &r_nocull );
|
|
||||||
gEngfuncs.Cvar_RegisterVariable( &r_lockpvs );
|
|
||||||
gEngfuncs.Cvar_RegisterVariable( &r_lockfrustum );
|
|
||||||
|
|
||||||
// init draw stack
|
|
||||||
tr.draw_list = &tr.draw_stack[0];
|
|
||||||
tr.draw_stack_pos = 0;
|
|
||||||
|
|
||||||
r_temppool = Mem_AllocPool("Render Zone");
|
|
||||||
|
|
||||||
// create the window
|
|
||||||
if (!gEngfuncs.R_Init_Video(REF_D3D))
|
|
||||||
{
|
|
||||||
Mem_FreePool(&r_temppool);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *handle = NULL;
|
|
||||||
ref_window_type_t wt = gEngfuncs.R_GetWindowHandle( &handle, REF_WINDOW_TYPE_WIN32 );
|
|
||||||
gEngfuncs.Con_Printf( "R_Init: WindowHandle %p type %d\n", handle, wt );
|
|
||||||
if (wt != REF_WINDOW_TYPE_WIN32 || !handle)
|
|
||||||
{
|
|
||||||
Mem_FreePool(&r_temppool);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
dxc.window = (HWND)handle;
|
|
||||||
|
|
||||||
RECT dstRect = { 0 };
|
|
||||||
GetClientRect(dxc.window, &dstRect);
|
|
||||||
dxc.windowWidth = dstRect.right - dstRect.left;
|
|
||||||
dxc.windowHeight = dstRect.bottom - dstRect.top;
|
|
||||||
|
|
||||||
DXCheck(DirectDrawCreate(NULL, &dxc.pdd, NULL));
|
|
||||||
gEngfuncs.Con_Reportf("DirectDrawCreate %p\n", dxc.pdd);
|
|
||||||
if (!dxc.pdd)
|
|
||||||
{
|
|
||||||
Mem_FreePool(&r_temppool);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DXCheck(IDirectDraw_SetCooperativeLevel(dxc.pdd, dxc.window, DDSCL_NORMAL));
|
|
||||||
|
|
||||||
if (!DD_CreatePrimarySurface())
|
|
||||||
{
|
|
||||||
Mem_FreePool(&r_temppool);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!DD_CreateBackSurface())
|
|
||||||
{
|
|
||||||
Mem_FreePool(&r_temppool);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!D3D_Init())
|
|
||||||
{
|
|
||||||
Mem_FreePool(&r_temppool);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!D3D_InitDevice())
|
|
||||||
{
|
|
||||||
Mem_FreePool(&r_temppool);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// see R_ProcessEntData for tr.entities initialization
|
|
||||||
tr.world = (struct world_static_s *)ENGINE_GET_PARM( PARM_GET_WORLD_PTR );
|
|
||||||
tr.viewent = (cl_entity_t *)ENGINE_GET_PARM( PARM_GET_VIEWENT_PTR );
|
|
||||||
|
|
||||||
dxc.renderMode = kRenderNormal;
|
|
||||||
Vector4Set(dxc.currentColor, 1, 1, 1, 1);
|
|
||||||
|
|
||||||
R_InitImages();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void R_Shutdown( void )
|
|
||||||
{
|
|
||||||
gEngfuncs.Con_Printf("ref: R_Shutdown()\n");
|
|
||||||
|
|
||||||
Mem_FreePool(&r_temppool);
|
|
||||||
|
|
||||||
gEngfuncs.R_Free_Video();
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D_Resize( int width, int height )
|
|
||||||
{
|
|
||||||
dxc.windowWidth = width;
|
|
||||||
dxc.windowHeight = height;
|
|
||||||
|
|
||||||
if( dxc.pd3deb )
|
|
||||||
IDirect3DExecuteBuffer_Release(dxc.pd3deb);
|
|
||||||
dxc.pd3deb = NULL;
|
|
||||||
if( dxc.pd3dd )
|
|
||||||
IDirect3DDevice_Release(dxc.pd3dd);
|
|
||||||
dxc.pd3dd = NULL;
|
|
||||||
if( dxc.pddsBack )
|
|
||||||
IDirectDrawSurface_Release(dxc.pddsBack);
|
|
||||||
dxc.pddsBack = NULL;
|
|
||||||
if( dxc.pddsZBuffer )
|
|
||||||
IDirectDrawSurface_Release(dxc.pddsZBuffer);
|
|
||||||
dxc.pddsZBuffer = NULL;
|
|
||||||
if( dxc.pddBackClipper )
|
|
||||||
IDirectDrawClipper_Release(dxc.pddBackClipper);
|
|
||||||
dxc.pddBackClipper = NULL;
|
|
||||||
if( DD_CreateBackSurface() )
|
|
||||||
{
|
|
||||||
if( D3D_InitDevice() )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GL_SetupAttributes( int safegl )
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GL_InitExtensions( void )
|
|
||||||
{
|
|
||||||
tr.framecount = tr.visframecount = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GL_ClearExtensions( void )
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DX2_CREATE_EB 0
|
|
||||||
|
|
||||||
qboolean D3D_StartExecuteBuffer( d3dEBContext_t *ctx )
|
|
||||||
{
|
|
||||||
#if DX2_CREATE_EB
|
|
||||||
ctx->pd3deb = NULL;
|
|
||||||
D3DEXECUTEBUFFERDESC ebd = { 0 };
|
|
||||||
memset(&ebd, 0, sizeof(ebd));
|
|
||||||
ebd.dwSize = sizeof(ebd);
|
|
||||||
ebd.dwFlags = D3DDEB_BUFSIZE;
|
|
||||||
ebd.dwBufferSize = 512;
|
|
||||||
DXCheck(IDirect3DDevice_CreateExecuteBuffer(dxc.pd3dd, &ebd, &ctx->pd3deb, NULL));
|
|
||||||
#else
|
|
||||||
ctx->pd3deb = dxc.pd3deb;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!ctx->pd3deb)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
D3DEXECUTEBUFFERDESC ebDesc = { 0 };
|
|
||||||
memset(&ebDesc, 0, sizeof(ebDesc));
|
|
||||||
ebDesc.dwSize = sizeof(ebDesc);
|
|
||||||
ebDesc.dwFlags = D3DDEB_LPDATA;
|
|
||||||
HRESULT r = D3D_OK;
|
|
||||||
DXCheckRet(r, IDirect3DExecuteBuffer_Lock(ctx->pd3deb, &ebDesc));
|
|
||||||
if (r != D3D_OK)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
//gEngfuncs.Con_Printf("IDirect3DExecuteBuffer_Lock size %lu data %p\n", ebDesc.dwBufferSize, ebDesc.lpData);
|
|
||||||
|
|
||||||
ctx->bufferSize = ebDesc.dwBufferSize;
|
|
||||||
ctx->data = ebDesc.lpData;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
qboolean D3D_EndExecuteBuffer( d3dEBContext_t *ctx )
|
|
||||||
{
|
|
||||||
HRESULT r = D3D_OK;
|
|
||||||
DXCheckRet(r, IDirect3DExecuteBuffer_Unlock(ctx->pd3deb));
|
|
||||||
if( r != D3D_OK )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
D3DEXECUTEDATA exData = { 0 };
|
|
||||||
memset(&exData, 0, sizeof(exData));
|
|
||||||
exData.dwSize = sizeof(exData);
|
|
||||||
exData.dwVertexCount = ctx->vertCount;
|
|
||||||
exData.dwVertexOffset = 0;
|
|
||||||
exData.dwInstructionOffset = ctx->insOffset;
|
|
||||||
exData.dwInstructionLength = ctx->insLength;
|
|
||||||
DXCheckRet(r, IDirect3DExecuteBuffer_SetExecuteData(ctx->pd3deb, &exData));
|
|
||||||
|
|
||||||
return r == D3D_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D_ReleaseExecuteBuffer( d3dEBContext_t *ctx )
|
|
||||||
{
|
|
||||||
#if DX2_CREATE_EB
|
|
||||||
if( ctx->pd3deb && ctx->pd3deb != dxc.pd3deb )
|
|
||||||
IDirect3DExecuteBuffer_Release( ctx->pd3deb );
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D_SetVertTL( D3DTLVERTEX* v, float x, float y, float z, float w, float tu, float tv )
|
|
||||||
{
|
|
||||||
v->sx = x;
|
|
||||||
v->sy = y;
|
|
||||||
v->sz = z;
|
|
||||||
v->rhw = w;
|
|
||||||
//v->color = RGBA_MAKE(250, 10, 10, 255);
|
|
||||||
v->tu = tu;
|
|
||||||
v->tv = tv;
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D_SetTri( D3DTRIANGLE *t, int v1, int v2, int v3 )
|
|
||||||
{
|
|
||||||
t->v1 = v1;
|
|
||||||
t->v2 = v2;
|
|
||||||
t->v3 = v3;
|
|
||||||
t->wFlags = D3DTRIFLAG_EDGEENABLETRIANGLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D_PutInstruction( void **dst, BYTE opcode, BYTE size, WORD count )
|
|
||||||
{
|
|
||||||
D3DINSTRUCTION* inst = (D3DINSTRUCTION*)*dst;
|
|
||||||
inst->bOpcode = opcode;
|
|
||||||
inst->bSize = size;
|
|
||||||
inst->wCount = count;
|
|
||||||
*dst = (void*)(((D3DINSTRUCTION*)*dst) + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D_PutProcessVertices( void** dst, DWORD flags, WORD start, WORD count )
|
|
||||||
{
|
|
||||||
D3D_PutInstruction(dst, D3DOP_PROCESSVERTICES, sizeof(D3DPROCESSVERTICES), 1);
|
|
||||||
|
|
||||||
D3DPROCESSVERTICES* pv = (D3DPROCESSVERTICES*)*dst;
|
|
||||||
pv->dwFlags = flags;
|
|
||||||
pv->wStart = start;
|
|
||||||
pv->wDest = start;
|
|
||||||
pv->dwCount = count;
|
|
||||||
pv->dwReserved = 0;
|
|
||||||
*dst = (void*)(((D3DPROCESSVERTICES*)*dst) + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D_PutRenderState( void** dst, D3DRENDERSTATETYPE type, DWORD arg )
|
|
||||||
{
|
|
||||||
D3DSTATE* s = (D3DSTATE*)*dst;
|
|
||||||
|
|
||||||
s->drstRenderStateType = type;
|
|
||||||
s->dwArg[0] = arg;
|
|
||||||
*dst = (void*)(((D3DSTATE*)*dst) + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D_PutTransformState( void** dst, D3DTRANSFORMSTATETYPE type, DWORD arg )
|
|
||||||
{
|
|
||||||
D3DSTATE* s = (D3DSTATE*)*dst;
|
|
||||||
|
|
||||||
s->dtstTransformStateType = type;
|
|
||||||
s->dwArg[0] = arg;
|
|
||||||
*dst = (void*)(((D3DSTATE*)*dst) + 1);
|
|
||||||
}
|
|
||||||
204
ref/dx2/r_draw.c
204
ref/dx2/r_draw.c
@@ -1,204 +0,0 @@
|
|||||||
/*
|
|
||||||
r_draw.c -- dx2 2D drawing
|
|
||||||
Copyright (C) 2025-2026 lewa_j
|
|
||||||
|
|
||||||
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 "r_local.h"
|
|
||||||
#include "xash3d_mathlib.h"
|
|
||||||
|
|
||||||
void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, int texnum )
|
|
||||||
{
|
|
||||||
if (texnum <= 0 || texnum >= MAX_TEXTURES)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dx_texture_t *tex = R_GetTexture(texnum);
|
|
||||||
if (!tex->dds)
|
|
||||||
return;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
RECT dstRect = { x, y, x + w, y + h };
|
|
||||||
RECT srcRect = { s1 * tex->width, t1 * tex->height, s2 * tex->width, t2 * tex->height};
|
|
||||||
|
|
||||||
if (dxc.renderMode == kRenderNormal)
|
|
||||||
{
|
|
||||||
DXCheck(IDirectDrawSurface_Blt(dxc.pddsBack, &dstRect, tex->dds, &srcRect, DDBLT_WAIT, NULL));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DDCOLORKEY ddck;
|
|
||||||
ddck.dwColorSpaceLowValue = 0;
|
|
||||||
ddck.dwColorSpaceHighValue = ddck.dwColorSpaceLowValue;
|
|
||||||
DXCheck(IDirectDrawSurface_SetColorKey(tex->dds, DDCKEY_SRCBLT, &ddck));
|
|
||||||
|
|
||||||
DXCheck(IDirectDrawSurface_Blt(dxc.pddsBack, &dstRect, tex->dds, &srcRect, DDBLT_WAIT | DDBLT_KEYSRC, NULL));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
|
|
||||||
if (!dxc.pd3dd)
|
|
||||||
return;
|
|
||||||
|
|
||||||
d3dEBContext_t ebc = { 0 };
|
|
||||||
{
|
|
||||||
if( !D3D_StartExecuteBuffer( &ebc ))
|
|
||||||
return;
|
|
||||||
|
|
||||||
void *cur = ebc.data;
|
|
||||||
|
|
||||||
const int vertCount = 4;
|
|
||||||
D3DTLVERTEX* verts = (D3DTLVERTEX*)cur;
|
|
||||||
|
|
||||||
// fix for half coordinate pixel centers in d3d compared to gl
|
|
||||||
x -= 0.5;
|
|
||||||
y -= 0.5;
|
|
||||||
|
|
||||||
#define VecToD3DCOLOR(v) D3DRGBA(v[0], v[1], v[2], v[3])
|
|
||||||
|
|
||||||
verts[0].color = VecToD3DCOLOR(dxc.currentColor);
|
|
||||||
D3D_SetVertTL(verts, x, y, 0.5, 1, s1, t1);
|
|
||||||
verts[1].color = verts[0].color;
|
|
||||||
D3D_SetVertTL(verts + 1, x + w, y, 0.5, 1, s2, t1);
|
|
||||||
verts[2].color = verts[0].color;
|
|
||||||
D3D_SetVertTL(verts + 2, x + w, y + h, 0.5, 1, s2, t2);
|
|
||||||
verts[3].color = verts[0].color;
|
|
||||||
D3D_SetVertTL(verts + 3, x, y + h, 0.5, 1, s1, t2);
|
|
||||||
|
|
||||||
cur = (void*)(((D3DTLVERTEX*)cur) + vertCount);
|
|
||||||
|
|
||||||
void* insStart = cur;
|
|
||||||
|
|
||||||
D3D_PutProcessVertices(&cur, D3DPROCESSVERTICES_COPY | D3DPROCESSVERTICES_UPDATEEXTENTS, 0, vertCount);
|
|
||||||
|
|
||||||
D3D_PutInstruction(&cur, D3DOP_STATERENDER, sizeof(D3DSTATE), 3);
|
|
||||||
// TODO disable when == tr.whiteTexture
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_TEXTUREHANDLE, tex->d3dHandle);
|
|
||||||
//D3D_PutRenderState(&cur, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_DECAL);
|
|
||||||
|
|
||||||
if (dxc.renderMode == kRenderTransAlpha)
|
|
||||||
{
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_BLENDENABLE, FALSE);
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_ALPHATESTENABLE, TRUE);
|
|
||||||
}
|
|
||||||
else if (dxc.renderMode == kRenderGlow ||
|
|
||||||
dxc.renderMode == kRenderTransAdd)
|
|
||||||
{
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_BLENDENABLE, TRUE);
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_ALPHATESTENABLE, FALSE);
|
|
||||||
D3D_PutInstruction(&cur, D3DOP_STATERENDER, sizeof(D3DSTATE), 2);
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE);
|
|
||||||
}
|
|
||||||
else if (dxc.renderMode == kRenderTransColor || dxc.renderMode == kRenderTransTexture)
|
|
||||||
{
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_BLENDENABLE, TRUE);
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_ALPHATESTENABLE, FALSE);
|
|
||||||
D3D_PutInstruction(&cur, D3DOP_STATERENDER, sizeof(D3DSTATE), 2);
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
|
||||||
}
|
|
||||||
else// if (dxc.renderMode == kRenderNormal)
|
|
||||||
{
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_BLENDENABLE, FALSE);
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_ALPHATESTENABLE, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// align
|
|
||||||
if (((ULONG)cur) & 7) {
|
|
||||||
D3D_PutInstruction(&cur, D3DOP_TRIANGLE, sizeof(D3DTRIANGLE), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D_PutInstruction(&cur, D3DOP_TRIANGLE, sizeof(D3DTRIANGLE), 2);
|
|
||||||
|
|
||||||
D3DTRIANGLE* tris = (D3DTRIANGLE*)cur;
|
|
||||||
D3D_SetTri(tris, 0, 1, 2);
|
|
||||||
D3D_SetTri(tris + 1, 0, 2, 3);
|
|
||||||
cur = (void*)(((D3DTRIANGLE*)cur) + 2);
|
|
||||||
|
|
||||||
D3D_PutInstruction(&cur, D3DOP_EXIT, 0, 0);
|
|
||||||
|
|
||||||
ebc.vertCount = 4;
|
|
||||||
ebc.insOffset = ((char*)insStart - (char*)ebc.data);
|
|
||||||
ebc.insLength = ((char*)cur - (char*)insStart);
|
|
||||||
|
|
||||||
if( !D3D_EndExecuteBuffer( &ebc ))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DXCheck(IDirect3DDevice_BeginScene(dxc.pd3dd));
|
|
||||||
DXCheck(IDirect3DDevice_Execute(dxc.pd3dd, ebc.pd3deb, dxc.viewport, D3DEXECUTE_CLIPPED));
|
|
||||||
DXCheck(IDirect3DDevice_EndScene(dxc.pd3dd));
|
|
||||||
|
|
||||||
D3D_ReleaseExecuteBuffer( &ebc );
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void FillRGBA( int rendermode, float x, float y, float w, float h, byte r, byte g, byte b, byte a )
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
RECT dstRect = { x, y, x + w, y + h };
|
|
||||||
DDBLTFX bltFx = { 0 };
|
|
||||||
bltFx.dwSize = sizeof(bltFx);
|
|
||||||
bltFx.dwFillColor = RGBA_MAKE(r, g, b, a);
|
|
||||||
DXCheck(IDirectDrawSurface_Blt(dxc.pddsBack, &dstRect, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &bltFx));
|
|
||||||
#else
|
|
||||||
// TODO Restore after?
|
|
||||||
GL_SetRenderMode( (rendermode == kRenderTransAdd) ? rendermode : kRenderTransColor);
|
|
||||||
Vector4Set( dxc.currentColor, r / 255.f, g / 255.f, b / 255.f, a / 255.f );
|
|
||||||
R_DrawStretchPic( x, y, w, h, 0, 0, 0, 0, tr.whiteTexture );
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void R_Set2DMode( qboolean enable )
|
|
||||||
{
|
|
||||||
if( enable && dxc.in2DMode )
|
|
||||||
return;
|
|
||||||
dxc.in2DMode = enable;
|
|
||||||
|
|
||||||
d3dEBContext_t ebc = { 0 };
|
|
||||||
if( !D3D_StartExecuteBuffer( &ebc ))
|
|
||||||
return;
|
|
||||||
void *cur = ebc.data;
|
|
||||||
|
|
||||||
if( enable )
|
|
||||||
{
|
|
||||||
D3D_PutInstruction(&cur, D3DOP_STATERENDER, sizeof(D3DSTATE), 4);
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_ZENABLE, FALSE);
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_ZWRITEENABLE, FALSE);
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_ALPHATESTENABLE, TRUE);
|
|
||||||
Vector4Set( dxc.currentColor, 1.0f, 1.0f, 1.0f, 1.0f );
|
|
||||||
|
|
||||||
RI.currententity = NULL;
|
|
||||||
RI.currentmodel = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
D3D_PutInstruction(&cur, D3DOP_STATERENDER, sizeof(D3DSTATE), 3);
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_ZENABLE, TRUE);
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_ZWRITEENABLE, TRUE);
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_CULLMODE, D3DCULL_CCW);
|
|
||||||
}
|
|
||||||
|
|
||||||
ebc.vertCount = 0;
|
|
||||||
ebc.insOffset = 0;
|
|
||||||
ebc.insLength = ((char *)cur - (char *)ebc.data);
|
|
||||||
|
|
||||||
if (!D3D_EndExecuteBuffer(&ebc))
|
|
||||||
return;
|
|
||||||
|
|
||||||
DXCheck(IDirect3DDevice_BeginScene(dxc.pd3dd));
|
|
||||||
DXCheck(IDirect3DDevice_Execute(dxc.pd3dd, ebc.pd3deb, dxc.viewport, D3DEXECUTE_CLIPPED));
|
|
||||||
DXCheck(IDirect3DDevice_EndScene(dxc.pd3dd));
|
|
||||||
|
|
||||||
D3D_ReleaseExecuteBuffer(&ebc);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,185 +0,0 @@
|
|||||||
/*
|
|
||||||
r_frustum.c - frustum test implementation
|
|
||||||
Copyright (C) 2016 Uncle Mike
|
|
||||||
|
|
||||||
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 "r_local.h"
|
|
||||||
#include "xash3d_mathlib.h"
|
|
||||||
|
|
||||||
static void GL_FrustumSetPlane( gl_frustum_t *out, int side, const vec3_t vecNormal, float flDist )
|
|
||||||
{
|
|
||||||
Assert( side >= 0 && side < FRUSTUM_PLANES );
|
|
||||||
|
|
||||||
out->planes[side].type = PlaneTypeForNormal( vecNormal );
|
|
||||||
out->planes[side].signbits = SignbitsForPlane( vecNormal );
|
|
||||||
VectorCopy( vecNormal, out->planes[side].normal );
|
|
||||||
out->planes[side].dist = flDist;
|
|
||||||
|
|
||||||
SetBits( out->clipFlags, BIT( side ));
|
|
||||||
}
|
|
||||||
|
|
||||||
void GL_FrustumInitProj( gl_frustum_t *out, float flZNear, float flZFar, float flFovX, float flFovY )
|
|
||||||
{
|
|
||||||
float xs, xc;
|
|
||||||
vec3_t farpoint, nearpoint;
|
|
||||||
vec3_t normal, iforward;
|
|
||||||
|
|
||||||
// horizontal fov used for left and right planes
|
|
||||||
SinCos( DEG2RAD( flFovX ) * 0.5f, &xs, &xc );
|
|
||||||
|
|
||||||
// setup left plane
|
|
||||||
VectorMAM( xs, RI.cull_vforward, -xc, RI.cull_vright, normal );
|
|
||||||
GL_FrustumSetPlane( out, FRUSTUM_LEFT, normal, DotProduct( RI.cullorigin, normal ));
|
|
||||||
|
|
||||||
// setup right plane
|
|
||||||
VectorMAM( xs, RI.cull_vforward, xc, RI.cull_vright, normal );
|
|
||||||
GL_FrustumSetPlane( out, FRUSTUM_RIGHT, normal, DotProduct( RI.cullorigin, normal ));
|
|
||||||
|
|
||||||
// vertical fov used for top and bottom planes
|
|
||||||
SinCos( DEG2RAD( flFovY ) * 0.5f, &xs, &xc );
|
|
||||||
VectorNegate( RI.cull_vforward, iforward );
|
|
||||||
|
|
||||||
// setup bottom plane
|
|
||||||
VectorMAM( xs, RI.cull_vforward, -xc, RI.cull_vup, normal );
|
|
||||||
GL_FrustumSetPlane( out, FRUSTUM_BOTTOM, normal, DotProduct( RI.cullorigin, normal ));
|
|
||||||
|
|
||||||
// setup top plane
|
|
||||||
VectorMAM( xs, RI.cull_vforward, xc, RI.cull_vup, normal );
|
|
||||||
GL_FrustumSetPlane( out, FRUSTUM_TOP, normal, DotProduct( RI.cullorigin, normal ));
|
|
||||||
|
|
||||||
// setup far plane
|
|
||||||
VectorMA( RI.cullorigin, flZFar, RI.cull_vforward, farpoint );
|
|
||||||
GL_FrustumSetPlane( out, FRUSTUM_FAR, iforward, DotProduct( iforward, farpoint ));
|
|
||||||
|
|
||||||
// no need to setup backplane for general view.
|
|
||||||
if( flZNear == 0.0f ) return;
|
|
||||||
|
|
||||||
// setup near plane
|
|
||||||
VectorMA( RI.cullorigin, flZNear, RI.cull_vforward, nearpoint );
|
|
||||||
GL_FrustumSetPlane( out, FRUSTUM_NEAR, RI.cull_vforward, DotProduct( RI.cull_vforward, nearpoint ));
|
|
||||||
}
|
|
||||||
|
|
||||||
void GL_FrustumInitOrtho( gl_frustum_t *out, float xLeft, float xRight, float yTop, float yBottom, float flZNear, float flZFar )
|
|
||||||
{
|
|
||||||
vec3_t iforward, iright, iup;
|
|
||||||
|
|
||||||
// setup the near and far planes
|
|
||||||
float orgOffset = DotProduct( RI.cullorigin, RI.cull_vforward );
|
|
||||||
VectorNegate( RI.cull_vforward, iforward );
|
|
||||||
|
|
||||||
// because quake ortho is inverted and far and near should be swaped
|
|
||||||
GL_FrustumSetPlane( out, FRUSTUM_FAR, iforward, -flZNear - orgOffset );
|
|
||||||
GL_FrustumSetPlane( out, FRUSTUM_NEAR, RI.cull_vforward, flZFar + orgOffset );
|
|
||||||
|
|
||||||
// setup left and right planes
|
|
||||||
orgOffset = DotProduct( RI.cullorigin, RI.cull_vright );
|
|
||||||
VectorNegate( RI.cull_vright, iright );
|
|
||||||
|
|
||||||
GL_FrustumSetPlane( out, FRUSTUM_LEFT, RI.cull_vright, xLeft + orgOffset );
|
|
||||||
GL_FrustumSetPlane( out, FRUSTUM_RIGHT, iright, -xRight - orgOffset );
|
|
||||||
|
|
||||||
// setup top and buttom planes
|
|
||||||
orgOffset = DotProduct( RI.cullorigin, RI.cull_vup );
|
|
||||||
VectorNegate( RI.cull_vup, iup );
|
|
||||||
|
|
||||||
GL_FrustumSetPlane( out, FRUSTUM_TOP, RI.cull_vup, yTop + orgOffset );
|
|
||||||
GL_FrustumSetPlane( out, FRUSTUM_BOTTOM, iup, -yBottom - orgOffset );
|
|
||||||
}
|
|
||||||
|
|
||||||
// cull methods
|
|
||||||
qboolean GL_FrustumCullBox( const gl_frustum_t *out, const vec3_t mins, const vec3_t maxs, int userClipFlags )
|
|
||||||
{
|
|
||||||
int iClipFlags;
|
|
||||||
int i, bit;
|
|
||||||
|
|
||||||
if( r_nocull.value )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if( userClipFlags != 0 )
|
|
||||||
iClipFlags = userClipFlags;
|
|
||||||
else iClipFlags = out->clipFlags;
|
|
||||||
|
|
||||||
for( i = FRUSTUM_PLANES, bit = 1; i > 0; i--, bit <<= 1 )
|
|
||||||
{
|
|
||||||
const mplane_t *p = &out->planes[FRUSTUM_PLANES - i];
|
|
||||||
|
|
||||||
if( !FBitSet( iClipFlags, bit ))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
switch( p->signbits )
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
if( p->normal[0] * maxs[0] + p->normal[1] * maxs[1] + p->normal[2] * maxs[2] < p->dist )
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
if( p->normal[0] * mins[0] + p->normal[1] * maxs[1] + p->normal[2] * maxs[2] < p->dist )
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
if( p->normal[0] * maxs[0] + p->normal[1] * mins[1] + p->normal[2] * maxs[2] < p->dist )
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
if( p->normal[0] * mins[0] + p->normal[1] * mins[1] + p->normal[2] * maxs[2] < p->dist )
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
if( p->normal[0] * maxs[0] + p->normal[1] * maxs[1] + p->normal[2] * mins[2] < p->dist )
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
if( p->normal[0] * mins[0] + p->normal[1] * maxs[1] + p->normal[2] * mins[2] < p->dist )
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
if( p->normal[0] * maxs[0] + p->normal[1] * mins[1] + p->normal[2] * mins[2] < p->dist )
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
if( p->normal[0] * mins[0] + p->normal[1] * mins[1] + p->normal[2] * mins[2] < p->dist )
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
qboolean GL_FrustumCullSphere( const gl_frustum_t *out, const vec3_t center, float radius, int userClipFlags )
|
|
||||||
{
|
|
||||||
int iClipFlags;
|
|
||||||
int i, bit;
|
|
||||||
|
|
||||||
if( r_nocull.value )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if( userClipFlags != 0 )
|
|
||||||
iClipFlags = userClipFlags;
|
|
||||||
else iClipFlags = out->clipFlags;
|
|
||||||
|
|
||||||
for( i = FRUSTUM_PLANES, bit = 1; i > 0; i--, bit <<= 1 )
|
|
||||||
{
|
|
||||||
const mplane_t *p = &out->planes[FRUSTUM_PLANES - i];
|
|
||||||
|
|
||||||
if( !FBitSet( iClipFlags, bit ))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if( DotProduct( center, p->normal ) - p->dist <= -radius )
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
r_frustum.h - frustum test implementation
|
|
||||||
Copyright (C) 2016 Uncle Mike
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GL_FRUSTUM_H
|
|
||||||
#define GL_FRUSTUM_H
|
|
||||||
|
|
||||||
// don't change this order
|
|
||||||
#define FRUSTUM_LEFT 0
|
|
||||||
#define FRUSTUM_RIGHT 1
|
|
||||||
#define FRUSTUM_BOTTOM 2
|
|
||||||
#define FRUSTUM_TOP 3
|
|
||||||
#define FRUSTUM_FAR 4
|
|
||||||
#define FRUSTUM_NEAR 5
|
|
||||||
#define FRUSTUM_PLANES 6
|
|
||||||
|
|
||||||
typedef struct gl_frustum_s
|
|
||||||
{
|
|
||||||
mplane_t planes[FRUSTUM_PLANES];
|
|
||||||
unsigned int clipFlags;
|
|
||||||
} gl_frustum_t;
|
|
||||||
|
|
||||||
void GL_FrustumInitProj( gl_frustum_t *out, float flZNear, float flZFar, float flFovX, float flFovY );
|
|
||||||
void GL_FrustumInitOrtho( gl_frustum_t *out, float xLeft, float xRight, float yTop, float yBottom, float flZNear, float flZFar );
|
|
||||||
|
|
||||||
// cull methods
|
|
||||||
qboolean GL_FrustumCullBox( const gl_frustum_t *out, const vec3_t mins, const vec3_t maxs, int userClipFlags );
|
|
||||||
qboolean GL_FrustumCullSphere( const gl_frustum_t *out, const vec3_t centre, float radius, int userClipFlags );
|
|
||||||
|
|
||||||
#endif//GL_FRUSTUM_H
|
|
||||||
@@ -1,622 +0,0 @@
|
|||||||
/*
|
|
||||||
r_context.c -- dx2 renderer texture uploading and processing
|
|
||||||
Copyright (C) 2010 Uncle Mike
|
|
||||||
Copyright (C) 2025 lewa_j
|
|
||||||
|
|
||||||
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 "r_local.h"
|
|
||||||
#include "xash3d_mathlib.h"
|
|
||||||
#include "crtlib.h"
|
|
||||||
#include "crclib.h"
|
|
||||||
|
|
||||||
static dx_texture_t dx_textures[MAX_TEXTURES];
|
|
||||||
static dx_texture_t *dx_texturesHashTable[TEXTURES_HASH_SIZE];
|
|
||||||
static uint dx_numTextures;
|
|
||||||
|
|
||||||
void R_InitImages( void )
|
|
||||||
{
|
|
||||||
memset(dx_textures, 0, sizeof(dx_textures));
|
|
||||||
memset(dx_texturesHashTable, 0, sizeof(dx_texturesHashTable));
|
|
||||||
dx_numTextures = 0;
|
|
||||||
|
|
||||||
// create unused 0-entry
|
|
||||||
Q_strncpy(dx_textures->name, "*unused*", sizeof(dx_textures->name));
|
|
||||||
dx_textures->hashValue = COM_HashKey(dx_textures->name, TEXTURES_HASH_SIZE);
|
|
||||||
dx_textures->nextHash = dx_texturesHashTable[dx_textures->hashValue];
|
|
||||||
dx_texturesHashTable[dx_textures->hashValue] = dx_textures;
|
|
||||||
dx_numTextures = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
dx_texture_t *R_GetTexture( unsigned int texnum )
|
|
||||||
{
|
|
||||||
Assert(texnum < MAX_TEXTURES);
|
|
||||||
return &dx_textures[texnum];
|
|
||||||
}
|
|
||||||
|
|
||||||
void R_ShowTextures( void )
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const byte *R_GetTextureOriginalBuffer( unsigned int idx )
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static qboolean GL_CheckTexName( const char *name )
|
|
||||||
{
|
|
||||||
int len;
|
|
||||||
|
|
||||||
if( COM_StringEmptyOrNULL( name ))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
len = Q_strlen( name );
|
|
||||||
|
|
||||||
// because multi-layered textures can exceed name string
|
|
||||||
if( len >= sizeof( dx_textures->name ))
|
|
||||||
{
|
|
||||||
gEngfuncs.Con_Printf( S_ERROR "LoadTexture: too long name %s (%d)\n", name, len );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static dx_texture_t *GL_TextureForName( const char *name )
|
|
||||||
{
|
|
||||||
dx_texture_t *tex;
|
|
||||||
uint hash;
|
|
||||||
|
|
||||||
// find the texture in array
|
|
||||||
hash = COM_HashKey(name, TEXTURES_HASH_SIZE);
|
|
||||||
|
|
||||||
for (tex = dx_texturesHashTable[hash]; tex != NULL; tex = tex->nextHash)
|
|
||||||
{
|
|
||||||
if (!Q_stricmp(tex->name, name))
|
|
||||||
return tex;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static dx_texture_t *GL_AllocTexture( const char *name, texFlags_t flags )
|
|
||||||
{
|
|
||||||
dx_texture_t *tex = NULL;
|
|
||||||
|
|
||||||
// find a free texture_t slot
|
|
||||||
uint i;
|
|
||||||
|
|
||||||
//skip 0
|
|
||||||
for (i = 1; i < MAX_TEXTURES; i++)
|
|
||||||
{
|
|
||||||
if (dx_textures[i].used)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
tex = &dx_textures[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tex == NULL)
|
|
||||||
{
|
|
||||||
gEngfuncs.Host_Error("%s: MAX_TEXTURES limit exceeds\n", __func__);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy initial params
|
|
||||||
Q_strncpy(tex->name, name, sizeof(tex->name));
|
|
||||||
tex->used = 1;
|
|
||||||
tex->flags = flags;
|
|
||||||
|
|
||||||
// increase counter
|
|
||||||
dx_numTextures = Q_max((tex - dx_textures) + 1, dx_numTextures);
|
|
||||||
|
|
||||||
// add to hash table
|
|
||||||
tex->hashValue = COM_HashKey(name, TEXTURES_HASH_SIZE);
|
|
||||||
tex->nextHash = dx_texturesHashTable[tex->hashValue];
|
|
||||||
dx_texturesHashTable[tex->hashValue] = tex;
|
|
||||||
|
|
||||||
return tex;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void GL_ProcessImage( dx_texture_t *tex, rgbdata_t *pic )
|
|
||||||
{
|
|
||||||
uint img_flags = 0;
|
|
||||||
|
|
||||||
// force upload texture as RGB or RGBA (detail textures requires this)
|
|
||||||
if (tex->flags & TF_FORCE_COLOR) pic->flags |= IMAGE_HAS_COLOR;
|
|
||||||
if (pic->flags & IMAGE_HAS_ALPHA) tex->flags |= TF_HAS_ALPHA;
|
|
||||||
|
|
||||||
if (ImageCompressed(pic->type))
|
|
||||||
{
|
|
||||||
if (!pic->numMips)
|
|
||||||
tex->flags |= TF_NOMIPMAP; // disable mipmapping by user request
|
|
||||||
|
|
||||||
// clear all the unsupported flags
|
|
||||||
tex->flags &= ~TF_KEEP_SOURCE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// copy flag about luma pixels
|
|
||||||
if (pic->flags & IMAGE_HAS_LUMA)
|
|
||||||
tex->flags |= TF_HAS_LUMA;
|
|
||||||
|
|
||||||
if (pic->flags & IMAGE_QUAKEPAL)
|
|
||||||
tex->flags |= TF_QUAKEPAL;
|
|
||||||
|
|
||||||
// create luma texture from quake texture
|
|
||||||
if (tex->flags & TF_MAKELUMA)
|
|
||||||
{
|
|
||||||
img_flags |= IMAGE_MAKE_LUMA;
|
|
||||||
tex->flags &= ~TF_MAKELUMA;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!FBitSet(tex->flags, TF_IMG_UPLOADED) && FBitSet(tex->flags, TF_KEEP_SOURCE))
|
|
||||||
tex->original = gEngfuncs.FS_CopyImage(pic); // because current pic will be expanded to rgba
|
|
||||||
|
|
||||||
// we need to expand image into RGBA buffer
|
|
||||||
if (pic->type == PF_INDEXED_24 || pic->type == PF_INDEXED_32)
|
|
||||||
img_flags |= IMAGE_FORCE_RGBA;
|
|
||||||
|
|
||||||
// processing image before uploading (force to rgba, make luma etc)
|
|
||||||
if (pic->buffer) gEngfuncs.Image_Process(&pic, 0, 0, img_flags, 0);
|
|
||||||
|
|
||||||
if (FBitSet(tex->flags, TF_LUMINANCE))
|
|
||||||
ClearBits(pic->flags, IMAGE_HAS_COLOR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int GL_CalcMipmapCount( dx_texture_t *tex, qboolean haveBuffer )
|
|
||||||
{
|
|
||||||
int width, height;
|
|
||||||
int mipcount;
|
|
||||||
|
|
||||||
Assert(tex != NULL);
|
|
||||||
|
|
||||||
//TEMP
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (!haveBuffer)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
// generate mip-levels by user request
|
|
||||||
if (FBitSet(tex->flags, TF_NOMIPMAP))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
// mip-maps can't exceeds 16
|
|
||||||
for (mipcount = 0; mipcount < 16; mipcount++)
|
|
||||||
{
|
|
||||||
width = Q_max(1, (tex->width >> mipcount));
|
|
||||||
height = Q_max(1, (tex->height >> mipcount));
|
|
||||||
if (width == 1 && height == 1)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mipcount + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void GL_TextureImageRAW( dx_texture_t *tex, int width, int height, int type, const char *data )
|
|
||||||
{
|
|
||||||
if (!data)
|
|
||||||
return;
|
|
||||||
|
|
||||||
DDSURFACEDESC ddsd = {};
|
|
||||||
ZeroMemory(&ddsd, sizeof(ddsd));
|
|
||||||
ddsd.dwSize = sizeof(ddsd);
|
|
||||||
ddsd.dwFlags = DDSD_LPSURFACE;
|
|
||||||
DXCheck(IDirectDrawSurface_Lock(tex->dds, NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL));
|
|
||||||
|
|
||||||
int pitch = ddsd.lPitch;
|
|
||||||
if (!pitch)
|
|
||||||
pitch = ddsd.dwWidth * 4;
|
|
||||||
char *dst = (char *)ddsd.lpSurface;
|
|
||||||
|
|
||||||
for (int j = 0; j < (int)ddsd.dwHeight; j++)
|
|
||||||
{
|
|
||||||
//RGBA to BGRA
|
|
||||||
if (type == PF_RGBA_32)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < ddsd.dwWidth; i++)
|
|
||||||
{
|
|
||||||
dst[i * 4 + 0] = data[i * 4 + 2];
|
|
||||||
dst[i * 4 + 1] = data[i * 4 + 1];
|
|
||||||
dst[i * 4 + 2] = data[i * 4 + 0];
|
|
||||||
dst[i * 4 + 3] = data[i * 4 + 3];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (type == PF_BGRA_32)
|
|
||||||
{
|
|
||||||
memcpy(dst, data, ddsd.dwWidth * 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
dst += pitch;
|
|
||||||
data += ddsd.dwWidth * 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
DXCheck(IDirectDrawSurface_Unlock(tex->dds, ddsd.lpSurface));
|
|
||||||
}
|
|
||||||
|
|
||||||
static qboolean GL_UploadTexture( dx_texture_t *tex, rgbdata_t *pic )
|
|
||||||
{
|
|
||||||
byte *buf, *data;
|
|
||||||
size_t size;
|
|
||||||
uint width, height;
|
|
||||||
uint j;
|
|
||||||
qboolean normalMap;
|
|
||||||
const byte *bufend;
|
|
||||||
|
|
||||||
// dedicated server
|
|
||||||
if (!dxc.window)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
Assert(pic != NULL);
|
|
||||||
Assert(tex != NULL);
|
|
||||||
|
|
||||||
qboolean supported = true;
|
|
||||||
|
|
||||||
if (FBitSet(pic->flags, IMAGE_CUBEMAP))
|
|
||||||
supported = false;
|
|
||||||
else if (FBitSet(pic->flags, IMAGE_MULTILAYER) && pic->depth >= 1)
|
|
||||||
supported = false;
|
|
||||||
else if (pic->width > 1 && pic->height > 1 && pic->depth > 1)
|
|
||||||
supported = false;
|
|
||||||
else if (FBitSet(tex->flags, TF_RECTANGLE))
|
|
||||||
supported = false;
|
|
||||||
else if (FBitSet(tex->flags, TF_MULTISAMPLE))
|
|
||||||
supported = false;
|
|
||||||
|
|
||||||
// make sure what target is correct
|
|
||||||
if (!supported)
|
|
||||||
{
|
|
||||||
gEngfuncs.Con_DPrintf(S_ERROR "%s: %s is not supported\n", __func__, tex->name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//if (pic->type == PF_BC6H_SIGNED || pic->type == PF_BC6H_UNSIGNED || pic->type == PF_BC7_UNORM || pic->type == PF_BC7_SRGB)
|
|
||||||
if (ImageCompressed(pic->type))
|
|
||||||
{
|
|
||||||
gEngfuncs.Con_DPrintf(S_ERROR "%s: compressed textures are not supported\n", __func__);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// store original sizes
|
|
||||||
tex->srcWidth = pic->width;
|
|
||||||
tex->srcHeight = pic->height;
|
|
||||||
|
|
||||||
// set the texture dimensions
|
|
||||||
{
|
|
||||||
int step = 0;// (int)gl_round_down.value;
|
|
||||||
int scaled_width, scaled_height;
|
|
||||||
|
|
||||||
for (scaled_width = 1; scaled_width < pic->width; scaled_width <<= 1);
|
|
||||||
|
|
||||||
if (step > 0 && pic->width < scaled_width && (step == 1 || (scaled_width - pic->width) > (scaled_width >> step)))
|
|
||||||
scaled_width >>= 1;
|
|
||||||
|
|
||||||
for (scaled_height = 1; scaled_height < pic->height; scaled_height <<= 1);
|
|
||||||
|
|
||||||
if (step > 0 && pic->height < scaled_height && (step == 1 || (scaled_height - pic->height) > (scaled_height >> step)))
|
|
||||||
scaled_height >>= 1;
|
|
||||||
|
|
||||||
tex->width = Q_max(1, scaled_width);
|
|
||||||
tex->height = Q_max(1, scaled_height);
|
|
||||||
}
|
|
||||||
|
|
||||||
DDSURFACEDESC ddsd = {};
|
|
||||||
ZeroMemory(&ddsd, sizeof(ddsd));
|
|
||||||
ddsd.dwSize = sizeof(ddsd);
|
|
||||||
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
|
|
||||||
ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
|
|
||||||
//if (pic->numMips > 1)
|
|
||||||
// ddsd.ddsCaps.dwCaps |= DDSCAPS_MIPMAP | DDSCAPS_COMPLEX;
|
|
||||||
ddsd.dwWidth = tex->width;
|
|
||||||
ddsd.dwHeight = tex->height;
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
//BGRA8
|
|
||||||
ddsd.dwFlags |= DDSD_PIXELFORMAT;
|
|
||||||
ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
|
|
||||||
ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
|
|
||||||
if(FBitSet(pic->flags, IMAGE_HAS_ALPHA))
|
|
||||||
ddsd.ddpfPixelFormat.dwFlags |= DDPF_ALPHAPIXELS;
|
|
||||||
ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
|
|
||||||
ddsd.ddpfPixelFormat.dwBBitMask = 0xFF;
|
|
||||||
ddsd.ddpfPixelFormat.dwGBitMask = 0xFF00;
|
|
||||||
ddsd.ddpfPixelFormat.dwRBitMask = 0xFF0000;
|
|
||||||
ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xFF000000;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DXCheck(IDirectDraw_CreateSurface(dxc.pdd, &ddsd, &tex->dds, NULL));
|
|
||||||
DXCheck(IDirectDrawSurface_QueryInterface(tex->dds, &IID_IDirect3DTexture, (void**)&tex->d3dTex));
|
|
||||||
DXCheck(IDirect3DTexture_GetHandle(tex->d3dTex, dxc.pd3dd, &tex->d3dHandle));
|
|
||||||
|
|
||||||
tex->fogParams[0] = pic->fogParams[0];
|
|
||||||
tex->fogParams[1] = pic->fogParams[1];
|
|
||||||
tex->fogParams[2] = pic->fogParams[2];
|
|
||||||
tex->fogParams[3] = pic->fogParams[3];
|
|
||||||
|
|
||||||
buf = pic->buffer;
|
|
||||||
bufend = pic->buffer + pic->size; // total image size include all the layers, cube sides, mipmaps
|
|
||||||
normalMap = FBitSet(tex->flags, TF_NORMALMAP) ? true : false;
|
|
||||||
|
|
||||||
if (Q_max(1, pic->numMips) > 1) // not-compressed DDS
|
|
||||||
{
|
|
||||||
//TEMP
|
|
||||||
j = 0;
|
|
||||||
//for (j = 0; j < Q_max(1, pic->numMips); j++)
|
|
||||||
{
|
|
||||||
// track the buffer bounds
|
|
||||||
if (buf != NULL && buf >= bufend)
|
|
||||||
gEngfuncs.Host_Error("%s: %s image buffer overflow\n", __func__, tex->name);
|
|
||||||
|
|
||||||
width = Q_max(1, (tex->width >> j));
|
|
||||||
height = Q_max(1, (tex->height >> j));
|
|
||||||
size = gEngfuncs.Image_CalcImageSize(pic->type, width, height, 1);
|
|
||||||
GL_TextureImageRAW(tex, width, height, pic->type, buf);
|
|
||||||
buf += size; // move pointer
|
|
||||||
tex->numMips++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // RGBA32
|
|
||||||
{
|
|
||||||
// track the buffer bounds
|
|
||||||
if (buf != NULL && buf >= bufend)
|
|
||||||
gEngfuncs.Host_Error("%s: %s image buffer overflow\n", __func__, tex->name);
|
|
||||||
|
|
||||||
int mipCount = GL_CalcMipmapCount(tex, (buf != NULL));
|
|
||||||
|
|
||||||
// NOTE: only single uncompressed textures can be resamples, no mips, no layers, no sides
|
|
||||||
if (((pic->width != tex->width) || (pic->height != tex->height)))
|
|
||||||
data = GL_ResampleTexture(buf, pic->width, pic->height, tex->width, tex->height, normalMap);
|
|
||||||
else data = buf;
|
|
||||||
|
|
||||||
//if (!ImageCompressed(pic->type) && !FBitSet(tex->flags, TF_NOMIPMAP) && FBitSet(pic->flags, IMAGE_ONEBIT_ALPHA))
|
|
||||||
// data = GL_ApplyFilter(data, tex->width, tex->height);
|
|
||||||
|
|
||||||
// mips will be auto-generated if desired
|
|
||||||
for (j = 0; j < mipCount; j++)
|
|
||||||
{
|
|
||||||
width = Q_max(1, (tex->width >> j));
|
|
||||||
height = Q_max(1, (tex->height >> j));
|
|
||||||
size = gEngfuncs.Image_CalcImageSize(pic->type, width, height, 1);
|
|
||||||
GL_TextureImageRAW(tex, width, height, pic->type, data);
|
|
||||||
//if (mipCount > 1)
|
|
||||||
// GL_BuildMipMap(data, width, height, tex->depth, tex->flags);
|
|
||||||
tex->numMips++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SetBits(tex->flags, TF_IMG_UPLOADED); // done
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GL_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update )
|
|
||||||
{
|
|
||||||
dx_texture_t *tex;
|
|
||||||
|
|
||||||
if (!GL_CheckTexName(name))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// see if already loaded
|
|
||||||
if ((tex = GL_TextureForName(name)) && !update)
|
|
||||||
return (tex - dx_textures);
|
|
||||||
|
|
||||||
// couldn't loading image
|
|
||||||
if (!pic) return 0;
|
|
||||||
|
|
||||||
if (update)
|
|
||||||
{
|
|
||||||
if (tex == NULL)
|
|
||||||
gEngfuncs.Host_Error("%s: couldn't find texture %s for update\n", __func__, name);
|
|
||||||
SetBits(tex->flags, flags);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// allocate the new one
|
|
||||||
tex = GL_AllocTexture(name, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
GL_ProcessImage(tex, pic);
|
|
||||||
|
|
||||||
if (!GL_UploadTexture(tex, pic))
|
|
||||||
{
|
|
||||||
memset(tex, 0, sizeof(dx_texture_t));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (tex - dx_textures);
|
|
||||||
}
|
|
||||||
|
|
||||||
int GL_CreateTexture( const char *name, int width, int height, const void *buffer, texFlags_t flags )
|
|
||||||
{
|
|
||||||
qboolean update = FBitSet( flags, TF_UPDATE ) ? true : false;
|
|
||||||
int datasize = 1;
|
|
||||||
rgbdata_t r_empty;
|
|
||||||
|
|
||||||
if( FBitSet( flags, TF_ARB_16BIT ))
|
|
||||||
datasize = 2;
|
|
||||||
else if( FBitSet( flags, TF_ARB_FLOAT ))
|
|
||||||
datasize = 4;
|
|
||||||
|
|
||||||
ClearBits( flags, TF_UPDATE );
|
|
||||||
memset( &r_empty, 0, sizeof( r_empty ));
|
|
||||||
r_empty.width = width;
|
|
||||||
r_empty.height = height;
|
|
||||||
r_empty.type = PF_RGBA_32;
|
|
||||||
r_empty.size = r_empty.width * r_empty.height * datasize * 4;
|
|
||||||
r_empty.buffer = (byte *)buffer;
|
|
||||||
|
|
||||||
// clear invalid combinations
|
|
||||||
ClearBits( flags, TF_TEXTURE_3D );
|
|
||||||
|
|
||||||
// if image not luminance and not alphacontrast it will have color
|
|
||||||
if( !FBitSet( flags, TF_LUMINANCE ) && !FBitSet( flags, TF_ALPHACONTRAST ))
|
|
||||||
SetBits( r_empty.flags, IMAGE_HAS_COLOR );
|
|
||||||
|
|
||||||
if( FBitSet( flags, TF_HAS_ALPHA ))
|
|
||||||
SetBits( r_empty.flags, IMAGE_HAS_ALPHA );
|
|
||||||
|
|
||||||
if( FBitSet( flags, TF_CUBEMAP ))
|
|
||||||
{
|
|
||||||
// no cubemaps in dx2
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int texnum = GL_LoadTextureFromBuffer( name, &r_empty, flags, update );
|
|
||||||
|
|
||||||
if( !Q_strcmp( name, REF_DEFAULT_TEXTURE ))
|
|
||||||
tr.defaultTexture = texnum;
|
|
||||||
else if( !Q_strcmp( name, REF_PARTICLE_TEXTURE ))
|
|
||||||
tr.particleTexture = texnum;
|
|
||||||
else if( !Q_strcmp( name, REF_WHITE_TEXTURE ))
|
|
||||||
tr.whiteTexture = texnum;
|
|
||||||
else if( !Q_strcmp( name, REF_GRAY_TEXTURE ))
|
|
||||||
tr.grayTexture = texnum;
|
|
||||||
else if( !Q_strcmp( name, REF_BLACK_TEXTURE ))
|
|
||||||
tr.blackTexture = texnum;
|
|
||||||
|
|
||||||
return texnum;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor )
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
void R_GetDetailScaleForTexture( int texture, float *xScale, float *yScale )
|
|
||||||
{
|
|
||||||
*xScale = *yScale = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void R_SetDetailScaleForTexture( int texture, float xScale, float yScale )
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GL_FindTexture( const char *name )
|
|
||||||
{
|
|
||||||
gEngfuncs.Con_Printf("GL_FindTexture(%s)\n", name);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *GL_TextureName( unsigned int texnum )
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const byte *GL_TextureData( unsigned int texnum )
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags )
|
|
||||||
{
|
|
||||||
dx_texture_t *tex;
|
|
||||||
rgbdata_t *pic;
|
|
||||||
uint picFlags = 0;
|
|
||||||
|
|
||||||
if (!GL_CheckTexName(name))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// see if already loaded
|
|
||||||
if ((tex = GL_TextureForName(name)))
|
|
||||||
return (tex - dx_textures);
|
|
||||||
|
|
||||||
gEngfuncs.Con_Printf("GL_LoadTexture(%s, %p, %zu, %X)\n", name, buf, size, flags);
|
|
||||||
|
|
||||||
if (FBitSet(flags, TF_NOFLIP_TGA))
|
|
||||||
SetBits(picFlags, IL_DONTFLIP_TGA);
|
|
||||||
|
|
||||||
if (FBitSet(flags, TF_KEEP_SOURCE) && !FBitSet(flags, TF_EXPAND_SOURCE))
|
|
||||||
SetBits(picFlags, IL_KEEP_8BIT);
|
|
||||||
|
|
||||||
// set some image flags
|
|
||||||
gEngfuncs.Image_SetForceFlags(picFlags);
|
|
||||||
|
|
||||||
pic = gEngfuncs.FS_LoadImage(name, buf, size);
|
|
||||||
if (!pic) return 0; // couldn't loading image
|
|
||||||
|
|
||||||
// allocate the new one
|
|
||||||
tex = GL_AllocTexture(name, flags);
|
|
||||||
GL_ProcessImage(tex, pic);
|
|
||||||
|
|
||||||
if (!GL_UploadTexture(tex, pic))
|
|
||||||
{
|
|
||||||
memset(tex, 0, sizeof(dx_texture_t));
|
|
||||||
gEngfuncs.FS_FreeImage(pic); // release source texture
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//GL_ApplyTextureParams(tex); // update texture filter, wrap etc
|
|
||||||
gEngfuncs.FS_FreeImage(pic); // release source texture
|
|
||||||
|
|
||||||
// NOTE: always return texnum as index in array or engine will stop work !!!
|
|
||||||
return tex - dx_textures;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GL_FreeTexture( unsigned int texnum )
|
|
||||||
{
|
|
||||||
if (texnum <= 0 || texnum >= MAX_TEXTURES)
|
|
||||||
return;
|
|
||||||
|
|
||||||
gEngfuncs.Con_Printf("GL_FreeTexture(%d) %s\n", texnum, dx_textures[texnum].name);
|
|
||||||
|
|
||||||
dx_texture_t* tex = R_GetTexture(texnum);
|
|
||||||
if (!tex->dds)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// debug
|
|
||||||
if (!tex->name[0])
|
|
||||||
{
|
|
||||||
gEngfuncs.Con_Printf(S_ERROR "%s: trying to free unnamed texture with handle %X\n", __func__, tex->d3dHandle);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove from hash table
|
|
||||||
dx_texture_t **prev = &dx_texturesHashTable[tex->hashValue];
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
dx_texture_t *cur = *prev;
|
|
||||||
if (!cur) break;
|
|
||||||
|
|
||||||
if (cur == tex)
|
|
||||||
{
|
|
||||||
*prev = cur->nextHash;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
prev = &cur->nextHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO invalidate texture state
|
|
||||||
|
|
||||||
// release source
|
|
||||||
if (tex->original)
|
|
||||||
gEngfuncs.FS_FreeImage(tex->original);
|
|
||||||
|
|
||||||
if (tex->d3dTex)
|
|
||||||
IDirect3DTexture_Release(tex->d3dTex);
|
|
||||||
if (tex->dds)
|
|
||||||
IDirectDrawSurface_Release(tex->dds);
|
|
||||||
memset(tex, 0, sizeof(*tex));
|
|
||||||
}
|
|
||||||
|
|
||||||
void R_OverrideTextureSourceSize( unsigned int textnum, unsigned int srcWidth, unsigned int srcHeight )
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void GL_UpdateTexture( int texnum, int cols, int rows, int width, int height, const byte *buffer, pixformat_t fmt )
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
@@ -1,319 +0,0 @@
|
|||||||
/*
|
|
||||||
r_local.h - renderer local declarations
|
|
||||||
Copyright (C) 2010 Uncle Mike
|
|
||||||
Copyright (C) 2025-2026 lewa_j
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "ref_common.h"
|
|
||||||
#include "ref_api.h"
|
|
||||||
#include "r_frustum.h"
|
|
||||||
#include "ref_params.h"
|
|
||||||
#include "mod_local.h"
|
|
||||||
#include "com_strings.h"
|
|
||||||
#include "pmove.h"
|
|
||||||
|
|
||||||
#define DIRECTDRAW_VERSION 0x0200
|
|
||||||
#define DIRECT3D_VERSION 0x0500//D3DCOLORMODEL bug
|
|
||||||
#include <ddraw.h>
|
|
||||||
#include <d3d.h>
|
|
||||||
|
|
||||||
#define MAX_TEXTURES 8192
|
|
||||||
#define TEXTURES_HASH_SIZE (MAX_TEXTURES >> 2)
|
|
||||||
|
|
||||||
#define MAX_DRAW_STACK 2 // normal view and menu view
|
|
||||||
|
|
||||||
#define CULL_VISIBLE 0 // not culled
|
|
||||||
#define CULL_BACKSIDE 1 // backside of transparent wall
|
|
||||||
#define CULL_FRUSTUM 2 // culled by frustum
|
|
||||||
#define CULL_VISFRAME 3 // culled by PVS
|
|
||||||
#define CULL_OTHER 4 // culled by other reason
|
|
||||||
|
|
||||||
typedef struct dx_texture_s
|
|
||||||
{
|
|
||||||
char name[256]; // game path, including extension (can be store image programs)
|
|
||||||
word srcWidth; // keep unscaled sizes
|
|
||||||
word srcHeight;
|
|
||||||
word width; // upload width\height
|
|
||||||
word height;
|
|
||||||
|
|
||||||
byte numMips; // mipmap count
|
|
||||||
|
|
||||||
int used;
|
|
||||||
texFlags_t flags;
|
|
||||||
rgba_t fogParams; // some water textures
|
|
||||||
// contain info about underwater fog
|
|
||||||
rgbdata_t *original; // keep original image
|
|
||||||
#if 0
|
|
||||||
word depth; // texture depth or count of layers for 2D_ARRAY
|
|
||||||
|
|
||||||
GLuint target; // glTarget
|
|
||||||
GLuint texnum; // gl texture binding
|
|
||||||
GLint format; // uploaded format
|
|
||||||
|
|
||||||
// debug info
|
|
||||||
size_t size; // upload size for debug targets
|
|
||||||
|
|
||||||
// detail textures stuff
|
|
||||||
float xscale;
|
|
||||||
float yscale;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
IDirectDrawSurface *dds;
|
|
||||||
IDirect3DTexture *d3dTex;
|
|
||||||
D3DTEXTUREHANDLE d3dHandle;
|
|
||||||
uint hashValue;
|
|
||||||
struct dx_texture_s *nextHash;
|
|
||||||
} dx_texture_t;
|
|
||||||
|
|
||||||
typedef struct d3dEBContext_s
|
|
||||||
{
|
|
||||||
IDirect3DExecuteBuffer *pd3deb;
|
|
||||||
DWORD bufferSize;
|
|
||||||
void *data;
|
|
||||||
DWORD vertCount;
|
|
||||||
DWORD insOffset;
|
|
||||||
DWORD insLength;
|
|
||||||
} d3dEBContext_t;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
ref_viewpass_t rvp;
|
|
||||||
|
|
||||||
cl_entity_t *currententity;
|
|
||||||
model_t *currentmodel;
|
|
||||||
cl_entity_t *currentbeam; // same as above but for beams
|
|
||||||
|
|
||||||
gl_frustum_t frustum;
|
|
||||||
|
|
||||||
mleaf_t *viewleaf;
|
|
||||||
mleaf_t *oldviewleaf;
|
|
||||||
vec3_t vforward;
|
|
||||||
vec3_t vright;
|
|
||||||
vec3_t vup;
|
|
||||||
|
|
||||||
vec3_t cullorigin;
|
|
||||||
vec3_t cull_vforward;
|
|
||||||
vec3_t cull_vright;
|
|
||||||
vec3_t cull_vup;
|
|
||||||
|
|
||||||
float farClip;
|
|
||||||
|
|
||||||
qboolean fogCustom;
|
|
||||||
qboolean fogEnabled;
|
|
||||||
qboolean fogSkybox;
|
|
||||||
vec4_t fogColor;
|
|
||||||
float fogDensity;
|
|
||||||
float fogStart;
|
|
||||||
float fogEnd;
|
|
||||||
int cached_contents; // in water
|
|
||||||
int cached_waterlevel; // was in water
|
|
||||||
|
|
||||||
float skyMins[2][SKYBOX_MAX_SIDES];
|
|
||||||
float skyMaxs[2][SKYBOX_MAX_SIDES];
|
|
||||||
|
|
||||||
matrix4x4 objectMatrix; // currententity matrix
|
|
||||||
matrix4x4 worldviewMatrix; // modelview for world
|
|
||||||
matrix4x4 modelviewMatrix; // worldviewMatrix * objectMatrix
|
|
||||||
|
|
||||||
matrix4x4 projectionMatrix;
|
|
||||||
matrix4x4 worldviewProjectionMatrix; // worldviewMatrix * projectionMatrix
|
|
||||||
byte visbytes[( MAX_MAP_LEAFS + 7 ) / 8];// actual PVS for current frame
|
|
||||||
|
|
||||||
float viewplanedist;
|
|
||||||
mplane_t clipPlane;
|
|
||||||
} ref_instance_t;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
cl_entity_t *solid_entities[MAX_VISIBLE_PACKET]; // opaque moving or alpha brushes
|
|
||||||
cl_entity_t *trans_entities[MAX_VISIBLE_PACKET]; // translucent brushes
|
|
||||||
cl_entity_t *beam_entities[MAX_VISIBLE_PACKET];
|
|
||||||
uint num_solid_entities;
|
|
||||||
uint num_trans_entities;
|
|
||||||
uint num_beam_entities;
|
|
||||||
} draw_list_t;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int defaultTexture; // use for bad textures
|
|
||||||
int particleTexture;
|
|
||||||
int whiteTexture;
|
|
||||||
int grayTexture;
|
|
||||||
int blackTexture;
|
|
||||||
|
|
||||||
int skytexturenum; // index into model_t::textures
|
|
||||||
|
|
||||||
// entity lists
|
|
||||||
draw_list_t draw_stack[MAX_DRAW_STACK];
|
|
||||||
int draw_stack_pos;
|
|
||||||
draw_list_t *draw_list;
|
|
||||||
|
|
||||||
// matrix states
|
|
||||||
qboolean modelviewIdentity;
|
|
||||||
|
|
||||||
int visframecount; // PVS frame
|
|
||||||
int dlightframecount; // dynamic light frame
|
|
||||||
int realframecount; // not including viewpasses
|
|
||||||
int framecount;
|
|
||||||
|
|
||||||
qboolean fCustomRendering;
|
|
||||||
qboolean fResetVis;
|
|
||||||
|
|
||||||
double frametime; // special frametime for multipass rendering (will set to 0 on a nextview)
|
|
||||||
float blend; // global blend value
|
|
||||||
|
|
||||||
// cull info
|
|
||||||
vec3_t modelorg; // relative to viewpoint
|
|
||||||
|
|
||||||
// get from engine
|
|
||||||
model_t *worldmodel;
|
|
||||||
world_static_t *world;
|
|
||||||
cl_entity_t *entities;
|
|
||||||
cl_entity_t *viewent;
|
|
||||||
|
|
||||||
uint max_entities;
|
|
||||||
|
|
||||||
ref_screen_rotation_t rotation;
|
|
||||||
} dx_globals_t;
|
|
||||||
|
|
||||||
struct dx_context_s
|
|
||||||
{
|
|
||||||
HWND window;
|
|
||||||
int windowWidth;
|
|
||||||
int windowHeight;
|
|
||||||
IDirectDraw *pdd;
|
|
||||||
IDirectDrawSurface *pddsPrimary;
|
|
||||||
IDirectDrawSurface *pddsBack;
|
|
||||||
IDirectDrawSurface *pddsZBuffer;
|
|
||||||
IDirectDrawClipper *pddClipper;
|
|
||||||
IDirectDrawClipper *pddBackClipper;
|
|
||||||
IDirect3D *pd3d;
|
|
||||||
IDirect3DDevice *pd3dd;
|
|
||||||
IDirect3DExecuteBuffer *pd3deb;
|
|
||||||
IDirect3DViewport *viewport;
|
|
||||||
D3DMATRIXHANDLE mtxWorld;
|
|
||||||
D3DMATRIXHANDLE mtxProjection;
|
|
||||||
|
|
||||||
qboolean in2DMode;
|
|
||||||
int renderMode;
|
|
||||||
vec4_t currentColor;
|
|
||||||
D3DTEXTUREHANDLE currentTexture;
|
|
||||||
D3DTEXTUREHANDLE lastBoundTexture;
|
|
||||||
};
|
|
||||||
typedef struct dx_context_s dx_context_t;
|
|
||||||
|
|
||||||
extern ref_instance_t RI;
|
|
||||||
extern dx_globals_t tr;
|
|
||||||
extern dx_context_t dxc;
|
|
||||||
|
|
||||||
|
|
||||||
static inline cl_entity_t *CL_GetEntityByIndex( int index )
|
|
||||||
{
|
|
||||||
if( unlikely( index < 0 || index >= tr.max_entities || !tr.entities ))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return &tr.entities[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline model_t *CL_ModelHandle( int index )
|
|
||||||
{
|
|
||||||
if( unlikely( index < 0 || index >= gp_cl->nummodels ))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return gp_cl->models[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *dxResultToStr( HRESULT r );
|
|
||||||
|
|
||||||
#define DXCheckRet(DST, CALL) \
|
|
||||||
(DST) = (CALL);\
|
|
||||||
if ((DST) != DD_OK)\
|
|
||||||
gEngfuncs.Con_Printf( S_ERROR "%s():%s:%d: DirectX error %X(%d 0x%X %d) %s at \"" #CALL "\"\n", __FUNCTION__, __FILE__, __LINE__, (DST), ( (DST) >> 31 ) & 1, ( (DST) >> 16 ) & 0x7FFF, (DST) & 0xFFFF, dxResultToStr( r ));
|
|
||||||
|
|
||||||
#define DXCheck(CALL) \
|
|
||||||
{\
|
|
||||||
HRESULT r = DD_OK;\
|
|
||||||
DXCheckRet(r, CALL)\
|
|
||||||
}
|
|
||||||
|
|
||||||
void GL_SetRenderMode( int mode );
|
|
||||||
void GL_Bind( int tmu, unsigned int texnum );
|
|
||||||
|
|
||||||
// r_d3d.c
|
|
||||||
qboolean R_Init( void );
|
|
||||||
void R_Shutdown( void );
|
|
||||||
void GL_SetupAttributes( int safegl );
|
|
||||||
void GL_InitExtensions( void );
|
|
||||||
void GL_ClearExtensions( void );
|
|
||||||
void D3D_Resize( int width, int height );
|
|
||||||
qboolean D3D_StartExecuteBuffer( d3dEBContext_t *ctx );
|
|
||||||
qboolean D3D_EndExecuteBuffer( d3dEBContext_t *ctx );
|
|
||||||
void D3D_ReleaseExecuteBuffer( d3dEBContext_t *ctx );
|
|
||||||
void D3D_SetVertTL( D3DTLVERTEX *v, float x, float y, float z, float w, float tu, float tv );
|
|
||||||
void D3D_SetTri( D3DTRIANGLE *t, int v1, int v2, int v3 );
|
|
||||||
void D3D_PutInstruction( void **dst, BYTE opcode, BYTE size, WORD count );
|
|
||||||
void D3D_PutProcessVertices( void **dst, DWORD flags, WORD start, WORD count );
|
|
||||||
void D3D_PutRenderState( void **dst, D3DRENDERSTATETYPE type, DWORD arg );
|
|
||||||
void D3D_PutTransformState( void **dst, D3DTRANSFORMSTATETYPE type, DWORD arg );
|
|
||||||
|
|
||||||
// r_main.c
|
|
||||||
void R_GammaChanged( qboolean do_reset_gamma );
|
|
||||||
void R_BeginFrame( qboolean clearScene );
|
|
||||||
void R_RenderScene( void );
|
|
||||||
void R_EndFrame( void );
|
|
||||||
void R_AllowFog( qboolean allowed );
|
|
||||||
void R_RenderFrame( const struct ref_viewpass_s *rvp );
|
|
||||||
qboolean R_AddEntity( struct cl_entity_s *clent, int type );
|
|
||||||
void R_ClearScene( void );
|
|
||||||
int WorldToScreen( const vec3_t world, vec3_t screen );
|
|
||||||
void R_LoadIdentity( void );
|
|
||||||
void R_SetupD3D( qboolean set_state );
|
|
||||||
|
|
||||||
// r_draw.c
|
|
||||||
void R_Set2DMode( qboolean enable );
|
|
||||||
void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, int texnum );
|
|
||||||
void FillRGBA( int rendermode, float x, float y, float w, float h, byte r, byte g, byte b, byte a );
|
|
||||||
|
|
||||||
// r_image.c
|
|
||||||
void R_InitImages( void );
|
|
||||||
dx_texture_t *R_GetTexture( unsigned int texnum );
|
|
||||||
void R_ShowTextures( void );
|
|
||||||
const byte *R_GetTextureOriginalBuffer( unsigned int idx );
|
|
||||||
int GL_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update );
|
|
||||||
void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor );
|
|
||||||
void R_GetDetailScaleForTexture( int texture, float *xScale, float *yScale );
|
|
||||||
void R_SetDetailScaleForTexture( int texture, float xScale, float yScale );
|
|
||||||
int GL_FindTexture( const char *name );
|
|
||||||
const char *GL_TextureName( unsigned int texnum );
|
|
||||||
const byte *GL_TextureData( unsigned int texnum );
|
|
||||||
int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags );
|
|
||||||
int GL_CreateTexture( const char *name, int width, int height, const void *buffer, texFlags_t flags );
|
|
||||||
void GL_FreeTexture( unsigned int texnum );
|
|
||||||
void R_OverrideTextureSourceSize( unsigned int textnum, unsigned int srcWidth, unsigned int srcHeight );
|
|
||||||
void GL_UpdateTexture( int texnum, int cols, int rows, int width, int height, const byte *buffer, pixformat_t fmt );
|
|
||||||
|
|
||||||
// r_surf.c
|
|
||||||
void GL_SubdivideSurface( model_t *mod, msurface_t *fa );
|
|
||||||
void GL_OrthoBounds( const float *mins, const float *maxs );
|
|
||||||
byte *Mod_GetCurrentVis( void );
|
|
||||||
void R_DrawWorld( void );
|
|
||||||
void R_MarkLeaves( void );
|
|
||||||
void GL_BuildLightmaps( void );
|
|
||||||
|
|
||||||
extern convar_t r_novis;
|
|
||||||
extern convar_t r_nocull;
|
|
||||||
extern convar_t r_lockpvs;
|
|
||||||
extern convar_t r_lockfrustum;
|
|
||||||
|
|
||||||
380
ref/dx2/r_main.c
380
ref/dx2/r_main.c
@@ -1,380 +0,0 @@
|
|||||||
/*
|
|
||||||
r_main.c -- dx2 renderer main loop
|
|
||||||
Copyright (C) 2010 Uncle Mike
|
|
||||||
Copyright (C) 2025-2026 lewa_j
|
|
||||||
|
|
||||||
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 "r_local.h"
|
|
||||||
#include "ref_params.h"
|
|
||||||
#include "xash3d_mathlib.h"
|
|
||||||
|
|
||||||
ref_instance_t RI;
|
|
||||||
|
|
||||||
static void R_Clear( int bitMask )
|
|
||||||
{
|
|
||||||
int bits = D3DCLEAR_ZBUFFER;
|
|
||||||
//bits &= bitMask;
|
|
||||||
|
|
||||||
D3DRECT rect = {
|
|
||||||
.x1 = 0,
|
|
||||||
.y1 = 0,
|
|
||||||
.x2 = dxc.windowWidth,
|
|
||||||
.y2 = dxc.windowHeight,
|
|
||||||
};
|
|
||||||
DXCheck(IDirect3DViewport_Clear(dxc.viewport, 1, &rect, bits));
|
|
||||||
}
|
|
||||||
|
|
||||||
static float R_GetFarClip( void )
|
|
||||||
{
|
|
||||||
if( tr.worldmodel && FBitSet( RI.rvp.flags, RF_DRAW_WORLD ) )
|
|
||||||
return gp_movevars->zmax * 1.73f;
|
|
||||||
|
|
||||||
return 2048.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void R_SetupFrustum( void )
|
|
||||||
{
|
|
||||||
// build the transformation matrix for the given view angles
|
|
||||||
AngleVectors( RI.rvp.viewangles, RI.vforward, RI.vright, RI.vup );
|
|
||||||
|
|
||||||
if( !r_lockfrustum.value )
|
|
||||||
{
|
|
||||||
VectorCopy( RI.rvp.vieworigin, RI.cullorigin );
|
|
||||||
VectorCopy( RI.vforward, RI.cull_vforward );
|
|
||||||
VectorCopy( RI.vright, RI.cull_vright );
|
|
||||||
VectorCopy( RI.vup, RI.cull_vup );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( FBitSet( RI.rvp.flags, RF_DRAW_OVERVIEW ))
|
|
||||||
{
|
|
||||||
const ref_overview_t *ov = gEngfuncs.GetOverviewParms();
|
|
||||||
GL_FrustumInitOrtho( &RI.frustum, ov->xLeft, ov->xRight, ov->yTop, ov->yBottom, ov->zNear, ov->zFar );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GL_FrustumInitProj( &RI.frustum, 0.0f, R_GetFarClip(), RI.rvp.fov_x, RI.rvp.fov_y ); // NOTE: we ignore nearplane here (mirrors only)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void R_SetupProjectionMatrix( matrix4x4 m )
|
|
||||||
{
|
|
||||||
float xMin, xMax, yMin, yMax, zNear, zFar;
|
|
||||||
|
|
||||||
if( FBitSet( RI.rvp.flags, RF_DRAW_OVERVIEW ))
|
|
||||||
{
|
|
||||||
const ref_overview_t *ov = gEngfuncs.GetOverviewParms();
|
|
||||||
Matrix4x4_CreateOrtho( m, ov->xLeft, ov->xRight, ov->yTop, ov->yBottom, ov->zNear, ov->zFar );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RI.farClip = R_GetFarClip();
|
|
||||||
|
|
||||||
zNear = 4.0f;
|
|
||||||
zFar = Q_max( 256.0f, RI.farClip );
|
|
||||||
|
|
||||||
yMax = zNear * tan( RI.rvp.fov_y * M_PI_F / 360.0f );
|
|
||||||
yMin = -yMax;
|
|
||||||
|
|
||||||
xMax = zNear * tan( RI.rvp.fov_x * M_PI_F / 360.0f );
|
|
||||||
xMin = -xMax;
|
|
||||||
|
|
||||||
if( tr.rotation & 1 )
|
|
||||||
{
|
|
||||||
Matrix4x4_CreateProjection( m, yMax, yMin, xMax, xMin, zNear, zFar );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Matrix4x4_CreateProjection( m, xMax, xMin, yMax, yMin, zNear, zFar );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
=============
|
|
||||||
R_SetupModelviewMatrix
|
|
||||||
=============
|
|
||||||
*/
|
|
||||||
static void R_SetupModelviewMatrix( matrix4x4 m )
|
|
||||||
{
|
|
||||||
Matrix4x4_CreateModelview( m );
|
|
||||||
if( tr.rotation & 1 )
|
|
||||||
{
|
|
||||||
Matrix4x4_ConcatRotate( m, anglemod( -RI.rvp.viewangles[2] + 90 ), 1, 0, 0 );
|
|
||||||
Matrix4x4_ConcatRotate( m, -RI.rvp.viewangles[0], 0, 1, 0 );
|
|
||||||
Matrix4x4_ConcatRotate( m, -RI.rvp.viewangles[1], 0, 0, 1 );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Matrix4x4_ConcatRotate( m, -RI.rvp.viewangles[2], 1, 0, 0 );
|
|
||||||
Matrix4x4_ConcatRotate( m, -RI.rvp.viewangles[0], 0, 1, 0 );
|
|
||||||
Matrix4x4_ConcatRotate( m, -RI.rvp.viewangles[1], 0, 0, 1 );
|
|
||||||
}
|
|
||||||
Matrix4x4_ConcatTranslate( m, -RI.rvp.vieworigin[0], -RI.rvp.vieworigin[1], -RI.rvp.vieworigin[2] );
|
|
||||||
}
|
|
||||||
|
|
||||||
void R_LoadIdentity( void )
|
|
||||||
{
|
|
||||||
if( tr.modelviewIdentity ) return;
|
|
||||||
|
|
||||||
Matrix4x4_LoadIdentity( RI.objectMatrix );
|
|
||||||
Matrix4x4_Copy( RI.modelviewMatrix, RI.worldviewMatrix );
|
|
||||||
|
|
||||||
//TODO GL_LoadMatrix( MODELVIEW, RI.modelviewMatrix );
|
|
||||||
tr.modelviewIdentity = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void R_GammaChanged( qboolean do_reset_gamma )
|
|
||||||
{
|
|
||||||
if( do_reset_gamma )
|
|
||||||
{
|
|
||||||
// paranoia cubemap rendering
|
|
||||||
if( gEngfuncs.drawFuncs->GL_BuildLightmaps )
|
|
||||||
gEngfuncs.drawFuncs->GL_BuildLightmaps( );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//GL_RebuildLightmaps();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void R_BeginFrame( qboolean clearScene )
|
|
||||||
{
|
|
||||||
if(( gl_clear->value || ENGINE_GET_PARM( PARM_DEV_OVERVIEW )) &&
|
|
||||||
clearScene && ENGINE_GET_PARM( PARM_CONNSTATE ) != ca_cinematic )
|
|
||||||
{
|
|
||||||
D3DRECT rect = {
|
|
||||||
.x1 = 0,
|
|
||||||
.y1 = 0,
|
|
||||||
.x2 = dxc.windowWidth,
|
|
||||||
.y2 = dxc.windowHeight,
|
|
||||||
};
|
|
||||||
DXCheck(IDirect3DViewport_Clear(dxc.viewport, 1, &rect, D3DCLEAR_TARGET));
|
|
||||||
}
|
|
||||||
|
|
||||||
R_Set2DMode( true );
|
|
||||||
|
|
||||||
gEngfuncs.CL_ExtraUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void R_DrawEntitiesOnList( void )
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void R_RenderScene( void )
|
|
||||||
{
|
|
||||||
if( !tr.worldmodel && FBitSet( RI.rvp.flags, RF_DRAW_WORLD ) )
|
|
||||||
gEngfuncs.Host_Error("%s: NULL worldmodel\n", __func__);
|
|
||||||
|
|
||||||
// frametime is valid only for normal pass
|
|
||||||
if( !FBitSet( RI.rvp.flags, RF_DRAW_CUBEMAP ))
|
|
||||||
tr.frametime = gp_cl->time - gp_cl->oldtime;
|
|
||||||
else tr.frametime = 0.0;
|
|
||||||
|
|
||||||
// begin a new frame
|
|
||||||
tr.framecount++;
|
|
||||||
|
|
||||||
tr.dlightframecount = R_PushDlights( tr.worldmodel, tr.framecount );
|
|
||||||
|
|
||||||
R_SetupFrustum();
|
|
||||||
#if 0
|
|
||||||
R_SetupFrame();
|
|
||||||
#endif
|
|
||||||
R_SetupD3D(true);
|
|
||||||
R_Clear(~0);
|
|
||||||
R_MarkLeaves();
|
|
||||||
#if 0
|
|
||||||
R_DrawFog();
|
|
||||||
if( FBitSet( RI.rvp.flags, RF_DRAW_WORLD ))
|
|
||||||
R_AnimateRipples();
|
|
||||||
|
|
||||||
R_CheckGLFog();
|
|
||||||
#endif
|
|
||||||
R_DrawWorld();
|
|
||||||
|
|
||||||
// R_CheckFog();
|
|
||||||
|
|
||||||
gEngfuncs.CL_ExtraUpdate(); // don't let sound get messed up if going slow
|
|
||||||
|
|
||||||
R_DrawEntitiesOnList();
|
|
||||||
|
|
||||||
// R_DrawWaterSurfaces();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void R_EndFrame( void )
|
|
||||||
{
|
|
||||||
|
|
||||||
if (!dxc.window)
|
|
||||||
return;
|
|
||||||
|
|
||||||
R_Set2DMode( false );
|
|
||||||
|
|
||||||
//swap
|
|
||||||
if (dxc.pddsBack)
|
|
||||||
{
|
|
||||||
RECT dstRect = { 0 };
|
|
||||||
POINT point = { 0,0 };
|
|
||||||
ClientToScreen(dxc.window, &point);
|
|
||||||
GetClientRect(dxc.window, &dstRect);
|
|
||||||
OffsetRect(&dstRect, point.x, point.y);
|
|
||||||
|
|
||||||
RECT srcRect = { 0,0,dxc.windowWidth,dxc.windowHeight };
|
|
||||||
DXCheck(IDirectDrawSurface_Blt(dxc.pddsPrimary, &dstRect, dxc.pddsBack, &srcRect, DDBLT_WAIT, NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
//resize
|
|
||||||
RECT rect = { 0 };
|
|
||||||
GetClientRect(dxc.window, &rect);
|
|
||||||
int w = rect.right - rect.left;
|
|
||||||
int h = rect.bottom - rect.top;
|
|
||||||
|
|
||||||
if (w != dxc.windowWidth || h != dxc.windowHeight)
|
|
||||||
{
|
|
||||||
D3D_Resize(w, h);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void R_AllowFog( qboolean allowed )
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void R_SetupRefParams( const ref_viewpass_t *rvp )
|
|
||||||
{
|
|
||||||
RI.rvp = *rvp;
|
|
||||||
|
|
||||||
RI.farClip = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void R_RenderFrame( const ref_viewpass_t *rvp )
|
|
||||||
{
|
|
||||||
if( r_norefresh->value )
|
|
||||||
return;
|
|
||||||
|
|
||||||
// setup the initial render params
|
|
||||||
R_SetupRefParams( rvp );
|
|
||||||
|
|
||||||
// completely override rendering
|
|
||||||
if( gEngfuncs.drawFuncs->GL_RenderFrame != NULL )
|
|
||||||
{
|
|
||||||
tr.fCustomRendering = true;
|
|
||||||
|
|
||||||
if( gEngfuncs.drawFuncs->GL_RenderFrame( rvp ))
|
|
||||||
{
|
|
||||||
R_GatherPlayerLight( tr.viewent );
|
|
||||||
tr.realframecount++;
|
|
||||||
tr.fResetVis = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tr.fCustomRendering = false;
|
|
||||||
#if 0
|
|
||||||
if( !FBitSet( RI.rvp.flags, RF_ONLY_CLIENTDRAW ))
|
|
||||||
R_RunViewmodelEvents();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
tr.realframecount++; // right called after viewmodel events
|
|
||||||
R_RenderScene();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
qboolean R_AddEntity( struct cl_entity_s *clent, int type )
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void R_ClearScene( void )
|
|
||||||
{
|
|
||||||
tr.draw_list->num_solid_entities = 0;
|
|
||||||
tr.draw_list->num_trans_entities = 0;
|
|
||||||
tr.draw_list->num_beam_entities = 0;
|
|
||||||
|
|
||||||
// clear the scene befor start new frame
|
|
||||||
if (gEngfuncs.drawFuncs->R_ClearScene != NULL)
|
|
||||||
gEngfuncs.drawFuncs->R_ClearScene();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int WorldToScreen( const vec3_t world, vec3_t screen )
|
|
||||||
{
|
|
||||||
VectorClear( screen );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void R_SetupD3D( qboolean set_state )
|
|
||||||
{
|
|
||||||
R_SetupModelviewMatrix( RI.worldviewMatrix );
|
|
||||||
R_SetupProjectionMatrix( RI.projectionMatrix );
|
|
||||||
|
|
||||||
Matrix4x4_Concat( RI.worldviewProjectionMatrix, RI.projectionMatrix, RI.worldviewMatrix );
|
|
||||||
|
|
||||||
if( !set_state ) return;
|
|
||||||
|
|
||||||
D3DVIEWPORT viewport = { 0 };
|
|
||||||
viewport.dwSize = sizeof(viewport);
|
|
||||||
|
|
||||||
if( !FBitSet( RI.rvp.flags, RF_DRAW_CUBEMAP ))
|
|
||||||
{
|
|
||||||
int x, x2, y, y2;
|
|
||||||
|
|
||||||
// set up viewport (main, playersetup)
|
|
||||||
x = floor( RI.rvp.viewport[0] * gpGlobals->width / gpGlobals->width );
|
|
||||||
x2 = ceil( (RI.rvp.viewport[0] + RI.rvp.viewport[2]) * gpGlobals->width / gpGlobals->width );
|
|
||||||
y = floor( gpGlobals->height - RI.rvp.viewport[1] * gpGlobals->height / gpGlobals->height );
|
|
||||||
y2 = ceil( gpGlobals->height - (RI.rvp.viewport[1] + RI.rvp.viewport[3]) * gpGlobals->height / gpGlobals->height );
|
|
||||||
|
|
||||||
if( tr.rotation & 1 )
|
|
||||||
{
|
|
||||||
viewport.dwX = y2;
|
|
||||||
viewport.dwY = x;
|
|
||||||
viewport.dwWidth = y - y2;
|
|
||||||
viewport.dwHeight = x2 - x;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
viewport.dwX = x;
|
|
||||||
viewport.dwY = y2;
|
|
||||||
viewport.dwWidth = x2 - x;
|
|
||||||
viewport.dwHeight = y - y2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// envpass, mirrorpass
|
|
||||||
viewport.dwX = RI.rvp.viewport[0];
|
|
||||||
viewport.dwY = RI.rvp.viewport[1];
|
|
||||||
viewport.dwWidth = RI.rvp.viewport[2];
|
|
||||||
viewport.dwHeight = RI.rvp.viewport[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
viewport.dvScaleX = 0.5f * viewport.dwWidth;
|
|
||||||
viewport.dvScaleY = 0.5f * viewport.dwHeight;
|
|
||||||
viewport.dvMaxX = 1;//calc for partial views
|
|
||||||
viewport.dvMaxY = 1;
|
|
||||||
viewport.dvMinZ = 0;
|
|
||||||
viewport.dvMaxZ = 1;
|
|
||||||
DXCheck(IDirect3DViewport_SetViewport(dxc.viewport, &viewport));
|
|
||||||
|
|
||||||
{
|
|
||||||
float dest[16];
|
|
||||||
Matrix4x4_ToArrayFloatGL(RI.projectionMatrix, dest);
|
|
||||||
DXCheck(IDirect3DDevice_SetMatrix(dxc.pd3dd, dxc.mtxProjection, (D3DMATRIX *)&dest));
|
|
||||||
Matrix4x4_ToArrayFloatGL(RI.worldviewMatrix, dest);
|
|
||||||
DXCheck(IDirect3DDevice_SetMatrix(dxc.pd3dd, dxc.mtxWorld, (D3DMATRIX *)&dest));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
625
ref/dx2/r_surf.c
625
ref/dx2/r_surf.c
@@ -1,625 +0,0 @@
|
|||||||
/*
|
|
||||||
r_surf.c - surface-related refresh code
|
|
||||||
Copyright (C) 2025-2026 lewa_j
|
|
||||||
|
|
||||||
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 "r_local.h"
|
|
||||||
#include "xash3d_mathlib.h"
|
|
||||||
|
|
||||||
|
|
||||||
void GL_OrthoBounds( const float *mins, const float *maxs )
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte *Mod_GetCurrentVis( void )
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void R_LightmapCoord( const vec3_t v, const msurface_t *surf, const float sample_size, vec2_t coords )
|
|
||||||
{
|
|
||||||
const mextrasurf_t *info = surf->info;
|
|
||||||
float s, t;
|
|
||||||
|
|
||||||
#define BLOCK_SIZE 256
|
|
||||||
|
|
||||||
s = DotProduct( v, info->lmvecs[0] ) + info->lmvecs[0][3] - info->lightmapmins[0];
|
|
||||||
s += surf->light_s * sample_size;
|
|
||||||
s += sample_size * 0.5f;
|
|
||||||
s /= BLOCK_SIZE * sample_size;
|
|
||||||
|
|
||||||
t = DotProduct( v, info->lmvecs[1] ) + info->lmvecs[1][3] - info->lightmapmins[1];
|
|
||||||
t += surf->light_t * sample_size;
|
|
||||||
t += sample_size * 0.5f;
|
|
||||||
t /= BLOCK_SIZE * sample_size;
|
|
||||||
|
|
||||||
#undef BLOCK_SIZE
|
|
||||||
|
|
||||||
Vector2Set( coords, s, t );
|
|
||||||
}
|
|
||||||
|
|
||||||
static void R_TextureCoord( const vec3_t v, const msurface_t *surf, vec2_t coords )
|
|
||||||
{
|
|
||||||
const mtexinfo_t *info = surf->texinfo;
|
|
||||||
float s, t;
|
|
||||||
|
|
||||||
s = DotProduct( v, info->vecs[0] );
|
|
||||||
t = DotProduct( v, info->vecs[1] );
|
|
||||||
|
|
||||||
if( !FBitSet( surf->flags, SURF_DRAWTURB ))
|
|
||||||
{
|
|
||||||
s = ( s + info->vecs[0][3] ) / info->texture->width;
|
|
||||||
t = ( t + info->vecs[1][3] ) / info->texture->height;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2Set( coords, s, t );
|
|
||||||
}
|
|
||||||
|
|
||||||
static void R_GetEdgePosition( const model_t *mod, const msurface_t *fa, int i, vec3_t vec )
|
|
||||||
{
|
|
||||||
const int lindex = mod->surfedges[fa->firstedge + i];
|
|
||||||
|
|
||||||
if( FBitSet( mod->flags, MODEL_QBSP2 ))
|
|
||||||
{
|
|
||||||
const medge32_t *pedges = mod->edges32;
|
|
||||||
|
|
||||||
if( lindex > 0 )
|
|
||||||
VectorCopy( mod->vertexes[pedges[lindex].v[0]].position, vec );
|
|
||||||
else
|
|
||||||
VectorCopy( mod->vertexes[pedges[-lindex].v[1]].position, vec );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const medge16_t *pedges = mod->edges16;
|
|
||||||
|
|
||||||
if( lindex > 0 )
|
|
||||||
VectorCopy( mod->vertexes[pedges[lindex].v[0]].position, vec );
|
|
||||||
else
|
|
||||||
VectorCopy( mod->vertexes[pedges[-lindex].v[1]].position, vec );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GL_SubdivideSurface( model_t *mod, msurface_t *fa )
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
GL_BuildPolygonFromSurface
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
static int GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa )
|
|
||||||
{
|
|
||||||
int i, lnumverts, nColinElim = 0;
|
|
||||||
float sample_size;
|
|
||||||
texture_t *tex;
|
|
||||||
dx_texture_t *dxt;
|
|
||||||
glpoly2_t *poly;
|
|
||||||
|
|
||||||
if( !mod || !fa->texinfo || !fa->texinfo->texture )
|
|
||||||
return nColinElim; // bad polygon ?
|
|
||||||
|
|
||||||
if( FBitSet( fa->flags, SURF_CONVEYOR ) && fa->texinfo->texture->gl_texturenum != 0 )
|
|
||||||
{
|
|
||||||
dxt = R_GetTexture( fa->texinfo->texture->gl_texturenum );
|
|
||||||
tex = fa->texinfo->texture;
|
|
||||||
Assert( dxt != NULL && tex != NULL );
|
|
||||||
|
|
||||||
// update conveyor widths for keep properly speed of scrolling
|
|
||||||
dxt->srcWidth = tex->width;
|
|
||||||
dxt->srcHeight = tex->height;
|
|
||||||
}
|
|
||||||
|
|
||||||
sample_size = gEngfuncs.Mod_SampleSizeForFace( fa );
|
|
||||||
|
|
||||||
// reconstruct the polygon
|
|
||||||
lnumverts = fa->numedges;
|
|
||||||
|
|
||||||
// detach if already created, reconstruct again
|
|
||||||
poly = fa->polys;
|
|
||||||
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( glpoly2_t ) + lnumverts * VERTEXSIZE * sizeof( float ));
|
|
||||||
poly->next = fa->polys;
|
|
||||||
poly->flags = fa->flags;
|
|
||||||
fa->polys = poly;
|
|
||||||
poly->numverts = lnumverts;
|
|
||||||
|
|
||||||
for( i = 0; i < lnumverts; i++ )
|
|
||||||
{
|
|
||||||
R_GetEdgePosition( mod, fa, i, poly->verts[i] );
|
|
||||||
R_TextureCoord( poly->verts[i], fa, &poly->verts[i][3] );
|
|
||||||
R_LightmapCoord( poly->verts[i], fa, sample_size, &poly->verts[i][5] );
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO or not TODO gl_keeptjunctions?
|
|
||||||
|
|
||||||
poly->numverts = lnumverts;
|
|
||||||
return nColinElim;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
===============
|
|
||||||
R_TextureAnimation
|
|
||||||
|
|
||||||
Returns the proper texture for a given time and surface
|
|
||||||
===============
|
|
||||||
*/
|
|
||||||
static texture_t *R_TextureAnimation( msurface_t *s )
|
|
||||||
{
|
|
||||||
texture_t *base = s->texinfo->texture;
|
|
||||||
// TODO
|
|
||||||
return base;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void DrawGLPoly( glpoly2_t *p, float xScale, float yScale )
|
|
||||||
{
|
|
||||||
float *v;
|
|
||||||
float sOffset, sy;
|
|
||||||
float tOffset, cy;
|
|
||||||
cl_entity_t *e = RI.currententity;
|
|
||||||
int i, hasScale = false;
|
|
||||||
|
|
||||||
if( !p ) return;
|
|
||||||
|
|
||||||
{
|
|
||||||
sOffset = tOffset = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( xScale != 0.0f && yScale != 0.0f )
|
|
||||||
hasScale = true;
|
|
||||||
|
|
||||||
d3dEBContext_t ebc = { 0 };
|
|
||||||
if( !D3D_StartExecuteBuffer( &ebc ))
|
|
||||||
return;
|
|
||||||
|
|
||||||
void *cur = ebc.data;
|
|
||||||
|
|
||||||
D3DLVERTEX* verts = (D3DLVERTEX*)cur;
|
|
||||||
|
|
||||||
for( i = 0, v = p->verts[0]; i < p->numverts; i++, v += VERTEXSIZE )
|
|
||||||
{
|
|
||||||
D3DLVERTEX *dv = verts + i;
|
|
||||||
if( hasScale )
|
|
||||||
{
|
|
||||||
dv->tu = ( v[3] + sOffset ) * xScale;
|
|
||||||
dv->tv = ( v[4] + tOffset ) * yScale;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dv->tu = v[3] + sOffset;
|
|
||||||
dv->tv = v[4] + tOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
dv->x = v[0];
|
|
||||||
dv->y = v[1];
|
|
||||||
dv->z = v[2];
|
|
||||||
dv->color = 0xFFFFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
cur = (void*)(((D3DTLVERTEX*)cur) + p->numverts);
|
|
||||||
|
|
||||||
void* insStart = cur;
|
|
||||||
|
|
||||||
D3D_PutProcessVertices(&cur, D3DPROCESSVERTICES_TRANSFORM | D3DPROCESSVERTICES_UPDATEEXTENTS, 0, p->numverts);
|
|
||||||
|
|
||||||
D3D_PutInstruction(&cur, D3DOP_STATERENDER, sizeof(D3DSTATE), 4);
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_TEXTUREHANDLE, dxc.currentTexture);
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_DECAL);
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_BLENDENABLE, FALSE);
|
|
||||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_ALPHATESTENABLE, FALSE);
|
|
||||||
|
|
||||||
// align
|
|
||||||
if (((ULONG)cur) & 7) {
|
|
||||||
D3D_PutInstruction(&cur, D3DOP_TRIANGLE, sizeof(D3DTRIANGLE), 0);
|
|
||||||
}
|
|
||||||
D3D_PutInstruction(&cur, D3DOP_TRIANGLE, sizeof(D3DTRIANGLE), p->numverts - 2);
|
|
||||||
|
|
||||||
for (i = 0; i < p->numverts; i++)
|
|
||||||
{
|
|
||||||
D3D_SetTri(cur, 0, i + 1, i + 2);
|
|
||||||
cur = (void*)(((D3DTRIANGLE*)cur) + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D_PutInstruction(&cur, D3DOP_EXIT, 0, 0);
|
|
||||||
|
|
||||||
ebc.vertCount = p->numverts;
|
|
||||||
ebc.insOffset = ((char*)insStart - (char*)ebc.data);
|
|
||||||
ebc.insLength = ((char*)cur - (char*)insStart);
|
|
||||||
|
|
||||||
if( !D3D_EndExecuteBuffer( &ebc ))
|
|
||||||
return;
|
|
||||||
|
|
||||||
DXCheck(IDirect3DDevice_BeginScene(dxc.pd3dd));
|
|
||||||
DXCheck(IDirect3DDevice_Execute(dxc.pd3dd, ebc.pd3deb, dxc.viewport, D3DEXECUTE_CLIPPED));
|
|
||||||
DXCheck(IDirect3DDevice_EndScene(dxc.pd3dd));
|
|
||||||
|
|
||||||
D3D_ReleaseExecuteBuffer( &ebc );
|
|
||||||
//
|
|
||||||
|
|
||||||
//if( FBitSet( p->flags, SURF_DRAWTILED ))
|
|
||||||
// GL_SetupFogColorForSurfaces();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void R_RenderBrushPoly( msurface_t *fa, int cull_type )
|
|
||||||
{
|
|
||||||
texture_t *t;
|
|
||||||
|
|
||||||
//r_stats.c_world_polys++;
|
|
||||||
|
|
||||||
if( fa->flags & SURF_DRAWSKY )
|
|
||||||
return; // already handled
|
|
||||||
|
|
||||||
t = R_TextureAnimation( fa );
|
|
||||||
|
|
||||||
GL_Bind( XASH_TEXTURE0, t->gl_texturenum );
|
|
||||||
|
|
||||||
DrawGLPoly( fa->polys, 0.0f, 0.0f );
|
|
||||||
}
|
|
||||||
|
|
||||||
static void R_DrawTextureChains( void )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
msurface_t *s;
|
|
||||||
texture_t *t;
|
|
||||||
|
|
||||||
// make sure what color is reset
|
|
||||||
Vector4Set( dxc.currentColor, 1, 1, 1, 1 );
|
|
||||||
R_LoadIdentity(); // set identity matrix
|
|
||||||
|
|
||||||
//GL_SetupFogColorForSurfaces();
|
|
||||||
|
|
||||||
// restore worldmodel
|
|
||||||
RI.currententity = CL_GetEntityByIndex( 0 );
|
|
||||||
RI.currentmodel = RI.currententity->model;
|
|
||||||
|
|
||||||
for( i = 0; i < tr.worldmodel->numtextures; i++ )
|
|
||||||
{
|
|
||||||
t = tr.worldmodel->textures[i];
|
|
||||||
if( !t ) continue;
|
|
||||||
|
|
||||||
s = t->texturechain;
|
|
||||||
|
|
||||||
if( !s || ( i == tr.skytexturenum ))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for( ; s != NULL; s = s->texturechain )
|
|
||||||
R_RenderBrushPoly( s, CULL_VISIBLE );
|
|
||||||
t->texturechain = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
=================
|
|
||||||
R_CullSurface
|
|
||||||
|
|
||||||
cull invisible surfaces
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
static int R_CullSurface( msurface_t *surf, gl_frustum_t *frustum, uint clipflags )
|
|
||||||
{
|
|
||||||
cl_entity_t *e = RI.currententity;
|
|
||||||
|
|
||||||
if( !surf || !surf->texinfo || !surf->texinfo->texture )
|
|
||||||
return CULL_OTHER;
|
|
||||||
|
|
||||||
//TODO
|
|
||||||
return CULL_VISIBLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void R_RecursiveWorldNode( mnode_t *node, uint clipflags )
|
|
||||||
{
|
|
||||||
int i, clipped;
|
|
||||||
msurface_t *surf, **mark;
|
|
||||||
mleaf_t *pleaf;
|
|
||||||
int c, side;
|
|
||||||
float dot;
|
|
||||||
mnode_t *children[2];
|
|
||||||
int numsurfaces, firstsurface;
|
|
||||||
|
|
||||||
loc0:
|
|
||||||
if( node->contents == CONTENTS_SOLID )
|
|
||||||
return; // hit a solid leaf
|
|
||||||
|
|
||||||
if( node->visframe != tr.visframecount )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if( clipflags && !r_nocull.value )
|
|
||||||
{
|
|
||||||
for( i = 0; i < 6; i++ )
|
|
||||||
{
|
|
||||||
const mplane_t *p = &RI.frustum.planes[i];
|
|
||||||
|
|
||||||
if( !FBitSet( clipflags, BIT( i )))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
clipped = BoxOnPlaneSide( node->minmaxs, node->minmaxs + 3, p );
|
|
||||||
if( clipped == 2 ) return;
|
|
||||||
if( clipped == 1 ) ClearBits( clipflags, BIT( i ));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if a leaf node, draw stuff
|
|
||||||
if( node->contents < 0 )
|
|
||||||
{
|
|
||||||
pleaf = (mleaf_t *)node;
|
|
||||||
|
|
||||||
mark = pleaf->firstmarksurface;
|
|
||||||
c = pleaf->nummarksurfaces;
|
|
||||||
|
|
||||||
if( c )
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
(*mark)->visframe = tr.framecount;
|
|
||||||
mark++;
|
|
||||||
} while( --c );
|
|
||||||
}
|
|
||||||
|
|
||||||
// deal with model fragments in this leaf
|
|
||||||
if( pleaf->efrags )
|
|
||||||
gEngfuncs.R_StoreEfrags( &pleaf->efrags, tr.realframecount );
|
|
||||||
|
|
||||||
// r_stats.c_world_leafs++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// node is just a decision point, so go down the apropriate sides
|
|
||||||
|
|
||||||
// find which side of the node we are on
|
|
||||||
dot = PlaneDiff( tr.modelorg, node->plane );
|
|
||||||
side = (dot >= 0.0f) ? 0 : 1;
|
|
||||||
|
|
||||||
// recurse down the children, front side first
|
|
||||||
node_children( children, node, tr.worldmodel );
|
|
||||||
R_RecursiveWorldNode( children[side], clipflags );
|
|
||||||
|
|
||||||
firstsurface = node_firstsurface( node, tr.worldmodel );
|
|
||||||
numsurfaces = node_numsurfaces( node, tr.worldmodel );
|
|
||||||
|
|
||||||
// draw stuff
|
|
||||||
for( c = numsurfaces, surf = tr.worldmodel->surfaces + firstsurface; c; c--, surf++ )
|
|
||||||
{
|
|
||||||
if( R_CullSurface( surf, &RI.frustum, clipflags ))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if( surf->flags & SURF_DRAWSKY )
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
// make sky chain to right clip the skybox
|
|
||||||
surf->texturechain = skychain;
|
|
||||||
skychain = surf;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
surf->texturechain = surf->texinfo->texture->texturechain;
|
|
||||||
surf->texinfo->texture->texturechain = surf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// recurse down the back side
|
|
||||||
node = children[!side];
|
|
||||||
goto loc0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void R_DrawWorld( void )
|
|
||||||
{
|
|
||||||
double start, end;
|
|
||||||
|
|
||||||
// paranoia issues: when gl_renderer is "0" we need have something valid for currententity
|
|
||||||
// to prevent crashing until HeadShield drawing.
|
|
||||||
RI.currententity = CL_GetEntityByIndex( 0 );
|
|
||||||
if( !RI.currententity )
|
|
||||||
return;
|
|
||||||
|
|
||||||
RI.currentmodel = RI.currententity->model;
|
|
||||||
if( !FBitSet( RI.rvp.flags, RF_DRAW_WORLD ) || FBitSet( RI.rvp.flags, RF_ONLY_CLIENTDRAW ))
|
|
||||||
return;
|
|
||||||
|
|
||||||
VectorCopy( RI.cullorigin, tr.modelorg );
|
|
||||||
//memset( gl_lms.lightmap_surfaces, 0, sizeof( gl_lms.lightmap_surfaces ));
|
|
||||||
//memset( fullbright_surfaces, 0, sizeof( fullbright_surfaces ));
|
|
||||||
//memset( detail_surfaces, 0, sizeof( detail_surfaces ));
|
|
||||||
|
|
||||||
//gl_lms.dynamic_surfaces = NULL;
|
|
||||||
tr.blend = 1.0f;
|
|
||||||
|
|
||||||
//R_ClearSkyBox ();
|
|
||||||
|
|
||||||
start = gEngfuncs.pfnTime();
|
|
||||||
if( FBitSet( RI.rvp.flags, RF_DRAW_OVERVIEW ))
|
|
||||||
{
|
|
||||||
//R_DrawWorldTopView( tr.worldmodel->nodes, RI.frustum.clipFlags );
|
|
||||||
}
|
|
||||||
else R_RecursiveWorldNode( tr.worldmodel->nodes, RI.frustum.clipFlags );
|
|
||||||
end = gEngfuncs.pfnTime();
|
|
||||||
|
|
||||||
//r_stats.t_world_node = end - start;
|
|
||||||
|
|
||||||
start = gEngfuncs.pfnTime();
|
|
||||||
|
|
||||||
R_DrawTextureChains();
|
|
||||||
|
|
||||||
end = gEngfuncs.pfnTime();
|
|
||||||
|
|
||||||
//r_stats.t_world_draw = end - start;
|
|
||||||
//tr.num_draw_decals = 0;
|
|
||||||
//skychain = NULL;
|
|
||||||
|
|
||||||
gEngfuncs.R_DrawWorldHull();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
===============
|
|
||||||
R_MarkLeaves
|
|
||||||
|
|
||||||
Mark the leaves and nodes that are in the PVS for the current leaf
|
|
||||||
===============
|
|
||||||
*/
|
|
||||||
void R_MarkLeaves( void )
|
|
||||||
{
|
|
||||||
qboolean novis = false;
|
|
||||||
qboolean force = false;
|
|
||||||
mleaf_t *leaf = NULL;
|
|
||||||
mnode_t *node;
|
|
||||||
vec3_t test;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if( !FBitSet( RI.rvp.flags, RF_DRAW_WORLD ) ) return;
|
|
||||||
|
|
||||||
if( FBitSet( r_novis.flags, FCVAR_CHANGED ) || tr.fResetVis )
|
|
||||||
{
|
|
||||||
// force recalc viewleaf
|
|
||||||
ClearBits( r_novis.flags, FCVAR_CHANGED );
|
|
||||||
tr.fResetVis = false;
|
|
||||||
RI.viewleaf = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
VectorCopy( RI.rvp.vieworigin, test );
|
|
||||||
|
|
||||||
if( RI.viewleaf != NULL )
|
|
||||||
{
|
|
||||||
// merge two leafs that can be a crossed-line contents
|
|
||||||
if( RI.viewleaf->contents == CONTENTS_EMPTY )
|
|
||||||
VectorSet( test, RI.rvp.vieworigin[0], RI.rvp.vieworigin[1], RI.rvp.vieworigin[2] - 16.0f );
|
|
||||||
else
|
|
||||||
VectorSet( test, RI.rvp.vieworigin[0], RI.rvp.vieworigin[1], RI.rvp.vieworigin[2] + 16.0f );
|
|
||||||
|
|
||||||
leaf = gEngfuncs.Mod_PointInLeaf( test, tr.worldmodel->nodes, tr.worldmodel );
|
|
||||||
|
|
||||||
if(( leaf->contents != CONTENTS_SOLID ) && ( RI.viewleaf != leaf ))
|
|
||||||
force = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( RI.viewleaf == RI.oldviewleaf && RI.viewleaf != NULL && !force )
|
|
||||||
return;
|
|
||||||
|
|
||||||
// development aid to let you run around
|
|
||||||
// and see exactly where the pvs ends
|
|
||||||
if( r_lockpvs.value ) return;
|
|
||||||
|
|
||||||
RI.oldviewleaf = RI.viewleaf;
|
|
||||||
tr.visframecount++;
|
|
||||||
|
|
||||||
if( r_novis.value || FBitSet( RI.rvp.flags, RF_DRAW_OVERVIEW ) || !RI.viewleaf || !tr.worldmodel->visdata )
|
|
||||||
novis = true;
|
|
||||||
|
|
||||||
gEngfuncs.R_FatPVS( RI.rvp.vieworigin, r_pvs_radius->value, RI.visbytes, false, novis );
|
|
||||||
if( force && !novis )
|
|
||||||
gEngfuncs.R_FatPVS( test, r_pvs_radius->value, RI.visbytes, true, novis );
|
|
||||||
|
|
||||||
for( i = 0; i < tr.worldmodel->numleafs; i++ )
|
|
||||||
{
|
|
||||||
if( CHECKVISBIT( RI.visbytes, i ))
|
|
||||||
{
|
|
||||||
node = (mnode_t *)&tr.worldmodel->leafs[i+1];
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if( node->visframe == tr.visframecount )
|
|
||||||
break;
|
|
||||||
node->visframe = tr.visframecount;
|
|
||||||
node = node->parent;
|
|
||||||
} while( node );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
==================
|
|
||||||
GL_BuildLightmaps
|
|
||||||
|
|
||||||
Builds the lightmap texture
|
|
||||||
with all the surfaces from all brush models
|
|
||||||
==================
|
|
||||||
*/
|
|
||||||
void GL_BuildLightmaps( void )
|
|
||||||
{
|
|
||||||
int i, j, nColinElim = 0;
|
|
||||||
model_t *m;
|
|
||||||
#if 0
|
|
||||||
// release old lightmaps
|
|
||||||
for( i = 0; i < MAX_LIGHTMAPS; i++ )
|
|
||||||
{
|
|
||||||
if( !tr.lightmapTextures[i] ) break;
|
|
||||||
GL_FreeTexture( tr.lightmapTextures[i] );
|
|
||||||
}
|
|
||||||
|
|
||||||
memset( tr.lightmapTextures, 0, sizeof( tr.lightmapTextures ));
|
|
||||||
#endif
|
|
||||||
memset( &RI, 0, sizeof( RI ));
|
|
||||||
#if 0
|
|
||||||
// update the lightmap blocksize
|
|
||||||
if( FBitSet( gp_host->features, ENGINE_LARGE_LIGHTMAPS ) || tr.world->version == QBSP2_VERSION || r_large_lightmaps.value )
|
|
||||||
tr.block_size = BLOCK_SIZE_MAX;
|
|
||||||
else tr.block_size = BLOCK_SIZE_DEFAULT;
|
|
||||||
|
|
||||||
skychain = NULL;
|
|
||||||
#endif
|
|
||||||
tr.framecount = tr.visframecount = 1; // no dlight cache
|
|
||||||
//gl_lms.current_lightmap_texture = 0;
|
|
||||||
tr.modelviewIdentity = false;
|
|
||||||
tr.realframecount = 1;
|
|
||||||
#if 0
|
|
||||||
// setup the texture for dlights
|
|
||||||
R_InitDlightTexture();
|
|
||||||
|
|
||||||
// setup all the lightstyles
|
|
||||||
CL_RunLightStyles((lightstyle_t *)ENGINE_GET_PARM( PARM_GET_LIGHTSTYLES_PTR ));
|
|
||||||
|
|
||||||
LM_InitBlock();
|
|
||||||
#endif
|
|
||||||
for( i = 0; i < gp_cl->nummodels; i++ )
|
|
||||||
{
|
|
||||||
if(( m = CL_ModelHandle( i + 1 )) == NULL )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if( m->name[0] == '*' || m->type != mod_brush )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for( j = 0; j < m->numsurfaces; j++ )
|
|
||||||
{
|
|
||||||
// clearing all decal chains
|
|
||||||
m->surfaces[j].pdecals = NULL;
|
|
||||||
m->surfaces[j].visframe = 0;
|
|
||||||
|
|
||||||
//GL_CreateSurfaceLightmap( m->surfaces + j, m );
|
|
||||||
|
|
||||||
if( m->surfaces[j].flags & SURF_DRAWTURB )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
nColinElim += GL_BuildPolygonFromSurface( m, m->surfaces + j );
|
|
||||||
}
|
|
||||||
|
|
||||||
// clearing visframe
|
|
||||||
for( j = 0; j < m->numleafs; j++ )
|
|
||||||
m->leafs[j+1].visframe = 0;
|
|
||||||
for( j = 0; j < m->numnodes; j++ )
|
|
||||||
m->nodes[j].visframe = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//LM_UploadBlock( false );
|
|
||||||
|
|
||||||
if( gEngfuncs.drawFuncs->GL_BuildLightmaps )
|
|
||||||
{
|
|
||||||
// build lightmaps on the client-side
|
|
||||||
gEngfuncs.drawFuncs->GL_BuildLightmaps( );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
#! /usr/bin/env python
|
|
||||||
# encoding: utf-8
|
|
||||||
# mittorn, 2018
|
|
||||||
|
|
||||||
def options(opt):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def configure(conf):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def build(bld):
|
|
||||||
bld.shlib(
|
|
||||||
source = ['r_context.c', 'r_image.c', 'r_d3d.c', 'r_main.c', 'r_draw.c', 'r_surf.c', 'r_frustum.c'],
|
|
||||||
target = 'ref_dx2',
|
|
||||||
defines = 'REF_DLL',
|
|
||||||
use = 'ref_common engine_includes sdk_includes werror public USER32 DDRAW',
|
|
||||||
install_path = bld.env.LIBDIR
|
|
||||||
)
|
|
||||||
@@ -736,6 +736,7 @@ extern convar_t r_vbo_detail;
|
|||||||
extern convar_t r_vbo_overbrightmode;
|
extern convar_t r_vbo_overbrightmode;
|
||||||
extern convar_t r_studio_sort_textures;
|
extern convar_t r_studio_sort_textures;
|
||||||
extern convar_t r_studio_drawelements;
|
extern convar_t r_studio_drawelements;
|
||||||
|
extern convar_t r_studio_builtin_renderer;
|
||||||
extern convar_t r_shadows;
|
extern convar_t r_shadows;
|
||||||
extern convar_t r_ripple;
|
extern convar_t r_ripple;
|
||||||
extern convar_t r_ripple_updatetime;
|
extern convar_t r_ripple_updatetime;
|
||||||
|
|||||||
@@ -1149,6 +1149,7 @@ static void GL_InitCommands( void )
|
|||||||
gEngfuncs.Cvar_RegisterVariable( &r_traceglow );
|
gEngfuncs.Cvar_RegisterVariable( &r_traceglow );
|
||||||
gEngfuncs.Cvar_RegisterVariable( &r_studio_sort_textures );
|
gEngfuncs.Cvar_RegisterVariable( &r_studio_sort_textures );
|
||||||
gEngfuncs.Cvar_RegisterVariable( &r_studio_drawelements );
|
gEngfuncs.Cvar_RegisterVariable( &r_studio_drawelements );
|
||||||
|
gEngfuncs.Cvar_RegisterVariable( &r_studio_builtin_renderer );
|
||||||
gEngfuncs.Cvar_RegisterVariable( &r_ripple );
|
gEngfuncs.Cvar_RegisterVariable( &r_ripple );
|
||||||
gEngfuncs.Cvar_RegisterVariable( &r_ripple_updatetime );
|
gEngfuncs.Cvar_RegisterVariable( &r_ripple_updatetime );
|
||||||
gEngfuncs.Cvar_RegisterVariable( &r_ripple_spawntime );
|
gEngfuncs.Cvar_RegisterVariable( &r_ripple_spawntime );
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ typedef struct
|
|||||||
// studio-related cvars
|
// studio-related cvars
|
||||||
CVAR_DEFINE_AUTO( r_studio_sort_textures, "0", FCVAR_GLCONFIG, "change draw order for additive meshes" );
|
CVAR_DEFINE_AUTO( r_studio_sort_textures, "0", FCVAR_GLCONFIG, "change draw order for additive meshes" );
|
||||||
CVAR_DEFINE_AUTO( r_studio_drawelements, "1", FCVAR_GLCONFIG, "use glDrawElements for studiomodels" );
|
CVAR_DEFINE_AUTO( r_studio_drawelements, "1", FCVAR_GLCONFIG, "use glDrawElements for studiomodels" );
|
||||||
|
CVAR_DEFINE_AUTO( r_studio_builtin_renderer, "0", 0, "use built-in studio model renderer instead of the one provided by client library (debugging)" );
|
||||||
static cvar_t *cl_righthand = NULL;
|
static cvar_t *cl_righthand = NULL;
|
||||||
|
|
||||||
static r_studio_interface_t *pStudioDraw;
|
static r_studio_interface_t *pStudioDraw;
|
||||||
@@ -1904,6 +1905,43 @@ static void R_StudioDrawArrays( uint startverts, uint startelems )
|
|||||||
pglDisableClientState( GL_COLOR_ARRAY );
|
pglDisableClientState( GL_COLOR_ARRAY );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
R_StudioSubmitMesh
|
||||||
|
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
static void R_StudioSubmitMesh( short *ptricmds, vec3_t *pstudionorms, float s, float t, float shellscale, int tesslevel )
|
||||||
|
{
|
||||||
|
if( tesslevel > 0 )
|
||||||
|
{
|
||||||
|
// R_StudioDrawTruformMesh( ptricmds, pstudionorms, s, t, shellscale, tesslevel );
|
||||||
|
}
|
||||||
|
else if( r_studio_drawelements.value )
|
||||||
|
{
|
||||||
|
uint startArrayVerts = g_studio.numverts;
|
||||||
|
uint startArrayElems = g_studio.numelems;
|
||||||
|
|
||||||
|
if( FBitSet( g_nFaceFlags, STUDIO_NF_CHROME ))
|
||||||
|
R_StudioBuildArrayChromeMesh( ptricmds, pstudionorms, s, t, shellscale );
|
||||||
|
else if( FBitSet( g_nFaceFlags, STUDIO_NF_UV_COORDS ))
|
||||||
|
R_StudioBuildArrayFloatMesh( ptricmds, pstudionorms );
|
||||||
|
else
|
||||||
|
R_StudioBuildArrayNormalMesh( ptricmds, pstudionorms, s, t );
|
||||||
|
|
||||||
|
R_StudioDrawArrays( startArrayVerts, startArrayElems );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( FBitSet( g_nFaceFlags, STUDIO_NF_CHROME ))
|
||||||
|
R_StudioDrawChromeMesh( ptricmds, pstudionorms, s, t, shellscale );
|
||||||
|
else if( FBitSet( g_nFaceFlags, STUDIO_NF_UV_COORDS ))
|
||||||
|
R_StudioDrawFloatMesh( ptricmds, pstudionorms );
|
||||||
|
else
|
||||||
|
R_StudioDrawNormalMesh( ptricmds, pstudionorms, s, t );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
===============
|
===============
|
||||||
R_StudioDrawPoints
|
R_StudioDrawPoints
|
||||||
@@ -2040,8 +2078,6 @@ static void R_StudioDrawPoints( void )
|
|||||||
for( int j = 0; j < m_pSubModel->nummesh; j++ )
|
for( int j = 0; j < m_pSubModel->nummesh; j++ )
|
||||||
{
|
{
|
||||||
float oldblend = tr.blend;
|
float oldblend = tr.blend;
|
||||||
uint startArrayVerts = g_studio.numverts;
|
|
||||||
uint startArrayElems = g_studio.numelems;
|
|
||||||
|
|
||||||
pmesh = g_studio.meshes[j].mesh;
|
pmesh = g_studio.meshes[j].mesh;
|
||||||
short *ptricmds = (short *)((byte *)m_pStudioHeader + pmesh->triindex);
|
short *ptricmds = (short *)((byte *)m_pStudioHeader + pmesh->triindex);
|
||||||
@@ -2073,24 +2109,7 @@ static void R_StudioDrawPoints( void )
|
|||||||
|
|
||||||
R_StudioSetupSkin( m_pStudioHeader, pskinref[pmesh->skinref] );
|
R_StudioSetupSkin( m_pStudioHeader, pskinref[pmesh->skinref] );
|
||||||
|
|
||||||
if( r_studio_drawelements.value )
|
R_StudioSubmitMesh( ptricmds, pstudionorms, s, t, shellscale, 0 );
|
||||||
{
|
|
||||||
if( FBitSet( g_nFaceFlags, STUDIO_NF_CHROME ))
|
|
||||||
R_StudioBuildArrayChromeMesh( ptricmds, pstudionorms, s, t, shellscale );
|
|
||||||
else if( FBitSet( g_nFaceFlags, STUDIO_NF_UV_COORDS ))
|
|
||||||
R_StudioBuildArrayFloatMesh( ptricmds, pstudionorms );
|
|
||||||
else R_StudioBuildArrayNormalMesh( ptricmds, pstudionorms, s, t );
|
|
||||||
|
|
||||||
R_StudioDrawArrays( startArrayVerts, startArrayElems );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if( FBitSet( g_nFaceFlags, STUDIO_NF_CHROME ))
|
|
||||||
R_StudioDrawChromeMesh( ptricmds, pstudionorms, s, t, shellscale );
|
|
||||||
else if( FBitSet( g_nFaceFlags, STUDIO_NF_UV_COORDS ))
|
|
||||||
R_StudioDrawFloatMesh( ptricmds, pstudionorms );
|
|
||||||
else R_StudioDrawNormalMesh( ptricmds, pstudionorms, s, t );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( FBitSet( g_nFaceFlags, STUDIO_NF_MASKED ))
|
if( FBitSet( g_nFaceFlags, STUDIO_NF_MASKED ))
|
||||||
{
|
{
|
||||||
@@ -3192,6 +3211,12 @@ static void R_StudioDrawModelInternal( cl_entity_t *e, int flags )
|
|||||||
R_StudioDrawPlayer( flags, &e->curstate );
|
R_StudioDrawPlayer( flags, &e->curstate );
|
||||||
else R_StudioDrawModel( flags );
|
else R_StudioDrawModel( flags );
|
||||||
}
|
}
|
||||||
|
else if( unlikely( r_studio_builtin_renderer.value ))
|
||||||
|
{
|
||||||
|
if( e->player )
|
||||||
|
R_StudioDrawPlayer( flags, R_StudioGetPlayerState( e->index - 1 ));
|
||||||
|
else R_StudioDrawModel( flags );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// select the properly method
|
// select the properly method
|
||||||
|
|||||||
@@ -955,6 +955,7 @@ extern convar_t sw_texfilt;
|
|||||||
extern convar_t r_traceglow;
|
extern convar_t r_traceglow;
|
||||||
extern convar_t sw_noalphabrushes;
|
extern convar_t sw_noalphabrushes;
|
||||||
extern convar_t r_studio_sort_textures;
|
extern convar_t r_studio_sort_textures;
|
||||||
|
extern convar_t r_studio_builtin_renderer;
|
||||||
|
|
||||||
extern struct qfrustum_s
|
extern struct qfrustum_s
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1341,6 +1341,7 @@ qboolean GAME_EXPORT R_Init( void )
|
|||||||
#endif
|
#endif
|
||||||
gEngfuncs.Cvar_RegisterVariable( &r_novis );
|
gEngfuncs.Cvar_RegisterVariable( &r_novis );
|
||||||
gEngfuncs.Cvar_RegisterVariable( &r_studio_sort_textures );
|
gEngfuncs.Cvar_RegisterVariable( &r_studio_sort_textures );
|
||||||
|
gEngfuncs.Cvar_RegisterVariable( &r_studio_builtin_renderer );
|
||||||
|
|
||||||
r_temppool = Mem_AllocPool( "ref_soft zone" );
|
r_temppool = Mem_AllocPool( "ref_soft zone" );
|
||||||
|
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ typedef struct
|
|||||||
|
|
||||||
// studio-related cvars
|
// studio-related cvars
|
||||||
CVAR_DEFINE_AUTO( r_studio_sort_textures, "0", FCVAR_GLCONFIG, "change draw order for additive meshes" );
|
CVAR_DEFINE_AUTO( r_studio_sort_textures, "0", FCVAR_GLCONFIG, "change draw order for additive meshes" );
|
||||||
|
CVAR_DEFINE_AUTO( r_studio_builtin_renderer, "0", 0, "use built-in studio model renderer instead of the one provided by client library (debugging)" );
|
||||||
static cvar_t *cl_righthand = NULL;
|
static cvar_t *cl_righthand = NULL;
|
||||||
|
|
||||||
static r_studio_interface_t *pStudioDraw;
|
static r_studio_interface_t *pStudioDraw;
|
||||||
@@ -2822,6 +2823,13 @@ static void R_StudioDrawModelInternal( cl_entity_t *e, int flags )
|
|||||||
else
|
else
|
||||||
R_StudioDrawModel( flags );
|
R_StudioDrawModel( flags );
|
||||||
}
|
}
|
||||||
|
else if( unlikely( r_studio_builtin_renderer.value ))
|
||||||
|
{
|
||||||
|
if( e->player )
|
||||||
|
R_StudioDrawPlayer( flags, R_StudioGetPlayerState( e->index - 1 ));
|
||||||
|
else
|
||||||
|
R_StudioDrawModel( flags );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// select the properly method
|
// select the properly method
|
||||||
|
|||||||
6
wscript
6
wscript
@@ -118,7 +118,6 @@ SUBDIRS = [
|
|||||||
Subproject('ref/common', lambda x: x.env.CLIENT),
|
Subproject('ref/common', lambda x: x.env.CLIENT),
|
||||||
Subproject('ref/gl', lambda x: x.env.CLIENT and (x.env.GL or x.env.NANOGL or x.env.GLWES or x.env.GL4ES or x.env.GLES3COMPAT)),
|
Subproject('ref/gl', lambda x: x.env.CLIENT and (x.env.GL or x.env.NANOGL or x.env.GLWES or x.env.GL4ES or x.env.GLES3COMPAT)),
|
||||||
Subproject('ref/soft', lambda x: x.env.CLIENT and x.env.SOFT),
|
Subproject('ref/soft', lambda x: x.env.CLIENT and x.env.SOFT),
|
||||||
Subproject('ref/dx2', lambda x: x.env.CLIENT and x.env.DX2),
|
|
||||||
Subproject('ref/null', lambda x: x.env.CLIENT and x.env.NULL),
|
Subproject('ref/null', lambda x: x.env.CLIENT and x.env.NULL),
|
||||||
Subproject('3rdparty/bzip2', lambda x: x.env.CLIENT and not x.env.HAVE_SYSTEM_BZ2),
|
Subproject('3rdparty/bzip2', lambda x: x.env.CLIENT and not x.env.HAVE_SYSTEM_BZ2),
|
||||||
Subproject('3rdparty/mbedtls'),
|
Subproject('3rdparty/mbedtls'),
|
||||||
@@ -152,7 +151,6 @@ REFDLLS = [
|
|||||||
RefDll('gl4es', False),
|
RefDll('gl4es', False),
|
||||||
RefDll('gles3compat', False, 'GLES3COMPAT'),
|
RefDll('gles3compat', False, 'GLES3COMPAT'),
|
||||||
RefDll('null', False),
|
RefDll('null', False),
|
||||||
RefDll('dx2', False),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
def options(opt):
|
def options(opt):
|
||||||
@@ -367,6 +365,7 @@ def configure(conf):
|
|||||||
'-Werror=duplicated-cond',
|
'-Werror=duplicated-cond',
|
||||||
'-Werror=format=2',
|
'-Werror=format=2',
|
||||||
'-Werror=free-nonheap-object',
|
'-Werror=free-nonheap-object',
|
||||||
|
'-Werror=init-self',
|
||||||
'-Werror=implicit-fallthrough=2',
|
'-Werror=implicit-fallthrough=2',
|
||||||
'-Werror=logical-op',
|
'-Werror=logical-op',
|
||||||
'-Werror=nonnull',
|
'-Werror=nonnull',
|
||||||
@@ -387,7 +386,6 @@ def configure(conf):
|
|||||||
|
|
||||||
# unstable diagnostics, may cause false positives
|
# unstable diagnostics, may cause false positives
|
||||||
'-Walloc-zero',
|
'-Walloc-zero',
|
||||||
'-Winit-self',
|
|
||||||
'-Wmisleading-indentation',
|
'-Wmisleading-indentation',
|
||||||
'-Wmismatched-dealloc',
|
'-Wmismatched-dealloc',
|
||||||
'-Wstringop-overflow',
|
'-Wstringop-overflow',
|
||||||
@@ -497,7 +495,7 @@ def configure(conf):
|
|||||||
# Don't check them more than once, to save time
|
# Don't check them more than once, to save time
|
||||||
# Usually, they are always available
|
# Usually, they are always available
|
||||||
# but we need them in uselib
|
# but we need them in uselib
|
||||||
a = [ 'user32', 'shell32', 'gdi32', 'advapi32', 'dbghelp', 'psapi', 'ws2_32', 'bcrypt', 'ddraw' ]
|
a = [ 'user32', 'shell32', 'gdi32', 'advapi32', 'dbghelp', 'psapi', 'ws2_32', 'bcrypt' ]
|
||||||
if conf.env.COMPILER_CC == 'msvc':
|
if conf.env.COMPILER_CC == 'msvc':
|
||||||
for i in a:
|
for i in a:
|
||||||
conf.start_msg('Checking for MSVC library')
|
conf.start_msg('Checking for MSVC library')
|
||||||
|
|||||||
Reference in New Issue
Block a user