Browse Source
Added Quake engine code from UQE project that will be gradually stripped down and used as the basis for a Unity plugin
console
Added Quake engine code from UQE project that will be gradually stripped down and used as the basis for a Unity plugin
console
202 changed files with 114554 additions and 0 deletions
-
87engine/GNU.TXT
-
60engine/README.TXT
-
69engine/code/3dfx.txt
-
22engine/code/WinQuake.sln
-
305engine/code/WinQuake.vcxproj
-
37engine/code/anorm_dots.h
-
181engine/code/anorms.h
-
324engine/code/bspfile.h
-
595engine/code/cd_win.c
-
33engine/code/cdaudio.h
-
595engine/code/cl_demo.c
-
469engine/code/cl_input.c
-
800engine/code/cl_main.c
-
1026engine/code/cl_parse.c
-
394engine/code/cl_tent.c
-
408engine/code/client.h
-
753engine/code/cmd.c
-
121engine/code/cmd.h
-
2226engine/code/common.c
-
198engine/code/common.h
-
365engine/code/conproc.c
-
37engine/code/conproc.h
-
671engine/code/console.c
-
46engine/code/console.h
-
81engine/code/crc.c
-
24engine/code/crc.h
-
289engine/code/cvar.c
-
99engine/code/cvar.h
-
55engine/code/draw.h
-
2466engine/code/gl_draw.c
-
88engine/code/gl_fullbright.c
-
27engine/code/gl_fullbright.h
-
362engine/code/gl_mesh.c
-
2261engine/code/gl_model.c
-
454engine/code/gl_model.h
-
234engine/code/gl_refrag.c
-
579engine/code/gl_rlight.c
-
1683engine/code/gl_rmain.c
-
543engine/code/gl_rmisc.c
-
2230engine/code/gl_rsurf.c
-
1172engine/code/gl_screen.c
-
182engine/code/gl_test.c
-
2260engine/code/gl_vidnt.c
-
1182engine/code/gl_warp.c
-
51engine/code/gl_warp_sin.h
-
12050engine/code/glext.h
-
171engine/code/glqnotes.txt
-
358engine/code/glquake.h
-
1040engine/code/host.c
-
1935engine/code/host_cmd.c
-
1293engine/code/in_win.c
-
34engine/code/input.h
-
763engine/code/keys.c
-
136engine/code/keys.h
-
587engine/code/mathlib.c
-
107engine/code/mathlib.h
-
3364engine/code/menu.c
-
38engine/code/menu.h
-
134engine/code/modelgen.h
-
337engine/code/net.h
-
1390engine/code/net_dgrm.c
-
34engine/code/net_dgrm.h
-
245engine/code/net_loop.c
-
33engine/code/net_loop.h
-
1012engine/code/net_main.c
-
167engine/code/net_vcr.c
-
37engine/code/net_vcr.h
-
120engine/code/net_win.c
-
580engine/code/net_wins.c
-
39engine/code/net_wins.h
-
440engine/code/net_wipx.c
-
39engine/code/net_wipx.h
-
1940engine/code/pr_cmds.c
-
180engine/code/pr_comp.h
-
1112engine/code/pr_edict.c
-
673engine/code/pr_exec.c
-
24engine/code/progdefs.h
-
143engine/code/progdefs.q1
-
158engine/code/progdefs.q2
-
134engine/code/progs.h
-
173engine/code/protocol.h
-
BINengine/code/quake.bmp
-
BINengine/code/quake.ico
-
359engine/code/quakedef.h
-
819engine/code/r_part.c
-
162engine/code/render.h
-
19engine/code/resource.h
-
1391engine/code/sbar.c
-
41engine/code/sbar.h
-
55engine/code/screen.h
-
262engine/code/server.h
-
1027engine/code/snd_dma.c
-
1129engine/code/snd_fmod.c
-
45engine/code/snd_fmod.h
-
341engine/code/snd_mem.c
-
398engine/code/snd_mix.c
-
737engine/code/snd_win.c
-
177engine/code/sound.h
-
110engine/code/spritegn.h
-
1227engine/code/sv_main.c
@ -0,0 +1,87 @@ |
|||||
|
GNU GENERAL PUBLIC LICENSE |
||||
|
Version 2, June 1991 |
||||
|
|
||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc. |
||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
||||
|
|
||||
|
Everyone is permitted to copy and distribute verbatim copies |
||||
|
of this license document, but changing it is not allowed. |
||||
|
Preamble |
||||
|
The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. |
||||
|
|
||||
|
When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. |
||||
|
|
||||
|
To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. |
||||
|
|
||||
|
For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. |
||||
|
|
||||
|
We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. |
||||
|
|
||||
|
Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. |
||||
|
|
||||
|
Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. |
||||
|
|
||||
|
The precise terms and conditions for copying, distribution and modification follow. |
||||
|
|
||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION |
||||
|
0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". |
||||
|
|
||||
|
Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. |
||||
|
|
||||
|
1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. |
||||
|
|
||||
|
You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. |
||||
|
|
||||
|
2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: |
||||
|
|
||||
|
|
||||
|
a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. |
||||
|
|
||||
|
b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. |
||||
|
|
||||
|
c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) |
||||
|
These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. |
||||
|
Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. |
||||
|
|
||||
|
In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. |
||||
|
|
||||
|
3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: |
||||
|
|
||||
|
a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, |
||||
|
|
||||
|
b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, |
||||
|
|
||||
|
c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) |
||||
|
The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. |
||||
|
If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. |
||||
|
|
||||
|
4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. |
||||
|
|
||||
|
5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. |
||||
|
|
||||
|
6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. |
||||
|
|
||||
|
7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. |
||||
|
|
||||
|
If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. |
||||
|
|
||||
|
It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. |
||||
|
|
||||
|
This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. |
||||
|
|
||||
|
8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. |
||||
|
|
||||
|
9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. |
||||
|
|
||||
|
Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. |
||||
|
|
||||
|
10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. |
||||
|
|
||||
|
NO WARRANTY |
||||
|
|
||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. |
||||
|
|
||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. |
||||
|
|
||||
|
|
||||
|
END OF TERMS AND CONDITIONS |
||||
@ -0,0 +1,60 @@ |
|||||
|
|
||||
|
This is the complete source code for winquake, glquake, quakeworld, and |
||||
|
glquakeworld. |
||||
|
|
||||
|
The projects have been tested with visual C++ 6.0, but masm is also required |
||||
|
to build the assembly language files. It is possible to change a #define and |
||||
|
build with only C code, but the software rendering versions lose almost half |
||||
|
its speed. The OpenGL versions will not be effected very much. The |
||||
|
gas2masm tool was created to allow us to use the same source for the dos, |
||||
|
linux, and windows versions, but I don't really recommend anyone mess |
||||
|
with the asm code. |
||||
|
|
||||
|
The original dos version of Quake should also be buildable from these |
||||
|
sources, but we didn't bother trying. |
||||
|
|
||||
|
The code is all licensed under the terms of the GPL (gnu public license). |
||||
|
You should read the entire license, but the gist of it is that you can do |
||||
|
anything you want with the code, including sell your new version. The catch |
||||
|
is that if you distribute new binary versions, you are required to make the |
||||
|
entire source code available for free to everyone. |
||||
|
|
||||
|
Our previous code releases have been under licenses that preclude |
||||
|
commercial exploitation, but have no clause forcing sharing of source code. |
||||
|
There have been some unfortunate losses to the community as a result of |
||||
|
mod teams keeping their sources closed (and sometimes losing them). If |
||||
|
you are going to publicly release modified versions of this code, you must |
||||
|
also make source code available. I would encourage teams to even go a step |
||||
|
farther and investigate using public CVS servers for development where |
||||
|
possible. |
||||
|
|
||||
|
The primary intent of this release is for entertainment and educational |
||||
|
purposes, but the GPL does allow commercial exploitation if you obey the |
||||
|
full license. If you want to do something commercial and you just can't bear |
||||
|
to have your source changes released, we could still negotiate a separate |
||||
|
license agreement (for $$$), but I would encourage you to just live with the |
||||
|
GPL. |
||||
|
|
||||
|
All of the Quake data files remain copyrighted and licensed under the |
||||
|
original terms, so you cannot redistribute data from the original game, but if |
||||
|
you do a true total conversion, you can create a standalone game based on |
||||
|
this code. |
||||
|
|
||||
|
I will see about having the license changed on the shareware episode of |
||||
|
quake to allow it to be duplicated more freely (for linux distributions, for |
||||
|
example), but I can't give a timeframe for it. You can still download one of |
||||
|
the original quake demos and use that data with the code, but there are |
||||
|
restrictions on the redistribution of the demo data. |
||||
|
|
||||
|
If you never actually bought a complete version of Quake, you might want |
||||
|
to rummage around in a local software bargain bin for one of the originals, |
||||
|
or perhaps find a copy of the "Quake: the offering" boxed set with both |
||||
|
mission packs. |
||||
|
|
||||
|
Thanks to Dave "Zoid" Kirsh and Robert Duffy for doing the grunt work of |
||||
|
building this release. |
||||
|
|
||||
|
John Carmack |
||||
|
Id Software |
||||
|
|
||||
|
|
||||
@ -0,0 +1,69 @@ |
|||||
|
GLQuake Drivers |
||||
|
|
||||
|
Graphics Subsystem: Voodoo Graphics or Voodoo Rush |
||||
|
|
||||
|
Copyright ( 1997 3Dfx Interactive, Inc. ) |
||||
|
All Rights Reserved |
||||
|
|
||||
|
3Dfx Interactive, Inc. |
||||
|
www: www.3dfx.com |
||||
|
news: news.3dfx.com |
||||
|
|
||||
|
----------------------------------------------------------------------- |
||||
|
NOTE: GLQuake requires DirectX support DirectSound. DirectX can be |
||||
|
installed from the media provided with your Voodoo Based 3D Accelerator. |
||||
|
|
||||
|
Glide 2.31 or HIGHER runtime drivers *MUST* be installed to use this |
||||
|
GLQuake driver. Please download these drivers from your board |
||||
|
manufacturer OR unsupported drivers from http://www.3dfx.com |
||||
|
----------------------------------------------------------------------- |
||||
|
|
||||
|
Release Notes for GLQuake's mini-GL driver |
||||
|
|
||||
|
What's in the distribution? |
||||
|
--------------------------- |
||||
|
|
||||
|
This distribution contains GLQuake Drivers for Voodoo Based 3D |
||||
|
Accelerators. These drivers were tested on the following boards: |
||||
|
|
||||
|
Voodoo Graphics: |
||||
|
- Quantum 3D Obsidian |
||||
|
- Diamond Monster 3D |
||||
|
- Orchid Righteous 3D |
||||
|
- Deltron Realvision Flash 3D |
||||
|
- Guillemot MaxiGamer |
||||
|
- Skywell Magic 3D |
||||
|
|
||||
|
Voodoo Rush: |
||||
|
- Hercules Stringray 128-3D |
||||
|
- Intergraph Intense 3D Voodoo |
||||
|
- Jazz Multimedia Adrenaline Rush |
||||
|
|
||||
|
NOTE: The enclosed drivers are not meant to replace any Direct3D or |
||||
|
Glide drivers provided by your Voodoo Graphics card manufacturer. |
||||
|
Please obtain supported drivers from your board manufacturer. |
||||
|
|
||||
|
OEMSR2 and NT users: Do NOT replace OPENGL32.DLL located in your |
||||
|
Windows\SYSTEM directory. |
||||
|
|
||||
|
Requirements |
||||
|
------------ |
||||
|
|
||||
|
- Voodoo Graphics or Voodoo Rush Based 3D Accelerator |
||||
|
- Windows 95 (Windows NT is supported for Voodoo Rush) |
||||
|
- A PC with a Pentium 90 or higher CPU |
||||
|
- 16MB of RAM |
||||
|
- 2D Video card set at 16 bit color |
||||
|
|
||||
|
Support and Frequently Asked Questions |
||||
|
-------------------------------------- |
||||
|
|
||||
|
GLQuake is currently unsupported. You may however find answers to |
||||
|
questions on various Quake dedicated websites. 3Dfx provides a GLQuake |
||||
|
newsgroup on news.3dfx.com (Newsgroup name is 3dfx.games.glquake ) to |
||||
|
discuss GLQuake with other users. 3Dfx also provides a regularly |
||||
|
updated GLQuake FAQ at: http://www.3dfx.com/game_dev/quake_faq.html |
||||
|
|
||||
|
|
||||
|
Voodoo Graphics and Voodoo Rush are trademarks of 3Dfx Interactive, Inc. |
||||
|
All other trademarks are the property of their respective owners. |
||||
@ -0,0 +1,22 @@ |
|||||
|
|
||||
|
Microsoft Visual Studio Solution File, Format Version 12.00 |
||||
|
# Visual Studio 14 |
||||
|
VisualStudioVersion = 14.0.25420.1 |
||||
|
MinimumVisualStudioVersion = 10.0.40219.1 |
||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WinQuake", "WinQuake.vcxproj", "{6BF8FC22-9003-40F6-BF03-68A262C348BA}" |
||||
|
EndProject |
||||
|
Global |
||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
||||
|
Debug|Win32 = Debug|Win32 |
||||
|
Release|Win32 = Release|Win32 |
||||
|
EndGlobalSection |
||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
||||
|
{6BF8FC22-9003-40F6-BF03-68A262C348BA}.Debug|Win32.ActiveCfg = Debug|Win32 |
||||
|
{6BF8FC22-9003-40F6-BF03-68A262C348BA}.Debug|Win32.Build.0 = Debug|Win32 |
||||
|
{6BF8FC22-9003-40F6-BF03-68A262C348BA}.Release|Win32.ActiveCfg = Release|Win32 |
||||
|
{6BF8FC22-9003-40F6-BF03-68A262C348BA}.Release|Win32.Build.0 = Release|Win32 |
||||
|
EndGlobalSection |
||||
|
GlobalSection(SolutionProperties) = preSolution |
||||
|
HideSolutionNode = FALSE |
||||
|
EndGlobalSection |
||||
|
EndGlobal |
||||
@ -0,0 +1,305 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
|
<ItemGroup Label="ProjectConfigurations"> |
||||
|
<ProjectConfiguration Include="Debug|Win32"> |
||||
|
<Configuration>Debug</Configuration> |
||||
|
<Platform>Win32</Platform> |
||||
|
</ProjectConfiguration> |
||||
|
<ProjectConfiguration Include="Release|Win32"> |
||||
|
<Configuration>Release</Configuration> |
||||
|
<Platform>Win32</Platform> |
||||
|
</ProjectConfiguration> |
||||
|
</ItemGroup> |
||||
|
<PropertyGroup Label="Globals"> |
||||
|
<ProjectGuid>{6BF8FC22-9003-40F6-BF03-68A262C348BA}</ProjectGuid> |
||||
|
<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion> |
||||
|
</PropertyGroup> |
||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> |
||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> |
||||
|
<ConfigurationType>Application</ConfigurationType> |
||||
|
<UseOfMfc>false</UseOfMfc> |
||||
|
<PlatformToolset>v140</PlatformToolset> |
||||
|
</PropertyGroup> |
||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> |
||||
|
<ConfigurationType>Application</ConfigurationType> |
||||
|
<UseOfMfc>false</UseOfMfc> |
||||
|
<PlatformToolset>v140</PlatformToolset> |
||||
|
</PropertyGroup> |
||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> |
||||
|
<ImportGroup Label="ExtensionSettings"> |
||||
|
</ImportGroup> |
||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets"> |
||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> |
||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" /> |
||||
|
</ImportGroup> |
||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> |
||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> |
||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" /> |
||||
|
</ImportGroup> |
||||
|
<PropertyGroup Label="UserMacros" /> |
||||
|
<PropertyGroup> |
||||
|
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion> |
||||
|
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</OutDir> |
||||
|
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir> |
||||
|
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</OutDir> |
||||
|
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</IntDir> |
||||
|
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet> |
||||
|
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" /> |
||||
|
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" /> |
||||
|
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet> |
||||
|
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" /> |
||||
|
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" /> |
||||
|
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">UQE-Quake</TargetName> |
||||
|
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">UQE-Quake</TargetName> |
||||
|
</PropertyGroup> |
||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> |
||||
|
<LinkIncremental>false</LinkIncremental> |
||||
|
</PropertyGroup> |
||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> |
||||
|
<LinkIncremental>false</LinkIncremental> |
||||
|
</PropertyGroup> |
||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> |
||||
|
<Midl> |
||||
|
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
||||
|
<MkTypLibCompatible>true</MkTypLibCompatible> |
||||
|
<SuppressStartupBanner>true</SuppressStartupBanner> |
||||
|
<TargetEnvironment>Win32</TargetEnvironment> |
||||
|
<TypeLibraryName>$(TargetDir)/$(ProjectName).tlb</TypeLibraryName> |
||||
|
<HeaderFileName> |
||||
|
</HeaderFileName> |
||||
|
</Midl> |
||||
|
<ClCompile> |
||||
|
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_WINDOWS;GLQUAKE</PreprocessorDefinitions> |
||||
|
<PrecompiledHeaderOutputFile>.\Release\WinQuake.pch</PrecompiledHeaderOutputFile> |
||||
|
<AssemblerListingLocation>.\Release\</AssemblerListingLocation> |
||||
|
<ObjectFileName>.\Release\</ObjectFileName> |
||||
|
<ProgramDataBaseFileName>.\Release\</ProgramDataBaseFileName> |
||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> |
||||
|
<BrowseInformation>true</BrowseInformation> |
||||
|
</ClCompile> |
||||
|
<ResourceCompile> |
||||
|
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
||||
|
<Culture>0x0409</Culture> |
||||
|
</ResourceCompile> |
||||
|
<Link> |
||||
|
<OutputFile>.\Release\UQE-Quake.exe</OutputFile> |
||||
|
<GenerateDebugInformation>false</GenerateDebugInformation> |
||||
|
<SubSystem>Windows</SubSystem> |
||||
|
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;opengl32.lib;winmm.lib;wsock32.lib;glu32.lib</AdditionalDependencies> |
||||
|
</Link> |
||||
|
<Bscmake> |
||||
|
<SuppressStartupBanner>true</SuppressStartupBanner> |
||||
|
<OutputFile>$(TargetDir)/$(ProjectName).bsc</OutputFile> |
||||
|
</Bscmake> |
||||
|
</ItemDefinitionGroup> |
||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> |
||||
|
<Midl> |
||||
|
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
||||
|
<MkTypLibCompatible>true</MkTypLibCompatible> |
||||
|
<SuppressStartupBanner>true</SuppressStartupBanner> |
||||
|
<TargetEnvironment>Win32</TargetEnvironment> |
||||
|
<TypeLibraryName>$(TargetDir)/$(ProjectName).tlb</TypeLibraryName> |
||||
|
<HeaderFileName> |
||||
|
</HeaderFileName> |
||||
|
</Midl> |
||||
|
<ClCompile> |
||||
|
<PrecompiledHeaderOutputFile>.\Debug\WinQuake.pch</PrecompiledHeaderOutputFile> |
||||
|
<AssemblerListingLocation>.\Debug\</AssemblerListingLocation> |
||||
|
<ObjectFileName>.\Debug\</ObjectFileName> |
||||
|
<ProgramDataBaseFileName>.\Debug\</ProgramDataBaseFileName> |
||||
|
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;GLQUAKE</PreprocessorDefinitions> |
||||
|
<Optimization>Disabled</Optimization> |
||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> |
||||
|
<BrowseInformation>true</BrowseInformation> |
||||
|
</ClCompile> |
||||
|
<ResourceCompile> |
||||
|
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
||||
|
<Culture>0x0409</Culture> |
||||
|
</ResourceCompile> |
||||
|
<Link> |
||||
|
<OutputFile>.\Debug\UQE-Quake.exe</OutputFile> |
||||
|
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;opengl32.lib;winmm.lib;wsock32.lib;glu32.lib</AdditionalDependencies> |
||||
|
<SubSystem>Windows</SubSystem> |
||||
|
</Link> |
||||
|
<Bscmake> |
||||
|
<SuppressStartupBanner>true</SuppressStartupBanner> |
||||
|
<OutputFile>$(TargetDir)/$(ProjectName).bsc</OutputFile> |
||||
|
</Bscmake> |
||||
|
</ItemDefinitionGroup> |
||||
|
<ItemGroup> |
||||
|
<ClCompile Include="..\jpeg-6\jcapimin.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jccoefct.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jccolor.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jcdctmgr.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jchuff.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jcinit.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jcmainct.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jcmarker.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jcmaster.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jcomapi.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jcparam.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jcphuff.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jcprepct.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jcsample.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jctrans.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jdapimin.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jdapistd.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jdatadst.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jdatasrc.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jdcoefct.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jdcolor.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jddctmgr.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jdhuff.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jdinput.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jdmainct.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jdmarker.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jdmaster.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jdpostct.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jdsample.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jdtrans.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jerror.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jfdctflt.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jidctflt.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jmemmgr.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jmemnobs.c" /> |
||||
|
<ClCompile Include="..\jpeg-6\jutils.c" /> |
||||
|
<ClCompile Include="cd_win.c" /> |
||||
|
<ClCompile Include="cl_demo.c" /> |
||||
|
<ClCompile Include="cl_input.c" /> |
||||
|
<ClCompile Include="cl_main.c" /> |
||||
|
<ClCompile Include="cl_parse.c" /> |
||||
|
<ClCompile Include="cl_tent.c" /> |
||||
|
<ClCompile Include="cmd.c" /> |
||||
|
<ClCompile Include="common.c" /> |
||||
|
<ClCompile Include="conproc.c" /> |
||||
|
<ClCompile Include="console.c" /> |
||||
|
<ClCompile Include="crc.c" /> |
||||
|
<ClCompile Include="cvar.c" /> |
||||
|
<ClCompile Include="gl_draw.c" /> |
||||
|
<ClCompile Include="gl_fullbright.c" /> |
||||
|
<ClCompile Include="gl_mesh.c" /> |
||||
|
<ClCompile Include="gl_model.c" /> |
||||
|
<ClCompile Include="gl_refrag.c" /> |
||||
|
<ClCompile Include="gl_rlight.c" /> |
||||
|
<ClCompile Include="gl_rmain.c" /> |
||||
|
<ClCompile Include="gl_rmisc.c" /> |
||||
|
<ClCompile Include="gl_rsurf.c" /> |
||||
|
<ClCompile Include="gl_screen.c" /> |
||||
|
<ClCompile Include="gl_test.c" /> |
||||
|
<ClCompile Include="gl_vidnt.c" /> |
||||
|
<ClCompile Include="gl_warp.c" /> |
||||
|
<ClCompile Include="host.c" /> |
||||
|
<ClCompile Include="host_cmd.c" /> |
||||
|
<ClCompile Include="in_win.c" /> |
||||
|
<ClCompile Include="keys.c" /> |
||||
|
<ClCompile Include="mathlib.c" /> |
||||
|
<ClCompile Include="menu.c" /> |
||||
|
<ClCompile Include="net_dgrm.c" /> |
||||
|
<ClCompile Include="net_loop.c" /> |
||||
|
<ClCompile Include="net_main.c" /> |
||||
|
<ClCompile Include="net_vcr.c" /> |
||||
|
<ClCompile Include="net_win.c" /> |
||||
|
<ClCompile Include="net_wins.c" /> |
||||
|
<ClCompile Include="net_wipx.c" /> |
||||
|
<ClCompile Include="pr_cmds.c" /> |
||||
|
<ClCompile Include="pr_edict.c" /> |
||||
|
<ClCompile Include="pr_exec.c" /> |
||||
|
<ClCompile Include="r_part.c" /> |
||||
|
<ClCompile Include="sbar.c" /> |
||||
|
<ClCompile Include="snd_dma.c" /> |
||||
|
<ClCompile Include="snd_fmod.c" /> |
||||
|
<ClCompile Include="snd_mem.c" /> |
||||
|
<ClCompile Include="snd_mix.c" /> |
||||
|
<ClCompile Include="snd_win.c" /> |
||||
|
<ClCompile Include="sv_main.c" /> |
||||
|
<ClCompile Include="sv_move.c" /> |
||||
|
<ClCompile Include="sv_phys.c" /> |
||||
|
<ClCompile Include="sv_user.c" /> |
||||
|
<ClCompile Include="sys_win.c" /> |
||||
|
<ClCompile Include="unzip.c" /> |
||||
|
<ClCompile Include="vid_gamma.c" /> |
||||
|
<ClCompile Include="view.c" /> |
||||
|
<ClCompile Include="wad.c" /> |
||||
|
<ClCompile Include="world.c" /> |
||||
|
<ClCompile Include="zone.c" /> |
||||
|
</ItemGroup> |
||||
|
<ItemGroup> |
||||
|
<None Include="quake.bmp" /> |
||||
|
<None Include="quake.ico" /> |
||||
|
<None Include="progdefs.q1" /> |
||||
|
<None Include="progdefs.q2" /> |
||||
|
</ItemGroup> |
||||
|
<ItemGroup> |
||||
|
<ResourceCompile Include="winquake.rc" /> |
||||
|
</ItemGroup> |
||||
|
<ItemGroup> |
||||
|
<ClInclude Include="..\jpeg-6\jchuff.h" /> |
||||
|
<ClInclude Include="..\jpeg-6\jconfig.h" /> |
||||
|
<ClInclude Include="..\jpeg-6\jdct.h" /> |
||||
|
<ClInclude Include="..\jpeg-6\jdhuff.h" /> |
||||
|
<ClInclude Include="..\jpeg-6\jerror.h" /> |
||||
|
<ClInclude Include="..\jpeg-6\jinclude.h" /> |
||||
|
<ClInclude Include="..\jpeg-6\jmemsys.h" /> |
||||
|
<ClInclude Include="..\jpeg-6\jmorecfg.h" /> |
||||
|
<ClInclude Include="..\jpeg-6\jpegint.h" /> |
||||
|
<ClInclude Include="..\jpeg-6\jpeglib.h" /> |
||||
|
<ClInclude Include="..\jpeg-6\jversion.h" /> |
||||
|
<ClInclude Include="anorm_dots.h" /> |
||||
|
<ClInclude Include="anorms.h" /> |
||||
|
<ClInclude Include="bspfile.h" /> |
||||
|
<ClInclude Include="cdaudio.h" /> |
||||
|
<ClInclude Include="client.h" /> |
||||
|
<ClInclude Include="cmd.h" /> |
||||
|
<ClInclude Include="common.h" /> |
||||
|
<ClInclude Include="conproc.h" /> |
||||
|
<ClInclude Include="console.h" /> |
||||
|
<ClInclude Include="crc.h" /> |
||||
|
<ClInclude Include="cvar.h" /> |
||||
|
<ClInclude Include="draw.h" /> |
||||
|
<ClInclude Include="glext.h" /> |
||||
|
<ClInclude Include="gl_fullbright.h" /> |
||||
|
<ClInclude Include="gl_model.h" /> |
||||
|
<ClInclude Include="gl_warp_sin.h"> |
||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> |
||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> |
||||
|
</ClInclude> |
||||
|
<ClInclude Include="glquake.h" /> |
||||
|
<ClInclude Include="input.h" /> |
||||
|
<ClInclude Include="keys.h" /> |
||||
|
<ClInclude Include="mathlib.h" /> |
||||
|
<ClInclude Include="menu.h" /> |
||||
|
<ClInclude Include="modelgen.h" /> |
||||
|
<ClInclude Include="net.h" /> |
||||
|
<ClInclude Include="net_dgrm.h" /> |
||||
|
<ClInclude Include="net_loop.h" /> |
||||
|
<ClInclude Include="net_vcr.h" /> |
||||
|
<ClInclude Include="net_wins.h" /> |
||||
|
<ClInclude Include="net_wipx.h" /> |
||||
|
<ClInclude Include="pr_comp.h" /> |
||||
|
<ClInclude Include="progdefs.h" /> |
||||
|
<ClInclude Include="progs.h" /> |
||||
|
<ClInclude Include="protocol.h" /> |
||||
|
<ClInclude Include="quakedef.h" /> |
||||
|
<ClInclude Include="resource.h" /> |
||||
|
<ClInclude Include="render.h" /> |
||||
|
<ClInclude Include="sbar.h" /> |
||||
|
<ClInclude Include="screen.h" /> |
||||
|
<ClInclude Include="server.h" /> |
||||
|
<ClInclude Include="snd_fmod.h" /> |
||||
|
<ClInclude Include="sound.h" /> |
||||
|
<ClInclude Include="spritegn.h" /> |
||||
|
<ClInclude Include="sys.h" /> |
||||
|
<ClInclude Include="unzip.h" /> |
||||
|
<ClInclude Include="vid.h" /> |
||||
|
<ClInclude Include="vid_gamma.h" /> |
||||
|
<ClInclude Include="view.h" /> |
||||
|
<ClInclude Include="wad.h" /> |
||||
|
<ClInclude Include="wglext.h" /> |
||||
|
<ClInclude Include="winquake.h" /> |
||||
|
<ClInclude Include="world.h" /> |
||||
|
<ClInclude Include="zone.h" /> |
||||
|
</ItemGroup> |
||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> |
||||
|
<ImportGroup Label="ExtensionTargets"> |
||||
|
</ImportGroup> |
||||
|
</Project> |
||||
@ -0,0 +1,37 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
{ |
||||
|
{1.23,1.30,1.47,1.35,1.56,1.71,1.37,1.38,1.59,1.60,1.79,1.97,1.88,1.92,1.79,1.02,0.93,1.07,0.82,0.87,0.88,0.94,0.96,1.14,1.11,0.82,0.83,0.89,0.89,0.86,0.94,0.91,1.00,1.21,0.98,1.48,1.30,1.57,0.96,1.07,1.14,1.60,1.61,1.40,1.37,1.72,1.78,1.79,1.93,1.99,1.90,1.68,1.71,1.86,1.60,1.68,1.78,1.86,1.93,1.99,1.97,1.44,1.22,1.49,0.93,0.99,0.99,1.23,1.22,1.44,1.49,0.89,0.89,0.97,0.91,0.98,1.19,0.82,0.76,0.82,0.71,0.72,0.73,0.76,0.79,0.86,0.83,0.72,0.76,0.76,0.89,0.82,0.89,0.82,0.89,0.91,0.83,0.96,1.14,0.97,1.40,1.19,0.98,0.94,1.00,1.07,1.37,1.21,1.48,1.30,1.57,1.61,1.37,0.86,0.83,0.91,0.82,0.82,0.88,0.89,0.96,1.14,0.98,0.87,0.93,0.94,1.02,1.30,1.07,1.35,1.38,1.11,1.56,1.92,1.79,1.79,1.59,1.60,1.72,1.90,1.79,0.80,0.85,0.79,0.93,0.80,0.85,0.77,0.74,0.72,0.77,0.74,0.72,0.70,0.70,0.71,0.76,0.73,0.79,0.79,0.73,0.76,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, |
||||
|
{1.26,1.26,1.48,1.23,1.50,1.71,1.14,1.19,1.38,1.46,1.64,1.94,1.87,1.84,1.71,1.02,0.92,1.00,0.79,0.85,0.84,0.91,0.90,0.98,0.99,0.77,0.77,0.83,0.82,0.79,0.86,0.84,0.92,0.99,0.91,1.24,1.03,1.33,0.88,0.94,0.97,1.41,1.39,1.18,1.11,1.51,1.61,1.59,1.80,1.91,1.76,1.54,1.65,1.76,1.70,1.70,1.85,1.85,1.97,1.99,1.93,1.28,1.09,1.39,0.92,0.97,0.99,1.18,1.26,1.52,1.48,0.83,0.85,0.90,0.88,0.93,1.00,0.77,0.73,0.78,0.72,0.71,0.74,0.75,0.79,0.86,0.81,0.75,0.81,0.79,0.96,0.88,0.94,0.86,0.93,0.92,0.85,1.08,1.33,1.05,1.55,1.31,1.01,1.05,1.27,1.31,1.60,1.47,1.70,1.54,1.76,1.76,1.57,0.93,0.90,0.99,0.88,0.88,0.95,0.97,1.11,1.39,1.20,0.92,0.97,1.01,1.10,1.39,1.22,1.51,1.58,1.32,1.64,1.97,1.85,1.91,1.77,1.74,1.88,1.99,1.91,0.79,0.86,0.80,0.94,0.84,0.88,0.74,0.74,0.71,0.82,0.77,0.76,0.70,0.73,0.72,0.73,0.70,0.74,0.85,0.77,0.82,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, |
||||
|
{1.34,1.27,1.53,1.17,1.46,1.71,0.98,1.05,1.20,1.34,1.48,1.86,1.82,1.71,1.62,1.09,0.94,0.99,0.79,0.85,0.82,0.90,0.87,0.93,0.96,0.76,0.74,0.79,0.76,0.74,0.79,0.78,0.85,0.92,0.85,1.00,0.93,1.06,0.81,0.86,0.89,1.16,1.12,0.97,0.95,1.28,1.38,1.35,1.60,1.77,1.57,1.33,1.50,1.58,1.69,1.63,1.82,1.74,1.91,1.92,1.80,1.04,0.97,1.21,0.90,0.93,0.97,1.05,1.21,1.48,1.37,0.77,0.80,0.84,0.85,0.88,0.92,0.73,0.71,0.74,0.74,0.71,0.75,0.73,0.79,0.84,0.78,0.79,0.86,0.81,1.05,0.94,0.99,0.90,0.95,0.92,0.86,1.24,1.44,1.14,1.59,1.34,1.02,1.27,1.50,1.49,1.80,1.69,1.86,1.72,1.87,1.80,1.69,1.00,0.98,1.23,0.95,0.96,1.09,1.16,1.37,1.63,1.46,0.99,1.10,1.25,1.24,1.51,1.41,1.67,1.77,1.55,1.72,1.95,1.89,1.98,1.91,1.86,1.97,1.99,1.94,0.81,0.89,0.85,0.98,0.90,0.94,0.75,0.78,0.73,0.89,0.83,0.82,0.72,0.77,0.76,0.72,0.70,0.71,0.91,0.83,0.89,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, |
||||
|
{1.46,1.34,1.60,1.16,1.46,1.71,0.94,0.99,1.05,1.26,1.33,1.74,1.76,1.57,1.54,1.23,0.98,1.05,0.83,0.89,0.84,0.92,0.87,0.91,0.96,0.78,0.74,0.79,0.72,0.72,0.75,0.76,0.80,0.88,0.83,0.94,0.87,0.95,0.76,0.80,0.82,0.97,0.96,0.89,0.88,1.08,1.11,1.10,1.37,1.59,1.37,1.07,1.27,1.34,1.57,1.45,1.69,1.55,1.77,1.79,1.60,0.93,0.90,0.99,0.86,0.87,0.93,0.96,1.07,1.35,1.18,0.73,0.76,0.77,0.81,0.82,0.85,0.70,0.71,0.72,0.78,0.73,0.77,0.73,0.79,0.82,0.76,0.83,0.90,0.84,1.18,0.98,1.03,0.92,0.95,0.90,0.86,1.32,1.45,1.15,1.53,1.27,0.99,1.42,1.65,1.58,1.93,1.83,1.94,1.81,1.88,1.74,1.70,1.19,1.17,1.44,1.11,1.15,1.36,1.41,1.61,1.81,1.67,1.22,1.34,1.50,1.42,1.65,1.61,1.82,1.91,1.75,1.80,1.89,1.89,1.98,1.99,1.94,1.98,1.92,1.87,0.86,0.95,0.92,1.14,0.98,1.03,0.79,0.84,0.77,0.97,0.90,0.89,0.76,0.82,0.82,0.74,0.72,0.71,0.98,0.89,0.97,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, |
||||
|
{1.60,1.44,1.68,1.22,1.49,1.71,0.93,0.99,0.99,1.23,1.22,1.60,1.68,1.44,1.49,1.40,1.14,1.19,0.89,0.96,0.89,0.97,0.89,0.91,0.98,0.82,0.76,0.82,0.71,0.72,0.73,0.76,0.79,0.86,0.83,0.91,0.83,0.89,0.72,0.76,0.76,0.89,0.89,0.82,0.82,0.98,0.96,0.97,1.14,1.40,1.19,0.94,1.00,1.07,1.37,1.21,1.48,1.30,1.57,1.61,1.37,0.86,0.83,0.91,0.82,0.82,0.88,0.89,0.96,1.14,0.98,0.70,0.72,0.73,0.77,0.76,0.79,0.70,0.72,0.71,0.82,0.77,0.80,0.74,0.79,0.80,0.74,0.87,0.93,0.85,1.23,1.02,1.02,0.93,0.93,0.87,0.85,1.30,1.35,1.07,1.38,1.11,0.94,1.47,1.71,1.56,1.97,1.88,1.92,1.79,1.79,1.59,1.60,1.30,1.35,1.56,1.37,1.38,1.59,1.60,1.79,1.92,1.79,1.48,1.57,1.72,1.61,1.78,1.79,1.93,1.99,1.90,1.86,1.78,1.86,1.93,1.99,1.97,1.90,1.79,1.72,0.94,1.07,1.00,1.37,1.21,1.30,0.86,0.91,0.83,1.14,0.98,0.96,0.82,0.88,0.89,0.79,0.76,0.73,1.07,0.94,1.11,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, |
||||
|
{1.74,1.57,1.76,1.33,1.54,1.71,0.94,1.05,0.99,1.26,1.16,1.46,1.60,1.34,1.46,1.59,1.37,1.37,0.97,1.11,0.96,1.10,0.95,0.94,1.08,0.89,0.82,0.88,0.72,0.76,0.75,0.80,0.80,0.88,0.87,0.91,0.83,0.87,0.72,0.76,0.74,0.83,0.84,0.78,0.79,0.96,0.89,0.92,0.98,1.23,1.05,0.86,0.92,0.95,1.11,0.98,1.22,1.03,1.34,1.42,1.14,0.79,0.77,0.84,0.78,0.76,0.82,0.82,0.89,0.97,0.90,0.70,0.71,0.71,0.73,0.72,0.74,0.73,0.76,0.72,0.86,0.81,0.82,0.76,0.79,0.77,0.73,0.90,0.95,0.86,1.18,1.03,0.98,0.92,0.90,0.83,0.84,1.19,1.17,0.98,1.15,0.97,0.89,1.42,1.65,1.44,1.93,1.83,1.81,1.67,1.61,1.36,1.41,1.32,1.45,1.58,1.57,1.53,1.74,1.70,1.88,1.94,1.81,1.69,1.77,1.87,1.79,1.89,1.92,1.98,1.99,1.98,1.89,1.65,1.80,1.82,1.91,1.94,1.75,1.61,1.50,1.07,1.34,1.27,1.60,1.45,1.55,0.93,0.99,0.90,1.35,1.18,1.07,0.87,0.93,0.96,0.85,0.82,0.77,1.15,0.99,1.27,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, |
||||
|
{1.86,1.71,1.82,1.48,1.62,1.71,0.98,1.20,1.05,1.34,1.17,1.34,1.53,1.27,1.46,1.77,1.60,1.57,1.16,1.38,1.12,1.35,1.06,1.00,1.28,0.97,0.89,0.95,0.76,0.81,0.79,0.86,0.85,0.92,0.93,0.93,0.85,0.87,0.74,0.78,0.74,0.79,0.82,0.76,0.79,0.96,0.85,0.90,0.94,1.09,0.99,0.81,0.85,0.89,0.95,0.90,0.99,0.94,1.10,1.24,0.98,0.75,0.73,0.78,0.74,0.72,0.77,0.76,0.82,0.89,0.83,0.73,0.71,0.71,0.71,0.70,0.72,0.77,0.80,0.74,0.90,0.85,0.84,0.78,0.79,0.75,0.73,0.92,0.95,0.86,1.05,0.99,0.94,0.90,0.86,0.79,0.81,1.00,0.98,0.91,0.96,0.89,0.83,1.27,1.50,1.23,1.80,1.69,1.63,1.46,1.37,1.09,1.16,1.24,1.44,1.49,1.69,1.59,1.80,1.69,1.87,1.86,1.72,1.82,1.91,1.94,1.92,1.95,1.99,1.98,1.91,1.97,1.89,1.51,1.72,1.67,1.77,1.86,1.55,1.41,1.25,1.33,1.58,1.50,1.80,1.63,1.74,1.04,1.21,0.97,1.48,1.37,1.21,0.93,0.97,1.05,0.92,0.88,0.84,1.14,1.02,1.34,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, |
||||
|
{1.94,1.84,1.87,1.64,1.71,1.71,1.14,1.38,1.19,1.46,1.23,1.26,1.48,1.26,1.50,1.91,1.80,1.76,1.41,1.61,1.39,1.59,1.33,1.24,1.51,1.18,0.97,1.11,0.82,0.88,0.86,0.94,0.92,0.99,1.03,0.98,0.91,0.90,0.79,0.84,0.77,0.79,0.84,0.77,0.83,0.99,0.85,0.91,0.92,1.02,1.00,0.79,0.80,0.86,0.88,0.84,0.92,0.88,0.97,1.10,0.94,0.74,0.71,0.74,0.72,0.70,0.73,0.72,0.76,0.82,0.77,0.77,0.73,0.74,0.71,0.70,0.73,0.83,0.85,0.78,0.92,0.88,0.86,0.81,0.79,0.74,0.75,0.92,0.93,0.85,0.96,0.94,0.88,0.86,0.81,0.75,0.79,0.93,0.90,0.85,0.88,0.82,0.77,1.05,1.27,0.99,1.60,1.47,1.39,1.20,1.11,0.95,0.97,1.08,1.33,1.31,1.70,1.55,1.76,1.57,1.76,1.70,1.54,1.85,1.97,1.91,1.99,1.97,1.99,1.91,1.77,1.88,1.85,1.39,1.64,1.51,1.58,1.74,1.32,1.22,1.01,1.54,1.76,1.65,1.93,1.70,1.85,1.28,1.39,1.09,1.52,1.48,1.26,0.97,0.99,1.18,1.00,0.93,0.90,1.05,1.01,1.31,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, |
||||
|
{1.97,1.92,1.88,1.79,1.79,1.71,1.37,1.59,1.38,1.60,1.35,1.23,1.47,1.30,1.56,1.99,1.93,1.90,1.60,1.78,1.61,1.79,1.57,1.48,1.72,1.40,1.14,1.37,0.89,0.96,0.94,1.07,1.00,1.21,1.30,1.14,0.98,0.96,0.86,0.91,0.83,0.82,0.88,0.82,0.89,1.11,0.87,0.94,0.93,1.02,1.07,0.80,0.79,0.85,0.82,0.80,0.87,0.85,0.93,1.02,0.93,0.77,0.72,0.74,0.71,0.70,0.70,0.71,0.72,0.77,0.74,0.82,0.76,0.79,0.72,0.73,0.76,0.89,0.89,0.82,0.93,0.91,0.86,0.83,0.79,0.73,0.76,0.91,0.89,0.83,0.89,0.89,0.82,0.82,0.76,0.72,0.76,0.86,0.83,0.79,0.82,0.76,0.73,0.94,1.00,0.91,1.37,1.21,1.14,0.98,0.96,0.88,0.89,0.96,1.14,1.07,1.60,1.40,1.61,1.37,1.57,1.48,1.30,1.78,1.93,1.79,1.99,1.92,1.90,1.79,1.59,1.72,1.79,1.30,1.56,1.35,1.38,1.60,1.11,1.07,0.94,1.68,1.86,1.71,1.97,1.68,1.86,1.44,1.49,1.22,1.44,1.49,1.22,0.99,0.99,1.23,1.19,0.98,0.97,0.97,0.98,1.19,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, |
||||
|
{1.94,1.97,1.87,1.91,1.85,1.71,1.60,1.77,1.58,1.74,1.51,1.26,1.48,1.39,1.64,1.99,1.97,1.99,1.70,1.85,1.76,1.91,1.76,1.70,1.88,1.55,1.33,1.57,0.96,1.08,1.05,1.31,1.27,1.47,1.54,1.39,1.20,1.11,0.93,0.99,0.90,0.88,0.95,0.88,0.97,1.32,0.92,1.01,0.97,1.10,1.22,0.84,0.80,0.88,0.79,0.79,0.85,0.86,0.92,1.02,0.94,0.82,0.76,0.77,0.72,0.73,0.70,0.72,0.71,0.74,0.74,0.88,0.81,0.85,0.75,0.77,0.82,0.94,0.93,0.86,0.92,0.92,0.86,0.85,0.79,0.74,0.79,0.88,0.85,0.81,0.82,0.83,0.77,0.78,0.73,0.71,0.75,0.79,0.77,0.74,0.77,0.73,0.70,0.86,0.92,0.84,1.14,0.99,0.98,0.91,0.90,0.84,0.83,0.88,0.97,0.94,1.41,1.18,1.39,1.11,1.33,1.24,1.03,1.61,1.80,1.59,1.91,1.84,1.76,1.64,1.38,1.51,1.71,1.26,1.50,1.23,1.19,1.46,0.99,1.00,0.91,1.70,1.85,1.65,1.93,1.54,1.76,1.52,1.48,1.26,1.28,1.39,1.09,0.99,0.97,1.18,1.31,1.01,1.05,0.90,0.93,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, |
||||
|
{1.86,1.95,1.82,1.98,1.89,1.71,1.80,1.91,1.77,1.86,1.67,1.34,1.53,1.51,1.72,1.92,1.91,1.99,1.69,1.82,1.80,1.94,1.87,1.86,1.97,1.59,1.44,1.69,1.05,1.24,1.27,1.49,1.50,1.69,1.72,1.63,1.46,1.37,1.00,1.23,0.98,0.95,1.09,0.96,1.16,1.55,0.99,1.25,1.10,1.24,1.41,0.90,0.85,0.94,0.79,0.81,0.85,0.89,0.94,1.09,0.98,0.89,0.82,0.83,0.74,0.77,0.72,0.76,0.73,0.75,0.78,0.94,0.86,0.91,0.79,0.83,0.89,0.99,0.95,0.90,0.90,0.92,0.84,0.86,0.79,0.75,0.81,0.85,0.80,0.78,0.76,0.77,0.73,0.74,0.71,0.71,0.73,0.74,0.74,0.71,0.76,0.72,0.70,0.79,0.85,0.78,0.98,0.92,0.93,0.85,0.87,0.82,0.79,0.81,0.89,0.86,1.16,0.97,1.12,0.95,1.06,1.00,0.93,1.38,1.60,1.35,1.77,1.71,1.57,1.48,1.20,1.28,1.62,1.27,1.46,1.17,1.05,1.34,0.96,0.99,0.90,1.63,1.74,1.50,1.80,1.33,1.58,1.48,1.37,1.21,1.04,1.21,0.97,0.97,0.93,1.05,1.34,1.02,1.14,0.84,0.88,0.92,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, |
||||
|
{1.74,1.89,1.76,1.98,1.89,1.71,1.93,1.99,1.91,1.94,1.82,1.46,1.60,1.65,1.80,1.79,1.77,1.92,1.57,1.69,1.74,1.87,1.88,1.94,1.98,1.53,1.45,1.70,1.18,1.32,1.42,1.58,1.65,1.83,1.81,1.81,1.67,1.61,1.19,1.44,1.17,1.11,1.36,1.15,1.41,1.75,1.22,1.50,1.34,1.42,1.61,0.98,0.92,1.03,0.83,0.86,0.89,0.95,0.98,1.23,1.14,0.97,0.89,0.90,0.78,0.82,0.76,0.82,0.77,0.79,0.84,0.98,0.90,0.98,0.83,0.89,0.97,1.03,0.95,0.92,0.86,0.90,0.82,0.86,0.79,0.77,0.84,0.81,0.76,0.76,0.72,0.73,0.70,0.72,0.71,0.73,0.73,0.72,0.74,0.71,0.78,0.74,0.72,0.75,0.80,0.76,0.94,0.88,0.91,0.83,0.87,0.84,0.79,0.76,0.82,0.80,0.97,0.89,0.96,0.88,0.95,0.94,0.87,1.11,1.37,1.10,1.59,1.57,1.37,1.33,1.05,1.08,1.54,1.34,1.46,1.16,0.99,1.26,0.96,1.05,0.92,1.45,1.55,1.27,1.60,1.07,1.34,1.35,1.18,1.07,0.93,0.99,0.90,0.93,0.87,0.96,1.27,0.99,1.15,0.77,0.82,0.85,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, |
||||
|
{1.60,1.78,1.68,1.93,1.86,1.71,1.97,1.99,1.99,1.97,1.93,1.60,1.68,1.78,1.86,1.61,1.57,1.79,1.37,1.48,1.59,1.72,1.79,1.92,1.90,1.38,1.35,1.60,1.23,1.30,1.47,1.56,1.71,1.88,1.79,1.92,1.79,1.79,1.30,1.56,1.35,1.37,1.59,1.38,1.60,1.90,1.48,1.72,1.57,1.61,1.79,1.21,1.00,1.30,0.89,0.94,0.96,1.07,1.14,1.40,1.37,1.14,0.96,0.98,0.82,0.88,0.82,0.89,0.83,0.86,0.91,1.02,0.93,1.07,0.87,0.94,1.11,1.02,0.93,0.93,0.82,0.87,0.80,0.85,0.79,0.80,0.85,0.77,0.72,0.74,0.71,0.70,0.70,0.71,0.72,0.77,0.74,0.72,0.76,0.73,0.82,0.79,0.76,0.73,0.79,0.76,0.93,0.86,0.91,0.83,0.89,0.89,0.82,0.72,0.76,0.76,0.89,0.82,0.89,0.82,0.89,0.91,0.83,0.96,1.14,0.97,1.40,1.44,1.19,1.22,0.99,0.98,1.49,1.44,1.49,1.22,0.99,1.23,0.98,1.19,0.97,1.21,1.30,1.00,1.37,0.94,1.07,1.14,0.98,0.96,0.86,0.91,0.83,0.88,0.82,0.89,1.11,0.94,1.07,0.73,0.76,0.79,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, |
||||
|
{1.46,1.65,1.60,1.82,1.80,1.71,1.93,1.91,1.99,1.94,1.98,1.74,1.76,1.89,1.89,1.42,1.34,1.61,1.11,1.22,1.36,1.50,1.61,1.81,1.75,1.15,1.17,1.41,1.18,1.19,1.42,1.44,1.65,1.83,1.67,1.94,1.81,1.88,1.32,1.58,1.45,1.57,1.74,1.53,1.70,1.98,1.69,1.87,1.77,1.79,1.92,1.45,1.27,1.55,0.97,1.07,1.11,1.34,1.37,1.59,1.60,1.35,1.07,1.18,0.86,0.93,0.87,0.96,0.90,0.93,0.99,1.03,0.95,1.15,0.90,0.99,1.27,0.98,0.90,0.92,0.78,0.83,0.77,0.84,0.79,0.82,0.86,0.73,0.71,0.73,0.72,0.70,0.73,0.72,0.76,0.81,0.76,0.76,0.82,0.77,0.89,0.85,0.82,0.75,0.80,0.80,0.94,0.88,0.94,0.87,0.95,0.96,0.88,0.72,0.74,0.76,0.83,0.78,0.84,0.79,0.87,0.91,0.83,0.89,0.98,0.92,1.23,1.34,1.05,1.16,0.99,0.96,1.46,1.57,1.54,1.33,1.05,1.26,1.08,1.37,1.10,0.98,1.03,0.92,1.14,0.86,0.95,0.97,0.90,0.89,0.79,0.84,0.77,0.82,0.76,0.82,0.97,0.89,0.98,0.71,0.72,0.74,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, |
||||
|
{1.34,1.51,1.53,1.67,1.72,1.71,1.80,1.77,1.91,1.86,1.98,1.86,1.82,1.95,1.89,1.24,1.10,1.41,0.95,0.99,1.09,1.25,1.37,1.63,1.55,0.96,0.98,1.16,1.05,1.00,1.27,1.23,1.50,1.69,1.46,1.86,1.72,1.87,1.24,1.49,1.44,1.69,1.80,1.59,1.69,1.97,1.82,1.94,1.91,1.92,1.99,1.63,1.50,1.74,1.16,1.33,1.38,1.58,1.60,1.77,1.80,1.48,1.21,1.37,0.90,0.97,0.93,1.05,0.97,1.04,1.21,0.99,0.95,1.14,0.92,1.02,1.34,0.94,0.86,0.90,0.74,0.79,0.75,0.81,0.79,0.84,0.86,0.71,0.71,0.73,0.76,0.73,0.77,0.74,0.80,0.85,0.78,0.81,0.89,0.84,0.97,0.92,0.88,0.79,0.85,0.86,0.98,0.92,1.00,0.93,1.06,1.12,0.95,0.74,0.74,0.78,0.79,0.76,0.82,0.79,0.87,0.93,0.85,0.85,0.94,0.90,1.09,1.27,0.99,1.17,1.05,0.96,1.46,1.71,1.62,1.48,1.20,1.34,1.28,1.57,1.35,0.90,0.94,0.85,0.98,0.81,0.89,0.89,0.83,0.82,0.75,0.78,0.73,0.77,0.72,0.76,0.89,0.83,0.91,0.71,0.70,0.72,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, |
||||
|
{1.26,1.39,1.48,1.51,1.64,1.71,1.60,1.58,1.77,1.74,1.91,1.94,1.87,1.97,1.85,1.10,0.97,1.22,0.88,0.92,0.95,1.01,1.11,1.39,1.32,0.88,0.90,0.97,0.96,0.93,1.05,0.99,1.27,1.47,1.20,1.70,1.54,1.76,1.08,1.31,1.33,1.70,1.76,1.55,1.57,1.88,1.85,1.91,1.97,1.99,1.99,1.70,1.65,1.85,1.41,1.54,1.61,1.76,1.80,1.91,1.93,1.52,1.26,1.48,0.92,0.99,0.97,1.18,1.09,1.28,1.39,0.94,0.93,1.05,0.92,1.01,1.31,0.88,0.81,0.86,0.72,0.75,0.74,0.79,0.79,0.86,0.85,0.71,0.73,0.75,0.82,0.77,0.83,0.78,0.85,0.88,0.81,0.88,0.97,0.90,1.18,1.00,0.93,0.86,0.92,0.94,1.14,0.99,1.24,1.03,1.33,1.39,1.11,0.79,0.77,0.84,0.79,0.77,0.84,0.83,0.90,0.98,0.91,0.85,0.92,0.91,1.02,1.26,1.00,1.23,1.19,0.99,1.50,1.84,1.71,1.64,1.38,1.46,1.51,1.76,1.59,0.84,0.88,0.80,0.94,0.79,0.86,0.82,0.77,0.76,0.74,0.74,0.71,0.73,0.70,0.72,0.82,0.77,0.85,0.74,0.70,0.73,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00} |
||||
|
} |
||||
@ -0,0 +1,181 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
{-0.525731, 0.000000, 0.850651}, |
||||
|
{-0.442863, 0.238856, 0.864188}, |
||||
|
{-0.295242, 0.000000, 0.955423}, |
||||
|
{-0.309017, 0.500000, 0.809017}, |
||||
|
{-0.162460, 0.262866, 0.951056}, |
||||
|
{0.000000, 0.000000, 1.000000}, |
||||
|
{0.000000, 0.850651, 0.525731}, |
||||
|
{-0.147621, 0.716567, 0.681718}, |
||||
|
{0.147621, 0.716567, 0.681718}, |
||||
|
{0.000000, 0.525731, 0.850651}, |
||||
|
{0.309017, 0.500000, 0.809017}, |
||||
|
{0.525731, 0.000000, 0.850651}, |
||||
|
{0.295242, 0.000000, 0.955423}, |
||||
|
{0.442863, 0.238856, 0.864188}, |
||||
|
{0.162460, 0.262866, 0.951056}, |
||||
|
{-0.681718, 0.147621, 0.716567}, |
||||
|
{-0.809017, 0.309017, 0.500000}, |
||||
|
{-0.587785, 0.425325, 0.688191}, |
||||
|
{-0.850651, 0.525731, 0.000000}, |
||||
|
{-0.864188, 0.442863, 0.238856}, |
||||
|
{-0.716567, 0.681718, 0.147621}, |
||||
|
{-0.688191, 0.587785, 0.425325}, |
||||
|
{-0.500000, 0.809017, 0.309017}, |
||||
|
{-0.238856, 0.864188, 0.442863}, |
||||
|
{-0.425325, 0.688191, 0.587785}, |
||||
|
{-0.716567, 0.681718, -0.147621}, |
||||
|
{-0.500000, 0.809017, -0.309017}, |
||||
|
{-0.525731, 0.850651, 0.000000}, |
||||
|
{0.000000, 0.850651, -0.525731}, |
||||
|
{-0.238856, 0.864188, -0.442863}, |
||||
|
{0.000000, 0.955423, -0.295242}, |
||||
|
{-0.262866, 0.951056, -0.162460}, |
||||
|
{0.000000, 1.000000, 0.000000}, |
||||
|
{0.000000, 0.955423, 0.295242}, |
||||
|
{-0.262866, 0.951056, 0.162460}, |
||||
|
{0.238856, 0.864188, 0.442863}, |
||||
|
{0.262866, 0.951056, 0.162460}, |
||||
|
{0.500000, 0.809017, 0.309017}, |
||||
|
{0.238856, 0.864188, -0.442863}, |
||||
|
{0.262866, 0.951056, -0.162460}, |
||||
|
{0.500000, 0.809017, -0.309017}, |
||||
|
{0.850651, 0.525731, 0.000000}, |
||||
|
{0.716567, 0.681718, 0.147621}, |
||||
|
{0.716567, 0.681718, -0.147621}, |
||||
|
{0.525731, 0.850651, 0.000000}, |
||||
|
{0.425325, 0.688191, 0.587785}, |
||||
|
{0.864188, 0.442863, 0.238856}, |
||||
|
{0.688191, 0.587785, 0.425325}, |
||||
|
{0.809017, 0.309017, 0.500000}, |
||||
|
{0.681718, 0.147621, 0.716567}, |
||||
|
{0.587785, 0.425325, 0.688191}, |
||||
|
{0.955423, 0.295242, 0.000000}, |
||||
|
{1.000000, 0.000000, 0.000000}, |
||||
|
{0.951056, 0.162460, 0.262866}, |
||||
|
{0.850651, -0.525731, 0.000000}, |
||||
|
{0.955423, -0.295242, 0.000000}, |
||||
|
{0.864188, -0.442863, 0.238856}, |
||||
|
{0.951056, -0.162460, 0.262866}, |
||||
|
{0.809017, -0.309017, 0.500000}, |
||||
|
{0.681718, -0.147621, 0.716567}, |
||||
|
{0.850651, 0.000000, 0.525731}, |
||||
|
{0.864188, 0.442863, -0.238856}, |
||||
|
{0.809017, 0.309017, -0.500000}, |
||||
|
{0.951056, 0.162460, -0.262866}, |
||||
|
{0.525731, 0.000000, -0.850651}, |
||||
|
{0.681718, 0.147621, -0.716567}, |
||||
|
{0.681718, -0.147621, -0.716567}, |
||||
|
{0.850651, 0.000000, -0.525731}, |
||||
|
{0.809017, -0.309017, -0.500000}, |
||||
|
{0.864188, -0.442863, -0.238856}, |
||||
|
{0.951056, -0.162460, -0.262866}, |
||||
|
{0.147621, 0.716567, -0.681718}, |
||||
|
{0.309017, 0.500000, -0.809017}, |
||||
|
{0.425325, 0.688191, -0.587785}, |
||||
|
{0.442863, 0.238856, -0.864188}, |
||||
|
{0.587785, 0.425325, -0.688191}, |
||||
|
{0.688191, 0.587785, -0.425325}, |
||||
|
{-0.147621, 0.716567, -0.681718}, |
||||
|
{-0.309017, 0.500000, -0.809017}, |
||||
|
{0.000000, 0.525731, -0.850651}, |
||||
|
{-0.525731, 0.000000, -0.850651}, |
||||
|
{-0.442863, 0.238856, -0.864188}, |
||||
|
{-0.295242, 0.000000, -0.955423}, |
||||
|
{-0.162460, 0.262866, -0.951056}, |
||||
|
{0.000000, 0.000000, -1.000000}, |
||||
|
{0.295242, 0.000000, -0.955423}, |
||||
|
{0.162460, 0.262866, -0.951056}, |
||||
|
{-0.442863, -0.238856, -0.864188}, |
||||
|
{-0.309017, -0.500000, -0.809017}, |
||||
|
{-0.162460, -0.262866, -0.951056}, |
||||
|
{0.000000, -0.850651, -0.525731}, |
||||
|
{-0.147621, -0.716567, -0.681718}, |
||||
|
{0.147621, -0.716567, -0.681718}, |
||||
|
{0.000000, -0.525731, -0.850651}, |
||||
|
{0.309017, -0.500000, -0.809017}, |
||||
|
{0.442863, -0.238856, -0.864188}, |
||||
|
{0.162460, -0.262866, -0.951056}, |
||||
|
{0.238856, -0.864188, -0.442863}, |
||||
|
{0.500000, -0.809017, -0.309017}, |
||||
|
{0.425325, -0.688191, -0.587785}, |
||||
|
{0.716567, -0.681718, -0.147621}, |
||||
|
{0.688191, -0.587785, -0.425325}, |
||||
|
{0.587785, -0.425325, -0.688191}, |
||||
|
{0.000000, -0.955423, -0.295242}, |
||||
|
{0.000000, -1.000000, 0.000000}, |
||||
|
{0.262866, -0.951056, -0.162460}, |
||||
|
{0.000000, -0.850651, 0.525731}, |
||||
|
{0.000000, -0.955423, 0.295242}, |
||||
|
{0.238856, -0.864188, 0.442863}, |
||||
|
{0.262866, -0.951056, 0.162460}, |
||||
|
{0.500000, -0.809017, 0.309017}, |
||||
|
{0.716567, -0.681718, 0.147621}, |
||||
|
{0.525731, -0.850651, 0.000000}, |
||||
|
{-0.238856, -0.864188, -0.442863}, |
||||
|
{-0.500000, -0.809017, -0.309017}, |
||||
|
{-0.262866, -0.951056, -0.162460}, |
||||
|
{-0.850651, -0.525731, 0.000000}, |
||||
|
{-0.716567, -0.681718, -0.147621}, |
||||
|
{-0.716567, -0.681718, 0.147621}, |
||||
|
{-0.525731, -0.850651, 0.000000}, |
||||
|
{-0.500000, -0.809017, 0.309017}, |
||||
|
{-0.238856, -0.864188, 0.442863}, |
||||
|
{-0.262866, -0.951056, 0.162460}, |
||||
|
{-0.864188, -0.442863, 0.238856}, |
||||
|
{-0.809017, -0.309017, 0.500000}, |
||||
|
{-0.688191, -0.587785, 0.425325}, |
||||
|
{-0.681718, -0.147621, 0.716567}, |
||||
|
{-0.442863, -0.238856, 0.864188}, |
||||
|
{-0.587785, -0.425325, 0.688191}, |
||||
|
{-0.309017, -0.500000, 0.809017}, |
||||
|
{-0.147621, -0.716567, 0.681718}, |
||||
|
{-0.425325, -0.688191, 0.587785}, |
||||
|
{-0.162460, -0.262866, 0.951056}, |
||||
|
{0.442863, -0.238856, 0.864188}, |
||||
|
{0.162460, -0.262866, 0.951056}, |
||||
|
{0.309017, -0.500000, 0.809017}, |
||||
|
{0.147621, -0.716567, 0.681718}, |
||||
|
{0.000000, -0.525731, 0.850651}, |
||||
|
{0.425325, -0.688191, 0.587785}, |
||||
|
{0.587785, -0.425325, 0.688191}, |
||||
|
{0.688191, -0.587785, 0.425325}, |
||||
|
{-0.955423, 0.295242, 0.000000}, |
||||
|
{-0.951056, 0.162460, 0.262866}, |
||||
|
{-1.000000, 0.000000, 0.000000}, |
||||
|
{-0.850651, 0.000000, 0.525731}, |
||||
|
{-0.955423, -0.295242, 0.000000}, |
||||
|
{-0.951056, -0.162460, 0.262866}, |
||||
|
{-0.864188, 0.442863, -0.238856}, |
||||
|
{-0.951056, 0.162460, -0.262866}, |
||||
|
{-0.809017, 0.309017, -0.500000}, |
||||
|
{-0.864188, -0.442863, -0.238856}, |
||||
|
{-0.951056, -0.162460, -0.262866}, |
||||
|
{-0.809017, -0.309017, -0.500000}, |
||||
|
{-0.681718, 0.147621, -0.716567}, |
||||
|
{-0.681718, -0.147621, -0.716567}, |
||||
|
{-0.850651, 0.000000, -0.525731}, |
||||
|
{-0.688191, 0.587785, -0.425325}, |
||||
|
{-0.587785, 0.425325, -0.688191}, |
||||
|
{-0.425325, 0.688191, -0.587785}, |
||||
|
{-0.425325, -0.688191, -0.587785}, |
||||
|
{-0.587785, -0.425325, -0.688191}, |
||||
|
{-0.688191, -0.587785, -0.425325}, |
||||
@ -0,0 +1,324 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
|
||||
|
// upper design bounds |
||||
|
|
||||
|
#define MAX_MAP_HULLS 4 |
||||
|
|
||||
|
#define MAX_MAP_MODELS 1024 // jkrige - design bounds : 256 |
||||
|
#define MAX_MAP_BRUSHES 8192 // jkrige - design bounds : 4096 |
||||
|
#define MAX_MAP_ENTITIES 2048 // jkrige - design bounds : 1024 |
||||
|
#define MAX_MAP_ENTSTRING 0x40000 // jkrige - design bounds : 65536 |
||||
|
|
||||
|
#define MAX_MAP_PLANES 65536 // jkrige - design bounds : 32767 |
||||
|
#define MAX_MAP_NODES 65536 // jkrige - design bounds : 32767 // because negative shorts are contents |
||||
|
#define MAX_MAP_CLIPNODES 65536 // jkrige - design bounds : 32767 // |
||||
|
#define MAX_MAP_LEAFS 16384 // jkrige - design bounds : 8192 |
||||
|
#define MAX_MAP_VERTS 65535 |
||||
|
#define MAX_MAP_FACES 65535 |
||||
|
#define MAX_MAP_MARKSURFACES 65535 |
||||
|
#define MAX_MAP_TEXINFO 8192 // jkrige - design bounds : 4096 |
||||
|
#define MAX_MAP_EDGES 256000 |
||||
|
#define MAX_MAP_SURFEDGES 512000 |
||||
|
#define MAX_MAP_TEXTURES 1024 // jkrige - design bounds : 512 |
||||
|
#define MAX_MAP_MIPTEX 0x400000 // jkrige - design bounds : 0x200000 |
||||
|
#define MAX_MAP_LIGHTING 0x200000 // jkrige - design bounds : 0x100000 |
||||
|
#define MAX_MAP_VISIBILITY 0x200000 // jkrige - design bounds : 0x100000 |
||||
|
|
||||
|
#define MAX_MAP_PORTALS 65536 |
||||
|
|
||||
|
// key / value pair sizes |
||||
|
|
||||
|
#define MAX_KEY 32 |
||||
|
#define MAX_VALUE 1024 |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
|
||||
|
#define BSPVERSION 29 |
||||
|
#define TOOLVERSION 2 |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
int fileofs, filelen; |
||||
|
} lump_t; |
||||
|
|
||||
|
#define LUMP_ENTITIES 0 |
||||
|
#define LUMP_PLANES 1 |
||||
|
#define LUMP_TEXTURES 2 |
||||
|
#define LUMP_VERTEXES 3 |
||||
|
#define LUMP_VISIBILITY 4 |
||||
|
#define LUMP_NODES 5 |
||||
|
#define LUMP_TEXINFO 6 |
||||
|
#define LUMP_FACES 7 |
||||
|
#define LUMP_LIGHTING 8 |
||||
|
#define LUMP_CLIPNODES 9 |
||||
|
#define LUMP_LEAFS 10 |
||||
|
#define LUMP_MARKSURFACES 11 |
||||
|
#define LUMP_EDGES 12 |
||||
|
#define LUMP_SURFEDGES 13 |
||||
|
#define LUMP_MODELS 14 |
||||
|
|
||||
|
#define HEADER_LUMPS 15 |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
float mins[3], maxs[3]; |
||||
|
float origin[3]; |
||||
|
int headnode[MAX_MAP_HULLS]; |
||||
|
int visleafs; // not including the solid leaf 0 |
||||
|
int firstface, numfaces; |
||||
|
} dmodel_t; |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
int version; |
||||
|
lump_t lumps[HEADER_LUMPS]; |
||||
|
} dheader_t; |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
int nummiptex; |
||||
|
int dataofs[4]; // [nummiptex] |
||||
|
} dmiptexlump_t; |
||||
|
|
||||
|
#define MIPLEVELS 4 |
||||
|
typedef struct miptex_s |
||||
|
{ |
||||
|
char name[16]; |
||||
|
unsigned width, height; |
||||
|
unsigned offsets[MIPLEVELS]; // four mip maps stored |
||||
|
} miptex_t; |
||||
|
|
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
float point[3]; |
||||
|
} dvertex_t; |
||||
|
|
||||
|
|
||||
|
// 0-2 are axial planes |
||||
|
#define PLANE_X 0 |
||||
|
#define PLANE_Y 1 |
||||
|
#define PLANE_Z 2 |
||||
|
|
||||
|
// 3-5 are non-axial planes snapped to the nearest |
||||
|
#define PLANE_ANYX 3 |
||||
|
#define PLANE_ANYY 4 |
||||
|
#define PLANE_ANYZ 5 |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
float normal[3]; |
||||
|
float dist; |
||||
|
int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate |
||||
|
} dplane_t; |
||||
|
|
||||
|
|
||||
|
|
||||
|
#define CONTENTS_EMPTY -1 |
||||
|
#define CONTENTS_SOLID -2 |
||||
|
#define CONTENTS_WATER -3 |
||||
|
#define CONTENTS_SLIME -4 |
||||
|
#define CONTENTS_LAVA -5 |
||||
|
#define CONTENTS_SKY -6 |
||||
|
#define CONTENTS_ORIGIN -7 // removed at csg time |
||||
|
#define CONTENTS_CLIP -8 // changed to contents_solid |
||||
|
|
||||
|
#define CONTENTS_CURRENT_0 -9 |
||||
|
#define CONTENTS_CURRENT_90 -10 |
||||
|
#define CONTENTS_CURRENT_180 -11 |
||||
|
#define CONTENTS_CURRENT_270 -12 |
||||
|
#define CONTENTS_CURRENT_UP -13 |
||||
|
#define CONTENTS_CURRENT_DOWN -14 |
||||
|
|
||||
|
|
||||
|
// !!! if this is changed, it must be changed in asm_i386.h too !!! |
||||
|
typedef struct |
||||
|
{ |
||||
|
int planenum; |
||||
|
short children[2]; // negative numbers are -(leafs+1), not nodes |
||||
|
short mins[3]; // for sphere culling |
||||
|
short maxs[3]; |
||||
|
unsigned short firstface; |
||||
|
unsigned short numfaces; // counting both sides |
||||
|
} dnode_t; |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
int planenum; |
||||
|
short children[2]; // negative numbers are contents |
||||
|
} dclipnode_t; |
||||
|
|
||||
|
|
||||
|
typedef struct texinfo_s |
||||
|
{ |
||||
|
float vecs[2][4]; // [s/t][xyz offset] |
||||
|
int miptex; |
||||
|
int flags; |
||||
|
} texinfo_t; |
||||
|
#define TEX_SPECIAL 1 // sky or slime, no lightmap or 256 subdivision |
||||
|
|
||||
|
// note that edge 0 is never used, because negative edge nums are used for |
||||
|
// counterclockwise use of the edge in a face |
||||
|
typedef struct |
||||
|
{ |
||||
|
unsigned short v[2]; // vertex numbers |
||||
|
} dedge_t; |
||||
|
|
||||
|
#define MAXLIGHTMAPS 4 |
||||
|
typedef struct |
||||
|
{ |
||||
|
short planenum; |
||||
|
short side; |
||||
|
|
||||
|
int firstedge; // we must support > 64k edges |
||||
|
short numedges; |
||||
|
short texinfo; |
||||
|
|
||||
|
// lighting info |
||||
|
byte styles[MAXLIGHTMAPS]; |
||||
|
int lightofs; // start of [numstyles*surfsize] samples |
||||
|
} dface_t; |
||||
|
|
||||
|
|
||||
|
|
||||
|
#define AMBIENT_WATER 0 |
||||
|
#define AMBIENT_SKY 1 |
||||
|
#define AMBIENT_SLIME 2 |
||||
|
#define AMBIENT_LAVA 3 |
||||
|
|
||||
|
#define NUM_AMBIENTS 4 // automatic ambient sounds |
||||
|
|
||||
|
// leaf 0 is the generic CONTENTS_SOLID leaf, used for all solid areas |
||||
|
// all other leafs need visibility info |
||||
|
typedef struct |
||||
|
{ |
||||
|
int contents; |
||||
|
int visofs; // -1 = no visibility info |
||||
|
|
||||
|
short mins[3]; // for frustum culling |
||||
|
short maxs[3]; |
||||
|
|
||||
|
unsigned short firstmarksurface; |
||||
|
unsigned short nummarksurfaces; |
||||
|
|
||||
|
byte ambient_level[NUM_AMBIENTS]; |
||||
|
} dleaf_t; |
||||
|
|
||||
|
|
||||
|
//============================================================================ |
||||
|
|
||||
|
#ifndef QUAKE_GAME |
||||
|
|
||||
|
#define ANGLE_UP -1 |
||||
|
#define ANGLE_DOWN -2 |
||||
|
|
||||
|
|
||||
|
// the utilities get to be lazy and just use large static arrays |
||||
|
|
||||
|
extern int nummodels; |
||||
|
extern dmodel_t dmodels[MAX_MAP_MODELS]; |
||||
|
|
||||
|
extern int visdatasize; |
||||
|
extern byte dvisdata[MAX_MAP_VISIBILITY]; |
||||
|
|
||||
|
extern int lightdatasize; |
||||
|
extern byte dlightdata[MAX_MAP_LIGHTING]; |
||||
|
|
||||
|
extern int texdatasize; |
||||
|
extern byte dtexdata[MAX_MAP_MIPTEX]; // (dmiptexlump_t) |
||||
|
|
||||
|
extern int entdatasize; |
||||
|
extern char dentdata[MAX_MAP_ENTSTRING]; |
||||
|
|
||||
|
extern int numleafs; |
||||
|
extern dleaf_t dleafs[MAX_MAP_LEAFS]; |
||||
|
|
||||
|
extern int numplanes; |
||||
|
extern dplane_t dplanes[MAX_MAP_PLANES]; |
||||
|
|
||||
|
extern int numvertexes; |
||||
|
extern dvertex_t dvertexes[MAX_MAP_VERTS]; |
||||
|
|
||||
|
extern int numnodes; |
||||
|
extern dnode_t dnodes[MAX_MAP_NODES]; |
||||
|
|
||||
|
extern int numtexinfo; |
||||
|
extern texinfo_t texinfo[MAX_MAP_TEXINFO]; |
||||
|
|
||||
|
extern int numfaces; |
||||
|
extern dface_t dfaces[MAX_MAP_FACES]; |
||||
|
|
||||
|
extern int numclipnodes; |
||||
|
extern dclipnode_t dclipnodes[MAX_MAP_CLIPNODES]; |
||||
|
|
||||
|
extern int numedges; |
||||
|
extern dedge_t dedges[MAX_MAP_EDGES]; |
||||
|
|
||||
|
extern int nummarksurfaces; |
||||
|
extern unsigned short dmarksurfaces[MAX_MAP_MARKSURFACES]; |
||||
|
|
||||
|
extern int numsurfedges; |
||||
|
extern int dsurfedges[MAX_MAP_SURFEDGES]; |
||||
|
|
||||
|
|
||||
|
void DecompressVis (byte *in, byte *decompressed); |
||||
|
int CompressVis (byte *vis, byte *dest); |
||||
|
|
||||
|
void LoadBSPFile (char *filename); |
||||
|
void WriteBSPFile (char *filename); |
||||
|
void PrintBSPFileSizes (void); |
||||
|
|
||||
|
//=============== |
||||
|
|
||||
|
|
||||
|
typedef struct epair_s |
||||
|
{ |
||||
|
struct epair_s *next; |
||||
|
char *key; |
||||
|
char *value; |
||||
|
} epair_t; |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
vec3_t origin; |
||||
|
int firstbrush; |
||||
|
int numbrushes; |
||||
|
epair_t *epairs; |
||||
|
} entity_t; |
||||
|
|
||||
|
extern int num_entities; |
||||
|
extern entity_t entities[MAX_MAP_ENTITIES]; |
||||
|
|
||||
|
void ParseEntities (void); |
||||
|
void UnparseEntities (void); |
||||
|
|
||||
|
void SetKeyValue (entity_t *ent, char *key, char *value); |
||||
|
char *ValueForKey (entity_t *ent, char *key); |
||||
|
// will return "" if not present |
||||
|
|
||||
|
vec_t FloatForKey (entity_t *ent, char *key); |
||||
|
void GetVectorForKey (entity_t *ent, char *key, vec3_t vec); |
||||
|
|
||||
|
epair_t *ParseEpair (void); |
||||
|
|
||||
|
#endif |
||||
@ -0,0 +1,595 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All |
||||
|
// rights reserved. |
||||
|
|
||||
|
|
||||
|
#include "quakedef.h" |
||||
|
|
||||
|
#ifndef UQE_FMOD_CDAUDIO |
||||
|
#include <windows.h> |
||||
|
|
||||
|
extern HWND mainwindow; |
||||
|
extern cvar_t bgmvolume; |
||||
|
|
||||
|
static qboolean cdValid = false; |
||||
|
static qboolean playing = false; |
||||
|
static qboolean wasPlaying = false; |
||||
|
static qboolean initialized = false; |
||||
|
static qboolean enabled = false; |
||||
|
static qboolean playLooping = false; |
||||
|
static float cdvolume; |
||||
|
static byte remap[100]; |
||||
|
static byte cdrom; |
||||
|
static byte playTrack; |
||||
|
static byte maxTrack; |
||||
|
|
||||
|
// jkrige - cd audio volume fix |
||||
|
static UINT CD_ID; |
||||
|
static unsigned long CD_OrigVolume; |
||||
|
// jkrige - cd audio volume fix |
||||
|
|
||||
|
UINT wDeviceID; |
||||
|
|
||||
|
// jkrige - CD Resume |
||||
|
static DWORD end_pos; |
||||
|
// jkrige - CD Resume |
||||
|
|
||||
|
|
||||
|
static void CDAudio_Eject(void) |
||||
|
{ |
||||
|
DWORD dwReturn; |
||||
|
|
||||
|
if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_OPEN, (DWORD)NULL)) |
||||
|
Con_DPrintf("MCI_SET_DOOR_OPEN failed (%i)\n", dwReturn); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
static void CDAudio_CloseDoor(void) |
||||
|
{ |
||||
|
DWORD dwReturn; |
||||
|
|
||||
|
if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_CLOSED, (DWORD)NULL)) |
||||
|
Con_DPrintf("MCI_SET_DOOR_CLOSED failed (%i)\n", dwReturn); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
static int CDAudio_GetAudioDiskInfo(void) |
||||
|
{ |
||||
|
DWORD dwReturn; |
||||
|
MCI_STATUS_PARMS mciStatusParms; |
||||
|
|
||||
|
|
||||
|
cdValid = false; |
||||
|
|
||||
|
mciStatusParms.dwItem = MCI_STATUS_READY; |
||||
|
dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms); |
||||
|
if (dwReturn) |
||||
|
{ |
||||
|
Con_DPrintf("CDAudio: drive ready test - get status failed\n"); |
||||
|
return -1; |
||||
|
} |
||||
|
if (!mciStatusParms.dwReturn) |
||||
|
{ |
||||
|
Con_DPrintf("CDAudio: drive not ready\n"); |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
mciStatusParms.dwItem = MCI_STATUS_NUMBER_OF_TRACKS; |
||||
|
dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms); |
||||
|
if (dwReturn) |
||||
|
{ |
||||
|
Con_DPrintf("CDAudio: get tracks - status failed\n"); |
||||
|
return -1; |
||||
|
} |
||||
|
if (mciStatusParms.dwReturn < 1) |
||||
|
{ |
||||
|
Con_DPrintf("CDAudio: no music tracks\n"); |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
cdValid = true; |
||||
|
maxTrack = mciStatusParms.dwReturn; |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void CDAudio_Play(byte track, qboolean looping) |
||||
|
{ |
||||
|
DWORD dwReturn; |
||||
|
MCI_PLAY_PARMS mciPlayParms; |
||||
|
MCI_STATUS_PARMS mciStatusParms; |
||||
|
|
||||
|
if (!enabled) |
||||
|
return; |
||||
|
|
||||
|
if (!cdValid) |
||||
|
{ |
||||
|
CDAudio_GetAudioDiskInfo(); |
||||
|
if (!cdValid) |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
track = remap[track]; |
||||
|
|
||||
|
if (track < 1 || track > maxTrack) |
||||
|
{ |
||||
|
Con_DPrintf("CDAudio: Bad track number %u.\n", track); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// don't try to play a non-audio track |
||||
|
mciStatusParms.dwItem = MCI_CDA_STATUS_TYPE_TRACK; |
||||
|
mciStatusParms.dwTrack = track; |
||||
|
dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms); |
||||
|
if (dwReturn) |
||||
|
{ |
||||
|
Con_DPrintf("MCI_STATUS failed (%i)\n", dwReturn); |
||||
|
return; |
||||
|
} |
||||
|
if (mciStatusParms.dwReturn != MCI_CDA_TRACK_AUDIO) |
||||
|
{ |
||||
|
Con_Printf("CDAudio: track %i is not audio\n", track); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// get the length of the track to be played |
||||
|
mciStatusParms.dwItem = MCI_STATUS_LENGTH; |
||||
|
mciStatusParms.dwTrack = track; |
||||
|
dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms); |
||||
|
if (dwReturn) |
||||
|
{ |
||||
|
Con_DPrintf("MCI_STATUS failed (%i)\n", dwReturn); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (playing) |
||||
|
{ |
||||
|
if (playTrack == track) |
||||
|
return; |
||||
|
CDAudio_Stop(); |
||||
|
} |
||||
|
|
||||
|
mciPlayParms.dwFrom = MCI_MAKE_TMSF(track, 0, 0, 0); |
||||
|
mciPlayParms.dwTo = (mciStatusParms.dwReturn << 8) | track; |
||||
|
|
||||
|
// jkrige - CD Resume |
||||
|
end_pos = mciPlayParms.dwTo; |
||||
|
// jkrige - CD Resume |
||||
|
|
||||
|
mciPlayParms.dwCallback = (DWORD)mainwindow; |
||||
|
dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY | MCI_FROM | MCI_TO, (DWORD)(LPVOID) &mciPlayParms); |
||||
|
if (dwReturn) |
||||
|
{ |
||||
|
Con_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
playLooping = looping; |
||||
|
playTrack = track; |
||||
|
playing = true; |
||||
|
|
||||
|
if (cdvolume == 0.0) |
||||
|
CDAudio_Pause (); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void CDAudio_Stop(void) |
||||
|
{ |
||||
|
DWORD dwReturn; |
||||
|
|
||||
|
if (!enabled) |
||||
|
return; |
||||
|
|
||||
|
if (!playing) |
||||
|
return; |
||||
|
|
||||
|
if (dwReturn = mciSendCommand(wDeviceID, MCI_STOP, 0, (DWORD)NULL)) |
||||
|
Con_DPrintf("MCI_STOP failed (%i)", dwReturn); |
||||
|
|
||||
|
wasPlaying = false; |
||||
|
playing = false; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void CDAudio_Pause(void) |
||||
|
{ |
||||
|
DWORD dwReturn; |
||||
|
MCI_GENERIC_PARMS mciGenericParms; |
||||
|
|
||||
|
if (!enabled) |
||||
|
return; |
||||
|
|
||||
|
if (!playing) |
||||
|
return; |
||||
|
|
||||
|
mciGenericParms.dwCallback = (DWORD)mainwindow; |
||||
|
if (dwReturn = mciSendCommand(wDeviceID, MCI_PAUSE, 0, (DWORD)(LPVOID) &mciGenericParms)) |
||||
|
Con_DPrintf("MCI_PAUSE failed (%i)", dwReturn); |
||||
|
|
||||
|
wasPlaying = playing; |
||||
|
playing = false; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void CDAudio_Resume(void) |
||||
|
{ |
||||
|
DWORD dwReturn; |
||||
|
|
||||
|
// jkrige - CD Resume |
||||
|
MCI_STATUS_PARMS mciStatusParms; |
||||
|
// jkrige - CD Resume |
||||
|
|
||||
|
MCI_PLAY_PARMS mciPlayParms; |
||||
|
|
||||
|
if (!enabled) |
||||
|
return; |
||||
|
|
||||
|
if (!cdValid) |
||||
|
return; |
||||
|
|
||||
|
if (!wasPlaying) |
||||
|
return; |
||||
|
|
||||
|
// jkrige - CD Resume |
||||
|
//mciPlayParms.dwFrom = MCI_MAKE_TMSF(playTrack, 0, 0, 0); |
||||
|
//mciPlayParms.dwTo = MCI_MAKE_TMSF(playTrack + 1, 0, 0, 0); |
||||
|
//mciPlayParms.dwCallback = (DWORD)mainwindow; |
||||
|
//dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_TO | MCI_NOTIFY, (DWORD)(LPVOID) &mciPlayParms); |
||||
|
|
||||
|
mciStatusParms.dwItem = MCI_STATUS_POSITION; |
||||
|
dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD_PTR) (LPVOID) &mciStatusParms); |
||||
|
if (dwReturn) |
||||
|
{ |
||||
|
Con_DPrintf("MCI_STATUS failed (%i)\n", dwReturn); |
||||
|
return; |
||||
|
} |
||||
|
mciPlayParms.dwFrom = mciStatusParms.dwReturn; |
||||
|
mciPlayParms.dwTo = end_pos; // set in CDAudio_Play() |
||||
|
mciPlayParms.dwCallback = (DWORD_PTR)mainwindow; |
||||
|
dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_FROM | MCI_TO | MCI_NOTIFY, (DWORD_PTR)(LPVOID) &mciPlayParms); |
||||
|
// jkrige - CD Resume |
||||
|
|
||||
|
|
||||
|
if (dwReturn) |
||||
|
{ |
||||
|
Con_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn); |
||||
|
return; |
||||
|
} |
||||
|
playing = true; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
static void CD_f (void) |
||||
|
{ |
||||
|
char *command; |
||||
|
int ret; |
||||
|
int n; |
||||
|
int startAddress; |
||||
|
|
||||
|
if (Cmd_Argc() < 2) |
||||
|
return; |
||||
|
|
||||
|
command = Cmd_Argv (1); |
||||
|
|
||||
|
if (Q_strcasecmp(command, "on") == 0) |
||||
|
{ |
||||
|
enabled = true; |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (Q_strcasecmp(command, "off") == 0) |
||||
|
{ |
||||
|
if (playing) |
||||
|
CDAudio_Stop(); |
||||
|
enabled = false; |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (Q_strcasecmp(command, "reset") == 0) |
||||
|
{ |
||||
|
enabled = true; |
||||
|
if (playing) |
||||
|
CDAudio_Stop(); |
||||
|
for (n = 0; n < 100; n++) |
||||
|
remap[n] = n; |
||||
|
CDAudio_GetAudioDiskInfo(); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (Q_strcasecmp(command, "remap") == 0) |
||||
|
{ |
||||
|
ret = Cmd_Argc() - 2; |
||||
|
if (ret <= 0) |
||||
|
{ |
||||
|
for (n = 1; n < 100; n++) |
||||
|
if (remap[n] != n) |
||||
|
Con_Printf(" %u -> %u\n", n, remap[n]); |
||||
|
return; |
||||
|
} |
||||
|
for (n = 1; n <= ret; n++) |
||||
|
remap[n] = Q_atoi(Cmd_Argv (n+1)); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (Q_strcasecmp(command, "close") == 0) |
||||
|
{ |
||||
|
CDAudio_CloseDoor(); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (!cdValid) |
||||
|
{ |
||||
|
CDAudio_GetAudioDiskInfo(); |
||||
|
if (!cdValid) |
||||
|
{ |
||||
|
Con_Printf("No CD in player.\n"); |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (Q_strcasecmp(command, "play") == 0) |
||||
|
{ |
||||
|
CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), false); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (Q_strcasecmp(command, "loop") == 0) |
||||
|
{ |
||||
|
CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), true); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (Q_strcasecmp(command, "stop") == 0) |
||||
|
{ |
||||
|
CDAudio_Stop(); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (Q_strcasecmp(command, "pause") == 0) |
||||
|
{ |
||||
|
CDAudio_Pause(); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (Q_strcasecmp(command, "resume") == 0) |
||||
|
{ |
||||
|
CDAudio_Resume(); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (Q_strcasecmp(command, "eject") == 0) |
||||
|
{ |
||||
|
if (playing) |
||||
|
CDAudio_Stop(); |
||||
|
CDAudio_Eject(); |
||||
|
cdValid = false; |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (Q_strcasecmp(command, "info") == 0) |
||||
|
{ |
||||
|
Con_Printf("%u tracks\n", maxTrack); |
||||
|
if (playing) |
||||
|
Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack); |
||||
|
else if (wasPlaying) |
||||
|
Con_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack); |
||||
|
Con_Printf("Volume is %f\n", cdvolume); |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) |
||||
|
{ |
||||
|
if (lParam != wDeviceID) |
||||
|
return 1; |
||||
|
|
||||
|
switch (wParam) |
||||
|
{ |
||||
|
case MCI_NOTIFY_SUCCESSFUL: |
||||
|
if (playing) |
||||
|
{ |
||||
|
playing = false; |
||||
|
if (playLooping) |
||||
|
CDAudio_Play(playTrack, true); |
||||
|
} |
||||
|
break; |
||||
|
|
||||
|
case MCI_NOTIFY_ABORTED: |
||||
|
case MCI_NOTIFY_SUPERSEDED: |
||||
|
break; |
||||
|
|
||||
|
case MCI_NOTIFY_FAILURE: |
||||
|
Con_DPrintf("MCI_NOTIFY_FAILURE\n"); |
||||
|
CDAudio_Stop (); |
||||
|
cdValid = false; |
||||
|
break; |
||||
|
|
||||
|
default: |
||||
|
Con_DPrintf("Unexpected MM_MCINOTIFY type (%i)\n", wParam); |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
// jkrige - cd audio volume fix |
||||
|
void CD_SetVolume(unsigned long Volume) |
||||
|
{ |
||||
|
if (CD_ID != -1) |
||||
|
auxSetVolume(CD_ID,(Volume<<16)+Volume); |
||||
|
} |
||||
|
|
||||
|
void CD_FindCDAux(void) |
||||
|
{ |
||||
|
UINT NumDevs,counter; |
||||
|
MMRESULT Result; |
||||
|
AUXCAPS Caps; |
||||
|
|
||||
|
CD_ID = -1; |
||||
|
if (!COM_CheckParm("-usecdvolume")) |
||||
|
return; |
||||
|
NumDevs = auxGetNumDevs(); |
||||
|
for(counter=0;counter<NumDevs;counter++) |
||||
|
{ |
||||
|
Result = auxGetDevCaps(counter,&Caps,sizeof(Caps)); |
||||
|
if (!Result) // valid |
||||
|
{ |
||||
|
if (Caps.wTechnology == AUXCAPS_CDAUDIO) |
||||
|
{ |
||||
|
CD_ID = counter; |
||||
|
auxGetVolume(CD_ID,&CD_OrigVolume); |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void CDAudio_Update(void) |
||||
|
{ |
||||
|
if (!enabled) |
||||
|
return; |
||||
|
|
||||
|
if (bgmvolume.value != cdvolume) |
||||
|
CD_SetVolume(bgmvolume.value * 0xffff); |
||||
|
|
||||
|
if ((!bgmvolume.value && cdvolume) || |
||||
|
(bgmvolume.value && !cdvolume)) |
||||
|
{ |
||||
|
if (cdvolume) |
||||
|
{ |
||||
|
// Cvar_SetValue ("bgmvolume", 0.0); |
||||
|
CDAudio_Pause (); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
// Cvar_SetValue ("bgmvolume", 1.0); |
||||
|
CDAudio_Resume (); |
||||
|
} |
||||
|
} |
||||
|
cdvolume = bgmvolume.value; |
||||
|
} |
||||
|
/*void CDAudio_Update(void) |
||||
|
{ |
||||
|
if (!enabled) |
||||
|
return; |
||||
|
|
||||
|
if (bgmvolume.value != cdvolume) |
||||
|
{ |
||||
|
if (cdvolume) |
||||
|
{ |
||||
|
Cvar_SetValue ("bgmvolume", 0.0); |
||||
|
cdvolume = bgmvolume.value; |
||||
|
CDAudio_Pause (); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
Cvar_SetValue ("bgmvolume", 1.0); |
||||
|
cdvolume = bgmvolume.value; |
||||
|
CDAudio_Resume (); |
||||
|
} |
||||
|
} |
||||
|
}*/ |
||||
|
// jkrige - cd audio volume fix |
||||
|
|
||||
|
int CDAudio_Init(void) |
||||
|
{ |
||||
|
DWORD dwReturn; |
||||
|
MCI_OPEN_PARMS mciOpenParms; |
||||
|
MCI_SET_PARMS mciSetParms; |
||||
|
int n; |
||||
|
|
||||
|
if (cls.state == ca_dedicated) |
||||
|
return -1; |
||||
|
|
||||
|
if (COM_CheckParm("-nocdaudio")) |
||||
|
return -1; |
||||
|
|
||||
|
mciOpenParms.lpstrDeviceType = "cdaudio"; |
||||
|
if (dwReturn = mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_SHAREABLE, (DWORD) (LPVOID) &mciOpenParms)) |
||||
|
{ |
||||
|
Con_Printf("CDAudio_Init: MCI_OPEN failed (%i)\n", dwReturn); |
||||
|
return -1; |
||||
|
} |
||||
|
wDeviceID = mciOpenParms.wDeviceID; |
||||
|
|
||||
|
// Set the time format to track/minute/second/frame (TMSF). |
||||
|
mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF; |
||||
|
if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD)(LPVOID) &mciSetParms)) |
||||
|
{ |
||||
|
Con_Printf("MCI_SET_TIME_FORMAT failed (%i)\n", dwReturn); |
||||
|
mciSendCommand(wDeviceID, MCI_CLOSE, 0, (DWORD)NULL); |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
for (n = 0; n < 100; n++) |
||||
|
remap[n] = n; |
||||
|
initialized = true; |
||||
|
enabled = true; |
||||
|
|
||||
|
if (CDAudio_GetAudioDiskInfo()) |
||||
|
{ |
||||
|
Con_Printf("CDAudio_Init: No CD in player.\n"); |
||||
|
cdValid = false; |
||||
|
} |
||||
|
|
||||
|
Cmd_AddCommand ("cd", CD_f); |
||||
|
|
||||
|
// jkrige - cd audio volume fix |
||||
|
CD_FindCDAux(); |
||||
|
// jkrige - cd audio volume fix |
||||
|
|
||||
|
Con_Printf("CD Audio Initialized\n"); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void CDAudio_Shutdown(void) |
||||
|
{ |
||||
|
if (!initialized) |
||||
|
return; |
||||
|
CDAudio_Stop(); |
||||
|
if (mciSendCommand(wDeviceID, MCI_CLOSE, MCI_WAIT, (DWORD)NULL)) |
||||
|
Con_DPrintf("CDAudio_Shutdown: MCI_CLOSE failed\n"); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
// jkrige - fmod sound system - begin |
||||
|
/* |
||||
|
=========== |
||||
|
CDAudio_Activate |
||||
|
|
||||
|
Called when the main window gains or loses focus. |
||||
|
The window have been destroyed and recreated |
||||
|
between a deactivate and an activate. |
||||
|
=========== |
||||
|
*/ |
||||
|
void CDAudio_Activate(qboolean active) |
||||
|
{ |
||||
|
if (active) |
||||
|
CDAudio_Resume(); |
||||
|
else |
||||
|
CDAudio_Pause(); |
||||
|
} |
||||
|
// jkrige - fmod sound system - end |
||||
|
#endif |
||||
@ -0,0 +1,33 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
#ifndef UQE_FMOD_CDAUDIO |
||||
|
|
||||
|
int CDAudio_Init(void); |
||||
|
void CDAudio_Play(byte track, qboolean looping); |
||||
|
void CDAudio_Stop(void); |
||||
|
void CDAudio_Pause(void); |
||||
|
void CDAudio_Resume(void); |
||||
|
void CDAudio_Shutdown(void); |
||||
|
void CDAudio_Update(void); |
||||
|
|
||||
|
void CDAudio_Activate(qboolean active); // jkrige - fmod sound system |
||||
|
|
||||
|
#endif |
||||
@ -0,0 +1,595 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
#include "quakedef.h" |
||||
|
|
||||
|
// jkrige - fix demo playback across maps |
||||
|
// Pa3PyX: new variable |
||||
|
int stufftext_frame; |
||||
|
// jkrige - fix demo playback across maps |
||||
|
|
||||
|
void CL_FinishTimeDemo (void); |
||||
|
|
||||
|
/* |
||||
|
============================================================================== |
||||
|
|
||||
|
DEMO CODE |
||||
|
|
||||
|
When a demo is playing back, all NET_SendMessages are skipped, and |
||||
|
NET_GetMessages are read from the demo file. |
||||
|
|
||||
|
Whenever cl.time gets past the last received message, another message is |
||||
|
read from the demo file. |
||||
|
============================================================================== |
||||
|
*/ |
||||
|
|
||||
|
/* |
||||
|
============== |
||||
|
CL_StopPlayback |
||||
|
|
||||
|
Called when a demo file runs out, or the user starts a game |
||||
|
============== |
||||
|
*/ |
||||
|
void CL_StopPlayback (void) |
||||
|
{ |
||||
|
if (!cls.demoplayback) |
||||
|
return; |
||||
|
|
||||
|
cls.demoplayback = false; |
||||
|
cls.state = ca_disconnected; |
||||
|
|
||||
|
|
||||
|
// jkrige - pk3 file support |
||||
|
//fclose (cls.demofile); |
||||
|
//cls.demofile = NULL; |
||||
|
|
||||
|
if(cls.demobuffer) |
||||
|
free(cls.demobuffer); |
||||
|
|
||||
|
cls.demobuffer = NULL; |
||||
|
cls.demobufferposition = 0; |
||||
|
cls.demobufferlength = 0; |
||||
|
// jkrige - pk3 file support |
||||
|
|
||||
|
|
||||
|
if (cls.timedemo) |
||||
|
CL_FinishTimeDemo (); |
||||
|
|
||||
|
|
||||
|
// jkrige - fmod sound system - begin |
||||
|
// stop demo music playback |
||||
|
#ifdef UQE_FMOD |
||||
|
FMOD_MusicStop(); |
||||
|
#else |
||||
|
CDAudio_Stop(); |
||||
|
#endif |
||||
|
// jkrige - fmod sound system - end |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
==================== |
||||
|
CL_WriteDemoMessage |
||||
|
|
||||
|
Dumps the current net message, prefixed by the length and view angles |
||||
|
==================== |
||||
|
*/ |
||||
|
void CL_WriteDemoMessage (void) |
||||
|
{ |
||||
|
int len; |
||||
|
int i; |
||||
|
float f; |
||||
|
|
||||
|
len = LittleLong (net_message.cursize); |
||||
|
fwrite (&len, 4, 1, cls.demofile); |
||||
|
for (i=0 ; i<3 ; i++) |
||||
|
{ |
||||
|
f = LittleFloat (cl.viewangles[i]); |
||||
|
fwrite (&f, 4, 1, cls.demofile); |
||||
|
} |
||||
|
fwrite (net_message.data, net_message.cursize, 1, cls.demofile); |
||||
|
fflush (cls.demofile); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
==================== |
||||
|
CL_GetMessage |
||||
|
|
||||
|
Handles recording and playback of demos, on top of NET_ code |
||||
|
==================== |
||||
|
*/ |
||||
|
// jkrige - pk3 file support |
||||
|
/*int CL_GetMessage (void) |
||||
|
{ |
||||
|
int r, i; |
||||
|
float f; |
||||
|
|
||||
|
if (cls.demoplayback) |
||||
|
{ |
||||
|
// decide if it is time to grab the next message |
||||
|
if (cls.signon == SIGNONS) // always grab until fully connected |
||||
|
{ |
||||
|
// jkrige - fix demo playback across maps |
||||
|
// Pa3PyX: always wait for full frame update on stuff |
||||
|
// messages. If the server stuffs a reconnect, |
||||
|
// we must wait for the client to re-initialize |
||||
|
// before accepting further messages. Otherwise |
||||
|
// demo playback may freeze. |
||||
|
if (stufftext_frame == host_framecount) { |
||||
|
return 0; |
||||
|
} |
||||
|
// jkrige - fix demo playback across maps |
||||
|
|
||||
|
if (cls.timedemo) |
||||
|
{ |
||||
|
if (host_framecount == cls.td_lastframe) |
||||
|
return 0; // allready read this frame's message |
||||
|
cls.td_lastframe = host_framecount; |
||||
|
// if this is the second frame, grab the real td_starttime |
||||
|
// so the bogus time on the first frame doesn't count |
||||
|
if (host_framecount == cls.td_startframe + 1) |
||||
|
cls.td_starttime = realtime; |
||||
|
} |
||||
|
else if (cl.time <= cl.mtime[0]) // cl.time > 0 && |
||||
|
{ |
||||
|
return 0; // don't need another message yet |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// get the next message |
||||
|
fread (&net_message.cursize, 4, 1, cls.demofile); |
||||
|
VectorCopy (cl.mviewangles[0], cl.mviewangles[1]); |
||||
|
for (i=0 ; i<3 ; i++) |
||||
|
{ |
||||
|
r = fread (&f, 4, 1, cls.demofile); |
||||
|
cl.mviewangles[0][i] = LittleFloat (f); |
||||
|
} |
||||
|
|
||||
|
net_message.cursize = LittleLong (net_message.cursize); |
||||
|
if (net_message.cursize > MAX_MSGLEN) |
||||
|
Sys_Error ("Demo message > MAX_MSGLEN"); |
||||
|
r = fread (net_message.data, net_message.cursize, 1, cls.demofile); |
||||
|
if (r != 1) |
||||
|
{ |
||||
|
CL_StopPlayback (); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
while (1) |
||||
|
{ |
||||
|
r = NET_GetMessage (cls.netcon); |
||||
|
|
||||
|
if (r != 1 && r != 2) |
||||
|
return r; |
||||
|
|
||||
|
// discard nop keepalive message |
||||
|
if (net_message.cursize == 1 && net_message.data[0] == svc_nop) |
||||
|
Con_Printf ("<-- server to client keepalive\n"); |
||||
|
else |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
if (cls.demorecording) |
||||
|
CL_WriteDemoMessage (); |
||||
|
|
||||
|
return r; |
||||
|
}*/ |
||||
|
|
||||
|
int CL_GetMessage (void) |
||||
|
{ |
||||
|
int r, i; |
||||
|
float f; |
||||
|
|
||||
|
if (cls.demoplayback) |
||||
|
{ |
||||
|
// decide if it is time to grab the next message |
||||
|
if (cls.signon == SIGNONS) // always grab until fully connected |
||||
|
{ |
||||
|
// jkrige - fix demo playback across maps |
||||
|
// Pa3PyX: always wait for full frame update on stuff |
||||
|
// messages. If the server stuffs a reconnect, |
||||
|
// we must wait for the client to re-initialize |
||||
|
// before accepting further messages. Otherwise |
||||
|
// demo playback may freeze. |
||||
|
if (stufftext_frame == host_framecount) { |
||||
|
return 0; |
||||
|
} |
||||
|
// jkrige - fix demo playback across maps |
||||
|
|
||||
|
if (cls.timedemo) |
||||
|
{ |
||||
|
if (host_framecount == cls.td_lastframe) |
||||
|
return 0; // allready read this frame's message |
||||
|
cls.td_lastframe = host_framecount; |
||||
|
// if this is the second frame, grab the real td_starttime |
||||
|
// so the bogus time on the first frame doesn't count |
||||
|
if (host_framecount == cls.td_startframe + 1) |
||||
|
cls.td_starttime = realtime; |
||||
|
} |
||||
|
else if (/* cl.time > 0 && */ cl.time <= cl.mtime[0]) |
||||
|
{ |
||||
|
return 0; // don't need another message yet |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// get the next message |
||||
|
|
||||
|
//fread (&net_message.cursize, 4, 1, cls.demofile); |
||||
|
net_message.cursize = ( (cls.demobuffer[cls.demobufferposition + 3] << 24) + (cls.demobuffer[cls.demobufferposition + 2] << 16) + (cls.demobuffer[cls.demobufferposition + 1] << 8) + (cls.demobuffer[cls.demobufferposition + 0]) ); |
||||
|
cls.demobufferposition += 4; |
||||
|
net_message.cursize = LittleLong (net_message.cursize); |
||||
|
|
||||
|
VectorCopy (cl.mviewangles[0], cl.mviewangles[1]); |
||||
|
for (i=0 ; i<3 ; i++) |
||||
|
{ |
||||
|
//r = fread (&f, 4, 1, cls.demofile); |
||||
|
memcpy(&f, &cls.demobuffer[cls.demobufferposition], 4); |
||||
|
cls.demobufferposition += 4; |
||||
|
cl.mviewangles[0][i] = LittleFloat (f); |
||||
|
} |
||||
|
|
||||
|
if (net_message.cursize > MAX_MSGLEN) |
||||
|
Sys_Error ("Demo message > MAX_MSGLEN"); |
||||
|
|
||||
|
//r = fread (net_message.data, net_message.cursize, 1, cls.demofile); |
||||
|
//if (r != 1) |
||||
|
//{ |
||||
|
// CL_StopPlayback (); |
||||
|
// return 0; |
||||
|
//} |
||||
|
|
||||
|
if(net_message.cursize == 0 || net_message.cursize > (cls.demobufferlength - cls.demobufferposition)) |
||||
|
{ |
||||
|
CL_StopPlayback (); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
for(i = 0; i < net_message.cursize; i++) |
||||
|
{ |
||||
|
net_message.data[i] = cls.demobuffer[cls.demobufferposition++]; |
||||
|
} |
||||
|
|
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
while (1) |
||||
|
{ |
||||
|
r = NET_GetMessage (cls.netcon); |
||||
|
|
||||
|
if (r != 1 && r != 2) |
||||
|
return r; |
||||
|
|
||||
|
// discard nop keepalive message |
||||
|
if (net_message.cursize == 1 && net_message.data[0] == svc_nop) |
||||
|
Con_Printf ("<-- server to client keepalive\n"); |
||||
|
else |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
if (cls.demorecording) |
||||
|
CL_WriteDemoMessage (); |
||||
|
|
||||
|
return r; |
||||
|
} |
||||
|
// jkrige - pk3 file support |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
==================== |
||||
|
CL_Stop_f |
||||
|
|
||||
|
stop recording a demo |
||||
|
==================== |
||||
|
*/ |
||||
|
void CL_Stop_f (void) |
||||
|
{ |
||||
|
if (cmd_source != src_command) |
||||
|
return; |
||||
|
|
||||
|
if (!cls.demorecording) |
||||
|
{ |
||||
|
Con_Printf ("Not recording a demo.\n"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// write a disconnect message to the demo file |
||||
|
SZ_Clear (&net_message); |
||||
|
MSG_WriteByte (&net_message, svc_disconnect); |
||||
|
CL_WriteDemoMessage (); |
||||
|
|
||||
|
// finish up |
||||
|
fclose (cls.demofile); |
||||
|
cls.demofile = NULL; |
||||
|
cls.demorecording = false; |
||||
|
Con_Printf ("Completed demo\n"); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
==================== |
||||
|
CL_Record_f |
||||
|
|
||||
|
record <demoname> <map> [cd track] |
||||
|
==================== |
||||
|
*/ |
||||
|
void CL_Record_f (void) |
||||
|
{ |
||||
|
int c; |
||||
|
char name[MAX_OSPATH]; |
||||
|
int track; |
||||
|
|
||||
|
if (cmd_source != src_command) |
||||
|
return; |
||||
|
|
||||
|
c = Cmd_Argc(); |
||||
|
if (c != 2 && c != 3 && c != 4) |
||||
|
{ |
||||
|
Con_Printf ("record <demoname> [<map> [cd track]]\n"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (strstr(Cmd_Argv(1), "..")) |
||||
|
{ |
||||
|
Con_Printf ("Relative pathnames are not allowed.\n"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (c == 2 && cls.state == ca_connected) |
||||
|
{ |
||||
|
Con_Printf("Can not record - already connected to server\nClient demo recording must be started before connecting\n"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// write the forced cd track number, or -1 |
||||
|
if (c == 4) |
||||
|
{ |
||||
|
track = atoi(Cmd_Argv(3)); |
||||
|
Con_Printf ("Forcing CD track to %i\n", cls.forcetrack); |
||||
|
} |
||||
|
else |
||||
|
track = -1; |
||||
|
|
||||
|
sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1)); |
||||
|
|
||||
|
// |
||||
|
// start the map up |
||||
|
// |
||||
|
if (c > 2) |
||||
|
Cmd_ExecuteString ( va("map %s", Cmd_Argv(2)), src_command); |
||||
|
|
||||
|
// |
||||
|
// open the demo file |
||||
|
// |
||||
|
COM_DefaultExtension (name, ".dem"); |
||||
|
|
||||
|
Con_Printf ("recording to %s.\n", name); |
||||
|
cls.demofile = fopen (name, "wb"); |
||||
|
if (!cls.demofile) |
||||
|
{ |
||||
|
Con_Printf ("ERROR: couldn't open.\n"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
cls.forcetrack = track; |
||||
|
fprintf (cls.demofile, "%i\n", cls.forcetrack); |
||||
|
|
||||
|
cls.demorecording = true; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
==================== |
||||
|
CL_PlayDemo_f |
||||
|
|
||||
|
play [demoname] |
||||
|
==================== |
||||
|
*/ |
||||
|
|
||||
|
// jkrige - get rid of the menu and/or console |
||||
|
#define m_none 0 // enumerated menu state from menu.c |
||||
|
extern int m_state; |
||||
|
// jkrige - get rid of the menu and/or console |
||||
|
|
||||
|
// jkrige - pk3 file support |
||||
|
/*void CL_PlayDemo_f (void) |
||||
|
{ |
||||
|
char name[256]; |
||||
|
int c; |
||||
|
qboolean neg = false; |
||||
|
|
||||
|
if (cmd_source != src_command) |
||||
|
return; |
||||
|
|
||||
|
if (Cmd_Argc() != 2) |
||||
|
{ |
||||
|
Con_Printf ("play <demoname> : plays a demo\n"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// |
||||
|
// disconnect from server |
||||
|
// |
||||
|
CL_Disconnect (); |
||||
|
|
||||
|
// |
||||
|
// open the demo file |
||||
|
// |
||||
|
strcpy (name, Cmd_Argv(1)); |
||||
|
COM_DefaultExtension (name, ".dem"); |
||||
|
|
||||
|
Con_Printf ("Playing demo from %s.\n", name); |
||||
|
COM_FOpenFile (name, &cls.demofile); |
||||
|
if (!cls.demofile) |
||||
|
{ |
||||
|
Con_Printf ("ERROR: couldn't open.\n"); |
||||
|
cls.demonum = -1; // stop demo loop |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
cls.demoplayback = true; |
||||
|
cls.state = ca_connected; |
||||
|
cls.forcetrack = 0; |
||||
|
|
||||
|
while ((c = getc(cls.demofile)) != '\n') |
||||
|
if (c == '-') |
||||
|
neg = true; |
||||
|
else |
||||
|
cls.forcetrack = cls.forcetrack * 10 + (c - '0'); |
||||
|
|
||||
|
if (neg) |
||||
|
cls.forcetrack = -cls.forcetrack; |
||||
|
// ZOID, fscanf is evil |
||||
|
// fscanf (cls.demofile, "%i\n", &cls.forcetrack); |
||||
|
|
||||
|
// jkrige - moved to CL_PlayDemo_f |
||||
|
// Get a new message on playback start. |
||||
|
cls.td_lastframe = -1; |
||||
|
// jkrige - moved to CL_PlayDemo_f |
||||
|
}*/ |
||||
|
void CL_PlayDemo_f (void) |
||||
|
{ |
||||
|
char name[256]; |
||||
|
int c; |
||||
|
//int fi; |
||||
|
qboolean neg = false; |
||||
|
|
||||
|
if (cmd_source != src_command) |
||||
|
return; |
||||
|
|
||||
|
if (Cmd_Argc() != 2) |
||||
|
{ |
||||
|
Con_Printf ("playdemo <demoname> : plays a demo\n"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// |
||||
|
// disconnect from server |
||||
|
// |
||||
|
CL_Disconnect (); |
||||
|
|
||||
|
// |
||||
|
// open the demo file |
||||
|
// |
||||
|
strcpy (name, Cmd_Argv(1)); |
||||
|
COM_DefaultExtension (name, ".dem"); |
||||
|
|
||||
|
Con_Printf ("Playing demo from %s.\n", name); |
||||
|
cls.demobufferlength = COM_FOpenFile (name, &cls.demofile); |
||||
|
cls.demobufferposition = 0; |
||||
|
|
||||
|
if (/*!cls.demofile |*/ cls.demobufferlength < 1) |
||||
|
{ |
||||
|
Con_Printf ("ERROR: couldn't open.\n"); |
||||
|
cls.demonum = -1; // stop demo loop |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
cls.demobuffer = COM_FReadFile(cls.demofile, cls.demobufferlength); |
||||
|
if (!cls.demobuffer) |
||||
|
return; |
||||
|
|
||||
|
cls.demoplayback = true; |
||||
|
cls.state = ca_connected; |
||||
|
cls.forcetrack = 0; |
||||
|
|
||||
|
while ((c = cls.demobuffer[cls.demobufferposition++]) != '\n') |
||||
|
{ |
||||
|
if (c == '-') |
||||
|
neg = true; |
||||
|
else |
||||
|
cls.forcetrack = cls.forcetrack * 10 + (c - '0'); |
||||
|
} |
||||
|
|
||||
|
if (neg) |
||||
|
cls.forcetrack = -cls.forcetrack; |
||||
|
|
||||
|
// jkrige - get rid of the menu and/or console |
||||
|
if (key_dest == key_console || key_dest == key_menu) |
||||
|
{ |
||||
|
key_dest = key_game; |
||||
|
m_state = m_none; |
||||
|
} |
||||
|
// jkrige - get rid of the menu and/or console |
||||
|
|
||||
|
|
||||
|
// ZOID, fscanf is evil |
||||
|
// fscanf (cls.demofile, "%i\n", &cls.forcetrack); |
||||
|
|
||||
|
// jkrige - moved to CL_PlayDemo_f |
||||
|
// Get a new message on playback start. |
||||
|
cls.td_lastframe = -1; |
||||
|
// jkrige - moved to CL_PlayDemo_f |
||||
|
} |
||||
|
// jkrige - pk3 file support |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
==================== |
||||
|
CL_FinishTimeDemo |
||||
|
|
||||
|
==================== |
||||
|
*/ |
||||
|
void CL_FinishTimeDemo (void) |
||||
|
{ |
||||
|
int frames; |
||||
|
float time; |
||||
|
|
||||
|
cls.timedemo = false; |
||||
|
|
||||
|
// the first frame didn't count |
||||
|
frames = (host_framecount - cls.td_startframe) - 1; |
||||
|
time = realtime - cls.td_starttime; |
||||
|
if (!time) |
||||
|
time = 1; |
||||
|
Con_Printf ("%i frames %5.1f seconds %5.1f fps\n", frames, time, frames/time); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
==================== |
||||
|
CL_TimeDemo_f |
||||
|
|
||||
|
timedemo [demoname] |
||||
|
==================== |
||||
|
*/ |
||||
|
void CL_TimeDemo_f (void) |
||||
|
{ |
||||
|
if (cmd_source != src_command) |
||||
|
return; |
||||
|
|
||||
|
if (Cmd_Argc() != 2) |
||||
|
{ |
||||
|
Con_Printf ("timedemo <demoname> : gets demo speeds\n"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
CL_PlayDemo_f (); |
||||
|
|
||||
|
// cls.td_starttime will be grabbed at the second frame of the demo, so |
||||
|
// all the loading time doesn't get counted |
||||
|
|
||||
|
cls.timedemo = true; |
||||
|
cls.td_startframe = host_framecount; |
||||
|
|
||||
|
// jkrige - moved to CL_PlayDemo_f() |
||||
|
//cls.td_lastframe = -1; // get a new message this frame |
||||
|
// jkrige - moved to CL_PlayDemo_f() |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,469 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// cl.input.c -- builds an intended movement command to send to the server |
||||
|
|
||||
|
// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All |
||||
|
// rights reserved. |
||||
|
|
||||
|
#include "quakedef.h" |
||||
|
|
||||
|
/* |
||||
|
=============================================================================== |
||||
|
|
||||
|
KEY BUTTONS |
||||
|
|
||||
|
Continuous button event tracking is complicated by the fact that two different |
||||
|
input sources (say, mouse button 1 and the control key) can both press the |
||||
|
same button, but the button should only be released when both of the |
||||
|
pressing key have been released. |
||||
|
|
||||
|
When a key event issues a button command (+forward, +attack, etc), it appends |
||||
|
its key number as a parameter to the command so it can be matched up with |
||||
|
the release. |
||||
|
|
||||
|
state bit 0 is the current state of the key |
||||
|
state bit 1 is edge triggered on the up to down transition |
||||
|
state bit 2 is edge triggered on the down to up transition |
||||
|
|
||||
|
=============================================================================== |
||||
|
*/ |
||||
|
|
||||
|
|
||||
|
//kbutton_t /*in_mlook,*/ in_klook; // jkrige - mlook cvar, removed klook command |
||||
|
kbutton_t in_left, in_right, in_forward, in_back; |
||||
|
kbutton_t in_lookup, in_lookdown, in_moveleft, in_moveright; |
||||
|
kbutton_t in_strafe, in_speed, in_use, in_jump, in_attack; |
||||
|
kbutton_t in_up, in_down; |
||||
|
|
||||
|
int in_impulse; |
||||
|
|
||||
|
|
||||
|
void KeyDown (kbutton_t *b) |
||||
|
{ |
||||
|
int k; |
||||
|
char *c; |
||||
|
|
||||
|
c = Cmd_Argv(1); |
||||
|
if (c[0]) |
||||
|
k = atoi(c); |
||||
|
else |
||||
|
k = -1; // typed manually at the console for continuous down |
||||
|
|
||||
|
if (k == b->down[0] || k == b->down[1]) |
||||
|
return; // repeating key |
||||
|
|
||||
|
if (!b->down[0]) |
||||
|
b->down[0] = k; |
||||
|
else if (!b->down[1]) |
||||
|
b->down[1] = k; |
||||
|
else |
||||
|
{ |
||||
|
Con_Printf ("Three keys down for a button!\n"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (b->state & 1) |
||||
|
return; // still down |
||||
|
b->state |= 1 + 2; // down + impulse down |
||||
|
} |
||||
|
|
||||
|
void KeyUp (kbutton_t *b) |
||||
|
{ |
||||
|
int k; |
||||
|
char *c; |
||||
|
|
||||
|
c = Cmd_Argv(1); |
||||
|
if (c[0]) |
||||
|
k = atoi(c); |
||||
|
else |
||||
|
{ // typed manually at the console, assume for unsticking, so clear all |
||||
|
b->down[0] = b->down[1] = 0; |
||||
|
b->state = 4; // impulse up |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (b->down[0] == k) |
||||
|
b->down[0] = 0; |
||||
|
else if (b->down[1] == k) |
||||
|
b->down[1] = 0; |
||||
|
else |
||||
|
return; // key up without coresponding down (menu pass through) |
||||
|
if (b->down[0] || b->down[1]) |
||||
|
return; // some other key is still holding it down |
||||
|
|
||||
|
if (!(b->state & 1)) |
||||
|
return; // still up (this should not happen) |
||||
|
b->state &= ~1; // now up |
||||
|
b->state |= 4; // impulse up |
||||
|
} |
||||
|
|
||||
|
// jkrige - removed klook command |
||||
|
//void IN_KLookDown (void) {KeyDown(&in_klook);} |
||||
|
//void IN_KLookUp (void) {KeyUp(&in_klook);} |
||||
|
// jkrige - removed klook command |
||||
|
|
||||
|
// jkrige - mlook cvar |
||||
|
/*void IN_MLookDown (void) {KeyDown(&in_mlook);} |
||||
|
void IN_MLookUp (void) { |
||||
|
KeyUp(&in_mlook); |
||||
|
if ( !(in_mlook.state&1) && lookspring.value) |
||||
|
V_StartPitchDrift(); |
||||
|
}*/ |
||||
|
// jkrige - mlook cvar |
||||
|
|
||||
|
void IN_UpDown(void) {KeyDown(&in_up);} |
||||
|
void IN_UpUp(void) {KeyUp(&in_up);} |
||||
|
void IN_DownDown(void) {KeyDown(&in_down);} |
||||
|
void IN_DownUp(void) {KeyUp(&in_down);} |
||||
|
void IN_LeftDown(void) {KeyDown(&in_left);} |
||||
|
void IN_LeftUp(void) {KeyUp(&in_left);} |
||||
|
void IN_RightDown(void) {KeyDown(&in_right);} |
||||
|
void IN_RightUp(void) {KeyUp(&in_right);} |
||||
|
void IN_ForwardDown(void) {KeyDown(&in_forward);} |
||||
|
void IN_ForwardUp(void) {KeyUp(&in_forward);} |
||||
|
void IN_BackDown(void) {KeyDown(&in_back);} |
||||
|
void IN_BackUp(void) {KeyUp(&in_back);} |
||||
|
void IN_LookupDown(void) {KeyDown(&in_lookup);} |
||||
|
void IN_LookupUp(void) {KeyUp(&in_lookup);} |
||||
|
void IN_LookdownDown(void) {KeyDown(&in_lookdown);} |
||||
|
void IN_LookdownUp(void) {KeyUp(&in_lookdown);} |
||||
|
void IN_MoveleftDown(void) {KeyDown(&in_moveleft);} |
||||
|
void IN_MoveleftUp(void) {KeyUp(&in_moveleft);} |
||||
|
void IN_MoverightDown(void) {KeyDown(&in_moveright);} |
||||
|
void IN_MoverightUp(void) {KeyUp(&in_moveright);} |
||||
|
|
||||
|
void IN_SpeedDown(void) {KeyDown(&in_speed);} |
||||
|
void IN_SpeedUp(void) {KeyUp(&in_speed);} |
||||
|
void IN_StrafeDown(void) {KeyDown(&in_strafe);} |
||||
|
void IN_StrafeUp(void) {KeyUp(&in_strafe);} |
||||
|
|
||||
|
void IN_AttackDown(void) {KeyDown(&in_attack);} |
||||
|
void IN_AttackUp(void) {KeyUp(&in_attack);} |
||||
|
|
||||
|
void IN_UseDown (void) {KeyDown(&in_use);} |
||||
|
void IN_UseUp (void) {KeyUp(&in_use);} |
||||
|
void IN_JumpDown (void) {KeyDown(&in_jump);} |
||||
|
void IN_JumpUp (void) {KeyUp(&in_jump);} |
||||
|
|
||||
|
void IN_Impulse (void) {in_impulse=Q_atoi(Cmd_Argv(1));} |
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
CL_KeyState |
||||
|
|
||||
|
Returns 0.25 if a key was pressed and released during the frame, |
||||
|
0.5 if it was pressed and held |
||||
|
0 if held then released, and |
||||
|
1.0 if held for the entire time |
||||
|
=============== |
||||
|
*/ |
||||
|
float CL_KeyState (kbutton_t *key) |
||||
|
{ |
||||
|
float val; |
||||
|
qboolean impulsedown, impulseup, down; |
||||
|
|
||||
|
impulsedown = key->state & 2; |
||||
|
impulseup = key->state & 4; |
||||
|
down = key->state & 1; |
||||
|
val = 0; |
||||
|
|
||||
|
if (impulsedown && !impulseup) |
||||
|
if (down) |
||||
|
val = 0.5; // pressed and held this frame |
||||
|
else |
||||
|
val = 0; // I_Error (); |
||||
|
if (impulseup && !impulsedown) |
||||
|
if (down) |
||||
|
val = 0; // I_Error (); |
||||
|
else |
||||
|
val = 0; // released this frame |
||||
|
if (!impulsedown && !impulseup) |
||||
|
if (down) |
||||
|
val = 1.0; // held the entire frame |
||||
|
else |
||||
|
val = 0; // up the entire frame |
||||
|
if (impulsedown && impulseup) |
||||
|
if (down) |
||||
|
val = 0.75; // released and re-pressed this frame |
||||
|
else |
||||
|
val = 0.25; // pressed and released this frame |
||||
|
|
||||
|
key->state &= 1; // clear impulses |
||||
|
|
||||
|
return val; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
//========================================================================== |
||||
|
|
||||
|
cvar_t cl_upspeed = {"cl_upspeed","200"}; |
||||
|
cvar_t cl_forwardspeed = {"cl_forwardspeed","200", true}; |
||||
|
cvar_t cl_backspeed = {"cl_backspeed","200", true}; |
||||
|
|
||||
|
// jkrige - reduced strafe speed |
||||
|
//cvar_t cl_sidespeed = {"cl_sidespeed","350"}; |
||||
|
cvar_t cl_sidespeed = {"cl_sidespeed","225"}; |
||||
|
// jkrige - reduced strafe speed |
||||
|
|
||||
|
|
||||
|
cvar_t cl_movespeedkey = {"cl_movespeedkey","2.0"}; |
||||
|
|
||||
|
cvar_t cl_yawspeed = {"cl_yawspeed","140"}; |
||||
|
cvar_t cl_pitchspeed = {"cl_pitchspeed","150"}; |
||||
|
|
||||
|
cvar_t cl_anglespeedkey = {"cl_anglespeedkey","1.5"}; |
||||
|
|
||||
|
cvar_t cl_mlook = {"cl_mlook", "1", true}; // jkrige - mlook cvar |
||||
|
cvar_t cl_slook = {"cl_slook", "0", true}; // jkrige - slook cvar |
||||
|
|
||||
|
/* |
||||
|
================ |
||||
|
CL_AdjustAngles |
||||
|
|
||||
|
Moves the local angle positions |
||||
|
================ |
||||
|
*/ |
||||
|
void CL_AdjustAngles (void) |
||||
|
{ |
||||
|
float speed; |
||||
|
float up, down; |
||||
|
|
||||
|
if (in_speed.state & 1) |
||||
|
speed = host_frametime * cl_anglespeedkey.value; |
||||
|
else |
||||
|
speed = host_frametime; |
||||
|
|
||||
|
if (!(in_strafe.state & 1)) |
||||
|
{ |
||||
|
cl.viewangles[YAW] -= speed*cl_yawspeed.value*CL_KeyState (&in_right); |
||||
|
cl.viewangles[YAW] += speed*cl_yawspeed.value*CL_KeyState (&in_left); |
||||
|
cl.viewangles[YAW] = anglemod(cl.viewangles[YAW]); |
||||
|
} |
||||
|
|
||||
|
// jkrige - removed klook command |
||||
|
/*if (in_klook.state & 1) |
||||
|
{ |
||||
|
V_StopPitchDrift (); |
||||
|
cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * CL_KeyState (&in_forward); |
||||
|
cl.viewangles[PITCH] += speed*cl_pitchspeed.value * CL_KeyState (&in_back); |
||||
|
}*/ |
||||
|
// jkrige - removed klook command |
||||
|
|
||||
|
up = CL_KeyState (&in_lookup); |
||||
|
down = CL_KeyState(&in_lookdown); |
||||
|
|
||||
|
cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * up; |
||||
|
cl.viewangles[PITCH] += speed*cl_pitchspeed.value * down; |
||||
|
|
||||
|
if (up || down) |
||||
|
V_StopPitchDrift (); |
||||
|
|
||||
|
if (cl.viewangles[PITCH] > 80) |
||||
|
cl.viewangles[PITCH] = 80; |
||||
|
if (cl.viewangles[PITCH] < -70) |
||||
|
cl.viewangles[PITCH] = -70; |
||||
|
|
||||
|
if (cl.viewangles[ROLL] > 50) |
||||
|
cl.viewangles[ROLL] = 50; |
||||
|
if (cl.viewangles[ROLL] < -50) |
||||
|
cl.viewangles[ROLL] = -50; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
================ |
||||
|
CL_BaseMove |
||||
|
|
||||
|
Send the intended movement message to the server |
||||
|
================ |
||||
|
*/ |
||||
|
void CL_BaseMove (usercmd_t *cmd) |
||||
|
{ |
||||
|
if (cls.signon != SIGNONS) |
||||
|
return; |
||||
|
|
||||
|
CL_AdjustAngles (); |
||||
|
|
||||
|
Q_memset (cmd, 0, sizeof(*cmd)); |
||||
|
|
||||
|
if (in_strafe.state & 1) |
||||
|
{ |
||||
|
cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_right); |
||||
|
cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_left); |
||||
|
} |
||||
|
|
||||
|
cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_moveright); |
||||
|
cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_moveleft); |
||||
|
|
||||
|
cmd->upmove += cl_upspeed.value * CL_KeyState (&in_up); |
||||
|
cmd->upmove -= cl_upspeed.value * CL_KeyState (&in_down); |
||||
|
|
||||
|
// jkrige - removed klook command |
||||
|
//if (! (in_klook.state & 1) ) |
||||
|
//{ |
||||
|
cmd->forwardmove += cl_forwardspeed.value * CL_KeyState (&in_forward); |
||||
|
cmd->forwardmove -= cl_backspeed.value * CL_KeyState (&in_back); |
||||
|
//} |
||||
|
// jkrige - removed klook command |
||||
|
|
||||
|
// |
||||
|
// adjust for speed key |
||||
|
// |
||||
|
// jkrige - speed key now acts as slow key when always run is chosen |
||||
|
//if (in_speed.state & 1) |
||||
|
if ( ( (cl_forwardspeed.value <= 200 && in_speed.state & 1) || (cl_forwardspeed.value > 200 && !(in_speed.state & 1)) ) ) |
||||
|
{ |
||||
|
cmd->forwardmove *= cl_movespeedkey.value; |
||||
|
cmd->sidemove *= cl_movespeedkey.value; |
||||
|
cmd->upmove *= cl_movespeedkey.value; |
||||
|
} |
||||
|
// jkrige - speed key now acts as slow key when always run is chosen |
||||
|
|
||||
|
#ifdef QUAKE2 |
||||
|
cmd->lightlevel = cl.light_level; |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/* |
||||
|
============== |
||||
|
CL_SendMove |
||||
|
============== |
||||
|
*/ |
||||
|
void CL_SendMove (usercmd_t *cmd) |
||||
|
{ |
||||
|
int i; |
||||
|
int bits; |
||||
|
sizebuf_t buf; |
||||
|
byte data[128]; |
||||
|
|
||||
|
buf.maxsize = 128; |
||||
|
buf.cursize = 0; |
||||
|
buf.data = data; |
||||
|
|
||||
|
cl.cmd = *cmd; |
||||
|
|
||||
|
// |
||||
|
// send the movement message |
||||
|
// |
||||
|
MSG_WriteByte (&buf, clc_move); |
||||
|
|
||||
|
MSG_WriteFloat (&buf, cl.mtime[0]); // so server can get ping times |
||||
|
|
||||
|
for (i=0 ; i<3 ; i++) |
||||
|
MSG_WriteAngle (&buf, cl.viewangles[i]); |
||||
|
|
||||
|
MSG_WriteShort (&buf, cmd->forwardmove); |
||||
|
MSG_WriteShort (&buf, cmd->sidemove); |
||||
|
MSG_WriteShort (&buf, cmd->upmove); |
||||
|
|
||||
|
// |
||||
|
// send button bits |
||||
|
// |
||||
|
bits = 0; |
||||
|
|
||||
|
if ( in_attack.state & 3 ) |
||||
|
bits |= 1; |
||||
|
in_attack.state &= ~2; |
||||
|
|
||||
|
if (in_jump.state & 3) |
||||
|
bits |= 2; |
||||
|
in_jump.state &= ~2; |
||||
|
|
||||
|
MSG_WriteByte (&buf, bits); |
||||
|
|
||||
|
MSG_WriteByte (&buf, in_impulse); |
||||
|
in_impulse = 0; |
||||
|
|
||||
|
#ifdef QUAKE2 |
||||
|
// |
||||
|
// light level |
||||
|
// |
||||
|
MSG_WriteByte (&buf, cmd->lightlevel); |
||||
|
#endif |
||||
|
|
||||
|
// |
||||
|
// deliver the message |
||||
|
// |
||||
|
if (cls.demoplayback) |
||||
|
return; |
||||
|
|
||||
|
// |
||||
|
// allways dump the first two message, because it may contain leftover inputs |
||||
|
// from the last level |
||||
|
// |
||||
|
if (++cl.movemessages <= 2) |
||||
|
return; |
||||
|
|
||||
|
if (NET_SendUnreliableMessage (cls.netcon, &buf) == -1) |
||||
|
{ |
||||
|
Con_Printf ("CL_SendMove: lost server connection\n"); |
||||
|
CL_Disconnect (); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
CL_InitInput |
||||
|
============ |
||||
|
*/ |
||||
|
void CL_InitInput (void) |
||||
|
{ |
||||
|
Cmd_AddCommand ("+moveup",IN_UpDown); |
||||
|
Cmd_AddCommand ("-moveup",IN_UpUp); |
||||
|
Cmd_AddCommand ("+movedown",IN_DownDown); |
||||
|
Cmd_AddCommand ("-movedown",IN_DownUp); |
||||
|
Cmd_AddCommand ("+left",IN_LeftDown); |
||||
|
Cmd_AddCommand ("-left",IN_LeftUp); |
||||
|
Cmd_AddCommand ("+right",IN_RightDown); |
||||
|
Cmd_AddCommand ("-right",IN_RightUp); |
||||
|
Cmd_AddCommand ("+forward",IN_ForwardDown); |
||||
|
Cmd_AddCommand ("-forward",IN_ForwardUp); |
||||
|
Cmd_AddCommand ("+back",IN_BackDown); |
||||
|
Cmd_AddCommand ("-back",IN_BackUp); |
||||
|
Cmd_AddCommand ("+lookup", IN_LookupDown); |
||||
|
Cmd_AddCommand ("-lookup", IN_LookupUp); |
||||
|
Cmd_AddCommand ("+lookdown", IN_LookdownDown); |
||||
|
Cmd_AddCommand ("-lookdown", IN_LookdownUp); |
||||
|
Cmd_AddCommand ("+strafe", IN_StrafeDown); |
||||
|
Cmd_AddCommand ("-strafe", IN_StrafeUp); |
||||
|
Cmd_AddCommand ("+moveleft", IN_MoveleftDown); |
||||
|
Cmd_AddCommand ("-moveleft", IN_MoveleftUp); |
||||
|
Cmd_AddCommand ("+moveright", IN_MoverightDown); |
||||
|
Cmd_AddCommand ("-moveright", IN_MoverightUp); |
||||
|
Cmd_AddCommand ("+speed", IN_SpeedDown); |
||||
|
Cmd_AddCommand ("-speed", IN_SpeedUp); |
||||
|
Cmd_AddCommand ("+attack", IN_AttackDown); |
||||
|
Cmd_AddCommand ("-attack", IN_AttackUp); |
||||
|
Cmd_AddCommand ("+use", IN_UseDown); |
||||
|
Cmd_AddCommand ("-use", IN_UseUp); |
||||
|
Cmd_AddCommand ("+jump", IN_JumpDown); |
||||
|
Cmd_AddCommand ("-jump", IN_JumpUp); |
||||
|
Cmd_AddCommand ("impulse", IN_Impulse); |
||||
|
//Cmd_AddCommand ("+klook", IN_KLookDown); // jkrige - removed klook command |
||||
|
//Cmd_AddCommand ("-klook", IN_KLookUp); // jkrige - removed klook command |
||||
|
//Cmd_AddCommand ("+mlook", IN_MLookDown); // jkrige - removed mlook command |
||||
|
//Cmd_AddCommand ("-mlook", IN_MLookUp); // jkrige - removed mlook command |
||||
|
|
||||
|
} |
||||
|
|
||||
@ -0,0 +1,800 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// cl_main.c -- client main loop |
||||
|
|
||||
|
#include "quakedef.h" |
||||
|
|
||||
|
// we need to declare some mouse variables here, because the menu system |
||||
|
// references them even when on a unix system. |
||||
|
|
||||
|
// these two are not intended to be set directly |
||||
|
cvar_t cl_name = {"_cl_name", "player", true}; |
||||
|
cvar_t cl_color = {"_cl_color", "0", true}; |
||||
|
|
||||
|
cvar_t cl_shownet = {"cl_shownet","0"}; // can be 0, 1, or 2 |
||||
|
cvar_t cl_nolerp = {"cl_nolerp","0"}; |
||||
|
|
||||
|
// jkrige - configurable fps caps |
||||
|
cvar_t cl_maxfps = {"cl_maxfps", "110", true}; |
||||
|
// jkrige - configurable fps caps |
||||
|
|
||||
|
cvar_t lookspring = {"lookspring","0", true}; |
||||
|
cvar_t lookstrafe = {"lookstrafe","0", true}; |
||||
|
|
||||
|
// jkrige - mouse sensitivity |
||||
|
//cvar_t sensitivity = {"sensitivity","5", true}; |
||||
|
cvar_t sensitivity = {"sensitivity","5.5", true}; |
||||
|
// jkrige - mouse sensitivity |
||||
|
|
||||
|
cvar_t m_pitch = {"m_pitch","0.022", true}; |
||||
|
cvar_t m_yaw = {"m_yaw","0.022", true}; |
||||
|
cvar_t m_forward = {"m_forward","1", true}; |
||||
|
cvar_t m_side = {"m_side","0.8", true}; |
||||
|
|
||||
|
|
||||
|
client_static_t cls; |
||||
|
client_state_t cl; |
||||
|
// FIXME: put these on hunk? |
||||
|
efrag_t cl_efrags[MAX_EFRAGS]; |
||||
|
entity_t cl_entities[MAX_EDICTS]; |
||||
|
entity_t cl_static_entities[MAX_STATIC_ENTITIES]; |
||||
|
lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; |
||||
|
dlight_t cl_dlights[MAX_DLIGHTS]; |
||||
|
|
||||
|
int cl_numvisedicts; |
||||
|
entity_t *cl_visedicts[MAX_VISEDICTS]; |
||||
|
|
||||
|
/* |
||||
|
===================== |
||||
|
CL_ClearState |
||||
|
|
||||
|
===================== |
||||
|
*/ |
||||
|
void CL_ClearState (void) |
||||
|
{ |
||||
|
int i; |
||||
|
|
||||
|
if (!sv.active) |
||||
|
Host_ClearMemory (); |
||||
|
|
||||
|
// wipe the entire cl structure |
||||
|
memset (&cl, 0, sizeof(cl)); |
||||
|
|
||||
|
SZ_Clear (&cls.message); |
||||
|
|
||||
|
// clear other arrays |
||||
|
memset (cl_efrags, 0, sizeof(cl_efrags)); |
||||
|
memset (cl_entities, 0, sizeof(cl_entities)); |
||||
|
memset (cl_dlights, 0, sizeof(cl_dlights)); |
||||
|
memset (cl_lightstyle, 0, sizeof(cl_lightstyle)); |
||||
|
memset (cl_temp_entities, 0, sizeof(cl_temp_entities)); |
||||
|
memset (cl_beams, 0, sizeof(cl_beams)); |
||||
|
|
||||
|
// |
||||
|
// allocate the efrags and chain together into a free list |
||||
|
// |
||||
|
cl.free_efrags = cl_efrags; |
||||
|
for (i=0 ; i<MAX_EFRAGS-1 ; i++) |
||||
|
cl.free_efrags[i].entnext = &cl.free_efrags[i+1]; |
||||
|
cl.free_efrags[i].entnext = NULL; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
===================== |
||||
|
CL_Disconnect |
||||
|
|
||||
|
Sends a disconnect message to the server |
||||
|
This is also called on Host_Error, so it shouldn't cause any errors |
||||
|
===================== |
||||
|
*/ |
||||
|
void CL_Disconnect (void) |
||||
|
{ |
||||
|
// stop sounds (especially looping!) |
||||
|
S_StopAllSounds (true); |
||||
|
|
||||
|
// bring the console down and fade the colors back to normal |
||||
|
// SCR_BringDownConsole (); |
||||
|
|
||||
|
// if running a local server, shut it down |
||||
|
if (cls.demoplayback) |
||||
|
CL_StopPlayback (); |
||||
|
else if (cls.state == ca_connected) |
||||
|
{ |
||||
|
if (cls.demorecording) |
||||
|
CL_Stop_f (); |
||||
|
|
||||
|
Con_DPrintf ("Sending clc_disconnect\n"); |
||||
|
SZ_Clear (&cls.message); |
||||
|
MSG_WriteByte (&cls.message, clc_disconnect); |
||||
|
NET_SendUnreliableMessage (cls.netcon, &cls.message); |
||||
|
SZ_Clear (&cls.message); |
||||
|
NET_Close (cls.netcon); |
||||
|
|
||||
|
cls.state = ca_disconnected; |
||||
|
if (sv.active) |
||||
|
Host_ShutdownServer(false); |
||||
|
} |
||||
|
|
||||
|
cls.demoplayback = cls.timedemo = false; |
||||
|
cls.signon = 0; |
||||
|
|
||||
|
|
||||
|
// jkrige - fmod sound system - begin |
||||
|
// stop disconnect music playback |
||||
|
#ifdef UQE_FMOD |
||||
|
FMOD_MusicStop(); |
||||
|
#else |
||||
|
CDAudio_Stop(); |
||||
|
#endif |
||||
|
// jkrige - fmod sound system - end |
||||
|
} |
||||
|
|
||||
|
void CL_Disconnect_f (void) |
||||
|
{ |
||||
|
CL_Disconnect (); |
||||
|
if (sv.active) |
||||
|
Host_ShutdownServer (false); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/* |
||||
|
===================== |
||||
|
CL_EstablishConnection |
||||
|
|
||||
|
Host should be either "local" or a net address to be passed on |
||||
|
===================== |
||||
|
*/ |
||||
|
void CL_EstablishConnection (char *host) |
||||
|
{ |
||||
|
if (cls.state == ca_dedicated) |
||||
|
return; |
||||
|
|
||||
|
if (cls.demoplayback) |
||||
|
return; |
||||
|
|
||||
|
CL_Disconnect (); |
||||
|
|
||||
|
cls.netcon = NET_Connect (host); |
||||
|
if (!cls.netcon) |
||||
|
Host_Error ("CL_Connect: connect failed\n"); |
||||
|
Con_DPrintf ("CL_EstablishConnection: connected to %s\n", host); |
||||
|
|
||||
|
cls.demonum = -1; // not in the demo loop now |
||||
|
cls.state = ca_connected; |
||||
|
cls.signon = 0; // need all the signon messages before playing |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
===================== |
||||
|
CL_SignonReply |
||||
|
|
||||
|
An svc_signonnum has been received, perform a client side setup |
||||
|
===================== |
||||
|
*/ |
||||
|
void CL_SignonReply (void) |
||||
|
{ |
||||
|
char str[8192]; |
||||
|
|
||||
|
Con_DPrintf ("CL_SignonReply: %i\n", cls.signon); |
||||
|
|
||||
|
switch (cls.signon) |
||||
|
{ |
||||
|
case 1: |
||||
|
MSG_WriteByte (&cls.message, clc_stringcmd); |
||||
|
MSG_WriteString (&cls.message, "prespawn"); |
||||
|
break; |
||||
|
|
||||
|
case 2: |
||||
|
MSG_WriteByte (&cls.message, clc_stringcmd); |
||||
|
MSG_WriteString (&cls.message, va("name \"%s\"\n", cl_name.string)); |
||||
|
|
||||
|
MSG_WriteByte (&cls.message, clc_stringcmd); |
||||
|
MSG_WriteString (&cls.message, va("color %i %i\n", ((int)cl_color.value)>>4, ((int)cl_color.value)&15)); |
||||
|
|
||||
|
MSG_WriteByte (&cls.message, clc_stringcmd); |
||||
|
sprintf (str, "spawn %s", cls.spawnparms); |
||||
|
MSG_WriteString (&cls.message, str); |
||||
|
break; |
||||
|
|
||||
|
case 3: |
||||
|
MSG_WriteByte (&cls.message, clc_stringcmd); |
||||
|
MSG_WriteString (&cls.message, "begin"); |
||||
|
Cache_Report (); // print remaining memory |
||||
|
break; |
||||
|
|
||||
|
case 4: |
||||
|
SCR_EndLoadingPlaque (); // allow normal screen updates |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
===================== |
||||
|
CL_NextDemo |
||||
|
|
||||
|
Called to play the next demo in the demo loop |
||||
|
===================== |
||||
|
*/ |
||||
|
void CL_NextDemo (void) |
||||
|
{ |
||||
|
char str[1024]; |
||||
|
|
||||
|
if (cls.demonum == -1) |
||||
|
return; // don't play demos |
||||
|
|
||||
|
SCR_BeginLoadingPlaque (); |
||||
|
|
||||
|
if (!cls.demos[cls.demonum][0] || cls.demonum == MAX_DEMOS) |
||||
|
{ |
||||
|
cls.demonum = 0; |
||||
|
if (!cls.demos[cls.demonum][0]) |
||||
|
{ |
||||
|
Con_Printf ("No demos listed with startdemos\n"); |
||||
|
cls.demonum = -1; |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
sprintf (str,"playdemo %s\n", cls.demos[cls.demonum]); |
||||
|
Cbuf_InsertText (str); |
||||
|
cls.demonum++; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
============== |
||||
|
CL_PrintEntities_f |
||||
|
============== |
||||
|
*/ |
||||
|
void CL_PrintEntities_f (void) |
||||
|
{ |
||||
|
entity_t *ent; |
||||
|
int i; |
||||
|
|
||||
|
for (i=0,ent=cl_entities ; i<cl.num_entities ; i++,ent++) |
||||
|
{ |
||||
|
Con_Printf ("%3i:",i); |
||||
|
if (!ent->model) |
||||
|
{ |
||||
|
Con_Printf ("EMPTY\n"); |
||||
|
continue; |
||||
|
} |
||||
|
Con_Printf ("%s:%2i (%5.1f,%5.1f,%5.1f) [%5.1f %5.1f %5.1f]\n" |
||||
|
,ent->model->name,ent->frame, ent->origin[0], ent->origin[1], ent->origin[2], ent->angles[0], ent->angles[1], ent->angles[2]); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
SetPal |
||||
|
|
||||
|
Debugging tool, just flashes the screen |
||||
|
=============== |
||||
|
*/ |
||||
|
void SetPal (int i) |
||||
|
{ |
||||
|
#if 0 |
||||
|
static int old; |
||||
|
byte pal[768]; |
||||
|
int c; |
||||
|
|
||||
|
if (i == old) |
||||
|
return; |
||||
|
old = i; |
||||
|
|
||||
|
if (i==0) |
||||
|
VID_SetPalette (host_basepal); |
||||
|
else if (i==1) |
||||
|
{ |
||||
|
for (c=0 ; c<768 ; c+=3) |
||||
|
{ |
||||
|
pal[c] = 0; |
||||
|
pal[c+1] = 255; |
||||
|
pal[c+2] = 0; |
||||
|
} |
||||
|
VID_SetPalette (pal); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
for (c=0 ; c<768 ; c+=3) |
||||
|
{ |
||||
|
pal[c] = 0; |
||||
|
pal[c+1] = 0; |
||||
|
pal[c+2] = 255; |
||||
|
} |
||||
|
VID_SetPalette (pal); |
||||
|
} |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
CL_AllocDlight |
||||
|
|
||||
|
=============== |
||||
|
*/ |
||||
|
dlight_t *CL_AllocDlight (int key) |
||||
|
{ |
||||
|
int i; |
||||
|
dlight_t *dl; |
||||
|
|
||||
|
// first look for an exact key match |
||||
|
if (key) |
||||
|
{ |
||||
|
dl = cl_dlights; |
||||
|
for (i=0 ; i<MAX_DLIGHTS ; i++, dl++) |
||||
|
{ |
||||
|
if (dl->key == key) |
||||
|
{ |
||||
|
memset (dl, 0, sizeof(*dl)); |
||||
|
dl->key = key; |
||||
|
|
||||
|
// jkrige - .lit colored lights |
||||
|
dl->color [0] = dl->color[1] = dl->color[2] = 1; |
||||
|
// jkrige - .lit colored lights |
||||
|
|
||||
|
return dl; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// then look for anything else |
||||
|
dl = cl_dlights; |
||||
|
for (i=0 ; i<MAX_DLIGHTS ; i++, dl++) |
||||
|
{ |
||||
|
if (dl->die < cl.time) |
||||
|
{ |
||||
|
memset (dl, 0, sizeof(*dl)); |
||||
|
dl->key = key; |
||||
|
|
||||
|
// jkrige - .lit colored lights |
||||
|
dl->color [0] = dl->color[1] = dl->color[2] = 1; |
||||
|
// jkrige - .lit colored lights |
||||
|
|
||||
|
return dl; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
dl = &cl_dlights[0]; |
||||
|
memset (dl, 0, sizeof(*dl)); |
||||
|
dl->key = key; |
||||
|
|
||||
|
// jkrige - .lit colored lights |
||||
|
dl->color [0] = dl->color[1] = dl->color[2] = 1; |
||||
|
// jkrige - .lit colored lights |
||||
|
|
||||
|
return dl; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
CL_DecayLights |
||||
|
|
||||
|
=============== |
||||
|
*/ |
||||
|
void CL_DecayLights (void) |
||||
|
{ |
||||
|
int i; |
||||
|
dlight_t *dl; |
||||
|
float time; |
||||
|
|
||||
|
time = cl.time - cl.oldtime; |
||||
|
|
||||
|
dl = cl_dlights; |
||||
|
for (i=0 ; i<MAX_DLIGHTS ; i++, dl++) |
||||
|
{ |
||||
|
if (dl->die < cl.time || !dl->radius) |
||||
|
continue; |
||||
|
|
||||
|
dl->radius -= time*dl->decay; |
||||
|
if (dl->radius < 0) |
||||
|
dl->radius = 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
CL_LerpPoint |
||||
|
|
||||
|
Determines the fraction between the last two messages that the objects |
||||
|
should be put at. |
||||
|
=============== |
||||
|
*/ |
||||
|
float CL_LerpPoint (void) |
||||
|
{ |
||||
|
float f, frac; |
||||
|
|
||||
|
f = cl.mtime[0] - cl.mtime[1]; |
||||
|
|
||||
|
if (!f || cl_nolerp.value || cls.timedemo || sv.active) |
||||
|
{ |
||||
|
cl.time = cl.mtime[0]; |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
if (f > 0.1) |
||||
|
{ // dropped packet, or start of demo |
||||
|
cl.mtime[1] = cl.mtime[0] - 0.1; |
||||
|
f = 0.1; |
||||
|
} |
||||
|
frac = (cl.time - cl.mtime[1]) / f; |
||||
|
//Con_Printf ("frac: %f\n",frac); |
||||
|
if (frac < 0) |
||||
|
{ |
||||
|
if (frac < -0.01) |
||||
|
{ |
||||
|
SetPal(1); |
||||
|
cl.time = cl.mtime[1]; |
||||
|
// Con_Printf ("low frac\n"); |
||||
|
} |
||||
|
frac = 0; |
||||
|
} |
||||
|
else if (frac > 1) |
||||
|
{ |
||||
|
if (frac > 1.01) |
||||
|
{ |
||||
|
SetPal(2); |
||||
|
cl.time = cl.mtime[0]; |
||||
|
// Con_Printf ("high frac\n"); |
||||
|
} |
||||
|
frac = 1; |
||||
|
} |
||||
|
else |
||||
|
SetPal(0); |
||||
|
|
||||
|
return frac; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
CL_RelinkEntities |
||||
|
=============== |
||||
|
*/ |
||||
|
void CL_RelinkEntities (void) |
||||
|
{ |
||||
|
entity_t *ent; |
||||
|
int i, j; |
||||
|
float frac, f, d; |
||||
|
vec3_t delta; |
||||
|
float bobjrotate; |
||||
|
vec3_t oldorg; |
||||
|
dlight_t *dl; |
||||
|
|
||||
|
// determine partial update time |
||||
|
frac = CL_LerpPoint (); |
||||
|
|
||||
|
cl_numvisedicts = 0; |
||||
|
|
||||
|
// |
||||
|
// interpolate player info |
||||
|
// |
||||
|
for (i=0 ; i<3 ; i++) |
||||
|
cl.velocity[i] = cl.mvelocity[1][i] + |
||||
|
frac * (cl.mvelocity[0][i] - cl.mvelocity[1][i]); |
||||
|
|
||||
|
if (cls.demoplayback) |
||||
|
{ |
||||
|
// interpolate the angles |
||||
|
for (j=0 ; j<3 ; j++) |
||||
|
{ |
||||
|
d = cl.mviewangles[0][j] - cl.mviewangles[1][j]; |
||||
|
if (d > 180) |
||||
|
d -= 360; |
||||
|
else if (d < -180) |
||||
|
d += 360; |
||||
|
cl.viewangles[j] = cl.mviewangles[1][j] + frac*d; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
bobjrotate = anglemod(100*cl.time); |
||||
|
|
||||
|
// start on the entity after the world |
||||
|
for (i=1,ent=cl_entities+1 ; i<cl.num_entities ; i++,ent++) |
||||
|
{ |
||||
|
if (!ent->model) |
||||
|
{ // empty slot |
||||
|
if (ent->forcelink) |
||||
|
R_RemoveEfrags (ent); // just became empty |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
// if the object wasn't included in the last packet, remove it |
||||
|
if (ent->msgtime != cl.mtime[0]) |
||||
|
{ |
||||
|
ent->model = NULL; |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
VectorCopy (ent->origin, oldorg); |
||||
|
|
||||
|
if (ent->forcelink) |
||||
|
{ // the entity was not updated in the last message |
||||
|
// so move to the final spot |
||||
|
VectorCopy (ent->msg_origins[0], ent->origin); |
||||
|
VectorCopy (ent->msg_angles[0], ent->angles); |
||||
|
} |
||||
|
else |
||||
|
{ // if the delta is large, assume a teleport and don't lerp |
||||
|
f = frac; |
||||
|
for (j=0 ; j<3 ; j++) |
||||
|
{ |
||||
|
delta[j] = ent->msg_origins[0][j] - ent->msg_origins[1][j]; |
||||
|
if (delta[j] > 100 || delta[j] < -100) |
||||
|
f = 1; // assume a teleportation, not a motion |
||||
|
} |
||||
|
|
||||
|
// interpolate the origin and angles |
||||
|
for (j=0 ; j<3 ; j++) |
||||
|
{ |
||||
|
ent->origin[j] = ent->msg_origins[1][j] + f*delta[j]; |
||||
|
|
||||
|
d = ent->msg_angles[0][j] - ent->msg_angles[1][j]; |
||||
|
if (d > 180) |
||||
|
d -= 360; |
||||
|
else if (d < -180) |
||||
|
d += 360; |
||||
|
ent->angles[j] = ent->msg_angles[1][j] + f*d; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
// rotate binary objects locally |
||||
|
if (ent->model->flags & EF_ROTATE) |
||||
|
ent->angles[1] = bobjrotate; |
||||
|
|
||||
|
if (ent->effects & EF_BRIGHTFIELD) |
||||
|
R_EntityParticles (ent); |
||||
|
#ifdef QUAKE2 |
||||
|
if (ent->effects & EF_DARKFIELD) |
||||
|
R_DarkFieldParticles (ent); |
||||
|
#endif |
||||
|
if (ent->effects & EF_MUZZLEFLASH) |
||||
|
{ |
||||
|
vec3_t fv, rv, uv; |
||||
|
|
||||
|
dl = CL_AllocDlight (i); |
||||
|
VectorCopy (ent->origin, dl->origin); |
||||
|
dl->origin[2] += 16; |
||||
|
AngleVectors (ent->angles, fv, rv, uv); |
||||
|
|
||||
|
VectorMA (dl->origin, 18, fv, dl->origin); |
||||
|
dl->radius = 200 + (rand()&31); |
||||
|
dl->minlight = 32; |
||||
|
dl->die = cl.time + 0.1; |
||||
|
} |
||||
|
if (ent->effects & EF_BRIGHTLIGHT) |
||||
|
{ |
||||
|
dl = CL_AllocDlight (i); |
||||
|
VectorCopy (ent->origin, dl->origin); |
||||
|
dl->origin[2] += 16; |
||||
|
dl->radius = 400 + (rand()&31); |
||||
|
dl->die = cl.time + 0.001; |
||||
|
} |
||||
|
if (ent->effects & EF_DIMLIGHT) |
||||
|
{ |
||||
|
dl = CL_AllocDlight (i); |
||||
|
VectorCopy (ent->origin, dl->origin); |
||||
|
dl->radius = 200 + (rand()&31); |
||||
|
dl->die = cl.time + 0.001; |
||||
|
} |
||||
|
#ifdef QUAKE2 |
||||
|
if (ent->effects & EF_DARKLIGHT) |
||||
|
{ |
||||
|
dl = CL_AllocDlight (i); |
||||
|
VectorCopy (ent->origin, dl->origin); |
||||
|
dl->radius = 200.0 + (rand()&31); |
||||
|
dl->die = cl.time + 0.001; |
||||
|
dl->dark = true; |
||||
|
} |
||||
|
if (ent->effects & EF_LIGHT) |
||||
|
{ |
||||
|
dl = CL_AllocDlight (i); |
||||
|
VectorCopy (ent->origin, dl->origin); |
||||
|
dl->radius = 200; |
||||
|
dl->die = cl.time + 0.001; |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
if (ent->model->flags & EF_GIB) |
||||
|
R_RocketTrail (oldorg, ent->origin, 2); |
||||
|
else if (ent->model->flags & EF_ZOMGIB) |
||||
|
R_RocketTrail (oldorg, ent->origin, 4); |
||||
|
else if (ent->model->flags & EF_TRACER) |
||||
|
R_RocketTrail (oldorg, ent->origin, 3); |
||||
|
else if (ent->model->flags & EF_TRACER2) |
||||
|
R_RocketTrail (oldorg, ent->origin, 5); |
||||
|
else if (ent->model->flags & EF_ROCKET) |
||||
|
{ |
||||
|
R_RocketTrail (oldorg, ent->origin, 0); |
||||
|
dl = CL_AllocDlight (i); |
||||
|
VectorCopy (ent->origin, dl->origin); |
||||
|
dl->radius = 200; |
||||
|
dl->die = cl.time + 0.01; |
||||
|
} |
||||
|
else if (ent->model->flags & EF_GRENADE) |
||||
|
R_RocketTrail (oldorg, ent->origin, 1); |
||||
|
else if (ent->model->flags & EF_TRACER3) |
||||
|
R_RocketTrail (oldorg, ent->origin, 6); |
||||
|
|
||||
|
ent->forcelink = false; |
||||
|
|
||||
|
// jkrige - removed chase |
||||
|
if (i == cl.viewentity) // && !chase_active.value |
||||
|
continue; |
||||
|
// jkrige - removed chase |
||||
|
|
||||
|
#ifdef QUAKE2 |
||||
|
if ( ent->effects & EF_NODRAW ) |
||||
|
continue; |
||||
|
#endif |
||||
|
if (cl_numvisedicts < MAX_VISEDICTS) |
||||
|
{ |
||||
|
cl_visedicts[cl_numvisedicts] = ent; |
||||
|
cl_numvisedicts++; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
CL_ReadFromServer |
||||
|
|
||||
|
Read all incoming data from the server |
||||
|
=============== |
||||
|
*/ |
||||
|
int CL_ReadFromServer (void) |
||||
|
{ |
||||
|
int ret; |
||||
|
|
||||
|
cl.oldtime = cl.time; |
||||
|
cl.time += host_frametime; |
||||
|
|
||||
|
do |
||||
|
{ |
||||
|
ret = CL_GetMessage (); |
||||
|
if (ret == -1) |
||||
|
Host_Error ("CL_ReadFromServer: lost server connection"); |
||||
|
if (!ret) |
||||
|
break; |
||||
|
|
||||
|
cl.last_received_message = realtime; |
||||
|
CL_ParseServerMessage (); |
||||
|
} while (ret && cls.state == ca_connected); |
||||
|
|
||||
|
if (cl_shownet.value) |
||||
|
Con_Printf ("\n"); |
||||
|
|
||||
|
CL_RelinkEntities (); |
||||
|
CL_UpdateTEnts (); |
||||
|
|
||||
|
// |
||||
|
// bring the links up to date |
||||
|
// |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
================= |
||||
|
CL_SendCmd |
||||
|
================= |
||||
|
*/ |
||||
|
void CL_SendCmd (void) |
||||
|
{ |
||||
|
usercmd_t cmd; |
||||
|
|
||||
|
if (cls.state != ca_connected) |
||||
|
return; |
||||
|
|
||||
|
if (cls.signon == SIGNONS) |
||||
|
{ |
||||
|
// get basic movement from keyboard |
||||
|
CL_BaseMove (&cmd); |
||||
|
|
||||
|
// allow mice or other external controllers to add to the move |
||||
|
IN_Move (&cmd); |
||||
|
|
||||
|
// send the unreliable message |
||||
|
CL_SendMove (&cmd); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
if (cls.demoplayback) |
||||
|
{ |
||||
|
SZ_Clear (&cls.message); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// send the reliable message |
||||
|
if (!cls.message.cursize) |
||||
|
return; // no message at all |
||||
|
|
||||
|
if (!NET_CanSendMessage (cls.netcon)) |
||||
|
{ |
||||
|
Con_DPrintf ("CL_WriteToServer: can't send\n"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (NET_SendMessage (cls.netcon, &cls.message) == -1) |
||||
|
Host_Error ("CL_WriteToServer: lost server connection"); |
||||
|
|
||||
|
SZ_Clear (&cls.message); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
================= |
||||
|
CL_Init |
||||
|
================= |
||||
|
*/ |
||||
|
void CL_Init (void) |
||||
|
{ |
||||
|
SZ_Alloc (&cls.message, 1024); |
||||
|
|
||||
|
CL_InitInput (); |
||||
|
CL_InitTEnts (); |
||||
|
|
||||
|
// |
||||
|
// register our commands |
||||
|
// |
||||
|
Cvar_RegisterVariable (&cl_name); |
||||
|
Cvar_RegisterVariable (&cl_color); |
||||
|
Cvar_RegisterVariable (&cl_upspeed); |
||||
|
Cvar_RegisterVariable (&cl_forwardspeed); |
||||
|
Cvar_RegisterVariable (&cl_backspeed); |
||||
|
Cvar_RegisterVariable (&cl_sidespeed); |
||||
|
Cvar_RegisterVariable (&cl_movespeedkey); |
||||
|
Cvar_RegisterVariable (&cl_yawspeed); |
||||
|
Cvar_RegisterVariable (&cl_pitchspeed); |
||||
|
Cvar_RegisterVariable (&cl_anglespeedkey); |
||||
|
Cvar_RegisterVariable (&cl_shownet); |
||||
|
Cvar_RegisterVariable (&cl_nolerp); |
||||
|
|
||||
|
// jkrige - configurable fps caps |
||||
|
Cvar_RegisterVariable (&cl_maxfps); |
||||
|
// jkrige - configurable fps caps |
||||
|
|
||||
|
Cvar_RegisterVariable (&lookspring); |
||||
|
Cvar_RegisterVariable (&lookstrafe); |
||||
|
Cvar_RegisterVariable (&sensitivity); |
||||
|
|
||||
|
Cvar_RegisterVariable (&cl_mlook); // jkrige - mlook cvar |
||||
|
Cvar_RegisterVariable (&cl_slook); // jkrige - slook cvar |
||||
|
|
||||
|
Cvar_RegisterVariable (&m_pitch); |
||||
|
Cvar_RegisterVariable (&m_yaw); |
||||
|
Cvar_RegisterVariable (&m_forward); |
||||
|
Cvar_RegisterVariable (&m_side); |
||||
|
|
||||
|
// Cvar_RegisterVariable (&cl_autofire); |
||||
|
|
||||
|
Cmd_AddCommand ("entities", CL_PrintEntities_f); |
||||
|
Cmd_AddCommand ("disconnect", CL_Disconnect_f); |
||||
|
Cmd_AddCommand ("record", CL_Record_f); |
||||
|
Cmd_AddCommand ("stop", CL_Stop_f); |
||||
|
Cmd_AddCommand ("playdemo", CL_PlayDemo_f); |
||||
|
Cmd_AddCommand ("timedemo", CL_TimeDemo_f); |
||||
|
} |
||||
|
|
||||
1026
engine/code/cl_parse.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,394 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// cl_tent.c -- client side temporary entities |
||||
|
|
||||
|
#include "quakedef.h" |
||||
|
|
||||
|
int num_temp_entities; |
||||
|
entity_t cl_temp_entities[MAX_TEMP_ENTITIES]; |
||||
|
beam_t cl_beams[MAX_BEAMS]; |
||||
|
|
||||
|
sfx_t *cl_sfx_wizhit; |
||||
|
sfx_t *cl_sfx_knighthit; |
||||
|
sfx_t *cl_sfx_tink1; |
||||
|
sfx_t *cl_sfx_ric1; |
||||
|
sfx_t *cl_sfx_ric2; |
||||
|
sfx_t *cl_sfx_ric3; |
||||
|
sfx_t *cl_sfx_r_exp3; |
||||
|
#ifdef QUAKE2 |
||||
|
sfx_t *cl_sfx_imp; |
||||
|
sfx_t *cl_sfx_rail; |
||||
|
#endif |
||||
|
|
||||
|
/* |
||||
|
================= |
||||
|
CL_ParseTEnt |
||||
|
================= |
||||
|
*/ |
||||
|
void CL_InitTEnts (void) |
||||
|
{ |
||||
|
cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav"); |
||||
|
cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav"); |
||||
|
cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav"); |
||||
|
cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav"); |
||||
|
cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav"); |
||||
|
cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav"); |
||||
|
cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav"); |
||||
|
#ifdef QUAKE2 |
||||
|
cl_sfx_imp = S_PrecacheSound ("shambler/sattck1.wav"); |
||||
|
cl_sfx_rail = S_PrecacheSound ("weapons/lstart.wav"); |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
================= |
||||
|
CL_ParseBeam |
||||
|
================= |
||||
|
*/ |
||||
|
void CL_ParseBeam (model_t *m) |
||||
|
{ |
||||
|
int ent; |
||||
|
vec3_t start, end; |
||||
|
beam_t *b; |
||||
|
int i; |
||||
|
|
||||
|
ent = MSG_ReadShort (); |
||||
|
|
||||
|
start[0] = MSG_ReadCoord (); |
||||
|
start[1] = MSG_ReadCoord (); |
||||
|
start[2] = MSG_ReadCoord (); |
||||
|
|
||||
|
end[0] = MSG_ReadCoord (); |
||||
|
end[1] = MSG_ReadCoord (); |
||||
|
end[2] = MSG_ReadCoord (); |
||||
|
|
||||
|
// override any beam with the same entity |
||||
|
for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++) |
||||
|
if (b->entity == ent) |
||||
|
{ |
||||
|
b->entity = ent; |
||||
|
b->model = m; |
||||
|
b->endtime = cl.time + 0.2; |
||||
|
VectorCopy (start, b->start); |
||||
|
VectorCopy (end, b->end); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// find a free beam |
||||
|
for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++) |
||||
|
{ |
||||
|
if (!b->model || b->endtime < cl.time) |
||||
|
{ |
||||
|
b->entity = ent; |
||||
|
b->model = m; |
||||
|
b->endtime = cl.time + 0.2; |
||||
|
VectorCopy (start, b->start); |
||||
|
VectorCopy (end, b->end); |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
Con_Printf ("beam list overflow!\n"); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
================= |
||||
|
CL_ParseTEnt |
||||
|
================= |
||||
|
*/ |
||||
|
void CL_ParseTEnt (void) |
||||
|
{ |
||||
|
int type; |
||||
|
vec3_t pos; |
||||
|
#ifdef QUAKE2 |
||||
|
vec3_t endpos; |
||||
|
#endif |
||||
|
dlight_t *dl; |
||||
|
int rnd; |
||||
|
int colorStart, colorLength; |
||||
|
|
||||
|
type = MSG_ReadByte (); |
||||
|
switch (type) |
||||
|
{ |
||||
|
case TE_WIZSPIKE: // spike hitting wall |
||||
|
pos[0] = MSG_ReadCoord (); |
||||
|
pos[1] = MSG_ReadCoord (); |
||||
|
pos[2] = MSG_ReadCoord (); |
||||
|
R_RunParticleEffect (pos, vec3_origin, 20, 30); |
||||
|
S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1); |
||||
|
break; |
||||
|
|
||||
|
case TE_KNIGHTSPIKE: // spike hitting wall |
||||
|
pos[0] = MSG_ReadCoord (); |
||||
|
pos[1] = MSG_ReadCoord (); |
||||
|
pos[2] = MSG_ReadCoord (); |
||||
|
R_RunParticleEffect (pos, vec3_origin, 226, 20); |
||||
|
S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1); |
||||
|
break; |
||||
|
|
||||
|
case TE_SPIKE: // spike hitting wall |
||||
|
pos[0] = MSG_ReadCoord (); |
||||
|
pos[1] = MSG_ReadCoord (); |
||||
|
pos[2] = MSG_ReadCoord (); |
||||
|
#ifdef GLTEST |
||||
|
Test_Spawn (pos); |
||||
|
#else |
||||
|
R_RunParticleEffect (pos, vec3_origin, 0, 10); |
||||
|
#endif |
||||
|
if ( rand() % 5 ) |
||||
|
S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1); |
||||
|
else |
||||
|
{ |
||||
|
rnd = rand() & 3; |
||||
|
if (rnd == 1) |
||||
|
S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1); |
||||
|
else if (rnd == 2) |
||||
|
S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1); |
||||
|
else |
||||
|
S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1); |
||||
|
} |
||||
|
break; |
||||
|
case TE_SUPERSPIKE: // super spike hitting wall |
||||
|
pos[0] = MSG_ReadCoord (); |
||||
|
pos[1] = MSG_ReadCoord (); |
||||
|
pos[2] = MSG_ReadCoord (); |
||||
|
R_RunParticleEffect (pos, vec3_origin, 0, 20); |
||||
|
|
||||
|
if ( rand() % 5 ) |
||||
|
S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1); |
||||
|
else |
||||
|
{ |
||||
|
rnd = rand() & 3; |
||||
|
if (rnd == 1) |
||||
|
S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1); |
||||
|
else if (rnd == 2) |
||||
|
S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1); |
||||
|
else |
||||
|
S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1); |
||||
|
} |
||||
|
break; |
||||
|
|
||||
|
case TE_GUNSHOT: // bullet hitting wall |
||||
|
pos[0] = MSG_ReadCoord (); |
||||
|
pos[1] = MSG_ReadCoord (); |
||||
|
pos[2] = MSG_ReadCoord (); |
||||
|
R_RunParticleEffect (pos, vec3_origin, 0, 20); |
||||
|
break; |
||||
|
|
||||
|
case TE_EXPLOSION: // rocket explosion |
||||
|
pos[0] = MSG_ReadCoord (); |
||||
|
pos[1] = MSG_ReadCoord (); |
||||
|
pos[2] = MSG_ReadCoord (); |
||||
|
R_ParticleExplosion (pos); |
||||
|
dl = CL_AllocDlight (0); |
||||
|
VectorCopy (pos, dl->origin); |
||||
|
dl->radius = 350; |
||||
|
dl->die = cl.time + 0.5; |
||||
|
dl->decay = 300; |
||||
|
S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); |
||||
|
break; |
||||
|
|
||||
|
case TE_TAREXPLOSION: // tarbaby explosion |
||||
|
pos[0] = MSG_ReadCoord (); |
||||
|
pos[1] = MSG_ReadCoord (); |
||||
|
pos[2] = MSG_ReadCoord (); |
||||
|
R_BlobExplosion (pos); |
||||
|
|
||||
|
S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); |
||||
|
break; |
||||
|
|
||||
|
case TE_LIGHTNING1: // lightning bolts |
||||
|
CL_ParseBeam (Mod_ForName("progs/bolt.mdl", true)); |
||||
|
break; |
||||
|
|
||||
|
case TE_LIGHTNING2: // lightning bolts |
||||
|
CL_ParseBeam (Mod_ForName("progs/bolt2.mdl", true)); |
||||
|
break; |
||||
|
|
||||
|
case TE_LIGHTNING3: // lightning bolts |
||||
|
CL_ParseBeam (Mod_ForName("progs/bolt3.mdl", true)); |
||||
|
break; |
||||
|
|
||||
|
// PGM 01/21/97 |
||||
|
case TE_BEAM: // grappling hook beam |
||||
|
CL_ParseBeam (Mod_ForName("progs/beam.mdl", true)); |
||||
|
break; |
||||
|
// PGM 01/21/97 |
||||
|
|
||||
|
case TE_LAVASPLASH: |
||||
|
pos[0] = MSG_ReadCoord (); |
||||
|
pos[1] = MSG_ReadCoord (); |
||||
|
pos[2] = MSG_ReadCoord (); |
||||
|
R_LavaSplash (pos); |
||||
|
break; |
||||
|
|
||||
|
case TE_TELEPORT: |
||||
|
pos[0] = MSG_ReadCoord (); |
||||
|
pos[1] = MSG_ReadCoord (); |
||||
|
pos[2] = MSG_ReadCoord (); |
||||
|
R_TeleportSplash (pos); |
||||
|
break; |
||||
|
|
||||
|
case TE_EXPLOSION2: // color mapped explosion |
||||
|
pos[0] = MSG_ReadCoord (); |
||||
|
pos[1] = MSG_ReadCoord (); |
||||
|
pos[2] = MSG_ReadCoord (); |
||||
|
colorStart = MSG_ReadByte (); |
||||
|
colorLength = MSG_ReadByte (); |
||||
|
R_ParticleExplosion2 (pos, colorStart, colorLength); |
||||
|
dl = CL_AllocDlight (0); |
||||
|
VectorCopy (pos, dl->origin); |
||||
|
dl->radius = 350; |
||||
|
dl->die = cl.time + 0.5; |
||||
|
dl->decay = 300; |
||||
|
S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); |
||||
|
break; |
||||
|
|
||||
|
#ifdef QUAKE2 |
||||
|
case TE_IMPLOSION: |
||||
|
pos[0] = MSG_ReadCoord (); |
||||
|
pos[1] = MSG_ReadCoord (); |
||||
|
pos[2] = MSG_ReadCoord (); |
||||
|
S_StartSound (-1, 0, cl_sfx_imp, pos, 1, 1); |
||||
|
break; |
||||
|
|
||||
|
case TE_RAILTRAIL: |
||||
|
pos[0] = MSG_ReadCoord (); |
||||
|
pos[1] = MSG_ReadCoord (); |
||||
|
pos[2] = MSG_ReadCoord (); |
||||
|
endpos[0] = MSG_ReadCoord (); |
||||
|
endpos[1] = MSG_ReadCoord (); |
||||
|
endpos[2] = MSG_ReadCoord (); |
||||
|
S_StartSound (-1, 0, cl_sfx_rail, pos, 1, 1); |
||||
|
S_StartSound (-1, 1, cl_sfx_r_exp3, endpos, 1, 1); |
||||
|
R_RocketTrail (pos, endpos, 0+128); |
||||
|
R_ParticleExplosion (endpos); |
||||
|
dl = CL_AllocDlight (-1); |
||||
|
VectorCopy (endpos, dl->origin); |
||||
|
dl->radius = 350; |
||||
|
dl->die = cl.time + 0.5; |
||||
|
dl->decay = 300; |
||||
|
break; |
||||
|
#endif |
||||
|
|
||||
|
default: |
||||
|
Sys_Error ("CL_ParseTEnt: bad type"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================= |
||||
|
CL_NewTempEntity |
||||
|
================= |
||||
|
*/ |
||||
|
entity_t *CL_NewTempEntity (void) |
||||
|
{ |
||||
|
entity_t *ent; |
||||
|
|
||||
|
if (cl_numvisedicts == MAX_VISEDICTS) |
||||
|
return NULL; |
||||
|
if (num_temp_entities == MAX_TEMP_ENTITIES) |
||||
|
return NULL; |
||||
|
ent = &cl_temp_entities[num_temp_entities]; |
||||
|
memset (ent, 0, sizeof(*ent)); |
||||
|
num_temp_entities++; |
||||
|
cl_visedicts[cl_numvisedicts] = ent; |
||||
|
cl_numvisedicts++; |
||||
|
|
||||
|
ent->colormap = vid.colormap; |
||||
|
return ent; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================= |
||||
|
CL_UpdateTEnts |
||||
|
================= |
||||
|
*/ |
||||
|
void CL_UpdateTEnts (void) |
||||
|
{ |
||||
|
int i; |
||||
|
beam_t *b; |
||||
|
vec3_t dist, org; |
||||
|
float d; |
||||
|
entity_t *ent; |
||||
|
float yaw, pitch; |
||||
|
float forward; |
||||
|
|
||||
|
num_temp_entities = 0; |
||||
|
|
||||
|
// update lightning |
||||
|
for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++) |
||||
|
{ |
||||
|
if (!b->model || b->endtime < cl.time) |
||||
|
continue; |
||||
|
|
||||
|
// if coming from the player, update the start position |
||||
|
if (b->entity == cl.viewentity) |
||||
|
{ |
||||
|
VectorCopy (cl_entities[cl.viewentity].origin, b->start); |
||||
|
} |
||||
|
|
||||
|
// calculate pitch and yaw |
||||
|
VectorSubtract (b->end, b->start, dist); |
||||
|
|
||||
|
if (dist[1] == 0 && dist[0] == 0) |
||||
|
{ |
||||
|
yaw = 0; |
||||
|
if (dist[2] > 0) |
||||
|
pitch = 90; |
||||
|
else |
||||
|
pitch = 270; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
yaw = (int) (atan2(dist[1], dist[0]) * 180 / M_PI); |
||||
|
if (yaw < 0) |
||||
|
yaw += 360; |
||||
|
|
||||
|
forward = sqrt (dist[0]*dist[0] + dist[1]*dist[1]); |
||||
|
pitch = (int) (atan2(dist[2], forward) * 180 / M_PI); |
||||
|
if (pitch < 0) |
||||
|
pitch += 360; |
||||
|
} |
||||
|
|
||||
|
// add new entities for the lightning |
||||
|
VectorCopy (b->start, org); |
||||
|
d = VectorNormalize(dist); |
||||
|
while (d > 0) |
||||
|
{ |
||||
|
ent = CL_NewTempEntity (); |
||||
|
if (!ent) |
||||
|
return; |
||||
|
VectorCopy (org, ent->origin); |
||||
|
ent->model = b->model; |
||||
|
ent->angles[0] = pitch; |
||||
|
ent->angles[1] = yaw; |
||||
|
ent->angles[2] = rand()%360; |
||||
|
|
||||
|
for (i=0 ; i<3 ; i++) |
||||
|
org[i] += dist[i]*30; |
||||
|
d -= 30; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
@ -0,0 +1,408 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// client.h |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
vec3_t viewangles; |
||||
|
|
||||
|
// intended velocities |
||||
|
float forwardmove; |
||||
|
float sidemove; |
||||
|
float upmove; |
||||
|
|
||||
|
#ifdef QUAKE2 |
||||
|
byte lightlevel; |
||||
|
#endif |
||||
|
|
||||
|
} usercmd_t; |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
int length; |
||||
|
char map[MAX_STYLESTRING]; |
||||
|
} lightstyle_t; |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
char name[MAX_SCOREBOARDNAME]; |
||||
|
float entertime; |
||||
|
int frags; |
||||
|
int colors; // two 4 bit fields |
||||
|
byte translations[VID_GRADES*256]; |
||||
|
} scoreboard_t; |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
int destcolor[3]; |
||||
|
int percent; // 0-256 |
||||
|
} cshift_t; |
||||
|
|
||||
|
#define CSHIFT_CONTENTS 0 |
||||
|
#define CSHIFT_DAMAGE 1 |
||||
|
#define CSHIFT_BONUS 2 |
||||
|
#define CSHIFT_POWERUP 3 |
||||
|
#define NUM_CSHIFTS 4 |
||||
|
|
||||
|
#define NAME_LENGTH 64 |
||||
|
|
||||
|
|
||||
|
// |
||||
|
// client_state_t should hold all pieces of the client state |
||||
|
// |
||||
|
|
||||
|
#define SIGNONS 4 // signon messages to receive before connected |
||||
|
|
||||
|
// jkrige - increase dlights |
||||
|
//#define MAX_DLIGHTS 32 |
||||
|
#define MAX_DLIGHTS 64 |
||||
|
// jkrige - increase dlights |
||||
|
|
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
vec3_t origin; |
||||
|
float radius; |
||||
|
float die; // stop lighting after this time |
||||
|
float decay; // drop this each second |
||||
|
float minlight; // don't add when contributing less |
||||
|
int key; |
||||
|
#ifdef QUAKE2 |
||||
|
qboolean dark; // subtracts light instead of adding |
||||
|
#endif |
||||
|
|
||||
|
// jkrige - .lit colored lights |
||||
|
vec3_t color; |
||||
|
// jkrige - .lit colored lights |
||||
|
|
||||
|
} dlight_t; |
||||
|
|
||||
|
|
||||
|
#define MAX_BEAMS 24 |
||||
|
typedef struct |
||||
|
{ |
||||
|
int entity; |
||||
|
struct model_s *model; |
||||
|
float endtime; |
||||
|
vec3_t start, end; |
||||
|
} beam_t; |
||||
|
|
||||
|
#define MAX_EFRAGS 640 |
||||
|
|
||||
|
#define MAX_MAPSTRING 2048 |
||||
|
#define MAX_DEMOS 8 |
||||
|
#define MAX_DEMONAME 16 |
||||
|
|
||||
|
typedef enum { |
||||
|
ca_dedicated, // a dedicated server with no ability to start a client |
||||
|
ca_disconnected, // full screen console with no connection |
||||
|
ca_connected // valid netcon, talking to a server |
||||
|
} cactive_t; |
||||
|
|
||||
|
// |
||||
|
// the client_static_t structure is persistant through an arbitrary number |
||||
|
// of server connections |
||||
|
// |
||||
|
typedef struct |
||||
|
{ |
||||
|
cactive_t state; |
||||
|
|
||||
|
// personalization data sent to server |
||||
|
char mapstring[MAX_QPATH]; |
||||
|
char spawnparms[MAX_MAPSTRING]; // to restart a level |
||||
|
|
||||
|
// demo loop control |
||||
|
int demonum; // -1 = don't play demos |
||||
|
char demos[MAX_DEMOS][MAX_DEMONAME]; // when not playing |
||||
|
|
||||
|
// demo recording info must be here, because record is started before |
||||
|
// entering a map (and clearing client_state_t) |
||||
|
qboolean demorecording; |
||||
|
qboolean demoplayback; |
||||
|
qboolean timedemo; |
||||
|
int forcetrack; // -1 = use normal cd track |
||||
|
FILE *demofile; |
||||
|
|
||||
|
// jkrige - pk3 file support |
||||
|
byte *demobuffer; |
||||
|
int demobufferlength; |
||||
|
int demobufferposition; |
||||
|
// jkrige - pk3 file support |
||||
|
|
||||
|
int td_lastframe; // to meter out one message a frame |
||||
|
int td_startframe; // host_framecount at start |
||||
|
float td_starttime; // realtime at second frame of timedemo |
||||
|
|
||||
|
|
||||
|
// connection information |
||||
|
int signon; // 0 to SIGNONS |
||||
|
struct qsocket_s *netcon; |
||||
|
sizebuf_t message; // writing buffer to send to server |
||||
|
|
||||
|
} client_static_t; |
||||
|
|
||||
|
extern client_static_t cls; |
||||
|
|
||||
|
// |
||||
|
// the client_state_t structure is wiped completely at every |
||||
|
// server signon |
||||
|
// |
||||
|
typedef struct |
||||
|
{ |
||||
|
int movemessages; // since connecting to this server |
||||
|
// throw out the first couple, so the player |
||||
|
// doesn't accidentally do something the |
||||
|
// first frame |
||||
|
usercmd_t cmd; // last command sent to the server |
||||
|
|
||||
|
// information for local display |
||||
|
int stats[MAX_CL_STATS]; // health, etc |
||||
|
int items; // inventory bit flags |
||||
|
float item_gettime[32]; // cl.time of aquiring item, for blinking |
||||
|
float faceanimtime; // use anim frame if cl.time < this |
||||
|
|
||||
|
cshift_t cshifts[NUM_CSHIFTS]; // color shifts for damage, powerups |
||||
|
cshift_t prev_cshifts[NUM_CSHIFTS]; // and content types |
||||
|
|
||||
|
// the client maintains its own idea of view angles, which are |
||||
|
// sent to the server each frame. The server sets punchangle when |
||||
|
// the view is temporarliy offset, and an angle reset commands at the start |
||||
|
// of each level and after teleporting. |
||||
|
vec3_t mviewangles[2]; // during demo playback viewangles is lerped |
||||
|
// between these |
||||
|
vec3_t viewangles; |
||||
|
|
||||
|
vec3_t mvelocity[2]; // update by server, used for lean+bob |
||||
|
// (0 is newest) |
||||
|
vec3_t velocity; // lerped between mvelocity[0] and [1] |
||||
|
|
||||
|
vec3_t punchangle; // temporary offset |
||||
|
|
||||
|
// pitch drifting vars |
||||
|
float idealpitch; |
||||
|
float pitchvel; |
||||
|
qboolean nodrift; |
||||
|
float driftmove; |
||||
|
double laststop; |
||||
|
|
||||
|
float viewheight; |
||||
|
float crouch; // local amount for smoothing stepups |
||||
|
|
||||
|
qboolean paused; // send over by server |
||||
|
qboolean onground; |
||||
|
qboolean inwater; |
||||
|
|
||||
|
|
||||
|
int intermission; // don't change view angle, full screen, etc |
||||
|
int completed_time; // latched at intermission start |
||||
|
|
||||
|
double mtime[2]; // the timestamp of last two messages |
||||
|
double time; // clients view of time, should be between |
||||
|
// servertime and oldservertime to generate |
||||
|
// a lerp point for other data |
||||
|
double oldtime; // previous cl.time, time-oldtime is used |
||||
|
// to decay light values and smooth step ups |
||||
|
|
||||
|
|
||||
|
float last_received_message; // (realtime) for net trouble icon |
||||
|
|
||||
|
// |
||||
|
// information that is static for the entire time connected to a server |
||||
|
// |
||||
|
struct model_s *model_precache[MAX_MODELS]; |
||||
|
struct sfx_s *sound_precache[MAX_SOUNDS]; |
||||
|
|
||||
|
char levelname[40]; // for display on solo scoreboard |
||||
|
int viewentity; // cl_entitites[cl.viewentity] = player |
||||
|
int maxclients; |
||||
|
int gametype; |
||||
|
|
||||
|
// refresh related state |
||||
|
struct model_s *worldmodel; // cl_entitites[0].model |
||||
|
struct efrag_s *free_efrags; |
||||
|
int num_entities; // held in cl_entities array |
||||
|
int num_statics; // held in cl_staticentities array |
||||
|
entity_t viewent; // the gun model |
||||
|
|
||||
|
int cdtrack, looptrack; // cd audio |
||||
|
|
||||
|
// jkrige - skybox |
||||
|
char skybox[128]; |
||||
|
// jkrige - skybox |
||||
|
|
||||
|
// frag scoreboard |
||||
|
scoreboard_t *scores; // [cl.maxclients] |
||||
|
|
||||
|
#ifdef QUAKE2 |
||||
|
// light level at player's position including dlights |
||||
|
// this is sent back to the server each frame |
||||
|
// architectually ugly but it works |
||||
|
int light_level; |
||||
|
#endif |
||||
|
} client_state_t; |
||||
|
|
||||
|
|
||||
|
// |
||||
|
// cvars |
||||
|
// |
||||
|
extern cvar_t cl_name; |
||||
|
extern cvar_t cl_color; |
||||
|
|
||||
|
extern cvar_t cl_upspeed; |
||||
|
extern cvar_t cl_forwardspeed; |
||||
|
extern cvar_t cl_backspeed; |
||||
|
extern cvar_t cl_sidespeed; |
||||
|
|
||||
|
extern cvar_t cl_movespeedkey; |
||||
|
|
||||
|
extern cvar_t cl_yawspeed; |
||||
|
extern cvar_t cl_pitchspeed; |
||||
|
|
||||
|
extern cvar_t cl_anglespeedkey; |
||||
|
|
||||
|
extern cvar_t cl_autofire; |
||||
|
|
||||
|
extern cvar_t cl_shownet; |
||||
|
extern cvar_t cl_nolerp; |
||||
|
|
||||
|
// jkrige - configurable fps caps |
||||
|
extern cvar_t cl_maxfps; |
||||
|
// jkrige - configurable fps caps |
||||
|
|
||||
|
extern cvar_t cl_pitchdriftspeed; |
||||
|
extern cvar_t lookspring; |
||||
|
extern cvar_t lookstrafe; |
||||
|
extern cvar_t sensitivity; |
||||
|
|
||||
|
extern cvar_t crosshair; // jkrige - crosshair |
||||
|
|
||||
|
extern cvar_t cl_mlook; // jkrige - mlook cvar |
||||
|
extern cvar_t cl_slook; // jkrige - slook cvar |
||||
|
|
||||
|
extern cvar_t m_pitch; |
||||
|
extern cvar_t m_yaw; |
||||
|
extern cvar_t m_forward; |
||||
|
extern cvar_t m_side; |
||||
|
|
||||
|
|
||||
|
#define MAX_TEMP_ENTITIES 64 // lightning bolts, etc |
||||
|
#define MAX_STATIC_ENTITIES 128 // torches, etc |
||||
|
|
||||
|
extern client_state_t cl; |
||||
|
|
||||
|
// FIXME, allocate dynamically |
||||
|
extern efrag_t cl_efrags[MAX_EFRAGS]; |
||||
|
extern entity_t cl_entities[MAX_EDICTS]; |
||||
|
extern entity_t cl_static_entities[MAX_STATIC_ENTITIES]; |
||||
|
extern lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; |
||||
|
extern dlight_t cl_dlights[MAX_DLIGHTS]; |
||||
|
extern entity_t cl_temp_entities[MAX_TEMP_ENTITIES]; |
||||
|
extern beam_t cl_beams[MAX_BEAMS]; |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
// |
||||
|
// cl_main |
||||
|
// |
||||
|
dlight_t *CL_AllocDlight (int key); |
||||
|
void CL_DecayLights (void); |
||||
|
|
||||
|
void CL_Init (void); |
||||
|
|
||||
|
void CL_EstablishConnection (char *host); |
||||
|
void CL_Signon1 (void); |
||||
|
void CL_Signon2 (void); |
||||
|
void CL_Signon3 (void); |
||||
|
void CL_Signon4 (void); |
||||
|
|
||||
|
void CL_Disconnect (void); |
||||
|
void CL_Disconnect_f (void); |
||||
|
void CL_NextDemo (void); |
||||
|
|
||||
|
#define MAX_VISEDICTS 256 |
||||
|
extern int cl_numvisedicts; |
||||
|
extern entity_t *cl_visedicts[MAX_VISEDICTS]; |
||||
|
|
||||
|
// |
||||
|
// cl_input |
||||
|
// |
||||
|
typedef struct |
||||
|
{ |
||||
|
int down[2]; // key nums holding it down |
||||
|
int state; // low bit is down state |
||||
|
} kbutton_t; |
||||
|
|
||||
|
//extern kbutton_t /*in_mlook,*/ in_klook; // jkrige - mlook cvar, removed klook command |
||||
|
extern kbutton_t in_strafe; |
||||
|
extern kbutton_t in_speed; |
||||
|
|
||||
|
void CL_InitInput (void); |
||||
|
void CL_SendCmd (void); |
||||
|
void CL_SendMove (usercmd_t *cmd); |
||||
|
|
||||
|
void CL_ParseTEnt (void); |
||||
|
void CL_UpdateTEnts (void); |
||||
|
|
||||
|
void CL_ClearState (void); |
||||
|
|
||||
|
|
||||
|
int CL_ReadFromServer (void); |
||||
|
void CL_WriteToServer (usercmd_t *cmd); |
||||
|
void CL_BaseMove (usercmd_t *cmd); |
||||
|
|
||||
|
|
||||
|
float CL_KeyState (kbutton_t *key); |
||||
|
char *Key_KeynumToString (int keynum); |
||||
|
|
||||
|
// |
||||
|
// cl_demo.c |
||||
|
// |
||||
|
void CL_StopPlayback (void); |
||||
|
int CL_GetMessage (void); |
||||
|
|
||||
|
void CL_Stop_f (void); |
||||
|
void CL_Record_f (void); |
||||
|
void CL_PlayDemo_f (void); |
||||
|
void CL_TimeDemo_f (void); |
||||
|
|
||||
|
// |
||||
|
// cl_parse.c |
||||
|
// |
||||
|
void CL_ParseServerMessage (void); |
||||
|
void CL_NewTranslation (int slot); |
||||
|
|
||||
|
// |
||||
|
// view |
||||
|
// |
||||
|
void V_StartPitchDrift (void); |
||||
|
void V_StopPitchDrift (void); |
||||
|
|
||||
|
void V_RenderView (void); |
||||
|
void V_UpdatePalette (void); |
||||
|
void V_Register (void); |
||||
|
void V_ParseDamage (void); |
||||
|
void V_SetContentsColor (int contents); |
||||
|
|
||||
|
|
||||
|
// |
||||
|
// cl_tent |
||||
|
// |
||||
|
void CL_InitTEnts (void); |
||||
|
void CL_SignonReply (void); |
||||
@ -0,0 +1,753 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// cmd.c -- Quake script command processing module |
||||
|
|
||||
|
#include "quakedef.h" |
||||
|
|
||||
|
void Cmd_ForwardToServer (void); |
||||
|
|
||||
|
#define MAX_ALIAS_NAME 32 |
||||
|
|
||||
|
typedef struct cmdalias_s |
||||
|
{ |
||||
|
struct cmdalias_s *next; |
||||
|
char name[MAX_ALIAS_NAME]; |
||||
|
char *value; |
||||
|
} cmdalias_t; |
||||
|
|
||||
|
cmdalias_t *cmd_alias; |
||||
|
|
||||
|
int trashtest; |
||||
|
int *trashspot; |
||||
|
|
||||
|
qboolean cmd_wait; |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
Cmd_Wait_f |
||||
|
|
||||
|
Causes execution of the remainder of the command buffer to be delayed until |
||||
|
next frame. This allows commands like: |
||||
|
bind g "impulse 5 ; +attack ; wait ; -attack ; impulse 2" |
||||
|
============ |
||||
|
*/ |
||||
|
void Cmd_Wait_f (void) |
||||
|
{ |
||||
|
cmd_wait = true; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
============================================================================= |
||||
|
|
||||
|
COMMAND BUFFER |
||||
|
|
||||
|
============================================================================= |
||||
|
*/ |
||||
|
|
||||
|
sizebuf_t cmd_text; |
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
Cbuf_Init |
||||
|
============ |
||||
|
*/ |
||||
|
void Cbuf_Init (void) |
||||
|
{ |
||||
|
SZ_Alloc (&cmd_text, 8192); // space for commands and script files |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
Cbuf_AddText |
||||
|
|
||||
|
Adds command text at the end of the buffer |
||||
|
============ |
||||
|
*/ |
||||
|
void Cbuf_AddText (char *text) |
||||
|
{ |
||||
|
int l; |
||||
|
|
||||
|
l = Q_strlen (text); |
||||
|
|
||||
|
if (cmd_text.cursize + l >= cmd_text.maxsize) |
||||
|
{ |
||||
|
Con_Printf ("Cbuf_AddText: overflow\n"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
SZ_Write (&cmd_text, text, Q_strlen (text)); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
Cbuf_InsertText |
||||
|
|
||||
|
Adds command text immediately after the current command |
||||
|
Adds a \n to the text |
||||
|
FIXME: actually change the command buffer to do less copying |
||||
|
============ |
||||
|
*/ |
||||
|
void Cbuf_InsertText (char *text) |
||||
|
{ |
||||
|
char *temp; |
||||
|
int templen; |
||||
|
|
||||
|
// copy off any commands still remaining in the exec buffer |
||||
|
templen = cmd_text.cursize; |
||||
|
if (templen) |
||||
|
{ |
||||
|
temp = Z_Malloc (templen); |
||||
|
Q_memcpy (temp, cmd_text.data, templen); |
||||
|
SZ_Clear (&cmd_text); |
||||
|
} |
||||
|
else |
||||
|
temp = NULL; // shut up compiler |
||||
|
|
||||
|
// add the entire text of the file |
||||
|
Cbuf_AddText (text); |
||||
|
|
||||
|
// add the copied off data |
||||
|
if (templen) |
||||
|
{ |
||||
|
SZ_Write (&cmd_text, temp, templen); |
||||
|
Z_Free (temp); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
Cbuf_Execute |
||||
|
============ |
||||
|
*/ |
||||
|
void Cbuf_Execute (void) |
||||
|
{ |
||||
|
int i; |
||||
|
char *text; |
||||
|
char line[1024]; |
||||
|
int quotes; |
||||
|
|
||||
|
while (cmd_text.cursize) |
||||
|
{ |
||||
|
// find a \n or ; line break |
||||
|
text = (char *)cmd_text.data; |
||||
|
|
||||
|
quotes = 0; |
||||
|
for (i=0 ; i< cmd_text.cursize ; i++) |
||||
|
{ |
||||
|
if (text[i] == '"') |
||||
|
quotes++; |
||||
|
if ( !(quotes&1) && text[i] == ';') |
||||
|
break; // don't break if inside a quoted string |
||||
|
if (text[i] == '\n') |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
memcpy (line, text, i); |
||||
|
line[i] = 0; |
||||
|
|
||||
|
// delete the text from the command buffer and move remaining commands down |
||||
|
// this is necessary because commands (exec, alias) can insert data at the |
||||
|
// beginning of the text buffer |
||||
|
|
||||
|
if (i == cmd_text.cursize) |
||||
|
cmd_text.cursize = 0; |
||||
|
else |
||||
|
{ |
||||
|
i++; |
||||
|
cmd_text.cursize -= i; |
||||
|
Q_memcpy (text, text+i, cmd_text.cursize); |
||||
|
} |
||||
|
|
||||
|
// execute the command line |
||||
|
Cmd_ExecuteString (line, src_command); |
||||
|
|
||||
|
if (cmd_wait) |
||||
|
{ // skip out while text still remains in buffer, leaving it |
||||
|
// for next frame |
||||
|
cmd_wait = false; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
============================================================================== |
||||
|
|
||||
|
SCRIPT COMMANDS |
||||
|
|
||||
|
============================================================================== |
||||
|
*/ |
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
Cmd_StuffCmds_f |
||||
|
|
||||
|
Adds command line parameters as script statements |
||||
|
Commands lead with a +, and continue until a - or another + |
||||
|
quake +prog jctest.qp +cmd amlev1 |
||||
|
quake -nosound +cmd amlev1 |
||||
|
=============== |
||||
|
*/ |
||||
|
void Cmd_StuffCmds_f (void) |
||||
|
{ |
||||
|
int i, j; |
||||
|
int s; |
||||
|
char *text, *build, c; |
||||
|
|
||||
|
if (Cmd_Argc () != 1) |
||||
|
{ |
||||
|
Con_Printf ("stuffcmds : execute command line parameters\n"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// build the combined string to parse from |
||||
|
s = 0; |
||||
|
for (i=1 ; i<com_argc ; i++) |
||||
|
{ |
||||
|
if (!com_argv[i]) |
||||
|
continue; // NEXTSTEP nulls out -NXHost |
||||
|
s += Q_strlen (com_argv[i]) + 1; |
||||
|
} |
||||
|
if (!s) |
||||
|
return; |
||||
|
|
||||
|
text = Z_Malloc (s+1); |
||||
|
text[0] = 0; |
||||
|
for (i=1 ; i<com_argc ; i++) |
||||
|
{ |
||||
|
if (!com_argv[i]) |
||||
|
continue; // NEXTSTEP nulls out -NXHost |
||||
|
Q_strcat (text,com_argv[i]); |
||||
|
if (i != com_argc-1) |
||||
|
Q_strcat (text, " "); |
||||
|
} |
||||
|
|
||||
|
// pull out the commands |
||||
|
build = Z_Malloc (s+1); |
||||
|
build[0] = 0; |
||||
|
|
||||
|
for (i=0 ; i<s-1 ; i++) |
||||
|
{ |
||||
|
if (text[i] == '+') |
||||
|
{ |
||||
|
i++; |
||||
|
|
||||
|
for (j=i ; (text[j] != '+') && (text[j] != '-') && (text[j] != 0) ; j++) |
||||
|
; |
||||
|
|
||||
|
c = text[j]; |
||||
|
text[j] = 0; |
||||
|
|
||||
|
Q_strcat (build, text+i); |
||||
|
Q_strcat (build, "\n"); |
||||
|
text[j] = c; |
||||
|
i = j-1; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (build[0]) |
||||
|
Cbuf_InsertText (build); |
||||
|
|
||||
|
Z_Free (text); |
||||
|
Z_Free (build); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
Cmd_Exec_f |
||||
|
=============== |
||||
|
*/ |
||||
|
void Cmd_Exec_f (void) |
||||
|
{ |
||||
|
char *f; |
||||
|
int mark; |
||||
|
|
||||
|
if (Cmd_Argc () != 2) |
||||
|
{ |
||||
|
Con_Printf ("exec <filename> : execute a script file\n"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
mark = Hunk_LowMark (); |
||||
|
f = (char *)COM_LoadHunkFile (Cmd_Argv(1)); |
||||
|
if (!f) |
||||
|
{ |
||||
|
Con_Printf ("couldn't exec %s\n",Cmd_Argv(1)); |
||||
|
return; |
||||
|
} |
||||
|
Con_Printf ("execing %s\n",Cmd_Argv(1)); |
||||
|
|
||||
|
Cbuf_InsertText (f); |
||||
|
Hunk_FreeToLowMark (mark); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
Cmd_Echo_f |
||||
|
|
||||
|
Just prints the rest of the line to the console |
||||
|
=============== |
||||
|
*/ |
||||
|
void Cmd_Echo_f (void) |
||||
|
{ |
||||
|
int i; |
||||
|
|
||||
|
for (i=1 ; i<Cmd_Argc() ; i++) |
||||
|
Con_Printf ("%s ",Cmd_Argv(i)); |
||||
|
Con_Printf ("\n"); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
Cmd_Alias_f |
||||
|
|
||||
|
Creates a new command that executes a command string (possibly ; seperated) |
||||
|
=============== |
||||
|
*/ |
||||
|
|
||||
|
char *CopyString (char *in) |
||||
|
{ |
||||
|
char *out; |
||||
|
|
||||
|
out = Z_Malloc (strlen(in)+1); |
||||
|
strcpy (out, in); |
||||
|
return out; |
||||
|
} |
||||
|
|
||||
|
void Cmd_Alias_f (void) |
||||
|
{ |
||||
|
cmdalias_t *a; |
||||
|
char cmd[1024]; |
||||
|
int i, c; |
||||
|
char *s; |
||||
|
|
||||
|
if (Cmd_Argc() == 1) |
||||
|
{ |
||||
|
Con_Printf ("Current alias commands:\n"); |
||||
|
for (a = cmd_alias ; a ; a=a->next) |
||||
|
Con_Printf ("%s : %s\n", a->name, a->value); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
s = Cmd_Argv(1); |
||||
|
if (strlen(s) >= MAX_ALIAS_NAME) |
||||
|
{ |
||||
|
Con_Printf ("Alias name is too long\n"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// if the alias allready exists, reuse it |
||||
|
for (a = cmd_alias ; a ; a=a->next) |
||||
|
{ |
||||
|
if (!strcmp(s, a->name)) |
||||
|
{ |
||||
|
Z_Free (a->value); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (!a) |
||||
|
{ |
||||
|
a = Z_Malloc (sizeof(cmdalias_t)); |
||||
|
a->next = cmd_alias; |
||||
|
cmd_alias = a; |
||||
|
} |
||||
|
strcpy (a->name, s); |
||||
|
|
||||
|
// copy the rest of the command line |
||||
|
cmd[0] = 0; // start out with a null string |
||||
|
c = Cmd_Argc(); |
||||
|
for (i=2 ; i< c ; i++) |
||||
|
{ |
||||
|
strcat (cmd, Cmd_Argv(i)); |
||||
|
if (i != c) |
||||
|
strcat (cmd, " "); |
||||
|
} |
||||
|
strcat (cmd, "\n"); |
||||
|
|
||||
|
a->value = CopyString (cmd); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
============================================================================= |
||||
|
|
||||
|
COMMAND EXECUTION |
||||
|
|
||||
|
============================================================================= |
||||
|
*/ |
||||
|
|
||||
|
typedef struct cmd_function_s |
||||
|
{ |
||||
|
struct cmd_function_s *next; |
||||
|
char *name; |
||||
|
xcommand_t function; |
||||
|
} cmd_function_t; |
||||
|
|
||||
|
|
||||
|
#define MAX_ARGS 80 |
||||
|
|
||||
|
static int cmd_argc; |
||||
|
static char *cmd_argv[MAX_ARGS]; |
||||
|
static char *cmd_null_string = ""; |
||||
|
static char *cmd_args = NULL; |
||||
|
|
||||
|
cmd_source_t cmd_source; |
||||
|
|
||||
|
|
||||
|
static cmd_function_t *cmd_functions; // possible commands to execute |
||||
|
|
||||
|
// jkrige - cmdlist |
||||
|
/* |
||||
|
======== |
||||
|
Cmd_List |
||||
|
======== |
||||
|
*/ |
||||
|
void Cmd_List_f (void) |
||||
|
{ |
||||
|
cmd_function_t *cmd; |
||||
|
char *partial; |
||||
|
int len; |
||||
|
int count; |
||||
|
|
||||
|
if (Cmd_Argc() > 1) |
||||
|
{ |
||||
|
partial = Cmd_Argv (1); |
||||
|
len = strlen(partial); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
partial = NULL; |
||||
|
len = 0; |
||||
|
} |
||||
|
|
||||
|
count=0; |
||||
|
|
||||
|
for (cmd=cmd_functions ; cmd ; cmd=cmd->next) |
||||
|
{ |
||||
|
if (partial && strncmp (partial,cmd->name, len)) |
||||
|
{ |
||||
|
continue; |
||||
|
} |
||||
|
Con_Printf ("\"%s\"\n", cmd->name); |
||||
|
count++; |
||||
|
} |
||||
|
|
||||
|
Con_Printf ("%i command(s)", count); |
||||
|
|
||||
|
if (partial) |
||||
|
{ |
||||
|
Con_Printf (" beginning with \"%s\"", partial); |
||||
|
} |
||||
|
Con_Printf ("\n"); |
||||
|
} |
||||
|
// jkrige - cmdlist |
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
Cmd_Init |
||||
|
============ |
||||
|
*/ |
||||
|
void Cmd_Init (void) |
||||
|
{ |
||||
|
// |
||||
|
// register our commands |
||||
|
// |
||||
|
Cmd_AddCommand ("stuffcmds",Cmd_StuffCmds_f); |
||||
|
Cmd_AddCommand ("exec",Cmd_Exec_f); |
||||
|
Cmd_AddCommand ("echo",Cmd_Echo_f); |
||||
|
Cmd_AddCommand ("alias",Cmd_Alias_f); |
||||
|
Cmd_AddCommand ("cmd", Cmd_ForwardToServer); |
||||
|
Cmd_AddCommand ("wait", Cmd_Wait_f); |
||||
|
Cmd_AddCommand ("cmdlist", Cmd_List_f); // jkrige - cmdlist |
||||
|
Cmd_AddCommand ("cvarlist", Cvar_List_f); // jkrige - cvarlist |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
Cmd_Argc |
||||
|
============ |
||||
|
*/ |
||||
|
int Cmd_Argc (void) |
||||
|
{ |
||||
|
return cmd_argc; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
Cmd_Argv |
||||
|
============ |
||||
|
*/ |
||||
|
char *Cmd_Argv (int arg) |
||||
|
{ |
||||
|
if ( (unsigned)arg >= cmd_argc ) |
||||
|
return cmd_null_string; |
||||
|
return cmd_argv[arg]; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
Cmd_Args |
||||
|
============ |
||||
|
*/ |
||||
|
char *Cmd_Args (void) |
||||
|
{ |
||||
|
return cmd_args; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
Cmd_TokenizeString |
||||
|
|
||||
|
Parses the given string into command line tokens. |
||||
|
============ |
||||
|
*/ |
||||
|
void Cmd_TokenizeString (char *text) |
||||
|
{ |
||||
|
int i; |
||||
|
|
||||
|
// clear the args from the last string |
||||
|
for (i=0 ; i<cmd_argc ; i++) |
||||
|
Z_Free (cmd_argv[i]); |
||||
|
|
||||
|
cmd_argc = 0; |
||||
|
cmd_args = NULL; |
||||
|
|
||||
|
while (1) |
||||
|
{ |
||||
|
// skip whitespace up to a /n |
||||
|
while (*text && *text <= ' ' && *text != '\n') |
||||
|
{ |
||||
|
text++; |
||||
|
} |
||||
|
|
||||
|
if (*text == '\n') |
||||
|
{ // a newline seperates commands in the buffer |
||||
|
text++; |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
if (!*text) |
||||
|
return; |
||||
|
|
||||
|
if (cmd_argc == 1) |
||||
|
cmd_args = text; |
||||
|
|
||||
|
text = COM_Parse (text); |
||||
|
if (!text) |
||||
|
return; |
||||
|
|
||||
|
if (cmd_argc < MAX_ARGS) |
||||
|
{ |
||||
|
cmd_argv[cmd_argc] = Z_Malloc (Q_strlen(com_token)+1); |
||||
|
Q_strcpy (cmd_argv[cmd_argc], com_token); |
||||
|
cmd_argc++; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
Cmd_AddCommand |
||||
|
============ |
||||
|
*/ |
||||
|
void Cmd_AddCommand (char *cmd_name, xcommand_t function) |
||||
|
{ |
||||
|
cmd_function_t *cmd; |
||||
|
|
||||
|
if (host_initialized) // because hunk allocation would get stomped |
||||
|
Sys_Error ("Cmd_AddCommand after host_initialized"); |
||||
|
|
||||
|
// fail if the command is a variable name |
||||
|
if (Cvar_VariableString(cmd_name)[0]) |
||||
|
{ |
||||
|
Con_Printf ("Cmd_AddCommand: %s already defined as a var\n", cmd_name); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// fail if the command already exists |
||||
|
for (cmd=cmd_functions ; cmd ; cmd=cmd->next) |
||||
|
{ |
||||
|
if (!Q_strcmp (cmd_name, cmd->name)) |
||||
|
{ |
||||
|
Con_Printf ("Cmd_AddCommand: %s already defined\n", cmd_name); |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
cmd = Hunk_Alloc (sizeof(cmd_function_t)); |
||||
|
cmd->name = cmd_name; |
||||
|
cmd->function = function; |
||||
|
cmd->next = cmd_functions; |
||||
|
cmd_functions = cmd; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
Cmd_Exists |
||||
|
============ |
||||
|
*/ |
||||
|
qboolean Cmd_Exists (char *cmd_name) |
||||
|
{ |
||||
|
cmd_function_t *cmd; |
||||
|
|
||||
|
for (cmd=cmd_functions ; cmd ; cmd=cmd->next) |
||||
|
{ |
||||
|
if (!Q_strcmp (cmd_name,cmd->name)) |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
Cmd_CompleteCommand |
||||
|
============ |
||||
|
*/ |
||||
|
char *Cmd_CompleteCommand (char *partial) |
||||
|
{ |
||||
|
cmd_function_t *cmd; |
||||
|
int len; |
||||
|
|
||||
|
len = Q_strlen(partial); |
||||
|
|
||||
|
if (!len) |
||||
|
return NULL; |
||||
|
|
||||
|
// check functions |
||||
|
for (cmd=cmd_functions ; cmd ; cmd=cmd->next) |
||||
|
if (!Q_strncmp (partial,cmd->name, len)) |
||||
|
return cmd->name; |
||||
|
|
||||
|
return NULL; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
Cmd_ExecuteString |
||||
|
|
||||
|
A complete command line has been parsed, so try to execute it |
||||
|
FIXME: lookupnoadd the token to speed search? |
||||
|
============ |
||||
|
*/ |
||||
|
void Cmd_ExecuteString (char *text, cmd_source_t src) |
||||
|
{ |
||||
|
cmd_function_t *cmd; |
||||
|
cmdalias_t *a; |
||||
|
|
||||
|
cmd_source = src; |
||||
|
Cmd_TokenizeString (text); |
||||
|
|
||||
|
// execute the command line |
||||
|
if (!Cmd_Argc()) |
||||
|
return; // no tokens |
||||
|
|
||||
|
// check functions |
||||
|
for (cmd=cmd_functions ; cmd ; cmd=cmd->next) |
||||
|
{ |
||||
|
if (!Q_strcasecmp (cmd_argv[0],cmd->name)) |
||||
|
{ |
||||
|
cmd->function (); |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// check alias |
||||
|
for (a=cmd_alias ; a ; a=a->next) |
||||
|
{ |
||||
|
if (!Q_strcasecmp (cmd_argv[0], a->name)) |
||||
|
{ |
||||
|
Cbuf_InsertText (a->value); |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// check cvars |
||||
|
if (!Cvar_Command ()) |
||||
|
Con_Printf ("Unknown command \"%s\"\n", Cmd_Argv(0)); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
=================== |
||||
|
Cmd_ForwardToServer |
||||
|
|
||||
|
Sends the entire command line over to the server |
||||
|
=================== |
||||
|
*/ |
||||
|
void Cmd_ForwardToServer (void) |
||||
|
{ |
||||
|
if (cls.state != ca_connected) |
||||
|
{ |
||||
|
Con_Printf ("Can't \"%s\", not connected\n", Cmd_Argv(0)); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (cls.demoplayback) |
||||
|
return; // not really connected |
||||
|
|
||||
|
MSG_WriteByte (&cls.message, clc_stringcmd); |
||||
|
if (Q_strcasecmp(Cmd_Argv(0), "cmd") != 0) |
||||
|
{ |
||||
|
SZ_Print (&cls.message, Cmd_Argv(0)); |
||||
|
SZ_Print (&cls.message, " "); |
||||
|
} |
||||
|
if (Cmd_Argc() > 1) |
||||
|
SZ_Print (&cls.message, Cmd_Args()); |
||||
|
else |
||||
|
SZ_Print (&cls.message, "\n"); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================ |
||||
|
Cmd_CheckParm |
||||
|
|
||||
|
Returns the position (1 to argc-1) in the command's argument list |
||||
|
where the given parameter apears, or 0 if not present |
||||
|
================ |
||||
|
*/ |
||||
|
|
||||
|
int Cmd_CheckParm (char *parm) |
||||
|
{ |
||||
|
int i; |
||||
|
|
||||
|
if (!parm) |
||||
|
Sys_Error ("Cmd_CheckParm: NULL"); |
||||
|
|
||||
|
for (i = 1; i < Cmd_Argc (); i++) |
||||
|
if (! Q_strcasecmp (parm, Cmd_Argv (i))) |
||||
|
return i; |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
@ -0,0 +1,121 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
// cmd.h -- Command buffer and command execution |
||||
|
|
||||
|
//=========================================================================== |
||||
|
|
||||
|
/* |
||||
|
|
||||
|
Any number of commands can be added in a frame, from several different sources. |
||||
|
Most commands come from either keybindings or console line input, but remote |
||||
|
servers can also send across commands and entire text files can be execed. |
||||
|
|
||||
|
The + command line options are also added to the command buffer. |
||||
|
|
||||
|
The game starts with a Cbuf_AddText ("exec quake.rc\n"); Cbuf_Execute (); |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
|
||||
|
void Cbuf_Init (void); |
||||
|
// allocates an initial text buffer that will grow as needed |
||||
|
|
||||
|
void Cbuf_AddText (char *text); |
||||
|
// as new commands are generated from the console or keybindings, |
||||
|
// the text is added to the end of the command buffer. |
||||
|
|
||||
|
void Cbuf_InsertText (char *text); |
||||
|
// when a command wants to issue other commands immediately, the text is |
||||
|
// inserted at the beginning of the buffer, before any remaining unexecuted |
||||
|
// commands. |
||||
|
|
||||
|
void Cbuf_Execute (void); |
||||
|
// Pulls off \n terminated lines of text from the command buffer and sends |
||||
|
// them through Cmd_ExecuteString. Stops when the buffer is empty. |
||||
|
// Normally called once per frame, but may be explicitly invoked. |
||||
|
// Do not call inside a command function! |
||||
|
|
||||
|
//=========================================================================== |
||||
|
|
||||
|
/* |
||||
|
|
||||
|
Command execution takes a null terminated string, breaks it into tokens, |
||||
|
then searches for a command or variable that matches the first token. |
||||
|
|
||||
|
Commands can come from three sources, but the handler functions may choose |
||||
|
to dissallow the action or forward it to a remote server if the source is |
||||
|
not apropriate. |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
typedef void (*xcommand_t) (void); |
||||
|
|
||||
|
typedef enum |
||||
|
{ |
||||
|
src_client, // came in over a net connection as a clc_stringcmd |
||||
|
// host_client will be valid during this state. |
||||
|
src_command // from the command buffer |
||||
|
} cmd_source_t; |
||||
|
|
||||
|
extern cmd_source_t cmd_source; |
||||
|
|
||||
|
void Cmd_Init (void); |
||||
|
|
||||
|
void Cmd_AddCommand (char *cmd_name, xcommand_t function); |
||||
|
// called by the init functions of other parts of the program to |
||||
|
// register commands and functions to call for them. |
||||
|
// The cmd_name is referenced later, so it should not be in temp memory |
||||
|
|
||||
|
qboolean Cmd_Exists (char *cmd_name); |
||||
|
// used by the cvar code to check for cvar / command name overlap |
||||
|
|
||||
|
char *Cmd_CompleteCommand (char *partial); |
||||
|
// attempts to match a partial command for automatic command line completion |
||||
|
// returns NULL if nothing fits |
||||
|
|
||||
|
int Cmd_Argc (void); |
||||
|
char *Cmd_Argv (int arg); |
||||
|
char *Cmd_Args (void); |
||||
|
// The functions that execute commands get their parameters with these |
||||
|
// functions. Cmd_Argv () will return an empty string, not a NULL |
||||
|
// if arg > argc, so string operations are allways safe. |
||||
|
|
||||
|
int Cmd_CheckParm (char *parm); |
||||
|
// Returns the position (1 to argc-1) in the command's argument list |
||||
|
// where the given parameter apears, or 0 if not present |
||||
|
|
||||
|
void Cmd_TokenizeString (char *text); |
||||
|
// Takes a null terminated string. Does not need to be /n terminated. |
||||
|
// breaks the string up into arg tokens. |
||||
|
|
||||
|
void Cmd_ExecuteString (char *text, cmd_source_t src); |
||||
|
// Parses a single line of text into arguments and tries to execute it. |
||||
|
// The text can come from the command buffer, a remote client, or stdin. |
||||
|
|
||||
|
void Cmd_ForwardToServer (void); |
||||
|
// adds the current command line as a clc_stringcmd to the client message. |
||||
|
// things like godmode, noclip, etc, are commands directed to the server, |
||||
|
// so when they are typed in at the console, they will need to be forwarded. |
||||
|
|
||||
|
void Cmd_Print (char *text); |
||||
|
// used by command functions to send output to either the graphics console or |
||||
|
// passed as a print message to the client |
||||
|
|
||||
2226
engine/code/common.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,198 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// comndef.h -- general definitions |
||||
|
|
||||
|
#if !defined BYTE_DEFINED |
||||
|
typedef unsigned char byte; |
||||
|
#define BYTE_DEFINED 1 |
||||
|
#endif |
||||
|
|
||||
|
#undef true |
||||
|
#undef false |
||||
|
|
||||
|
typedef enum {false, true} qboolean; |
||||
|
|
||||
|
//============================================================================ |
||||
|
|
||||
|
typedef struct sizebuf_s |
||||
|
{ |
||||
|
qboolean allowoverflow; // if false, do a Sys_Error |
||||
|
qboolean overflowed; // set to true if the buffer size failed |
||||
|
byte *data; |
||||
|
int maxsize; |
||||
|
int cursize; |
||||
|
} sizebuf_t; |
||||
|
|
||||
|
void SZ_Alloc (sizebuf_t *buf, int startsize); |
||||
|
void SZ_Free (sizebuf_t *buf); |
||||
|
void SZ_Clear (sizebuf_t *buf); |
||||
|
void *SZ_GetSpace (sizebuf_t *buf, int length); |
||||
|
void SZ_Write (sizebuf_t *buf, void *data, int length); |
||||
|
void SZ_Print (sizebuf_t *buf, char *data); // strcats onto the sizebuf |
||||
|
|
||||
|
//============================================================================ |
||||
|
|
||||
|
typedef struct link_s |
||||
|
{ |
||||
|
struct link_s *prev, *next; |
||||
|
} link_t; |
||||
|
|
||||
|
|
||||
|
void ClearLink (link_t *l); |
||||
|
void RemoveLink (link_t *l); |
||||
|
void InsertLinkBefore (link_t *l, link_t *before); |
||||
|
void InsertLinkAfter (link_t *l, link_t *after); |
||||
|
|
||||
|
// (type *)STRUCT_FROM_LINK(link_t *link, type, member) |
||||
|
// ent = STRUCT_FROM_LINK(link,entity_t,order) |
||||
|
// FIXME: remove this mess! |
||||
|
#define STRUCT_FROM_LINK(l,t,m) ((t *)((byte *)l - (int)&(((t *)0)->m))) |
||||
|
|
||||
|
//============================================================================ |
||||
|
|
||||
|
#ifndef NULL |
||||
|
#define NULL ((void *)0) |
||||
|
#endif |
||||
|
|
||||
|
#define Q_MAXCHAR ((char)0x7f) |
||||
|
#define Q_MAXSHORT ((short)0x7fff) |
||||
|
#define Q_MAXINT ((int)0x7fffffff) |
||||
|
#define Q_MAXLONG ((int)0x7fffffff) |
||||
|
#define Q_MAXFLOAT ((int)0x7fffffff) |
||||
|
|
||||
|
#define Q_MINCHAR ((char)0x80) |
||||
|
#define Q_MINSHORT ((short)0x8000) |
||||
|
#define Q_MININT ((int)0x80000000) |
||||
|
#define Q_MINLONG ((int)0x80000000) |
||||
|
#define Q_MINFLOAT ((int)0x7fffffff) |
||||
|
|
||||
|
//============================================================================ |
||||
|
|
||||
|
extern qboolean bigendien; |
||||
|
|
||||
|
extern short (*BigShort) (short l); |
||||
|
extern short (*LittleShort) (short l); |
||||
|
extern int (*BigLong) (int l); |
||||
|
extern int (*LittleLong) (int l); |
||||
|
extern float (*BigFloat) (float l); |
||||
|
extern float (*LittleFloat) (float l); |
||||
|
|
||||
|
//============================================================================ |
||||
|
|
||||
|
void MSG_WriteChar (sizebuf_t *sb, int c); |
||||
|
void MSG_WriteByte (sizebuf_t *sb, int c); |
||||
|
void MSG_WriteShort (sizebuf_t *sb, int c); |
||||
|
void MSG_WriteLong (sizebuf_t *sb, int c); |
||||
|
void MSG_WriteFloat (sizebuf_t *sb, float f); |
||||
|
void MSG_WriteString (sizebuf_t *sb, char *s); |
||||
|
void MSG_WriteCoord (sizebuf_t *sb, float f); |
||||
|
void MSG_WriteAngle (sizebuf_t *sb, float f); |
||||
|
|
||||
|
extern int msg_readcount; |
||||
|
extern qboolean msg_badread; // set if a read goes beyond end of message |
||||
|
|
||||
|
void MSG_BeginReading (void); |
||||
|
int MSG_ReadChar (void); |
||||
|
int MSG_ReadByte (void); |
||||
|
int MSG_ReadShort (void); |
||||
|
int MSG_ReadLong (void); |
||||
|
float MSG_ReadFloat (void); |
||||
|
char *MSG_ReadString (void); |
||||
|
|
||||
|
float MSG_ReadCoord (void); |
||||
|
float MSG_ReadAngle (void); |
||||
|
|
||||
|
//============================================================================ |
||||
|
|
||||
|
// jkrige - scale2d |
||||
|
extern int Scale2DWidth; |
||||
|
extern int Scale2DHeight; |
||||
|
extern float Scale2DFactor; |
||||
|
extern void COM_SetScale2D(); |
||||
|
// jkrige - scale2d |
||||
|
|
||||
|
void Q_memset (void *dest, int fill, int count); |
||||
|
void Q_memcpy (void *dest, void *src, int count); |
||||
|
int Q_memcmp (void *m1, void *m2, int count); |
||||
|
void Q_strcpy (char *dest, char *src); |
||||
|
void Q_strncpy (char *dest, char *src, int count); |
||||
|
int Q_strlen (char *str); |
||||
|
char *Q_strrchr (char *s, char c); |
||||
|
void Q_strcat (char *dest, char *src); |
||||
|
int Q_strcmp (char *s1, char *s2); |
||||
|
int Q_strncmp (char *s1, char *s2, int count); |
||||
|
int Q_strcasecmp (char *s1, char *s2); |
||||
|
int Q_strncasecmp (char *s1, char *s2, int n); |
||||
|
int Q_atoi (char *str); |
||||
|
float Q_atof (char *str); |
||||
|
|
||||
|
//============================================================================ |
||||
|
|
||||
|
extern char com_token[1024]; |
||||
|
extern qboolean com_eof; |
||||
|
|
||||
|
char *COM_Parse (char *data); |
||||
|
|
||||
|
|
||||
|
extern int com_argc; |
||||
|
extern char **com_argv; |
||||
|
|
||||
|
int COM_CheckParm (char *parm); |
||||
|
void COM_Init (char *path); |
||||
|
void COM_InitArgv (int argc, char **argv); |
||||
|
|
||||
|
char *COM_SkipPath (char *pathname); |
||||
|
void COM_StripExtension (char *in, char *out); |
||||
|
void COM_FileBase (char *in, char *out); |
||||
|
void COM_DefaultExtension (char *path, char *extension); |
||||
|
|
||||
|
char *va(char *format, ...); |
||||
|
// does a varargs printf into a temp buffer |
||||
|
|
||||
|
|
||||
|
//============================================================================ |
||||
|
|
||||
|
extern int com_filesize; |
||||
|
struct cache_user_s; |
||||
|
|
||||
|
extern char com_gamedir[MAX_OSPATH]; |
||||
|
|
||||
|
void COM_WriteFile (char *filename, void *data, int len); |
||||
|
int COM_OpenFile (char *filename, int *hndl); |
||||
|
int COM_FOpenFile (char *filename, FILE **file); |
||||
|
void COM_CloseFile (int h); |
||||
|
|
||||
|
|
||||
|
// jkrige - pk3 file support |
||||
|
extern qboolean LoadFromPK3; |
||||
|
byte *COM_ReadFile (int handle, int len); |
||||
|
byte *COM_FReadFile (FILE *file, int len); |
||||
|
// jkrige - pk3 file support |
||||
|
|
||||
|
|
||||
|
byte *COM_LoadStackFile (char *path, void *buffer, int bufsize); |
||||
|
byte *COM_LoadTempFile (char *path); |
||||
|
byte *COM_LoadHunkFile (char *path); |
||||
|
void COM_LoadCacheFile (char *path, struct cache_user_s *cu); |
||||
|
|
||||
|
|
||||
|
extern struct cvar_s registered; |
||||
|
|
||||
|
extern qboolean standard_quake, rogue, hipnotic; |
||||
@ -0,0 +1,365 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// conproc.c |
||||
|
|
||||
|
#include <windows.h> |
||||
|
#include "conproc.h" |
||||
|
#include "quakedef.h" |
||||
|
|
||||
|
HANDLE heventDone; |
||||
|
HANDLE hfileBuffer; |
||||
|
HANDLE heventChildSend; |
||||
|
HANDLE heventParentSend; |
||||
|
HANDLE hStdout; |
||||
|
HANDLE hStdin; |
||||
|
|
||||
|
DWORD RequestProc (DWORD dwNichts); |
||||
|
LPVOID GetMappedBuffer (HANDLE hfileBuffer); |
||||
|
void ReleaseMappedBuffer (LPVOID pBuffer); |
||||
|
BOOL GetScreenBufferLines (int *piLines); |
||||
|
BOOL SetScreenBufferLines (int iLines); |
||||
|
BOOL ReadText (LPTSTR pszText, int iBeginLine, int iEndLine); |
||||
|
BOOL WriteText (LPCTSTR szText); |
||||
|
int CharToCode (char c); |
||||
|
BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy); |
||||
|
|
||||
|
|
||||
|
void InitConProc (HANDLE hFile, HANDLE heventParent, HANDLE heventChild) |
||||
|
{ |
||||
|
DWORD dwID; |
||||
|
CONSOLE_SCREEN_BUFFER_INFO info; |
||||
|
int wheight, wwidth; |
||||
|
|
||||
|
// ignore if we don't have all the events. |
||||
|
if (!hFile || !heventParent || !heventChild) |
||||
|
return; |
||||
|
|
||||
|
hfileBuffer = hFile; |
||||
|
heventParentSend = heventParent; |
||||
|
heventChildSend = heventChild; |
||||
|
|
||||
|
// so we'll know when to go away. |
||||
|
heventDone = CreateEvent (NULL, FALSE, FALSE, NULL); |
||||
|
|
||||
|
if (!heventDone) |
||||
|
{ |
||||
|
Con_SafePrintf ("Couldn't create heventDone\n"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (!CreateThread (NULL, |
||||
|
0, |
||||
|
(LPTHREAD_START_ROUTINE) RequestProc, |
||||
|
0, |
||||
|
0, |
||||
|
&dwID)) |
||||
|
{ |
||||
|
CloseHandle (heventDone); |
||||
|
Con_SafePrintf ("Couldn't create QHOST thread\n"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// save off the input/output handles. |
||||
|
hStdout = GetStdHandle (STD_OUTPUT_HANDLE); |
||||
|
hStdin = GetStdHandle (STD_INPUT_HANDLE); |
||||
|
|
||||
|
// force 80 character width, at least 25 character height |
||||
|
SetConsoleCXCY (hStdout, 80, 25); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void DeinitConProc (void) |
||||
|
{ |
||||
|
if (heventDone) |
||||
|
SetEvent (heventDone); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
DWORD RequestProc (DWORD dwNichts) |
||||
|
{ |
||||
|
int *pBuffer; |
||||
|
DWORD dwRet; |
||||
|
HANDLE heventWait[2]; |
||||
|
int iBeginLine, iEndLine; |
||||
|
|
||||
|
heventWait[0] = heventParentSend; |
||||
|
heventWait[1] = heventDone; |
||||
|
|
||||
|
while (1) |
||||
|
{ |
||||
|
dwRet = WaitForMultipleObjects (2, heventWait, FALSE, INFINITE); |
||||
|
|
||||
|
// heventDone fired, so we're exiting. |
||||
|
if (dwRet == WAIT_OBJECT_0 + 1) |
||||
|
break; |
||||
|
|
||||
|
pBuffer = (int *) GetMappedBuffer (hfileBuffer); |
||||
|
|
||||
|
// hfileBuffer is invalid. Just leave. |
||||
|
if (!pBuffer) |
||||
|
{ |
||||
|
Con_SafePrintf ("Invalid hfileBuffer\n"); |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
switch (pBuffer[0]) |
||||
|
{ |
||||
|
case CCOM_WRITE_TEXT: |
||||
|
// Param1 : Text |
||||
|
pBuffer[0] = WriteText ((LPCTSTR) (pBuffer + 1)); |
||||
|
break; |
||||
|
|
||||
|
case CCOM_GET_TEXT: |
||||
|
// Param1 : Begin line |
||||
|
// Param2 : End line |
||||
|
iBeginLine = pBuffer[1]; |
||||
|
iEndLine = pBuffer[2]; |
||||
|
pBuffer[0] = ReadText ((LPTSTR) (pBuffer + 1), iBeginLine, |
||||
|
iEndLine); |
||||
|
break; |
||||
|
|
||||
|
case CCOM_GET_SCR_LINES: |
||||
|
// No params |
||||
|
pBuffer[0] = GetScreenBufferLines (&pBuffer[1]); |
||||
|
break; |
||||
|
|
||||
|
case CCOM_SET_SCR_LINES: |
||||
|
// Param1 : Number of lines |
||||
|
pBuffer[0] = SetScreenBufferLines (pBuffer[1]); |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
ReleaseMappedBuffer (pBuffer); |
||||
|
SetEvent (heventChildSend); |
||||
|
} |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
LPVOID GetMappedBuffer (HANDLE hfileBuffer) |
||||
|
{ |
||||
|
LPVOID pBuffer; |
||||
|
|
||||
|
pBuffer = MapViewOfFile (hfileBuffer, |
||||
|
FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); |
||||
|
|
||||
|
return pBuffer; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void ReleaseMappedBuffer (LPVOID pBuffer) |
||||
|
{ |
||||
|
UnmapViewOfFile (pBuffer); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
BOOL GetScreenBufferLines (int *piLines) |
||||
|
{ |
||||
|
CONSOLE_SCREEN_BUFFER_INFO info; |
||||
|
BOOL bRet; |
||||
|
|
||||
|
bRet = GetConsoleScreenBufferInfo (hStdout, &info); |
||||
|
|
||||
|
if (bRet) |
||||
|
*piLines = info.dwSize.Y; |
||||
|
|
||||
|
return bRet; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
BOOL SetScreenBufferLines (int iLines) |
||||
|
{ |
||||
|
|
||||
|
return SetConsoleCXCY (hStdout, 80, iLines); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
BOOL ReadText (LPTSTR pszText, int iBeginLine, int iEndLine) |
||||
|
{ |
||||
|
COORD coord; |
||||
|
DWORD dwRead; |
||||
|
BOOL bRet; |
||||
|
|
||||
|
coord.X = 0; |
||||
|
coord.Y = iBeginLine; |
||||
|
|
||||
|
bRet = ReadConsoleOutputCharacter( |
||||
|
hStdout, |
||||
|
pszText, |
||||
|
80 * (iEndLine - iBeginLine + 1), |
||||
|
coord, |
||||
|
&dwRead); |
||||
|
|
||||
|
// Make sure it's null terminated. |
||||
|
if (bRet) |
||||
|
pszText[dwRead] = '\0'; |
||||
|
|
||||
|
return bRet; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
BOOL WriteText (LPCTSTR szText) |
||||
|
{ |
||||
|
DWORD dwWritten; |
||||
|
INPUT_RECORD rec; |
||||
|
char upper, *sz; |
||||
|
|
||||
|
sz = (LPTSTR) szText; |
||||
|
|
||||
|
while (*sz) |
||||
|
{ |
||||
|
// 13 is the code for a carriage return (\n) instead of 10. |
||||
|
if (*sz == 10) |
||||
|
*sz = 13; |
||||
|
|
||||
|
upper = toupper(*sz); |
||||
|
|
||||
|
rec.EventType = KEY_EVENT; |
||||
|
rec.Event.KeyEvent.bKeyDown = TRUE; |
||||
|
rec.Event.KeyEvent.wRepeatCount = 1; |
||||
|
rec.Event.KeyEvent.wVirtualKeyCode = upper; |
||||
|
rec.Event.KeyEvent.wVirtualScanCode = CharToCode (*sz); |
||||
|
rec.Event.KeyEvent.uChar.AsciiChar = *sz; |
||||
|
rec.Event.KeyEvent.uChar.UnicodeChar = *sz; |
||||
|
rec.Event.KeyEvent.dwControlKeyState = isupper(*sz) ? 0x80 : 0x0; |
||||
|
|
||||
|
WriteConsoleInput( |
||||
|
hStdin, |
||||
|
&rec, |
||||
|
1, |
||||
|
&dwWritten); |
||||
|
|
||||
|
rec.Event.KeyEvent.bKeyDown = FALSE; |
||||
|
|
||||
|
WriteConsoleInput( |
||||
|
hStdin, |
||||
|
&rec, |
||||
|
1, |
||||
|
&dwWritten); |
||||
|
|
||||
|
sz++; |
||||
|
} |
||||
|
|
||||
|
return TRUE; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
int CharToCode (char c) |
||||
|
{ |
||||
|
char upper; |
||||
|
|
||||
|
upper = toupper(c); |
||||
|
|
||||
|
switch (c) |
||||
|
{ |
||||
|
case 13: |
||||
|
return 28; |
||||
|
|
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
if (isalpha(c)) |
||||
|
return (30 + upper - 65); |
||||
|
|
||||
|
if (isdigit(c)) |
||||
|
return (1 + upper - 47); |
||||
|
|
||||
|
return c; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy) |
||||
|
{ |
||||
|
CONSOLE_SCREEN_BUFFER_INFO info; |
||||
|
COORD coordMax; |
||||
|
|
||||
|
coordMax = GetLargestConsoleWindowSize(hStdout); |
||||
|
|
||||
|
if (cy > coordMax.Y) |
||||
|
cy = coordMax.Y; |
||||
|
|
||||
|
if (cx > coordMax.X) |
||||
|
cx = coordMax.X; |
||||
|
|
||||
|
if (!GetConsoleScreenBufferInfo(hStdout, &info)) |
||||
|
return FALSE; |
||||
|
|
||||
|
// height |
||||
|
info.srWindow.Left = 0; |
||||
|
info.srWindow.Right = info.dwSize.X - 1; |
||||
|
info.srWindow.Top = 0; |
||||
|
info.srWindow.Bottom = cy - 1; |
||||
|
|
||||
|
if (cy < info.dwSize.Y) |
||||
|
{ |
||||
|
if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow)) |
||||
|
return FALSE; |
||||
|
|
||||
|
info.dwSize.Y = cy; |
||||
|
|
||||
|
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize)) |
||||
|
return FALSE; |
||||
|
} |
||||
|
else if (cy > info.dwSize.Y) |
||||
|
{ |
||||
|
info.dwSize.Y = cy; |
||||
|
|
||||
|
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize)) |
||||
|
return FALSE; |
||||
|
|
||||
|
if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow)) |
||||
|
return FALSE; |
||||
|
} |
||||
|
|
||||
|
if (!GetConsoleScreenBufferInfo(hStdout, &info)) |
||||
|
return FALSE; |
||||
|
|
||||
|
// width |
||||
|
info.srWindow.Left = 0; |
||||
|
info.srWindow.Right = cx - 1; |
||||
|
info.srWindow.Top = 0; |
||||
|
info.srWindow.Bottom = info.dwSize.Y - 1; |
||||
|
|
||||
|
if (cx < info.dwSize.X) |
||||
|
{ |
||||
|
if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow)) |
||||
|
return FALSE; |
||||
|
|
||||
|
info.dwSize.X = cx; |
||||
|
|
||||
|
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize)) |
||||
|
return FALSE; |
||||
|
} |
||||
|
else if (cx > info.dwSize.X) |
||||
|
{ |
||||
|
info.dwSize.X = cx; |
||||
|
|
||||
|
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize)) |
||||
|
return FALSE; |
||||
|
|
||||
|
if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow)) |
||||
|
return FALSE; |
||||
|
} |
||||
|
|
||||
|
return TRUE; |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,37 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// conproc.h |
||||
|
|
||||
|
#define CCOM_WRITE_TEXT 0x2 |
||||
|
// Param1 : Text |
||||
|
|
||||
|
#define CCOM_GET_TEXT 0x3 |
||||
|
// Param1 : Begin line |
||||
|
// Param2 : End line |
||||
|
|
||||
|
#define CCOM_GET_SCR_LINES 0x4 |
||||
|
// No params |
||||
|
|
||||
|
#define CCOM_SET_SCR_LINES 0x5 |
||||
|
// Param1 : Number of lines |
||||
|
|
||||
|
void InitConProc (HANDLE hFile, HANDLE heventParent, HANDLE heventChild); |
||||
|
void DeinitConProc (void); |
||||
|
|
||||
@ -0,0 +1,671 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// console.c |
||||
|
|
||||
|
#ifdef NeXT |
||||
|
#include <libc.h> |
||||
|
#endif |
||||
|
#ifndef _MSC_VER |
||||
|
#include <unistd.h> |
||||
|
#endif |
||||
|
#include <fcntl.h> |
||||
|
#include "quakedef.h" |
||||
|
|
||||
|
// jkrige - scale2d |
||||
|
#ifdef _WIN32 |
||||
|
#include "winquake.h" |
||||
|
#endif |
||||
|
// jkrige - scale2d |
||||
|
|
||||
|
int con_linewidth; |
||||
|
|
||||
|
float con_cursorspeed = 4; |
||||
|
|
||||
|
#define CON_TEXTSIZE 16384 |
||||
|
|
||||
|
qboolean con_forcedup; // because no entities to refresh |
||||
|
|
||||
|
int con_totallines; // total lines in console scrollback |
||||
|
int con_backscroll; // lines up from bottom to display |
||||
|
int con_current; // where next message will be printed |
||||
|
int con_x; // offset in current line for next print |
||||
|
char *con_text=0; |
||||
|
|
||||
|
cvar_t con_notifytime = {"con_notifytime","3"}; //seconds |
||||
|
|
||||
|
#define NUM_CON_TIMES 4 |
||||
|
float con_times[NUM_CON_TIMES]; // realtime time the line was generated |
||||
|
// for transparent notify lines |
||||
|
|
||||
|
int con_vislines; |
||||
|
|
||||
|
qboolean con_debuglog; |
||||
|
|
||||
|
#define MAXCMDLINE 256 |
||||
|
extern char key_lines[32][MAXCMDLINE]; |
||||
|
extern int edit_line; |
||||
|
extern int key_linepos; |
||||
|
|
||||
|
|
||||
|
qboolean con_initialized; |
||||
|
|
||||
|
int con_notifylines; // scan lines to clear for notify lines |
||||
|
|
||||
|
extern void M_Menu_Main_f (void); |
||||
|
|
||||
|
/* |
||||
|
================ |
||||
|
Con_ToggleConsole_f |
||||
|
================ |
||||
|
*/ |
||||
|
void Con_ToggleConsole_f (void) |
||||
|
{ |
||||
|
if (key_dest == key_console) |
||||
|
{ |
||||
|
if (cls.state == ca_connected) |
||||
|
{ |
||||
|
key_dest = key_game; |
||||
|
key_lines[edit_line][1] = 0; // clear any typing |
||||
|
key_linepos = 1; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
M_Menu_Main_f (); |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
key_dest = key_console; |
||||
|
|
||||
|
SCR_EndLoadingPlaque (); |
||||
|
memset (con_times, 0, sizeof(con_times)); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
================ |
||||
|
Con_Clear_f |
||||
|
================ |
||||
|
*/ |
||||
|
void Con_Clear_f (void) |
||||
|
{ |
||||
|
if (con_text) |
||||
|
Q_memset (con_text, ' ', CON_TEXTSIZE); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================ |
||||
|
Con_ClearNotify |
||||
|
================ |
||||
|
*/ |
||||
|
void Con_ClearNotify (void) |
||||
|
{ |
||||
|
int i; |
||||
|
|
||||
|
for (i=0 ; i<NUM_CON_TIMES ; i++) |
||||
|
con_times[i] = 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================ |
||||
|
Con_MessageMode_f |
||||
|
================ |
||||
|
*/ |
||||
|
extern qboolean team_message; |
||||
|
|
||||
|
void Con_MessageMode_f (void) |
||||
|
{ |
||||
|
key_dest = key_message; |
||||
|
team_message = false; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================ |
||||
|
Con_MessageMode2_f |
||||
|
================ |
||||
|
*/ |
||||
|
void Con_MessageMode2_f (void) |
||||
|
{ |
||||
|
key_dest = key_message; |
||||
|
team_message = true; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================ |
||||
|
Con_CheckResize |
||||
|
|
||||
|
If the line width has changed, reformat the buffer. |
||||
|
================ |
||||
|
*/ |
||||
|
void Con_CheckResize (void) |
||||
|
{ |
||||
|
int i, j, width, oldwidth, oldtotallines, numlines, numchars; |
||||
|
char tbuf[CON_TEXTSIZE]; |
||||
|
|
||||
|
// jkrige - scale2d |
||||
|
#if GLQUAKE |
||||
|
if (Scale2DFactor > 1.0f) |
||||
|
{ |
||||
|
vid.width = vid.conwidth = conback->width = Scale2DWidth; |
||||
|
vid.height = vid.conheight = conback->height = Scale2DHeight; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
vid.width = vid.conwidth = conback->width = modelist[(int)vid_mode.value].width; |
||||
|
vid.height = vid.conheight = conback->height = modelist[(int)vid_mode.value].height; |
||||
|
} |
||||
|
#endif |
||||
|
// jkrige - scale2d |
||||
|
|
||||
|
|
||||
|
width = (vid.width >> 3) - 2; |
||||
|
|
||||
|
if (width == con_linewidth) |
||||
|
return; |
||||
|
|
||||
|
if (width < 1) // video hasn't been initialized yet |
||||
|
{ |
||||
|
width = 38; |
||||
|
con_linewidth = width; |
||||
|
con_totallines = CON_TEXTSIZE / con_linewidth; |
||||
|
Q_memset (con_text, ' ', CON_TEXTSIZE); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
oldwidth = con_linewidth; |
||||
|
con_linewidth = width; |
||||
|
oldtotallines = con_totallines; |
||||
|
con_totallines = CON_TEXTSIZE / con_linewidth; |
||||
|
numlines = oldtotallines; |
||||
|
|
||||
|
if (con_totallines < numlines) |
||||
|
numlines = con_totallines; |
||||
|
|
||||
|
numchars = oldwidth; |
||||
|
|
||||
|
if (con_linewidth < numchars) |
||||
|
numchars = con_linewidth; |
||||
|
|
||||
|
Q_memcpy (tbuf, con_text, CON_TEXTSIZE); |
||||
|
Q_memset (con_text, ' ', CON_TEXTSIZE); |
||||
|
|
||||
|
for (i=0 ; i<numlines ; i++) |
||||
|
{ |
||||
|
for (j=0 ; j<numchars ; j++) |
||||
|
{ |
||||
|
con_text[(con_totallines - 1 - i) * con_linewidth + j] = |
||||
|
tbuf[((con_current - i + oldtotallines) % |
||||
|
oldtotallines) * oldwidth + j]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
Con_ClearNotify (); |
||||
|
} |
||||
|
|
||||
|
con_backscroll = 0; |
||||
|
con_current = con_totallines - 1; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================ |
||||
|
Con_Init |
||||
|
================ |
||||
|
*/ |
||||
|
void Con_Init (void) |
||||
|
{ |
||||
|
#define MAXGAMEDIRLEN 1000 |
||||
|
char temp[MAXGAMEDIRLEN+1]; |
||||
|
char *t2 = "/qconsole.log"; |
||||
|
|
||||
|
con_debuglog = COM_CheckParm("-condebug"); |
||||
|
|
||||
|
if (con_debuglog) |
||||
|
{ |
||||
|
if (strlen (com_gamedir) < (MAXGAMEDIRLEN - strlen (t2))) |
||||
|
{ |
||||
|
sprintf (temp, "%s%s", com_gamedir, t2); |
||||
|
unlink (temp); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
con_text = Hunk_AllocName (CON_TEXTSIZE, "context"); |
||||
|
Q_memset (con_text, ' ', CON_TEXTSIZE); |
||||
|
con_linewidth = -1; |
||||
|
Con_CheckResize (); |
||||
|
|
||||
|
Con_Printf ("Console initialized.\n"); |
||||
|
|
||||
|
// |
||||
|
// register our commands |
||||
|
// |
||||
|
Cvar_RegisterVariable (&con_notifytime); |
||||
|
|
||||
|
Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f); |
||||
|
Cmd_AddCommand ("messagemode", Con_MessageMode_f); |
||||
|
Cmd_AddCommand ("messagemode2", Con_MessageMode2_f); |
||||
|
Cmd_AddCommand ("clear", Con_Clear_f); |
||||
|
con_initialized = true; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
Con_Linefeed |
||||
|
=============== |
||||
|
*/ |
||||
|
void Con_Linefeed (void) |
||||
|
{ |
||||
|
con_x = 0; |
||||
|
con_current++; |
||||
|
Q_memset (&con_text[(con_current%con_totallines)*con_linewidth] |
||||
|
, ' ', con_linewidth); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
================ |
||||
|
Con_Print |
||||
|
|
||||
|
Handles cursor positioning, line wrapping, etc |
||||
|
All console printing must go through this in order to be logged to disk |
||||
|
If no console is visible, the notify window will pop up. |
||||
|
================ |
||||
|
*/ |
||||
|
void Con_Print (char *txt) |
||||
|
{ |
||||
|
int y; |
||||
|
int c, l; |
||||
|
static int cr; |
||||
|
int mask; |
||||
|
|
||||
|
con_backscroll = 0; |
||||
|
|
||||
|
if (txt[0] == 1) |
||||
|
{ |
||||
|
mask = 128; // go to colored text |
||||
|
S_LocalSound ("misc/talk.wav"); |
||||
|
// play talk wav |
||||
|
txt++; |
||||
|
} |
||||
|
else if (txt[0] == 2) |
||||
|
{ |
||||
|
mask = 128; // go to colored text |
||||
|
txt++; |
||||
|
} |
||||
|
else |
||||
|
mask = 0; |
||||
|
|
||||
|
|
||||
|
while ( (c = *txt) ) |
||||
|
{ |
||||
|
// count word length |
||||
|
for (l=0 ; l< con_linewidth ; l++) |
||||
|
if ( txt[l] <= ' ') |
||||
|
break; |
||||
|
|
||||
|
// word wrap |
||||
|
if (l != con_linewidth && (con_x + l > con_linewidth) ) |
||||
|
con_x = 0; |
||||
|
|
||||
|
txt++; |
||||
|
|
||||
|
if (cr) |
||||
|
{ |
||||
|
con_current--; |
||||
|
cr = false; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
if (!con_x) |
||||
|
{ |
||||
|
Con_Linefeed (); |
||||
|
// mark time for transparent overlay |
||||
|
if (con_current >= 0) |
||||
|
con_times[con_current % NUM_CON_TIMES] = realtime; |
||||
|
} |
||||
|
|
||||
|
switch (c) |
||||
|
{ |
||||
|
case '\n': |
||||
|
con_x = 0; |
||||
|
break; |
||||
|
|
||||
|
case '\r': |
||||
|
con_x = 0; |
||||
|
cr = 1; |
||||
|
break; |
||||
|
|
||||
|
default: // display character and advance |
||||
|
y = con_current % con_totallines; |
||||
|
con_text[y*con_linewidth+con_x] = c | mask; |
||||
|
con_x++; |
||||
|
if (con_x >= con_linewidth) |
||||
|
con_x = 0; |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================ |
||||
|
Con_DebugLog |
||||
|
================ |
||||
|
*/ |
||||
|
void Con_DebugLog(char *file, char *fmt, ...) |
||||
|
{ |
||||
|
va_list argptr; |
||||
|
static char data[1024]; |
||||
|
int fd; |
||||
|
|
||||
|
va_start(argptr, fmt); |
||||
|
vsprintf(data, fmt, argptr); |
||||
|
va_end(argptr); |
||||
|
fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666); |
||||
|
write(fd, data, strlen(data)); |
||||
|
close(fd); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================ |
||||
|
Con_Printf |
||||
|
|
||||
|
Handles cursor positioning, line wrapping, etc |
||||
|
================ |
||||
|
*/ |
||||
|
#define MAXPRINTMSG 4096 |
||||
|
// FIXME: make a buffer size safe vsprintf? |
||||
|
void Con_Printf (char *fmt, ...) |
||||
|
{ |
||||
|
va_list argptr; |
||||
|
char msg[MAXPRINTMSG]; |
||||
|
static qboolean inupdate; |
||||
|
|
||||
|
va_start (argptr,fmt); |
||||
|
vsprintf (msg,fmt,argptr); |
||||
|
va_end (argptr); |
||||
|
|
||||
|
// also echo to debugging console |
||||
|
Sys_Printf ("%s", msg); // also echo to debugging console |
||||
|
|
||||
|
// log all messages to file |
||||
|
if (con_debuglog) |
||||
|
Con_DebugLog(va("%s/qconsole.log",com_gamedir), "%s", msg); |
||||
|
|
||||
|
if (!con_initialized) |
||||
|
return; |
||||
|
|
||||
|
if (cls.state == ca_dedicated) |
||||
|
return; // no graphics mode |
||||
|
|
||||
|
// write it to the scrollable buffer |
||||
|
Con_Print (msg); |
||||
|
|
||||
|
// update the screen if the console is displayed |
||||
|
if (cls.signon != SIGNONS && !scr_disabled_for_loading ) |
||||
|
{ |
||||
|
// protect against infinite loop if something in SCR_UpdateScreen calls |
||||
|
// Con_Printd |
||||
|
if (!inupdate) |
||||
|
{ |
||||
|
inupdate = true; |
||||
|
SCR_UpdateScreen (); |
||||
|
inupdate = false; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
================ |
||||
|
Con_DPrintf |
||||
|
|
||||
|
A Con_Printf that only shows up if the "developer" cvar is set |
||||
|
================ |
||||
|
*/ |
||||
|
void Con_DPrintf (char *fmt, ...) |
||||
|
{ |
||||
|
va_list argptr; |
||||
|
char msg[MAXPRINTMSG]; |
||||
|
|
||||
|
if (!developer.value) |
||||
|
return; // don't confuse non-developers with techie stuff... |
||||
|
|
||||
|
va_start (argptr,fmt); |
||||
|
vsprintf (msg,fmt,argptr); |
||||
|
va_end (argptr); |
||||
|
|
||||
|
Con_Printf ("%s", msg); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================== |
||||
|
Con_SafePrintf |
||||
|
|
||||
|
Okay to call even when the screen can't be updated |
||||
|
================== |
||||
|
*/ |
||||
|
void Con_SafePrintf (char *fmt, ...) |
||||
|
{ |
||||
|
va_list argptr; |
||||
|
char msg[1024]; |
||||
|
int temp; |
||||
|
|
||||
|
va_start (argptr,fmt); |
||||
|
vsprintf (msg,fmt,argptr); |
||||
|
va_end (argptr); |
||||
|
|
||||
|
temp = scr_disabled_for_loading; |
||||
|
scr_disabled_for_loading = true; |
||||
|
Con_Printf ("%s", msg); |
||||
|
scr_disabled_for_loading = temp; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
============================================================================== |
||||
|
|
||||
|
DRAWING |
||||
|
|
||||
|
============================================================================== |
||||
|
*/ |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================ |
||||
|
Con_DrawInput |
||||
|
|
||||
|
The input line scrolls horizontally if typing goes beyond the right edge |
||||
|
================ |
||||
|
*/ |
||||
|
void Con_DrawInput (void) |
||||
|
{ |
||||
|
int y; |
||||
|
int i; |
||||
|
char *text; |
||||
|
|
||||
|
if (key_dest != key_console && !con_forcedup) |
||||
|
return; // don't draw anything |
||||
|
|
||||
|
text = key_lines[edit_line]; |
||||
|
|
||||
|
// add the cursor frame |
||||
|
text[key_linepos] = 10+((int)(realtime*con_cursorspeed)&1); |
||||
|
|
||||
|
// fill out remainder with spaces |
||||
|
for (i=key_linepos+1 ; i< con_linewidth ; i++) |
||||
|
text[i] = ' '; |
||||
|
|
||||
|
// prestep if horizontally scrolling |
||||
|
if (key_linepos >= con_linewidth) |
||||
|
text += 1 + key_linepos - con_linewidth; |
||||
|
|
||||
|
// draw it |
||||
|
y = con_vislines-16; |
||||
|
|
||||
|
for (i=0 ; i<con_linewidth ; i++) |
||||
|
Draw_Character ( (i+1)<<3, con_vislines - 16, text[i]); |
||||
|
|
||||
|
// remove cursor |
||||
|
key_lines[edit_line][key_linepos] = 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================ |
||||
|
Con_DrawNotify |
||||
|
|
||||
|
Draws the last few lines of output transparently over the game top |
||||
|
================ |
||||
|
*/ |
||||
|
void Con_DrawNotify (void) |
||||
|
{ |
||||
|
int x, v; |
||||
|
char *text; |
||||
|
int i; |
||||
|
float time; |
||||
|
extern char chat_buffer[]; |
||||
|
|
||||
|
v = 0; |
||||
|
for (i= con_current-NUM_CON_TIMES+1 ; i<=con_current ; i++) |
||||
|
{ |
||||
|
if (i < 0) |
||||
|
continue; |
||||
|
time = con_times[i % NUM_CON_TIMES]; |
||||
|
if (time == 0) |
||||
|
continue; |
||||
|
time = realtime - time; |
||||
|
if (time > con_notifytime.value) |
||||
|
continue; |
||||
|
text = con_text + (i % con_totallines)*con_linewidth; |
||||
|
|
||||
|
clearnotify = 0; |
||||
|
scr_copytop = 1; |
||||
|
|
||||
|
for (x = 0 ; x < con_linewidth ; x++) |
||||
|
Draw_Character ( (x+1)<<3, v, text[x]); |
||||
|
|
||||
|
v += 8; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
if (key_dest == key_message) |
||||
|
{ |
||||
|
clearnotify = 0; |
||||
|
scr_copytop = 1; |
||||
|
|
||||
|
x = 0; |
||||
|
|
||||
|
Draw_String (8, v, "say:"); |
||||
|
while(chat_buffer[x]) |
||||
|
{ |
||||
|
Draw_Character ( (x+5)<<3, v, chat_buffer[x]); |
||||
|
x++; |
||||
|
} |
||||
|
Draw_Character ( (x+5)<<3, v, 10+((int)(realtime*con_cursorspeed)&1)); |
||||
|
v += 8; |
||||
|
} |
||||
|
|
||||
|
if (v > con_notifylines) |
||||
|
con_notifylines = v; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
================ |
||||
|
Con_DrawConsole |
||||
|
|
||||
|
Draws the console with the solid background |
||||
|
The typing input line at the bottom should only be drawn if typing is allowed |
||||
|
================ |
||||
|
*/ |
||||
|
void Con_DrawConsole (int lines, qboolean drawinput) |
||||
|
{ |
||||
|
int i, x, y; |
||||
|
int rows; |
||||
|
char *text; |
||||
|
int j; |
||||
|
|
||||
|
if (lines <= 0) |
||||
|
return; |
||||
|
|
||||
|
// draw the background |
||||
|
Draw_ConsoleBackground (lines); |
||||
|
|
||||
|
// draw the text |
||||
|
con_vislines = lines; |
||||
|
|
||||
|
rows = (lines-16)>>3; // rows of text to draw |
||||
|
y = lines - 16 - (rows<<3); // may start slightly negative |
||||
|
|
||||
|
for (i= con_current - rows + 1 ; i<=con_current ; i++, y+=8 ) |
||||
|
{ |
||||
|
j = i - con_backscroll; |
||||
|
if (j<0) |
||||
|
j = 0; |
||||
|
text = con_text + (j % con_totallines)*con_linewidth; |
||||
|
|
||||
|
for (x=0 ; x<con_linewidth ; x++) |
||||
|
Draw_Character ( (x+1)<<3, y, text[x]); |
||||
|
} |
||||
|
|
||||
|
// draw the input prompt, user text, and cursor if desired |
||||
|
if (drawinput) |
||||
|
Con_DrawInput (); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================== |
||||
|
Con_NotifyBox |
||||
|
================== |
||||
|
*/ |
||||
|
void Con_NotifyBox (char *text) |
||||
|
{ |
||||
|
double t1, t2; |
||||
|
|
||||
|
// during startup for sound / cd warnings |
||||
|
Con_Printf("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n"); |
||||
|
|
||||
|
Con_Printf (text); |
||||
|
|
||||
|
Con_Printf ("Press a key.\n"); |
||||
|
Con_Printf("\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n"); |
||||
|
|
||||
|
key_count = -2; // wait for a key down and up |
||||
|
key_dest = key_console; |
||||
|
|
||||
|
do |
||||
|
{ |
||||
|
t1 = Sys_FloatTime (); |
||||
|
SCR_UpdateScreen (); |
||||
|
Sys_SendKeyEvents (); |
||||
|
t2 = Sys_FloatTime (); |
||||
|
realtime += t2-t1; // make the cursor blink |
||||
|
} while (key_count < 0); |
||||
|
|
||||
|
Con_Printf ("\n"); |
||||
|
key_dest = key_game; |
||||
|
realtime = 0; // put the cursor back to invisible |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,46 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
// |
||||
|
// console |
||||
|
// |
||||
|
extern int con_totallines; |
||||
|
extern int con_backscroll; |
||||
|
extern qboolean con_forcedup; // because no entities to refresh |
||||
|
extern qboolean con_initialized; |
||||
|
extern byte *con_chars; |
||||
|
extern int con_notifylines; // scan lines to clear for notify lines |
||||
|
|
||||
|
void Con_DrawCharacter (int cx, int line, int num); |
||||
|
|
||||
|
void Con_CheckResize (void); |
||||
|
void Con_Init (void); |
||||
|
void Con_DrawConsole (int lines, qboolean drawinput); |
||||
|
void Con_Print (char *txt); |
||||
|
void Con_Printf (char *fmt, ...); |
||||
|
void Con_DPrintf (char *fmt, ...); |
||||
|
void Con_SafePrintf (char *fmt, ...); |
||||
|
void Con_Clear_f (void); |
||||
|
void Con_DrawNotify (void); |
||||
|
void Con_ClearNotify (void); |
||||
|
void Con_ToggleConsole_f (void); |
||||
|
|
||||
|
void Con_NotifyBox (char *text); // during startup for sound / cd warnings |
||||
|
|
||||
@ -0,0 +1,81 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
/* crc.c */ |
||||
|
|
||||
|
#include "quakedef.h" |
||||
|
#include "crc.h" |
||||
|
|
||||
|
// this is a 16 bit, non-reflected CRC using the polynomial 0x1021 |
||||
|
// and the initial and final xor values shown below... in other words, the |
||||
|
// CCITT standard CRC used by XMODEM |
||||
|
|
||||
|
#define CRC_INIT_VALUE 0xffff |
||||
|
#define CRC_XOR_VALUE 0x0000 |
||||
|
|
||||
|
static unsigned short crctable[256] = |
||||
|
{ |
||||
|
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, |
||||
|
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, |
||||
|
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, |
||||
|
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, |
||||
|
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, |
||||
|
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, |
||||
|
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, |
||||
|
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, |
||||
|
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, |
||||
|
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, |
||||
|
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, |
||||
|
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, |
||||
|
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, |
||||
|
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, |
||||
|
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, |
||||
|
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, |
||||
|
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, |
||||
|
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, |
||||
|
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, |
||||
|
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, |
||||
|
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, |
||||
|
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, |
||||
|
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, |
||||
|
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, |
||||
|
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, |
||||
|
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, |
||||
|
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, |
||||
|
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, |
||||
|
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, |
||||
|
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, |
||||
|
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, |
||||
|
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 |
||||
|
}; |
||||
|
|
||||
|
void CRC_Init(unsigned short *crcvalue) |
||||
|
{ |
||||
|
*crcvalue = CRC_INIT_VALUE; |
||||
|
} |
||||
|
|
||||
|
void CRC_ProcessByte(unsigned short *crcvalue, byte data) |
||||
|
{ |
||||
|
*crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data]; |
||||
|
} |
||||
|
|
||||
|
unsigned short CRC_Value(unsigned short crcvalue) |
||||
|
{ |
||||
|
return crcvalue ^ CRC_XOR_VALUE; |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
/* crc.h */ |
||||
|
|
||||
|
void CRC_Init(unsigned short *crcvalue); |
||||
|
void CRC_ProcessByte(unsigned short *crcvalue, byte data); |
||||
|
unsigned short CRC_Value(unsigned short crcvalue); |
||||
@ -0,0 +1,289 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// cvar.c -- dynamic variable tracking |
||||
|
|
||||
|
#include "quakedef.h" |
||||
|
|
||||
|
cvar_t *cvar_vars; |
||||
|
char *cvar_null_string = ""; |
||||
|
|
||||
|
// jkrige - cvarlist |
||||
|
/* |
||||
|
========= |
||||
|
Cvar_List |
||||
|
========= |
||||
|
*/ |
||||
|
|
||||
|
void Cvar_List_f (void) |
||||
|
{ |
||||
|
cvar_t *cvar; |
||||
|
char *partial; |
||||
|
int len; |
||||
|
int count; |
||||
|
|
||||
|
if (Cmd_Argc() > 1) |
||||
|
{ |
||||
|
partial = Cmd_Argv (1); |
||||
|
len = strlen(partial); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
partial = NULL; |
||||
|
len = 0; |
||||
|
} |
||||
|
|
||||
|
count=0; |
||||
|
|
||||
|
for (cvar=cvar_vars ; cvar ; cvar=cvar->next) |
||||
|
{ |
||||
|
if (partial && strncmp (partial,cvar->name, len)) |
||||
|
{ |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
Con_Printf ("\"%s\" is \"%s\"\n", cvar->name, cvar->string); |
||||
|
|
||||
|
count++; |
||||
|
} |
||||
|
|
||||
|
Con_Printf ("%i cvar(s)", count); |
||||
|
|
||||
|
if (partial) |
||||
|
{ |
||||
|
Con_Printf (" beginning with \"%s\"", partial); |
||||
|
} |
||||
|
|
||||
|
Con_Printf ("\n"); |
||||
|
} |
||||
|
// jkrige - cvarlist |
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
Cvar_FindVar |
||||
|
============ |
||||
|
*/ |
||||
|
cvar_t *Cvar_FindVar (char *var_name) |
||||
|
{ |
||||
|
cvar_t *var; |
||||
|
|
||||
|
for (var=cvar_vars ; var ; var=var->next) |
||||
|
if (!Q_strcmp (var_name, var->name)) |
||||
|
return var; |
||||
|
|
||||
|
return NULL; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
Cvar_VariableValue |
||||
|
============ |
||||
|
*/ |
||||
|
float Cvar_VariableValue (char *var_name) |
||||
|
{ |
||||
|
cvar_t *var; |
||||
|
|
||||
|
var = Cvar_FindVar (var_name); |
||||
|
if (!var) |
||||
|
return 0; |
||||
|
return Q_atof (var->string); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
Cvar_VariableString |
||||
|
============ |
||||
|
*/ |
||||
|
char *Cvar_VariableString (char *var_name) |
||||
|
{ |
||||
|
cvar_t *var; |
||||
|
|
||||
|
var = Cvar_FindVar (var_name); |
||||
|
if (!var) |
||||
|
return cvar_null_string; |
||||
|
return var->string; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
Cvar_CompleteVariable |
||||
|
============ |
||||
|
*/ |
||||
|
char *Cvar_CompleteVariable (char *partial) |
||||
|
{ |
||||
|
cvar_t *cvar; |
||||
|
int len; |
||||
|
|
||||
|
len = Q_strlen(partial); |
||||
|
|
||||
|
if (!len) |
||||
|
return NULL; |
||||
|
|
||||
|
// check functions |
||||
|
for (cvar=cvar_vars ; cvar ; cvar=cvar->next) |
||||
|
if (!Q_strncmp (partial,cvar->name, len)) |
||||
|
return cvar->name; |
||||
|
|
||||
|
return NULL; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
Cvar_Set |
||||
|
============ |
||||
|
*/ |
||||
|
void Cvar_Set (char *var_name, char *value) |
||||
|
{ |
||||
|
cvar_t *var; |
||||
|
qboolean changed; |
||||
|
|
||||
|
var = Cvar_FindVar (var_name); |
||||
|
if (!var) |
||||
|
{ // there is an error in C code if this happens |
||||
|
Con_Printf ("Cvar_Set: variable %s not found\n", var_name); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
changed = Q_strcmp(var->string, value); |
||||
|
|
||||
|
Z_Free (var->string); // free the old value string |
||||
|
|
||||
|
var->string = Z_Malloc (Q_strlen(value)+1); |
||||
|
Q_strcpy (var->string, value); |
||||
|
var->value = Q_atof (var->string); |
||||
|
if (var->server && changed) |
||||
|
{ |
||||
|
if (sv.active) |
||||
|
SV_BroadcastPrintf ("\"%s\" changed to \"%s\"\n", var->name, var->string); |
||||
|
} |
||||
|
|
||||
|
// jkrige - deathmatch/coop not at the same time fix |
||||
|
if ( (var->value != 0) && (!Q_strcmp (var->name, deathmatch.name)) ) |
||||
|
Cvar_Set ("coop", "0"); |
||||
|
|
||||
|
if ( (var->value != 0) && (!Q_strcmp (var->name, coop.name)) ) |
||||
|
Cvar_Set ("deathmatch", "0"); |
||||
|
// jkrige - deathmatch/coop not at the same time fix |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
Cvar_SetValue |
||||
|
============ |
||||
|
*/ |
||||
|
void Cvar_SetValue (char *var_name, float value) |
||||
|
{ |
||||
|
char val[32]; |
||||
|
|
||||
|
// jkrige - cvar zeros fix |
||||
|
//sprintf (val, "%f",value); |
||||
|
if (value == (int)value) |
||||
|
sprintf (val, "%d", (int)value); |
||||
|
else |
||||
|
sprintf (val, "%f",value); |
||||
|
// jkrige - cvar zeros fix |
||||
|
|
||||
|
Cvar_Set (var_name, val); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
Cvar_RegisterVariable |
||||
|
|
||||
|
Adds a freestanding variable to the variable list. |
||||
|
============ |
||||
|
*/ |
||||
|
void Cvar_RegisterVariable (cvar_t *variable) |
||||
|
{ |
||||
|
char *oldstr; |
||||
|
|
||||
|
// first check to see if it has allready been defined |
||||
|
if (Cvar_FindVar (variable->name)) |
||||
|
{ |
||||
|
Con_Printf ("Can't register variable %s, allready defined\n", variable->name); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// check for overlap with a command |
||||
|
if (Cmd_Exists (variable->name)) |
||||
|
{ |
||||
|
Con_Printf ("Cvar_RegisterVariable: %s is a command\n", variable->name); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// copy the value off, because future sets will Z_Free it |
||||
|
oldstr = variable->string; |
||||
|
variable->string = Z_Malloc (Q_strlen(variable->string)+1); |
||||
|
Q_strcpy (variable->string, oldstr); |
||||
|
variable->value = Q_atof (variable->string); |
||||
|
|
||||
|
// link the variable in |
||||
|
variable->next = cvar_vars; |
||||
|
cvar_vars = variable; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
Cvar_Command |
||||
|
|
||||
|
Handles variable inspection and changing from the console |
||||
|
============ |
||||
|
*/ |
||||
|
qboolean Cvar_Command (void) |
||||
|
{ |
||||
|
cvar_t *v; |
||||
|
|
||||
|
// check variables |
||||
|
v = Cvar_FindVar (Cmd_Argv(0)); |
||||
|
if (!v) |
||||
|
return false; |
||||
|
|
||||
|
// perform a variable print or set |
||||
|
if (Cmd_Argc() == 1) |
||||
|
{ |
||||
|
Con_Printf ("\"%s\" is \"%s\"\n", v->name, v->string); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
Cvar_Set (v->name, Cmd_Argv(1)); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
Cvar_WriteVariables |
||||
|
|
||||
|
Writes lines containing "set variable value" for all variables |
||||
|
with the archive flag set to true. |
||||
|
============ |
||||
|
*/ |
||||
|
void Cvar_WriteVariables (FILE *f) |
||||
|
{ |
||||
|
cvar_t *var; |
||||
|
|
||||
|
for (var = cvar_vars ; var ; var = var->next) |
||||
|
if (var->archive) |
||||
|
fprintf (f, "%s \"%s\"\n", var->name, var->string); |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,99 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// cvar.h |
||||
|
|
||||
|
/* |
||||
|
|
||||
|
cvar_t variables are used to hold scalar or string variables that can be changed or displayed at the console or prog code as well as accessed directly |
||||
|
in C code. |
||||
|
|
||||
|
it is sufficient to initialize a cvar_t with just the first two fields, or |
||||
|
you can add a ,true flag for variables that you want saved to the configuration |
||||
|
file when the game is quit: |
||||
|
|
||||
|
cvar_t r_draworder = {"r_draworder","1"}; |
||||
|
cvar_t scr_screensize = {"screensize","1",true}; |
||||
|
|
||||
|
Cvars must be registered before use, or they will have a 0 value instead of the float interpretation of the string. Generally, all cvar_t declarations should be registered in the apropriate init function before any console commands are executed: |
||||
|
Cvar_RegisterVariable (&host_framerate); |
||||
|
|
||||
|
|
||||
|
C code usually just references a cvar in place: |
||||
|
if ( r_draworder.value ) |
||||
|
|
||||
|
It could optionally ask for the value to be looked up for a string name: |
||||
|
if (Cvar_VariableValue ("r_draworder")) |
||||
|
|
||||
|
Interpreted prog code can access cvars with the cvar(name) or |
||||
|
cvar_set (name, value) internal functions: |
||||
|
teamplay = cvar("teamplay"); |
||||
|
cvar_set ("registered", "1"); |
||||
|
|
||||
|
The user can access cvars from the console in two ways: |
||||
|
r_draworder prints the current value |
||||
|
r_draworder 0 sets the current value to 0 |
||||
|
Cvars are restricted from having the same names as commands to keep this |
||||
|
interface from being ambiguous. |
||||
|
*/ |
||||
|
|
||||
|
typedef struct cvar_s |
||||
|
{ |
||||
|
char *name; |
||||
|
char *string; |
||||
|
qboolean archive; // set to true to cause it to be saved to vars.rc |
||||
|
qboolean server; // notifies players when changed |
||||
|
float value; |
||||
|
struct cvar_s *next; |
||||
|
} cvar_t; |
||||
|
|
||||
|
void Cvar_RegisterVariable (cvar_t *variable); |
||||
|
// registers a cvar that allready has the name, string, and optionally the |
||||
|
// archive elements set. |
||||
|
|
||||
|
void Cvar_Set (char *var_name, char *value); |
||||
|
// equivelant to "<name> <variable>" typed at the console |
||||
|
|
||||
|
void Cvar_SetValue (char *var_name, float value); |
||||
|
// expands value to a string and calls Cvar_Set |
||||
|
|
||||
|
float Cvar_VariableValue (char *var_name); |
||||
|
// returns 0 if not defined or non numeric |
||||
|
|
||||
|
char *Cvar_VariableString (char *var_name); |
||||
|
// returns an empty string if not defined |
||||
|
|
||||
|
char *Cvar_CompleteVariable (char *partial); |
||||
|
// attempts to match a partial variable name for command line completion |
||||
|
// returns NULL if nothing fits |
||||
|
|
||||
|
qboolean Cvar_Command (void); |
||||
|
// called by Cmd_ExecuteString when Cmd_Argv(0) doesn't match a known |
||||
|
// command. Returns true if the command was a variable reference that |
||||
|
// was handled. (print or change) |
||||
|
|
||||
|
void Cvar_WriteVariables (FILE *f); |
||||
|
// Writes lines containing "set variable value" for all variables |
||||
|
// with the archive flag set to true. |
||||
|
|
||||
|
cvar_t *Cvar_FindVar (char *var_name); |
||||
|
|
||||
|
void Cvar_List_f (void); // jkrige - cvarlist |
||||
|
|
||||
|
extern cvar_t *cvar_vars; |
||||
@ -0,0 +1,55 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
// draw.h -- these are the only functions outside the refresh allowed |
||||
|
// to touch the vid buffer |
||||
|
|
||||
|
extern qpic_t *draw_disc; // also used on sbar |
||||
|
|
||||
|
// jkrige - external texture loading |
||||
|
extern int image_width; |
||||
|
extern int image_height; |
||||
|
extern int image_bits; |
||||
|
extern int image_alpha; |
||||
|
// jkrige - external texture loading |
||||
|
|
||||
|
// jkrige - .lit colored lights |
||||
|
extern vec3_t lightcolor; // jkrige - used by model rendering |
||||
|
// jkrige - .lit colored lights |
||||
|
|
||||
|
void Draw_Init (void); |
||||
|
void Draw_Character (int x, int y, int num); |
||||
|
void Draw_DebugChar (char num); |
||||
|
void Draw_Pic (int x, int y, qpic_t *pic); |
||||
|
void Draw_TransPic (int x, int y, qpic_t *pic); |
||||
|
void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation); |
||||
|
void Draw_ConsoleBackground (int lines); |
||||
|
void Draw_BeginDisc (void); |
||||
|
void Draw_EndDisc (void); |
||||
|
void Draw_TileClear (int x, int y, int w, int h); |
||||
|
void Draw_Fill (int x, int y, int w, int h, int c); |
||||
|
void Draw_FadeScreen (void); |
||||
|
void Draw_String (int x, int y, char *str); |
||||
|
qpic_t *Draw_PicFromWad (char *name); |
||||
|
qpic_t *Draw_CachePic (char *path); |
||||
|
|
||||
|
// jkrige - external texture loading |
||||
|
byte* LoadImagePixels (char* filename, qboolean complain); |
||||
|
// jkrige - external texture loading |
||||
2466
engine/code/gl_draw.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,88 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// gl_fullbright.c: fullbright pixel processing |
||||
|
|
||||
|
// Developed by Jacques Krige |
||||
|
// Ultimate Quake Engine |
||||
|
// http://www.jacqueskrige.com |
||||
|
|
||||
|
|
||||
|
#include "quakedef.h" |
||||
|
|
||||
|
|
||||
|
qboolean GL_FullbrightTexture (byte *in, byte *out, int width, int height) |
||||
|
{ |
||||
|
int i, j; |
||||
|
int p; |
||||
|
int numpixels; |
||||
|
qboolean fbtex; |
||||
|
|
||||
|
numpixels = width * height; |
||||
|
fbtex = false; |
||||
|
|
||||
|
// check if this texture has fullbrights |
||||
|
for (i = 0; i < numpixels; i++) |
||||
|
{ |
||||
|
p = in[i]; |
||||
|
|
||||
|
if (p > 238 && p != 255) |
||||
|
{ |
||||
|
fbtex = true; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
// replace non fullbrights with black |
||||
|
if (fbtex == true) |
||||
|
{ |
||||
|
for (i = 0, j = 0; i < numpixels; i++, j+=4) |
||||
|
{ |
||||
|
if (in[i] < 239) |
||||
|
in[i] = 0; |
||||
|
|
||||
|
p = in[i]; |
||||
|
|
||||
|
if (p == 0) |
||||
|
{ |
||||
|
out[j+0] = 0; |
||||
|
out[j+1] = 0; |
||||
|
out[j+2] = 0; |
||||
|
out[j+3] = 255; |
||||
|
} |
||||
|
else if (p == 255) |
||||
|
{ |
||||
|
out[j+0] = 0; |
||||
|
out[j+1] = 0; |
||||
|
out[j+2] = 0; |
||||
|
out[j+3] = 0; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
out[j+0] = host_basepal[(p*3)+0]; |
||||
|
out[j+1] = host_basepal[(p*3)+1]; |
||||
|
out[j+2] = host_basepal[(p*3)+2]; |
||||
|
out[j+3] = 255; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return fbtex; |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// gl_fullbright.h: fullbright pixel processing |
||||
|
|
||||
|
// Developed by Jacques Krige |
||||
|
// Ultimate Quake Engine |
||||
|
// http://www.jacqueskrige.com |
||||
|
|
||||
|
|
||||
|
qboolean GL_FullbrightTexture (byte *in, byte *out, int width, int height); |
||||
@ -0,0 +1,362 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// gl_mesh.c: triangle model functions |
||||
|
|
||||
|
#include "quakedef.h" |
||||
|
|
||||
|
/* |
||||
|
================================================================= |
||||
|
|
||||
|
ALIAS MODEL DISPLAY LIST GENERATION |
||||
|
|
||||
|
================================================================= |
||||
|
*/ |
||||
|
|
||||
|
model_t *aliasmodel; |
||||
|
aliashdr_t *paliashdr; |
||||
|
|
||||
|
qboolean used[8192]; |
||||
|
|
||||
|
// the command list holds counts and s/t values that are valid for |
||||
|
// every frame |
||||
|
int commands[8192]; |
||||
|
int numcommands; |
||||
|
|
||||
|
// all frames will have their vertexes rearranged and expanded |
||||
|
// so they are in the order expected by the command list |
||||
|
int vertexorder[8192]; |
||||
|
int numorder; |
||||
|
|
||||
|
int allverts, alltris; |
||||
|
|
||||
|
int stripverts[128]; |
||||
|
int striptris[128]; |
||||
|
int stripcount; |
||||
|
|
||||
|
/* |
||||
|
================ |
||||
|
StripLength |
||||
|
================ |
||||
|
*/ |
||||
|
int StripLength (int starttri, int startv) |
||||
|
{ |
||||
|
int m1, m2; |
||||
|
int j; |
||||
|
mtriangle_t *last, *check; |
||||
|
int k; |
||||
|
|
||||
|
used[starttri] = 2; |
||||
|
|
||||
|
last = &triangles[starttri]; |
||||
|
|
||||
|
stripverts[0] = last->vertindex[(startv)%3]; |
||||
|
stripverts[1] = last->vertindex[(startv+1)%3]; |
||||
|
stripverts[2] = last->vertindex[(startv+2)%3]; |
||||
|
|
||||
|
striptris[0] = starttri; |
||||
|
stripcount = 1; |
||||
|
|
||||
|
m1 = last->vertindex[(startv+2)%3]; |
||||
|
m2 = last->vertindex[(startv+1)%3]; |
||||
|
|
||||
|
// look for a matching triangle |
||||
|
nexttri: |
||||
|
for (j=starttri+1, check=&triangles[starttri+1] ; j<pheader->numtris ; j++, check++) |
||||
|
{ |
||||
|
if (check->facesfront != last->facesfront) |
||||
|
continue; |
||||
|
for (k=0 ; k<3 ; k++) |
||||
|
{ |
||||
|
if (check->vertindex[k] != m1) |
||||
|
continue; |
||||
|
if (check->vertindex[ (k+1)%3 ] != m2) |
||||
|
continue; |
||||
|
|
||||
|
// this is the next part of the fan |
||||
|
|
||||
|
// if we can't use this triangle, this tristrip is done |
||||
|
if (used[j]) |
||||
|
goto done; |
||||
|
|
||||
|
// the new edge |
||||
|
if (stripcount & 1) |
||||
|
m2 = check->vertindex[ (k+2)%3 ]; |
||||
|
else |
||||
|
m1 = check->vertindex[ (k+2)%3 ]; |
||||
|
|
||||
|
stripverts[stripcount+2] = check->vertindex[ (k+2)%3 ]; |
||||
|
striptris[stripcount] = j; |
||||
|
stripcount++; |
||||
|
|
||||
|
used[j] = 2; |
||||
|
goto nexttri; |
||||
|
} |
||||
|
} |
||||
|
done: |
||||
|
|
||||
|
// clear the temp used flags |
||||
|
for (j=starttri+1 ; j<pheader->numtris ; j++) |
||||
|
if (used[j] == 2) |
||||
|
used[j] = 0; |
||||
|
|
||||
|
return stripcount; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
=========== |
||||
|
FanLength |
||||
|
=========== |
||||
|
*/ |
||||
|
int FanLength (int starttri, int startv) |
||||
|
{ |
||||
|
int m1, m2; |
||||
|
int j; |
||||
|
mtriangle_t *last, *check; |
||||
|
int k; |
||||
|
|
||||
|
used[starttri] = 2; |
||||
|
|
||||
|
last = &triangles[starttri]; |
||||
|
|
||||
|
stripverts[0] = last->vertindex[(startv)%3]; |
||||
|
stripverts[1] = last->vertindex[(startv+1)%3]; |
||||
|
stripverts[2] = last->vertindex[(startv+2)%3]; |
||||
|
|
||||
|
striptris[0] = starttri; |
||||
|
stripcount = 1; |
||||
|
|
||||
|
m1 = last->vertindex[(startv+0)%3]; |
||||
|
m2 = last->vertindex[(startv+2)%3]; |
||||
|
|
||||
|
|
||||
|
// look for a matching triangle |
||||
|
nexttri: |
||||
|
for (j=starttri+1, check=&triangles[starttri+1] ; j<pheader->numtris ; j++, check++) |
||||
|
{ |
||||
|
if (check->facesfront != last->facesfront) |
||||
|
continue; |
||||
|
for (k=0 ; k<3 ; k++) |
||||
|
{ |
||||
|
if (check->vertindex[k] != m1) |
||||
|
continue; |
||||
|
if (check->vertindex[ (k+1)%3 ] != m2) |
||||
|
continue; |
||||
|
|
||||
|
// this is the next part of the fan |
||||
|
|
||||
|
// if we can't use this triangle, this tristrip is done |
||||
|
if (used[j]) |
||||
|
goto done; |
||||
|
|
||||
|
// the new edge |
||||
|
m2 = check->vertindex[ (k+2)%3 ]; |
||||
|
|
||||
|
stripverts[stripcount+2] = m2; |
||||
|
striptris[stripcount] = j; |
||||
|
stripcount++; |
||||
|
|
||||
|
used[j] = 2; |
||||
|
goto nexttri; |
||||
|
} |
||||
|
} |
||||
|
done: |
||||
|
|
||||
|
// clear the temp used flags |
||||
|
for (j=starttri+1 ; j<pheader->numtris ; j++) |
||||
|
if (used[j] == 2) |
||||
|
used[j] = 0; |
||||
|
|
||||
|
return stripcount; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================ |
||||
|
BuildTris |
||||
|
|
||||
|
Generate a list of trifans or strips |
||||
|
for the model, which holds for all frames |
||||
|
================ |
||||
|
*/ |
||||
|
void BuildTris (void) |
||||
|
{ |
||||
|
int i, j, k; |
||||
|
int startv; |
||||
|
mtriangle_t *last, *check; |
||||
|
int m1, m2; |
||||
|
int striplength; |
||||
|
trivertx_t *v; |
||||
|
mtriangle_t *tv; |
||||
|
float s, t; |
||||
|
int index; |
||||
|
int len, bestlen, besttype; |
||||
|
int bestverts[1024]; |
||||
|
int besttris[1024]; |
||||
|
int type; |
||||
|
|
||||
|
// |
||||
|
// build tristrips |
||||
|
// |
||||
|
numorder = 0; |
||||
|
numcommands = 0; |
||||
|
memset (used, 0, sizeof(used)); |
||||
|
for (i=0 ; i<pheader->numtris ; i++) |
||||
|
{ |
||||
|
// pick an unused triangle and start the trifan |
||||
|
if (used[i]) |
||||
|
continue; |
||||
|
|
||||
|
bestlen = 0; |
||||
|
for (type = 0 ; type < 2 ; type++) |
||||
|
// type = 1; |
||||
|
{ |
||||
|
for (startv =0 ; startv < 3 ; startv++) |
||||
|
{ |
||||
|
if (type == 1) |
||||
|
len = StripLength (i, startv); |
||||
|
else |
||||
|
len = FanLength (i, startv); |
||||
|
if (len > bestlen) |
||||
|
{ |
||||
|
besttype = type; |
||||
|
bestlen = len; |
||||
|
for (j=0 ; j<bestlen+2 ; j++) |
||||
|
bestverts[j] = stripverts[j]; |
||||
|
for (j=0 ; j<bestlen ; j++) |
||||
|
besttris[j] = striptris[j]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// mark the tris on the best strip as used |
||||
|
for (j=0 ; j<bestlen ; j++) |
||||
|
used[besttris[j]] = 1; |
||||
|
|
||||
|
if (besttype == 1) |
||||
|
commands[numcommands++] = (bestlen+2); |
||||
|
else |
||||
|
commands[numcommands++] = -(bestlen+2); |
||||
|
|
||||
|
for (j=0 ; j<bestlen+2 ; j++) |
||||
|
{ |
||||
|
// emit a vertex into the reorder buffer |
||||
|
k = bestverts[j]; |
||||
|
vertexorder[numorder++] = k; |
||||
|
|
||||
|
// emit s/t coords into the commands stream |
||||
|
s = stverts[k].s; |
||||
|
t = stverts[k].t; |
||||
|
if (!triangles[besttris[0]].facesfront && stverts[k].onseam) |
||||
|
s += pheader->skinwidth / 2; // on back side |
||||
|
s = (s + 0.5) / pheader->skinwidth; |
||||
|
t = (t + 0.5) / pheader->skinheight; |
||||
|
|
||||
|
*(float *)&commands[numcommands++] = s; |
||||
|
*(float *)&commands[numcommands++] = t; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
commands[numcommands++] = 0; // end of list marker |
||||
|
|
||||
|
Con_DPrintf ("%3i tri %3i vert %3i cmd\n", pheader->numtris, numorder, numcommands); |
||||
|
|
||||
|
allverts += numorder; |
||||
|
alltris += pheader->numtris; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================ |
||||
|
GL_MakeAliasModelDisplayLists |
||||
|
================ |
||||
|
*/ |
||||
|
void GL_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr) |
||||
|
{ |
||||
|
int i, j; |
||||
|
maliasgroup_t *paliasgroup; |
||||
|
int *cmds; |
||||
|
trivertx_t *verts; |
||||
|
char cache[MAX_QPATH], fullpath[MAX_OSPATH], *c; |
||||
|
FILE *f; |
||||
|
int len; |
||||
|
byte *data; |
||||
|
|
||||
|
aliasmodel = m; |
||||
|
paliashdr = hdr; // (aliashdr_t *)Mod_Extradata (m); |
||||
|
|
||||
|
// jkrige - mdl meshing removal |
||||
|
// |
||||
|
// look for a cached version |
||||
|
// |
||||
|
/*strcpy (cache, "glquake/"); |
||||
|
COM_StripExtension (m->name+strlen("progs/"), cache+strlen("glquake/")); |
||||
|
strcat (cache, ".ms2"); |
||||
|
|
||||
|
COM_FOpenFile (cache, &f); |
||||
|
if (f) |
||||
|
{ |
||||
|
fread (&numcommands, 4, 1, f); |
||||
|
fread (&numorder, 4, 1, f); |
||||
|
fread (&commands, numcommands * sizeof(commands[0]), 1, f); |
||||
|
fread (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f); |
||||
|
fclose (f); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
// |
||||
|
// build it from scratch |
||||
|
// |
||||
|
Con_Printf ("meshing %s...\n",m->name); |
||||
|
|
||||
|
BuildTris (); // trifans or lists |
||||
|
|
||||
|
// |
||||
|
// save out the cached version |
||||
|
// |
||||
|
sprintf (fullpath, "%s/%s", com_gamedir, cache); |
||||
|
f = fopen (fullpath, "wb"); |
||||
|
if (f) |
||||
|
{ |
||||
|
fwrite (&numcommands, 4, 1, f); |
||||
|
fwrite (&numorder, 4, 1, f); |
||||
|
fwrite (&commands, numcommands * sizeof(commands[0]), 1, f); |
||||
|
fwrite (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f); |
||||
|
fclose (f); |
||||
|
} |
||||
|
}*/ |
||||
|
BuildTris (); |
||||
|
// jkrige - mdl meshing removal |
||||
|
|
||||
|
// save the data out |
||||
|
|
||||
|
paliashdr->poseverts = numorder; |
||||
|
|
||||
|
cmds = Hunk_Alloc (numcommands * 4); |
||||
|
paliashdr->commands = (byte *)cmds - (byte *)paliashdr; |
||||
|
memcpy (cmds, commands, numcommands * 4); |
||||
|
|
||||
|
verts = Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts |
||||
|
* sizeof(trivertx_t) ); |
||||
|
paliashdr->posedata = (byte *)verts - (byte *)paliashdr; |
||||
|
for (i=0 ; i<paliashdr->numposes ; i++) |
||||
|
for (j=0 ; j<numorder ; j++) |
||||
|
*verts++ = poseverts[i][vertexorder[j]]; |
||||
|
} |
||||
|
|
||||
2261
engine/code/gl_model.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,454 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
#ifndef __MODEL__ |
||||
|
#define __MODEL__ |
||||
|
|
||||
|
#include "modelgen.h" |
||||
|
#include "spritegn.h" |
||||
|
|
||||
|
/* |
||||
|
|
||||
|
d*_t structures are on-disk representations |
||||
|
m*_t structures are in-memory |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
// entity effects |
||||
|
|
||||
|
#define EF_BRIGHTFIELD 1 |
||||
|
#define EF_MUZZLEFLASH 2 |
||||
|
#define EF_BRIGHTLIGHT 4 |
||||
|
#define EF_DIMLIGHT 8 |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
============================================================================== |
||||
|
|
||||
|
BRUSH MODELS |
||||
|
|
||||
|
============================================================================== |
||||
|
*/ |
||||
|
|
||||
|
|
||||
|
// |
||||
|
// in memory representation |
||||
|
// |
||||
|
// !!! if this is changed, it must be changed in asm_draw.h too !!! |
||||
|
typedef struct |
||||
|
{ |
||||
|
vec3_t position; |
||||
|
} mvertex_t; |
||||
|
|
||||
|
#define SIDE_FRONT 0 |
||||
|
#define SIDE_BACK 1 |
||||
|
#define SIDE_ON 2 |
||||
|
|
||||
|
|
||||
|
// plane_t structure |
||||
|
// !!! if this is changed, it must be changed in asm_i386.h too !!! |
||||
|
typedef struct mplane_s |
||||
|
{ |
||||
|
vec3_t normal; |
||||
|
float dist; |
||||
|
byte type; // for texture axis selection and fast side tests |
||||
|
byte signbits; // signx + signy<<1 + signz<<1 |
||||
|
byte pad[2]; |
||||
|
} mplane_t; |
||||
|
|
||||
|
typedef struct texture_s |
||||
|
{ |
||||
|
char name[16]; |
||||
|
unsigned width, height; |
||||
|
int gl_texturenum; |
||||
|
|
||||
|
qboolean tex_luma; // jkrige - luma textures |
||||
|
qboolean tex_luma8bit; // jkrige - fullbright pixels |
||||
|
|
||||
|
struct msurface_s *texturechain; // for gl_texsort drawing |
||||
|
int anim_total; // total tenths in sequence ( 0 = no) |
||||
|
int anim_min, anim_max; // time for this frame min <=time< max |
||||
|
struct texture_s *anim_next; // in the animation sequence |
||||
|
struct texture_s *alternate_anims; // bmodels in frmae 1 use these |
||||
|
unsigned offsets[MIPLEVELS]; // four mip maps stored |
||||
|
} texture_t; |
||||
|
|
||||
|
|
||||
|
#define SURF_PLANEBACK 2 |
||||
|
#define SURF_DRAWSKY 4 |
||||
|
#define SURF_DRAWSPRITE 8 |
||||
|
#define SURF_DRAWTURB 0x10 |
||||
|
#define SURF_DRAWTILED 0x20 |
||||
|
#define SURF_DRAWBACKGROUND 0x40 |
||||
|
#define SURF_UNDERWATER 0x80 |
||||
|
|
||||
|
// !!! if this is changed, it must be changed in asm_draw.h too !!! |
||||
|
typedef struct |
||||
|
{ |
||||
|
unsigned short v[2]; |
||||
|
unsigned int cachededgeoffset; |
||||
|
} medge_t; |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
float vecs[2][4]; |
||||
|
float mipadjust; |
||||
|
texture_t *texture; |
||||
|
int flags; |
||||
|
} mtexinfo_t; |
||||
|
|
||||
|
#define VERTEXSIZE 7 |
||||
|
|
||||
|
typedef struct glpoly_s |
||||
|
{ |
||||
|
struct glpoly_s *next; |
||||
|
struct glpoly_s *chain; |
||||
|
int numverts; |
||||
|
int flags; // for SURF_UNDERWATER |
||||
|
float verts[4][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2) |
||||
|
} glpoly_t; |
||||
|
|
||||
|
typedef struct msurface_s |
||||
|
{ |
||||
|
int visframe; // should be drawn when node is crossed |
||||
|
|
||||
|
mplane_t *plane; |
||||
|
int flags; |
||||
|
|
||||
|
int firstedge; // look up in model->surfedges[], negative numbers |
||||
|
int numedges; // are backwards edges |
||||
|
|
||||
|
short texturemins[2]; |
||||
|
short extents[2]; |
||||
|
|
||||
|
int light_s, light_t; // gl lightmap coordinates |
||||
|
|
||||
|
glpoly_t *polys; // multiple if warped |
||||
|
struct msurface_s *texturechain; |
||||
|
|
||||
|
mtexinfo_t *texinfo; |
||||
|
|
||||
|
// jkrige - luma textures |
||||
|
qboolean luma_mark; |
||||
|
// jkrige - luma textures |
||||
|
|
||||
|
// lighting info |
||||
|
int dlightframe; |
||||
|
// jkrige - increase dlights |
||||
|
//int dlightbits; |
||||
|
byte dlightbits[(MAX_DLIGHTS + 7) / 8]; |
||||
|
// jkrige - increase dlights |
||||
|
|
||||
|
int lightmaptexturenum; |
||||
|
byte styles[MAXLIGHTMAPS]; |
||||
|
int cached_light[MAXLIGHTMAPS]; // values currently used in lightmap |
||||
|
qboolean cached_dlight; // true if dynamic light in cache |
||||
|
byte *samples; // [numstyles*surfsize] |
||||
|
|
||||
|
// jkrige - overbrights |
||||
|
qboolean overbright; |
||||
|
// jkrige - overbrights |
||||
|
|
||||
|
} msurface_t; |
||||
|
|
||||
|
typedef struct mnode_s |
||||
|
{ |
||||
|
// common with leaf |
||||
|
int contents; // 0, to differentiate from leafs |
||||
|
int visframe; // node needs to be traversed if current |
||||
|
|
||||
|
float minmaxs[6]; // for bounding box culling |
||||
|
|
||||
|
struct mnode_s *parent; |
||||
|
|
||||
|
// node specific |
||||
|
mplane_t *plane; |
||||
|
struct mnode_s *children[2]; |
||||
|
|
||||
|
unsigned short firstsurface; |
||||
|
unsigned short numsurfaces; |
||||
|
} mnode_t; |
||||
|
|
||||
|
|
||||
|
|
||||
|
typedef struct mleaf_s |
||||
|
{ |
||||
|
// common with node |
||||
|
int contents; // wil be a negative contents number |
||||
|
int visframe; // node needs to be traversed if current |
||||
|
|
||||
|
float minmaxs[6]; // for bounding box culling |
||||
|
|
||||
|
struct mnode_s *parent; |
||||
|
|
||||
|
// leaf specific |
||||
|
byte *compressed_vis; |
||||
|
efrag_t *efrags; |
||||
|
|
||||
|
msurface_t **firstmarksurface; |
||||
|
int nummarksurfaces; |
||||
|
int key; // BSP sequence number for leaf's contents |
||||
|
byte ambient_sound_level[NUM_AMBIENTS]; |
||||
|
} mleaf_t; |
||||
|
|
||||
|
// !!! if this is changed, it must be changed in asm_i386.h too !!! |
||||
|
typedef struct |
||||
|
{ |
||||
|
dclipnode_t *clipnodes; |
||||
|
mplane_t *planes; |
||||
|
int firstclipnode; |
||||
|
int lastclipnode; |
||||
|
vec3_t clip_mins; |
||||
|
vec3_t clip_maxs; |
||||
|
} hull_t; |
||||
|
|
||||
|
/* |
||||
|
============================================================================== |
||||
|
|
||||
|
SPRITE MODELS |
||||
|
|
||||
|
============================================================================== |
||||
|
*/ |
||||
|
|
||||
|
|
||||
|
// FIXME: shorten these? |
||||
|
typedef struct mspriteframe_s |
||||
|
{ |
||||
|
int width; |
||||
|
int height; |
||||
|
float up, down, left, right; |
||||
|
int gl_texturenum; |
||||
|
} mspriteframe_t; |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
int numframes; |
||||
|
float *intervals; |
||||
|
mspriteframe_t *frames[1]; |
||||
|
} mspritegroup_t; |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
spriteframetype_t type; |
||||
|
mspriteframe_t *frameptr; |
||||
|
} mspriteframedesc_t; |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
int type; |
||||
|
int maxwidth; |
||||
|
int maxheight; |
||||
|
int numframes; |
||||
|
float beamlength; // remove? |
||||
|
void *cachespot; // remove? |
||||
|
mspriteframedesc_t frames[1]; |
||||
|
} msprite_t; |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
============================================================================== |
||||
|
|
||||
|
ALIAS MODELS |
||||
|
|
||||
|
Alias models are position independent, so the cache manager can move them. |
||||
|
============================================================================== |
||||
|
*/ |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
int firstpose; |
||||
|
int numposes; |
||||
|
float interval; |
||||
|
trivertx_t bboxmin; |
||||
|
trivertx_t bboxmax; |
||||
|
int frame; |
||||
|
char name[16]; |
||||
|
} maliasframedesc_t; |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
trivertx_t bboxmin; |
||||
|
trivertx_t bboxmax; |
||||
|
int frame; |
||||
|
} maliasgroupframedesc_t; |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
int numframes; |
||||
|
int intervals; |
||||
|
maliasgroupframedesc_t frames[1]; |
||||
|
} maliasgroup_t; |
||||
|
|
||||
|
// !!! if this is changed, it must be changed in asm_draw.h too !!! |
||||
|
typedef struct mtriangle_s { |
||||
|
int facesfront; |
||||
|
int vertindex[3]; |
||||
|
} mtriangle_t; |
||||
|
|
||||
|
|
||||
|
#define MAX_SKINS 32 |
||||
|
typedef struct { |
||||
|
int ident; |
||||
|
int version; |
||||
|
vec3_t scale; |
||||
|
vec3_t scale_origin; |
||||
|
float boundingradius; |
||||
|
vec3_t eyeposition; |
||||
|
int numskins; |
||||
|
int skinwidth; |
||||
|
int skinheight; |
||||
|
int numverts; |
||||
|
int numtris; |
||||
|
int numframes; |
||||
|
synctype_t synctype; |
||||
|
int flags; |
||||
|
float size; |
||||
|
|
||||
|
int numposes; |
||||
|
int poseverts; |
||||
|
int posedata; // numposes*poseverts trivert_t |
||||
|
int commands; // gl command list with embedded s/t |
||||
|
int gl_texturenum[MAX_SKINS][4]; |
||||
|
int texels[MAX_SKINS]; // only for player skins |
||||
|
|
||||
|
// jkrige - fullbright pixels |
||||
|
qboolean skin_luma[MAX_SKINS]; |
||||
|
qboolean skin_luma8bit[MAX_SKINS]; |
||||
|
// jkrige - fullbright pixels |
||||
|
|
||||
|
|
||||
|
maliasframedesc_t frames[1]; // variable sized |
||||
|
} aliashdr_t; |
||||
|
|
||||
|
#define MAXALIASVERTS 1024 |
||||
|
#define MAXALIASFRAMES 256 |
||||
|
#define MAXALIASTRIS 2048 |
||||
|
extern aliashdr_t *pheader; |
||||
|
extern stvert_t stverts[MAXALIASVERTS]; |
||||
|
extern mtriangle_t triangles[MAXALIASTRIS]; |
||||
|
extern trivertx_t *poseverts[MAXALIASFRAMES]; |
||||
|
|
||||
|
//=================================================================== |
||||
|
|
||||
|
// |
||||
|
// Whole model |
||||
|
// |
||||
|
|
||||
|
typedef enum {mod_brush, mod_sprite, mod_alias} modtype_t; |
||||
|
|
||||
|
#define EF_ROCKET 1 // leave a trail |
||||
|
#define EF_GRENADE 2 // leave a trail |
||||
|
#define EF_GIB 4 // leave a trail |
||||
|
#define EF_ROTATE 8 // rotate (bonus items) |
||||
|
#define EF_TRACER 16 // green split trail |
||||
|
#define EF_ZOMGIB 32 // small blood trail |
||||
|
#define EF_TRACER2 64 // orange split trail + rotate |
||||
|
#define EF_TRACER3 128 // purple trail |
||||
|
|
||||
|
typedef struct model_s |
||||
|
{ |
||||
|
char name[MAX_QPATH]; |
||||
|
qboolean needload; // bmodels and sprites don't cache normally |
||||
|
|
||||
|
modtype_t type; |
||||
|
int numframes; |
||||
|
synctype_t synctype; |
||||
|
|
||||
|
int flags; |
||||
|
|
||||
|
|
||||
|
// |
||||
|
// volume occupied by the model graphics |
||||
|
// |
||||
|
vec3_t mins, maxs; |
||||
|
float radius; |
||||
|
|
||||
|
// |
||||
|
// solid volume for clipping |
||||
|
// |
||||
|
qboolean clipbox; |
||||
|
vec3_t clipmins, clipmaxs; |
||||
|
|
||||
|
// |
||||
|
// brush model |
||||
|
// |
||||
|
int firstmodelsurface, nummodelsurfaces; |
||||
|
|
||||
|
int numsubmodels; |
||||
|
dmodel_t *submodels; |
||||
|
|
||||
|
int numplanes; |
||||
|
mplane_t *planes; |
||||
|
|
||||
|
int numleafs; // number of visible leafs, not counting 0 |
||||
|
mleaf_t *leafs; |
||||
|
|
||||
|
int numvertexes; |
||||
|
mvertex_t *vertexes; |
||||
|
|
||||
|
int numedges; |
||||
|
medge_t *edges; |
||||
|
|
||||
|
int numnodes; |
||||
|
mnode_t *nodes; |
||||
|
|
||||
|
int numtexinfo; |
||||
|
mtexinfo_t *texinfo; |
||||
|
|
||||
|
int numsurfaces; |
||||
|
msurface_t *surfaces; |
||||
|
|
||||
|
int numsurfedges; |
||||
|
int *surfedges; |
||||
|
|
||||
|
int numclipnodes; |
||||
|
dclipnode_t *clipnodes; |
||||
|
|
||||
|
int nummarksurfaces; |
||||
|
msurface_t **marksurfaces; |
||||
|
|
||||
|
hull_t hulls[MAX_MAP_HULLS]; |
||||
|
|
||||
|
int numtextures; |
||||
|
texture_t **textures; |
||||
|
|
||||
|
byte *visdata; |
||||
|
byte *lightdata; |
||||
|
char *entities; |
||||
|
|
||||
|
// |
||||
|
// additional model data |
||||
|
// |
||||
|
cache_user_t cache; // only access through Mod_Extradata |
||||
|
|
||||
|
} model_t; |
||||
|
|
||||
|
//============================================================================ |
||||
|
|
||||
|
void Mod_Init (void); |
||||
|
void Mod_ClearAll (void); |
||||
|
model_t *Mod_ForName (char *name, qboolean crash); |
||||
|
void *Mod_Extradata (model_t *mod); // handles caching |
||||
|
void Mod_TouchModel (char *name); |
||||
|
|
||||
|
mleaf_t *Mod_PointInLeaf (float *p, model_t *model); |
||||
|
byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model); |
||||
|
|
||||
|
#endif // __MODEL__ |
||||
@ -0,0 +1,234 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// r_efrag.c |
||||
|
|
||||
|
#include "quakedef.h" |
||||
|
|
||||
|
mnode_t *r_pefragtopnode; |
||||
|
|
||||
|
|
||||
|
//=========================================================================== |
||||
|
|
||||
|
/* |
||||
|
=============================================================================== |
||||
|
|
||||
|
ENTITY FRAGMENT FUNCTIONS |
||||
|
|
||||
|
=============================================================================== |
||||
|
*/ |
||||
|
|
||||
|
efrag_t **lastlink; |
||||
|
|
||||
|
vec3_t r_emins, r_emaxs; |
||||
|
|
||||
|
entity_t *r_addent; |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================ |
||||
|
R_RemoveEfrags |
||||
|
|
||||
|
Call when removing an object from the world or moving it to another position |
||||
|
================ |
||||
|
*/ |
||||
|
void R_RemoveEfrags (entity_t *ent) |
||||
|
{ |
||||
|
efrag_t *ef, *old, *walk, **prev; |
||||
|
|
||||
|
ef = ent->efrag; |
||||
|
|
||||
|
while (ef) |
||||
|
{ |
||||
|
prev = &ef->leaf->efrags; |
||||
|
while (1) |
||||
|
{ |
||||
|
walk = *prev; |
||||
|
if (!walk) |
||||
|
break; |
||||
|
if (walk == ef) |
||||
|
{ // remove this fragment |
||||
|
*prev = ef->leafnext; |
||||
|
break; |
||||
|
} |
||||
|
else |
||||
|
prev = &walk->leafnext; |
||||
|
} |
||||
|
|
||||
|
old = ef; |
||||
|
ef = ef->entnext; |
||||
|
|
||||
|
// put it on the free list |
||||
|
old->entnext = cl.free_efrags; |
||||
|
cl.free_efrags = old; |
||||
|
} |
||||
|
|
||||
|
ent->efrag = NULL; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
=================== |
||||
|
R_SplitEntityOnNode |
||||
|
=================== |
||||
|
*/ |
||||
|
void R_SplitEntityOnNode (mnode_t *node) |
||||
|
{ |
||||
|
efrag_t *ef; |
||||
|
mplane_t *splitplane; |
||||
|
mleaf_t *leaf; |
||||
|
int sides; |
||||
|
|
||||
|
if (node->contents == CONTENTS_SOLID) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// add an efrag if the node is a leaf |
||||
|
|
||||
|
if ( node->contents < 0) |
||||
|
{ |
||||
|
if (!r_pefragtopnode) |
||||
|
r_pefragtopnode = node; |
||||
|
|
||||
|
leaf = (mleaf_t *)node; |
||||
|
|
||||
|
// grab an efrag off the free list |
||||
|
ef = cl.free_efrags; |
||||
|
if (!ef) |
||||
|
{ |
||||
|
Con_Printf ("Too many efrags!\n"); |
||||
|
return; // no free fragments... |
||||
|
} |
||||
|
cl.free_efrags = cl.free_efrags->entnext; |
||||
|
|
||||
|
ef->entity = r_addent; |
||||
|
|
||||
|
// add the entity link |
||||
|
*lastlink = ef; |
||||
|
lastlink = &ef->entnext; |
||||
|
ef->entnext = NULL; |
||||
|
|
||||
|
// set the leaf links |
||||
|
ef->leaf = leaf; |
||||
|
ef->leafnext = leaf->efrags; |
||||
|
leaf->efrags = ef; |
||||
|
|
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// NODE_MIXED |
||||
|
|
||||
|
splitplane = node->plane; |
||||
|
sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane); |
||||
|
|
||||
|
if (sides == 3) |
||||
|
{ |
||||
|
// split on this plane |
||||
|
// if this is the first splitter of this bmodel, remember it |
||||
|
if (!r_pefragtopnode) |
||||
|
r_pefragtopnode = node; |
||||
|
} |
||||
|
|
||||
|
// recurse down the contacted sides |
||||
|
if (sides & 1) |
||||
|
R_SplitEntityOnNode (node->children[0]); |
||||
|
|
||||
|
if (sides & 2) |
||||
|
R_SplitEntityOnNode (node->children[1]); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/* |
||||
|
=========== |
||||
|
R_AddEfrags |
||||
|
=========== |
||||
|
*/ |
||||
|
void R_AddEfrags (entity_t *ent) |
||||
|
{ |
||||
|
model_t *entmodel; |
||||
|
int i; |
||||
|
|
||||
|
if (!ent->model) |
||||
|
return; |
||||
|
|
||||
|
r_addent = ent; |
||||
|
|
||||
|
lastlink = &ent->efrag; |
||||
|
r_pefragtopnode = NULL; |
||||
|
|
||||
|
entmodel = ent->model; |
||||
|
|
||||
|
for (i=0 ; i<3 ; i++) |
||||
|
{ |
||||
|
r_emins[i] = ent->origin[i] + entmodel->mins[i]; |
||||
|
r_emaxs[i] = ent->origin[i] + entmodel->maxs[i]; |
||||
|
} |
||||
|
|
||||
|
R_SplitEntityOnNode (cl.worldmodel->nodes); |
||||
|
|
||||
|
ent->topnode = r_pefragtopnode; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================ |
||||
|
R_StoreEfrags |
||||
|
|
||||
|
// FIXME: a lot of this goes away with edge-based |
||||
|
================ |
||||
|
*/ |
||||
|
void R_StoreEfrags (efrag_t **ppefrag) |
||||
|
{ |
||||
|
entity_t *pent; |
||||
|
model_t *clmodel; |
||||
|
efrag_t *pefrag; |
||||
|
|
||||
|
|
||||
|
while ((pefrag = *ppefrag) != NULL) |
||||
|
{ |
||||
|
pent = pefrag->entity; |
||||
|
clmodel = pent->model; |
||||
|
|
||||
|
switch (clmodel->type) |
||||
|
{ |
||||
|
case mod_alias: |
||||
|
case mod_brush: |
||||
|
case mod_sprite: |
||||
|
pent = pefrag->entity; |
||||
|
|
||||
|
if ((pent->visframe != r_framecount) && |
||||
|
(cl_numvisedicts < MAX_VISEDICTS)) |
||||
|
{ |
||||
|
cl_visedicts[cl_numvisedicts++] = pent; |
||||
|
|
||||
|
// mark that we've recorded this entity for this frame |
||||
|
pent->visframe = r_framecount; |
||||
|
} |
||||
|
|
||||
|
ppefrag = &pefrag->leafnext; |
||||
|
break; |
||||
|
|
||||
|
default: |
||||
|
Sys_Error ("R_StoreEfrags: Bad entity type %d\n", clmodel->type); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
@ -0,0 +1,579 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// r_light.c |
||||
|
|
||||
|
#include "quakedef.h" |
||||
|
|
||||
|
int r_dlightframecount; |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================== |
||||
|
R_AnimateLight |
||||
|
================== |
||||
|
*/ |
||||
|
void R_AnimateLight (void) |
||||
|
{ |
||||
|
int i,j,k; |
||||
|
|
||||
|
// |
||||
|
// light animations |
||||
|
// 'm' is normal light, 'a' is no light, 'z' is double bright |
||||
|
i = (int)(cl.time*10); |
||||
|
for (j=0 ; j<MAX_LIGHTSTYLES ; j++) |
||||
|
{ |
||||
|
if (!cl_lightstyle[j].length) |
||||
|
{ |
||||
|
d_lightstylevalue[j] = 256; |
||||
|
continue; |
||||
|
} |
||||
|
k = i % cl_lightstyle[j].length; |
||||
|
k = cl_lightstyle[j].map[k] - 'a'; |
||||
|
k = k*22; |
||||
|
d_lightstylevalue[j] = k; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
============================================================================= |
||||
|
|
||||
|
DYNAMIC LIGHTS BLEND RENDERING |
||||
|
|
||||
|
============================================================================= |
||||
|
*/ |
||||
|
|
||||
|
// jkrige - flashblend removal |
||||
|
/*void AddLightBlend (float r, float g, float b, float a2) |
||||
|
{ |
||||
|
float a; |
||||
|
|
||||
|
v_blend[3] = a = v_blend[3] + a2*(1-v_blend[3]); |
||||
|
|
||||
|
a2 = a2/a; |
||||
|
|
||||
|
v_blend[0] = v_blend[1]*(1-a2) + r*a2; |
||||
|
v_blend[1] = v_blend[1]*(1-a2) + g*a2; |
||||
|
v_blend[2] = v_blend[2]*(1-a2) + b*a2; |
||||
|
}*/ |
||||
|
// jkrige - flashblend removal |
||||
|
|
||||
|
|
||||
|
// jkrige - flashblend removal |
||||
|
/*void R_RenderDlight (dlight_t *light) |
||||
|
{ |
||||
|
int i, j; |
||||
|
float a; |
||||
|
vec3_t v; |
||||
|
float rad; |
||||
|
|
||||
|
rad = light->radius * 0.35; |
||||
|
|
||||
|
VectorSubtract (light->origin, r_origin, v); |
||||
|
if (Length (v) < rad) |
||||
|
{ // view is inside the dlight |
||||
|
AddLightBlend (1, 0.5, 0, light->radius * 0.0003); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
glBegin (GL_TRIANGLE_FAN); |
||||
|
glColor3f (0.2,0.1,0.0); |
||||
|
for (i=0 ; i<3 ; i++) |
||||
|
v[i] = light->origin[i] - vpn[i]*rad; |
||||
|
glVertex3fv (v); |
||||
|
glColor3f (0,0,0); |
||||
|
for (i=16 ; i>=0 ; i--) |
||||
|
{ |
||||
|
a = i/16.0 * M_PI*2; |
||||
|
for (j=0 ; j<3 ; j++) |
||||
|
v[j] = light->origin[j] + vright[j]*cos(a)*rad |
||||
|
+ vup[j]*sin(a)*rad; |
||||
|
glVertex3fv (v); |
||||
|
} |
||||
|
glEnd (); |
||||
|
}*/ |
||||
|
// jkrige - flashblend removal |
||||
|
|
||||
|
|
||||
|
// jkrige - flashblend removal |
||||
|
/* |
||||
|
============= |
||||
|
R_RenderDlights |
||||
|
============= |
||||
|
*/ |
||||
|
/*void R_RenderDlights (void) |
||||
|
{ |
||||
|
int i; |
||||
|
dlight_t *l; |
||||
|
|
||||
|
if (!gl_flashblend.value) |
||||
|
return; |
||||
|
|
||||
|
r_dlightframecount = r_framecount + 1; // because the count hasn't |
||||
|
// advanced yet for this frame |
||||
|
glDepthMask (0); |
||||
|
glDisable (GL_TEXTURE_2D); |
||||
|
glShadeModel (GL_SMOOTH); |
||||
|
glEnable (GL_BLEND); |
||||
|
glBlendFunc (GL_ONE, GL_ONE); |
||||
|
|
||||
|
l = cl_dlights; |
||||
|
for (i=0 ; i<MAX_DLIGHTS ; i++, l++) |
||||
|
{ |
||||
|
if (l->die < cl.time || !l->radius) |
||||
|
continue; |
||||
|
R_RenderDlight (l); |
||||
|
} |
||||
|
|
||||
|
glColor3f (1,1,1); |
||||
|
glDisable (GL_BLEND); |
||||
|
glEnable (GL_TEXTURE_2D); |
||||
|
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
||||
|
glDepthMask (1); |
||||
|
}*/ |
||||
|
// jkrige - flashblend removal |
||||
|
|
||||
|
/* |
||||
|
============================================================================= |
||||
|
|
||||
|
DYNAMIC LIGHTS |
||||
|
|
||||
|
============================================================================= |
||||
|
*/ |
||||
|
|
||||
|
/* |
||||
|
============= |
||||
|
R_MarkLights |
||||
|
============= |
||||
|
*/ |
||||
|
void R_MarkLights (dlight_t *light, int lnum, mnode_t *node) |
||||
|
{ |
||||
|
mplane_t *splitplane; |
||||
|
float dist; |
||||
|
msurface_t *surf; |
||||
|
int i; |
||||
|
|
||||
|
// jkrige - fix dynamic light shine through |
||||
|
int sidebit; |
||||
|
// jkrige - fix dynamic light shine through |
||||
|
|
||||
|
// jkrige - speed increase |
||||
|
float l, maxdist; |
||||
|
int j, s, t; |
||||
|
vec3_t impact; |
||||
|
loc0: |
||||
|
// jkrige - speed increase |
||||
|
|
||||
|
if (node->contents < 0) |
||||
|
return; |
||||
|
|
||||
|
splitplane = node->plane; |
||||
|
|
||||
|
// jkrige - speed increase |
||||
|
if (splitplane->type < 3) |
||||
|
dist = light->origin[splitplane->type] - splitplane->dist; |
||||
|
else |
||||
|
dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist; |
||||
|
//dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist; |
||||
|
// jkrige - speed increase |
||||
|
|
||||
|
if (dist > light->radius) |
||||
|
{ |
||||
|
// jkrige - speed increase |
||||
|
node = node->children[0]; |
||||
|
goto loc0; |
||||
|
//R_MarkLights (light, lnum, node->children[0]); |
||||
|
//return; |
||||
|
// jkrige - speed increase |
||||
|
} |
||||
|
if (dist < -light->radius) |
||||
|
{ |
||||
|
// jkrige - speed increase |
||||
|
node = node->children[1]; |
||||
|
goto loc0; |
||||
|
//R_MarkLights (light, lnum, node->children[1]); |
||||
|
//return; |
||||
|
// jkrige - speed increase |
||||
|
} |
||||
|
|
||||
|
// jkrige - speed increase |
||||
|
maxdist = light->radius*light->radius; |
||||
|
// jkrige - speed increase |
||||
|
|
||||
|
// mark the polygons |
||||
|
surf = cl.worldmodel->surfaces + node->firstsurface; |
||||
|
for (i=0 ; i<node->numsurfaces ; i++, surf++) |
||||
|
{ |
||||
|
// jkrige - fix dynamic light shine through |
||||
|
if (r_dynamic_sidemark.value) |
||||
|
{ |
||||
|
if (dist >= 0) |
||||
|
sidebit = 0; |
||||
|
else |
||||
|
sidebit = SURF_PLANEBACK; |
||||
|
|
||||
|
if ( (surf->flags & SURF_PLANEBACK) != sidebit ) |
||||
|
continue; |
||||
|
} |
||||
|
// jkrige - fix dynamic light shine through |
||||
|
|
||||
|
|
||||
|
// jkrige - speed increase |
||||
|
for (j=0 ; j<3 ; j++) |
||||
|
impact[j] = light->origin[j] - surf->plane->normal[j] * dist; |
||||
|
|
||||
|
// clamp center of light to corner and check brightness |
||||
|
l = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0]; |
||||
|
s = l + 0.5; |
||||
|
if (s < 0) |
||||
|
s = 0; |
||||
|
else if (s > surf->extents[0]) |
||||
|
s = surf->extents[0]; |
||||
|
s = l - s; |
||||
|
l = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1]; |
||||
|
t = l + 0.5; |
||||
|
if (t < 0) |
||||
|
t = 0; |
||||
|
else if (t > surf->extents[1]) |
||||
|
t = surf->extents[1]; |
||||
|
t = l - t; |
||||
|
// jkrige - speed increase |
||||
|
|
||||
|
|
||||
|
// jkrige - increase dlights |
||||
|
//if (surf->dlightframe != r_dlightframecount) |
||||
|
//{ |
||||
|
// surf->dlightbits = 0; |
||||
|
// surf->dlightframe = r_dlightframecount; |
||||
|
//} |
||||
|
//surf->dlightbits |= lnum; // jkrige - was bit |
||||
|
|
||||
|
|
||||
|
if ((s*s+t*t+dist*dist) < maxdist) // jkrige - speed increase |
||||
|
{ |
||||
|
if (surf->dlightframe != r_dlightframecount) |
||||
|
{ |
||||
|
// init a new dlight on the surf |
||||
|
int j; |
||||
|
|
||||
|
for (j = 0; j < MAX_DLIGHTS; j += 8) |
||||
|
surf->dlightbits[(j >> 3)] = 0; |
||||
|
|
||||
|
surf->dlightframe = r_dlightframecount; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
// mark it |
||||
|
surf->dlightbits[(lnum >> 3)] |= (1 << (lnum & 7)); |
||||
|
} |
||||
|
// jkrige - increase dlights |
||||
|
} |
||||
|
|
||||
|
// jkrige - speed increase |
||||
|
if (node->children[0]->contents >= 0) |
||||
|
R_MarkLights (light, lnum, node->children[0]); |
||||
|
if (node->children[1]->contents >= 0) |
||||
|
R_MarkLights (light, lnum, node->children[1]); |
||||
|
//R_MarkLights (light, lnum, node->children[0]); |
||||
|
//R_MarkLights (light, lnum, node->children[1]); |
||||
|
// jkrige - speed increase |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
============= |
||||
|
R_PushDlights |
||||
|
============= |
||||
|
*/ |
||||
|
void R_PushDlights (void) |
||||
|
{ |
||||
|
int i; |
||||
|
dlight_t *l; |
||||
|
|
||||
|
// jkrige - flashblend removal |
||||
|
//if (gl_flashblend.value) |
||||
|
// return; |
||||
|
// jkrige - flashblend removal |
||||
|
|
||||
|
r_dlightframecount = r_framecount + 1; // because the count hasn't |
||||
|
// advanced yet for this frame |
||||
|
l = cl_dlights; |
||||
|
|
||||
|
for (i=0 ; i<MAX_DLIGHTS ; i++, l++) |
||||
|
{ |
||||
|
if (l->die < cl.time || !l->radius) |
||||
|
continue; |
||||
|
|
||||
|
// jkrige - increase dlights |
||||
|
//R_MarkLights ( l, 1<<i, cl.worldmodel->nodes ); |
||||
|
R_MarkLights ( l, i, cl.worldmodel->nodes ); |
||||
|
// jkrige - increase dlights |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
============================================================================= |
||||
|
|
||||
|
LIGHT SAMPLING |
||||
|
|
||||
|
============================================================================= |
||||
|
*/ |
||||
|
|
||||
|
mplane_t *lightplane; |
||||
|
vec3_t lightspot; |
||||
|
|
||||
|
// jkrige - .lit colored lights |
||||
|
int RecursiveLightPoint (vec3_t color, mnode_t *node, vec3_t start, vec3_t end) |
||||
|
{ |
||||
|
float front, back, frac; |
||||
|
vec3_t mid; |
||||
|
|
||||
|
loc0: |
||||
|
if (node->contents < 0) |
||||
|
return false; // didn't hit anything |
||||
|
|
||||
|
// calculate mid point |
||||
|
if (node->plane->type < 3) |
||||
|
{ |
||||
|
front = start[node->plane->type] - node->plane->dist; |
||||
|
back = end[node->plane->type] - node->plane->dist; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
front = DotProduct(start, node->plane->normal) - node->plane->dist; |
||||
|
back = DotProduct(end, node->plane->normal) - node->plane->dist; |
||||
|
} |
||||
|
|
||||
|
// LordHavoc: optimized recursion |
||||
|
if ((back < 0) == (front < 0)) |
||||
|
// return RecursiveLightPoint (color, node->children[front < 0], start, end); |
||||
|
{ |
||||
|
node = node->children[front < 0]; |
||||
|
goto loc0; |
||||
|
} |
||||
|
|
||||
|
frac = front / (front-back); |
||||
|
mid[0] = start[0] + (end[0] - start[0])*frac; |
||||
|
mid[1] = start[1] + (end[1] - start[1])*frac; |
||||
|
mid[2] = start[2] + (end[2] - start[2])*frac; |
||||
|
|
||||
|
// go down front side |
||||
|
if (RecursiveLightPoint (color, node->children[front < 0], start, mid)) |
||||
|
return true; // hit something |
||||
|
else |
||||
|
{ |
||||
|
int i, ds, dt; |
||||
|
msurface_t *surf; |
||||
|
// check for impact on this node |
||||
|
VectorCopy (mid, lightspot); |
||||
|
lightplane = node->plane; |
||||
|
|
||||
|
surf = cl.worldmodel->surfaces + node->firstsurface; |
||||
|
for (i = 0;i < node->numsurfaces;i++, surf++) |
||||
|
{ |
||||
|
if (surf->flags & SURF_DRAWTILED) |
||||
|
continue; // no lightmaps |
||||
|
|
||||
|
ds = (int) ((float) DotProduct (mid, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]); |
||||
|
dt = (int) ((float) DotProduct (mid, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]); |
||||
|
|
||||
|
if (ds < surf->texturemins[0] || dt < surf->texturemins[1]) |
||||
|
continue; |
||||
|
|
||||
|
ds -= surf->texturemins[0]; |
||||
|
dt -= surf->texturemins[1]; |
||||
|
|
||||
|
if (ds > surf->extents[0] || dt > surf->extents[1]) |
||||
|
continue; |
||||
|
|
||||
|
if (surf->samples) |
||||
|
{ |
||||
|
// LordHavoc: enhanced to interpolate lighting |
||||
|
byte *lightmap; |
||||
|
int maps, line3, dsfrac = ds & 15, dtfrac = dt & 15, r00 = 0, g00 = 0, b00 = 0, r01 = 0, g01 = 0, b01 = 0, r10 = 0, g10 = 0, b10 = 0, r11 = 0, g11 = 0, b11 = 0; |
||||
|
float scale; |
||||
|
line3 = ((surf->extents[0]>>4)+1)*3; |
||||
|
|
||||
|
lightmap = surf->samples + ((dt>>4) * ((surf->extents[0]>>4)+1) + (ds>>4))*3; // LordHavoc: *3 for color |
||||
|
|
||||
|
for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != 255;maps++) |
||||
|
{ |
||||
|
scale = (float) d_lightstylevalue[surf->styles[maps]] * 1.0 / 256.0; |
||||
|
r00 += (float) lightmap[ 0] * scale;g00 += (float) lightmap[ 1] * scale;b00 += (float) lightmap[2] * scale; |
||||
|
r01 += (float) lightmap[ 3] * scale;g01 += (float) lightmap[ 4] * scale;b01 += (float) lightmap[5] * scale; |
||||
|
r10 += (float) lightmap[line3+0] * scale;g10 += (float) lightmap[line3+1] * scale;b10 += (float) lightmap[line3+2] * scale; |
||||
|
r11 += (float) lightmap[line3+3] * scale;g11 += (float) lightmap[line3+4] * scale;b11 += (float) lightmap[line3+5] * scale; |
||||
|
lightmap += ((surf->extents[0]>>4)+1) * ((surf->extents[1]>>4)+1)*3; // LordHavoc: *3 for colored lighting |
||||
|
} |
||||
|
|
||||
|
color[0] += (float) ((int) ((((((((r11-r10) * dsfrac) >> 4) + r10)-((((r01-r00) * dsfrac) >> 4) + r00)) * dtfrac) >> 4) + ((((r01-r00) * dsfrac) >> 4) + r00))); |
||||
|
color[1] += (float) ((int) ((((((((g11-g10) * dsfrac) >> 4) + g10)-((((g01-g00) * dsfrac) >> 4) + g00)) * dtfrac) >> 4) + ((((g01-g00) * dsfrac) >> 4) + g00))); |
||||
|
color[2] += (float) ((int) ((((((((b11-b10) * dsfrac) >> 4) + b10)-((((b01-b00) * dsfrac) >> 4) + b00)) * dtfrac) >> 4) + ((((b01-b00) * dsfrac) >> 4) + b00))); |
||||
|
} |
||||
|
return true; // success |
||||
|
} |
||||
|
|
||||
|
// go down back side |
||||
|
return RecursiveLightPoint (color, node->children[front >= 0], mid, end); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*int RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end) |
||||
|
{ |
||||
|
int r; |
||||
|
float front, back, frac; |
||||
|
int side; |
||||
|
mplane_t *plane; |
||||
|
vec3_t mid; |
||||
|
msurface_t *surf; |
||||
|
int s, t, ds, dt; |
||||
|
int i; |
||||
|
mtexinfo_t *tex; |
||||
|
byte *lightmap; |
||||
|
unsigned scale; |
||||
|
int maps; |
||||
|
|
||||
|
if (node->contents < 0) |
||||
|
return -1; // didn't hit anything |
||||
|
|
||||
|
// calculate mid point |
||||
|
|
||||
|
// FIXME: optimize for axial |
||||
|
plane = node->plane; |
||||
|
front = DotProduct (start, plane->normal) - plane->dist; |
||||
|
back = DotProduct (end, plane->normal) - plane->dist; |
||||
|
side = front < 0; |
||||
|
|
||||
|
if ( (back < 0) == side) |
||||
|
return RecursiveLightPoint (node->children[side], start, end); |
||||
|
|
||||
|
frac = front / (front-back); |
||||
|
mid[0] = start[0] + (end[0] - start[0])*frac; |
||||
|
mid[1] = start[1] + (end[1] - start[1])*frac; |
||||
|
mid[2] = start[2] + (end[2] - start[2])*frac; |
||||
|
|
||||
|
// go down front side |
||||
|
r = RecursiveLightPoint (node->children[side], start, mid); |
||||
|
if (r >= 0) |
||||
|
return r; // hit something |
||||
|
|
||||
|
if ( (back < 0) == side ) |
||||
|
return -1; // didn't hit anuthing |
||||
|
|
||||
|
// check for impact on this node |
||||
|
VectorCopy (mid, lightspot); |
||||
|
lightplane = plane; |
||||
|
|
||||
|
surf = cl.worldmodel->surfaces + node->firstsurface; |
||||
|
for (i=0 ; i<node->numsurfaces ; i++, surf++) |
||||
|
{ |
||||
|
if (surf->flags & SURF_DRAWTILED) |
||||
|
continue; // no lightmaps |
||||
|
|
||||
|
tex = surf->texinfo; |
||||
|
|
||||
|
s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3]; |
||||
|
t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];; |
||||
|
|
||||
|
if (s < surf->texturemins[0] || |
||||
|
t < surf->texturemins[1]) |
||||
|
continue; |
||||
|
|
||||
|
ds = s - surf->texturemins[0]; |
||||
|
dt = t - surf->texturemins[1]; |
||||
|
|
||||
|
if ( ds > surf->extents[0] || dt > surf->extents[1] ) |
||||
|
continue; |
||||
|
|
||||
|
if (!surf->samples) |
||||
|
return 0; |
||||
|
|
||||
|
ds >>= 4; |
||||
|
dt >>= 4; |
||||
|
|
||||
|
lightmap = surf->samples; |
||||
|
r = 0; |
||||
|
if (lightmap) |
||||
|
{ |
||||
|
|
||||
|
lightmap += dt * ((surf->extents[0]>>4)+1) + ds; |
||||
|
|
||||
|
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ; |
||||
|
maps++) |
||||
|
{ |
||||
|
scale = d_lightstylevalue[surf->styles[maps]]; |
||||
|
r += *lightmap * scale; |
||||
|
lightmap += ((surf->extents[0]>>4)+1) * |
||||
|
((surf->extents[1]>>4)+1); |
||||
|
} |
||||
|
|
||||
|
r >>= 8; |
||||
|
} |
||||
|
|
||||
|
return r; |
||||
|
} |
||||
|
|
||||
|
// go down back side |
||||
|
return RecursiveLightPoint (node->children[!side], mid, end); |
||||
|
}*/ |
||||
|
// jkrige - .lit colored lights |
||||
|
|
||||
|
|
||||
|
// jkrige - .lit colored lights |
||||
|
vec3_t lightcolor; // jkrige - used by model rendering |
||||
|
int R_LightPoint (vec3_t p) |
||||
|
{ |
||||
|
vec3_t end; |
||||
|
|
||||
|
if (r_fullbright.value || !cl.worldmodel->lightdata) |
||||
|
{ |
||||
|
lightcolor[0] = lightcolor[1] = lightcolor[2] = 255; |
||||
|
return 255; |
||||
|
} |
||||
|
|
||||
|
end[0] = p[0]; |
||||
|
end[1] = p[1]; |
||||
|
end[2] = p[2] - 2048; |
||||
|
|
||||
|
lightcolor[0] = lightcolor[1] = lightcolor[2] = 0; |
||||
|
RecursiveLightPoint (lightcolor, cl.worldmodel->nodes, p, end); |
||||
|
return ((lightcolor[0] + lightcolor[1] + lightcolor[2]) * (1.0f / 3.0f)); |
||||
|
} |
||||
|
|
||||
|
/*int R_LightPoint (vec3_t p) |
||||
|
{ |
||||
|
vec3_t end; |
||||
|
int r; |
||||
|
|
||||
|
if (!cl.worldmodel->lightdata) |
||||
|
return 255; |
||||
|
|
||||
|
end[0] = p[0]; |
||||
|
end[1] = p[1]; |
||||
|
end[2] = p[2] - 2048; |
||||
|
|
||||
|
r = RecursiveLightPoint (cl.worldmodel->nodes, p, end); |
||||
|
|
||||
|
if (r == -1) |
||||
|
r = 0; |
||||
|
|
||||
|
return r; |
||||
|
}*/ |
||||
|
// jkrige - .lit colored lights |
||||
1683
engine/code/gl_rmain.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,543 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// r_misc.c |
||||
|
|
||||
|
#include "quakedef.h" |
||||
|
|
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================== |
||||
|
R_InitTextures |
||||
|
================== |
||||
|
*/ |
||||
|
void R_InitTextures (void) |
||||
|
{ |
||||
|
int x,y, m; |
||||
|
byte *dest; |
||||
|
|
||||
|
// create a simple checkerboard texture for the default |
||||
|
r_notexture_mip = Hunk_AllocName (sizeof(texture_t) + 16*16+8*8+4*4+2*2, "notexture"); |
||||
|
|
||||
|
r_notexture_mip->width = r_notexture_mip->height = 16; |
||||
|
r_notexture_mip->offsets[0] = sizeof(texture_t); |
||||
|
r_notexture_mip->offsets[1] = r_notexture_mip->offsets[0] + 16*16; |
||||
|
r_notexture_mip->offsets[2] = r_notexture_mip->offsets[1] + 8*8; |
||||
|
r_notexture_mip->offsets[3] = r_notexture_mip->offsets[2] + 4*4; |
||||
|
|
||||
|
for (m=0 ; m<4 ; m++) |
||||
|
{ |
||||
|
dest = (byte *)r_notexture_mip + r_notexture_mip->offsets[m]; |
||||
|
for (y=0 ; y< (16>>m) ; y++) |
||||
|
for (x=0 ; x< (16>>m) ; x++) |
||||
|
{ |
||||
|
if ( (y< (8>>m) ) ^ (x< (8>>m) ) ) |
||||
|
*dest++ = 0; |
||||
|
else |
||||
|
*dest++ = 0xff; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
byte dottexture[8][8] = |
||||
|
{ |
||||
|
{0,1,1,0,0,0,0,0}, |
||||
|
{1,1,1,1,0,0,0,0}, |
||||
|
{1,1,1,1,0,0,0,0}, |
||||
|
{0,1,1,0,0,0,0,0}, |
||||
|
{0,0,0,0,0,0,0,0}, |
||||
|
{0,0,0,0,0,0,0,0}, |
||||
|
{0,0,0,0,0,0,0,0}, |
||||
|
{0,0,0,0,0,0,0,0}, |
||||
|
}; |
||||
|
|
||||
|
// jkrige - texture mode |
||||
|
byte dottexture_point[8][8] = |
||||
|
{ |
||||
|
{1,1,1,0,0,0,0,0}, |
||||
|
{1,1,1,0,0,0,0,0}, |
||||
|
{1,1,1,0,0,0,0,0}, |
||||
|
{0,0,0,0,0,0,0,0}, |
||||
|
{0,0,0,0,0,0,0,0}, |
||||
|
{0,0,0,0,0,0,0,0}, |
||||
|
{0,0,0,0,0,0,0,0}, |
||||
|
{0,0,0,0,0,0,0,0}, |
||||
|
}; |
||||
|
|
||||
|
void R_InitParticleTexture_Linear (void) |
||||
|
{ |
||||
|
int x,y; |
||||
|
byte data[8][8][4]; |
||||
|
|
||||
|
// |
||||
|
// particle texture |
||||
|
// |
||||
|
particletexture_linear = texture_extension_number++; |
||||
|
GL_Bind(particletexture_linear); |
||||
|
|
||||
|
for (x=0 ; x<8 ; x++) |
||||
|
{ |
||||
|
for (y=0 ; y<8 ; y++) |
||||
|
{ |
||||
|
data[y][x][0] = 255; |
||||
|
data[y][x][1] = 255; |
||||
|
data[y][x][2] = 255; |
||||
|
data[y][x][3] = dottexture[x][y]*255; |
||||
|
} |
||||
|
} |
||||
|
glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); |
||||
|
|
||||
|
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); |
||||
|
|
||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
||||
|
} |
||||
|
|
||||
|
void R_InitParticleTexture_Point (void) |
||||
|
{ |
||||
|
int x,y; |
||||
|
byte data[8][8][4]; |
||||
|
|
||||
|
// |
||||
|
// particle texture |
||||
|
// |
||||
|
particletexture_point = texture_extension_number++; |
||||
|
GL_Bind(particletexture_point); |
||||
|
|
||||
|
for (x=0 ; x<8 ; x++) |
||||
|
{ |
||||
|
for (y=0 ; y<8 ; y++) |
||||
|
{ |
||||
|
data[y][x][0] = 255; |
||||
|
data[y][x][1] = 255; |
||||
|
data[y][x][2] = 255; |
||||
|
data[y][x][3] = dottexture_point[x][y]*255; |
||||
|
} |
||||
|
} |
||||
|
glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); |
||||
|
|
||||
|
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); |
||||
|
|
||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
||||
|
} |
||||
|
|
||||
|
void R_InitParticleTexture (void) |
||||
|
{ |
||||
|
R_InitParticleTexture_Point(); |
||||
|
R_InitParticleTexture_Linear(); |
||||
|
} |
||||
|
// jkrige - texture mode |
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
R_Envmap_f |
||||
|
|
||||
|
Grab six views for environment mapping tests |
||||
|
=============== |
||||
|
*/ |
||||
|
void R_Envmap_f (void) |
||||
|
{ |
||||
|
byte buffer[256*256*4]; |
||||
|
char name[1024]; |
||||
|
|
||||
|
glDrawBuffer (GL_FRONT); |
||||
|
glReadBuffer (GL_FRONT); |
||||
|
envmap = true; |
||||
|
|
||||
|
r_refdef.vrect.x = 0; |
||||
|
r_refdef.vrect.y = 0; |
||||
|
r_refdef.vrect.width = 256; |
||||
|
r_refdef.vrect.height = 256; |
||||
|
|
||||
|
r_refdef.viewangles[0] = 0; |
||||
|
r_refdef.viewangles[1] = 0; |
||||
|
r_refdef.viewangles[2] = 0; |
||||
|
GL_BeginRendering (&glx, &gly, &glwidth, &glheight); |
||||
|
R_RenderView (); |
||||
|
glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); |
||||
|
COM_WriteFile ("env0.rgb", buffer, sizeof(buffer)); |
||||
|
|
||||
|
r_refdef.viewangles[1] = 90; |
||||
|
GL_BeginRendering (&glx, &gly, &glwidth, &glheight); |
||||
|
R_RenderView (); |
||||
|
glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); |
||||
|
COM_WriteFile ("env1.rgb", buffer, sizeof(buffer)); |
||||
|
|
||||
|
r_refdef.viewangles[1] = 180; |
||||
|
GL_BeginRendering (&glx, &gly, &glwidth, &glheight); |
||||
|
R_RenderView (); |
||||
|
glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); |
||||
|
COM_WriteFile ("env2.rgb", buffer, sizeof(buffer)); |
||||
|
|
||||
|
r_refdef.viewangles[1] = 270; |
||||
|
GL_BeginRendering (&glx, &gly, &glwidth, &glheight); |
||||
|
R_RenderView (); |
||||
|
glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); |
||||
|
COM_WriteFile ("env3.rgb", buffer, sizeof(buffer)); |
||||
|
|
||||
|
r_refdef.viewangles[0] = -90; |
||||
|
r_refdef.viewangles[1] = 0; |
||||
|
GL_BeginRendering (&glx, &gly, &glwidth, &glheight); |
||||
|
R_RenderView (); |
||||
|
glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); |
||||
|
COM_WriteFile ("env4.rgb", buffer, sizeof(buffer)); |
||||
|
|
||||
|
r_refdef.viewangles[0] = 90; |
||||
|
r_refdef.viewangles[1] = 0; |
||||
|
GL_BeginRendering (&glx, &gly, &glwidth, &glheight); |
||||
|
R_RenderView (); |
||||
|
glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); |
||||
|
COM_WriteFile ("env5.rgb", buffer, sizeof(buffer)); |
||||
|
|
||||
|
envmap = false; |
||||
|
glDrawBuffer (GL_BACK); |
||||
|
glReadBuffer (GL_BACK); |
||||
|
GL_EndRendering (); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
R_Init |
||||
|
=============== |
||||
|
*/ |
||||
|
void R_Init (void) |
||||
|
{ |
||||
|
extern byte *hunk_base; |
||||
|
|
||||
|
// jkrige - remove gl_finish |
||||
|
//extern cvar_t gl_finish; |
||||
|
// jkrige - remove gl_finish |
||||
|
|
||||
|
Cmd_AddCommand ("timerefresh", R_TimeRefresh_f); |
||||
|
Cmd_AddCommand ("envmap", R_Envmap_f); |
||||
|
Cmd_AddCommand ("pointfile", R_ReadPointFile_f); |
||||
|
|
||||
|
Cvar_RegisterVariable (&r_norefresh); |
||||
|
Cvar_RegisterVariable (&r_lightmap); |
||||
|
Cvar_RegisterVariable (&r_fullbright); |
||||
|
Cvar_RegisterVariable (&r_drawentities); |
||||
|
Cvar_RegisterVariable (&r_drawviewmodel); |
||||
|
//Cvar_RegisterVariable (&r_shadows); // jkrige - removed alias shadows |
||||
|
Cvar_RegisterVariable (&r_mirroralpha); |
||||
|
Cvar_RegisterVariable (&r_wateralpha); |
||||
|
Cvar_RegisterVariable (&r_dynamic); |
||||
|
Cvar_RegisterVariable (&r_novis); |
||||
|
Cvar_RegisterVariable (&r_speeds); |
||||
|
|
||||
|
// jkrige - fix dynamic light shine through |
||||
|
Cvar_RegisterVariable (&r_dynamic_sidemark); |
||||
|
// jkrige - fix dynamic light shine through |
||||
|
|
||||
|
// jkrige - remove gl_finish |
||||
|
//Cvar_RegisterVariable (&gl_finish); |
||||
|
// jkrige - remove gl_finish |
||||
|
|
||||
|
Cvar_RegisterVariable (&gl_clear); |
||||
|
Cvar_RegisterVariable (&gl_texsort); |
||||
|
|
||||
|
// jkrige - remove multitexture |
||||
|
//if (gl_mtexable) |
||||
|
// Cvar_SetValue ("gl_texsort", 0.0); |
||||
|
// jkrige - remove multitexture |
||||
|
|
||||
|
Cvar_RegisterVariable (&gl_cull); |
||||
|
Cvar_RegisterVariable (&gl_smoothmodels); |
||||
|
Cvar_RegisterVariable (&gl_affinemodels); |
||||
|
Cvar_RegisterVariable (&gl_polyblend); |
||||
|
|
||||
|
// jkrige - flashblend removal |
||||
|
//Cvar_RegisterVariable (&gl_flashblend); |
||||
|
// jkrige - flashblend removal |
||||
|
|
||||
|
|
||||
|
Cvar_RegisterVariable (&gl_playermip); |
||||
|
Cvar_RegisterVariable (&gl_nocolors); |
||||
|
|
||||
|
// jkrige - disabled tjunction removal |
||||
|
//Cvar_RegisterVariable (&gl_keeptjunctions); |
||||
|
//Cvar_RegisterVariable (&gl_reporttjunctions); |
||||
|
// jkrige - disabled tjunction removal |
||||
|
|
||||
|
Cvar_RegisterVariable (&gl_skytype); // jkrige - skybox |
||||
|
|
||||
|
Cvar_RegisterVariable (&gl_doubleeyes); |
||||
|
|
||||
|
// jkrige - texture mode |
||||
|
Cvar_RegisterVariable (&gl_texturemode); |
||||
|
// jkrige - texture mode |
||||
|
|
||||
|
// jkrige - wireframe |
||||
|
Cvar_RegisterVariable(&gl_wireframe); |
||||
|
// jkrige - wireframe |
||||
|
|
||||
|
// jkrige - .lit colored lights |
||||
|
Cvar_RegisterVariable (&gl_lightmapfmt); |
||||
|
Cvar_RegisterVariable (&gl_coloredlight); |
||||
|
// jkrige - .lit colored lights |
||||
|
|
||||
|
R_InitParticles (); |
||||
|
R_InitParticleTexture (); |
||||
|
|
||||
|
#ifdef GLTEST |
||||
|
Test_Init (); |
||||
|
#endif |
||||
|
|
||||
|
playertextures = texture_extension_number; |
||||
|
texture_extension_number += 16; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
R_TranslatePlayerSkin |
||||
|
|
||||
|
Translates a skin texture by the per-player color lookup |
||||
|
=============== |
||||
|
*/ |
||||
|
void R_TranslatePlayerSkin (int playernum) |
||||
|
{ |
||||
|
int top, bottom; |
||||
|
byte translate[256]; |
||||
|
unsigned translate32[256]; |
||||
|
int i, j, s; |
||||
|
model_t *model; |
||||
|
aliashdr_t *paliashdr; |
||||
|
byte *original; |
||||
|
unsigned pixels[512*256], *out; |
||||
|
unsigned scaled_width, scaled_height; |
||||
|
int inwidth, inheight; |
||||
|
byte *inrow; |
||||
|
unsigned frac, fracstep; |
||||
|
extern byte **player_8bit_texels_tbl; |
||||
|
|
||||
|
// jkrige - remove multitexture |
||||
|
//GL_DisableMultitexture(); |
||||
|
// jkrige - remove multitexture |
||||
|
|
||||
|
top = cl.scores[playernum].colors & 0xf0; |
||||
|
bottom = (cl.scores[playernum].colors &15)<<4; |
||||
|
|
||||
|
for (i=0 ; i<256 ; i++) |
||||
|
translate[i] = i; |
||||
|
|
||||
|
for (i=0 ; i<16 ; i++) |
||||
|
{ |
||||
|
if (top < 128) // the artists made some backwards ranges. sigh. |
||||
|
translate[TOP_RANGE+i] = top+i; |
||||
|
else |
||||
|
translate[TOP_RANGE+i] = top+15-i; |
||||
|
|
||||
|
if (bottom < 128) |
||||
|
translate[BOTTOM_RANGE+i] = bottom+i; |
||||
|
else |
||||
|
translate[BOTTOM_RANGE+i] = bottom+15-i; |
||||
|
} |
||||
|
|
||||
|
// |
||||
|
// locate the original skin pixels |
||||
|
// |
||||
|
currententity = &cl_entities[1+playernum]; |
||||
|
model = currententity->model; |
||||
|
if (!model) |
||||
|
return; // player doesn't have a model yet |
||||
|
if (model->type != mod_alias) |
||||
|
return; // only translate skins on alias models |
||||
|
|
||||
|
paliashdr = (aliashdr_t *)Mod_Extradata (model); |
||||
|
s = paliashdr->skinwidth * paliashdr->skinheight; |
||||
|
if (currententity->skinnum < 0 || currententity->skinnum >= paliashdr->numskins) { |
||||
|
Con_Printf("(%d): Invalid player skin #%d\n", playernum, currententity->skinnum); |
||||
|
original = (byte *)paliashdr + paliashdr->texels[0]; |
||||
|
} else |
||||
|
original = (byte *)paliashdr + paliashdr->texels[currententity->skinnum]; |
||||
|
if (s & 3) |
||||
|
Sys_Error ("R_TranslateSkin: s&3"); |
||||
|
|
||||
|
inwidth = paliashdr->skinwidth; |
||||
|
inheight = paliashdr->skinheight; |
||||
|
|
||||
|
// because this happens during gameplay, do it fast |
||||
|
// instead of sending it through gl_upload 8 |
||||
|
GL_Bind(playertextures + playernum); |
||||
|
|
||||
|
#if 0 |
||||
|
byte translated[320*200]; |
||||
|
|
||||
|
for (i=0 ; i<s ; i+=4) |
||||
|
{ |
||||
|
translated[i] = translate[original[i]]; |
||||
|
translated[i+1] = translate[original[i+1]]; |
||||
|
translated[i+2] = translate[original[i+2]]; |
||||
|
translated[i+3] = translate[original[i+3]]; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
// don't mipmap these, because it takes too long |
||||
|
GL_Upload8 (translated, paliashdr->skinwidth, paliashdr->skinheight, false, false, true); |
||||
|
#else |
||||
|
scaled_width = gl_max_size.value < 512 ? gl_max_size.value : 512; |
||||
|
scaled_height = gl_max_size.value < 256 ? gl_max_size.value : 256; |
||||
|
|
||||
|
// allow users to crunch sizes down even more if they want |
||||
|
scaled_width >>= (int)gl_playermip.value; |
||||
|
scaled_height >>= (int)gl_playermip.value; |
||||
|
|
||||
|
// jkrige - no 8bit palette extensions |
||||
|
/*if (VID_Is8bit()) { // 8bit texture upload |
||||
|
byte *out2; |
||||
|
|
||||
|
out2 = (byte *)pixels; |
||||
|
memset(pixels, 0, sizeof(pixels)); |
||||
|
fracstep = inwidth*0x10000/scaled_width; |
||||
|
for (i=0 ; i<scaled_height ; i++, out2 += scaled_width) |
||||
|
{ |
||||
|
inrow = original + inwidth*(i*inheight/scaled_height); |
||||
|
frac = fracstep >> 1; |
||||
|
for (j=0 ; j<scaled_width ; j+=4) |
||||
|
{ |
||||
|
out2[j] = translate[inrow[frac>>16]]; |
||||
|
frac += fracstep; |
||||
|
out2[j+1] = translate[inrow[frac>>16]]; |
||||
|
frac += fracstep; |
||||
|
out2[j+2] = translate[inrow[frac>>16]]; |
||||
|
frac += fracstep; |
||||
|
out2[j+3] = translate[inrow[frac>>16]]; |
||||
|
frac += fracstep; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
GL_Upload8_EXT ((byte *)pixels, scaled_width, scaled_height, false, false); |
||||
|
return; |
||||
|
}*/ |
||||
|
// jkrige - no 8bit palette extensions |
||||
|
|
||||
|
for (i=0 ; i<256 ; i++) |
||||
|
translate32[i] = d_8to24table[translate[i]]; |
||||
|
|
||||
|
out = pixels; |
||||
|
fracstep = inwidth*0x10000/scaled_width; |
||||
|
for (i=0 ; i<scaled_height ; i++, out += scaled_width) |
||||
|
{ |
||||
|
inrow = original + inwidth*(i*inheight/scaled_height); |
||||
|
frac = fracstep >> 1; |
||||
|
for (j=0 ; j<scaled_width ; j+=4) |
||||
|
{ |
||||
|
out[j] = translate32[inrow[frac>>16]]; |
||||
|
frac += fracstep; |
||||
|
out[j+1] = translate32[inrow[frac>>16]]; |
||||
|
frac += fracstep; |
||||
|
out[j+2] = translate32[inrow[frac>>16]]; |
||||
|
frac += fracstep; |
||||
|
out[j+3] = translate32[inrow[frac>>16]]; |
||||
|
frac += fracstep; |
||||
|
} |
||||
|
} |
||||
|
glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); |
||||
|
|
||||
|
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); |
||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
||||
|
#endif |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
R_NewMap |
||||
|
=============== |
||||
|
*/ |
||||
|
void R_NewMap (void) |
||||
|
{ |
||||
|
int i; |
||||
|
|
||||
|
for (i=0 ; i<256 ; i++) |
||||
|
d_lightstylevalue[i] = 264; // normal light value |
||||
|
|
||||
|
memset (&r_worldentity, 0, sizeof(r_worldentity)); |
||||
|
r_worldentity.model = cl.worldmodel; |
||||
|
|
||||
|
// clear out efrags in case the level hasn't been reloaded |
||||
|
// FIXME: is this one short? |
||||
|
for (i=0 ; i<cl.worldmodel->numleafs ; i++) |
||||
|
cl.worldmodel->leafs[i].efrags = NULL; |
||||
|
|
||||
|
r_viewleaf = NULL; |
||||
|
R_ClearParticles (); |
||||
|
|
||||
|
GL_BuildLightmaps (); |
||||
|
|
||||
|
// identify sky texture |
||||
|
skytexturenum = -1; |
||||
|
mirrortexturenum = -1; |
||||
|
for (i=0 ; i<cl.worldmodel->numtextures ; i++) |
||||
|
{ |
||||
|
if (!cl.worldmodel->textures[i]) |
||||
|
continue; |
||||
|
if (!Q_strncmp(cl.worldmodel->textures[i]->name,"sky",3) ) |
||||
|
skytexturenum = i; |
||||
|
if (!Q_strncmp(cl.worldmodel->textures[i]->name,"window02_1",10) ) |
||||
|
mirrortexturenum = i; |
||||
|
cl.worldmodel->textures[i]->texturechain = NULL; |
||||
|
} |
||||
|
//#ifdef QUAKE2 // jkrige - skybox |
||||
|
// R_LoadSkys (); |
||||
|
//#endif |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
==================== |
||||
|
R_TimeRefresh_f |
||||
|
|
||||
|
For program optimization |
||||
|
==================== |
||||
|
*/ |
||||
|
void R_TimeRefresh_f (void) |
||||
|
{ |
||||
|
int i; |
||||
|
float start, stop, time; |
||||
|
int startangle; |
||||
|
vrect_t vr; |
||||
|
|
||||
|
glDrawBuffer (GL_FRONT); |
||||
|
glFinish (); |
||||
|
|
||||
|
start = Sys_FloatTime (); |
||||
|
for (i=0 ; i<128 ; i++) |
||||
|
{ |
||||
|
r_refdef.viewangles[1] = i/128.0*360.0; |
||||
|
R_RenderView (); |
||||
|
} |
||||
|
|
||||
|
glFinish (); |
||||
|
stop = Sys_FloatTime (); |
||||
|
time = stop-start; |
||||
|
Con_Printf ("%f seconds (%f fps)\n", time, 128/time); |
||||
|
|
||||
|
glDrawBuffer (GL_BACK); |
||||
|
GL_EndRendering (); |
||||
|
} |
||||
|
|
||||
|
void D_FlushCaches (void) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
|
||||
2230
engine/code/gl_rsurf.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1172
engine/code/gl_screen.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,182 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
#include "quakedef.h" |
||||
|
|
||||
|
#ifdef GLTEST |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
plane_t *plane; |
||||
|
vec3_t origin; |
||||
|
vec3_t normal; |
||||
|
vec3_t up; |
||||
|
vec3_t right; |
||||
|
vec3_t reflect; |
||||
|
float length; |
||||
|
} puff_t; |
||||
|
|
||||
|
#define MAX_PUFFS 64 |
||||
|
|
||||
|
puff_t puffs[MAX_PUFFS]; |
||||
|
|
||||
|
|
||||
|
void Test_Init (void) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
plane_t junk; |
||||
|
plane_t *HitPlane (vec3_t start, vec3_t end) |
||||
|
{ |
||||
|
trace_t trace; |
||||
|
|
||||
|
// fill in a default trace |
||||
|
memset (&trace, 0, sizeof(trace_t)); |
||||
|
trace.fraction = 1; |
||||
|
trace.allsolid = true; |
||||
|
VectorCopy (end, trace.endpos); |
||||
|
|
||||
|
SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &trace); |
||||
|
|
||||
|
junk = trace.plane; |
||||
|
return &junk; |
||||
|
} |
||||
|
|
||||
|
void Test_Spawn (vec3_t origin) |
||||
|
{ |
||||
|
int i; |
||||
|
puff_t *p; |
||||
|
vec3_t temp; |
||||
|
vec3_t normal; |
||||
|
vec3_t incoming; |
||||
|
plane_t *plane; |
||||
|
float d; |
||||
|
|
||||
|
for (i=0,p=puffs ; i<MAX_PUFFS ; i++,p++) |
||||
|
{ |
||||
|
if (p->length <= 0) |
||||
|
break; |
||||
|
} |
||||
|
if (i == MAX_PUFFS) |
||||
|
return; |
||||
|
|
||||
|
VectorSubtract (r_refdef.vieworg, origin, incoming); |
||||
|
VectorSubtract (origin, incoming, temp); |
||||
|
plane = HitPlane (r_refdef.vieworg, temp); |
||||
|
|
||||
|
VectorNormalize (incoming); |
||||
|
d = DotProduct (incoming, plane->normal); |
||||
|
VectorSubtract (vec3_origin, incoming, p->reflect); |
||||
|
VectorMA (p->reflect, d*2, plane->normal, p->reflect); |
||||
|
|
||||
|
VectorCopy (origin, p->origin); |
||||
|
VectorCopy (plane->normal, p->normal); |
||||
|
|
||||
|
CrossProduct (incoming, p->normal, p->up); |
||||
|
|
||||
|
CrossProduct (p->up, p->normal, p->right); |
||||
|
|
||||
|
p->length = 8; |
||||
|
} |
||||
|
|
||||
|
void DrawPuff (puff_t *p) |
||||
|
{ |
||||
|
vec3_t pts[2][3]; |
||||
|
int i, j; |
||||
|
float s, d; |
||||
|
|
||||
|
for (i=0 ; i<2 ; i++) |
||||
|
{ |
||||
|
if (i == 1) |
||||
|
{ |
||||
|
s = 6; |
||||
|
d = p->length; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
s = 2; |
||||
|
d = 0; |
||||
|
} |
||||
|
|
||||
|
for (j=0 ; j<3 ; j++) |
||||
|
{ |
||||
|
pts[i][0][j] = p->origin[j] + p->up[j]*s + p->reflect[j]*d; |
||||
|
pts[i][1][j] = p->origin[j] + p->right[j]*s + p->reflect[j]*d; |
||||
|
pts[i][2][j] = p->origin[j] + -p->right[j]*s + p->reflect[j]*d; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
glColor3f (1, 0, 0); |
||||
|
|
||||
|
#if 0 |
||||
|
glBegin (GL_LINES); |
||||
|
glVertex3fv (p->origin); |
||||
|
glVertex3f (p->origin[0] + p->length*p->reflect[0], |
||||
|
p->origin[1] + p->length*p->reflect[1], |
||||
|
p->origin[2] + p->length*p->reflect[2]); |
||||
|
|
||||
|
glVertex3fv (pts[0][0]); |
||||
|
glVertex3fv (pts[1][0]); |
||||
|
|
||||
|
glVertex3fv (pts[0][1]); |
||||
|
glVertex3fv (pts[1][1]); |
||||
|
|
||||
|
glVertex3fv (pts[0][2]); |
||||
|
glVertex3fv (pts[1][2]); |
||||
|
|
||||
|
glEnd (); |
||||
|
#endif |
||||
|
|
||||
|
glBegin (GL_QUADS); |
||||
|
for (i=0 ; i<3 ; i++) |
||||
|
{ |
||||
|
j = (i+1)%3; |
||||
|
glVertex3fv (pts[0][j]); |
||||
|
glVertex3fv (pts[1][j]); |
||||
|
glVertex3fv (pts[1][i]); |
||||
|
glVertex3fv (pts[0][i]); |
||||
|
} |
||||
|
glEnd (); |
||||
|
|
||||
|
glBegin (GL_TRIANGLES); |
||||
|
glVertex3fv (pts[1][0]); |
||||
|
glVertex3fv (pts[1][1]); |
||||
|
glVertex3fv (pts[1][2]); |
||||
|
glEnd (); |
||||
|
|
||||
|
p->length -= host_frametime*2; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void Test_Draw (void) |
||||
|
{ |
||||
|
int i; |
||||
|
puff_t *p; |
||||
|
|
||||
|
for (i=0, p=puffs ; i<MAX_PUFFS ; i++,p++) |
||||
|
{ |
||||
|
if (p->length > 0) |
||||
|
DrawPuff (p); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#endif |
||||
2260
engine/code/gl_vidnt.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1182
engine/code/gl_warp.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,51 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
0, 0.19633, 0.392541, 0.588517, 0.784137, 0.979285, 1.17384, 1.3677, |
||||
|
1.56072, 1.75281, 1.94384, 2.1337, 2.32228, 2.50945, 2.69512, 2.87916, |
||||
|
3.06147, 3.24193, 3.42044, 3.59689, 3.77117, 3.94319, 4.11282, 4.27998, |
||||
|
4.44456, 4.60647, 4.76559, 4.92185, 5.07515, 5.22538, 5.37247, 5.51632, |
||||
|
5.65685, 5.79398, 5.92761, 6.05767, 6.18408, 6.30677, 6.42566, 6.54068, |
||||
|
6.65176, 6.75883, 6.86183, 6.9607, 7.05537, 7.14579, 7.23191, 7.31368, |
||||
|
7.39104, 7.46394, 7.53235, 7.59623, 7.65552, 7.71021, 7.76025, 7.80562, |
||||
|
7.84628, 7.88222, 7.91341, 7.93984, 7.96148, 7.97832, 7.99036, 7.99759, |
||||
|
8, 7.99759, 7.99036, 7.97832, 7.96148, 7.93984, 7.91341, 7.88222, |
||||
|
7.84628, 7.80562, 7.76025, 7.71021, 7.65552, 7.59623, 7.53235, 7.46394, |
||||
|
7.39104, 7.31368, 7.23191, 7.14579, 7.05537, 6.9607, 6.86183, 6.75883, |
||||
|
6.65176, 6.54068, 6.42566, 6.30677, 6.18408, 6.05767, 5.92761, 5.79398, |
||||
|
5.65685, 5.51632, 5.37247, 5.22538, 5.07515, 4.92185, 4.76559, 4.60647, |
||||
|
4.44456, 4.27998, 4.11282, 3.94319, 3.77117, 3.59689, 3.42044, 3.24193, |
||||
|
3.06147, 2.87916, 2.69512, 2.50945, 2.32228, 2.1337, 1.94384, 1.75281, |
||||
|
1.56072, 1.3677, 1.17384, 0.979285, 0.784137, 0.588517, 0.392541, 0.19633, |
||||
|
9.79717e-16, -0.19633, -0.392541, -0.588517, -0.784137, -0.979285, -1.17384, -1.3677, |
||||
|
-1.56072, -1.75281, -1.94384, -2.1337, -2.32228, -2.50945, -2.69512, -2.87916, |
||||
|
-3.06147, -3.24193, -3.42044, -3.59689, -3.77117, -3.94319, -4.11282, -4.27998, |
||||
|
-4.44456, -4.60647, -4.76559, -4.92185, -5.07515, -5.22538, -5.37247, -5.51632, |
||||
|
-5.65685, -5.79398, -5.92761, -6.05767, -6.18408, -6.30677, -6.42566, -6.54068, |
||||
|
-6.65176, -6.75883, -6.86183, -6.9607, -7.05537, -7.14579, -7.23191, -7.31368, |
||||
|
-7.39104, -7.46394, -7.53235, -7.59623, -7.65552, -7.71021, -7.76025, -7.80562, |
||||
|
-7.84628, -7.88222, -7.91341, -7.93984, -7.96148, -7.97832, -7.99036, -7.99759, |
||||
|
-8, -7.99759, -7.99036, -7.97832, -7.96148, -7.93984, -7.91341, -7.88222, |
||||
|
-7.84628, -7.80562, -7.76025, -7.71021, -7.65552, -7.59623, -7.53235, -7.46394, |
||||
|
-7.39104, -7.31368, -7.23191, -7.14579, -7.05537, -6.9607, -6.86183, -6.75883, |
||||
|
-6.65176, -6.54068, -6.42566, -6.30677, -6.18408, -6.05767, -5.92761, -5.79398, |
||||
|
-5.65685, -5.51632, -5.37247, -5.22538, -5.07515, -4.92185, -4.76559, -4.60647, |
||||
|
-4.44456, -4.27998, -4.11282, -3.94319, -3.77117, -3.59689, -3.42044, -3.24193, |
||||
|
-3.06147, -2.87916, -2.69512, -2.50945, -2.32228, -2.1337, -1.94384, -1.75281, |
||||
|
-1.56072, -1.3677, -1.17384, -0.979285, -0.784137, -0.588517, -0.392541, -0.19633, |
||||
12050
engine/code/glext.h
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,171 @@ |
|||||
|
Glquake v0.99, Quake v1.09 release notes |
||||
|
|
||||
|
3dfx owners -- read the 3dfx.txt file. |
||||
|
|
||||
|
On a standard OpenGL system, all you should need to do to run glquake is put |
||||
|
glquake.exe in your quake directory, and run it from there. DO NOT install |
||||
|
the opengl32.dll unless you have a 3dfx! Glquake should change the screen |
||||
|
resolution to 640*480*32k colors and run full screen by default. |
||||
|
|
||||
|
If you are running win-95, your desktop must be set to 32k or 64k colors |
||||
|
before running glquake. NT can switch automatically. |
||||
|
|
||||
|
Theoretically, glquake will run on any compliant OpenGL that supports the |
||||
|
texture objects extensions, but unless it is very powerfull hardware that |
||||
|
accelerates everything needed, the game play will not be acceptable. If it |
||||
|
has to go through any software emulation paths, the performance will likely |
||||
|
by well under one frame per second. |
||||
|
|
||||
|
3dfx has provided an opengl32.dll that implements everything glquake needs, |
||||
|
but it is not a full opengl implementation. Other opengl applications are |
||||
|
very unlikely to work with it, so consider it basically a "glquake driver". |
||||
|
See the encluded 3dfx.txt for specific instalation notes. 3dfx can only run |
||||
|
full screen, but you must still have your desktop set to a 16 bit color mode |
||||
|
for glquake to start. |
||||
|
|
||||
|
resolution options |
||||
|
------------------ |
||||
|
We had dynamic resolution changing in glquake for a while, but every single |
||||
|
opengl driver I tried it on messed up in one way or another, so it is now |
||||
|
limited to startup time only. |
||||
|
|
||||
|
glquake -window |
||||
|
This will start glquake in a window on your desktop instead of switching the |
||||
|
screen to lower resolution and covering everything. |
||||
|
|
||||
|
glquake -width 800 -height 600 |
||||
|
Tries to run glquake at the specified resolution. Combined with -window, it |
||||
|
creates a desktop window that size, otherwise it tries to set a full screen |
||||
|
resolution. |
||||
|
|
||||
|
You can also specify the resolution of the console independant of the screen |
||||
|
resolution. |
||||
|
|
||||
|
glquake -conwidth 320 |
||||
|
This will specify a console resolution of 320 by 240 (the height is |
||||
|
automatically determined by the default 4:3 aspect ratio, you can also |
||||
|
specify the height directly with -conheight). |
||||
|
|
||||
|
In higher resolution modes such as 800x600 and 1024x768, glquake will default |
||||
|
to a 640x480 console, since the font becomes small enough at higher |
||||
|
resolutions to become unreadable. If do you wish to have a higher resolution |
||||
|
console and status bar, specify it as well, such as: |
||||
|
glquake -width 800 -height 600 -conwidth 800 |
||||
|
|
||||
|
texture options |
||||
|
--------------- |
||||
|
The amount of textures used in the game can have a large impact on performance. |
||||
|
There are several options that let you trade off visual quality for better |
||||
|
performance. |
||||
|
|
||||
|
There is no way to flush already loaded textures, so it is best to change |
||||
|
these options on the command line, or they will only take effect on some of |
||||
|
the textures when you change levels. |
||||
|
|
||||
|
OpenGL only allows textures to repeat on power of two boundaries (32, 64, |
||||
|
128, etc), but software quake had a number of textures that repeated at 24 |
||||
|
or 96 pixel boundaries. These need to be either stretched out to the next |
||||
|
higher size, or shrunk down to the next lower. By default, they are filtered |
||||
|
down to the smaller size, but you can cause it to use the larger size if you |
||||
|
really want by using: |
||||
|
|
||||
|
glquake +gl_round_down 0 |
||||
|
This will generally run well on a normal 4 MB 3dfx card, but for other cards |
||||
|
that have either worse texture management or slower texture swapping speeds, |
||||
|
there are some additional settings that can drastically lower the amount of |
||||
|
textures to be managed. |
||||
|
|
||||
|
glquake +gl_picmip 1 |
||||
|
This causes all textures to have one half the dimensions they otherwise would. |
||||
|
This makes them blurry, but very small. You can set this to 2 to make the |
||||
|
textures one quarter the resolution on each axis for REALLY blurry textures. |
||||
|
|
||||
|
glquake +gl_playermip 1 |
||||
|
This is similar to picmip, but is only used for other players in deathmatch. |
||||
|
Each player in a deathmatch requires an individual skin texture, so this can |
||||
|
be a serious problem for texture management. It wouldn't be unreasonable to |
||||
|
set this to 2 or even 3 if you are playing competatively (and don't care if |
||||
|
the other guys have smudged skins). If you change this during the game, it |
||||
|
will take effect as soon as a player changes their skin colors. |
||||
|
|
||||
|
GLQuake also supports the following extensions for faster texture operation: |
||||
|
|
||||
|
GL_SGIS_multitexture |
||||
|
Multitextures support allows certain hardware to render the world in one |
||||
|
pass instead of two. GLQuake uses two passes, one for the world textures |
||||
|
and the second for the lightmaps that are blended on the textures. On some |
||||
|
hardware, with a GL_SIGS_multitexture supported OpenGL implementation, this |
||||
|
can be done in one pass. On hardware that supports this, you will get a |
||||
|
60% to 100% increase in frame rate. Currently, only 3DFX dual TMU cards |
||||
|
(such as the Obsidian 2220) support this extension, but other hardware will |
||||
|
soon follow. |
||||
|
|
||||
|
This extension will be autodetected and used. If for some reason it is not |
||||
|
working correctly, specify the command line option "-nomtex" to disable it. |
||||
|
|
||||
|
GL_EXT_shared_texture_palette |
||||
|
GLQuake uses 16bit textures by default but on OpenGL implementations |
||||
|
that support the GL_EXT_shared_texture_palette extension, GLQuake will use |
||||
|
8bit textures instead. This results in using half the needed texture memory |
||||
|
of 16bit texture and can improve performance. This is very little difference |
||||
|
in visual quality due to the fact that the textures are 8bit sources to |
||||
|
begin with. |
||||
|
|
||||
|
run time options |
||||
|
---------------- |
||||
|
At the console, you can set these values to effect drawing. |
||||
|
|
||||
|
gl_texturemode GL_NEAREST |
||||
|
Sets texture mapping to point sampled, which may be faster on some GL systems |
||||
|
(not on 3dfx). |
||||
|
|
||||
|
gl_texturemode GL_LINEAR_MIPMAP |
||||
|
This is the default texture mode. |
||||
|
|
||||
|
gl_texturemode GL_LINEAR_MIPMAP_LINEAR |
||||
|
This is the highest quality texture mapping (trilinear), but only very high |
||||
|
end hardware (intergraph intense 3D / realizm) supports it. Not that big of |
||||
|
a deal, actually. |
||||
|
|
||||
|
gl_finish 0 |
||||
|
This causes the game to not issue a glFinish() call each frame, which may make |
||||
|
some hardware run faster. If this is cleared, the 3dfx will back up a number |
||||
|
of frames and not be very playable. |
||||
|
|
||||
|
gl_flashblend 0 |
||||
|
By default, glquake just draws a shaded ball around objects that are emiting |
||||
|
light. Clearing this variable will cause it to properly relight the world |
||||
|
like normal quake, but it can be a significant speed hit on some systems. |
||||
|
|
||||
|
gl_ztrick 0 |
||||
|
Glquake uses a buffering method that avoids clearing the Z buffer, but some |
||||
|
hardware platforms don't like it. If the status bar and console are flashing |
||||
|
every other frame, clear this variable. |
||||
|
|
||||
|
gl_keeptjunctions 0 |
||||
|
If you clear this, glquake will remove colinear vertexes when it reloads the |
||||
|
level. This can give a few percent speedup, but it can leave a couple stray |
||||
|
blinking pixels on the screen. |
||||
|
|
||||
|
novelty features |
||||
|
---------------- |
||||
|
These are some rendering tricks that were easy to do in glquake. They aren't |
||||
|
very robust, but they are pretty cool to look at. |
||||
|
|
||||
|
r_shadows 1 |
||||
|
This causes every object to cast a shadow. |
||||
|
|
||||
|
r_wateralpha 0.7 |
||||
|
This sets the opacity of water textures, so you can see through it in properly |
||||
|
processed maps. 0.3 is very faint, almost like fog. 1 is completely solid |
||||
|
(the default). Unfortunately, the standard quake maps don't contain any |
||||
|
visibility information for seeing past water surfaces, so you can't just play |
||||
|
quake with this turned on. If you just want to see what it looks like, you |
||||
|
can set "r_novis 1", but that will make things go very slow. When I get a |
||||
|
chance, I will probably release some maps that have been processed properly |
||||
|
for this. |
||||
|
|
||||
|
r_mirroralpha 0.3 |
||||
|
This changes one particular texture (the stained glass texture in the EASY |
||||
|
start hall) into a mirror. The value is the opacity of the mirror surface. |
||||
|
|
||||
@ -0,0 +1,358 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// disable data conversion warnings |
||||
|
|
||||
|
#pragma warning(disable : 4244) // MIPS |
||||
|
#pragma warning(disable : 4136) // X86 |
||||
|
#pragma warning(disable : 4051) // ALPHA |
||||
|
|
||||
|
#ifdef _WIN32 |
||||
|
#include <windows.h> |
||||
|
#endif |
||||
|
|
||||
|
#include <GL/gl.h> |
||||
|
#include <GL/glu.h> |
||||
|
|
||||
|
#include "glext.h" // jkrige - opengl extensions |
||||
|
#include "wglext.h" // jkrige - windows opengl extensions |
||||
|
|
||||
|
|
||||
|
void GL_BeginRendering (int *x, int *y, int *width, int *height); |
||||
|
void GL_EndRendering (void); |
||||
|
|
||||
|
|
||||
|
#ifdef _WIN32 |
||||
|
// Function prototypes for the Texture Object Extension routines |
||||
|
typedef GLboolean (APIENTRY *ARETEXRESFUNCPTR)(GLsizei, const GLuint *, |
||||
|
const GLboolean *); |
||||
|
typedef void (APIENTRY *BINDTEXFUNCPTR)(GLenum, GLuint); |
||||
|
typedef void (APIENTRY *DELTEXFUNCPTR)(GLsizei, const GLuint *); |
||||
|
typedef void (APIENTRY *GENTEXFUNCPTR)(GLsizei, GLuint *); |
||||
|
typedef GLboolean (APIENTRY *ISTEXFUNCPTR)(GLuint); |
||||
|
typedef void (APIENTRY *PRIORTEXFUNCPTR)(GLsizei, const GLuint *, |
||||
|
const GLclampf *); |
||||
|
typedef void (APIENTRY *TEXSUBIMAGEPTR)(int, int, int, int, int, int, int, int, void *); |
||||
|
|
||||
|
extern BINDTEXFUNCPTR bindTexFunc; |
||||
|
extern DELTEXFUNCPTR delTexFunc; |
||||
|
extern TEXSUBIMAGEPTR TexSubImage2DFunc; |
||||
|
#endif |
||||
|
|
||||
|
|
||||
|
// jkrige - moved to glquake.h |
||||
|
typedef struct |
||||
|
{ |
||||
|
int texnum; |
||||
|
|
||||
|
qboolean tex_luma; // jkrige - luma textures |
||||
|
qboolean tex_luma8bit; // jkrige - fullbright pixels |
||||
|
|
||||
|
char identifier[64]; |
||||
|
int width, height; |
||||
|
qboolean mipmap; |
||||
|
int lhcsum; // jkrige - memleak & texture mismatch |
||||
|
} gltexture_t; |
||||
|
|
||||
|
//#define MAX_GLTEXTURES 2048 |
||||
|
#define MAX_GLTEXTURES 4096 // jkrige - increased maximum number of opengl textures |
||||
|
// jkrige - moved to glquake.h |
||||
|
|
||||
|
|
||||
|
extern gltexture_t gltextures[MAX_GLTEXTURES]; |
||||
|
extern int numgltextures; |
||||
|
|
||||
|
// jkrige - luma textures |
||||
|
#define JK_LUMA_TEX (MAX_GLTEXTURES) |
||||
|
// jkrige - luma textures |
||||
|
|
||||
|
extern int texture_extension_number; |
||||
|
extern int texture_mode; |
||||
|
|
||||
|
extern float gldepthmin, gldepthmax; |
||||
|
|
||||
|
|
||||
|
// jkrige - gamma |
||||
|
extern BOOL ( WINAPI * qwglGetDeviceGammaRamp3DFX)( HDC, LPVOID ); |
||||
|
extern BOOL ( WINAPI * qwglSetDeviceGammaRamp3DFX)( HDC, LPVOID ); |
||||
|
// jkrige - gamma |
||||
|
|
||||
|
|
||||
|
// jkrige - anisotropic filtering |
||||
|
extern qboolean anisotropic_ext; |
||||
|
extern float maximumAnisotrophy; |
||||
|
// jkrige - anisotropic filtering |
||||
|
|
||||
|
|
||||
|
// jkrige - non power of two |
||||
|
extern qboolean npow2_ext; |
||||
|
// jkrige - non power of two |
||||
|
|
||||
|
|
||||
|
void GL_Upload32 (unsigned *data, int width, int height, qboolean mipmap, qboolean alpha); |
||||
|
void GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean alpha); |
||||
|
|
||||
|
// jkrige - bytesperpixel |
||||
|
//int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha); |
||||
|
int GL_LoadTexture (char *identifier, char *textype, int width, int height, byte *data, int mipmap, int alpha, int bytesperpixel); |
||||
|
// jkrige - bytesperpixel |
||||
|
|
||||
|
int GL_FindTexture (char *identifier); |
||||
|
|
||||
|
// jkrige - .lit colored lights |
||||
|
void GL_SetupLightmapFmt (qboolean check_cmdline); |
||||
|
// jkrige - .lit colored lights |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
float x, y, z; |
||||
|
float s, t; |
||||
|
float r, g, b; |
||||
|
} glvert_t; |
||||
|
|
||||
|
extern glvert_t glv; |
||||
|
|
||||
|
extern int glx, gly, glwidth, glheight; |
||||
|
|
||||
|
// jkrige - opengl extensions |
||||
|
//#ifdef _WIN32 |
||||
|
//extern PROC glArrayElementEXT; |
||||
|
//extern PROC glColorPointerEXT; |
||||
|
//extern PROC glTexturePointerEXT; |
||||
|
//extern PROC glVertexPointerEXT; |
||||
|
//#endif |
||||
|
// jkrige - opengl extensions |
||||
|
|
||||
|
// r_local.h -- private refresh defs |
||||
|
|
||||
|
#define ALIAS_BASE_SIZE_RATIO (1.0 / 11.0) |
||||
|
// normalizing factor so player model works out to about |
||||
|
// 1 pixel per triangle |
||||
|
#define MAX_LBM_HEIGHT 480 |
||||
|
|
||||
|
#define TILE_SIZE 128 // size of textures generated by R_GenTiledSurf |
||||
|
|
||||
|
#define SKYSHIFT 7 |
||||
|
#define SKYSIZE (1 << SKYSHIFT) |
||||
|
#define SKYMASK (SKYSIZE - 1) |
||||
|
|
||||
|
#define BACKFACE_EPSILON 0.01 |
||||
|
|
||||
|
|
||||
|
void R_TimeRefresh_f (void); |
||||
|
void R_ReadPointFile_f (void); |
||||
|
texture_t *R_TextureAnimation (texture_t *base); |
||||
|
|
||||
|
typedef struct surfcache_s |
||||
|
{ |
||||
|
struct surfcache_s *next; |
||||
|
struct surfcache_s **owner; // NULL is an empty chunk of memory |
||||
|
int lightadj[MAXLIGHTMAPS]; // checked for strobe flush |
||||
|
int dlight; |
||||
|
int size; // including header |
||||
|
unsigned width; |
||||
|
unsigned height; // DEBUG only needed for debug |
||||
|
float mipscale; |
||||
|
struct texture_s *texture; // checked for animating textures |
||||
|
byte data[4]; // width*height elements |
||||
|
} surfcache_t; |
||||
|
|
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
pixel_t *surfdat; // destination for generated surface |
||||
|
int rowbytes; // destination logical width in bytes |
||||
|
msurface_t *surf; // description for surface to generate |
||||
|
fixed8_t lightadj[MAXLIGHTMAPS]; |
||||
|
// adjust for lightmap levels for dynamic lighting |
||||
|
texture_t *texture; // corrected for animating textures |
||||
|
int surfmip; // mipmapped ratio of surface texels / world pixels |
||||
|
int surfwidth; // in mipmapped texels |
||||
|
int surfheight; // in mipmapped texels |
||||
|
} drawsurf_t; |
||||
|
|
||||
|
|
||||
|
typedef enum { |
||||
|
pt_static, pt_grav, pt_slowgrav, pt_fire, pt_explode, pt_explode2, pt_blob, pt_blob2 |
||||
|
} ptype_t; |
||||
|
|
||||
|
// !!! if this is changed, it must be changed in d_ifacea.h too !!! |
||||
|
typedef struct particle_s |
||||
|
{ |
||||
|
// driver-usable fields |
||||
|
vec3_t org; |
||||
|
float color; |
||||
|
// drivers never touch the following fields |
||||
|
struct particle_s *next; |
||||
|
vec3_t vel; |
||||
|
float ramp; |
||||
|
float die; |
||||
|
ptype_t type; |
||||
|
} particle_t; |
||||
|
|
||||
|
|
||||
|
//==================================================== |
||||
|
|
||||
|
|
||||
|
extern entity_t r_worldentity; |
||||
|
extern qboolean r_cache_thrash; // compatability |
||||
|
extern vec3_t modelorg, r_entorigin; |
||||
|
extern entity_t *currententity; |
||||
|
extern int r_visframecount; // ??? what difs? |
||||
|
extern int r_framecount; |
||||
|
extern mplane_t frustum[4]; |
||||
|
extern int c_brush_polys, c_alias_polys; |
||||
|
|
||||
|
|
||||
|
// |
||||
|
// view origin |
||||
|
// |
||||
|
extern vec3_t vup; |
||||
|
extern vec3_t vpn; |
||||
|
extern vec3_t vright; |
||||
|
extern vec3_t r_origin; |
||||
|
|
||||
|
// |
||||
|
// screen size info |
||||
|
// |
||||
|
extern refdef_t r_refdef; |
||||
|
extern mleaf_t *r_viewleaf, *r_oldviewleaf; |
||||
|
extern texture_t *r_notexture_mip; |
||||
|
extern int d_lightstylevalue[256]; // 8.8 fraction of base light value |
||||
|
|
||||
|
extern qboolean envmap; |
||||
|
extern int currenttexture; |
||||
|
extern int cnttextures[2]; |
||||
|
|
||||
|
// jkrige - texture mode |
||||
|
extern int particletexture_linear; |
||||
|
extern int particletexture_point; |
||||
|
// jkrige - texture mode |
||||
|
|
||||
|
extern int playertextures; |
||||
|
|
||||
|
extern int skytexturenum; // index in cl.loadmodel, not gl texture object |
||||
|
|
||||
|
extern cvar_t r_norefresh; |
||||
|
extern cvar_t r_drawentities; |
||||
|
extern cvar_t r_drawworld; |
||||
|
extern cvar_t r_drawviewmodel; |
||||
|
extern cvar_t r_speeds; |
||||
|
extern cvar_t r_waterwarp; |
||||
|
extern cvar_t r_fullbright; |
||||
|
extern cvar_t r_lightmap; |
||||
|
//extern cvar_t r_shadows; // jkrige - removed alias shadows |
||||
|
extern cvar_t r_mirroralpha; |
||||
|
extern cvar_t r_wateralpha; |
||||
|
extern cvar_t r_dynamic; |
||||
|
extern cvar_t r_novis; |
||||
|
|
||||
|
// jkrige - fix dynamic light shine through |
||||
|
extern cvar_t r_dynamic_sidemark; |
||||
|
// jkrige - fix dynamic light shine through |
||||
|
|
||||
|
extern cvar_t gl_clear; |
||||
|
extern cvar_t gl_cull; |
||||
|
extern cvar_t gl_poly; |
||||
|
extern cvar_t gl_texsort; |
||||
|
extern cvar_t gl_smoothmodels; |
||||
|
extern cvar_t gl_affinemodels; |
||||
|
extern cvar_t gl_polyblend; |
||||
|
|
||||
|
// jkrige - disabled tjunction removal |
||||
|
//extern cvar_t gl_keeptjunctions; |
||||
|
//extern cvar_t gl_reporttjunctions; |
||||
|
// jkrige - disabled tjunction removal |
||||
|
|
||||
|
// jkrige - flashblend removal |
||||
|
//extern cvar_t gl_flashblend; |
||||
|
// jkrige - flashblend removal |
||||
|
|
||||
|
extern cvar_t gl_nocolors; |
||||
|
extern cvar_t gl_skytype; // jkrige - skybox |
||||
|
extern cvar_t gl_doubleeyes; |
||||
|
|
||||
|
// jkrige - .lit colored lights |
||||
|
extern int gl_coloredstatic; |
||||
|
// jkrige - .lit colored lights |
||||
|
|
||||
|
extern int gl_lightmap_format; |
||||
|
extern int gl_solid_format; |
||||
|
extern int gl_alpha_format; |
||||
|
|
||||
|
extern cvar_t gl_max_size; |
||||
|
extern cvar_t gl_playermip; |
||||
|
|
||||
|
// jkrige - texture mode |
||||
|
extern cvar_t gl_texturemode; |
||||
|
// jkrige - texture mode |
||||
|
|
||||
|
// jkrige - wireframe |
||||
|
extern cvar_t gl_wireframe; |
||||
|
// jkrige - wireframe |
||||
|
|
||||
|
// jkrige - .lit colored lights |
||||
|
extern cvar_t gl_coloredlight; |
||||
|
extern cvar_t gl_lightmapfmt; |
||||
|
// jkrige - .lit colored lights |
||||
|
|
||||
|
// jkrige - luma textures |
||||
|
extern cvar_t gl_lumatex_render; |
||||
|
// jkrige - luma textures |
||||
|
|
||||
|
|
||||
|
extern int mirrortexturenum; // quake texturenum, not gltexturenum |
||||
|
extern qboolean mirror; |
||||
|
extern mplane_t *mirror_plane; |
||||
|
|
||||
|
extern float r_world_matrix[16]; |
||||
|
|
||||
|
extern const char *gl_vendor; |
||||
|
extern const char *gl_renderer; |
||||
|
extern const char *gl_version; |
||||
|
extern const char *gl_extensions; |
||||
|
|
||||
|
void R_TranslatePlayerSkin (int playernum); |
||||
|
void GL_Bind (int texnum); |
||||
|
|
||||
|
// Multitexture |
||||
|
// jkrige - remove multitexture |
||||
|
//#define TEXTURE0_SGIS 0x835E |
||||
|
//#define TEXTURE1_SGIS 0x835F |
||||
|
// jkrige - remove multitexture |
||||
|
|
||||
|
#ifndef _WIN32 |
||||
|
#define APIENTRY /* */ |
||||
|
#endif |
||||
|
|
||||
|
// jkrige - overbrights |
||||
|
extern cvar_t gl_overbright; |
||||
|
// jkrige - overbrights |
||||
|
|
||||
|
// jkrige - remove multitexture |
||||
|
/*typedef void (APIENTRY *lpMTexFUNC) (GLenum, GLfloat, GLfloat); |
||||
|
typedef void (APIENTRY *lpSelTexFUNC) (GLenum); |
||||
|
extern lpMTexFUNC qglMTexCoord2fSGIS; |
||||
|
extern lpSelTexFUNC qglSelectTextureSGIS; |
||||
|
|
||||
|
extern qboolean gl_mtexable; |
||||
|
|
||||
|
void GL_DisableMultitexture(void); |
||||
|
void GL_EnableMultitexture(void);*/ |
||||
|
// jkrige - remove multitexture |
||||
1040
engine/code/host.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1935
engine/code/host_cmd.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1293
engine/code/in_win.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,34 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// input.h -- external (non-keyboard) input devices |
||||
|
|
||||
|
void IN_Init (void); |
||||
|
|
||||
|
void IN_Shutdown (void); |
||||
|
|
||||
|
void IN_Commands (void); |
||||
|
// oportunity for devices to stick commands on the script buffer |
||||
|
|
||||
|
void IN_Move (usercmd_t *cmd); |
||||
|
// add additional movement on top of the keyboard move cmd |
||||
|
|
||||
|
void IN_ClearStates (void); |
||||
|
// restores all button and position states to defaults |
||||
|
|
||||
@ -0,0 +1,763 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
#include "quakedef.h" |
||||
|
|
||||
|
/* |
||||
|
|
||||
|
key up events are sent even if in console mode |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
#define MAXCMDLINE 256 |
||||
|
char key_lines[32][MAXCMDLINE]; |
||||
|
int key_linepos; |
||||
|
int shift_down=false; |
||||
|
int key_lastpress; |
||||
|
|
||||
|
int edit_line=0; |
||||
|
int history_line=0; |
||||
|
|
||||
|
keydest_t key_dest; |
||||
|
|
||||
|
int key_count; // incremented every key event |
||||
|
|
||||
|
char *keybindings[256]; |
||||
|
qboolean consolekeys[256]; // if true, can't be rebound while in console |
||||
|
qboolean menubound[256]; // if true, can't be rebound while in menu |
||||
|
int keyshift[256]; // key to map to if shift held down in console |
||||
|
int key_repeats[256]; // if > 1, it is autorepeating |
||||
|
qboolean keydown[256]; |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
char *name; |
||||
|
int keynum; |
||||
|
} keyname_t; |
||||
|
|
||||
|
keyname_t keynames[] = |
||||
|
{ |
||||
|
{"TAB", K_TAB}, |
||||
|
{"ENTER", K_ENTER}, |
||||
|
{"ESCAPE", K_ESCAPE}, |
||||
|
{"SPACE", K_SPACE}, |
||||
|
{"BACKSPACE", K_BACKSPACE}, |
||||
|
{"UPARROW", K_UPARROW}, |
||||
|
{"DOWNARROW", K_DOWNARROW}, |
||||
|
{"LEFTARROW", K_LEFTARROW}, |
||||
|
{"RIGHTARROW", K_RIGHTARROW}, |
||||
|
|
||||
|
{"ALT", K_ALT}, |
||||
|
{"CTRL", K_CTRL}, |
||||
|
{"SHIFT", K_SHIFT}, |
||||
|
|
||||
|
{"F1", K_F1}, |
||||
|
{"F2", K_F2}, |
||||
|
{"F3", K_F3}, |
||||
|
{"F4", K_F4}, |
||||
|
{"F5", K_F5}, |
||||
|
{"F6", K_F6}, |
||||
|
{"F7", K_F7}, |
||||
|
{"F8", K_F8}, |
||||
|
{"F9", K_F9}, |
||||
|
{"F10", K_F10}, |
||||
|
{"F11", K_F11}, |
||||
|
{"F12", K_F12}, |
||||
|
|
||||
|
{"INS", K_INS}, |
||||
|
{"DEL", K_DEL}, |
||||
|
{"PGDN", K_PGDN}, |
||||
|
{"PGUP", K_PGUP}, |
||||
|
{"HOME", K_HOME}, |
||||
|
{"END", K_END}, |
||||
|
|
||||
|
{"MOUSE1", K_MOUSE1}, |
||||
|
{"MOUSE2", K_MOUSE2}, |
||||
|
{"MOUSE3", K_MOUSE3}, |
||||
|
|
||||
|
{"JOY1", K_JOY1}, |
||||
|
{"JOY2", K_JOY2}, |
||||
|
{"JOY3", K_JOY3}, |
||||
|
{"JOY4", K_JOY4}, |
||||
|
|
||||
|
{"AUX1", K_AUX1}, |
||||
|
{"AUX2", K_AUX2}, |
||||
|
{"AUX3", K_AUX3}, |
||||
|
{"AUX4", K_AUX4}, |
||||
|
{"AUX5", K_AUX5}, |
||||
|
{"AUX6", K_AUX6}, |
||||
|
{"AUX7", K_AUX7}, |
||||
|
{"AUX8", K_AUX8}, |
||||
|
{"AUX9", K_AUX9}, |
||||
|
{"AUX10", K_AUX10}, |
||||
|
{"AUX11", K_AUX11}, |
||||
|
{"AUX12", K_AUX12}, |
||||
|
{"AUX13", K_AUX13}, |
||||
|
{"AUX14", K_AUX14}, |
||||
|
{"AUX15", K_AUX15}, |
||||
|
{"AUX16", K_AUX16}, |
||||
|
{"AUX17", K_AUX17}, |
||||
|
{"AUX18", K_AUX18}, |
||||
|
{"AUX19", K_AUX19}, |
||||
|
{"AUX20", K_AUX20}, |
||||
|
{"AUX21", K_AUX21}, |
||||
|
{"AUX22", K_AUX22}, |
||||
|
{"AUX23", K_AUX23}, |
||||
|
{"AUX24", K_AUX24}, |
||||
|
{"AUX25", K_AUX25}, |
||||
|
{"AUX26", K_AUX26}, |
||||
|
{"AUX27", K_AUX27}, |
||||
|
{"AUX28", K_AUX28}, |
||||
|
{"AUX29", K_AUX29}, |
||||
|
{"AUX30", K_AUX30}, |
||||
|
{"AUX31", K_AUX31}, |
||||
|
{"AUX32", K_AUX32}, |
||||
|
|
||||
|
{"PAUSE", K_PAUSE}, |
||||
|
|
||||
|
{"MWHEELUP", K_MWHEELUP}, |
||||
|
{"MWHEELDOWN", K_MWHEELDOWN}, |
||||
|
|
||||
|
|
||||
|
// jkrige - mouse thumb buttons |
||||
|
{ "MOUSE4", K_MOUSE4 }, |
||||
|
{ "MOUSE5", K_MOUSE5 }, |
||||
|
// jkrige - mouse thumb buttons |
||||
|
|
||||
|
|
||||
|
{"SEMICOLON", ';'}, // because a raw semicolon seperates commands |
||||
|
|
||||
|
{NULL,0} |
||||
|
}; |
||||
|
|
||||
|
/* |
||||
|
============================================================================== |
||||
|
|
||||
|
LINE TYPING INTO THE CONSOLE |
||||
|
|
||||
|
============================================================================== |
||||
|
*/ |
||||
|
|
||||
|
/* |
||||
|
==================== |
||||
|
Key_Console |
||||
|
|
||||
|
Interactive line editing and console scrollback |
||||
|
==================== |
||||
|
*/ |
||||
|
void Key_Console (int key) |
||||
|
{ |
||||
|
char *cmd; |
||||
|
|
||||
|
if (key == K_ENTER) |
||||
|
{ |
||||
|
Cbuf_AddText (key_lines[edit_line]+1); // skip the > |
||||
|
Cbuf_AddText ("\n"); |
||||
|
Con_Printf ("%s\n",key_lines[edit_line]); |
||||
|
edit_line = (edit_line + 1) & 31; |
||||
|
history_line = edit_line; |
||||
|
key_lines[edit_line][0] = ']'; |
||||
|
key_linepos = 1; |
||||
|
if (cls.state == ca_disconnected) |
||||
|
SCR_UpdateScreen (); // force an update, because the command |
||||
|
// may take some time |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (key == K_TAB) |
||||
|
{ // command completion |
||||
|
cmd = Cmd_CompleteCommand (key_lines[edit_line]+1); |
||||
|
if (!cmd) |
||||
|
cmd = Cvar_CompleteVariable (key_lines[edit_line]+1); |
||||
|
if (cmd) |
||||
|
{ |
||||
|
Q_strcpy (key_lines[edit_line]+1, cmd); |
||||
|
key_linepos = Q_strlen(cmd)+1; |
||||
|
key_lines[edit_line][key_linepos] = ' '; |
||||
|
key_linepos++; |
||||
|
key_lines[edit_line][key_linepos] = 0; |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (key == K_BACKSPACE || key == K_LEFTARROW) |
||||
|
{ |
||||
|
if (key_linepos > 1) |
||||
|
key_linepos--; |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (key == K_UPARROW) |
||||
|
{ |
||||
|
do |
||||
|
{ |
||||
|
history_line = (history_line - 1) & 31; |
||||
|
} while (history_line != edit_line |
||||
|
&& !key_lines[history_line][1]); |
||||
|
if (history_line == edit_line) |
||||
|
history_line = (edit_line+1)&31; |
||||
|
Q_strcpy(key_lines[edit_line], key_lines[history_line]); |
||||
|
key_linepos = Q_strlen(key_lines[edit_line]); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (key == K_DOWNARROW) |
||||
|
{ |
||||
|
if (history_line == edit_line) return; |
||||
|
do |
||||
|
{ |
||||
|
history_line = (history_line + 1) & 31; |
||||
|
} |
||||
|
while (history_line != edit_line |
||||
|
&& !key_lines[history_line][1]); |
||||
|
if (history_line == edit_line) |
||||
|
{ |
||||
|
key_lines[edit_line][0] = ']'; |
||||
|
key_linepos = 1; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
Q_strcpy(key_lines[edit_line], key_lines[history_line]); |
||||
|
key_linepos = Q_strlen(key_lines[edit_line]); |
||||
|
} |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (key == K_PGUP || key==K_MWHEELUP) |
||||
|
{ |
||||
|
con_backscroll += 2; |
||||
|
if (con_backscroll > con_totallines - (vid.height>>3) - 1) |
||||
|
con_backscroll = con_totallines - (vid.height>>3) - 1; |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (key == K_PGDN || key==K_MWHEELDOWN) |
||||
|
{ |
||||
|
con_backscroll -= 2; |
||||
|
if (con_backscroll < 0) |
||||
|
con_backscroll = 0; |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (key == K_HOME) |
||||
|
{ |
||||
|
con_backscroll = con_totallines - (vid.height>>3) - 1; |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (key == K_END) |
||||
|
{ |
||||
|
con_backscroll = 0; |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (key < 32 || key > 127) |
||||
|
return; // non printable |
||||
|
|
||||
|
if (key_linepos < MAXCMDLINE-1) |
||||
|
{ |
||||
|
key_lines[edit_line][key_linepos] = key; |
||||
|
key_linepos++; |
||||
|
key_lines[edit_line][key_linepos] = 0; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
//============================================================================ |
||||
|
|
||||
|
char chat_buffer[32]; |
||||
|
qboolean team_message = false; |
||||
|
|
||||
|
void Key_Message (int key) |
||||
|
{ |
||||
|
static int chat_bufferlen = 0; |
||||
|
|
||||
|
if (key == K_ENTER) |
||||
|
{ |
||||
|
if (team_message) |
||||
|
Cbuf_AddText ("say_team \""); |
||||
|
else |
||||
|
Cbuf_AddText ("say \""); |
||||
|
Cbuf_AddText(chat_buffer); |
||||
|
Cbuf_AddText("\"\n"); |
||||
|
|
||||
|
key_dest = key_game; |
||||
|
chat_bufferlen = 0; |
||||
|
chat_buffer[0] = 0; |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (key == K_ESCAPE) |
||||
|
{ |
||||
|
key_dest = key_game; |
||||
|
chat_bufferlen = 0; |
||||
|
chat_buffer[0] = 0; |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (key < 32 || key > 127) |
||||
|
return; // non printable |
||||
|
|
||||
|
if (key == K_BACKSPACE) |
||||
|
{ |
||||
|
if (chat_bufferlen) |
||||
|
{ |
||||
|
chat_bufferlen--; |
||||
|
chat_buffer[chat_bufferlen] = 0; |
||||
|
} |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (chat_bufferlen == 31) |
||||
|
return; // all full |
||||
|
|
||||
|
chat_buffer[chat_bufferlen++] = key; |
||||
|
chat_buffer[chat_bufferlen] = 0; |
||||
|
} |
||||
|
|
||||
|
//============================================================================ |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
=================== |
||||
|
Key_StringToKeynum |
||||
|
|
||||
|
Returns a key number to be used to index keybindings[] by looking at |
||||
|
the given string. Single ascii characters return themselves, while |
||||
|
the K_* names are matched up. |
||||
|
=================== |
||||
|
*/ |
||||
|
int Key_StringToKeynum (char *str) |
||||
|
{ |
||||
|
keyname_t *kn; |
||||
|
|
||||
|
if (!str || !str[0]) |
||||
|
return -1; |
||||
|
if (!str[1]) |
||||
|
return str[0]; |
||||
|
|
||||
|
for (kn=keynames ; kn->name ; kn++) |
||||
|
{ |
||||
|
if (!Q_strcasecmp(str,kn->name)) |
||||
|
return kn->keynum; |
||||
|
} |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
=================== |
||||
|
Key_KeynumToString |
||||
|
|
||||
|
Returns a string (either a single ascii char, or a K_* name) for the |
||||
|
given keynum. |
||||
|
FIXME: handle quote special (general escape sequence?) |
||||
|
=================== |
||||
|
*/ |
||||
|
char *Key_KeynumToString (int keynum) |
||||
|
{ |
||||
|
keyname_t *kn; |
||||
|
static char tinystr[2]; |
||||
|
|
||||
|
if (keynum == -1) |
||||
|
return "<KEY NOT FOUND>"; |
||||
|
if (keynum > 32 && keynum < 127) |
||||
|
{ // printable ascii |
||||
|
tinystr[0] = keynum; |
||||
|
tinystr[1] = 0; |
||||
|
return tinystr; |
||||
|
} |
||||
|
|
||||
|
for (kn=keynames ; kn->name ; kn++) |
||||
|
if (keynum == kn->keynum) |
||||
|
return kn->name; |
||||
|
|
||||
|
return "<UNKNOWN KEYNUM>"; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
=================== |
||||
|
Key_SetBinding |
||||
|
=================== |
||||
|
*/ |
||||
|
void Key_SetBinding (int keynum, char *binding) |
||||
|
{ |
||||
|
char *new; |
||||
|
int l; |
||||
|
|
||||
|
if (keynum == -1) |
||||
|
return; |
||||
|
|
||||
|
// free old bindings |
||||
|
if (keybindings[keynum]) |
||||
|
{ |
||||
|
Z_Free (keybindings[keynum]); |
||||
|
keybindings[keynum] = NULL; |
||||
|
} |
||||
|
|
||||
|
// allocate memory for new binding |
||||
|
l = Q_strlen (binding); |
||||
|
new = Z_Malloc (l+1); |
||||
|
Q_strcpy (new, binding); |
||||
|
new[l] = 0; |
||||
|
keybindings[keynum] = new; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
=================== |
||||
|
Key_Unbind_f |
||||
|
=================== |
||||
|
*/ |
||||
|
void Key_Unbind_f (void) |
||||
|
{ |
||||
|
int b; |
||||
|
|
||||
|
if (Cmd_Argc() != 2) |
||||
|
{ |
||||
|
Con_Printf ("unbind <key> : remove commands from a key\n"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
b = Key_StringToKeynum (Cmd_Argv(1)); |
||||
|
if (b==-1) |
||||
|
{ |
||||
|
Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1)); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
Key_SetBinding (b, ""); |
||||
|
} |
||||
|
|
||||
|
void Key_Unbindall_f (void) |
||||
|
{ |
||||
|
int i; |
||||
|
|
||||
|
for (i=0 ; i<256 ; i++) |
||||
|
if (keybindings[i]) |
||||
|
Key_SetBinding (i, ""); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
=================== |
||||
|
Key_Bind_f |
||||
|
=================== |
||||
|
*/ |
||||
|
void Key_Bind_f (void) |
||||
|
{ |
||||
|
int i, c, b; |
||||
|
char cmd[1024]; |
||||
|
|
||||
|
c = Cmd_Argc(); |
||||
|
|
||||
|
if (c != 2 && c != 3) |
||||
|
{ |
||||
|
Con_Printf ("bind <key> [command] : attach a command to a key\n"); |
||||
|
return; |
||||
|
} |
||||
|
b = Key_StringToKeynum (Cmd_Argv(1)); |
||||
|
if (b==-1) |
||||
|
{ |
||||
|
Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1)); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (c == 2) |
||||
|
{ |
||||
|
if (keybindings[b]) |
||||
|
Con_Printf ("\"%s\" = \"%s\"\n", Cmd_Argv(1), keybindings[b] ); |
||||
|
else |
||||
|
Con_Printf ("\"%s\" is not bound\n", Cmd_Argv(1) ); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// copy the rest of the command line |
||||
|
cmd[0] = 0; // start out with a null string |
||||
|
for (i=2 ; i< c ; i++) |
||||
|
{ |
||||
|
if (i > 2) |
||||
|
strcat (cmd, " "); |
||||
|
strcat (cmd, Cmd_Argv(i)); |
||||
|
} |
||||
|
|
||||
|
Key_SetBinding (b, cmd); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
Key_WriteBindings |
||||
|
|
||||
|
Writes lines containing "bind key value" |
||||
|
============ |
||||
|
*/ |
||||
|
void Key_WriteBindings (FILE *f) |
||||
|
{ |
||||
|
int i; |
||||
|
|
||||
|
for (i=0 ; i<256 ; i++) |
||||
|
if (keybindings[i]) |
||||
|
if (*keybindings[i]) |
||||
|
fprintf (f, "bind \"%s\" \"%s\"\n", Key_KeynumToString(i), keybindings[i]); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
=================== |
||||
|
Key_Init |
||||
|
=================== |
||||
|
*/ |
||||
|
void Key_Init (void) |
||||
|
{ |
||||
|
int i; |
||||
|
|
||||
|
for (i=0 ; i<32 ; i++) |
||||
|
{ |
||||
|
key_lines[i][0] = ']'; |
||||
|
key_lines[i][1] = 0; |
||||
|
} |
||||
|
key_linepos = 1; |
||||
|
|
||||
|
// |
||||
|
// init ascii characters in console mode |
||||
|
// |
||||
|
for (i=32 ; i<128 ; i++) |
||||
|
consolekeys[i] = true; |
||||
|
consolekeys[K_ENTER] = true; |
||||
|
consolekeys[K_TAB] = true; |
||||
|
consolekeys[K_LEFTARROW] = true; |
||||
|
consolekeys[K_RIGHTARROW] = true; |
||||
|
consolekeys[K_UPARROW] = true; |
||||
|
consolekeys[K_DOWNARROW] = true; |
||||
|
consolekeys[K_BACKSPACE] = true; |
||||
|
consolekeys[K_PGUP] = true; |
||||
|
consolekeys[K_PGDN] = true; |
||||
|
consolekeys[K_SHIFT] = true; |
||||
|
consolekeys[K_MWHEELUP] = true; |
||||
|
consolekeys[K_MWHEELDOWN] = true; |
||||
|
consolekeys['`'] = false; |
||||
|
consolekeys['~'] = false; |
||||
|
|
||||
|
for (i=0 ; i<256 ; i++) |
||||
|
keyshift[i] = i; |
||||
|
for (i='a' ; i<='z' ; i++) |
||||
|
keyshift[i] = i - 'a' + 'A'; |
||||
|
keyshift['1'] = '!'; |
||||
|
keyshift['2'] = '@'; |
||||
|
keyshift['3'] = '#'; |
||||
|
keyshift['4'] = '$'; |
||||
|
keyshift['5'] = '%'; |
||||
|
keyshift['6'] = '^'; |
||||
|
keyshift['7'] = '&'; |
||||
|
keyshift['8'] = '*'; |
||||
|
keyshift['9'] = '('; |
||||
|
keyshift['0'] = ')'; |
||||
|
keyshift['-'] = '_'; |
||||
|
keyshift['='] = '+'; |
||||
|
keyshift[','] = '<'; |
||||
|
keyshift['.'] = '>'; |
||||
|
keyshift['/'] = '?'; |
||||
|
keyshift[';'] = ':'; |
||||
|
keyshift['\''] = '"'; |
||||
|
keyshift['['] = '{'; |
||||
|
keyshift[']'] = '}'; |
||||
|
keyshift['`'] = '~'; |
||||
|
keyshift['\\'] = '|'; |
||||
|
|
||||
|
menubound[K_ESCAPE] = true; |
||||
|
for (i=0 ; i<12 ; i++) |
||||
|
menubound[K_F1+i] = true; |
||||
|
|
||||
|
// |
||||
|
// register our functions |
||||
|
// |
||||
|
Cmd_AddCommand ("bind",Key_Bind_f); |
||||
|
Cmd_AddCommand ("unbind",Key_Unbind_f); |
||||
|
Cmd_AddCommand ("unbindall",Key_Unbindall_f); |
||||
|
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
=================== |
||||
|
Key_Event |
||||
|
|
||||
|
Called by the system between frames for both key up and key down events |
||||
|
Should NOT be called during an interrupt! |
||||
|
=================== |
||||
|
*/ |
||||
|
void Key_Event (int key, qboolean down) |
||||
|
{ |
||||
|
char *kb; |
||||
|
char cmd[1024]; |
||||
|
|
||||
|
keydown[key] = down; |
||||
|
|
||||
|
if (!down) |
||||
|
key_repeats[key] = 0; |
||||
|
|
||||
|
key_lastpress = key; |
||||
|
key_count++; |
||||
|
if (key_count <= 0) |
||||
|
{ |
||||
|
return; // just catching keys for Con_NotifyBox |
||||
|
} |
||||
|
|
||||
|
// update auto-repeat status |
||||
|
if (down) |
||||
|
{ |
||||
|
key_repeats[key]++; |
||||
|
if (key != K_BACKSPACE && key != K_PAUSE && key_repeats[key] > 1) |
||||
|
{ |
||||
|
return; // ignore most autorepeats |
||||
|
} |
||||
|
|
||||
|
if (key >= 200 && !keybindings[key]) |
||||
|
Con_Printf ("%s is unbound, hit F4 to set.\n", Key_KeynumToString (key) ); |
||||
|
} |
||||
|
|
||||
|
if (key == K_SHIFT) |
||||
|
shift_down = down; |
||||
|
|
||||
|
// |
||||
|
// handle escape specialy, so the user can never unbind it |
||||
|
// |
||||
|
if (key == K_ESCAPE) |
||||
|
{ |
||||
|
if (!down) |
||||
|
return; |
||||
|
switch (key_dest) |
||||
|
{ |
||||
|
case key_message: |
||||
|
Key_Message (key); |
||||
|
break; |
||||
|
case key_menu: |
||||
|
M_Keydown (key); |
||||
|
break; |
||||
|
case key_game: |
||||
|
case key_console: |
||||
|
M_ToggleMenu_f (); |
||||
|
break; |
||||
|
default: |
||||
|
Sys_Error ("Bad key_dest"); |
||||
|
} |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// |
||||
|
// key up events only generate commands if the game key binding is |
||||
|
// a button command (leading + sign). These will occur even in console mode, |
||||
|
// to keep the character from continuing an action started before a console |
||||
|
// switch. Button commands include the kenum as a parameter, so multiple |
||||
|
// downs can be matched with ups |
||||
|
// |
||||
|
if (!down) |
||||
|
{ |
||||
|
kb = keybindings[key]; |
||||
|
if (kb && kb[0] == '+') |
||||
|
{ |
||||
|
sprintf (cmd, "-%s %i\n", kb+1, key); |
||||
|
Cbuf_AddText (cmd); |
||||
|
} |
||||
|
if (keyshift[key] != key) |
||||
|
{ |
||||
|
kb = keybindings[keyshift[key]]; |
||||
|
if (kb && kb[0] == '+') |
||||
|
{ |
||||
|
sprintf (cmd, "-%s %i\n", kb+1, key); |
||||
|
Cbuf_AddText (cmd); |
||||
|
} |
||||
|
} |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// |
||||
|
// during demo playback, most keys bring up the main menu |
||||
|
// |
||||
|
if (cls.demoplayback && down && consolekeys[key] && key_dest == key_game) |
||||
|
{ |
||||
|
M_ToggleMenu_f (); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// |
||||
|
// if not a consolekey, send to the interpreter no matter what mode is |
||||
|
// |
||||
|
if ( (key_dest == key_menu && menubound[key]) |
||||
|
|| (key_dest == key_console && !consolekeys[key]) |
||||
|
|| (key_dest == key_game && ( !con_forcedup || !consolekeys[key] ) ) ) |
||||
|
{ |
||||
|
kb = keybindings[key]; |
||||
|
if (kb) |
||||
|
{ |
||||
|
if (kb[0] == '+') |
||||
|
{ // button commands add keynum as a parm |
||||
|
sprintf (cmd, "%s %i\n", kb, key); |
||||
|
Cbuf_AddText (cmd); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
Cbuf_AddText (kb); |
||||
|
Cbuf_AddText ("\n"); |
||||
|
} |
||||
|
} |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (!down) |
||||
|
return; // other systems only care about key down events |
||||
|
|
||||
|
if (shift_down) |
||||
|
{ |
||||
|
key = keyshift[key]; |
||||
|
} |
||||
|
|
||||
|
switch (key_dest) |
||||
|
{ |
||||
|
case key_message: |
||||
|
Key_Message (key); |
||||
|
break; |
||||
|
case key_menu: |
||||
|
M_Keydown (key); |
||||
|
break; |
||||
|
|
||||
|
case key_game: |
||||
|
case key_console: |
||||
|
Key_Console (key); |
||||
|
break; |
||||
|
default: |
||||
|
Sys_Error ("Bad key_dest"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
=================== |
||||
|
Key_ClearStates |
||||
|
=================== |
||||
|
*/ |
||||
|
void Key_ClearStates (void) |
||||
|
{ |
||||
|
int i; |
||||
|
|
||||
|
for (i=0 ; i<256 ; i++) |
||||
|
{ |
||||
|
keydown[i] = false; |
||||
|
key_repeats[i] = 0; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,136 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
// |
||||
|
// these are the key numbers that should be passed to Key_Event |
||||
|
// |
||||
|
#define K_TAB 9 |
||||
|
#define K_ENTER 13 |
||||
|
#define K_ESCAPE 27 |
||||
|
#define K_SPACE 32 |
||||
|
|
||||
|
// normal keys should be passed as lowercased ascii |
||||
|
|
||||
|
#define K_BACKSPACE 127 |
||||
|
#define K_UPARROW 128 |
||||
|
#define K_DOWNARROW 129 |
||||
|
#define K_LEFTARROW 130 |
||||
|
#define K_RIGHTARROW 131 |
||||
|
|
||||
|
#define K_ALT 132 |
||||
|
#define K_CTRL 133 |
||||
|
#define K_SHIFT 134 |
||||
|
#define K_F1 135 |
||||
|
#define K_F2 136 |
||||
|
#define K_F3 137 |
||||
|
#define K_F4 138 |
||||
|
#define K_F5 139 |
||||
|
#define K_F6 140 |
||||
|
#define K_F7 141 |
||||
|
#define K_F8 142 |
||||
|
#define K_F9 143 |
||||
|
#define K_F10 144 |
||||
|
#define K_F11 145 |
||||
|
#define K_F12 146 |
||||
|
#define K_INS 147 |
||||
|
#define K_DEL 148 |
||||
|
#define K_PGDN 149 |
||||
|
#define K_PGUP 150 |
||||
|
#define K_HOME 151 |
||||
|
#define K_END 152 |
||||
|
|
||||
|
#define K_PAUSE 255 |
||||
|
|
||||
|
// |
||||
|
// mouse buttons generate virtual keys |
||||
|
// |
||||
|
#define K_MOUSE1 200 |
||||
|
#define K_MOUSE2 201 |
||||
|
#define K_MOUSE3 202 |
||||
|
|
||||
|
// |
||||
|
// joystick buttons |
||||
|
// |
||||
|
#define K_JOY1 203 |
||||
|
#define K_JOY2 204 |
||||
|
#define K_JOY3 205 |
||||
|
#define K_JOY4 206 |
||||
|
|
||||
|
// |
||||
|
// aux keys are for multi-buttoned joysticks to generate so they can use |
||||
|
// the normal binding process |
||||
|
// |
||||
|
#define K_AUX1 207 |
||||
|
#define K_AUX2 208 |
||||
|
#define K_AUX3 209 |
||||
|
#define K_AUX4 210 |
||||
|
#define K_AUX5 211 |
||||
|
#define K_AUX6 212 |
||||
|
#define K_AUX7 213 |
||||
|
#define K_AUX8 214 |
||||
|
#define K_AUX9 215 |
||||
|
#define K_AUX10 216 |
||||
|
#define K_AUX11 217 |
||||
|
#define K_AUX12 218 |
||||
|
#define K_AUX13 219 |
||||
|
#define K_AUX14 220 |
||||
|
#define K_AUX15 221 |
||||
|
#define K_AUX16 222 |
||||
|
#define K_AUX17 223 |
||||
|
#define K_AUX18 224 |
||||
|
#define K_AUX19 225 |
||||
|
#define K_AUX20 226 |
||||
|
#define K_AUX21 227 |
||||
|
#define K_AUX22 228 |
||||
|
#define K_AUX23 229 |
||||
|
#define K_AUX24 230 |
||||
|
#define K_AUX25 231 |
||||
|
#define K_AUX26 232 |
||||
|
#define K_AUX27 233 |
||||
|
#define K_AUX28 234 |
||||
|
#define K_AUX29 235 |
||||
|
#define K_AUX30 236 |
||||
|
#define K_AUX31 237 |
||||
|
#define K_AUX32 238 |
||||
|
|
||||
|
// JACK: Intellimouse(c) Mouse Wheel Support |
||||
|
|
||||
|
#define K_MWHEELUP 239 |
||||
|
#define K_MWHEELDOWN 240 |
||||
|
|
||||
|
// jkrige - mouse thumb buttons |
||||
|
#define K_MOUSE4 241 |
||||
|
#define K_MOUSE5 242 |
||||
|
// jkrige - mouse thumb buttons |
||||
|
|
||||
|
|
||||
|
typedef enum {key_game, key_console, key_message, key_menu} keydest_t; |
||||
|
|
||||
|
extern keydest_t key_dest; |
||||
|
extern char *keybindings[256]; |
||||
|
extern int key_repeats[256]; |
||||
|
extern int key_count; // incremented every key event |
||||
|
extern int key_lastpress; |
||||
|
|
||||
|
void Key_Event (int key, qboolean down); |
||||
|
void Key_Init (void); |
||||
|
void Key_WriteBindings (FILE *f); |
||||
|
void Key_SetBinding (int keynum, char *binding); |
||||
|
void Key_ClearStates (void); |
||||
@ -0,0 +1,587 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// mathlib.c -- math primitives |
||||
|
|
||||
|
#include <math.h> |
||||
|
#include "quakedef.h" |
||||
|
|
||||
|
void Sys_Error (char *error, ...); |
||||
|
|
||||
|
vec3_t vec3_origin = {0,0,0}; |
||||
|
int nanmask = 255<<23; |
||||
|
|
||||
|
/*-----------------------------------------------------------------*/ |
||||
|
|
||||
|
// jkrige - quake2 warps |
||||
|
//#define DEG2RAD( a ) ( a * M_PI ) / 180.0F |
||||
|
// jkrige - quake2 warps |
||||
|
|
||||
|
void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal ) |
||||
|
{ |
||||
|
float d; |
||||
|
vec3_t n; |
||||
|
float inv_denom; |
||||
|
|
||||
|
inv_denom = 1.0F / DotProduct( normal, normal ); |
||||
|
|
||||
|
d = DotProduct( normal, p ) * inv_denom; |
||||
|
|
||||
|
n[0] = normal[0] * inv_denom; |
||||
|
n[1] = normal[1] * inv_denom; |
||||
|
n[2] = normal[2] * inv_denom; |
||||
|
|
||||
|
dst[0] = p[0] - d * n[0]; |
||||
|
dst[1] = p[1] - d * n[1]; |
||||
|
dst[2] = p[2] - d * n[2]; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
** assumes "src" is normalized |
||||
|
*/ |
||||
|
void PerpendicularVector( vec3_t dst, const vec3_t src ) |
||||
|
{ |
||||
|
int pos; |
||||
|
int i; |
||||
|
float minelem = 1.0F; |
||||
|
vec3_t tempvec; |
||||
|
|
||||
|
/* |
||||
|
** find the smallest magnitude axially aligned vector |
||||
|
*/ |
||||
|
for ( pos = 0, i = 0; i < 3; i++ ) |
||||
|
{ |
||||
|
if ( fabs( src[i] ) < minelem ) |
||||
|
{ |
||||
|
pos = i; |
||||
|
minelem = fabs( src[i] ); |
||||
|
} |
||||
|
} |
||||
|
tempvec[0] = tempvec[1] = tempvec[2] = 0.0F; |
||||
|
tempvec[pos] = 1.0F; |
||||
|
|
||||
|
/* |
||||
|
** project the point onto the plane defined by src |
||||
|
*/ |
||||
|
ProjectPointOnPlane( dst, tempvec, src ); |
||||
|
|
||||
|
/* |
||||
|
** normalize the result |
||||
|
*/ |
||||
|
VectorNormalize( dst ); |
||||
|
} |
||||
|
|
||||
|
#ifdef _WIN32 |
||||
|
#pragma optimize( "", off ) |
||||
|
#endif |
||||
|
|
||||
|
|
||||
|
void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees ) |
||||
|
{ |
||||
|
float m[3][3]; |
||||
|
float im[3][3]; |
||||
|
float zrot[3][3]; |
||||
|
float tmpmat[3][3]; |
||||
|
float rot[3][3]; |
||||
|
int i; |
||||
|
vec3_t vr, vup, vf; |
||||
|
|
||||
|
vf[0] = dir[0]; |
||||
|
vf[1] = dir[1]; |
||||
|
vf[2] = dir[2]; |
||||
|
|
||||
|
PerpendicularVector( vr, dir ); |
||||
|
CrossProduct( vr, vf, vup ); |
||||
|
|
||||
|
m[0][0] = vr[0]; |
||||
|
m[1][0] = vr[1]; |
||||
|
m[2][0] = vr[2]; |
||||
|
|
||||
|
m[0][1] = vup[0]; |
||||
|
m[1][1] = vup[1]; |
||||
|
m[2][1] = vup[2]; |
||||
|
|
||||
|
m[0][2] = vf[0]; |
||||
|
m[1][2] = vf[1]; |
||||
|
m[2][2] = vf[2]; |
||||
|
|
||||
|
memcpy( im, m, sizeof( im ) ); |
||||
|
|
||||
|
im[0][1] = m[1][0]; |
||||
|
im[0][2] = m[2][0]; |
||||
|
im[1][0] = m[0][1]; |
||||
|
im[1][2] = m[2][1]; |
||||
|
im[2][0] = m[0][2]; |
||||
|
im[2][1] = m[1][2]; |
||||
|
|
||||
|
memset( zrot, 0, sizeof( zrot ) ); |
||||
|
zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F; |
||||
|
|
||||
|
zrot[0][0] = cos( DEG2RAD( degrees ) ); |
||||
|
zrot[0][1] = sin( DEG2RAD( degrees ) ); |
||||
|
zrot[1][0] = -sin( DEG2RAD( degrees ) ); |
||||
|
zrot[1][1] = cos( DEG2RAD( degrees ) ); |
||||
|
|
||||
|
R_ConcatRotations( m, zrot, tmpmat ); |
||||
|
R_ConcatRotations( tmpmat, im, rot ); |
||||
|
|
||||
|
for ( i = 0; i < 3; i++ ) |
||||
|
{ |
||||
|
dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#ifdef _WIN32 |
||||
|
#pragma optimize( "", on ) |
||||
|
#endif |
||||
|
|
||||
|
/*-----------------------------------------------------------------*/ |
||||
|
|
||||
|
|
||||
|
float anglemod(float a) |
||||
|
{ |
||||
|
#if 0 |
||||
|
if (a >= 0) |
||||
|
a -= 360*(int)(a/360); |
||||
|
else |
||||
|
a += 360*( 1 + (int)(-a/360) ); |
||||
|
#endif |
||||
|
a = (360.0/65536) * ((int)(a*(65536/360.0)) & 65535); |
||||
|
return a; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
================== |
||||
|
BOPS_Error |
||||
|
|
||||
|
Split out like this for ASM to call. |
||||
|
================== |
||||
|
*/ |
||||
|
void BOPS_Error (void) |
||||
|
{ |
||||
|
Sys_Error ("BoxOnPlaneSide: Bad signbits"); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
#if !id386 |
||||
|
|
||||
|
/* |
||||
|
================== |
||||
|
BoxOnPlaneSide |
||||
|
|
||||
|
Returns 1, 2, or 1 + 2 |
||||
|
================== |
||||
|
*/ |
||||
|
int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, mplane_t *p) |
||||
|
{ |
||||
|
float dist1, dist2; |
||||
|
int sides; |
||||
|
|
||||
|
#if 0 // this is done by the BOX_ON_PLANE_SIDE macro before calling this |
||||
|
// function |
||||
|
// fast axial cases |
||||
|
if (p->type < 3) |
||||
|
{ |
||||
|
if (p->dist <= emins[p->type]) |
||||
|
return 1; |
||||
|
if (p->dist >= emaxs[p->type]) |
||||
|
return 2; |
||||
|
return 3; |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
// general case |
||||
|
switch (p->signbits) |
||||
|
{ |
||||
|
case 0: |
||||
|
dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; |
||||
|
dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; |
||||
|
break; |
||||
|
case 1: |
||||
|
dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; |
||||
|
dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; |
||||
|
break; |
||||
|
case 2: |
||||
|
dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; |
||||
|
dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; |
||||
|
break; |
||||
|
case 3: |
||||
|
dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; |
||||
|
dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; |
||||
|
break; |
||||
|
case 4: |
||||
|
dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; |
||||
|
dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; |
||||
|
break; |
||||
|
case 5: |
||||
|
dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; |
||||
|
dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; |
||||
|
break; |
||||
|
case 6: |
||||
|
dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; |
||||
|
dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; |
||||
|
break; |
||||
|
case 7: |
||||
|
dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; |
||||
|
dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; |
||||
|
break; |
||||
|
default: |
||||
|
dist1 = dist2 = 0; // shut up compiler |
||||
|
BOPS_Error (); |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
#if 0 |
||||
|
int i; |
||||
|
vec3_t corners[2]; |
||||
|
|
||||
|
for (i=0 ; i<3 ; i++) |
||||
|
{ |
||||
|
if (plane->normal[i] < 0) |
||||
|
{ |
||||
|
corners[0][i] = emins[i]; |
||||
|
corners[1][i] = emaxs[i]; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
corners[1][i] = emins[i]; |
||||
|
corners[0][i] = emaxs[i]; |
||||
|
} |
||||
|
} |
||||
|
dist = DotProduct (plane->normal, corners[0]) - plane->dist; |
||||
|
dist2 = DotProduct (plane->normal, corners[1]) - plane->dist; |
||||
|
sides = 0; |
||||
|
if (dist1 >= 0) |
||||
|
sides = 1; |
||||
|
if (dist2 < 0) |
||||
|
sides |= 2; |
||||
|
|
||||
|
#endif |
||||
|
|
||||
|
sides = 0; |
||||
|
if (dist1 >= p->dist) |
||||
|
sides = 1; |
||||
|
if (dist2 < p->dist) |
||||
|
sides |= 2; |
||||
|
|
||||
|
#ifdef PARANOID |
||||
|
if (sides == 0) |
||||
|
Sys_Error ("BoxOnPlaneSide: sides==0"); |
||||
|
#endif |
||||
|
|
||||
|
return sides; |
||||
|
} |
||||
|
|
||||
|
#endif |
||||
|
|
||||
|
|
||||
|
void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) |
||||
|
{ |
||||
|
float angle; |
||||
|
float sr, sp, sy, cr, cp, cy; |
||||
|
|
||||
|
angle = angles[YAW] * (M_PI*2 / 360); |
||||
|
sy = sin(angle); |
||||
|
cy = cos(angle); |
||||
|
angle = angles[PITCH] * (M_PI*2 / 360); |
||||
|
sp = sin(angle); |
||||
|
cp = cos(angle); |
||||
|
angle = angles[ROLL] * (M_PI*2 / 360); |
||||
|
sr = sin(angle); |
||||
|
cr = cos(angle); |
||||
|
|
||||
|
forward[0] = cp*cy; |
||||
|
forward[1] = cp*sy; |
||||
|
forward[2] = -sp; |
||||
|
right[0] = (-1*sr*sp*cy+-1*cr*-sy); |
||||
|
right[1] = (-1*sr*sp*sy+-1*cr*cy); |
||||
|
right[2] = -1*sr*cp; |
||||
|
up[0] = (cr*sp*cy+-sr*-sy); |
||||
|
up[1] = (cr*sp*sy+-sr*cy); |
||||
|
up[2] = cr*cp; |
||||
|
} |
||||
|
|
||||
|
int VectorCompare (vec3_t v1, vec3_t v2) |
||||
|
{ |
||||
|
int i; |
||||
|
|
||||
|
for (i=0 ; i<3 ; i++) |
||||
|
if (v1[i] != v2[i]) |
||||
|
return 0; |
||||
|
|
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc) |
||||
|
{ |
||||
|
vecc[0] = veca[0] + scale*vecb[0]; |
||||
|
vecc[1] = veca[1] + scale*vecb[1]; |
||||
|
vecc[2] = veca[2] + scale*vecb[2]; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
vec_t _DotProduct (vec3_t v1, vec3_t v2) |
||||
|
{ |
||||
|
return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; |
||||
|
} |
||||
|
|
||||
|
void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out) |
||||
|
{ |
||||
|
out[0] = veca[0]-vecb[0]; |
||||
|
out[1] = veca[1]-vecb[1]; |
||||
|
out[2] = veca[2]-vecb[2]; |
||||
|
} |
||||
|
|
||||
|
void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out) |
||||
|
{ |
||||
|
out[0] = veca[0]+vecb[0]; |
||||
|
out[1] = veca[1]+vecb[1]; |
||||
|
out[2] = veca[2]+vecb[2]; |
||||
|
} |
||||
|
|
||||
|
void _VectorCopy (vec3_t in, vec3_t out) |
||||
|
{ |
||||
|
out[0] = in[0]; |
||||
|
out[1] = in[1]; |
||||
|
out[2] = in[2]; |
||||
|
} |
||||
|
|
||||
|
void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross) |
||||
|
{ |
||||
|
cross[0] = v1[1]*v2[2] - v1[2]*v2[1]; |
||||
|
cross[1] = v1[2]*v2[0] - v1[0]*v2[2]; |
||||
|
cross[2] = v1[0]*v2[1] - v1[1]*v2[0]; |
||||
|
} |
||||
|
|
||||
|
double sqrt(double x); |
||||
|
|
||||
|
vec_t Length(vec3_t v) |
||||
|
{ |
||||
|
int i; |
||||
|
float length; |
||||
|
|
||||
|
length = 0; |
||||
|
for (i=0 ; i< 3 ; i++) |
||||
|
length += v[i]*v[i]; |
||||
|
length = sqrt (length); // FIXME |
||||
|
|
||||
|
return length; |
||||
|
} |
||||
|
|
||||
|
float VectorNormalize (vec3_t v) |
||||
|
{ |
||||
|
float length, ilength; |
||||
|
|
||||
|
length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; |
||||
|
length = sqrt (length); // FIXME |
||||
|
|
||||
|
if (length) |
||||
|
{ |
||||
|
ilength = 1/length; |
||||
|
v[0] *= ilength; |
||||
|
v[1] *= ilength; |
||||
|
v[2] *= ilength; |
||||
|
} |
||||
|
|
||||
|
return length; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
void VectorInverse (vec3_t v) |
||||
|
{ |
||||
|
v[0] = -v[0]; |
||||
|
v[1] = -v[1]; |
||||
|
v[2] = -v[2]; |
||||
|
} |
||||
|
|
||||
|
void VectorScale (vec3_t in, vec_t scale, vec3_t out) |
||||
|
{ |
||||
|
out[0] = in[0]*scale; |
||||
|
out[1] = in[1]*scale; |
||||
|
out[2] = in[2]*scale; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
int Q_log2(int val) |
||||
|
{ |
||||
|
int answer=0; |
||||
|
while (val>>=1) |
||||
|
answer++; |
||||
|
return answer; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================ |
||||
|
R_ConcatRotations |
||||
|
================ |
||||
|
*/ |
||||
|
void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3]) |
||||
|
{ |
||||
|
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + |
||||
|
in1[0][2] * in2[2][0]; |
||||
|
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + |
||||
|
in1[0][2] * in2[2][1]; |
||||
|
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + |
||||
|
in1[0][2] * in2[2][2]; |
||||
|
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + |
||||
|
in1[1][2] * in2[2][0]; |
||||
|
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + |
||||
|
in1[1][2] * in2[2][1]; |
||||
|
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + |
||||
|
in1[1][2] * in2[2][2]; |
||||
|
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + |
||||
|
in1[2][2] * in2[2][0]; |
||||
|
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + |
||||
|
in1[2][2] * in2[2][1]; |
||||
|
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + |
||||
|
in1[2][2] * in2[2][2]; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================ |
||||
|
R_ConcatTransforms |
||||
|
================ |
||||
|
*/ |
||||
|
void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]) |
||||
|
{ |
||||
|
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + |
||||
|
in1[0][2] * in2[2][0]; |
||||
|
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + |
||||
|
in1[0][2] * in2[2][1]; |
||||
|
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + |
||||
|
in1[0][2] * in2[2][2]; |
||||
|
out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + |
||||
|
in1[0][2] * in2[2][3] + in1[0][3]; |
||||
|
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + |
||||
|
in1[1][2] * in2[2][0]; |
||||
|
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + |
||||
|
in1[1][2] * in2[2][1]; |
||||
|
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + |
||||
|
in1[1][2] * in2[2][2]; |
||||
|
out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + |
||||
|
in1[1][2] * in2[2][3] + in1[1][3]; |
||||
|
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + |
||||
|
in1[2][2] * in2[2][0]; |
||||
|
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + |
||||
|
in1[2][2] * in2[2][1]; |
||||
|
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + |
||||
|
in1[2][2] * in2[2][2]; |
||||
|
out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + |
||||
|
in1[2][2] * in2[2][3] + in1[2][3]; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
=================== |
||||
|
FloorDivMod |
||||
|
|
||||
|
Returns mathematically correct (floor-based) quotient and remainder for |
||||
|
numer and denom, both of which should contain no fractional part. The |
||||
|
quotient must fit in 32 bits. |
||||
|
==================== |
||||
|
*/ |
||||
|
|
||||
|
void FloorDivMod (double numer, double denom, int *quotient, |
||||
|
int *rem) |
||||
|
{ |
||||
|
int q, r; |
||||
|
double x; |
||||
|
|
||||
|
#ifndef PARANOID |
||||
|
if (denom <= 0.0) |
||||
|
Sys_Error ("FloorDivMod: bad denominator %d\n", denom); |
||||
|
|
||||
|
// if ((floor(numer) != numer) || (floor(denom) != denom)) |
||||
|
// Sys_Error ("FloorDivMod: non-integer numer or denom %f %f\n", |
||||
|
// numer, denom); |
||||
|
#endif |
||||
|
|
||||
|
if (numer >= 0.0) |
||||
|
{ |
||||
|
|
||||
|
x = floor(numer / denom); |
||||
|
q = (int)x; |
||||
|
r = (int)floor(numer - (x * denom)); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
// |
||||
|
// perform operations with positive values, and fix mod to make floor-based |
||||
|
// |
||||
|
x = floor(-numer / denom); |
||||
|
q = -(int)x; |
||||
|
r = (int)floor(-numer - (x * denom)); |
||||
|
if (r != 0) |
||||
|
{ |
||||
|
q--; |
||||
|
r = (int)denom - r; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
*quotient = q; |
||||
|
*rem = r; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
=================== |
||||
|
GreatestCommonDivisor |
||||
|
==================== |
||||
|
*/ |
||||
|
int GreatestCommonDivisor (int i1, int i2) |
||||
|
{ |
||||
|
if (i1 > i2) |
||||
|
{ |
||||
|
if (i2 == 0) |
||||
|
return (i1); |
||||
|
return GreatestCommonDivisor (i2, i1 % i2); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
if (i1 == 0) |
||||
|
return (i2); |
||||
|
return GreatestCommonDivisor (i1, i2 % i1); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
#if !id386 |
||||
|
|
||||
|
// TODO: move to nonintel.c |
||||
|
|
||||
|
/* |
||||
|
=================== |
||||
|
Invert24To16 |
||||
|
|
||||
|
Inverts an 8.24 value to a 16.16 value |
||||
|
==================== |
||||
|
*/ |
||||
|
|
||||
|
fixed16_t Invert24To16(fixed16_t val) |
||||
|
{ |
||||
|
if (val < 256) |
||||
|
return (0xFFFFFFFF); |
||||
|
|
||||
|
return (fixed16_t) |
||||
|
(((double)0x10000 * (double)0x1000000 / (double)val) + 0.5); |
||||
|
} |
||||
|
|
||||
|
#endif |
||||
@ -0,0 +1,107 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// mathlib.h |
||||
|
|
||||
|
typedef float vec_t; |
||||
|
typedef vec_t vec3_t[3]; |
||||
|
typedef vec_t vec5_t[5]; |
||||
|
|
||||
|
typedef int fixed4_t; |
||||
|
typedef int fixed8_t; |
||||
|
typedef int fixed16_t; |
||||
|
|
||||
|
#ifndef M_PI |
||||
|
#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h |
||||
|
#endif |
||||
|
|
||||
|
// jkrige - quake2 warps |
||||
|
#ifndef DEG2RAD |
||||
|
#define DEG2RAD( a ) ( a * M_PI ) / 180.0F |
||||
|
#endif |
||||
|
// jkrige - quake2 warps |
||||
|
|
||||
|
struct mplane_s; |
||||
|
|
||||
|
extern vec3_t vec3_origin; |
||||
|
extern int nanmask; |
||||
|
|
||||
|
#define IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask) |
||||
|
|
||||
|
#define DotProduct(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2]) |
||||
|
#define VectorSubtract(a,b,c) {c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];} |
||||
|
#define VectorAdd(a,b,c) {c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];} |
||||
|
#define VectorCopy(a,b) {b[0]=a[0];b[1]=a[1];b[2]=a[2];} |
||||
|
|
||||
|
// jkrige - quake2 warps |
||||
|
#define VectorClear(a) (a[0]=a[1]=a[2]=0) |
||||
|
#define VectorNegate(a,b) (b[0]=-a[0],b[1]=-a[1],b[2]=-a[2]) |
||||
|
#define VectorSet(v, x, y, z) (v[0]=(x), v[1]=(y), v[2]=(z)) |
||||
|
// jkrige - quake2 warps |
||||
|
|
||||
|
|
||||
|
// jkrige - field of view (fov) fix |
||||
|
void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees ); |
||||
|
// jkrige - field of view (fov) fix |
||||
|
|
||||
|
|
||||
|
void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc); |
||||
|
|
||||
|
vec_t _DotProduct (vec3_t v1, vec3_t v2); |
||||
|
void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out); |
||||
|
void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out); |
||||
|
void _VectorCopy (vec3_t in, vec3_t out); |
||||
|
|
||||
|
int VectorCompare (vec3_t v1, vec3_t v2); |
||||
|
vec_t Length (vec3_t v); |
||||
|
void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross); |
||||
|
float VectorNormalize (vec3_t v); // returns vector length |
||||
|
void VectorInverse (vec3_t v); |
||||
|
void VectorScale (vec3_t in, vec_t scale, vec3_t out); |
||||
|
int Q_log2(int val); |
||||
|
|
||||
|
void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3]); |
||||
|
void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]); |
||||
|
|
||||
|
void FloorDivMod (double numer, double denom, int *quotient, |
||||
|
int *rem); |
||||
|
fixed16_t Invert24To16(fixed16_t val); |
||||
|
int GreatestCommonDivisor (int i1, int i2); |
||||
|
|
||||
|
void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up); |
||||
|
int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct mplane_s *plane); |
||||
|
float anglemod(float a); |
||||
|
|
||||
|
|
||||
|
|
||||
|
#define BOX_ON_PLANE_SIDE(emins, emaxs, p) \ |
||||
|
(((p)->type < 3)? \ |
||||
|
( \ |
||||
|
((p)->dist <= (emins)[(p)->type])? \ |
||||
|
1 \ |
||||
|
: \ |
||||
|
( \ |
||||
|
((p)->dist >= (emaxs)[(p)->type])?\ |
||||
|
2 \ |
||||
|
: \ |
||||
|
3 \ |
||||
|
) \ |
||||
|
) \ |
||||
|
: \ |
||||
|
BoxOnPlaneSide( (emins), (emaxs), (p))) |
||||
3364
engine/code/menu.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,38 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
// |
||||
|
// the net drivers should just set the apropriate bits in m_activenet, |
||||
|
// instead of having the menu code look through their internal tables |
||||
|
// |
||||
|
#define MNET_IPX 1 |
||||
|
#define MNET_TCP 2 |
||||
|
|
||||
|
extern int m_activenet; |
||||
|
|
||||
|
// |
||||
|
// menus |
||||
|
// |
||||
|
void M_Init (void); |
||||
|
void M_Keydown (int key); |
||||
|
void M_Draw (void); |
||||
|
void M_ToggleMenu_f (void); |
||||
|
|
||||
|
|
||||
@ -0,0 +1,134 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// |
||||
|
// modelgen.h: header file for model generation program |
||||
|
// |
||||
|
|
||||
|
// ********************************************************* |
||||
|
// * This file must be identical in the modelgen directory * |
||||
|
// * and in the Quake directory, because it's used to * |
||||
|
// * pass data from one to the other via model files. * |
||||
|
// ********************************************************* |
||||
|
|
||||
|
#ifdef INCLUDELIBS |
||||
|
|
||||
|
#include <stdlib.h> |
||||
|
#include <stdio.h> |
||||
|
#include <math.h> |
||||
|
#include <string.h> |
||||
|
|
||||
|
#include "cmdlib.h" |
||||
|
#include "scriplib.h" |
||||
|
#include "trilib.h" |
||||
|
#include "lbmlib.h" |
||||
|
#include "mathlib.h" |
||||
|
|
||||
|
#endif |
||||
|
|
||||
|
#define ALIAS_VERSION 6 |
||||
|
|
||||
|
#define ALIAS_ONSEAM 0x0020 |
||||
|
|
||||
|
// must match definition in spritegn.h |
||||
|
#ifndef SYNCTYPE_T |
||||
|
#define SYNCTYPE_T |
||||
|
typedef enum {ST_SYNC=0, ST_RAND } synctype_t; |
||||
|
#endif |
||||
|
|
||||
|
typedef enum { ALIAS_SINGLE=0, ALIAS_GROUP } aliasframetype_t; |
||||
|
|
||||
|
typedef enum { ALIAS_SKIN_SINGLE=0, ALIAS_SKIN_GROUP } aliasskintype_t; |
||||
|
|
||||
|
typedef struct { |
||||
|
int ident; |
||||
|
int version; |
||||
|
vec3_t scale; |
||||
|
vec3_t scale_origin; |
||||
|
float boundingradius; |
||||
|
vec3_t eyeposition; |
||||
|
int numskins; |
||||
|
int skinwidth; |
||||
|
int skinheight; |
||||
|
int numverts; |
||||
|
int numtris; |
||||
|
int numframes; |
||||
|
synctype_t synctype; |
||||
|
int flags; |
||||
|
float size; |
||||
|
} mdl_t; |
||||
|
|
||||
|
// TODO: could be shorts |
||||
|
|
||||
|
typedef struct { |
||||
|
int onseam; |
||||
|
int s; |
||||
|
int t; |
||||
|
} stvert_t; |
||||
|
|
||||
|
typedef struct dtriangle_s { |
||||
|
int facesfront; |
||||
|
int vertindex[3]; |
||||
|
} dtriangle_t; |
||||
|
|
||||
|
#define DT_FACES_FRONT 0x0010 |
||||
|
|
||||
|
// This mirrors trivert_t in trilib.h, is present so Quake knows how to |
||||
|
// load this data |
||||
|
|
||||
|
typedef struct { |
||||
|
byte v[3]; |
||||
|
byte lightnormalindex; |
||||
|
} trivertx_t; |
||||
|
|
||||
|
typedef struct { |
||||
|
trivertx_t bboxmin; // lightnormal isn't used |
||||
|
trivertx_t bboxmax; // lightnormal isn't used |
||||
|
char name[16]; // frame name from grabbing |
||||
|
} daliasframe_t; |
||||
|
|
||||
|
typedef struct { |
||||
|
int numframes; |
||||
|
trivertx_t bboxmin; // lightnormal isn't used |
||||
|
trivertx_t bboxmax; // lightnormal isn't used |
||||
|
} daliasgroup_t; |
||||
|
|
||||
|
typedef struct { |
||||
|
int numskins; |
||||
|
} daliasskingroup_t; |
||||
|
|
||||
|
typedef struct { |
||||
|
float interval; |
||||
|
} daliasinterval_t; |
||||
|
|
||||
|
typedef struct { |
||||
|
float interval; |
||||
|
} daliasskininterval_t; |
||||
|
|
||||
|
typedef struct { |
||||
|
aliasframetype_t type; |
||||
|
} daliasframetype_t; |
||||
|
|
||||
|
typedef struct { |
||||
|
aliasskintype_t type; |
||||
|
} daliasskintype_t; |
||||
|
|
||||
|
#define IDPOLYHEADER (('O'<<24)+('P'<<16)+('D'<<8)+'I') |
||||
|
// little-endian "IDPO" |
||||
|
|
||||
@ -0,0 +1,337 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// net.h -- quake's interface to the networking layer |
||||
|
|
||||
|
struct qsockaddr |
||||
|
{ |
||||
|
short sa_family; |
||||
|
unsigned char sa_data[14]; |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
#define NET_NAMELEN 64 |
||||
|
|
||||
|
#define NET_MAXMESSAGE 8192 |
||||
|
#define NET_HEADERSIZE (2 * sizeof(unsigned int)) |
||||
|
#define NET_DATAGRAMSIZE (MAX_DATAGRAM + NET_HEADERSIZE) |
||||
|
|
||||
|
// NetHeader flags |
||||
|
#define NETFLAG_LENGTH_MASK 0x0000ffff |
||||
|
#define NETFLAG_DATA 0x00010000 |
||||
|
#define NETFLAG_ACK 0x00020000 |
||||
|
#define NETFLAG_NAK 0x00040000 |
||||
|
#define NETFLAG_EOM 0x00080000 |
||||
|
#define NETFLAG_UNRELIABLE 0x00100000 |
||||
|
#define NETFLAG_CTL 0x80000000 |
||||
|
|
||||
|
|
||||
|
#define NET_PROTOCOL_VERSION 3 |
||||
|
|
||||
|
// This is the network info/connection protocol. It is used to find Quake |
||||
|
// servers, get info about them, and connect to them. Once connected, the |
||||
|
// Quake game protocol (documented elsewhere) is used. |
||||
|
// |
||||
|
// |
||||
|
// General notes: |
||||
|
// game_name is currently always "QUAKE", but is there so this same protocol |
||||
|
// can be used for future games as well; can you say Quake2? |
||||
|
// |
||||
|
// CCREQ_CONNECT |
||||
|
// string game_name "QUAKE" |
||||
|
// byte net_protocol_version NET_PROTOCOL_VERSION |
||||
|
// |
||||
|
// CCREQ_SERVER_INFO |
||||
|
// string game_name "QUAKE" |
||||
|
// byte net_protocol_version NET_PROTOCOL_VERSION |
||||
|
// |
||||
|
// CCREQ_PLAYER_INFO |
||||
|
// byte player_number |
||||
|
// |
||||
|
// CCREQ_RULE_INFO |
||||
|
// string rule |
||||
|
// |
||||
|
// |
||||
|
// |
||||
|
// CCREP_ACCEPT |
||||
|
// long port |
||||
|
// |
||||
|
// CCREP_REJECT |
||||
|
// string reason |
||||
|
// |
||||
|
// CCREP_SERVER_INFO |
||||
|
// string server_address |
||||
|
// string host_name |
||||
|
// string level_name |
||||
|
// byte current_players |
||||
|
// byte max_players |
||||
|
// byte protocol_version NET_PROTOCOL_VERSION |
||||
|
// |
||||
|
// CCREP_PLAYER_INFO |
||||
|
// byte player_number |
||||
|
// string name |
||||
|
// long colors |
||||
|
// long frags |
||||
|
// long connect_time |
||||
|
// string address |
||||
|
// |
||||
|
// CCREP_RULE_INFO |
||||
|
// string rule |
||||
|
// string value |
||||
|
|
||||
|
// note: |
||||
|
// There are two address forms used above. The short form is just a |
||||
|
// port number. The address that goes along with the port is defined as |
||||
|
// "whatever address you receive this reponse from". This lets us use |
||||
|
// the host OS to solve the problem of multiple host addresses (possibly |
||||
|
// with no routing between them); the host will use the right address |
||||
|
// when we reply to the inbound connection request. The long from is |
||||
|
// a full address and port in a string. It is used for returning the |
||||
|
// address of a server that is not running locally. |
||||
|
|
||||
|
#define CCREQ_CONNECT 0x01 |
||||
|
#define CCREQ_SERVER_INFO 0x02 |
||||
|
#define CCREQ_PLAYER_INFO 0x03 |
||||
|
#define CCREQ_RULE_INFO 0x04 |
||||
|
|
||||
|
#define CCREP_ACCEPT 0x81 |
||||
|
#define CCREP_REJECT 0x82 |
||||
|
#define CCREP_SERVER_INFO 0x83 |
||||
|
#define CCREP_PLAYER_INFO 0x84 |
||||
|
#define CCREP_RULE_INFO 0x85 |
||||
|
|
||||
|
typedef struct qsocket_s |
||||
|
{ |
||||
|
struct qsocket_s *next; |
||||
|
double connecttime; |
||||
|
double lastMessageTime; |
||||
|
double lastSendTime; |
||||
|
|
||||
|
qboolean disconnected; |
||||
|
qboolean canSend; |
||||
|
qboolean sendNext; |
||||
|
|
||||
|
int driver; |
||||
|
int landriver; |
||||
|
int socket; |
||||
|
void *driverdata; |
||||
|
|
||||
|
unsigned int ackSequence; |
||||
|
unsigned int sendSequence; |
||||
|
unsigned int unreliableSendSequence; |
||||
|
int sendMessageLength; |
||||
|
byte sendMessage [NET_MAXMESSAGE]; |
||||
|
|
||||
|
unsigned int receiveSequence; |
||||
|
unsigned int unreliableReceiveSequence; |
||||
|
int receiveMessageLength; |
||||
|
byte receiveMessage [NET_MAXMESSAGE]; |
||||
|
|
||||
|
struct qsockaddr addr; |
||||
|
char address[NET_NAMELEN]; |
||||
|
|
||||
|
} qsocket_t; |
||||
|
|
||||
|
extern qsocket_t *net_activeSockets; |
||||
|
extern qsocket_t *net_freeSockets; |
||||
|
extern int net_numsockets; |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
char *name; |
||||
|
qboolean initialized; |
||||
|
int controlSock; |
||||
|
int (*Init) (void); |
||||
|
void (*Shutdown) (void); |
||||
|
void (*Listen) (qboolean state); |
||||
|
int (*OpenSocket) (int port); |
||||
|
int (*CloseSocket) (int socket); |
||||
|
int (*Connect) (int socket, struct qsockaddr *addr); |
||||
|
int (*CheckNewConnections) (void); |
||||
|
int (*Read) (int socket, byte *buf, int len, struct qsockaddr *addr); |
||||
|
int (*Write) (int socket, byte *buf, int len, struct qsockaddr *addr); |
||||
|
int (*Broadcast) (int socket, byte *buf, int len); |
||||
|
char * (*AddrToString) (struct qsockaddr *addr); |
||||
|
int (*StringToAddr) (char *string, struct qsockaddr *addr); |
||||
|
int (*GetSocketAddr) (int socket, struct qsockaddr *addr); |
||||
|
int (*GetNameFromAddr) (struct qsockaddr *addr, char *name); |
||||
|
int (*GetAddrFromName) (char *name, struct qsockaddr *addr); |
||||
|
int (*AddrCompare) (struct qsockaddr *addr1, struct qsockaddr *addr2); |
||||
|
int (*GetSocketPort) (struct qsockaddr *addr); |
||||
|
int (*SetSocketPort) (struct qsockaddr *addr, int port); |
||||
|
} net_landriver_t; |
||||
|
|
||||
|
#define MAX_NET_DRIVERS 8 |
||||
|
extern int net_numlandrivers; |
||||
|
extern net_landriver_t net_landrivers[MAX_NET_DRIVERS]; |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
char *name; |
||||
|
qboolean initialized; |
||||
|
int (*Init) (void); |
||||
|
void (*Listen) (qboolean state); |
||||
|
void (*SearchForHosts) (qboolean xmit); |
||||
|
qsocket_t *(*Connect) (char *host); |
||||
|
qsocket_t *(*CheckNewConnections) (void); |
||||
|
int (*QGetMessage) (qsocket_t *sock); |
||||
|
int (*QSendMessage) (qsocket_t *sock, sizebuf_t *data); |
||||
|
int (*SendUnreliableMessage) (qsocket_t *sock, sizebuf_t *data); |
||||
|
qboolean (*CanSendMessage) (qsocket_t *sock); |
||||
|
qboolean (*CanSendUnreliableMessage) (qsocket_t *sock); |
||||
|
void (*Close) (qsocket_t *sock); |
||||
|
void (*Shutdown) (void); |
||||
|
int controlSock; |
||||
|
} net_driver_t; |
||||
|
|
||||
|
extern int net_numdrivers; |
||||
|
extern net_driver_t net_drivers[MAX_NET_DRIVERS]; |
||||
|
|
||||
|
extern int DEFAULTnet_hostport; |
||||
|
extern int net_hostport; |
||||
|
|
||||
|
extern int net_driverlevel; |
||||
|
extern cvar_t hostname; |
||||
|
extern char playername[]; |
||||
|
extern int playercolor; |
||||
|
|
||||
|
extern int messagesSent; |
||||
|
extern int messagesReceived; |
||||
|
extern int unreliableMessagesSent; |
||||
|
extern int unreliableMessagesReceived; |
||||
|
|
||||
|
qsocket_t *NET_NewQSocket (void); |
||||
|
void NET_FreeQSocket(qsocket_t *); |
||||
|
double SetNetTime(void); |
||||
|
|
||||
|
|
||||
|
#define HOSTCACHESIZE 8 |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
char name[16]; |
||||
|
char map[16]; |
||||
|
char cname[32]; |
||||
|
int users; |
||||
|
int maxusers; |
||||
|
int driver; |
||||
|
int ldriver; |
||||
|
struct qsockaddr addr; |
||||
|
} hostcache_t; |
||||
|
|
||||
|
extern int hostCacheCount; |
||||
|
extern hostcache_t hostcache[HOSTCACHESIZE]; |
||||
|
|
||||
|
#if !defined(_WIN32 ) && !defined (__linux__) && !defined (__sun__) |
||||
|
#ifndef htonl |
||||
|
extern unsigned long htonl (unsigned long hostlong); |
||||
|
#endif |
||||
|
#ifndef htons |
||||
|
extern unsigned short htons (unsigned short hostshort); |
||||
|
#endif |
||||
|
#ifndef ntohl |
||||
|
extern unsigned long ntohl (unsigned long netlong); |
||||
|
#endif |
||||
|
#ifndef ntohs |
||||
|
extern unsigned short ntohs (unsigned short netshort); |
||||
|
#endif |
||||
|
#endif |
||||
|
|
||||
|
#ifdef IDGODS |
||||
|
qboolean IsID(struct qsockaddr *addr); |
||||
|
#endif |
||||
|
|
||||
|
//============================================================================ |
||||
|
// |
||||
|
// public network functions |
||||
|
// |
||||
|
//============================================================================ |
||||
|
|
||||
|
extern double net_time; |
||||
|
extern sizebuf_t net_message; |
||||
|
extern int net_activeconnections; |
||||
|
|
||||
|
void NET_Init (void); |
||||
|
void NET_Shutdown (void); |
||||
|
|
||||
|
struct qsocket_s *NET_CheckNewConnections (void); |
||||
|
// returns a new connection number if there is one pending, else -1 |
||||
|
|
||||
|
struct qsocket_s *NET_Connect (char *host); |
||||
|
// called by client to connect to a host. Returns -1 if not able to |
||||
|
|
||||
|
qboolean NET_CanSendMessage (qsocket_t *sock); |
||||
|
// Returns true or false if the given qsocket can currently accept a |
||||
|
// message to be transmitted. |
||||
|
|
||||
|
int NET_GetMessage (struct qsocket_s *sock); |
||||
|
// returns data in net_message sizebuf |
||||
|
// returns 0 if no data is waiting |
||||
|
// returns 1 if a message was received |
||||
|
// returns 2 if an unreliable message was received |
||||
|
// returns -1 if the connection died |
||||
|
|
||||
|
int NET_SendMessage (struct qsocket_s *sock, sizebuf_t *data); |
||||
|
int NET_SendUnreliableMessage (struct qsocket_s *sock, sizebuf_t *data); |
||||
|
// returns 0 if the message connot be delivered reliably, but the connection |
||||
|
// is still considered valid |
||||
|
// returns 1 if the message was sent properly |
||||
|
// returns -1 if the connection died |
||||
|
|
||||
|
int NET_SendToAll(sizebuf_t *data, int blocktime); |
||||
|
// This is a reliable *blocking* send to all attached clients. |
||||
|
|
||||
|
|
||||
|
void NET_Close (struct qsocket_s *sock); |
||||
|
// if a dead connection is returned by a get or send function, this function |
||||
|
// should be called when it is convenient |
||||
|
|
||||
|
// Server calls when a client is kicked off for a game related misbehavior |
||||
|
// like an illegal protocal conversation. Client calls when disconnecting |
||||
|
// from a server. |
||||
|
// A netcon_t number will not be reused until this function is called for it |
||||
|
|
||||
|
void NET_Poll(void); |
||||
|
|
||||
|
|
||||
|
typedef struct _PollProcedure |
||||
|
{ |
||||
|
struct _PollProcedure *next; |
||||
|
double nextTime; |
||||
|
void (*procedure)(); |
||||
|
void *arg; |
||||
|
} PollProcedure; |
||||
|
|
||||
|
void SchedulePollProcedure(PollProcedure *pp, double timeOffset); |
||||
|
|
||||
|
extern qboolean serialAvailable; |
||||
|
extern qboolean ipxAvailable; |
||||
|
extern qboolean tcpipAvailable; |
||||
|
extern char my_ipx_address[NET_NAMELEN]; |
||||
|
extern char my_tcpip_address[NET_NAMELEN]; |
||||
|
extern void (*GetComPortConfig) (int portNumber, int *port, int *irq, int *baud, qboolean *useModem); |
||||
|
extern void (*SetComPortConfig) (int portNumber, int port, int irq, int baud, qboolean useModem); |
||||
|
extern void (*GetModemConfig) (int portNumber, char *dialType, char *clear, char *init, char *hangup); |
||||
|
extern void (*SetModemConfig) (int portNumber, char *dialType, char *clear, char *init, char *hangup); |
||||
|
|
||||
|
extern qboolean slistInProgress; |
||||
|
extern qboolean slistSilent; |
||||
|
extern qboolean slistLocal; |
||||
|
|
||||
|
void NET_Slist_f (void); |
||||
1390
engine/code/net_dgrm.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,34 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// net_dgrm.h |
||||
|
|
||||
|
|
||||
|
int Datagram_Init (void); |
||||
|
void Datagram_Listen (qboolean state); |
||||
|
void Datagram_SearchForHosts (qboolean xmit); |
||||
|
qsocket_t *Datagram_Connect (char *host); |
||||
|
qsocket_t *Datagram_CheckNewConnections (void); |
||||
|
int Datagram_GetMessage (qsocket_t *sock); |
||||
|
int Datagram_SendMessage (qsocket_t *sock, sizebuf_t *data); |
||||
|
int Datagram_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data); |
||||
|
qboolean Datagram_CanSendMessage (qsocket_t *sock); |
||||
|
qboolean Datagram_CanSendUnreliableMessage (qsocket_t *sock); |
||||
|
void Datagram_Close (qsocket_t *sock); |
||||
|
void Datagram_Shutdown (void); |
||||
@ -0,0 +1,245 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// net_loop.c |
||||
|
|
||||
|
#include "quakedef.h" |
||||
|
#include "net_loop.h" |
||||
|
|
||||
|
qboolean localconnectpending = false; |
||||
|
qsocket_t *loop_client = NULL; |
||||
|
qsocket_t *loop_server = NULL; |
||||
|
|
||||
|
int Loop_Init (void) |
||||
|
{ |
||||
|
if (cls.state == ca_dedicated) |
||||
|
return -1; |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void Loop_Shutdown (void) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void Loop_Listen (qboolean state) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void Loop_SearchForHosts (qboolean xmit) |
||||
|
{ |
||||
|
if (!sv.active) |
||||
|
return; |
||||
|
|
||||
|
hostCacheCount = 1; |
||||
|
if (Q_strcmp(hostname.string, "UNNAMED") == 0) |
||||
|
Q_strcpy(hostcache[0].name, "local"); |
||||
|
else |
||||
|
Q_strcpy(hostcache[0].name, hostname.string); |
||||
|
Q_strcpy(hostcache[0].map, sv.name); |
||||
|
hostcache[0].users = net_activeconnections; |
||||
|
hostcache[0].maxusers = svs.maxclients; |
||||
|
hostcache[0].driver = net_driverlevel; |
||||
|
Q_strcpy(hostcache[0].cname, "local"); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
qsocket_t *Loop_Connect (char *host) |
||||
|
{ |
||||
|
if (Q_strcmp(host,"local") != 0) |
||||
|
return NULL; |
||||
|
|
||||
|
localconnectpending = true; |
||||
|
|
||||
|
if (!loop_client) |
||||
|
{ |
||||
|
if ((loop_client = NET_NewQSocket ()) == NULL) |
||||
|
{ |
||||
|
Con_Printf("Loop_Connect: no qsocket available\n"); |
||||
|
return NULL; |
||||
|
} |
||||
|
Q_strcpy (loop_client->address, "localhost"); |
||||
|
} |
||||
|
loop_client->receiveMessageLength = 0; |
||||
|
loop_client->sendMessageLength = 0; |
||||
|
loop_client->canSend = true; |
||||
|
|
||||
|
if (!loop_server) |
||||
|
{ |
||||
|
if ((loop_server = NET_NewQSocket ()) == NULL) |
||||
|
{ |
||||
|
Con_Printf("Loop_Connect: no qsocket available\n"); |
||||
|
return NULL; |
||||
|
} |
||||
|
Q_strcpy (loop_server->address, "LOCAL"); |
||||
|
} |
||||
|
loop_server->receiveMessageLength = 0; |
||||
|
loop_server->sendMessageLength = 0; |
||||
|
loop_server->canSend = true; |
||||
|
|
||||
|
loop_client->driverdata = (void *)loop_server; |
||||
|
loop_server->driverdata = (void *)loop_client; |
||||
|
|
||||
|
return loop_client; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
qsocket_t *Loop_CheckNewConnections (void) |
||||
|
{ |
||||
|
if (!localconnectpending) |
||||
|
return NULL; |
||||
|
|
||||
|
localconnectpending = false; |
||||
|
loop_server->sendMessageLength = 0; |
||||
|
loop_server->receiveMessageLength = 0; |
||||
|
loop_server->canSend = true; |
||||
|
loop_client->sendMessageLength = 0; |
||||
|
loop_client->receiveMessageLength = 0; |
||||
|
loop_client->canSend = true; |
||||
|
return loop_server; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
static int IntAlign(int value) |
||||
|
{ |
||||
|
return (value + (sizeof(int) - 1)) & (~(sizeof(int) - 1)); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
int Loop_GetMessage (qsocket_t *sock) |
||||
|
{ |
||||
|
int ret; |
||||
|
int length; |
||||
|
|
||||
|
if (sock->receiveMessageLength == 0) |
||||
|
return 0; |
||||
|
|
||||
|
ret = sock->receiveMessage[0]; |
||||
|
length = sock->receiveMessage[1] + (sock->receiveMessage[2] << 8); |
||||
|
// alignment byte skipped here |
||||
|
SZ_Clear (&net_message); |
||||
|
SZ_Write (&net_message, &sock->receiveMessage[4], length); |
||||
|
|
||||
|
length = IntAlign(length + 4); |
||||
|
sock->receiveMessageLength -= length; |
||||
|
|
||||
|
if (sock->receiveMessageLength) |
||||
|
Q_memcpy(sock->receiveMessage, &sock->receiveMessage[length], sock->receiveMessageLength); |
||||
|
|
||||
|
if (sock->driverdata && ret == 1) |
||||
|
((qsocket_t *)sock->driverdata)->canSend = true; |
||||
|
|
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
int Loop_SendMessage (qsocket_t *sock, sizebuf_t *data) |
||||
|
{ |
||||
|
byte *buffer; |
||||
|
int *bufferLength; |
||||
|
|
||||
|
if (!sock->driverdata) |
||||
|
return -1; |
||||
|
|
||||
|
bufferLength = &((qsocket_t *)sock->driverdata)->receiveMessageLength; |
||||
|
|
||||
|
if ((*bufferLength + data->cursize + 4) > NET_MAXMESSAGE) |
||||
|
Sys_Error("Loop_SendMessage: overflow\n"); |
||||
|
|
||||
|
buffer = ((qsocket_t *)sock->driverdata)->receiveMessage + *bufferLength; |
||||
|
|
||||
|
// message type |
||||
|
*buffer++ = 1; |
||||
|
|
||||
|
// length |
||||
|
*buffer++ = data->cursize & 0xff; |
||||
|
*buffer++ = data->cursize >> 8; |
||||
|
|
||||
|
// align |
||||
|
buffer++; |
||||
|
|
||||
|
// message |
||||
|
Q_memcpy(buffer, data->data, data->cursize); |
||||
|
*bufferLength = IntAlign(*bufferLength + data->cursize + 4); |
||||
|
|
||||
|
sock->canSend = false; |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
int Loop_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data) |
||||
|
{ |
||||
|
byte *buffer; |
||||
|
int *bufferLength; |
||||
|
|
||||
|
if (!sock->driverdata) |
||||
|
return -1; |
||||
|
|
||||
|
bufferLength = &((qsocket_t *)sock->driverdata)->receiveMessageLength; |
||||
|
|
||||
|
if ((*bufferLength + data->cursize + sizeof(byte) + sizeof(short)) > NET_MAXMESSAGE) |
||||
|
return 0; |
||||
|
|
||||
|
buffer = ((qsocket_t *)sock->driverdata)->receiveMessage + *bufferLength; |
||||
|
|
||||
|
// message type |
||||
|
*buffer++ = 2; |
||||
|
|
||||
|
// length |
||||
|
*buffer++ = data->cursize & 0xff; |
||||
|
*buffer++ = data->cursize >> 8; |
||||
|
|
||||
|
// align |
||||
|
buffer++; |
||||
|
|
||||
|
// message |
||||
|
Q_memcpy(buffer, data->data, data->cursize); |
||||
|
*bufferLength = IntAlign(*bufferLength + data->cursize + 4); |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
qboolean Loop_CanSendMessage (qsocket_t *sock) |
||||
|
{ |
||||
|
if (!sock->driverdata) |
||||
|
return false; |
||||
|
return sock->canSend; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
qboolean Loop_CanSendUnreliableMessage (qsocket_t *sock) |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void Loop_Close (qsocket_t *sock) |
||||
|
{ |
||||
|
if (sock->driverdata) |
||||
|
((qsocket_t *)sock->driverdata)->driverdata = NULL; |
||||
|
sock->receiveMessageLength = 0; |
||||
|
sock->sendMessageLength = 0; |
||||
|
sock->canSend = true; |
||||
|
if (sock == loop_client) |
||||
|
loop_client = NULL; |
||||
|
else |
||||
|
loop_server = NULL; |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// net_loop.h |
||||
|
|
||||
|
int Loop_Init (void); |
||||
|
void Loop_Listen (qboolean state); |
||||
|
void Loop_SearchForHosts (qboolean xmit); |
||||
|
qsocket_t *Loop_Connect (char *host); |
||||
|
qsocket_t *Loop_CheckNewConnections (void); |
||||
|
int Loop_GetMessage (qsocket_t *sock); |
||||
|
int Loop_SendMessage (qsocket_t *sock, sizebuf_t *data); |
||||
|
int Loop_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data); |
||||
|
qboolean Loop_CanSendMessage (qsocket_t *sock); |
||||
|
qboolean Loop_CanSendUnreliableMessage (qsocket_t *sock); |
||||
|
void Loop_Close (qsocket_t *sock); |
||||
|
void Loop_Shutdown (void); |
||||
1012
engine/code/net_main.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,167 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// net_vcr.c |
||||
|
|
||||
|
#include "quakedef.h" |
||||
|
#include "net_vcr.h" |
||||
|
|
||||
|
extern int vcrFile; |
||||
|
|
||||
|
// This is the playback portion of the VCR. It reads the file produced |
||||
|
// by the recorder and plays it back to the host. The recording contains |
||||
|
// everything necessary (events, timestamps, and data) to duplicate the game |
||||
|
// from the viewpoint of everything above the network layer. |
||||
|
|
||||
|
static struct |
||||
|
{ |
||||
|
double time; |
||||
|
int op; |
||||
|
long session; |
||||
|
} next; |
||||
|
|
||||
|
int VCR_Init (void) |
||||
|
{ |
||||
|
net_drivers[0].Init = VCR_Init; |
||||
|
|
||||
|
net_drivers[0].SearchForHosts = VCR_SearchForHosts; |
||||
|
net_drivers[0].Connect = VCR_Connect; |
||||
|
net_drivers[0].CheckNewConnections = VCR_CheckNewConnections; |
||||
|
net_drivers[0].QGetMessage = VCR_GetMessage; |
||||
|
net_drivers[0].QSendMessage = VCR_SendMessage; |
||||
|
net_drivers[0].CanSendMessage = VCR_CanSendMessage; |
||||
|
net_drivers[0].Close = VCR_Close; |
||||
|
net_drivers[0].Shutdown = VCR_Shutdown; |
||||
|
|
||||
|
Sys_FileRead(vcrFile, &next, sizeof(next)); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
void VCR_ReadNext (void) |
||||
|
{ |
||||
|
if (Sys_FileRead(vcrFile, &next, sizeof(next)) == 0) |
||||
|
{ |
||||
|
next.op = 255; |
||||
|
Sys_Error ("=== END OF PLAYBACK===\n"); |
||||
|
} |
||||
|
if (next.op < 1 || next.op > VCR_MAX_MESSAGE) |
||||
|
Sys_Error ("VCR_ReadNext: bad op"); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void VCR_Listen (qboolean state) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void VCR_Shutdown (void) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
|
||||
|
int VCR_GetMessage (qsocket_t *sock) |
||||
|
{ |
||||
|
int ret; |
||||
|
|
||||
|
if (host_time != next.time || next.op != VCR_OP_GETMESSAGE || next.session != *(long *)(&sock->driverdata)) |
||||
|
Sys_Error ("VCR missmatch"); |
||||
|
|
||||
|
Sys_FileRead(vcrFile, &ret, sizeof(int)); |
||||
|
if (ret != 1) |
||||
|
{ |
||||
|
VCR_ReadNext (); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
Sys_FileRead(vcrFile, &net_message.cursize, sizeof(int)); |
||||
|
Sys_FileRead(vcrFile, net_message.data, net_message.cursize); |
||||
|
|
||||
|
VCR_ReadNext (); |
||||
|
|
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
int VCR_SendMessage (qsocket_t *sock, sizebuf_t *data) |
||||
|
{ |
||||
|
int ret; |
||||
|
|
||||
|
if (host_time != next.time || next.op != VCR_OP_SENDMESSAGE || next.session != *(long *)(&sock->driverdata)) |
||||
|
Sys_Error ("VCR missmatch"); |
||||
|
|
||||
|
Sys_FileRead(vcrFile, &ret, sizeof(int)); |
||||
|
|
||||
|
VCR_ReadNext (); |
||||
|
|
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
qboolean VCR_CanSendMessage (qsocket_t *sock) |
||||
|
{ |
||||
|
qboolean ret; |
||||
|
|
||||
|
if (host_time != next.time || next.op != VCR_OP_CANSENDMESSAGE || next.session != *(long *)(&sock->driverdata)) |
||||
|
Sys_Error ("VCR missmatch"); |
||||
|
|
||||
|
Sys_FileRead(vcrFile, &ret, sizeof(int)); |
||||
|
|
||||
|
VCR_ReadNext (); |
||||
|
|
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void VCR_Close (qsocket_t *sock) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void VCR_SearchForHosts (qboolean xmit) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
|
||||
|
qsocket_t *VCR_Connect (char *host) |
||||
|
{ |
||||
|
return NULL; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
qsocket_t *VCR_CheckNewConnections (void) |
||||
|
{ |
||||
|
qsocket_t *sock; |
||||
|
|
||||
|
if (host_time != next.time || next.op != VCR_OP_CONNECT) |
||||
|
Sys_Error ("VCR missmatch"); |
||||
|
|
||||
|
if (!next.session) |
||||
|
{ |
||||
|
VCR_ReadNext (); |
||||
|
return NULL; |
||||
|
} |
||||
|
|
||||
|
sock = NET_NewQSocket (); |
||||
|
*(long *)(&sock->driverdata) = next.session; |
||||
|
|
||||
|
Sys_FileRead (vcrFile, sock->address, NET_NAMELEN); |
||||
|
VCR_ReadNext (); |
||||
|
|
||||
|
return sock; |
||||
|
} |
||||
@ -0,0 +1,37 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// net_vcr.h |
||||
|
|
||||
|
#define VCR_OP_CONNECT 1 |
||||
|
#define VCR_OP_GETMESSAGE 2 |
||||
|
#define VCR_OP_SENDMESSAGE 3 |
||||
|
#define VCR_OP_CANSENDMESSAGE 4 |
||||
|
#define VCR_MAX_MESSAGE 4 |
||||
|
|
||||
|
int VCR_Init (void); |
||||
|
void VCR_Listen (qboolean state); |
||||
|
void VCR_SearchForHosts (qboolean xmit); |
||||
|
qsocket_t *VCR_Connect (char *host); |
||||
|
qsocket_t *VCR_CheckNewConnections (void); |
||||
|
int VCR_GetMessage (qsocket_t *sock); |
||||
|
int VCR_SendMessage (qsocket_t *sock, sizebuf_t *data); |
||||
|
qboolean VCR_CanSendMessage (qsocket_t *sock); |
||||
|
void VCR_Close (qsocket_t *sock); |
||||
|
void VCR_Shutdown (void); |
||||
@ -0,0 +1,120 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
#include "quakedef.h" |
||||
|
|
||||
|
#include "net_loop.h" |
||||
|
#include "net_dgrm.h" |
||||
|
//#include "net_ser.h" |
||||
|
|
||||
|
net_driver_t net_drivers[MAX_NET_DRIVERS] = |
||||
|
{ |
||||
|
{ |
||||
|
"Loopback", |
||||
|
false, |
||||
|
Loop_Init, |
||||
|
Loop_Listen, |
||||
|
Loop_SearchForHosts, |
||||
|
Loop_Connect, |
||||
|
Loop_CheckNewConnections, |
||||
|
Loop_GetMessage, |
||||
|
Loop_SendMessage, |
||||
|
Loop_SendUnreliableMessage, |
||||
|
Loop_CanSendMessage, |
||||
|
Loop_CanSendUnreliableMessage, |
||||
|
Loop_Close, |
||||
|
Loop_Shutdown |
||||
|
} |
||||
|
, |
||||
|
{ |
||||
|
"Datagram", |
||||
|
false, |
||||
|
Datagram_Init, |
||||
|
Datagram_Listen, |
||||
|
Datagram_SearchForHosts, |
||||
|
Datagram_Connect, |
||||
|
Datagram_CheckNewConnections, |
||||
|
Datagram_GetMessage, |
||||
|
Datagram_SendMessage, |
||||
|
Datagram_SendUnreliableMessage, |
||||
|
Datagram_CanSendMessage, |
||||
|
Datagram_CanSendUnreliableMessage, |
||||
|
Datagram_Close, |
||||
|
Datagram_Shutdown |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
int net_numdrivers = 2; |
||||
|
|
||||
|
|
||||
|
#include "net_wins.h" |
||||
|
#include "net_wipx.h" |
||||
|
|
||||
|
net_landriver_t net_landrivers[MAX_NET_DRIVERS] = |
||||
|
{ |
||||
|
{ |
||||
|
"Winsock TCPIP", |
||||
|
false, |
||||
|
0, |
||||
|
WINS_Init, |
||||
|
WINS_Shutdown, |
||||
|
WINS_Listen, |
||||
|
WINS_OpenSocket, |
||||
|
WINS_CloseSocket, |
||||
|
WINS_Connect, |
||||
|
WINS_CheckNewConnections, |
||||
|
WINS_Read, |
||||
|
WINS_Write, |
||||
|
WINS_Broadcast, |
||||
|
WINS_AddrToString, |
||||
|
WINS_StringToAddr, |
||||
|
WINS_GetSocketAddr, |
||||
|
WINS_GetNameFromAddr, |
||||
|
WINS_GetAddrFromName, |
||||
|
WINS_AddrCompare, |
||||
|
WINS_GetSocketPort, |
||||
|
WINS_SetSocketPort |
||||
|
}, |
||||
|
{ |
||||
|
"Winsock IPX", |
||||
|
false, |
||||
|
0, |
||||
|
WIPX_Init, |
||||
|
WIPX_Shutdown, |
||||
|
WIPX_Listen, |
||||
|
WIPX_OpenSocket, |
||||
|
WIPX_CloseSocket, |
||||
|
WIPX_Connect, |
||||
|
WIPX_CheckNewConnections, |
||||
|
WIPX_Read, |
||||
|
WIPX_Write, |
||||
|
WIPX_Broadcast, |
||||
|
WIPX_AddrToString, |
||||
|
WIPX_StringToAddr, |
||||
|
WIPX_GetSocketAddr, |
||||
|
WIPX_GetNameFromAddr, |
||||
|
WIPX_GetAddrFromName, |
||||
|
WIPX_AddrCompare, |
||||
|
WIPX_GetSocketPort, |
||||
|
WIPX_SetSocketPort |
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
int net_numlandrivers = 2; |
||||
@ -0,0 +1,580 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// net_wins.c |
||||
|
|
||||
|
#include "quakedef.h" |
||||
|
#include "winquake.h" |
||||
|
|
||||
|
extern cvar_t hostname; |
||||
|
|
||||
|
#define MAXHOSTNAMELEN 256 |
||||
|
|
||||
|
static int net_acceptsocket = -1; // socket for fielding new connections |
||||
|
static int net_controlsocket; |
||||
|
static int net_broadcastsocket = 0; |
||||
|
static struct qsockaddr broadcastaddr; |
||||
|
|
||||
|
static unsigned long myAddr; |
||||
|
|
||||
|
qboolean winsock_lib_initialized; |
||||
|
|
||||
|
int (PASCAL FAR *pWSAStartup)(WORD wVersionRequired, LPWSADATA lpWSAData); |
||||
|
int (PASCAL FAR *pWSACleanup)(void); |
||||
|
int (PASCAL FAR *pWSAGetLastError)(void); |
||||
|
SOCKET (PASCAL FAR *psocket)(int af, int type, int protocol); |
||||
|
int (PASCAL FAR *pioctlsocket)(SOCKET s, long cmd, u_long FAR *argp); |
||||
|
int (PASCAL FAR *psetsockopt)(SOCKET s, int level, int optname, |
||||
|
const char FAR * optval, int optlen); |
||||
|
int (PASCAL FAR *precvfrom)(SOCKET s, char FAR * buf, int len, int flags, |
||||
|
struct sockaddr FAR *from, int FAR * fromlen); |
||||
|
int (PASCAL FAR *psendto)(SOCKET s, const char FAR * buf, int len, int flags, |
||||
|
const struct sockaddr FAR *to, int tolen); |
||||
|
int (PASCAL FAR *pclosesocket)(SOCKET s); |
||||
|
int (PASCAL FAR *pgethostname)(char FAR * name, int namelen); |
||||
|
struct hostent FAR * (PASCAL FAR *pgethostbyname)(const char FAR * name); |
||||
|
struct hostent FAR * (PASCAL FAR *pgethostbyaddr)(const char FAR * addr, |
||||
|
int len, int type); |
||||
|
int (PASCAL FAR *pgetsockname)(SOCKET s, struct sockaddr FAR *name, |
||||
|
int FAR * namelen); |
||||
|
|
||||
|
#include "net_wins.h" |
||||
|
|
||||
|
int winsock_initialized = 0; |
||||
|
WSADATA winsockdata; |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
static double blocktime; |
||||
|
|
||||
|
BOOL PASCAL FAR BlockingHook(void) |
||||
|
{ |
||||
|
MSG msg; |
||||
|
BOOL ret; |
||||
|
|
||||
|
if ((Sys_FloatTime() - blocktime) > 2.0) |
||||
|
{ |
||||
|
WSACancelBlockingCall(); |
||||
|
return FALSE; |
||||
|
} |
||||
|
|
||||
|
/* get the next message, if any */ |
||||
|
ret = (BOOL) PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); |
||||
|
|
||||
|
/* if we got one, process it */ |
||||
|
if (ret) { |
||||
|
TranslateMessage(&msg); |
||||
|
DispatchMessage(&msg); |
||||
|
} |
||||
|
|
||||
|
/* TRUE if we got a message */ |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void WINS_GetLocalAddress() |
||||
|
{ |
||||
|
struct hostent *local = NULL; |
||||
|
char buff[MAXHOSTNAMELEN]; |
||||
|
unsigned long addr; |
||||
|
|
||||
|
if (myAddr != INADDR_ANY) |
||||
|
return; |
||||
|
|
||||
|
if (pgethostname(buff, MAXHOSTNAMELEN) == SOCKET_ERROR) |
||||
|
return; |
||||
|
|
||||
|
blocktime = Sys_FloatTime(); |
||||
|
WSASetBlockingHook(BlockingHook); |
||||
|
local = pgethostbyname(buff); |
||||
|
WSAUnhookBlockingHook(); |
||||
|
if (local == NULL) |
||||
|
return; |
||||
|
|
||||
|
myAddr = *(int *)local->h_addr_list[0]; |
||||
|
|
||||
|
addr = ntohl(myAddr); |
||||
|
sprintf(my_tcpip_address, "%d.%d.%d.%d", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
int WINS_Init (void) |
||||
|
{ |
||||
|
int i; |
||||
|
char buff[MAXHOSTNAMELEN]; |
||||
|
char *p; |
||||
|
int r; |
||||
|
WORD wVersionRequested; |
||||
|
HINSTANCE hInst; |
||||
|
|
||||
|
// initialize the Winsock function vectors (we do this instead of statically linking |
||||
|
// so we can run on Win 3.1, where there isn't necessarily Winsock) |
||||
|
hInst = LoadLibrary("wsock32.dll"); |
||||
|
|
||||
|
if (hInst == NULL) |
||||
|
{ |
||||
|
Con_SafePrintf ("Failed to load winsock.dll\n"); |
||||
|
winsock_lib_initialized = false; |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
winsock_lib_initialized = true; |
||||
|
|
||||
|
pWSAStartup = (void *)GetProcAddress(hInst, "WSAStartup"); |
||||
|
pWSACleanup = (void *)GetProcAddress(hInst, "WSACleanup"); |
||||
|
pWSAGetLastError = (void *)GetProcAddress(hInst, "WSAGetLastError"); |
||||
|
psocket = (void *)GetProcAddress(hInst, "socket"); |
||||
|
pioctlsocket = (void *)GetProcAddress(hInst, "ioctlsocket"); |
||||
|
psetsockopt = (void *)GetProcAddress(hInst, "setsockopt"); |
||||
|
precvfrom = (void *)GetProcAddress(hInst, "recvfrom"); |
||||
|
psendto = (void *)GetProcAddress(hInst, "sendto"); |
||||
|
pclosesocket = (void *)GetProcAddress(hInst, "closesocket"); |
||||
|
pgethostname = (void *)GetProcAddress(hInst, "gethostname"); |
||||
|
pgethostbyname = (void *)GetProcAddress(hInst, "gethostbyname"); |
||||
|
pgethostbyaddr = (void *)GetProcAddress(hInst, "gethostbyaddr"); |
||||
|
pgetsockname = (void *)GetProcAddress(hInst, "getsockname"); |
||||
|
|
||||
|
if (!pWSAStartup || !pWSACleanup || !pWSAGetLastError || |
||||
|
!psocket || !pioctlsocket || !psetsockopt || |
||||
|
!precvfrom || !psendto || !pclosesocket || |
||||
|
!pgethostname || !pgethostbyname || !pgethostbyaddr || |
||||
|
!pgetsockname) |
||||
|
{ |
||||
|
Con_SafePrintf ("Couldn't GetProcAddress from winsock.dll\n"); |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
if (COM_CheckParm ("-noudp")) |
||||
|
return -1; |
||||
|
|
||||
|
if (winsock_initialized == 0) |
||||
|
{ |
||||
|
wVersionRequested = MAKEWORD(1, 1); |
||||
|
|
||||
|
r = pWSAStartup (MAKEWORD(1, 1), &winsockdata); |
||||
|
|
||||
|
if (r) |
||||
|
{ |
||||
|
Con_SafePrintf ("Winsock initialization failed.\n"); |
||||
|
return -1; |
||||
|
} |
||||
|
} |
||||
|
winsock_initialized++; |
||||
|
|
||||
|
// determine my name |
||||
|
if (pgethostname(buff, MAXHOSTNAMELEN) == SOCKET_ERROR) |
||||
|
{ |
||||
|
Con_DPrintf ("Winsock TCP/IP Initialization failed.\n"); |
||||
|
if (--winsock_initialized == 0) |
||||
|
pWSACleanup (); |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
// if the quake hostname isn't set, set it to the machine name |
||||
|
if (Q_strcmp(hostname.string, "UNNAMED") == 0) |
||||
|
{ |
||||
|
// see if it's a text IP address (well, close enough) |
||||
|
for (p = buff; *p; p++) |
||||
|
if ((*p < '0' || *p > '9') && *p != '.') |
||||
|
break; |
||||
|
|
||||
|
// if it is a real name, strip off the domain; we only want the host |
||||
|
if (*p) |
||||
|
{ |
||||
|
for (i = 0; i < 15; i++) |
||||
|
if (buff[i] == '.') |
||||
|
break; |
||||
|
buff[i] = 0; |
||||
|
} |
||||
|
Cvar_Set ("hostname", buff); |
||||
|
} |
||||
|
|
||||
|
i = COM_CheckParm ("-ip"); |
||||
|
if (i) |
||||
|
{ |
||||
|
if (i < com_argc-1) |
||||
|
{ |
||||
|
myAddr = inet_addr(com_argv[i+1]); |
||||
|
if (myAddr == INADDR_NONE) |
||||
|
Sys_Error ("%s is not a valid IP address", com_argv[i+1]); |
||||
|
strcpy(my_tcpip_address, com_argv[i+1]); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
Sys_Error ("NET_Init: you must specify an IP address after -ip"); |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
myAddr = INADDR_ANY; |
||||
|
strcpy(my_tcpip_address, "INADDR_ANY"); |
||||
|
} |
||||
|
|
||||
|
if ((net_controlsocket = WINS_OpenSocket (0)) == -1) |
||||
|
{ |
||||
|
Con_Printf("WINS_Init: Unable to open control socket\n"); |
||||
|
if (--winsock_initialized == 0) |
||||
|
pWSACleanup (); |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET; |
||||
|
((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST; |
||||
|
((struct sockaddr_in *)&broadcastaddr)->sin_port = htons((unsigned short)net_hostport); |
||||
|
|
||||
|
Con_Printf("Winsock TCP/IP Initialized\n"); |
||||
|
tcpipAvailable = true; |
||||
|
|
||||
|
return net_controlsocket; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
void WINS_Shutdown (void) |
||||
|
{ |
||||
|
WINS_Listen (false); |
||||
|
WINS_CloseSocket (net_controlsocket); |
||||
|
if (--winsock_initialized == 0) |
||||
|
pWSACleanup (); |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
void WINS_Listen (qboolean state) |
||||
|
{ |
||||
|
// enable listening |
||||
|
if (state) |
||||
|
{ |
||||
|
if (net_acceptsocket != -1) |
||||
|
return; |
||||
|
WINS_GetLocalAddress(); |
||||
|
if ((net_acceptsocket = WINS_OpenSocket (net_hostport)) == -1) |
||||
|
Sys_Error ("WINS_Listen: Unable to open accept socket\n"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// disable listening |
||||
|
if (net_acceptsocket == -1) |
||||
|
return; |
||||
|
WINS_CloseSocket (net_acceptsocket); |
||||
|
net_acceptsocket = -1; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WINS_OpenSocket (int port) |
||||
|
{ |
||||
|
int newsocket; |
||||
|
struct sockaddr_in address; |
||||
|
u_long _true = 1; |
||||
|
|
||||
|
if ((newsocket = psocket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) |
||||
|
return -1; |
||||
|
|
||||
|
if (pioctlsocket (newsocket, FIONBIO, &_true) == -1) |
||||
|
goto ErrorReturn; |
||||
|
|
||||
|
address.sin_family = AF_INET; |
||||
|
address.sin_addr.s_addr = myAddr; |
||||
|
address.sin_port = htons((unsigned short)port); |
||||
|
if( bind (newsocket, (void *)&address, sizeof(address)) == 0) |
||||
|
return newsocket; |
||||
|
|
||||
|
Sys_Error ("Unable to bind to %s", WINS_AddrToString((struct qsockaddr *)&address)); |
||||
|
ErrorReturn: |
||||
|
pclosesocket (newsocket); |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WINS_CloseSocket (int socket) |
||||
|
{ |
||||
|
if (socket == net_broadcastsocket) |
||||
|
net_broadcastsocket = 0; |
||||
|
return pclosesocket (socket); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
//============================================================================= |
||||
|
/* |
||||
|
============ |
||||
|
PartialIPAddress |
||||
|
|
||||
|
this lets you type only as much of the net address as required, using |
||||
|
the local network components to fill in the rest |
||||
|
============ |
||||
|
*/ |
||||
|
static int PartialIPAddress (char *in, struct qsockaddr *hostaddr) |
||||
|
{ |
||||
|
char buff[256]; |
||||
|
char *b; |
||||
|
int addr; |
||||
|
int num; |
||||
|
int mask; |
||||
|
int run; |
||||
|
int port; |
||||
|
|
||||
|
buff[0] = '.'; |
||||
|
b = buff; |
||||
|
strcpy(buff+1, in); |
||||
|
if (buff[1] == '.') |
||||
|
b++; |
||||
|
|
||||
|
addr = 0; |
||||
|
mask=-1; |
||||
|
while (*b == '.') |
||||
|
{ |
||||
|
b++; |
||||
|
num = 0; |
||||
|
run = 0; |
||||
|
while (!( *b < '0' || *b > '9')) |
||||
|
{ |
||||
|
num = num*10 + *b++ - '0'; |
||||
|
if (++run > 3) |
||||
|
return -1; |
||||
|
} |
||||
|
if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0) |
||||
|
return -1; |
||||
|
if (num < 0 || num > 255) |
||||
|
return -1; |
||||
|
mask<<=8; |
||||
|
addr = (addr<<8) + num; |
||||
|
} |
||||
|
|
||||
|
if (*b++ == ':') |
||||
|
port = Q_atoi(b); |
||||
|
else |
||||
|
port = net_hostport; |
||||
|
|
||||
|
hostaddr->sa_family = AF_INET; |
||||
|
((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port); |
||||
|
((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
//============================================================================= |
||||
|
|
||||
|
int WINS_Connect (int socket, struct qsockaddr *addr) |
||||
|
{ |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WINS_CheckNewConnections (void) |
||||
|
{ |
||||
|
char buf[4096]; |
||||
|
|
||||
|
if (net_acceptsocket == -1) |
||||
|
return -1; |
||||
|
|
||||
|
if (precvfrom (net_acceptsocket, buf, sizeof(buf), MSG_PEEK, NULL, NULL) > 0) |
||||
|
{ |
||||
|
return net_acceptsocket; |
||||
|
} |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WINS_Read (int socket, byte *buf, int len, struct qsockaddr *addr) |
||||
|
{ |
||||
|
int addrlen = sizeof (struct qsockaddr); |
||||
|
int ret; |
||||
|
|
||||
|
ret = precvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen); |
||||
|
if (ret == -1) |
||||
|
{ |
||||
|
// jkrige - vs2005 |
||||
|
//int errno = pWSAGetLastError(); |
||||
|
|
||||
|
//if (errno == WSAEWOULDBLOCK || errno == WSAECONNREFUSED) |
||||
|
// return 0; |
||||
|
int err = pWSAGetLastError(); |
||||
|
|
||||
|
if (err == WSAEWOULDBLOCK || err == WSAECONNREFUSED) |
||||
|
return 0; |
||||
|
// jkrige - vs2005 |
||||
|
} |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WINS_MakeSocketBroadcastCapable (int socket) |
||||
|
{ |
||||
|
int i = 1; |
||||
|
|
||||
|
// make this socket broadcast capable |
||||
|
if (psetsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0) |
||||
|
return -1; |
||||
|
net_broadcastsocket = socket; |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WINS_Broadcast (int socket, byte *buf, int len) |
||||
|
{ |
||||
|
int ret; |
||||
|
|
||||
|
if (socket != net_broadcastsocket) |
||||
|
{ |
||||
|
if (net_broadcastsocket != 0) |
||||
|
Sys_Error("Attempted to use multiple broadcasts sockets\n"); |
||||
|
WINS_GetLocalAddress(); |
||||
|
ret = WINS_MakeSocketBroadcastCapable (socket); |
||||
|
if (ret == -1) |
||||
|
{ |
||||
|
Con_Printf("Unable to make socket broadcast capable\n"); |
||||
|
return ret; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return WINS_Write (socket, buf, len, &broadcastaddr); |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WINS_Write (int socket, byte *buf, int len, struct qsockaddr *addr) |
||||
|
{ |
||||
|
int ret; |
||||
|
|
||||
|
ret = psendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr)); |
||||
|
if (ret == -1) |
||||
|
if (pWSAGetLastError() == WSAEWOULDBLOCK) |
||||
|
return 0; |
||||
|
|
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
char *WINS_AddrToString (struct qsockaddr *addr) |
||||
|
{ |
||||
|
static char buffer[22]; |
||||
|
int haddr; |
||||
|
|
||||
|
haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr); |
||||
|
sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff, (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff, ntohs(((struct sockaddr_in *)addr)->sin_port)); |
||||
|
return buffer; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WINS_StringToAddr (char *string, struct qsockaddr *addr) |
||||
|
{ |
||||
|
int ha1, ha2, ha3, ha4, hp; |
||||
|
int ipaddr; |
||||
|
|
||||
|
sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp); |
||||
|
ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4; |
||||
|
|
||||
|
addr->sa_family = AF_INET; |
||||
|
((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr); |
||||
|
((struct sockaddr_in *)addr)->sin_port = htons((unsigned short)hp); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WINS_GetSocketAddr (int socket, struct qsockaddr *addr) |
||||
|
{ |
||||
|
int addrlen = sizeof(struct qsockaddr); |
||||
|
unsigned int a; |
||||
|
|
||||
|
Q_memset(addr, 0, sizeof(struct qsockaddr)); |
||||
|
pgetsockname(socket, (struct sockaddr *)addr, &addrlen); |
||||
|
a = ((struct sockaddr_in *)addr)->sin_addr.s_addr; |
||||
|
if (a == 0 || a == inet_addr("127.0.0.1")) |
||||
|
((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr; |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WINS_GetNameFromAddr (struct qsockaddr *addr, char *name) |
||||
|
{ |
||||
|
struct hostent *hostentry; |
||||
|
|
||||
|
hostentry = pgethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET); |
||||
|
if (hostentry) |
||||
|
{ |
||||
|
Q_strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
Q_strcpy (name, WINS_AddrToString (addr)); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WINS_GetAddrFromName(char *name, struct qsockaddr *addr) |
||||
|
{ |
||||
|
struct hostent *hostentry; |
||||
|
|
||||
|
if (name[0] >= '0' && name[0] <= '9') |
||||
|
return PartialIPAddress (name, addr); |
||||
|
|
||||
|
hostentry = pgethostbyname (name); |
||||
|
if (!hostentry) |
||||
|
return -1; |
||||
|
|
||||
|
addr->sa_family = AF_INET; |
||||
|
((struct sockaddr_in *)addr)->sin_port = htons((unsigned short)net_hostport); |
||||
|
((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0]; |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WINS_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2) |
||||
|
{ |
||||
|
if (addr1->sa_family != addr2->sa_family) |
||||
|
return -1; |
||||
|
|
||||
|
if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr) |
||||
|
return -1; |
||||
|
|
||||
|
if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port) |
||||
|
return 1; |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WINS_GetSocketPort (struct qsockaddr *addr) |
||||
|
{ |
||||
|
return ntohs(((struct sockaddr_in *)addr)->sin_port); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
int WINS_SetSocketPort (struct qsockaddr *addr, int port) |
||||
|
{ |
||||
|
((struct sockaddr_in *)addr)->sin_port = htons((unsigned short)port); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
@ -0,0 +1,39 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// net_wins.h |
||||
|
|
||||
|
int WINS_Init (void); |
||||
|
void WINS_Shutdown (void); |
||||
|
void WINS_Listen (qboolean state); |
||||
|
int WINS_OpenSocket (int port); |
||||
|
int WINS_CloseSocket (int socket); |
||||
|
int WINS_Connect (int socket, struct qsockaddr *addr); |
||||
|
int WINS_CheckNewConnections (void); |
||||
|
int WINS_Read (int socket, byte *buf, int len, struct qsockaddr *addr); |
||||
|
int WINS_Write (int socket, byte *buf, int len, struct qsockaddr *addr); |
||||
|
int WINS_Broadcast (int socket, byte *buf, int len); |
||||
|
char *WINS_AddrToString (struct qsockaddr *addr); |
||||
|
int WINS_StringToAddr (char *string, struct qsockaddr *addr); |
||||
|
int WINS_GetSocketAddr (int socket, struct qsockaddr *addr); |
||||
|
int WINS_GetNameFromAddr (struct qsockaddr *addr, char *name); |
||||
|
int WINS_GetAddrFromName (char *name, struct qsockaddr *addr); |
||||
|
int WINS_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2); |
||||
|
int WINS_GetSocketPort (struct qsockaddr *addr); |
||||
|
int WINS_SetSocketPort (struct qsockaddr *addr, int port); |
||||
@ -0,0 +1,440 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// net_wipx.c |
||||
|
|
||||
|
#include "quakedef.h" |
||||
|
#include "winquake.h" |
||||
|
#include <wsipx.h> |
||||
|
#include "net_wipx.h" |
||||
|
|
||||
|
extern cvar_t hostname; |
||||
|
|
||||
|
#define MAXHOSTNAMELEN 256 |
||||
|
|
||||
|
static int net_acceptsocket = -1; // socket for fielding new connections |
||||
|
static int net_controlsocket; |
||||
|
static struct qsockaddr broadcastaddr; |
||||
|
|
||||
|
extern qboolean winsock_initialized; |
||||
|
extern WSADATA winsockdata; |
||||
|
|
||||
|
#define IPXSOCKETS 18 |
||||
|
static int ipxsocket[IPXSOCKETS]; |
||||
|
static int sequence[IPXSOCKETS]; |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WIPX_Init (void) |
||||
|
{ |
||||
|
int i; |
||||
|
char buff[MAXHOSTNAMELEN]; |
||||
|
struct qsockaddr addr; |
||||
|
char *p; |
||||
|
int r; |
||||
|
WORD wVersionRequested; |
||||
|
|
||||
|
if (COM_CheckParm ("-noipx")) |
||||
|
return -1; |
||||
|
|
||||
|
// make sure LoadLibrary has happened successfully |
||||
|
if (!winsock_lib_initialized) |
||||
|
return -1; |
||||
|
|
||||
|
if (winsock_initialized == 0) |
||||
|
{ |
||||
|
wVersionRequested = MAKEWORD(1, 1); |
||||
|
|
||||
|
r = pWSAStartup (MAKEWORD(1, 1), &winsockdata); |
||||
|
|
||||
|
if (r) |
||||
|
{ |
||||
|
Con_Printf ("Winsock initialization failed.\n"); |
||||
|
return -1; |
||||
|
} |
||||
|
} |
||||
|
winsock_initialized++; |
||||
|
|
||||
|
for (i = 0; i < IPXSOCKETS; i++) |
||||
|
ipxsocket[i] = 0; |
||||
|
|
||||
|
// determine my name & address |
||||
|
if (pgethostname(buff, MAXHOSTNAMELEN) == 0) |
||||
|
{ |
||||
|
// if the quake hostname isn't set, set it to the machine name |
||||
|
if (Q_strcmp(hostname.string, "UNNAMED") == 0) |
||||
|
{ |
||||
|
// see if it's a text IP address (well, close enough) |
||||
|
for (p = buff; *p; p++) |
||||
|
if ((*p < '0' || *p > '9') && *p != '.') |
||||
|
break; |
||||
|
|
||||
|
// if it is a real name, strip off the domain; we only want the host |
||||
|
if (*p) |
||||
|
{ |
||||
|
for (i = 0; i < 15; i++) |
||||
|
if (buff[i] == '.') |
||||
|
break; |
||||
|
buff[i] = 0; |
||||
|
} |
||||
|
Cvar_Set ("hostname", buff); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if ((net_controlsocket = WIPX_OpenSocket (0)) == -1) |
||||
|
{ |
||||
|
Con_Printf("WIPX_Init: Unable to open control socket\n"); |
||||
|
if (--winsock_initialized == 0) |
||||
|
pWSACleanup (); |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
((struct sockaddr_ipx *)&broadcastaddr)->sa_family = AF_IPX; |
||||
|
memset(((struct sockaddr_ipx *)&broadcastaddr)->sa_netnum, 0, 4); |
||||
|
memset(((struct sockaddr_ipx *)&broadcastaddr)->sa_nodenum, 0xff, 6); |
||||
|
((struct sockaddr_ipx *)&broadcastaddr)->sa_socket = htons((unsigned short)net_hostport); |
||||
|
|
||||
|
WIPX_GetSocketAddr (net_controlsocket, &addr); |
||||
|
Q_strcpy(my_ipx_address, WIPX_AddrToString (&addr)); |
||||
|
p = Q_strrchr (my_ipx_address, ':'); |
||||
|
if (p) |
||||
|
*p = 0; |
||||
|
|
||||
|
Con_Printf("Winsock IPX Initialized\n"); |
||||
|
ipxAvailable = true; |
||||
|
|
||||
|
return net_controlsocket; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
void WIPX_Shutdown (void) |
||||
|
{ |
||||
|
WIPX_Listen (false); |
||||
|
WIPX_CloseSocket (net_controlsocket); |
||||
|
if (--winsock_initialized == 0) |
||||
|
pWSACleanup (); |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
void WIPX_Listen (qboolean state) |
||||
|
{ |
||||
|
// enable listening |
||||
|
if (state) |
||||
|
{ |
||||
|
if (net_acceptsocket != -1) |
||||
|
return; |
||||
|
if ((net_acceptsocket = WIPX_OpenSocket (net_hostport)) == -1) |
||||
|
Sys_Error ("WIPX_Listen: Unable to open accept socket\n"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// disable listening |
||||
|
if (net_acceptsocket == -1) |
||||
|
return; |
||||
|
WIPX_CloseSocket (net_acceptsocket); |
||||
|
net_acceptsocket = -1; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WIPX_OpenSocket (int port) |
||||
|
{ |
||||
|
int handle; |
||||
|
int newsocket; |
||||
|
struct sockaddr_ipx address; |
||||
|
u_long _true = 1; |
||||
|
|
||||
|
for (handle = 0; handle < IPXSOCKETS; handle++) |
||||
|
if (ipxsocket[handle] == 0) |
||||
|
break; |
||||
|
if (handle == IPXSOCKETS) |
||||
|
return -1; |
||||
|
|
||||
|
if ((newsocket = psocket (AF_IPX, SOCK_DGRAM, NSPROTO_IPX)) == INVALID_SOCKET) |
||||
|
return -1; |
||||
|
|
||||
|
if (pioctlsocket (newsocket, FIONBIO, &_true) == -1) |
||||
|
goto ErrorReturn; |
||||
|
|
||||
|
if (psetsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&_true, sizeof(_true)) < 0) |
||||
|
goto ErrorReturn; |
||||
|
|
||||
|
address.sa_family = AF_IPX; |
||||
|
memset(address.sa_netnum, 0, 4); |
||||
|
memset(address.sa_nodenum, 0, 6);; |
||||
|
address.sa_socket = htons((unsigned short)port); |
||||
|
if( bind (newsocket, (void *)&address, sizeof(address)) == 0) |
||||
|
{ |
||||
|
ipxsocket[handle] = newsocket; |
||||
|
sequence[handle] = 0; |
||||
|
return handle; |
||||
|
} |
||||
|
|
||||
|
Sys_Error ("Winsock IPX bind failed\n"); |
||||
|
ErrorReturn: |
||||
|
pclosesocket (newsocket); |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WIPX_CloseSocket (int handle) |
||||
|
{ |
||||
|
int socket = ipxsocket[handle]; |
||||
|
int ret; |
||||
|
|
||||
|
ret = pclosesocket (socket); |
||||
|
ipxsocket[handle] = 0; |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WIPX_Connect (int handle, struct qsockaddr *addr) |
||||
|
{ |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WIPX_CheckNewConnections (void) |
||||
|
{ |
||||
|
unsigned long available; |
||||
|
|
||||
|
if (net_acceptsocket == -1) |
||||
|
return -1; |
||||
|
|
||||
|
if (pioctlsocket (ipxsocket[net_acceptsocket], FIONREAD, &available) == -1) |
||||
|
Sys_Error ("WIPX: ioctlsocket (FIONREAD) failed\n"); |
||||
|
if (available) |
||||
|
return net_acceptsocket; |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
static byte packetBuffer[NET_DATAGRAMSIZE + 4]; |
||||
|
|
||||
|
int WIPX_Read (int handle, byte *buf, int len, struct qsockaddr *addr) |
||||
|
{ |
||||
|
int addrlen = sizeof (struct qsockaddr); |
||||
|
int socket = ipxsocket[handle]; |
||||
|
int ret; |
||||
|
|
||||
|
ret = precvfrom (socket, packetBuffer, len+4, 0, (struct sockaddr *)addr, &addrlen); |
||||
|
if (ret == -1) |
||||
|
{ |
||||
|
// jkrige - vs2005 |
||||
|
//int errno = pWSAGetLastError(); |
||||
|
|
||||
|
//if (errno == WSAEWOULDBLOCK || errno == WSAECONNREFUSED) |
||||
|
// return 0; |
||||
|
int err = pWSAGetLastError(); |
||||
|
|
||||
|
if (err == WSAEWOULDBLOCK || err == WSAECONNREFUSED) |
||||
|
return 0; |
||||
|
// jkrige - vs2005 |
||||
|
} |
||||
|
|
||||
|
if (ret < 4) |
||||
|
return 0; |
||||
|
|
||||
|
// remove sequence number, it's only needed for DOS IPX |
||||
|
ret -= 4; |
||||
|
memcpy(buf, packetBuffer+4, ret); |
||||
|
|
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WIPX_Broadcast (int handle, byte *buf, int len) |
||||
|
{ |
||||
|
return WIPX_Write (handle, buf, len, &broadcastaddr); |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WIPX_Write (int handle, byte *buf, int len, struct qsockaddr *addr) |
||||
|
{ |
||||
|
int socket = ipxsocket[handle]; |
||||
|
int ret; |
||||
|
|
||||
|
// build packet with sequence number |
||||
|
*(int *)(&packetBuffer[0]) = sequence[handle]; |
||||
|
sequence[handle]++; |
||||
|
memcpy(&packetBuffer[4], buf, len); |
||||
|
len += 4; |
||||
|
|
||||
|
ret = psendto (socket, packetBuffer, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr)); |
||||
|
if (ret == -1) |
||||
|
if (pWSAGetLastError() == WSAEWOULDBLOCK) |
||||
|
return 0; |
||||
|
|
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
char *WIPX_AddrToString (struct qsockaddr *addr) |
||||
|
{ |
||||
|
static char buf[28]; |
||||
|
|
||||
|
sprintf(buf, "%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%u", |
||||
|
((struct sockaddr_ipx *)addr)->sa_netnum[0] & 0xff, |
||||
|
((struct sockaddr_ipx *)addr)->sa_netnum[1] & 0xff, |
||||
|
((struct sockaddr_ipx *)addr)->sa_netnum[2] & 0xff, |
||||
|
((struct sockaddr_ipx *)addr)->sa_netnum[3] & 0xff, |
||||
|
((struct sockaddr_ipx *)addr)->sa_nodenum[0] & 0xff, |
||||
|
((struct sockaddr_ipx *)addr)->sa_nodenum[1] & 0xff, |
||||
|
((struct sockaddr_ipx *)addr)->sa_nodenum[2] & 0xff, |
||||
|
((struct sockaddr_ipx *)addr)->sa_nodenum[3] & 0xff, |
||||
|
((struct sockaddr_ipx *)addr)->sa_nodenum[4] & 0xff, |
||||
|
((struct sockaddr_ipx *)addr)->sa_nodenum[5] & 0xff, |
||||
|
ntohs(((struct sockaddr_ipx *)addr)->sa_socket) |
||||
|
); |
||||
|
return buf; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WIPX_StringToAddr (char *string, struct qsockaddr *addr) |
||||
|
{ |
||||
|
int val; |
||||
|
char buf[3]; |
||||
|
|
||||
|
buf[2] = 0; |
||||
|
Q_memset(addr, 0, sizeof(struct qsockaddr)); |
||||
|
addr->sa_family = AF_IPX; |
||||
|
|
||||
|
#define DO(src,dest) \ |
||||
|
buf[0] = string[src]; \ |
||||
|
buf[1] = string[src + 1]; \ |
||||
|
if (sscanf (buf, "%x", &val) != 1) \ |
||||
|
return -1; \ |
||||
|
((struct sockaddr_ipx *)addr)->dest = val |
||||
|
|
||||
|
DO(0, sa_netnum[0]); |
||||
|
DO(2, sa_netnum[1]); |
||||
|
DO(4, sa_netnum[2]); |
||||
|
DO(6, sa_netnum[3]); |
||||
|
DO(9, sa_nodenum[0]); |
||||
|
DO(11, sa_nodenum[1]); |
||||
|
DO(13, sa_nodenum[2]); |
||||
|
DO(15, sa_nodenum[3]); |
||||
|
DO(17, sa_nodenum[4]); |
||||
|
DO(19, sa_nodenum[5]); |
||||
|
#undef DO |
||||
|
|
||||
|
sscanf (&string[22], "%u", &val); |
||||
|
((struct sockaddr_ipx *)addr)->sa_socket = htons((unsigned short)val); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WIPX_GetSocketAddr (int handle, struct qsockaddr *addr) |
||||
|
{ |
||||
|
int socket = ipxsocket[handle]; |
||||
|
int addrlen = sizeof(struct qsockaddr); |
||||
|
unsigned int a; |
||||
|
|
||||
|
Q_memset(addr, 0, sizeof(struct qsockaddr)); |
||||
|
if(pgetsockname(socket, (struct sockaddr *)addr, &addrlen) != 0) |
||||
|
{ |
||||
|
// jkrige - vs2005 |
||||
|
//int errno = pWSAGetLastError(); |
||||
|
int err = pWSAGetLastError(); |
||||
|
// jkrige - vs2005 |
||||
|
} |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WIPX_GetNameFromAddr (struct qsockaddr *addr, char *name) |
||||
|
{ |
||||
|
Q_strcpy(name, WIPX_AddrToString(addr)); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WIPX_GetAddrFromName(char *name, struct qsockaddr *addr) |
||||
|
{ |
||||
|
int n; |
||||
|
char buf[32]; |
||||
|
|
||||
|
n = Q_strlen(name); |
||||
|
|
||||
|
if (n == 12) |
||||
|
{ |
||||
|
sprintf(buf, "00000000:%s:%u", name, net_hostport); |
||||
|
return WIPX_StringToAddr (buf, addr); |
||||
|
} |
||||
|
if (n == 21) |
||||
|
{ |
||||
|
sprintf(buf, "%s:%u", name, net_hostport); |
||||
|
return WIPX_StringToAddr (buf, addr); |
||||
|
} |
||||
|
if (n > 21 && n <= 27) |
||||
|
return WIPX_StringToAddr (name, addr); |
||||
|
|
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WIPX_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2) |
||||
|
{ |
||||
|
if (addr1->sa_family != addr2->sa_family) |
||||
|
return -1; |
||||
|
|
||||
|
if (*((struct sockaddr_ipx *)addr1)->sa_netnum && *((struct sockaddr_ipx *)addr2)->sa_netnum) |
||||
|
if (memcmp(((struct sockaddr_ipx *)addr1)->sa_netnum, ((struct sockaddr_ipx *)addr2)->sa_netnum, 4) != 0) |
||||
|
return -1; |
||||
|
if (memcmp(((struct sockaddr_ipx *)addr1)->sa_nodenum, ((struct sockaddr_ipx *)addr2)->sa_nodenum, 6) != 0) |
||||
|
return -1; |
||||
|
|
||||
|
if (((struct sockaddr_ipx *)addr1)->sa_socket != ((struct sockaddr_ipx *)addr2)->sa_socket) |
||||
|
return 1; |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
int WIPX_GetSocketPort (struct qsockaddr *addr) |
||||
|
{ |
||||
|
return ntohs(((struct sockaddr_ipx *)addr)->sa_socket); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
int WIPX_SetSocketPort (struct qsockaddr *addr, int port) |
||||
|
{ |
||||
|
((struct sockaddr_ipx *)addr)->sa_socket = htons((unsigned short)port); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
@ -0,0 +1,39 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// net_wipx.h |
||||
|
|
||||
|
int WIPX_Init (void); |
||||
|
void WIPX_Shutdown (void); |
||||
|
void WIPX_Listen (qboolean state); |
||||
|
int WIPX_OpenSocket (int port); |
||||
|
int WIPX_CloseSocket (int socket); |
||||
|
int WIPX_Connect (int socket, struct qsockaddr *addr); |
||||
|
int WIPX_CheckNewConnections (void); |
||||
|
int WIPX_Read (int socket, byte *buf, int len, struct qsockaddr *addr); |
||||
|
int WIPX_Write (int socket, byte *buf, int len, struct qsockaddr *addr); |
||||
|
int WIPX_Broadcast (int socket, byte *buf, int len); |
||||
|
char *WIPX_AddrToString (struct qsockaddr *addr); |
||||
|
int WIPX_StringToAddr (char *string, struct qsockaddr *addr); |
||||
|
int WIPX_GetSocketAddr (int socket, struct qsockaddr *addr); |
||||
|
int WIPX_GetNameFromAddr (struct qsockaddr *addr, char *name); |
||||
|
int WIPX_GetAddrFromName (char *name, struct qsockaddr *addr); |
||||
|
int WIPX_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2); |
||||
|
int WIPX_GetSocketPort (struct qsockaddr *addr); |
||||
|
int WIPX_SetSocketPort (struct qsockaddr *addr, int port); |
||||
1940
engine/code/pr_cmds.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,180 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
// this file is shared by quake and qcc |
||||
|
|
||||
|
typedef int func_t; |
||||
|
typedef int string_t; |
||||
|
|
||||
|
typedef enum {ev_void, ev_string, ev_float, ev_vector, ev_entity, ev_field, ev_function, ev_pointer} etype_t; |
||||
|
|
||||
|
|
||||
|
#define OFS_NULL 0 |
||||
|
#define OFS_RETURN 1 |
||||
|
#define OFS_PARM0 4 // leave 3 ofs for each parm to hold vectors |
||||
|
#define OFS_PARM1 7 |
||||
|
#define OFS_PARM2 10 |
||||
|
#define OFS_PARM3 13 |
||||
|
#define OFS_PARM4 16 |
||||
|
#define OFS_PARM5 19 |
||||
|
#define OFS_PARM6 22 |
||||
|
#define OFS_PARM7 25 |
||||
|
#define RESERVED_OFS 28 |
||||
|
|
||||
|
|
||||
|
enum { |
||||
|
OP_DONE, |
||||
|
OP_MUL_F, |
||||
|
OP_MUL_V, |
||||
|
OP_MUL_FV, |
||||
|
OP_MUL_VF, |
||||
|
OP_DIV_F, |
||||
|
OP_ADD_F, |
||||
|
OP_ADD_V, |
||||
|
OP_SUB_F, |
||||
|
OP_SUB_V, |
||||
|
|
||||
|
OP_EQ_F, |
||||
|
OP_EQ_V, |
||||
|
OP_EQ_S, |
||||
|
OP_EQ_E, |
||||
|
OP_EQ_FNC, |
||||
|
|
||||
|
OP_NE_F, |
||||
|
OP_NE_V, |
||||
|
OP_NE_S, |
||||
|
OP_NE_E, |
||||
|
OP_NE_FNC, |
||||
|
|
||||
|
OP_LE, |
||||
|
OP_GE, |
||||
|
OP_LT, |
||||
|
OP_GT, |
||||
|
|
||||
|
OP_LOAD_F, |
||||
|
OP_LOAD_V, |
||||
|
OP_LOAD_S, |
||||
|
OP_LOAD_ENT, |
||||
|
OP_LOAD_FLD, |
||||
|
OP_LOAD_FNC, |
||||
|
|
||||
|
OP_ADDRESS, |
||||
|
|
||||
|
OP_STORE_F, |
||||
|
OP_STORE_V, |
||||
|
OP_STORE_S, |
||||
|
OP_STORE_ENT, |
||||
|
OP_STORE_FLD, |
||||
|
OP_STORE_FNC, |
||||
|
|
||||
|
OP_STOREP_F, |
||||
|
OP_STOREP_V, |
||||
|
OP_STOREP_S, |
||||
|
OP_STOREP_ENT, |
||||
|
OP_STOREP_FLD, |
||||
|
OP_STOREP_FNC, |
||||
|
|
||||
|
OP_RETURN, |
||||
|
OP_NOT_F, |
||||
|
OP_NOT_V, |
||||
|
OP_NOT_S, |
||||
|
OP_NOT_ENT, |
||||
|
OP_NOT_FNC, |
||||
|
OP_IF, |
||||
|
OP_IFNOT, |
||||
|
OP_CALL0, |
||||
|
OP_CALL1, |
||||
|
OP_CALL2, |
||||
|
OP_CALL3, |
||||
|
OP_CALL4, |
||||
|
OP_CALL5, |
||||
|
OP_CALL6, |
||||
|
OP_CALL7, |
||||
|
OP_CALL8, |
||||
|
OP_STATE, |
||||
|
OP_GOTO, |
||||
|
OP_AND, |
||||
|
OP_OR, |
||||
|
|
||||
|
OP_BITAND, |
||||
|
OP_BITOR |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
typedef struct statement_s |
||||
|
{ |
||||
|
unsigned short op; |
||||
|
short a,b,c; |
||||
|
} dstatement_t; |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
unsigned short type; // if DEF_SAVEGLOBGAL bit is set |
||||
|
// the variable needs to be saved in savegames |
||||
|
unsigned short ofs; |
||||
|
int s_name; |
||||
|
} ddef_t; |
||||
|
#define DEF_SAVEGLOBAL (1<<15) |
||||
|
|
||||
|
#define MAX_PARMS 8 |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
int first_statement; // negative numbers are builtins |
||||
|
int parm_start; |
||||
|
int locals; // total ints of parms + locals |
||||
|
|
||||
|
int profile; // runtime |
||||
|
|
||||
|
int s_name; |
||||
|
int s_file; // source file defined in |
||||
|
|
||||
|
int numparms; |
||||
|
byte parm_size[MAX_PARMS]; |
||||
|
} dfunction_t; |
||||
|
|
||||
|
|
||||
|
#define PROG_VERSION 6 |
||||
|
typedef struct |
||||
|
{ |
||||
|
int version; |
||||
|
int crc; // check of header file |
||||
|
|
||||
|
int ofs_statements; |
||||
|
int numstatements; // statement 0 is an error |
||||
|
|
||||
|
int ofs_globaldefs; |
||||
|
int numglobaldefs; |
||||
|
|
||||
|
int ofs_fielddefs; |
||||
|
int numfielddefs; |
||||
|
|
||||
|
int ofs_functions; |
||||
|
int numfunctions; // function 0 is an empty |
||||
|
|
||||
|
int ofs_strings; |
||||
|
int numstrings; // first string is a null string |
||||
|
|
||||
|
int ofs_globals; |
||||
|
int numglobals; |
||||
|
|
||||
|
int entityfields; |
||||
|
} dprograms_t; |
||||
|
|
||||
1112
engine/code/pr_edict.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,673 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
#include "quakedef.h" |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
int s; |
||||
|
dfunction_t *f; |
||||
|
} prstack_t; |
||||
|
|
||||
|
// jkrige - increase stack size to avoid overflows |
||||
|
//#define MAX_STACK_DEPTH 32 |
||||
|
//#define LOCALSTACK_SIZE 2048 |
||||
|
#define MAX_STACK_DEPTH 64 |
||||
|
#define LOCALSTACK_SIZE 4096 |
||||
|
// jkrige - increase stack size to avoid overflows |
||||
|
|
||||
|
prstack_t pr_stack[MAX_STACK_DEPTH]; |
||||
|
int pr_depth; |
||||
|
|
||||
|
int localstack[LOCALSTACK_SIZE]; |
||||
|
int localstack_used; |
||||
|
|
||||
|
|
||||
|
qboolean pr_trace; |
||||
|
dfunction_t *pr_xfunction; |
||||
|
int pr_xstatement; |
||||
|
|
||||
|
|
||||
|
int pr_argc; |
||||
|
|
||||
|
char *pr_opnames[] = |
||||
|
{ |
||||
|
"DONE", |
||||
|
|
||||
|
"MUL_F", |
||||
|
"MUL_V", |
||||
|
"MUL_FV", |
||||
|
"MUL_VF", |
||||
|
|
||||
|
"DIV", |
||||
|
|
||||
|
"ADD_F", |
||||
|
"ADD_V", |
||||
|
|
||||
|
"SUB_F", |
||||
|
"SUB_V", |
||||
|
|
||||
|
"EQ_F", |
||||
|
"EQ_V", |
||||
|
"EQ_S", |
||||
|
"EQ_E", |
||||
|
"EQ_FNC", |
||||
|
|
||||
|
"NE_F", |
||||
|
"NE_V", |
||||
|
"NE_S", |
||||
|
"NE_E", |
||||
|
"NE_FNC", |
||||
|
|
||||
|
"LE", |
||||
|
"GE", |
||||
|
"LT", |
||||
|
"GT", |
||||
|
|
||||
|
"INDIRECT", |
||||
|
"INDIRECT", |
||||
|
"INDIRECT", |
||||
|
"INDIRECT", |
||||
|
"INDIRECT", |
||||
|
"INDIRECT", |
||||
|
|
||||
|
"ADDRESS", |
||||
|
|
||||
|
"STORE_F", |
||||
|
"STORE_V", |
||||
|
"STORE_S", |
||||
|
"STORE_ENT", |
||||
|
"STORE_FLD", |
||||
|
"STORE_FNC", |
||||
|
|
||||
|
"STOREP_F", |
||||
|
"STOREP_V", |
||||
|
"STOREP_S", |
||||
|
"STOREP_ENT", |
||||
|
"STOREP_FLD", |
||||
|
"STOREP_FNC", |
||||
|
|
||||
|
"RETURN", |
||||
|
|
||||
|
"NOT_F", |
||||
|
"NOT_V", |
||||
|
"NOT_S", |
||||
|
"NOT_ENT", |
||||
|
"NOT_FNC", |
||||
|
|
||||
|
"IF", |
||||
|
"IFNOT", |
||||
|
|
||||
|
"CALL0", |
||||
|
"CALL1", |
||||
|
"CALL2", |
||||
|
"CALL3", |
||||
|
"CALL4", |
||||
|
"CALL5", |
||||
|
"CALL6", |
||||
|
"CALL7", |
||||
|
"CALL8", |
||||
|
|
||||
|
"STATE", |
||||
|
|
||||
|
"GOTO", |
||||
|
|
||||
|
"AND", |
||||
|
"OR", |
||||
|
|
||||
|
"BITAND", |
||||
|
"BITOR" |
||||
|
}; |
||||
|
|
||||
|
char *PR_GlobalString (int ofs); |
||||
|
char *PR_GlobalStringNoContents (int ofs); |
||||
|
|
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
/* |
||||
|
================= |
||||
|
PR_PrintStatement |
||||
|
================= |
||||
|
*/ |
||||
|
void PR_PrintStatement (dstatement_t *s) |
||||
|
{ |
||||
|
int i; |
||||
|
|
||||
|
if ( (unsigned)s->op < sizeof(pr_opnames)/sizeof(pr_opnames[0])) |
||||
|
{ |
||||
|
Con_Printf ("%s ", pr_opnames[s->op]); |
||||
|
i = strlen(pr_opnames[s->op]); |
||||
|
for ( ; i<10 ; i++) |
||||
|
Con_Printf (" "); |
||||
|
} |
||||
|
|
||||
|
if (s->op == OP_IF || s->op == OP_IFNOT) |
||||
|
Con_Printf ("%sbranch %i",PR_GlobalString(s->a),s->b); |
||||
|
else if (s->op == OP_GOTO) |
||||
|
{ |
||||
|
Con_Printf ("branch %i",s->a); |
||||
|
} |
||||
|
else if ( (unsigned)(s->op - OP_STORE_F) < 6) |
||||
|
{ |
||||
|
Con_Printf ("%s",PR_GlobalString(s->a)); |
||||
|
Con_Printf ("%s", PR_GlobalStringNoContents(s->b)); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
if (s->a) |
||||
|
Con_Printf ("%s",PR_GlobalString(s->a)); |
||||
|
if (s->b) |
||||
|
Con_Printf ("%s",PR_GlobalString(s->b)); |
||||
|
if (s->c) |
||||
|
Con_Printf ("%s", PR_GlobalStringNoContents(s->c)); |
||||
|
} |
||||
|
Con_Printf ("\n"); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
PR_StackTrace |
||||
|
============ |
||||
|
*/ |
||||
|
void PR_StackTrace (void) |
||||
|
{ |
||||
|
dfunction_t *f; |
||||
|
int i; |
||||
|
|
||||
|
if (pr_depth == 0) |
||||
|
{ |
||||
|
Con_Printf ("<NO STACK>\n"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
pr_stack[pr_depth].f = pr_xfunction; |
||||
|
for (i=pr_depth ; i>=0 ; i--) |
||||
|
{ |
||||
|
f = pr_stack[i].f; |
||||
|
|
||||
|
if (!f) |
||||
|
{ |
||||
|
Con_Printf ("<NO FUNCTION>\n"); |
||||
|
} |
||||
|
else |
||||
|
Con_Printf ("%12s : %s\n", pr_strings + f->s_file, pr_strings + f->s_name); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
PR_Profile_f |
||||
|
|
||||
|
============ |
||||
|
*/ |
||||
|
void PR_Profile_f (void) |
||||
|
{ |
||||
|
dfunction_t *f, *best; |
||||
|
int max; |
||||
|
int num; |
||||
|
int i; |
||||
|
|
||||
|
num = 0; |
||||
|
do |
||||
|
{ |
||||
|
max = 0; |
||||
|
best = NULL; |
||||
|
for (i=0 ; i<progs->numfunctions ; i++) |
||||
|
{ |
||||
|
f = &pr_functions[i]; |
||||
|
if (f->profile > max) |
||||
|
{ |
||||
|
max = f->profile; |
||||
|
best = f; |
||||
|
} |
||||
|
} |
||||
|
if (best) |
||||
|
{ |
||||
|
if (num < 10) |
||||
|
Con_Printf ("%7i %s\n", best->profile, pr_strings+best->s_name); |
||||
|
num++; |
||||
|
best->profile = 0; |
||||
|
} |
||||
|
} while (best); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
PR_RunError |
||||
|
|
||||
|
Aborts the currently executing function |
||||
|
============ |
||||
|
*/ |
||||
|
void PR_RunError (char *error, ...) |
||||
|
{ |
||||
|
va_list argptr; |
||||
|
char string[1024]; |
||||
|
|
||||
|
va_start (argptr,error); |
||||
|
vsprintf (string,error,argptr); |
||||
|
va_end (argptr); |
||||
|
|
||||
|
PR_PrintStatement (pr_statements + pr_xstatement); |
||||
|
PR_StackTrace (); |
||||
|
Con_Printf ("%s\n", string); |
||||
|
|
||||
|
pr_depth = 0; // dump the stack so host_error can shutdown functions |
||||
|
|
||||
|
Host_Error ("Program error"); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
============================================================================ |
||||
|
PR_ExecuteProgram |
||||
|
|
||||
|
The interpretation main loop |
||||
|
============================================================================ |
||||
|
*/ |
||||
|
|
||||
|
/* |
||||
|
==================== |
||||
|
PR_EnterFunction |
||||
|
|
||||
|
Returns the new program statement counter |
||||
|
==================== |
||||
|
*/ |
||||
|
int PR_EnterFunction (dfunction_t *f) |
||||
|
{ |
||||
|
int i, j, c, o; |
||||
|
|
||||
|
pr_stack[pr_depth].s = pr_xstatement; |
||||
|
pr_stack[pr_depth].f = pr_xfunction; |
||||
|
pr_depth++; |
||||
|
if (pr_depth >= MAX_STACK_DEPTH) |
||||
|
PR_RunError ("stack overflow"); |
||||
|
|
||||
|
// save off any locals that the new function steps on |
||||
|
c = f->locals; |
||||
|
if (localstack_used + c > LOCALSTACK_SIZE) |
||||
|
PR_RunError ("PR_ExecuteProgram: locals stack overflow\n"); |
||||
|
|
||||
|
for (i=0 ; i < c ; i++) |
||||
|
localstack[localstack_used+i] = ((int *)pr_globals)[f->parm_start + i]; |
||||
|
localstack_used += c; |
||||
|
|
||||
|
// copy parameters |
||||
|
o = f->parm_start; |
||||
|
for (i=0 ; i<f->numparms ; i++) |
||||
|
{ |
||||
|
for (j=0 ; j<f->parm_size[i] ; j++) |
||||
|
{ |
||||
|
((int *)pr_globals)[o] = ((int *)pr_globals)[OFS_PARM0+i*3+j]; |
||||
|
o++; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
pr_xfunction = f; |
||||
|
return f->first_statement - 1; // offset the s++ |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
==================== |
||||
|
PR_LeaveFunction |
||||
|
==================== |
||||
|
*/ |
||||
|
int PR_LeaveFunction (void) |
||||
|
{ |
||||
|
int i, c; |
||||
|
|
||||
|
if (pr_depth <= 0) |
||||
|
Sys_Error ("prog stack underflow"); |
||||
|
|
||||
|
// restore locals from the stack |
||||
|
c = pr_xfunction->locals; |
||||
|
localstack_used -= c; |
||||
|
if (localstack_used < 0) |
||||
|
PR_RunError ("PR_ExecuteProgram: locals stack underflow\n"); |
||||
|
|
||||
|
for (i=0 ; i < c ; i++) |
||||
|
((int *)pr_globals)[pr_xfunction->parm_start + i] = localstack[localstack_used+i]; |
||||
|
|
||||
|
// up stack |
||||
|
pr_depth--; |
||||
|
pr_xfunction = pr_stack[pr_depth].f; |
||||
|
return pr_stack[pr_depth].s; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
==================== |
||||
|
PR_ExecuteProgram |
||||
|
==================== |
||||
|
*/ |
||||
|
void PR_ExecuteProgram (func_t fnum) |
||||
|
{ |
||||
|
eval_t *a, *b, *c; |
||||
|
int s; |
||||
|
dstatement_t *st; |
||||
|
dfunction_t *f, *newf; |
||||
|
int runaway; |
||||
|
int i; |
||||
|
edict_t *ed; |
||||
|
int exitdepth; |
||||
|
eval_t *ptr; |
||||
|
|
||||
|
if (!fnum || fnum >= progs->numfunctions) |
||||
|
{ |
||||
|
if (pr_global_struct->self) |
||||
|
ED_Print (PROG_TO_EDICT(pr_global_struct->self)); |
||||
|
Host_Error ("PR_ExecuteProgram: NULL function"); |
||||
|
} |
||||
|
|
||||
|
f = &pr_functions[fnum]; |
||||
|
|
||||
|
runaway = 100000; |
||||
|
pr_trace = false; |
||||
|
|
||||
|
// make a stack frame |
||||
|
exitdepth = pr_depth; |
||||
|
|
||||
|
s = PR_EnterFunction (f); |
||||
|
|
||||
|
while (1) |
||||
|
{ |
||||
|
s++; // next statement |
||||
|
|
||||
|
st = &pr_statements[s]; |
||||
|
a = (eval_t *)&pr_globals[st->a]; |
||||
|
b = (eval_t *)&pr_globals[st->b]; |
||||
|
c = (eval_t *)&pr_globals[st->c]; |
||||
|
|
||||
|
if (!--runaway) |
||||
|
PR_RunError ("runaway loop error"); |
||||
|
|
||||
|
pr_xfunction->profile++; |
||||
|
pr_xstatement = s; |
||||
|
|
||||
|
if (pr_trace) |
||||
|
PR_PrintStatement (st); |
||||
|
|
||||
|
switch (st->op) |
||||
|
{ |
||||
|
case OP_ADD_F: |
||||
|
c->_float = a->_float + b->_float; |
||||
|
break; |
||||
|
case OP_ADD_V: |
||||
|
c->vector[0] = a->vector[0] + b->vector[0]; |
||||
|
c->vector[1] = a->vector[1] + b->vector[1]; |
||||
|
c->vector[2] = a->vector[2] + b->vector[2]; |
||||
|
break; |
||||
|
|
||||
|
case OP_SUB_F: |
||||
|
c->_float = a->_float - b->_float; |
||||
|
break; |
||||
|
case OP_SUB_V: |
||||
|
c->vector[0] = a->vector[0] - b->vector[0]; |
||||
|
c->vector[1] = a->vector[1] - b->vector[1]; |
||||
|
c->vector[2] = a->vector[2] - b->vector[2]; |
||||
|
break; |
||||
|
|
||||
|
case OP_MUL_F: |
||||
|
c->_float = a->_float * b->_float; |
||||
|
break; |
||||
|
case OP_MUL_V: |
||||
|
c->_float = a->vector[0]*b->vector[0] |
||||
|
+ a->vector[1]*b->vector[1] |
||||
|
+ a->vector[2]*b->vector[2]; |
||||
|
break; |
||||
|
case OP_MUL_FV: |
||||
|
c->vector[0] = a->_float * b->vector[0]; |
||||
|
c->vector[1] = a->_float * b->vector[1]; |
||||
|
c->vector[2] = a->_float * b->vector[2]; |
||||
|
break; |
||||
|
case OP_MUL_VF: |
||||
|
c->vector[0] = b->_float * a->vector[0]; |
||||
|
c->vector[1] = b->_float * a->vector[1]; |
||||
|
c->vector[2] = b->_float * a->vector[2]; |
||||
|
break; |
||||
|
|
||||
|
case OP_DIV_F: |
||||
|
c->_float = a->_float / b->_float; |
||||
|
break; |
||||
|
|
||||
|
case OP_BITAND: |
||||
|
c->_float = (int)a->_float & (int)b->_float; |
||||
|
break; |
||||
|
|
||||
|
case OP_BITOR: |
||||
|
c->_float = (int)a->_float | (int)b->_float; |
||||
|
break; |
||||
|
|
||||
|
|
||||
|
case OP_GE: |
||||
|
c->_float = a->_float >= b->_float; |
||||
|
break; |
||||
|
case OP_LE: |
||||
|
c->_float = a->_float <= b->_float; |
||||
|
break; |
||||
|
case OP_GT: |
||||
|
c->_float = a->_float > b->_float; |
||||
|
break; |
||||
|
case OP_LT: |
||||
|
c->_float = a->_float < b->_float; |
||||
|
break; |
||||
|
case OP_AND: |
||||
|
c->_float = a->_float && b->_float; |
||||
|
break; |
||||
|
case OP_OR: |
||||
|
c->_float = a->_float || b->_float; |
||||
|
break; |
||||
|
|
||||
|
case OP_NOT_F: |
||||
|
c->_float = !a->_float; |
||||
|
break; |
||||
|
case OP_NOT_V: |
||||
|
c->_float = !a->vector[0] && !a->vector[1] && !a->vector[2]; |
||||
|
break; |
||||
|
case OP_NOT_S: |
||||
|
c->_float = !a->string || !pr_strings[a->string]; |
||||
|
break; |
||||
|
case OP_NOT_FNC: |
||||
|
c->_float = !a->function; |
||||
|
break; |
||||
|
case OP_NOT_ENT: |
||||
|
c->_float = (PROG_TO_EDICT(a->edict) == sv.edicts); |
||||
|
break; |
||||
|
|
||||
|
case OP_EQ_F: |
||||
|
c->_float = a->_float == b->_float; |
||||
|
break; |
||||
|
case OP_EQ_V: |
||||
|
c->_float = (a->vector[0] == b->vector[0]) && |
||||
|
(a->vector[1] == b->vector[1]) && |
||||
|
(a->vector[2] == b->vector[2]); |
||||
|
break; |
||||
|
case OP_EQ_S: |
||||
|
c->_float = !strcmp(pr_strings+a->string,pr_strings+b->string); |
||||
|
break; |
||||
|
case OP_EQ_E: |
||||
|
c->_float = a->_int == b->_int; |
||||
|
break; |
||||
|
case OP_EQ_FNC: |
||||
|
c->_float = a->function == b->function; |
||||
|
break; |
||||
|
|
||||
|
|
||||
|
case OP_NE_F: |
||||
|
c->_float = a->_float != b->_float; |
||||
|
break; |
||||
|
case OP_NE_V: |
||||
|
c->_float = (a->vector[0] != b->vector[0]) || |
||||
|
(a->vector[1] != b->vector[1]) || |
||||
|
(a->vector[2] != b->vector[2]); |
||||
|
break; |
||||
|
case OP_NE_S: |
||||
|
c->_float = strcmp(pr_strings+a->string,pr_strings+b->string); |
||||
|
break; |
||||
|
case OP_NE_E: |
||||
|
c->_float = a->_int != b->_int; |
||||
|
break; |
||||
|
case OP_NE_FNC: |
||||
|
c->_float = a->function != b->function; |
||||
|
break; |
||||
|
|
||||
|
//================== |
||||
|
case OP_STORE_F: |
||||
|
case OP_STORE_ENT: |
||||
|
case OP_STORE_FLD: // integers |
||||
|
case OP_STORE_S: |
||||
|
case OP_STORE_FNC: // pointers |
||||
|
b->_int = a->_int; |
||||
|
break; |
||||
|
case OP_STORE_V: |
||||
|
b->vector[0] = a->vector[0]; |
||||
|
b->vector[1] = a->vector[1]; |
||||
|
b->vector[2] = a->vector[2]; |
||||
|
break; |
||||
|
|
||||
|
case OP_STOREP_F: |
||||
|
case OP_STOREP_ENT: |
||||
|
case OP_STOREP_FLD: // integers |
||||
|
case OP_STOREP_S: |
||||
|
case OP_STOREP_FNC: // pointers |
||||
|
ptr = (eval_t *)((byte *)sv.edicts + b->_int); |
||||
|
ptr->_int = a->_int; |
||||
|
break; |
||||
|
case OP_STOREP_V: |
||||
|
ptr = (eval_t *)((byte *)sv.edicts + b->_int); |
||||
|
ptr->vector[0] = a->vector[0]; |
||||
|
ptr->vector[1] = a->vector[1]; |
||||
|
ptr->vector[2] = a->vector[2]; |
||||
|
break; |
||||
|
|
||||
|
case OP_ADDRESS: |
||||
|
ed = PROG_TO_EDICT(a->edict); |
||||
|
#ifdef PARANOID |
||||
|
NUM_FOR_EDICT(ed); // make sure it's in range |
||||
|
#endif |
||||
|
if (ed == (edict_t *)sv.edicts && sv.state == ss_active) |
||||
|
PR_RunError ("assignment to world entity"); |
||||
|
c->_int = (byte *)((int *)&ed->v + b->_int) - (byte *)sv.edicts; |
||||
|
break; |
||||
|
|
||||
|
case OP_LOAD_F: |
||||
|
case OP_LOAD_FLD: |
||||
|
case OP_LOAD_ENT: |
||||
|
case OP_LOAD_S: |
||||
|
case OP_LOAD_FNC: |
||||
|
ed = PROG_TO_EDICT(a->edict); |
||||
|
#ifdef PARANOID |
||||
|
NUM_FOR_EDICT(ed); // make sure it's in range |
||||
|
#endif |
||||
|
a = (eval_t *)((int *)&ed->v + b->_int); |
||||
|
c->_int = a->_int; |
||||
|
break; |
||||
|
|
||||
|
case OP_LOAD_V: |
||||
|
ed = PROG_TO_EDICT(a->edict); |
||||
|
#ifdef PARANOID |
||||
|
NUM_FOR_EDICT(ed); // make sure it's in range |
||||
|
#endif |
||||
|
a = (eval_t *)((int *)&ed->v + b->_int); |
||||
|
c->vector[0] = a->vector[0]; |
||||
|
c->vector[1] = a->vector[1]; |
||||
|
c->vector[2] = a->vector[2]; |
||||
|
break; |
||||
|
|
||||
|
//================== |
||||
|
|
||||
|
case OP_IFNOT: |
||||
|
if (!a->_int) |
||||
|
s += st->b - 1; // offset the s++ |
||||
|
break; |
||||
|
|
||||
|
case OP_IF: |
||||
|
if (a->_int) |
||||
|
s += st->b - 1; // offset the s++ |
||||
|
break; |
||||
|
|
||||
|
case OP_GOTO: |
||||
|
s += st->a - 1; // offset the s++ |
||||
|
break; |
||||
|
|
||||
|
case OP_CALL0: |
||||
|
case OP_CALL1: |
||||
|
case OP_CALL2: |
||||
|
case OP_CALL3: |
||||
|
case OP_CALL4: |
||||
|
case OP_CALL5: |
||||
|
case OP_CALL6: |
||||
|
case OP_CALL7: |
||||
|
case OP_CALL8: |
||||
|
pr_argc = st->op - OP_CALL0; |
||||
|
if (!a->function) |
||||
|
PR_RunError ("NULL function"); |
||||
|
|
||||
|
newf = &pr_functions[a->function]; |
||||
|
|
||||
|
if (newf->first_statement < 0) |
||||
|
{ // negative statements are built in functions |
||||
|
i = -newf->first_statement; |
||||
|
if (i >= pr_numbuiltins) |
||||
|
PR_RunError ("Bad builtin call number"); |
||||
|
pr_builtins[i] (); |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
s = PR_EnterFunction (newf); |
||||
|
break; |
||||
|
|
||||
|
case OP_DONE: |
||||
|
case OP_RETURN: |
||||
|
pr_globals[OFS_RETURN] = pr_globals[st->a]; |
||||
|
pr_globals[OFS_RETURN+1] = pr_globals[st->a+1]; |
||||
|
pr_globals[OFS_RETURN+2] = pr_globals[st->a+2]; |
||||
|
|
||||
|
s = PR_LeaveFunction (); |
||||
|
if (pr_depth == exitdepth) |
||||
|
return; // all done |
||||
|
break; |
||||
|
|
||||
|
case OP_STATE: |
||||
|
ed = PROG_TO_EDICT(pr_global_struct->self); |
||||
|
#ifdef FPS_20 |
||||
|
ed->v.nextthink = pr_global_struct->time + 0.05; |
||||
|
#else |
||||
|
ed->v.nextthink = pr_global_struct->time + 0.1; |
||||
|
#endif |
||||
|
if (a->_float != ed->v.frame) |
||||
|
{ |
||||
|
ed->v.frame = a->_float; |
||||
|
} |
||||
|
ed->v.think = b->function; |
||||
|
break; |
||||
|
|
||||
|
default: |
||||
|
PR_RunError ("Bad opcode %i", st->op); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
#ifdef QUAKE2 |
||||
|
#include "progdefs.q2" |
||||
|
#else |
||||
|
#include "progdefs.q1" |
||||
|
#endif |
||||
@ -0,0 +1,143 @@ |
|||||
|
|
||||
|
/* file generated by qcc, do not modify */ |
||||
|
|
||||
|
typedef struct |
||||
|
{ int pad[28]; |
||||
|
int self; |
||||
|
int other; |
||||
|
int world; |
||||
|
float time; |
||||
|
float frametime; |
||||
|
float force_retouch; |
||||
|
string_t mapname; |
||||
|
float deathmatch; |
||||
|
float coop; |
||||
|
float teamplay; |
||||
|
float serverflags; |
||||
|
float total_secrets; |
||||
|
float total_monsters; |
||||
|
float found_secrets; |
||||
|
float killed_monsters; |
||||
|
float parm1; |
||||
|
float parm2; |
||||
|
float parm3; |
||||
|
float parm4; |
||||
|
float parm5; |
||||
|
float parm6; |
||||
|
float parm7; |
||||
|
float parm8; |
||||
|
float parm9; |
||||
|
float parm10; |
||||
|
float parm11; |
||||
|
float parm12; |
||||
|
float parm13; |
||||
|
float parm14; |
||||
|
float parm15; |
||||
|
float parm16; |
||||
|
vec3_t v_forward; |
||||
|
vec3_t v_up; |
||||
|
vec3_t v_right; |
||||
|
float trace_allsolid; |
||||
|
float trace_startsolid; |
||||
|
float trace_fraction; |
||||
|
vec3_t trace_endpos; |
||||
|
vec3_t trace_plane_normal; |
||||
|
float trace_plane_dist; |
||||
|
int trace_ent; |
||||
|
float trace_inopen; |
||||
|
float trace_inwater; |
||||
|
int msg_entity; |
||||
|
func_t main; |
||||
|
func_t StartFrame; |
||||
|
func_t PlayerPreThink; |
||||
|
func_t PlayerPostThink; |
||||
|
func_t ClientKill; |
||||
|
func_t ClientConnect; |
||||
|
func_t PutClientInServer; |
||||
|
func_t ClientDisconnect; |
||||
|
func_t SetNewParms; |
||||
|
func_t SetChangeParms; |
||||
|
} globalvars_t; |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
float modelindex; |
||||
|
vec3_t absmin; |
||||
|
vec3_t absmax; |
||||
|
float ltime; |
||||
|
float movetype; |
||||
|
float solid; |
||||
|
vec3_t origin; |
||||
|
vec3_t oldorigin; |
||||
|
vec3_t velocity; |
||||
|
vec3_t angles; |
||||
|
vec3_t avelocity; |
||||
|
vec3_t punchangle; |
||||
|
string_t classname; |
||||
|
string_t model; |
||||
|
float frame; |
||||
|
float skin; |
||||
|
float effects; |
||||
|
vec3_t mins; |
||||
|
vec3_t maxs; |
||||
|
vec3_t size; |
||||
|
func_t touch; |
||||
|
func_t use; |
||||
|
func_t think; |
||||
|
func_t blocked; |
||||
|
float nextthink; |
||||
|
int groundentity; |
||||
|
float health; |
||||
|
float frags; |
||||
|
float weapon; |
||||
|
string_t weaponmodel; |
||||
|
float weaponframe; |
||||
|
float currentammo; |
||||
|
float ammo_shells; |
||||
|
float ammo_nails; |
||||
|
float ammo_rockets; |
||||
|
float ammo_cells; |
||||
|
float items; |
||||
|
float takedamage; |
||||
|
int chain; |
||||
|
float deadflag; |
||||
|
vec3_t view_ofs; |
||||
|
float button0; |
||||
|
float button1; |
||||
|
float button2; |
||||
|
float impulse; |
||||
|
float fixangle; |
||||
|
vec3_t v_angle; |
||||
|
float idealpitch; |
||||
|
string_t netname; |
||||
|
int enemy; |
||||
|
float flags; |
||||
|
float colormap; |
||||
|
float team; |
||||
|
float max_health; |
||||
|
float teleport_time; |
||||
|
float armortype; |
||||
|
float armorvalue; |
||||
|
float waterlevel; |
||||
|
float watertype; |
||||
|
float ideal_yaw; |
||||
|
float yaw_speed; |
||||
|
int aiment; |
||||
|
int goalentity; |
||||
|
float spawnflags; |
||||
|
string_t target; |
||||
|
string_t targetname; |
||||
|
float dmg_take; |
||||
|
float dmg_save; |
||||
|
int dmg_inflictor; |
||||
|
int owner; |
||||
|
vec3_t movedir; |
||||
|
string_t message; |
||||
|
float sounds; |
||||
|
string_t noise; |
||||
|
string_t noise1; |
||||
|
string_t noise2; |
||||
|
string_t noise3; |
||||
|
} entvars_t; |
||||
|
|
||||
|
#define PROGHEADER_CRC 5927 |
||||
@ -0,0 +1,158 @@ |
|||||
|
|
||||
|
/* file generated by qcc, do not modify */ |
||||
|
|
||||
|
typedef struct |
||||
|
{ int pad[28]; |
||||
|
int self; |
||||
|
int other; |
||||
|
int world; |
||||
|
float time; |
||||
|
float frametime; |
||||
|
float force_retouch; |
||||
|
string_t mapname; |
||||
|
string_t startspot; |
||||
|
float deathmatch; |
||||
|
float coop; |
||||
|
float teamplay; |
||||
|
float serverflags; |
||||
|
float total_secrets; |
||||
|
float total_monsters; |
||||
|
float found_secrets; |
||||
|
float killed_monsters; |
||||
|
float parm1; |
||||
|
float parm2; |
||||
|
float parm3; |
||||
|
float parm4; |
||||
|
float parm5; |
||||
|
float parm6; |
||||
|
float parm7; |
||||
|
float parm8; |
||||
|
float parm9; |
||||
|
float parm10; |
||||
|
float parm11; |
||||
|
float parm12; |
||||
|
float parm13; |
||||
|
float parm14; |
||||
|
float parm15; |
||||
|
float parm16; |
||||
|
vec3_t v_forward; |
||||
|
vec3_t v_up; |
||||
|
vec3_t v_right; |
||||
|
float trace_allsolid; |
||||
|
float trace_startsolid; |
||||
|
float trace_fraction; |
||||
|
vec3_t trace_endpos; |
||||
|
vec3_t trace_plane_normal; |
||||
|
float trace_plane_dist; |
||||
|
int trace_ent; |
||||
|
float trace_inopen; |
||||
|
float trace_inwater; |
||||
|
int msg_entity; |
||||
|
string_t null; |
||||
|
func_t main; |
||||
|
func_t StartFrame; |
||||
|
func_t PlayerPreThink; |
||||
|
func_t PlayerPostThink; |
||||
|
func_t ClientKill; |
||||
|
func_t ClientConnect; |
||||
|
func_t PutClientInServer; |
||||
|
func_t ClientDisconnect; |
||||
|
func_t SetNewParms; |
||||
|
func_t SetChangeParms; |
||||
|
} globalvars_t; |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
float modelindex; |
||||
|
vec3_t absmin; |
||||
|
vec3_t absmax; |
||||
|
float ltime; |
||||
|
float movetype; |
||||
|
float solid; |
||||
|
vec3_t origin; |
||||
|
vec3_t oldorigin; |
||||
|
vec3_t velocity; |
||||
|
vec3_t angles; |
||||
|
vec3_t avelocity; |
||||
|
vec3_t basevelocity; |
||||
|
vec3_t punchangle; |
||||
|
string_t classname; |
||||
|
string_t model; |
||||
|
float frame; |
||||
|
float skin; |
||||
|
float effects; |
||||
|
float drawPercent; |
||||
|
float gravity; |
||||
|
float mass; |
||||
|
float light_level; |
||||
|
vec3_t mins; |
||||
|
vec3_t maxs; |
||||
|
vec3_t size; |
||||
|
func_t touch; |
||||
|
func_t use; |
||||
|
func_t think; |
||||
|
func_t blocked; |
||||
|
float nextthink; |
||||
|
int groundentity; |
||||
|
float health; |
||||
|
float frags; |
||||
|
float weapon; |
||||
|
string_t weaponmodel; |
||||
|
float weaponframe; |
||||
|
float currentammo; |
||||
|
float ammo_shells; |
||||
|
float ammo_nails; |
||||
|
float ammo_rockets; |
||||
|
float ammo_cells; |
||||
|
float items; |
||||
|
float items2; |
||||
|
float takedamage; |
||||
|
int chain; |
||||
|
float deadflag; |
||||
|
vec3_t view_ofs; |
||||
|
float button0; |
||||
|
float button1; |
||||
|
float button2; |
||||
|
float impulse; |
||||
|
float fixangle; |
||||
|
vec3_t v_angle; |
||||
|
float idealpitch; |
||||
|
float pitch_speed; |
||||
|
string_t netname; |
||||
|
int enemy; |
||||
|
float flags; |
||||
|
float colormap; |
||||
|
float team; |
||||
|
float max_health; |
||||
|
float teleport_time; |
||||
|
float armortype; |
||||
|
float armorvalue; |
||||
|
float waterlevel; |
||||
|
float watertype; |
||||
|
float ideal_yaw; |
||||
|
float yaw_speed; |
||||
|
int aiment; |
||||
|
int goalentity; |
||||
|
float spawnflags; |
||||
|
string_t target; |
||||
|
string_t targetname; |
||||
|
float dmg_take; |
||||
|
float dmg_save; |
||||
|
int dmg_inflictor; |
||||
|
int owner; |
||||
|
vec3_t movedir; |
||||
|
string_t message; |
||||
|
float sounds; |
||||
|
string_t noise; |
||||
|
string_t noise1; |
||||
|
string_t noise2; |
||||
|
string_t noise3; |
||||
|
float dmg; |
||||
|
float dmgtime; |
||||
|
float air_finished; |
||||
|
float pain_finished; |
||||
|
float radsuit_finished; |
||||
|
float speed; |
||||
|
} entvars_t; |
||||
|
|
||||
|
#define PROGHEADER_CRC 31586 |
||||
@ -0,0 +1,134 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
#include "pr_comp.h" // defs shared with qcc |
||||
|
#include "progdefs.h" // generated by program cdefs |
||||
|
|
||||
|
typedef union eval_s |
||||
|
{ |
||||
|
string_t string; |
||||
|
float _float; |
||||
|
float vector[3]; |
||||
|
func_t function; |
||||
|
int _int; |
||||
|
int edict; |
||||
|
} eval_t; |
||||
|
|
||||
|
#define MAX_ENT_LEAFS 16 |
||||
|
typedef struct edict_s |
||||
|
{ |
||||
|
qboolean free; |
||||
|
link_t area; // linked to a division node or leaf |
||||
|
|
||||
|
int num_leafs; |
||||
|
short leafnums[MAX_ENT_LEAFS]; |
||||
|
|
||||
|
entity_state_t baseline; |
||||
|
|
||||
|
float freetime; // sv.time when the object was freed |
||||
|
entvars_t v; // C exported fields from progs |
||||
|
// other fields from progs come immediately after |
||||
|
} edict_t; |
||||
|
#define EDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,edict_t,area) |
||||
|
|
||||
|
//============================================================================ |
||||
|
|
||||
|
extern dprograms_t *progs; |
||||
|
extern dfunction_t *pr_functions; |
||||
|
extern char *pr_strings; |
||||
|
extern ddef_t *pr_globaldefs; |
||||
|
extern ddef_t *pr_fielddefs; |
||||
|
extern dstatement_t *pr_statements; |
||||
|
extern globalvars_t *pr_global_struct; |
||||
|
extern float *pr_globals; // same as pr_global_struct |
||||
|
|
||||
|
extern int pr_edict_size; // in bytes |
||||
|
|
||||
|
//============================================================================ |
||||
|
|
||||
|
void PR_Init (void); |
||||
|
|
||||
|
void PR_ExecuteProgram (func_t fnum); |
||||
|
void PR_LoadProgs (void); |
||||
|
|
||||
|
void PR_Profile_f (void); |
||||
|
|
||||
|
edict_t *ED_Alloc (void); |
||||
|
void ED_Free (edict_t *ed); |
||||
|
|
||||
|
char *ED_NewString (char *string); |
||||
|
// returns a copy of the string allocated from the server's string heap |
||||
|
|
||||
|
void ED_Print (edict_t *ed); |
||||
|
void ED_Write (FILE *f, edict_t *ed); |
||||
|
char *ED_ParseEdict (char *data, edict_t *ent); |
||||
|
|
||||
|
void ED_WriteGlobals (FILE *f); |
||||
|
void ED_ParseGlobals (char *data); |
||||
|
|
||||
|
void ED_LoadFromFile (char *data); |
||||
|
|
||||
|
//define EDICT_NUM(n) ((edict_t *)(sv.edicts+ (n)*pr_edict_size)) |
||||
|
//define NUM_FOR_EDICT(e) (((byte *)(e) - sv.edicts)/pr_edict_size) |
||||
|
|
||||
|
edict_t *EDICT_NUM(int n); |
||||
|
int NUM_FOR_EDICT(edict_t *e); |
||||
|
|
||||
|
#define NEXT_EDICT(e) ((edict_t *)( (byte *)e + pr_edict_size)) |
||||
|
|
||||
|
#define EDICT_TO_PROG(e) ((byte *)e - (byte *)sv.edicts) |
||||
|
#define PROG_TO_EDICT(e) ((edict_t *)((byte *)sv.edicts + e)) |
||||
|
|
||||
|
//============================================================================ |
||||
|
|
||||
|
#define G_FLOAT(o) (pr_globals[o]) |
||||
|
#define G_INT(o) (*(int *)&pr_globals[o]) |
||||
|
#define G_EDICT(o) ((edict_t *)((byte *)sv.edicts+ *(int *)&pr_globals[o])) |
||||
|
#define G_EDICTNUM(o) NUM_FOR_EDICT(G_EDICT(o)) |
||||
|
#define G_VECTOR(o) (&pr_globals[o]) |
||||
|
#define G_STRING(o) (pr_strings + *(string_t *)&pr_globals[o]) |
||||
|
#define G_FUNCTION(o) (*(func_t *)&pr_globals[o]) |
||||
|
|
||||
|
#define E_FLOAT(e,o) (((float*)&e->v)[o]) |
||||
|
#define E_INT(e,o) (*(int *)&((float*)&e->v)[o]) |
||||
|
#define E_VECTOR(e,o) (&((float*)&e->v)[o]) |
||||
|
#define E_STRING(e,o) (pr_strings + *(string_t *)&((float*)&e->v)[o]) |
||||
|
|
||||
|
extern int type_size[8]; |
||||
|
|
||||
|
typedef void (*builtin_t) (void); |
||||
|
extern builtin_t *pr_builtins; |
||||
|
extern int pr_numbuiltins; |
||||
|
|
||||
|
extern int pr_argc; |
||||
|
|
||||
|
extern qboolean pr_trace; |
||||
|
extern dfunction_t *pr_xfunction; |
||||
|
extern int pr_xstatement; |
||||
|
|
||||
|
extern unsigned short pr_crc; |
||||
|
|
||||
|
void PR_RunError (char *error, ...); |
||||
|
|
||||
|
void ED_PrintEdicts (void); |
||||
|
void ED_PrintNum (int ent); |
||||
|
|
||||
|
eval_t *GetEdictFieldValue(edict_t *ed, char *field); |
||||
|
|
||||
@ -0,0 +1,173 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// protocol.h -- communications protocols |
||||
|
|
||||
|
#define PROTOCOL_VERSION 15 |
||||
|
|
||||
|
// if the high bit of the servercmd is set, the low bits are fast update flags: |
||||
|
#define U_MOREBITS (1<<0) |
||||
|
#define U_ORIGIN1 (1<<1) |
||||
|
#define U_ORIGIN2 (1<<2) |
||||
|
#define U_ORIGIN3 (1<<3) |
||||
|
#define U_ANGLE2 (1<<4) |
||||
|
#define U_NOLERP (1<<5) // don't interpolate movement |
||||
|
#define U_FRAME (1<<6) |
||||
|
#define U_SIGNAL (1<<7) // just differentiates from other updates |
||||
|
|
||||
|
// svc_update can pass all of the fast update bits, plus more |
||||
|
#define U_ANGLE1 (1<<8) |
||||
|
#define U_ANGLE3 (1<<9) |
||||
|
#define U_MODEL (1<<10) |
||||
|
#define U_COLORMAP (1<<11) |
||||
|
#define U_SKIN (1<<12) |
||||
|
#define U_EFFECTS (1<<13) |
||||
|
#define U_LONGENTITY (1<<14) |
||||
|
|
||||
|
|
||||
|
#define SU_VIEWHEIGHT (1<<0) |
||||
|
#define SU_IDEALPITCH (1<<1) |
||||
|
#define SU_PUNCH1 (1<<2) |
||||
|
#define SU_PUNCH2 (1<<3) |
||||
|
#define SU_PUNCH3 (1<<4) |
||||
|
#define SU_VELOCITY1 (1<<5) |
||||
|
#define SU_VELOCITY2 (1<<6) |
||||
|
#define SU_VELOCITY3 (1<<7) |
||||
|
//define SU_AIMENT (1<<8) AVAILABLE BIT |
||||
|
#define SU_ITEMS (1<<9) |
||||
|
#define SU_ONGROUND (1<<10) // no data follows, the bit is it |
||||
|
#define SU_INWATER (1<<11) // no data follows, the bit is it |
||||
|
#define SU_WEAPONFRAME (1<<12) |
||||
|
#define SU_ARMOR (1<<13) |
||||
|
#define SU_WEAPON (1<<14) |
||||
|
|
||||
|
// a sound with no channel is a local only sound |
||||
|
#define SND_VOLUME (1<<0) // a byte |
||||
|
#define SND_ATTENUATION (1<<1) // a byte |
||||
|
#define SND_LOOPING (1<<2) // a long |
||||
|
|
||||
|
|
||||
|
// defaults for clientinfo messages |
||||
|
#define DEFAULT_VIEWHEIGHT 22 |
||||
|
|
||||
|
|
||||
|
// game types sent by serverinfo |
||||
|
// these determine which intermission screen plays |
||||
|
#define GAME_COOP 0 |
||||
|
#define GAME_DEATHMATCH 1 |
||||
|
|
||||
|
//================== |
||||
|
// note that there are some defs.qc that mirror to these numbers |
||||
|
// also related to svc_strings[] in cl_parse |
||||
|
//================== |
||||
|
|
||||
|
// |
||||
|
// server to client |
||||
|
// |
||||
|
#define svc_bad 0 |
||||
|
#define svc_nop 1 |
||||
|
#define svc_disconnect 2 |
||||
|
#define svc_updatestat 3 // [byte] [long] |
||||
|
#define svc_version 4 // [long] server version |
||||
|
#define svc_setview 5 // [short] entity number |
||||
|
#define svc_sound 6 // <see code> |
||||
|
#define svc_time 7 // [float] server time |
||||
|
#define svc_print 8 // [string] null terminated string |
||||
|
#define svc_stufftext 9 // [string] stuffed into client's console buffer |
||||
|
// the string should be \n terminated |
||||
|
#define svc_setangle 10 // [angle3] set the view angle to this absolute value |
||||
|
|
||||
|
#define svc_serverinfo 11 // [long] version |
||||
|
// [string] signon string |
||||
|
// [string]..[0]model cache |
||||
|
// [string]...[0]sounds cache |
||||
|
#define svc_lightstyle 12 // [byte] [string] |
||||
|
#define svc_updatename 13 // [byte] [string] |
||||
|
#define svc_updatefrags 14 // [byte] [short] |
||||
|
#define svc_clientdata 15 // <shortbits + data> |
||||
|
#define svc_stopsound 16 // <see code> |
||||
|
#define svc_updatecolors 17 // [byte] [byte] |
||||
|
#define svc_particle 18 // [vec3] <variable> |
||||
|
#define svc_damage 19 |
||||
|
|
||||
|
#define svc_spawnstatic 20 |
||||
|
// svc_spawnbinary 21 |
||||
|
#define svc_spawnbaseline 22 |
||||
|
|
||||
|
#define svc_temp_entity 23 |
||||
|
|
||||
|
#define svc_setpause 24 // [byte] on / off |
||||
|
#define svc_signonnum 25 // [byte] used for the signon sequence |
||||
|
|
||||
|
#define svc_centerprint 26 // [string] to put in center of the screen |
||||
|
|
||||
|
#define svc_killedmonster 27 |
||||
|
#define svc_foundsecret 28 |
||||
|
|
||||
|
#define svc_spawnstaticsound 29 // [coord3] [byte] samp [byte] vol [byte] aten |
||||
|
|
||||
|
#define svc_intermission 30 // [string] music |
||||
|
#define svc_finale 31 // [string] music [string] text |
||||
|
|
||||
|
#define svc_cdtrack 32 // [byte] track [byte] looptrack |
||||
|
#define svc_sellscreen 33 |
||||
|
|
||||
|
#define svc_cutscene 34 |
||||
|
|
||||
|
|
||||
|
// jkrige - skybox |
||||
|
#define svc_skybox 35 // [string] name |
||||
|
// jkrige - skybox |
||||
|
|
||||
|
|
||||
|
// |
||||
|
// client to server |
||||
|
// |
||||
|
#define clc_bad 0 |
||||
|
#define clc_nop 1 |
||||
|
#define clc_disconnect 2 |
||||
|
#define clc_move 3 // [usercmd_t] |
||||
|
#define clc_stringcmd 4 // [string] message |
||||
|
|
||||
|
|
||||
|
// |
||||
|
// temp entity events |
||||
|
// |
||||
|
#define TE_SPIKE 0 |
||||
|
#define TE_SUPERSPIKE 1 |
||||
|
#define TE_GUNSHOT 2 |
||||
|
#define TE_EXPLOSION 3 |
||||
|
#define TE_TAREXPLOSION 4 |
||||
|
#define TE_LIGHTNING1 5 |
||||
|
#define TE_LIGHTNING2 6 |
||||
|
#define TE_WIZSPIKE 7 |
||||
|
#define TE_KNIGHTSPIKE 8 |
||||
|
#define TE_LIGHTNING3 9 |
||||
|
#define TE_LAVASPLASH 10 |
||||
|
#define TE_TELEPORT 11 |
||||
|
#define TE_EXPLOSION2 12 |
||||
|
|
||||
|
// PGM 01/21/97 |
||||
|
#define TE_BEAM 13 |
||||
|
// PGM 01/21/97 |
||||
|
|
||||
|
#ifdef QUAKE2 |
||||
|
#define TE_IMPLOSION 14 |
||||
|
#define TE_RAILTRAIL 15 |
||||
|
#endif |
||||
@ -0,0 +1,359 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// quakedef.h -- primary header for client |
||||
|
|
||||
|
//#define GLTEST // experimental stuff |
||||
|
|
||||
|
#define QUAKE_GAME // as opposed to utilities |
||||
|
|
||||
|
#define QUAKE_VERSION 1.13 // jkrige - new version |
||||
|
//#define VERSION 1.09 |
||||
|
//#define GLQUAKE_VERSION 1.00 |
||||
|
//#define D3DQUAKE_VERSION 0.01 |
||||
|
//#define WINQUAKE_VERSION 0.996 |
||||
|
#define LINUX_VERSION 1.30 |
||||
|
#define X11_VERSION 1.10 |
||||
|
|
||||
|
//define PARANOID // speed sapping error checking |
||||
|
|
||||
|
#ifdef QUAKE2 |
||||
|
#define GAMENAME "id1" // directory to look in by default |
||||
|
#else |
||||
|
#define GAMENAME "id1" |
||||
|
#endif |
||||
|
|
||||
|
#include <math.h> |
||||
|
#include <string.h> |
||||
|
#include <stdarg.h> |
||||
|
#include <stdio.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <setjmp.h> |
||||
|
|
||||
|
// jkrige - pack naming convention |
||||
|
#include <io.h> |
||||
|
// jkrige - pack naming convention |
||||
|
|
||||
|
#if defined(_WIN32) && !defined(WINDED) |
||||
|
|
||||
|
#if defined(_M_IX86) |
||||
|
#define __i386__ 1 |
||||
|
#endif |
||||
|
|
||||
|
void VID_LockBuffer (void); |
||||
|
void VID_UnlockBuffer (void); |
||||
|
|
||||
|
#else |
||||
|
|
||||
|
#define VID_LockBuffer() |
||||
|
#define VID_UnlockBuffer() |
||||
|
|
||||
|
#endif |
||||
|
|
||||
|
#if defined __i386__ // && !defined __sun__ |
||||
|
#define id386 0 // jkrige - assembly removal (was 1) |
||||
|
#else |
||||
|
#define id386 0 |
||||
|
#endif |
||||
|
|
||||
|
#if id386 |
||||
|
#define UNALIGNED_OK 1 // set to 0 if unaligned accesses are not supported |
||||
|
#else |
||||
|
#define UNALIGNED_OK 0 |
||||
|
#endif |
||||
|
|
||||
|
// !!! if this is changed, it must be changed in d_ifacea.h too !!! |
||||
|
#define CACHE_SIZE 32 // used to align key data structures |
||||
|
|
||||
|
#define UNUSED(x) (x = x) // for pesky compiler / lint warnings |
||||
|
|
||||
|
//#define MINIMUM_MEMORY 0x550000 // jkrige - memory increase: 5 570 560 bytes |
||||
|
#define MINIMUM_MEMORY 0xAA0000 // jkrige - memory increase: 11 141 120 bytes |
||||
|
#define MINIMUM_MEMORY_LEVELPAK (MINIMUM_MEMORY + 0x100000) |
||||
|
|
||||
|
#define MAX_NUM_ARGVS 50 |
||||
|
|
||||
|
// up / down |
||||
|
#define PITCH 0 |
||||
|
|
||||
|
// left / right |
||||
|
#define YAW 1 |
||||
|
|
||||
|
// fall over |
||||
|
#define ROLL 2 |
||||
|
|
||||
|
|
||||
|
#define MAX_QPATH 64 // max length of a quake game pathname |
||||
|
#define MAX_OSPATH 128 // max length of a filesystem pathname |
||||
|
|
||||
|
// jkrige - pk3 file support |
||||
|
#define MAX_ZPATH 256 // max length of a filesystem pathname, which must include a terminating zero |
||||
|
// jkrige - pk3 file support |
||||
|
|
||||
|
|
||||
|
#define ON_EPSILON 0.1 // point on plane side epsilon |
||||
|
|
||||
|
#define MAX_MSGLEN 8000 // max length of a reliable message |
||||
|
#define MAX_DATAGRAM 1024 // max length of unreliable message |
||||
|
|
||||
|
// |
||||
|
// per-level limits |
||||
|
// |
||||
|
#define MAX_EDICTS 600 // FIXME: ouch! ouch! ouch! |
||||
|
#define MAX_LIGHTSTYLES 64 |
||||
|
#define MAX_MODELS 256 // these are sent over the net as bytes |
||||
|
#define MAX_SOUNDS 256 // so they cannot be blindly increased |
||||
|
|
||||
|
#define SAVEGAME_COMMENT_LENGTH 39 |
||||
|
|
||||
|
#define MAX_STYLESTRING 64 |
||||
|
|
||||
|
// |
||||
|
// stats are integers communicated to the client by the server |
||||
|
// |
||||
|
#define MAX_CL_STATS 32 |
||||
|
#define STAT_HEALTH 0 |
||||
|
#define STAT_FRAGS 1 |
||||
|
#define STAT_WEAPON 2 |
||||
|
#define STAT_AMMO 3 |
||||
|
#define STAT_ARMOR 4 |
||||
|
#define STAT_WEAPONFRAME 5 |
||||
|
#define STAT_SHELLS 6 |
||||
|
#define STAT_NAILS 7 |
||||
|
#define STAT_ROCKETS 8 |
||||
|
#define STAT_CELLS 9 |
||||
|
#define STAT_ACTIVEWEAPON 10 |
||||
|
#define STAT_TOTALSECRETS 11 |
||||
|
#define STAT_TOTALMONSTERS 12 |
||||
|
#define STAT_SECRETS 13 // bumped on client side by svc_foundsecret |
||||
|
#define STAT_MONSTERS 14 // bumped by svc_killedmonster |
||||
|
|
||||
|
// stock defines |
||||
|
|
||||
|
#define IT_SHOTGUN 1 |
||||
|
#define IT_SUPER_SHOTGUN 2 |
||||
|
#define IT_NAILGUN 4 |
||||
|
#define IT_SUPER_NAILGUN 8 |
||||
|
#define IT_GRENADE_LAUNCHER 16 |
||||
|
#define IT_ROCKET_LAUNCHER 32 |
||||
|
#define IT_LIGHTNING 64 |
||||
|
#define IT_SUPER_LIGHTNING 128 |
||||
|
#define IT_SHELLS 256 |
||||
|
#define IT_NAILS 512 |
||||
|
#define IT_ROCKETS 1024 |
||||
|
#define IT_CELLS 2048 |
||||
|
#define IT_AXE 4096 |
||||
|
#define IT_ARMOR1 8192 |
||||
|
#define IT_ARMOR2 16384 |
||||
|
#define IT_ARMOR3 32768 |
||||
|
#define IT_SUPERHEALTH 65536 |
||||
|
#define IT_KEY1 131072 |
||||
|
#define IT_KEY2 262144 |
||||
|
#define IT_INVISIBILITY 524288 |
||||
|
#define IT_INVULNERABILITY 1048576 |
||||
|
#define IT_SUIT 2097152 |
||||
|
#define IT_QUAD 4194304 |
||||
|
#define IT_SIGIL1 (1<<28) |
||||
|
#define IT_SIGIL2 (1<<29) |
||||
|
#define IT_SIGIL3 (1<<30) |
||||
|
#define IT_SIGIL4 (1<<31) |
||||
|
|
||||
|
//=========================================== |
||||
|
//rogue changed and added defines |
||||
|
|
||||
|
#define RIT_SHELLS 128 |
||||
|
#define RIT_NAILS 256 |
||||
|
#define RIT_ROCKETS 512 |
||||
|
#define RIT_CELLS 1024 |
||||
|
#define RIT_AXE 2048 |
||||
|
#define RIT_LAVA_NAILGUN 4096 |
||||
|
#define RIT_LAVA_SUPER_NAILGUN 8192 |
||||
|
#define RIT_MULTI_GRENADE 16384 |
||||
|
#define RIT_MULTI_ROCKET 32768 |
||||
|
#define RIT_PLASMA_GUN 65536 |
||||
|
#define RIT_ARMOR1 8388608 |
||||
|
#define RIT_ARMOR2 16777216 |
||||
|
#define RIT_ARMOR3 33554432 |
||||
|
#define RIT_LAVA_NAILS 67108864 |
||||
|
#define RIT_PLASMA_AMMO 134217728 |
||||
|
#define RIT_MULTI_ROCKETS 268435456 |
||||
|
#define RIT_SHIELD 536870912 |
||||
|
#define RIT_ANTIGRAV 1073741824 |
||||
|
#define RIT_SUPERHEALTH 2147483648 |
||||
|
|
||||
|
//MED 01/04/97 added hipnotic defines |
||||
|
//=========================================== |
||||
|
//hipnotic added defines |
||||
|
#define HIT_PROXIMITY_GUN_BIT 16 |
||||
|
#define HIT_MJOLNIR_BIT 7 |
||||
|
#define HIT_LASER_CANNON_BIT 23 |
||||
|
#define HIT_PROXIMITY_GUN (1<<HIT_PROXIMITY_GUN_BIT) |
||||
|
#define HIT_MJOLNIR (1<<HIT_MJOLNIR_BIT) |
||||
|
#define HIT_LASER_CANNON (1<<HIT_LASER_CANNON_BIT) |
||||
|
#define HIT_WETSUIT (1<<(23+2)) |
||||
|
#define HIT_EMPATHY_SHIELDS (1<<(23+3)) |
||||
|
|
||||
|
//=========================================== |
||||
|
|
||||
|
#define MAX_SCOREBOARD 16 |
||||
|
#define MAX_SCOREBOARDNAME 32 |
||||
|
|
||||
|
#define SOUND_CHANNELS 8 |
||||
|
|
||||
|
// This makes anyone on id's net privileged |
||||
|
// Use for multiplayer testing only - VERY dangerous!!! |
||||
|
// #define IDGODS |
||||
|
|
||||
|
#include "common.h" |
||||
|
#include "bspfile.h" |
||||
|
#include "vid.h" |
||||
|
|
||||
|
// jkrige - pk3 file support |
||||
|
#include "unzip.h" |
||||
|
// jkrige - pk3 file support |
||||
|
|
||||
|
#include "sys.h" |
||||
|
#include "zone.h" |
||||
|
#include "mathlib.h" |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
vec3_t origin; |
||||
|
vec3_t angles; |
||||
|
int modelindex; |
||||
|
int frame; |
||||
|
int colormap; |
||||
|
int skin; |
||||
|
int effects; |
||||
|
} entity_state_t; |
||||
|
|
||||
|
|
||||
|
#include "wad.h" |
||||
|
#include "draw.h" |
||||
|
#include "cvar.h" |
||||
|
#include "screen.h" |
||||
|
#include "net.h" |
||||
|
#include "protocol.h" |
||||
|
#include "cmd.h" |
||||
|
#include "sbar.h" |
||||
|
#include "sound.h" |
||||
|
#include "snd_fmod.h" // jkrige - fmod sound system |
||||
|
|
||||
|
#include "render.h" |
||||
|
#include "client.h" |
||||
|
#include "progs.h" |
||||
|
#include "server.h" |
||||
|
|
||||
|
// jkrige - gamma |
||||
|
#include "vid_gamma.h" |
||||
|
// jkrige - gamma |
||||
|
|
||||
|
#include "gl_model.h" |
||||
|
|
||||
|
// jkrige - fullbright pixels |
||||
|
#include "gl_fullbright.h" |
||||
|
// jkrige - fullbright pixels |
||||
|
|
||||
|
#include "input.h" |
||||
|
#include "world.h" |
||||
|
#include "keys.h" |
||||
|
#include "console.h" |
||||
|
#include "view.h" |
||||
|
#include "menu.h" |
||||
|
#include "crc.h" |
||||
|
#include "cdaudio.h" |
||||
|
|
||||
|
#ifdef GLQUAKE |
||||
|
#include "glquake.h" |
||||
|
#endif |
||||
|
|
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
// the host system specifies the base of the directory tree, the |
||||
|
// command line parms passed to the program, and the amount of memory |
||||
|
// available for the program to use |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
char *basedir; |
||||
|
char *cachedir; // for development over ISDN lines |
||||
|
int argc; |
||||
|
char **argv; |
||||
|
void *membase; |
||||
|
int memsize; |
||||
|
} quakeparms_t; |
||||
|
|
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
|
||||
|
|
||||
|
extern qboolean noclip_anglehack; |
||||
|
|
||||
|
|
||||
|
// |
||||
|
// host |
||||
|
// |
||||
|
extern quakeparms_t host_parms; |
||||
|
|
||||
|
extern cvar_t sys_ticrate; |
||||
|
extern cvar_t sys_nostdout; |
||||
|
extern cvar_t developer; |
||||
|
|
||||
|
extern qboolean host_initialized; // true if into command execution |
||||
|
extern double host_frametime; |
||||
|
extern byte *host_basepal; |
||||
|
extern byte *host_colormap; |
||||
|
extern int host_framecount; // incremented every frame, never reset |
||||
|
extern double realtime; // not bounded in any way, changed at |
||||
|
// start of every frame, never reset |
||||
|
|
||||
|
void Host_ClearMemory (void); |
||||
|
void Host_ServerFrame (void); |
||||
|
void Host_InitCommands (void); |
||||
|
void Host_Init (quakeparms_t *parms); |
||||
|
void Host_Shutdown(void); |
||||
|
void Host_Error (char *error, ...); |
||||
|
void Host_EndGame (char *message, ...); |
||||
|
void Host_Frame (float time); |
||||
|
void Host_Quit_f (void); |
||||
|
void Host_ClientCommands (char *fmt, ...); |
||||
|
void Host_ShutdownServer (qboolean crash); |
||||
|
|
||||
|
extern qboolean msg_suppress_1; // suppresses resolution and cache size console output |
||||
|
// an fullscreen DIB focus gain/loss |
||||
|
extern int current_skill; // skill level for currently loaded level (in case |
||||
|
// the user changes the cvar while the level is |
||||
|
// running, this reflects the level actually in use) |
||||
|
|
||||
|
extern qboolean isDedicated; |
||||
|
|
||||
|
extern int minimum_memory; |
||||
|
|
||||
|
// |
||||
|
// chase |
||||
|
// |
||||
|
// jkrige - removed chase |
||||
|
//extern cvar_t chase_active; |
||||
|
|
||||
|
//void Chase_Init (void); |
||||
|
//void Chase_Reset (void); |
||||
|
//void Chase_Update (void); |
||||
|
// jkrige - removed chase |
||||
@ -0,0 +1,819 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
#include "quakedef.h" |
||||
|
//#include "r_local.h" // jkrige - removed |
||||
|
|
||||
|
#define MAX_PARTICLES 2048 // default max # of particles at one |
||||
|
// time |
||||
|
#define ABSOLUTE_MIN_PARTICLES 512 // no fewer than this no matter what's |
||||
|
// on the command line |
||||
|
|
||||
|
int ramp1[8] = {0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61}; |
||||
|
int ramp2[8] = {0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66}; |
||||
|
int ramp3[8] = {0x6d, 0x6b, 6, 5, 4, 3}; |
||||
|
|
||||
|
particle_t *active_particles, *free_particles; |
||||
|
|
||||
|
particle_t *particles; |
||||
|
int r_numparticles; |
||||
|
|
||||
|
vec3_t r_pright, r_pup, r_ppn; |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
R_InitParticles |
||||
|
=============== |
||||
|
*/ |
||||
|
void R_InitParticles (void) |
||||
|
{ |
||||
|
int i; |
||||
|
|
||||
|
i = COM_CheckParm ("-particles"); |
||||
|
|
||||
|
if (i) |
||||
|
{ |
||||
|
r_numparticles = (int)(Q_atoi(com_argv[i+1])); |
||||
|
if (r_numparticles < ABSOLUTE_MIN_PARTICLES) |
||||
|
r_numparticles = ABSOLUTE_MIN_PARTICLES; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
r_numparticles = MAX_PARTICLES; |
||||
|
} |
||||
|
|
||||
|
particles = (particle_t *) |
||||
|
Hunk_AllocName (r_numparticles * sizeof(particle_t), "particles"); |
||||
|
} |
||||
|
|
||||
|
#ifdef QUAKE2 |
||||
|
void R_DarkFieldParticles (entity_t *ent) |
||||
|
{ |
||||
|
int i, j, k; |
||||
|
particle_t *p; |
||||
|
float vel; |
||||
|
vec3_t dir; |
||||
|
vec3_t org; |
||||
|
|
||||
|
org[0] = ent->origin[0]; |
||||
|
org[1] = ent->origin[1]; |
||||
|
org[2] = ent->origin[2]; |
||||
|
for (i=-16 ; i<16 ; i+=8) |
||||
|
for (j=-16 ; j<16 ; j+=8) |
||||
|
for (k=0 ; k<32 ; k+=8) |
||||
|
{ |
||||
|
if (!free_particles) |
||||
|
return; |
||||
|
p = free_particles; |
||||
|
free_particles = p->next; |
||||
|
p->next = active_particles; |
||||
|
active_particles = p; |
||||
|
|
||||
|
p->die = cl.time + 0.2 + (rand()&7) * 0.02; |
||||
|
p->color = 150 + rand()%6; |
||||
|
p->type = pt_slowgrav; |
||||
|
|
||||
|
dir[0] = j*8; |
||||
|
dir[1] = i*8; |
||||
|
dir[2] = k*8; |
||||
|
|
||||
|
p->org[0] = org[0] + i + (rand()&3); |
||||
|
p->org[1] = org[1] + j + (rand()&3); |
||||
|
p->org[2] = org[2] + k + (rand()&3); |
||||
|
|
||||
|
VectorNormalize (dir); |
||||
|
vel = 50 + (rand()&63); |
||||
|
VectorScale (dir, vel, p->vel); |
||||
|
} |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
R_EntityParticles |
||||
|
=============== |
||||
|
*/ |
||||
|
|
||||
|
#define NUMVERTEXNORMALS 162 |
||||
|
extern float r_avertexnormals[NUMVERTEXNORMALS][3]; |
||||
|
vec3_t avelocities[NUMVERTEXNORMALS]; |
||||
|
float beamlength = 16; |
||||
|
vec3_t avelocity = {23, 7, 3}; |
||||
|
float partstep = 0.01; |
||||
|
float timescale = 0.01; |
||||
|
|
||||
|
void R_EntityParticles (entity_t *ent) |
||||
|
{ |
||||
|
int count; |
||||
|
int i; |
||||
|
particle_t *p; |
||||
|
float angle; |
||||
|
float sr, sp, sy, cr, cp, cy; |
||||
|
vec3_t forward; |
||||
|
float dist; |
||||
|
|
||||
|
dist = 64; |
||||
|
count = 50; |
||||
|
|
||||
|
if (!avelocities[0][0]) |
||||
|
{ |
||||
|
for (i=0 ; i<NUMVERTEXNORMALS*3 ; i++) |
||||
|
avelocities[0][i] = (rand()&255) * 0.01; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
for (i=0 ; i<NUMVERTEXNORMALS ; i++) |
||||
|
{ |
||||
|
angle = cl.time * avelocities[i][0]; |
||||
|
sy = sin(angle); |
||||
|
cy = cos(angle); |
||||
|
angle = cl.time * avelocities[i][1]; |
||||
|
sp = sin(angle); |
||||
|
cp = cos(angle); |
||||
|
angle = cl.time * avelocities[i][2]; |
||||
|
sr = sin(angle); |
||||
|
cr = cos(angle); |
||||
|
|
||||
|
forward[0] = cp*cy; |
||||
|
forward[1] = cp*sy; |
||||
|
forward[2] = -sp; |
||||
|
|
||||
|
if (!free_particles) |
||||
|
return; |
||||
|
p = free_particles; |
||||
|
free_particles = p->next; |
||||
|
p->next = active_particles; |
||||
|
active_particles = p; |
||||
|
|
||||
|
p->die = cl.time + 0.01; |
||||
|
p->color = 0x6f; |
||||
|
p->type = pt_explode; |
||||
|
|
||||
|
p->org[0] = ent->origin[0] + r_avertexnormals[i][0]*dist + forward[0]*beamlength; |
||||
|
p->org[1] = ent->origin[1] + r_avertexnormals[i][1]*dist + forward[1]*beamlength; |
||||
|
p->org[2] = ent->origin[2] + r_avertexnormals[i][2]*dist + forward[2]*beamlength; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
R_ClearParticles |
||||
|
=============== |
||||
|
*/ |
||||
|
void R_ClearParticles (void) |
||||
|
{ |
||||
|
int i; |
||||
|
|
||||
|
free_particles = &particles[0]; |
||||
|
active_particles = NULL; |
||||
|
|
||||
|
for (i=0 ;i<r_numparticles ; i++) |
||||
|
particles[i].next = &particles[i+1]; |
||||
|
particles[r_numparticles-1].next = NULL; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void R_ReadPointFile_f (void) |
||||
|
{ |
||||
|
FILE *f; |
||||
|
vec3_t org; |
||||
|
int r; |
||||
|
int c; |
||||
|
particle_t *p; |
||||
|
char name[MAX_OSPATH]; |
||||
|
|
||||
|
sprintf (name,"maps/%s.pts", sv.name); |
||||
|
|
||||
|
COM_FOpenFile (name, &f); |
||||
|
if (!f) |
||||
|
{ |
||||
|
Con_Printf ("couldn't open %s\n", name); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
Con_Printf ("Reading %s...\n", name); |
||||
|
c = 0; |
||||
|
for ( ;; ) |
||||
|
{ |
||||
|
r = fscanf (f,"%f %f %f\n", &org[0], &org[1], &org[2]); |
||||
|
if (r != 3) |
||||
|
break; |
||||
|
c++; |
||||
|
|
||||
|
if (!free_particles) |
||||
|
{ |
||||
|
Con_Printf ("Not enough free particles\n"); |
||||
|
break; |
||||
|
} |
||||
|
p = free_particles; |
||||
|
free_particles = p->next; |
||||
|
p->next = active_particles; |
||||
|
active_particles = p; |
||||
|
|
||||
|
p->die = 99999; |
||||
|
p->color = (-c)&15; |
||||
|
p->type = pt_static; |
||||
|
VectorCopy (vec3_origin, p->vel); |
||||
|
VectorCopy (org, p->org); |
||||
|
} |
||||
|
|
||||
|
fclose (f); |
||||
|
Con_Printf ("%i points read\n", c); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
R_ParseParticleEffect |
||||
|
|
||||
|
Parse an effect out of the server message |
||||
|
=============== |
||||
|
*/ |
||||
|
void R_ParseParticleEffect (void) |
||||
|
{ |
||||
|
vec3_t org, dir; |
||||
|
int i, count, msgcount, color; |
||||
|
|
||||
|
for (i=0 ; i<3 ; i++) |
||||
|
org[i] = MSG_ReadCoord (); |
||||
|
for (i=0 ; i<3 ; i++) |
||||
|
dir[i] = MSG_ReadChar () * (1.0/16); |
||||
|
msgcount = MSG_ReadByte (); |
||||
|
color = MSG_ReadByte (); |
||||
|
|
||||
|
if (msgcount == 255) |
||||
|
count = 1024; |
||||
|
else |
||||
|
count = msgcount; |
||||
|
|
||||
|
R_RunParticleEffect (org, dir, color, count); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
R_ParticleExplosion |
||||
|
|
||||
|
=============== |
||||
|
*/ |
||||
|
void R_ParticleExplosion (vec3_t org) |
||||
|
{ |
||||
|
int i, j; |
||||
|
particle_t *p; |
||||
|
|
||||
|
for (i=0 ; i<1024 ; i++) |
||||
|
{ |
||||
|
if (!free_particles) |
||||
|
return; |
||||
|
p = free_particles; |
||||
|
free_particles = p->next; |
||||
|
p->next = active_particles; |
||||
|
active_particles = p; |
||||
|
|
||||
|
p->die = cl.time + 5; |
||||
|
p->color = ramp1[0]; |
||||
|
p->ramp = rand()&3; |
||||
|
if (i & 1) |
||||
|
{ |
||||
|
p->type = pt_explode; |
||||
|
for (j=0 ; j<3 ; j++) |
||||
|
{ |
||||
|
p->org[j] = org[j] + ((rand()%32)-16); |
||||
|
p->vel[j] = (rand()%512)-256; |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
p->type = pt_explode2; |
||||
|
for (j=0 ; j<3 ; j++) |
||||
|
{ |
||||
|
p->org[j] = org[j] + ((rand()%32)-16); |
||||
|
p->vel[j] = (rand()%512)-256; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
R_ParticleExplosion2 |
||||
|
|
||||
|
=============== |
||||
|
*/ |
||||
|
void R_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength) |
||||
|
{ |
||||
|
int i, j; |
||||
|
particle_t *p; |
||||
|
int colorMod = 0; |
||||
|
|
||||
|
for (i=0; i<512; i++) |
||||
|
{ |
||||
|
if (!free_particles) |
||||
|
return; |
||||
|
p = free_particles; |
||||
|
free_particles = p->next; |
||||
|
p->next = active_particles; |
||||
|
active_particles = p; |
||||
|
|
||||
|
p->die = cl.time + 0.3; |
||||
|
p->color = colorStart + (colorMod % colorLength); |
||||
|
colorMod++; |
||||
|
|
||||
|
p->type = pt_blob; |
||||
|
for (j=0 ; j<3 ; j++) |
||||
|
{ |
||||
|
p->org[j] = org[j] + ((rand()%32)-16); |
||||
|
p->vel[j] = (rand()%512)-256; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
R_BlobExplosion |
||||
|
|
||||
|
=============== |
||||
|
*/ |
||||
|
void R_BlobExplosion (vec3_t org) |
||||
|
{ |
||||
|
int i, j; |
||||
|
particle_t *p; |
||||
|
|
||||
|
for (i=0 ; i<1024 ; i++) |
||||
|
{ |
||||
|
if (!free_particles) |
||||
|
return; |
||||
|
p = free_particles; |
||||
|
free_particles = p->next; |
||||
|
p->next = active_particles; |
||||
|
active_particles = p; |
||||
|
|
||||
|
p->die = cl.time + 1 + (rand()&8)*0.05; |
||||
|
|
||||
|
if (i & 1) |
||||
|
{ |
||||
|
p->type = pt_blob; |
||||
|
p->color = 66 + rand()%6; |
||||
|
for (j=0 ; j<3 ; j++) |
||||
|
{ |
||||
|
p->org[j] = org[j] + ((rand()%32)-16); |
||||
|
p->vel[j] = (rand()%512)-256; |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
p->type = pt_blob2; |
||||
|
p->color = 150 + rand()%6; |
||||
|
for (j=0 ; j<3 ; j++) |
||||
|
{ |
||||
|
p->org[j] = org[j] + ((rand()%32)-16); |
||||
|
p->vel[j] = (rand()%512)-256; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
R_RunParticleEffect |
||||
|
|
||||
|
=============== |
||||
|
*/ |
||||
|
void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count) |
||||
|
{ |
||||
|
int i, j; |
||||
|
particle_t *p; |
||||
|
|
||||
|
for (i=0 ; i<count ; i++) |
||||
|
{ |
||||
|
if (!free_particles) |
||||
|
return; |
||||
|
p = free_particles; |
||||
|
free_particles = p->next; |
||||
|
p->next = active_particles; |
||||
|
active_particles = p; |
||||
|
|
||||
|
if (count == 1024) |
||||
|
{ // rocket explosion |
||||
|
p->die = cl.time + 5; |
||||
|
p->color = ramp1[0]; |
||||
|
p->ramp = rand()&3; |
||||
|
if (i & 1) |
||||
|
{ |
||||
|
p->type = pt_explode; |
||||
|
for (j=0 ; j<3 ; j++) |
||||
|
{ |
||||
|
p->org[j] = org[j] + ((rand()%32)-16); |
||||
|
p->vel[j] = (rand()%512)-256; |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
p->type = pt_explode2; |
||||
|
for (j=0 ; j<3 ; j++) |
||||
|
{ |
||||
|
p->org[j] = org[j] + ((rand()%32)-16); |
||||
|
p->vel[j] = (rand()%512)-256; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
p->die = cl.time + 0.1*(rand()%5); |
||||
|
p->color = (color&~7) + (rand()&7); |
||||
|
p->type = pt_slowgrav; |
||||
|
for (j=0 ; j<3 ; j++) |
||||
|
{ |
||||
|
p->org[j] = org[j] + ((rand()&15)-8); |
||||
|
p->vel[j] = dir[j]*15;// + (rand()%300)-150; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
R_LavaSplash |
||||
|
|
||||
|
=============== |
||||
|
*/ |
||||
|
void R_LavaSplash (vec3_t org) |
||||
|
{ |
||||
|
int i, j, k; |
||||
|
particle_t *p; |
||||
|
float vel; |
||||
|
vec3_t dir; |
||||
|
|
||||
|
for (i=-16 ; i<16 ; i++) |
||||
|
for (j=-16 ; j<16 ; j++) |
||||
|
for (k=0 ; k<1 ; k++) |
||||
|
{ |
||||
|
if (!free_particles) |
||||
|
return; |
||||
|
p = free_particles; |
||||
|
free_particles = p->next; |
||||
|
p->next = active_particles; |
||||
|
active_particles = p; |
||||
|
|
||||
|
p->die = cl.time + 2 + (rand()&31) * 0.02; |
||||
|
p->color = 224 + (rand()&7); |
||||
|
p->type = pt_slowgrav; |
||||
|
|
||||
|
dir[0] = j*8 + (rand()&7); |
||||
|
dir[1] = i*8 + (rand()&7); |
||||
|
dir[2] = 256; |
||||
|
|
||||
|
p->org[0] = org[0] + dir[0]; |
||||
|
p->org[1] = org[1] + dir[1]; |
||||
|
p->org[2] = org[2] + (rand()&63); |
||||
|
|
||||
|
VectorNormalize (dir); |
||||
|
vel = 50 + (rand()&63); |
||||
|
VectorScale (dir, vel, p->vel); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
R_TeleportSplash |
||||
|
|
||||
|
=============== |
||||
|
*/ |
||||
|
void R_TeleportSplash (vec3_t org) |
||||
|
{ |
||||
|
int i, j, k; |
||||
|
particle_t *p; |
||||
|
float vel; |
||||
|
vec3_t dir; |
||||
|
|
||||
|
for (i=-16 ; i<16 ; i+=4) |
||||
|
for (j=-16 ; j<16 ; j+=4) |
||||
|
for (k=-24 ; k<32 ; k+=4) |
||||
|
{ |
||||
|
if (!free_particles) |
||||
|
return; |
||||
|
p = free_particles; |
||||
|
free_particles = p->next; |
||||
|
p->next = active_particles; |
||||
|
active_particles = p; |
||||
|
|
||||
|
p->die = cl.time + 0.2 + (rand()&7) * 0.02; |
||||
|
p->color = 7 + (rand()&7); |
||||
|
p->type = pt_slowgrav; |
||||
|
|
||||
|
dir[0] = j*8; |
||||
|
dir[1] = i*8; |
||||
|
dir[2] = k*8; |
||||
|
|
||||
|
p->org[0] = org[0] + i + (rand()&3); |
||||
|
p->org[1] = org[1] + j + (rand()&3); |
||||
|
p->org[2] = org[2] + k + (rand()&3); |
||||
|
|
||||
|
VectorNormalize (dir); |
||||
|
vel = 50 + (rand()&63); |
||||
|
VectorScale (dir, vel, p->vel); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void R_RocketTrail (vec3_t start, vec3_t end, int type) |
||||
|
{ |
||||
|
vec3_t vec; |
||||
|
float len; |
||||
|
int j; |
||||
|
particle_t *p; |
||||
|
int dec; |
||||
|
static int tracercount; |
||||
|
|
||||
|
VectorSubtract (end, start, vec); |
||||
|
len = VectorNormalize (vec); |
||||
|
if (type < 128) |
||||
|
dec = 3; |
||||
|
else |
||||
|
{ |
||||
|
dec = 1; |
||||
|
type -= 128; |
||||
|
} |
||||
|
|
||||
|
while (len > 0) |
||||
|
{ |
||||
|
len -= dec; |
||||
|
|
||||
|
if (!free_particles) |
||||
|
return; |
||||
|
p = free_particles; |
||||
|
free_particles = p->next; |
||||
|
p->next = active_particles; |
||||
|
active_particles = p; |
||||
|
|
||||
|
VectorCopy (vec3_origin, p->vel); |
||||
|
p->die = cl.time + 2; |
||||
|
|
||||
|
switch (type) |
||||
|
{ |
||||
|
case 0: // rocket trail |
||||
|
p->ramp = (rand()&3); |
||||
|
p->color = ramp3[(int)p->ramp]; |
||||
|
p->type = pt_fire; |
||||
|
for (j=0 ; j<3 ; j++) |
||||
|
p->org[j] = start[j] + ((rand()%6)-3); |
||||
|
break; |
||||
|
|
||||
|
case 1: // smoke smoke |
||||
|
p->ramp = (rand()&3) + 2; |
||||
|
p->color = ramp3[(int)p->ramp]; |
||||
|
p->type = pt_fire; |
||||
|
for (j=0 ; j<3 ; j++) |
||||
|
p->org[j] = start[j] + ((rand()%6)-3); |
||||
|
break; |
||||
|
|
||||
|
case 2: // blood |
||||
|
p->type = pt_grav; |
||||
|
p->color = 67 + (rand()&3); |
||||
|
for (j=0 ; j<3 ; j++) |
||||
|
p->org[j] = start[j] + ((rand()%6)-3); |
||||
|
break; |
||||
|
|
||||
|
case 3: |
||||
|
case 5: // tracer |
||||
|
p->die = cl.time + 0.5; |
||||
|
p->type = pt_static; |
||||
|
if (type == 3) |
||||
|
p->color = 52 + ((tracercount&4)<<1); |
||||
|
else |
||||
|
p->color = 230 + ((tracercount&4)<<1); |
||||
|
|
||||
|
tracercount++; |
||||
|
|
||||
|
VectorCopy (start, p->org); |
||||
|
if (tracercount & 1) |
||||
|
{ |
||||
|
p->vel[0] = 30*vec[1]; |
||||
|
p->vel[1] = 30*-vec[0]; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
p->vel[0] = 30*-vec[1]; |
||||
|
p->vel[1] = 30*vec[0]; |
||||
|
} |
||||
|
break; |
||||
|
|
||||
|
case 4: // slight blood |
||||
|
p->type = pt_grav; |
||||
|
p->color = 67 + (rand()&3); |
||||
|
for (j=0 ; j<3 ; j++) |
||||
|
p->org[j] = start[j] + ((rand()%6)-3); |
||||
|
len -= 3; |
||||
|
break; |
||||
|
|
||||
|
case 6: // voor trail |
||||
|
p->color = 9*16 + 8 + (rand()&3); |
||||
|
p->type = pt_static; |
||||
|
p->die = cl.time + 0.3; |
||||
|
for (j=0 ; j<3 ; j++) |
||||
|
p->org[j] = start[j] + ((rand()&15)-8); |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
VectorAdd (start, vec, start); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
=============== |
||||
|
R_DrawParticles |
||||
|
=============== |
||||
|
*/ |
||||
|
extern cvar_t sv_gravity; |
||||
|
|
||||
|
void R_DrawParticles (void) |
||||
|
{ |
||||
|
particle_t *p, *kill; |
||||
|
float grav; |
||||
|
int i; |
||||
|
float time2, time3; |
||||
|
float time1; |
||||
|
float dvel; |
||||
|
float frametime; |
||||
|
|
||||
|
#ifdef GLQUAKE |
||||
|
vec3_t up, right; |
||||
|
float scale; |
||||
|
#endif |
||||
|
|
||||
|
// jkrige - wireframe |
||||
|
if (gl_wireframe.value) |
||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); |
||||
|
// jkrige - wireframe |
||||
|
|
||||
|
#ifdef GLQUAKE |
||||
|
|
||||
|
// jkrige - texture mode |
||||
|
//GL_Bind(particletexture); |
||||
|
if(gl_texturemode.value == 0.0f) |
||||
|
GL_Bind(particletexture_point); |
||||
|
else |
||||
|
GL_Bind(particletexture_linear); |
||||
|
// jkrige - texture mode |
||||
|
|
||||
|
glEnable (GL_BLEND); |
||||
|
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); |
||||
|
glBegin (GL_TRIANGLES); |
||||
|
|
||||
|
VectorScale (vup, 1.5, up); |
||||
|
VectorScale (vright, 1.5, right); |
||||
|
#else |
||||
|
D_StartParticles (); |
||||
|
|
||||
|
VectorScale (vright, xscaleshrink, r_pright); |
||||
|
VectorScale (vup, yscaleshrink, r_pup); |
||||
|
VectorCopy (vpn, r_ppn); |
||||
|
#endif |
||||
|
frametime = cl.time - cl.oldtime; |
||||
|
time3 = frametime * 15; |
||||
|
time2 = frametime * 10; // 15; |
||||
|
time1 = frametime * 5; |
||||
|
grav = frametime * sv_gravity.value * 0.05; |
||||
|
dvel = 4*frametime; |
||||
|
|
||||
|
for ( ;; ) |
||||
|
{ |
||||
|
kill = active_particles; |
||||
|
if (kill && kill->die < cl.time) |
||||
|
{ |
||||
|
active_particles = kill->next; |
||||
|
kill->next = free_particles; |
||||
|
free_particles = kill; |
||||
|
continue; |
||||
|
} |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
for (p=active_particles ; p ; p=p->next) |
||||
|
{ |
||||
|
for ( ;; ) |
||||
|
{ |
||||
|
kill = p->next; |
||||
|
if (kill && kill->die < cl.time) |
||||
|
{ |
||||
|
p->next = kill->next; |
||||
|
kill->next = free_particles; |
||||
|
free_particles = kill; |
||||
|
continue; |
||||
|
} |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
#ifdef GLQUAKE |
||||
|
// hack a scale up to keep particles from disapearing |
||||
|
scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1] |
||||
|
+ (p->org[2] - r_origin[2])*vpn[2]; |
||||
|
if (scale < 20) |
||||
|
scale = 1; |
||||
|
else |
||||
|
scale = 1 + scale * 0.004; |
||||
|
glColor3ubv ((byte *)&d_8to24table[(int)p->color]); |
||||
|
glTexCoord2f (0,0); |
||||
|
glVertex3fv (p->org); |
||||
|
glTexCoord2f (1,0); |
||||
|
glVertex3f (p->org[0] + up[0]*scale, p->org[1] + up[1]*scale, p->org[2] + up[2]*scale); |
||||
|
glTexCoord2f (0,1); |
||||
|
glVertex3f (p->org[0] + right[0]*scale, p->org[1] + right[1]*scale, p->org[2] + right[2]*scale); |
||||
|
#else |
||||
|
D_DrawParticle (p); |
||||
|
#endif |
||||
|
p->org[0] += p->vel[0]*frametime; |
||||
|
p->org[1] += p->vel[1]*frametime; |
||||
|
p->org[2] += p->vel[2]*frametime; |
||||
|
|
||||
|
switch (p->type) |
||||
|
{ |
||||
|
case pt_static: |
||||
|
break; |
||||
|
case pt_fire: |
||||
|
p->ramp += time1; |
||||
|
if (p->ramp >= 6) |
||||
|
p->die = -1; |
||||
|
else |
||||
|
p->color = ramp3[(int)p->ramp]; |
||||
|
p->vel[2] += grav; |
||||
|
break; |
||||
|
|
||||
|
case pt_explode: |
||||
|
p->ramp += time2; |
||||
|
if (p->ramp >=8) |
||||
|
p->die = -1; |
||||
|
else |
||||
|
p->color = ramp1[(int)p->ramp]; |
||||
|
for (i=0 ; i<3 ; i++) |
||||
|
p->vel[i] += p->vel[i]*dvel; |
||||
|
p->vel[2] -= grav; |
||||
|
break; |
||||
|
|
||||
|
case pt_explode2: |
||||
|
p->ramp += time3; |
||||
|
if (p->ramp >=8) |
||||
|
p->die = -1; |
||||
|
else |
||||
|
p->color = ramp2[(int)p->ramp]; |
||||
|
for (i=0 ; i<3 ; i++) |
||||
|
p->vel[i] -= p->vel[i]*frametime; |
||||
|
p->vel[2] -= grav; |
||||
|
break; |
||||
|
|
||||
|
case pt_blob: |
||||
|
for (i=0 ; i<3 ; i++) |
||||
|
p->vel[i] += p->vel[i]*dvel; |
||||
|
p->vel[2] -= grav; |
||||
|
break; |
||||
|
|
||||
|
case pt_blob2: |
||||
|
for (i=0 ; i<2 ; i++) |
||||
|
p->vel[i] -= p->vel[i]*dvel; |
||||
|
p->vel[2] -= grav; |
||||
|
break; |
||||
|
|
||||
|
case pt_grav: |
||||
|
#ifdef QUAKE2 |
||||
|
p->vel[2] -= grav * 20; |
||||
|
break; |
||||
|
#endif |
||||
|
case pt_slowgrav: |
||||
|
p->vel[2] -= grav; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#ifdef GLQUAKE |
||||
|
glEnd (); |
||||
|
glDisable (GL_BLEND); |
||||
|
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); |
||||
|
#else |
||||
|
D_EndParticles (); |
||||
|
#endif |
||||
|
|
||||
|
// jkrige - wireframe |
||||
|
if (gl_wireframe.value) |
||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); |
||||
|
// jkrige - wireframe |
||||
|
} |
||||
@ -0,0 +1,162 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
// refresh.h -- public interface to refresh functions |
||||
|
|
||||
|
#define MAXCLIPPLANES 11 |
||||
|
|
||||
|
#define TOP_RANGE 16 // soldier uniform colors |
||||
|
#define BOTTOM_RANGE 96 |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
typedef struct efrag_s |
||||
|
{ |
||||
|
struct mleaf_s *leaf; |
||||
|
struct efrag_s *leafnext; |
||||
|
struct entity_s *entity; |
||||
|
struct efrag_s *entnext; |
||||
|
} efrag_t; |
||||
|
|
||||
|
|
||||
|
typedef struct entity_s |
||||
|
{ |
||||
|
qboolean forcelink; // model changed |
||||
|
|
||||
|
int update_type; |
||||
|
|
||||
|
entity_state_t baseline; // to fill in defaults in updates |
||||
|
|
||||
|
double msgtime; // time of last update |
||||
|
vec3_t msg_origins[2]; // last two updates (0 is newest) |
||||
|
vec3_t origin; |
||||
|
vec3_t msg_angles[2]; // last two updates (0 is newest) |
||||
|
vec3_t angles; |
||||
|
struct model_s *model; // NULL = no model |
||||
|
struct efrag_s *efrag; // linked list of efrags |
||||
|
int frame; |
||||
|
float syncbase; // for client-side animations |
||||
|
byte *colormap; |
||||
|
int effects; // light, particals, etc |
||||
|
int skinnum; // for Alias models |
||||
|
int visframe; // last frame this entity was |
||||
|
// found in an active leaf |
||||
|
|
||||
|
int dlightframe; // dynamic lighting |
||||
|
int dlightbits; |
||||
|
|
||||
|
// FIXME: could turn these into a union |
||||
|
int trivial_accept; |
||||
|
struct mnode_s *topnode; // for bmodels, first world node |
||||
|
// that splits bmodel, or NULL if |
||||
|
// not split |
||||
|
} entity_t; |
||||
|
|
||||
|
// !!! if this is changed, it must be changed in asm_draw.h too !!! |
||||
|
typedef struct |
||||
|
{ |
||||
|
vrect_t vrect; // subwindow in video for refresh |
||||
|
// FIXME: not need vrect next field here? |
||||
|
vrect_t aliasvrect; // scaled Alias version |
||||
|
int vrectright, vrectbottom; // right & bottom screen coords |
||||
|
int aliasvrectright, aliasvrectbottom; // scaled Alias versions |
||||
|
float vrectrightedge; // rightmost right edge we care about, |
||||
|
// for use in edge list |
||||
|
float fvrectx, fvrecty; // for floating-point compares |
||||
|
float fvrectx_adj, fvrecty_adj; // left and top edges, for clamping |
||||
|
int vrect_x_adj_shift20; // (vrect.x + 0.5 - epsilon) << 20 |
||||
|
int vrectright_adj_shift20; // (vrectright + 0.5 - epsilon) << 20 |
||||
|
float fvrectright_adj, fvrectbottom_adj; |
||||
|
// right and bottom edges, for clamping |
||||
|
float fvrectright; // rightmost edge, for Alias clamping |
||||
|
float fvrectbottom; // bottommost edge, for Alias clamping |
||||
|
float horizontalFieldOfView; // at Z = 1.0, this many X is visible |
||||
|
// 2.0 = 90 degrees |
||||
|
float xOrigin; // should probably allways be 0.5 |
||||
|
float yOrigin; // between be around 0.3 to 0.5 |
||||
|
|
||||
|
vec3_t vieworg; |
||||
|
vec3_t viewangles; |
||||
|
|
||||
|
float fov_x, fov_y; |
||||
|
|
||||
|
int ambientlight; |
||||
|
} refdef_t; |
||||
|
|
||||
|
|
||||
|
// |
||||
|
// refresh |
||||
|
// |
||||
|
extern int reinit_surfcache; |
||||
|
|
||||
|
|
||||
|
extern refdef_t r_refdef; |
||||
|
extern vec3_t r_origin, vpn, vright, vup; |
||||
|
|
||||
|
extern struct texture_s *r_notexture_mip; |
||||
|
|
||||
|
|
||||
|
void R_Init (void); |
||||
|
void R_InitTextures (void); |
||||
|
void R_InitEfrags (void); |
||||
|
void R_RenderView (void); // must set r_refdef first |
||||
|
void R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect); |
||||
|
// called whenever r_refdef or vid change |
||||
|
void R_InitSky (struct texture_s *mt); // called at level load |
||||
|
|
||||
|
// jkrige - 2D polyblend |
||||
|
void R_PolyBlend (void); |
||||
|
// jkrige - 2D polyblend |
||||
|
|
||||
|
void R_AddEfrags (entity_t *ent); |
||||
|
void R_RemoveEfrags (entity_t *ent); |
||||
|
|
||||
|
void R_NewMap (void); |
||||
|
|
||||
|
|
||||
|
void R_ParseParticleEffect (void); |
||||
|
void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count); |
||||
|
void R_RocketTrail (vec3_t start, vec3_t end, int type); |
||||
|
|
||||
|
#ifdef QUAKE2 |
||||
|
void R_DarkFieldParticles (entity_t *ent); |
||||
|
#endif |
||||
|
void R_EntityParticles (entity_t *ent); |
||||
|
void R_BlobExplosion (vec3_t org); |
||||
|
void R_ParticleExplosion (vec3_t org); |
||||
|
void R_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength); |
||||
|
void R_LavaSplash (vec3_t org); |
||||
|
void R_TeleportSplash (vec3_t org); |
||||
|
|
||||
|
void R_PushDlights (void); |
||||
|
|
||||
|
|
||||
|
// |
||||
|
// surface cache related |
||||
|
// |
||||
|
extern int reinit_surfcache; // if 1, surface cache is currently empty and |
||||
|
extern qboolean r_cache_thrash; // set if thrashing the surface cache |
||||
|
|
||||
|
int D_SurfaceCacheForRes (int width, int height); |
||||
|
void D_FlushCaches (void); |
||||
|
void D_DeleteSurfaceCache (void); |
||||
|
void D_InitCaches (void *buffer, int size); |
||||
|
void R_SetVrect (vrect_t *pvrect, vrect_t *pvrectin, int lineadj); |
||||
|
|
||||
@ -0,0 +1,19 @@ |
|||||
|
//{{NO_DEPENDENCIES}} |
||||
|
// Microsoft Visual C++ generated include file. |
||||
|
// Used by winquake.rc |
||||
|
// |
||||
|
#define IDI_ICON2 1 |
||||
|
#define IDD_DIALOG1 108 |
||||
|
#define IDB_BITMAP1 111 |
||||
|
#define IDB_QUAKE1 111 |
||||
|
|
||||
|
// Next default values for new objects |
||||
|
// |
||||
|
#ifdef APSTUDIO_INVOKED |
||||
|
#ifndef APSTUDIO_READONLY_SYMBOLS |
||||
|
#define _APS_NEXT_RESOURCE_VALUE 112 |
||||
|
#define _APS_NEXT_COMMAND_VALUE 40001 |
||||
|
#define _APS_NEXT_CONTROL_VALUE 1004 |
||||
|
#define _APS_NEXT_SYMED_VALUE 101 |
||||
|
#endif |
||||
|
#endif |
||||
1391
engine/code/sbar.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,41 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
// the status bar is only redrawn if something has changed, but if anything |
||||
|
// does, the entire thing will be redrawn for the next vid.numpages frames. |
||||
|
|
||||
|
#define SBAR_HEIGHT 24 |
||||
|
|
||||
|
extern int sb_lines; // scan lines to draw |
||||
|
|
||||
|
void Sbar_Init (void); |
||||
|
|
||||
|
// jkrige - always draw sbar |
||||
|
//void Sbar_Changed (void); |
||||
|
// call whenever any of the client stats represented on the sbar changes |
||||
|
// jkrige - always draw sbar |
||||
|
|
||||
|
void Sbar_Draw (void); |
||||
|
// called every frame by screen |
||||
|
|
||||
|
void Sbar_IntermissionOverlay (void); |
||||
|
// called each frame after the level has been completed |
||||
|
|
||||
|
void Sbar_FinaleOverlay (void); |
||||
@ -0,0 +1,55 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// screen.h |
||||
|
|
||||
|
void SCR_Init (void); |
||||
|
|
||||
|
void SCR_UpdateScreen (void); |
||||
|
|
||||
|
|
||||
|
void SCR_SizeUp (void); |
||||
|
void SCR_SizeDown (void); |
||||
|
void SCR_BringDownConsole (void); |
||||
|
void SCR_CenterPrint (char *str); |
||||
|
|
||||
|
void SCR_BeginLoadingPlaque (void); |
||||
|
void SCR_EndLoadingPlaque (void); |
||||
|
|
||||
|
int SCR_ModalMessage (char *text); |
||||
|
|
||||
|
extern float scr_con_current; |
||||
|
extern float scr_conlines; // lines of console to display |
||||
|
|
||||
|
extern int scr_fullupdate; // set to 0 to force full redraw |
||||
|
extern int sb_lines; |
||||
|
|
||||
|
extern int clearnotify; // set to 0 whenever notify text is drawn |
||||
|
extern qboolean scr_disabled_for_loading; |
||||
|
extern qboolean scr_skipupdate; |
||||
|
|
||||
|
extern cvar_t scr_viewsize; |
||||
|
|
||||
|
// only the refresh window will be updated unless these variables are flagged |
||||
|
extern int scr_copytop; |
||||
|
extern int scr_copyeverything; |
||||
|
|
||||
|
extern qboolean block_drawing; |
||||
|
|
||||
|
void SCR_UpdateWholeScreen (void); |
||||
@ -0,0 +1,262 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// server.h |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
int maxclients; |
||||
|
int maxclientslimit; |
||||
|
struct client_s *clients; // [maxclients] |
||||
|
int serverflags; // episode completion information |
||||
|
qboolean changelevel_issued; // cleared when at SV_SpawnServer |
||||
|
} server_static_t; |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
typedef enum {ss_loading, ss_active} server_state_t; |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
qboolean active; // false if only a net client |
||||
|
|
||||
|
qboolean paused; |
||||
|
qboolean loadgame; // handle connections specially |
||||
|
|
||||
|
double time; |
||||
|
|
||||
|
int lastcheck; // used by PF_checkclient |
||||
|
double lastchecktime; |
||||
|
|
||||
|
char name[64]; // map name |
||||
|
|
||||
|
// jkrige - skybox |
||||
|
char skybox[128]; |
||||
|
// jkrige - skybox |
||||
|
|
||||
|
#ifdef QUAKE2 |
||||
|
char startspot[64]; |
||||
|
#endif |
||||
|
char modelname[64]; // maps/<name>.bsp, for model_precache[0] |
||||
|
struct model_s *worldmodel; |
||||
|
char *model_precache[MAX_MODELS]; // NULL terminated |
||||
|
struct model_s *models[MAX_MODELS]; |
||||
|
char *sound_precache[MAX_SOUNDS]; // NULL terminated |
||||
|
char *lightstyles[MAX_LIGHTSTYLES]; |
||||
|
int num_edicts; |
||||
|
int max_edicts; |
||||
|
edict_t *edicts; // can NOT be array indexed, because |
||||
|
// edict_t is variable sized, but can |
||||
|
// be used to reference the world ent |
||||
|
server_state_t state; // some actions are only valid during load |
||||
|
|
||||
|
sizebuf_t datagram; |
||||
|
byte datagram_buf[MAX_DATAGRAM]; |
||||
|
|
||||
|
sizebuf_t reliable_datagram; // copied to all clients at end of frame |
||||
|
byte reliable_datagram_buf[MAX_DATAGRAM]; |
||||
|
|
||||
|
sizebuf_t signon; |
||||
|
byte signon_buf[8192]; |
||||
|
} server_t; |
||||
|
|
||||
|
|
||||
|
#define NUM_PING_TIMES 16 |
||||
|
#define NUM_SPAWN_PARMS 16 |
||||
|
|
||||
|
typedef struct client_s |
||||
|
{ |
||||
|
qboolean active; // false = client is free |
||||
|
qboolean spawned; // false = don't send datagrams |
||||
|
qboolean dropasap; // has been told to go to another level |
||||
|
qboolean privileged; // can execute any host command |
||||
|
qboolean sendsignon; // only valid before spawned |
||||
|
|
||||
|
double last_message; // reliable messages must be sent |
||||
|
// periodically |
||||
|
|
||||
|
struct qsocket_s *netconnection; // communications handle |
||||
|
|
||||
|
usercmd_t cmd; // movement |
||||
|
vec3_t wishdir; // intended motion calced from cmd |
||||
|
|
||||
|
sizebuf_t message; // can be added to at any time, |
||||
|
// copied and clear once per frame |
||||
|
byte msgbuf[MAX_MSGLEN]; |
||||
|
edict_t *edict; // EDICT_NUM(clientnum+1) |
||||
|
char name[32]; // for printing to other people |
||||
|
int colors; |
||||
|
|
||||
|
float ping_times[NUM_PING_TIMES]; |
||||
|
int num_pings; // ping_times[num_pings%NUM_PING_TIMES] |
||||
|
|
||||
|
// spawn parms are carried from level to level |
||||
|
float spawn_parms[NUM_SPAWN_PARMS]; |
||||
|
|
||||
|
// client known data for deltas |
||||
|
int old_frags; |
||||
|
} client_t; |
||||
|
|
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
// edict->movetype values |
||||
|
#define MOVETYPE_NONE 0 // never moves |
||||
|
#define MOVETYPE_ANGLENOCLIP 1 |
||||
|
#define MOVETYPE_ANGLECLIP 2 |
||||
|
#define MOVETYPE_WALK 3 // gravity |
||||
|
#define MOVETYPE_STEP 4 // gravity, special edge handling |
||||
|
#define MOVETYPE_FLY 5 |
||||
|
#define MOVETYPE_TOSS 6 // gravity |
||||
|
#define MOVETYPE_PUSH 7 // no clip to world, push and crush |
||||
|
#define MOVETYPE_NOCLIP 8 |
||||
|
#define MOVETYPE_FLYMISSILE 9 // extra size to monsters |
||||
|
#define MOVETYPE_BOUNCE 10 |
||||
|
#ifdef QUAKE2 |
||||
|
#define MOVETYPE_BOUNCEMISSILE 11 // bounce w/o gravity |
||||
|
#define MOVETYPE_FOLLOW 12 // track movement of aiment |
||||
|
#endif |
||||
|
|
||||
|
// edict->solid values |
||||
|
#define SOLID_NOT 0 // no interaction with other objects |
||||
|
#define SOLID_TRIGGER 1 // touch on edge, but not blocking |
||||
|
#define SOLID_BBOX 2 // touch on edge, block |
||||
|
#define SOLID_SLIDEBOX 3 // touch on edge, but not an onground |
||||
|
#define SOLID_BSP 4 // bsp clip, touch on edge, block |
||||
|
|
||||
|
// edict->deadflag values |
||||
|
#define DEAD_NO 0 |
||||
|
#define DEAD_DYING 1 |
||||
|
#define DEAD_DEAD 2 |
||||
|
|
||||
|
#define DAMAGE_NO 0 |
||||
|
#define DAMAGE_YES 1 |
||||
|
#define DAMAGE_AIM 2 |
||||
|
|
||||
|
// edict->flags |
||||
|
#define FL_FLY 1 |
||||
|
#define FL_SWIM 2 |
||||
|
//#define FL_GLIMPSE 4 |
||||
|
#define FL_CONVEYOR 4 |
||||
|
#define FL_CLIENT 8 |
||||
|
#define FL_INWATER 16 |
||||
|
#define FL_MONSTER 32 |
||||
|
#define FL_GODMODE 64 |
||||
|
#define FL_NOTARGET 128 |
||||
|
#define FL_ITEM 256 |
||||
|
#define FL_ONGROUND 512 |
||||
|
#define FL_PARTIALGROUND 1024 // not all corners are valid |
||||
|
#define FL_WATERJUMP 2048 // player jumping out of water |
||||
|
#define FL_JUMPRELEASED 4096 // for jump debouncing |
||||
|
#ifdef QUAKE2 |
||||
|
#define FL_FLASHLIGHT 8192 |
||||
|
#define FL_ARCHIVE_OVERRIDE 1048576 |
||||
|
#endif |
||||
|
|
||||
|
// entity effects |
||||
|
|
||||
|
#define EF_BRIGHTFIELD 1 |
||||
|
#define EF_MUZZLEFLASH 2 |
||||
|
#define EF_BRIGHTLIGHT 4 |
||||
|
#define EF_DIMLIGHT 8 |
||||
|
#ifdef QUAKE2 |
||||
|
#define EF_DARKLIGHT 16 |
||||
|
#define EF_DARKFIELD 32 |
||||
|
#define EF_LIGHT 64 |
||||
|
#define EF_NODRAW 128 |
||||
|
#endif |
||||
|
|
||||
|
#define SPAWNFLAG_NOT_EASY 256 |
||||
|
#define SPAWNFLAG_NOT_MEDIUM 512 |
||||
|
#define SPAWNFLAG_NOT_HARD 1024 |
||||
|
#define SPAWNFLAG_NOT_DEATHMATCH 2048 |
||||
|
|
||||
|
#ifdef QUAKE2 |
||||
|
// server flags |
||||
|
#define SFL_EPISODE_1 1 |
||||
|
#define SFL_EPISODE_2 2 |
||||
|
#define SFL_EPISODE_3 4 |
||||
|
#define SFL_EPISODE_4 8 |
||||
|
#define SFL_NEW_UNIT 16 |
||||
|
#define SFL_NEW_EPISODE 32 |
||||
|
#define SFL_CROSS_TRIGGERS 65280 |
||||
|
#endif |
||||
|
|
||||
|
//============================================================================ |
||||
|
|
||||
|
extern cvar_t teamplay; |
||||
|
extern cvar_t skill; |
||||
|
extern cvar_t deathmatch; |
||||
|
extern cvar_t coop; |
||||
|
extern cvar_t fraglimit; |
||||
|
extern cvar_t timelimit; |
||||
|
|
||||
|
extern server_static_t svs; // persistant server info |
||||
|
extern server_t sv; // local server |
||||
|
|
||||
|
extern client_t *host_client; |
||||
|
|
||||
|
extern jmp_buf host_abortserver; |
||||
|
|
||||
|
extern double host_time; |
||||
|
|
||||
|
extern edict_t *sv_player; |
||||
|
|
||||
|
//=========================================================== |
||||
|
|
||||
|
void SV_Init (void); |
||||
|
|
||||
|
void SV_StartParticle (vec3_t org, vec3_t dir, int color, int count); |
||||
|
void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, |
||||
|
float attenuation); |
||||
|
|
||||
|
void SV_DropClient (qboolean crash); |
||||
|
|
||||
|
void SV_SendClientMessages (void); |
||||
|
void SV_ClearDatagram (void); |
||||
|
|
||||
|
int SV_ModelIndex (char *name); |
||||
|
|
||||
|
void SV_SetIdealPitch (void); |
||||
|
|
||||
|
void SV_AddUpdates (void); |
||||
|
|
||||
|
void SV_ClientThink (void); |
||||
|
void SV_AddClientToServer (struct qsocket_s *ret); |
||||
|
|
||||
|
void SV_ClientPrintf (char *fmt, ...); |
||||
|
void SV_BroadcastPrintf (char *fmt, ...); |
||||
|
|
||||
|
void SV_Physics (void); |
||||
|
|
||||
|
qboolean SV_CheckBottom (edict_t *ent); |
||||
|
qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink); |
||||
|
|
||||
|
void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg); |
||||
|
|
||||
|
void SV_MoveToGoal (void); |
||||
|
|
||||
|
void SV_CheckForNewClients (void); |
||||
|
void SV_RunClients (void); |
||||
|
void SV_SaveSpawnparms (); |
||||
|
#ifdef QUAKE2 |
||||
|
void SV_SpawnServer (char *server, char *startspot); |
||||
|
#else |
||||
|
void SV_SpawnServer (char *server); |
||||
|
#endif |
||||
1027
engine/code/snd_dma.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1129
engine/code/snd_fmod.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,45 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// snd_fmod.c: FMOD sound system implementation for music playback |
||||
|
|
||||
|
// Developed by Jacques Krige |
||||
|
// Ultimate Quake Engine |
||||
|
// http://www.jacqueskrige.com |
||||
|
|
||||
|
#ifndef _SND_FMOD_H_ |
||||
|
#define _SND_FMOD_H_ |
||||
|
|
||||
|
#define UQE_FMOD |
||||
|
|
||||
|
#ifdef UQE_FMOD |
||||
|
#define UQE_FMOD_CDAUDIO |
||||
|
|
||||
|
void FMOD_Init (void); |
||||
|
void FMOD_Shutdown (void); |
||||
|
void FMOD_MusicStart (char *name, qboolean loop, qboolean notify); |
||||
|
void FMOD_MusicStop (void); |
||||
|
void FMOD_MusicPause (void); |
||||
|
void FMOD_MusicResume (void); |
||||
|
void FMOD_MusicUpdate (char *newbgmtype); |
||||
|
void FMOD_MusicActivate (qboolean active); |
||||
|
qboolean FMOD_MusicActive (void); |
||||
|
#endif |
||||
|
|
||||
|
#endif |
||||
@ -0,0 +1,341 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// snd_mem.c: sound caching |
||||
|
|
||||
|
#include "quakedef.h" |
||||
|
|
||||
|
int cache_full_cycle; |
||||
|
|
||||
|
byte *S_Alloc (int size); |
||||
|
|
||||
|
/* |
||||
|
================ |
||||
|
ResampleSfx |
||||
|
================ |
||||
|
*/ |
||||
|
void ResampleSfx (sfx_t *sfx, int inrate, int inwidth, byte *data) |
||||
|
{ |
||||
|
int outcount; |
||||
|
int srcsample; |
||||
|
float stepscale; |
||||
|
int i; |
||||
|
int sample, samplefrac, fracstep; |
||||
|
sfxcache_t *sc; |
||||
|
|
||||
|
sc = Cache_Check (&sfx->cache); |
||||
|
if (!sc) |
||||
|
return; |
||||
|
|
||||
|
stepscale = (float)inrate / shm->speed; // this is usually 0.5, 1, or 2 |
||||
|
|
||||
|
outcount = sc->length / stepscale; |
||||
|
sc->length = outcount; |
||||
|
if (sc->loopstart != -1) |
||||
|
sc->loopstart = sc->loopstart / stepscale; |
||||
|
|
||||
|
sc->speed = shm->speed; |
||||
|
if (loadas8bit.value) |
||||
|
sc->width = 1; |
||||
|
else |
||||
|
sc->width = inwidth; |
||||
|
sc->stereo = 0; |
||||
|
|
||||
|
// resample / decimate to the current source rate |
||||
|
|
||||
|
if (stepscale == 1 && inwidth == 1 && sc->width == 1) |
||||
|
{ |
||||
|
// fast special case |
||||
|
for (i=0 ; i<outcount ; i++) |
||||
|
((signed char *)sc->data)[i] |
||||
|
= (int)( (unsigned char)(data[i]) - 128); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
// general case |
||||
|
samplefrac = 0; |
||||
|
fracstep = stepscale*256; |
||||
|
for (i=0 ; i<outcount ; i++) |
||||
|
{ |
||||
|
srcsample = samplefrac >> 8; |
||||
|
samplefrac += fracstep; |
||||
|
if (inwidth == 2) |
||||
|
sample = LittleShort ( ((short *)data)[srcsample] ); |
||||
|
else |
||||
|
sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8; |
||||
|
if (sc->width == 2) |
||||
|
((short *)sc->data)[i] = sample; |
||||
|
else |
||||
|
((signed char *)sc->data)[i] = sample >> 8; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
//============================================================================= |
||||
|
|
||||
|
/* |
||||
|
============== |
||||
|
S_LoadSound |
||||
|
============== |
||||
|
*/ |
||||
|
sfxcache_t *S_LoadSound (sfx_t *s) |
||||
|
{ |
||||
|
char namebuffer[256]; |
||||
|
byte *data; |
||||
|
wavinfo_t info; |
||||
|
int len; |
||||
|
float stepscale; |
||||
|
sfxcache_t *sc; |
||||
|
byte stackbuf[1*1024]; // avoid dirtying the cache heap |
||||
|
|
||||
|
// see if still in memory |
||||
|
sc = Cache_Check (&s->cache); |
||||
|
if (sc) |
||||
|
return sc; |
||||
|
|
||||
|
//Con_Printf ("S_LoadSound: %x\n", (int)stackbuf); |
||||
|
// load it in |
||||
|
Q_strcpy(namebuffer, "sound/"); |
||||
|
Q_strcat(namebuffer, s->name); |
||||
|
|
||||
|
// Con_Printf ("loading %s\n",namebuffer); |
||||
|
|
||||
|
data = COM_LoadStackFile(namebuffer, stackbuf, sizeof(stackbuf)); |
||||
|
|
||||
|
if (!data) |
||||
|
{ |
||||
|
Con_Printf ("Couldn't load %s\n", namebuffer); |
||||
|
return NULL; |
||||
|
} |
||||
|
|
||||
|
info = GetWavinfo (s->name, data, com_filesize); |
||||
|
if (info.channels != 1) |
||||
|
{ |
||||
|
Con_Printf ("%s is a stereo sample\n",s->name); |
||||
|
return NULL; |
||||
|
} |
||||
|
|
||||
|
stepscale = (float)info.rate / shm->speed; |
||||
|
len = info.samples / stepscale; |
||||
|
|
||||
|
len = len * info.width * info.channels; |
||||
|
|
||||
|
sc = Cache_Alloc ( &s->cache, len + sizeof(sfxcache_t), s->name); |
||||
|
if (!sc) |
||||
|
return NULL; |
||||
|
|
||||
|
sc->length = info.samples; |
||||
|
sc->loopstart = info.loopstart; |
||||
|
sc->speed = info.rate; |
||||
|
sc->width = info.width; |
||||
|
sc->stereo = info.channels; |
||||
|
|
||||
|
ResampleSfx (s, sc->speed, sc->width, data + info.dataofs); |
||||
|
|
||||
|
return sc; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/* |
||||
|
=============================================================================== |
||||
|
|
||||
|
WAV loading |
||||
|
|
||||
|
=============================================================================== |
||||
|
*/ |
||||
|
|
||||
|
|
||||
|
byte *data_p; |
||||
|
byte *iff_end; |
||||
|
byte *last_chunk; |
||||
|
byte *iff_data; |
||||
|
int iff_chunk_len; |
||||
|
|
||||
|
|
||||
|
short GetLittleShort(void) |
||||
|
{ |
||||
|
short val = 0; |
||||
|
val = *data_p; |
||||
|
val = val + (*(data_p+1)<<8); |
||||
|
data_p += 2; |
||||
|
return val; |
||||
|
} |
||||
|
|
||||
|
int GetLittleLong(void) |
||||
|
{ |
||||
|
int val = 0; |
||||
|
val = *data_p; |
||||
|
val = val + (*(data_p+1)<<8); |
||||
|
val = val + (*(data_p+2)<<16); |
||||
|
val = val + (*(data_p+3)<<24); |
||||
|
data_p += 4; |
||||
|
return val; |
||||
|
} |
||||
|
|
||||
|
void FindNextChunk(char *name) |
||||
|
{ |
||||
|
while (1) |
||||
|
{ |
||||
|
data_p=last_chunk; |
||||
|
|
||||
|
if (data_p >= iff_end) |
||||
|
{ // didn't find the chunk |
||||
|
data_p = NULL; |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
data_p += 4; |
||||
|
iff_chunk_len = GetLittleLong(); |
||||
|
if (iff_chunk_len < 0) |
||||
|
{ |
||||
|
data_p = NULL; |
||||
|
return; |
||||
|
} |
||||
|
// if (iff_chunk_len > 1024*1024) |
||||
|
// Sys_Error ("FindNextChunk: %i length is past the 1 meg sanity limit", iff_chunk_len); |
||||
|
data_p -= 8; |
||||
|
last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 ); |
||||
|
if (!Q_strncmp(data_p, name, 4)) |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void FindChunk(char *name) |
||||
|
{ |
||||
|
last_chunk = iff_data; |
||||
|
FindNextChunk (name); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void DumpChunks(void) |
||||
|
{ |
||||
|
char str[5]; |
||||
|
|
||||
|
str[4] = 0; |
||||
|
data_p=iff_data; |
||||
|
do |
||||
|
{ |
||||
|
memcpy (str, data_p, 4); |
||||
|
data_p += 4; |
||||
|
iff_chunk_len = GetLittleLong(); |
||||
|
Con_Printf ("0x%x : %s (%d)\n", (int)(data_p - 4), str, iff_chunk_len); |
||||
|
data_p += (iff_chunk_len + 1) & ~1; |
||||
|
} while (data_p < iff_end); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
============ |
||||
|
GetWavinfo |
||||
|
============ |
||||
|
*/ |
||||
|
wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength) |
||||
|
{ |
||||
|
wavinfo_t info; |
||||
|
int i; |
||||
|
int format; |
||||
|
int samples; |
||||
|
|
||||
|
memset (&info, 0, sizeof(info)); |
||||
|
|
||||
|
if (!wav) |
||||
|
return info; |
||||
|
|
||||
|
iff_data = wav; |
||||
|
iff_end = wav + wavlength; |
||||
|
|
||||
|
// find "RIFF" chunk |
||||
|
FindChunk("RIFF"); |
||||
|
if (!(data_p && !Q_strncmp(data_p+8, "WAVE", 4))) |
||||
|
{ |
||||
|
Con_Printf("Missing RIFF/WAVE chunks\n"); |
||||
|
return info; |
||||
|
} |
||||
|
|
||||
|
// get "fmt " chunk |
||||
|
iff_data = data_p + 12; |
||||
|
// DumpChunks (); |
||||
|
|
||||
|
FindChunk("fmt "); |
||||
|
if (!data_p) |
||||
|
{ |
||||
|
Con_Printf("Missing fmt chunk\n"); |
||||
|
return info; |
||||
|
} |
||||
|
data_p += 8; |
||||
|
format = GetLittleShort(); |
||||
|
if (format != 1) |
||||
|
{ |
||||
|
Con_Printf("Microsoft PCM format only\n"); |
||||
|
return info; |
||||
|
} |
||||
|
|
||||
|
info.channels = GetLittleShort(); |
||||
|
info.rate = GetLittleLong(); |
||||
|
data_p += 4+2; |
||||
|
info.width = GetLittleShort() / 8; |
||||
|
|
||||
|
// get cue chunk |
||||
|
FindChunk("cue "); |
||||
|
if (data_p) |
||||
|
{ |
||||
|
data_p += 32; |
||||
|
info.loopstart = GetLittleLong(); |
||||
|
// Con_Printf("loopstart=%d\n", sfx->loopstart); |
||||
|
|
||||
|
// if the next chunk is a LIST chunk, look for a cue length marker |
||||
|
FindNextChunk ("LIST"); |
||||
|
if (data_p) |
||||
|
{ |
||||
|
if (!strncmp (data_p + 28, "mark", 4)) |
||||
|
{ // this is not a proper parse, but it works with cooledit... |
||||
|
data_p += 24; |
||||
|
i = GetLittleLong (); // samples in loop |
||||
|
info.samples = info.loopstart + i; |
||||
|
// Con_Printf("looped length: %i\n", i); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
info.loopstart = -1; |
||||
|
|
||||
|
// find data chunk |
||||
|
FindChunk("data"); |
||||
|
if (!data_p) |
||||
|
{ |
||||
|
Con_Printf("Missing data chunk\n"); |
||||
|
return info; |
||||
|
} |
||||
|
|
||||
|
data_p += 4; |
||||
|
samples = GetLittleLong () / info.width; |
||||
|
|
||||
|
if (info.samples) |
||||
|
{ |
||||
|
if (samples < info.samples) |
||||
|
Sys_Error ("Sound %s has a bad loop length", name); |
||||
|
} |
||||
|
else |
||||
|
info.samples = samples; |
||||
|
|
||||
|
info.dataofs = data_p - wav; |
||||
|
|
||||
|
return info; |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,398 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// snd_mix.c -- portable code to mix sounds for snd_dma.c |
||||
|
|
||||
|
#include "quakedef.h" |
||||
|
|
||||
|
#ifdef _WIN32 |
||||
|
#include "winquake.h" |
||||
|
#else |
||||
|
#define DWORD unsigned long |
||||
|
#endif |
||||
|
|
||||
|
#define PAINTBUFFER_SIZE 512 |
||||
|
portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE]; |
||||
|
int snd_scaletable[32][256]; |
||||
|
int *snd_p, snd_linear_count, snd_vol; |
||||
|
short *snd_out; |
||||
|
|
||||
|
void Snd_WriteLinearBlastStereo16 (void); |
||||
|
|
||||
|
#if !id386 |
||||
|
void Snd_WriteLinearBlastStereo16 (void) |
||||
|
{ |
||||
|
int i; |
||||
|
int val; |
||||
|
|
||||
|
for (i=0 ; i<snd_linear_count ; i+=2) |
||||
|
{ |
||||
|
val = (snd_p[i]*snd_vol)>>8; |
||||
|
if (val > 0x7fff) |
||||
|
snd_out[i] = 0x7fff; |
||||
|
else if (val < (short)0x8000) |
||||
|
snd_out[i] = (short)0x8000; |
||||
|
else |
||||
|
snd_out[i] = val; |
||||
|
|
||||
|
val = (snd_p[i+1]*snd_vol)>>8; |
||||
|
if (val > 0x7fff) |
||||
|
snd_out[i+1] = 0x7fff; |
||||
|
else if (val < (short)0x8000) |
||||
|
snd_out[i+1] = (short)0x8000; |
||||
|
else |
||||
|
snd_out[i+1] = val; |
||||
|
} |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
void S_TransferStereo16 (int endtime) |
||||
|
{ |
||||
|
int lpos; |
||||
|
int lpaintedtime; |
||||
|
DWORD *pbuf; |
||||
|
#ifdef _WIN32 |
||||
|
int reps; |
||||
|
DWORD dwSize,dwSize2; |
||||
|
DWORD *pbuf2; |
||||
|
HRESULT hresult; |
||||
|
#endif |
||||
|
|
||||
|
snd_vol = volume.value*256; |
||||
|
|
||||
|
snd_p = (int *) paintbuffer; |
||||
|
lpaintedtime = paintedtime; |
||||
|
|
||||
|
#ifdef _WIN32 |
||||
|
if (pDSBuf) |
||||
|
{ |
||||
|
reps = 0; |
||||
|
|
||||
|
while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize, |
||||
|
&pbuf2, &dwSize2, 0)) != DS_OK) |
||||
|
{ |
||||
|
if (hresult != DSERR_BUFFERLOST) |
||||
|
{ |
||||
|
Con_Printf ("S_TransferStereo16: DS::Lock Sound Buffer Failed\n"); |
||||
|
S_Shutdown (); |
||||
|
S_Startup (); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (++reps > 10000) |
||||
|
{ |
||||
|
Con_Printf ("S_TransferStereo16: DS: couldn't restore buffer\n"); |
||||
|
S_Shutdown (); |
||||
|
S_Startup (); |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
#endif |
||||
|
{ |
||||
|
pbuf = (DWORD *)shm->buffer; |
||||
|
} |
||||
|
|
||||
|
while (lpaintedtime < endtime) |
||||
|
{ |
||||
|
// handle recirculating buffer issues |
||||
|
lpos = lpaintedtime & ((shm->samples>>1)-1); |
||||
|
|
||||
|
snd_out = (short *) pbuf + (lpos<<1); |
||||
|
|
||||
|
snd_linear_count = (shm->samples>>1) - lpos; |
||||
|
if (lpaintedtime + snd_linear_count > endtime) |
||||
|
snd_linear_count = endtime - lpaintedtime; |
||||
|
|
||||
|
snd_linear_count <<= 1; |
||||
|
|
||||
|
// write a linear blast of samples |
||||
|
Snd_WriteLinearBlastStereo16 (); |
||||
|
|
||||
|
snd_p += snd_linear_count; |
||||
|
lpaintedtime += (snd_linear_count>>1); |
||||
|
} |
||||
|
|
||||
|
#ifdef _WIN32 |
||||
|
if (pDSBuf) |
||||
|
pDSBuf->lpVtbl->Unlock(pDSBuf, pbuf, dwSize, NULL, 0); |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
void S_TransferPaintBuffer(int endtime) |
||||
|
{ |
||||
|
int out_idx; |
||||
|
int count; |
||||
|
int out_mask; |
||||
|
int *p; |
||||
|
int step; |
||||
|
int val; |
||||
|
int snd_vol; |
||||
|
DWORD *pbuf; |
||||
|
#ifdef _WIN32 |
||||
|
int reps; |
||||
|
DWORD dwSize,dwSize2; |
||||
|
DWORD *pbuf2; |
||||
|
HRESULT hresult; |
||||
|
#endif |
||||
|
|
||||
|
if (shm->samplebits == 16 && shm->channels == 2) |
||||
|
{ |
||||
|
S_TransferStereo16 (endtime); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
p = (int *) paintbuffer; |
||||
|
count = (endtime - paintedtime) * shm->channels; |
||||
|
out_mask = shm->samples - 1; |
||||
|
out_idx = paintedtime * shm->channels & out_mask; |
||||
|
step = 3 - shm->channels; |
||||
|
snd_vol = volume.value*256; |
||||
|
|
||||
|
#ifdef _WIN32 |
||||
|
if (pDSBuf) |
||||
|
{ |
||||
|
reps = 0; |
||||
|
|
||||
|
while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize, |
||||
|
&pbuf2,&dwSize2, 0)) != DS_OK) |
||||
|
{ |
||||
|
if (hresult != DSERR_BUFFERLOST) |
||||
|
{ |
||||
|
Con_Printf ("S_TransferPaintBuffer: DS::Lock Sound Buffer Failed\n"); |
||||
|
S_Shutdown (); |
||||
|
S_Startup (); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (++reps > 10000) |
||||
|
{ |
||||
|
Con_Printf ("S_TransferPaintBuffer: DS: couldn't restore buffer\n"); |
||||
|
S_Shutdown (); |
||||
|
S_Startup (); |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
#endif |
||||
|
{ |
||||
|
pbuf = (DWORD *)shm->buffer; |
||||
|
} |
||||
|
|
||||
|
if (shm->samplebits == 16) |
||||
|
{ |
||||
|
short *out = (short *) pbuf; |
||||
|
while (count--) |
||||
|
{ |
||||
|
val = (*p * snd_vol) >> 8; |
||||
|
p+= step; |
||||
|
if (val > 0x7fff) |
||||
|
val = 0x7fff; |
||||
|
else if (val < (short)0x8000) |
||||
|
val = (short)0x8000; |
||||
|
out[out_idx] = val; |
||||
|
out_idx = (out_idx + 1) & out_mask; |
||||
|
} |
||||
|
} |
||||
|
else if (shm->samplebits == 8) |
||||
|
{ |
||||
|
unsigned char *out = (unsigned char *) pbuf; |
||||
|
while (count--) |
||||
|
{ |
||||
|
val = (*p * snd_vol) >> 8; |
||||
|
p+= step; |
||||
|
if (val > 0x7fff) |
||||
|
val = 0x7fff; |
||||
|
else if (val < (short)0x8000) |
||||
|
val = (short)0x8000; |
||||
|
out[out_idx] = (val>>8) + 128; |
||||
|
out_idx = (out_idx + 1) & out_mask; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#ifdef _WIN32 |
||||
|
if (pDSBuf) { |
||||
|
DWORD dwNewpos, dwWrite; |
||||
|
int il = paintedtime; |
||||
|
int ir = endtime - paintedtime; |
||||
|
|
||||
|
ir += il; |
||||
|
|
||||
|
pDSBuf->lpVtbl->Unlock(pDSBuf, pbuf, dwSize, NULL, 0); |
||||
|
|
||||
|
pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &dwNewpos, &dwWrite); |
||||
|
|
||||
|
// if ((dwNewpos >= il) && (dwNewpos <= ir)) |
||||
|
// Con_Printf("%d-%d p %d c\n", il, ir, dwNewpos); |
||||
|
} |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
=============================================================================== |
||||
|
|
||||
|
CHANNEL MIXING |
||||
|
|
||||
|
=============================================================================== |
||||
|
*/ |
||||
|
|
||||
|
void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int endtime); |
||||
|
void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int endtime); |
||||
|
|
||||
|
void S_PaintChannels(int endtime) |
||||
|
{ |
||||
|
int i; |
||||
|
int end; |
||||
|
channel_t *ch; |
||||
|
sfxcache_t *sc; |
||||
|
int ltime, count; |
||||
|
|
||||
|
while (paintedtime < endtime) |
||||
|
{ |
||||
|
// if paintbuffer is smaller than DMA buffer |
||||
|
end = endtime; |
||||
|
if (endtime - paintedtime > PAINTBUFFER_SIZE) |
||||
|
end = paintedtime + PAINTBUFFER_SIZE; |
||||
|
|
||||
|
// clear the paint buffer |
||||
|
Q_memset(paintbuffer, 0, (end - paintedtime) * sizeof(portable_samplepair_t)); |
||||
|
|
||||
|
// paint in the channels. |
||||
|
ch = channels; |
||||
|
for (i=0; i<total_channels ; i++, ch++) |
||||
|
{ |
||||
|
if (!ch->sfx) |
||||
|
continue; |
||||
|
if (!ch->leftvol && !ch->rightvol) |
||||
|
continue; |
||||
|
sc = S_LoadSound (ch->sfx); |
||||
|
if (!sc) |
||||
|
continue; |
||||
|
|
||||
|
ltime = paintedtime; |
||||
|
|
||||
|
while (ltime < end) |
||||
|
{ // paint up to end |
||||
|
if (ch->end < end) |
||||
|
count = ch->end - ltime; |
||||
|
else |
||||
|
count = end - ltime; |
||||
|
|
||||
|
if (count > 0) |
||||
|
{ |
||||
|
if (sc->width == 1) |
||||
|
SND_PaintChannelFrom8(ch, sc, count); |
||||
|
else |
||||
|
SND_PaintChannelFrom16(ch, sc, count); |
||||
|
|
||||
|
ltime += count; |
||||
|
} |
||||
|
|
||||
|
// if at end of loop, restart |
||||
|
if (ltime >= ch->end) |
||||
|
{ |
||||
|
if (sc->loopstart >= 0) |
||||
|
{ |
||||
|
ch->pos = sc->loopstart; |
||||
|
ch->end = ltime + sc->length - ch->pos; |
||||
|
} |
||||
|
else |
||||
|
{ // channel just stopped |
||||
|
ch->sfx = NULL; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
// transfer out according to DMA format |
||||
|
S_TransferPaintBuffer(end); |
||||
|
paintedtime = end; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void SND_InitScaletable (void) |
||||
|
{ |
||||
|
int i, j; |
||||
|
|
||||
|
for (i=0 ; i<32 ; i++) |
||||
|
for (j=0 ; j<256 ; j++) |
||||
|
snd_scaletable[i][j] = ((signed char)j) * i * 8; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
#if !id386 |
||||
|
|
||||
|
void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count) |
||||
|
{ |
||||
|
int data; |
||||
|
int *lscale, *rscale; |
||||
|
unsigned char *sfx; |
||||
|
int i; |
||||
|
|
||||
|
if (ch->leftvol > 255) |
||||
|
ch->leftvol = 255; |
||||
|
if (ch->rightvol > 255) |
||||
|
ch->rightvol = 255; |
||||
|
|
||||
|
lscale = snd_scaletable[ch->leftvol >> 3]; |
||||
|
rscale = snd_scaletable[ch->rightvol >> 3]; |
||||
|
sfx = (signed char *)sc->data + ch->pos; |
||||
|
|
||||
|
for (i=0 ; i<count ; i++) |
||||
|
{ |
||||
|
data = sfx[i]; |
||||
|
paintbuffer[i].left += lscale[data]; |
||||
|
paintbuffer[i].right += rscale[data]; |
||||
|
} |
||||
|
|
||||
|
ch->pos += count; |
||||
|
} |
||||
|
|
||||
|
#endif // !id386 |
||||
|
|
||||
|
|
||||
|
void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count) |
||||
|
{ |
||||
|
int data; |
||||
|
int left, right; |
||||
|
int leftvol, rightvol; |
||||
|
signed short *sfx; |
||||
|
int i; |
||||
|
|
||||
|
leftvol = ch->leftvol; |
||||
|
rightvol = ch->rightvol; |
||||
|
sfx = (signed short *)sc->data + ch->pos; |
||||
|
|
||||
|
for (i=0 ; i<count ; i++) |
||||
|
{ |
||||
|
data = sfx[i]; |
||||
|
left = (data * leftvol) >> 8; |
||||
|
right = (data * rightvol) >> 8; |
||||
|
paintbuffer[i].left += left; |
||||
|
paintbuffer[i].right += right; |
||||
|
} |
||||
|
|
||||
|
ch->pos += count; |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,737 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
#include "quakedef.h" |
||||
|
#include "winquake.h" |
||||
|
|
||||
|
#define iDirectSoundCreate(a,b,c) pDirectSoundCreate(a,b,c) |
||||
|
|
||||
|
HRESULT (WINAPI *pDirectSoundCreate)(GUID FAR *lpGUID, LPDIRECTSOUND FAR *lplpDS, IUnknown FAR *pUnkOuter); |
||||
|
|
||||
|
// 64K is > 1 second at 16-bit, 22050 Hz |
||||
|
#define WAV_BUFFERS 64 |
||||
|
#define WAV_MASK 0x3F |
||||
|
#define WAV_BUFFER_SIZE 0x0400 |
||||
|
#define SECONDARY_BUFFER_SIZE 0x10000 |
||||
|
|
||||
|
typedef enum {SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL} sndinitstat; |
||||
|
|
||||
|
static qboolean wavonly; |
||||
|
static qboolean dsound_init; |
||||
|
static qboolean wav_init; |
||||
|
static qboolean snd_firsttime = true, snd_isdirect, snd_iswave; |
||||
|
static qboolean primary_format_set; |
||||
|
|
||||
|
static int sample16; |
||||
|
static int snd_sent, snd_completed; |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
* Global variables. Must be visible to window-procedure function |
||||
|
* so it can unlock and free the data block after it has been played. |
||||
|
*/ |
||||
|
|
||||
|
HANDLE hData; |
||||
|
HPSTR lpData, lpData2; |
||||
|
|
||||
|
HGLOBAL hWaveHdr; |
||||
|
LPWAVEHDR lpWaveHdr; |
||||
|
|
||||
|
HWAVEOUT hWaveOut; |
||||
|
|
||||
|
WAVEOUTCAPS wavecaps; |
||||
|
|
||||
|
DWORD gSndBufSize; |
||||
|
|
||||
|
MMTIME mmstarttime; |
||||
|
|
||||
|
LPDIRECTSOUND pDS; |
||||
|
LPDIRECTSOUNDBUFFER pDSBuf, pDSPBuf; |
||||
|
|
||||
|
HINSTANCE hInstDS; |
||||
|
|
||||
|
qboolean SNDDMA_InitDirect (void); |
||||
|
qboolean SNDDMA_InitWav (void); |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================== |
||||
|
S_BlockSound |
||||
|
================== |
||||
|
*/ |
||||
|
void S_BlockSound (void) |
||||
|
{ |
||||
|
|
||||
|
// DirectSound takes care of blocking itself |
||||
|
if (snd_iswave) |
||||
|
{ |
||||
|
snd_blocked++; |
||||
|
|
||||
|
if (snd_blocked == 1) |
||||
|
{ |
||||
|
waveOutReset (hWaveOut); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================== |
||||
|
S_UnblockSound |
||||
|
================== |
||||
|
*/ |
||||
|
void S_UnblockSound (void) |
||||
|
{ |
||||
|
|
||||
|
// DirectSound takes care of blocking itself |
||||
|
if (snd_iswave) |
||||
|
{ |
||||
|
snd_blocked--; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================== |
||||
|
FreeSound |
||||
|
================== |
||||
|
*/ |
||||
|
void FreeSound (void) |
||||
|
{ |
||||
|
int i; |
||||
|
|
||||
|
if (pDSBuf) |
||||
|
{ |
||||
|
pDSBuf->lpVtbl->Stop(pDSBuf); |
||||
|
pDSBuf->lpVtbl->Release(pDSBuf); |
||||
|
} |
||||
|
|
||||
|
// only release primary buffer if it's not also the mixing buffer we just released |
||||
|
if (pDSPBuf && (pDSBuf != pDSPBuf)) |
||||
|
{ |
||||
|
pDSPBuf->lpVtbl->Release(pDSPBuf); |
||||
|
} |
||||
|
|
||||
|
if (pDS) |
||||
|
{ |
||||
|
pDS->lpVtbl->SetCooperativeLevel (pDS, mainwindow, DSSCL_NORMAL); |
||||
|
pDS->lpVtbl->Release(pDS); |
||||
|
} |
||||
|
|
||||
|
if (hWaveOut) |
||||
|
{ |
||||
|
waveOutReset (hWaveOut); |
||||
|
|
||||
|
if (lpWaveHdr) |
||||
|
{ |
||||
|
for (i=0 ; i< WAV_BUFFERS ; i++) |
||||
|
waveOutUnprepareHeader (hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR)); |
||||
|
} |
||||
|
|
||||
|
waveOutClose (hWaveOut); |
||||
|
|
||||
|
if (hWaveHdr) |
||||
|
{ |
||||
|
GlobalUnlock(hWaveHdr); |
||||
|
GlobalFree(hWaveHdr); |
||||
|
} |
||||
|
|
||||
|
if (hData) |
||||
|
{ |
||||
|
GlobalUnlock(hData); |
||||
|
GlobalFree(hData); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
pDS = NULL; |
||||
|
pDSBuf = NULL; |
||||
|
pDSPBuf = NULL; |
||||
|
hWaveOut = 0; |
||||
|
hData = 0; |
||||
|
hWaveHdr = 0; |
||||
|
lpData = NULL; |
||||
|
lpWaveHdr = NULL; |
||||
|
dsound_init = false; |
||||
|
wav_init = false; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================== |
||||
|
SNDDMA_InitDirect |
||||
|
|
||||
|
Direct-Sound support |
||||
|
================== |
||||
|
*/ |
||||
|
sndinitstat SNDDMA_InitDirect (void) |
||||
|
{ |
||||
|
DSBUFFERDESC dsbuf; |
||||
|
DSBCAPS dsbcaps; |
||||
|
DWORD dwSize, dwWrite; |
||||
|
DSCAPS dscaps; |
||||
|
WAVEFORMATEX format, pformat; |
||||
|
HRESULT hresult; |
||||
|
int reps; |
||||
|
|
||||
|
memset ((void *)&sn, 0, sizeof (sn)); |
||||
|
|
||||
|
shm = &sn; |
||||
|
|
||||
|
shm->channels = 2; |
||||
|
shm->samplebits = 16; |
||||
|
|
||||
|
// jkrige - change sound speed |
||||
|
//shm->speed = 11025; |
||||
|
shm->speed = 22050; |
||||
|
// jkrige - change sound speed |
||||
|
|
||||
|
memset (&format, 0, sizeof(format)); |
||||
|
format.wFormatTag = WAVE_FORMAT_PCM; |
||||
|
format.nChannels = shm->channels; |
||||
|
format.wBitsPerSample = shm->samplebits; |
||||
|
format.nSamplesPerSec = shm->speed; |
||||
|
format.nBlockAlign = format.nChannels |
||||
|
*format.wBitsPerSample / 8; |
||||
|
format.cbSize = 0; |
||||
|
format.nAvgBytesPerSec = format.nSamplesPerSec |
||||
|
*format.nBlockAlign; |
||||
|
|
||||
|
if (!hInstDS) |
||||
|
{ |
||||
|
hInstDS = LoadLibrary("dsound.dll"); |
||||
|
|
||||
|
if (hInstDS == NULL) |
||||
|
{ |
||||
|
Con_SafePrintf ("Couldn't load dsound.dll\n"); |
||||
|
return SIS_FAILURE; |
||||
|
} |
||||
|
|
||||
|
pDirectSoundCreate = (void *)GetProcAddress(hInstDS,"DirectSoundCreate"); |
||||
|
|
||||
|
if (!pDirectSoundCreate) |
||||
|
{ |
||||
|
Con_SafePrintf ("Couldn't get DS proc addr\n"); |
||||
|
return SIS_FAILURE; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
while ((hresult = iDirectSoundCreate(NULL, &pDS, NULL)) != DS_OK) |
||||
|
{ |
||||
|
if (hresult != DSERR_ALLOCATED) |
||||
|
{ |
||||
|
Con_SafePrintf ("DirectSound create failed\n"); |
||||
|
return SIS_FAILURE; |
||||
|
} |
||||
|
|
||||
|
if (MessageBox (NULL, |
||||
|
"The sound hardware is in use by another app.\n\n" |
||||
|
"Select Retry to try to start sound again or Cancel to run Quake with no sound.", |
||||
|
"Sound not available", |
||||
|
MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY) |
||||
|
{ |
||||
|
Con_SafePrintf ("DirectSoundCreate failure\n" |
||||
|
" hardware already in use\n"); |
||||
|
return SIS_NOTAVAIL; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
dscaps.dwSize = sizeof(dscaps); |
||||
|
|
||||
|
if (DS_OK != pDS->lpVtbl->GetCaps (pDS, &dscaps)) |
||||
|
{ |
||||
|
Con_SafePrintf ("Couldn't get DS caps\n"); |
||||
|
} |
||||
|
|
||||
|
if (dscaps.dwFlags & DSCAPS_EMULDRIVER) |
||||
|
{ |
||||
|
Con_SafePrintf ("No DirectSound driver installed\n"); |
||||
|
FreeSound (); |
||||
|
return SIS_FAILURE; |
||||
|
} |
||||
|
|
||||
|
if (DS_OK != pDS->lpVtbl->SetCooperativeLevel (pDS, mainwindow, DSSCL_EXCLUSIVE)) |
||||
|
{ |
||||
|
Con_SafePrintf ("Set coop level failed\n"); |
||||
|
FreeSound (); |
||||
|
return SIS_FAILURE; |
||||
|
} |
||||
|
|
||||
|
// get access to the primary buffer, if possible, so we can set the |
||||
|
// sound hardware format |
||||
|
memset (&dsbuf, 0, sizeof(dsbuf)); |
||||
|
dsbuf.dwSize = sizeof(DSBUFFERDESC); |
||||
|
dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER; |
||||
|
dsbuf.dwBufferBytes = 0; |
||||
|
dsbuf.lpwfxFormat = NULL; |
||||
|
|
||||
|
memset(&dsbcaps, 0, sizeof(dsbcaps)); |
||||
|
dsbcaps.dwSize = sizeof(dsbcaps); |
||||
|
primary_format_set = false; |
||||
|
|
||||
|
if (!COM_CheckParm ("-snoforceformat")) |
||||
|
{ |
||||
|
if (DS_OK == pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSPBuf, NULL)) |
||||
|
{ |
||||
|
pformat = format; |
||||
|
|
||||
|
if (DS_OK != pDSPBuf->lpVtbl->SetFormat (pDSPBuf, &pformat)) |
||||
|
{ |
||||
|
if (snd_firsttime) |
||||
|
Con_SafePrintf ("Set primary sound buffer format: no\n"); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
if (snd_firsttime) |
||||
|
Con_SafePrintf ("Set primary sound buffer format: yes\n"); |
||||
|
|
||||
|
primary_format_set = true; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (!primary_format_set || !COM_CheckParm ("-primarysound")) |
||||
|
{ |
||||
|
// create the secondary buffer we'll actually work with |
||||
|
memset (&dsbuf, 0, sizeof(dsbuf)); |
||||
|
dsbuf.dwSize = sizeof(DSBUFFERDESC); |
||||
|
dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_LOCSOFTWARE; |
||||
|
dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE; |
||||
|
dsbuf.lpwfxFormat = &format; |
||||
|
|
||||
|
memset(&dsbcaps, 0, sizeof(dsbcaps)); |
||||
|
dsbcaps.dwSize = sizeof(dsbcaps); |
||||
|
|
||||
|
if (DS_OK != pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSBuf, NULL)) |
||||
|
{ |
||||
|
Con_SafePrintf ("DS:CreateSoundBuffer Failed"); |
||||
|
FreeSound (); |
||||
|
return SIS_FAILURE; |
||||
|
} |
||||
|
|
||||
|
shm->channels = format.nChannels; |
||||
|
shm->samplebits = format.wBitsPerSample; |
||||
|
shm->speed = format.nSamplesPerSec; |
||||
|
|
||||
|
if (DS_OK != pDSBuf->lpVtbl->GetCaps (pDSBuf, &dsbcaps)) |
||||
|
{ |
||||
|
Con_SafePrintf ("DS:GetCaps failed\n"); |
||||
|
FreeSound (); |
||||
|
return SIS_FAILURE; |
||||
|
} |
||||
|
|
||||
|
if (snd_firsttime) |
||||
|
Con_SafePrintf ("Using secondary sound buffer\n"); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
if (DS_OK != pDS->lpVtbl->SetCooperativeLevel (pDS, mainwindow, DSSCL_WRITEPRIMARY)) |
||||
|
{ |
||||
|
Con_SafePrintf ("Set coop level failed\n"); |
||||
|
FreeSound (); |
||||
|
return SIS_FAILURE; |
||||
|
} |
||||
|
|
||||
|
if (DS_OK != pDSPBuf->lpVtbl->GetCaps (pDSPBuf, &dsbcaps)) |
||||
|
{ |
||||
|
Con_Printf ("DS:GetCaps failed\n"); |
||||
|
return SIS_FAILURE; |
||||
|
} |
||||
|
|
||||
|
pDSBuf = pDSPBuf; |
||||
|
Con_SafePrintf ("Using primary sound buffer\n"); |
||||
|
} |
||||
|
|
||||
|
// Make sure mixer is active |
||||
|
pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING); |
||||
|
|
||||
|
if (snd_firsttime) |
||||
|
Con_SafePrintf(" %d channel(s)\n" |
||||
|
" %d bits/sample\n" |
||||
|
" %d bytes/sec\n", |
||||
|
shm->channels, shm->samplebits, shm->speed); |
||||
|
|
||||
|
gSndBufSize = dsbcaps.dwBufferBytes; |
||||
|
|
||||
|
// initialize the buffer |
||||
|
reps = 0; |
||||
|
|
||||
|
while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &lpData, &dwSize, NULL, NULL, 0)) != DS_OK) |
||||
|
{ |
||||
|
if (hresult != DSERR_BUFFERLOST) |
||||
|
{ |
||||
|
Con_SafePrintf ("SNDDMA_InitDirect: DS::Lock Sound Buffer Failed\n"); |
||||
|
FreeSound (); |
||||
|
return SIS_FAILURE; |
||||
|
} |
||||
|
|
||||
|
if (++reps > 10000) |
||||
|
{ |
||||
|
Con_SafePrintf ("SNDDMA_InitDirect: DS: couldn't restore buffer\n"); |
||||
|
FreeSound (); |
||||
|
return SIS_FAILURE; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
memset(lpData, 0, dwSize); |
||||
|
// lpData[4] = lpData[5] = 0x7f; // force a pop for debugging |
||||
|
|
||||
|
pDSBuf->lpVtbl->Unlock(pDSBuf, lpData, dwSize, NULL, 0); |
||||
|
|
||||
|
/* we don't want anyone to access the buffer directly w/o locking it first. */ |
||||
|
lpData = NULL; |
||||
|
|
||||
|
pDSBuf->lpVtbl->Stop(pDSBuf); |
||||
|
pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &mmstarttime.u.sample, &dwWrite); |
||||
|
pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING); |
||||
|
|
||||
|
shm->soundalive = true; |
||||
|
shm->splitbuffer = false; |
||||
|
shm->samples = gSndBufSize/(shm->samplebits/8); |
||||
|
shm->samplepos = 0; |
||||
|
shm->submission_chunk = 1; |
||||
|
shm->buffer = (unsigned char *) lpData; |
||||
|
sample16 = (shm->samplebits/8) - 1; |
||||
|
|
||||
|
dsound_init = true; |
||||
|
|
||||
|
return SIS_SUCCESS; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
================== |
||||
|
SNDDM_InitWav |
||||
|
|
||||
|
Crappy windows multimedia base |
||||
|
================== |
||||
|
*/ |
||||
|
qboolean SNDDMA_InitWav (void) |
||||
|
{ |
||||
|
WAVEFORMATEX format; |
||||
|
int i; |
||||
|
HRESULT hr; |
||||
|
|
||||
|
snd_sent = 0; |
||||
|
snd_completed = 0; |
||||
|
|
||||
|
shm = &sn; |
||||
|
|
||||
|
shm->channels = 2; |
||||
|
shm->samplebits = 16; |
||||
|
|
||||
|
// jkrige - change sound speed |
||||
|
//shm->speed = 11025; |
||||
|
shm->speed = 22050; |
||||
|
// jkrige - change sound speed |
||||
|
|
||||
|
memset (&format, 0, sizeof(format)); |
||||
|
format.wFormatTag = WAVE_FORMAT_PCM; |
||||
|
format.nChannels = shm->channels; |
||||
|
format.wBitsPerSample = shm->samplebits; |
||||
|
format.nSamplesPerSec = shm->speed; |
||||
|
format.nBlockAlign = format.nChannels |
||||
|
*format.wBitsPerSample / 8; |
||||
|
format.cbSize = 0; |
||||
|
format.nAvgBytesPerSec = format.nSamplesPerSec |
||||
|
*format.nBlockAlign; |
||||
|
|
||||
|
/* Open a waveform device for output using window callback. */ |
||||
|
while ((hr = waveOutOpen((LPHWAVEOUT)&hWaveOut, WAVE_MAPPER, |
||||
|
&format, |
||||
|
0, 0L, CALLBACK_NULL)) != MMSYSERR_NOERROR) |
||||
|
{ |
||||
|
if (hr != MMSYSERR_ALLOCATED) |
||||
|
{ |
||||
|
Con_SafePrintf ("waveOutOpen failed\n"); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
if (MessageBox (NULL, |
||||
|
"The sound hardware is in use by another app.\n\n" |
||||
|
"Select Retry to try to start sound again or Cancel to run Quake with no sound.", |
||||
|
"Sound not available", |
||||
|
MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY) |
||||
|
{ |
||||
|
Con_SafePrintf ("waveOutOpen failure;\n" |
||||
|
" hardware already in use\n"); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Allocate and lock memory for the waveform data. The memory |
||||
|
* for waveform data must be globally allocated with |
||||
|
* GMEM_MOVEABLE and GMEM_SHARE flags. |
||||
|
|
||||
|
*/ |
||||
|
gSndBufSize = WAV_BUFFERS*WAV_BUFFER_SIZE; |
||||
|
hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, gSndBufSize); |
||||
|
if (!hData) |
||||
|
{ |
||||
|
Con_SafePrintf ("Sound: Out of memory.\n"); |
||||
|
FreeSound (); |
||||
|
return false; |
||||
|
} |
||||
|
lpData = GlobalLock(hData); |
||||
|
if (!lpData) |
||||
|
{ |
||||
|
Con_SafePrintf ("Sound: Failed to lock.\n"); |
||||
|
FreeSound (); |
||||
|
return false; |
||||
|
} |
||||
|
memset (lpData, 0, gSndBufSize); |
||||
|
|
||||
|
/* |
||||
|
* Allocate and lock memory for the header. This memory must |
||||
|
* also be globally allocated with GMEM_MOVEABLE and |
||||
|
* GMEM_SHARE flags. |
||||
|
*/ |
||||
|
hWaveHdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, |
||||
|
(DWORD) sizeof(WAVEHDR) * WAV_BUFFERS); |
||||
|
|
||||
|
if (hWaveHdr == NULL) |
||||
|
{ |
||||
|
Con_SafePrintf ("Sound: Failed to Alloc header.\n"); |
||||
|
FreeSound (); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
lpWaveHdr = (LPWAVEHDR) GlobalLock(hWaveHdr); |
||||
|
|
||||
|
if (lpWaveHdr == NULL) |
||||
|
{ |
||||
|
Con_SafePrintf ("Sound: Failed to lock header.\n"); |
||||
|
FreeSound (); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
memset (lpWaveHdr, 0, sizeof(WAVEHDR) * WAV_BUFFERS); |
||||
|
|
||||
|
/* After allocation, set up and prepare headers. */ |
||||
|
for (i=0 ; i<WAV_BUFFERS ; i++) |
||||
|
{ |
||||
|
lpWaveHdr[i].dwBufferLength = WAV_BUFFER_SIZE; |
||||
|
lpWaveHdr[i].lpData = lpData + i*WAV_BUFFER_SIZE; |
||||
|
|
||||
|
if (waveOutPrepareHeader(hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR)) != |
||||
|
MMSYSERR_NOERROR) |
||||
|
{ |
||||
|
Con_SafePrintf ("Sound: failed to prepare wave headers\n"); |
||||
|
FreeSound (); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
shm->soundalive = true; |
||||
|
shm->splitbuffer = false; |
||||
|
shm->samples = gSndBufSize/(shm->samplebits/8); |
||||
|
shm->samplepos = 0; |
||||
|
shm->submission_chunk = 1; |
||||
|
shm->buffer = (unsigned char *) lpData; |
||||
|
sample16 = (shm->samplebits/8) - 1; |
||||
|
|
||||
|
wav_init = true; |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
================== |
||||
|
SNDDMA_Init |
||||
|
|
||||
|
Try to find a sound device to mix for. |
||||
|
Returns false if nothing is found. |
||||
|
================== |
||||
|
*/ |
||||
|
|
||||
|
int SNDDMA_Init(void) |
||||
|
{ |
||||
|
sndinitstat stat; |
||||
|
|
||||
|
if (COM_CheckParm ("-wavonly")) |
||||
|
wavonly = true; |
||||
|
|
||||
|
dsound_init = wav_init = 0; |
||||
|
|
||||
|
stat = SIS_FAILURE; // assume DirectSound won't initialize |
||||
|
|
||||
|
/* Init DirectSound */ |
||||
|
if (!wavonly) |
||||
|
{ |
||||
|
if (snd_firsttime || snd_isdirect) |
||||
|
{ |
||||
|
stat = SNDDMA_InitDirect ();; |
||||
|
|
||||
|
if (stat == SIS_SUCCESS) |
||||
|
{ |
||||
|
snd_isdirect = true; |
||||
|
|
||||
|
if (snd_firsttime) |
||||
|
Con_SafePrintf ("DirectSound initialized\n"); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
snd_isdirect = false; |
||||
|
Con_SafePrintf ("DirectSound failed to init\n"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// if DirectSound didn't succeed in initializing, try to initialize |
||||
|
// waveOut sound, unless DirectSound failed because the hardware is |
||||
|
// already allocated (in which case the user has already chosen not |
||||
|
// to have sound) |
||||
|
if (!dsound_init && (stat != SIS_NOTAVAIL)) |
||||
|
{ |
||||
|
if (snd_firsttime || snd_iswave) |
||||
|
{ |
||||
|
|
||||
|
snd_iswave = SNDDMA_InitWav (); |
||||
|
|
||||
|
if (snd_iswave) |
||||
|
{ |
||||
|
if (snd_firsttime) |
||||
|
Con_SafePrintf ("Wave sound initialized\n"); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
Con_SafePrintf ("Wave sound failed to init\n"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
snd_firsttime = false; |
||||
|
|
||||
|
if (!dsound_init && !wav_init) |
||||
|
{ |
||||
|
if (snd_firsttime) |
||||
|
Con_SafePrintf ("No sound device initialized\n"); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
============== |
||||
|
SNDDMA_GetDMAPos |
||||
|
|
||||
|
return the current sample position (in mono samples read) |
||||
|
inside the recirculating dma buffer, so the mixing code will know |
||||
|
how many sample are required to fill it up. |
||||
|
=============== |
||||
|
*/ |
||||
|
int SNDDMA_GetDMAPos(void) |
||||
|
{ |
||||
|
MMTIME mmtime; |
||||
|
int s; |
||||
|
DWORD dwWrite; |
||||
|
|
||||
|
if (dsound_init) |
||||
|
{ |
||||
|
mmtime.wType = TIME_SAMPLES; |
||||
|
pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &mmtime.u.sample, &dwWrite); |
||||
|
s = mmtime.u.sample - mmstarttime.u.sample; |
||||
|
} |
||||
|
else if (wav_init) |
||||
|
{ |
||||
|
s = snd_sent * WAV_BUFFER_SIZE; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
s >>= sample16; |
||||
|
|
||||
|
s &= (shm->samples-1); |
||||
|
|
||||
|
return s; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
============== |
||||
|
SNDDMA_Submit |
||||
|
|
||||
|
Send sound to device if buffer isn't really the dma buffer |
||||
|
=============== |
||||
|
*/ |
||||
|
void SNDDMA_Submit(void) |
||||
|
{ |
||||
|
LPWAVEHDR h; |
||||
|
int wResult; |
||||
|
|
||||
|
if (!wav_init) |
||||
|
return; |
||||
|
|
||||
|
// |
||||
|
// find which sound blocks have completed |
||||
|
// |
||||
|
while (1) |
||||
|
{ |
||||
|
if ( snd_completed == snd_sent ) |
||||
|
{ |
||||
|
Con_DPrintf ("Sound overrun\n"); |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
if ( ! (lpWaveHdr[ snd_completed & WAV_MASK].dwFlags & WHDR_DONE) ) |
||||
|
{ |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
snd_completed++; // this buffer has been played |
||||
|
} |
||||
|
|
||||
|
// |
||||
|
// submit two new sound blocks |
||||
|
// |
||||
|
while (((snd_sent - snd_completed) >> sample16) < 4) |
||||
|
{ |
||||
|
h = lpWaveHdr + ( snd_sent&WAV_MASK ); |
||||
|
|
||||
|
snd_sent++; |
||||
|
/* |
||||
|
* Now the data block can be sent to the output device. The |
||||
|
* waveOutWrite function returns immediately and waveform |
||||
|
* data is sent to the output device in the background. |
||||
|
*/ |
||||
|
wResult = waveOutWrite(hWaveOut, h, sizeof(WAVEHDR)); |
||||
|
|
||||
|
if (wResult != MMSYSERR_NOERROR) |
||||
|
{ |
||||
|
Con_SafePrintf ("Failed to write block to device\n"); |
||||
|
FreeSound (); |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
============== |
||||
|
SNDDMA_Shutdown |
||||
|
|
||||
|
Reset the sound device for exiting |
||||
|
=============== |
||||
|
*/ |
||||
|
void SNDDMA_Shutdown(void) |
||||
|
{ |
||||
|
FreeSound (); |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,177 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// sound.h -- client sound i/o functions |
||||
|
|
||||
|
#ifndef __SOUND__ |
||||
|
#define __SOUND__ |
||||
|
|
||||
|
#define DEFAULT_SOUND_PACKET_VOLUME 255 |
||||
|
#define DEFAULT_SOUND_PACKET_ATTENUATION 1.0 |
||||
|
|
||||
|
// !!! if this is changed, it much be changed in asm_i386.h too !!! |
||||
|
typedef struct |
||||
|
{ |
||||
|
int left; |
||||
|
int right; |
||||
|
} portable_samplepair_t; |
||||
|
|
||||
|
typedef struct sfx_s |
||||
|
{ |
||||
|
char name[MAX_QPATH]; |
||||
|
cache_user_t cache; |
||||
|
} sfx_t; |
||||
|
|
||||
|
// !!! if this is changed, it much be changed in asm_i386.h too !!! |
||||
|
typedef struct |
||||
|
{ |
||||
|
int length; |
||||
|
int loopstart; |
||||
|
int speed; |
||||
|
int width; |
||||
|
int stereo; |
||||
|
byte data[1]; // variable sized |
||||
|
} sfxcache_t; |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
qboolean gamealive; |
||||
|
qboolean soundalive; |
||||
|
qboolean splitbuffer; |
||||
|
int channels; |
||||
|
int samples; // mono samples in buffer |
||||
|
int submission_chunk; // don't mix less than this # |
||||
|
int samplepos; // in mono samples |
||||
|
int samplebits; |
||||
|
int speed; |
||||
|
unsigned char *buffer; |
||||
|
} dma_t; |
||||
|
|
||||
|
// !!! if this is changed, it much be changed in asm_i386.h too !!! |
||||
|
typedef struct |
||||
|
{ |
||||
|
sfx_t *sfx; // sfx number |
||||
|
int leftvol; // 0-255 volume |
||||
|
int rightvol; // 0-255 volume |
||||
|
int end; // end time in global paintsamples |
||||
|
int pos; // sample position in sfx |
||||
|
int looping; // where to loop, -1 = no looping |
||||
|
int entnum; // to allow overriding a specific sound |
||||
|
int entchannel; // |
||||
|
vec3_t origin; // origin of sound effect |
||||
|
vec_t dist_mult; // distance multiplier (attenuation/clipK) |
||||
|
int master_vol; // 0-255 master volume |
||||
|
} channel_t; |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
int rate; |
||||
|
int width; |
||||
|
int channels; |
||||
|
int loopstart; |
||||
|
int samples; |
||||
|
int dataofs; // chunk starts this many bytes from file start |
||||
|
} wavinfo_t; |
||||
|
|
||||
|
void S_Init (void); |
||||
|
void S_Startup (void); |
||||
|
void S_Shutdown (void); |
||||
|
void S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation); |
||||
|
void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation); |
||||
|
void S_StopSound (int entnum, int entchannel); |
||||
|
void S_StopAllSounds(qboolean clear); |
||||
|
void S_ClearBuffer (void); |
||||
|
void S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up); |
||||
|
void S_ExtraUpdate (void); |
||||
|
|
||||
|
sfx_t *S_PrecacheSound (char *sample); |
||||
|
void S_TouchSound (char *sample); |
||||
|
void S_ClearPrecache (void); |
||||
|
void S_BeginPrecaching (void); |
||||
|
void S_EndPrecaching (void); |
||||
|
void S_PaintChannels(int endtime); |
||||
|
void S_InitPaintChannels (void); |
||||
|
|
||||
|
// picks a channel based on priorities, empty slots, number of channels |
||||
|
channel_t *SND_PickChannel(int entnum, int entchannel); |
||||
|
|
||||
|
// spatializes a channel |
||||
|
void SND_Spatialize(channel_t *ch); |
||||
|
|
||||
|
// initializes cycling through a DMA buffer and returns information on it |
||||
|
qboolean SNDDMA_Init(void); |
||||
|
|
||||
|
// gets the current DMA position |
||||
|
int SNDDMA_GetDMAPos(void); |
||||
|
|
||||
|
// shutdown the DMA xfer. |
||||
|
void SNDDMA_Shutdown(void); |
||||
|
|
||||
|
// ==================================================================== |
||||
|
// User-setable variables |
||||
|
// ==================================================================== |
||||
|
|
||||
|
#define MAX_CHANNELS 128 |
||||
|
#define MAX_DYNAMIC_CHANNELS 8 |
||||
|
|
||||
|
|
||||
|
extern channel_t channels[MAX_CHANNELS]; |
||||
|
// 0 to MAX_DYNAMIC_CHANNELS-1 = normal entity sounds |
||||
|
// MAX_DYNAMIC_CHANNELS to MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS -1 = water, etc |
||||
|
// MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS to total_channels = static sounds |
||||
|
|
||||
|
extern int total_channels; |
||||
|
|
||||
|
// |
||||
|
// Fake dma is a synchronous faking of the DMA progress used for |
||||
|
// isolating performance in the renderer. The fakedma_updates is |
||||
|
// number of times S_Update() is called per second. |
||||
|
// |
||||
|
|
||||
|
extern qboolean fakedma; |
||||
|
extern int fakedma_updates; |
||||
|
extern int paintedtime; |
||||
|
extern vec3_t listener_origin; |
||||
|
extern vec3_t listener_forward; |
||||
|
extern vec3_t listener_right; |
||||
|
extern vec3_t listener_up; |
||||
|
extern volatile dma_t *shm; |
||||
|
extern volatile dma_t sn; |
||||
|
extern vec_t sound_nominal_clip_dist; |
||||
|
|
||||
|
extern cvar_t loadas8bit; |
||||
|
extern cvar_t bgmvolume; |
||||
|
extern cvar_t volume; |
||||
|
|
||||
|
extern qboolean snd_initialized; |
||||
|
|
||||
|
extern int snd_blocked; |
||||
|
|
||||
|
void S_LocalSound (char *s); |
||||
|
sfxcache_t *S_LoadSound (sfx_t *s); |
||||
|
|
||||
|
wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength); |
||||
|
|
||||
|
void SND_InitScaletable (void); |
||||
|
void SNDDMA_Submit(void); |
||||
|
|
||||
|
void S_AmbientOff (void); |
||||
|
void S_AmbientOn (void); |
||||
|
|
||||
|
#endif |
||||
@ -0,0 +1,110 @@ |
|||||
|
/* |
||||
|
Copyright (C) 1996-1997 Id Software, Inc. |
||||
|
|
||||
|
This program is free software; you can redistribute it and/or |
||||
|
modify it under the terms of the GNU General Public License |
||||
|
as published by the Free Software Foundation; either version 2 |
||||
|
of the License, or (at your option) any later version. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||||
|
|
||||
|
*/ |
||||
|
// |
||||
|
// spritegn.h: header file for sprite generation program |
||||
|
// |
||||
|
|
||||
|
// ********************************************************** |
||||
|
// * This file must be identical in the spritegen directory * |
||||
|
// * and in the Quake directory, because it's used to * |
||||
|
// * pass data from one to the other via .spr files. * |
||||
|
// ********************************************************** |
||||
|
|
||||
|
//------------------------------------------------------- |
||||
|
// This program generates .spr sprite package files. |
||||
|
// The format of the files is as follows: |
||||
|
// |
||||
|
// dsprite_t file header structure |
||||
|
// <repeat dsprite_t.numframes times> |
||||
|
// <if spritegroup, repeat dspritegroup_t.numframes times> |
||||
|
// dspriteframe_t frame header structure |
||||
|
// sprite bitmap |
||||
|
// <else (single sprite frame)> |
||||
|
// dspriteframe_t frame header structure |
||||
|
// sprite bitmap |
||||
|
// <endrepeat> |
||||
|
//------------------------------------------------------- |
||||
|
|
||||
|
#ifdef INCLUDELIBS |
||||
|
|
||||
|
#include <stdlib.h> |
||||
|
#include <stdio.h> |
||||
|
#include <math.h> |
||||
|
#include <string.h> |
||||
|
|
||||
|
#include "cmdlib.h" |
||||
|
#include "scriplib.h" |
||||
|
#include "dictlib.h" |
||||
|
#include "trilib.h" |
||||
|
#include "lbmlib.h" |
||||
|
#include "mathlib.h" |
||||
|
|
||||
|
#endif |
||||
|
|
||||
|
#define SPRITE_VERSION 1 |
||||
|
|
||||
|
// must match definition in modelgen.h |
||||
|
#ifndef SYNCTYPE_T |
||||
|
#define SYNCTYPE_T |
||||
|
typedef enum {ST_SYNC=0, ST_RAND } synctype_t; |
||||
|
#endif |
||||
|
|
||||
|
// TODO: shorten these? |
||||
|
typedef struct { |
||||
|
int ident; |
||||
|
int version; |
||||
|
int type; |
||||
|
float boundingradius; |
||||
|
int width; |
||||
|
int height; |
||||
|
int numframes; |
||||
|
float beamlength; |
||||
|
synctype_t synctype; |
||||
|
} dsprite_t; |
||||
|
|
||||
|
#define SPR_VP_PARALLEL_UPRIGHT 0 |
||||
|
#define SPR_FACING_UPRIGHT 1 |
||||
|
#define SPR_VP_PARALLEL 2 |
||||
|
#define SPR_ORIENTED 3 |
||||
|
#define SPR_VP_PARALLEL_ORIENTED 4 |
||||
|
|
||||
|
typedef struct { |
||||
|
int origin[2]; |
||||
|
int width; |
||||
|
int height; |
||||
|
} dspriteframe_t; |
||||
|
|
||||
|
typedef struct { |
||||
|
int numframes; |
||||
|
} dspritegroup_t; |
||||
|
|
||||
|
typedef struct { |
||||
|
float interval; |
||||
|
} dspriteinterval_t; |
||||
|
|
||||
|
typedef enum { SPR_SINGLE=0, SPR_GROUP } spriteframetype_t; |
||||
|
|
||||
|
typedef struct { |
||||
|
spriteframetype_t type; |
||||
|
} dspriteframetype_t; |
||||
|
|
||||
|
#define IDSPRITEHEADER (('P'<<24)+('S'<<16)+('D'<<8)+'I') |
||||
|
// little-endian "IDSP" |
||||
|
|
||||
1227
engine/code/sv_main.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
Some files were not shown because too many files changed in this diff
Write
Preview
Loading…
Cancel
Save
Reference in new issue