Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 5130 → Rev 5131

/contrib/other/sdlquake-1.0.9/3dfx.txt
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.
/contrib/other/sdlquake-1.0.9/COPYING
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
/contrib/other/sdlquake-1.0.9/Makefile.Solaris
0,0 → 1,483
#
# Quake Makefile for Solaris
#
# Nov '97 by Zoid <zoid@idsoftware.com>
#
# ELF only
#
 
VERSION=1.09
 
ifneq (,$(findstring i86pc,$(shell uname -m)))
ARCH=i386
else
ARCH=sparc
endif
 
MOUNT_DIR=/grog/Projects/WinQuake
 
BUILD_DEBUG_DIR=debug$(ARCH)
BUILD_RELEASE_DIR=release$(ARCH)
 
CC=gcc
BASE_CFLAGS=-I/usr/openwin/include
 
RELEASE_CFLAGS=$(BASE_CFLAGS) -O6 -ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations
DEBUG_CFLAGS=$(BASE_CFLAGS) -g
LDFLAGS=-R /usr/openwin/lib -L /usr/openwin/lib -lm -lX11 -lXext -lsocket -lnsl -lthread -ldl
XIL_LDFLAGS=-L /opt/SUNWits/Graphics-sw/xil/lib -R /opt/SUNWits/Graphics-sw/xil/lib:/usr/openwin/lib -L /usr/openwin/lib -lm -lxil -lX11 -lXext -lsocket -lnsl -lthread -ldl
 
DO_CC=$(CC) $(CFLAGS) -o $@ -c $<
DO_AS=$(CC) $(CFLAGS) -DELF -x assembler-with-cpp -o $@ -c $<
 
#############################################################################
# SETUP AND BUILD
#############################################################################
 
TARGETS=$(BUILDDIR)/quake.sw $(BUILDDIR)/quake.xil
 
build_debug:
@-mkdir $(BUILD_DEBUG_DIR)
$(MAKE) targets BUILDDIR=$(BUILD_DEBUG_DIR) CFLAGS="$(DEBUG_CFLAGS)"
 
build_release:
@-mkdir $(BUILD_RELEASE_DIR)
$(MAKE) targets BUILDDIR=$(BUILD_RELEASE_DIR) CFLAGS="$(RELEASE_CFLAGS)"
 
all: build_debug build_release
 
targets: $(TARGETS)
 
#############################################################################
# CLIENT/SERVER
#############################################################################
 
QUAKE_OBJS= \
$(BUILDDIR)/chase.o \
$(BUILDDIR)/cl_demo.o \
$(BUILDDIR)/cl_input.o \
$(BUILDDIR)/cl_main.o \
$(BUILDDIR)/cl_parse.o \
$(BUILDDIR)/cl_tent.o \
$(BUILDDIR)/cmd.o \
$(BUILDDIR)/common.o \
$(BUILDDIR)/console.o \
$(BUILDDIR)/crc.o \
$(BUILDDIR)/cvar.o \
$(BUILDDIR)/draw.o \
$(BUILDDIR)/d_edge.o \
$(BUILDDIR)/d_fill.o \
$(BUILDDIR)/d_init.o \
$(BUILDDIR)/d_modech.o \
$(BUILDDIR)/d_part.o \
$(BUILDDIR)/d_polyse.o \
$(BUILDDIR)/d_scan.o \
$(BUILDDIR)/d_sky.o \
$(BUILDDIR)/d_sprite.o \
$(BUILDDIR)/d_surf.o \
$(BUILDDIR)/d_vars.o \
$(BUILDDIR)/d_zpoint.o \
$(BUILDDIR)/host.o \
$(BUILDDIR)/host_cmd.o \
$(BUILDDIR)/keys.o \
$(BUILDDIR)/menu.o \
$(BUILDDIR)/mathlib.o \
$(BUILDDIR)/model.o \
$(BUILDDIR)/nonintel.o \
$(BUILDDIR)/pr_cmds.o \
$(BUILDDIR)/pr_edict.o \
$(BUILDDIR)/pr_exec.o \
$(BUILDDIR)/r_aclip.o \
$(BUILDDIR)/r_alias.o \
$(BUILDDIR)/r_bsp.o \
$(BUILDDIR)/r_light.o \
$(BUILDDIR)/r_draw.o \
$(BUILDDIR)/r_efrag.o \
$(BUILDDIR)/r_edge.o \
$(BUILDDIR)/r_misc.o \
$(BUILDDIR)/r_main.o \
$(BUILDDIR)/r_sky.o \
$(BUILDDIR)/r_sprite.o \
$(BUILDDIR)/r_surf.o \
$(BUILDDIR)/r_part.o \
$(BUILDDIR)/r_vars.o \
$(BUILDDIR)/screen.o \
$(BUILDDIR)/sbar.o \
$(BUILDDIR)/sv_main.o \
$(BUILDDIR)/sv_phys.o \
$(BUILDDIR)/sv_move.o \
$(BUILDDIR)/sv_user.o \
$(BUILDDIR)/zone.o \
$(BUILDDIR)/view.o \
$(BUILDDIR)/wad.o \
$(BUILDDIR)/world.o \
$(BUILDDIR)/cd_null.o \
$(BUILDDIR)/snd_dma.o \
$(BUILDDIR)/snd_mix.o \
$(BUILDDIR)/snd_mem.o \
$(BUILDDIR)/net_dgrm.o \
$(BUILDDIR)/net_loop.o \
$(BUILDDIR)/net_main.o \
$(BUILDDIR)/net_vcr.o \
$(BUILDDIR)/net_udp.o \
$(BUILDDIR)/net_bsd.o \
$(BUILDDIR)/sys_sun.o \
$(BUILDDIR)/snd_sun.o
 
QUAKE_AS_OBJS= \
$(BUILDDIR)/d_copy.o \
$(BUILDDIR)/d_draw.o \
$(BUILDDIR)/d_draw16.o \
$(BUILDDIR)/d_parta.o \
$(BUILDDIR)/d_polysa.o \
$(BUILDDIR)/d_scana.o \
$(BUILDDIR)/d_spr8.o \
$(BUILDDIR)/d_varsa.o \
$(BUILDDIR)/math.o \
$(BUILDDIR)/r_aliasa.o \
$(BUILDDIR)/r_drawa.o \
$(BUILDDIR)/r_edgea.o \
$(BUILDDIR)/r_varsa.o \
$(BUILDDIR)/surf16.o \
$(BUILDDIR)/surf8.o \
$(BUILDDIR)/worlda.o \
$(BUILDDIR)/r_aclipa.o \
$(BUILDDIR)/snd_mixa.o \
$(BUILDDIR)/sys_dosa.o
 
QUAKE_X_OBJS = $(BUILDDIR)/vid_sunx.o
 
QUAKE_XIL_OBJS = $(BUILDDIR)/vid_sunxil.o
 
ifeq ($(ARCH),i386)
$(BUILDDIR)/quake.sw : $(QUAKE_OBJS) $(QUAKE_AS_OBJS) $(QUAKE_X_OBJS)
$(CC) -o $(@) $(QUAKE_OBJS) $(QUAKE_AS_OBJS) $(QUAKE_X_OBJS) $(LDFLAGS)
 
$(BUILDDIR)/quake.xil: $(QUAKE_OBJS) $(QUAKE_AS_OBJS) $(QUAKE_XIL_OBJS)
$(CC) -o $(@) $(QUAKE_OBJS) $(QUAKE_AS_OBJS) $(QUAKE_XIL_OBJS) $(XIL_LDFLAGS)
else
$(BUILDDIR)/quake.sw : $(QUAKE_OBJS) $(QUAKE_X_OBJS)
$(CC) -o $(@) $(QUAKE_OBJS) $(QUAKE_X_OBJS) $(LDFLAGS)
 
$(BUILDDIR)/quake.xil: $(QUAKE_OBJS) $(QUAKE_XIL_OBJS)
$(CC) -o $(@) $(QUAKE_OBJS) $(QUAKE_XIL_OBJS) $(XIL_LDFLAGS)
endif
 
##
 
$(BUILDDIR)/chase.o : $(MOUNT_DIR)/chase.c
$(DO_CC)
 
$(BUILDDIR)/cl_demo.o : $(MOUNT_DIR)/cl_demo.c
$(DO_CC)
 
$(BUILDDIR)/cl_input.o : $(MOUNT_DIR)/cl_input.c
$(DO_CC)
 
$(BUILDDIR)/cl_main.o : $(MOUNT_DIR)/cl_main.c
$(DO_CC)
 
$(BUILDDIR)/cl_parse.o : $(MOUNT_DIR)/cl_parse.c
$(DO_CC)
 
$(BUILDDIR)/cl_tent.o : $(MOUNT_DIR)/cl_tent.c
$(DO_CC)
 
$(BUILDDIR)/cmd.o : $(MOUNT_DIR)/cmd.c
$(DO_CC)
 
$(BUILDDIR)/common.o : $(MOUNT_DIR)/common.c
$(DO_CC)
 
$(BUILDDIR)/console.o : $(MOUNT_DIR)/console.c
$(DO_CC)
 
$(BUILDDIR)/crc.o : $(MOUNT_DIR)/crc.c
$(DO_CC)
 
$(BUILDDIR)/cvar.o : $(MOUNT_DIR)/cvar.c
$(DO_CC)
 
$(BUILDDIR)/draw.o : $(MOUNT_DIR)/draw.c
$(DO_CC)
 
$(BUILDDIR)/d_edge.o : $(MOUNT_DIR)/d_edge.c
$(DO_CC)
 
$(BUILDDIR)/d_fill.o : $(MOUNT_DIR)/d_fill.c
$(DO_CC)
 
$(BUILDDIR)/d_init.o : $(MOUNT_DIR)/d_init.c
$(DO_CC)
 
$(BUILDDIR)/d_modech.o : $(MOUNT_DIR)/d_modech.c
$(DO_CC)
 
$(BUILDDIR)/d_part.o : $(MOUNT_DIR)/d_part.c
$(DO_CC)
 
$(BUILDDIR)/d_polyse.o : $(MOUNT_DIR)/d_polyse.c
$(DO_CC)
 
$(BUILDDIR)/d_scan.o : $(MOUNT_DIR)/d_scan.c
$(DO_CC)
 
$(BUILDDIR)/d_sky.o : $(MOUNT_DIR)/d_sky.c
$(DO_CC)
 
$(BUILDDIR)/d_sprite.o : $(MOUNT_DIR)/d_sprite.c
$(DO_CC)
 
$(BUILDDIR)/d_surf.o : $(MOUNT_DIR)/d_surf.c
$(DO_CC)
 
$(BUILDDIR)/d_vars.o : $(MOUNT_DIR)/d_vars.c
$(DO_CC)
 
$(BUILDDIR)/d_zpoint.o : $(MOUNT_DIR)/d_zpoint.c
$(DO_CC)
 
$(BUILDDIR)/host.o : $(MOUNT_DIR)/host.c
$(DO_CC)
 
$(BUILDDIR)/host_cmd.o : $(MOUNT_DIR)/host_cmd.c
$(DO_CC)
 
$(BUILDDIR)/keys.o : $(MOUNT_DIR)/keys.c
$(DO_CC)
 
$(BUILDDIR)/menu.o : $(MOUNT_DIR)/menu.c
$(DO_CC)
 
$(BUILDDIR)/mathlib.o : $(MOUNT_DIR)/mathlib.c
$(DO_CC)
 
$(BUILDDIR)/model.o : $(MOUNT_DIR)/model.c
$(DO_CC)
 
$(BUILDDIR)/nonintel.o : $(MOUNT_DIR)/nonintel.c
$(DO_CC)
 
$(BUILDDIR)/pr_cmds.o : $(MOUNT_DIR)/pr_cmds.c
$(DO_CC)
 
$(BUILDDIR)/pr_edict.o : $(MOUNT_DIR)/pr_edict.c
$(DO_CC)
 
$(BUILDDIR)/pr_exec.o : $(MOUNT_DIR)/pr_exec.c
$(DO_CC)
 
$(BUILDDIR)/r_aclip.o : $(MOUNT_DIR)/r_aclip.c
$(DO_CC)
 
$(BUILDDIR)/r_alias.o : $(MOUNT_DIR)/r_alias.c
$(DO_CC)
 
$(BUILDDIR)/r_bsp.o : $(MOUNT_DIR)/r_bsp.c
$(DO_CC)
 
$(BUILDDIR)/r_light.o : $(MOUNT_DIR)/r_light.c
$(DO_CC)
 
$(BUILDDIR)/r_draw.o : $(MOUNT_DIR)/r_draw.c
$(DO_CC)
 
$(BUILDDIR)/r_efrag.o : $(MOUNT_DIR)/r_efrag.c
$(DO_CC)
 
$(BUILDDIR)/r_edge.o : $(MOUNT_DIR)/r_edge.c
$(DO_CC)
 
$(BUILDDIR)/r_misc.o : $(MOUNT_DIR)/r_misc.c
$(DO_CC)
 
$(BUILDDIR)/r_main.o : $(MOUNT_DIR)/r_main.c
$(DO_CC)
 
$(BUILDDIR)/r_sky.o : $(MOUNT_DIR)/r_sky.c
$(DO_CC)
 
$(BUILDDIR)/r_sprite.o : $(MOUNT_DIR)/r_sprite.c
$(DO_CC)
 
$(BUILDDIR)/r_surf.o : $(MOUNT_DIR)/r_surf.c
$(DO_CC)
 
$(BUILDDIR)/r_part.o : $(MOUNT_DIR)/r_part.c
$(DO_CC)
 
$(BUILDDIR)/r_vars.o : $(MOUNT_DIR)/r_vars.c
$(DO_CC)
 
$(BUILDDIR)/screen.o : $(MOUNT_DIR)/screen.c
$(DO_CC)
 
$(BUILDDIR)/sbar.o : $(MOUNT_DIR)/sbar.c
$(DO_CC)
 
$(BUILDDIR)/sv_main.o : $(MOUNT_DIR)/sv_main.c
$(DO_CC)
 
$(BUILDDIR)/sv_phys.o : $(MOUNT_DIR)/sv_phys.c
$(DO_CC)
 
$(BUILDDIR)/sv_move.o : $(MOUNT_DIR)/sv_move.c
$(DO_CC)
 
$(BUILDDIR)/sv_user.o : $(MOUNT_DIR)/sv_user.c
$(DO_CC)
 
$(BUILDDIR)/zone.o : $(MOUNT_DIR)/zone.c
$(DO_CC)
 
$(BUILDDIR)/view.o : $(MOUNT_DIR)/view.c
$(DO_CC)
 
$(BUILDDIR)/wad.o : $(MOUNT_DIR)/wad.c
$(DO_CC)
 
$(BUILDDIR)/world.o : $(MOUNT_DIR)/world.c
$(DO_CC)
 
$(BUILDDIR)/cd_null.o : $(MOUNT_DIR)/cd_null.c
$(DO_CC)
 
$(BUILDDIR)/snd_dma.o : $(MOUNT_DIR)/snd_dma.c
$(DO_CC)
 
$(BUILDDIR)/snd_mix.o : $(MOUNT_DIR)/snd_mix.c
$(DO_CC)
 
$(BUILDDIR)/snd_mem.o : $(MOUNT_DIR)/snd_mem.c
$(DO_CC)
 
$(BUILDDIR)/net_dgrm.o : $(MOUNT_DIR)/net_dgrm.c
$(DO_CC)
 
$(BUILDDIR)/net_loop.o : $(MOUNT_DIR)/net_loop.c
$(DO_CC)
 
$(BUILDDIR)/net_main.o : $(MOUNT_DIR)/net_main.c
$(DO_CC)
 
$(BUILDDIR)/net_vcr.o : $(MOUNT_DIR)/net_vcr.c
$(DO_CC)
 
$(BUILDDIR)/net_udp.o : $(MOUNT_DIR)/net_udp.c
$(DO_CC)
 
$(BUILDDIR)/net_bsd.o : $(MOUNT_DIR)/net_bsd.c
$(DO_CC)
 
$(BUILDDIR)/sys_sun.o : $(MOUNT_DIR)/sys_sun.c
$(DO_CC)
 
$(BUILDDIR)/snd_sun.o : $(MOUNT_DIR)/snd_sun.c
$(DO_CC)
 
$(BUILDDIR)/in_sun.o : $(MOUNT_DIR)/in_sun.c
$(DO_CC)
 
$(BUILDDIR)/vid_sunx.o : $(MOUNT_DIR)/vid_sunx.c
$(DO_CC)
 
$(BUILDDIR)/vid_sunxil.o : $(MOUNT_DIR)/vid_sunxil.c
$(DO_CC)
 
#####
 
$(BUILDDIR)/d_copy.o : $(MOUNT_DIR)/d_copy.s
$(DO_AS)
 
$(BUILDDIR)/d_draw.o : $(MOUNT_DIR)/d_draw.s
$(DO_AS)
 
$(BUILDDIR)/d_draw16.o : $(MOUNT_DIR)/d_draw16.s
$(DO_AS)
 
$(BUILDDIR)/d_parta.o : $(MOUNT_DIR)/d_parta.s
$(DO_AS)
 
$(BUILDDIR)/d_polysa.o : $(MOUNT_DIR)/d_polysa.s
$(DO_AS)
 
$(BUILDDIR)/d_scana.o : $(MOUNT_DIR)/d_scana.s
$(DO_AS)
 
$(BUILDDIR)/d_spr8.o : $(MOUNT_DIR)/d_spr8.s
$(DO_AS)
 
$(BUILDDIR)/d_varsa.o : $(MOUNT_DIR)/d_varsa.s
$(DO_AS)
 
$(BUILDDIR)/math.o : $(MOUNT_DIR)/math.s
$(DO_AS)
 
$(BUILDDIR)/r_aliasa.o : $(MOUNT_DIR)/r_aliasa.s
$(DO_AS)
 
$(BUILDDIR)/r_drawa.o : $(MOUNT_DIR)/r_drawa.s
$(DO_AS)
 
$(BUILDDIR)/r_edgea.o : $(MOUNT_DIR)/r_edgea.s
$(DO_AS)
 
$(BUILDDIR)/r_varsa.o : $(MOUNT_DIR)/r_varsa.s
$(DO_AS)
 
$(BUILDDIR)/surf16.o : $(MOUNT_DIR)/surf16.s
$(DO_AS)
 
$(BUILDDIR)/surf8.o : $(MOUNT_DIR)/surf8.s
$(DO_AS)
 
$(BUILDDIR)/worlda.o : $(MOUNT_DIR)/worlda.s
$(DO_AS)
 
$(BUILDDIR)/r_aclipa.o : $(MOUNT_DIR)/r_aclipa.s
$(DO_AS)
 
$(BUILDDIR)/snd_mixa.o : $(MOUNT_DIR)/snd_mixa.s
$(DO_AS)
 
$(BUILDDIR)/sys_dosa.o : $(MOUNT_DIR)/sys_dosa.s
$(DO_AS)
 
#############################################################################
# TAR
#############################################################################
 
# Make RPMs. You need to be root to make this work
RPMDIR = /var/tmp/quake-$(VERSION)
 
tar:
if [ ! -d archives ];then mkdir archives;fi
$(MAKE) copyfiles COPYDIR=$(RPMDIR)
cd $(RPMDIR); tar cvf q2ded-$(VERSION)-$(ARCH)-sun-solaris2.5.1.tar *
cd $(RPMDIR); compress q2ded-$(VERSION)-$(ARCH)-sun-solaris2.5.1.tar
mv $(RPMDIR)/*.tar.Z archives/.
rm -rf $(RPMDIR)
 
copyfiles:
-mkdirhier $(COPYDIR)
cp $(BUILD_RELEASE_DIR)/quake.sw $(COPYDIR)
cp $(BUILD_RELEASE_DIR)/quake.xil $(COPYDIR)
strip $(COPYDIR)/quake
strip $(COPYDIR)/quake.xil
cp $(MOUNT_DIR)/README.Solaris $(COPYDIR)/README.Solaris
 
#############################################################################
# MISC
#############################################################################
 
clean: clean-debug clean-release
 
clean-debug:
$(MAKE) clean2 BUILDDIR=$(BUILD_DEBUG_DIR) CFLAGS="$(DEBUG_CFLAGS)"
 
clean-release:
$(MAKE) clean2 BUILDDIR=$(BUILD_RELEASE_DIR) CFLAGS="$(DEBUG_CFLAGS)"
 
clean2:
-rm -f $(QUAKE_OBJS) $(QUAKE_X_OBJS) $(QUAKE_XIL_OBJS)
 
/contrib/other/sdlquake-1.0.9/Makefile.am
0,0 → 1,292
 
bin_PROGRAMS = sdlquake
 
sdlquake_LDADD = @MATHLIB@ @INETLIB@
 
sdlquake_SOURCES = \
adivtab.h \
anorm_dots.h \
anorms.h \
asm_draw.h \
asm_i386.h \
block16.h \
block8.h \
bspfile.h \
cd_sdl.c \
cdaudio.h \
chase.c \
cl_demo.c \
cl_input.c \
cl_main.c \
cl_parse.c \
cl_tent.c \
clean.bat \
client.h \
cmd.c \
cmd.h \
common.c \
common.h \
conproc.h \
console.c \
console.h \
crc.c \
crc.h \
cvar.c \
cvar.h \
d_copy.S \
d_edge.c \
d_fill.c \
d_iface.h \
d_ifacea.h \
d_init.c \
d_local.h \
d_modech.c \
d_part.c \
d_polyse.c \
d_scan.c \
d_sky.c \
d_sprite.c \
d_surf.c \
d_zpoint.c \
dosasm.S \
dosisms.h \
draw.c \
draw.h \
host.c \
host_cmd.c \
input.h \
keys.c \
keys.h \
mathlib.c \
mathlib.h \
menu.c \
menu.h \
model.c \
model.h \
modelgen.h \
mpdosock.h \
net.h \
net_bsd.c \
net_bw.h \
net_dgrm.c \
net_dgrm.h \
net_loop.c \
net_loop.h \
net_main.c \
net_udp.c \
net_udp.h \
net_vcr.c \
net_vcr.h \
net_wso.c \
pr_cmds.c \
pr_comp.h \
pr_edict.c \
pr_exec.c \
progdefs.h \
progs.h \
protocol.h \
quakeasm.h \
quakedef.h \
r_aclip.c \
r_alias.c \
r_bsp.c \
r_draw.c \
r_edge.c \
r_efrag.c \
r_light.c \
r_local.h \
r_main.c \
r_misc.c \
r_part.c \
r_shared.h \
r_sky.c \
r_sprite.c \
r_surf.c \
r_vars.c \
r_varsa.S \
render.h \
resource.h \
sbar.c \
sbar.h \
scitech \
screen.c \
screen.h \
server.h \
snd_dma.c \
snd_mem.c \
snd_mix.c \
snd_sdl.c \
sound.h \
spritegn.h \
sv_main.c \
sv_move.c \
sv_phys.c \
sv_user.c \
sys.h \
sys_sdl.c \
vgamodes.h \
vid.h \
vid_sdl.c \
view.c \
view.h \
wad.c \
wad.h \
winquake.h \
world.c \
world.h \
zone.c \
zone.h \
$(X86_SRCS) $(NONX86_SRCS)
 
X86_SRCS = \
snd_mixa.S \
sys_dosa.S \
d_draw.S \
d_draw16.S \
d_parta.S \
d_polysa.S \
d_scana.S \
d_spr8.S \
d_varsa.S \
math.S \
r_aclipa.S \
r_aliasa.S \
r_drawa.S \
r_edgea.S \
surf16.S \
surf8.S \
worlda.S
 
NONX86_SRCS = \
d_vars.c \
nonintel.c
 
 
NULL_SRCS = \
cd_null.c \
in_null.c \
net_none.c \
snd_null.c \
sys_null.c \
vid_null.c
 
DOS_SRCS = \
cd_audio.c \
dos_v2.c \
in_dos.c \
mplib.c \
mplpc.c \
net_bw.c \
net_comx.c \
net_dos.c \
net_ipx.c \
net_ipx.h \
net_ser.c \
net_ser.h \
snd_dos.c \
snd_gus.c \
sys_dos.c \
vid_dos.c \
vid_dos.h \
vid_ext.c \
vid_vga.c \
vregset.c \
vregset.h
 
WIN_SRCS = \
cd_win.c \
conproc.c \
in_win.c \
net_mp.c \
net_mp.h \
net_win.c \
net_wins.c \
net_wins.h \
net_wipx.c \
net_wipx.h \
snd_win.c \
sys_win.c \
sys_wina.S \
sys_wind.c \
vid_win.c
 
LNX_SRCS = \
cd_linux.c \
snd_linux.c \
sys_linux.c \
vid_svgalib.c \
vid_x.c
 
SUN_SRCS = \
snd_sun.c \
in_sun.c \
sys_sun.c \
vid_sunx.c \
vid_sunxil.c
 
NEXT_SRCS = \
snd_next.c
 
GL_SRCS = \
gl_draw.c \
gl_mesh.c \
gl_model.c \
gl_model.h \
gl_refrag.c \
gl_rlight.c \
gl_rmain.c \
gl_rmisc.c \
gl_rsurf.c \
gl_screen.c \
gl_test.c \
gl_vidlinux.c \
gl_vidlinuxglx.c \
gl_vidnt.c \
gl_warp.c \
gl_warp_sin.h \
glquake.h \
glquake2.h
 
EXTRA_DIST = \
README.SDL \
3dfx.txt \
Makefile.Solaris \
Makefile.linuxi386 \
README.Solaris \
WinQuake.dsp \
WinQuake.dsw \
WinQuake.mdp \
WinQuake.ncb \
WinQuake.opt \
WinQuake.plg \
cwsdpmi.exe \
glqnotes.txt \
makezip.bat \
progdefs.q1 \
progdefs.q2 \
q.bat \
qa.bat \
qb.bat \
qe3.ico \
qt.bat \
quake-data.spec.sh \
quake-hipnotic.spec.sh \
quake-rogue.spec.sh \
quake-shareware.spec.sh \
quake.gif \
quake.ico \
quake.spec.sh \
winquake.aps \
winquake.rc \
wq.bat \
wqreadme.txt \
$(NULL_SRCS) \
$(DOS_SRCS) \
$(WIN_SRCS) \
$(LNX_SRCS) \
$(SUN_SRCS) \
$(NEXT_SRCS) \
$(GL_SRCS)
 
dist-hook:
cp -rp data docs dxsdk gas2masm kit scitech $(distdir)/
/contrib/other/sdlquake-1.0.9/Makefile.in
0,0 → 1,765
# Makefile.in generated automatically by automake 1.4 from Makefile.am
 
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
 
 
SHELL = @SHELL@
 
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
 
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
 
DESTDIR =
 
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
 
top_builddir = .
 
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
 
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
 
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_alias = @host_alias@
host_triplet = @host@
CC = @CC@
ICONOBJ = @ICONOBJ@
INETLIB = @INETLIB@
MAKEINFO = @MAKEINFO@
MATHLIB = @MATHLIB@
PACKAGE = @PACKAGE@
SDL_CFLAGS = @SDL_CFLAGS@
SDL_CONFIG = @SDL_CONFIG@
SDL_LIBS = @SDL_LIBS@
VERSION = @VERSION@
 
bin_PROGRAMS = sdlquake
 
sdlquake_LDADD = @MATHLIB@ @INETLIB@
 
sdlquake_SOURCES = adivtab.h anorm_dots.h anorms.h asm_draw.h asm_i386.h block16.h block8.h bspfile.h cd_sdl.c cdaudio.h chase.c cl_demo.c cl_input.c cl_main.c cl_parse.c cl_tent.c clean.bat client.h cmd.c cmd.h common.c common.h conproc.h console.c console.h crc.c crc.h cvar.c cvar.h d_copy.S d_edge.c d_fill.c d_iface.h d_ifacea.h d_init.c d_local.h d_modech.c d_part.c d_polyse.c d_scan.c d_sky.c d_sprite.c d_surf.c d_zpoint.c dosasm.S dosisms.h draw.c draw.h host.c host_cmd.c input.h keys.c keys.h mathlib.c mathlib.h menu.c menu.h model.c model.h modelgen.h mpdosock.h net.h net_bsd.c net_bw.h net_dgrm.c net_dgrm.h net_loop.c net_loop.h net_main.c net_udp.c net_udp.h net_vcr.c net_vcr.h net_wso.c pr_cmds.c pr_comp.h pr_edict.c pr_exec.c progdefs.h progs.h protocol.h quakeasm.h quakedef.h r_aclip.c r_alias.c r_bsp.c r_draw.c r_edge.c r_efrag.c r_light.c r_local.h r_main.c r_misc.c r_part.c r_shared.h r_sky.c r_sprite.c r_surf.c r_vars.c r_varsa.S render.h resource.h sbar.c sbar.h scitech screen.c screen.h server.h snd_dma.c snd_mem.c snd_mix.c snd_sdl.c sound.h spritegn.h sv_main.c sv_move.c sv_phys.c sv_user.c sys.h sys_sdl.c vgamodes.h vid.h vid_sdl.c view.c view.h wad.c wad.h winquake.h world.c world.h zone.c zone.h $(X86_SRCS) $(NONX86_SRCS)
 
 
X86_SRCS = snd_mixa.S sys_dosa.S d_draw.S d_draw16.S d_parta.S d_polysa.S d_scana.S d_spr8.S d_varsa.S math.S r_aclipa.S r_aliasa.S r_drawa.S r_edgea.S surf16.S surf8.S worlda.S
 
 
NONX86_SRCS = d_vars.c nonintel.c
 
 
NULL_SRCS = cd_null.c in_null.c net_none.c snd_null.c sys_null.c vid_null.c
 
 
DOS_SRCS = cd_audio.c dos_v2.c in_dos.c mplib.c mplpc.c net_bw.c net_comx.c net_dos.c net_ipx.c net_ipx.h net_ser.c net_ser.h snd_dos.c snd_gus.c sys_dos.c vid_dos.c vid_dos.h vid_ext.c vid_vga.c vregset.c vregset.h
 
 
WIN_SRCS = cd_win.c conproc.c in_win.c net_mp.c net_mp.h net_win.c net_wins.c net_wins.h net_wipx.c net_wipx.h snd_win.c sys_win.c sys_wina.S sys_wind.c vid_win.c
 
 
LNX_SRCS = cd_linux.c snd_linux.c sys_linux.c vid_svgalib.c vid_x.c
 
 
SUN_SRCS = snd_sun.c in_sun.c sys_sun.c vid_sunx.c vid_sunxil.c
 
 
NEXT_SRCS = snd_next.c
 
 
GL_SRCS = gl_draw.c gl_mesh.c gl_model.c gl_model.h gl_refrag.c gl_rlight.c gl_rmain.c gl_rmisc.c gl_rsurf.c gl_screen.c gl_test.c gl_vidlinux.c gl_vidlinuxglx.c gl_vidnt.c gl_warp.c gl_warp_sin.h glquake.h glquake2.h
 
 
EXTRA_DIST = README.SDL 3dfx.txt Makefile.Solaris Makefile.linuxi386 README.Solaris WinQuake.dsp WinQuake.dsw WinQuake.mdp WinQuake.ncb WinQuake.opt WinQuake.plg cwsdpmi.exe glqnotes.txt makezip.bat progdefs.q1 progdefs.q2 q.bat qa.bat qb.bat qe3.ico qt.bat quake-data.spec.sh quake-hipnotic.spec.sh quake-rogue.spec.sh quake-shareware.spec.sh quake.gif quake.ico quake.spec.sh winquake.aps winquake.rc wq.bat wqreadme.txt $(NULL_SRCS) $(DOS_SRCS) $(WIN_SRCS) $(LNX_SRCS) $(SUN_SRCS) $(NEXT_SRCS) $(GL_SRCS)
 
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_CLEAN_FILES =
PROGRAMS = $(bin_PROGRAMS)
 
 
DEFS = @DEFS@ -I. -I$(srcdir)
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
sdlquake_OBJECTS = cd_sdl.o chase.o cl_demo.o cl_input.o cl_main.o \
cl_parse.o cl_tent.o cmd.o common.o console.o crc.o cvar.o d_copy.o \
d_edge.o d_fill.o d_init.o d_modech.o d_part.o d_polyse.o d_scan.o \
d_sky.o d_sprite.o d_surf.o d_zpoint.o dosasm.o draw.o host.o \
host_cmd.o keys.o mathlib.o menu.o model.o net_bsd.o net_dgrm.o \
net_loop.o net_main.o net_udp.o net_vcr.o net_wso.o pr_cmds.o \
pr_edict.o pr_exec.o r_aclip.o r_alias.o r_bsp.o r_draw.o r_edge.o \
r_efrag.o r_light.o r_main.o r_misc.o r_part.o r_sky.o r_sprite.o \
r_surf.o r_vars.o r_varsa.o sbar.o screen.o snd_dma.o snd_mem.o \
snd_mix.o snd_sdl.o sv_main.o sv_move.o sv_phys.o sv_user.o sys_sdl.o \
vid_sdl.o view.o wad.o world.o zone.o snd_mixa.o sys_dosa.o d_draw.o \
d_draw16.o d_parta.o d_polysa.o d_scana.o d_spr8.o d_varsa.o math.o \
r_aclipa.o r_aliasa.o r_drawa.o r_edgea.o surf16.o surf8.o worlda.o \
d_vars.o nonintel.o
sdlquake_DEPENDENCIES =
sdlquake_LDFLAGS =
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
DIST_COMMON = COPYING Makefile.am Makefile.in acinclude.m4 aclocal.m4 \
config.guess config.sub configure configure.in install-sh missing \
mkinstalldirs
 
 
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
 
TAR = gtar
GZIP_ENV = --best
SOURCES = $(sdlquake_SOURCES)
OBJECTS = $(sdlquake_OBJECTS)
 
all: all-redirect
.SUFFIXES:
.SUFFIXES: .S .c .o .s
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --foreign --include-deps Makefile
 
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
 
$(ACLOCAL_M4): configure.in acinclude.m4
cd $(srcdir) && $(ACLOCAL)
 
config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
cd $(srcdir) && $(AUTOCONF)
 
mostlyclean-binPROGRAMS:
 
clean-binPROGRAMS:
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
 
distclean-binPROGRAMS:
 
maintainer-clean-binPROGRAMS:
 
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(bindir)
@list='$(bin_PROGRAMS)'; for p in $$list; do \
if test -f $$p; then \
echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
$(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
else :; fi; \
done
 
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
list='$(bin_PROGRAMS)'; for p in $$list; do \
rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
done
 
.c.o:
$(COMPILE) -c $<
 
.s.o:
$(COMPILE) -c $<
 
.S.o:
$(COMPILE) -c $<
 
mostlyclean-compile:
-rm -f *.o core *.core
 
clean-compile:
 
distclean-compile:
-rm -f *.tab.c
 
maintainer-clean-compile:
 
sdlquake: $(sdlquake_OBJECTS) $(sdlquake_DEPENDENCIES)
@rm -f sdlquake
$(LINK) $(sdlquake_LDFLAGS) $(sdlquake_OBJECTS) $(sdlquake_LDADD) $(LIBS)
 
tags: TAGS
 
ID: $(HEADERS) $(SOURCES) $(LISP)
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
here=`pwd` && cd $(srcdir) \
&& mkid -f$$here/ID $$unique $(LISP)
 
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
 
mostlyclean-tags:
 
clean-tags:
 
distclean-tags:
-rm -f TAGS ID
 
maintainer-clean-tags:
 
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
 
# This target untars the dist file and tries a VPATH configuration. Then
# it guarantees that the distribution is self-contained by making another
# tarfile.
distcheck: dist
-rm -rf $(distdir)
GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz
mkdir $(distdir)/=build
mkdir $(distdir)/=inst
dc_install_base=`cd $(distdir)/=inst && pwd`; \
cd $(distdir)/=build \
&& ../configure --srcdir=.. --prefix=$$dc_install_base \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
&& $(MAKE) $(AM_MAKEFLAGS) dist
-rm -rf $(distdir)
@banner="$(distdir).tar.gz is ready for distribution"; \
dashes=`echo "$$banner" | sed s/./=/g`; \
echo "$$dashes"; \
echo "$$banner"; \
echo "$$dashes"
dist: distdir
-chmod -R a+r $(distdir)
GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
-rm -rf $(distdir)
dist-all: distdir
-chmod -R a+r $(distdir)
GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
-rm -rf $(distdir)
distdir: $(DISTFILES)
-rm -rf $(distdir)
mkdir $(distdir)
-chmod 777 $(distdir)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
$(MAKE) $(AM_MAKEFLAGS) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-hook
cd_sdl.o: cd_sdl.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
chase.o: chase.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
cl_demo.o: cl_demo.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
cl_input.o: cl_input.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
cl_main.o: cl_main.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
cl_parse.o: cl_parse.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
cl_tent.o: cl_tent.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
cmd.o: cmd.c quakedef.h common.h bspfile.h vid.h sys.h zone.h mathlib.h \
wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h sbar.h \
sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
common.o: common.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
console.o: console.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
crc.o: crc.c quakedef.h common.h bspfile.h vid.h sys.h zone.h mathlib.h \
wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h sbar.h \
sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
cvar.o: cvar.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
d_edge.o: d_edge.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
d_local.h r_shared.h
d_fill.o: d_fill.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
d_init.o: d_init.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
d_local.h r_shared.h
d_modech.o: d_modech.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
d_local.h r_shared.h
d_part.o: d_part.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
d_local.h r_shared.h
d_polyse.o: d_polyse.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
r_local.h r_shared.h d_local.h adivtab.h
draw.o: draw.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
d_scan.o: d_scan.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
r_local.h r_shared.h d_local.h
d_sky.o: d_sky.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
r_local.h r_shared.h d_local.h
d_sprite.o: d_sprite.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
d_local.h r_shared.h
d_surf.o: d_surf.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
d_local.h r_shared.h r_local.h
d_vars.o: d_vars.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
d_zpoint.o: d_zpoint.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
d_local.h r_shared.h
host_cmd.o: host_cmd.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
host.o: host.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
r_local.h r_shared.h
keys.o: keys.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
mathlib.o: mathlib.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
menu.o: menu.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
model.o: model.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
r_local.h r_shared.h
net_bsd.o: net_bsd.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
net_loop.h net_dgrm.h net_udp.h
net_dgrm.o: net_dgrm.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
net_dgrm.h
net_loop.o: net_loop.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
net_loop.h
net_main.o: net_main.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
net_vcr.h
net_udp.o: net_udp.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
net_udp.h
net_vcr.o: net_vcr.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
net_vcr.h
net_wso.o: net_wso.c
nonintel.o: nonintel.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
r_local.h r_shared.h d_local.h
pr_cmds.o: pr_cmds.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
pr_edict.o: pr_edict.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
pr_exec.o: pr_exec.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
r_aclip.o: r_aclip.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
r_local.h r_shared.h d_local.h
r_alias.o: r_alias.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
r_local.h r_shared.h d_local.h anorms.h
r_bsp.o: r_bsp.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
r_local.h r_shared.h
r_draw.o: r_draw.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
r_local.h r_shared.h d_local.h
r_edge.o: r_edge.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
r_local.h r_shared.h
r_efrag.o: r_efrag.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
r_local.h r_shared.h
r_light.o: r_light.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
r_local.h r_shared.h
r_main.o: r_main.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
r_local.h r_shared.h
r_misc.o: r_misc.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
r_local.h r_shared.h
r_part.o: r_part.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
r_local.h r_shared.h
r_sky.o: r_sky.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
r_local.h r_shared.h d_local.h
r_sprite.o: r_sprite.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
r_local.h r_shared.h
r_surf.o: r_surf.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
r_local.h r_shared.h
r_vars.o: r_vars.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
sbar.o: sbar.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
screen.o: screen.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
r_local.h r_shared.h
snd_dma.o: snd_dma.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
snd_mem.o: snd_mem.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
snd_mix.o: snd_mix.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
snd_sdl.o: snd_sdl.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
sv_main.o: sv_main.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
sv_move.o: sv_move.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
sv_phys.o: sv_phys.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
sv_user.o: sv_user.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
sys_sdl.o: sys_sdl.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
vid_sdl.o: vid_sdl.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
d_local.h r_shared.h
view.o: view.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h \
r_local.h r_shared.h
wad.o: wad.c quakedef.h common.h bspfile.h vid.h sys.h zone.h mathlib.h \
wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h sbar.h \
sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
world.o: world.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
zone.o: zone.c quakedef.h common.h bspfile.h vid.h sys.h zone.h \
mathlib.h wad.h draw.h cvar.h screen.h net.h protocol.h cmd.h \
sbar.h sound.h render.h client.h progs.h pr_comp.h progdefs.h \
progdefs.q1 server.h model.h modelgen.h spritegn.h d_iface.h \
input.h world.h keys.h console.h view.h menu.h crc.h cdaudio.h
 
info-am:
info: info-am
dvi-am:
dvi: dvi-am
check-am: all-am
check: check-am
installcheck-am:
installcheck: installcheck-am
install-exec-am: install-binPROGRAMS
install-exec: install-exec-am
 
install-data-am:
install-data: install-data-am
 
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-am
uninstall-am: uninstall-binPROGRAMS
uninstall: uninstall-am
all-am: Makefile $(PROGRAMS)
all-redirect: all-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
installdirs:
$(mkinstalldirs) $(DESTDIR)$(bindir)
 
 
mostlyclean-generic:
 
clean-generic:
 
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
 
maintainer-clean-generic:
mostlyclean-am: mostlyclean-binPROGRAMS mostlyclean-compile \
mostlyclean-tags mostlyclean-generic
 
mostlyclean: mostlyclean-am
 
clean-am: clean-binPROGRAMS clean-compile clean-tags clean-generic \
mostlyclean-am
 
clean: clean-am
 
distclean-am: distclean-binPROGRAMS distclean-compile distclean-tags \
distclean-generic clean-am
 
distclean: distclean-am
-rm -f config.status
 
maintainer-clean-am: maintainer-clean-binPROGRAMS \
maintainer-clean-compile maintainer-clean-tags \
maintainer-clean-generic distclean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
 
maintainer-clean: maintainer-clean-am
-rm -f config.status
 
.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
mostlyclean-compile distclean-compile clean-compile \
maintainer-clean-compile tags mostlyclean-tags distclean-tags \
clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
check-am installcheck-am installcheck install-exec-am install-exec \
install-data-am install-data install-am install uninstall-am uninstall \
all-redirect all-am all installdirs mostlyclean-generic \
distclean-generic clean-generic maintainer-clean-generic clean \
mostlyclean distclean maintainer-clean
 
 
dist-hook:
cp -rp data docs dxsdk gas2masm kit scitech $(distdir)/
 
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
/contrib/other/sdlquake-1.0.9/Makefile.linuxi386
0,0 → 1,1242
#
# Quake Makefile for Linux 2.0
#
# Aug '98 by Zoid <zoid@idsoftware.com>
#
# ELF only
#
 
BASEVERSION=1.09
VERSION=$(BASEVERSION)$(GLIBC)
 
# RPM release number
RPM_RELEASE=5
 
ifneq (,$(findstring libc6,$(shell if [ -e /lib/libc.so.6 ];then echo libc6;fi)))
GLIBC=-glibc
else
GLIBC=
endif
 
ifneq (,$(findstring alpha,$(shell uname -m)))
ARCH=axp
else
ARCH=i386
endif
NOARCH=noarch
 
#MOUNT_DIR=/grog/Projects/WinQuake
MOUNT_DIR := $(shell pwd)
MASTER_DIR=/grog/Projects/QuakeMaster
MESA_DIR=/usr/local/src/Mesa-2.6
TDFXGL_DIR = /home/zoid/3dfxgl
 
BUILD_DEBUG_DIR=debug$(ARCH)$(GLIBC)
BUILD_RELEASE_DIR=release$(ARCH)$(GLIBC)
 
#EGCS=/usr/local/egcs-1.1.2/bin/gcc
#CC=$(EGCS)
 
BASE_CFLAGS=-Dstricmp=strcasecmp
RELEASE_CFLAGS=$(BASE_CFLAGS) -g -mpentiumpro -O6 -ffast-math -funroll-loops \
-fomit-frame-pointer -fexpensive-optimizations
DEBUG_CFLAGS=$(BASE_CFLAGS) -g
LDFLAGS=-lm
SVGALDFLAGS=-lvga
XLDFLAGS=-L/usr/X11R6/lib -lX11 -lXext -lXxf86dga
XCFLAGS=-DX11
 
MESAGLLDFLAGS=-L/usr/X11/lib -L/usr/local/lib -L$(MESA_DIR)/lib -lMesaGL -lglide2x -lX11 -lXext -ldl
TDFXGLLDFLAGS=-L$(TDFXGL_DIR)/release$(ARCH)$(GLIBC) -l3dfxgl -lglide2x -ldl
GLLDFLAGS=-L/usr/X11/lib -L/usr/local/lib -lGL -lX11 -lXext -ldl -lXxf86dga -lXxf86vm -lm
GLCFLAGS=-DGLQUAKE -I$(MESA_DIR)/include -I/usr/include/glide
 
DO_CC=$(CC) $(CFLAGS) -o $@ -c $<
DO_DEBUG_CC=$(CC) $(DEBUG_CFLAGS) -o $@ -c $<
DO_GL_CC=$(CC) $(CFLAGS) $(GLCFLAGS) -o $@ -c $<
DO_GL_DEBUG_CC=$(CC) $(DEBUG_CFLAGS) $(GLCFLAGS) -o $@ -c $<
DO_X11_CC=$(CC) $(CFLAGS) $(XCFLAGS) -o $@ -c $<
DO_X11_DEBUG_CC=$(CC) $(DEBUG_CFLAGS) $(XCFLAGS) -o $@ -c $<
DO_O_CC=$(CC) -O $(CFLAGS) -o $@ -c $<
#DO_AS=$(CC) $(CFLAGS) -DELF -x assembler-with-cpp -o $@ -c $<
DO_AS=$(CC) $(CFLAGS) -DELF -o $@ -c $<
DO_GL_AS=$(CC) $(CFLAGS) $(GLCFLAGS) -DELF -x assembler-with-cpp -o $@ -c $<
 
#############################################################################
# SETUP AND BUILD
#############################################################################
 
TARGETS=$(BUILDDIR)/bin/quake.x11\
$(BUILDDIR)/bin/squake \
$(BUILDDIR)/bin/glquake \
$(BUILDDIR)/bin/glquake.glx \
$(BUILDDIR)/bin/glquake.3dfxgl \
# $(BUILDDIR)/bin/unixded
 
build_debug:
@-mkdir $(BUILD_DEBUG_DIR) \
$(BUILD_DEBUG_DIR)/bin \
$(BUILD_DEBUG_DIR)/glquake \
$(BUILD_DEBUG_DIR)/squake \
$(BUILD_DEBUG_DIR)/unixded \
$(BUILD_DEBUG_DIR)/x11
$(MAKE) targets BUILDDIR=$(BUILD_DEBUG_DIR) CFLAGS="$(DEBUG_CFLAGS)"
 
build_release:
@-mkdir $(BUILD_RELEASE_DIR) \
$(BUILD_RELEASE_DIR)/bin \
$(BUILD_RELEASE_DIR)/glquake \
$(BUILD_RELEASE_DIR)/squake \
$(BUILD_RELEASE_DIR)/unixded \
$(BUILD_RELEASE_DIR)/x11
$(MAKE) targets BUILDDIR=$(BUILD_RELEASE_DIR) CFLAGS="$(RELEASE_CFLAGS)"
 
all: build_debug build_release
 
targets: $(TARGETS)
 
#############################################################################
# SVGALIB Quake
#############################################################################
 
SQUAKE_OBJS = \
$(BUILDDIR)/squake/cl_demo.o \
$(BUILDDIR)/squake/cl_input.o \
$(BUILDDIR)/squake/cl_main.o \
$(BUILDDIR)/squake/cl_parse.o \
$(BUILDDIR)/squake/cl_tent.o \
$(BUILDDIR)/squake/chase.o \
$(BUILDDIR)/squake/cmd.o \
$(BUILDDIR)/squake/common.o \
$(BUILDDIR)/squake/console.o \
$(BUILDDIR)/squake/crc.o \
$(BUILDDIR)/squake/cvar.o \
$(BUILDDIR)/squake/draw.o \
$(BUILDDIR)/squake/d_edge.o \
$(BUILDDIR)/squake/d_fill.o \
$(BUILDDIR)/squake/d_init.o \
$(BUILDDIR)/squake/d_modech.o \
$(BUILDDIR)/squake/d_part.o \
$(BUILDDIR)/squake/d_polyse.o \
$(BUILDDIR)/squake/d_scan.o \
$(BUILDDIR)/squake/d_sky.o \
$(BUILDDIR)/squake/d_sprite.o \
$(BUILDDIR)/squake/d_surf.o \
$(BUILDDIR)/squake/d_vars.o \
$(BUILDDIR)/squake/d_zpoint.o \
$(BUILDDIR)/squake/host.o \
$(BUILDDIR)/squake/host_cmd.o \
$(BUILDDIR)/squake/keys.o \
$(BUILDDIR)/squake/menu.o \
$(BUILDDIR)/squake/mathlib.o \
$(BUILDDIR)/squake/model.o \
$(BUILDDIR)/squake/net_dgrm.o \
$(BUILDDIR)/squake/net_loop.o \
$(BUILDDIR)/squake/net_main.o \
$(BUILDDIR)/squake/net_vcr.o \
$(BUILDDIR)/squake/net_udp.o \
$(BUILDDIR)/squake/net_bsd.o \
$(BUILDDIR)/squake/nonintel.o \
$(BUILDDIR)/squake/pr_cmds.o \
$(BUILDDIR)/squake/pr_edict.o \
$(BUILDDIR)/squake/pr_exec.o \
$(BUILDDIR)/squake/r_aclip.o \
$(BUILDDIR)/squake/r_alias.o \
$(BUILDDIR)/squake/r_bsp.o \
$(BUILDDIR)/squake/r_light.o \
$(BUILDDIR)/squake/r_draw.o \
$(BUILDDIR)/squake/r_efrag.o \
$(BUILDDIR)/squake/r_edge.o \
$(BUILDDIR)/squake/r_misc.o \
$(BUILDDIR)/squake/r_main.o \
$(BUILDDIR)/squake/r_sky.o \
$(BUILDDIR)/squake/r_sprite.o \
$(BUILDDIR)/squake/r_surf.o \
$(BUILDDIR)/squake/r_part.o \
$(BUILDDIR)/squake/r_vars.o \
$(BUILDDIR)/squake/screen.o \
$(BUILDDIR)/squake/sbar.o \
$(BUILDDIR)/squake/sv_main.o \
$(BUILDDIR)/squake/sv_phys.o \
$(BUILDDIR)/squake/sv_move.o \
$(BUILDDIR)/squake/sv_user.o \
$(BUILDDIR)/squake/zone.o \
$(BUILDDIR)/squake/view.o \
$(BUILDDIR)/squake/wad.o \
$(BUILDDIR)/squake/world.o \
$(BUILDDIR)/squake/cd_linux.o \
$(BUILDDIR)/squake/sys_linux.o \
$(BUILDDIR)/squake/vid_svgalib.o \
$(BUILDDIR)/squake/snd_dma.o \
$(BUILDDIR)/squake/snd_mem.o \
$(BUILDDIR)/squake/snd_mix.o \
$(BUILDDIR)/squake/snd_linux.o \
\
$(BUILDDIR)/squake/d_copy.o \
$(BUILDDIR)/squake/d_draw.o \
$(BUILDDIR)/squake/d_draw16.o \
$(BUILDDIR)/squake/d_parta.o \
$(BUILDDIR)/squake/d_polysa.o \
$(BUILDDIR)/squake/d_scana.o \
$(BUILDDIR)/squake/d_spr8.o \
$(BUILDDIR)/squake/d_varsa.o \
$(BUILDDIR)/squake/math.o \
$(BUILDDIR)/squake/r_aliasa.o \
$(BUILDDIR)/squake/r_drawa.o \
$(BUILDDIR)/squake/r_edgea.o \
$(BUILDDIR)/squake/r_varsa.o \
$(BUILDDIR)/squake/surf16.o \
$(BUILDDIR)/squake/surf8.o \
$(BUILDDIR)/squake/worlda.o \
$(BUILDDIR)/squake/r_aclipa.o \
$(BUILDDIR)/squake/snd_mixa.o \
$(BUILDDIR)/squake/sys_dosa.o
 
$(BUILDDIR)/bin/squake : $(SQUAKE_OBJS)
$(CC) $(CFLAGS) -o $@ $(SQUAKE_OBJS) $(SVGALDFLAGS) $(LDFLAGS)
 
####
 
$(BUILDDIR)/squake/cl_demo.o : $(MOUNT_DIR)/cl_demo.c
$(DO_CC)
 
$(BUILDDIR)/squake/cl_input.o : $(MOUNT_DIR)/cl_input.c
$(DO_CC)
 
$(BUILDDIR)/squake/cl_main.o : $(MOUNT_DIR)/cl_main.c
$(DO_CC)
 
$(BUILDDIR)/squake/cl_parse.o : $(MOUNT_DIR)/cl_parse.c
$(DO_CC)
 
$(BUILDDIR)/squake/cl_tent.o : $(MOUNT_DIR)/cl_tent.c
$(DO_CC)
 
$(BUILDDIR)/squake/chase.o : $(MOUNT_DIR)/chase.c
$(DO_CC)
 
$(BUILDDIR)/squake/cmd.o : $(MOUNT_DIR)/cmd.c
$(DO_CC)
 
$(BUILDDIR)/squake/common.o : $(MOUNT_DIR)/common.c
$(DO_DEBUG_CC)
 
$(BUILDDIR)/squake/console.o : $(MOUNT_DIR)/console.c
$(DO_CC)
 
$(BUILDDIR)/squake/crc.o : $(MOUNT_DIR)/crc.c
$(DO_CC)
 
$(BUILDDIR)/squake/cvar.o : $(MOUNT_DIR)/cvar.c
$(DO_CC)
 
$(BUILDDIR)/squake/draw.o : $(MOUNT_DIR)/draw.c
$(DO_CC)
 
$(BUILDDIR)/squake/d_edge.o : $(MOUNT_DIR)/d_edge.c
$(DO_CC)
 
$(BUILDDIR)/squake/d_fill.o : $(MOUNT_DIR)/d_fill.c
$(DO_CC)
 
$(BUILDDIR)/squake/d_init.o : $(MOUNT_DIR)/d_init.c
$(DO_CC)
 
$(BUILDDIR)/squake/d_modech.o : $(MOUNT_DIR)/d_modech.c
$(DO_CC)
 
$(BUILDDIR)/squake/d_part.o : $(MOUNT_DIR)/d_part.c
$(DO_CC)
 
$(BUILDDIR)/squake/d_polyse.o : $(MOUNT_DIR)/d_polyse.c
$(DO_CC)
 
$(BUILDDIR)/squake/d_scan.o : $(MOUNT_DIR)/d_scan.c
$(DO_CC)
 
$(BUILDDIR)/squake/d_sky.o : $(MOUNT_DIR)/d_sky.c
$(DO_CC)
 
$(BUILDDIR)/squake/d_sprite.o : $(MOUNT_DIR)/d_sprite.c
$(DO_CC)
 
$(BUILDDIR)/squake/d_surf.o : $(MOUNT_DIR)/d_surf.c
$(DO_CC)
 
$(BUILDDIR)/squake/d_vars.o : $(MOUNT_DIR)/d_vars.c
$(DO_CC)
 
$(BUILDDIR)/squake/d_zpoint.o : $(MOUNT_DIR)/d_zpoint.c
$(DO_CC)
 
$(BUILDDIR)/squake/host.o : $(MOUNT_DIR)/host.c
$(DO_CC)
 
$(BUILDDIR)/squake/host_cmd.o : $(MOUNT_DIR)/host_cmd.c
$(DO_CC)
 
$(BUILDDIR)/squake/keys.o : $(MOUNT_DIR)/keys.c
$(DO_CC)
 
$(BUILDDIR)/squake/menu.o : $(MOUNT_DIR)/menu.c
$(DO_CC)
 
$(BUILDDIR)/squake/mathlib.o : $(MOUNT_DIR)/mathlib.c
$(DO_CC)
 
$(BUILDDIR)/squake/model.o : $(MOUNT_DIR)/model.c
$(DO_CC)
 
$(BUILDDIR)/squake/net_dgrm.o : $(MOUNT_DIR)/net_dgrm.c
$(DO_CC)
 
$(BUILDDIR)/squake/net_loop.o : $(MOUNT_DIR)/net_loop.c
$(DO_CC)
 
$(BUILDDIR)/squake/net_main.o : $(MOUNT_DIR)/net_main.c
$(DO_CC)
 
$(BUILDDIR)/squake/net_vcr.o : $(MOUNT_DIR)/net_vcr.c
$(DO_CC)
 
$(BUILDDIR)/squake/net_udp.o : $(MOUNT_DIR)/net_udp.c
$(DO_CC)
 
$(BUILDDIR)/squake/net_bsd.o : $(MOUNT_DIR)/net_bsd.c
$(DO_CC)
 
$(BUILDDIR)/squake/nonintel.o : $(MOUNT_DIR)/nonintel.c
$(DO_CC)
 
$(BUILDDIR)/squake/pr_cmds.o : $(MOUNT_DIR)/pr_cmds.c
$(DO_CC)
 
$(BUILDDIR)/squake/pr_edict.o : $(MOUNT_DIR)/pr_edict.c
$(DO_CC)
 
$(BUILDDIR)/squake/pr_exec.o : $(MOUNT_DIR)/pr_exec.c
$(DO_CC)
 
$(BUILDDIR)/squake/r_aclip.o : $(MOUNT_DIR)/r_aclip.c
$(DO_CC)
 
$(BUILDDIR)/squake/r_alias.o : $(MOUNT_DIR)/r_alias.c
$(DO_CC)
 
$(BUILDDIR)/squake/r_bsp.o : $(MOUNT_DIR)/r_bsp.c
$(DO_CC)
 
$(BUILDDIR)/squake/r_light.o : $(MOUNT_DIR)/r_light.c
$(DO_CC)
 
$(BUILDDIR)/squake/r_draw.o : $(MOUNT_DIR)/r_draw.c
$(DO_CC)
 
$(BUILDDIR)/squake/r_efrag.o : $(MOUNT_DIR)/r_efrag.c
$(DO_CC)
 
$(BUILDDIR)/squake/r_edge.o : $(MOUNT_DIR)/r_edge.c
$(DO_CC)
 
$(BUILDDIR)/squake/r_misc.o : $(MOUNT_DIR)/r_misc.c
$(DO_CC)
 
$(BUILDDIR)/squake/r_main.o : $(MOUNT_DIR)/r_main.c
$(DO_CC)
 
$(BUILDDIR)/squake/r_sky.o : $(MOUNT_DIR)/r_sky.c
$(DO_CC)
 
$(BUILDDIR)/squake/r_sprite.o : $(MOUNT_DIR)/r_sprite.c
$(DO_CC)
 
$(BUILDDIR)/squake/r_surf.o : $(MOUNT_DIR)/r_surf.c
$(DO_CC)
 
$(BUILDDIR)/squake/r_part.o : $(MOUNT_DIR)/r_part.c
$(DO_CC)
 
$(BUILDDIR)/squake/r_vars.o : $(MOUNT_DIR)/r_vars.c
$(DO_CC)
 
$(BUILDDIR)/squake/screen.o : $(MOUNT_DIR)/screen.c
$(DO_CC)
 
$(BUILDDIR)/squake/sbar.o : $(MOUNT_DIR)/sbar.c
$(DO_CC)
 
$(BUILDDIR)/squake/sv_main.o : $(MOUNT_DIR)/sv_main.c
$(DO_CC)
 
$(BUILDDIR)/squake/sv_phys.o : $(MOUNT_DIR)/sv_phys.c
$(DO_CC)
 
$(BUILDDIR)/squake/sv_move.o : $(MOUNT_DIR)/sv_move.c
$(DO_CC)
 
$(BUILDDIR)/squake/sv_user.o : $(MOUNT_DIR)/sv_user.c
$(DO_CC)
 
$(BUILDDIR)/squake/zone.o : $(MOUNT_DIR)/zone.c
$(DO_CC)
 
$(BUILDDIR)/squake/view.o : $(MOUNT_DIR)/view.c
$(DO_CC)
 
$(BUILDDIR)/squake/wad.o : $(MOUNT_DIR)/wad.c
$(DO_CC)
 
$(BUILDDIR)/squake/world.o : $(MOUNT_DIR)/world.c
$(DO_CC)
 
$(BUILDDIR)/squake/cd_linux.o : $(MOUNT_DIR)/cd_linux.c
$(DO_CC)
 
$(BUILDDIR)/squake/sys_linux.o :$(MOUNT_DIR)/sys_linux.c
$(DO_CC)
 
$(BUILDDIR)/squake/vid_svgalib.o:$(MOUNT_DIR)/vid_svgalib.c
$(DO_O_CC)
 
$(BUILDDIR)/squake/snd_dma.o : $(MOUNT_DIR)/snd_dma.c
$(DO_CC)
 
$(BUILDDIR)/squake/snd_mem.o : $(MOUNT_DIR)/snd_mem.c
$(DO_CC)
 
$(BUILDDIR)/squake/snd_mix.o : $(MOUNT_DIR)/snd_mix.c
$(DO_CC)
 
$(BUILDDIR)/squake/snd_linux.o :$(MOUNT_DIR)/snd_linux.c
$(DO_CC)
 
#####
 
$(BUILDDIR)/squake/d_copy.o : $(MOUNT_DIR)/d_copy.S
$(DO_AS)
 
$(BUILDDIR)/squake/d_draw.o : $(MOUNT_DIR)/d_draw.S
$(DO_AS)
 
$(BUILDDIR)/squake/d_draw16.o : $(MOUNT_DIR)/d_draw16.S
$(DO_AS)
 
$(BUILDDIR)/squake/d_parta.o : $(MOUNT_DIR)/d_parta.S
$(DO_AS)
 
$(BUILDDIR)/squake/d_polysa.o : $(MOUNT_DIR)/d_polysa.S
$(DO_AS)
 
$(BUILDDIR)/squake/d_scana.o : $(MOUNT_DIR)/d_scana.S
$(DO_AS)
 
$(BUILDDIR)/squake/d_spr8.o : $(MOUNT_DIR)/d_spr8.S
$(DO_AS)
 
$(BUILDDIR)/squake/d_varsa.o : $(MOUNT_DIR)/d_varsa.S
$(DO_AS)
 
$(BUILDDIR)/squake/math.o : $(MOUNT_DIR)/math.S
$(DO_AS)
 
$(BUILDDIR)/squake/r_aliasa.o : $(MOUNT_DIR)/r_aliasa.S
$(DO_AS)
 
$(BUILDDIR)/squake/r_drawa.o : $(MOUNT_DIR)/r_drawa.S
$(DO_AS)
 
$(BUILDDIR)/squake/r_edgea.o : $(MOUNT_DIR)/r_edgea.S
$(DO_AS)
 
$(BUILDDIR)/squake/r_varsa.o : $(MOUNT_DIR)/r_varsa.S
$(DO_AS)
 
$(BUILDDIR)/squake/surf16.o : $(MOUNT_DIR)/surf16.S
$(DO_AS)
 
$(BUILDDIR)/squake/surf8.o : $(MOUNT_DIR)/surf8.S
$(DO_AS)
 
$(BUILDDIR)/squake/worlda.o : $(MOUNT_DIR)/worlda.S
$(DO_AS)
 
$(BUILDDIR)/squake/r_aclipa.o : $(MOUNT_DIR)/r_aclipa.S
$(DO_AS)
 
$(BUILDDIR)/squake/snd_mixa.o : $(MOUNT_DIR)/snd_mixa.S
$(DO_AS)
 
$(BUILDDIR)/squake/sys_dosa.o : $(MOUNT_DIR)/sys_dosa.S
$(DO_AS)
 
#############################################################################
# X11 Quake
#############################################################################
 
X11_OBJS = \
$(BUILDDIR)/x11/cl_demo.o \
$(BUILDDIR)/x11/cl_input.o \
$(BUILDDIR)/x11/cl_main.o \
$(BUILDDIR)/x11/cl_parse.o \
$(BUILDDIR)/x11/cl_tent.o \
$(BUILDDIR)/x11/chase.o \
$(BUILDDIR)/x11/cmd.o \
$(BUILDDIR)/x11/common.o \
$(BUILDDIR)/x11/console.o \
$(BUILDDIR)/x11/crc.o \
$(BUILDDIR)/x11/cvar.o \
$(BUILDDIR)/x11/draw.o \
$(BUILDDIR)/x11/d_edge.o \
$(BUILDDIR)/x11/d_fill.o \
$(BUILDDIR)/x11/d_init.o \
$(BUILDDIR)/x11/d_modech.o \
$(BUILDDIR)/x11/d_part.o \
$(BUILDDIR)/x11/d_polyse.o \
$(BUILDDIR)/x11/d_scan.o \
$(BUILDDIR)/x11/d_sky.o \
$(BUILDDIR)/x11/d_sprite.o \
$(BUILDDIR)/x11/d_surf.o \
$(BUILDDIR)/x11/d_vars.o \
$(BUILDDIR)/x11/d_zpoint.o \
$(BUILDDIR)/x11/host.o \
$(BUILDDIR)/x11/host_cmd.o \
$(BUILDDIR)/x11/keys.o \
$(BUILDDIR)/x11/menu.o \
$(BUILDDIR)/x11/mathlib.o \
$(BUILDDIR)/x11/model.o \
$(BUILDDIR)/x11/net_dgrm.o \
$(BUILDDIR)/x11/net_loop.o \
$(BUILDDIR)/x11/net_main.o \
$(BUILDDIR)/x11/net_vcr.o \
$(BUILDDIR)/x11/net_udp.o \
$(BUILDDIR)/x11/net_bsd.o \
$(BUILDDIR)/x11/nonintel.o \
$(BUILDDIR)/x11/pr_cmds.o \
$(BUILDDIR)/x11/pr_edict.o \
$(BUILDDIR)/x11/pr_exec.o \
$(BUILDDIR)/x11/r_aclip.o \
$(BUILDDIR)/x11/r_alias.o \
$(BUILDDIR)/x11/r_bsp.o \
$(BUILDDIR)/x11/r_light.o \
$(BUILDDIR)/x11/r_draw.o \
$(BUILDDIR)/x11/r_efrag.o \
$(BUILDDIR)/x11/r_edge.o \
$(BUILDDIR)/x11/r_misc.o \
$(BUILDDIR)/x11/r_main.o \
$(BUILDDIR)/x11/r_sky.o \
$(BUILDDIR)/x11/r_sprite.o \
$(BUILDDIR)/x11/r_surf.o \
$(BUILDDIR)/x11/r_part.o \
$(BUILDDIR)/x11/r_vars.o \
$(BUILDDIR)/x11/screen.o \
$(BUILDDIR)/x11/sbar.o \
$(BUILDDIR)/x11/sv_main.o \
$(BUILDDIR)/x11/sv_phys.o \
$(BUILDDIR)/x11/sv_move.o \
$(BUILDDIR)/x11/sv_user.o \
$(BUILDDIR)/x11/zone.o \
$(BUILDDIR)/x11/view.o \
$(BUILDDIR)/x11/wad.o \
$(BUILDDIR)/x11/world.o \
$(BUILDDIR)/x11/cd_linux.o \
$(BUILDDIR)/x11/sys_linux.o \
$(BUILDDIR)/x11/vid_x.o \
$(BUILDDIR)/x11/snd_dma.o \
$(BUILDDIR)/x11/snd_mem.o \
$(BUILDDIR)/x11/snd_mix.o \
$(BUILDDIR)/x11/snd_linux.o \
\
$(BUILDDIR)/x11/d_draw.o \
$(BUILDDIR)/x11/d_draw16.o \
$(BUILDDIR)/x11/d_parta.o \
$(BUILDDIR)/x11/d_polysa.o \
$(BUILDDIR)/x11/d_scana.o \
$(BUILDDIR)/x11/d_spr8.o \
$(BUILDDIR)/x11/d_varsa.o \
$(BUILDDIR)/x11/math.o \
$(BUILDDIR)/x11/r_aliasa.o \
$(BUILDDIR)/x11/r_drawa.o \
$(BUILDDIR)/x11/r_edgea.o \
$(BUILDDIR)/x11/r_varsa.o \
$(BUILDDIR)/x11/surf16.o \
$(BUILDDIR)/x11/surf8.o \
$(BUILDDIR)/x11/worlda.o \
$(BUILDDIR)/x11/r_aclipa.o \
$(BUILDDIR)/x11/snd_mixa.o \
$(BUILDDIR)/x11/sys_dosa.o
 
$(BUILDDIR)/bin/quake.x11 : $(X11_OBJS)
$(CC) $(CFLAGS) -o $@ $(X11_OBJS) $(XLDFLAGS) $(LDFLAGS)
 
####
 
$(BUILDDIR)/x11/cl_demo.o : $(MOUNT_DIR)/cl_demo.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/cl_input.o : $(MOUNT_DIR)/cl_input.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/cl_main.o : $(MOUNT_DIR)/cl_main.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/cl_parse.o : $(MOUNT_DIR)/cl_parse.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/cl_tent.o : $(MOUNT_DIR)/cl_tent.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/chase.o : $(MOUNT_DIR)/chase.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/cmd.o : $(MOUNT_DIR)/cmd.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/common.o : $(MOUNT_DIR)/common.c
$(DO_X11_DEBUG_CC)
 
$(BUILDDIR)/x11/console.o : $(MOUNT_DIR)/console.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/crc.o : $(MOUNT_DIR)/crc.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/cvar.o : $(MOUNT_DIR)/cvar.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/draw.o : $(MOUNT_DIR)/draw.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/d_edge.o : $(MOUNT_DIR)/d_edge.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/d_fill.o : $(MOUNT_DIR)/d_fill.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/d_init.o : $(MOUNT_DIR)/d_init.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/d_modech.o : $(MOUNT_DIR)/d_modech.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/d_part.o : $(MOUNT_DIR)/d_part.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/d_polyse.o : $(MOUNT_DIR)/d_polyse.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/d_scan.o : $(MOUNT_DIR)/d_scan.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/d_sky.o : $(MOUNT_DIR)/d_sky.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/d_sprite.o : $(MOUNT_DIR)/d_sprite.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/d_surf.o : $(MOUNT_DIR)/d_surf.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/d_vars.o : $(MOUNT_DIR)/d_vars.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/d_zpoint.o : $(MOUNT_DIR)/d_zpoint.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/host.o : $(MOUNT_DIR)/host.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/host_cmd.o : $(MOUNT_DIR)/host_cmd.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/keys.o : $(MOUNT_DIR)/keys.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/menu.o : $(MOUNT_DIR)/menu.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/mathlib.o : $(MOUNT_DIR)/mathlib.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/model.o : $(MOUNT_DIR)/model.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/net_dgrm.o : $(MOUNT_DIR)/net_dgrm.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/net_loop.o : $(MOUNT_DIR)/net_loop.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/net_main.o : $(MOUNT_DIR)/net_main.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/net_vcr.o : $(MOUNT_DIR)/net_vcr.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/net_udp.o : $(MOUNT_DIR)/net_udp.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/net_bsd.o : $(MOUNT_DIR)/net_bsd.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/nonintel.o : $(MOUNT_DIR)/nonintel.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/pr_cmds.o : $(MOUNT_DIR)/pr_cmds.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/pr_edict.o : $(MOUNT_DIR)/pr_edict.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/pr_exec.o : $(MOUNT_DIR)/pr_exec.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/r_aclip.o : $(MOUNT_DIR)/r_aclip.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/r_alias.o : $(MOUNT_DIR)/r_alias.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/r_bsp.o : $(MOUNT_DIR)/r_bsp.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/r_light.o : $(MOUNT_DIR)/r_light.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/r_draw.o : $(MOUNT_DIR)/r_draw.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/r_efrag.o : $(MOUNT_DIR)/r_efrag.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/r_edge.o : $(MOUNT_DIR)/r_edge.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/r_misc.o : $(MOUNT_DIR)/r_misc.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/r_main.o : $(MOUNT_DIR)/r_main.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/r_sky.o : $(MOUNT_DIR)/r_sky.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/r_sprite.o : $(MOUNT_DIR)/r_sprite.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/r_surf.o : $(MOUNT_DIR)/r_surf.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/r_part.o : $(MOUNT_DIR)/r_part.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/r_vars.o : $(MOUNT_DIR)/r_vars.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/screen.o : $(MOUNT_DIR)/screen.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/sbar.o : $(MOUNT_DIR)/sbar.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/sv_main.o : $(MOUNT_DIR)/sv_main.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/sv_phys.o : $(MOUNT_DIR)/sv_phys.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/sv_move.o : $(MOUNT_DIR)/sv_move.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/sv_user.o : $(MOUNT_DIR)/sv_user.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/zone.o : $(MOUNT_DIR)/zone.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/view.o : $(MOUNT_DIR)/view.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/wad.o : $(MOUNT_DIR)/wad.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/world.o : $(MOUNT_DIR)/world.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/cd_linux.o : $(MOUNT_DIR)/cd_linux.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/sys_linux.o :$(MOUNT_DIR)/sys_linux.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/vid_x.o: $(MOUNT_DIR)/vid_x.c
$(DO_O_CC)
 
$(BUILDDIR)/x11/snd_dma.o : $(MOUNT_DIR)/snd_dma.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/snd_mem.o : $(MOUNT_DIR)/snd_mem.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/snd_mix.o : $(MOUNT_DIR)/snd_mix.c
$(DO_X11_CC)
 
$(BUILDDIR)/x11/snd_linux.o :$(MOUNT_DIR)/snd_linux.c
$(DO_X11_CC)
 
#####
 
$(BUILDDIR)/x11/d_copy.o : $(MOUNT_DIR)/d_copy.S
$(DO_AS)
 
$(BUILDDIR)/x11/d_draw.o : $(MOUNT_DIR)/d_draw.S
$(DO_AS)
 
$(BUILDDIR)/x11/d_draw16.o : $(MOUNT_DIR)/d_draw16.S
$(DO_AS)
 
$(BUILDDIR)/x11/d_parta.o : $(MOUNT_DIR)/d_parta.S
$(DO_AS)
 
$(BUILDDIR)/x11/d_polysa.o : $(MOUNT_DIR)/d_polysa.S
$(DO_AS)
 
$(BUILDDIR)/x11/d_scana.o : $(MOUNT_DIR)/d_scana.S
$(DO_AS)
 
$(BUILDDIR)/x11/d_spr8.o : $(MOUNT_DIR)/d_spr8.S
$(DO_AS)
 
$(BUILDDIR)/x11/d_varsa.o : $(MOUNT_DIR)/d_varsa.S
$(DO_AS)
 
$(BUILDDIR)/x11/math.o : $(MOUNT_DIR)/math.S
$(DO_AS)
 
$(BUILDDIR)/x11/r_aliasa.o : $(MOUNT_DIR)/r_aliasa.S
$(DO_AS)
 
$(BUILDDIR)/x11/r_drawa.o : $(MOUNT_DIR)/r_drawa.S
$(DO_AS)
 
$(BUILDDIR)/x11/r_edgea.o : $(MOUNT_DIR)/r_edgea.S
$(DO_AS)
 
$(BUILDDIR)/x11/r_varsa.o : $(MOUNT_DIR)/r_varsa.S
$(DO_AS)
 
$(BUILDDIR)/x11/surf16.o : $(MOUNT_DIR)/surf16.S
$(DO_AS)
 
$(BUILDDIR)/x11/surf8.o : $(MOUNT_DIR)/surf8.S
$(DO_AS)
 
$(BUILDDIR)/x11/worlda.o : $(MOUNT_DIR)/worlda.S
$(DO_AS)
 
$(BUILDDIR)/x11/r_aclipa.o : $(MOUNT_DIR)/r_aclipa.S
$(DO_AS)
 
$(BUILDDIR)/x11/snd_mixa.o : $(MOUNT_DIR)/snd_mixa.S
$(DO_AS)
 
$(BUILDDIR)/x11/sys_dosa.o : $(MOUNT_DIR)/sys_dosa.S
$(DO_AS)
 
#############################################################################
# GLQuake
#############################################################################
 
GLQUAKE_OBJS= \
$(BUILDDIR)/glquake/cl_demo.o \
$(BUILDDIR)/glquake/cl_input.o \
$(BUILDDIR)/glquake/cl_main.o \
$(BUILDDIR)/glquake/cl_parse.o \
$(BUILDDIR)/glquake/cl_tent.o \
$(BUILDDIR)/glquake/chase.o \
$(BUILDDIR)/glquake/cmd.o \
$(BUILDDIR)/glquake/common.o \
$(BUILDDIR)/glquake/console.o \
$(BUILDDIR)/glquake/crc.o \
$(BUILDDIR)/glquake/cvar.o \
\
$(BUILDDIR)/glquake/gl_draw.o \
$(BUILDDIR)/glquake/gl_mesh.o \
$(BUILDDIR)/glquake/gl_model.o \
$(BUILDDIR)/glquake/gl_refrag.o \
$(BUILDDIR)/glquake/gl_rlight.o \
$(BUILDDIR)/glquake/gl_rmain.o \
$(BUILDDIR)/glquake/gl_rmisc.o \
$(BUILDDIR)/glquake/gl_rsurf.o \
$(BUILDDIR)/glquake/gl_screen.o \
$(BUILDDIR)/glquake/gl_test.o \
$(BUILDDIR)/glquake/gl_warp.o \
\
$(BUILDDIR)/glquake/host.o \
$(BUILDDIR)/glquake/host_cmd.o \
$(BUILDDIR)/glquake/keys.o \
$(BUILDDIR)/glquake/menu.o \
$(BUILDDIR)/glquake/mathlib.o \
$(BUILDDIR)/glquake/net_dgrm.o \
$(BUILDDIR)/glquake/net_loop.o \
$(BUILDDIR)/glquake/net_main.o \
$(BUILDDIR)/glquake/net_vcr.o \
$(BUILDDIR)/glquake/net_udp.o \
$(BUILDDIR)/glquake/net_bsd.o \
$(BUILDDIR)/glquake/pr_cmds.o \
$(BUILDDIR)/glquake/pr_edict.o \
$(BUILDDIR)/glquake/pr_exec.o \
$(BUILDDIR)/glquake/r_part.o \
$(BUILDDIR)/glquake/sbar.o \
$(BUILDDIR)/glquake/sv_main.o \
$(BUILDDIR)/glquake/sv_phys.o \
$(BUILDDIR)/glquake/sv_move.o \
$(BUILDDIR)/glquake/sv_user.o \
$(BUILDDIR)/glquake/zone.o \
$(BUILDDIR)/glquake/view.o \
$(BUILDDIR)/glquake/wad.o \
$(BUILDDIR)/glquake/world.o \
$(BUILDDIR)/glquake/cd_linux.o \
$(BUILDDIR)/glquake/sys_linux.o \
$(BUILDDIR)/glquake/snd_dma.o \
$(BUILDDIR)/glquake/snd_mem.o \
$(BUILDDIR)/glquake/snd_mix.o \
$(BUILDDIR)/glquake/snd_linux.o \
\
$(BUILDDIR)/glquake/math.o \
$(BUILDDIR)/glquake/worlda.o \
$(BUILDDIR)/glquake/snd_mixa.o \
$(BUILDDIR)/glquake/sys_dosa.o
 
GLSVGA_OBJS=$(BUILDDIR)/glquake/gl_vidlinux.o
 
GLX_OBJS=$(BUILDDIR)/glquake/gl_vidlinuxglx.o
 
$(BUILDDIR)/bin/glquake : $(GLQUAKE_OBJS) $(GLSVGA_OBJS)
$(CC) $(CFLAGS) -o $@ $(GLQUAKE_OBJS) $(GLSVGA_OBJS) $(MESAGLLDFLAGS) $(SVGALDFLAGS) $(LDFLAGS)
 
$(BUILDDIR)/bin/glquake.glx : $(GLQUAKE_OBJS) $(GLX_OBJS)
$(CC) $(CFLAGS) -o $@ $(GLQUAKE_OBJS) $(GLX_OBJS) $(GLLDFLAGS) $(LDFLAGS)
 
$(BUILDDIR)/bin/glquake.3dfxgl : $(GLQUAKE_OBJS) $(GLSVGA_OBJS)
$(CC) $(CFLAGS) -o $@ $(GLQUAKE_OBJS) $(GLSVGA_OBJS) $(TDFXGLLDFLAGS) $(SVGALDFLAGS) $(LDFLAGS)
 
$(BUILDDIR)/glquake/cl_demo.o : $(MOUNT_DIR)/cl_demo.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/cl_input.o : $(MOUNT_DIR)/cl_input.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/cl_main.o : $(MOUNT_DIR)/cl_main.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/cl_parse.o : $(MOUNT_DIR)/cl_parse.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/cl_tent.o : $(MOUNT_DIR)/cl_tent.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/chase.o : $(MOUNT_DIR)/chase.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/cmd.o : $(MOUNT_DIR)/cmd.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/common.o : $(MOUNT_DIR)/common.c
$(DO_GL_DEBUG_CC)
 
$(BUILDDIR)/glquake/console.o : $(MOUNT_DIR)/console.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/crc.o : $(MOUNT_DIR)/crc.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/cvar.o : $(MOUNT_DIR)/cvar.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/gl_draw.o : $(MOUNT_DIR)/gl_draw.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/gl_mesh.o : $(MOUNT_DIR)/gl_mesh.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/gl_model.o : $(MOUNT_DIR)/gl_model.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/gl_refrag.o : $(MOUNT_DIR)/gl_refrag.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/gl_rlight.o : $(MOUNT_DIR)/gl_rlight.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/gl_rmain.o : $(MOUNT_DIR)/gl_rmain.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/gl_rmisc.o : $(MOUNT_DIR)/gl_rmisc.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/gl_rsurf.o : $(MOUNT_DIR)/gl_rsurf.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/gl_screen.o : $(MOUNT_DIR)/gl_screen.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/gl_test.o : $(MOUNT_DIR)/gl_test.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/gl_vidlinux.o : $(MOUNT_DIR)/gl_vidlinux.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/gl_vidlinuxglx.o : $(MOUNT_DIR)/gl_vidlinuxglx.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/gl_warp.o : $(MOUNT_DIR)/gl_warp.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/host.o : $(MOUNT_DIR)/host.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/host_cmd.o : $(MOUNT_DIR)/host_cmd.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/keys.o : $(MOUNT_DIR)/keys.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/menu.o : $(MOUNT_DIR)/menu.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/mathlib.o : $(MOUNT_DIR)/mathlib.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/net_dgrm.o : $(MOUNT_DIR)/net_dgrm.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/net_loop.o : $(MOUNT_DIR)/net_loop.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/net_main.o : $(MOUNT_DIR)/net_main.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/net_vcr.o : $(MOUNT_DIR)/net_vcr.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/net_udp.o : $(MOUNT_DIR)/net_udp.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/net_bsd.o : $(MOUNT_DIR)/net_bsd.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/pr_cmds.o : $(MOUNT_DIR)/pr_cmds.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/pr_edict.o : $(MOUNT_DIR)/pr_edict.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/pr_exec.o : $(MOUNT_DIR)/pr_exec.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/r_part.o : $(MOUNT_DIR)/r_part.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/sbar.o : $(MOUNT_DIR)/sbar.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/sv_main.o : $(MOUNT_DIR)/sv_main.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/sv_phys.o : $(MOUNT_DIR)/sv_phys.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/sv_move.o : $(MOUNT_DIR)/sv_move.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/sv_user.o : $(MOUNT_DIR)/sv_user.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/zone.o : $(MOUNT_DIR)/zone.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/view.o : $(MOUNT_DIR)/view.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/wad.o : $(MOUNT_DIR)/wad.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/world.o : $(MOUNT_DIR)/world.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/cd_linux.o : $(MOUNT_DIR)/cd_linux.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/sys_linux.o : $(MOUNT_DIR)/sys_linux.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/snd_dma.o : $(MOUNT_DIR)/snd_dma.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/snd_mem.o : $(MOUNT_DIR)/snd_mem.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/snd_mix.o : $(MOUNT_DIR)/snd_mix.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/snd_linux.o : $(MOUNT_DIR)/snd_linux.c
$(DO_GL_CC)
 
$(BUILDDIR)/glquake/math.o : $(MOUNT_DIR)/math.S
$(DO_GL_AS)
 
$(BUILDDIR)/glquake/worlda.o : $(MOUNT_DIR)/worlda.S
$(DO_GL_AS)
 
$(BUILDDIR)/glquake/snd_mixa.o : $(MOUNT_DIR)/snd_mixa.S
$(DO_GL_AS)
 
$(BUILDDIR)/glquake/sys_dosa.o : $(MOUNT_DIR)/sys_dosa.S
$(DO_GL_AS)
 
#############################################################################
# RPM
#############################################################################
 
# Make RPMs. You need to be root to make this work
RPMROOT=/usr/src/redhat
RPM = rpm
RPMFLAGS = -bb
INSTALLDIR = /usr/local/games/quake
TMPDIR = /var/tmp
RPMDIR = $(TMPDIR)/quake-$(VERSION)
BASERPMDIR = $(TMPDIR)/quake-$(BASEVERSION)
 
rpm: rpm-quake rpm-quake-data rpm-hipnotic rpm-rogue
 
rpm-quake: quake.spec \
$(BUILD_RELEASE_DIR)/bin/squake \
$(BUILD_RELEASE_DIR)/bin/quake.x11 \
$(BUILD_RELEASE_DIR)/bin/glquake \
$(BUILD_RELEASE_DIR)/bin/glquake.glx \
$(BUILD_RELEASE_DIR)/bin/glquake.3dfxgl
touch $(RPMROOT)/SOURCES/quake-$(VERSION).tar.gz
if [ ! -d RPMS ];then mkdir RPMS;fi
cp $(MOUNT_DIR)/quake.gif $(RPMROOT)/SOURCES/quake.gif
 
# basic binaries rpm
-mkdirhier $(RPMDIR)/$(INSTALLDIR)
cp $(MOUNT_DIR)/docs/README $(RPMDIR)/$(INSTALLDIR)/.
cp $(BUILD_RELEASE_DIR)/bin/squake $(RPMDIR)/$(INSTALLDIR)/squake
strip $(RPMDIR)/$(INSTALLDIR)/squake
cp $(BUILD_RELEASE_DIR)/bin/quake.x11 $(RPMDIR)/$(INSTALLDIR)/quake.x11
strip $(RPMDIR)/$(INSTALLDIR)/quake.x11
cp $(BUILD_RELEASE_DIR)/bin/glquake $(RPMDIR)/$(INSTALLDIR)/glquake
strip $(RPMDIR)/$(INSTALLDIR)/glquake
cp $(BUILD_RELEASE_DIR)/bin/glquake.glx $(RPMDIR)/$(INSTALLDIR)/glquake.glx
strip $(RPMDIR)/$(INSTALLDIR)/glquake.glx
cp $(BUILD_RELEASE_DIR)/bin/glquake.3dfxgl $(RPMDIR)/$(INSTALLDIR)/glquake.3dfxgl
strip $(RPMDIR)/$(INSTALLDIR)/glquake.3dfxgl
-mkdirhier $(RPMDIR)/usr/lib
cp $(TDFXGL_DIR)/release$(ARCH)$(GLIBC)/lib3dfxgl.so $(RPMDIR)/usr/lib/lib3dfxgl.so
cp $(MESA_DIR)/lib/libMesaGL.so.2.6 $(RPMDIR)/usr/lib/libMesaGL.so.2.6
 
cp quake.spec $(RPMROOT)/SPECS/.
cd $(RPMROOT)/SPECS; $(RPM) $(RPMFLAGS) quake.spec
rm -rf $(RPMDIR)
rm -f $(RPMROOT)/SOURCES/quake-$(VERSION).tar.gz
 
mv $(RPMROOT)/RPMS/$(ARCH)/quake-$(VERSION)-$(RPM_RELEASE).$(ARCH).rpm RPMS/.
 
QUAKEDATADIR=$(TMPDIR)/quake-data-$(BASEVERSION)
rpm-quake-data: quake-data.spec
# data rpm
touch $(RPMROOT)/SOURCES/quake-$(BASEVERSION)-data.tar.gz
 
-mkdirhier $(QUAKEDATADIR)/$(INSTALLDIR)/id1
cp $(MASTER_DIR)/id1/pak0.pak $(QUAKEDATADIR)/$(INSTALLDIR)/id1/.
cp $(MASTER_DIR)/id1/pak1.pak $(QUAKEDATADIR)/$(INSTALLDIR)/id1/.
cp $(MOUNT_DIR)/docs/README $(QUAKEDATADIR)/$(INSTALLDIR)/.
cp $(MOUNT_DIR)/data/comexp.txt $(QUAKEDATADIR)/$(INSTALLDIR)/.
cp $(MOUNT_DIR)/data/help.txt $(QUAKEDATADIR)/$(INSTALLDIR)/.
cp $(MOUNT_DIR)/data/licinfo.txt $(QUAKEDATADIR)/$(INSTALLDIR)/.
cp $(MOUNT_DIR)/data/manual.txt $(QUAKEDATADIR)/$(INSTALLDIR)/.
cp $(MOUNT_DIR)/data/readme.txt $(QUAKEDATADIR)/$(INSTALLDIR)/.
cp $(MOUNT_DIR)/data/rlicnse.txt $(QUAKEDATADIR)/$(INSTALLDIR)/.
cp $(MOUNT_DIR)/data/slicnse.txt $(QUAKEDATADIR)/$(INSTALLDIR)/.
cp $(MOUNT_DIR)/data/techinfo.txt $(QUAKEDATADIR)/$(INSTALLDIR)/.
cp quake-data.spec $(RPMROOT)/SPECS/.
cd $(RPMROOT)/SPECS; $(RPM) $(RPMFLAGS) quake-data.spec
rm -rf $(QUAKEDATADIR)
rm -f $(RPMROOT)/SOURCES/quake-$(BASEVERSION)-data.tar.gz
 
mv $(RPMROOT)/RPMS/$(NOARCH)/quake-data-$(BASEVERSION)-$(RPM_RELEASE).$(NOARCH).rpm RPMS/.
 
RPMHIPNOTICDIR=$(TMPDIR)/quake-hipnotic-$(BASEVERSION)
rpm-hipnotic: quake-hipnotic.spec
touch $(RPMROOT)/SOURCES/quake-hipnotic-$(BASEVERSION).tar.gz
if [ ! -d RPMS ];then mkdir RPMS;fi
cp $(MOUNT_DIR)/quake.gif $(RPMROOT)/SOURCES/quake.gif
-mkdirhier $(RPMHIPNOTICDIR)/$(INSTALLDIR)/hipnotic/docs
cp $(MASTER_DIR)/hipnotic/pak0.pak $(RPMHIPNOTICDIR)/$(INSTALLDIR)/hipnotic/.
cp $(MASTER_DIR)/hipnotic/config.cfg $(RPMHIPNOTICDIR)/$(INSTALLDIR)/hipnotic/.
cp $(MASTER_DIR)/hipnotic/docs/manual.doc $(RPMHIPNOTICDIR)/$(INSTALLDIR)/hipnotic/docs/.
cp $(MASTER_DIR)/hipnotic/docs/manual.htm $(RPMHIPNOTICDIR)/$(INSTALLDIR)/hipnotic/docs/.
cp $(MASTER_DIR)/hipnotic/docs/manual.txt $(RPMHIPNOTICDIR)/$(INSTALLDIR)/hipnotic/docs/.
cp $(MASTER_DIR)/hipnotic/docs/readme.doc $(RPMHIPNOTICDIR)/$(INSTALLDIR)/hipnotic/docs/.
cp $(MASTER_DIR)/hipnotic/docs/readme.htm $(RPMHIPNOTICDIR)/$(INSTALLDIR)/hipnotic/docs/.
cp $(MASTER_DIR)/hipnotic/docs/readme.txt $(RPMHIPNOTICDIR)/$(INSTALLDIR)/hipnotic/docs/.
cp quake-hipnotic.spec $(RPMROOT)/SPECS/.
cd $(RPMROOT)/SPECS; $(RPM) $(RPMFLAGS) quake-hipnotic.spec
rm -rf $(RPMHIPNOTICDIR)
rm -f $(RPMROOT)/SOURCES/quake-hipnotic-$(BASEVERSION).tar.gz
 
mv $(RPMROOT)/RPMS/$(NOARCH)/quake-hipnotic-$(BASEVERSION)-$(RPM_RELEASE).$(NOARCH).rpm RPMS/.
 
RPMROGUEDIR=$(TMPDIR)/quake-rogue-$(BASEVERSION)
rpm-rogue: quake-rogue.spec
touch $(RPMROOT)/SOURCES/quake-rogue-$(BASEVERSION).tar.gz
if [ ! -d RPMS ];then mkdir RPMS;fi
cp $(MOUNT_DIR)/quake.gif $(RPMROOT)/SOURCES/quake.gif
-mkdirhier $(RPMROGUEDIR)/$(INSTALLDIR)/rogue/docs
cp $(MASTER_DIR)/rogue/pak0.pak $(RPMROGUEDIR)/$(INSTALLDIR)/rogue/.
cp $(MASTER_DIR)/rogue/docs/manual.doc $(RPMROGUEDIR)/$(INSTALLDIR)/rogue/docs/.
cp $(MASTER_DIR)/rogue/docs/manual.htm $(RPMROGUEDIR)/$(INSTALLDIR)/rogue/docs/.
cp $(MASTER_DIR)/rogue/docs/manual.txt $(RPMROGUEDIR)/$(INSTALLDIR)/rogue/docs/.
cp $(MASTER_DIR)/rogue/docs/readme.doc $(RPMROGUEDIR)/$(INSTALLDIR)/rogue/docs/.
cp $(MASTER_DIR)/rogue/docs/readme.htm $(RPMROGUEDIR)/$(INSTALLDIR)/rogue/docs/.
cp $(MASTER_DIR)/rogue/docs/readme.txt $(RPMROGUEDIR)/$(INSTALLDIR)/rogue/docs/.
cp $(MASTER_DIR)/rogue/docs/ctf.doc $(RPMROGUEDIR)/$(INSTALLDIR)/rogue/docs/.
cp $(MASTER_DIR)/rogue/docs/ctf.htm $(RPMROGUEDIR)/$(INSTALLDIR)/rogue/docs/.
cp $(MASTER_DIR)/rogue/docs/ctf.txt $(RPMROGUEDIR)/$(INSTALLDIR)/rogue/docs/.
cp quake-rogue.spec $(RPMROOT)/SPECS/.
cd $(RPMROOT)/SPECS; $(RPM) $(RPMFLAGS) quake-rogue.spec
rm -rf $(RPMROGUEDIR)
rm -f $(RPMROOT)/SOURCES/quake-rogue-$(BASEVERSION).tar.gz
 
mv $(RPMROOT)/RPMS/$(NOARCH)/quake-rogue-$(BASEVERSION)-$(RPM_RELEASE).$(NOARCH).rpm RPMS/.
 
quake.spec : $(MOUNT_DIR)/quake.spec.sh
sh $< $(VERSION) $(RPM_RELEASE) $(INSTALLDIR) > $@
 
quake-data.spec : $(MOUNT_DIR)/quake-data.spec.sh
sh $< $(BASEVERSION) $(RPM_RELEASE) $(INSTALLDIR) > $@
 
quake-hipnotic.spec : $(MOUNT_DIR)/quake-hipnotic.spec.sh
sh $< $(BASEVERSION) $(RPM_RELEASE) $(INSTALLDIR) > $@
 
quake-rogue.spec : $(MOUNT_DIR)/quake-rogue.spec.sh
sh $< $(BASEVERSION) $(RPM_RELEASE) $(INSTALLDIR) > $@
 
#############################################################################
# MISC
#############################################################################
 
clean: clean-debug clean-release
rm -f squake.spec glquake.spec quake.x11.spec
 
clean-debug:
$(MAKE) clean2 BUILDDIR=$(BUILD_DEBUG_DIR) CFLAGS="$(DEBUG_CFLAGS)"
 
clean-release:
$(MAKE) clean2 BUILDDIR=$(BUILD_RELEASE_DIR) CFLAGS="$(DEBUG_CFLAGS)"
 
clean2:
-rm -f $(SQUAKE_OBJS) $(X11_OBJS) $(GLQUAKE_OBJS) $(GLSVGA_OBJS) \
$(GLX_OBJS)
 
/contrib/other/sdlquake-1.0.9/README.SDL
0,0 → 1,34
 
This is a quick hack of Quake ported to the Simple DirectMedia Layer library.
http://www.devolution.com/~slouken/SDL/
 
To build under Linux, simply run ./configure; make
 
This game requires the original Quake datafiles. You can get the shareware
data files from http://www.idsoftware.com/.
 
Of interest in the original X sources is the following:
// Duff's Device
count = width;
n = (count + 7) / 8;
dest = ((PIXEL16 *)src) + x+width - 1;
src += x+width - 1;
 
switch (count % 8) {
case 0: do { *dest-- = st2d_8to16table[*src--];
case 7: *dest-- = st2d_8to16table[*src--];
case 6: *dest-- = st2d_8to16table[*src--];
case 5: *dest-- = st2d_8to16table[*src--];
case 4: *dest-- = st2d_8to16table[*src--];
case 3: *dest-- = st2d_8to16table[*src--];
case 2: *dest-- = st2d_8to16table[*src--];
case 1: *dest-- = st2d_8to16table[*src--];
} while (--n > 0);
}
This idea may make it into the SDL blitters if it turns out to be faster
than my current code. :)
 
Thanks to Zoid, Dave Taylor, John Carmack, and everyone else involved in the
open source release of id games. :)
 
- Sam Lantinga (slouken@devolution.com) 12/25/1999
/contrib/other/sdlquake-1.0.9/README.Solaris
0,0 → 1,98
Solaris 2 Quake / QuakeWorld
----------------------------
 
This is an UNSUPPORTED version of Quake and QuakeWorld. Don't
bother id software about it. Bug reports will be ignored.
PORT DETAILS
------------
 
There are a few major difference between this port and the
vanilla Quake/QuakeWorld available on the internet. For
optimum performance, you should copy everything to a directory
on your local system before starting play so that you are
not mounting files from a remote filesystem.
 
In order to use this program, you need the files pak0.pak
and pak1.pak in the id1 directory found on a registered copy of
Quake. You can ftp them to your Solaris host from a Windows95
machine for example. The files must be in an id1 subdirectory from
the directory you install Quake/QuakeWorld, and all file names must
be lowercase. Add on packages such as ThreeWave CTF work fine as
well, just place such addon packages in their own directory as you
would on a Windows95 installation. But again, make sure all files
are lowercase.
COMMAND LINE FLAGS:
+pixel_multiply
You can magnify the screen by using this flag:
Ex: % quake +pixel_multiply 2
You can also use this command (without the dash)
from the Quake console. pixel_multiply is a Quake
cvar and is saved from session to session in the
config.cfg file.
 
-winsize <width> <height>
 
Set the size of the window when you start
 
-count_frames
 
See how many frames per second you're getting
 
GAME SETTINGS
 
mouse binding
 
You can bind and unbind the mouse to the Quake window
by using the Use Mouse selection in the Options menu,
or with the "_windowed_mouse" command in the console,
ex "_windowed_mouse 1" Now, moving the mouse will move
your player. Use "_windowed_mouse 0" to unbind. You
can bind or alias this to a key.
 
Example command:
 
% quake.xil +pixel_multiply 2 -winsize 400 300
 
WHAT IS "QUAKEWORLD" AND HOW DO I USE IT?
-----------------------------------------
 
In a nutshell, QuakeWorld is an extension of Quake that is
much more user friendly. It allows the user to dynamically
download changes from the server, such as new maps and new
weapons while inside the Quake client. It is not directly
compatible with Quake (ie, you can't connect to a Quake server
from a QuakeWorld client) but in general it is superior to
Quake. QuakeWorld also offers much smoother play over the
Internet by using client prediction. For more information,
check out http://www.quakeworld.net/.
 
In order to use it, you must make a copy of the "qw"
directory. Any new stuff that is downloaded from a QuakeWorld
server will be stored in this directory. All regular Quake
flags apply so you can use the same command line as before.
 
Example command:
 
% qwcl.xil +pixel_multiply 2 -winsize 400 300
 
WHERE CAN I FIND OUT ABOUT...
-----------------------------
 
If you've got questions about Quake, rest assured that there
are answers out there. Try checking out these web sites:
 
http://www.planetquake.com/
http://www.stomped.com/
http://www.quakeworld.net/
If all else fails use a search engine.
 
Happy fragging,
the Quake/Solaris team
/contrib/other/sdlquake-1.0.9/Tupfile.lua
0,0 → 1,41
if tup.getconfig("NO_GCC") ~= "" then return end
if tup.getconfig("HELPERDIR") == ""
then
if tup.getconfig("NO_NASM") ~= "" then return end -- required for SDL compilation
HELPERDIR = "../../../programs"
end
tup.include(HELPERDIR .. "/use_gcc.lua")
tup.include(HELPERDIR .. "/use_menuetlibc.lua")
use_dynamic_stack() -- default 64K are not sufficient
tup.include(HELPERDIR .. "/use_sdl.lua")
CFLAGS = CFLAGS .. " -DSDL -UWIN32 -U_WIN32 -U__WIN32__ -D_KOLIBRI"
CFLAGS = CFLAGS .. " -DUSE_ASM"
-- CFLAGS = CFLAGS:gsub("-Os", "-O2")
compile_gcc{
"chase.c", "cl_demo.c", "cl_input.c", "cl_main.c", "cl_parse.c", "cl_tent.c",
"cmd.c", "common.c", "console.c", "crc.c", "cvar.c", "d_edge.c", "d_init.c",
"d_modech.c", "d_part.c", "d_polyse.c", "d_scan.c", "d_sky.c", "d_sprite.c",
"d_surf.c", "draw.c", "host.c", "host_cmd.c", "keys.c", "mathlib.c",
"menu.c", "model.c", "net_loop.c", "net_main.c", "net_vcr.c", "pr_cmds.c",
"pr_edict.c", "pr_exec.c", "r_aclip.c", "r_alias.c", "r_bsp.c", "r_draw.c",
"r_edge.c", "r_efrag.c", "r_light.c", "r_main.c", "r_misc.c", "r_part.c",
"r_sky.c", "r_sprite.c", "r_surf.c", "sbar.c", "screen.c", "snd_dma.c",
"snd_mem.c", "snd_mix.c", "sv_main.c", "sv_move.c", "sv_phys.c", "sv_user.c",
"view.c", "wad.c", "world.c", "zone.c"
}
-- asm vs c
--[[compile_gcc{
"d_vars.c", "r_vars.c", "nonintel.c"
}]]
compile_gcc{
"d_draw.S", "d_draw16.S", "d_parta.S", "d_polysa.S", "d_scana.S", "d_spr8.S",
"d_varsa.S", "math.S", "r_aclipa.S", "r_aliasa.S", "r_drawa.S", "r_edgea.S",
"r_varsa.S", "snd_mixa.S", "surf8.S", "surf16.S", "sys_wina.S", "worlda.S"
}
-- select variants
compile_gcc{"sys_sdl.c"} -- SDL frontend
compile_gcc{"vid_sdl.c"} -- video and mouse from SDL
compile_gcc{"cd_null.c"} -- no CD audio
compile_gcc{"snd_sdl.c"} -- sound from SDL
compile_gcc{"net_none.c"} -- no network
link_gcc("sdlquake")
/contrib/other/sdlquake-1.0.9/WinQuake.dsp
0,0 → 1,2240
# Microsoft Developer Studio Project File - Name="winquake" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
 
# TARGTYPE "Win32 (x86) Application" 0x0101
 
CFG=winquake - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "WinQuake.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "WinQuake.mak" CFG="winquake - Win32 Release"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "winquake - Win32 Release" (based on "Win32 (x86) Application")
!MESSAGE "winquake - Win32 Debug" (based on "Win32 (x86) Application")
!MESSAGE "winquake - Win32 GL Debug" (based on "Win32 (x86) Application")
!MESSAGE "winquake - Win32 GL Release" (based on "Win32 (x86) Application")
!MESSAGE
 
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir ".\Release"
# PROP BASE Intermediate_Dir ".\Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ".\Release"
# PROP Intermediate_Dir ".\Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /G5 /GX /Ox /Ot /Ow /I ".\scitech\include" /I ".\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR /YX /FD /c
# SUBTRACT CPP /Oa /Og
# ADD BASE MTL /nologo /D "NDEBUG" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
# ADD LINK32 .\dxsdk\sdk\lib\dxguid.lib .\scitech\lib\win32\vc\mgllt.lib winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /machine:I386
# SUBTRACT LINK32 /map /debug
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir ".\Debug"
# PROP BASE Intermediate_Dir ".\Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ".\Debug"
# PROP Intermediate_Dir ".\Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /G5 /ML /GX /ZI /Od /I ".\scitech\include" /I ".\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
# ADD BASE MTL /nologo /D "_DEBUG" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
# ADD LINK32 .\dxsdk\sdk\lib\dxguid.lib .\scitech\lib\win32\vc\mgllt.lib winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
# SUBTRACT LINK32 /nodefaultlib
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir ".\winquake"
# PROP BASE Intermediate_Dir ".\winquake"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ".\debug_gl"
# PROP Intermediate_Dir ".\debug_gl"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /G5 /ML /GX /Zi /Od /I ".\scitech\include" /I ".\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /G5 /ML /GX /ZI /Od /I ".\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "GLQUAKE" /FR /YX /FD /c
# ADD BASE MTL /nologo /D "_DEBUG" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib .\scitech\lib\win32\vc\mgllt.lib /nologo /subsystem:windows /debug /machine:I386
# SUBTRACT BASE LINK32 /nodefaultlib
# ADD LINK32 .\dxsdk\sdk\lib\dxguid.lib comctl32.lib winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /out:".\debug_gl\glquake.exe"
# SUBTRACT LINK32 /nodefaultlib
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir ".\winquak0"
# PROP BASE Intermediate_Dir ".\winquak0"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ".\release_gl"
# PROP Intermediate_Dir ".\release_gl"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /G5 /GX /Ox /Ot /Ow /I ".\scitech\include" /I ".\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
# SUBTRACT BASE CPP /Oa /Og
# ADD CPP /nologo /G5 /GX /Ot /Ow /I ".\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "GLQUAKE" /FR /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib .\scitech\lib\win32\vc\mgllt.lib /nologo /subsystem:windows /profile /machine:I386
# SUBTRACT BASE LINK32 /map /debug
# ADD LINK32 .\dxsdk\sdk\lib\dxguid.lib comctl32.lib winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /machine:I386 /out:".\release_gl\glquake.exe"
# SUBTRACT LINK32 /map /debug
 
!ENDIF
 
# Begin Target
 
# Name "winquake - Win32 Release"
# Name "winquake - Win32 Debug"
# Name "winquake - Win32 GL Debug"
# Name "winquake - Win32 GL Release"
# Begin Group "Source Files"
 
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
# Begin Source File
 
SOURCE=.\cd_win.c
# End Source File
# Begin Source File
 
SOURCE=.\chase.c
# End Source File
# Begin Source File
 
SOURCE=.\cl_demo.c
# End Source File
# Begin Source File
 
SOURCE=.\cl_input.c
# End Source File
# Begin Source File
 
SOURCE=.\cl_main.c
# End Source File
# Begin Source File
 
SOURCE=.\cl_parse.c
# End Source File
# Begin Source File
 
SOURCE=.\cl_tent.c
# End Source File
# Begin Source File
 
SOURCE=.\cmd.c
# End Source File
# Begin Source File
 
SOURCE=.\common.c
# End Source File
# Begin Source File
 
SOURCE=.\conproc.c
# End Source File
# Begin Source File
 
SOURCE=.\console.c
# End Source File
# Begin Source File
 
SOURCE=.\crc.c
# End Source File
# Begin Source File
 
SOURCE=.\cvar.c
# End Source File
# Begin Source File
 
SOURCE=.\d_draw.s
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Release
InputPath=.\d_draw.s
InputName=d_draw
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Debug
InputPath=.\d_draw.s
InputName=d_draw
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\d_draw16.s
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Release
InputPath=.\d_draw16.s
InputName=d_draw16
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Debug
InputPath=.\d_draw16.s
InputName=d_draw16
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\d_edge.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\d_fill.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\d_init.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\d_modech.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\d_part.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\d_parta.s
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Release
InputPath=.\d_parta.s
InputName=d_parta
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Debug
InputPath=.\d_parta.s
InputName=d_parta
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\d_polysa.s
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Release
InputPath=.\d_polysa.s
InputName=d_polysa
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Debug
InputPath=.\d_polysa.s
InputName=d_polysa
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\d_polyse.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\d_scan.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\d_scana.s
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Release
InputPath=.\d_scana.s
InputName=d_scana
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Debug
InputPath=.\d_scana.s
InputName=d_scana
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\d_sky.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\d_spr8.s
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Release
InputPath=.\d_spr8.s
InputName=d_spr8
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Debug
InputPath=.\d_spr8.s
InputName=d_spr8
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\d_sprite.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\d_surf.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\d_vars.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\d_varsa.s
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Release
InputPath=.\d_varsa.s
InputName=d_varsa
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Debug
InputPath=.\d_varsa.s
InputName=d_varsa
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\d_zpoint.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\draw.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\gl_draw.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\gl_mesh.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\gl_model.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\gl_refrag.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\gl_rlight.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\gl_rmain.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\gl_rmisc.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\gl_rsurf.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\gl_screen.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\gl_test.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\gl_vidnt.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\gl_warp.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\host.c
# End Source File
# Begin Source File
 
SOURCE=.\host_cmd.c
# End Source File
# Begin Source File
 
SOURCE=.\in_win.c
# End Source File
# Begin Source File
 
SOURCE=.\keys.c
# End Source File
# Begin Source File
 
SOURCE=.\math.s
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Release
InputPath=.\math.s
InputName=math
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Debug
InputPath=.\math.s
InputName=math
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# Begin Custom Build - mycoolbuild
OutDir=.\debug_gl
InputPath=.\math.s
InputName=math
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# Begin Custom Build - mycoolbuild
OutDir=.\release_gl
InputPath=.\math.s
InputName=math
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\mathlib.c
# End Source File
# Begin Source File
 
SOURCE=.\menu.c
# End Source File
# Begin Source File
 
SOURCE=.\model.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\net_dgrm.c
# End Source File
# Begin Source File
 
SOURCE=.\net_loop.c
# End Source File
# Begin Source File
 
SOURCE=.\net_main.c
# End Source File
# Begin Source File
 
SOURCE=.\net_vcr.c
# End Source File
# Begin Source File
 
SOURCE=.\net_win.c
# End Source File
# Begin Source File
 
SOURCE=.\net_wins.c
# End Source File
# Begin Source File
 
SOURCE=.\net_wipx.c
# End Source File
# Begin Source File
 
SOURCE=.\pr_cmds.c
# End Source File
# Begin Source File
 
SOURCE=.\pr_edict.c
# End Source File
# Begin Source File
 
SOURCE=.\pr_exec.c
# End Source File
# Begin Source File
 
SOURCE=.\r_aclip.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\r_aclipa.s
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Release
InputPath=.\r_aclipa.s
InputName=r_aclipa
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Debug
InputPath=.\r_aclipa.s
InputName=r_aclipa
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\r_alias.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\r_aliasa.s
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Release
InputPath=.\r_aliasa.s
InputName=r_aliasa
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Debug
InputPath=.\r_aliasa.s
InputName=r_aliasa
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\r_bsp.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\r_draw.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\r_drawa.s
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Release
InputPath=.\r_drawa.s
InputName=r_drawa
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Debug
InputPath=.\r_drawa.s
InputName=r_drawa
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\r_edge.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\r_edgea.s
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Release
InputPath=.\r_edgea.s
InputName=r_edgea
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Debug
InputPath=.\r_edgea.s
InputName=r_edgea
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\r_efrag.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\r_light.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\r_main.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\r_misc.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\r_part.c
# End Source File
# Begin Source File
 
SOURCE=.\r_sky.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\r_sprite.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\r_surf.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\r_vars.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\r_varsa.s
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Release
InputPath=.\r_varsa.s
InputName=r_varsa
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Debug
InputPath=.\r_varsa.s
InputName=r_varsa
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\sbar.c
# End Source File
# Begin Source File
 
SOURCE=.\screen.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\snd_dma.c
# End Source File
# Begin Source File
 
SOURCE=.\snd_mem.c
# End Source File
# Begin Source File
 
SOURCE=.\snd_mix.c
# End Source File
# Begin Source File
 
SOURCE=.\snd_mixa.s
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Release
InputPath=.\snd_mixa.s
InputName=snd_mixa
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Debug
InputPath=.\snd_mixa.s
InputName=snd_mixa
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# Begin Custom Build - mycoolbuild
OutDir=.\debug_gl
InputPath=.\snd_mixa.s
InputName=snd_mixa
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# Begin Custom Build - mycoolbuild
OutDir=.\release_gl
InputPath=.\snd_mixa.s
InputName=snd_mixa
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\snd_win.c
# End Source File
# Begin Source File
 
SOURCE=.\surf16.s
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Release
InputPath=.\surf16.s
InputName=surf16
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Debug
InputPath=.\surf16.s
InputName=surf16
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\surf8.s
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Release
InputPath=.\surf8.s
InputName=surf8
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Debug
InputPath=.\surf8.s
InputName=surf8
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\sv_main.c
# End Source File
# Begin Source File
 
SOURCE=.\sv_move.c
# End Source File
# Begin Source File
 
SOURCE=.\sv_phys.c
# End Source File
# Begin Source File
 
SOURCE=.\sv_user.c
# End Source File
# Begin Source File
 
SOURCE=.\sys_win.c
# End Source File
# Begin Source File
 
SOURCE=.\sys_wina.s
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Release
InputPath=.\sys_wina.s
InputName=sys_wina
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Debug
InputPath=.\sys_wina.s
InputName=sys_wina
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# Begin Custom Build - mycoolbuild
OutDir=.\debug_gl
InputPath=.\sys_wina.s
InputName=sys_wina
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# Begin Custom Build - mycoolbuild
OutDir=.\release_gl
InputPath=.\sys_wina.s
InputName=sys_wina
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\vid_win.c
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# PROP Exclude_From_Build 1
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# PROP Exclude_From_Build 1
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\view.c
# End Source File
# Begin Source File
 
SOURCE=.\wad.c
# End Source File
# Begin Source File
 
SOURCE=.\winquake.rc
# End Source File
# Begin Source File
 
SOURCE=.\world.c
# End Source File
# Begin Source File
 
SOURCE=.\worlda.s
 
!IF "$(CFG)" == "winquake - Win32 Release"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Release
InputPath=.\worlda.s
InputName=worlda
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 Debug"
 
# Begin Custom Build - mycoolbuild
OutDir=.\Debug
InputPath=.\worlda.s
InputName=worlda
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug"
 
# Begin Custom Build - mycoolbuild
OutDir=.\debug_gl
InputPath=.\worlda.s
InputName=worlda
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ELSEIF "$(CFG)" == "winquake - Win32 GL Release"
 
# Begin Custom Build - mycoolbuild
OutDir=.\release_gl
InputPath=.\worlda.s
InputName=worlda
 
"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath)
gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm
ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm
del $(OUTDIR)\$(InputName).spp
# End Custom Build
 
!ENDIF
 
# End Source File
# Begin Source File
 
SOURCE=.\zone.c
# End Source File
# End Group
# Begin Group "Header Files"
 
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
# Begin Source File
 
SOURCE=.\anorm_dots.h
# End Source File
# Begin Source File
 
SOURCE=.\anorms.h
# End Source File
# Begin Source File
 
SOURCE=.\bspfile.h
# End Source File
# Begin Source File
 
SOURCE=.\cdaudio.h
# End Source File
# Begin Source File
 
SOURCE=.\client.h
# End Source File
# Begin Source File
 
SOURCE=.\cmd.h
# End Source File
# Begin Source File
 
SOURCE=.\common.h
# End Source File
# Begin Source File
 
SOURCE=.\conproc.h
# End Source File
# Begin Source File
 
SOURCE=.\console.h
# End Source File
# Begin Source File
 
SOURCE=.\crc.h
# End Source File
# Begin Source File
 
SOURCE=.\cvar.h
# End Source File
# Begin Source File
 
SOURCE=.\d_iface.h
# End Source File
# Begin Source File
 
SOURCE=.\dosisms.h
# End Source File
# Begin Source File
 
SOURCE=.\draw.h
# End Source File
# Begin Source File
 
SOURCE=.\gl_model.h
# End Source File
# Begin Source File
 
SOURCE=.\gl_warp_sin.h
# End Source File
# Begin Source File
 
SOURCE=.\glquake.h
# End Source File
# Begin Source File
 
SOURCE=.\input.h
# End Source File
# Begin Source File
 
SOURCE=.\keys.h
# End Source File
# Begin Source File
 
SOURCE=.\mathlib.h
# End Source File
# Begin Source File
 
SOURCE=.\menu.h
# End Source File
# Begin Source File
 
SOURCE=.\model.h
# End Source File
# Begin Source File
 
SOURCE=.\modelgen.h
# End Source File
# Begin Source File
 
SOURCE=.\net.h
# End Source File
# Begin Source File
 
SOURCE=.\net_dgrm.h
# End Source File
# Begin Source File
 
SOURCE=.\net_loop.h
# End Source File
# Begin Source File
 
SOURCE=.\net_ser.h
# End Source File
# Begin Source File
 
SOURCE=.\net_vcr.h
# End Source File
# Begin Source File
 
SOURCE=.\net_wins.h
# End Source File
# Begin Source File
 
SOURCE=.\net_wipx.h
# End Source File
# Begin Source File
 
SOURCE=.\pr_comp.h
# End Source File
# Begin Source File
 
SOURCE=.\progdefs.h
# End Source File
# Begin Source File
 
SOURCE=.\progs.h
# End Source File
# Begin Source File
 
SOURCE=.\protocol.h
# End Source File
# Begin Source File
 
SOURCE=.\quakedef.h
# End Source File
# Begin Source File
 
SOURCE=.\r_local.h
# End Source File
# Begin Source File
 
SOURCE=.\r_shared.h
# End Source File
# Begin Source File
 
SOURCE=.\render.h
# End Source File
# Begin Source File
 
SOURCE=.\sbar.h
# End Source File
# Begin Source File
 
SOURCE=.\screen.h
# End Source File
# Begin Source File
 
SOURCE=.\server.h
# End Source File
# Begin Source File
 
SOURCE=.\sound.h
# End Source File
# Begin Source File
 
SOURCE=.\spritegn.h
# End Source File
# Begin Source File
 
SOURCE=.\sys.h
# End Source File
# Begin Source File
 
SOURCE=.\vid.h
# End Source File
# Begin Source File
 
SOURCE=.\view.h
# End Source File
# Begin Source File
 
SOURCE=.\wad.h
# End Source File
# Begin Source File
 
SOURCE=.\winquake.h
# End Source File
# Begin Source File
 
SOURCE=.\world.h
# End Source File
# Begin Source File
 
SOURCE=.\zone.h
# End Source File
# End Group
# Begin Group "Resource Files"
 
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
# Begin Source File
 
SOURCE=.\qe3.ico
# End Source File
# Begin Source File
 
SOURCE=.\quake.ico
# End Source File
# End Group
# Begin Source File
 
SOURCE=.\progdefs.q1
# End Source File
# Begin Source File
 
SOURCE=.\progdefs.q2
# End Source File
# End Target
# End Project
/contrib/other/sdlquake-1.0.9/WinQuake.dsw
0,0 → 1,44
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
 
###############################################################################
 
Project: "gas2masm"=.\gas2masm\gas2masm.dsp - Package Owner=<4>
 
Package=<5>
{{{
}}}
 
Package=<4>
{{{
}}}
 
###############################################################################
 
Project: "winquake"=.\WinQuake.dsp - Package Owner=<4>
 
Package=<5>
{{{
}}}
 
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name gas2masm
End Project Dependency
}}}
 
###############################################################################
 
Global:
 
Package=<5>
{{{
}}}
 
Package=<3>
{{{
}}}
 
###############################################################################
 
/contrib/other/sdlquake-1.0.9/acinclude.m4
0,0 → 1,165
# Configure paths for SDL
# Sam Lantinga 9/21/99
# stolen from Manish Singh
# stolen back from Frank Belew
# stolen from Manish Singh
# Shamelessly stolen from Owen Taylor
 
dnl AM_PATH_SDL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS
dnl
AC_DEFUN(AM_PATH_SDL,
[dnl
dnl Get the cflags and libraries from the sdl-config script
dnl
AC_ARG_WITH(sdl-prefix,[ --with-sdl-prefix=PFX Prefix where SDL is installed (optional)],
sdl_prefix="$withval", sdl_prefix="")
AC_ARG_WITH(sdl-exec-prefix,[ --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional)],
sdl_exec_prefix="$withval", sdl_exec_prefix="")
AC_ARG_ENABLE(sdltest, [ --disable-sdltest Do not try to compile and run a test SDL program],
, enable_sdltest=yes)
 
if test x$sdl_exec_prefix != x ; then
sdl_args="$sdl_args --exec-prefix=$sdl_exec_prefix"
if test x${SDL_CONFIG+set} != xset ; then
SDL_CONFIG=$sdl_exec_prefix/bin/sdl-config
fi
fi
if test x$sdl_prefix != x ; then
sdl_args="$sdl_args --prefix=$sdl_prefix"
if test x${SDL_CONFIG+set} != xset ; then
SDL_CONFIG=$sdl_prefix/bin/sdl-config
fi
fi
 
AC_PATH_PROG(SDL_CONFIG, sdl-config, no)
min_sdl_version=ifelse([$1], ,0.11.0,$1)
AC_MSG_CHECKING(for SDL - version >= $min_sdl_version)
no_sdl=""
if test "$SDL_CONFIG" = "no" ; then
no_sdl=yes
else
SDL_CFLAGS=`$SDL_CONFIG $sdlconf_args --cflags`
SDL_LIBS=`$SDL_CONFIG $sdlconf_args --libs`
 
sdl_major_version=`$SDL_CONFIG $sdl_args --version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
sdl_minor_version=`$SDL_CONFIG $sdl_args --version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
sdl_micro_version=`$SDL_CONFIG $sdl_config_args --version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
if test "x$enable_sdltest" = "xyes" ; then
ac_save_CFLAGS="$CFLAGS"
ac_save_LIBS="$LIBS"
CFLAGS="$CFLAGS $SDL_CFLAGS"
LIBS="$LIBS $SDL_LIBS"
dnl
dnl Now check if the installed SDL is sufficiently new. (Also sanity
dnl checks the results of sdl-config to some extent
dnl
rm -f conf.sdltest
AC_TRY_RUN([
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SDL.h"
 
char*
my_strdup (char *str)
{
char *new_str;
if (str)
{
new_str = malloc ((strlen (str) + 1) * sizeof(char));
strcpy (new_str, str);
}
else
new_str = NULL;
return new_str;
}
 
int main ()
{
int major, minor, micro;
char *tmp_version;
 
system ("touch conf.sdltest");
 
/* HP/UX 9 (%@#!) writes to sscanf strings */
tmp_version = my_strdup("$min_sdl_version");
if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
printf("%s, bad version string\n", "$min_sdl_version");
exit(1);
}
 
if (($sdl_major_version > major) ||
(($sdl_major_version == major) && ($sdl_minor_version > minor)) ||
(($sdl_major_version == major) && ($sdl_minor_version == minor) && ($sdl_micro_version >= micro)))
{
return 0;
}
else
{
printf("\n*** 'sdl-config --version' returned %d.%d.%d, but the minimum version\n", $sdl_major_version, $sdl_minor_version, $sdl_micro_version);
printf("*** of SDL required is %d.%d.%d. If sdl-config is correct, then it is\n", major, minor, micro);
printf("*** best to upgrade to the required version.\n");
printf("*** If sdl-config was wrong, set the environment variable SDL_CONFIG\n");
printf("*** to point to the correct copy of sdl-config, and remove the file\n");
printf("*** config.cache before re-running configure\n");
return 1;
}
}
 
],, no_sdl=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
fi
if test "x$no_sdl" = x ; then
AC_MSG_RESULT(yes)
ifelse([$2], , :, [$2])
else
AC_MSG_RESULT(no)
if test "$SDL_CONFIG" = "no" ; then
echo "*** The sdl-config script installed by SDL could not be found"
echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in"
echo "*** your path, or set the SDL_CONFIG environment variable to the"
echo "*** full path to sdl-config."
else
if test -f conf.sdltest ; then
:
else
echo "*** Could not run SDL test program, checking why..."
CFLAGS="$CFLAGS $SDL_CFLAGS"
LIBS="$LIBS $SDL_LIBS"
AC_TRY_LINK([
#include <stdio.h>
#include "SDL.h"
], [ return 0; ],
[ echo "*** The test program compiled, but did not run. This usually means"
echo "*** that the run-time linker is not finding SDL or finding the wrong"
echo "*** version of SDL. If it is not finding SDL, you'll need to set your"
echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
echo "*** to the installed location Also, make sure you have run ldconfig if that"
echo "*** is required on your system"
echo "***"
echo "*** If you have an old version installed, it is best to remove it, although"
echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
[ echo "*** The test program failed to compile or link. See the file config.log for the"
echo "*** exact error that occured. This usually means SDL was incorrectly installed"
echo "*** or that you have moved SDL since it was installed. In the latter case, you"
echo "*** may want to edit the sdl-config script: $SDL_CONFIG" ])
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
fi
SDL_CFLAGS=""
SDL_LIBS=""
ifelse([$3], , :, [$3])
fi
AC_SUBST(SDL_CFLAGS)
AC_SUBST(SDL_LIBS)
rm -f conf.sdltest
])
/contrib/other/sdlquake-1.0.9/aclocal.m4
0,0 → 1,270
dnl aclocal.m4 generated automatically by aclocal 1.4
 
dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
 
dnl This program is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
dnl PARTICULAR PURPOSE.
 
# Configure paths for SDL
# Sam Lantinga 9/21/99
# stolen from Manish Singh
# stolen back from Frank Belew
# stolen from Manish Singh
# Shamelessly stolen from Owen Taylor
 
dnl AM_PATH_SDL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS
dnl
AC_DEFUN(AM_PATH_SDL,
[dnl
dnl Get the cflags and libraries from the sdl-config script
dnl
AC_ARG_WITH(sdl-prefix,[ --with-sdl-prefix=PFX Prefix where SDL is installed (optional)],
sdl_prefix="$withval", sdl_prefix="")
AC_ARG_WITH(sdl-exec-prefix,[ --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional)],
sdl_exec_prefix="$withval", sdl_exec_prefix="")
AC_ARG_ENABLE(sdltest, [ --disable-sdltest Do not try to compile and run a test SDL program],
, enable_sdltest=yes)
 
if test x$sdl_exec_prefix != x ; then
sdl_args="$sdl_args --exec-prefix=$sdl_exec_prefix"
if test x${SDL_CONFIG+set} != xset ; then
SDL_CONFIG=$sdl_exec_prefix/bin/sdl-config
fi
fi
if test x$sdl_prefix != x ; then
sdl_args="$sdl_args --prefix=$sdl_prefix"
if test x${SDL_CONFIG+set} != xset ; then
SDL_CONFIG=$sdl_prefix/bin/sdl-config
fi
fi
 
AC_PATH_PROG(SDL_CONFIG, sdl-config, no)
min_sdl_version=ifelse([$1], ,0.11.0,$1)
AC_MSG_CHECKING(for SDL - version >= $min_sdl_version)
no_sdl=""
if test "$SDL_CONFIG" = "no" ; then
no_sdl=yes
else
SDL_CFLAGS=`$SDL_CONFIG $sdlconf_args --cflags`
SDL_LIBS=`$SDL_CONFIG $sdlconf_args --libs`
 
sdl_major_version=`$SDL_CONFIG $sdl_args --version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
sdl_minor_version=`$SDL_CONFIG $sdl_args --version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
sdl_micro_version=`$SDL_CONFIG $sdl_config_args --version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
if test "x$enable_sdltest" = "xyes" ; then
ac_save_CFLAGS="$CFLAGS"
ac_save_LIBS="$LIBS"
CFLAGS="$CFLAGS $SDL_CFLAGS"
LIBS="$LIBS $SDL_LIBS"
dnl
dnl Now check if the installed SDL is sufficiently new. (Also sanity
dnl checks the results of sdl-config to some extent
dnl
rm -f conf.sdltest
AC_TRY_RUN([
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SDL.h"
 
char*
my_strdup (char *str)
{
char *new_str;
if (str)
{
new_str = malloc ((strlen (str) + 1) * sizeof(char));
strcpy (new_str, str);
}
else
new_str = NULL;
return new_str;
}
 
int main ()
{
int major, minor, micro;
char *tmp_version;
 
system ("touch conf.sdltest");
 
/* HP/UX 9 (%@#!) writes to sscanf strings */
tmp_version = my_strdup("$min_sdl_version");
if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
printf("%s, bad version string\n", "$min_sdl_version");
exit(1);
}
 
if (($sdl_major_version > major) ||
(($sdl_major_version == major) && ($sdl_minor_version > minor)) ||
(($sdl_major_version == major) && ($sdl_minor_version == minor) && ($sdl_micro_version >= micro)))
{
return 0;
}
else
{
printf("\n*** 'sdl-config --version' returned %d.%d.%d, but the minimum version\n", $sdl_major_version, $sdl_minor_version, $sdl_micro_version);
printf("*** of SDL required is %d.%d.%d. If sdl-config is correct, then it is\n", major, minor, micro);
printf("*** best to upgrade to the required version.\n");
printf("*** If sdl-config was wrong, set the environment variable SDL_CONFIG\n");
printf("*** to point to the correct copy of sdl-config, and remove the file\n");
printf("*** config.cache before re-running configure\n");
return 1;
}
}
 
],, no_sdl=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
fi
if test "x$no_sdl" = x ; then
AC_MSG_RESULT(yes)
ifelse([$2], , :, [$2])
else
AC_MSG_RESULT(no)
if test "$SDL_CONFIG" = "no" ; then
echo "*** The sdl-config script installed by SDL could not be found"
echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in"
echo "*** your path, or set the SDL_CONFIG environment variable to the"
echo "*** full path to sdl-config."
else
if test -f conf.sdltest ; then
:
else
echo "*** Could not run SDL test program, checking why..."
CFLAGS="$CFLAGS $SDL_CFLAGS"
LIBS="$LIBS $SDL_LIBS"
AC_TRY_LINK([
#include <stdio.h>
#include "SDL.h"
], [ return 0; ],
[ echo "*** The test program compiled, but did not run. This usually means"
echo "*** that the run-time linker is not finding SDL or finding the wrong"
echo "*** version of SDL. If it is not finding SDL, you'll need to set your"
echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
echo "*** to the installed location Also, make sure you have run ldconfig if that"
echo "*** is required on your system"
echo "***"
echo "*** If you have an old version installed, it is best to remove it, although"
echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
[ echo "*** The test program failed to compile or link. See the file config.log for the"
echo "*** exact error that occured. This usually means SDL was incorrectly installed"
echo "*** or that you have moved SDL since it was installed. In the latter case, you"
echo "*** may want to edit the sdl-config script: $SDL_CONFIG" ])
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
fi
SDL_CFLAGS=""
SDL_LIBS=""
ifelse([$3], , :, [$3])
fi
AC_SUBST(SDL_CFLAGS)
AC_SUBST(SDL_LIBS)
rm -f conf.sdltest
])
 
# Do all the work for Automake. This macro actually does too much --
# some checks are only needed if your package does certain things.
# But this isn't really a big deal.
 
# serial 1
 
dnl Usage:
dnl AM_INIT_AUTOMAKE(package,version, [no-define])
 
AC_DEFUN(AM_INIT_AUTOMAKE,
[AC_REQUIRE([AC_PROG_INSTALL])
PACKAGE=[$1]
AC_SUBST(PACKAGE)
VERSION=[$2]
AC_SUBST(VERSION)
dnl test to see if srcdir already configured
if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
fi
ifelse([$3],,
AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]))
AC_REQUIRE([AM_SANITY_CHECK])
AC_REQUIRE([AC_ARG_PROGRAM])
dnl FIXME This is truly gross.
missing_dir=`cd $ac_aux_dir && pwd`
AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
AC_REQUIRE([AC_PROG_MAKE_SET])])
 
#
# Check to make sure that the build environment is sane.
#
 
AC_DEFUN(AM_SANITY_CHECK,
[AC_MSG_CHECKING([whether build environment is sane])
# Just in case
sleep 1
echo timestamp > conftestfile
# Do `set' in a subshell so we don't clobber the current shell's
# arguments. Must try -L first in case configure is actually a
# symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing
# directory).
if (
set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
if test "[$]*" = "X"; then
# -L didn't work.
set X `ls -t $srcdir/configure conftestfile`
fi
if test "[$]*" != "X $srcdir/configure conftestfile" \
&& test "[$]*" != "X conftestfile $srcdir/configure"; then
 
# If neither matched, then we have a broken ls. This can happen
# if, for instance, CONFIG_SHELL is bash and it inherits a
# broken ls alias from the environment. This has actually
# happened. Such a system could not be considered "sane".
AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
alias in your environment])
fi
 
test "[$]2" = conftestfile
)
then
# Ok.
:
else
AC_MSG_ERROR([newly created file is older than distributed files!
Check your system clock])
fi
rm -f conftest*
AC_MSG_RESULT(yes)])
 
dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
dnl The program must properly implement --version.
AC_DEFUN(AM_MISSING_PROG,
[AC_MSG_CHECKING(for working $2)
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
if ($2 --version) < /dev/null > /dev/null 2>&1; then
$1=$2
AC_MSG_RESULT(found)
else
$1="$3/missing $2"
AC_MSG_RESULT(missing)
fi
AC_SUBST($1)])
 
/contrib/other/sdlquake-1.0.9/adivtab.h
0,0 → 1,1077
/*
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.
 
*/
// table of quotients and remainders for [-15...16] / [-15...16]
 
// numerator = -15
{1, 0},
{1, -1},
{1, -2},
{1, -3},
{1, -4},
{1, -5},
{1, -6},
{1, -7},
{2, -1},
{2, -3},
{3, 0},
{3, -3},
{5, 0},
{7, -1},
{15, 0},
{0, 0},
{-15, 0},
{-8, 1},
{-5, 0},
{-4, 1},
{-3, 0},
{-3, 3},
{-3, 6},
{-2, 1},
{-2, 3},
{-2, 5},
{-2, 7},
{-2, 9},
{-2, 11},
{-2, 13},
{-1, 0},
{-1, 1},
// numerator = -14
{0, -14},
{1, 0},
{1, -1},
{1, -2},
{1, -3},
{1, -4},
{1, -5},
{1, -6},
{2, 0},
{2, -2},
{2, -4},
{3, -2},
{4, -2},
{7, 0},
{14, 0},
{0, 0},
{-14, 0},
{-7, 0},
{-5, 1},
{-4, 2},
{-3, 1},
{-3, 4},
{-2, 0},
{-2, 2},
{-2, 4},
{-2, 6},
{-2, 8},
{-2, 10},
{-2, 12},
{-1, 0},
{-1, 1},
{-1, 2},
// numerator = -13
{0, -13},
{0, -13},
{1, 0},
{1, -1},
{1, -2},
{1, -3},
{1, -4},
{1, -5},
{1, -6},
{2, -1},
{2, -3},
{3, -1},
{4, -1},
{6, -1},
{13, 0},
{0, 0},
{-13, 0},
{-7, 1},
{-5, 2},
{-4, 3},
{-3, 2},
{-3, 5},
{-2, 1},
{-2, 3},
{-2, 5},
{-2, 7},
{-2, 9},
{-2, 11},
{-1, 0},
{-1, 1},
{-1, 2},
{-1, 3},
// numerator = -12
{0, -12},
{0, -12},
{0, -12},
{1, 0},
{1, -1},
{1, -2},
{1, -3},
{1, -4},
{1, -5},
{2, 0},
{2, -2},
{3, 0},
{4, 0},
{6, 0},
{12, 0},
{0, 0},
{-12, 0},
{-6, 0},
{-4, 0},
{-3, 0},
{-3, 3},
{-2, 0},
{-2, 2},
{-2, 4},
{-2, 6},
{-2, 8},
{-2, 10},
{-1, 0},
{-1, 1},
{-1, 2},
{-1, 3},
{-1, 4},
// numerator = -11
{0, -11},
{0, -11},
{0, -11},
{0, -11},
{1, 0},
{1, -1},
{1, -2},
{1, -3},
{1, -4},
{1, -5},
{2, -1},
{2, -3},
{3, -2},
{5, -1},
{11, 0},
{0, 0},
{-11, 0},
{-6, 1},
{-4, 1},
{-3, 1},
{-3, 4},
{-2, 1},
{-2, 3},
{-2, 5},
{-2, 7},
{-2, 9},
{-1, 0},
{-1, 1},
{-1, 2},
{-1, 3},
{-1, 4},
{-1, 5},
// numerator = -10
{0, -10},
{0, -10},
{0, -10},
{0, -10},
{0, -10},
{1, 0},
{1, -1},
{1, -2},
{1, -3},
{1, -4},
{2, 0},
{2, -2},
{3, -1},
{5, 0},
{10, 0},
{0, 0},
{-10, 0},
{-5, 0},
{-4, 2},
{-3, 2},
{-2, 0},
{-2, 2},
{-2, 4},
{-2, 6},
{-2, 8},
{-1, 0},
{-1, 1},
{-1, 2},
{-1, 3},
{-1, 4},
{-1, 5},
{-1, 6},
// numerator = -9
{0, -9},
{0, -9},
{0, -9},
{0, -9},
{0, -9},
{0, -9},
{1, 0},
{1, -1},
{1, -2},
{1, -3},
{1, -4},
{2, -1},
{3, 0},
{4, -1},
{9, 0},
{0, 0},
{-9, 0},
{-5, 1},
{-3, 0},
{-3, 3},
{-2, 1},
{-2, 3},
{-2, 5},
{-2, 7},
{-1, 0},
{-1, 1},
{-1, 2},
{-1, 3},
{-1, 4},
{-1, 5},
{-1, 6},
{-1, 7},
// numerator = -8
{0, -8},
{0, -8},
{0, -8},
{0, -8},
{0, -8},
{0, -8},
{0, -8},
{1, 0},
{1, -1},
{1, -2},
{1, -3},
{2, 0},
{2, -2},
{4, 0},
{8, 0},
{0, 0},
{-8, 0},
{-4, 0},
{-3, 1},
{-2, 0},
{-2, 2},
{-2, 4},
{-2, 6},
{-1, 0},
{-1, 1},
{-1, 2},
{-1, 3},
{-1, 4},
{-1, 5},
{-1, 6},
{-1, 7},
{-1, 8},
// numerator = -7
{0, -7},
{0, -7},
{0, -7},
{0, -7},
{0, -7},
{0, -7},
{0, -7},
{0, -7},
{1, 0},
{1, -1},
{1, -2},
{1, -3},
{2, -1},
{3, -1},
{7, 0},
{0, 0},
{-7, 0},
{-4, 1},
{-3, 2},
{-2, 1},
{-2, 3},
{-2, 5},
{-1, 0},
{-1, 1},
{-1, 2},
{-1, 3},
{-1, 4},
{-1, 5},
{-1, 6},
{-1, 7},
{-1, 8},
{-1, 9},
// numerator = -6
{0, -6},
{0, -6},
{0, -6},
{0, -6},
{0, -6},
{0, -6},
{0, -6},
{0, -6},
{0, -6},
{1, 0},
{1, -1},
{1, -2},
{2, 0},
{3, 0},
{6, 0},
{0, 0},
{-6, 0},
{-3, 0},
{-2, 0},
{-2, 2},
{-2, 4},
{-1, 0},
{-1, 1},
{-1, 2},
{-1, 3},
{-1, 4},
{-1, 5},
{-1, 6},
{-1, 7},
{-1, 8},
{-1, 9},
{-1, 10},
// numerator = -5
{0, -5},
{0, -5},
{0, -5},
{0, -5},
{0, -5},
{0, -5},
{0, -5},
{0, -5},
{0, -5},
{0, -5},
{1, 0},
{1, -1},
{1, -2},
{2, -1},
{5, 0},
{0, 0},
{-5, 0},
{-3, 1},
{-2, 1},
{-2, 3},
{-1, 0},
{-1, 1},
{-1, 2},
{-1, 3},
{-1, 4},
{-1, 5},
{-1, 6},
{-1, 7},
{-1, 8},
{-1, 9},
{-1, 10},
{-1, 11},
// numerator = -4
{0, -4},
{0, -4},
{0, -4},
{0, -4},
{0, -4},
{0, -4},
{0, -4},
{0, -4},
{0, -4},
{0, -4},
{0, -4},
{1, 0},
{1, -1},
{2, 0},
{4, 0},
{0, 0},
{-4, 0},
{-2, 0},
{-2, 2},
{-1, 0},
{-1, 1},
{-1, 2},
{-1, 3},
{-1, 4},
{-1, 5},
{-1, 6},
{-1, 7},
{-1, 8},
{-1, 9},
{-1, 10},
{-1, 11},
{-1, 12},
// numerator = -3
{0, -3},
{0, -3},
{0, -3},
{0, -3},
{0, -3},
{0, -3},
{0, -3},
{0, -3},
{0, -3},
{0, -3},
{0, -3},
{0, -3},
{1, 0},
{1, -1},
{3, 0},
{0, 0},
{-3, 0},
{-2, 1},
{-1, 0},
{-1, 1},
{-1, 2},
{-1, 3},
{-1, 4},
{-1, 5},
{-1, 6},
{-1, 7},
{-1, 8},
{-1, 9},
{-1, 10},
{-1, 11},
{-1, 12},
{-1, 13},
// numerator = -2
{0, -2},
{0, -2},
{0, -2},
{0, -2},
{0, -2},
{0, -2},
{0, -2},
{0, -2},
{0, -2},
{0, -2},
{0, -2},
{0, -2},
{0, -2},
{1, 0},
{2, 0},
{0, 0},
{-2, 0},
{-1, 0},
{-1, 1},
{-1, 2},
{-1, 3},
{-1, 4},
{-1, 5},
{-1, 6},
{-1, 7},
{-1, 8},
{-1, 9},
{-1, 10},
{-1, 11},
{-1, 12},
{-1, 13},
{-1, 14},
// numerator = -1
{0, -1},
{0, -1},
{0, -1},
{0, -1},
{0, -1},
{0, -1},
{0, -1},
{0, -1},
{0, -1},
{0, -1},
{0, -1},
{0, -1},
{0, -1},
{0, -1},
{1, 0},
{0, 0},
{-1, 0},
{-1, 1},
{-1, 2},
{-1, 3},
{-1, 4},
{-1, 5},
{-1, 6},
{-1, 7},
{-1, 8},
{-1, 9},
{-1, 10},
{-1, 11},
{-1, 12},
{-1, 13},
{-1, 14},
{-1, 15},
// numerator = 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},
{0, 0},
{0, 0},
{0, 0},
{0, 0},
{0, 0},
{0, 0},
{0, 0},
{0, 0},
{0, 0},
{0, 0},
// numerator = 1
{-1, -14},
{-1, -13},
{-1, -12},
{-1, -11},
{-1, -10},
{-1, -9},
{-1, -8},
{-1, -7},
{-1, -6},
{-1, -5},
{-1, -4},
{-1, -3},
{-1, -2},
{-1, -1},
{-1, 0},
{0, 0},
{1, 0},
{0, 1},
{0, 1},
{0, 1},
{0, 1},
{0, 1},
{0, 1},
{0, 1},
{0, 1},
{0, 1},
{0, 1},
{0, 1},
{0, 1},
{0, 1},
{0, 1},
{0, 1},
// numerator = 2
{-1, -13},
{-1, -12},
{-1, -11},
{-1, -10},
{-1, -9},
{-1, -8},
{-1, -7},
{-1, -6},
{-1, -5},
{-1, -4},
{-1, -3},
{-1, -2},
{-1, -1},
{-1, 0},
{-2, 0},
{0, 0},
{2, 0},
{1, 0},
{0, 2},
{0, 2},
{0, 2},
{0, 2},
{0, 2},
{0, 2},
{0, 2},
{0, 2},
{0, 2},
{0, 2},
{0, 2},
{0, 2},
{0, 2},
{0, 2},
// numerator = 3
{-1, -12},
{-1, -11},
{-1, -10},
{-1, -9},
{-1, -8},
{-1, -7},
{-1, -6},
{-1, -5},
{-1, -4},
{-1, -3},
{-1, -2},
{-1, -1},
{-1, 0},
{-2, -1},
{-3, 0},
{0, 0},
{3, 0},
{1, 1},
{1, 0},
{0, 3},
{0, 3},
{0, 3},
{0, 3},
{0, 3},
{0, 3},
{0, 3},
{0, 3},
{0, 3},
{0, 3},
{0, 3},
{0, 3},
{0, 3},
// numerator = 4
{-1, -11},
{-1, -10},
{-1, -9},
{-1, -8},
{-1, -7},
{-1, -6},
{-1, -5},
{-1, -4},
{-1, -3},
{-1, -2},
{-1, -1},
{-1, 0},
{-2, -2},
{-2, 0},
{-4, 0},
{0, 0},
{4, 0},
{2, 0},
{1, 1},
{1, 0},
{0, 4},
{0, 4},
{0, 4},
{0, 4},
{0, 4},
{0, 4},
{0, 4},
{0, 4},
{0, 4},
{0, 4},
{0, 4},
{0, 4},
// numerator = 5
{-1, -10},
{-1, -9},
{-1, -8},
{-1, -7},
{-1, -6},
{-1, -5},
{-1, -4},
{-1, -3},
{-1, -2},
{-1, -1},
{-1, 0},
{-2, -3},
{-2, -1},
{-3, -1},
{-5, 0},
{0, 0},
{5, 0},
{2, 1},
{1, 2},
{1, 1},
{1, 0},
{0, 5},
{0, 5},
{0, 5},
{0, 5},
{0, 5},
{0, 5},
{0, 5},
{0, 5},
{0, 5},
{0, 5},
{0, 5},
// numerator = 6
{-1, -9},
{-1, -8},
{-1, -7},
{-1, -6},
{-1, -5},
{-1, -4},
{-1, -3},
{-1, -2},
{-1, -1},
{-1, 0},
{-2, -4},
{-2, -2},
{-2, 0},
{-3, 0},
{-6, 0},
{0, 0},
{6, 0},
{3, 0},
{2, 0},
{1, 2},
{1, 1},
{1, 0},
{0, 6},
{0, 6},
{0, 6},
{0, 6},
{0, 6},
{0, 6},
{0, 6},
{0, 6},
{0, 6},
{0, 6},
// numerator = 7
{-1, -8},
{-1, -7},
{-1, -6},
{-1, -5},
{-1, -4},
{-1, -3},
{-1, -2},
{-1, -1},
{-1, 0},
{-2, -5},
{-2, -3},
{-2, -1},
{-3, -2},
{-4, -1},
{-7, 0},
{0, 0},
{7, 0},
{3, 1},
{2, 1},
{1, 3},
{1, 2},
{1, 1},
{1, 0},
{0, 7},
{0, 7},
{0, 7},
{0, 7},
{0, 7},
{0, 7},
{0, 7},
{0, 7},
{0, 7},
// numerator = 8
{-1, -7},
{-1, -6},
{-1, -5},
{-1, -4},
{-1, -3},
{-1, -2},
{-1, -1},
{-1, 0},
{-2, -6},
{-2, -4},
{-2, -2},
{-2, 0},
{-3, -1},
{-4, 0},
{-8, 0},
{0, 0},
{8, 0},
{4, 0},
{2, 2},
{2, 0},
{1, 3},
{1, 2},
{1, 1},
{1, 0},
{0, 8},
{0, 8},
{0, 8},
{0, 8},
{0, 8},
{0, 8},
{0, 8},
{0, 8},
// numerator = 9
{-1, -6},
{-1, -5},
{-1, -4},
{-1, -3},
{-1, -2},
{-1, -1},
{-1, 0},
{-2, -7},
{-2, -5},
{-2, -3},
{-2, -1},
{-3, -3},
{-3, 0},
{-5, -1},
{-9, 0},
{0, 0},
{9, 0},
{4, 1},
{3, 0},
{2, 1},
{1, 4},
{1, 3},
{1, 2},
{1, 1},
{1, 0},
{0, 9},
{0, 9},
{0, 9},
{0, 9},
{0, 9},
{0, 9},
{0, 9},
// numerator = 10
{-1, -5},
{-1, -4},
{-1, -3},
{-1, -2},
{-1, -1},
{-1, 0},
{-2, -8},
{-2, -6},
{-2, -4},
{-2, -2},
{-2, 0},
{-3, -2},
{-4, -2},
{-5, 0},
{-10, 0},
{0, 0},
{10, 0},
{5, 0},
{3, 1},
{2, 2},
{2, 0},
{1, 4},
{1, 3},
{1, 2},
{1, 1},
{1, 0},
{0, 10},
{0, 10},
{0, 10},
{0, 10},
{0, 10},
{0, 10},
// numerator = 11
{-1, -4},
{-1, -3},
{-1, -2},
{-1, -1},
{-1, 0},
{-2, -9},
{-2, -7},
{-2, -5},
{-2, -3},
{-2, -1},
{-3, -4},
{-3, -1},
{-4, -1},
{-6, -1},
{-11, 0},
{0, 0},
{11, 0},
{5, 1},
{3, 2},
{2, 3},
{2, 1},
{1, 5},
{1, 4},
{1, 3},
{1, 2},
{1, 1},
{1, 0},
{0, 11},
{0, 11},
{0, 11},
{0, 11},
{0, 11},
// numerator = 12
{-1, -3},
{-1, -2},
{-1, -1},
{-1, 0},
{-2, -10},
{-2, -8},
{-2, -6},
{-2, -4},
{-2, -2},
{-2, 0},
{-3, -3},
{-3, 0},
{-4, 0},
{-6, 0},
{-12, 0},
{0, 0},
{12, 0},
{6, 0},
{4, 0},
{3, 0},
{2, 2},
{2, 0},
{1, 5},
{1, 4},
{1, 3},
{1, 2},
{1, 1},
{1, 0},
{0, 12},
{0, 12},
{0, 12},
{0, 12},
// numerator = 13
{-1, -2},
{-1, -1},
{-1, 0},
{-2, -11},
{-2, -9},
{-2, -7},
{-2, -5},
{-2, -3},
{-2, -1},
{-3, -5},
{-3, -2},
{-4, -3},
{-5, -2},
{-7, -1},
{-13, 0},
{0, 0},
{13, 0},
{6, 1},
{4, 1},
{3, 1},
{2, 3},
{2, 1},
{1, 6},
{1, 5},
{1, 4},
{1, 3},
{1, 2},
{1, 1},
{1, 0},
{0, 13},
{0, 13},
{0, 13},
// numerator = 14
{-1, -1},
{-1, 0},
{-2, -12},
{-2, -10},
{-2, -8},
{-2, -6},
{-2, -4},
{-2, -2},
{-2, 0},
{-3, -4},
{-3, -1},
{-4, -2},
{-5, -1},
{-7, 0},
{-14, 0},
{0, 0},
{14, 0},
{7, 0},
{4, 2},
{3, 2},
{2, 4},
{2, 2},
{2, 0},
{1, 6},
{1, 5},
{1, 4},
{1, 3},
{1, 2},
{1, 1},
{1, 0},
{0, 14},
{0, 14},
// numerator = 15
{-1, 0},
{-2, -13},
{-2, -11},
{-2, -9},
{-2, -7},
{-2, -5},
{-2, -3},
{-2, -1},
{-3, -6},
{-3, -3},
{-3, 0},
{-4, -1},
{-5, 0},
{-8, -1},
{-15, 0},
{0, 0},
{15, 0},
{7, 1},
{5, 0},
{3, 3},
{3, 0},
{2, 3},
{2, 1},
{1, 7},
{1, 6},
{1, 5},
{1, 4},
{1, 3},
{1, 2},
{1, 1},
{1, 0},
{0, 15},
// numerator = 16
{-2, -14},
{-2, -12},
{-2, -10},
{-2, -8},
{-2, -6},
{-2, -4},
{-2, -2},
{-2, 0},
{-3, -5},
{-3, -2},
{-4, -4},
{-4, 0},
{-6, -2},
{-8, 0},
{-16, 0},
{0, 0},
{16, 0},
{8, 0},
{5, 1},
{4, 0},
{3, 1},
{2, 4},
{2, 2},
{2, 0},
{1, 7},
{1, 6},
{1, 5},
{1, 4},
{1, 3},
{1, 2},
{1, 1},
{1, 0},
/contrib/other/sdlquake-1.0.9/anorm_dots.h
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}
}
/contrib/other/sdlquake-1.0.9/anorms.h
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},
/contrib/other/sdlquake-1.0.9/asm_draw.h
0,0 → 1,151
/*
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.
 
*/
//
// asm_draw.h
//
// Include file for asm drawing routines.
//
 
//
// !!! note that this file must match the corresponding C structures at all
// times !!!
//
 
// !!! if this is changed, it must be changed in r_local.h too !!!
#define NEAR_CLIP 0.01
 
// !!! if this is changed, it must be changed in r_local.h too !!!
#define CYCLE 128
 
// espan_t structure
// !!! if this is changed, it must be changed in r_shared.h too !!!
#define espan_t_u 0
#define espan_t_v 4
#define espan_t_count 8
#define espan_t_pnext 12
#define espan_t_size 16
 
// sspan_t structure
// !!! if this is changed, it must be changed in d_local.h too !!!
#define sspan_t_u 0
#define sspan_t_v 4
#define sspan_t_count 8
#define sspan_t_size 12
 
// spanpackage_t structure
// !!! if this is changed, it must be changed in d_polyset.c too !!!
#define spanpackage_t_pdest 0
#define spanpackage_t_pz 4
#define spanpackage_t_count 8
#define spanpackage_t_ptex 12
#define spanpackage_t_sfrac 16
#define spanpackage_t_tfrac 20
#define spanpackage_t_light 24
#define spanpackage_t_zi 28
#define spanpackage_t_size 32
 
// edge_t structure
// !!! if this is changed, it must be changed in r_shared.h too !!!
#define et_u 0
#define et_u_step 4
#define et_prev 8
#define et_next 12
#define et_surfs 16
#define et_nextremove 20
#define et_nearzi 24
#define et_owner 28
#define et_size 32
 
// surf_t structure
// !!! if this is changed, it must be changed in r_shared.h too !!!
#define SURF_T_SHIFT 6
#define st_next 0
#define st_prev 4
#define st_spans 8
#define st_key 12
#define st_last_u 16
#define st_spanstate 20
#define st_flags 24
#define st_data 28
#define st_entity 32
#define st_nearzi 36
#define st_insubmodel 40
#define st_d_ziorigin 44
#define st_d_zistepu 48
#define st_d_zistepv 52
#define st_pad 56
#define st_size 64
 
// clipplane_t structure
// !!! if this is changed, it must be changed in r_local.h too !!!
#define cp_normal 0
#define cp_dist 12
#define cp_next 16
#define cp_leftedge 20
#define cp_rightedge 21
#define cp_reserved 22
#define cp_size 24
 
// medge_t structure
// !!! if this is changed, it must be changed in model.h too !!!
#define me_v 0
#define me_cachededgeoffset 4
#define me_size 8
 
// mvertex_t structure
// !!! if this is changed, it must be changed in model.h too !!!
#define mv_position 0
#define mv_size 12
 
// refdef_t structure
// !!! if this is changed, it must be changed in render.h too !!!
#define rd_vrect 0
#define rd_aliasvrect 20
#define rd_vrectright 40
#define rd_vrectbottom 44
#define rd_aliasvrectright 48
#define rd_aliasvrectbottom 52
#define rd_vrectrightedge 56
#define rd_fvrectx 60
#define rd_fvrecty 64
#define rd_fvrectx_adj 68
#define rd_fvrecty_adj 72
#define rd_vrect_x_adj_shift20 76
#define rd_vrectright_adj_shift20 80
#define rd_fvrectright_adj 84
#define rd_fvrectbottom_adj 88
#define rd_fvrectright 92
#define rd_fvrectbottom 96
#define rd_horizontalFieldOfView 100
#define rd_xOrigin 104
#define rd_yOrigin 108
#define rd_vieworg 112
#define rd_viewangles 124
#define rd_ambientlight 136
#define rd_size 140
 
// mtriangle_t structure
// !!! if this is changed, it must be changed in model.h too !!!
#define mtri_facesfront 0
#define mtri_vertindex 4
#define mtri_size 16 // !!! if this changes, array indexing in !!!
// !!! d_polysa.s must be changed to match !!!
#define mtri_shift 4
 
/contrib/other/sdlquake-1.0.9/asm_i386.h
0,0 → 1,97
/*
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 __ASM_I386__
#define __ASM_I386__
 
#ifdef ELF
#define C(label) label
#else
#define C(label) _##label
#endif
 
//
// !!! note that this file must match the corresponding C structures at all
// times !!!
//
 
// plane_t structure
// !!! if this is changed, it must be changed in model.h too !!!
// !!! if the size of this is changed, the array lookup in SV_HullPointContents
// must be changed too !!!
#define pl_normal 0
#define pl_dist 12
#define pl_type 16
#define pl_signbits 17
#define pl_pad 18
#define pl_size 20
 
// hull_t structure
// !!! if this is changed, it must be changed in model.h too !!!
#define hu_clipnodes 0
#define hu_planes 4
#define hu_firstclipnode 8
#define hu_lastclipnode 12
#define hu_clip_mins 16
#define hu_clip_maxs 28
#define hu_size 40
 
// dnode_t structure
// !!! if this is changed, it must be changed in bspfile.h too !!!
#define nd_planenum 0
#define nd_children 4
#define nd_mins 8
#define nd_maxs 20
#define nd_firstface 32
#define nd_numfaces 36
#define nd_size 40
 
// sfxcache_t structure
// !!! if this is changed, it much be changed in sound.h too !!!
#define sfxc_length 0
#define sfxc_loopstart 4
#define sfxc_speed 8
#define sfxc_width 12
#define sfxc_stereo 16
#define sfxc_data 20
 
// channel_t structure
// !!! if this is changed, it much be changed in sound.h too !!!
#define ch_sfx 0
#define ch_leftvol 4
#define ch_rightvol 8
#define ch_end 12
#define ch_pos 16
#define ch_looping 20
#define ch_entnum 24
#define ch_entchannel 28
#define ch_origin 32
#define ch_dist_mult 44
#define ch_master_vol 48
#define ch_size 52
 
// portable_samplepair_t structure
// !!! if this is changed, it much be changed in sound.h too !!!
#define psp_left 0
#define psp_right 4
#define psp_size 8
 
#endif
 
/contrib/other/sdlquake-1.0.9/block16.h
0,0 → 1,142
/*
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.
 
*/
LEnter16_16:
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movw 0x12345678(,%eax,2),%ax
LBPatch0:
addl %ebp,%edx
movw %ax,(%edi)
movw 0x12345678(,%ecx,2),%cx
LBPatch1:
movw %cx,2(%edi)
addl $0x4,%edi
 
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movw 0x12345678(,%eax,2),%ax
LBPatch2:
addl %ebp,%edx
movw %ax,(%edi)
movw 0x12345678(,%ecx,2),%cx
LBPatch3:
movw %cx,2(%edi)
addl $0x4,%edi
 
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movw 0x12345678(,%eax,2),%ax
LBPatch4:
addl %ebp,%edx
movw %ax,(%edi)
movw 0x12345678(,%ecx,2),%cx
LBPatch5:
movw %cx,2(%edi)
addl $0x4,%edi
 
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movw 0x12345678(,%eax,2),%ax
LBPatch6:
addl %ebp,%edx
movw %ax,(%edi)
movw 0x12345678(,%ecx,2),%cx
LBPatch7:
movw %cx,2(%edi)
addl $0x4,%edi
 
LEnter8_16:
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movw 0x12345678(,%eax,2),%ax
LBPatch8:
addl %ebp,%edx
movw %ax,(%edi)
movw 0x12345678(,%ecx,2),%cx
LBPatch9:
movw %cx,2(%edi)
addl $0x4,%edi
 
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movw 0x12345678(,%eax,2),%ax
LBPatch10:
addl %ebp,%edx
movw %ax,(%edi)
movw 0x12345678(,%ecx,2),%cx
LBPatch11:
movw %cx,2(%edi)
addl $0x4,%edi
 
LEnter4_16:
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movw 0x12345678(,%eax,2),%ax
LBPatch12:
addl %ebp,%edx
movw %ax,(%edi)
movw 0x12345678(,%ecx,2),%cx
LBPatch13:
movw %cx,2(%edi)
addl $0x4,%edi
 
LEnter2_16:
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movw 0x12345678(,%eax,2),%ax
LBPatch14:
addl %ebp,%edx
movw %ax,(%edi)
movw 0x12345678(,%ecx,2),%cx
LBPatch15:
movw %cx,2(%edi)
addl $0x4,%edi
/contrib/other/sdlquake-1.0.9/block8.h
0,0 → 1,143
/*
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.
 
*/
LEnter16_8:
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movb 0x12345678(%eax),%al
LBPatch0:
addl %ebp,%edx
movb %al,(%edi)
movb 0x12345678(%ecx),%cl
LBPatch1:
movb %cl,1(%edi)
addl $0x2,%edi
 
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movb 0x12345678(%eax),%al
LBPatch2:
addl %ebp,%edx
movb %al,(%edi)
movb 0x12345678(%ecx),%cl
LBPatch3:
movb %cl,1(%edi)
addl $0x2,%edi
 
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movb 0x12345678(%eax),%al
LBPatch4:
addl %ebp,%edx
movb %al,(%edi)
movb 0x12345678(%ecx),%cl
LBPatch5:
movb %cl,1(%edi)
addl $0x2,%edi
 
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movb 0x12345678(%eax),%al
LBPatch6:
addl %ebp,%edx
movb %al,(%edi)
movb 0x12345678(%ecx),%cl
LBPatch7:
movb %cl,1(%edi)
addl $0x2,%edi
 
LEnter8_8:
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movb 0x12345678(%eax),%al
LBPatch8:
addl %ebp,%edx
movb %al,(%edi)
movb 0x12345678(%ecx),%cl
LBPatch9:
movb %cl,1(%edi)
addl $0x2,%edi
 
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movb 0x12345678(%eax),%al
LBPatch10:
addl %ebp,%edx
movb %al,(%edi)
movb 0x12345678(%ecx),%cl
LBPatch11:
movb %cl,1(%edi)
addl $0x2,%edi
 
LEnter4_8:
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movb 0x12345678(%eax),%al
LBPatch12:
addl %ebp,%edx
movb %al,(%edi)
movb 0x12345678(%ecx),%cl
LBPatch13:
movb %cl,1(%edi)
addl $0x2,%edi
 
LEnter2_8:
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movb 0x12345678(%eax),%al
LBPatch14:
addl %ebp,%edx
movb %al,(%edi)
movb 0x12345678(%ecx),%cl
LBPatch15:
movb %cl,1(%edi)
addl $0x2,%edi
 
/contrib/other/sdlquake-1.0.9/bspfile.h
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 256
#define MAX_MAP_BRUSHES 4096
#define MAX_MAP_ENTITIES 1024
#define MAX_MAP_ENTSTRING 65536
 
#define MAX_MAP_PLANES 32767
#define MAX_MAP_NODES 32767 // because negative shorts are contents
#define MAX_MAP_CLIPNODES 32767 //
#define MAX_MAP_LEAFS 8192
#define MAX_MAP_VERTS 65535
#define MAX_MAP_FACES 65535
#define MAX_MAP_MARKSURFACES 65535
#define MAX_MAP_TEXINFO 4096
#define MAX_MAP_EDGES 256000
#define MAX_MAP_SURFEDGES 512000
#define MAX_MAP_TEXTURES 512
#define MAX_MAP_MIPTEX 0x200000
#define MAX_MAP_LIGHTING 0x100000
#define MAX_MAP_VISIBILITY 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
/contrib/other/sdlquake-1.0.9/cd_audio.c
0,0 → 1,886
/*
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 <dpmi.h>
#include "quakedef.h"
#include "dosisms.h"
 
extern cvar_t bgmvolume;
 
#define ADDRESS_MODE_HSG 0
#define ADDRESS_MODE_RED_BOOK 1
 
#define STATUS_ERROR_BIT 0x8000
#define STATUS_BUSY_BIT 0x0200
#define STATUS_DONE_BIT 0x0100
#define STATUS_ERROR_MASK 0x00ff
 
#define ERROR_WRITE_PROTECT 0
#define ERROR_UNKNOWN_UNIT 1
#define ERROR_DRIVE_NOT_READY 2
#define ERROR_UNKNOWN_COMMAND 3
#define ERROR_CRC_ERROR 4
#define ERROR_BAD_REQUEST_LEN 5
#define ERROR_SEEK_ERROR 6
#define ERROR_UNKNOWN_MEDIA 7
#define ERROR_SECTOR_NOT_FOUND 8
#define ERROR_OUT_OF_PAPER 9
#define ERROR_WRITE_FAULT 10
#define ERROR_READ_FAULT 11
#define ERROR_GENERAL_FAILURE 12
#define ERROR_RESERVED_13 13
#define ERROR_RESERVED_14 14
#define ERROR_BAD_DISK_CHANGE 15
 
#define COMMAND_READ 3
#define COMMAND_WRITE 12
#define COMMAND_PLAY_AUDIO 132
#define COMMAND_STOP_AUDIO 133
#define COMMAND_RESUME_AUDIO 136
 
#define READ_REQUEST_AUDIO_CHANNEL_INFO 4
#define READ_REQUEST_DEVICE_STATUS 6
#define READ_REQUEST_MEDIA_CHANGE 9
#define READ_REQUEST_AUDIO_DISK_INFO 10
#define READ_REQUEST_AUDIO_TRACK_INFO 11
#define READ_REQUEST_AUDIO_STATUS 15
 
#define WRITE_REQUEST_EJECT 0
#define WRITE_REQUEST_RESET 2
#define WRITE_REQUEST_AUDIO_CHANNEL_INFO 3
 
#define STATUS_DOOR_OPEN 0x00000001
#define STATUS_DOOR_UNLOCKED 0x00000002
#define STATUS_RAW_SUPPORT 0x00000004
#define STATUS_READ_WRITE 0x00000008
#define STATUS_AUDIO_SUPPORT 0x00000010
#define STATUS_INTERLEAVE_SUPPORT 0x00000020
#define STATUS_BIT_6_RESERVED 0x00000040
#define STATUS_PREFETCH_SUPPORT 0x00000080
#define STATUS_AUDIO_MANIPLUATION_SUPPORT 0x00000100
#define STATUS_RED_BOOK_ADDRESS_SUPPORT 0x00000200
 
#define MEDIA_NOT_CHANGED 1
#define MEDIA_STATUS_UNKNOWN 0
#define MEDIA_CHANGED -1
 
#define AUDIO_CONTROL_MASK 0xd0
#define AUDIO_CONTROL_DATA_TRACK 0x40
#define AUDIO_CONTROL_AUDIO_2_TRACK 0x00
#define AUDIO_CONTROL_AUDIO_2P_TRACK 0x10
#define AUDIO_CONTROL_AUDIO_4_TRACK 0x80
#define AUDIO_CONTROL_AUDIO_4P_TRACK 0x90
 
#define AUDIO_STATUS_PAUSED 0x0001
 
#pragma pack(1)
 
struct playAudioRequest
{
char addressingMode;
int startLocation;
int sectors;
};
 
struct readRequest
{
char mediaDescriptor;
short bufferOffset;
short bufferSegment;
short length;
short startSector;
int volumeID;
};
 
struct writeRequest
{
char mediaDescriptor;
short bufferOffset;
short bufferSegment;
short length;
short startSector;
int volumeID;
};
 
struct cd_request
{
char headerLength;
char unit;
char command;
short status;
char reserved[8];
union
{
struct playAudioRequest playAudio;
struct readRequest read;
struct writeRequest write;
} x;
};
 
 
struct audioChannelInfo_s
{
char code;
char channel0input;
char channel0volume;
char channel1input;
char channel1volume;
char channel2input;
char channel2volume;
char channel3input;
char channel3volume;
};
 
struct deviceStatus_s
{
char code;
int status;
};
 
struct mediaChange_s
{
char code;
char status;
};
 
struct audioDiskInfo_s
{
char code;
char lowTrack;
char highTrack;
int leadOutStart;
};
 
struct audioTrackInfo_s
{
char code;
char track;
int start;
char control;
};
 
struct audioStatus_s
{
char code;
short status;
int PRstartLocation;
int PRendLocation;
};
 
struct reset_s
{
char code;
};
 
union readInfo_u
{
struct audioChannelInfo_s audioChannelInfo;
struct deviceStatus_s deviceStatus;
struct mediaChange_s mediaChange;
struct audioDiskInfo_s audioDiskInfo;
struct audioTrackInfo_s audioTrackInfo;
struct audioStatus_s audioStatus;
struct reset_s reset;
};
 
#pragma pack()
 
#define MAXIMUM_TRACKS 100
 
typedef struct
{
int start;
int length;
qboolean isData;
} track_info;
 
typedef struct
{
qboolean valid;
int leadOutAddress;
track_info track[MAXIMUM_TRACKS];
byte lowTrack;
byte highTrack;
} cd_info;
 
static struct cd_request *cdRequest;
static union readInfo_u *readInfo;
static cd_info cd;
 
static qboolean playing = false;
static qboolean wasPlaying = false;
static qboolean mediaCheck = false;
static qboolean initialized = false;
static qboolean enabled = true;
static qboolean playLooping = false;
static short cdRequestSegment;
static short cdRequestOffset;
static short readInfoSegment;
static short readInfoOffset;
static byte remap[256];
static byte cdrom;
static byte playTrack;
static byte cdvolume;
 
 
static int RedBookToSector(int rb)
{
byte minute;
byte second;
byte frame;
 
minute = (rb >> 16) & 0xff;
second = (rb >> 8) & 0xff;
frame = rb & 0xff;
return minute * 60 * 75 + second * 75 + frame;
}
 
 
static void CDAudio_Reset(void)
{
cdRequest->headerLength = 13;
cdRequest->unit = 0;
cdRequest->command = COMMAND_WRITE;
cdRequest->status = 0;
 
cdRequest->x.write.mediaDescriptor = 0;
cdRequest->x.write.bufferOffset = readInfoOffset;
cdRequest->x.write.bufferSegment = readInfoSegment;
cdRequest->x.write.length = sizeof(struct reset_s);
cdRequest->x.write.startSector = 0;
cdRequest->x.write.volumeID = 0;
 
readInfo->reset.code = WRITE_REQUEST_RESET;
 
regs.x.ax = 0x1510;
regs.x.cx = cdrom;
regs.x.es = cdRequestSegment;
regs.x.bx = cdRequestOffset;
dos_int86 (0x2f);
}
 
 
static void CDAudio_Eject(void)
{
cdRequest->headerLength = 13;
cdRequest->unit = 0;
cdRequest->command = COMMAND_WRITE;
cdRequest->status = 0;
 
cdRequest->x.write.mediaDescriptor = 0;
cdRequest->x.write.bufferOffset = readInfoOffset;
cdRequest->x.write.bufferSegment = readInfoSegment;
cdRequest->x.write.length = sizeof(struct reset_s);
cdRequest->x.write.startSector = 0;
cdRequest->x.write.volumeID = 0;
 
readInfo->reset.code = WRITE_REQUEST_EJECT;
 
regs.x.ax = 0x1510;
regs.x.cx = cdrom;
regs.x.es = cdRequestSegment;
regs.x.bx = cdRequestOffset;
dos_int86 (0x2f);
}
 
 
static int CDAudio_GetAudioTrackInfo(byte track, int *start)
{
byte control;
 
cdRequest->headerLength = 13;
cdRequest->unit = 0;
cdRequest->command = COMMAND_READ;
cdRequest->status = 0;
 
cdRequest->x.read.mediaDescriptor = 0;
cdRequest->x.read.bufferOffset = readInfoOffset;
cdRequest->x.read.bufferSegment = readInfoSegment;
cdRequest->x.read.length = sizeof(struct audioTrackInfo_s);
cdRequest->x.read.startSector = 0;
cdRequest->x.read.volumeID = 0;
 
readInfo->audioTrackInfo.code = READ_REQUEST_AUDIO_TRACK_INFO;
readInfo->audioTrackInfo.track = track;
 
regs.x.ax = 0x1510;
regs.x.cx = cdrom;
regs.x.es = cdRequestSegment;
regs.x.bx = cdRequestOffset;
dos_int86 (0x2f);
 
if (cdRequest->status & STATUS_ERROR_BIT)
{
Con_DPrintf("CDAudio_GetAudioTrackInfo %04x\n", cdRequest->status & 0xffff);
return -1;
}
 
*start = readInfo->audioTrackInfo.start;
control = readInfo->audioTrackInfo.control & AUDIO_CONTROL_MASK;
return (control & AUDIO_CONTROL_DATA_TRACK);
}
 
 
static int CDAudio_GetAudioDiskInfo(void)
{
int n;
 
cdRequest->headerLength = 13;
cdRequest->unit = 0;
cdRequest->command = COMMAND_READ;
cdRequest->status = 0;
 
cdRequest->x.read.mediaDescriptor = 0;
cdRequest->x.read.bufferOffset = readInfoOffset;
cdRequest->x.read.bufferSegment = readInfoSegment;
cdRequest->x.read.length = sizeof(struct audioDiskInfo_s);
cdRequest->x.read.startSector = 0;
cdRequest->x.read.volumeID = 0;
 
readInfo->audioDiskInfo.code = READ_REQUEST_AUDIO_DISK_INFO;
 
regs.x.ax = 0x1510;
regs.x.cx = cdrom;
regs.x.es = cdRequestSegment;
regs.x.bx = cdRequestOffset;
dos_int86 (0x2f);
 
if (cdRequest->status & STATUS_ERROR_BIT)
{
Con_DPrintf("CDAudio_GetAudioDiskInfo %04x\n", cdRequest->status & 0xffff);
return -1;
}
 
cd.valid = true;
cd.lowTrack = readInfo->audioDiskInfo.lowTrack;
cd.highTrack = readInfo->audioDiskInfo.highTrack;
cd.leadOutAddress = readInfo->audioDiskInfo.leadOutStart;
 
for (n = cd.lowTrack; n <= cd.highTrack; n++)
{
cd.track[n].isData = CDAudio_GetAudioTrackInfo (n, &cd.track[n].start);
if (n > cd.lowTrack)
{
cd.track[n-1].length = RedBookToSector(cd.track[n].start) - RedBookToSector(cd.track[n-1].start);
if (n == cd.highTrack)
cd.track[n].length = RedBookToSector(cd.leadOutAddress) - RedBookToSector(cd.track[n].start);
}
}
 
return 0;
}
 
 
static int CDAudio_GetAudioStatus(void)
{
cdRequest->headerLength = 13;
cdRequest->unit = 0;
cdRequest->command = COMMAND_READ;
cdRequest->status = 0;
 
cdRequest->x.read.mediaDescriptor = 0;
cdRequest->x.read.bufferOffset = readInfoOffset;
cdRequest->x.read.bufferSegment = readInfoSegment;
cdRequest->x.read.length = sizeof(struct audioStatus_s);
cdRequest->x.read.startSector = 0;
cdRequest->x.read.volumeID = 0;
 
readInfo->audioDiskInfo.code = READ_REQUEST_AUDIO_STATUS;
 
regs.x.ax = 0x1510;
regs.x.cx = cdrom;
regs.x.es = cdRequestSegment;
regs.x.bx = cdRequestOffset;
dos_int86 (0x2f);
 
if (cdRequest->status & STATUS_ERROR_BIT)
return -1;
return 0;
}
 
 
static int CDAudio_MediaChange(void)
{
cdRequest->headerLength = 13;
cdRequest->unit = 0;
cdRequest->command = COMMAND_READ;
cdRequest->status = 0;
 
cdRequest->x.read.mediaDescriptor = 0;
cdRequest->x.read.bufferOffset = readInfoOffset;
cdRequest->x.read.bufferSegment = readInfoSegment;
cdRequest->x.read.length = sizeof(struct mediaChange_s);
cdRequest->x.read.startSector = 0;
cdRequest->x.read.volumeID = 0;
 
readInfo->mediaChange.code = READ_REQUEST_MEDIA_CHANGE;
 
regs.x.ax = 0x1510;
regs.x.cx = cdrom;
regs.x.es = cdRequestSegment;
regs.x.bx = cdRequestOffset;
dos_int86 (0x2f);
 
return readInfo->mediaChange.status;
}
 
 
// we set the volume to 0 first and then to the desired volume
// some cd-rom drivers seem to need it done this way
void CDAudio_SetVolume (byte volume)
{
if (!initialized || !enabled)
return;
 
cdRequest->headerLength = 13;
cdRequest->unit = 0;
cdRequest->command = COMMAND_WRITE;
cdRequest->status = 0;
 
cdRequest->x.read.mediaDescriptor = 0;
cdRequest->x.read.bufferOffset = readInfoOffset;
cdRequest->x.read.bufferSegment = readInfoSegment;
cdRequest->x.read.length = sizeof(struct audioChannelInfo_s);
cdRequest->x.read.startSector = 0;
cdRequest->x.read.volumeID = 0;
 
readInfo->audioChannelInfo.code = WRITE_REQUEST_AUDIO_CHANNEL_INFO;
readInfo->audioChannelInfo.channel0input = 0;
readInfo->audioChannelInfo.channel0volume = 0;
readInfo->audioChannelInfo.channel1input = 1;
readInfo->audioChannelInfo.channel1volume = 0;
readInfo->audioChannelInfo.channel2input = 2;
readInfo->audioChannelInfo.channel2volume = 0;
readInfo->audioChannelInfo.channel3input = 3;
readInfo->audioChannelInfo.channel3volume = 0;
 
regs.x.ax = 0x1510;
regs.x.cx = cdrom;
regs.x.es = cdRequestSegment;
regs.x.bx = cdRequestOffset;
dos_int86 (0x2f);
 
readInfo->audioChannelInfo.channel0volume = volume;
readInfo->audioChannelInfo.channel1volume = volume;
 
regs.x.ax = 0x1510;
regs.x.cx = cdrom;
regs.x.es = cdRequestSegment;
regs.x.bx = cdRequestOffset;
dos_int86 (0x2f);
 
cdvolume = volume;
}
 
 
void CDAudio_Play(byte track, qboolean looping)
{
int volume;
 
if (!initialized || !enabled)
return;
if (!cd.valid)
return;
 
track = remap[track];
 
if (playing)
{
if (playTrack == track)
return;
CDAudio_Stop();
}
 
playLooping = looping;
 
if (track < cd.lowTrack || track > cd.highTrack)
{
Con_DPrintf("CDAudio_Play: Bad track number %u.\n", track);
return;
}
 
playTrack = track;
 
if (cd.track[track].isData)
{
Con_DPrintf("CDAudio_Play: Can not play data.\n");
return;
}
 
volume = (int)(bgmvolume.value * 255.0);
if (volume < 0)
{
Cvar_SetValue ("bgmvolume", 0.0);
volume = 0;
}
else if (volume > 255)
{
Cvar_SetValue ("bgmvolume", 1.0);
volume = 255;
}
CDAudio_SetVolume (volume);
 
cdRequest->headerLength = 13;
cdRequest->unit = 0;
cdRequest->command = COMMAND_PLAY_AUDIO;
cdRequest->status = 0;
 
cdRequest->x.playAudio.addressingMode = ADDRESS_MODE_RED_BOOK;
cdRequest->x.playAudio.startLocation = cd.track[track].start;
cdRequest->x.playAudio.sectors = cd.track[track].length;
 
regs.x.ax = 0x1510;
regs.x.cx = cdrom;
regs.x.es = cdRequestSegment;
regs.x.bx = cdRequestOffset;
dos_int86 (0x2f);
 
if (cdRequest->status & STATUS_ERROR_BIT)
{
Con_DPrintf("CDAudio_Play: track %u failed\n", track);
cd.valid = false;
playing = false;
return;
}
 
playing = true;
}
 
 
void CDAudio_Stop(void)
{
if (!initialized || !enabled)
return;
cdRequest->headerLength = 13;
cdRequest->unit = 0;
cdRequest->command = COMMAND_STOP_AUDIO;
cdRequest->status = 0;
 
regs.x.ax = 0x1510;
regs.x.cx = cdrom;
regs.x.es = cdRequestSegment;
regs.x.bx = cdRequestOffset;
dos_int86 (0x2f);
 
wasPlaying = playing;
playing = false;
}
 
 
void CDAudio_Pause(void)
{
CDAudio_Stop();
}
 
 
void CDAudio_Resume(void)
{
if (!initialized || !enabled)
return;
if (!cd.valid)
return;
 
if (!wasPlaying)
return;
cdRequest->headerLength = 13;
cdRequest->unit = 0;
cdRequest->command = COMMAND_RESUME_AUDIO;
cdRequest->status = 0;
 
regs.x.ax = 0x1510;
regs.x.cx = cdrom;
regs.x.es = cdRequestSegment;
regs.x.bx = cdRequestOffset;
dos_int86 (0x2f);
 
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 < 256; n++)
remap[n] = n;
CDAudio_Reset();
CDAudio_GetAudioDiskInfo();
return;
}
 
if (Q_strcasecmp(command, "remap") == 0)
{
ret = Cmd_Argc() - 2;
if (ret <= 0)
{
for (n = 1; n < 256; 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 (!cd.valid)
{
Con_Printf("No CD in player.\n");
return;
}
 
if (Q_strcasecmp(command, "play") == 0)
{
CDAudio_Play(Q_atoi(Cmd_Argv (2)), false);
return;
}
 
if (Q_strcasecmp(command, "loop") == 0)
{
CDAudio_Play(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();
cd.valid = false;
return;
}
 
if (Q_strcasecmp(command, "info") == 0)
{
Con_Printf("%u tracks\n", cd.highTrack - cd.lowTrack + 1);
for (n = cd.lowTrack; n <= cd.highTrack; n++)
{
ret = CDAudio_GetAudioTrackInfo (n, &startAddress);
Con_Printf("Track %2u: %s at %2u:%02u\n", n, ret ? "data " : "music", (startAddress >> 16) & 0xff, (startAddress >> 8) & 0xff);
}
if (playing)
Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
Con_Printf("Volume is %u\n", cdvolume);
CDAudio_MediaChange();
Con_Printf("Status %04x\n", cdRequest->status & 0xffff);
return;
}
}
 
 
void CDAudio_Update(void)
{
int ret;
int newVolume;
static double lastUpdate;
 
if (!initialized || !enabled)
return;
 
if ((realtime - lastUpdate) < 0.25)
return;
lastUpdate = realtime;
 
if (mediaCheck)
{
static double lastCheck;
 
if ((realtime - lastCheck) < 5.0)
return;
lastCheck = realtime;
 
ret = CDAudio_MediaChange();
if (ret == MEDIA_CHANGED)
{
Con_DPrintf("CDAudio: media changed\n");
playing = false;
wasPlaying = false;
cd.valid = false;
CDAudio_GetAudioDiskInfo();
return;
}
}
 
newVolume = (int)(bgmvolume.value * 255.0);
if (newVolume != cdvolume)
{
if (newVolume < 0)
{
Cvar_SetValue ("bgmvolume", 0.0);
newVolume = 0;
}
else if (newVolume > 255)
{
Cvar_SetValue ("bgmvolume", 1.0);
newVolume = 255;
}
CDAudio_SetVolume (newVolume);
}
 
if (playing)
{
CDAudio_GetAudioStatus();
if ((cdRequest->status & STATUS_BUSY_BIT) == 0)
{
playing = false;
if (playLooping)
CDAudio_Play(playTrack, true);
}
}
}
 
 
int CDAudio_Init(void)
{
char *memory;
int n;
 
if (cls.state == ca_dedicated)
return -1;
 
if (COM_CheckParm("-nocdaudio"))
return -1;
 
if (COM_CheckParm("-cdmediacheck"))
mediaCheck = true;
 
regs.x.ax = 0x1500;
regs.x.bx = 0;
dos_int86 (0x2f);
if (regs.x.bx == 0)
{
Con_NotifyBox (
"MSCDEX not loaded, music is\n"
"disabled. Use \"-nocdaudio\" if you\n"
"wish to avoid this message in the\n"
"future. See README.TXT for help.\n"
);
return -1;
}
if (regs.x.bx > 1)
Con_DPrintf("CDAudio_Init: First CD-ROM drive will be used\n");
cdrom = regs.x.cx;
 
regs.x.ax = 0x150c;
regs.x.bx = 0;
dos_int86 (0x2f);
if (regs.x.bx == 0)
{
Con_NotifyBox (
"MSCDEX version 2.00 or later\n"
"required for music. See README.TXT\n"
"for help.\n"
);
Con_DPrintf("CDAudio_Init: MSCDEX version 2.00 or later required.\n");
return -1;
}
 
memory = dos_getmemory(sizeof(struct cd_request
) + sizeof(union readInfo_u));
if (memory == NULL)
{
Con_DPrintf("CDAudio_Init: Unable to allocate low memory.\n");
return -1;
}
 
cdRequest = (struct cd_request *)memory;
cdRequestSegment = ptr2real(cdRequest) >> 4;
cdRequestOffset = ptr2real(cdRequest) & 0xf;
 
readInfo = (union readInfo_u *)(memory + sizeof(struct cd_request));
readInfoSegment = ptr2real(readInfo) >> 4;
readInfoOffset = ptr2real(readInfo) & 0xf;
 
for (n = 0; n < 256; n++)
remap[n] = n;
initialized = true;
 
CDAudio_SetVolume (255);
if (CDAudio_GetAudioDiskInfo())
{
Con_Printf("CDAudio_Init: No CD in player.\n");
enabled = false;
}
 
Cmd_AddCommand ("cd", CD_f);
 
Con_Printf("CD Audio Initialized\n");
 
return 0;
}
 
 
void CDAudio_Shutdown(void)
{
if (!initialized)
return;
CDAudio_Stop();
}
/contrib/other/sdlquake-1.0.9/cd_linux.c
0,0 → 1,416
/*
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 <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <errno.h>
 
#include <linux/cdrom.h>
 
#include "quakedef.h"
 
static qboolean cdValid = false;
static qboolean playing = false;
static qboolean wasPlaying = false;
static qboolean initialized = false;
static qboolean enabled = true;
static qboolean playLooping = false;
static float cdvolume;
static byte remap[100];
static byte playTrack;
static byte maxTrack;
 
static int cdfile = -1;
static char cd_dev[64] = "/dev/cdrom";
 
static void CDAudio_Eject(void)
{
if (cdfile == -1 || !enabled)
return; // no cd init'd
 
if ( ioctl(cdfile, CDROMEJECT) == -1 )
Con_DPrintf("ioctl cdromeject failed\n");
}
 
 
static void CDAudio_CloseDoor(void)
{
if (cdfile == -1 || !enabled)
return; // no cd init'd
 
if ( ioctl(cdfile, CDROMCLOSETRAY) == -1 )
Con_DPrintf("ioctl cdromclosetray failed\n");
}
 
static int CDAudio_GetAudioDiskInfo(void)
{
struct cdrom_tochdr tochdr;
 
cdValid = false;
 
if ( ioctl(cdfile, CDROMREADTOCHDR, &tochdr) == -1 )
{
Con_DPrintf("ioctl cdromreadtochdr failed\n");
return -1;
}
 
if (tochdr.cdth_trk0 < 1)
{
Con_DPrintf("CDAudio: no music tracks\n");
return -1;
}
 
cdValid = true;
maxTrack = tochdr.cdth_trk1;
 
return 0;
}
 
 
void CDAudio_Play(byte track, qboolean looping)
{
struct cdrom_tocentry entry;
struct cdrom_ti ti;
 
if (cdfile == -1 || !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
entry.cdte_track = track;
entry.cdte_format = CDROM_MSF;
if ( ioctl(cdfile, CDROMREADTOCENTRY, &entry) == -1 )
{
Con_DPrintf("ioctl cdromreadtocentry failed\n");
return;
}
if (entry.cdte_ctrl == CDROM_DATA_TRACK)
{
Con_Printf("CDAudio: track %i is not audio\n", track);
return;
}
 
if (playing)
{
if (playTrack == track)
return;
CDAudio_Stop();
}
 
ti.cdti_trk0 = track;
ti.cdti_trk1 = track;
ti.cdti_ind0 = 1;
ti.cdti_ind1 = 99;
 
if ( ioctl(cdfile, CDROMPLAYTRKIND, &ti) == -1 )
{
Con_DPrintf("ioctl cdromplaytrkind failed\n");
return;
}
 
if ( ioctl(cdfile, CDROMRESUME) == -1 )
Con_DPrintf("ioctl cdromresume failed\n");
 
playLooping = looping;
playTrack = track;
playing = true;
 
if (cdvolume == 0.0)
CDAudio_Pause ();
}
 
 
void CDAudio_Stop(void)
{
if (cdfile == -1 || !enabled)
return;
if (!playing)
return;
 
if ( ioctl(cdfile, CDROMSTOP) == -1 )
Con_DPrintf("ioctl cdromstop failed (%d)\n", errno);
 
wasPlaying = false;
playing = false;
}
 
void CDAudio_Pause(void)
{
if (cdfile == -1 || !enabled)
return;
 
if (!playing)
return;
 
if ( ioctl(cdfile, CDROMPAUSE) == -1 )
Con_DPrintf("ioctl cdrompause failed\n");
 
wasPlaying = playing;
playing = false;
}
 
 
void CDAudio_Resume(void)
{
if (cdfile == -1 || !enabled)
return;
if (!cdValid)
return;
 
if (!wasPlaying)
return;
if ( ioctl(cdfile, CDROMRESUME) == -1 )
Con_DPrintf("ioctl cdromresume failed\n");
playing = true;
}
 
static void CD_f (void)
{
char *command;
int ret;
int n;
 
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;
}
}
 
void CDAudio_Update(void)
{
struct cdrom_subchnl subchnl;
static time_t lastchk;
 
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 ();
}
}
 
if (playing && lastchk < time(NULL)) {
lastchk = time(NULL) + 2; //two seconds between chks
subchnl.cdsc_format = CDROM_MSF;
if (ioctl(cdfile, CDROMSUBCHNL, &subchnl) == -1 ) {
Con_DPrintf("ioctl cdromsubchnl failed\n");
playing = false;
return;
}
if (subchnl.cdsc_audiostatus != CDROM_AUDIO_PLAY &&
subchnl.cdsc_audiostatus != CDROM_AUDIO_PAUSED) {
playing = false;
if (playLooping)
CDAudio_Play(playTrack, true);
}
}
}
 
int CDAudio_Init(void)
{
int i;
 
if (cls.state == ca_dedicated)
return -1;
 
if (COM_CheckParm("-nocdaudio"))
return -1;
 
if ((i = COM_CheckParm("-cddev")) != 0 && i < com_argc - 1) {
strncpy(cd_dev, com_argv[i + 1], sizeof(cd_dev));
cd_dev[sizeof(cd_dev) - 1] = 0;
}
 
if ((cdfile = open(cd_dev, O_RDONLY)) == -1) {
Con_Printf("CDAudio_Init: open of \"%s\" failed (%i)\n", cd_dev, errno);
cdfile = -1;
return -1;
}
 
for (i = 0; i < 100; i++)
remap[i] = i;
initialized = true;
enabled = true;
 
if (CDAudio_GetAudioDiskInfo())
{
Con_Printf("CDAudio_Init: No CD in player.\n");
cdValid = false;
}
 
Cmd_AddCommand ("cd", CD_f);
 
Con_Printf("CD Audio Initialized\n");
 
return 0;
}
 
 
void CDAudio_Shutdown(void)
{
if (!initialized)
return;
CDAudio_Stop();
close(cdfile);
cdfile = -1;
}
/contrib/other/sdlquake-1.0.9/cd_null.c
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.
 
*/
#include "quakedef.h"
 
void CDAudio_Play(byte track, qboolean looping)
{
}
 
 
void CDAudio_Stop(void)
{
}
 
 
void CDAudio_Pause(void)
{
}
 
 
void CDAudio_Resume(void)
{
}
 
 
void CDAudio_Update(void)
{
}
 
 
int CDAudio_Init(void)
{
return 0;
}
 
 
void CDAudio_Shutdown(void)
{
}
/contrib/other/sdlquake-1.0.9/cd_sdl.c
0,0 → 1,223
/*
Some of this may not work. I'm not overly familiar with SDL, I just sort
of podged this together from the SDL headers, and the other cd-rom code.
 
Mark Baker <homer1@together.net>
*/
 
#include <SDL.h>
 
#include "quakedef.h"
 
static qboolean cdValid = false;
static qboolean initialized = false;
static qboolean enabled = true;
static qboolean playLooping = false;
static SDL_CD *cd_id;
static float cdvolume = 1.0;
 
static void CD_f();
 
static void CDAudio_Eject()
{
if(!cd_id || !enabled) return;
 
if(SDL_CDEject(cd_id))
Con_DPrintf("Unable to eject CD-ROM tray.\n");
}
 
void CDAudio_Play(byte track, qboolean looping)
{
CDstatus cd_stat;
if(!cd_id || !enabled) return;
if(!cdValid)
{
if(!CD_INDRIVE(cd_stat=SDL_CDStatus(cd_id)) ||(!cd_id->numtracks)) return;
cdValid = true;
}
 
if((track < 1) || (track >= cd_id->numtracks))
{
Con_DPrintf("CDAudio: Bad track number: %d\n",track);
return;
}
track--; /* Convert track from person to SDL value */
if(cd_stat == CD_PLAYING)
{
if(cd_id->cur_track == track) return;
CDAudio_Stop();
}
 
if(SDL_CDPlay(cd_id,cd_id->track[track].offset,
cd_id->track[track].length))
{
Con_DPrintf("CDAudio_Play: Unable to play track: %d\n",track+1);
return;
}
playLooping = looping;
}
 
 
void CDAudio_Stop()
{
int cdstate;
if(!cd_id || !enabled) return;
cdstate = SDL_CDStatus(cd_id);
if((cdstate != CD_PLAYING) && (cdstate != CD_PAUSED)) return;
 
if(SDL_CDStop(cd_id))
Con_DPrintf("CDAudio_Stop: Failed to stop track.\n");
}
 
void CDAudio_Pause()
{
if(!cd_id || !enabled) return;
if(SDL_CDStatus(cd_id) != CD_PLAYING) return;
 
if(SDL_CDPause(cd_id))
Con_DPrintf("CDAudio_Pause: Failed to pause track.\n");
}
 
 
void CDAudio_Resume()
{
if(!cd_id || !enabled) return;
if(SDL_CDStatus(cd_id) != CD_PAUSED) return;
 
if(SDL_CDResume(cd_id))
Con_DPrintf("CDAudio_Resume: Failed tp resume track.\n");
}
 
void CDAudio_Update()
{
if(!cd_id || !enabled) return;
if(bgmvolume.value != cdvolume)
{
if(cdvolume)
{
Cvar_SetValue("bgmvolume",0.0);
CDAudio_Pause();
}
else
{
Cvar_SetValue("bgmvolume",1.0);
CDAudio_Resume();
}
cdvolume = bgmvolume.value;
return;
}
if(playLooping && (SDL_CDStatus(cd_id) != CD_PLAYING)
&& (SDL_CDStatus(cd_id) != CD_PAUSED))
CDAudio_Play(cd_id->cur_track+1,true);
}
 
int CDAudio_Init()
{
if((cls.state == ca_dedicated) || COM_CheckParm("-nocdaudio"))
return -1;
cd_id = SDL_CDOpen(0);
if(!cd_id)
{
Con_Printf("CDAudio_Init: Unable to open default CD-ROM drive: %s\n",
SDL_GetError());
return -1;
}
initialized = true;
enabled = true;
cdValid = true;
if(!CD_INDRIVE(SDL_CDStatus(cd_id)))
{
Con_Printf("CDAudio_Init: No CD in drive.\n");
cdValid = false;
}
if(!cd_id->numtracks)
{
Con_Printf("CDAudio_Init: CD contains no audio tracks.\n");
cdValid = false;
}
Cmd_AddCommand("cd",CD_f);
Con_Printf("CD Audio Initialized.\n");
return 0;
}
 
 
void CDAudio_Shutdown()
{
if(!cd_id) return;
CDAudio_Stop();
SDL_CDClose(cd_id);
cd_id = NULL;
}
 
static void CD_f()
{
char *command;
int cdstate;
if(Cmd_Argc() < 2) return;
 
command = Cmd_Argv(1);
if(!Q_strcasecmp(command,"on"))
{
enabled = true;
}
if(!Q_strcasecmp(command,"off"))
{
if(!cd_id) return;
cdstate = SDL_CDStatus(cd_id);
if((cdstate == CD_PLAYING) || (cdstate == CD_PAUSED))
CDAudio_Stop();
enabled = false;
return;
}
if(!Q_strcasecmp(command,"play"))
{
CDAudio_Play(Q_atoi(Cmd_Argv(2)),false);
return;
}
if(!Q_strcasecmp(command,"loop"))
{
CDAudio_Play(Q_atoi(Cmd_Argv(2)),true);
return;
}
if(!Q_strcasecmp(command,"stop"))
{
CDAudio_Stop();
return;
}
if(!Q_strcasecmp(command,"pause"))
{
CDAudio_Pause();
return;
}
if(!Q_strcasecmp(command,"resume"))
{
CDAudio_Resume();
return;
}
if(!Q_strcasecmp(command,"eject"))
{
CDAudio_Eject();
return;
}
if(!Q_strcasecmp(command,"info"))
{
if(!cd_id) return;
cdstate = SDL_CDStatus(cd_id);
Con_Printf("%d tracks\n",cd_id->numtracks);
if(cdstate == CD_PLAYING)
Con_Printf("Currently %s track %d\n",
playLooping ? "looping" : "playing",
cd_id->cur_track+1);
else
if(cdstate == CD_PAUSED)
Con_Printf("Paused %s track %d\n",
playLooping ? "looping" : "playing",
cd_id->cur_track+1);
return;
}
}
 
/contrib/other/sdlquake-1.0.9/cd_win.c
0,0 → 1,477
/*
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 <windows.h>
#include "quakedef.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;
 
UINT wDeviceID;
 
 
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;
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;
MCI_PLAY_PARMS mciPlayParms;
 
if (!enabled)
return;
if (!cdValid)
return;
 
if (!wasPlaying)
return;
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);
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;
}
 
 
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 ();
}
}
}
 
 
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);
 
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");
}
/contrib/other/sdlquake-1.0.9/cdaudio.h
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.
 
*/
 
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);
/contrib/other/sdlquake-1.0.9/chase.c
0,0 → 1,92
/*
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.
 
*/
// chase.c -- chase camera code
 
#include "quakedef.h"
 
cvar_t chase_back = {"chase_back", "100"};
cvar_t chase_up = {"chase_up", "16"};
cvar_t chase_right = {"chase_right", "0"};
cvar_t chase_active = {"chase_active", "0"};
 
vec3_t chase_pos;
vec3_t chase_angles;
 
vec3_t chase_dest;
vec3_t chase_dest_angles;
 
 
void Chase_Init (void)
{
Cvar_RegisterVariable (&chase_back);
Cvar_RegisterVariable (&chase_up);
Cvar_RegisterVariable (&chase_right);
Cvar_RegisterVariable (&chase_active);
}
 
void Chase_Reset (void)
{
// for respawning and teleporting
// start position 12 units behind head
}
 
void TraceLine (vec3_t start, vec3_t end, vec3_t impact)
{
trace_t trace;
 
memset (&trace, 0, sizeof(trace));
SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &trace);
 
VectorCopy (trace.endpos, impact);
}
 
void Chase_Update (void)
{
int i;
float dist;
vec3_t forward, up, right;
vec3_t dest, stop;
 
 
// if can't see player, reset
AngleVectors (cl.viewangles, forward, right, up);
 
// calc exact destination
for (i=0 ; i<3 ; i++)
chase_dest[i] = r_refdef.vieworg[i]
- forward[i]*chase_back.value
- right[i]*chase_right.value;
chase_dest[2] = r_refdef.vieworg[2] + chase_up.value;
 
// find the spot the player is looking at
VectorMA (r_refdef.vieworg, 4096, forward, dest);
TraceLine (r_refdef.vieworg, dest, stop);
 
// calculate pitch to look at the same spot from camera
VectorSubtract (stop, r_refdef.vieworg, stop);
dist = DotProduct (stop, forward);
if (dist < 1)
dist = 1;
r_refdef.viewangles[PITCH] = -atan(stop[2] / dist) / M_PI * 180;
 
// move towards destination
VectorCopy (chase_dest, r_refdef.vieworg);
}
 
/contrib/other/sdlquake-1.0.9/cl_demo.c
0,0 → 1,367
/*
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"
 
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;
 
fclose (cls.demofile);
cls.demoplayback = false;
cls.demofile = NULL;
cls.state = ca_disconnected;
 
if (cls.timedemo)
CL_FinishTimeDemo ();
}
 
/*
====================
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
====================
*/
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) // allways grab until fully connected
{
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);
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;
}
 
 
/*
====================
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]
====================
*/
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);
}
 
/*
====================
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;
cls.td_lastframe = -1; // get a new message this frame
}
 
/contrib/other/sdlquake-1.0.9/cl_input.c
0,0 → 1,448
/*
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;
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
}
 
void IN_KLookDown (void) {KeyDown(&in_klook);}
void IN_KLookUp (void) {KeyUp(&in_klook);}
void IN_MLookDown (void) {KeyDown(&in_mlook);}
void IN_MLookUp (void) {
KeyUp(&in_mlook);
if ( !(in_mlook.state&1) && lookspring.value)
V_StartPitchDrift();
}
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};
cvar_t cl_sidespeed = {"cl_sidespeed","350"};
 
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"};
 
 
/*
================
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]);
}
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);
}
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);
 
if (! (in_klook.state & 1) )
{
cmd->forwardmove += cl_forwardspeed.value * CL_KeyState (&in_forward);
cmd->forwardmove -= cl_backspeed.value * CL_KeyState (&in_back);
}
 
//
// adjust for speed key
//
if (in_speed.state & 1)
{
cmd->forwardmove *= cl_movespeedkey.value;
cmd->sidemove *= cl_movespeedkey.value;
cmd->upmove *= cl_movespeedkey.value;
}
 
#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);
Cmd_AddCommand ("-klook", IN_KLookUp);
Cmd_AddCommand ("+mlook", IN_MLookDown);
Cmd_AddCommand ("-mlook", IN_MLookUp);
 
}
 
/contrib/other/sdlquake-1.0.9/cl_main.c
0,0 → 1,757
/*
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"};
 
cvar_t lookspring = {"lookspring","0", true};
cvar_t lookstrafe = {"lookstrafe","0", true};
cvar_t sensitivity = {"sensitivity","3", true};
 
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;
}
 
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;
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;
return dl;
}
}
 
dl = &cl_dlights[0];
memset (dl, 0, sizeof(*dl));
dl->key = key;
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;
 
if (i == cl.viewentity && !chase_active.value)
continue;
 
#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);
Cvar_RegisterVariable (&lookspring);
Cvar_RegisterVariable (&lookstrafe);
Cvar_RegisterVariable (&sensitivity);
 
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);
}
 
/contrib/other/sdlquake-1.0.9/cl_parse.c
0,0 → 1,963
/*
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_parse.c -- parse a message received from the server
 
#include "quakedef.h"
 
char *svc_strings[] =
{
"svc_bad",
"svc_nop",
"svc_disconnect",
"svc_updatestat",
"svc_version", // [long] server version
"svc_setview", // [short] entity number
"svc_sound", // <see code>
"svc_time", // [float] server time
"svc_print", // [string] null terminated string
"svc_stufftext", // [string] stuffed into client's console buffer
// the string should be \n terminated
"svc_setangle", // [vec3] set the view angle to this absolute value
"svc_serverinfo", // [long] version
// [string] signon string
// [string]..[0]model cache [string]...[0]sounds cache
// [string]..[0]item cache
"svc_lightstyle", // [byte] [string]
"svc_updatename", // [byte] [string]
"svc_updatefrags", // [byte] [short]
"svc_clientdata", // <shortbits + data>
"svc_stopsound", // <see code>
"svc_updatecolors", // [byte] [byte]
"svc_particle", // [vec3] <variable>
"svc_damage", // [byte] impact [byte] blood [vec3] from
"svc_spawnstatic",
"OBSOLETE svc_spawnbinary",
"svc_spawnbaseline",
"svc_temp_entity", // <variable>
"svc_setpause",
"svc_signonnum",
"svc_centerprint",
"svc_killedmonster",
"svc_foundsecret",
"svc_spawnstaticsound",
"svc_intermission",
"svc_finale", // [string] music [string] text
"svc_cdtrack", // [byte] track [byte] looptrack
"svc_sellscreen",
"svc_cutscene"
};
 
//=============================================================================
 
/*
===============
CL_EntityNum
 
This error checks and tracks the total number of entities
===============
*/
entity_t *CL_EntityNum (int num)
{
if (num >= cl.num_entities)
{
if (num >= MAX_EDICTS)
Host_Error ("CL_EntityNum: %i is an invalid number",num);
while (cl.num_entities<=num)
{
cl_entities[cl.num_entities].colormap = vid.colormap;
cl.num_entities++;
}
}
return &cl_entities[num];
}
 
 
/*
==================
CL_ParseStartSoundPacket
==================
*/
void CL_ParseStartSoundPacket(void)
{
vec3_t pos;
int channel, ent;
int sound_num;
int volume;
int field_mask;
float attenuation;
int i;
field_mask = MSG_ReadByte();
 
if (field_mask & SND_VOLUME)
volume = MSG_ReadByte ();
else
volume = DEFAULT_SOUND_PACKET_VOLUME;
if (field_mask & SND_ATTENUATION)
attenuation = MSG_ReadByte () / 64.0;
else
attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
channel = MSG_ReadShort ();
sound_num = MSG_ReadByte ();
 
ent = channel >> 3;
channel &= 7;
 
if (ent > MAX_EDICTS)
Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
for (i=0 ; i<3 ; i++)
pos[i] = MSG_ReadCoord ();
S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
}
 
/*
==================
CL_KeepaliveMessage
 
When the client is taking a long time to load stuff, send keepalive messages
so the server doesn't disconnect.
==================
*/
void CL_KeepaliveMessage (void)
{
float time;
static float lastmsg;
int ret;
sizebuf_t old;
byte olddata[8192];
if (sv.active)
return; // no need if server is local
if (cls.demoplayback)
return;
 
// read messages from server, should just be nops
old = net_message;
memcpy (olddata, net_message.data, net_message.cursize);
do
{
ret = CL_GetMessage ();
switch (ret)
{
default:
Host_Error ("CL_KeepaliveMessage: CL_GetMessage failed");
case 0:
break; // nothing waiting
case 1:
Host_Error ("CL_KeepaliveMessage: received a message");
break;
case 2:
if (MSG_ReadByte() != svc_nop)
Host_Error ("CL_KeepaliveMessage: datagram wasn't a nop");
break;
}
} while (ret);
 
net_message = old;
memcpy (net_message.data, olddata, net_message.cursize);
 
// check time
time = Sys_FloatTime ();
if (time - lastmsg < 5)
return;
lastmsg = time;
 
// write out a nop
Con_Printf ("--> client to server keepalive\n");
 
MSG_WriteByte (&cls.message, clc_nop);
NET_SendMessage (cls.netcon, &cls.message);
SZ_Clear (&cls.message);
}
 
/*
==================
CL_ParseServerInfo
==================
*/
void CL_ParseServerInfo (void)
{
char *str;
int i;
int nummodels, numsounds;
char model_precache[MAX_MODELS][MAX_QPATH];
char sound_precache[MAX_SOUNDS][MAX_QPATH];
Con_DPrintf ("Serverinfo packet received.\n");
//
// wipe the client_state_t struct
//
CL_ClearState ();
 
// parse protocol version number
i = MSG_ReadLong ();
if (i != PROTOCOL_VERSION)
{
Con_Printf ("Server returned version %i, not %i", i, PROTOCOL_VERSION);
return;
}
 
// parse maxclients
cl.maxclients = MSG_ReadByte ();
if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
{
Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
return;
}
cl.scores = Hunk_AllocName (cl.maxclients*sizeof(*cl.scores), "scores");
 
// parse gametype
cl.gametype = MSG_ReadByte ();
 
// parse signon message
str = MSG_ReadString ();
strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
 
// seperate the printfs so the server message can have a color
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\n");
Con_Printf ("%c%s\n", 2, str);
 
//
// first we go through and touch all of the precache data that still
// happens to be in the cache, so precaching something else doesn't
// needlessly purge it
//
 
// precache models
memset (cl.model_precache, 0, sizeof(cl.model_precache));
for (nummodels=1 ; ; nummodels++)
{
str = MSG_ReadString ();
if (!str[0])
break;
if (nummodels==MAX_MODELS)
{
Con_Printf ("Server sent too many model precaches\n");
return;
}
strcpy (model_precache[nummodels], str);
Mod_TouchModel (str);
}
 
// precache sounds
memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
for (numsounds=1 ; ; numsounds++)
{
str = MSG_ReadString ();
if (!str[0])
break;
if (numsounds==MAX_SOUNDS)
{
Con_Printf ("Server sent too many sound precaches\n");
return;
}
strcpy (sound_precache[numsounds], str);
S_TouchSound (str);
}
 
//
// now we try to load everything else until a cache allocation fails
//
 
for (i=1 ; i<nummodels ; i++)
{
cl.model_precache[i] = Mod_ForName (model_precache[i], false);
if (cl.model_precache[i] == NULL)
{
Con_Printf("Model %s not found\n", model_precache[i]);
return;
}
CL_KeepaliveMessage ();
}
 
S_BeginPrecaching ();
for (i=1 ; i<numsounds ; i++)
{
cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]);
CL_KeepaliveMessage ();
}
S_EndPrecaching ();
 
 
// local state
cl_entities[0].model = cl.worldmodel = cl.model_precache[1];
R_NewMap ();
 
Hunk_Check (); // make sure nothing is hurt
noclip_anglehack = false; // noclip is turned off at start
}
 
 
/*
==================
CL_ParseUpdate
 
Parse an entity update message from the server
If an entities model or origin changes from frame to frame, it must be
relinked. Other attributes can change without relinking.
==================
*/
int bitcounts[16];
 
void CL_ParseUpdate (int bits)
{
int i;
model_t *model;
int modnum;
qboolean forcelink;
entity_t *ent;
int num;
int skin;
 
if (cls.signon == SIGNONS - 1)
{ // first update is the final signon stage
cls.signon = SIGNONS;
CL_SignonReply ();
}
 
if (bits & U_MOREBITS)
{
i = MSG_ReadByte ();
bits |= (i<<8);
}
 
if (bits & U_LONGENTITY)
num = MSG_ReadShort ();
else
num = MSG_ReadByte ();
 
ent = CL_EntityNum (num);
 
for (i=0 ; i<16 ; i++)
if (bits&(1<<i))
bitcounts[i]++;
 
if (ent->msgtime != cl.mtime[1])
forcelink = true; // no previous frame to lerp from
else
forcelink = false;
 
ent->msgtime = cl.mtime[0];
if (bits & U_MODEL)
{
modnum = MSG_ReadByte ();
if (modnum >= MAX_MODELS)
Host_Error ("CL_ParseModel: bad modnum");
}
else
modnum = ent->baseline.modelindex;
model = cl.model_precache[modnum];
if (model != ent->model)
{
ent->model = model;
// automatic animation (torches, etc) can be either all together
// or randomized
if (model)
{
if (model->synctype == ST_RAND)
ent->syncbase = (float)(rand()&0x7fff) / 0x7fff;
else
ent->syncbase = 0.0;
}
else
forcelink = true; // hack to make null model players work
#ifdef GLQUAKE
if (num > 0 && num <= cl.maxclients)
R_TranslatePlayerSkin (num - 1);
#endif
}
if (bits & U_FRAME)
ent->frame = MSG_ReadByte ();
else
ent->frame = ent->baseline.frame;
 
if (bits & U_COLORMAP)
i = MSG_ReadByte();
else
i = ent->baseline.colormap;
if (!i)
ent->colormap = vid.colormap;
else
{
if (i > cl.maxclients)
Sys_Error ("i >= cl.maxclients");
ent->colormap = cl.scores[i-1].translations;
}
 
#ifdef GLQUAKE
if (bits & U_SKIN)
skin = MSG_ReadByte();
else
skin = ent->baseline.skin;
if (skin != ent->skinnum) {
ent->skinnum = skin;
if (num > 0 && num <= cl.maxclients)
R_TranslatePlayerSkin (num - 1);
}
 
#else
 
if (bits & U_SKIN)
ent->skinnum = MSG_ReadByte();
else
ent->skinnum = ent->baseline.skin;
#endif
 
if (bits & U_EFFECTS)
ent->effects = MSG_ReadByte();
else
ent->effects = ent->baseline.effects;
 
// shift the known values for interpolation
VectorCopy (ent->msg_origins[0], ent->msg_origins[1]);
VectorCopy (ent->msg_angles[0], ent->msg_angles[1]);
 
if (bits & U_ORIGIN1)
ent->msg_origins[0][0] = MSG_ReadCoord ();
else
ent->msg_origins[0][0] = ent->baseline.origin[0];
if (bits & U_ANGLE1)
ent->msg_angles[0][0] = MSG_ReadAngle();
else
ent->msg_angles[0][0] = ent->baseline.angles[0];
 
if (bits & U_ORIGIN2)
ent->msg_origins[0][1] = MSG_ReadCoord ();
else
ent->msg_origins[0][1] = ent->baseline.origin[1];
if (bits & U_ANGLE2)
ent->msg_angles[0][1] = MSG_ReadAngle();
else
ent->msg_angles[0][1] = ent->baseline.angles[1];
 
if (bits & U_ORIGIN3)
ent->msg_origins[0][2] = MSG_ReadCoord ();
else
ent->msg_origins[0][2] = ent->baseline.origin[2];
if (bits & U_ANGLE3)
ent->msg_angles[0][2] = MSG_ReadAngle();
else
ent->msg_angles[0][2] = ent->baseline.angles[2];
 
if ( bits & U_NOLERP )
ent->forcelink = true;
 
if ( forcelink )
{ // didn't have an update last message
VectorCopy (ent->msg_origins[0], ent->msg_origins[1]);
VectorCopy (ent->msg_origins[0], ent->origin);
VectorCopy (ent->msg_angles[0], ent->msg_angles[1]);
VectorCopy (ent->msg_angles[0], ent->angles);
ent->forcelink = true;
}
}
 
/*
==================
CL_ParseBaseline
==================
*/
void CL_ParseBaseline (entity_t *ent)
{
int i;
ent->baseline.modelindex = MSG_ReadByte ();
ent->baseline.frame = MSG_ReadByte ();
ent->baseline.colormap = MSG_ReadByte();
ent->baseline.skin = MSG_ReadByte();
for (i=0 ; i<3 ; i++)
{
ent->baseline.origin[i] = MSG_ReadCoord ();
ent->baseline.angles[i] = MSG_ReadAngle ();
}
}
 
 
/*
==================
CL_ParseClientdata
 
Server information pertaining to this client only
==================
*/
void CL_ParseClientdata (int bits)
{
int i, j;
if (bits & SU_VIEWHEIGHT)
cl.viewheight = MSG_ReadChar ();
else
cl.viewheight = DEFAULT_VIEWHEIGHT;
 
if (bits & SU_IDEALPITCH)
cl.idealpitch = MSG_ReadChar ();
else
cl.idealpitch = 0;
VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
for (i=0 ; i<3 ; i++)
{
if (bits & (SU_PUNCH1<<i) )
cl.punchangle[i] = MSG_ReadChar();
else
cl.punchangle[i] = 0;
if (bits & (SU_VELOCITY1<<i) )
cl.mvelocity[0][i] = MSG_ReadChar()*16;
else
cl.mvelocity[0][i] = 0;
}
 
// [always sent] if (bits & SU_ITEMS)
i = MSG_ReadLong ();
 
if (cl.items != i)
{ // set flash times
Sbar_Changed ();
for (j=0 ; j<32 ; j++)
if ( (i & (1<<j)) && !(cl.items & (1<<j)))
cl.item_gettime[j] = cl.time;
cl.items = i;
}
cl.onground = (bits & SU_ONGROUND) != 0;
cl.inwater = (bits & SU_INWATER) != 0;
 
if (bits & SU_WEAPONFRAME)
cl.stats[STAT_WEAPONFRAME] = MSG_ReadByte ();
else
cl.stats[STAT_WEAPONFRAME] = 0;
 
if (bits & SU_ARMOR)
i = MSG_ReadByte ();
else
i = 0;
if (cl.stats[STAT_ARMOR] != i)
{
cl.stats[STAT_ARMOR] = i;
Sbar_Changed ();
}
 
if (bits & SU_WEAPON)
i = MSG_ReadByte ();
else
i = 0;
if (cl.stats[STAT_WEAPON] != i)
{
cl.stats[STAT_WEAPON] = i;
Sbar_Changed ();
}
i = MSG_ReadShort ();
if (cl.stats[STAT_HEALTH] != i)
{
cl.stats[STAT_HEALTH] = i;
Sbar_Changed ();
}
 
i = MSG_ReadByte ();
if (cl.stats[STAT_AMMO] != i)
{
cl.stats[STAT_AMMO] = i;
Sbar_Changed ();
}
 
for (i=0 ; i<4 ; i++)
{
j = MSG_ReadByte ();
if (cl.stats[STAT_SHELLS+i] != j)
{
cl.stats[STAT_SHELLS+i] = j;
Sbar_Changed ();
}
}
 
i = MSG_ReadByte ();
 
if (standard_quake)
{
if (cl.stats[STAT_ACTIVEWEAPON] != i)
{
cl.stats[STAT_ACTIVEWEAPON] = i;
Sbar_Changed ();
}
}
else
{
if (cl.stats[STAT_ACTIVEWEAPON] != (1<<i))
{
cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
Sbar_Changed ();
}
}
}
 
/*
=====================
CL_NewTranslation
=====================
*/
void CL_NewTranslation (int slot)
{
int i, j;
int top, bottom;
byte *dest, *source;
if (slot > cl.maxclients)
Sys_Error ("CL_NewTranslation: slot > cl.maxclients");
dest = cl.scores[slot].translations;
source = vid.colormap;
memcpy (dest, vid.colormap, sizeof(cl.scores[slot].translations));
top = cl.scores[slot].colors & 0xf0;
bottom = (cl.scores[slot].colors &15)<<4;
#ifdef GLQUAKE
R_TranslatePlayerSkin (slot);
#endif
 
for (i=0 ; i<VID_GRADES ; i++, dest += 256, source+=256)
{
if (top < 128) // the artists made some backwards ranges. sigh.
memcpy (dest + TOP_RANGE, source + top, 16);
else
for (j=0 ; j<16 ; j++)
dest[TOP_RANGE+j] = source[top+15-j];
if (bottom < 128)
memcpy (dest + BOTTOM_RANGE, source + bottom, 16);
else
for (j=0 ; j<16 ; j++)
dest[BOTTOM_RANGE+j] = source[bottom+15-j];
}
}
 
/*
=====================
CL_ParseStatic
=====================
*/
void CL_ParseStatic (void)
{
entity_t *ent;
int i;
i = cl.num_statics;
if (i >= MAX_STATIC_ENTITIES)
Host_Error ("Too many static entities");
ent = &cl_static_entities[i];
cl.num_statics++;
CL_ParseBaseline (ent);
 
// copy it to the current state
ent->model = cl.model_precache[ent->baseline.modelindex];
ent->frame = ent->baseline.frame;
ent->colormap = vid.colormap;
ent->skinnum = ent->baseline.skin;
ent->effects = ent->baseline.effects;
 
VectorCopy (ent->baseline.origin, ent->origin);
VectorCopy (ent->baseline.angles, ent->angles);
R_AddEfrags (ent);
}
 
/*
===================
CL_ParseStaticSound
===================
*/
void CL_ParseStaticSound (void)
{
vec3_t org;
int sound_num, vol, atten;
int i;
for (i=0 ; i<3 ; i++)
org[i] = MSG_ReadCoord ();
sound_num = MSG_ReadByte ();
vol = MSG_ReadByte ();
atten = MSG_ReadByte ();
S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
}
 
 
#define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
 
/*
=====================
CL_ParseServerMessage
=====================
*/
void CL_ParseServerMessage (void)
{
int cmd;
int i;
//
// if recording demos, copy the message out
//
if (cl_shownet.value == 1)
Con_Printf ("%i ",net_message.cursize);
else if (cl_shownet.value == 2)
Con_Printf ("------------------\n");
cl.onground = false; // unless the server says otherwise
//
// parse the message
//
MSG_BeginReading ();
while (1)
{
if (msg_badread)
Host_Error ("CL_ParseServerMessage: Bad server message");
 
cmd = MSG_ReadByte ();
 
if (cmd == -1)
{
SHOWNET("END OF MESSAGE");
return; // end of message
}
 
// if the high bit of the command byte is set, it is a fast update
if (cmd & 128)
{
SHOWNET("fast update");
CL_ParseUpdate (cmd&127);
continue;
}
 
SHOWNET(svc_strings[cmd]);
// other commands
switch (cmd)
{
default:
Host_Error ("CL_ParseServerMessage: Illegible server message\n");
break;
case svc_nop:
// Con_Printf ("svc_nop\n");
break;
case svc_time:
cl.mtime[1] = cl.mtime[0];
cl.mtime[0] = MSG_ReadFloat ();
break;
case svc_clientdata:
i = MSG_ReadShort ();
CL_ParseClientdata (i);
break;
case svc_version:
i = MSG_ReadLong ();
if (i != PROTOCOL_VERSION)
Host_Error ("CL_ParseServerMessage: Server is protocol %i instead of %i\n", i, PROTOCOL_VERSION);
break;
case svc_disconnect:
Host_EndGame ("Server disconnected\n");
 
case svc_print:
Con_Printf ("%s", MSG_ReadString ());
break;
case svc_centerprint:
SCR_CenterPrint (MSG_ReadString ());
break;
case svc_stufftext:
Cbuf_AddText (MSG_ReadString ());
break;
case svc_damage:
V_ParseDamage ();
break;
case svc_serverinfo:
CL_ParseServerInfo ();
vid.recalc_refdef = true; // leave intermission full screen
break;
case svc_setangle:
for (i=0 ; i<3 ; i++)
cl.viewangles[i] = MSG_ReadAngle ();
break;
case svc_setview:
cl.viewentity = MSG_ReadShort ();
break;
case svc_lightstyle:
i = MSG_ReadByte ();
if (i >= MAX_LIGHTSTYLES)
Sys_Error ("svc_lightstyle > MAX_LIGHTSTYLES");
Q_strcpy (cl_lightstyle[i].map, MSG_ReadString());
cl_lightstyle[i].length = Q_strlen(cl_lightstyle[i].map);
break;
case svc_sound:
CL_ParseStartSoundPacket();
break;
case svc_stopsound:
i = MSG_ReadShort();
S_StopSound(i>>3, i&7);
break;
case svc_updatename:
Sbar_Changed ();
i = MSG_ReadByte ();
if (i >= cl.maxclients)
Host_Error ("CL_ParseServerMessage: svc_updatename > MAX_SCOREBOARD");
strcpy (cl.scores[i].name, MSG_ReadString ());
break;
case svc_updatefrags:
Sbar_Changed ();
i = MSG_ReadByte ();
if (i >= cl.maxclients)
Host_Error ("CL_ParseServerMessage: svc_updatefrags > MAX_SCOREBOARD");
cl.scores[i].frags = MSG_ReadShort ();
break;
 
case svc_updatecolors:
Sbar_Changed ();
i = MSG_ReadByte ();
if (i >= cl.maxclients)
Host_Error ("CL_ParseServerMessage: svc_updatecolors > MAX_SCOREBOARD");
cl.scores[i].colors = MSG_ReadByte ();
CL_NewTranslation (i);
break;
case svc_particle:
R_ParseParticleEffect ();
break;
 
case svc_spawnbaseline:
i = MSG_ReadShort ();
// must use CL_EntityNum() to force cl.num_entities up
CL_ParseBaseline (CL_EntityNum(i));
break;
case svc_spawnstatic:
CL_ParseStatic ();
break;
case svc_temp_entity:
CL_ParseTEnt ();
break;
 
case svc_setpause:
{
cl.paused = MSG_ReadByte ();
 
if (cl.paused)
{
CDAudio_Pause ();
#ifdef _WIN32
VID_HandlePause (true);
#endif
}
else
{
CDAudio_Resume ();
#ifdef _WIN32
VID_HandlePause (false);
#endif
}
}
break;
case svc_signonnum:
i = MSG_ReadByte ();
if (i <= cls.signon)
Host_Error ("Received signon %i when at %i", i, cls.signon);
cls.signon = i;
CL_SignonReply ();
break;
 
case svc_killedmonster:
cl.stats[STAT_MONSTERS]++;
break;
 
case svc_foundsecret:
cl.stats[STAT_SECRETS]++;
break;
 
case svc_updatestat:
i = MSG_ReadByte ();
if (i < 0 || i >= MAX_CL_STATS)
Sys_Error ("svc_updatestat: %i is invalid", i);
cl.stats[i] = MSG_ReadLong ();;
break;
case svc_spawnstaticsound:
CL_ParseStaticSound ();
break;
 
case svc_cdtrack:
cl.cdtrack = MSG_ReadByte ();
cl.looptrack = MSG_ReadByte ();
if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
CDAudio_Play ((byte)cls.forcetrack, true);
else
CDAudio_Play ((byte)cl.cdtrack, true);
break;
 
case svc_intermission:
cl.intermission = 1;
cl.completed_time = cl.time;
vid.recalc_refdef = true; // go to full screen
break;
 
case svc_finale:
cl.intermission = 2;
cl.completed_time = cl.time;
vid.recalc_refdef = true; // go to full screen
SCR_CenterPrint (MSG_ReadString ());
break;
 
case svc_cutscene:
cl.intermission = 3;
cl.completed_time = cl.time;
vid.recalc_refdef = true; // go to full screen
SCR_CenterPrint (MSG_ReadString ());
break;
 
case svc_sellscreen:
Cmd_ExecuteString ("help", src_command);
break;
}
}
}
 
/contrib/other/sdlquake-1.0.9/cl_tent.c
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;
}
}
}
 
 
/contrib/other/sdlquake-1.0.9/clean.bat
0,0 → 1,18
rmdir /s /q debug
rmdir /s /q release
rmdir /s /q debug_gl
rmdir /s /q release_gl
 
rmdir /s /q gas2masm\debug
rmdir /s /q gas2masm\release
 
del gas2masm\gas2masm.opt
del gas2masm\gas2masm.plg
del gas2masm\gas2masm.ncb
del gas2masm\gas2masm.stt
 
del WinQuake.opt
del WinQuake.plg
del WinQuake.ncb
del WinQuake.stt
 
/contrib/other/sdlquake-1.0.9/client.h
0,0 → 1,375
/*
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
 
#define MAX_DLIGHTS 32
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
} 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;
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
 
// 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;
 
extern cvar_t cl_pitchdriftspeed;
extern cvar_t lookspring;
extern cvar_t lookstrafe;
extern cvar_t sensitivity;
 
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;
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);
/contrib/other/sdlquake-1.0.9/cmd.c
0,0 → 1,705
/*
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
 
/*
============
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_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;
}
/contrib/other/sdlquake-1.0.9/cmd.h
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
 
/contrib/other/sdlquake-1.0.9/common.c
0,0 → 1,1840
/*
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.
 
*/
// common.c -- misc functions used in client and server
 
#include "quakedef.h"
 
#define NUM_SAFE_ARGVS 7
 
static char *largv[MAX_NUM_ARGVS + NUM_SAFE_ARGVS + 1];
static char *argvdummy = " ";
 
static char *safeargvs[NUM_SAFE_ARGVS] =
{"-stdvid", "-nolan", "-nosound", "-nocdaudio", "-nojoy", "-nomouse", "-dibonly"};
 
cvar_t registered = {"registered","0"};
cvar_t cmdline = {"cmdline","0", false, true};
 
qboolean com_modified; // set true if using non-id files
 
qboolean proghack;
 
int static_registered = 1; // only for startup check, then set
 
qboolean msg_suppress_1 = 0;
 
void COM_InitFilesystem (void);
 
// if a packfile directory differs from this, it is assumed to be hacked
#define PAK0_COUNT 339
#define PAK0_CRC 32981
 
char com_token[1024];
int com_argc;
char **com_argv;
 
#define CMDLINE_LENGTH 256
char com_cmdline[CMDLINE_LENGTH];
 
qboolean standard_quake = true, rogue, hipnotic;
 
// this graphic needs to be in the pak file to use registered features
unsigned short pop[] =
{
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
,0x0000,0x0000,0x6600,0x0000,0x0000,0x0000,0x6600,0x0000
,0x0000,0x0066,0x0000,0x0000,0x0000,0x0000,0x0067,0x0000
,0x0000,0x6665,0x0000,0x0000,0x0000,0x0000,0x0065,0x6600
,0x0063,0x6561,0x0000,0x0000,0x0000,0x0000,0x0061,0x6563
,0x0064,0x6561,0x0000,0x0000,0x0000,0x0000,0x0061,0x6564
,0x0064,0x6564,0x0000,0x6469,0x6969,0x6400,0x0064,0x6564
,0x0063,0x6568,0x6200,0x0064,0x6864,0x0000,0x6268,0x6563
,0x0000,0x6567,0x6963,0x0064,0x6764,0x0063,0x6967,0x6500
,0x0000,0x6266,0x6769,0x6a68,0x6768,0x6a69,0x6766,0x6200
,0x0000,0x0062,0x6566,0x6666,0x6666,0x6666,0x6562,0x0000
,0x0000,0x0000,0x0062,0x6364,0x6664,0x6362,0x0000,0x0000
,0x0000,0x0000,0x0000,0x0062,0x6662,0x0000,0x0000,0x0000
,0x0000,0x0000,0x0000,0x0061,0x6661,0x0000,0x0000,0x0000
,0x0000,0x0000,0x0000,0x0000,0x6500,0x0000,0x0000,0x0000
,0x0000,0x0000,0x0000,0x0000,0x6400,0x0000,0x0000,0x0000
};
 
/*
 
 
All of Quake's data access is through a hierchal file system, but the contents of the file system can be transparently merged from several sources.
 
The "base directory" is the path to the directory holding the quake.exe and all game directories. The sys_* files pass this to host_init in quakeparms_t->basedir. This can be overridden with the "-basedir" command line parm to allow code debugging in a different directory. The base directory is
only used during filesystem initialization.
 
The "game directory" is the first tree on the search path and directory that all generated files (savegames, screenshots, demos, config files) will be saved to. This can be overridden with the "-game" command line parameter. The game directory can never be changed while quake is executing. This is a precacution against having a malicious server instruct clients to write files over areas they shouldn't.
 
The "cache directory" is only used during development to save network bandwidth, especially over ISDN / T1 lines. If there is a cache directory
specified, when a file is found by the normal search path, it will be mirrored
into the cache directory, then opened there.
 
 
 
FIXME:
The file "parms.txt" will be read out of the game directory and appended to the current command line arguments to allow different games to initialize startup parms differently. This could be used to add a "-sspeed 22050" for the high quality sound edition. Because they are added at the end, they will not override an explicit setting on the original command line.
*/
 
//============================================================================
 
 
// ClearLink is used for new headnodes
void ClearLink (link_t *l)
{
l->prev = l->next = l;
}
 
void RemoveLink (link_t *l)
{
l->next->prev = l->prev;
l->prev->next = l->next;
}
 
void InsertLinkBefore (link_t *l, link_t *before)
{
l->next = before;
l->prev = before->prev;
l->prev->next = l;
l->next->prev = l;
}
void InsertLinkAfter (link_t *l, link_t *after)
{
l->next = after->next;
l->prev = after;
l->prev->next = l;
l->next->prev = l;
}
 
/*
============================================================================
 
LIBRARY REPLACEMENT FUNCTIONS
 
============================================================================
*/
 
void Q_memset (void *dest, int fill, int count)
{
int i;
if ( (((long)dest | count) & 3) == 0)
{
count >>= 2;
fill = fill | (fill<<8) | (fill<<16) | (fill<<24);
for (i=0 ; i<count ; i++)
((int *)dest)[i] = fill;
}
else
for (i=0 ; i<count ; i++)
((byte *)dest)[i] = fill;
}
 
void Q_memcpy (void *dest, void *src, int count)
{
int i;
if (( ( (long)dest | (long)src | count) & 3) == 0 )
{
count>>=2;
for (i=0 ; i<count ; i++)
((int *)dest)[i] = ((int *)src)[i];
}
else
for (i=0 ; i<count ; i++)
((byte *)dest)[i] = ((byte *)src)[i];
}
 
int Q_memcmp (void *m1, void *m2, int count)
{
while(count)
{
count--;
if (((byte *)m1)[count] != ((byte *)m2)[count])
return -1;
}
return 0;
}
 
void Q_strcpy (char *dest, char *src)
{
while (*src)
{
*dest++ = *src++;
}
*dest++ = 0;
}
 
void Q_strncpy (char *dest, char *src, int count)
{
while (*src && count--)
{
*dest++ = *src++;
}
if (count)
*dest++ = 0;
}
 
int Q_strlen (char *str)
{
int count;
count = 0;
while (str[count])
count++;
 
return count;
}
 
char *Q_strrchr(char *s, char c)
{
int len = Q_strlen(s);
s += len;
while (len--)
if (*--s == c) return s;
return 0;
}
 
void Q_strcat (char *dest, char *src)
{
dest += Q_strlen(dest);
Q_strcpy (dest, src);
}
 
int Q_strcmp (char *s1, char *s2)
{
while (1)
{
if (*s1 != *s2)
return -1; // strings not equal
if (!*s1)
return 0; // strings are equal
s1++;
s2++;
}
return -1;
}
 
int Q_strncmp (char *s1, char *s2, int count)
{
while (1)
{
if (!count--)
return 0;
if (*s1 != *s2)
return -1; // strings not equal
if (!*s1)
return 0; // strings are equal
s1++;
s2++;
}
return -1;
}
 
int Q_strncasecmp (char *s1, char *s2, int n)
{
int c1, c2;
while (1)
{
c1 = *s1++;
c2 = *s2++;
 
if (!n--)
return 0; // strings are equal until end point
if (c1 != c2)
{
if (c1 >= 'a' && c1 <= 'z')
c1 -= ('a' - 'A');
if (c2 >= 'a' && c2 <= 'z')
c2 -= ('a' - 'A');
if (c1 != c2)
return -1; // strings not equal
}
if (!c1)
return 0; // strings are equal
// s1++;
// s2++;
}
return -1;
}
 
int Q_strcasecmp (char *s1, char *s2)
{
return Q_strncasecmp (s1, s2, 99999);
}
 
int Q_atoi (char *str)
{
int val;
int sign;
int c;
if (*str == '-')
{
sign = -1;
str++;
}
else
sign = 1;
val = 0;
 
//
// check for hex
//
if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
{
str += 2;
while (1)
{
c = *str++;
if (c >= '0' && c <= '9')
val = (val<<4) + c - '0';
else if (c >= 'a' && c <= 'f')
val = (val<<4) + c - 'a' + 10;
else if (c >= 'A' && c <= 'F')
val = (val<<4) + c - 'A' + 10;
else
return val*sign;
}
}
//
// check for character
//
if (str[0] == '\'')
{
return sign * str[1];
}
//
// assume decimal
//
while (1)
{
c = *str++;
if (c <'0' || c > '9')
return val*sign;
val = val*10 + c - '0';
}
return 0;
}
 
 
float Q_atof (char *str)
{
double val;
int sign;
int c;
int decimal, total;
if (*str == '-')
{
sign = -1;
str++;
}
else
sign = 1;
val = 0;
 
//
// check for hex
//
if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
{
str += 2;
while (1)
{
c = *str++;
if (c >= '0' && c <= '9')
val = (val*16) + c - '0';
else if (c >= 'a' && c <= 'f')
val = (val*16) + c - 'a' + 10;
else if (c >= 'A' && c <= 'F')
val = (val*16) + c - 'A' + 10;
else
return val*sign;
}
}
//
// check for character
//
if (str[0] == '\'')
{
return sign * str[1];
}
//
// assume decimal
//
decimal = -1;
total = 0;
while (1)
{
c = *str++;
if (c == '.')
{
decimal = total;
continue;
}
if (c <'0' || c > '9')
break;
val = val*10 + c - '0';
total++;
}
 
if (decimal == -1)
return val*sign;
while (total > decimal)
{
val /= 10;
total--;
}
return val*sign;
}
 
/*
============================================================================
 
BYTE ORDER FUNCTIONS
 
============================================================================
*/
 
#ifdef SDL
#include "SDL_byteorder.h"
#endif
 
qboolean bigendien;
 
short (*BigShort) (short l);
short (*LittleShort) (short l);
int (*BigLong) (int l);
int (*LittleLong) (int l);
float (*BigFloat) (float l);
float (*LittleFloat) (float l);
 
short ShortSwap (short l)
{
byte b1,b2;
 
b1 = l&255;
b2 = (l>>8)&255;
 
return (b1<<8) + b2;
}
 
short ShortNoSwap (short l)
{
return l;
}
 
int LongSwap (int l)
{
byte b1,b2,b3,b4;
 
b1 = l&255;
b2 = (l>>8)&255;
b3 = (l>>16)&255;
b4 = (l>>24)&255;
 
return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
}
 
int LongNoSwap (int l)
{
return l;
}
 
float FloatSwap (float f)
{
union
{
float f;
byte b[4];
} dat1, dat2;
dat1.f = f;
dat2.b[0] = dat1.b[3];
dat2.b[1] = dat1.b[2];
dat2.b[2] = dat1.b[1];
dat2.b[3] = dat1.b[0];
return dat2.f;
}
 
float FloatNoSwap (float f)
{
return f;
}
 
/*
==============================================================================
 
MESSAGE IO FUNCTIONS
 
Handles byte ordering and avoids alignment errors
==============================================================================
*/
 
//
// writing functions
//
 
void MSG_WriteChar (sizebuf_t *sb, int c)
{
byte *buf;
#ifdef PARANOID
if (c < -128 || c > 127)
Sys_Error ("MSG_WriteChar: range error");
#endif
 
buf = SZ_GetSpace (sb, 1);
buf[0] = c;
}
 
void MSG_WriteByte (sizebuf_t *sb, int c)
{
byte *buf;
#ifdef PARANOID
if (c < 0 || c > 255)
Sys_Error ("MSG_WriteByte: range error");
#endif
 
buf = SZ_GetSpace (sb, 1);
buf[0] = c;
}
 
void MSG_WriteShort (sizebuf_t *sb, int c)
{
byte *buf;
#ifdef PARANOID
if (c < ((short)0x8000) || c > (short)0x7fff)
Sys_Error ("MSG_WriteShort: range error");
#endif
 
buf = SZ_GetSpace (sb, 2);
buf[0] = c&0xff;
buf[1] = c>>8;
}
 
void MSG_WriteLong (sizebuf_t *sb, int c)
{
byte *buf;
buf = SZ_GetSpace (sb, 4);
buf[0] = c&0xff;
buf[1] = (c>>8)&0xff;
buf[2] = (c>>16)&0xff;
buf[3] = c>>24;
}
 
void MSG_WriteFloat (sizebuf_t *sb, float f)
{
union
{
float f;
int l;
} dat;
dat.f = f;
dat.l = LittleLong (dat.l);
SZ_Write (sb, &dat.l, 4);
}
 
void MSG_WriteString (sizebuf_t *sb, char *s)
{
if (!s)
SZ_Write (sb, "", 1);
else
SZ_Write (sb, s, Q_strlen(s)+1);
}
 
void MSG_WriteCoord (sizebuf_t *sb, float f)
{
MSG_WriteShort (sb, (int)(f*8));
}
 
void MSG_WriteAngle (sizebuf_t *sb, float f)
{
MSG_WriteByte (sb, ((int)f*256/360) & 255);
}
 
//
// reading functions
//
int msg_readcount;
qboolean msg_badread;
 
void MSG_BeginReading (void)
{
msg_readcount = 0;
msg_badread = false;
}
 
// returns -1 and sets msg_badread if no more characters are available
int MSG_ReadChar (void)
{
int c;
if (msg_readcount+1 > net_message.cursize)
{
msg_badread = true;
return -1;
}
c = (signed char)net_message.data[msg_readcount];
msg_readcount++;
return c;
}
 
int MSG_ReadByte (void)
{
int c;
if (msg_readcount+1 > net_message.cursize)
{
msg_badread = true;
return -1;
}
c = (unsigned char)net_message.data[msg_readcount];
msg_readcount++;
return c;
}
 
int MSG_ReadShort (void)
{
int c;
if (msg_readcount+2 > net_message.cursize)
{
msg_badread = true;
return -1;
}
c = (short)(net_message.data[msg_readcount]
+ (net_message.data[msg_readcount+1]<<8));
msg_readcount += 2;
return c;
}
 
int MSG_ReadLong (void)
{
int c;
if (msg_readcount+4 > net_message.cursize)
{
msg_badread = true;
return -1;
}
c = net_message.data[msg_readcount]
+ (net_message.data[msg_readcount+1]<<8)
+ (net_message.data[msg_readcount+2]<<16)
+ (net_message.data[msg_readcount+3]<<24);
msg_readcount += 4;
return c;
}
 
float MSG_ReadFloat (void)
{
union
{
byte b[4];
float f;
int l;
} dat;
dat.b[0] = net_message.data[msg_readcount];
dat.b[1] = net_message.data[msg_readcount+1];
dat.b[2] = net_message.data[msg_readcount+2];
dat.b[3] = net_message.data[msg_readcount+3];
msg_readcount += 4;
dat.l = LittleLong (dat.l);
 
return dat.f;
}
 
char *MSG_ReadString (void)
{
static char string[2048];
int l,c;
l = 0;
do
{
c = MSG_ReadChar ();
if (c == -1 || c == 0)
break;
string[l] = c;
l++;
} while (l < sizeof(string)-1);
string[l] = 0;
return string;
}
 
float MSG_ReadCoord (void)
{
return MSG_ReadShort() * (1.0/8);
}
 
float MSG_ReadAngle (void)
{
return MSG_ReadChar() * (360.0/256);
}
 
 
 
//===========================================================================
 
void SZ_Alloc (sizebuf_t *buf, int startsize)
{
if (startsize < 256)
startsize = 256;
buf->data = Hunk_AllocName (startsize, "sizebuf");
buf->maxsize = startsize;
buf->cursize = 0;
}
 
 
void SZ_Free (sizebuf_t *buf)
{
// Z_Free (buf->data);
// buf->data = NULL;
// buf->maxsize = 0;
buf->cursize = 0;
}
 
void SZ_Clear (sizebuf_t *buf)
{
buf->cursize = 0;
}
 
void *SZ_GetSpace (sizebuf_t *buf, int length)
{
void *data;
if (buf->cursize + length > buf->maxsize)
{
if (!buf->allowoverflow)
Sys_Error ("SZ_GetSpace: overflow without allowoverflow set");
if (length > buf->maxsize)
Sys_Error ("SZ_GetSpace: %i is > full buffer size", length);
buf->overflowed = true;
Con_Printf ("SZ_GetSpace: overflow");
SZ_Clear (buf);
}
 
data = buf->data + buf->cursize;
buf->cursize += length;
return data;
}
 
void SZ_Write (sizebuf_t *buf, void *data, int length)
{
Q_memcpy (SZ_GetSpace(buf,length),data,length);
}
 
void SZ_Print (sizebuf_t *buf, char *data)
{
int len;
len = Q_strlen(data)+1;
 
// byte * cast to keep VC++ happy
if (buf->data[buf->cursize-1])
Q_memcpy ((byte *)SZ_GetSpace(buf, len),data,len); // no trailing 0
else
Q_memcpy ((byte *)SZ_GetSpace(buf, len-1)-1,data,len); // write over trailing 0
}
 
 
//============================================================================
 
 
/*
============
COM_SkipPath
============
*/
char *COM_SkipPath (char *pathname)
{
char *last;
last = pathname;
while (*pathname)
{
if (*pathname=='/')
last = pathname+1;
pathname++;
}
return last;
}
 
/*
============
COM_StripExtension
============
*/
void COM_StripExtension (char *in, char *out)
{
while (*in && *in != '.')
*out++ = *in++;
*out = 0;
}
 
/*
============
COM_FileExtension
============
*/
char *COM_FileExtension (char *in)
{
static char exten[8];
int i;
 
while (*in && *in != '.')
in++;
if (!*in)
return "";
in++;
for (i=0 ; i<7 && *in ; i++,in++)
exten[i] = *in;
exten[i] = 0;
return exten;
}
 
/*
============
COM_FileBase
============
*/
void COM_FileBase (char *in, char *out)
{
char *s, *s2;
s = in + strlen(in) - 1;
while (s != in && *s != '.')
s--;
for (s2 = s ; *s2 && *s2 != '/' ; s2--)
;
if (s-s2 < 2)
strcpy (out,"?model?");
else
{
s--;
strncpy (out,s2+1, s-s2);
out[s-s2] = 0;
}
}
 
 
/*
==================
COM_DefaultExtension
==================
*/
void COM_DefaultExtension (char *path, char *extension)
{
char *src;
//
// if path doesn't have a .EXT, append extension
// (extension should include the .)
//
src = path + strlen(path) - 1;
 
while (*src != '/' && src != path)
{
if (*src == '.')
return; // it has an extension
src--;
}
 
strcat (path, extension);
}
 
 
/*
==============
COM_Parse
 
Parse a token out of a string
==============
*/
char *COM_Parse (char *data)
{
int c;
int len;
len = 0;
com_token[0] = 0;
if (!data)
return NULL;
// skip whitespace
skipwhite:
while ( (c = *data) <= ' ')
{
if (c == 0)
return NULL; // end of file;
data++;
}
// skip // comments
if (c=='/' && data[1] == '/')
{
while (*data && *data != '\n')
data++;
goto skipwhite;
}
 
// handle quoted strings specially
if (c == '\"')
{
data++;
while (1)
{
c = *data++;
if (c=='\"' || !c)
{
com_token[len] = 0;
return data;
}
com_token[len] = c;
len++;
}
}
 
// parse single characters
if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
{
com_token[len] = c;
len++;
com_token[len] = 0;
return data+1;
}
 
// parse a regular word
do
{
com_token[len] = c;
data++;
len++;
c = *data;
if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
break;
} while (c>32);
com_token[len] = 0;
return data;
}
 
 
/*
================
COM_CheckParm
 
Returns the position (1 to argc-1) in the program's argument list
where the given parameter apears, or 0 if not present
================
*/
int COM_CheckParm (char *parm)
{
int i;
for (i=1 ; i<com_argc ; i++)
{
if (!com_argv[i])
continue; // NEXTSTEP sometimes clears appkit vars.
if (!Q_strcmp (parm,com_argv[i]))
return i;
}
return 0;
}
 
/*
================
COM_CheckRegistered
 
Looks for the pop.txt file and verifies it.
Sets the "registered" cvar.
Immediately exits out if an alternate game was attempted to be started without
being registered.
================
*/
void COM_CheckRegistered (void)
{
int h;
unsigned short check[128];
int i;
 
COM_OpenFile("gfx/pop.lmp", &h);
static_registered = 0;
 
if (h == -1)
{
#if WINDED
Sys_Error ("This dedicated server requires a full registered copy of Quake");
#endif
Con_Printf ("Playing shareware version.\n");
if (com_modified)
Sys_Error ("You must have the registered version to use modified games");
return;
}
 
Sys_FileRead (h, check, sizeof(check));
COM_CloseFile (h);
for (i=0 ; i<128 ; i++)
if (pop[i] != (unsigned short)BigShort (check[i]))
Sys_Error ("Corrupted data file.");
Cvar_Set ("cmdline", com_cmdline);
Cvar_Set ("registered", "1");
static_registered = 1;
Con_Printf ("Playing registered version.\n");
}
 
 
void COM_Path_f (void);
 
 
/*
================
COM_InitArgv
================
*/
void COM_InitArgv (int argc, char **argv)
{
qboolean safe;
int i, j, n;
 
// reconstitute the command line for the cmdline externally visible cvar
n = 0;
 
for (j=0 ; (j<MAX_NUM_ARGVS) && (j< argc) ; j++)
{
i = 0;
 
while ((n < (CMDLINE_LENGTH - 1)) && argv[j][i])
{
com_cmdline[n++] = argv[j][i++];
}
 
if (n < (CMDLINE_LENGTH - 1))
com_cmdline[n++] = ' ';
else
break;
}
 
com_cmdline[n] = 0;
 
safe = false;
 
for (com_argc=0 ; (com_argc<MAX_NUM_ARGVS) && (com_argc < argc) ;
com_argc++)
{
largv[com_argc] = argv[com_argc];
if (!Q_strcmp ("-safe", argv[com_argc]))
safe = true;
}
 
if (safe)
{
// force all the safe-mode switches. Note that we reserved extra space in
// case we need to add these, so we don't need an overflow check
for (i=0 ; i<NUM_SAFE_ARGVS ; i++)
{
largv[com_argc] = safeargvs[i];
com_argc++;
}
}
 
largv[com_argc] = argvdummy;
com_argv = largv;
 
if (COM_CheckParm ("-rogue"))
{
rogue = true;
standard_quake = false;
}
 
if (COM_CheckParm ("-hipnotic"))
{
hipnotic = true;
standard_quake = false;
}
}
 
 
/*
================
COM_Init
================
*/
void COM_Init (char *basedir)
{
byte swaptest[2] = {1,0};
 
// set the byte swapping variables in a portable manner
#ifdef SDL
// This is necessary because egcs 1.1.1 mis-compiles swaptest with -O2
if ( SDL_BYTEORDER == SDL_LIL_ENDIAN )
#else
if ( *(short *)swaptest == 1)
#endif
{
bigendien = false;
BigShort = ShortSwap;
LittleShort = ShortNoSwap;
BigLong = LongSwap;
LittleLong = LongNoSwap;
BigFloat = FloatSwap;
LittleFloat = FloatNoSwap;
}
else
{
bigendien = true;
BigShort = ShortNoSwap;
LittleShort = ShortSwap;
BigLong = LongNoSwap;
LittleLong = LongSwap;
BigFloat = FloatNoSwap;
LittleFloat = FloatSwap;
}
 
Cvar_RegisterVariable (&registered);
Cvar_RegisterVariable (&cmdline);
Cmd_AddCommand ("path", COM_Path_f);
 
COM_InitFilesystem ();
COM_CheckRegistered ();
}
 
 
/*
============
va
 
does a varargs printf into a temp buffer, so I don't need to have
varargs versions of all text functions.
FIXME: make this buffer size safe someday
============
*/
char *va(char *format, ...)
{
va_list argptr;
static char string[1024];
va_start (argptr, format);
vsprintf (string, format,argptr);
va_end (argptr);
 
return string;
}
 
 
/// just for debugging
int memsearch (byte *start, int count, int search)
{
int i;
for (i=0 ; i<count ; i++)
if (start[i] == search)
return i;
return -1;
}
 
/*
=============================================================================
 
QUAKE FILESYSTEM
 
=============================================================================
*/
 
int com_filesize;
 
 
//
// in memory
//
 
typedef struct
{
char name[MAX_QPATH];
int filepos, filelen;
} packfile_t;
 
typedef struct pack_s
{
char filename[MAX_OSPATH];
int handle;
int numfiles;
packfile_t *files;
} pack_t;
 
//
// on disk
//
typedef struct
{
char name[56];
int filepos, filelen;
} dpackfile_t;
 
typedef struct
{
char id[4];
int dirofs;
int dirlen;
} dpackheader_t;
 
#define MAX_FILES_IN_PACK 2048
 
char com_cachedir[MAX_OSPATH];
char com_gamedir[MAX_OSPATH];
 
typedef struct searchpath_s
{
char filename[MAX_OSPATH];
pack_t *pack; // only one of filename / pack will be used
struct searchpath_s *next;
} searchpath_t;
 
searchpath_t *com_searchpaths;
 
/*
============
COM_Path_f
 
============
*/
void COM_Path_f (void)
{
searchpath_t *s;
Con_Printf ("Current search path:\n");
for (s=com_searchpaths ; s ; s=s->next)
{
if (s->pack)
{
Con_Printf ("%s (%i files)\n", s->pack->filename, s->pack->numfiles);
}
else
Con_Printf ("%s\n", s->filename);
}
}
 
/*
============
COM_WriteFile
 
The filename will be prefixed by the current game directory
============
*/
void COM_WriteFile (char *filename, void *data, int len)
{
int handle;
char name[MAX_OSPATH];
sprintf (name, "%s/%s", com_gamedir, filename);
 
handle = Sys_FileOpenWrite (name);
if (handle == -1)
{
Sys_Printf ("COM_WriteFile: failed on %s\n", name);
return;
}
Sys_Printf ("COM_WriteFile: %s\n", name);
Sys_FileWrite (handle, data, len);
Sys_FileClose (handle);
}
 
 
/*
============
COM_CreatePath
 
Only used for CopyFile
============
*/
void COM_CreatePath (char *path)
{
char *ofs;
for (ofs = path+1 ; *ofs ; ofs++)
{
if (*ofs == '/')
{ // create the directory
*ofs = 0;
Sys_mkdir (path);
*ofs = '/';
}
}
}
 
 
/*
===========
COM_CopyFile
 
Copies a file over from the net to the local cache, creating any directories
needed. This is for the convenience of developers using ISDN from home.
===========
*/
void COM_CopyFile (char *netpath, char *cachepath)
{
int in, out;
int remaining, count;
char buf[4096];
remaining = Sys_FileOpenRead (netpath, &in);
COM_CreatePath (cachepath); // create directories up to the cache file
out = Sys_FileOpenWrite (cachepath);
while (remaining)
{
if (remaining < sizeof(buf))
count = remaining;
else
count = sizeof(buf);
Sys_FileRead (in, buf, count);
Sys_FileWrite (out, buf, count);
remaining -= count;
}
 
Sys_FileClose (in);
Sys_FileClose (out);
}
 
/*
===========
COM_FindFile
 
Finds the file in the search path.
Sets com_filesize and one of handle or file
===========
*/
int COM_FindFile (char *filename, int *handle, FILE **file)
{
searchpath_t *search;
char netpath[MAX_OSPATH];
char cachepath[MAX_OSPATH];
pack_t *pak;
int i;
int findtime, cachetime;
 
if (file && handle)
Sys_Error ("COM_FindFile: both handle and file set");
if (!file && !handle)
Sys_Error ("COM_FindFile: neither handle or file set");
//
// search through the path, one element at a time
//
search = com_searchpaths;
if (proghack)
{ // gross hack to use quake 1 progs with quake 2 maps
if (!strcmp(filename, "progs.dat"))
search = search->next;
}
 
for ( ; search ; search = search->next)
{
// is the element a pak file?
if (search->pack)
{
// look through all the pak file elements
pak = search->pack;
for (i=0 ; i<pak->numfiles ; i++)
if (!strcmp (pak->files[i].name, filename))
{ // found it!
Sys_Printf ("PackFile: %s : %s\n",pak->filename, filename);
if (handle)
{
*handle = pak->handle;
Sys_FileSeek (pak->handle, pak->files[i].filepos);
}
else
{ // open a new file on the pakfile
*file = fopen (pak->filename, "rb");
if (*file)
fseek (*file, pak->files[i].filepos, SEEK_SET);
}
com_filesize = pak->files[i].filelen;
return com_filesize;
}
}
else
{
// check a file in the directory tree
if (!static_registered)
{ // if not a registered version, don't ever go beyond base
if ( strchr (filename, '/') || strchr (filename,'\\'))
continue;
}
sprintf (netpath, "%s/%s",search->filename, filename);
findtime = Sys_FileTime (netpath);
if (findtime == -1)
continue;
// see if the file needs to be updated in the cache
if (!com_cachedir[0])
strcpy (cachepath, netpath);
else
{
#if defined(_WIN32)
if ((strlen(netpath) < 2) || (netpath[1] != ':'))
sprintf (cachepath,"%s%s", com_cachedir, netpath);
else
sprintf (cachepath,"%s%s", com_cachedir, netpath+2);
#else
sprintf (cachepath,"%s/%s", com_cachedir, netpath);
#endif
 
cachetime = Sys_FileTime (cachepath);
if (cachetime < findtime)
COM_CopyFile (netpath, cachepath);
strcpy (netpath, cachepath);
}
 
Sys_Printf ("FindFile: %s\n",netpath);
com_filesize = Sys_FileOpenRead (netpath, &i);
if (handle)
*handle = i;
else
{
Sys_FileClose (i);
*file = fopen (netpath, "rb");
}
return com_filesize;
}
}
Sys_Printf ("FindFile: can't find %s\n", filename);
if (handle)
*handle = -1;
else
*file = NULL;
com_filesize = -1;
return -1;
}
 
 
/*
===========
COM_OpenFile
 
filename never has a leading slash, but may contain directory walks
returns a handle and a length
it may actually be inside a pak file
===========
*/
int COM_OpenFile (char *filename, int *handle)
{
return COM_FindFile (filename, handle, NULL);
}
 
/*
===========
COM_FOpenFile
 
If the requested file is inside a packfile, a new FILE * will be opened
into the file.
===========
*/
int COM_FOpenFile (char *filename, FILE **file)
{
return COM_FindFile (filename, NULL, file);
}
 
/*
============
COM_CloseFile
 
If it is a pak file handle, don't really close it
============
*/
void COM_CloseFile (int h)
{
searchpath_t *s;
for (s = com_searchpaths ; s ; s=s->next)
if (s->pack && s->pack->handle == h)
return;
Sys_FileClose (h);
}
 
 
/*
============
COM_LoadFile
 
Filename are reletive to the quake directory.
Allways appends a 0 byte.
============
*/
cache_user_t *loadcache;
byte *loadbuf;
int loadsize;
byte *COM_LoadFile (char *path, int usehunk)
{
int h;
byte *buf;
char base[32];
int len;
 
buf = NULL; // quiet compiler warning
 
// look for it in the filesystem or pack files
len = COM_OpenFile (path, &h);
if (h == -1)
return NULL;
// extract the filename base name for hunk tag
COM_FileBase (path, base);
if (usehunk == 1)
buf = Hunk_AllocName (len+1, base);
else if (usehunk == 2)
buf = Hunk_TempAlloc (len+1);
else if (usehunk == 0)
buf = Z_Malloc (len+1);
else if (usehunk == 3)
buf = Cache_Alloc (loadcache, len+1, base);
else if (usehunk == 4)
{
if (len+1 > loadsize)
buf = Hunk_TempAlloc (len+1);
else
buf = loadbuf;
}
else
Sys_Error ("COM_LoadFile: bad usehunk");
 
if (!buf)
Sys_Error ("COM_LoadFile: not enough space for %s", path);
((byte *)buf)[len] = 0;
 
Draw_BeginDisc ();
Sys_FileRead (h, buf, len);
COM_CloseFile (h);
Draw_EndDisc ();
 
return buf;
}
 
byte *COM_LoadHunkFile (char *path)
{
return COM_LoadFile (path, 1);
}
 
byte *COM_LoadTempFile (char *path)
{
return COM_LoadFile (path, 2);
}
 
void COM_LoadCacheFile (char *path, struct cache_user_s *cu)
{
loadcache = cu;
COM_LoadFile (path, 3);
}
 
// uses temp hunk if larger than bufsize
byte *COM_LoadStackFile (char *path, void *buffer, int bufsize)
{
byte *buf;
loadbuf = (byte *)buffer;
loadsize = bufsize;
buf = COM_LoadFile (path, 4);
return buf;
}
 
/*
=================
COM_LoadPackFile
 
Takes an explicit (not game tree related) path to a pak file.
 
Loads the header and directory, adding the files at the beginning
of the list so they override previous pack files.
=================
*/
pack_t *COM_LoadPackFile (char *packfile)
{
dpackheader_t header;
int i;
packfile_t *newfiles;
int numpackfiles;
pack_t *pack;
int packhandle;
dpackfile_t info[MAX_FILES_IN_PACK];
unsigned short crc;
 
if (Sys_FileOpenRead (packfile, &packhandle) == -1)
{
// Con_Printf ("Couldn't open %s\n", packfile);
return NULL;
}
Sys_FileRead (packhandle, (void *)&header, sizeof(header));
if (header.id[0] != 'P' || header.id[1] != 'A'
|| header.id[2] != 'C' || header.id[3] != 'K')
Sys_Error ("%s is not a packfile", packfile);
header.dirofs = LittleLong (header.dirofs);
header.dirlen = LittleLong (header.dirlen);
 
numpackfiles = header.dirlen / sizeof(dpackfile_t);
 
if (numpackfiles > MAX_FILES_IN_PACK)
Sys_Error ("%s has %i files", packfile, numpackfiles);
 
if (numpackfiles != PAK0_COUNT)
com_modified = true; // not the original file
 
newfiles = Hunk_AllocName (numpackfiles * sizeof(packfile_t), "packfile");
 
Sys_FileSeek (packhandle, header.dirofs);
Sys_FileRead (packhandle, (void *)info, header.dirlen);
 
// crc the directory to check for modifications
CRC_Init (&crc);
for (i=0 ; i<header.dirlen ; i++)
CRC_ProcessByte (&crc, ((byte *)info)[i]);
if (crc != PAK0_CRC)
com_modified = true;
 
// parse the directory
for (i=0 ; i<numpackfiles ; i++)
{
strcpy (newfiles[i].name, info[i].name);
newfiles[i].filepos = LittleLong(info[i].filepos);
newfiles[i].filelen = LittleLong(info[i].filelen);
}
 
pack = Hunk_Alloc (sizeof (pack_t));
strcpy (pack->filename, packfile);
pack->handle = packhandle;
pack->numfiles = numpackfiles;
pack->files = newfiles;
Con_Printf ("Added packfile %s (%i files)\n", packfile, numpackfiles);
return pack;
}
 
 
/*
================
COM_AddGameDirectory
 
Sets com_gamedir, adds the directory to the head of the path,
then loads and adds pak1.pak pak2.pak ...
================
*/
void COM_AddGameDirectory (char *dir)
{
int i;
searchpath_t *search;
pack_t *pak;
char pakfile[MAX_OSPATH];
 
strcpy (com_gamedir, dir);
 
//
// add the directory to the search path
//
search = Hunk_Alloc (sizeof(searchpath_t));
strcpy (search->filename, dir);
search->next = com_searchpaths;
com_searchpaths = search;
 
//
// add any pak files in the format pak0.pak pak1.pak, ...
//
for (i=0 ; ; i++)
{
sprintf (pakfile, "%s/pak%i.pak", dir, i);
pak = COM_LoadPackFile (pakfile);
if (!pak)
break;
search = Hunk_Alloc (sizeof(searchpath_t));
search->pack = pak;
search->next = com_searchpaths;
com_searchpaths = search;
}
 
//
// add the contents of the parms.txt file to the end of the command line
//
 
}
 
/*
================
COM_InitFilesystem
================
*/
void COM_InitFilesystem (void)
{
int i, j;
char basedir[MAX_OSPATH];
searchpath_t *search;
 
//
// -basedir <path>
// Overrides the system supplied base directory (under GAMENAME)
//
i = COM_CheckParm ("-basedir");
if (i && i < com_argc-1)
strcpy (basedir, com_argv[i+1]);
else
strcpy (basedir, host_parms.basedir);
 
j = strlen (basedir);
 
if (j > 0)
{
if ((basedir[j-1] == '\\') || (basedir[j-1] == '/'))
basedir[j-1] = 0;
}
 
//
// -cachedir <path>
// Overrides the system supplied cache directory (NULL or /qcache)
// -cachedir - will disable caching.
//
i = COM_CheckParm ("-cachedir");
if (i && i < com_argc-1)
{
if (com_argv[i+1][0] == '-')
com_cachedir[0] = 0;
else
strcpy (com_cachedir, com_argv[i+1]);
}
else if (host_parms.cachedir)
strcpy (com_cachedir, host_parms.cachedir);
else
com_cachedir[0] = 0;
 
//
// start up with GAMENAME by default (id1)
//
#ifdef _KOLIBRI
COM_AddGameDirectory (basedir);
#else
COM_AddGameDirectory (va("%s/"GAMENAME, basedir) );
#endif
 
if (COM_CheckParm ("-rogue"))
COM_AddGameDirectory (va("%s/rogue", basedir) );
if (COM_CheckParm ("-hipnotic"))
COM_AddGameDirectory (va("%s/hipnotic", basedir) );
 
//
// -game <gamedir>
// Adds basedir/gamedir as an override game
//
i = COM_CheckParm ("-game");
if (i && i < com_argc-1)
{
com_modified = true;
COM_AddGameDirectory (va("%s/%s", basedir, com_argv[i+1]));
}
 
//
// -path <dir or packfile> [<dir or packfile>] ...
// Fully specifies the exact serach path, overriding the generated one
//
i = COM_CheckParm ("-path");
if (i)
{
com_modified = true;
com_searchpaths = NULL;
while (++i < com_argc)
{
if (!com_argv[i] || com_argv[i][0] == '+' || com_argv[i][0] == '-')
break;
search = Hunk_Alloc (sizeof(searchpath_t));
if ( !strcmp(COM_FileExtension(com_argv[i]), "pak") )
{
search->pack = COM_LoadPackFile (com_argv[i]);
if (!search->pack)
Sys_Error ("Couldn't load packfile: %s", com_argv[i]);
}
else
strcpy (search->filename, com_argv[i]);
search->next = com_searchpaths;
com_searchpaths = search;
}
}
 
if (COM_CheckParm ("-proghack"))
proghack = true;
}
 
 
/contrib/other/sdlquake-1.0.9/common.h
0,0 → 1,183
/*
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);
 
//============================================================================
 
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);
 
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;
/contrib/other/sdlquake-1.0.9/config.guess
0,0 → 1,997
#! /bin/sh
# Attempt to guess a canonical system name.
# Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
#
# This file 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.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
 
# Written by Per Bothner <bothner@cygnus.com>.
# The master version of this file is at the FSF in /home/gd/gnu/lib.
# Please send patches to the Autoconf mailing list <autoconf@gnu.org>.
#
# This script attempts to guess a canonical system name similar to
# config.sub. If it succeeds, it prints the system name on stdout, and
# exits with 0. Otherwise, it exits with 1.
#
# The plan is that this can be called by configure scripts if you
# don't specify an explicit system type (host/target name).
#
# Only a few systems have been added to this list; please add others
# (but try to keep the structure clean).
#
 
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
# (ghazi@noc.rutgers.edu 8/24/94.)
if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
PATH=$PATH:/.attbin ; export PATH
fi
 
UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
 
dummy=dummy-$$
trap 'rm -f $dummy.c $dummy.o $dummy; exit 1' 1 2 15
 
# Note: order is significant - the case branches are not exclusive.
 
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
alpha:OSF1:*:*)
if test $UNAME_RELEASE = "V4.0"; then
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
fi
# A Vn.n version is a released version.
# A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
cat <<EOF >$dummy.s
.globl main
.ent main
main:
.frame \$30,0,\$26,0
.prologue 0
.long 0x47e03d80 # implver $0
lda \$2,259
.long 0x47e20c21 # amask $2,$1
srl \$1,8,\$2
sll \$2,2,\$2
sll \$0,3,\$0
addl \$1,\$0,\$0
addl \$2,\$0,\$0
ret \$31,(\$26),1
.end main
EOF
${CC-cc} $dummy.s -o $dummy 2>/dev/null
if test "$?" = 0 ; then
./$dummy
case "$?" in
7)
UNAME_MACHINE="alpha"
;;
15)
UNAME_MACHINE="alphaev5"
;;
14)
UNAME_MACHINE="alphaev56"
;;
10)
UNAME_MACHINE="alphapca56"
;;
16)
UNAME_MACHINE="alphaev6"
;;
esac
fi
rm -f $dummy.s $dummy
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr [[A-Z]] [[a-z]]`
exit 0 ;;
21064:Windows_NT:50:3)
echo alpha-dec-winnt3.5
exit 0 ;;
Amiga*:UNIX_System_V:4.0:*)
echo m68k-cbm-sysv4
exit 0;;
amiga:NetBSD:*:*)
echo m68k-cbm-netbsd${UNAME_RELEASE}
exit 0 ;;
amiga:OpenBSD:*:*)
echo m68k-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
*:[Aa]miga[Oo][Ss]:*:*)
echo ${UNAME_MACHINE}-unknown-amigaos
exit 0 ;;
arc64:OpenBSD:*:*)
echo mips64el-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
arc:OpenBSD:*:*)
echo mipsel-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
hkmips:OpenBSD:*:*)
echo mips-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
pmax:OpenBSD:*:*)
echo mipsel-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
sgi:OpenBSD:*:*)
echo mips-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
wgrisc:OpenBSD:*:*)
echo mipsel-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
echo arm-acorn-riscix${UNAME_RELEASE}
exit 0;;
arm32:NetBSD:*:*)
echo arm-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
exit 0 ;;
SR2?01:HI-UX/MPP:*:*)
echo hppa1.1-hitachi-hiuxmpp
exit 0;;
Pyramid*:OSx*:*:*|MIS*:OSx*:*:*|MIS*:SMP_DC-OSx*:*:*)
# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
if test "`(/bin/universe) 2>/dev/null`" = att ; then
echo pyramid-pyramid-sysv3
else
echo pyramid-pyramid-bsd
fi
exit 0 ;;
NILE*:*:*:dcosx)
echo pyramid-pyramid-svr4
exit 0 ;;
sun4H:SunOS:5.*:*)
echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
i86pc:SunOS:5.*:*)
echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize
# SunOS6. Hard to guess exactly what SunOS6 will be like, but
# it's likely to be more like Solaris than SunOS4.
echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
sun4*:SunOS:*:*)
case "`/usr/bin/arch -k`" in
Series*|S4*)
UNAME_RELEASE=`uname -v`
;;
esac
# Japanese Language versions have a version number like `4.1.3-JL'.
echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
exit 0 ;;
sun3*:SunOS:*:*)
echo m68k-sun-sunos${UNAME_RELEASE}
exit 0 ;;
sun*:*:4.2BSD:*)
UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
case "`/bin/arch`" in
sun3)
echo m68k-sun-sunos${UNAME_RELEASE}
;;
sun4)
echo sparc-sun-sunos${UNAME_RELEASE}
;;
esac
exit 0 ;;
aushp:SunOS:*:*)
echo sparc-auspex-sunos${UNAME_RELEASE}
exit 0 ;;
atari*:NetBSD:*:*)
echo m68k-atari-netbsd${UNAME_RELEASE}
exit 0 ;;
atari*:OpenBSD:*:*)
echo m68k-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
sun3*:NetBSD:*:*)
echo m68k-sun-netbsd${UNAME_RELEASE}
exit 0 ;;
sun3*:OpenBSD:*:*)
echo m68k-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
mac68k:NetBSD:*:*)
echo m68k-apple-netbsd${UNAME_RELEASE}
exit 0 ;;
mac68k:OpenBSD:*:*)
echo m68k-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
mvme68k:OpenBSD:*:*)
echo m68k-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
mvme88k:OpenBSD:*:*)
echo m88k-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
powerpc:machten:*:*)
echo powerpc-apple-machten${UNAME_RELEASE}
exit 0 ;;
macppc:NetBSD:*:*)
echo powerpc-apple-netbsd${UNAME_RELEASE}
exit 0 ;;
RISC*:Mach:*:*)
echo mips-dec-mach_bsd4.3
exit 0 ;;
RISC*:ULTRIX:*:*)
echo mips-dec-ultrix${UNAME_RELEASE}
exit 0 ;;
VAX*:ULTRIX*:*:*)
echo vax-dec-ultrix${UNAME_RELEASE}
exit 0 ;;
2020:CLIX:*:*)
echo clipper-intergraph-clix${UNAME_RELEASE}
exit 0 ;;
mips:*:*:UMIPS | mips:*:*:RISCos)
sed 's/^ //' << EOF >$dummy.c
#ifdef __cplusplus
int main (int argc, char *argv[]) {
#else
int main (argc, argv) int argc; char *argv[]; {
#endif
#if defined (host_mips) && defined (MIPSEB)
#if defined (SYSTYPE_SYSV)
printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_SVR4)
printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
#endif
#endif
exit (-1);
}
EOF
${CC-cc} $dummy.c -o $dummy \
&& ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
&& rm $dummy.c $dummy && exit 0
rm -f $dummy.c $dummy
echo mips-mips-riscos${UNAME_RELEASE}
exit 0 ;;
Night_Hawk:Power_UNIX:*:*)
echo powerpc-harris-powerunix
exit 0 ;;
m88k:CX/UX:7*:*)
echo m88k-harris-cxux7
exit 0 ;;
m88k:*:4*:R4*)
echo m88k-motorola-sysv4
exit 0 ;;
m88k:*:3*:R3*)
echo m88k-motorola-sysv3
exit 0 ;;
AViiON:dgux:*:*)
# DG/UX returns AViiON for all architectures
UNAME_PROCESSOR=`/usr/bin/uname -p`
if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
-o ${TARGET_BINARY_INTERFACE}x = x ] ; then
echo m88k-dg-dgux${UNAME_RELEASE}
else
echo m88k-dg-dguxbcs${UNAME_RELEASE}
fi
else echo i586-dg-dgux${UNAME_RELEASE}
fi
exit 0 ;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
echo m88k-dolphin-sysv3
exit 0 ;;
M88*:*:R3*:*)
# Delta 88k system running SVR3
echo m88k-motorola-sysv3
exit 0 ;;
XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
echo m88k-tektronix-sysv3
exit 0 ;;
Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
echo m68k-tektronix-bsd
exit 0 ;;
*:IRIX*:*:*)
echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
exit 0 ;;
????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
i?86:AIX:*:*)
echo i386-ibm-aix
exit 0 ;;
*:AIX:2:3)
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
sed 's/^ //' << EOF >$dummy.c
#include <sys/systemcfg.h>
 
main()
{
if (!__power_pc())
exit(1);
puts("powerpc-ibm-aix3.2.5");
exit(0);
}
EOF
${CC-cc} $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0
rm -f $dummy.c $dummy
echo rs6000-ibm-aix3.2.5
elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
echo rs6000-ibm-aix3.2.4
else
echo rs6000-ibm-aix3.2
fi
exit 0 ;;
*:AIX:*:4)
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'`
if /usr/sbin/lsattr -EHl ${IBM_CPU_ID} | grep POWER >/dev/null 2>&1; then
IBM_ARCH=rs6000
else
IBM_ARCH=powerpc
fi
if [ -x /usr/bin/oslevel ] ; then
IBM_REV=`/usr/bin/oslevel`
else
IBM_REV=4.${UNAME_RELEASE}
fi
echo ${IBM_ARCH}-ibm-aix${IBM_REV}
exit 0 ;;
*:AIX:*:*)
echo rs6000-ibm-aix
exit 0 ;;
ibmrt:4.4BSD:*|romp-ibm:BSD:*)
echo romp-ibm-bsd4.4
exit 0 ;;
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and
echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
exit 0 ;; # report: romp-ibm BSD 4.3
*:BOSX:*:*)
echo rs6000-bull-bosx
exit 0 ;;
DPX/2?00:B.O.S.:*:*)
echo m68k-bull-sysv3
exit 0 ;;
9000/[34]??:4.3bsd:1.*:*)
echo m68k-hp-bsd
exit 0 ;;
hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
echo m68k-hp-bsd4.4
exit 0 ;;
9000/[34678]??:HP-UX:*:*)
case "${UNAME_MACHINE}" in
9000/31? ) HP_ARCH=m68000 ;;
9000/[34]?? ) HP_ARCH=m68k ;;
9000/6?? | 9000/7?? | 9000/80[024] | 9000/8?[136790] | 9000/892 )
sed 's/^ //' << EOF >$dummy.c
#include <stdlib.h>
#include <unistd.h>
 
int main ()
{
#if defined(_SC_KERNEL_BITS)
long bits = sysconf(_SC_KERNEL_BITS);
#endif
long cpu = sysconf (_SC_CPU_VERSION);
 
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
case CPU_PA_RISC2_0:
#if defined(_SC_KERNEL_BITS)
switch (bits)
{
case 64: puts ("hppa2.0w"); break;
case 32: puts ("hppa2.0n"); break;
default: puts ("hppa2.0"); break;
} break;
#else /* !defined(_SC_KERNEL_BITS) */
puts ("hppa2.0"); break;
#endif
default: puts ("hppa1.0"); break;
}
exit (0);
}
EOF
(${CC-cc} $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy`
rm -f $dummy.c $dummy
esac
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
exit 0 ;;
3050*:HI-UX:*:*)
sed 's/^ //' << EOF >$dummy.c
#include <unistd.h>
int
main ()
{
long cpu = sysconf (_SC_CPU_VERSION);
/* The order matters, because CPU_IS_HP_MC68K erroneously returns
true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
results, however. */
if (CPU_IS_PA_RISC (cpu))
{
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
default: puts ("hppa-hitachi-hiuxwe2"); break;
}
}
else if (CPU_IS_HP_MC68K (cpu))
puts ("m68k-hitachi-hiuxwe2");
else puts ("unknown-hitachi-hiuxwe2");
exit (0);
}
EOF
${CC-cc} $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0
rm -f $dummy.c $dummy
echo unknown-hitachi-hiuxwe2
exit 0 ;;
9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
echo hppa1.1-hp-bsd
exit 0 ;;
9000/8??:4.3bsd:*:*)
echo hppa1.0-hp-bsd
exit 0 ;;
*9??*:MPE*:*:*)
echo hppa1.0-hp-mpeix
exit 0 ;;
*9??*:MPE*:*:*)
echo hppa1.0-hp-mpeix
exit 0 ;;
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
echo hppa1.1-hp-osf
exit 0 ;;
hp8??:OSF1:*:*)
echo hppa1.0-hp-osf
exit 0 ;;
i?86:OSF1:*:*)
if [ -x /usr/sbin/sysversion ] ; then
echo ${UNAME_MACHINE}-unknown-osf1mk
else
echo ${UNAME_MACHINE}-unknown-osf1
fi
exit 0 ;;
parisc*:Lites*:*:*)
echo hppa1.1-hp-lites
exit 0 ;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
echo c1-convex-bsd
exit 0 ;;
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
exit 0 ;;
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
echo c34-convex-bsd
exit 0 ;;
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
echo c38-convex-bsd
exit 0 ;;
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
echo c4-convex-bsd
exit 0 ;;
CRAY*X-MP:*:*:*)
echo xmp-cray-unicos
exit 0 ;;
CRAY*Y-MP:*:*:*)
echo ymp-cray-unicos${UNAME_RELEASE}
exit 0 ;;
CRAY*[A-Z]90:*:*:*)
echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
exit 0 ;;
CRAY*TS:*:*:*)
echo t90-cray-unicos${UNAME_RELEASE}
exit 0 ;;
CRAY*T3E:*:*:*)
echo t3e-cray-unicosmk${UNAME_RELEASE}
exit 0 ;;
CRAY-2:*:*:*)
echo cray2-cray-unicos
exit 0 ;;
F300:UNIX_System_V:*:*)
FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit 0 ;;
F301:UNIX_System_V:*:*)
echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'`
exit 0 ;;
hp3[0-9][05]:NetBSD:*:*)
echo m68k-hp-netbsd${UNAME_RELEASE}
exit 0 ;;
hp300:OpenBSD:*:*)
echo m68k-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
sparc*:BSD/OS:*:*)
echo sparc-unknown-bsdi${UNAME_RELEASE}
exit 0 ;;
i?86:BSD/386:*:* | i?86:BSD/OS:*:*)
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
exit 0 ;;
*:BSD/OS:*:*)
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
exit 0 ;;
*:FreeBSD:*:*)
if test -x /usr/bin/objformat; then
if test "elf" = "`/usr/bin/objformat`"; then
echo ${UNAME_MACHINE}-unknown-freebsdelf`echo ${UNAME_RELEASE}|sed -e 's/[-_].*//'`
exit 0
fi
fi
echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
exit 0 ;;
*:NetBSD:*:*)
echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
exit 0 ;;
*:OpenBSD:*:*)
echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
exit 0 ;;
i*:CYGWIN*:*)
echo ${UNAME_MACHINE}-pc-cygwin
exit 0 ;;
i*:MINGW*:*)
echo ${UNAME_MACHINE}-pc-mingw32
exit 0 ;;
p*:CYGWIN*:*)
echo powerpcle-unknown-cygwin
exit 0 ;;
prep*:SunOS:5.*:*)
echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
*:GNU:*:*)
echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
exit 0 ;;
*:Linux:*:*)
# # uname on the ARM produces all sorts of strangeness, and we need to
# # filter it out.
# case "$UNAME_MACHINE" in
# armv*) UNAME_MACHINE=$UNAME_MACHINE ;;
# arm* | sa110*) UNAME_MACHINE="arm" ;;
# esac
 
# The BFD linker knows what the default object file format is, so
# first see if it will tell us.
ld_help_string=`ld --help 2>&1`
ld_supported_emulations=`echo $ld_help_string \
| sed -ne '/supported emulations:/!d
s/[ ][ ]*/ /g
s/.*supported emulations: *//
s/ .*//
p'`
case "$ld_supported_emulations" in
i?86linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" ; exit 0 ;;
i?86coff) echo "${UNAME_MACHINE}-pc-linux-gnucoff" ; exit 0 ;;
sparclinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
armlinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
m68klinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
elf32arm) echo "${UNAME_MACHINE}-unknown-linux-gnu" ; exit 0 ;;
elf32ppc) echo "powerpc-unknown-linux-gnu" ; exit 0 ;;
esac
 
if test "${UNAME_MACHINE}" = "alpha" ; then
sed 's/^ //' <<EOF >$dummy.s
.globl main
.ent main
main:
.frame \$30,0,\$26,0
.prologue 0
.long 0x47e03d80 # implver $0
lda \$2,259
.long 0x47e20c21 # amask $2,$1
srl \$1,8,\$2
sll \$2,2,\$2
sll \$0,3,\$0
addl \$1,\$0,\$0
addl \$2,\$0,\$0
ret \$31,(\$26),1
.end main
EOF
LIBC=""
${CC-cc} $dummy.s -o $dummy 2>/dev/null
if test "$?" = 0 ; then
./$dummy
case "$?" in
7)
UNAME_MACHINE="alpha"
;;
15)
UNAME_MACHINE="alphaev5"
;;
14)
UNAME_MACHINE="alphaev56"
;;
10)
UNAME_MACHINE="alphapca56"
;;
16)
UNAME_MACHINE="alphaev6"
;;
esac
 
objdump --private-headers $dummy | \
grep ld.so.1 > /dev/null
if test "$?" = 0 ; then
LIBC="libc1"
fi
fi
rm -f $dummy.s $dummy
echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0
elif test "${UNAME_MACHINE}" = "mips" ; then
cat >$dummy.c <<EOF
#ifdef __cplusplus
int main (int argc, char *argv[]) {
#else
int main (argc, argv) int argc; char *argv[]; {
#endif
#ifdef __MIPSEB__
printf ("%s-unknown-linux-gnu\n", argv[1]);
#endif
#ifdef __MIPSEL__
printf ("%sel-unknown-linux-gnu\n", argv[1]);
#endif
return 0;
}
EOF
${CC-cc} $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0
rm -f $dummy.c $dummy
else
# Either a pre-BFD a.out linker (linux-gnuoldld)
# or one that does not give us useful --help.
# GCC wants to distinguish between linux-gnuoldld and linux-gnuaout.
# If ld does not provide *any* "supported emulations:"
# that means it is gnuoldld.
echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:"
test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0
 
case "${UNAME_MACHINE}" in
i?86)
VENDOR=pc;
;;
*)
VENDOR=unknown;
;;
esac
# Determine whether the default compiler is a.out or elf
cat >$dummy.c <<EOF
#include <features.h>
#ifdef __cplusplus
int main (int argc, char *argv[]) {
#else
int main (argc, argv) int argc; char *argv[]; {
#endif
#ifdef __ELF__
# ifdef __GLIBC__
# if __GLIBC__ >= 2
printf ("%s-${VENDOR}-linux-gnu\n", argv[1]);
# else
printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
# endif
# else
printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
# endif
#else
printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]);
#endif
return 0;
}
EOF
${CC-cc} $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0
rm -f $dummy.c $dummy
fi ;;
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions
# are messed up and put the nodename in both sysname and nodename.
i?86:DYNIX/ptx:4*:*)
echo i386-sequent-sysv4
exit 0 ;;
i?86:UNIX_SV:4.2MP:2.*)
# Unixware is an offshoot of SVR4, but it has its own version
# number series starting with 2...
# I am not positive that other SVR4 systems won't match this,
# I just have to hope. -- rms.
# Use sysv4.2uw... so that sysv4* matches it.
echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
exit 0 ;;
i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*)
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
else
echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
fi
exit 0 ;;
i?86:*:3.2:*)
if test -f /usr/options/cb.name; then
UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
elif /bin/uname -X 2>/dev/null >/dev/null ; then
UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
(/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
(/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
&& UNAME_MACHINE=i586
echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
else
echo ${UNAME_MACHINE}-pc-sysv32
fi
exit 0 ;;
i?86:UnixWare:*:*)
if /bin/uname -X 2>/dev/null >/dev/null ; then
(/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
&& UNAME_MACHINE=i586
fi
echo ${UNAME_MACHINE}-unixware-${UNAME_RELEASE}-${UNAME_VERSION}
exit 0 ;;
pc:*:*:*)
# uname -m prints for DJGPP always 'pc', but it prints nothing about
# the processor, so we play safe by assuming i386.
echo i386-pc-msdosdjgpp
exit 0 ;;
Intel:Mach:3*:*)
echo i386-pc-mach3
exit 0 ;;
paragon:*:*:*)
echo i860-intel-osf1
exit 0 ;;
i860:*:4.*:*) # i860-SVR4
if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
else # Add other i860-SVR4 vendors below as they are discovered.
echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
fi
exit 0 ;;
mini*:CTIX:SYS*5:*)
# "miniframe"
echo m68010-convergent-sysv
exit 0 ;;
M68*:*:R3V[567]*:*)
test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
OS_REL=''
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& echo i486-ncr-sysv4.3${OS_REL} && exit 0
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
&& echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& echo i486-ncr-sysv4 && exit 0 ;;
m68*:LynxOS:2.*:*)
echo m68k-unknown-lynxos${UNAME_RELEASE}
exit 0 ;;
mc68030:UNIX_System_V:4.*:*)
echo m68k-atari-sysv4
exit 0 ;;
i?86:LynxOS:2.*:* | i?86:LynxOS:3.[01]*:*)
echo i386-unknown-lynxos${UNAME_RELEASE}
exit 0 ;;
TSUNAMI:LynxOS:2.*:*)
echo sparc-unknown-lynxos${UNAME_RELEASE}
exit 0 ;;
rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*)
echo rs6000-unknown-lynxos${UNAME_RELEASE}
exit 0 ;;
SM[BE]S:UNIX_SV:*:*)
echo mips-dde-sysv${UNAME_RELEASE}
exit 0 ;;
RM*:ReliantUNIX-*:*:*)
echo mips-sni-sysv4
exit 0 ;;
RM*:SINIX-*:*:*)
echo mips-sni-sysv4
exit 0 ;;
*:SINIX-*:*:*)
if uname -p 2>/dev/null >/dev/null ; then
UNAME_MACHINE=`(uname -p) 2>/dev/null`
echo ${UNAME_MACHINE}-sni-sysv4
else
echo ns32k-sni-sysv
fi
exit 0 ;;
PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
# says <Richard.M.Bartel@ccMail.Census.GOV>
echo i586-unisys-sysv4
exit 0 ;;
*:UNIX_System_V:4*:FTX*)
# From Gerald Hewes <hewes@openmarket.com>.
# How about differentiating between stratus architectures? -djm
echo hppa1.1-stratus-sysv4
exit 0 ;;
*:*:*:FTX*)
# From seanf@swdc.stratus.com.
echo i860-stratus-sysv4
exit 0 ;;
mc68*:A/UX:*:*)
echo m68k-apple-aux${UNAME_RELEASE}
exit 0 ;;
news*:NEWS-OS:*:6*)
echo mips-sony-newsos6
exit 0 ;;
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R4000:UNIX_SV:*:*)
if [ -d /usr/nec ]; then
echo mips-nec-sysv${UNAME_RELEASE}
else
echo mips-unknown-sysv${UNAME_RELEASE}
fi
exit 0 ;;
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
echo powerpc-be-beos
exit 0 ;;
BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
echo powerpc-apple-beos
exit 0 ;;
BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
echo i586-pc-beos
exit 0 ;;
SX-4:SUPER-UX:*:*)
echo sx4-nec-superux${UNAME_RELEASE}
exit 0 ;;
SX-5:SUPER-UX:*:*)
echo sx5-nec-superux${UNAME_RELEASE}
exit 0 ;;
Power*:Rhapsody:*:*)
echo powerpc-apple-rhapsody${UNAME_RELEASE}
exit 0 ;;
*:Rhapsody:*:*)
echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
exit 0 ;;
esac
 
#echo '(No uname command or uname output not recognized.)' 1>&2
#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
 
cat >$dummy.c <<EOF
#ifdef _SEQUENT_
# include <sys/types.h>
# include <sys/utsname.h>
#endif
main ()
{
#if defined (sony)
#if defined (MIPSEB)
/* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
I don't know.... */
printf ("mips-sony-bsd\n"); exit (0);
#else
#include <sys/param.h>
printf ("m68k-sony-newsos%s\n",
#ifdef NEWSOS4
"4"
#else
""
#endif
); exit (0);
#endif
#endif
 
#if defined (__arm) && defined (__acorn) && defined (__unix)
printf ("arm-acorn-riscix"); exit (0);
#endif
 
#if defined (hp300) && !defined (hpux)
printf ("m68k-hp-bsd\n"); exit (0);
#endif
 
#if defined (NeXT)
#if !defined (__ARCHITECTURE__)
#define __ARCHITECTURE__ "m68k"
#endif
int version;
version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
if (version < 4)
printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
else
printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
exit (0);
#endif
 
#if defined (MULTIMAX) || defined (n16)
#if defined (UMAXV)
printf ("ns32k-encore-sysv\n"); exit (0);
#else
#if defined (CMU)
printf ("ns32k-encore-mach\n"); exit (0);
#else
printf ("ns32k-encore-bsd\n"); exit (0);
#endif
#endif
#endif
 
#if defined (__386BSD__)
printf ("i386-pc-bsd\n"); exit (0);
#endif
 
#if defined (sequent)
#if defined (i386)
printf ("i386-sequent-dynix\n"); exit (0);
#endif
#if defined (ns32000)
printf ("ns32k-sequent-dynix\n"); exit (0);
#endif
#endif
 
#if defined (_SEQUENT_)
struct utsname un;
 
uname(&un);
 
if (strncmp(un.version, "V2", 2) == 0) {
printf ("i386-sequent-ptx2\n"); exit (0);
}
if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
printf ("i386-sequent-ptx1\n"); exit (0);
}
printf ("i386-sequent-ptx\n"); exit (0);
 
#endif
 
#if defined (vax)
#if !defined (ultrix)
printf ("vax-dec-bsd\n"); exit (0);
#else
printf ("vax-dec-ultrix\n"); exit (0);
#endif
#endif
 
#if defined (alliant) && defined (i860)
printf ("i860-alliant-bsd\n"); exit (0);
#endif
 
exit (1);
}
EOF
 
${CC-cc} $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm $dummy.c $dummy && exit 0
rm -f $dummy.c $dummy
 
# Apollos put the system type in the environment.
 
test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
 
# Convex versions that predate uname can use getsysinfo(1)
 
if [ -x /usr/convex/getsysinfo ]
then
case `getsysinfo -f cpu_type` in
c1*)
echo c1-convex-bsd
exit 0 ;;
c2*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
exit 0 ;;
c34*)
echo c34-convex-bsd
exit 0 ;;
c38*)
echo c38-convex-bsd
exit 0 ;;
c4*)
echo c4-convex-bsd
exit 0 ;;
esac
fi
 
#echo '(Unable to guess system type)' 1>&2
 
exit 1
/contrib/other/sdlquake-1.0.9/config.sub
0,0 → 1,979
#! /bin/sh
# Configuration validation subroutine script, version 1.1.
# Copyright (C) 1991, 92-97, 1998 Free Software Foundation, Inc.
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
# can handle that machine. It does not imply ALL GNU software can.
#
# This file 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.
 
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
 
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
# If it is invalid, we print an error message on stderr and exit with code 1.
# Otherwise, we print the canonical config type on stdout and succeed.
 
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
# that are meaningful with *any* GNU software.
# Each package is responsible for reporting which valid configurations
# it does not support. The user should be able to distinguish
# a failure to support a valid configuration from a meaningless
# configuration.
 
# The goal of this file is to map all the various variations of a given
# machine specification into a single specification in the form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
# or in some cases, the newer four-part form:
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# It is wrong to echo any other type of specification.
 
if [ x$1 = x ]
then
echo Configuration name missing. 1>&2
echo "Usage: $0 CPU-MFR-OPSYS" 1>&2
echo "or $0 ALIAS" 1>&2
echo where ALIAS is a recognized configuration type. 1>&2
exit 1
fi
 
# First pass through any local machine types.
case $1 in
*local*)
echo $1
exit 0
;;
*)
;;
esac
 
# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
linux-gnu*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
*)
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
if [ $basic_machine != $1 ]
then os=`echo $1 | sed 's/.*-/-/'`
else os=; fi
;;
esac
 
### Let's recognize common machines as not being operating systems so
### that things like config.sub decstation-3100 work. We also
### recognize some manufacturers as not being operating systems, so we
### can provide default operating systems below.
case $os in
-sun*os*)
# Prevent following clause from handling this invalid input.
;;
-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-apple)
os=
basic_machine=$1
;;
-hiux*)
os=-hiuxwe2
;;
-sco5)
os=sco3.2v5
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco4)
os=-sco3.2v4
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco3.2.[4-9]*)
os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco3.2v[4-9]*)
# Don't forget version if it is 3.2v4 or newer.
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco*)
os=-sco3.2v2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-isc)
os=-isc2.2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-clix*)
basic_machine=clipper-intergraph
;;
-isc*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-lynx*)
os=-lynxos
;;
-ptx*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
;;
-windowsnt*)
os=`echo $os | sed -e 's/windowsnt/winnt/'`
;;
-psos*)
os=-psos
;;
esac
 
# Decode aliases for certain CPU-COMPANY combinations.
case $basic_machine in
# Recognize the basic CPU types without company name.
# Some are omitted here because they have special meanings below.
tahoe | i860 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \
| arme[lb] | pyramid | mn10200 | mn10300 | tron | a29k \
| 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 | hppa2.0 \
| hppa2.0w \
| alpha | alphaev5 | alphaev56 | we32k | ns16k | clipper \
| i370 | sh | powerpc | powerpcle | 1750a | dsp16xx | pdp11 \
| mips64 | mipsel | mips64el | mips64orion | mips64orionel \
| mipstx39 | mipstx39el | armv[34][lb] \
| sparc | sparclet | sparclite | sparc64 | v850)
basic_machine=$basic_machine-unknown
;;
# We use `pc' rather than `unknown'
# because (1) that's what they normally are, and
# (2) the word "unknown" tends to confuse beginning users.
i[34567]86)
basic_machine=$basic_machine-pc
;;
# Object if more than one company name word.
*-*-*)
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
exit 1
;;
# Recognize the basic CPU types with company name.
vax-* | tahoe-* | i[34567]86-* | i860-* | m32r-* | m68k-* | m68000-* \
| m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \
| mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
| power-* | none-* | 580-* | cray2-* | h8300-* | i960-* \
| xmp-* | ymp-* | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* \
| hppa2.0w-* \
| alpha-* | alphaev5-* | alphaev56-* | we32k-* | cydra-* \
| ns16k-* | pn-* | np1-* | xps100-* | clipper-* | orion-* \
| sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \
| sparc64-* | mips64-* | mipsel-* | armv[34][lb]-*\
| mips64el-* | mips64orion-* | mips64orionel-* \
| mipstx39-* | mipstx39el-* \
| f301-* | armv*-*)
;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
basic_machine=m68000-att
;;
3b*)
basic_machine=we32k-att
;;
alliant | fx80)
basic_machine=fx80-alliant
;;
altos | altos3068)
basic_machine=m68k-altos
;;
am29k)
basic_machine=a29k-none
os=-bsd
;;
amdahl)
basic_machine=580-amdahl
os=-sysv
;;
amiga | amiga-*)
basic_machine=m68k-cbm
;;
amigaos | amigados)
basic_machine=m68k-cbm
os=-amigaos
;;
amigaunix | amix)
basic_machine=m68k-cbm
os=-sysv4
;;
apollo68)
basic_machine=m68k-apollo
os=-sysv
;;
aux)
basic_machine=m68k-apple
os=-aux
;;
balance)
basic_machine=ns32k-sequent
os=-dynix
;;
convex-c1)
basic_machine=c1-convex
os=-bsd
;;
convex-c2)
basic_machine=c2-convex
os=-bsd
;;
convex-c32)
basic_machine=c32-convex
os=-bsd
;;
convex-c34)
basic_machine=c34-convex
os=-bsd
;;
convex-c38)
basic_machine=c38-convex
os=-bsd
;;
cray | ymp)
basic_machine=ymp-cray
os=-unicos
;;
cray2)
basic_machine=cray2-cray
os=-unicos
;;
[ctj]90-cray)
basic_machine=c90-cray
os=-unicos
;;
crds | unos)
basic_machine=m68k-crds
;;
da30 | da30-*)
basic_machine=m68k-da30
;;
decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
basic_machine=mips-dec
;;
delta | 3300 | motorola-3300 | motorola-delta \
| 3300-motorola | delta-motorola)
basic_machine=m68k-motorola
;;
delta88)
basic_machine=m88k-motorola
os=-sysv3
;;
dpx20 | dpx20-*)
basic_machine=rs6000-bull
os=-bosx
;;
dpx2* | dpx2*-bull)
basic_machine=m68k-bull
os=-sysv3
;;
ebmon29k)
basic_machine=a29k-amd
os=-ebmon
;;
elxsi)
basic_machine=elxsi-elxsi
os=-bsd
;;
encore | umax | mmax)
basic_machine=ns32k-encore
;;
fx2800)
basic_machine=i860-alliant
;;
genix)
basic_machine=ns32k-ns
;;
gmicro)
basic_machine=tron-gmicro
os=-sysv
;;
h3050r* | hiux*)
basic_machine=hppa1.1-hitachi
os=-hiuxwe2
;;
h8300hms)
basic_machine=h8300-hitachi
os=-hms
;;
harris)
basic_machine=m88k-harris
os=-sysv3
;;
hp300-*)
basic_machine=m68k-hp
;;
hp300bsd)
basic_machine=m68k-hp
os=-bsd
;;
hp300hpux)
basic_machine=m68k-hp
os=-hpux
;;
hp9k2[0-9][0-9] | hp9k31[0-9])
basic_machine=m68000-hp
;;
hp9k3[2-9][0-9])
basic_machine=m68k-hp
;;
hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7)
basic_machine=hppa1.1-hp
;;
hp9k8[0-9][0-9] | hp8[0-9][0-9])
basic_machine=hppa1.0-hp
;;
hppa-next)
os=-nextstep3
;;
hp3k9[0-9][0-9] | hp9[0-9][0-9])
basic_machine=hppa1.0-hp
os=-mpeix
;;
hp3k9[0-9][0-9] | hp9[0-9][0-9])
basic_machine=hppa1.0-hp
os=-mpeix
;;
i370-ibm* | ibm*)
basic_machine=i370-ibm
os=-mvs
;;
# I'm not sure what "Sysv32" means. Should this be sysv3.2?
i[34567]86v32)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv32
;;
i[34567]86v4*)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv4
;;
i[34567]86v)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv
;;
i[34567]86sol2)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-solaris2
;;
iris | iris4d)
basic_machine=mips-sgi
case $os in
-irix*)
;;
*)
os=-irix4
;;
esac
;;
isi68 | isi)
basic_machine=m68k-isi
os=-sysv
;;
m88k-omron*)
basic_machine=m88k-omron
;;
magnum | m3230)
basic_machine=mips-mips
os=-sysv
;;
merlin)
basic_machine=ns32k-utek
os=-sysv
;;
miniframe)
basic_machine=m68000-convergent
;;
mipsel*-linux*)
basic_machine=mipsel-unknown
os=-linux-gnu
;;
mips*-linux*)
basic_machine=mips-unknown
os=-linux-gnu
;;
mips3*-*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
;;
mips3*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
;;
ncr3000)
basic_machine=i486-ncr
os=-sysv4
;;
netwinder)
basic_machine=armv4l-corel
os=-linux
;;
news | news700 | news800 | news900)
basic_machine=m68k-sony
os=-newsos
;;
news1000)
basic_machine=m68030-sony
os=-newsos
;;
news-3600 | risc-news)
basic_machine=mips-sony
os=-newsos
;;
next | m*-next )
basic_machine=m68k-next
case $os in
-nextstep* )
;;
-ns2*)
os=-nextstep2
;;
*)
os=-nextstep3
;;
esac
;;
nh3000)
basic_machine=m68k-harris
os=-cxux
;;
nh[45]000)
basic_machine=m88k-harris
os=-cxux
;;
nindy960)
basic_machine=i960-intel
os=-nindy
;;
np1)
basic_machine=np1-gould
;;
pa-hitachi)
basic_machine=hppa1.1-hitachi
os=-hiuxwe2
;;
paragon)
basic_machine=i860-intel
os=-osf
;;
pbd)
basic_machine=sparc-tti
;;
pbb)
basic_machine=m68k-tti
;;
pc532 | pc532-*)
basic_machine=ns32k-pc532
;;
pentium | p5 | k5 | nexen)
basic_machine=i586-pc
;;
pentiumpro | p6 | k6 | 6x86)
basic_machine=i686-pc
;;
pentiumii | pentium2)
basic_machine=i786-pc
;;
pentium-* | p5-* | k5-* | nexen-*)
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentiumpro-* | p6-* | k6-* | 6x86-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentiumii-* | pentium2-*)
basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pn)
basic_machine=pn-gould
;;
power) basic_machine=rs6000-ibm
;;
ppc) basic_machine=powerpc-unknown
;;
ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppcle | powerpclittle | ppc-le | powerpc-little)
basic_machine=powerpcle-unknown
;;
ppcle-* | powerpclittle-*)
basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ps2)
basic_machine=i386-ibm
;;
rm[46]00)
basic_machine=mips-siemens
;;
rtpc | rtpc-*)
basic_machine=romp-ibm
;;
sequent)
basic_machine=i386-sequent
;;
sh)
basic_machine=sh-hitachi
os=-hms
;;
sps7)
basic_machine=m68k-bull
os=-sysv2
;;
spur)
basic_machine=spur-unknown
;;
sun2)
basic_machine=m68000-sun
;;
sun2os3)
basic_machine=m68000-sun
os=-sunos3
;;
sun2os4)
basic_machine=m68000-sun
os=-sunos4
;;
sun3os3)
basic_machine=m68k-sun
os=-sunos3
;;
sun3os4)
basic_machine=m68k-sun
os=-sunos4
;;
sun4os3)
basic_machine=sparc-sun
os=-sunos3
;;
sun4os4)
basic_machine=sparc-sun
os=-sunos4
;;
sun4sol2)
basic_machine=sparc-sun
os=-solaris2
;;
sun3 | sun3-*)
basic_machine=m68k-sun
;;
sun4)
basic_machine=sparc-sun
;;
sun386 | sun386i | roadrunner)
basic_machine=i386-sun
;;
symmetry)
basic_machine=i386-sequent
os=-dynix
;;
tx39)
basic_machine=mipstx39-unknown
;;
tx39el)
basic_machine=mipstx39el-unknown
;;
tower | tower-32)
basic_machine=m68k-ncr
;;
udi29k)
basic_machine=a29k-amd
os=-udi
;;
ultra3)
basic_machine=a29k-nyu
os=-sym1
;;
vaxv)
basic_machine=vax-dec
os=-sysv
;;
vms)
basic_machine=vax-dec
os=-vms
;;
vpp*|vx|vx-*)
basic_machine=f301-fujitsu
;;
vxworks960)
basic_machine=i960-wrs
os=-vxworks
;;
vxworks68)
basic_machine=m68k-wrs
os=-vxworks
;;
vxworks29k)
basic_machine=a29k-wrs
os=-vxworks
;;
xmp)
basic_machine=xmp-cray
os=-unicos
;;
xps | xps100)
basic_machine=xps100-honeywell
;;
none)
basic_machine=none-none
os=-none
;;
 
# Here we handle the default manufacturer of certain CPU types. It is in
# some cases the only manufacturer, in others, it is the most popular.
mips)
if [ x$os = x-linux-gnu ]; then
basic_machine=mips-unknown
else
basic_machine=mips-mips
fi
;;
romp)
basic_machine=romp-ibm
;;
rs6000)
basic_machine=rs6000-ibm
;;
vax)
basic_machine=vax-dec
;;
pdp11)
basic_machine=pdp11-dec
;;
we32k)
basic_machine=we32k-att
;;
sparc)
basic_machine=sparc-sun
;;
cydra)
basic_machine=cydra-cydrome
;;
orion)
basic_machine=orion-highlevel
;;
orion105)
basic_machine=clipper-highlevel
;;
*)
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
exit 1
;;
esac
 
# Here we canonicalize certain aliases for manufacturers.
case $basic_machine in
*-digital*)
basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
;;
*-commodore*)
basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
;;
*)
;;
esac
 
# Decode manufacturer-specific aliases for certain operating systems.
 
if [ x"$os" != x"" ]
then
case $os in
# First match some system type aliases
# that might get confused with valid system types.
# -solaris* is a basic system type, with this one exception.
-solaris1 | -solaris1.*)
os=`echo $os | sed -e 's|solaris1|sunos4|'`
;;
-solaris)
os=-solaris2
;;
-svr4*)
os=-sysv4
;;
-unixware*)
os=-sysv4.2uw
;;
-gnu/linux*)
os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
;;
# First accept the basic system types.
# The portable systems comes first.
# Each alternative MUST END IN A *, to match a version number.
# -sysv* is not here because it comes later, after sysvr4.
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
| -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
| -aos* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -linux-gnu* | -uxpv* | -beos* | -rhapsody* \
| -openstep* | -mpeix* | -oskit*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-linux*)
os=`echo $os | sed -e 's|linux|linux-gnu|'`
;;
-sunos5*)
os=`echo $os | sed -e 's|sunos5|solaris2|'`
;;
-sunos6*)
os=`echo $os | sed -e 's|sunos6|solaris3|'`
;;
-osfrose*)
os=-osfrose
;;
-osf*)
os=-osf
;;
-utek*)
os=-bsd
;;
-dynix*)
os=-bsd
;;
-acis*)
os=-aos
;;
-ctix* | -uts*)
os=-sysv
;;
-ns2 )
os=-nextstep2
;;
# Preserve the version number of sinix5.
-sinix5.*)
os=`echo $os | sed -e 's|sinix|sysv|'`
;;
-sinix*)
os=-sysv4
;;
-triton*)
os=-sysv3
;;
-oss*)
os=-sysv3
;;
-svr4)
os=-sysv4
;;
-svr3)
os=-sysv3
;;
-sysvr4)
os=-sysv4
;;
# This must come after -sysvr4.
-sysv*)
;;
-xenix)
os=-xenix
;;
-none)
;;
*)
# Get rid of the `-' at the beginning of $os.
os=`echo $os | sed 's/[^-]*-//'`
echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
exit 1
;;
esac
else
 
# Here we handle the default operating systems that come with various machines.
# The value should be what the vendor currently ships out the door with their
# machine or put another way, the most popular os provided with the machine.
 
# Note that if you're going to try to match "-MANUFACTURER" here (say,
# "-sun"), then you have to tell the case statement up towards the top
# that MANUFACTURER isn't an operating system. Otherwise, code above
# will signal an error saying that MANUFACTURER isn't an operating
# system, and we'll never get to this point.
 
case $basic_machine in
*-acorn)
os=-riscix1.2
;;
arm*-corel)
os=-linux
;;
arm*-semi)
os=-aout
;;
pdp11-*)
os=-none
;;
*-dec | vax-*)
os=-ultrix4.2
;;
m68*-apollo)
os=-domain
;;
i386-sun)
os=-sunos4.0.2
;;
m68000-sun)
os=-sunos3
# This also exists in the configure program, but was not the
# default.
# os=-sunos4
;;
*-tti) # must be before sparc entry or we get the wrong os.
os=-sysv3
;;
sparc-* | *-sun)
os=-sunos4.1.1
;;
*-be)
os=-beos
;;
*-ibm)
os=-aix
;;
*-hp)
os=-hpux
;;
*-hitachi)
os=-hiux
;;
i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
os=-sysv
;;
*-cbm)
os=-amigaos
;;
*-dg)
os=-dgux
;;
*-dolphin)
os=-sysv3
;;
m68k-ccur)
os=-rtu
;;
m88k-omron*)
os=-luna
;;
*-next )
os=-nextstep
;;
*-sequent)
os=-ptx
;;
*-crds)
os=-unos
;;
*-ns)
os=-genix
;;
i370-*)
os=-mvs
;;
*-next)
os=-nextstep3
;;
*-gould)
os=-sysv
;;
*-highlevel)
os=-bsd
;;
*-encore)
os=-bsd
;;
*-sgi)
os=-irix
;;
*-siemens)
os=-sysv4
;;
*-masscomp)
os=-rtu
;;
f301-fujitsu)
os=-uxpv
;;
*)
os=-none
;;
esac
fi
 
# Here we handle the case where we know the os, and the CPU type, but not the
# manufacturer. We pick the logical manufacturer.
vendor=unknown
case $basic_machine in
*-unknown)
case $os in
-riscix*)
vendor=acorn
;;
-sunos*)
vendor=sun
;;
-aix*)
vendor=ibm
;;
-hpux*)
vendor=hp
;;
-mpeix*)
vendor=hp
;;
-mpeix*)
vendor=hp
;;
-hiux*)
vendor=hitachi
;;
-unos*)
vendor=crds
;;
-dgux*)
vendor=dg
;;
-luna*)
vendor=omron
;;
-genix*)
vendor=ns
;;
-mvs*)
vendor=ibm
;;
-ptx*)
vendor=sequent
;;
-vxsim* | -vxworks*)
vendor=wrs
;;
-aux*)
vendor=apple
;;
esac
basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
;;
esac
 
echo $basic_machine$os
/contrib/other/sdlquake-1.0.9/configure
0,0 → 1,1745
#! /bin/sh
 
# Guess values for system-dependent variables and create Makefiles.
# Generated automatically using autoconf version 2.13
# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
 
# Defaults:
ac_help=
ac_default_prefix=/usr/local
# Any additions from configure.in:
ac_help="$ac_help
--with-sdl-prefix=PFX Prefix where SDL is installed (optional)"
ac_help="$ac_help
--with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional)"
ac_help="$ac_help
--disable-sdltest Do not try to compile and run a test SDL program"
ac_help="$ac_help
--enable-asm enable i686 assembly routines [default=no]"
 
# Initialize some variables set by options.
# The variables have the same names as the options, with
# dashes changed to underlines.
build=NONE
cache_file=./config.cache
exec_prefix=NONE
host=NONE
no_create=
nonopt=NONE
no_recursion=
prefix=NONE
program_prefix=NONE
program_suffix=NONE
program_transform_name=s,x,x,
silent=
site=
srcdir=
target=NONE
verbose=
x_includes=NONE
x_libraries=NONE
bindir='${exec_prefix}/bin'
sbindir='${exec_prefix}/sbin'
libexecdir='${exec_prefix}/libexec'
datadir='${prefix}/share'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
libdir='${exec_prefix}/lib'
includedir='${prefix}/include'
oldincludedir='/usr/include'
infodir='${prefix}/info'
mandir='${prefix}/man'
 
# Initialize some other variables.
subdirs=
MFLAGS= MAKEFLAGS=
SHELL=${CONFIG_SHELL-/bin/sh}
# Maximum number of lines to put in a shell here document.
ac_max_here_lines=12
 
ac_prev=
for ac_option
do
 
# If the previous option needs an argument, assign it.
if test -n "$ac_prev"; then
eval "$ac_prev=\$ac_option"
ac_prev=
continue
fi
 
case "$ac_option" in
-*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
*) ac_optarg= ;;
esac
 
# Accept the important Cygnus configure options, so we can diagnose typos.
 
case "$ac_option" in
 
-bindir | --bindir | --bindi | --bind | --bin | --bi)
ac_prev=bindir ;;
-bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
bindir="$ac_optarg" ;;
 
-build | --build | --buil | --bui | --bu)
ac_prev=build ;;
-build=* | --build=* | --buil=* | --bui=* | --bu=*)
build="$ac_optarg" ;;
 
-cache-file | --cache-file | --cache-fil | --cache-fi \
| --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
ac_prev=cache_file ;;
-cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
| --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
cache_file="$ac_optarg" ;;
 
-datadir | --datadir | --datadi | --datad | --data | --dat | --da)
ac_prev=datadir ;;
-datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
| --da=*)
datadir="$ac_optarg" ;;
 
-disable-* | --disable-*)
ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
# Reject names that are not valid shell variable names.
if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
{ echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
fi
ac_feature=`echo $ac_feature| sed 's/-/_/g'`
eval "enable_${ac_feature}=no" ;;
 
-enable-* | --enable-*)
ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
# Reject names that are not valid shell variable names.
if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
{ echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
fi
ac_feature=`echo $ac_feature| sed 's/-/_/g'`
case "$ac_option" in
*=*) ;;
*) ac_optarg=yes ;;
esac
eval "enable_${ac_feature}='$ac_optarg'" ;;
 
-exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
| --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
| --exec | --exe | --ex)
ac_prev=exec_prefix ;;
-exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
| --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
| --exec=* | --exe=* | --ex=*)
exec_prefix="$ac_optarg" ;;
 
-gas | --gas | --ga | --g)
# Obsolete; use --with-gas.
with_gas=yes ;;
 
-help | --help | --hel | --he)
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat << EOF
Usage: configure [options] [host]
Options: [defaults in brackets after descriptions]
Configuration:
--cache-file=FILE cache test results in FILE
--help print this message
--no-create do not create output files
--quiet, --silent do not print \`checking...' messages
--version print the version of autoconf that created configure
Directory and file names:
--prefix=PREFIX install architecture-independent files in PREFIX
[$ac_default_prefix]
--exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
[same as prefix]
--bindir=DIR user executables in DIR [EPREFIX/bin]
--sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
--libexecdir=DIR program executables in DIR [EPREFIX/libexec]
--datadir=DIR read-only architecture-independent data in DIR
[PREFIX/share]
--sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data in DIR
[PREFIX/com]
--localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
--libdir=DIR object code libraries in DIR [EPREFIX/lib]
--includedir=DIR C header files in DIR [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
--infodir=DIR info documentation in DIR [PREFIX/info]
--mandir=DIR man documentation in DIR [PREFIX/man]
--srcdir=DIR find the sources in DIR [configure dir or ..]
--program-prefix=PREFIX prepend PREFIX to installed program names
--program-suffix=SUFFIX append SUFFIX to installed program names
--program-transform-name=PROGRAM
run sed PROGRAM on installed program names
EOF
cat << EOF
Host type:
--build=BUILD configure for building on BUILD [BUILD=HOST]
--host=HOST configure for HOST [guessed]
--target=TARGET configure for TARGET [TARGET=HOST]
Features and packages:
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--x-includes=DIR X include files are in DIR
--x-libraries=DIR X library files are in DIR
EOF
if test -n "$ac_help"; then
echo "--enable and --with options recognized:$ac_help"
fi
exit 0 ;;
 
-host | --host | --hos | --ho)
ac_prev=host ;;
-host=* | --host=* | --hos=* | --ho=*)
host="$ac_optarg" ;;
 
-includedir | --includedir | --includedi | --included | --include \
| --includ | --inclu | --incl | --inc)
ac_prev=includedir ;;
-includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
| --includ=* | --inclu=* | --incl=* | --inc=*)
includedir="$ac_optarg" ;;
 
-infodir | --infodir | --infodi | --infod | --info | --inf)
ac_prev=infodir ;;
-infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
infodir="$ac_optarg" ;;
 
-libdir | --libdir | --libdi | --libd)
ac_prev=libdir ;;
-libdir=* | --libdir=* | --libdi=* | --libd=*)
libdir="$ac_optarg" ;;
 
-libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
| --libexe | --libex | --libe)
ac_prev=libexecdir ;;
-libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
| --libexe=* | --libex=* | --libe=*)
libexecdir="$ac_optarg" ;;
 
-localstatedir | --localstatedir | --localstatedi | --localstated \
| --localstate | --localstat | --localsta | --localst \
| --locals | --local | --loca | --loc | --lo)
ac_prev=localstatedir ;;
-localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
| --localstate=* | --localstat=* | --localsta=* | --localst=* \
| --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
localstatedir="$ac_optarg" ;;
 
-mandir | --mandir | --mandi | --mand | --man | --ma | --m)
ac_prev=mandir ;;
-mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
mandir="$ac_optarg" ;;
 
-nfp | --nfp | --nf)
# Obsolete; use --without-fp.
with_fp=no ;;
 
-no-create | --no-create | --no-creat | --no-crea | --no-cre \
| --no-cr | --no-c)
no_create=yes ;;
 
-no-recursion | --no-recursion | --no-recursio | --no-recursi \
| --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
no_recursion=yes ;;
 
-oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
| --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
| --oldin | --oldi | --old | --ol | --o)
ac_prev=oldincludedir ;;
-oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
| --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
| --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
oldincludedir="$ac_optarg" ;;
 
-prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
ac_prev=prefix ;;
-prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
prefix="$ac_optarg" ;;
 
-program-prefix | --program-prefix | --program-prefi | --program-pref \
| --program-pre | --program-pr | --program-p)
ac_prev=program_prefix ;;
-program-prefix=* | --program-prefix=* | --program-prefi=* \
| --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
program_prefix="$ac_optarg" ;;
 
-program-suffix | --program-suffix | --program-suffi | --program-suff \
| --program-suf | --program-su | --program-s)
ac_prev=program_suffix ;;
-program-suffix=* | --program-suffix=* | --program-suffi=* \
| --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
program_suffix="$ac_optarg" ;;
 
-program-transform-name | --program-transform-name \
| --program-transform-nam | --program-transform-na \
| --program-transform-n | --program-transform- \
| --program-transform | --program-transfor \
| --program-transfo | --program-transf \
| --program-trans | --program-tran \
| --progr-tra | --program-tr | --program-t)
ac_prev=program_transform_name ;;
-program-transform-name=* | --program-transform-name=* \
| --program-transform-nam=* | --program-transform-na=* \
| --program-transform-n=* | --program-transform-=* \
| --program-transform=* | --program-transfor=* \
| --program-transfo=* | --program-transf=* \
| --program-trans=* | --program-tran=* \
| --progr-tra=* | --program-tr=* | --program-t=*)
program_transform_name="$ac_optarg" ;;
 
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil)
silent=yes ;;
 
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
| --sbi=* | --sb=*)
sbindir="$ac_optarg" ;;
 
-sharedstatedir | --sharedstatedir | --sharedstatedi \
| --sharedstated | --sharedstate | --sharedstat | --sharedsta \
| --sharedst | --shareds | --shared | --share | --shar \
| --sha | --sh)
ac_prev=sharedstatedir ;;
-sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
| --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
| --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
| --sha=* | --sh=*)
sharedstatedir="$ac_optarg" ;;
 
-site | --site | --sit)
ac_prev=site ;;
-site=* | --site=* | --sit=*)
site="$ac_optarg" ;;
 
-srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
ac_prev=srcdir ;;
-srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
srcdir="$ac_optarg" ;;
 
-sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
| --syscon | --sysco | --sysc | --sys | --sy)
ac_prev=sysconfdir ;;
-sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
| --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
sysconfdir="$ac_optarg" ;;
 
-target | --target | --targe | --targ | --tar | --ta | --t)
ac_prev=target ;;
-target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
target="$ac_optarg" ;;
 
-v | -verbose | --verbose | --verbos | --verbo | --verb)
verbose=yes ;;
 
-version | --version | --versio | --versi | --vers)
echo "configure generated by autoconf version 2.13"
exit 0 ;;
 
-with-* | --with-*)
ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
# Reject names that are not valid shell variable names.
if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
{ echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
fi
ac_package=`echo $ac_package| sed 's/-/_/g'`
case "$ac_option" in
*=*) ;;
*) ac_optarg=yes ;;
esac
eval "with_${ac_package}='$ac_optarg'" ;;
 
-without-* | --without-*)
ac_package=`echo $ac_option|sed -e 's/-*without-//'`
# Reject names that are not valid shell variable names.
if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
{ echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
fi
ac_package=`echo $ac_package| sed 's/-/_/g'`
eval "with_${ac_package}=no" ;;
 
--x)
# Obsolete; use --with-x.
with_x=yes ;;
 
-x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
| --x-incl | --x-inc | --x-in | --x-i)
ac_prev=x_includes ;;
-x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
| --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
x_includes="$ac_optarg" ;;
 
-x-libraries | --x-libraries | --x-librarie | --x-librari \
| --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
ac_prev=x_libraries ;;
-x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
| --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
x_libraries="$ac_optarg" ;;
 
-*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
;;
 
*)
if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
echo "configure: warning: $ac_option: invalid host type" 1>&2
fi
if test "x$nonopt" != xNONE; then
{ echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
fi
nonopt="$ac_option"
;;
 
esac
done
 
if test -n "$ac_prev"; then
{ echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
fi
 
trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
 
# File descriptor usage:
# 0 standard input
# 1 file creation
# 2 errors and warnings
# 3 some systems may open it to /dev/tty
# 4 used on the Kubota Titan
# 6 checking for... messages and results
# 5 compiler messages saved in config.log
if test "$silent" = yes; then
exec 6>/dev/null
else
exec 6>&1
fi
exec 5>./config.log
 
echo "\
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
" 1>&5
 
# Strip out --no-create and --no-recursion so they do not pile up.
# Also quote any args containing shell metacharacters.
ac_configure_args=
for ac_arg
do
case "$ac_arg" in
-no-create | --no-create | --no-creat | --no-crea | --no-cre \
| --no-cr | --no-c) ;;
-no-recursion | --no-recursion | --no-recursio | --no-recursi \
| --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
*" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
ac_configure_args="$ac_configure_args '$ac_arg'" ;;
*) ac_configure_args="$ac_configure_args $ac_arg" ;;
esac
done
 
# NLS nuisances.
# Only set these to C if already set. These must not be set unconditionally
# because not all systems understand e.g. LANG=C (notably SCO).
# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
# Non-C LC_CTYPE values break the ctype check.
if test "${LANG+set}" = set; then LANG=C; export LANG; fi
if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
 
# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -rf conftest* confdefs.h
# AIX cpp loses on an empty file, so make sure it contains at least a newline.
echo > confdefs.h
 
# A filename unique to this package, relative to the directory that
# configure is in, which we can look for to find out if srcdir is correct.
ac_unique_file=README.SDL
 
# Find the source files, if location was not specified.
if test -z "$srcdir"; then
ac_srcdir_defaulted=yes
# Try the directory containing this script, then its parent.
ac_prog=$0
ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
srcdir=$ac_confdir
if test ! -r $srcdir/$ac_unique_file; then
srcdir=..
fi
else
ac_srcdir_defaulted=no
fi
if test ! -r $srcdir/$ac_unique_file; then
if test "$ac_srcdir_defaulted" = yes; then
{ echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
else
{ echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
fi
fi
srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
 
# Prefer explicitly selected file to automatically selected ones.
if test -z "$CONFIG_SITE"; then
if test "x$prefix" != xNONE; then
CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
else
CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
fi
fi
for ac_site_file in $CONFIG_SITE; do
if test -r "$ac_site_file"; then
echo "loading site script $ac_site_file"
. "$ac_site_file"
fi
done
 
if test -r "$cache_file"; then
echo "loading cache $cache_file"
. $cache_file
else
echo "creating cache $cache_file"
> $cache_file
fi
 
ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
cross_compiling=$ac_cv_prog_cc_cross
 
ac_exeext=
ac_objext=o
if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
# Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
ac_n= ac_c='
' ac_t=' '
else
ac_n=-n ac_c= ac_t=
fi
else
ac_n= ac_c='\c' ac_t=
fi
 
 
 
ac_aux_dir=
for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
if test -f $ac_dir/install-sh; then
ac_aux_dir=$ac_dir
ac_install_sh="$ac_aux_dir/install-sh -c"
break
elif test -f $ac_dir/install.sh; then
ac_aux_dir=$ac_dir
ac_install_sh="$ac_aux_dir/install.sh -c"
break
fi
done
if test -z "$ac_aux_dir"; then
{ echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
fi
ac_config_guess=$ac_aux_dir/config.guess
ac_config_sub=$ac_aux_dir/config.sub
ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
 
# Find a good install program. We prefer a C program (faster),
# so one script is as good as another. But avoid the broken or
# incompatible versions:
# SysV /etc/install, /usr/sbin/install
# SunOS /usr/etc/install
# IRIX /sbin/install
# AIX /bin/install
# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
# AFS /usr/afsws/bin/install, which mishandles nonexistent args
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
echo "configure:565: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
for ac_dir in $PATH; do
# Account for people who put trailing slashes in PATH elements.
case "$ac_dir/" in
/|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
*)
# OSF1 and SCO ODT 3.0 have their own names for install.
# Don't use installbsd from OSF since it installs stuff as root
# by default.
for ac_prog in ginstall scoinst install; do
if test -f $ac_dir/$ac_prog; then
if test $ac_prog = install &&
grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
# AIX install. It has an incompatible calling convention.
:
else
ac_cv_path_install="$ac_dir/$ac_prog -c"
break 2
fi
fi
done
;;
esac
done
IFS="$ac_save_IFS"
 
fi
if test "${ac_cv_path_install+set}" = set; then
INSTALL="$ac_cv_path_install"
else
# As a last resort, use the slow shell script. We don't cache a
# path for INSTALL within a source directory, because that will
# break other packages using the cache if that directory is
# removed, or if the path is relative.
INSTALL="$ac_install_sh"
fi
fi
echo "$ac_t""$INSTALL" 1>&6
 
# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
# It thinks the first close brace ends the variable substitution.
test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
 
test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
 
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
 
echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6
echo "configure:618: checking whether build environment is sane" >&5
# Just in case
sleep 1
echo timestamp > conftestfile
# Do `set' in a subshell so we don't clobber the current shell's
# arguments. Must try -L first in case configure is actually a
# symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing
# directory).
if (
set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
if test "$*" = "X"; then
# -L didn't work.
set X `ls -t $srcdir/configure conftestfile`
fi
if test "$*" != "X $srcdir/configure conftestfile" \
&& test "$*" != "X conftestfile $srcdir/configure"; then
 
# If neither matched, then we have a broken ls. This can happen
# if, for instance, CONFIG_SHELL is bash and it inherits a
# broken ls alias from the environment. This has actually
# happened. Such a system could not be considered "sane".
{ echo "configure: error: ls -t appears to fail. Make sure there is not a broken
alias in your environment" 1>&2; exit 1; }
fi
 
test "$2" = conftestfile
)
then
# Ok.
:
else
{ echo "configure: error: newly created file is older than distributed files!
Check your system clock" 1>&2; exit 1; }
fi
rm -f conftest*
echo "$ac_t""yes" 1>&6
if test "$program_transform_name" = s,x,x,; then
program_transform_name=
else
# Double any \ or $. echo might interpret backslashes.
cat <<\EOF_SED > conftestsed
s,\\,\\\\,g; s,\$,$$,g
EOF_SED
program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
rm -f conftestsed
fi
test "$program_prefix" != NONE &&
program_transform_name="s,^,${program_prefix},; $program_transform_name"
# Use a double $ so make ignores it.
test "$program_suffix" != NONE &&
program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
 
# sed with no file args requires a program.
test "$program_transform_name" = "" && program_transform_name="s,x,x,"
 
echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
echo "configure:675: checking whether ${MAKE-make} sets \${MAKE}" >&5
set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftestmake <<\EOF
all:
@echo 'ac_maketemp="${MAKE}"'
EOF
# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
if test -n "$ac_maketemp"; then
eval ac_cv_prog_make_${ac_make}_set=yes
else
eval ac_cv_prog_make_${ac_make}_set=no
fi
rm -f conftestmake
fi
if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
echo "$ac_t""yes" 1>&6
SET_MAKE=
else
echo "$ac_t""no" 1>&6
SET_MAKE="MAKE=${MAKE-make}"
fi
 
 
PACKAGE=sdlquake
 
VERSION=1.0.9
 
if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
{ echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; }
fi
cat >> confdefs.h <<EOF
#define PACKAGE "$PACKAGE"
EOF
 
cat >> confdefs.h <<EOF
#define VERSION "$VERSION"
EOF
 
 
 
missing_dir=`cd $ac_aux_dir && pwd`
echo $ac_n "checking for working aclocal""... $ac_c" 1>&6
echo "configure:721: checking for working aclocal" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
if (aclocal --version) < /dev/null > /dev/null 2>&1; then
ACLOCAL=aclocal
echo "$ac_t""found" 1>&6
else
ACLOCAL="$missing_dir/missing aclocal"
echo "$ac_t""missing" 1>&6
fi
 
echo $ac_n "checking for working autoconf""... $ac_c" 1>&6
echo "configure:734: checking for working autoconf" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
if (autoconf --version) < /dev/null > /dev/null 2>&1; then
AUTOCONF=autoconf
echo "$ac_t""found" 1>&6
else
AUTOCONF="$missing_dir/missing autoconf"
echo "$ac_t""missing" 1>&6
fi
 
echo $ac_n "checking for working automake""... $ac_c" 1>&6
echo "configure:747: checking for working automake" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
if (automake --version) < /dev/null > /dev/null 2>&1; then
AUTOMAKE=automake
echo "$ac_t""found" 1>&6
else
AUTOMAKE="$missing_dir/missing automake"
echo "$ac_t""missing" 1>&6
fi
 
echo $ac_n "checking for working autoheader""... $ac_c" 1>&6
echo "configure:760: checking for working autoheader" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
if (autoheader --version) < /dev/null > /dev/null 2>&1; then
AUTOHEADER=autoheader
echo "$ac_t""found" 1>&6
else
AUTOHEADER="$missing_dir/missing autoheader"
echo "$ac_t""missing" 1>&6
fi
 
echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6
echo "configure:773: checking for working makeinfo" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
if (makeinfo --version) < /dev/null > /dev/null 2>&1; then
MAKEINFO=makeinfo
echo "$ac_t""found" 1>&6
else
MAKEINFO="$missing_dir/missing makeinfo"
echo "$ac_t""missing" 1>&6
fi
 
 
 
 
# Make sure we can run config.sub.
if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
fi
 
echo $ac_n "checking host system type""... $ac_c" 1>&6
echo "configure:794: checking host system type" >&5
 
host_alias=$host
case "$host_alias" in
NONE)
case $nonopt in
NONE)
if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
fi ;;
*) host_alias=$nonopt ;;
esac ;;
esac
 
host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$host" 1>&6
 
echo $ac_n "checking target system type""... $ac_c" 1>&6
echo "configure:815: checking target system type" >&5
 
target_alias=$target
case "$target_alias" in
NONE)
case $nonopt in
NONE) target_alias=$host_alias ;;
*) target_alias=$nonopt ;;
esac ;;
esac
 
target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$target" 1>&6
 
 
 
echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
echo "configure:835: checking whether ${MAKE-make} sets \${MAKE}" >&5
set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftestmake <<\EOF
all:
@echo 'ac_maketemp="${MAKE}"'
EOF
# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
if test -n "$ac_maketemp"; then
eval ac_cv_prog_make_${ac_make}_set=yes
else
eval ac_cv_prog_make_${ac_make}_set=no
fi
rm -f conftestmake
fi
if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
echo "$ac_t""yes" 1>&6
SET_MAKE=
else
echo "$ac_t""no" 1>&6
SET_MAKE="MAKE=${MAKE-make}"
fi
 
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:864: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
ac_dummy="$PATH"
for ac_dir in $ac_dummy; do
test -z "$ac_dir" && ac_dir=.
if test -f $ac_dir/$ac_word; then
ac_cv_prog_CC="gcc"
break
fi
done
IFS="$ac_save_ifs"
fi
fi
CC="$ac_cv_prog_CC"
if test -n "$CC"; then
echo "$ac_t""$CC" 1>&6
else
echo "$ac_t""no" 1>&6
fi
 
if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:894: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
ac_prog_rejected=no
ac_dummy="$PATH"
for ac_dir in $ac_dummy; do
test -z "$ac_dir" && ac_dir=.
if test -f $ac_dir/$ac_word; then
if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
ac_prog_rejected=yes
continue
fi
ac_cv_prog_CC="cc"
break
fi
done
IFS="$ac_save_ifs"
if test $ac_prog_rejected = yes; then
# We found a bogon in the path, so make sure we never use it.
set dummy $ac_cv_prog_CC
shift
if test $# -gt 0; then
# We chose a different compiler from the bogus one.
# However, it has the same basename, so the bogon will be chosen
# first if we set CC to just the basename; use the full file name.
shift
set dummy "$ac_dir/$ac_word" "$@"
shift
ac_cv_prog_CC="$@"
fi
fi
fi
fi
CC="$ac_cv_prog_CC"
if test -n "$CC"; then
echo "$ac_t""$CC" 1>&6
else
echo "$ac_t""no" 1>&6
fi
 
if test -z "$CC"; then
case "`uname -s`" in
*win32* | *WIN32*)
# Extract the first word of "cl", so it can be a program name with args.
set dummy cl; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:945: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
ac_dummy="$PATH"
for ac_dir in $ac_dummy; do
test -z "$ac_dir" && ac_dir=.
if test -f $ac_dir/$ac_word; then
ac_cv_prog_CC="cl"
break
fi
done
IFS="$ac_save_ifs"
fi
fi
CC="$ac_cv_prog_CC"
if test -n "$CC"; then
echo "$ac_t""$CC" 1>&6
else
echo "$ac_t""no" 1>&6
fi
;;
esac
fi
test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
fi
 
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
echo "configure:977: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
 
ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
cross_compiling=$ac_cv_prog_cc_cross
 
cat > conftest.$ac_ext << EOF
 
#line 988 "configure"
#include "confdefs.h"
 
main(){return(0);}
EOF
if { (eval echo configure:993: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
ac_cv_prog_cc_works=yes
# If we can't run a trivial program, we are probably using a cross compiler.
if (./conftest; exit) 2>/dev/null; then
ac_cv_prog_cc_cross=no
else
ac_cv_prog_cc_cross=yes
fi
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
ac_cv_prog_cc_works=no
fi
rm -fr conftest*
ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
cross_compiling=$ac_cv_prog_cc_cross
 
echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
if test $ac_cv_prog_cc_works = no; then
{ echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
echo "configure:1019: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
cross_compiling=$ac_cv_prog_cc_cross
 
echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
echo "configure:1024: checking whether we are using GNU C" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.c <<EOF
#ifdef __GNUC__
yes;
#endif
EOF
if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1033: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
ac_cv_prog_gcc=yes
else
ac_cv_prog_gcc=no
fi
fi
 
echo "$ac_t""$ac_cv_prog_gcc" 1>&6
 
if test $ac_cv_prog_gcc = yes; then
GCC=yes
else
GCC=
fi
 
ac_test_CFLAGS="${CFLAGS+set}"
ac_save_CFLAGS="$CFLAGS"
CFLAGS=
echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
echo "configure:1052: checking whether ${CC-cc} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
echo 'void f(){}' > conftest.c
if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
ac_cv_prog_cc_g=yes
else
ac_cv_prog_cc_g=no
fi
rm -f conftest*
 
fi
 
echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
if test "$ac_test_CFLAGS" = set; then
CFLAGS="$ac_save_CFLAGS"
elif test $ac_cv_prog_cc_g = yes; then
if test "$GCC" = yes; then
CFLAGS="-g -O2"
else
CFLAGS="-g"
fi
else
if test "$GCC" = yes; then
CFLAGS="-O2"
else
CFLAGS=
fi
fi
 
# Find a good install program. We prefer a C program (faster),
# so one script is as good as another. But avoid the broken or
# incompatible versions:
# SysV /etc/install, /usr/sbin/install
# SunOS /usr/etc/install
# IRIX /sbin/install
# AIX /bin/install
# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
# AFS /usr/afsws/bin/install, which mishandles nonexistent args
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
echo "configure:1095: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
for ac_dir in $PATH; do
# Account for people who put trailing slashes in PATH elements.
case "$ac_dir/" in
/|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
*)
# OSF1 and SCO ODT 3.0 have their own names for install.
# Don't use installbsd from OSF since it installs stuff as root
# by default.
for ac_prog in ginstall scoinst install; do
if test -f $ac_dir/$ac_prog; then
if test $ac_prog = install &&
grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
# AIX install. It has an incompatible calling convention.
:
else
ac_cv_path_install="$ac_dir/$ac_prog -c"
break 2
fi
fi
done
;;
esac
done
IFS="$ac_save_IFS"
 
fi
if test "${ac_cv_path_install+set}" = set; then
INSTALL="$ac_cv_path_install"
else
# As a last resort, use the slow shell script. We don't cache a
# path for INSTALL within a source directory, because that will
# break other packages using the cache if that directory is
# removed, or if the path is relative.
INSTALL="$ac_install_sh"
fi
fi
echo "$ac_t""$INSTALL" 1>&6
 
# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
# It thinks the first close brace ends the variable substitution.
test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
 
test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
 
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
 
 
echo $ac_n "checking target system type""... $ac_c" 1>&6
echo "configure:1149: checking target system type" >&5
 
target_alias=$target
case "$target_alias" in
NONE)
case $nonopt in
NONE) target_alias=$host_alias ;;
*) target_alias=$nonopt ;;
esac ;;
esac
 
target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$target" 1>&6
 
case "$target" in
i686-*-linux*)
CFLAGS="-g -mpentiumpro -O6 -ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations"
#CFLAGS="-g -mpentiumpro -O6 -ffast-math -funroll-loops -fexpensive-optimizations"
;;
alpha*-*-linux*)
CFLAGS="$CFLAGS -mcpu=ev4 -Wa,-mall"
;;
esac
 
case "$target" in
*-*-mingw32*)
MATHLIB=""
INETLIB="-lwsock32"
;;
*-*-beos*)
MATHLIB=""
INETLIB=""
;;
*)
MATHLIB="-lm"
INETLIB=""
;;
esac
 
 
 
SDL_VERSION=1.0.1
# Check whether --with-sdl-prefix or --without-sdl-prefix was given.
if test "${with_sdl_prefix+set}" = set; then
withval="$with_sdl_prefix"
sdl_prefix="$withval"
else
sdl_prefix=""
fi
 
# Check whether --with-sdl-exec-prefix or --without-sdl-exec-prefix was given.
if test "${with_sdl_exec_prefix+set}" = set; then
withval="$with_sdl_exec_prefix"
sdl_exec_prefix="$withval"
else
sdl_exec_prefix=""
fi
 
# Check whether --enable-sdltest or --disable-sdltest was given.
if test "${enable_sdltest+set}" = set; then
enableval="$enable_sdltest"
:
else
enable_sdltest=yes
fi
 
 
if test x$sdl_exec_prefix != x ; then
sdl_args="$sdl_args --exec-prefix=$sdl_exec_prefix"
if test x${SDL_CONFIG+set} != xset ; then
SDL_CONFIG=$sdl_exec_prefix/bin/sdl-config
fi
fi
if test x$sdl_prefix != x ; then
sdl_args="$sdl_args --prefix=$sdl_prefix"
if test x${SDL_CONFIG+set} != xset ; then
SDL_CONFIG=$sdl_prefix/bin/sdl-config
fi
fi
 
# Extract the first word of "sdl-config", so it can be a program name with args.
set dummy sdl-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1235: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_SDL_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
case "$SDL_CONFIG" in
/*)
ac_cv_path_SDL_CONFIG="$SDL_CONFIG" # Let the user override the test with a path.
;;
?:/*)
ac_cv_path_SDL_CONFIG="$SDL_CONFIG" # Let the user override the test with a dos path.
;;
*)
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
ac_dummy="$PATH"
for ac_dir in $ac_dummy; do
test -z "$ac_dir" && ac_dir=.
if test -f $ac_dir/$ac_word; then
ac_cv_path_SDL_CONFIG="$ac_dir/$ac_word"
break
fi
done
IFS="$ac_save_ifs"
test -z "$ac_cv_path_SDL_CONFIG" && ac_cv_path_SDL_CONFIG="no"
;;
esac
fi
SDL_CONFIG="$ac_cv_path_SDL_CONFIG"
if test -n "$SDL_CONFIG"; then
echo "$ac_t""$SDL_CONFIG" 1>&6
else
echo "$ac_t""no" 1>&6
fi
 
min_sdl_version=$SDL_VERSION
echo $ac_n "checking for SDL - version >= $min_sdl_version""... $ac_c" 1>&6
echo "configure:1270: checking for SDL - version >= $min_sdl_version" >&5
no_sdl=""
if test "$SDL_CONFIG" = "no" ; then
no_sdl=yes
else
SDL_CFLAGS=`$SDL_CONFIG $sdlconf_args --cflags`
SDL_LIBS=`$SDL_CONFIG $sdlconf_args --libs`
 
sdl_major_version=`$SDL_CONFIG $sdl_args --version | \
sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'`
sdl_minor_version=`$SDL_CONFIG $sdl_args --version | \
sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'`
sdl_micro_version=`$SDL_CONFIG $sdl_config_args --version | \
sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'`
if test "x$enable_sdltest" = "xyes" ; then
ac_save_CFLAGS="$CFLAGS"
ac_save_LIBS="$LIBS"
CFLAGS="$CFLAGS $SDL_CFLAGS"
LIBS="$LIBS $SDL_LIBS"
rm -f conf.sdltest
if test "$cross_compiling" = yes; then
echo $ac_n "cross compiling; assumed OK... $ac_c"
else
cat > conftest.$ac_ext <<EOF
#line 1294 "configure"
#include "confdefs.h"
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SDL.h"
 
char*
my_strdup (char *str)
{
char *new_str;
if (str)
{
new_str = malloc ((strlen (str) + 1) * sizeof(char));
strcpy (new_str, str);
}
else
new_str = NULL;
return new_str;
}
 
int main ()
{
int major, minor, micro;
char *tmp_version;
 
system ("touch conf.sdltest");
 
/* HP/UX 9 (%@#!) writes to sscanf strings */
tmp_version = my_strdup("$min_sdl_version");
if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
printf("%s, bad version string\n", "$min_sdl_version");
exit(1);
}
 
if (($sdl_major_version > major) ||
(($sdl_major_version == major) && ($sdl_minor_version > minor)) ||
(($sdl_major_version == major) && ($sdl_minor_version == minor) && ($sdl_micro_version >= micro)))
{
return 0;
}
else
{
printf("\n*** 'sdl-config --version' returned %d.%d.%d, but the minimum version\n", $sdl_major_version, $sdl_minor_version, $sdl_micro_version);
printf("*** of SDL required is %d.%d.%d. If sdl-config is correct, then it is\n", major, minor, micro);
printf("*** best to upgrade to the required version.\n");
printf("*** If sdl-config was wrong, set the environment variable SDL_CONFIG\n");
printf("*** to point to the correct copy of sdl-config, and remove the file\n");
printf("*** config.cache before re-running configure\n");
return 1;
}
}
 
 
EOF
if { (eval echo configure:1352: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
:
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -fr conftest*
no_sdl=yes
fi
rm -fr conftest*
fi
 
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
fi
if test "x$no_sdl" = x ; then
echo "$ac_t""yes" 1>&6
:
else
echo "$ac_t""no" 1>&6
if test "$SDL_CONFIG" = "no" ; then
echo "*** The sdl-config script installed by SDL could not be found"
echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in"
echo "*** your path, or set the SDL_CONFIG environment variable to the"
echo "*** full path to sdl-config."
else
if test -f conf.sdltest ; then
:
else
echo "*** Could not run SDL test program, checking why..."
CFLAGS="$CFLAGS $SDL_CFLAGS"
LIBS="$LIBS $SDL_LIBS"
cat > conftest.$ac_ext <<EOF
#line 1386 "configure"
#include "confdefs.h"
 
#include <stdio.h>
#include "SDL.h"
 
int main() {
return 0;
; return 0; }
EOF
if { (eval echo configure:1396: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
echo "*** The test program compiled, but did not run. This usually means"
echo "*** that the run-time linker is not finding SDL or finding the wrong"
echo "*** version of SDL. If it is not finding SDL, you'll need to set your"
echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
echo "*** to the installed location Also, make sure you have run ldconfig if that"
echo "*** is required on your system"
echo "***"
echo "*** If you have an old version installed, it is best to remove it, although"
echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
echo "*** The test program failed to compile or link. See the file config.log for the"
echo "*** exact error that occured. This usually means SDL was incorrectly installed"
echo "*** or that you have moved SDL since it was installed. In the latter case, you"
echo "*** may want to edit the sdl-config script: $SDL_CONFIG"
fi
rm -f conftest*
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
fi
SDL_CFLAGS=""
SDL_LIBS=""
{ echo "configure: error: *** SDL version $SDL_VERSION not found!" 1>&2; exit 1; }
 
fi
rm -f conf.sdltest
 
CFLAGS="$CFLAGS $SDL_CFLAGS -DSDL"
LIBS="$LIBS $SDL_LIBS"
 
case "$target" in
*-*-mingw32*)
cp ico_o ico.o
ICONOBJ="ico.o"
;;
*)
ICONOBJ=""
;;
esac
 
 
# Check whether --enable-asm or --disable-asm was given.
if test "${enable_asm+set}" = set; then
enableval="$enable_asm"
:
else
enable_asm=no
fi
 
if test x$enable_asm = xyes; then
CFLAGS="$CFLAGS -DUSE_ASM"
fi
 
CFLAGS="$CFLAGS -DELF"
 
# Finally create all the generated files
trap '' 1 2 15
cat > confcache <<\EOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
# scripts and configure runs. It is not useful on other systems.
# If it contains results you don't want to keep, you may remove or edit it.
#
# By default, configure uses ./config.cache as the cache file,
# creating it if it does not exist already. You can give configure
# the --cache-file=FILE option to use a different cache file; that is
# what configure does when it calls configure scripts in
# subdirectories, so they share the cache.
# Giving --cache-file=/dev/null disables caching, for debugging configure.
# config.status only pays attention to the cache file if you give it the
# --recheck option to rerun configure.
#
EOF
# The following way of writing the cache mishandles newlines in values,
# but we know of no workaround that is simple, portable, and efficient.
# So, don't put newlines in cache variables' values.
# Ultrix sh set writes to stderr and can't be redirected directly,
# and sets the high bit in the cache file unless we assign to the vars.
(set) 2>&1 |
case `(ac_space=' '; set | grep ac_space) 2>&1` in
*ac_space=\ *)
# `set' does not quote correctly, so add quotes (double-quote substitution
# turns \\\\ into \\, and sed turns \\ into \).
sed -n \
-e "s/'/'\\\\''/g" \
-e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
;;
*)
# `set' quotes correctly as required by POSIX, so do not add quotes.
sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
;;
esac >> confcache
if cmp -s $cache_file confcache; then
:
else
if test -w $cache_file; then
echo "updating cache $cache_file"
cat confcache > $cache_file
else
echo "not updating unwritable cache $cache_file"
fi
fi
rm -f confcache
 
trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
 
test "x$prefix" = xNONE && prefix=$ac_default_prefix
# Let make expand exec_prefix.
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
 
# Any assignment to VPATH causes Sun make to only execute
# the first set of double-colon rules, so remove it if not needed.
# If there is a colon in the path, we need to keep it.
if test "x$srcdir" = x.; then
ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
fi
 
trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
 
# Transform confdefs.h into DEFS.
# Protect against shell expansion while executing Makefile rules.
# Protect against Makefile macro expansion.
cat > conftest.defs <<\EOF
s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
s%\[%\\&%g
s%\]%\\&%g
s%\$%$$%g
EOF
DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
rm -f conftest.defs
 
 
# Without the "./", some shells look in PATH for config.status.
: ${CONFIG_STATUS=./config.status}
 
echo creating $CONFIG_STATUS
rm -f $CONFIG_STATUS
cat > $CONFIG_STATUS <<EOF
#! /bin/sh
# Generated automatically by configure.
# Run this file to recreate the current configuration.
# This directory was configured as follows,
# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
#
# $0 $ac_configure_args
#
# Compiler output produced by configure, useful for debugging
# configure, is in ./config.log if it exists.
 
ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
for ac_option
do
case "\$ac_option" in
-recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
-version | --version | --versio | --versi | --vers | --ver | --ve | --v)
echo "$CONFIG_STATUS generated by autoconf version 2.13"
exit 0 ;;
-help | --help | --hel | --he | --h)
echo "\$ac_cs_usage"; exit 0 ;;
*) echo "\$ac_cs_usage"; exit 1 ;;
esac
done
 
ac_given_srcdir=$srcdir
ac_given_INSTALL="$INSTALL"
 
trap 'rm -fr `echo "
Makefile
" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
EOF
cat >> $CONFIG_STATUS <<EOF
 
# Protect against being on the right side of a sed subst in config.status.
sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
$ac_vpsub
$extrasub
s%@SHELL@%$SHELL%g
s%@CFLAGS@%$CFLAGS%g
s%@CPPFLAGS@%$CPPFLAGS%g
s%@CXXFLAGS@%$CXXFLAGS%g
s%@FFLAGS@%$FFLAGS%g
s%@DEFS@%$DEFS%g
s%@LDFLAGS@%$LDFLAGS%g
s%@LIBS@%$LIBS%g
s%@exec_prefix@%$exec_prefix%g
s%@prefix@%$prefix%g
s%@program_transform_name@%$program_transform_name%g
s%@bindir@%$bindir%g
s%@sbindir@%$sbindir%g
s%@libexecdir@%$libexecdir%g
s%@datadir@%$datadir%g
s%@sysconfdir@%$sysconfdir%g
s%@sharedstatedir@%$sharedstatedir%g
s%@localstatedir@%$localstatedir%g
s%@libdir@%$libdir%g
s%@includedir@%$includedir%g
s%@oldincludedir@%$oldincludedir%g
s%@infodir@%$infodir%g
s%@mandir@%$mandir%g
s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
s%@INSTALL_DATA@%$INSTALL_DATA%g
s%@PACKAGE@%$PACKAGE%g
s%@VERSION@%$VERSION%g
s%@ACLOCAL@%$ACLOCAL%g
s%@AUTOCONF@%$AUTOCONF%g
s%@AUTOMAKE@%$AUTOMAKE%g
s%@AUTOHEADER@%$AUTOHEADER%g
s%@MAKEINFO@%$MAKEINFO%g
s%@SET_MAKE@%$SET_MAKE%g
s%@host@%$host%g
s%@host_alias@%$host_alias%g
s%@host_cpu@%$host_cpu%g
s%@host_vendor@%$host_vendor%g
s%@host_os@%$host_os%g
s%@target@%$target%g
s%@target_alias@%$target_alias%g
s%@target_cpu@%$target_cpu%g
s%@target_vendor@%$target_vendor%g
s%@target_os@%$target_os%g
s%@CC@%$CC%g
s%@MATHLIB@%$MATHLIB%g
s%@INETLIB@%$INETLIB%g
s%@SDL_CONFIG@%$SDL_CONFIG%g
s%@SDL_CFLAGS@%$SDL_CFLAGS%g
s%@SDL_LIBS@%$SDL_LIBS%g
s%@ICONOBJ@%$ICONOBJ%g
 
CEOF
EOF
 
cat >> $CONFIG_STATUS <<\EOF
 
# Split the substitutions into bite-sized pieces for seds with
# small command number limits, like on Digital OSF/1 and HP-UX.
ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
ac_file=1 # Number of current file.
ac_beg=1 # First line for current file.
ac_end=$ac_max_sed_cmds # Line after last line for current file.
ac_more_lines=:
ac_sed_cmds=""
while $ac_more_lines; do
if test $ac_beg -gt 1; then
sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
else
sed "${ac_end}q" conftest.subs > conftest.s$ac_file
fi
if test ! -s conftest.s$ac_file; then
ac_more_lines=false
rm -f conftest.s$ac_file
else
if test -z "$ac_sed_cmds"; then
ac_sed_cmds="sed -f conftest.s$ac_file"
else
ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
fi
ac_file=`expr $ac_file + 1`
ac_beg=$ac_end
ac_end=`expr $ac_end + $ac_max_sed_cmds`
fi
done
if test -z "$ac_sed_cmds"; then
ac_sed_cmds=cat
fi
EOF
 
cat >> $CONFIG_STATUS <<EOF
 
CONFIG_FILES=\${CONFIG_FILES-"Makefile
"}
EOF
cat >> $CONFIG_STATUS <<\EOF
for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
# Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
case "$ac_file" in
*:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
*) ac_file_in="${ac_file}.in" ;;
esac
 
# Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
 
# Remove last slash and all that follows it. Not all systems have dirname.
ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
# The file is in a subdirectory.
test ! -d "$ac_dir" && mkdir "$ac_dir"
ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
# A "../" for each directory in $ac_dir_suffix.
ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
else
ac_dir_suffix= ac_dots=
fi
 
case "$ac_given_srcdir" in
.) srcdir=.
if test -z "$ac_dots"; then top_srcdir=.
else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
/*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
*) # Relative path.
srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
top_srcdir="$ac_dots$ac_given_srcdir" ;;
esac
 
case "$ac_given_INSTALL" in
[/$]*) INSTALL="$ac_given_INSTALL" ;;
*) INSTALL="$ac_dots$ac_given_INSTALL" ;;
esac
 
echo creating "$ac_file"
rm -f "$ac_file"
configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
case "$ac_file" in
*Makefile*) ac_comsub="1i\\
# $configure_input" ;;
*) ac_comsub= ;;
esac
 
ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
sed -e "$ac_comsub
s%@configure_input@%$configure_input%g
s%@srcdir@%$srcdir%g
s%@top_srcdir@%$top_srcdir%g
s%@INSTALL@%$INSTALL%g
" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
fi; done
rm -f conftest.s*
 
EOF
cat >> $CONFIG_STATUS <<EOF
 
EOF
cat >> $CONFIG_STATUS <<\EOF
 
exit 0
EOF
chmod +x $CONFIG_STATUS
rm -fr confdefs* $ac_clean_files
test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
 
/contrib/other/sdlquake-1.0.9/configure.in
0,0 → 1,81
dnl Process this file with autoconf to produce a configure script.
AC_INIT(README.SDL)
 
dnl Setup for automake
AM_INIT_AUTOMAKE(sdlquake, 1.0.9)
 
dnl Detect the canonical target build environment
AC_CANONICAL_HOST
AC_CANONICAL_TARGET
 
dnl Check for tools
 
AC_PROG_MAKE_SET
AC_PROG_CC
AC_PROG_INSTALL
 
dnl The alpha architecture needs special flags for binary portability
AC_CANONICAL_TARGET
case "$target" in
i686-*-linux*)
CFLAGS="-g -mpentiumpro -O6 -ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations"
#CFLAGS="-g -mpentiumpro -O6 -ffast-math -funroll-loops -fexpensive-optimizations"
;;
alpha*-*-linux*)
CFLAGS="$CFLAGS -mcpu=ev4 -Wa,-mall"
;;
esac
 
dnl Figure out which math and networking libraries to use
case "$target" in
*-*-mingw32*)
MATHLIB=""
INETLIB="-lwsock32"
;;
*-*-beos*)
MATHLIB=""
INETLIB=""
;;
*)
MATHLIB="-lm"
INETLIB=""
;;
esac
AC_SUBST(MATHLIB)
AC_SUBST(INETLIB)
 
dnl Check for SDL
SDL_VERSION=1.0.1
AM_PATH_SDL($SDL_VERSION,
:,
AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!])
)
CFLAGS="$CFLAGS $SDL_CFLAGS -DSDL"
LIBS="$LIBS $SDL_LIBS"
 
dnl Set up the icon object file, for Mingw32
case "$target" in
*-*-mingw32*)
cp ico_o ico.o
ICONOBJ="ico.o"
;;
*)
ICONOBJ=""
;;
esac
AC_SUBST(ICONOBJ)
 
dnl Enable/disable the i686 asm
AC_ARG_ENABLE(asm,
[ --enable-asm enable i686 assembly routines [default=no]],
, enable_asm=no)
if test x$enable_asm = xyes; then
CFLAGS="$CFLAGS -DUSE_ASM"
fi
 
CFLAGS="$CFLAGS -DELF"
 
# Finally create all the generated files
AC_OUTPUT([
Makefile
])
/contrib/other/sdlquake-1.0.9/conproc.c
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;
}
/contrib/other/sdlquake-1.0.9/conproc.h
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);
 
/contrib/other/sdlquake-1.0.9/console.c
0,0 → 1,651
/*
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"
 
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];
 
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)
{
if ( ! con_initialized ) return;
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;
if ( ! con_initialized ) return;
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
}
 
/contrib/other/sdlquake-1.0.9/console.h
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
 
/contrib/other/sdlquake-1.0.9/crc.c
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;
}
/contrib/other/sdlquake-1.0.9/crc.h
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);
/contrib/other/sdlquake-1.0.9/cvar.c
0,0 → 1,224
/*
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 = "";
 
/*
============
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);
}
}
 
/*
============
Cvar_SetValue
============
*/
void Cvar_SetValue (char *var_name, float value)
{
char val[32];
sprintf (val, "%f",value);
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);
}
 
/contrib/other/sdlquake-1.0.9/cvar.h
0,0 → 1,97
/*
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);
 
extern cvar_t *cvar_vars;
/contrib/other/sdlquake-1.0.9/d_copy.S
0,0 → 1,149
//
// d_copy.s
// x86 assembly-language screen copying code.
//
 
#include "asm_i386.h"
#include "quakeasm.h"
#include "asm_draw.h"
 
.data
 
LCopyWidth: .long 0
LBlockSrcStep: .long 0
LBlockDestStep: .long 0
LSrcDelta: .long 0
LDestDelta: .long 0
 
#define bufptr 4+16
 
// copies 16 rows per plane at a pop; idea is that 16*512 = 8k, and since
// no Mode X mode is wider than 360, all the data should fit in the cache for
// the passes for the next 3 planes
 
.text
 
.globl C(VGA_UpdatePlanarScreen)
C(VGA_UpdatePlanarScreen):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
 
movl C(VGA_bufferrowbytes),%eax
shll $1,%eax
movl %eax,LBlockSrcStep
movl C(VGA_rowbytes),%eax
shll $1,%eax
movl %eax,LBlockDestStep
 
movl $0x3C4,%edx
movb $2,%al
outb %al,%dx // point the SC to the Map Mask
incl %edx
 
movl bufptr(%esp),%esi
movl C(VGA_pagebase),%edi
movl C(VGA_height),%ebp
shrl $1,%ebp
 
movl C(VGA_width),%ecx
movl C(VGA_bufferrowbytes),%eax
subl %ecx,%eax
movl %eax,LSrcDelta
movl C(VGA_rowbytes),%eax
shll $2,%eax
subl %ecx,%eax
movl %eax,LDestDelta
shrl $4,%ecx
movl %ecx,LCopyWidth
 
LRowLoop:
movb $1,%al
 
LPlaneLoop:
outb %al,%dx
movb $2,%ah
 
pushl %esi
pushl %edi
LRowSetLoop:
movl LCopyWidth,%ecx
LColumnLoop:
movb 12(%esi),%bh
movb 8(%esi),%bl
shll $16,%ebx
movb 4(%esi),%bh
movb (%esi),%bl
movl %ebx,(%edi)
addl $16,%esi
addl $4,%edi
decl %ecx
jnz LColumnLoop
 
addl LDestDelta,%edi
addl LSrcDelta,%esi
decb %ah
jnz LRowSetLoop
 
popl %edi
popl %esi
incl %esi
 
shlb $1,%al
cmpb $16,%al
jnz LPlaneLoop
 
subl $4,%esi
addl LBlockSrcStep,%esi
addl LBlockDestStep,%edi
decl %ebp
jnz LRowLoop
 
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
 
ret
 
 
#define srcptr 4+16
#define destptr 8+16
#define width 12+16
#define height 16+16
#define srcrowbytes 20+16
#define destrowbytes 24+16
 
.globl C(VGA_UpdateLinearScreen)
C(VGA_UpdateLinearScreen):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
 
cld
movl srcptr(%esp),%esi
movl destptr(%esp),%edi
movl width(%esp),%ebx
movl srcrowbytes(%esp),%eax
subl %ebx,%eax
movl destrowbytes(%esp),%edx
subl %ebx,%edx
shrl $2,%ebx
movl height(%esp),%ebp
LLRowLoop:
movl %ebx,%ecx
rep/movsl (%esi),(%edi)
addl %eax,%esi
addl %edx,%edi
decl %ebp
jnz LLRowLoop
 
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
 
ret
 
/contrib/other/sdlquake-1.0.9/d_draw.S
0,0 → 1,1037
/*
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.
 
*/
//
// d_draw.s
// x86 assembly-language horizontal 8-bpp span-drawing code.
//
 
#include "asm_i386.h"
#include "quakeasm.h"
#include "asm_draw.h"
#include "d_ifacea.h"
 
#if id386
 
//----------------------------------------------------------------------
// 8-bpp horizontal span drawing code for polygons, with no transparency.
//
// Assumes there is at least one span in pspans, and that every span
// contains at least one pixel
//----------------------------------------------------------------------
 
.text
 
// out-of-line, rarely-needed clamping code
 
LClampHigh0:
movl C(bbextents),%esi
jmp LClampReentry0
LClampHighOrLow0:
jg LClampHigh0
xorl %esi,%esi
jmp LClampReentry0
 
LClampHigh1:
movl C(bbextentt),%edx
jmp LClampReentry1
LClampHighOrLow1:
jg LClampHigh1
xorl %edx,%edx
jmp LClampReentry1
 
LClampLow2:
movl $2048,%ebp
jmp LClampReentry2
LClampHigh2:
movl C(bbextents),%ebp
jmp LClampReentry2
 
LClampLow3:
movl $2048,%ecx
jmp LClampReentry3
LClampHigh3:
movl C(bbextentt),%ecx
jmp LClampReentry3
 
LClampLow4:
movl $2048,%eax
jmp LClampReentry4
LClampHigh4:
movl C(bbextents),%eax
jmp LClampReentry4
 
LClampLow5:
movl $2048,%ebx
jmp LClampReentry5
LClampHigh5:
movl C(bbextentt),%ebx
jmp LClampReentry5
 
 
#define pspans 4+16
 
.align 4
.globl C(D_DrawSpans8)
C(D_DrawSpans8):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
 
//
// set up scaled-by-8 steps, for 8-long segments; also set up cacheblock
// and span list pointers
//
// TODO: any overlap from rearranging?
flds C(d_sdivzstepu)
fmuls fp_8
movl C(cacheblock),%edx
flds C(d_tdivzstepu)
fmuls fp_8
movl pspans(%esp),%ebx // point to the first span descriptor
flds C(d_zistepu)
fmuls fp_8
movl %edx,pbase // pbase = cacheblock
fstps zi8stepu
fstps tdivz8stepu
fstps sdivz8stepu
 
LSpanLoop:
//
// set up the initial s/z, t/z, and 1/z on the FP stack, and generate the
// initial s and t values
//
// FIXME: pipeline FILD?
fildl espan_t_v(%ebx)
fildl espan_t_u(%ebx)
 
fld %st(1) // dv | du | dv
fmuls C(d_sdivzstepv) // dv*d_sdivzstepv | du | dv
fld %st(1) // du | dv*d_sdivzstepv | du | dv
fmuls C(d_sdivzstepu) // du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
fld %st(2) // du | du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
fmuls C(d_tdivzstepu) // du*d_tdivzstepu | du*d_sdivzstepu |
// dv*d_sdivzstepv | du | dv
fxch %st(1) // du*d_sdivzstepu | du*d_tdivzstepu |
// dv*d_sdivzstepv | du | dv
faddp %st(0),%st(2) // du*d_tdivzstepu |
// du*d_sdivzstepu + dv*d_sdivzstepv | du | dv
fxch %st(1) // du*d_sdivzstepu + dv*d_sdivzstepv |
// du*d_tdivzstepu | du | dv
fld %st(3) // dv | du*d_sdivzstepu + dv*d_sdivzstepv |
// du*d_tdivzstepu | du | dv
fmuls C(d_tdivzstepv) // dv*d_tdivzstepv |
// du*d_sdivzstepu + dv*d_sdivzstepv |
// du*d_tdivzstepu | du | dv
fxch %st(1) // du*d_sdivzstepu + dv*d_sdivzstepv |
// dv*d_tdivzstepv | du*d_tdivzstepu | du | dv
fadds C(d_sdivzorigin) // sdivz = d_sdivzorigin + dv*d_sdivzstepv +
// du*d_sdivzstepu; stays in %st(2) at end
fxch %st(4) // dv | dv*d_tdivzstepv | du*d_tdivzstepu | du |
// s/z
fmuls C(d_zistepv) // dv*d_zistepv | dv*d_tdivzstepv |
// du*d_tdivzstepu | du | s/z
fxch %st(1) // dv*d_tdivzstepv | dv*d_zistepv |
// du*d_tdivzstepu | du | s/z
faddp %st(0),%st(2) // dv*d_zistepv |
// dv*d_tdivzstepv + du*d_tdivzstepu | du | s/z
fxch %st(2) // du | dv*d_tdivzstepv + du*d_tdivzstepu |
// dv*d_zistepv | s/z
fmuls C(d_zistepu) // du*d_zistepu |
// dv*d_tdivzstepv + du*d_tdivzstepu |
// dv*d_zistepv | s/z
fxch %st(1) // dv*d_tdivzstepv + du*d_tdivzstepu |
// du*d_zistepu | dv*d_zistepv | s/z
fadds C(d_tdivzorigin) // tdivz = d_tdivzorigin + dv*d_tdivzstepv +
// du*d_tdivzstepu; stays in %st(1) at end
fxch %st(2) // dv*d_zistepv | du*d_zistepu | t/z | s/z
faddp %st(0),%st(1) // dv*d_zistepv + du*d_zistepu | t/z | s/z
 
flds fp_64k // fp_64k | dv*d_zistepv + du*d_zistepu | t/z | s/z
fxch %st(1) // dv*d_zistepv + du*d_zistepu | fp_64k | t/z | s/z
fadds C(d_ziorigin) // zi = d_ziorigin + dv*d_zistepv +
// du*d_zistepu; stays in %st(0) at end
// 1/z | fp_64k | t/z | s/z
//
// calculate and clamp s & t
//
fdivr %st(0),%st(1) // 1/z | z*64k | t/z | s/z
 
//
// point %edi to the first pixel in the span
//
movl C(d_viewbuffer),%ecx
movl espan_t_v(%ebx),%eax
movl %ebx,pspantemp // preserve spans pointer
 
movl C(tadjust),%edx
movl C(sadjust),%esi
movl C(d_scantable)(,%eax,4),%edi // v * screenwidth
addl %ecx,%edi
movl espan_t_u(%ebx),%ecx
addl %ecx,%edi // pdest = &pdestspan[scans->u];
movl espan_t_count(%ebx),%ecx
 
//
// now start the FDIV for the end of the span
//
cmpl $8,%ecx
ja LSetupNotLast1
 
decl %ecx
jz LCleanup1 // if only one pixel, no need to start an FDIV
movl %ecx,spancountminus1
 
// finish up the s and t calcs
fxch %st(1) // z*64k | 1/z | t/z | s/z
 
fld %st(0) // z*64k | z*64k | 1/z | t/z | s/z
fmul %st(4),%st(0) // s | z*64k | 1/z | t/z | s/z
fxch %st(1) // z*64k | s | 1/z | t/z | s/z
fmul %st(3),%st(0) // t | s | 1/z | t/z | s/z
fxch %st(1) // s | t | 1/z | t/z | s/z
fistpl s // 1/z | t | t/z | s/z
fistpl t // 1/z | t/z | s/z
 
fildl spancountminus1
 
flds C(d_tdivzstepu) // C(d_tdivzstepu) | spancountminus1
flds C(d_zistepu) // C(d_zistepu) | C(d_tdivzstepu) | spancountminus1
fmul %st(2),%st(0) // C(d_zistepu)*scm1 | C(d_tdivzstepu) | scm1
fxch %st(1) // C(d_tdivzstepu) | C(d_zistepu)*scm1 | scm1
fmul %st(2),%st(0) // C(d_tdivzstepu)*scm1 | C(d_zistepu)*scm1 | scm1
fxch %st(2) // scm1 | C(d_zistepu)*scm1 | C(d_tdivzstepu)*scm1
fmuls C(d_sdivzstepu) // C(d_sdivzstepu)*scm1 | C(d_zistepu)*scm1 |
// C(d_tdivzstepu)*scm1
fxch %st(1) // C(d_zistepu)*scm1 | C(d_sdivzstepu)*scm1 |
// C(d_tdivzstepu)*scm1
faddp %st(0),%st(3) // C(d_sdivzstepu)*scm1 | C(d_tdivzstepu)*scm1
fxch %st(1) // C(d_tdivzstepu)*scm1 | C(d_sdivzstepu)*scm1
faddp %st(0),%st(3) // C(d_sdivzstepu)*scm1
faddp %st(0),%st(3)
 
flds fp_64k
fdiv %st(1),%st(0) // this is what we've gone to all this trouble to
// overlap
jmp LFDIVInFlight1
 
LCleanup1:
// finish up the s and t calcs
fxch %st(1) // z*64k | 1/z | t/z | s/z
 
fld %st(0) // z*64k | z*64k | 1/z | t/z | s/z
fmul %st(4),%st(0) // s | z*64k | 1/z | t/z | s/z
fxch %st(1) // z*64k | s | 1/z | t/z | s/z
fmul %st(3),%st(0) // t | s | 1/z | t/z | s/z
fxch %st(1) // s | t | 1/z | t/z | s/z
fistpl s // 1/z | t | t/z | s/z
fistpl t // 1/z | t/z | s/z
jmp LFDIVInFlight1
 
.align 4
LSetupNotLast1:
// finish up the s and t calcs
fxch %st(1) // z*64k | 1/z | t/z | s/z
 
fld %st(0) // z*64k | z*64k | 1/z | t/z | s/z
fmul %st(4),%st(0) // s | z*64k | 1/z | t/z | s/z
fxch %st(1) // z*64k | s | 1/z | t/z | s/z
fmul %st(3),%st(0) // t | s | 1/z | t/z | s/z
fxch %st(1) // s | t | 1/z | t/z | s/z
fistpl s // 1/z | t | t/z | s/z
fistpl t // 1/z | t/z | s/z
 
fadds zi8stepu
fxch %st(2)
fadds sdivz8stepu
fxch %st(2)
flds tdivz8stepu
faddp %st(0),%st(2)
flds fp_64k
fdiv %st(1),%st(0) // z = 1/1/z
// this is what we've gone to all this trouble to
// overlap
LFDIVInFlight1:
 
addl s,%esi
addl t,%edx
movl C(bbextents),%ebx
movl C(bbextentt),%ebp
cmpl %ebx,%esi
ja LClampHighOrLow0
LClampReentry0:
movl %esi,s
movl pbase,%ebx
shll $16,%esi
cmpl %ebp,%edx
movl %esi,sfracf
ja LClampHighOrLow1
LClampReentry1:
movl %edx,t
movl s,%esi // sfrac = scans->sfrac;
shll $16,%edx
movl t,%eax // tfrac = scans->tfrac;
sarl $16,%esi
movl %edx,tfracf
 
//
// calculate the texture starting address
//
sarl $16,%eax
movl C(cachewidth),%edx
imull %edx,%eax // (tfrac >> 16) * cachewidth
addl %ebx,%esi
addl %eax,%esi // psource = pbase + (sfrac >> 16) +
// ((tfrac >> 16) * cachewidth);
 
//
// determine whether last span or not
//
cmpl $8,%ecx
jna LLastSegment
 
//
// not the last segment; do full 8-wide segment
//
LNotLastSegment:
 
//
// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
// get there
//
 
// pick up after the FDIV that was left in flight previously
 
fld %st(0) // duplicate it
fmul %st(4),%st(0) // s = s/z * z
fxch %st(1)
fmul %st(3),%st(0) // t = t/z * z
fxch %st(1)
fistpl snext
fistpl tnext
movl snext,%eax
movl tnext,%edx
 
movb (%esi),%bl // get first source texel
subl $8,%ecx // count off this segments' pixels
movl C(sadjust),%ebp
movl %ecx,counttemp // remember count of remaining pixels
 
movl C(tadjust),%ecx
movb %bl,(%edi) // store first dest pixel
 
addl %eax,%ebp
addl %edx,%ecx
 
movl C(bbextents),%eax
movl C(bbextentt),%edx
 
cmpl $2048,%ebp
jl LClampLow2
cmpl %eax,%ebp
ja LClampHigh2
LClampReentry2:
 
cmpl $2048,%ecx
jl LClampLow3
cmpl %edx,%ecx
ja LClampHigh3
LClampReentry3:
 
movl %ebp,snext
movl %ecx,tnext
 
subl s,%ebp
subl t,%ecx
//
// set up advancetable
//
movl %ecx,%eax
movl %ebp,%edx
sarl $19,%eax // tstep >>= 16;
jz LZero
sarl $19,%edx // sstep >>= 16;
movl C(cachewidth),%ebx
imull %ebx,%eax
jmp LSetUp1
 
LZero:
sarl $19,%edx // sstep >>= 16;
movl C(cachewidth),%ebx
 
LSetUp1:
 
addl %edx,%eax // add in sstep
// (tstep >> 16) * cachewidth + (sstep >> 16);
movl tfracf,%edx
movl %eax,advancetable+4 // advance base in t
addl %ebx,%eax // ((tstep >> 16) + 1) * cachewidth +
// (sstep >> 16);
shll $13,%ebp // left-justify sstep fractional part
movl sfracf,%ebx
shll $13,%ecx // left-justify tstep fractional part
movl %eax,advancetable // advance extra in t
 
movl %ecx,tstep
addl %ecx,%edx // advance tfrac fractional part by tstep frac
 
sbbl %ecx,%ecx // turn tstep carry into -1 (0 if none)
addl %ebp,%ebx // advance sfrac fractional part by sstep frac
adcl advancetable+4(,%ecx,4),%esi // point to next source texel
 
addl tstep,%edx
sbbl %ecx,%ecx
movb (%esi),%al
addl %ebp,%ebx
movb %al,1(%edi)
adcl advancetable+4(,%ecx,4),%esi
 
addl tstep,%edx
sbbl %ecx,%ecx
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
 
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,2(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
 
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,3(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
 
 
//
// start FDIV for end of next segment in flight, so it can overlap
//
movl counttemp,%ecx
cmpl $8,%ecx // more than one segment after this?
ja LSetupNotLast2 // yes
 
decl %ecx
jz LFDIVInFlight2 // if only one pixel, no need to start an FDIV
movl %ecx,spancountminus1
fildl spancountminus1
 
flds C(d_zistepu) // C(d_zistepu) | spancountminus1
fmul %st(1),%st(0) // C(d_zistepu)*scm1 | scm1
flds C(d_tdivzstepu) // C(d_tdivzstepu) | C(d_zistepu)*scm1 | scm1
fmul %st(2),%st(0) // C(d_tdivzstepu)*scm1 | C(d_zistepu)*scm1 | scm1
fxch %st(1) // C(d_zistepu)*scm1 | C(d_tdivzstepu)*scm1 | scm1
faddp %st(0),%st(3) // C(d_tdivzstepu)*scm1 | scm1
fxch %st(1) // scm1 | C(d_tdivzstepu)*scm1
fmuls C(d_sdivzstepu) // C(d_sdivzstepu)*scm1 | C(d_tdivzstepu)*scm1
fxch %st(1) // C(d_tdivzstepu)*scm1 | C(d_sdivzstepu)*scm1
faddp %st(0),%st(3) // C(d_sdivzstepu)*scm1
flds fp_64k // 64k | C(d_sdivzstepu)*scm1
fxch %st(1) // C(d_sdivzstepu)*scm1 | 64k
faddp %st(0),%st(4) // 64k
 
fdiv %st(1),%st(0) // this is what we've gone to all this trouble to
// overlap
jmp LFDIVInFlight2
 
.align 4
LSetupNotLast2:
fadds zi8stepu
fxch %st(2)
fadds sdivz8stepu
fxch %st(2)
flds tdivz8stepu
faddp %st(0),%st(2)
flds fp_64k
fdiv %st(1),%st(0) // z = 1/1/z
// this is what we've gone to all this trouble to
// overlap
LFDIVInFlight2:
movl %ecx,counttemp
 
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,4(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
 
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,5(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
 
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,6(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
 
addl $8,%edi
movl %edx,tfracf
movl snext,%edx
movl %ebx,sfracf
movl tnext,%ebx
movl %edx,s
movl %ebx,t
 
movl counttemp,%ecx // retrieve count
 
//
// determine whether last span or not
//
cmpl $8,%ecx // are there multiple segments remaining?
movb %al,-1(%edi)
ja LNotLastSegment // yes
 
//
// last segment of scan
//
LLastSegment:
 
//
// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
// get there. The number of pixels left is variable, and we want to land on the
// last pixel, not step one past it, so we can't run into arithmetic problems
//
testl %ecx,%ecx
jz LNoSteps // just draw the last pixel and we're done
 
// pick up after the FDIV that was left in flight previously
 
 
fld %st(0) // duplicate it
fmul %st(4),%st(0) // s = s/z * z
fxch %st(1)
fmul %st(3),%st(0) // t = t/z * z
fxch %st(1)
fistpl snext
fistpl tnext
 
movb (%esi),%al // load first texel in segment
movl C(tadjust),%ebx
movb %al,(%edi) // store first pixel in segment
movl C(sadjust),%eax
 
addl snext,%eax
addl tnext,%ebx
 
movl C(bbextents),%ebp
movl C(bbextentt),%edx
 
cmpl $2048,%eax
jl LClampLow4
cmpl %ebp,%eax
ja LClampHigh4
LClampReentry4:
movl %eax,snext
 
cmpl $2048,%ebx
jl LClampLow5
cmpl %edx,%ebx
ja LClampHigh5
LClampReentry5:
 
cmpl $1,%ecx // don't bother
je LOnlyOneStep // if two pixels in segment, there's only one step,
// of the segment length
subl s,%eax
subl t,%ebx
 
addl %eax,%eax // convert to 15.17 format so multiply by 1.31
addl %ebx,%ebx // reciprocal yields 16.48
 
imull reciprocal_table-8(,%ecx,4) // sstep = (snext - s) / (spancount-1)
movl %edx,%ebp
 
movl %ebx,%eax
imull reciprocal_table-8(,%ecx,4) // tstep = (tnext - t) / (spancount-1)
 
LSetEntryvec:
//
// set up advancetable
//
movl entryvec_table(,%ecx,4),%ebx
movl %edx,%eax
movl %ebx,jumptemp // entry point into code for RET later
movl %ebp,%ecx
sarl $16,%edx // tstep >>= 16;
movl C(cachewidth),%ebx
sarl $16,%ecx // sstep >>= 16;
imull %ebx,%edx
 
addl %ecx,%edx // add in sstep
// (tstep >> 16) * cachewidth + (sstep >> 16);
movl tfracf,%ecx
movl %edx,advancetable+4 // advance base in t
addl %ebx,%edx // ((tstep >> 16) + 1) * cachewidth +
// (sstep >> 16);
shll $16,%ebp // left-justify sstep fractional part
movl sfracf,%ebx
shll $16,%eax // left-justify tstep fractional part
movl %edx,advancetable // advance extra in t
 
movl %eax,tstep
movl %ecx,%edx
addl %eax,%edx
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
 
jmp *jumptemp // jump to the number-of-pixels handler
 
//----------------------------------------
 
LNoSteps:
movb (%esi),%al // load first texel in segment
subl $7,%edi // adjust for hardwired offset
jmp LEndSpan
 
 
LOnlyOneStep:
subl s,%eax
subl t,%ebx
movl %eax,%ebp
movl %ebx,%edx
jmp LSetEntryvec
 
//----------------------------------------
 
.globl Entry2_8
Entry2_8:
subl $6,%edi // adjust for hardwired offsets
movb (%esi),%al
jmp LLEntry2_8
 
//----------------------------------------
 
.globl Entry3_8
Entry3_8:
subl $5,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
jmp LLEntry3_8
 
//----------------------------------------
 
.globl Entry4_8
Entry4_8:
subl $4,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LLEntry4_8
 
//----------------------------------------
 
.globl Entry5_8
Entry5_8:
subl $3,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LLEntry5_8
 
//----------------------------------------
 
.globl Entry6_8
Entry6_8:
subl $2,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LLEntry6_8
 
//----------------------------------------
 
.globl Entry7_8
Entry7_8:
decl %edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LLEntry7_8
 
//----------------------------------------
 
.globl Entry8_8
Entry8_8:
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
 
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,1(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LLEntry7_8:
sbbl %ecx,%ecx
movb %al,2(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LLEntry6_8:
sbbl %ecx,%ecx
movb %al,3(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LLEntry5_8:
sbbl %ecx,%ecx
movb %al,4(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LLEntry4_8:
sbbl %ecx,%ecx
movb %al,5(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
LLEntry3_8:
movb %al,6(%edi)
movb (%esi),%al
LLEntry2_8:
 
LEndSpan:
 
//
// clear s/z, t/z, 1/z from FP stack
//
fstp %st(0)
fstp %st(0)
fstp %st(0)
 
movl pspantemp,%ebx // restore spans pointer
movl espan_t_pnext(%ebx),%ebx // point to next span
testl %ebx,%ebx // any more spans?
movb %al,7(%edi)
jnz LSpanLoop // more spans
 
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
 
//----------------------------------------------------------------------
// 8-bpp horizontal span z drawing codefor polygons, with no transparency.
//
// Assumes there is at least one span in pzspans, and that every span
// contains at least one pixel
//----------------------------------------------------------------------
 
.text
 
// z-clamp on a non-negative gradient span
LClamp:
movl $0x40000000,%edx
xorl %ebx,%ebx
fstp %st(0)
jmp LZDraw
 
// z-clamp on a negative gradient span
LClampNeg:
movl $0x40000000,%edx
xorl %ebx,%ebx
fstp %st(0)
jmp LZDrawNeg
 
 
#define pzspans 4+16
 
.globl C(D_DrawZSpans)
C(D_DrawZSpans):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
 
flds C(d_zistepu)
movl C(d_zistepu),%eax
movl pzspans(%esp),%esi
testl %eax,%eax
jz LFNegSpan
 
fmuls Float2ToThe31nd
fistpl izistep // note: we are relying on FP exceptions being turned
// off here to avoid range problems
movl izistep,%ebx // remains loaded for all spans
 
LFSpanLoop:
// set up the initial 1/z value
fildl espan_t_v(%esi)
fildl espan_t_u(%esi)
movl espan_t_v(%esi),%ecx
movl C(d_pzbuffer),%edi
fmuls C(d_zistepu)
fxch %st(1)
fmuls C(d_zistepv)
fxch %st(1)
fadds C(d_ziorigin)
imull C(d_zrowbytes),%ecx
faddp %st(0),%st(1)
 
// clamp if z is nearer than 2 (1/z > 0.5)
fcoms float_point5
addl %ecx,%edi
movl espan_t_u(%esi),%edx
addl %edx,%edx // word count
movl espan_t_count(%esi),%ecx
addl %edx,%edi // pdest = &pdestspan[scans->u];
pushl %esi // preserve spans pointer
fnstsw %ax
testb $0x45,%ah
jz LClamp
 
fmuls Float2ToThe31nd
fistpl izi // note: we are relying on FP exceptions being turned
// off here to avoid problems when the span is closer
// than 1/(2**31)
movl izi,%edx
 
// at this point:
// %ebx = izistep
// %ecx = count
// %edx = izi
// %edi = pdest
 
LZDraw:
 
// do a single pixel up front, if necessary to dword align the destination
testl $2,%edi
jz LFMiddle
movl %edx,%eax
addl %ebx,%edx
shrl $16,%eax
decl %ecx
movw %ax,(%edi)
addl $2,%edi
 
// do middle a pair of aligned dwords at a time
LFMiddle:
pushl %ecx
shrl $1,%ecx // count / 2
jz LFLast // no aligned dwords to do
shrl $1,%ecx // (count / 2) / 2
jnc LFMiddleLoop // even number of aligned dwords to do
 
movl %edx,%eax
addl %ebx,%edx
shrl $16,%eax
movl %edx,%esi
addl %ebx,%edx
andl $0xFFFF0000,%esi
orl %esi,%eax
movl %eax,(%edi)
addl $4,%edi
andl %ecx,%ecx
jz LFLast
 
LFMiddleLoop:
movl %edx,%eax
addl %ebx,%edx
shrl $16,%eax
movl %edx,%esi
addl %ebx,%edx
andl $0xFFFF0000,%esi
orl %esi,%eax
movl %edx,%ebp
movl %eax,(%edi)
addl %ebx,%edx
shrl $16,%ebp
movl %edx,%esi
addl %ebx,%edx
andl $0xFFFF0000,%esi
orl %esi,%ebp
movl %ebp,4(%edi) // FIXME: eliminate register contention
addl $8,%edi
 
decl %ecx
jnz LFMiddleLoop
 
LFLast:
popl %ecx // retrieve count
popl %esi // retrieve span pointer
 
// do the last, unaligned pixel, if there is one
andl $1,%ecx // is there an odd pixel left to do?
jz LFSpanDone // no
shrl $16,%edx
movw %dx,(%edi) // do the final pixel's z
 
LFSpanDone:
movl espan_t_pnext(%esi),%esi
testl %esi,%esi
jnz LFSpanLoop
 
jmp LFDone
 
LFNegSpan:
fmuls FloatMinus2ToThe31nd
fistpl izistep // note: we are relying on FP exceptions being turned
// off here to avoid range problems
movl izistep,%ebx // remains loaded for all spans
 
LFNegSpanLoop:
// set up the initial 1/z value
fildl espan_t_v(%esi)
fildl espan_t_u(%esi)
movl espan_t_v(%esi),%ecx
movl C(d_pzbuffer),%edi
fmuls C(d_zistepu)
fxch %st(1)
fmuls C(d_zistepv)
fxch %st(1)
fadds C(d_ziorigin)
imull C(d_zrowbytes),%ecx
faddp %st(0),%st(1)
 
// clamp if z is nearer than 2 (1/z > 0.5)
fcoms float_point5
addl %ecx,%edi
movl espan_t_u(%esi),%edx
addl %edx,%edx // word count
movl espan_t_count(%esi),%ecx
addl %edx,%edi // pdest = &pdestspan[scans->u];
pushl %esi // preserve spans pointer
fnstsw %ax
testb $0x45,%ah
jz LClampNeg
 
fmuls Float2ToThe31nd
fistpl izi // note: we are relying on FP exceptions being turned
// off here to avoid problems when the span is closer
// than 1/(2**31)
movl izi,%edx
 
// at this point:
// %ebx = izistep
// %ecx = count
// %edx = izi
// %edi = pdest
 
LZDrawNeg:
 
// do a single pixel up front, if necessary to dword align the destination
testl $2,%edi
jz LFNegMiddle
movl %edx,%eax
subl %ebx,%edx
shrl $16,%eax
decl %ecx
movw %ax,(%edi)
addl $2,%edi
 
// do middle a pair of aligned dwords at a time
LFNegMiddle:
pushl %ecx
shrl $1,%ecx // count / 2
jz LFNegLast // no aligned dwords to do
shrl $1,%ecx // (count / 2) / 2
jnc LFNegMiddleLoop // even number of aligned dwords to do
 
movl %edx,%eax
subl %ebx,%edx
shrl $16,%eax
movl %edx,%esi
subl %ebx,%edx
andl $0xFFFF0000,%esi
orl %esi,%eax
movl %eax,(%edi)
addl $4,%edi
andl %ecx,%ecx
jz LFNegLast
 
LFNegMiddleLoop:
movl %edx,%eax
subl %ebx,%edx
shrl $16,%eax
movl %edx,%esi
subl %ebx,%edx
andl $0xFFFF0000,%esi
orl %esi,%eax
movl %edx,%ebp
movl %eax,(%edi)
subl %ebx,%edx
shrl $16,%ebp
movl %edx,%esi
subl %ebx,%edx
andl $0xFFFF0000,%esi
orl %esi,%ebp
movl %ebp,4(%edi) // FIXME: eliminate register contention
addl $8,%edi
 
decl %ecx
jnz LFNegMiddleLoop
 
LFNegLast:
popl %ecx // retrieve count
popl %esi // retrieve span pointer
 
// do the last, unaligned pixel, if there is one
andl $1,%ecx // is there an odd pixel left to do?
jz LFNegSpanDone // no
shrl $16,%edx
movw %dx,(%edi) // do the final pixel's z
 
LFNegSpanDone:
movl espan_t_pnext(%esi),%esi
testl %esi,%esi
jnz LFNegSpanLoop
 
LFDone:
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
 
#endif // id386
/contrib/other/sdlquake-1.0.9/d_draw16.S
0,0 → 1,974
/*
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.
 
*/
//
// d_draw16.s
// x86 assembly-language horizontal 8-bpp span-drawing code, with 16-pixel
// subdivision.
//
 
#include "asm_i386.h"
#include "quakeasm.h"
#include "asm_draw.h"
#include "d_ifacea.h"
 
#if id386
 
//----------------------------------------------------------------------
// 8-bpp horizontal span drawing code for polygons, with no transparency and
// 16-pixel subdivision.
//
// Assumes there is at least one span in pspans, and that every span
// contains at least one pixel
//----------------------------------------------------------------------
 
.data
 
.text
 
// out-of-line, rarely-needed clamping code
 
LClampHigh0:
movl C(bbextents),%esi
jmp LClampReentry0
LClampHighOrLow0:
jg LClampHigh0
xorl %esi,%esi
jmp LClampReentry0
 
LClampHigh1:
movl C(bbextentt),%edx
jmp LClampReentry1
LClampHighOrLow1:
jg LClampHigh1
xorl %edx,%edx
jmp LClampReentry1
 
LClampLow2:
movl $4096,%ebp
jmp LClampReentry2
LClampHigh2:
movl C(bbextents),%ebp
jmp LClampReentry2
 
LClampLow3:
movl $4096,%ecx
jmp LClampReentry3
LClampHigh3:
movl C(bbextentt),%ecx
jmp LClampReentry3
 
LClampLow4:
movl $4096,%eax
jmp LClampReentry4
LClampHigh4:
movl C(bbextents),%eax
jmp LClampReentry4
 
LClampLow5:
movl $4096,%ebx
jmp LClampReentry5
LClampHigh5:
movl C(bbextentt),%ebx
jmp LClampReentry5
 
 
#define pspans 4+16
 
.align 4
.globl C(D_DrawSpans16)
C(D_DrawSpans16):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
 
//
// set up scaled-by-16 steps, for 16-long segments; also set up cacheblock
// and span list pointers
//
// TODO: any overlap from rearranging?
flds C(d_sdivzstepu)
fmuls fp_16
movl C(cacheblock),%edx
flds C(d_tdivzstepu)
fmuls fp_16
movl pspans(%esp),%ebx // point to the first span descriptor
flds C(d_zistepu)
fmuls fp_16
movl %edx,pbase // pbase = cacheblock
fstps zi16stepu
fstps tdivz16stepu
fstps sdivz16stepu
 
LSpanLoop:
//
// set up the initial s/z, t/z, and 1/z on the FP stack, and generate the
// initial s and t values
//
// FIXME: pipeline FILD?
fildl espan_t_v(%ebx)
fildl espan_t_u(%ebx)
 
fld %st(1) // dv | du | dv
fmuls C(d_sdivzstepv) // dv*d_sdivzstepv | du | dv
fld %st(1) // du | dv*d_sdivzstepv | du | dv
fmuls C(d_sdivzstepu) // du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
fld %st(2) // du | du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
fmuls C(d_tdivzstepu) // du*d_tdivzstepu | du*d_sdivzstepu |
// dv*d_sdivzstepv | du | dv
fxch %st(1) // du*d_sdivzstepu | du*d_tdivzstepu |
// dv*d_sdivzstepv | du | dv
faddp %st(0),%st(2) // du*d_tdivzstepu |
// du*d_sdivzstepu + dv*d_sdivzstepv | du | dv
fxch %st(1) // du*d_sdivzstepu + dv*d_sdivzstepv |
// du*d_tdivzstepu | du | dv
fld %st(3) // dv | du*d_sdivzstepu + dv*d_sdivzstepv |
// du*d_tdivzstepu | du | dv
fmuls C(d_tdivzstepv) // dv*d_tdivzstepv |
// du*d_sdivzstepu + dv*d_sdivzstepv |
// du*d_tdivzstepu | du | dv
fxch %st(1) // du*d_sdivzstepu + dv*d_sdivzstepv |
// dv*d_tdivzstepv | du*d_tdivzstepu | du | dv
fadds C(d_sdivzorigin) // sdivz = d_sdivzorigin + dv*d_sdivzstepv +
// du*d_sdivzstepu; stays in %st(2) at end
fxch %st(4) // dv | dv*d_tdivzstepv | du*d_tdivzstepu | du |
// s/z
fmuls C(d_zistepv) // dv*d_zistepv | dv*d_tdivzstepv |
// du*d_tdivzstepu | du | s/z
fxch %st(1) // dv*d_tdivzstepv | dv*d_zistepv |
// du*d_tdivzstepu | du | s/z
faddp %st(0),%st(2) // dv*d_zistepv |
// dv*d_tdivzstepv + du*d_tdivzstepu | du | s/z
fxch %st(2) // du | dv*d_tdivzstepv + du*d_tdivzstepu |
// dv*d_zistepv | s/z
fmuls C(d_zistepu) // du*d_zistepu |
// dv*d_tdivzstepv + du*d_tdivzstepu |
// dv*d_zistepv | s/z
fxch %st(1) // dv*d_tdivzstepv + du*d_tdivzstepu |
// du*d_zistepu | dv*d_zistepv | s/z
fadds C(d_tdivzorigin) // tdivz = d_tdivzorigin + dv*d_tdivzstepv +
// du*d_tdivzstepu; stays in %st(1) at end
fxch %st(2) // dv*d_zistepv | du*d_zistepu | t/z | s/z
faddp %st(0),%st(1) // dv*d_zistepv + du*d_zistepu | t/z | s/z
 
flds fp_64k // fp_64k | dv*d_zistepv + du*d_zistepu | t/z | s/z
fxch %st(1) // dv*d_zistepv + du*d_zistepu | fp_64k | t/z | s/z
fadds C(d_ziorigin) // zi = d_ziorigin + dv*d_zistepv +
// du*d_zistepu; stays in %st(0) at end
// 1/z | fp_64k | t/z | s/z
//
// calculate and clamp s & t
//
fdivr %st(0),%st(1) // 1/z | z*64k | t/z | s/z
 
//
// point %edi to the first pixel in the span
//
movl C(d_viewbuffer),%ecx
movl espan_t_v(%ebx),%eax
movl %ebx,pspantemp // preserve spans pointer
 
movl C(tadjust),%edx
movl C(sadjust),%esi
movl C(d_scantable)(,%eax,4),%edi // v * screenwidth
addl %ecx,%edi
movl espan_t_u(%ebx),%ecx
addl %ecx,%edi // pdest = &pdestspan[scans->u];
movl espan_t_count(%ebx),%ecx
 
//
// now start the FDIV for the end of the span
//
cmpl $16,%ecx
ja LSetupNotLast1
 
decl %ecx
jz LCleanup1 // if only one pixel, no need to start an FDIV
movl %ecx,spancountminus1
 
// finish up the s and t calcs
fxch %st(1) // z*64k | 1/z | t/z | s/z
 
fld %st(0) // z*64k | z*64k | 1/z | t/z | s/z
fmul %st(4),%st(0) // s | z*64k | 1/z | t/z | s/z
fxch %st(1) // z*64k | s | 1/z | t/z | s/z
fmul %st(3),%st(0) // t | s | 1/z | t/z | s/z
fxch %st(1) // s | t | 1/z | t/z | s/z
fistpl s // 1/z | t | t/z | s/z
fistpl t // 1/z | t/z | s/z
 
fildl spancountminus1
 
flds C(d_tdivzstepu) // C(d_tdivzstepu) | spancountminus1
flds C(d_zistepu) // C(d_zistepu) | C(d_tdivzstepu) | spancountminus1
fmul %st(2),%st(0) // C(d_zistepu)*scm1 | C(d_tdivzstepu) | scm1
fxch %st(1) // C(d_tdivzstepu) | C(d_zistepu)*scm1 | scm1
fmul %st(2),%st(0) // C(d_tdivzstepu)*scm1 | C(d_zistepu)*scm1 | scm1
fxch %st(2) // scm1 | C(d_zistepu)*scm1 | C(d_tdivzstepu)*scm1
fmuls C(d_sdivzstepu) // C(d_sdivzstepu)*scm1 | C(d_zistepu)*scm1 |
// C(d_tdivzstepu)*scm1
fxch %st(1) // C(d_zistepu)*scm1 | C(d_sdivzstepu)*scm1 |
// C(d_tdivzstepu)*scm1
faddp %st(0),%st(3) // C(d_sdivzstepu)*scm1 | C(d_tdivzstepu)*scm1
fxch %st(1) // C(d_tdivzstepu)*scm1 | C(d_sdivzstepu)*scm1
faddp %st(0),%st(3) // C(d_sdivzstepu)*scm1
faddp %st(0),%st(3)
 
flds fp_64k
fdiv %st(1),%st(0) // this is what we've gone to all this trouble to
// overlap
jmp LFDIVInFlight1
 
LCleanup1:
// finish up the s and t calcs
fxch %st(1) // z*64k | 1/z | t/z | s/z
 
fld %st(0) // z*64k | z*64k | 1/z | t/z | s/z
fmul %st(4),%st(0) // s | z*64k | 1/z | t/z | s/z
fxch %st(1) // z*64k | s | 1/z | t/z | s/z
fmul %st(3),%st(0) // t | s | 1/z | t/z | s/z
fxch %st(1) // s | t | 1/z | t/z | s/z
fistpl s // 1/z | t | t/z | s/z
fistpl t // 1/z | t/z | s/z
jmp LFDIVInFlight1
 
.align 4
LSetupNotLast1:
// finish up the s and t calcs
fxch %st(1) // z*64k | 1/z | t/z | s/z
 
fld %st(0) // z*64k | z*64k | 1/z | t/z | s/z
fmul %st(4),%st(0) // s | z*64k | 1/z | t/z | s/z
fxch %st(1) // z*64k | s | 1/z | t/z | s/z
fmul %st(3),%st(0) // t | s | 1/z | t/z | s/z
fxch %st(1) // s | t | 1/z | t/z | s/z
fistpl s // 1/z | t | t/z | s/z
fistpl t // 1/z | t/z | s/z
 
fadds zi16stepu
fxch %st(2)
fadds sdivz16stepu
fxch %st(2)
flds tdivz16stepu
faddp %st(0),%st(2)
flds fp_64k
fdiv %st(1),%st(0) // z = 1/1/z
// this is what we've gone to all this trouble to
// overlap
LFDIVInFlight1:
 
addl s,%esi
addl t,%edx
movl C(bbextents),%ebx
movl C(bbextentt),%ebp
cmpl %ebx,%esi
ja LClampHighOrLow0
LClampReentry0:
movl %esi,s
movl pbase,%ebx
shll $16,%esi
cmpl %ebp,%edx
movl %esi,sfracf
ja LClampHighOrLow1
LClampReentry1:
movl %edx,t
movl s,%esi // sfrac = scans->sfrac;
shll $16,%edx
movl t,%eax // tfrac = scans->tfrac;
sarl $16,%esi
movl %edx,tfracf
 
//
// calculate the texture starting address
//
sarl $16,%eax
movl C(cachewidth),%edx
imull %edx,%eax // (tfrac >> 16) * cachewidth
addl %ebx,%esi
addl %eax,%esi // psource = pbase + (sfrac >> 16) +
// ((tfrac >> 16) * cachewidth);
//
// determine whether last span or not
//
cmpl $16,%ecx
jna LLastSegment
 
//
// not the last segment; do full 16-wide segment
//
LNotLastSegment:
 
//
// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
// get there
//
 
// pick up after the FDIV that was left in flight previously
 
fld %st(0) // duplicate it
fmul %st(4),%st(0) // s = s/z * z
fxch %st(1)
fmul %st(3),%st(0) // t = t/z * z
fxch %st(1)
fistpl snext
fistpl tnext
movl snext,%eax
movl tnext,%edx
 
movb (%esi),%bl // get first source texel
subl $16,%ecx // count off this segments' pixels
movl C(sadjust),%ebp
movl %ecx,counttemp // remember count of remaining pixels
 
movl C(tadjust),%ecx
movb %bl,(%edi) // store first dest pixel
 
addl %eax,%ebp
addl %edx,%ecx
 
movl C(bbextents),%eax
movl C(bbextentt),%edx
 
cmpl $4096,%ebp
jl LClampLow2
cmpl %eax,%ebp
ja LClampHigh2
LClampReentry2:
 
cmpl $4096,%ecx
jl LClampLow3
cmpl %edx,%ecx
ja LClampHigh3
LClampReentry3:
 
movl %ebp,snext
movl %ecx,tnext
 
subl s,%ebp
subl t,%ecx
//
// set up advancetable
//
movl %ecx,%eax
movl %ebp,%edx
sarl $20,%eax // tstep >>= 16;
jz LZero
sarl $20,%edx // sstep >>= 16;
movl C(cachewidth),%ebx
imull %ebx,%eax
jmp LSetUp1
 
LZero:
sarl $20,%edx // sstep >>= 16;
movl C(cachewidth),%ebx
 
LSetUp1:
 
addl %edx,%eax // add in sstep
// (tstep >> 16) * cachewidth + (sstep >> 16);
movl tfracf,%edx
movl %eax,advancetable+4 // advance base in t
addl %ebx,%eax // ((tstep >> 16) + 1) * cachewidth +
// (sstep >> 16);
shll $12,%ebp // left-justify sstep fractional part
movl sfracf,%ebx
shll $12,%ecx // left-justify tstep fractional part
movl %eax,advancetable // advance extra in t
 
movl %ecx,tstep
addl %ecx,%edx // advance tfrac fractional part by tstep frac
 
sbbl %ecx,%ecx // turn tstep carry into -1 (0 if none)
addl %ebp,%ebx // advance sfrac fractional part by sstep frac
adcl advancetable+4(,%ecx,4),%esi // point to next source texel
 
addl tstep,%edx
sbbl %ecx,%ecx
movb (%esi),%al
addl %ebp,%ebx
movb %al,1(%edi)
adcl advancetable+4(,%ecx,4),%esi
 
addl tstep,%edx
sbbl %ecx,%ecx
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
 
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,2(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
 
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,3(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
 
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,4(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
 
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,5(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
 
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,6(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
 
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,7(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
 
 
//
// start FDIV for end of next segment in flight, so it can overlap
//
movl counttemp,%ecx
cmpl $16,%ecx // more than one segment after this?
ja LSetupNotLast2 // yes
 
decl %ecx
jz LFDIVInFlight2 // if only one pixel, no need to start an FDIV
movl %ecx,spancountminus1
fildl spancountminus1
 
flds C(d_zistepu) // C(d_zistepu) | spancountminus1
fmul %st(1),%st(0) // C(d_zistepu)*scm1 | scm1
flds C(d_tdivzstepu) // C(d_tdivzstepu) | C(d_zistepu)*scm1 | scm1
fmul %st(2),%st(0) // C(d_tdivzstepu)*scm1 | C(d_zistepu)*scm1 | scm1
fxch %st(1) // C(d_zistepu)*scm1 | C(d_tdivzstepu)*scm1 | scm1
faddp %st(0),%st(3) // C(d_tdivzstepu)*scm1 | scm1
fxch %st(1) // scm1 | C(d_tdivzstepu)*scm1
fmuls C(d_sdivzstepu) // C(d_sdivzstepu)*scm1 | C(d_tdivzstepu)*scm1
fxch %st(1) // C(d_tdivzstepu)*scm1 | C(d_sdivzstepu)*scm1
faddp %st(0),%st(3) // C(d_sdivzstepu)*scm1
flds fp_64k // 64k | C(d_sdivzstepu)*scm1
fxch %st(1) // C(d_sdivzstepu)*scm1 | 64k
faddp %st(0),%st(4) // 64k
 
fdiv %st(1),%st(0) // this is what we've gone to all this trouble to
// overlap
jmp LFDIVInFlight2
 
.align 4
LSetupNotLast2:
fadds zi16stepu
fxch %st(2)
fadds sdivz16stepu
fxch %st(2)
flds tdivz16stepu
faddp %st(0),%st(2)
flds fp_64k
fdiv %st(1),%st(0) // z = 1/1/z
// this is what we've gone to all this trouble to
// overlap
LFDIVInFlight2:
movl %ecx,counttemp
 
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,8(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
 
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,9(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
 
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,10(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
 
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,11(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
 
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,12(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
 
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,13(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
 
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,14(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
 
addl $16,%edi
movl %edx,tfracf
movl snext,%edx
movl %ebx,sfracf
movl tnext,%ebx
movl %edx,s
movl %ebx,t
 
movl counttemp,%ecx // retrieve count
 
//
// determine whether last span or not
//
cmpl $16,%ecx // are there multiple segments remaining?
movb %al,-1(%edi)
ja LNotLastSegment // yes
 
//
// last segment of scan
//
LLastSegment:
 
//
// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
// get there. The number of pixels left is variable, and we want to land on the
// last pixel, not step one past it, so we can't run into arithmetic problems
//
testl %ecx,%ecx
jz LNoSteps // just draw the last pixel and we're done
 
// pick up after the FDIV that was left in flight previously
 
 
fld %st(0) // duplicate it
fmul %st(4),%st(0) // s = s/z * z
fxch %st(1)
fmul %st(3),%st(0) // t = t/z * z
fxch %st(1)
fistpl snext
fistpl tnext
 
movb (%esi),%al // load first texel in segment
movl C(tadjust),%ebx
movb %al,(%edi) // store first pixel in segment
movl C(sadjust),%eax
 
addl snext,%eax
addl tnext,%ebx
 
movl C(bbextents),%ebp
movl C(bbextentt),%edx
 
cmpl $4096,%eax
jl LClampLow4
cmpl %ebp,%eax
ja LClampHigh4
LClampReentry4:
movl %eax,snext
 
cmpl $4096,%ebx
jl LClampLow5
cmpl %edx,%ebx
ja LClampHigh5
LClampReentry5:
 
cmpl $1,%ecx // don't bother
je LOnlyOneStep // if two pixels in segment, there's only one step,
// of the segment length
subl s,%eax
subl t,%ebx
 
addl %eax,%eax // convert to 15.17 format so multiply by 1.31
addl %ebx,%ebx // reciprocal yields 16.48
 
imull reciprocal_table_16-8(,%ecx,4) // sstep = (snext - s) /
// (spancount-1)
movl %edx,%ebp
 
movl %ebx,%eax
imull reciprocal_table_16-8(,%ecx,4) // tstep = (tnext - t) /
// (spancount-1)
LSetEntryvec:
//
// set up advancetable
//
movl entryvec_table_16(,%ecx,4),%ebx
movl %edx,%eax
movl %ebx,jumptemp // entry point into code for RET later
movl %ebp,%ecx
sarl $16,%edx // tstep >>= 16;
movl C(cachewidth),%ebx
sarl $16,%ecx // sstep >>= 16;
imull %ebx,%edx
 
addl %ecx,%edx // add in sstep
// (tstep >> 16) * cachewidth + (sstep >> 16);
movl tfracf,%ecx
movl %edx,advancetable+4 // advance base in t
addl %ebx,%edx // ((tstep >> 16) + 1) * cachewidth +
// (sstep >> 16);
shll $16,%ebp // left-justify sstep fractional part
movl sfracf,%ebx
shll $16,%eax // left-justify tstep fractional part
movl %edx,advancetable // advance extra in t
 
movl %eax,tstep
movl %ecx,%edx
addl %eax,%edx
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
 
jmp *jumptemp // jump to the number-of-pixels handler
 
//----------------------------------------
 
LNoSteps:
movb (%esi),%al // load first texel in segment
subl $15,%edi // adjust for hardwired offset
jmp LEndSpan
 
 
LOnlyOneStep:
subl s,%eax
subl t,%ebx
movl %eax,%ebp
movl %ebx,%edx
jmp LSetEntryvec
 
//----------------------------------------
 
.globl Entry2_16, Entry3_16, Entry4_16, Entry5_16
.globl Entry6_16, Entry7_16, Entry8_16, Entry9_16
.globl Entry10_16, Entry11_16, Entry12_16, Entry13_16
.globl Entry14_16, Entry15_16, Entry16_16
 
Entry2_16:
subl $14,%edi // adjust for hardwired offsets
movb (%esi),%al
jmp LEntry2_16
 
//----------------------------------------
 
Entry3_16:
subl $13,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
jmp LEntry3_16
 
//----------------------------------------
 
Entry4_16:
subl $12,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LEntry4_16
 
//----------------------------------------
 
Entry5_16:
subl $11,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LEntry5_16
 
//----------------------------------------
 
Entry6_16:
subl $10,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LEntry6_16
 
//----------------------------------------
 
Entry7_16:
subl $9,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LEntry7_16
 
//----------------------------------------
 
Entry8_16:
subl $8,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LEntry8_16
 
//----------------------------------------
 
Entry9_16:
subl $7,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LEntry9_16
 
//----------------------------------------
 
Entry10_16:
subl $6,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LEntry10_16
 
//----------------------------------------
 
Entry11_16:
subl $5,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LEntry11_16
 
//----------------------------------------
 
Entry12_16:
subl $4,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LEntry12_16
 
//----------------------------------------
 
Entry13_16:
subl $3,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LEntry13_16
 
//----------------------------------------
 
Entry14_16:
subl $2,%edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LEntry14_16
 
//----------------------------------------
 
Entry15_16:
decl %edi // adjust for hardwired offsets
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
jmp LEntry15_16
 
//----------------------------------------
 
Entry16_16:
addl %eax,%edx
movb (%esi),%al
sbbl %ecx,%ecx
addl %ebp,%ebx
adcl advancetable+4(,%ecx,4),%esi
 
addl tstep,%edx
sbbl %ecx,%ecx
movb %al,1(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LEntry15_16:
sbbl %ecx,%ecx
movb %al,2(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LEntry14_16:
sbbl %ecx,%ecx
movb %al,3(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LEntry13_16:
sbbl %ecx,%ecx
movb %al,4(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LEntry12_16:
sbbl %ecx,%ecx
movb %al,5(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LEntry11_16:
sbbl %ecx,%ecx
movb %al,6(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LEntry10_16:
sbbl %ecx,%ecx
movb %al,7(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LEntry9_16:
sbbl %ecx,%ecx
movb %al,8(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LEntry8_16:
sbbl %ecx,%ecx
movb %al,9(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LEntry7_16:
sbbl %ecx,%ecx
movb %al,10(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LEntry6_16:
sbbl %ecx,%ecx
movb %al,11(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LEntry5_16:
sbbl %ecx,%ecx
movb %al,12(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
addl tstep,%edx
LEntry4_16:
sbbl %ecx,%ecx
movb %al,13(%edi)
addl %ebp,%ebx
movb (%esi),%al
adcl advancetable+4(,%ecx,4),%esi
LEntry3_16:
movb %al,14(%edi)
movb (%esi),%al
LEntry2_16:
 
LEndSpan:
 
//
// clear s/z, t/z, 1/z from FP stack
//
fstp %st(0)
fstp %st(0)
fstp %st(0)
 
movl pspantemp,%ebx // restore spans pointer
movl espan_t_pnext(%ebx),%ebx // point to next span
testl %ebx,%ebx // any more spans?
movb %al,15(%edi)
jnz LSpanLoop // more spans
 
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
 
#endif // id386
/contrib/other/sdlquake-1.0.9/d_edge.c
0,0 → 1,331
/*
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.
 
*/
// d_edge.c
 
#include "quakedef.h"
#include "d_local.h"
 
static int miplevel;
 
float scale_for_mip;
int screenwidth;
int ubasestep, errorterm, erroradjustup, erroradjustdown;
int vstartscan;
 
// FIXME: should go away
extern void R_RotateBmodel (void);
extern void R_TransformFrustum (void);
 
vec3_t transformed_modelorg;
 
/*
==============
D_DrawPoly
 
==============
*/
void D_DrawPoly (void)
{
// this driver takes spans, not polygons
}
 
 
/*
=============
D_MipLevelForScale
=============
*/
int D_MipLevelForScale (float scale)
{
int lmiplevel;
 
if (scale >= d_scalemip[0] )
lmiplevel = 0;
else if (scale >= d_scalemip[1] )
lmiplevel = 1;
else if (scale >= d_scalemip[2] )
lmiplevel = 2;
else
lmiplevel = 3;
 
if (lmiplevel < d_minmip)
lmiplevel = d_minmip;
 
return lmiplevel;
}
 
 
/*
==============
D_DrawSolidSurface
==============
*/
 
// FIXME: clean this up
 
void D_DrawSolidSurface (surf_t *surf, int color)
{
espan_t *span;
byte *pdest;
int u, u2, pix;
pix = (color<<24) | (color<<16) | (color<<8) | color;
for (span=surf->spans ; span ; span=span->pnext)
{
pdest = (byte *)d_viewbuffer + screenwidth*span->v;
u = span->u;
u2 = span->u + span->count - 1;
((byte *)pdest)[u] = pix;
 
if (u2 - u < 8)
{
for (u++ ; u <= u2 ; u++)
((byte *)pdest)[u] = pix;
}
else
{
for (u++ ; u & 3 ; u++)
((byte *)pdest)[u] = pix;
 
u2 -= 4;
for ( ; u <= u2 ; u+=4)
*(int *)((byte *)pdest + u) = pix;
u2 += 4;
for ( ; u <= u2 ; u++)
((byte *)pdest)[u] = pix;
}
}
}
 
 
/*
==============
D_CalcGradients
==============
*/
void D_CalcGradients (msurface_t *pface)
{
mplane_t *pplane;
float mipscale;
vec3_t p_temp1;
vec3_t p_saxis, p_taxis;
float t;
 
pplane = pface->plane;
 
mipscale = 1.0 / (float)(1 << miplevel);
 
TransformVector (pface->texinfo->vecs[0], p_saxis);
TransformVector (pface->texinfo->vecs[1], p_taxis);
 
t = xscaleinv * mipscale;
d_sdivzstepu = p_saxis[0] * t;
d_tdivzstepu = p_taxis[0] * t;
 
t = yscaleinv * mipscale;
d_sdivzstepv = -p_saxis[1] * t;
d_tdivzstepv = -p_taxis[1] * t;
 
d_sdivzorigin = p_saxis[2] * mipscale - xcenter * d_sdivzstepu -
ycenter * d_sdivzstepv;
d_tdivzorigin = p_taxis[2] * mipscale - xcenter * d_tdivzstepu -
ycenter * d_tdivzstepv;
 
VectorScale (transformed_modelorg, mipscale, p_temp1);
 
t = 0x10000*mipscale;
sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
((pface->texturemins[0] << 16) >> miplevel)
+ pface->texinfo->vecs[0][3]*t;
tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
((pface->texturemins[1] << 16) >> miplevel)
+ pface->texinfo->vecs[1][3]*t;
 
//
// -1 (-epsilon) so we never wander off the edge of the texture
//
bbextents = ((pface->extents[0] << 16) >> miplevel) - 1;
bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1;
}
 
 
/*
==============
D_DrawSurfaces
==============
*/
void D_DrawSurfaces (void)
{
surf_t *s;
msurface_t *pface;
surfcache_t *pcurrentcache;
vec3_t world_transformed_modelorg;
vec3_t local_modelorg;
 
currententity = &cl_entities[0];
TransformVector (modelorg, transformed_modelorg);
VectorCopy (transformed_modelorg, world_transformed_modelorg);
 
// TODO: could preset a lot of this at mode set time
if (r_drawflat.value)
{
for (s = &surfaces[1] ; s<surface_p ; s++)
{
if (!s->spans)
continue;
 
d_zistepu = s->d_zistepu;
d_zistepv = s->d_zistepv;
d_ziorigin = s->d_ziorigin;
 
D_DrawSolidSurface (s, (int)s->data & 0xFF);
D_DrawZSpans (s->spans);
}
}
else
{
for (s = &surfaces[1] ; s<surface_p ; s++)
{
if (!s->spans)
continue;
 
r_drawnpolycount++;
 
d_zistepu = s->d_zistepu;
d_zistepv = s->d_zistepv;
d_ziorigin = s->d_ziorigin;
 
if (s->flags & SURF_DRAWSKY)
{
if (!r_skymade)
{
R_MakeSky ();
}
 
D_DrawSkyScans8 (s->spans);
D_DrawZSpans (s->spans);
}
else if (s->flags & SURF_DRAWBACKGROUND)
{
// set up a gradient for the background surface that places it
// effectively at infinity distance from the viewpoint
d_zistepu = 0;
d_zistepv = 0;
d_ziorigin = -0.9;
 
D_DrawSolidSurface (s, (int)r_clearcolor.value & 0xFF);
D_DrawZSpans (s->spans);
}
else if (s->flags & SURF_DRAWTURB)
{
pface = s->data;
miplevel = 0;
cacheblock = (pixel_t *)
((byte *)pface->texinfo->texture +
pface->texinfo->texture->offsets[0]);
cachewidth = 64;
 
if (s->insubmodel)
{
// FIXME: we don't want to do all this for every polygon!
// TODO: store once at start of frame
currententity = s->entity; //FIXME: make this passed in to
// R_RotateBmodel ()
VectorSubtract (r_origin, currententity->origin,
local_modelorg);
TransformVector (local_modelorg, transformed_modelorg);
 
R_RotateBmodel (); // FIXME: don't mess with the frustum,
// make entity passed in
}
 
D_CalcGradients (pface);
Turbulent8 (s->spans);
D_DrawZSpans (s->spans);
 
if (s->insubmodel)
{
//
// restore the old drawing state
// FIXME: we don't want to do this every time!
// TODO: speed up
//
currententity = &cl_entities[0];
VectorCopy (world_transformed_modelorg,
transformed_modelorg);
VectorCopy (base_vpn, vpn);
VectorCopy (base_vup, vup);
VectorCopy (base_vright, vright);
VectorCopy (base_modelorg, modelorg);
R_TransformFrustum ();
}
}
else
{
if (s->insubmodel)
{
// FIXME: we don't want to do all this for every polygon!
// TODO: store once at start of frame
currententity = s->entity; //FIXME: make this passed in to
// R_RotateBmodel ()
VectorSubtract (r_origin, currententity->origin, local_modelorg);
TransformVector (local_modelorg, transformed_modelorg);
 
R_RotateBmodel (); // FIXME: don't mess with the frustum,
// make entity passed in
}
 
pface = s->data;
miplevel = D_MipLevelForScale (s->nearzi * scale_for_mip
* pface->texinfo->mipadjust);
 
// FIXME: make this passed in to D_CacheSurface
pcurrentcache = D_CacheSurface (pface, miplevel);
 
cacheblock = (pixel_t *)pcurrentcache->data;
cachewidth = pcurrentcache->width;
 
D_CalcGradients (pface);
 
(*d_drawspans) (s->spans);
 
D_DrawZSpans (s->spans);
 
if (s->insubmodel)
{
//
// restore the old drawing state
// FIXME: we don't want to do this every time!
// TODO: speed up
//
currententity = &cl_entities[0];
VectorCopy (world_transformed_modelorg,
transformed_modelorg);
VectorCopy (base_vpn, vpn);
VectorCopy (base_vup, vup);
VectorCopy (base_vright, vright);
VectorCopy (base_modelorg, modelorg);
R_TransformFrustum ();
}
}
}
}
}
 
/contrib/other/sdlquake-1.0.9/d_fill.c
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.
 
*/
// d_clear: clears a specified rectangle to the specified color
 
#include "quakedef.h"
 
 
/*
================
D_FillRect
================
*/
void D_FillRect (vrect_t *rect, int color)
{
int rx, ry, rwidth, rheight;
unsigned char *dest;
unsigned *ldest;
 
rx = rect->x;
ry = rect->y;
rwidth = rect->width;
rheight = rect->height;
 
if (rx < 0)
{
rwidth += rx;
rx = 0;
}
if (ry < 0)
{
rheight += ry;
ry = 0;
}
if (rx+rwidth > vid.width)
rwidth = vid.width - rx;
if (ry+rheight > vid.height)
rheight = vid.height - rx;
if (rwidth < 1 || rheight < 1)
return;
 
dest = ((byte *)vid.buffer + ry*vid.rowbytes + rx);
 
if (((rwidth & 0x03) == 0) && (((long)dest & 0x03) == 0))
{
// faster aligned dword clear
ldest = (unsigned *)dest;
color += color << 16;
 
rwidth >>= 2;
color += color << 8;
 
for (ry=0 ; ry<rheight ; ry++)
{
for (rx=0 ; rx<rwidth ; rx++)
ldest[rx] = color;
ldest = (unsigned *)((byte*)ldest + vid.rowbytes);
}
}
else
{
// slower byte-by-byte clear for unaligned cases
for (ry=0 ; ry<rheight ; ry++)
{
for (rx=0 ; rx<rwidth ; rx++)
dest[rx] = color;
dest += vid.rowbytes;
}
}
}
 
/contrib/other/sdlquake-1.0.9/d_iface.h
0,0 → 1,229
/*
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.
 
*/
// d_iface.h: interface header file for rasterization driver modules
 
#define WARP_WIDTH 320
#define WARP_HEIGHT 200
 
#define MAX_LBM_HEIGHT 480
 
typedef struct
{
float u, v;
float s, t;
float zi;
} emitpoint_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;
 
#define PARTICLE_Z_CLIP 8.0
 
typedef struct polyvert_s {
float u, v, zi, s, t;
} polyvert_t;
 
typedef struct polydesc_s {
int numverts;
float nearzi;
msurface_t *pcurrentface;
polyvert_t *pverts;
} polydesc_t;
 
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
typedef struct finalvert_s {
int v[6]; // u, v, s, t, l, 1/z
int flags;
float reserved;
} finalvert_t;
 
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
typedef struct
{
void *pskin;
maliasskindesc_t *pskindesc;
int skinwidth;
int skinheight;
mtriangle_t *ptriangles;
finalvert_t *pfinalverts;
int numtriangles;
int drawtype;
int seamfixupX16;
} affinetridesc_t;
 
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
typedef struct {
float u, v, zi, color;
} screenpart_t;
 
typedef struct
{
int nump;
emitpoint_t *pverts; // there's room for an extra element at [nump],
// if the driver wants to duplicate element [0] at
// element [nump] to avoid dealing with wrapping
mspriteframe_t *pspriteframe;
vec3_t vup, vright, vpn; // in worldspace
float nearzi;
} spritedesc_t;
 
typedef struct
{
int u, v;
float zi;
int color;
} zpointdesc_t;
 
extern cvar_t r_drawflat;
extern int d_spanpixcount;
extern int r_framecount; // sequence # of current frame since Quake
// started
extern qboolean r_drawpolys; // 1 if driver wants clipped polygons
// rather than a span list
extern qboolean r_drawculledpolys; // 1 if driver wants clipped polygons that
// have been culled by the edge list
extern qboolean r_worldpolysbacktofront; // 1 if driver wants polygons
// delivered back to front rather
// than front to back
extern qboolean r_recursiveaffinetriangles; // true if a driver wants to use
// recursive triangular subdivison
// and vertex drawing via
// D_PolysetDrawFinalVerts() past
// a certain distance (normally
// only used by the software
// driver)
extern float r_aliasuvscale; // scale-up factor for screen u and v
// on Alias vertices passed to driver
extern int r_pixbytes;
extern qboolean r_dowarp;
 
extern affinetridesc_t r_affinetridesc;
extern spritedesc_t r_spritedesc;
extern zpointdesc_t r_zpointdesc;
extern polydesc_t r_polydesc;
 
extern int d_con_indirect; // if 0, Quake will draw console directly
// to vid.buffer; if 1, Quake will
// draw console via D_DrawRect. Must be
// defined by driver
 
extern vec3_t r_pright, r_pup, r_ppn;
 
 
void D_Aff8Patch (void *pcolormap);
void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height);
void D_DisableBackBufferAccess (void);
void D_EndDirectRect (int x, int y, int width, int height);
void D_PolysetDraw (void);
void D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts);
void D_DrawParticle (particle_t *pparticle);
void D_DrawPoly (void);
void D_DrawSprite (void);
void D_DrawSurfaces (void);
void D_DrawZPoint (void);
void D_EnableBackBufferAccess (void);
void D_EndParticles (void);
void D_Init (void);
void D_ViewChanged (void);
void D_SetupFrame (void);
void D_StartParticles (void);
void D_TurnZOn (void);
void D_WarpScreen (void);
 
void D_FillRect (vrect_t *vrect, int color);
void D_DrawRect (void);
void D_UpdateRects (vrect_t *prect);
 
// currently for internal use only, and should be a do-nothing function in
// hardware drivers
// FIXME: this should go away
void D_PolysetUpdateTables (void);
 
// these are currently for internal use only, and should not be used by drivers
extern int r_skydirect;
extern byte *r_skysource;
 
// transparency types for D_DrawRect ()
#define DR_SOLID 0
#define DR_TRANSPARENT 1
 
// !!! must be kept the same as in quakeasm.h !!!
#define TRANSPARENT_COLOR 0xFF
 
extern void *acolormap; // FIXME: should go away
 
//=======================================================================//
 
// callbacks to Quake
 
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;
 
extern drawsurf_t r_drawsurf;
 
void R_DrawSurface (void);
void R_GenTile (msurface_t *psurf, void *pdest);
 
 
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
#define TURB_TEX_SIZE 64 // base turbulent texture size
 
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
#define CYCLE 128 // turbulent cycle size
 
#define TILE_SIZE 128 // size of textures generated by R_GenTiledSurf
 
#define SKYSHIFT 7
#define SKYSIZE (1 << SKYSHIFT)
#define SKYMASK (SKYSIZE - 1)
 
extern float skyspeed, skyspeed2;
extern float skytime;
 
extern int c_surf;
extern vrect_t scr_vrect;
 
extern byte *r_warpbuffer;
 
/contrib/other/sdlquake-1.0.9/d_ifacea.h
0,0 → 1,98
/*
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.
 
*/
//
// d_ifacea.h
//
// Include file for asm driver interface.
//
 
//
// !!! note that this file must match the corresponding C structures in
// d_iface.h at all times !!!
//
 
// !!! if this is changed, it must be changed in r_shared.h too !!!
#define ALIAS_ONSEAM 0x0020
 
// !!! if this is changed, it must be changed in d_iface.h too !!!
#define TURB_TEX_SIZE 64 // base turbulent texture size
 
// !!! if this is changed, it must be changed in d_iface.h too !!!
#define CYCLE 128
 
// !!! if this is changed, it must be changed in r_shared.h too !!!
#define MAXHEIGHT 1024
 
// !!! if this is changed, it must be changed in quakedef.h too !!!
#define CACHE_SIZE 32 // used to align key data structures
 
// particle_t structure
// !!! if this is changed, it must be changed in d_iface.h too !!!
// driver-usable fields
#define pt_org 0
#define pt_color 12
// drivers never touch the following fields
#define pt_next 16
#define pt_vel 20
#define pt_ramp 32
#define pt_die 36
#define pt_type 40
#define pt_size 44
 
#define PARTICLE_Z_CLIP 8.0
 
// finalvert_t structure
// !!! if this is changed, it must be changed in d_iface.h too !!!
#define fv_v 0 // !!! if this is moved, cases where the !!!
// !!! address of this field is pushed in !!!
// !!! d_polysa.s must be changed !!!
#define fv_flags 24
#define fv_reserved 28
#define fv_size 32
#define fv_shift 5
 
 
// stvert_t structure
// !!! if this is changed, it must be changed in modelgen.h too !!!
#define stv_onseam 0
#define stv_s 4
#define stv_t 8
#define stv_size 12
 
 
// trivertx_t structure
// !!! if this is changed, it must be changed in modelgen.h too !!!
#define tv_v 0
#define tv_lightnormalindex 3
#define tv_size 4
 
// affinetridesc_t structure
// !!! if this is changed, it must be changed in d_iface.h too !!!
#define atd_pskin 0
#define atd_pskindesc 4
#define atd_skinwidth 8
#define atd_skinheight 12
#define atd_ptriangles 16
#define atd_pfinalverts 20
#define atd_numtriangles 24
#define atd_drawtype 28
#define atd_seamfixupX16 32
#define atd_size 36
 
/contrib/other/sdlquake-1.0.9/d_init.c
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.
 
*/
// d_init.c: rasterization driver initialization
 
#include "quakedef.h"
#include "d_local.h"
 
#define NUM_MIPS 4
 
cvar_t d_subdiv16 = {"d_subdiv16", "1"};
cvar_t d_mipcap = {"d_mipcap", "0"};
cvar_t d_mipscale = {"d_mipscale", "1"};
 
surfcache_t *d_initial_rover;
qboolean d_roverwrapped;
int d_minmip;
float d_scalemip[NUM_MIPS-1];
 
static float basemip[NUM_MIPS-1] = {1.0, 0.5*0.8, 0.25*0.8};
 
extern int d_aflatcolor;
 
void (*d_drawspans) (espan_t *pspan);
 
 
/*
===============
D_Init
===============
*/
void D_Init (void)
{
 
r_skydirect = 1;
 
Cvar_RegisterVariable (&d_subdiv16);
Cvar_RegisterVariable (&d_mipcap);
Cvar_RegisterVariable (&d_mipscale);
 
r_drawpolys = false;
r_worldpolysbacktofront = false;
r_recursiveaffinetriangles = true;
r_pixbytes = 1;
r_aliasuvscale = 1.0;
}
 
 
/*
===============
D_CopyRects
===============
*/
void D_CopyRects (vrect_t *prects, int transparent)
{
 
// this function is only required if the CPU doesn't have direct access to the
// back buffer, and there's some driver interface function that the driver
// doesn't support and requires Quake to do in software (such as drawing the
// console); Quake will then draw into wherever the driver points vid.buffer
// and will call this function before swapping buffers
 
UNUSED(prects);
UNUSED(transparent);
}
 
 
/*
===============
D_EnableBackBufferAccess
===============
*/
void D_EnableBackBufferAccess (void)
{
VID_LockBuffer ();
}
 
 
/*
===============
D_TurnZOn
===============
*/
void D_TurnZOn (void)
{
// not needed for software version
}
 
 
/*
===============
D_DisableBackBufferAccess
===============
*/
void D_DisableBackBufferAccess (void)
{
VID_UnlockBuffer ();
}
 
 
/*
===============
D_SetupFrame
===============
*/
void D_SetupFrame (void)
{
int i;
 
if (r_dowarp)
d_viewbuffer = r_warpbuffer;
else
d_viewbuffer = (void *)(byte *)vid.buffer;
 
if (r_dowarp)
screenwidth = WARP_WIDTH;
else
screenwidth = vid.rowbytes;
 
d_roverwrapped = false;
d_initial_rover = sc_rover;
 
d_minmip = d_mipcap.value;
if (d_minmip > 3)
d_minmip = 3;
else if (d_minmip < 0)
d_minmip = 0;
 
for (i=0 ; i<(NUM_MIPS-1) ; i++)
d_scalemip[i] = basemip[i] * d_mipscale.value;
 
#if id386
if (d_subdiv16.value)
d_drawspans = D_DrawSpans16;
else
d_drawspans = D_DrawSpans8;
#else
d_drawspans = D_DrawSpans8;
#endif
 
d_aflatcolor = 0;
}
 
 
/*
===============
D_UpdateRects
===============
*/
void D_UpdateRects (vrect_t *prect)
{
 
// the software driver draws these directly to the vid buffer
 
UNUSED(prect);
}
 
/contrib/other/sdlquake-1.0.9/d_local.h
0,0 → 1,111
/*
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.
 
*/
// d_local.h: private rasterization driver defs
 
#include "r_shared.h"
 
//
// TODO: fine-tune this; it's based on providing some overage even if there
// is a 2k-wide scan, with subdivision every 8, for 256 spans of 12 bytes each
//
#define SCANBUFFERPAD 0x1000
 
#define R_SKY_SMASK 0x007F0000
#define R_SKY_TMASK 0x007F0000
 
#define DS_SPAN_LIST_END -128
 
#define SURFCACHE_SIZE_AT_320X200 600*1024
 
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;
 
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct sspan_s
{
int u, v, count;
} sspan_t;
 
extern cvar_t d_subdiv16;
 
extern float scale_for_mip;
 
extern qboolean d_roverwrapped;
extern surfcache_t *sc_rover;
extern surfcache_t *d_initial_rover;
 
extern float d_sdivzstepu, d_tdivzstepu, d_zistepu;
extern float d_sdivzstepv, d_tdivzstepv, d_zistepv;
extern float d_sdivzorigin, d_tdivzorigin, d_ziorigin;
 
fixed16_t sadjust, tadjust;
fixed16_t bbextents, bbextentt;
 
 
void D_DrawSpans8 (espan_t *pspans);
void D_DrawSpans16 (espan_t *pspans);
void D_DrawZSpans (espan_t *pspans);
void Turbulent8 (espan_t *pspan);
void D_SpriteDrawSpans (sspan_t *pspan);
 
void D_DrawSkyScans8 (espan_t *pspan);
void D_DrawSkyScans16 (espan_t *pspan);
 
void R_ShowSubDiv (void);
void (*prealspandrawer)(void);
surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel);
 
extern int D_MipLevelForScale (float scale);
 
#if id386
extern void D_PolysetAff8Start (void);
extern void D_PolysetAff8End (void);
#endif
 
extern short *d_pzbuffer;
extern unsigned int d_zrowbytes, d_zwidth;
 
extern int *d_pscantable;
extern int d_scantable[MAXHEIGHT];
 
extern int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle;
 
extern int d_y_aspect_shift, d_pix_min, d_pix_max, d_pix_shift;
 
extern pixel_t *d_viewbuffer;
 
extern short *zspantable[MAXHEIGHT];
 
extern int d_minmip;
extern float d_scalemip[3];
 
extern void (*d_drawspans) (espan_t *pspan);
 
/contrib/other/sdlquake-1.0.9/d_modech.c
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.
 
*/
// d_modech.c: called when mode has just changed
 
#include "quakedef.h"
#include "d_local.h"
 
int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle;
 
int d_y_aspect_shift, d_pix_min, d_pix_max, d_pix_shift;
 
int d_scantable[MAXHEIGHT];
short *zspantable[MAXHEIGHT];
 
/*
================
D_Patch
================
*/
void D_Patch (void)
{
#if id386
 
static qboolean protectset8 = false;
 
if (!protectset8)
{
Sys_MakeCodeWriteable ((int)D_PolysetAff8Start,
(int)D_PolysetAff8End - (int)D_PolysetAff8Start);
protectset8 = true;
}
 
#endif // id386
}
 
 
/*
================
D_ViewChanged
================
*/
void D_ViewChanged (void)
{
int rowbytes;
 
if (r_dowarp)
rowbytes = WARP_WIDTH;
else
rowbytes = vid.rowbytes;
 
scale_for_mip = xscale;
if (yscale > xscale)
scale_for_mip = yscale;
 
d_zrowbytes = vid.width * 2;
d_zwidth = vid.width;
 
d_pix_min = r_refdef.vrect.width / 320;
if (d_pix_min < 1)
d_pix_min = 1;
 
d_pix_max = (int)((float)r_refdef.vrect.width / (320.0 / 4.0) + 0.5);
d_pix_shift = 8 - (int)((float)r_refdef.vrect.width / 320.0 + 0.5);
if (d_pix_max < 1)
d_pix_max = 1;
 
if (pixelAspect > 1.4)
d_y_aspect_shift = 1;
else
d_y_aspect_shift = 0;
 
d_vrectx = r_refdef.vrect.x;
d_vrecty = r_refdef.vrect.y;
d_vrectright_particle = r_refdef.vrectright - d_pix_max;
d_vrectbottom_particle =
r_refdef.vrectbottom - (d_pix_max << d_y_aspect_shift);
 
{
int i;
 
for (i=0 ; i<vid.height; i++)
{
d_scantable[i] = i*rowbytes;
zspantable[i] = d_pzbuffer + i*d_zwidth;
}
}
 
D_Patch ();
}
 
/contrib/other/sdlquake-1.0.9/d_part.c
0,0 → 1,207
/*
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.
 
*/
// d_part.c: software driver module for drawing particles
 
#include "quakedef.h"
#include "d_local.h"
 
 
/*
==============
D_EndParticles
==============
*/
void D_EndParticles (void)
{
// not used by software driver
}
 
 
/*
==============
D_StartParticles
==============
*/
void D_StartParticles (void)
{
// not used by software driver
}
 
 
#if !id386
 
/*
==============
D_DrawParticle
==============
*/
void D_DrawParticle (particle_t *pparticle)
{
vec3_t local, transformed;
float zi;
byte *pdest;
short *pz;
int i, izi, pix, count, u, v;
 
// transform point
VectorSubtract (pparticle->org, r_origin, local);
 
transformed[0] = DotProduct(local, r_pright);
transformed[1] = DotProduct(local, r_pup);
transformed[2] = DotProduct(local, r_ppn);
 
if (transformed[2] < PARTICLE_Z_CLIP)
return;
 
// project the point
// FIXME: preadjust xcenter and ycenter
zi = 1.0 / transformed[2];
u = (int)(xcenter + zi * transformed[0] + 0.5);
v = (int)(ycenter - zi * transformed[1] + 0.5);
 
if ((v > d_vrectbottom_particle) ||
(u > d_vrectright_particle) ||
(v < d_vrecty) ||
(u < d_vrectx))
{
return;
}
 
pz = d_pzbuffer + (d_zwidth * v) + u;
pdest = d_viewbuffer + d_scantable[v] + u;
izi = (int)(zi * 0x8000);
 
pix = izi >> d_pix_shift;
 
if (pix < d_pix_min)
pix = d_pix_min;
else if (pix > d_pix_max)
pix = d_pix_max;
 
switch (pix)
{
case 1:
count = 1 << d_y_aspect_shift;
 
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
{
if (pz[0] <= izi)
{
pz[0] = izi;
pdest[0] = pparticle->color;
}
}
break;
 
case 2:
count = 2 << d_y_aspect_shift;
 
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
{
if (pz[0] <= izi)
{
pz[0] = izi;
pdest[0] = pparticle->color;
}
 
if (pz[1] <= izi)
{
pz[1] = izi;
pdest[1] = pparticle->color;
}
}
break;
 
case 3:
count = 3 << d_y_aspect_shift;
 
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
{
if (pz[0] <= izi)
{
pz[0] = izi;
pdest[0] = pparticle->color;
}
 
if (pz[1] <= izi)
{
pz[1] = izi;
pdest[1] = pparticle->color;
}
 
if (pz[2] <= izi)
{
pz[2] = izi;
pdest[2] = pparticle->color;
}
}
break;
 
case 4:
count = 4 << d_y_aspect_shift;
 
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
{
if (pz[0] <= izi)
{
pz[0] = izi;
pdest[0] = pparticle->color;
}
 
if (pz[1] <= izi)
{
pz[1] = izi;
pdest[1] = pparticle->color;
}
 
if (pz[2] <= izi)
{
pz[2] = izi;
pdest[2] = pparticle->color;
}
 
if (pz[3] <= izi)
{
pz[3] = izi;
pdest[3] = pparticle->color;
}
}
break;
 
default:
count = pix << d_y_aspect_shift;
 
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
{
for (i=0 ; i<pix ; i++)
{
if (pz[i] <= izi)
{
pz[i] = izi;
pdest[i] = pparticle->color;
}
}
}
break;
}
}
 
#endif // !id386
 
/contrib/other/sdlquake-1.0.9/d_parta.S
0,0 → 1,477
/*
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.
 
*/
//
// d_parta.s
// x86 assembly-language 8-bpp particle-drawing code.
//
 
#include "asm_i386.h"
#include "quakeasm.h"
#include "d_ifacea.h"
#include "asm_draw.h"
 
#if id386
 
//----------------------------------------------------------------------
// 8-bpp particle drawing code.
//----------------------------------------------------------------------
 
//FIXME: comments, full optimization
 
//----------------------------------------------------------------------
// 8-bpp particle queueing code.
//----------------------------------------------------------------------
 
.text
 
#define P 12+4
 
.align 4
.globl C(D_DrawParticle)
C(D_DrawParticle):
pushl %ebp // preserve caller's stack frame
pushl %edi // preserve register variables
pushl %ebx
 
movl P(%esp),%edi
 
// FIXME: better FP overlap in general here
 
// transform point
// VectorSubtract (p->org, r_origin, local);
flds C(r_origin)
fsubrs pt_org(%edi)
flds pt_org+4(%edi)
fsubs C(r_origin)+4
flds pt_org+8(%edi)
fsubs C(r_origin)+8
fxch %st(2) // local[0] | local[1] | local[2]
 
// transformed[2] = DotProduct(local, r_ppn);
flds C(r_ppn) // r_ppn[0] | local[0] | local[1] | local[2]
fmul %st(1),%st(0) // dot0 | local[0] | local[1] | local[2]
flds C(r_ppn)+4 // r_ppn[1] | dot0 | local[0] | local[1] | local[2]
fmul %st(3),%st(0) // dot1 | dot0 | local[0] | local[1] | local[2]
flds C(r_ppn)+8 // r_ppn[2] | dot1 | dot0 | local[0] |
// local[1] | local[2]
fmul %st(5),%st(0) // dot2 | dot1 | dot0 | local[0] | local[1] | local[2]
fxch %st(2) // dot0 | dot1 | dot2 | local[0] | local[1] | local[2]
faddp %st(0),%st(1) // dot0 + dot1 | dot2 | local[0] | local[1] |
// local[2]
faddp %st(0),%st(1) // z | local[0] | local[1] | local[2]
fld %st(0) // z | z | local[0] | local[1] |
// local[2]
fdivrs float_1 // 1/z | z | local[0] | local[1] | local[2]
fxch %st(1) // z | 1/z | local[0] | local[1] | local[2]
 
// if (transformed[2] < PARTICLE_Z_CLIP)
// return;
fcomps float_particle_z_clip // 1/z | local[0] | local[1] | local[2]
fxch %st(3) // local[2] | local[0] | local[1] | 1/z
 
flds C(r_pup) // r_pup[0] | local[2] | local[0] | local[1] | 1/z
fmul %st(2),%st(0) // dot0 | local[2] | local[0] | local[1] | 1/z
flds C(r_pup)+4 // r_pup[1] | dot0 | local[2] | local[0] |
// local[1] | 1/z
 
fnstsw %ax
testb $1,%ah
jnz LPop6AndDone
 
// transformed[1] = DotProduct(local, r_pup);
fmul %st(4),%st(0) // dot1 | dot0 | local[2] | local[0] | local[1] | 1/z
flds C(r_pup)+8 // r_pup[2] | dot1 | dot0 | local[2] |
// local[0] | local[1] | 1/z
fmul %st(3),%st(0) // dot2 | dot1 | dot0 | local[2] | local[0] |
// local[1] | 1/z
fxch %st(2) // dot0 | dot1 | dot2 | local[2] | local[0] |
// local[1] | 1/z
faddp %st(0),%st(1) // dot0 + dot1 | dot2 | local[2] | local[0] |
// local[1] | 1/z
faddp %st(0),%st(1) // y | local[2] | local[0] | local[1] | 1/z
fxch %st(3) // local[1] | local[2] | local[0] | y | 1/z
 
// transformed[0] = DotProduct(local, r_pright);
fmuls C(r_pright)+4 // dot1 | local[2] | local[0] | y | 1/z
fxch %st(2) // local[0] | local[2] | dot1 | y | 1/z
fmuls C(r_pright) // dot0 | local[2] | dot1 | y | 1/z
fxch %st(1) // local[2] | dot0 | dot1 | y | 1/z
fmuls C(r_pright)+8 // dot2 | dot0 | dot1 | y | 1/z
fxch %st(2) // dot1 | dot0 | dot2 | y | 1/z
faddp %st(0),%st(1) // dot1 + dot0 | dot2 | y | 1/z
 
faddp %st(0),%st(1) // x | y | 1/z
fxch %st(1) // y | x | 1/z
 
// project the point
fmul %st(2),%st(0) // y/z | x | 1/z
fxch %st(1) // x | y/z | 1/z
fmul %st(2),%st(0) // x/z | y/z | 1/z
fxch %st(1) // y/z | x/z | 1/z
fsubrs C(ycenter) // v | x/z | 1/z
fxch %st(1) // x/z | v | 1/z
fadds C(xcenter) // u | v | 1/z
// FIXME: preadjust xcenter and ycenter
fxch %st(1) // v | u | 1/z
fadds float_point5 // v | u | 1/z
fxch %st(1) // u | v | 1/z
fadds float_point5 // u | v | 1/z
fxch %st(2) // 1/z | v | u
fmuls DP_32768 // 1/z * 0x8000 | v | u
fxch %st(2) // u | v | 1/z * 0x8000
 
// FIXME: use Terje's fp->int trick here?
// FIXME: check we're getting proper rounding here
fistpl DP_u // v | 1/z * 0x8000
fistpl DP_v // 1/z * 0x8000
 
movl DP_u,%eax
movl DP_v,%edx
 
// if ((v > d_vrectbottom_particle) ||
// (u > d_vrectright_particle) ||
// (v < d_vrecty) ||
// (u < d_vrectx))
// {
// continue;
// }
 
movl C(d_vrectbottom_particle),%ebx
movl C(d_vrectright_particle),%ecx
cmpl %ebx,%edx
jg LPop1AndDone
cmpl %ecx,%eax
jg LPop1AndDone
movl C(d_vrecty),%ebx
movl C(d_vrectx),%ecx
cmpl %ebx,%edx
jl LPop1AndDone
 
cmpl %ecx,%eax
jl LPop1AndDone
 
flds pt_color(%edi) // color | 1/z * 0x8000
// FIXME: use Terje's fast fp->int trick?
fistpl DP_Color // 1/z * 0x8000
 
movl C(d_viewbuffer),%ebx
 
addl %eax,%ebx
movl C(d_scantable)(,%edx,4),%edi // point to the pixel
 
imull C(d_zrowbytes),%edx // point to the z pixel
 
leal (%edx,%eax,2),%edx
movl C(d_pzbuffer),%eax
 
fistpl izi
 
addl %ebx,%edi
addl %eax,%edx
 
// pix = izi >> d_pix_shift;
 
movl izi,%eax
movl C(d_pix_shift),%ecx
shrl %cl,%eax
movl izi,%ebp
 
// if (pix < d_pix_min)
// pix = d_pix_min;
// else if (pix > d_pix_max)
// pix = d_pix_max;
 
movl C(d_pix_min),%ebx
movl C(d_pix_max),%ecx
cmpl %ebx,%eax
jnl LTestPixMax
movl %ebx,%eax
jmp LTestDone
 
LTestPixMax:
cmpl %ecx,%eax
jng LTestDone
movl %ecx,%eax
LTestDone:
 
movb DP_Color,%ch
 
movl C(d_y_aspect_shift),%ebx
testl %ebx,%ebx
jnz LDefault
 
cmpl $4,%eax
ja LDefault
 
jmp DP_EntryTable-4(,%eax,4)
 
// 1x1
.globl DP_1x1
DP_1x1:
cmpw %bp,(%edx) // just one pixel to do
jg LDone
movw %bp,(%edx)
movb %ch,(%edi)
jmp LDone
 
// 2x2
.globl DP_2x2
DP_2x2:
pushl %esi
movl C(screenwidth),%ebx
movl C(d_zrowbytes),%esi
 
cmpw %bp,(%edx)
jg L2x2_1
movw %bp,(%edx)
movb %ch,(%edi)
L2x2_1:
cmpw %bp,2(%edx)
jg L2x2_2
movw %bp,2(%edx)
movb %ch,1(%edi)
L2x2_2:
cmpw %bp,(%edx,%esi,1)
jg L2x2_3
movw %bp,(%edx,%esi,1)
movb %ch,(%edi,%ebx,1)
L2x2_3:
cmpw %bp,2(%edx,%esi,1)
jg L2x2_4
movw %bp,2(%edx,%esi,1)
movb %ch,1(%edi,%ebx,1)
L2x2_4:
 
popl %esi
jmp LDone
 
// 3x3
.globl DP_3x3
DP_3x3:
pushl %esi
movl C(screenwidth),%ebx
movl C(d_zrowbytes),%esi
 
cmpw %bp,(%edx)
jg L3x3_1
movw %bp,(%edx)
movb %ch,(%edi)
L3x3_1:
cmpw %bp,2(%edx)
jg L3x3_2
movw %bp,2(%edx)
movb %ch,1(%edi)
L3x3_2:
cmpw %bp,4(%edx)
jg L3x3_3
movw %bp,4(%edx)
movb %ch,2(%edi)
L3x3_3:
 
cmpw %bp,(%edx,%esi,1)
jg L3x3_4
movw %bp,(%edx,%esi,1)
movb %ch,(%edi,%ebx,1)
L3x3_4:
cmpw %bp,2(%edx,%esi,1)
jg L3x3_5
movw %bp,2(%edx,%esi,1)
movb %ch,1(%edi,%ebx,1)
L3x3_5:
cmpw %bp,4(%edx,%esi,1)
jg L3x3_6
movw %bp,4(%edx,%esi,1)
movb %ch,2(%edi,%ebx,1)
L3x3_6:
 
cmpw %bp,(%edx,%esi,2)
jg L3x3_7
movw %bp,(%edx,%esi,2)
movb %ch,(%edi,%ebx,2)
L3x3_7:
cmpw %bp,2(%edx,%esi,2)
jg L3x3_8
movw %bp,2(%edx,%esi,2)
movb %ch,1(%edi,%ebx,2)
L3x3_8:
cmpw %bp,4(%edx,%esi,2)
jg L3x3_9
movw %bp,4(%edx,%esi,2)
movb %ch,2(%edi,%ebx,2)
L3x3_9:
 
popl %esi
jmp LDone
 
 
// 4x4
.globl DP_4x4
DP_4x4:
pushl %esi
movl C(screenwidth),%ebx
movl C(d_zrowbytes),%esi
 
cmpw %bp,(%edx)
jg L4x4_1
movw %bp,(%edx)
movb %ch,(%edi)
L4x4_1:
cmpw %bp,2(%edx)
jg L4x4_2
movw %bp,2(%edx)
movb %ch,1(%edi)
L4x4_2:
cmpw %bp,4(%edx)
jg L4x4_3
movw %bp,4(%edx)
movb %ch,2(%edi)
L4x4_3:
cmpw %bp,6(%edx)
jg L4x4_4
movw %bp,6(%edx)
movb %ch,3(%edi)
L4x4_4:
 
cmpw %bp,(%edx,%esi,1)
jg L4x4_5
movw %bp,(%edx,%esi,1)
movb %ch,(%edi,%ebx,1)
L4x4_5:
cmpw %bp,2(%edx,%esi,1)
jg L4x4_6
movw %bp,2(%edx,%esi,1)
movb %ch,1(%edi,%ebx,1)
L4x4_6:
cmpw %bp,4(%edx,%esi,1)
jg L4x4_7
movw %bp,4(%edx,%esi,1)
movb %ch,2(%edi,%ebx,1)
L4x4_7:
cmpw %bp,6(%edx,%esi,1)
jg L4x4_8
movw %bp,6(%edx,%esi,1)
movb %ch,3(%edi,%ebx,1)
L4x4_8:
 
leal (%edx,%esi,2),%edx
leal (%edi,%ebx,2),%edi
 
cmpw %bp,(%edx)
jg L4x4_9
movw %bp,(%edx)
movb %ch,(%edi)
L4x4_9:
cmpw %bp,2(%edx)
jg L4x4_10
movw %bp,2(%edx)
movb %ch,1(%edi)
L4x4_10:
cmpw %bp,4(%edx)
jg L4x4_11
movw %bp,4(%edx)
movb %ch,2(%edi)
L4x4_11:
cmpw %bp,6(%edx)
jg L4x4_12
movw %bp,6(%edx)
movb %ch,3(%edi)
L4x4_12:
 
cmpw %bp,(%edx,%esi,1)
jg L4x4_13
movw %bp,(%edx,%esi,1)
movb %ch,(%edi,%ebx,1)
L4x4_13:
cmpw %bp,2(%edx,%esi,1)
jg L4x4_14
movw %bp,2(%edx,%esi,1)
movb %ch,1(%edi,%ebx,1)
L4x4_14:
cmpw %bp,4(%edx,%esi,1)
jg L4x4_15
movw %bp,4(%edx,%esi,1)
movb %ch,2(%edi,%ebx,1)
L4x4_15:
cmpw %bp,6(%edx,%esi,1)
jg L4x4_16
movw %bp,6(%edx,%esi,1)
movb %ch,3(%edi,%ebx,1)
L4x4_16:
 
popl %esi
jmp LDone
 
// default case, handling any size particle
LDefault:
 
// count = pix << d_y_aspect_shift;
 
movl %eax,%ebx
movl %eax,DP_Pix
movb C(d_y_aspect_shift),%cl
shll %cl,%ebx
 
// for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
// {
// for (i=0 ; i<pix ; i++)
// {
// if (pz[i] <= izi)
// {
// pz[i] = izi;
// pdest[i] = color;
// }
// }
// }
 
LGenRowLoop:
movl DP_Pix,%eax
 
LGenColLoop:
cmpw %bp,-2(%edx,%eax,2)
jg LGSkip
movw %bp,-2(%edx,%eax,2)
movb %ch,-1(%edi,%eax,1)
LGSkip:
decl %eax // --pix
jnz LGenColLoop
 
addl C(d_zrowbytes),%edx
addl C(screenwidth),%edi
 
decl %ebx // --count
jnz LGenRowLoop
 
LDone:
popl %ebx // restore register variables
popl %edi
popl %ebp // restore the caller's stack frame
ret
 
LPop6AndDone:
fstp %st(0)
fstp %st(0)
fstp %st(0)
fstp %st(0)
fstp %st(0)
LPop1AndDone:
fstp %st(0)
jmp LDone
 
#endif // id386
/contrib/other/sdlquake-1.0.9/d_polysa.S
0,0 → 1,1744
/*
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.
 
*/
//
// d_polysa.s
// x86 assembly-language polygon model drawing code
//
 
#include "asm_i386.h"
#include "quakeasm.h"
#include "asm_draw.h"
#include "d_ifacea.h"
 
#if id386
 
// !!! if this is changed, it must be changed in d_polyse.c too !!!
#define DPS_MAXSPANS MAXHEIGHT+1
// 1 extra for spanpackage that marks end
 
//#define SPAN_SIZE (((DPS_MAXSPANS + 1 + ((CACHE_SIZE - 1) / spanpackage_t_size)) + 1) * spanpackage_t_size)
#define SPAN_SIZE (1024+1+1+1)*32
 
 
.data
 
.align 4
p10_minus_p20: .single 0
p01_minus_p21: .single 0
temp0: .single 0
temp1: .single 0
Ltemp: .single 0
 
aff8entryvec_table: .long LDraw8, LDraw7, LDraw6, LDraw5
.long LDraw4, LDraw3, LDraw2, LDraw1
 
lzistepx: .long 0
 
 
.text
 
#ifndef NeXT
.extern C(D_PolysetSetEdgeTable)
.extern C(D_RasterizeAliasPolySmooth)
#endif
 
//----------------------------------------------------------------------
// affine triangle gradient calculation code
//----------------------------------------------------------------------
 
#define skinwidth 4+0
 
.globl C(D_PolysetCalcGradients)
C(D_PolysetCalcGradients):
 
// p00_minus_p20 = r_p0[0] - r_p2[0];
// p01_minus_p21 = r_p0[1] - r_p2[1];
// p10_minus_p20 = r_p1[0] - r_p2[0];
// p11_minus_p21 = r_p1[1] - r_p2[1];
//
// xstepdenominv = 1.0 / (p10_minus_p20 * p01_minus_p21 -
// p00_minus_p20 * p11_minus_p21);
//
// ystepdenominv = -xstepdenominv;
 
fildl C(r_p0)+0 // r_p0[0]
fildl C(r_p2)+0 // r_p2[0] | r_p0[0]
fildl C(r_p0)+4 // r_p0[1] | r_p2[0] | r_p0[0]
fildl C(r_p2)+4 // r_p2[1] | r_p0[1] | r_p2[0] | r_p0[0]
fildl C(r_p1)+0 // r_p1[0] | r_p2[1] | r_p0[1] | r_p2[0] | r_p0[0]
fildl C(r_p1)+4 // r_p1[1] | r_p1[0] | r_p2[1] | r_p0[1] |
// r_p2[0] | r_p0[0]
fxch %st(3) // r_p0[1] | r_p1[0] | r_p2[1] | r_p1[1] |
// r_p2[0] | r_p0[0]
fsub %st(2),%st(0) // p01_minus_p21 | r_p1[0] | r_p2[1] | r_p1[1] |
// r_p2[0] | r_p0[0]
fxch %st(1) // r_p1[0] | p01_minus_p21 | r_p2[1] | r_p1[1] |
// r_p2[0] | r_p0[0]
fsub %st(4),%st(0) // p10_minus_p20 | p01_minus_p21 | r_p2[1] |
// r_p1[1] | r_p2[0] | r_p0[0]
fxch %st(5) // r_p0[0] | p01_minus_p21 | r_p2[1] |
// r_p1[1] | r_p2[0] | p10_minus_p20
fsubp %st(0),%st(4) // p01_minus_p21 | r_p2[1] | r_p1[1] |
// p00_minus_p20 | p10_minus_p20
fxch %st(2) // r_p1[1] | r_p2[1] | p01_minus_p21 |
// p00_minus_p20 | p10_minus_p20
fsubp %st(0),%st(1) // p11_minus_p21 | p01_minus_p21 |
// p00_minus_p20 | p10_minus_p20
fxch %st(1) // p01_minus_p21 | p11_minus_p21 |
// p00_minus_p20 | p10_minus_p20
flds C(d_xdenom) // d_xdenom | p01_minus_p21 | p11_minus_p21 |
// p00_minus_p20 | p10_minus_p20
fxch %st(4) // p10_minus_p20 | p01_minus_p21 | p11_minus_p21 |
// p00_minus_p20 | d_xdenom
fstps p10_minus_p20 // p01_minus_p21 | p11_minus_p21 |
// p00_minus_p20 | d_xdenom
fstps p01_minus_p21 // p11_minus_p21 | p00_minus_p20 | xstepdenominv
fxch %st(2) // xstepdenominv | p00_minus_p20 | p11_minus_p21
 
//// ceil () for light so positive steps are exaggerated, negative steps
//// diminished, pushing us away from underflow toward overflow. Underflow is
//// very visible, overflow is very unlikely, because of ambient lighting
// t0 = r_p0[4] - r_p2[4];
// t1 = r_p1[4] - r_p2[4];
 
fildl C(r_p2)+16 // r_p2[4] | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
fildl C(r_p0)+16 // r_p0[4] | r_p2[4] | xstepdenominv |
// p00_minus_p20 | p11_minus_p21
fildl C(r_p1)+16 // r_p1[4] | r_p0[4] | r_p2[4] | xstepdenominv |
// p00_minus_p20 | p11_minus_p21
fxch %st(2) // r_p2[4] | r_p0[4] | r_p1[4] | xstepdenominv |
// p00_minus_p20 | p11_minus_p21
fld %st(0) // r_p2[4] | r_p2[4] | r_p0[4] | r_p1[4] |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fsubrp %st(0),%st(2) // r_p2[4] | t0 | r_p1[4] | xstepdenominv |
// p00_minus_p20 | p11_minus_p21
fsubrp %st(0),%st(2) // t0 | t1 | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
 
// r_lstepx = (int)
// ceil((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv);
// r_lstepy = (int)
// ceil((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv);
 
fld %st(0) // t0 | t0 | t1 | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
fmul %st(5),%st(0) // t0*p11_minus_p21 | t0 | t1 | xstepdenominv |
// p00_minus_p20 | p11_minus_p21
fxch %st(2) // t1 | t0 | t0*p11_minus_p21 | xstepdenominv |
// p00_minus_p20 | p11_minus_p21
fld %st(0) // t1 | t1 | t0 | t0*p11_minus_p21 |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fmuls p01_minus_p21 // t1*p01_minus_p21 | t1 | t0 | t0*p11_minus_p21 |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fxch %st(2) // t0 | t1 | t1*p01_minus_p21 | t0*p11_minus_p21 |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fmuls p10_minus_p20 // t0*p10_minus_p20 | t1 | t1*p01_minus_p21 |
// t0*p11_minus_p21 | xstepdenominv |
// p00_minus_p20 | p11_minus_p21
fxch %st(1) // t1 | t0*p10_minus_p20 | t1*p01_minus_p21 |
// t0*p11_minus_p21 | xstepdenominv |
// p00_minus_p20 | p11_minus_p21
fmul %st(5),%st(0) // t1*p00_minus_p20 | t0*p10_minus_p20 |
// t1*p01_minus_p21 | t0*p11_minus_p21 |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fxch %st(2) // t1*p01_minus_p21 | t0*p10_minus_p20 |
// t1*p00_minus_p20 | t0*p11_minus_p21 |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fsubp %st(0),%st(3) // t0*p10_minus_p20 | t1*p00_minus_p20 |
// t1*p01_minus_p21 - t0*p11_minus_p21 |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fsubrp %st(0),%st(1) // t1*p00_minus_p20 - t0*p10_minus_p20 |
// t1*p01_minus_p21 - t0*p11_minus_p21 |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fld %st(2) // xstepdenominv |
// t1*p00_minus_p20 - t0*p10_minus_p20 |
// t1*p01_minus_p21 - t0*p11_minus_p21 |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fmuls float_minus_1 // ystepdenominv |
// t1*p00_minus_p20 - t0*p10_minus_p20 |
// t1*p01_minus_p21 - t0*p11_minus_p21 |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fxch %st(2) // t1*p01_minus_p21 - t0*p11_minus_p21 |
// t1*p00_minus_p20 - t0*p10_minus_p20 |
// ystepdenominv | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
fmul %st(3),%st(0) // (t1*p01_minus_p21 - t0*p11_minus_p21)*
// xstepdenominv |
// t1*p00_minus_p20 - t0*p10_minus_p20 |
// | ystepdenominv | xstepdenominv |
// p00_minus_p20 | p11_minus_p21
fxch %st(1) // t1*p00_minus_p20 - t0*p10_minus_p20 |
// (t1*p01_minus_p21 - t0*p11_minus_p21)*
// xstepdenominv | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fmul %st(2),%st(0) // (t1*p00_minus_p20 - t0*p10_minus_p20)*
// ystepdenominv |
// (t1*p01_minus_p21 - t0*p11_minus_p21)*
// xstepdenominv | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fldcw ceil_cw
fistpl C(r_lstepy) // r_lstepx | ystepdenominv | xstepdenominv |
// p00_minus_p20 | p11_minus_p21
fistpl C(r_lstepx) // ystepdenominv | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
fldcw single_cw
 
// t0 = r_p0[2] - r_p2[2];
// t1 = r_p1[2] - r_p2[2];
 
fildl C(r_p2)+8 // r_p2[2] | ystepdenominv | xstepdenominv |
// p00_minus_p20 | p11_minus_p21
fildl C(r_p0)+8 // r_p0[2] | r_p2[2] | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fildl C(r_p1)+8 // r_p1[2] | r_p0[2] | r_p2[2] | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fxch %st(2) // r_p2[2] | r_p0[2] | r_p1[2] | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fld %st(0) // r_p2[2] | r_p2[2] | r_p0[2] | r_p1[2] |
// ystepdenominv | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
fsubrp %st(0),%st(2) // r_p2[2] | t0 | r_p1[2] | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fsubrp %st(0),%st(2) // t0 | t1 | ystepdenominv | xstepdenominv |
// p00_minus_p20 | p11_minus_p21
 
// r_sstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
// xstepdenominv);
// r_sstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
// ystepdenominv);
 
fld %st(0) // t0 | t0 | t1 | ystepdenominv | xstepdenominv
fmul %st(6),%st(0) // t0*p11_minus_p21 | t0 | t1 | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fxch %st(2) // t1 | t0 | t0*p11_minus_p21 | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fld %st(0) // t1 | t1 | t0 | t0*p11_minus_p21 |
// ystepdenominv | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
fmuls p01_minus_p21 // t1*p01_minus_p21 | t1 | t0 | t0*p11_minus_p21 |
// ystepdenominv | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
fxch %st(2) // t0 | t1 | t1*p01_minus_p21 | t0*p11_minus_p21 |
// ystepdenominv | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
fmuls p10_minus_p20 // t0*p10_minus_p20 | t1 | t1*p01_minus_p21 |
// t0*p11_minus_p21 | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fxch %st(1) // t1 | t0*p10_minus_p20 | t1*p01_minus_p21 |
// t0*p11_minus_p21 | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fmul %st(6),%st(0) // t1*p00_minus_p20 | t0*p10_minus_p20 |
// t1*p01_minus_p21 | t0*p11_minus_p21 |
// ystepdenominv | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
fxch %st(2) // t1*p01_minus_p21 | t0*p10_minus_p20 |
// t1*p00_minus_p20 | t0*p11_minus_p21 |
// ystepdenominv | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
fsubp %st(0),%st(3) // t0*p10_minus_p20 | t1*p00_minus_p20 |
// t1*p01_minus_p21 - t0*p11_minus_p21 |
// ystepdenominv | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
fsubrp %st(0),%st(1) // t1*p00_minus_p20 - t0*p10_minus_p20 |
// t1*p01_minus_p21 - t0*p11_minus_p21 |
// ystepdenominv | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
fmul %st(2),%st(0) // (t1*p00_minus_p20 - t0*p10_minus_p20)*
// ystepdenominv |
// t1*p01_minus_p21 - t0*p11_minus_p21 |
// ystepdenominv | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
fxch %st(1) // t1*p01_minus_p21 - t0*p11_minus_p21 |
// (t1*p00_minus_p20 - t0*p10_minus_p20)*
// ystepdenominv | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fmul %st(3),%st(0) // (t1*p01_minus_p21 - t0*p11_minus_p21)*
// xstepdenominv |
// (t1*p00_minus_p20 - t0*p10_minus_p20)*
// ystepdenominv | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fxch %st(1) // (t1*p00_minus_p20 - t0*p10_minus_p20)*
// ystepdenominv |
// (t1*p01_minus_p21 - t0*p11_minus_p21)*
// xstepdenominv | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fistpl C(r_sstepy) // r_sstepx | ystepdenominv | xstepdenominv |
// p00_minus_p20 | p11_minus_p21
fistpl C(r_sstepx) // ystepdenominv | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
 
// t0 = r_p0[3] - r_p2[3];
// t1 = r_p1[3] - r_p2[3];
 
fildl C(r_p2)+12 // r_p2[3] | ystepdenominv | xstepdenominv |
// p00_minus_p20 | p11_minus_p21
fildl C(r_p0)+12 // r_p0[3] | r_p2[3] | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fildl C(r_p1)+12 // r_p1[3] | r_p0[3] | r_p2[3] | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fxch %st(2) // r_p2[3] | r_p0[3] | r_p1[3] | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fld %st(0) // r_p2[3] | r_p2[3] | r_p0[3] | r_p1[3] |
// ystepdenominv | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
fsubrp %st(0),%st(2) // r_p2[3] | t0 | r_p1[3] | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fsubrp %st(0),%st(2) // t0 | t1 | ystepdenominv | xstepdenominv |
// p00_minus_p20 | p11_minus_p21
 
// r_tstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
// xstepdenominv);
// r_tstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
// ystepdenominv);
 
fld %st(0) // t0 | t0 | t1 | ystepdenominv | xstepdenominv |
// p00_minus_p20 | p11_minus_p21
fmul %st(6),%st(0) // t0*p11_minus_p21 | t0 | t1 | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fxch %st(2) // t1 | t0 | t0*p11_minus_p21 | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fld %st(0) // t1 | t1 | t0 | t0*p11_minus_p21 |
// ystepdenominv | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
fmuls p01_minus_p21 // t1*p01_minus_p21 | t1 | t0 | t0*p11_minus_p21 |
// ystepdenominv | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
fxch %st(2) // t0 | t1 | t1*p01_minus_p21 | t0*p11_minus_p21 |
// ystepdenominv | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
fmuls p10_minus_p20 // t0*p10_minus_p20 | t1 | t1*p01_minus_p21 |
// t0*p11_minus_p21 | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fxch %st(1) // t1 | t0*p10_minus_p20 | t1*p01_minus_p21 |
// t0*p11_minus_p21 | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fmul %st(6),%st(0) // t1*p00_minus_p20 | t0*p10_minus_p20 |
// t1*p01_minus_p21 | t0*p11_minus_p21 |
// ystepdenominv | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
fxch %st(2) // t1*p01_minus_p21 | t0*p10_minus_p20 |
// t1*p00_minus_p20 | t0*p11_minus_p21 |
// ystepdenominv | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
fsubp %st(0),%st(3) // t0*p10_minus_p20 | t1*p00_minus_p20 |
// t1*p01_minus_p21 - t0*p11_minus_p21 |
// ystepdenominv | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
fsubrp %st(0),%st(1) // t1*p00_minus_p20 - t0*p10_minus_p20 |
// t1*p01_minus_p21 - t0*p11_minus_p21 |
// ystepdenominv | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
fmul %st(2),%st(0) // (t1*p00_minus_p20 - t0*p10_minus_p20)*
// ystepdenominv |
// t1*p01_minus_p21 - t0*p11_minus_p21 |
// ystepdenominv | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
fxch %st(1) // t1*p01_minus_p21 - t0*p11_minus_p21 |
// (t1*p00_minus_p20 - t0*p10_minus_p20)*
// ystepdenominv | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fmul %st(3),%st(0) // (t1*p01_minus_p21 - t0*p11_minus_p21)*
// xstepdenominv |
// (t1*p00_minus_p20 - t0*p10_minus_p20)*
// ystepdenominv | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fxch %st(1) // (t1*p00_minus_p20 - t0*p10_minus_p20)*
// ystepdenominv |
// (t1*p01_minus_p21 - t0*p11_minus_p21)*
// xstepdenominv | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fistpl C(r_tstepy) // r_tstepx | ystepdenominv | xstepdenominv |
// p00_minus_p20 | p11_minus_p21
fistpl C(r_tstepx) // ystepdenominv | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
 
// t0 = r_p0[5] - r_p2[5];
// t1 = r_p1[5] - r_p2[5];
 
fildl C(r_p2)+20 // r_p2[5] | ystepdenominv | xstepdenominv |
// p00_minus_p20 | p11_minus_p21
fildl C(r_p0)+20 // r_p0[5] | r_p2[5] | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fildl C(r_p1)+20 // r_p1[5] | r_p0[5] | r_p2[5] | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fxch %st(2) // r_p2[5] | r_p0[5] | r_p1[5] | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fld %st(0) // r_p2[5] | r_p2[5] | r_p0[5] | r_p1[5] |
// ystepdenominv | xstepdenominv | p00_minus_p20 |
// p11_minus_p21
fsubrp %st(0),%st(2) // r_p2[5] | t0 | r_p1[5] | ystepdenominv |
// xstepdenominv | p00_minus_p20 | p11_minus_p21
fsubrp %st(0),%st(2) // t0 | t1 | ystepdenominv | xstepdenominv |
// p00_minus_p20 | p11_minus_p21
 
// r_zistepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
// xstepdenominv);
// r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
// ystepdenominv);
 
fld %st(0) // t0 | t0 | t1 | ystepdenominv | xstepdenominv |
// p00_minus_p20 | p11_minus_p21
fmulp %st(0),%st(6) // t0 | t1 | ystepdenominv | xstepdenominv |
// p00_minus_p20 | t0*p11_minus_p21
fxch %st(1) // t1 | t0 | ystepdenominv | xstepdenominv |
// p00_minus_p20 | t0*p11_minus_p21
fld %st(0) // t1 | t1 | t0 | ystepdenominv | xstepdenominv |
// p00_minus_p20 | t0*p11_minus_p21
fmuls p01_minus_p21 // t1*p01_minus_p21 | t1 | t0 | ystepdenominv |
// xstepdenominv | p00_minus_p20 |
// t0*p11_minus_p21
fxch %st(2) // t0 | t1 | t1*p01_minus_p21 | ystepdenominv |
// xstepdenominv | p00_minus_p20 |
// t0*p11_minus_p21
fmuls p10_minus_p20 // t0*p10_minus_p20 | t1 | t1*p01_minus_p21 |
// ystepdenominv | xstepdenominv | p00_minus_p20 |
// t0*p11_minus_p21
fxch %st(1) // t1 | t0*p10_minus_p20 | t1*p01_minus_p21 |
// ystepdenominv | xstepdenominv | p00_minus_p20 |
// t0*p11_minus_p21
fmulp %st(0),%st(5) // t0*p10_minus_p20 | t1*p01_minus_p21 |
// ystepdenominv | xstepdenominv |
// t1*p00_minus_p20 | t0*p11_minus_p21
fxch %st(5) // t0*p11_minus_p21 | t1*p01_minus_p21 |
// ystepdenominv | xstepdenominv |
// t1*p00_minus_p20 | t0*p10_minus_p20
fsubrp %st(0),%st(1) // t1*p01_minus_p21 - t0*p11_minus_p21 |
// ystepdenominv | xstepdenominv |
// t1*p00_minus_p20 | t0*p10_minus_p20
fxch %st(3) // t1*p00_minus_p20 | ystepdenominv |
// xstepdenominv |
// t1*p01_minus_p21 - t0*p11_minus_p21 |
// t0*p10_minus_p20
fsubp %st(0),%st(4) // ystepdenominv | xstepdenominv |
// t1*p01_minus_p21 - t0*p11_minus_p21 |
// t1*p00_minus_p20 - t0*p10_minus_p20
fxch %st(1) // xstepdenominv | ystepdenominv |
// t1*p01_minus_p21 - t0*p11_minus_p21 |
// t1*p00_minus_p20 - t0*p10_minus_p20
fmulp %st(0),%st(2) // ystepdenominv |
// (t1*p01_minus_p21 - t0*p11_minus_p21) *
// xstepdenominv |
// t1*p00_minus_p20 - t0*p10_minus_p20
fmulp %st(0),%st(2) // (t1*p01_minus_p21 - t0*p11_minus_p21) *
// xstepdenominv |
// (t1*p00_minus_p20 - t0*p10_minus_p20) *
// ystepdenominv
fistpl C(r_zistepx) // (t1*p00_minus_p20 - t0*p10_minus_p20) *
// ystepdenominv
fistpl C(r_zistepy)
 
// a_sstepxfrac = r_sstepx << 16;
// a_tstepxfrac = r_tstepx << 16;
//
// a_ststepxwhole = r_affinetridesc.skinwidth * (r_tstepx >> 16) +
// (r_sstepx >> 16);
 
movl C(r_sstepx),%eax
movl C(r_tstepx),%edx
shll $16,%eax
shll $16,%edx
movl %eax,C(a_sstepxfrac)
movl %edx,C(a_tstepxfrac)
 
movl C(r_sstepx),%ecx
movl C(r_tstepx),%eax
sarl $16,%ecx
sarl $16,%eax
imull skinwidth(%esp)
addl %ecx,%eax
movl %eax,C(a_ststepxwhole)
 
ret
 
 
//----------------------------------------------------------------------
// recursive subdivision affine triangle drawing code
//
// not C-callable because of stdcall return
//----------------------------------------------------------------------
 
#define lp1 4+16
#define lp2 8+16
#define lp3 12+16
 
.globl C(D_PolysetRecursiveTriangle)
C(D_PolysetRecursiveTriangle):
pushl %ebp // preserve caller stack frame pointer
pushl %esi // preserve register variables
pushl %edi
pushl %ebx
 
// int *temp;
// int d;
// int new[6];
// int i;
// int z;
// short *zbuf;
movl lp2(%esp),%esi
movl lp1(%esp),%ebx
movl lp3(%esp),%edi
 
// d = lp2[0] - lp1[0];
// if (d < -1 || d > 1)
// goto split;
movl 0(%esi),%eax
 
movl 0(%ebx),%edx
movl 4(%esi),%ebp
 
subl %edx,%eax
movl 4(%ebx),%ecx
 
subl %ecx,%ebp
incl %eax
 
cmpl $2,%eax
ja LSplit
 
// d = lp2[1] - lp1[1];
// if (d < -1 || d > 1)
// goto split;
movl 0(%edi),%eax
incl %ebp
 
cmpl $2,%ebp
ja LSplit
 
// d = lp3[0] - lp2[0];
// if (d < -1 || d > 1)
// goto split2;
movl 0(%esi),%edx
movl 4(%edi),%ebp
 
subl %edx,%eax
movl 4(%esi),%ecx
 
subl %ecx,%ebp
incl %eax
 
cmpl $2,%eax
ja LSplit2
 
// d = lp3[1] - lp2[1];
// if (d < -1 || d > 1)
// goto split2;
movl 0(%ebx),%eax
incl %ebp
 
cmpl $2,%ebp
ja LSplit2
 
// d = lp1[0] - lp3[0];
// if (d < -1 || d > 1)
// goto split3;
movl 0(%edi),%edx
movl 4(%ebx),%ebp
 
subl %edx,%eax
movl 4(%edi),%ecx
 
subl %ecx,%ebp
incl %eax
 
incl %ebp
movl %ebx,%edx
 
cmpl $2,%eax
ja LSplit3
 
// d = lp1[1] - lp3[1];
// if (d < -1 || d > 1)
// {
//split3:
// temp = lp1;
// lp3 = lp2;
// lp1 = lp3;
// lp2 = temp;
// goto split;
// }
//
// return; // entire tri is filled
//
cmpl $2,%ebp
jna LDone
 
LSplit3:
movl %edi,%ebx
movl %esi,%edi
movl %edx,%esi
jmp LSplit
 
//split2:
LSplit2:
 
// temp = lp1;
// lp1 = lp2;
// lp2 = lp3;
// lp3 = temp;
movl %ebx,%eax
movl %esi,%ebx
movl %edi,%esi
movl %eax,%edi
 
//split:
LSplit:
 
subl $24,%esp // allocate space for a new vertex
 
//// split this edge
// new[0] = (lp1[0] + lp2[0]) >> 1;
// new[1] = (lp1[1] + lp2[1]) >> 1;
// new[2] = (lp1[2] + lp2[2]) >> 1;
// new[3] = (lp1[3] + lp2[3]) >> 1;
// new[5] = (lp1[5] + lp2[5]) >> 1;
movl 8(%ebx),%eax
 
movl 8(%esi),%edx
movl 12(%ebx),%ecx
 
addl %edx,%eax
movl 12(%esi),%edx
 
sarl $1,%eax
addl %edx,%ecx
 
movl %eax,8(%esp)
movl 20(%ebx),%eax
 
sarl $1,%ecx
movl 20(%esi),%edx
 
movl %ecx,12(%esp)
addl %edx,%eax
 
movl 0(%ebx),%ecx
movl 0(%esi),%edx
 
sarl $1,%eax
addl %ecx,%edx
 
movl %eax,20(%esp)
movl 4(%ebx),%eax
 
sarl $1,%edx
movl 4(%esi),%ebp
 
movl %edx,0(%esp)
addl %eax,%ebp
 
sarl $1,%ebp
movl %ebp,4(%esp)
 
//// draw the point if splitting a leading edge
// if (lp2[1] > lp1[1])
// goto nodraw;
cmpl %eax,4(%esi)
jg LNoDraw
 
// if ((lp2[1] == lp1[1]) && (lp2[0] < lp1[0]))
// goto nodraw;
movl 0(%esi),%edx
jnz LDraw
 
cmpl %ecx,%edx
jl LNoDraw
 
LDraw:
 
// z = new[5] >> 16;
movl 20(%esp),%edx
movl 4(%esp),%ecx
 
sarl $16,%edx
movl 0(%esp),%ebp
 
// zbuf = zspantable[new[1]] + new[0];
movl C(zspantable)(,%ecx,4),%eax
 
// if (z >= *zbuf)
// {
cmpw (%eax,%ebp,2),%dx
jnge LNoDraw
 
// int pix;
//
// *zbuf = z;
movw %dx,(%eax,%ebp,2)
 
// pix = d_pcolormap[skintable[new[3]>>16][new[2]>>16]];
movl 12(%esp),%eax
 
sarl $16,%eax
movl 8(%esp),%edx
 
sarl $16,%edx
subl %ecx,%ecx
 
movl C(skintable)(,%eax,4),%eax
movl 4(%esp),%ebp
 
movb (%eax,%edx,),%cl
movl C(d_pcolormap),%edx
 
movb (%edx,%ecx,),%dl
movl 0(%esp),%ecx
 
// d_viewbuffer[d_scantable[new[1]] + new[0]] = pix;
movl C(d_scantable)(,%ebp,4),%eax
addl %eax,%ecx
movl C(d_viewbuffer),%eax
movb %dl,(%eax,%ecx,1)
 
// }
//
//nodraw:
LNoDraw:
 
//// recursively continue
// D_PolysetRecursiveTriangle (lp3, lp1, new);
pushl %esp
pushl %ebx
pushl %edi
call C(D_PolysetRecursiveTriangle)
 
// D_PolysetRecursiveTriangle (lp3, new, lp2);
movl %esp,%ebx
pushl %esi
pushl %ebx
pushl %edi
call C(D_PolysetRecursiveTriangle)
addl $24,%esp
 
LDone:
popl %ebx // restore register variables
popl %edi
popl %esi
popl %ebp // restore caller stack frame pointer
ret $12
 
 
//----------------------------------------------------------------------
// 8-bpp horizontal span drawing code for affine polygons, with smooth
// shading and no transparency
//----------------------------------------------------------------------
 
#define pspans 4+8
 
.globl C(D_PolysetAff8Start)
C(D_PolysetAff8Start):
 
.globl C(D_PolysetDrawSpans8)
C(D_PolysetDrawSpans8):
pushl %esi // preserve register variables
pushl %ebx
 
movl pspans(%esp),%esi // point to the first span descriptor
movl C(r_zistepx),%ecx
 
pushl %ebp // preserve caller's stack frame
pushl %edi
 
rorl $16,%ecx // put high 16 bits of 1/z step in low word
movl spanpackage_t_count(%esi),%edx
 
movl %ecx,lzistepx
 
LSpanLoop:
 
// lcount = d_aspancount - pspanpackage->count;
//
// errorterm += erroradjustup;
// if (errorterm >= 0)
// {
// d_aspancount += d_countextrastep;
// errorterm -= erroradjustdown;
// }
// else
// {
// d_aspancount += ubasestep;
// }
movl C(d_aspancount),%eax
subl %edx,%eax
 
movl C(erroradjustup),%edx
movl C(errorterm),%ebx
addl %edx,%ebx
js LNoTurnover
 
movl C(erroradjustdown),%edx
movl C(d_countextrastep),%edi
subl %edx,%ebx
movl C(d_aspancount),%ebp
movl %ebx,C(errorterm)
addl %edi,%ebp
movl %ebp,C(d_aspancount)
jmp LRightEdgeStepped
 
LNoTurnover:
movl C(d_aspancount),%edi
movl C(ubasestep),%edx
movl %ebx,C(errorterm)
addl %edx,%edi
movl %edi,C(d_aspancount)
 
LRightEdgeStepped:
cmpl $1,%eax
 
jl LNextSpan
jz LExactlyOneLong
 
//
// set up advancetable
//
movl C(a_ststepxwhole),%ecx
movl C(r_affinetridesc)+atd_skinwidth,%edx
 
movl %ecx,advancetable+4 // advance base in t
addl %edx,%ecx
 
movl %ecx,advancetable // advance extra in t
movl C(a_tstepxfrac),%ecx
 
movw C(r_lstepx),%cx
movl %eax,%edx // count
 
movl %ecx,tstep
addl $7,%edx
 
shrl $3,%edx // count of full and partial loops
movl spanpackage_t_sfrac(%esi),%ebx
 
movw %dx,%bx
movl spanpackage_t_pz(%esi),%ecx
 
negl %eax
 
movl spanpackage_t_pdest(%esi),%edi
andl $7,%eax // 0->0, 1->7, 2->6, ... , 7->1
 
subl %eax,%edi // compensate for hardwired offsets
subl %eax,%ecx
 
subl %eax,%ecx
movl spanpackage_t_tfrac(%esi),%edx
 
movw spanpackage_t_light(%esi),%dx
movl spanpackage_t_zi(%esi),%ebp
 
rorl $16,%ebp // put high 16 bits of 1/z in low word
pushl %esi
 
movl spanpackage_t_ptex(%esi),%esi
jmp aff8entryvec_table(,%eax,4)
 
// %bx = count of full and partial loops
// %ebx high word = sfrac
// %ecx = pz
// %dx = light
// %edx high word = tfrac
// %esi = ptex
// %edi = pdest
// %ebp = 1/z
// tstep low word = C(r_lstepx)
// tstep high word = C(a_tstepxfrac)
// C(a_sstepxfrac) low word = 0
// C(a_sstepxfrac) high word = C(a_sstepxfrac)
 
LDrawLoop:
 
// FIXME: do we need to clamp light? We may need at least a buffer bit to
// keep it from poking into tfrac and causing problems
 
LDraw8:
cmpw (%ecx),%bp
jl Lp1
xorl %eax,%eax
movb %dh,%ah
movb (%esi),%al
movw %bp,(%ecx)
movb 0x12345678(%eax),%al
LPatch8:
movb %al,(%edi)
Lp1:
addl tstep,%edx
sbbl %eax,%eax
addl lzistepx,%ebp
adcl $0,%ebp
addl C(a_sstepxfrac),%ebx
adcl advancetable+4(,%eax,4),%esi
 
LDraw7:
cmpw 2(%ecx),%bp
jl Lp2
xorl %eax,%eax
movb %dh,%ah
movb (%esi),%al
movw %bp,2(%ecx)
movb 0x12345678(%eax),%al
LPatch7:
movb %al,1(%edi)
Lp2:
addl tstep,%edx
sbbl %eax,%eax
addl lzistepx,%ebp
adcl $0,%ebp
addl C(a_sstepxfrac),%ebx
adcl advancetable+4(,%eax,4),%esi
 
LDraw6:
cmpw 4(%ecx),%bp
jl Lp3
xorl %eax,%eax
movb %dh,%ah
movb (%esi),%al
movw %bp,4(%ecx)
movb 0x12345678(%eax),%al
LPatch6:
movb %al,2(%edi)
Lp3:
addl tstep,%edx
sbbl %eax,%eax
addl lzistepx,%ebp
adcl $0,%ebp
addl C(a_sstepxfrac),%ebx
adcl advancetable+4(,%eax,4),%esi
 
LDraw5:
cmpw 6(%ecx),%bp
jl Lp4
xorl %eax,%eax
movb %dh,%ah
movb (%esi),%al
movw %bp,6(%ecx)
movb 0x12345678(%eax),%al
LPatch5:
movb %al,3(%edi)
Lp4:
addl tstep,%edx
sbbl %eax,%eax
addl lzistepx,%ebp
adcl $0,%ebp
addl C(a_sstepxfrac),%ebx
adcl advancetable+4(,%eax,4),%esi
 
LDraw4:
cmpw 8(%ecx),%bp
jl Lp5
xorl %eax,%eax
movb %dh,%ah
movb (%esi),%al
movw %bp,8(%ecx)
movb 0x12345678(%eax),%al
LPatch4:
movb %al,4(%edi)
Lp5:
addl tstep,%edx
sbbl %eax,%eax
addl lzistepx,%ebp
adcl $0,%ebp
addl C(a_sstepxfrac),%ebx
adcl advancetable+4(,%eax,4),%esi
 
LDraw3:
cmpw 10(%ecx),%bp
jl Lp6
xorl %eax,%eax
movb %dh,%ah
movb (%esi),%al
movw %bp,10(%ecx)
movb 0x12345678(%eax),%al
LPatch3:
movb %al,5(%edi)
Lp6:
addl tstep,%edx
sbbl %eax,%eax
addl lzistepx,%ebp
adcl $0,%ebp
addl C(a_sstepxfrac),%ebx
adcl advancetable+4(,%eax,4),%esi
 
LDraw2:
cmpw 12(%ecx),%bp
jl Lp7
xorl %eax,%eax
movb %dh,%ah
movb (%esi),%al
movw %bp,12(%ecx)
movb 0x12345678(%eax),%al
LPatch2:
movb %al,6(%edi)
Lp7:
addl tstep,%edx
sbbl %eax,%eax
addl lzistepx,%ebp
adcl $0,%ebp
addl C(a_sstepxfrac),%ebx
adcl advancetable+4(,%eax,4),%esi
 
LDraw1:
cmpw 14(%ecx),%bp
jl Lp8
xorl %eax,%eax
movb %dh,%ah
movb (%esi),%al
movw %bp,14(%ecx)
movb 0x12345678(%eax),%al
LPatch1:
movb %al,7(%edi)
Lp8:
addl tstep,%edx
sbbl %eax,%eax
addl lzistepx,%ebp
adcl $0,%ebp
addl C(a_sstepxfrac),%ebx
adcl advancetable+4(,%eax,4),%esi
 
addl $8,%edi
addl $16,%ecx
 
decw %bx
jnz LDrawLoop
 
popl %esi // restore spans pointer
LNextSpan:
addl $(spanpackage_t_size),%esi // point to next span
LNextSpanESISet:
movl spanpackage_t_count(%esi),%edx
cmpl $-999999,%edx // any more spans?
jnz LSpanLoop // yes
 
popl %edi
popl %ebp // restore the caller's stack frame
popl %ebx // restore register variables
popl %esi
ret
 
 
// draw a one-long span
 
LExactlyOneLong:
 
movl spanpackage_t_pz(%esi),%ecx
movl spanpackage_t_zi(%esi),%ebp
 
rorl $16,%ebp // put high 16 bits of 1/z in low word
movl spanpackage_t_ptex(%esi),%ebx
 
cmpw (%ecx),%bp
jl LNextSpan
xorl %eax,%eax
movl spanpackage_t_pdest(%esi),%edi
movb spanpackage_t_light+1(%esi),%ah
addl $(spanpackage_t_size),%esi // point to next span
movb (%ebx),%al
movw %bp,(%ecx)
movb 0x12345678(%eax),%al
LPatch9:
movb %al,(%edi)
 
jmp LNextSpanESISet
 
.globl C(D_PolysetAff8End)
C(D_PolysetAff8End):
 
 
#define pcolormap 4
 
.globl C(D_Aff8Patch)
C(D_Aff8Patch):
movl pcolormap(%esp),%eax
movl %eax,LPatch1-4
movl %eax,LPatch2-4
movl %eax,LPatch3-4
movl %eax,LPatch4-4
movl %eax,LPatch5-4
movl %eax,LPatch6-4
movl %eax,LPatch7-4
movl %eax,LPatch8-4
movl %eax,LPatch9-4
 
ret
 
 
//----------------------------------------------------------------------
// Alias model polygon dispatching code, combined with subdivided affine
// triangle drawing code
//----------------------------------------------------------------------
 
.globl C(D_PolysetDraw)
C(D_PolysetDraw):
 
// spanpackage_t spans[DPS_MAXSPANS + 1 +
// ((CACHE_SIZE - 1) / sizeof(spanpackage_t)) + 1];
// // one extra because of cache line pretouching
//
// a_spans = (spanpackage_t *)
// (((long)&spans[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
subl $(SPAN_SIZE),%esp
movl %esp,%eax
addl $(CACHE_SIZE - 1),%eax
andl $(~(CACHE_SIZE - 1)),%eax
movl %eax,C(a_spans)
 
// if (r_affinetridesc.drawtype)
// D_DrawSubdiv ();
// else
// D_DrawNonSubdiv ();
movl C(r_affinetridesc)+atd_drawtype,%eax
testl %eax,%eax
jz C(D_DrawNonSubdiv)
 
pushl %ebp // preserve caller stack frame pointer
 
// lnumtriangles = r_affinetridesc.numtriangles;
movl C(r_affinetridesc)+atd_numtriangles,%ebp
 
pushl %esi // preserve register variables
shll $4,%ebp
 
pushl %ebx
// ptri = r_affinetridesc.ptriangles;
movl C(r_affinetridesc)+atd_ptriangles,%ebx
 
pushl %edi
 
// mtriangle_t *ptri;
// finalvert_t *pfv, *index0, *index1, *index2;
// int i;
// int lnumtriangles;
// int s0, s1, s2;
 
// pfv = r_affinetridesc.pfinalverts;
movl C(r_affinetridesc)+atd_pfinalverts,%edi
 
// for (i=0 ; i<lnumtriangles ; i++)
// {
 
Llooptop:
 
// index0 = pfv + ptri[i].vertindex[0];
// index1 = pfv + ptri[i].vertindex[1];
// index2 = pfv + ptri[i].vertindex[2];
movl mtri_vertindex-16+0(%ebx,%ebp,),%ecx
movl mtri_vertindex-16+4(%ebx,%ebp,),%esi
 
shll $(fv_shift),%ecx
movl mtri_vertindex-16+8(%ebx,%ebp,),%edx
 
shll $(fv_shift),%esi
addl %edi,%ecx
 
shll $(fv_shift),%edx
addl %edi,%esi
 
addl %edi,%edx
 
// if (((index0->v[1]-index1->v[1]) *
// (index0->v[0]-index2->v[0]) -
// (index0->v[0]-index1->v[0])*(index0->v[1]-index2->v[1])) >= 0)
// {
// continue;
// }
//
// d_pcolormap = &((byte *)acolormap)[index0->v[4] & 0xFF00];
fildl fv_v+4(%ecx) // i0v1
fildl fv_v+4(%esi) // i1v1 | i0v1
fildl fv_v+0(%ecx) // i0v0 | i1v1 | i0v1
fildl fv_v+0(%edx) // i2v0 | i0v0 | i1v1 | i0v1
fxch %st(2) // i1v1 | i0v0 | i2v0 | i0v1
fsubr %st(3),%st(0) // i0v1-i1v1 | i0v0 | i2v0 | i0v1
fildl fv_v+0(%esi) // i1v0 | i0v1-i1v1 | i0v0 | i2v0 | i0v1
fxch %st(2) // i0v0 | i0v1-i1v1 | i1v0 | i2v0 | i0v1
fsub %st(0),%st(3) // i0v0 | i0v1-i1v1 | i1v0 | i0v0-i2v0 | i0v1
fildl fv_v+4(%edx) // i2v1 | i0v0 | i0v1-i1v1 | i1v0 | i0v0-i2v0| i0v1
fxch %st(1) // i0v0 | i2v1 | i0v1-i1v1 | i1v0 | i0v0-i2v0| i0v1
fsubp %st(0),%st(3) // i2v1 | i0v1-i1v1 | i0v0-i1v0 | i0v0-i2v0 | i0v1
fxch %st(1) // i0v1-i1v1 | i2v1 | i0v0-i1v0 | i0v0-i2v0 | i0v1
fmulp %st(0),%st(3) // i2v1 | i0v0-i1v0 | i0v1-i1v1*i0v0-i2v0 | i0v1
fsubrp %st(0),%st(3) // i0v0-i1v0 | i0v1-i1v1*i0v0-i2v0 | i0v1-i2v1
movl fv_v+16(%ecx),%eax
andl $0xFF00,%eax
fmulp %st(0),%st(2) // i0v1-i1v1*i0v0-i2v0 | i0v0-i1v0*i0v1-i2v1
addl C(acolormap),%eax
fsubp %st(0),%st(1) // (i0v1-i1v1)*(i0v0-i2v0)-(i0v0-i1v0)*(i0v1-i2v1)
movl %eax,C(d_pcolormap)
fstps Ltemp
movl Ltemp,%eax
subl $0x80000001,%eax
jc Lskip
 
// if (ptri[i].facesfront)
// {
// D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v);
movl mtri_facesfront-16(%ebx,%ebp,),%eax
testl %eax,%eax
jz Lfacesback
 
pushl %edx
pushl %esi
pushl %ecx
call C(D_PolysetRecursiveTriangle)
 
subl $16,%ebp
jnz Llooptop
jmp Ldone2
 
// }
// else
// {
Lfacesback:
 
// s0 = index0->v[2];
// s1 = index1->v[2];
// s2 = index2->v[2];
movl fv_v+8(%ecx),%eax
pushl %eax
movl fv_v+8(%esi),%eax
pushl %eax
movl fv_v+8(%edx),%eax
pushl %eax
pushl %ecx
pushl %edx
 
// if (index0->flags & ALIAS_ONSEAM)
// index0->v[2] += r_affinetridesc.seamfixupX16;
movl C(r_affinetridesc)+atd_seamfixupX16,%eax
testl $(ALIAS_ONSEAM),fv_flags(%ecx)
jz Lp11
addl %eax,fv_v+8(%ecx)
Lp11:
 
// if (index1->flags & ALIAS_ONSEAM)
// index1->v[2] += r_affinetridesc.seamfixupX16;
testl $(ALIAS_ONSEAM),fv_flags(%esi)
jz Lp12
addl %eax,fv_v+8(%esi)
Lp12:
 
// if (index2->flags & ALIAS_ONSEAM)
// index2->v[2] += r_affinetridesc.seamfixupX16;
testl $(ALIAS_ONSEAM),fv_flags(%edx)
jz Lp13
addl %eax,fv_v+8(%edx)
Lp13:
 
// D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v);
pushl %edx
pushl %esi
pushl %ecx
call C(D_PolysetRecursiveTriangle)
 
// index0->v[2] = s0;
// index1->v[2] = s1;
// index2->v[2] = s2;
popl %edx
popl %ecx
popl %eax
movl %eax,fv_v+8(%edx)
popl %eax
movl %eax,fv_v+8(%esi)
popl %eax
movl %eax,fv_v+8(%ecx)
 
// }
// }
Lskip:
subl $16,%ebp
jnz Llooptop
 
Ldone2:
popl %edi // restore the caller's stack frame
popl %ebx
popl %esi // restore register variables
popl %ebp
 
addl $(SPAN_SIZE),%esp
 
ret
 
 
//----------------------------------------------------------------------
// Alias model triangle left-edge scanning code
//----------------------------------------------------------------------
 
#define height 4+16
 
.globl C(D_PolysetScanLeftEdge)
C(D_PolysetScanLeftEdge):
pushl %ebp // preserve caller stack frame pointer
pushl %esi // preserve register variables
pushl %edi
pushl %ebx
 
movl height(%esp),%eax
movl C(d_sfrac),%ecx
andl $0xFFFF,%eax
movl C(d_ptex),%ebx
orl %eax,%ecx
movl C(d_pedgespanpackage),%esi
movl C(d_tfrac),%edx
movl C(d_light),%edi
movl C(d_zi),%ebp
 
// %eax: scratch
// %ebx: d_ptex
// %ecx: d_sfrac in high word, count in low word
// %edx: d_tfrac
// %esi: d_pedgespanpackage, errorterm, scratch alternately
// %edi: d_light
// %ebp: d_zi
 
// do
// {
 
LScanLoop:
 
// d_pedgespanpackage->ptex = ptex;
// d_pedgespanpackage->pdest = d_pdest;
// d_pedgespanpackage->pz = d_pz;
// d_pedgespanpackage->count = d_aspancount;
// d_pedgespanpackage->light = d_light;
// d_pedgespanpackage->zi = d_zi;
// d_pedgespanpackage->sfrac = d_sfrac << 16;
// d_pedgespanpackage->tfrac = d_tfrac << 16;
movl %ebx,spanpackage_t_ptex(%esi)
movl C(d_pdest),%eax
movl %eax,spanpackage_t_pdest(%esi)
movl C(d_pz),%eax
movl %eax,spanpackage_t_pz(%esi)
movl C(d_aspancount),%eax
movl %eax,spanpackage_t_count(%esi)
movl %edi,spanpackage_t_light(%esi)
movl %ebp,spanpackage_t_zi(%esi)
movl %ecx,spanpackage_t_sfrac(%esi)
movl %edx,spanpackage_t_tfrac(%esi)
 
// pretouch the next cache line
movb spanpackage_t_size(%esi),%al
 
// d_pedgespanpackage++;
addl $(spanpackage_t_size),%esi
movl C(erroradjustup),%eax
movl %esi,C(d_pedgespanpackage)
 
// errorterm += erroradjustup;
movl C(errorterm),%esi
addl %eax,%esi
movl C(d_pdest),%eax
 
// if (errorterm >= 0)
// {
js LNoLeftEdgeTurnover
 
// errorterm -= erroradjustdown;
// d_pdest += d_pdestextrastep;
subl C(erroradjustdown),%esi
addl C(d_pdestextrastep),%eax
movl %esi,C(errorterm)
movl %eax,C(d_pdest)
 
// d_pz += d_pzextrastep;
// d_aspancount += d_countextrastep;
// d_ptex += d_ptexextrastep;
// d_sfrac += d_sfracextrastep;
// d_ptex += d_sfrac >> 16;
// d_sfrac &= 0xFFFF;
// d_tfrac += d_tfracextrastep;
movl C(d_pz),%eax
movl C(d_aspancount),%esi
addl C(d_pzextrastep),%eax
addl C(d_sfracextrastep),%ecx
adcl C(d_ptexextrastep),%ebx
addl C(d_countextrastep),%esi
movl %eax,C(d_pz)
movl C(d_tfracextrastep),%eax
movl %esi,C(d_aspancount)
addl %eax,%edx
 
// if (d_tfrac & 0x10000)
// {
jnc LSkip1
 
// d_ptex += r_affinetridesc.skinwidth;
// d_tfrac &= 0xFFFF;
addl C(r_affinetridesc)+atd_skinwidth,%ebx
 
// }
 
LSkip1:
 
// d_light += d_lightextrastep;
// d_zi += d_ziextrastep;
addl C(d_lightextrastep),%edi
addl C(d_ziextrastep),%ebp
 
// }
movl C(d_pedgespanpackage),%esi
decl %ecx
testl $0xFFFF,%ecx
jnz LScanLoop
 
popl %ebx
popl %edi
popl %esi
popl %ebp
ret
 
// else
// {
 
LNoLeftEdgeTurnover:
movl %esi,C(errorterm)
 
// d_pdest += d_pdestbasestep;
addl C(d_pdestbasestep),%eax
movl %eax,C(d_pdest)
 
// d_pz += d_pzbasestep;
// d_aspancount += ubasestep;
// d_ptex += d_ptexbasestep;
// d_sfrac += d_sfracbasestep;
// d_ptex += d_sfrac >> 16;
// d_sfrac &= 0xFFFF;
movl C(d_pz),%eax
movl C(d_aspancount),%esi
addl C(d_pzbasestep),%eax
addl C(d_sfracbasestep),%ecx
adcl C(d_ptexbasestep),%ebx
addl C(ubasestep),%esi
movl %eax,C(d_pz)
movl %esi,C(d_aspancount)
 
// d_tfrac += d_tfracbasestep;
movl C(d_tfracbasestep),%esi
addl %esi,%edx
 
// if (d_tfrac & 0x10000)
// {
jnc LSkip2
 
// d_ptex += r_affinetridesc.skinwidth;
// d_tfrac &= 0xFFFF;
addl C(r_affinetridesc)+atd_skinwidth,%ebx
 
// }
 
LSkip2:
 
// d_light += d_lightbasestep;
// d_zi += d_zibasestep;
addl C(d_lightbasestep),%edi
addl C(d_zibasestep),%ebp
 
// }
// } while (--height);
movl C(d_pedgespanpackage),%esi
decl %ecx
testl $0xFFFF,%ecx
jnz LScanLoop
 
popl %ebx
popl %edi
popl %esi
popl %ebp
ret
 
 
//----------------------------------------------------------------------
// Alias model vertex drawing code
//----------------------------------------------------------------------
 
#define fv 4+8
#define numverts 8+8
 
.globl C(D_PolysetDrawFinalVerts)
C(D_PolysetDrawFinalVerts):
pushl %ebp // preserve caller stack frame pointer
pushl %ebx
 
// int i, z;
// short *zbuf;
 
movl numverts(%esp),%ecx
movl fv(%esp),%ebx
 
pushl %esi // preserve register variables
pushl %edi
 
LFVLoop:
 
// for (i=0 ; i<numverts ; i++, fv++)
// {
// // valid triangle coordinates for filling can include the bottom and
// // right clip edges, due to the fill rule; these shouldn't be drawn
// if ((fv->v[0] < r_refdef.vrectright) &&
// (fv->v[1] < r_refdef.vrectbottom))
// {
movl fv_v+0(%ebx),%eax
movl C(r_refdef)+rd_vrectright,%edx
cmpl %edx,%eax
jge LNextVert
movl fv_v+4(%ebx),%esi
movl C(r_refdef)+rd_vrectbottom,%edx
cmpl %edx,%esi
jge LNextVert
 
// zbuf = zspantable[fv->v[1]] + fv->v[0];
movl C(zspantable)(,%esi,4),%edi
 
// z = fv->v[5]>>16;
movl fv_v+20(%ebx),%edx
shrl $16,%edx
 
// if (z >= *zbuf)
// {
// int pix;
cmpw (%edi,%eax,2),%dx
jl LNextVert
 
// *zbuf = z;
movw %dx,(%edi,%eax,2)
 
// pix = skintable[fv->v[3]>>16][fv->v[2]>>16];
movl fv_v+12(%ebx),%edi
shrl $16,%edi
movl C(skintable)(,%edi,4),%edi
movl fv_v+8(%ebx),%edx
shrl $16,%edx
movb (%edi,%edx),%dl
 
// pix = ((byte *)acolormap)[pix + (fv->v[4] & 0xFF00)];
movl fv_v+16(%ebx),%edi
andl $0xFF00,%edi
andl $0x00FF,%edx
addl %edx,%edi
movl C(acolormap),%edx
movb (%edx,%edi,1),%dl
 
// d_viewbuffer[d_scantable[fv->v[1]] + fv->v[0]] = pix;
movl C(d_scantable)(,%esi,4),%edi
movl C(d_viewbuffer),%esi
addl %eax,%edi
movb %dl,(%esi,%edi)
 
// }
// }
// }
LNextVert:
addl $(fv_size),%ebx
decl %ecx
jnz LFVLoop
 
popl %edi
popl %esi
popl %ebx
popl %ebp
ret
 
 
//----------------------------------------------------------------------
// Alias model non-subdivided polygon dispatching code
//
// not C-callable because of stack buffer cleanup
//----------------------------------------------------------------------
 
.globl C(D_DrawNonSubdiv)
C(D_DrawNonSubdiv):
pushl %ebp // preserve caller stack frame pointer
movl C(r_affinetridesc)+atd_numtriangles,%ebp
pushl %ebx
shll $(mtri_shift),%ebp
pushl %esi // preserve register variables
movl C(r_affinetridesc)+atd_ptriangles,%esi
pushl %edi
 
// mtriangle_t *ptri;
// finalvert_t *pfv, *index0, *index1, *index2;
// int i;
// int lnumtriangles;
 
// pfv = r_affinetridesc.pfinalverts;
// ptri = r_affinetridesc.ptriangles;
// lnumtriangles = r_affinetridesc.numtriangles;
 
LNDLoop:
 
// for (i=0 ; i<lnumtriangles ; i++, ptri++)
// {
// index0 = pfv + ptri->vertindex[0];
// index1 = pfv + ptri->vertindex[1];
// index2 = pfv + ptri->vertindex[2];
movl C(r_affinetridesc)+atd_pfinalverts,%edi
movl mtri_vertindex+0-mtri_size(%esi,%ebp,1),%ecx
shll $(fv_shift),%ecx
movl mtri_vertindex+4-mtri_size(%esi,%ebp,1),%edx
shll $(fv_shift),%edx
movl mtri_vertindex+8-mtri_size(%esi,%ebp,1),%ebx
shll $(fv_shift),%ebx
addl %edi,%ecx
addl %edi,%edx
addl %edi,%ebx
 
// d_xdenom = (index0->v[1]-index1->v[1]) *
// (index0->v[0]-index2->v[0]) -
// (index0->v[0]-index1->v[0])*(index0->v[1]-index2->v[1]);
movl fv_v+4(%ecx),%eax
movl fv_v+0(%ecx),%esi
subl fv_v+4(%edx),%eax
subl fv_v+0(%ebx),%esi
imull %esi,%eax
movl fv_v+0(%ecx),%esi
movl fv_v+4(%ecx),%edi
subl fv_v+0(%edx),%esi
subl fv_v+4(%ebx),%edi
imull %esi,%edi
subl %edi,%eax
 
// if (d_xdenom >= 0)
// {
// continue;
jns LNextTri
 
// }
 
movl %eax,C(d_xdenom)
fildl C(d_xdenom)
 
// r_p0[0] = index0->v[0]; // u
// r_p0[1] = index0->v[1]; // v
// r_p0[2] = index0->v[2]; // s
// r_p0[3] = index0->v[3]; // t
// r_p0[4] = index0->v[4]; // light
// r_p0[5] = index0->v[5]; // iz
movl fv_v+0(%ecx),%eax
movl fv_v+4(%ecx),%esi
movl %eax,C(r_p0)+0
movl %esi,C(r_p0)+4
movl fv_v+8(%ecx),%eax
movl fv_v+12(%ecx),%esi
movl %eax,C(r_p0)+8
movl %esi,C(r_p0)+12
movl fv_v+16(%ecx),%eax
movl fv_v+20(%ecx),%esi
movl %eax,C(r_p0)+16
movl %esi,C(r_p0)+20
 
fdivrs float_1
 
// r_p1[0] = index1->v[0];
// r_p1[1] = index1->v[1];
// r_p1[2] = index1->v[2];
// r_p1[3] = index1->v[3];
// r_p1[4] = index1->v[4];
// r_p1[5] = index1->v[5];
movl fv_v+0(%edx),%eax
movl fv_v+4(%edx),%esi
movl %eax,C(r_p1)+0
movl %esi,C(r_p1)+4
movl fv_v+8(%edx),%eax
movl fv_v+12(%edx),%esi
movl %eax,C(r_p1)+8
movl %esi,C(r_p1)+12
movl fv_v+16(%edx),%eax
movl fv_v+20(%edx),%esi
movl %eax,C(r_p1)+16
movl %esi,C(r_p1)+20
 
// r_p2[0] = index2->v[0];
// r_p2[1] = index2->v[1];
// r_p2[2] = index2->v[2];
// r_p2[3] = index2->v[3];
// r_p2[4] = index2->v[4];
// r_p2[5] = index2->v[5];
movl fv_v+0(%ebx),%eax
movl fv_v+4(%ebx),%esi
movl %eax,C(r_p2)+0
movl %esi,C(r_p2)+4
movl fv_v+8(%ebx),%eax
movl fv_v+12(%ebx),%esi
movl %eax,C(r_p2)+8
movl %esi,C(r_p2)+12
movl fv_v+16(%ebx),%eax
movl fv_v+20(%ebx),%esi
movl %eax,C(r_p2)+16
movl C(r_affinetridesc)+atd_ptriangles,%edi
movl %esi,C(r_p2)+20
movl mtri_facesfront-mtri_size(%edi,%ebp,1),%eax
 
// if (!ptri->facesfront)
// {
testl %eax,%eax
jnz LFacesFront
 
// if (index0->flags & ALIAS_ONSEAM)
// r_p0[2] += r_affinetridesc.seamfixupX16;
movl fv_flags(%ecx),%eax
movl fv_flags(%edx),%esi
movl fv_flags(%ebx),%edi
testl $(ALIAS_ONSEAM),%eax
movl C(r_affinetridesc)+atd_seamfixupX16,%eax
jz LOnseamDone0
addl %eax,C(r_p0)+8
LOnseamDone0:
 
// if (index1->flags & ALIAS_ONSEAM)
// r_p1[2] += r_affinetridesc.seamfixupX16;
testl $(ALIAS_ONSEAM),%esi
jz LOnseamDone1
addl %eax,C(r_p1)+8
LOnseamDone1:
 
// if (index2->flags & ALIAS_ONSEAM)
// r_p2[2] += r_affinetridesc.seamfixupX16;
testl $(ALIAS_ONSEAM),%edi
jz LOnseamDone2
addl %eax,C(r_p2)+8
LOnseamDone2:
 
// }
 
LFacesFront:
 
fstps C(d_xdenom)
 
// D_PolysetSetEdgeTable ();
// D_RasterizeAliasPolySmooth ();
call C(D_PolysetSetEdgeTable)
call C(D_RasterizeAliasPolySmooth)
 
LNextTri:
movl C(r_affinetridesc)+atd_ptriangles,%esi
subl $16,%ebp
jnz LNDLoop
// }
 
popl %edi
popl %esi
popl %ebx
popl %ebp
 
addl $(SPAN_SIZE),%esp
 
ret
 
 
#endif // id386
 
/contrib/other/sdlquake-1.0.9/d_polyse.c
0,0 → 1,1111
/*
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.
 
*/
// d_polyset.c: routines for drawing sets of polygons sharing the same
// texture (used for Alias models)
 
#include "quakedef.h"
#include "r_local.h"
#include "d_local.h"
 
// TODO: put in span spilling to shrink list size
// !!! if this is changed, it must be changed in d_polysa.s too !!!
#define DPS_MAXSPANS MAXHEIGHT+1
// 1 extra for spanpackage that marks end
 
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct {
void *pdest;
short *pz;
int count;
byte *ptex;
int sfrac, tfrac, light, zi;
} spanpackage_t;
 
typedef struct {
int isflattop;
int numleftedges;
int *pleftedgevert0;
int *pleftedgevert1;
int *pleftedgevert2;
int numrightedges;
int *prightedgevert0;
int *prightedgevert1;
int *prightedgevert2;
} edgetable;
 
int r_p0[6], r_p1[6], r_p2[6];
 
byte *d_pcolormap;
 
int d_aflatcolor;
int d_xdenom;
 
edgetable *pedgetable;
 
edgetable edgetables[12] = {
{0, 1, r_p0, r_p2, NULL, 2, r_p0, r_p1, r_p2 },
{0, 2, r_p1, r_p0, r_p2, 1, r_p1, r_p2, NULL},
{1, 1, r_p0, r_p2, NULL, 1, r_p1, r_p2, NULL},
{0, 1, r_p1, r_p0, NULL, 2, r_p1, r_p2, r_p0 },
{0, 2, r_p0, r_p2, r_p1, 1, r_p0, r_p1, NULL},
{0, 1, r_p2, r_p1, NULL, 1, r_p2, r_p0, NULL},
{0, 1, r_p2, r_p1, NULL, 2, r_p2, r_p0, r_p1 },
{0, 2, r_p2, r_p1, r_p0, 1, r_p2, r_p0, NULL},
{0, 1, r_p1, r_p0, NULL, 1, r_p1, r_p2, NULL},
{1, 1, r_p2, r_p1, NULL, 1, r_p0, r_p1, NULL},
{1, 1, r_p1, r_p0, NULL, 1, r_p2, r_p0, NULL},
{0, 1, r_p0, r_p2, NULL, 1, r_p0, r_p1, NULL},
};
 
// FIXME: some of these can become statics
int a_sstepxfrac, a_tstepxfrac, r_lstepx, a_ststepxwhole;
int r_sstepx, r_tstepx, r_lstepy, r_sstepy, r_tstepy;
int r_zistepx, r_zistepy;
int d_aspancount, d_countextrastep;
 
spanpackage_t *a_spans;
spanpackage_t *d_pedgespanpackage;
static int ystart;
byte *d_pdest, *d_ptex;
short *d_pz;
int d_sfrac, d_tfrac, d_light, d_zi;
int d_ptexextrastep, d_sfracextrastep;
int d_tfracextrastep, d_lightextrastep, d_pdestextrastep;
int d_lightbasestep, d_pdestbasestep, d_ptexbasestep;
int d_sfracbasestep, d_tfracbasestep;
int d_ziextrastep, d_zibasestep;
int d_pzextrastep, d_pzbasestep;
 
typedef struct {
int quotient;
int remainder;
} adivtab_t;
 
static adivtab_t adivtab[32*32] = {
#include "adivtab.h"
};
 
byte *skintable[MAX_LBM_HEIGHT];
int skinwidth;
byte *skinstart;
 
void D_PolysetDrawSpans8 (spanpackage_t *pspanpackage);
void D_PolysetCalcGradients (int skinwidth);
void D_DrawSubdiv (void);
void D_DrawNonSubdiv (void);
void D_PolysetRecursiveTriangle (int *p1, int *p2, int *p3);
void D_PolysetSetEdgeTable (void);
void D_RasterizeAliasPolySmooth (void);
void D_PolysetScanLeftEdge (int height);
 
#if !id386
 
/*
================
D_PolysetDraw
================
*/
void D_PolysetDraw (void)
{
spanpackage_t spans[DPS_MAXSPANS + 1 +
((CACHE_SIZE - 1) / sizeof(spanpackage_t)) + 1];
// one extra because of cache line pretouching
 
a_spans = (spanpackage_t *)
(((long)&spans[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
 
if (r_affinetridesc.drawtype)
{
D_DrawSubdiv ();
}
else
{
D_DrawNonSubdiv ();
}
}
 
 
/*
================
D_PolysetDrawFinalVerts
================
*/
void D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts)
{
int i, z;
short *zbuf;
 
for (i=0 ; i<numverts ; i++, fv++)
{
// valid triangle coordinates for filling can include the bottom and
// right clip edges, due to the fill rule; these shouldn't be drawn
if ((fv->v[0] < r_refdef.vrectright) &&
(fv->v[1] < r_refdef.vrectbottom))
{
z = fv->v[5]>>16;
zbuf = zspantable[fv->v[1]] + fv->v[0];
if (z >= *zbuf)
{
int pix;
*zbuf = z;
pix = skintable[fv->v[3]>>16][fv->v[2]>>16];
pix = ((byte *)acolormap)[pix + (fv->v[4] & 0xFF00) ];
d_viewbuffer[d_scantable[fv->v[1]] + fv->v[0]] = pix;
}
}
}
}
 
 
/*
================
D_DrawSubdiv
================
*/
void D_DrawSubdiv (void)
{
mtriangle_t *ptri;
finalvert_t *pfv, *index0, *index1, *index2;
int i;
int lnumtriangles;
 
pfv = r_affinetridesc.pfinalverts;
ptri = r_affinetridesc.ptriangles;
lnumtriangles = r_affinetridesc.numtriangles;
 
for (i=0 ; i<lnumtriangles ; i++)
{
index0 = pfv + ptri[i].vertindex[0];
index1 = pfv + ptri[i].vertindex[1];
index2 = pfv + ptri[i].vertindex[2];
 
if (((index0->v[1]-index1->v[1]) *
(index0->v[0]-index2->v[0]) -
(index0->v[0]-index1->v[0]) *
(index0->v[1]-index2->v[1])) >= 0)
{
continue;
}
 
d_pcolormap = &((byte *)acolormap)[index0->v[4] & 0xFF00];
 
if (ptri[i].facesfront)
{
D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v);
}
else
{
int s0, s1, s2;
 
s0 = index0->v[2];
s1 = index1->v[2];
s2 = index2->v[2];
 
if (index0->flags & ALIAS_ONSEAM)
index0->v[2] += r_affinetridesc.seamfixupX16;
if (index1->flags & ALIAS_ONSEAM)
index1->v[2] += r_affinetridesc.seamfixupX16;
if (index2->flags & ALIAS_ONSEAM)
index2->v[2] += r_affinetridesc.seamfixupX16;
 
D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v);
 
index0->v[2] = s0;
index1->v[2] = s1;
index2->v[2] = s2;
}
}
}
 
 
/*
================
D_DrawNonSubdiv
================
*/
void D_DrawNonSubdiv (void)
{
mtriangle_t *ptri;
finalvert_t *pfv, *index0, *index1, *index2;
int i;
int lnumtriangles;
 
pfv = r_affinetridesc.pfinalverts;
ptri = r_affinetridesc.ptriangles;
lnumtriangles = r_affinetridesc.numtriangles;
 
for (i=0 ; i<lnumtriangles ; i++, ptri++)
{
index0 = pfv + ptri->vertindex[0];
index1 = pfv + ptri->vertindex[1];
index2 = pfv + ptri->vertindex[2];
 
d_xdenom = (index0->v[1]-index1->v[1]) *
(index0->v[0]-index2->v[0]) -
(index0->v[0]-index1->v[0])*(index0->v[1]-index2->v[1]);
 
if (d_xdenom >= 0)
{
continue;
}
 
r_p0[0] = index0->v[0]; // u
r_p0[1] = index0->v[1]; // v
r_p0[2] = index0->v[2]; // s
r_p0[3] = index0->v[3]; // t
r_p0[4] = index0->v[4]; // light
r_p0[5] = index0->v[5]; // iz
 
r_p1[0] = index1->v[0];
r_p1[1] = index1->v[1];
r_p1[2] = index1->v[2];
r_p1[3] = index1->v[3];
r_p1[4] = index1->v[4];
r_p1[5] = index1->v[5];
 
r_p2[0] = index2->v[0];
r_p2[1] = index2->v[1];
r_p2[2] = index2->v[2];
r_p2[3] = index2->v[3];
r_p2[4] = index2->v[4];
r_p2[5] = index2->v[5];
 
if (!ptri->facesfront)
{
if (index0->flags & ALIAS_ONSEAM)
r_p0[2] += r_affinetridesc.seamfixupX16;
if (index1->flags & ALIAS_ONSEAM)
r_p1[2] += r_affinetridesc.seamfixupX16;
if (index2->flags & ALIAS_ONSEAM)
r_p2[2] += r_affinetridesc.seamfixupX16;
}
 
D_PolysetSetEdgeTable ();
D_RasterizeAliasPolySmooth ();
}
}
 
 
/*
================
D_PolysetRecursiveTriangle
================
*/
void D_PolysetRecursiveTriangle (int *lp1, int *lp2, int *lp3)
{
int *temp;
int d;
int new[6];
int z;
short *zbuf;
 
d = lp2[0] - lp1[0];
if (d < -1 || d > 1)
goto split;
d = lp2[1] - lp1[1];
if (d < -1 || d > 1)
goto split;
 
d = lp3[0] - lp2[0];
if (d < -1 || d > 1)
goto split2;
d = lp3[1] - lp2[1];
if (d < -1 || d > 1)
goto split2;
 
d = lp1[0] - lp3[0];
if (d < -1 || d > 1)
goto split3;
d = lp1[1] - lp3[1];
if (d < -1 || d > 1)
{
split3:
temp = lp1;
lp1 = lp3;
lp3 = lp2;
lp2 = temp;
 
goto split;
}
 
return; // entire tri is filled
 
split2:
temp = lp1;
lp1 = lp2;
lp2 = lp3;
lp3 = temp;
 
split:
// split this edge
new[0] = (lp1[0] + lp2[0]) >> 1;
new[1] = (lp1[1] + lp2[1]) >> 1;
new[2] = (lp1[2] + lp2[2]) >> 1;
new[3] = (lp1[3] + lp2[3]) >> 1;
new[5] = (lp1[5] + lp2[5]) >> 1;
 
// draw the point if splitting a leading edge
if (lp2[1] > lp1[1])
goto nodraw;
if ((lp2[1] == lp1[1]) && (lp2[0] < lp1[0]))
goto nodraw;
 
 
z = new[5]>>16;
zbuf = zspantable[new[1]] + new[0];
if (z >= *zbuf)
{
int pix;
*zbuf = z;
pix = d_pcolormap[skintable[new[3]>>16][new[2]>>16]];
d_viewbuffer[d_scantable[new[1]] + new[0]] = pix;
}
 
nodraw:
// recursively continue
D_PolysetRecursiveTriangle (lp3, lp1, new);
D_PolysetRecursiveTriangle (lp3, new, lp2);
}
 
#endif // !id386
 
 
/*
================
D_PolysetUpdateTables
================
*/
void D_PolysetUpdateTables (void)
{
int i;
byte *s;
if (r_affinetridesc.skinwidth != skinwidth ||
r_affinetridesc.pskin != skinstart)
{
skinwidth = r_affinetridesc.skinwidth;
skinstart = r_affinetridesc.pskin;
s = skinstart;
for (i=0 ; i<MAX_LBM_HEIGHT ; i++, s+=skinwidth)
skintable[i] = s;
}
}
 
 
#if !id386
 
/*
===================
D_PolysetScanLeftEdge
====================
*/
void D_PolysetScanLeftEdge (int height)
{
 
do
{
d_pedgespanpackage->pdest = d_pdest;
d_pedgespanpackage->pz = d_pz;
d_pedgespanpackage->count = d_aspancount;
d_pedgespanpackage->ptex = d_ptex;
 
d_pedgespanpackage->sfrac = d_sfrac;
d_pedgespanpackage->tfrac = d_tfrac;
 
// FIXME: need to clamp l, s, t, at both ends?
d_pedgespanpackage->light = d_light;
d_pedgespanpackage->zi = d_zi;
 
d_pedgespanpackage++;
 
errorterm += erroradjustup;
if (errorterm >= 0)
{
d_pdest += d_pdestextrastep;
d_pz += d_pzextrastep;
d_aspancount += d_countextrastep;
d_ptex += d_ptexextrastep;
d_sfrac += d_sfracextrastep;
d_ptex += d_sfrac >> 16;
 
d_sfrac &= 0xFFFF;
d_tfrac += d_tfracextrastep;
if (d_tfrac & 0x10000)
{
d_ptex += r_affinetridesc.skinwidth;
d_tfrac &= 0xFFFF;
}
d_light += d_lightextrastep;
d_zi += d_ziextrastep;
errorterm -= erroradjustdown;
}
else
{
d_pdest += d_pdestbasestep;
d_pz += d_pzbasestep;
d_aspancount += ubasestep;
d_ptex += d_ptexbasestep;
d_sfrac += d_sfracbasestep;
d_ptex += d_sfrac >> 16;
d_sfrac &= 0xFFFF;
d_tfrac += d_tfracbasestep;
if (d_tfrac & 0x10000)
{
d_ptex += r_affinetridesc.skinwidth;
d_tfrac &= 0xFFFF;
}
d_light += d_lightbasestep;
d_zi += d_zibasestep;
}
} while (--height);
}
 
#endif // !id386
 
 
/*
===================
D_PolysetSetUpForLineScan
====================
*/
void D_PolysetSetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv,
fixed8_t endvertu, fixed8_t endvertv)
{
double dm, dn;
int tm, tn;
adivtab_t *ptemp;
 
// TODO: implement x86 version
 
errorterm = -1;
 
tm = endvertu - startvertu;
tn = endvertv - startvertv;
 
if (((tm <= 16) && (tm >= -15)) &&
((tn <= 16) && (tn >= -15)))
{
ptemp = &adivtab[((tm+15) << 5) + (tn+15)];
ubasestep = ptemp->quotient;
erroradjustup = ptemp->remainder;
erroradjustdown = tn;
}
else
{
dm = (double)tm;
dn = (double)tn;
 
FloorDivMod (dm, dn, &ubasestep, &erroradjustup);
 
erroradjustdown = dn;
}
}
 
 
#if !id386
 
/*
================
D_PolysetCalcGradients
================
*/
void D_PolysetCalcGradients (int skinwidth)
{
float xstepdenominv, ystepdenominv, t0, t1;
float p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20;
 
p00_minus_p20 = r_p0[0] - r_p2[0];
p01_minus_p21 = r_p0[1] - r_p2[1];
p10_minus_p20 = r_p1[0] - r_p2[0];
p11_minus_p21 = r_p1[1] - r_p2[1];
 
xstepdenominv = 1.0 / (float)d_xdenom;
 
ystepdenominv = -xstepdenominv;
 
// ceil () for light so positive steps are exaggerated, negative steps
// diminished, pushing us away from underflow toward overflow. Underflow is
// very visible, overflow is very unlikely, because of ambient lighting
t0 = r_p0[4] - r_p2[4];
t1 = r_p1[4] - r_p2[4];
r_lstepx = (int)
ceil((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv);
r_lstepy = (int)
ceil((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv);
 
t0 = r_p0[2] - r_p2[2];
t1 = r_p1[2] - r_p2[2];
r_sstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
xstepdenominv);
r_sstepy = (int)((t1 * p00_minus_p20 - t0* p10_minus_p20) *
ystepdenominv);
 
t0 = r_p0[3] - r_p2[3];
t1 = r_p1[3] - r_p2[3];
r_tstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
xstepdenominv);
r_tstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
ystepdenominv);
 
t0 = r_p0[5] - r_p2[5];
t1 = r_p1[5] - r_p2[5];
r_zistepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
xstepdenominv);
r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
ystepdenominv);
 
#if id386
a_sstepxfrac = r_sstepx << 16;
a_tstepxfrac = r_tstepx << 16;
#else
a_sstepxfrac = r_sstepx & 0xFFFF;
a_tstepxfrac = r_tstepx & 0xFFFF;
#endif
 
a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16);
}
 
#endif // !id386
 
 
#if 0
byte gelmap[256];
void InitGel (byte *palette)
{
int i;
int r;
 
for (i=0 ; i<256 ; i++)
{
// r = (palette[i*3]>>4);
r = (palette[i*3] + palette[i*3+1] + palette[i*3+2])/(16*3);
gelmap[i] = /* 64 */ 0 + r;
}
}
#endif
 
 
#if !id386
 
/*
================
D_PolysetDrawSpans8
================
*/
void D_PolysetDrawSpans8 (spanpackage_t *pspanpackage)
{
int lcount;
byte *lpdest;
byte *lptex;
int lsfrac, ltfrac;
int llight;
int lzi;
short *lpz;
 
do
{
lcount = d_aspancount - pspanpackage->count;
 
errorterm += erroradjustup;
if (errorterm >= 0)
{
d_aspancount += d_countextrastep;
errorterm -= erroradjustdown;
}
else
{
d_aspancount += ubasestep;
}
 
if (lcount)
{
lpdest = pspanpackage->pdest;
lptex = pspanpackage->ptex;
lpz = pspanpackage->pz;
lsfrac = pspanpackage->sfrac;
ltfrac = pspanpackage->tfrac;
llight = pspanpackage->light;
lzi = pspanpackage->zi;
 
do
{
if ((lzi >> 16) >= *lpz)
{
*lpdest = ((byte *)acolormap)[*lptex + (llight & 0xFF00)];
// gel mapping *lpdest = gelmap[*lpdest];
*lpz = lzi >> 16;
}
lpdest++;
lzi += r_zistepx;
lpz++;
llight += r_lstepx;
lptex += a_ststepxwhole;
lsfrac += a_sstepxfrac;
lptex += lsfrac >> 16;
lsfrac &= 0xFFFF;
ltfrac += a_tstepxfrac;
if (ltfrac & 0x10000)
{
lptex += r_affinetridesc.skinwidth;
ltfrac &= 0xFFFF;
}
} while (--lcount);
}
 
pspanpackage++;
} while (pspanpackage->count != -999999);
}
#endif // !id386
 
 
/*
================
D_PolysetFillSpans8
================
*/
void D_PolysetFillSpans8 (spanpackage_t *pspanpackage)
{
int color;
 
// FIXME: do z buffering
 
color = d_aflatcolor++;
 
while (1)
{
int lcount;
byte *lpdest;
 
lcount = pspanpackage->count;
 
if (lcount == -1)
return;
 
if (lcount)
{
lpdest = pspanpackage->pdest;
 
do
{
*lpdest++ = color;
} while (--lcount);
}
 
pspanpackage++;
}
}
 
/*
================
D_RasterizeAliasPolySmooth
================
*/
void D_RasterizeAliasPolySmooth (void)
{
int initialleftheight, initialrightheight;
int *plefttop, *prighttop, *pleftbottom, *prightbottom;
int working_lstepx, originalcount;
 
plefttop = pedgetable->pleftedgevert0;
prighttop = pedgetable->prightedgevert0;
 
pleftbottom = pedgetable->pleftedgevert1;
prightbottom = pedgetable->prightedgevert1;
 
initialleftheight = pleftbottom[1] - plefttop[1];
initialrightheight = prightbottom[1] - prighttop[1];
 
//
// set the s, t, and light gradients, which are consistent across the triangle
// because being a triangle, things are affine
//
D_PolysetCalcGradients (r_affinetridesc.skinwidth);
 
//
// rasterize the polygon
//
 
//
// scan out the top (and possibly only) part of the left edge
//
d_pedgespanpackage = a_spans;
 
ystart = plefttop[1];
d_aspancount = plefttop[0] - prighttop[0];
 
d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) +
(plefttop[3] >> 16) * r_affinetridesc.skinwidth;
#if id386
d_sfrac = (plefttop[2] & 0xFFFF) << 16;
d_tfrac = (plefttop[3] & 0xFFFF) << 16;
#else
d_sfrac = plefttop[2] & 0xFFFF;
d_tfrac = plefttop[3] & 0xFFFF;
#endif
d_light = plefttop[4];
d_zi = plefttop[5];
 
d_pdest = (byte *)d_viewbuffer +
ystart * screenwidth + plefttop[0];
d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0];
 
if (initialleftheight == 1)
{
d_pedgespanpackage->pdest = d_pdest;
d_pedgespanpackage->pz = d_pz;
d_pedgespanpackage->count = d_aspancount;
d_pedgespanpackage->ptex = d_ptex;
 
d_pedgespanpackage->sfrac = d_sfrac;
d_pedgespanpackage->tfrac = d_tfrac;
 
// FIXME: need to clamp l, s, t, at both ends?
d_pedgespanpackage->light = d_light;
d_pedgespanpackage->zi = d_zi;
 
d_pedgespanpackage++;
}
else
{
D_PolysetSetUpForLineScan(plefttop[0], plefttop[1],
pleftbottom[0], pleftbottom[1]);
 
#if id386
d_pzbasestep = (d_zwidth + ubasestep) << 1;
d_pzextrastep = d_pzbasestep + 2;
#else
d_pzbasestep = d_zwidth + ubasestep;
d_pzextrastep = d_pzbasestep + 1;
#endif
 
d_pdestbasestep = screenwidth + ubasestep;
d_pdestextrastep = d_pdestbasestep + 1;
 
// TODO: can reuse partial expressions here
 
// for negative steps in x along left edge, bias toward overflow rather than
// underflow (sort of turning the floor () we did in the gradient calcs into
// ceil (), but plus a little bit)
if (ubasestep < 0)
working_lstepx = r_lstepx - 1;
else
working_lstepx = r_lstepx;
 
d_countextrastep = ubasestep + 1;
d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
((r_tstepy + r_tstepx * ubasestep) >> 16) *
r_affinetridesc.skinwidth;
#if id386
d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16;
d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16;
#else
d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
#endif
d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
d_zibasestep = r_zistepy + r_zistepx * ubasestep;
 
d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
r_affinetridesc.skinwidth;
#if id386
d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) << 16;
d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) << 16;
#else
d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) & 0xFFFF;
d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) & 0xFFFF;
#endif
d_lightextrastep = d_lightbasestep + working_lstepx;
d_ziextrastep = d_zibasestep + r_zistepx;
 
D_PolysetScanLeftEdge (initialleftheight);
}
 
//
// scan out the bottom part of the left edge, if it exists
//
if (pedgetable->numleftedges == 2)
{
int height;
 
plefttop = pleftbottom;
pleftbottom = pedgetable->pleftedgevert2;
 
height = pleftbottom[1] - plefttop[1];
 
// TODO: make this a function; modularize this function in general
 
ystart = plefttop[1];
d_aspancount = plefttop[0] - prighttop[0];
d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) +
(plefttop[3] >> 16) * r_affinetridesc.skinwidth;
d_sfrac = 0;
d_tfrac = 0;
d_light = plefttop[4];
d_zi = plefttop[5];
 
d_pdest = (byte *)d_viewbuffer + ystart * screenwidth + plefttop[0];
d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0];
 
if (height == 1)
{
d_pedgespanpackage->pdest = d_pdest;
d_pedgespanpackage->pz = d_pz;
d_pedgespanpackage->count = d_aspancount;
d_pedgespanpackage->ptex = d_ptex;
 
d_pedgespanpackage->sfrac = d_sfrac;
d_pedgespanpackage->tfrac = d_tfrac;
 
// FIXME: need to clamp l, s, t, at both ends?
d_pedgespanpackage->light = d_light;
d_pedgespanpackage->zi = d_zi;
 
d_pedgespanpackage++;
}
else
{
D_PolysetSetUpForLineScan(plefttop[0], plefttop[1],
pleftbottom[0], pleftbottom[1]);
 
d_pdestbasestep = screenwidth + ubasestep;
d_pdestextrastep = d_pdestbasestep + 1;
 
#if id386
d_pzbasestep = (d_zwidth + ubasestep) << 1;
d_pzextrastep = d_pzbasestep + 2;
#else
d_pzbasestep = d_zwidth + ubasestep;
d_pzextrastep = d_pzbasestep + 1;
#endif
 
if (ubasestep < 0)
working_lstepx = r_lstepx - 1;
else
working_lstepx = r_lstepx;
 
d_countextrastep = ubasestep + 1;
d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
((r_tstepy + r_tstepx * ubasestep) >> 16) *
r_affinetridesc.skinwidth;
#if id386
d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16;
d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16;
#else
d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
#endif
d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
d_zibasestep = r_zistepy + r_zistepx * ubasestep;
 
d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
r_affinetridesc.skinwidth;
#if id386
d_sfracextrastep = ((r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF)<<16;
d_tfracextrastep = ((r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF)<<16;
#else
d_sfracextrastep = (r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF;
d_tfracextrastep = (r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF;
#endif
d_lightextrastep = d_lightbasestep + working_lstepx;
d_ziextrastep = d_zibasestep + r_zistepx;
 
D_PolysetScanLeftEdge (height);
}
}
 
// scan out the top (and possibly only) part of the right edge, updating the
// count field
d_pedgespanpackage = a_spans;
 
D_PolysetSetUpForLineScan(prighttop[0], prighttop[1],
prightbottom[0], prightbottom[1]);
d_aspancount = 0;
d_countextrastep = ubasestep + 1;
originalcount = a_spans[initialrightheight].count;
a_spans[initialrightheight].count = -999999; // mark end of the spanpackages
D_PolysetDrawSpans8 (a_spans);
 
// scan out the bottom part of the right edge, if it exists
if (pedgetable->numrightedges == 2)
{
int height;
spanpackage_t *pstart;
 
pstart = a_spans + initialrightheight;
pstart->count = originalcount;
 
d_aspancount = prightbottom[0] - prighttop[0];
 
prighttop = prightbottom;
prightbottom = pedgetable->prightedgevert2;
 
height = prightbottom[1] - prighttop[1];
 
D_PolysetSetUpForLineScan(prighttop[0], prighttop[1],
prightbottom[0], prightbottom[1]);
 
d_countextrastep = ubasestep + 1;
a_spans[initialrightheight + height].count = -999999;
// mark end of the spanpackages
D_PolysetDrawSpans8 (pstart);
}
}
 
 
/*
================
D_PolysetSetEdgeTable
================
*/
void D_PolysetSetEdgeTable (void)
{
int edgetableindex;
 
edgetableindex = 0; // assume the vertices are already in
// top to bottom order
 
//
// determine which edges are right & left, and the order in which
// to rasterize them
//
if (r_p0[1] >= r_p1[1])
{
if (r_p0[1] == r_p1[1])
{
if (r_p0[1] < r_p2[1])
pedgetable = &edgetables[2];
else
pedgetable = &edgetables[5];
 
return;
}
else
{
edgetableindex = 1;
}
}
 
if (r_p0[1] == r_p2[1])
{
if (edgetableindex)
pedgetable = &edgetables[8];
else
pedgetable = &edgetables[9];
 
return;
}
else if (r_p1[1] == r_p2[1])
{
if (edgetableindex)
pedgetable = &edgetables[10];
else
pedgetable = &edgetables[11];
 
return;
}
 
if (r_p0[1] > r_p2[1])
edgetableindex += 2;
 
if (r_p1[1] > r_p2[1])
edgetableindex += 4;
 
pedgetable = &edgetables[edgetableindex];
}
 
 
#if 0
 
void D_PolysetRecursiveDrawLine (int *lp1, int *lp2)
{
int d;
int new[6];
int ofs;
d = lp2[0] - lp1[0];
if (d < -1 || d > 1)
goto split;
d = lp2[1] - lp1[1];
if (d < -1 || d > 1)
goto split;
 
return; // line is completed
 
split:
// split this edge
new[0] = (lp1[0] + lp2[0]) >> 1;
new[1] = (lp1[1] + lp2[1]) >> 1;
new[5] = (lp1[5] + lp2[5]) >> 1;
new[2] = (lp1[2] + lp2[2]) >> 1;
new[3] = (lp1[3] + lp2[3]) >> 1;
new[4] = (lp1[4] + lp2[4]) >> 1;
 
// draw the point
ofs = d_scantable[new[1]] + new[0];
if (new[5] > d_pzbuffer[ofs])
{
int pix;
d_pzbuffer[ofs] = new[5];
pix = skintable[new[3]>>16][new[2]>>16];
// pix = ((byte *)acolormap)[pix + (new[4] & 0xFF00)];
d_viewbuffer[ofs] = pix;
}
 
// recursively continue
D_PolysetRecursiveDrawLine (lp1, new);
D_PolysetRecursiveDrawLine (new, lp2);
}
 
void D_PolysetRecursiveTriangle2 (int *lp1, int *lp2, int *lp3)
{
int d;
int new[4];
d = lp2[0] - lp1[0];
if (d < -1 || d > 1)
goto split;
d = lp2[1] - lp1[1];
if (d < -1 || d > 1)
goto split;
return;
 
split:
// split this edge
new[0] = (lp1[0] + lp2[0]) >> 1;
new[1] = (lp1[1] + lp2[1]) >> 1;
new[5] = (lp1[5] + lp2[5]) >> 1;
new[2] = (lp1[2] + lp2[2]) >> 1;
new[3] = (lp1[3] + lp2[3]) >> 1;
new[4] = (lp1[4] + lp2[4]) >> 1;
 
D_PolysetRecursiveDrawLine (new, lp3);
 
// recursively continue
D_PolysetRecursiveTriangle (lp1, new, lp3);
D_PolysetRecursiveTriangle (new, lp2, lp3);
}
 
#endif
 
/contrib/other/sdlquake-1.0.9/d_scan.c
0,0 → 1,449
/*
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.
 
*/
// d_scan.c
//
// Portable C scan-level rasterization code, all pixel depths.
 
#include "quakedef.h"
#include "r_local.h"
#include "d_local.h"
 
unsigned char *r_turb_pbase, *r_turb_pdest;
fixed16_t r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep;
int *r_turb_turb;
int r_turb_spancount;
 
void D_DrawTurbulent8Span (void);
 
 
/*
=============
D_WarpScreen
 
// this performs a slight compression of the screen at the same time as
// the sine warp, to keep the edges from wrapping
=============
*/
void D_WarpScreen (void)
{
int w, h;
int u,v;
byte *dest;
int *turb;
int *col;
byte **row;
byte *rowptr[MAXHEIGHT+(AMP2*2)];
int column[MAXWIDTH+(AMP2*2)];
float wratio, hratio;
 
w = r_refdef.vrect.width;
h = r_refdef.vrect.height;
 
wratio = w / (float)scr_vrect.width;
hratio = h / (float)scr_vrect.height;
 
for (v=0 ; v<scr_vrect.height+AMP2*2 ; v++)
{
rowptr[v] = d_viewbuffer + (r_refdef.vrect.y * screenwidth) +
(screenwidth * (int)((float)v * hratio * h / (h + AMP2 * 2)));
}
 
for (u=0 ; u<scr_vrect.width+AMP2*2 ; u++)
{
column[u] = r_refdef.vrect.x +
(int)((float)u * wratio * w / (w + AMP2 * 2));
}
 
turb = intsintable + ((int)(cl.time*SPEED)&(CYCLE-1));
dest = vid.buffer + scr_vrect.y * vid.rowbytes + scr_vrect.x;
 
for (v=0 ; v<scr_vrect.height ; v++, dest += vid.rowbytes)
{
col = &column[turb[v]];
row = &rowptr[v];
 
for (u=0 ; u<scr_vrect.width ; u+=4)
{
dest[u+0] = row[turb[u+0]][col[u+0]];
dest[u+1] = row[turb[u+1]][col[u+1]];
dest[u+2] = row[turb[u+2]][col[u+2]];
dest[u+3] = row[turb[u+3]][col[u+3]];
}
}
}
 
 
#if !id386
 
/*
=============
D_DrawTurbulent8Span
=============
*/
void D_DrawTurbulent8Span (void)
{
int sturb, tturb;
 
do
{
sturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)])>>16)&63;
tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63;
*r_turb_pdest++ = *(r_turb_pbase + (tturb<<6) + sturb);
r_turb_s += r_turb_sstep;
r_turb_t += r_turb_tstep;
} while (--r_turb_spancount > 0);
}
 
#endif // !id386
 
 
/*
=============
Turbulent8
=============
*/
void Turbulent8 (espan_t *pspan)
{
int count;
fixed16_t snext, tnext;
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
float sdivz16stepu, tdivz16stepu, zi16stepu;
r_turb_turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
 
r_turb_sstep = 0; // keep compiler happy
r_turb_tstep = 0; // ditto
 
r_turb_pbase = (unsigned char *)cacheblock;
 
sdivz16stepu = d_sdivzstepu * 16;
tdivz16stepu = d_tdivzstepu * 16;
zi16stepu = d_zistepu * 16;
 
do
{
r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer +
(screenwidth * pspan->v) + pspan->u);
 
count = pspan->count;
 
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float)pspan->u;
dv = (float)pspan->v;
 
sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
 
r_turb_s = (int)(sdivz * z) + sadjust;
if (r_turb_s > bbextents)
r_turb_s = bbextents;
else if (r_turb_s < 0)
r_turb_s = 0;
 
r_turb_t = (int)(tdivz * z) + tadjust;
if (r_turb_t > bbextentt)
r_turb_t = bbextentt;
else if (r_turb_t < 0)
r_turb_t = 0;
 
do
{
// calculate s and t at the far end of the span
if (count >= 16)
r_turb_spancount = 16;
else
r_turb_spancount = count;
 
count -= r_turb_spancount;
 
if (count)
{
// calculate s/z, t/z, zi->fixed s and t at far end of span,
// calculate s and t steps across span by shifting
sdivz += sdivz16stepu;
tdivz += tdivz16stepu;
zi += zi16stepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
 
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 16)
snext = 16; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
 
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 16)
tnext = 16; // guard against round-off error on <0 steps
 
r_turb_sstep = (snext - r_turb_s) >> 4;
r_turb_tstep = (tnext - r_turb_t) >> 4;
}
else
{
// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
// can't step off polygon), clamp, calculate s and t steps across
// span by division, biasing steps low so we don't run off the
// texture
spancountminus1 = (float)(r_turb_spancount - 1);
sdivz += d_sdivzstepu * spancountminus1;
tdivz += d_tdivzstepu * spancountminus1;
zi += d_zistepu * spancountminus1;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 16)
snext = 16; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
 
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 16)
tnext = 16; // guard against round-off error on <0 steps
 
if (r_turb_spancount > 1)
{
r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1);
r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1);
}
}
 
r_turb_s = r_turb_s & ((CYCLE<<16)-1);
r_turb_t = r_turb_t & ((CYCLE<<16)-1);
 
D_DrawTurbulent8Span ();
 
r_turb_s = snext;
r_turb_t = tnext;
 
} while (count > 0);
 
} while ((pspan = pspan->pnext) != NULL);
}
 
 
#if !id386
 
/*
=============
D_DrawSpans8
=============
*/
void D_DrawSpans8 (espan_t *pspan)
{
int count, spancount;
unsigned char *pbase, *pdest;
fixed16_t s, t, snext, tnext, sstep, tstep;
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
float sdivz8stepu, tdivz8stepu, zi8stepu;
 
sstep = 0; // keep compiler happy
tstep = 0; // ditto
 
pbase = (unsigned char *)cacheblock;
 
sdivz8stepu = d_sdivzstepu * 8;
tdivz8stepu = d_tdivzstepu * 8;
zi8stepu = d_zistepu * 8;
 
do
{
pdest = (unsigned char *)((byte *)d_viewbuffer +
(screenwidth * pspan->v) + pspan->u);
 
count = pspan->count;
 
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float)pspan->u;
dv = (float)pspan->v;
 
sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
 
s = (int)(sdivz * z) + sadjust;
if (s > bbextents)
s = bbextents;
else if (s < 0)
s = 0;
 
t = (int)(tdivz * z) + tadjust;
if (t > bbextentt)
t = bbextentt;
else if (t < 0)
t = 0;
 
do
{
// calculate s and t at the far end of the span
if (count >= 8)
spancount = 8;
else
spancount = count;
 
count -= spancount;
 
if (count)
{
// calculate s/z, t/z, zi->fixed s and t at far end of span,
// calculate s and t steps across span by shifting
sdivz += sdivz8stepu;
tdivz += tdivz8stepu;
zi += zi8stepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
 
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
 
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on <0 steps
 
sstep = (snext - s) >> 3;
tstep = (tnext - t) >> 3;
}
else
{
// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
// can't step off polygon), clamp, calculate s and t steps across
// span by division, biasing steps low so we don't run off the
// texture
spancountminus1 = (float)(spancount - 1);
sdivz += d_sdivzstepu * spancountminus1;
tdivz += d_tdivzstepu * spancountminus1;
zi += d_zistepu * spancountminus1;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
 
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on <0 steps
 
if (spancount > 1)
{
sstep = (snext - s) / (spancount - 1);
tstep = (tnext - t) / (spancount - 1);
}
}
 
do
{
*pdest++ = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
s += sstep;
t += tstep;
} while (--spancount > 0);
 
s = snext;
t = tnext;
 
} while (count > 0);
 
} while ((pspan = pspan->pnext) != NULL);
}
 
#endif
 
 
#if !id386
 
/*
=============
D_DrawZSpans
=============
*/
void D_DrawZSpans (espan_t *pspan)
{
int count, doublecount, izistep;
int izi;
short *pdest;
unsigned ltemp;
double zi;
float du, dv;
 
// FIXME: check for clamping/range problems
// we count on FP exceptions being turned off to avoid range problems
izistep = (int)(d_zistepu * 0x8000 * 0x10000);
 
do
{
pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
 
count = pspan->count;
 
// calculate the initial 1/z
du = (float)pspan->u;
dv = (float)pspan->v;
 
zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
// we count on FP exceptions being turned off to avoid range problems
izi = (int)(zi * 0x8000 * 0x10000);
 
if ((long)pdest & 0x02)
{
*pdest++ = (short)(izi >> 16);
izi += izistep;
count--;
}
 
if ((doublecount = count >> 1) > 0)
{
do
{
ltemp = izi >> 16;
izi += izistep;
ltemp |= izi & 0xFFFF0000;
izi += izistep;
*(int *)pdest = ltemp;
pdest += 2;
} while (--doublecount > 0);
}
 
if (count & 1)
*pdest = (short)(izi >> 16);
 
} while ((pspan = pspan->pnext) != NULL);
}
 
#endif
 
/contrib/other/sdlquake-1.0.9/d_scana.S
0,0 → 1,89
/*
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.
 
*/
//
// d_scana.s
// x86 assembly-language turbulent texture mapping code
//
 
#include "asm_i386.h"
#include "quakeasm.h"
#include "asm_draw.h"
#include "d_ifacea.h"
 
#if id386
 
.data
 
.text
 
//----------------------------------------------------------------------
// turbulent texture mapping code
//----------------------------------------------------------------------
 
.align 4
.globl C(D_DrawTurbulent8Span)
C(D_DrawTurbulent8Span):
pushl %ebp // preserve caller's stack frame pointer
pushl %esi // preserve register variables
pushl %edi
pushl %ebx
 
movl C(r_turb_s),%esi
movl C(r_turb_t),%ecx
movl C(r_turb_pdest),%edi
movl C(r_turb_spancount),%ebx
 
Llp:
movl %ecx,%eax
movl %esi,%edx
sarl $16,%eax
movl C(r_turb_turb),%ebp
sarl $16,%edx
andl $(CYCLE-1),%eax
andl $(CYCLE-1),%edx
movl (%ebp,%eax,4),%eax
movl (%ebp,%edx,4),%edx
addl %esi,%eax
sarl $16,%eax
addl %ecx,%edx
sarl $16,%edx
andl $(TURB_TEX_SIZE-1),%eax
andl $(TURB_TEX_SIZE-1),%edx
shll $6,%edx
movl C(r_turb_pbase),%ebp
addl %eax,%edx
incl %edi
addl C(r_turb_sstep),%esi
addl C(r_turb_tstep),%ecx
movb (%ebp,%edx,1),%dl
decl %ebx
movb %dl,-1(%edi)
jnz Llp
 
movl %edi,C(r_turb_pdest)
 
popl %ebx // restore register variables
popl %edi
popl %esi
popl %ebp // restore caller's stack frame pointer
ret
 
#endif // id386
 
/contrib/other/sdlquake-1.0.9/d_sky.c
0,0 → 1,138
/*
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.
 
*/
// d_sky.c
 
#include "quakedef.h"
#include "r_local.h"
#include "d_local.h"
 
#define SKY_SPAN_SHIFT 5
#define SKY_SPAN_MAX (1 << SKY_SPAN_SHIFT)
 
 
/*
=================
D_Sky_uv_To_st
=================
*/
void D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t)
{
float wu, wv, temp;
vec3_t end;
 
if (r_refdef.vrect.width >= r_refdef.vrect.height)
temp = (float)r_refdef.vrect.width;
else
temp = (float)r_refdef.vrect.height;
 
wu = 8192.0 * (float)(u-((int)vid.width>>1)) / temp;
wv = 8192.0 * (float)(((int)vid.height>>1)-v) / temp;
 
end[0] = 4096*vpn[0] + wu*vright[0] + wv*vup[0];
end[1] = 4096*vpn[1] + wu*vright[1] + wv*vup[1];
end[2] = 4096*vpn[2] + wu*vright[2] + wv*vup[2];
end[2] *= 3;
VectorNormalize (end);
 
temp = skytime*skyspeed; // TODO: add D_SetupFrame & set this there
*s = (int)((temp + 6*(SKYSIZE/2-1)*end[0]) * 0x10000);
*t = (int)((temp + 6*(SKYSIZE/2-1)*end[1]) * 0x10000);
}
 
 
/*
=================
D_DrawSkyScans8
=================
*/
void D_DrawSkyScans8 (espan_t *pspan)
{
int count, spancount, u, v;
unsigned char *pdest;
fixed16_t s, t, snext, tnext, sstep, tstep;
int spancountminus1;
 
sstep = 0; // keep compiler happy
tstep = 0; // ditto
 
do
{
pdest = (unsigned char *)((byte *)d_viewbuffer +
(screenwidth * pspan->v) + pspan->u);
 
count = pspan->count;
 
// calculate the initial s & t
u = pspan->u;
v = pspan->v;
D_Sky_uv_To_st (u, v, &s, &t);
 
do
{
if (count >= SKY_SPAN_MAX)
spancount = SKY_SPAN_MAX;
else
spancount = count;
 
count -= spancount;
 
if (count)
{
u += spancount;
 
// calculate s and t at far end of span,
// calculate s and t steps across span by shifting
D_Sky_uv_To_st (u, v, &snext, &tnext);
 
sstep = (snext - s) >> SKY_SPAN_SHIFT;
tstep = (tnext - t) >> SKY_SPAN_SHIFT;
}
else
{
// calculate s and t at last pixel in span,
// calculate s and t steps across span by division
spancountminus1 = (float)(spancount - 1);
 
if (spancountminus1 > 0)
{
u += spancountminus1;
D_Sky_uv_To_st (u, v, &snext, &tnext);
 
sstep = (snext - s) / spancountminus1;
tstep = (tnext - t) / spancountminus1;
}
}
 
do
{
*pdest++ = r_skysource[((t & R_SKY_TMASK) >> 8) +
((s & R_SKY_SMASK) >> 16)];
s += sstep;
t += tstep;
} while (--spancount > 0);
 
s = snext;
t = tnext;
 
} while (count > 0);
 
} while ((pspan = pspan->pnext) != NULL);
}
 
/contrib/other/sdlquake-1.0.9/d_spr8.S
0,0 → 1,900
/*
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.
 
*/
//
// d_spr8.s
// x86 assembly-language horizontal 8-bpp transparent span-drawing code.
//
 
#include "asm_i386.h"
#include "quakeasm.h"
#include "asm_draw.h"
 
#if id386
 
//----------------------------------------------------------------------
// 8-bpp horizontal span drawing code for polygons, with transparency.
//----------------------------------------------------------------------
 
.text
 
// out-of-line, rarely-needed clamping code
 
LClampHigh0:
movl C(bbextents),%esi
jmp LClampReentry0
LClampHighOrLow0:
jg LClampHigh0
xorl %esi,%esi
jmp LClampReentry0
 
LClampHigh1:
movl C(bbextentt),%edx
jmp LClampReentry1
LClampHighOrLow1:
jg LClampHigh1
xorl %edx,%edx
jmp LClampReentry1
 
LClampLow2:
movl $2048,%ebp
jmp LClampReentry2
LClampHigh2:
movl C(bbextents),%ebp
jmp LClampReentry2
 
LClampLow3:
movl $2048,%ecx
jmp LClampReentry3
LClampHigh3:
movl C(bbextentt),%ecx
jmp LClampReentry3
 
LClampLow4:
movl $2048,%eax
jmp LClampReentry4
LClampHigh4:
movl C(bbextents),%eax
jmp LClampReentry4
 
LClampLow5:
movl $2048,%ebx
jmp LClampReentry5
LClampHigh5:
movl C(bbextentt),%ebx
jmp LClampReentry5
 
 
#define pspans 4+16
 
.align 4
.globl C(D_SpriteDrawSpans)
C(D_SpriteDrawSpans):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
 
//
// set up scaled-by-8 steps, for 8-long segments; also set up cacheblock
// and span list pointers, and 1/z step in 0.32 fixed-point
//
// FIXME: any overlap from rearranging?
flds C(d_sdivzstepu)
fmuls fp_8
movl C(cacheblock),%edx
flds C(d_tdivzstepu)
fmuls fp_8
movl pspans(%esp),%ebx // point to the first span descriptor
flds C(d_zistepu)
fmuls fp_8
movl %edx,pbase // pbase = cacheblock
flds C(d_zistepu)
fmuls fp_64kx64k
fxch %st(3)
fstps sdivz8stepu
fstps zi8stepu
fstps tdivz8stepu
fistpl izistep
movl izistep,%eax
rorl $16,%eax // put upper 16 bits in low word
movl sspan_t_count(%ebx),%ecx
movl %eax,izistep
 
cmpl $0,%ecx
jle LNextSpan
 
LSpanLoop:
 
//
// set up the initial s/z, t/z, and 1/z on the FP stack, and generate the
// initial s and t values
//
// FIXME: pipeline FILD?
fildl sspan_t_v(%ebx)
fildl sspan_t_u(%ebx)
 
fld %st(1) // dv | du | dv
fmuls C(d_sdivzstepv) // dv*d_sdivzstepv | du | dv
fld %st(1) // du | dv*d_sdivzstepv | du | dv
fmuls C(d_sdivzstepu) // du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
fld %st(2) // du | du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
fmuls C(d_tdivzstepu) // du*d_tdivzstepu | du*d_sdivzstepu |
// dv*d_sdivzstepv | du | dv
fxch %st(1) // du*d_sdivzstepu | du*d_tdivzstepu |
// dv*d_sdivzstepv | du | dv
faddp %st(0),%st(2) // du*d_tdivzstepu |
// du*d_sdivzstepu + dv*d_sdivzstepv | du | dv
fxch %st(1) // du*d_sdivzstepu + dv*d_sdivzstepv |
// du*d_tdivzstepu | du | dv
fld %st(3) // dv | du*d_sdivzstepu + dv*d_sdivzstepv |
// du*d_tdivzstepu | du | dv
fmuls C(d_tdivzstepv) // dv*d_tdivzstepv |
// du*d_sdivzstepu + dv*d_sdivzstepv |
// du*d_tdivzstepu | du | dv
fxch %st(1) // du*d_sdivzstepu + dv*d_sdivzstepv |
// dv*d_tdivzstepv | du*d_tdivzstepu | du | dv
fadds C(d_sdivzorigin) // sdivz = d_sdivzorigin + dv*d_sdivzstepv +
// du*d_sdivzstepu; stays in %st(2) at end
fxch %st(4) // dv | dv*d_tdivzstepv | du*d_tdivzstepu | du |
// s/z
fmuls C(d_zistepv) // dv*d_zistepv | dv*d_tdivzstepv |
// du*d_tdivzstepu | du | s/z
fxch %st(1) // dv*d_tdivzstepv | dv*d_zistepv |
// du*d_tdivzstepu | du | s/z
faddp %st(0),%st(2) // dv*d_zistepv |
// dv*d_tdivzstepv + du*d_tdivzstepu | du | s/z
fxch %st(2) // du | dv*d_tdivzstepv + du*d_tdivzstepu |
// dv*d_zistepv | s/z
fmuls C(d_zistepu) // du*d_zistepu |
// dv*d_tdivzstepv + du*d_tdivzstepu |
// dv*d_zistepv | s/z
fxch %st(1) // dv*d_tdivzstepv + du*d_tdivzstepu |
// du*d_zistepu | dv*d_zistepv | s/z
fadds C(d_tdivzorigin) // tdivz = d_tdivzorigin + dv*d_tdivzstepv +
// du*d_tdivzstepu; stays in %st(1) at end
fxch %st(2) // dv*d_zistepv | du*d_zistepu | t/z | s/z
faddp %st(0),%st(1) // dv*d_zistepv + du*d_zistepu | t/z | s/z
 
flds fp_64k // fp_64k | dv*d_zistepv + du*d_zistepu | t/z | s/z
fxch %st(1) // dv*d_zistepv + du*d_zistepu | fp_64k | t/z | s/z
fadds C(d_ziorigin) // zi = d_ziorigin + dv*d_zistepv +
// du*d_zistepu; stays in %st(0) at end
// 1/z | fp_64k | t/z | s/z
 
fld %st(0) // FIXME: get rid of stall on FMUL?
fmuls fp_64kx64k
fxch %st(1)
 
//
// calculate and clamp s & t
//
fdivr %st(0),%st(2) // 1/z | z*64k | t/z | s/z
fxch %st(1)
 
fistpl izi // 0.32 fixed-point 1/z
movl izi,%ebp
 
//
// set pz to point to the first z-buffer pixel in the span
//
rorl $16,%ebp // put upper 16 bits in low word
movl sspan_t_v(%ebx),%eax
movl %ebp,izi
movl sspan_t_u(%ebx),%ebp
imull C(d_zrowbytes)
shll $1,%ebp // a word per pixel
addl C(d_pzbuffer),%eax
addl %ebp,%eax
movl %eax,pz
 
//
// point %edi to the first pixel in the span
//
movl C(d_viewbuffer),%ebp
movl sspan_t_v(%ebx),%eax
pushl %ebx // preserve spans pointer
movl C(tadjust),%edx
movl C(sadjust),%esi
movl C(d_scantable)(,%eax,4),%edi // v * screenwidth
addl %ebp,%edi
movl sspan_t_u(%ebx),%ebp
addl %ebp,%edi // pdest = &pdestspan[scans->u];
 
//
// now start the FDIV for the end of the span
//
cmpl $8,%ecx
ja LSetupNotLast1
 
decl %ecx
jz LCleanup1 // if only one pixel, no need to start an FDIV
movl %ecx,spancountminus1
 
// finish up the s and t calcs
fxch %st(1) // z*64k | 1/z | t/z | s/z
 
fld %st(0) // z*64k | z*64k | 1/z | t/z | s/z
fmul %st(4),%st(0) // s | z*64k | 1/z | t/z | s/z
fxch %st(1) // z*64k | s | 1/z | t/z | s/z
fmul %st(3),%st(0) // t | s | 1/z | t/z | s/z
fxch %st(1) // s | t | 1/z | t/z | s/z
fistpl s // 1/z | t | t/z | s/z
fistpl t // 1/z | t/z | s/z
 
fildl spancountminus1
 
flds C(d_tdivzstepu) // _d_tdivzstepu | spancountminus1
flds C(d_zistepu) // _d_zistepu | _d_tdivzstepu | spancountminus1
fmul %st(2),%st(0) // _d_zistepu*scm1 | _d_tdivzstepu | scm1
fxch %st(1) // _d_tdivzstepu | _d_zistepu*scm1 | scm1
fmul %st(2),%st(0) // _d_tdivzstepu*scm1 | _d_zistepu*scm1 | scm1
fxch %st(2) // scm1 | _d_zistepu*scm1 | _d_tdivzstepu*scm1
fmuls C(d_sdivzstepu) // _d_sdivzstepu*scm1 | _d_zistepu*scm1 |
// _d_tdivzstepu*scm1
fxch %st(1) // _d_zistepu*scm1 | _d_sdivzstepu*scm1 |
// _d_tdivzstepu*scm1
faddp %st(0),%st(3) // _d_sdivzstepu*scm1 | _d_tdivzstepu*scm1
fxch %st(1) // _d_tdivzstepu*scm1 | _d_sdivzstepu*scm1
faddp %st(0),%st(3) // _d_sdivzstepu*scm1
faddp %st(0),%st(3)
 
flds fp_64k
fdiv %st(1),%st(0) // this is what we've gone to all this trouble to
// overlap
jmp LFDIVInFlight1
 
LCleanup1:
// finish up the s and t calcs
fxch %st(1) // z*64k | 1/z | t/z | s/z
 
fld %st(0) // z*64k | z*64k | 1/z | t/z | s/z
fmul %st(4),%st(0) // s | z*64k | 1/z | t/z | s/z
fxch %st(1) // z*64k | s | 1/z | t/z | s/z
fmul %st(3),%st(0) // t | s | 1/z | t/z | s/z
fxch %st(1) // s | t | 1/z | t/z | s/z
fistpl s // 1/z | t | t/z | s/z
fistpl t // 1/z | t/z | s/z
jmp LFDIVInFlight1
 
.align 4
LSetupNotLast1:
// finish up the s and t calcs
fxch %st(1) // z*64k | 1/z | t/z | s/z
 
fld %st(0) // z*64k | z*64k | 1/z | t/z | s/z
fmul %st(4),%st(0) // s | z*64k | 1/z | t/z | s/z
fxch %st(1) // z*64k | s | 1/z | t/z | s/z
fmul %st(3),%st(0) // t | s | 1/z | t/z | s/z
fxch %st(1) // s | t | 1/z | t/z | s/z
fistpl s // 1/z | t | t/z | s/z
fistpl t // 1/z | t/z | s/z
 
fadds zi8stepu
fxch %st(2)
fadds sdivz8stepu
fxch %st(2)
flds tdivz8stepu
faddp %st(0),%st(2)
flds fp_64k
fdiv %st(1),%st(0) // z = 1/1/z
// this is what we've gone to all this trouble to
// overlap
LFDIVInFlight1:
 
addl s,%esi
addl t,%edx
movl C(bbextents),%ebx
movl C(bbextentt),%ebp
cmpl %ebx,%esi
ja LClampHighOrLow0
LClampReentry0:
movl %esi,s
movl pbase,%ebx
shll $16,%esi
cmpl %ebp,%edx
movl %esi,sfracf
ja LClampHighOrLow1
LClampReentry1:
movl %edx,t
movl s,%esi // sfrac = scans->sfrac;
shll $16,%edx
movl t,%eax // tfrac = scans->tfrac;
sarl $16,%esi
movl %edx,tfracf
 
//
// calculate the texture starting address
//
sarl $16,%eax
addl %ebx,%esi
imull C(cachewidth),%eax // (tfrac >> 16) * cachewidth
addl %eax,%esi // psource = pbase + (sfrac >> 16) +
// ((tfrac >> 16) * cachewidth);
 
//
// determine whether last span or not
//
cmpl $8,%ecx
jna LLastSegment
 
//
// not the last segment; do full 8-wide segment
//
LNotLastSegment:
 
//
// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
// get there
//
 
// pick up after the FDIV that was left in flight previously
 
fld %st(0) // duplicate it
fmul %st(4),%st(0) // s = s/z * z
fxch %st(1)
fmul %st(3),%st(0) // t = t/z * z
fxch %st(1)
fistpl snext
fistpl tnext
movl snext,%eax
movl tnext,%edx
 
subl $8,%ecx // count off this segments' pixels
movl C(sadjust),%ebp
pushl %ecx // remember count of remaining pixels
movl C(tadjust),%ecx
 
addl %eax,%ebp
addl %edx,%ecx
 
movl C(bbextents),%eax
movl C(bbextentt),%edx
 
cmpl $2048,%ebp
jl LClampLow2
cmpl %eax,%ebp
ja LClampHigh2
LClampReentry2:
 
cmpl $2048,%ecx
jl LClampLow3
cmpl %edx,%ecx
ja LClampHigh3
LClampReentry3:
 
movl %ebp,snext
movl %ecx,tnext
 
subl s,%ebp
subl t,%ecx
//
// set up advancetable
//
movl %ecx,%eax
movl %ebp,%edx
sarl $19,%edx // sstep >>= 16;
movl C(cachewidth),%ebx
sarl $19,%eax // tstep >>= 16;
jz LIsZero
imull %ebx,%eax // (tstep >> 16) * cachewidth;
LIsZero:
addl %edx,%eax // add in sstep
// (tstep >> 16) * cachewidth + (sstep >> 16);
movl tfracf,%edx
movl %eax,advancetable+4 // advance base in t
addl %ebx,%eax // ((tstep >> 16) + 1) * cachewidth +
// (sstep >> 16);
shll $13,%ebp // left-justify sstep fractional part
movl %ebp,sstep
movl sfracf,%ebx
shll $13,%ecx // left-justify tstep fractional part
movl %eax,advancetable // advance extra in t
movl %ecx,tstep
 
movl pz,%ecx
movl izi,%ebp
 
cmpw (%ecx),%bp
jl Lp1
movb (%esi),%al // get first source texel
cmpb $(TRANSPARENT_COLOR),%al
jz Lp1
movw %bp,(%ecx)
movb %al,(%edi) // store first dest pixel
Lp1:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx // advance tfrac fractional part by tstep frac
 
sbbl %eax,%eax // turn tstep carry into -1 (0 if none)
addl sstep,%ebx // advance sfrac fractional part by sstep frac
adcl advancetable+4(,%eax,4),%esi // point to next source texel
 
cmpw 2(%ecx),%bp
jl Lp2
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp2
movw %bp,2(%ecx)
movb %al,1(%edi)
Lp2:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
 
cmpw 4(%ecx),%bp
jl Lp3
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp3
movw %bp,4(%ecx)
movb %al,2(%edi)
Lp3:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
 
cmpw 6(%ecx),%bp
jl Lp4
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp4
movw %bp,6(%ecx)
movb %al,3(%edi)
Lp4:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
 
cmpw 8(%ecx),%bp
jl Lp5
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp5
movw %bp,8(%ecx)
movb %al,4(%edi)
Lp5:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
 
//
// start FDIV for end of next segment in flight, so it can overlap
//
popl %eax
cmpl $8,%eax // more than one segment after this?
ja LSetupNotLast2 // yes
 
decl %eax
jz LFDIVInFlight2 // if only one pixel, no need to start an FDIV
movl %eax,spancountminus1
fildl spancountminus1
 
flds C(d_zistepu) // _d_zistepu | spancountminus1
fmul %st(1),%st(0) // _d_zistepu*scm1 | scm1
flds C(d_tdivzstepu) // _d_tdivzstepu | _d_zistepu*scm1 | scm1
fmul %st(2),%st(0) // _d_tdivzstepu*scm1 | _d_zistepu*scm1 | scm1
fxch %st(1) // _d_zistepu*scm1 | _d_tdivzstepu*scm1 | scm1
faddp %st(0),%st(3) // _d_tdivzstepu*scm1 | scm1
fxch %st(1) // scm1 | _d_tdivzstepu*scm1
fmuls C(d_sdivzstepu) // _d_sdivzstepu*scm1 | _d_tdivzstepu*scm1
fxch %st(1) // _d_tdivzstepu*scm1 | _d_sdivzstepu*scm1
faddp %st(0),%st(3) // _d_sdivzstepu*scm1
flds fp_64k // 64k | _d_sdivzstepu*scm1
fxch %st(1) // _d_sdivzstepu*scm1 | 64k
faddp %st(0),%st(4) // 64k
 
fdiv %st(1),%st(0) // this is what we've gone to all this trouble to
// overlap
jmp LFDIVInFlight2
 
.align 4
LSetupNotLast2:
fadds zi8stepu
fxch %st(2)
fadds sdivz8stepu
fxch %st(2)
flds tdivz8stepu
faddp %st(0),%st(2)
flds fp_64k
fdiv %st(1),%st(0) // z = 1/1/z
// this is what we've gone to all this trouble to
// overlap
LFDIVInFlight2:
pushl %eax
 
cmpw 10(%ecx),%bp
jl Lp6
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp6
movw %bp,10(%ecx)
movb %al,5(%edi)
Lp6:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
 
cmpw 12(%ecx),%bp
jl Lp7
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp7
movw %bp,12(%ecx)
movb %al,6(%edi)
Lp7:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
 
cmpw 14(%ecx),%bp
jl Lp8
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp8
movw %bp,14(%ecx)
movb %al,7(%edi)
Lp8:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
 
addl $8,%edi
addl $16,%ecx
movl %edx,tfracf
movl snext,%edx
movl %ebx,sfracf
movl tnext,%ebx
movl %edx,s
movl %ebx,t
 
movl %ecx,pz
movl %ebp,izi
 
popl %ecx // retrieve count
 
//
// determine whether last span or not
//
cmpl $8,%ecx // are there multiple segments remaining?
ja LNotLastSegment // yes
 
//
// last segment of scan
//
LLastSegment:
 
//
// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
// get there. The number of pixels left is variable, and we want to land on the
// last pixel, not step one past it, so we can't run into arithmetic problems
//
testl %ecx,%ecx
jz LNoSteps // just draw the last pixel and we're done
 
// pick up after the FDIV that was left in flight previously
 
 
fld %st(0) // duplicate it
fmul %st(4),%st(0) // s = s/z * z
fxch %st(1)
fmul %st(3),%st(0) // t = t/z * z
fxch %st(1)
fistpl snext
fistpl tnext
 
movl C(tadjust),%ebx
movl C(sadjust),%eax
 
addl snext,%eax
addl tnext,%ebx
 
movl C(bbextents),%ebp
movl C(bbextentt),%edx
 
cmpl $2048,%eax
jl LClampLow4
cmpl %ebp,%eax
ja LClampHigh4
LClampReentry4:
movl %eax,snext
 
cmpl $2048,%ebx
jl LClampLow5
cmpl %edx,%ebx
ja LClampHigh5
LClampReentry5:
 
cmpl $1,%ecx // don't bother
je LOnlyOneStep // if two pixels in segment, there's only one step,
// of the segment length
subl s,%eax
subl t,%ebx
 
addl %eax,%eax // convert to 15.17 format so multiply by 1.31
addl %ebx,%ebx // reciprocal yields 16.48
imull reciprocal_table-8(,%ecx,4) // sstep = (snext - s) / (spancount-1)
movl %edx,%ebp
 
movl %ebx,%eax
imull reciprocal_table-8(,%ecx,4) // tstep = (tnext - t) / (spancount-1)
 
LSetEntryvec:
//
// set up advancetable
//
movl spr8entryvec_table(,%ecx,4),%ebx
movl %edx,%eax
pushl %ebx // entry point into code for RET later
movl %ebp,%ecx
sarl $16,%ecx // sstep >>= 16;
movl C(cachewidth),%ebx
sarl $16,%edx // tstep >>= 16;
jz LIsZeroLast
imull %ebx,%edx // (tstep >> 16) * cachewidth;
LIsZeroLast:
addl %ecx,%edx // add in sstep
// (tstep >> 16) * cachewidth + (sstep >> 16);
movl tfracf,%ecx
movl %edx,advancetable+4 // advance base in t
addl %ebx,%edx // ((tstep >> 16) + 1) * cachewidth +
// (sstep >> 16);
shll $16,%ebp // left-justify sstep fractional part
movl sfracf,%ebx
shll $16,%eax // left-justify tstep fractional part
movl %edx,advancetable // advance extra in t
 
movl %eax,tstep
movl %ebp,sstep
movl %ecx,%edx
 
movl pz,%ecx
movl izi,%ebp
 
ret // jump to the number-of-pixels handler
 
//----------------------------------------
 
LNoSteps:
movl pz,%ecx
subl $7,%edi // adjust for hardwired offset
subl $14,%ecx
jmp LEndSpan
 
 
LOnlyOneStep:
subl s,%eax
subl t,%ebx
movl %eax,%ebp
movl %ebx,%edx
jmp LSetEntryvec
 
//----------------------------------------
 
.globl Spr8Entry2_8
Spr8Entry2_8:
subl $6,%edi // adjust for hardwired offsets
subl $12,%ecx
movb (%esi),%al
jmp LLEntry2_8
 
//----------------------------------------
 
.globl Spr8Entry3_8
Spr8Entry3_8:
subl $5,%edi // adjust for hardwired offsets
subl $10,%ecx
jmp LLEntry3_8
 
//----------------------------------------
 
.globl Spr8Entry4_8
Spr8Entry4_8:
subl $4,%edi // adjust for hardwired offsets
subl $8,%ecx
jmp LLEntry4_8
 
//----------------------------------------
 
.globl Spr8Entry5_8
Spr8Entry5_8:
subl $3,%edi // adjust for hardwired offsets
subl $6,%ecx
jmp LLEntry5_8
 
//----------------------------------------
 
.globl Spr8Entry6_8
Spr8Entry6_8:
subl $2,%edi // adjust for hardwired offsets
subl $4,%ecx
jmp LLEntry6_8
 
//----------------------------------------
 
.globl Spr8Entry7_8
Spr8Entry7_8:
decl %edi // adjust for hardwired offsets
subl $2,%ecx
jmp LLEntry7_8
 
//----------------------------------------
 
.globl Spr8Entry8_8
Spr8Entry8_8:
cmpw (%ecx),%bp
jl Lp9
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp9
movw %bp,(%ecx)
movb %al,(%edi)
Lp9:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
LLEntry7_8:
cmpw 2(%ecx),%bp
jl Lp10
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp10
movw %bp,2(%ecx)
movb %al,1(%edi)
Lp10:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
LLEntry6_8:
cmpw 4(%ecx),%bp
jl Lp11
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp11
movw %bp,4(%ecx)
movb %al,2(%edi)
Lp11:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
LLEntry5_8:
cmpw 6(%ecx),%bp
jl Lp12
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp12
movw %bp,6(%ecx)
movb %al,3(%edi)
Lp12:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
LLEntry4_8:
cmpw 8(%ecx),%bp
jl Lp13
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp13
movw %bp,8(%ecx)
movb %al,4(%edi)
Lp13:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
LLEntry3_8:
cmpw 10(%ecx),%bp
jl Lp14
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp14
movw %bp,10(%ecx)
movb %al,5(%edi)
Lp14:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
LLEntry2_8:
cmpw 12(%ecx),%bp
jl Lp15
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp15
movw %bp,12(%ecx)
movb %al,6(%edi)
Lp15:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
 
LEndSpan:
cmpw 14(%ecx),%bp
jl Lp16
movb (%esi),%al // load first texel in segment
cmpb $(TRANSPARENT_COLOR),%al
jz Lp16
movw %bp,14(%ecx)
movb %al,7(%edi)
Lp16:
 
//
// clear s/z, t/z, 1/z from FP stack
//
fstp %st(0)
fstp %st(0)
fstp %st(0)
 
popl %ebx // restore spans pointer
LNextSpan:
addl $(sspan_t_size),%ebx // point to next span
movl sspan_t_count(%ebx),%ecx
cmpl $0,%ecx // any more spans?
jg LSpanLoop // yes
jz LNextSpan // yes, but this one's empty
 
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
 
#endif // id386
/contrib/other/sdlquake-1.0.9/d_sprite.c
0,0 → 1,442
/*
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.
 
*/
// d_sprite.c: software top-level rasterization driver module for drawing
// sprites
 
#include "quakedef.h"
#include "d_local.h"
 
static int sprite_height;
static int minindex, maxindex;
static sspan_t *sprite_spans;
 
#if !id386
 
/*
=====================
D_SpriteDrawSpans
=====================
*/
void D_SpriteDrawSpans (sspan_t *pspan)
{
int count, spancount, izistep;
int izi;
byte *pbase, *pdest;
fixed16_t s, t, snext, tnext, sstep, tstep;
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
float sdivz8stepu, tdivz8stepu, zi8stepu;
byte btemp;
short *pz;
 
sstep = 0; // keep compiler happy
tstep = 0; // ditto
 
pbase = cacheblock;
 
sdivz8stepu = d_sdivzstepu * 8;
tdivz8stepu = d_tdivzstepu * 8;
zi8stepu = d_zistepu * 8;
 
// we count on FP exceptions being turned off to avoid range problems
izistep = (int)(d_zistepu * 0x8000 * 0x10000);
 
do
{
pdest = (byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u;
pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
 
count = pspan->count;
 
if (count <= 0)
goto NextSpan;
 
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float)pspan->u;
dv = (float)pspan->v;
 
sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
// we count on FP exceptions being turned off to avoid range problems
izi = (int)(zi * 0x8000 * 0x10000);
 
s = (int)(sdivz * z) + sadjust;
if (s > bbextents)
s = bbextents;
else if (s < 0)
s = 0;
 
t = (int)(tdivz * z) + tadjust;
if (t > bbextentt)
t = bbextentt;
else if (t < 0)
t = 0;
 
do
{
// calculate s and t at the far end of the span
if (count >= 8)
spancount = 8;
else
spancount = count;
 
count -= spancount;
 
if (count)
{
// calculate s/z, t/z, zi->fixed s and t at far end of span,
// calculate s and t steps across span by shifting
sdivz += sdivz8stepu;
tdivz += tdivz8stepu;
zi += zi8stepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
 
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
 
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on <0 steps
 
sstep = (snext - s) >> 3;
tstep = (tnext - t) >> 3;
}
else
{
// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
// can't step off polygon), clamp, calculate s and t steps across
// span by division, biasing steps low so we don't run off the
// texture
spancountminus1 = (float)(spancount - 1);
sdivz += d_sdivzstepu * spancountminus1;
tdivz += d_tdivzstepu * spancountminus1;
zi += d_zistepu * spancountminus1;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
 
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on <0 steps
 
if (spancount > 1)
{
sstep = (snext - s) / (spancount - 1);
tstep = (tnext - t) / (spancount - 1);
}
}
 
do
{
btemp = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
if (btemp != 255)
{
if (*pz <= (izi >> 16))
{
*pz = izi >> 16;
*pdest = btemp;
}
}
 
izi += izistep;
pdest++;
pz++;
s += sstep;
t += tstep;
} while (--spancount > 0);
 
s = snext;
t = tnext;
 
} while (count > 0);
 
NextSpan:
pspan++;
 
} while (pspan->count != DS_SPAN_LIST_END);
}
 
#endif
 
 
/*
=====================
D_SpriteScanLeftEdge
=====================
*/
void D_SpriteScanLeftEdge (void)
{
int i, v, itop, ibottom, lmaxindex;
emitpoint_t *pvert, *pnext;
sspan_t *pspan;
float du, dv, vtop, vbottom, slope;
fixed16_t u, u_step;
 
pspan = sprite_spans;
i = minindex;
if (i == 0)
i = r_spritedesc.nump;
 
lmaxindex = maxindex;
if (lmaxindex == 0)
lmaxindex = r_spritedesc.nump;
 
vtop = ceil (r_spritedesc.pverts[i].v);
 
do
{
pvert = &r_spritedesc.pverts[i];
pnext = pvert - 1;
 
vbottom = ceil (pnext->v);
 
if (vtop < vbottom)
{
du = pnext->u - pvert->u;
dv = pnext->v - pvert->v;
slope = du / dv;
u_step = (int)(slope * 0x10000);
// adjust u to ceil the integer portion
u = (int)((pvert->u + (slope * (vtop - pvert->v))) * 0x10000) +
(0x10000 - 1);
itop = (int)vtop;
ibottom = (int)vbottom;
 
for (v=itop ; v<ibottom ; v++)
{
pspan->u = u >> 16;
pspan->v = v;
u += u_step;
pspan++;
}
}
 
vtop = vbottom;
 
i--;
if (i == 0)
i = r_spritedesc.nump;
 
} while (i != lmaxindex);
}
 
 
/*
=====================
D_SpriteScanRightEdge
=====================
*/
void D_SpriteScanRightEdge (void)
{
int i, v, itop, ibottom;
emitpoint_t *pvert, *pnext;
sspan_t *pspan;
float du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext;
fixed16_t u, u_step;
 
pspan = sprite_spans;
i = minindex;
 
vvert = r_spritedesc.pverts[i].v;
if (vvert < r_refdef.fvrecty_adj)
vvert = r_refdef.fvrecty_adj;
if (vvert > r_refdef.fvrectbottom_adj)
vvert = r_refdef.fvrectbottom_adj;
 
vtop = ceil (vvert);
 
do
{
pvert = &r_spritedesc.pverts[i];
pnext = pvert + 1;
 
vnext = pnext->v;
if (vnext < r_refdef.fvrecty_adj)
vnext = r_refdef.fvrecty_adj;
if (vnext > r_refdef.fvrectbottom_adj)
vnext = r_refdef.fvrectbottom_adj;
 
vbottom = ceil (vnext);
 
if (vtop < vbottom)
{
uvert = pvert->u;
if (uvert < r_refdef.fvrectx_adj)
uvert = r_refdef.fvrectx_adj;
if (uvert > r_refdef.fvrectright_adj)
uvert = r_refdef.fvrectright_adj;
 
unext = pnext->u;
if (unext < r_refdef.fvrectx_adj)
unext = r_refdef.fvrectx_adj;
if (unext > r_refdef.fvrectright_adj)
unext = r_refdef.fvrectright_adj;
 
du = unext - uvert;
dv = vnext - vvert;
slope = du / dv;
u_step = (int)(slope * 0x10000);
// adjust u to ceil the integer portion
u = (int)((uvert + (slope * (vtop - vvert))) * 0x10000) +
(0x10000 - 1);
itop = (int)vtop;
ibottom = (int)vbottom;
 
for (v=itop ; v<ibottom ; v++)
{
pspan->count = (u >> 16) - pspan->u;
u += u_step;
pspan++;
}
}
 
vtop = vbottom;
vvert = vnext;
 
i++;
if (i == r_spritedesc.nump)
i = 0;
 
} while (i != maxindex);
 
pspan->count = DS_SPAN_LIST_END; // mark the end of the span list
}
 
 
/*
=====================
D_SpriteCalculateGradients
=====================
*/
void D_SpriteCalculateGradients (void)
{
vec3_t p_normal, p_saxis, p_taxis, p_temp1;
float distinv;
 
TransformVector (r_spritedesc.vpn, p_normal);
TransformVector (r_spritedesc.vright, p_saxis);
TransformVector (r_spritedesc.vup, p_taxis);
VectorInverse (p_taxis);
 
distinv = 1.0 / (-DotProduct (modelorg, r_spritedesc.vpn));
 
d_sdivzstepu = p_saxis[0] * xscaleinv;
d_tdivzstepu = p_taxis[0] * xscaleinv;
 
d_sdivzstepv = -p_saxis[1] * yscaleinv;
d_tdivzstepv = -p_taxis[1] * yscaleinv;
 
d_zistepu = p_normal[0] * xscaleinv * distinv;
d_zistepv = -p_normal[1] * yscaleinv * distinv;
 
d_sdivzorigin = p_saxis[2] - xcenter * d_sdivzstepu -
ycenter * d_sdivzstepv;
d_tdivzorigin = p_taxis[2] - xcenter * d_tdivzstepu -
ycenter * d_tdivzstepv;
d_ziorigin = p_normal[2] * distinv - xcenter * d_zistepu -
ycenter * d_zistepv;
 
TransformVector (modelorg, p_temp1);
 
sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
(-(cachewidth >> 1) << 16);
tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
(-(sprite_height >> 1) << 16);
 
// -1 (-epsilon) so we never wander off the edge of the texture
bbextents = (cachewidth << 16) - 1;
bbextentt = (sprite_height << 16) - 1;
}
 
 
/*
=====================
D_DrawSprite
=====================
*/
void D_DrawSprite (void)
{
int i, nump;
float ymin, ymax;
emitpoint_t *pverts;
sspan_t spans[MAXHEIGHT+1];
 
sprite_spans = spans;
 
// find the top and bottom vertices, and make sure there's at least one scan to
// draw
ymin = 999999.9;
ymax = -999999.9;
pverts = r_spritedesc.pverts;
 
for (i=0 ; i<r_spritedesc.nump ; i++)
{
if (pverts->v < ymin)
{
ymin = pverts->v;
minindex = i;
}
 
if (pverts->v > ymax)
{
ymax = pverts->v;
maxindex = i;
}
 
pverts++;
}
 
ymin = ceil (ymin);
ymax = ceil (ymax);
 
if (ymin >= ymax)
return; // doesn't cross any scans at all
 
cachewidth = r_spritedesc.pspriteframe->width;
sprite_height = r_spritedesc.pspriteframe->height;
cacheblock = (byte *)&r_spritedesc.pspriteframe->pixels[0];
 
// copy the first vertex to the last vertex, so we don't have to deal with
// wrapping
nump = r_spritedesc.nump;
pverts = r_spritedesc.pverts;
pverts[nump] = pverts[0];
 
D_SpriteCalculateGradients ();
D_SpriteScanLeftEdge ();
D_SpriteScanRightEdge ();
D_SpriteDrawSpans (sprite_spans);
}
 
/contrib/other/sdlquake-1.0.9/d_surf.c
0,0 → 1,335
/*
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.
 
*/
// d_surf.c: rasterization driver surface heap manager
 
#include "quakedef.h"
#include "d_local.h"
#include "r_local.h"
 
float surfscale;
qboolean r_cache_thrash; // set if surface cache is thrashing
 
int sc_size;
surfcache_t *sc_rover, *sc_base;
 
#define GUARDSIZE 4
 
 
int D_SurfaceCacheForRes (int width, int height)
{
int size, pix;
 
if (COM_CheckParm ("-surfcachesize"))
{
size = Q_atoi(com_argv[COM_CheckParm("-surfcachesize")+1]) * 1024;
return size;
}
size = SURFCACHE_SIZE_AT_320X200;
 
pix = width*height;
if (pix > 64000)
size += (pix-64000)*3;
 
return size;
}
 
void D_CheckCacheGuard (void)
{
byte *s;
int i;
 
s = (byte *)sc_base + sc_size;
for (i=0 ; i<GUARDSIZE ; i++)
if (s[i] != (byte)i)
Sys_Error ("D_CheckCacheGuard: failed");
}
 
void D_ClearCacheGuard (void)
{
byte *s;
int i;
s = (byte *)sc_base + sc_size;
for (i=0 ; i<GUARDSIZE ; i++)
s[i] = (byte)i;
}
 
 
/*
================
D_InitCaches
 
================
*/
void D_InitCaches (void *buffer, int size)
{
 
if (!msg_suppress_1)
Con_Printf ("%ik surface cache\n", size/1024);
 
sc_size = size - GUARDSIZE;
sc_base = (surfcache_t *)buffer;
sc_rover = sc_base;
sc_base->next = NULL;
sc_base->owner = NULL;
sc_base->size = sc_size;
D_ClearCacheGuard ();
}
 
 
/*
==================
D_FlushCaches
==================
*/
void D_FlushCaches (void)
{
surfcache_t *c;
if (!sc_base)
return;
 
for (c = sc_base ; c ; c = c->next)
{
if (c->owner)
*c->owner = NULL;
}
sc_rover = sc_base;
sc_base->next = NULL;
sc_base->owner = NULL;
sc_base->size = sc_size;
}
 
/*
=================
D_SCAlloc
=================
*/
surfcache_t *D_SCAlloc (int width, int size)
{
surfcache_t *new;
qboolean wrapped_this_time;
 
if ((width < 0) || (width > 256))
Sys_Error ("D_SCAlloc: bad cache width %d\n", width);
 
if ((size <= 0) || (size > 0x10000))
Sys_Error ("D_SCAlloc: bad cache size %d\n", size);
size = (int)&((surfcache_t *)0)->data[size];
size = (size + 3) & ~3;
if (size > sc_size)
Sys_Error ("D_SCAlloc: %i > cache size",size);
 
// if there is not size bytes after the rover, reset to the start
wrapped_this_time = false;
 
if ( !sc_rover || (byte *)sc_rover - (byte *)sc_base > sc_size - size)
{
if (sc_rover)
{
wrapped_this_time = true;
}
sc_rover = sc_base;
}
// colect and free surfcache_t blocks until the rover block is large enough
new = sc_rover;
if (sc_rover->owner)
*sc_rover->owner = NULL;
while (new->size < size)
{
// free another
sc_rover = sc_rover->next;
if (!sc_rover)
Sys_Error ("D_SCAlloc: hit the end of memory");
if (sc_rover->owner)
*sc_rover->owner = NULL;
new->size += sc_rover->size;
new->next = sc_rover->next;
}
 
// create a fragment out of any leftovers
if (new->size - size > 256)
{
sc_rover = (surfcache_t *)( (byte *)new + size);
sc_rover->size = new->size - size;
sc_rover->next = new->next;
sc_rover->width = 0;
sc_rover->owner = NULL;
new->next = sc_rover;
new->size = size;
}
else
sc_rover = new->next;
new->width = width;
// DEBUG
if (width > 0)
new->height = (size - sizeof(*new) + sizeof(new->data)) / width;
 
new->owner = NULL; // should be set properly after return
 
if (d_roverwrapped)
{
if (wrapped_this_time || (sc_rover >= d_initial_rover))
r_cache_thrash = true;
}
else if (wrapped_this_time)
{
d_roverwrapped = true;
}
 
D_CheckCacheGuard (); // DEBUG
return new;
}
 
 
/*
=================
D_SCDump
=================
*/
void D_SCDump (void)
{
surfcache_t *test;
 
for (test = sc_base ; test ; test = test->next)
{
if (test == sc_rover)
Sys_Printf ("ROVER:\n");
printf ("%p : %i bytes %i width\n",test, test->size, test->width);
}
}
 
//=============================================================================
 
// if the num is not a power of 2, assume it will not repeat
 
int MaskForNum (int num)
{
if (num==128)
return 127;
if (num==64)
return 63;
if (num==32)
return 31;
if (num==16)
return 15;
return 255;
}
 
int D_log2 (int num)
{
int c;
c = 0;
while (num>>=1)
c++;
return c;
}
 
//=============================================================================
 
/*
================
D_CacheSurface
================
*/
surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel)
{
surfcache_t *cache;
 
//
// if the surface is animating or flashing, flush the cache
//
r_drawsurf.texture = R_TextureAnimation (surface->texinfo->texture);
r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]];
r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]];
r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]];
r_drawsurf.lightadj[3] = d_lightstylevalue[surface->styles[3]];
//
// see if the cache holds apropriate data
//
cache = surface->cachespots[miplevel];
 
if (cache && !cache->dlight && surface->dlightframe != r_framecount
&& cache->texture == r_drawsurf.texture
&& cache->lightadj[0] == r_drawsurf.lightadj[0]
&& cache->lightadj[1] == r_drawsurf.lightadj[1]
&& cache->lightadj[2] == r_drawsurf.lightadj[2]
&& cache->lightadj[3] == r_drawsurf.lightadj[3] )
return cache;
 
//
// determine shape of surface
//
surfscale = 1.0 / (1<<miplevel);
r_drawsurf.surfmip = miplevel;
r_drawsurf.surfwidth = surface->extents[0] >> miplevel;
r_drawsurf.rowbytes = r_drawsurf.surfwidth;
r_drawsurf.surfheight = surface->extents[1] >> miplevel;
//
// allocate memory if needed
//
if (!cache) // if a texture just animated, don't reallocate it
{
cache = D_SCAlloc (r_drawsurf.surfwidth,
r_drawsurf.surfwidth * r_drawsurf.surfheight);
surface->cachespots[miplevel] = cache;
cache->owner = &surface->cachespots[miplevel];
cache->mipscale = surfscale;
}
if (surface->dlightframe == r_framecount)
cache->dlight = 1;
else
cache->dlight = 0;
 
r_drawsurf.surfdat = (pixel_t *)cache->data;
cache->texture = r_drawsurf.texture;
cache->lightadj[0] = r_drawsurf.lightadj[0];
cache->lightadj[1] = r_drawsurf.lightadj[1];
cache->lightadj[2] = r_drawsurf.lightadj[2];
cache->lightadj[3] = r_drawsurf.lightadj[3];
 
//
// draw and light the surface texture
//
r_drawsurf.surf = surface;
 
c_surf++;
R_DrawSurface ();
 
return surface->cachespots[miplevel];
}
 
 
/contrib/other/sdlquake-1.0.9/d_vars.c
0,0 → 1,50
/*
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_vars.c: global refresh variables
 
#include "quakedef.h"
 
#if !id386
 
// all global and static refresh variables are collected in a contiguous block
// to avoid cache conflicts.
 
//-------------------------------------------------------
// global refresh variables
//-------------------------------------------------------
 
// FIXME: make into one big structure, like cl or sv
// FIXME: do separately for refresh engine and driver
 
float d_sdivzstepu, d_tdivzstepu, d_zistepu;
float d_sdivzstepv, d_tdivzstepv, d_zistepv;
float d_sdivzorigin, d_tdivzorigin, d_ziorigin;
 
fixed16_t sadjust, tadjust, bbextents, bbextentt;
 
pixel_t *cacheblock;
int cachewidth;
pixel_t *d_viewbuffer;
short *d_pzbuffer;
unsigned int d_zrowbytes;
unsigned int d_zwidth;
 
#endif // !id386
 
/contrib/other/sdlquake-1.0.9/d_varsa.S
0,0 → 1,213
/*
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.
 
*/
//
// d_varsa.s
//
 
#include "asm_i386.h"
#include "quakeasm.h"
#include "asm_draw.h"
#include "d_ifacea.h"
 
#if id386
 
.data
 
//-------------------------------------------------------
// global refresh variables
//-------------------------------------------------------
 
// FIXME: put all refresh variables into one contiguous block. Make into one
// big structure, like cl or sv?
 
.align 4
.globl C(d_sdivzstepu)
.globl C(d_tdivzstepu)
.globl C(d_zistepu)
.globl C(d_sdivzstepv)
.globl C(d_tdivzstepv)
.globl C(d_zistepv)
.globl C(d_sdivzorigin)
.globl C(d_tdivzorigin)
.globl C(d_ziorigin)
C(d_sdivzstepu): .single 0
C(d_tdivzstepu): .single 0
C(d_zistepu): .single 0
C(d_sdivzstepv): .single 0
C(d_tdivzstepv): .single 0
C(d_zistepv): .single 0
C(d_sdivzorigin): .single 0
C(d_tdivzorigin): .single 0
C(d_ziorigin): .single 0
 
.globl C(sadjust)
.globl C(tadjust)
.globl C(bbextents)
.globl C(bbextentt)
C(sadjust): .long 0
C(tadjust): .long 0
C(bbextents): .long 0
C(bbextentt): .long 0
 
.globl C(cacheblock)
.globl C(d_viewbuffer)
.globl C(cachewidth)
.globl C(d_pzbuffer)
.globl C(d_zrowbytes)
.globl C(d_zwidth)
C(cacheblock): .long 0
C(cachewidth): .long 0
C(d_viewbuffer): .long 0
C(d_pzbuffer): .long 0
C(d_zrowbytes): .long 0
C(d_zwidth): .long 0
 
 
//-------------------------------------------------------
// ASM-only variables
//-------------------------------------------------------
.globl izi
izi: .long 0
 
.globl pbase, s, t, sfracf, tfracf, snext, tnext
.globl spancountminus1, zi16stepu, sdivz16stepu, tdivz16stepu
.globl zi8stepu, sdivz8stepu, tdivz8stepu, pz
s: .long 0
t: .long 0
snext: .long 0
tnext: .long 0
sfracf: .long 0
tfracf: .long 0
pbase: .long 0
zi8stepu: .long 0
sdivz8stepu: .long 0
tdivz8stepu: .long 0
zi16stepu: .long 0
sdivz16stepu: .long 0
tdivz16stepu: .long 0
spancountminus1: .long 0
pz: .long 0
 
.globl izistep
izistep: .long 0
 
//-------------------------------------------------------
// local variables for d_draw16.s
//-------------------------------------------------------
 
.globl reciprocal_table_16, entryvec_table_16
// 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9, 1/10, 1/11, 1/12, 1/13,
// 1/14, and 1/15 in 0.32 form
reciprocal_table_16: .long 0x40000000, 0x2aaaaaaa, 0x20000000
.long 0x19999999, 0x15555555, 0x12492492
.long 0x10000000, 0xe38e38e, 0xccccccc, 0xba2e8ba
.long 0xaaaaaaa, 0x9d89d89, 0x9249249, 0x8888888
 
#ifndef NeXT
.extern Entry2_16
.extern Entry3_16
.extern Entry4_16
.extern Entry5_16
.extern Entry6_16
.extern Entry7_16
.extern Entry8_16
.extern Entry9_16
.extern Entry10_16
.extern Entry11_16
.extern Entry12_16
.extern Entry13_16
.extern Entry14_16
.extern Entry15_16
.extern Entry16_16
#endif
 
entryvec_table_16: .long 0, Entry2_16, Entry3_16, Entry4_16
.long Entry5_16, Entry6_16, Entry7_16, Entry8_16
.long Entry9_16, Entry10_16, Entry11_16, Entry12_16
.long Entry13_16, Entry14_16, Entry15_16, Entry16_16
 
//-------------------------------------------------------
// local variables for d_parta.s
//-------------------------------------------------------
.globl DP_Count, DP_u, DP_v, DP_32768, DP_Color, DP_Pix, DP_EntryTable
DP_Count: .long 0
DP_u: .long 0
DP_v: .long 0
DP_32768: .single 32768.0
DP_Color: .long 0
DP_Pix: .long 0
 
 
#ifndef NeXT
.extern DP_1x1
.extern DP_2x2
.extern DP_3x3
.extern DP_4x4
#endif
 
DP_EntryTable: .long DP_1x1, DP_2x2, DP_3x3, DP_4x4
 
//
// advancetable is 8 bytes, but points to the middle of that range so negative
// offsets will work
//
.globl advancetable, sstep, tstep, pspantemp, counttemp, jumptemp
advancetable: .long 0, 0
sstep: .long 0
tstep: .long 0
 
pspantemp: .long 0
counttemp: .long 0
jumptemp: .long 0
 
// 1/2, 1/3, 1/4, 1/5, 1/6, and 1/7 in 0.32 form
.globl reciprocal_table, entryvec_table
reciprocal_table: .long 0x40000000, 0x2aaaaaaa, 0x20000000
.long 0x19999999, 0x15555555, 0x12492492
 
#ifndef NeXT
.extern Entry2_8
.extern Entry3_8
.extern Entry4_8
.extern Entry5_8
.extern Entry6_8
.extern Entry7_8
.extern Entry8_8
#endif
 
entryvec_table: .long 0, Entry2_8, Entry3_8, Entry4_8
.long Entry5_8, Entry6_8, Entry7_8, Entry8_8
 
#ifndef NeXT
.extern Spr8Entry2_8
.extern Spr8Entry3_8
.extern Spr8Entry4_8
.extern Spr8Entry5_8
.extern Spr8Entry6_8
.extern Spr8Entry7_8
.extern Spr8Entry8_8
#endif
.globl spr8entryvec_table
spr8entryvec_table: .long 0, Spr8Entry2_8, Spr8Entry3_8, Spr8Entry4_8
.long Spr8Entry5_8, Spr8Entry6_8, Spr8Entry7_8, Spr8Entry8_8
 
#endif // id386
 
/contrib/other/sdlquake-1.0.9/d_zpoint.c
0,0 → 1,47
/*
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.
 
*/
// d_zpoint.c: software driver module for drawing z-buffered points
 
#include "quakedef.h"
#include "d_local.h"
 
 
/*
=====================
D_DrawZPoint
=====================
*/
void D_DrawZPoint (void)
{
byte *pdest;
short *pz;
int izi;
pz = d_pzbuffer + (d_zwidth * r_zpointdesc.v) + r_zpointdesc.u;
pdest = d_viewbuffer + d_scantable[r_zpointdesc.v] + r_zpointdesc.u;
izi = (int)(r_zpointdesc.zi * 0x8000);
 
if (*pz <= izi)
{
*pz = izi;
*pdest = r_zpointdesc.color;
}
}
 
/contrib/other/sdlquake-1.0.9/data/COMEXP.TXT
0,0 → 1,487
COMMERCIAL EXPLOITATION LICENSE AGREEMENT FOR QUAKE
 
This Commercial Exploitation License Agreement for QUAKE
(the "Agreement") is between Id Software, Inc., a Texas
Corporation, (hereinafter "Id Software") and Licensee (as described
on the signature page hereof) and is made effective beginning on
the date of last signature hereto (the "Effective Date").
 
R E C I T A L S
 
WHEREAS, Id Software is the owner and developer of the
computer software game entitled QUAKE;
 
WHEREAS, Id Software desires to license certain
non-exclusive rights regarding QUAKE to Licensee; and
 
WHEREAS, Licensee desires to receive a license for such
rights.
 
T E R M S A N D C O N D I T I O N S
NOW, THEREFORE, for and in consideration of the mutual
premises contained herein and for other good and valuable
consideration, the receipt and sufficiency of which is hereby
acknowledged, the undersigned parties do hereby agree as follows:
 
1. DEFINITIONS. As used in this Agreement, the parties
hereto agree the words set forth below shall have the specified
meanings:
 
a. "Authorized Copy" shall mean one (1) copy of the
Subject Game actually purchased by Licensee from an
Id Software approved retailer; and
 
b. "Subject Game" shall mean the full registered
version of QUAKE on a CD-ROM and shall not mean the
shareware or any other version.
 
2. GRANT OF RIGHTS. Id Software hereby grants to
Licensee and Licensee hereby accepts, subject to the provisions and
conditions hereof, a world-wide (except as otherwise provided
herein), non-exclusive, non-transferable, and non-assignable
license to:
 
a. publicly display an Authorized Copy in exchange for
rental payment;
 
b. run the Authorized Copy so that it will accept
network/modem connections in exchange for payments
from end-users who also must have actually purchased
an Authorized Copy; and
 
c. otherwise commercially exploit an Authorized Copy,
except that Licensee shall not copy, reproduce,
manufacture or distribute the Authorized Copy.
 
3. RESERVATION OF RIGHTS AND PROHIBITIONS. Id Software
expressly reserves all rights not granted herein. Under no
circumstances shall Licensee copy, reproduce, manufacture or
distribute (free of charge or otherwise) the Authorized Copy or the
Subject Game. Licensee shall not reverse engineer, decompile,
disassemble, modify or alter the Authorized Copy. Licensee is not
receiving any rights hereunder regarding the Trademark or any
artwork, sound, music or other element of the Subject Game.
 
4. OWNERSHIP. Title to and all ownership rights in and
to the Subject Game, and the QUAKE Trademark (the "Trademark") and
the copyrights, trademarks, patents and other intellectual property
rights related thereto shall remain with Id Software which shall have
the exclusive right to protect the same by copyright or otherwise.
Licensee shall have no ownership rights in or to the Subject Game or
the Trademark and Licensee shall not own any intellectual property
rights regarding the Authorized Copy, including, without limitation,
the copyright regarding the Authorized Copy. Licensee acknowledges
that it only has a limited license to use the Authorized Copy, as
specified in that certain QUAKE Enduser License contained within the
Authorized Copy and as specified in this Agreement.
 
5. TERM AND TERMINATION.
 
a. The term of this Agreement and the license granted
herein begins on the Effective Date and shall expire on a date one
(1) calendar year from the Effective Date.
 
b. Either party may terminate this Agreement, for any
reason or no reason, on thirty (30) days written notice to the
other party. Termination will be effective on the thirtieth (30th)
day following delivery of the described notice. Notwithstanding
anything to the contrary herein, this Agreement shall immediately
terminate, without the requirement of any notice from Id Software
to Licensee, upon the occurrence of any of the following: (a) if
Licensee shall file a petition in bankruptcy or make an assignment
for the benefit of creditors, or if any bankruptcy proceeding or
assignment for benefit of creditors, shall be commenced against
Licensee and not be dismissed within sixty (60) days after the date
of its commencement; (b) the insolvency of Licensee; (c) the
cessation by Licensee of its business; or (d) the cessation by
Licensee, without the prior written consent of Id Software of the
distribution, manufacture, and sale responsibilities embodied
herein. Further, Id Software may elect to terminate this Agreement
upon the occurrence of any of the following: (1) if Licensee's
business operations are interrupted for forty (40) consecutive
calendar days; or (2) if each of two Id Software audit inspections
during any eighteen (18) month period demonstrates an
understatement by Licensee of Royalty payments due Id Software for
the six (6) month period immediately preceding each such inspection
of five percent (5%) or more. Upon the occurrence of such
terminating event, and the election of Id Software, if necessary,
to cause such termination, this Agreement and any and all rights
thereunder shall terminate without prejudice to any rights or
claims Id Software may have, and all rights hereunder shall
thereupon terminate, revert to and be vested in Id Software.
 
6. EFFECT OF TERMINATION OR EXPIRATION. Termination or
expiration of this Agreement, either by Id Software or
automatically, shall not create any liability against Id Software.
Upon expiration or earlier termination of this Agreement, Licensee
shall have no further right to exercise the rights licensed
hereunder or otherwise acquired in relation to this Agreement.
 
7. INDEMNIFICATION. Licensee hereby agrees to
indemnify, hold harmless and defend Id Software and Id Software's
predecessors, successors, assigns, officers, directors,
shareholders, employees, agents, representatives, licensees,
sublicensees, distributors, attorneys and accountants
(collectively, the "Id Related Parties") from and against any and
all damages, claims, losses, causes of action, liabilities,
lawsuits, judgments and expenses (including, without limitation,
reasonable attorneys' fees and expenses) arising from, relating to
or in connection with a breach of this Agreement by Licensee and
arising from, relating to or in connection with the Licensee's use
or non-use of the Authorized Copy (collectively, the "Claims"). Id
Software agrees to notify Licensee of any such Claims within a
reasonable time after Id Software learns of same. Licensee, at its
own expense, shall defend Id Software and the Id Related Parties
from any and all Claims. Id Software and the Id Related Parties
reserve the right to participate in any defense of the Claims with
counsel of their choice, and at their own expense. In the event
Licensee fails to provide a defense, then Licensee shall be
responsible for paying the attorneys' fees and expenses incurred by
Id Software and the Id Related Parties regarding the defense of the
Claims. Id Software and the Id Related Parties, as applicable,
agree to reasonably assist in the defense of the Claims. No
settlement by Licensee of any Claims shall be valid unless Licensee
receives the prior written consent of Id Software and the Id
Related Parties, as applicable, to any such settlement.
 
8. CONFIDENTIALITY. It is understood and agreed that
any proprietary information of Id Software that may from time to
time be made available or become known to Licensee is to be treated
as confidential, is to be used solely in connection with Licensee's
performance under this Agreement, and is to be disclosed only to
employees of Licensee who have a need for access. Such proprietary
information shall include, but not be limited to, trade secrets,
release information, financial information, personnel information,
and the like. Reasonable measures shall be taken by Licensee to
protect the confidentiality of Id Software's proprietary
information and any memoranda or papers containing proprietary
information of Id Software's that Licensee may receive are to be
returned to Id Software upon request. Licensee's obligations and
duties under this paragraph shall survive expiration or earlier
termination of this Agreement. Licensee shall obtain from its
employees an undertaking in a form which may be supplied by Id
Software, and which is subject to Id Software's prior written
approval, not to use or disclose to any third party any information
or knowledge concerning the business of Id Software which may be
communicated to such employees.
 
9. LIMITATION OF LIABILITY. ID SOFTWARE EXPRESSLY
DISCLAIMS ALL WARRANTIES NOT PROVIDED BY ID SOFTWARE HEREUNDER.
UNDER NO CIRCUMSTANCES SHALL ID SOFTWARE BE LIABLE TO LICENSEE FOR
ACTUAL, SPECIAL, INCIDENTAL, CONSEQUENTIAL OR PUNITIVE DAMAGES OR
ANY OTHER DAMAGES, WHETHER OR NOT ID SOFTWARE RECEIVES NOTICE OF
ANY SUCH DAMAGES.
 
10. COMPLIANCE WITH APPLICABLE LAWS. In performing
under this Agreement, Licensee agrees to comply with all applicable
laws, [including, without limitation, 22 U.S.C., 2778 and 22
U.S.C. C.F.R. Parts 120-130 (1995)] regulations, ordinances and
statutes, including, but not limited to, the import/export laws and
regulations of the United States and its governmental and
regulatory agencies (including, without limitation, the Bureau of
Export Administration and the U.S. Department of Commerce) and all
applicable international treaties and laws. Further, Licensee
shall defend, indemnify and hold harmless Id Software from any and
all sales tax, tariffs and/or duties in connection with Licensee's
performance hereunder.
 
11. SPECIFIC UNDERTAKINGS BY LICENSEE. In addition to
the obligations of Licensee otherwise set forth in this Agreement,
during the term of this Agreement, and thereafter where specified,
Licensee agrees that:
 
a. It will not attack the title of Id Software to the
Subject Game or the Trademark and any copyright, patent or
trademark or other intellectual property right related thereto and
it will not attack the validity of the license granted hereunder
during the term hereof or thereafter; and
 
b. It will promptly inform Id Software of any
unauthorized use of the Authorized Copy, the Subject Game and the
Trademark and any portions thereof and reasonably assist Id
Software in the enforcement of any rights Id Software may have
against such unauthorized users.
 
12. FINANCIAL OBLIGATIONS AND ACCOUNTING.
 
a. Payment of Royalties. Licensee agrees to pay Id
Software a royalty ("Royalty") at the rate of twelve and one-half
percent (12.5%) of Net Income. The term "Net Income" shall mean
all revenue received by Licensee from the commercial use of the
Authorized Copy, less only Licensee's actual, documented costs
relating directly to such use. A Royalty shall only be due for
those months in which Licensee's gross revenue from QUAKE
distribution exceeds U.S. Five Thousand Dollars ($5,000.00) and in
such months Licensee shall pay a full Royalty on all revenue
received.
 
b. Rendition of Statements. Licensee shall account to
Id Software with regard to transactions hereunder within forty-five
(45) days following the conclusion of each calendar quarter.
Licensee hereby represents and warrants that such statements of
account to be prepared shall be true and correct. The accounts
shall show in summary form the appropriate calculations relating to
the computation of Royalties, if any. The statements shall also
show the gross revenue received by Licensee per month. The
Royalties payable to Id Software hereunder shall be remitted with
the particular statement indicating such amount to be due. All
statements hereunder shall be deemed rendered when deposited,
postage prepaid, in the United States mail, addressed to Id
Software at Id Software's address set forth on the signature page
hereof.
 
c. Books of Account and Audits. Licensee shall keep
books of account relating to the commercial use of the Authorized
Copy on the basis of generally accepted accounting principles and
shall maintain such books of account for a period of at least two
(2) years after the expiration or earlier termination of this
Agreement; provided, however, that Licensee shall not be required
to keep such records longer than seven (7) years from their date of
origination. Id Software may, upon reasonable notice and at its
own expense, audit the applicable records at Licensee's office, in
order to verify statements rendered hereunder. Any such audit
shall take place during reasonable business hours and in such
manner so as not to interfere with Licensee's normal business
activities. Id Software agrees that such information inspected
and/or copied on behalf of Id Software hereunder shall be used only
for the purpose of determining the accuracy of the statements, and
shall be revealed only to such officers, directors, employees,
agents and/or representatives of Id Software as necessary to verify
the accuracy of the statements. If in an audit of Licensee's books
and records it is determined that there is a short fall of ten
percent (10%) or more in Royalties reported for any calendar
quarter, in addition to payment of such short fall and interest as
may be due, as provided herein, Licensee shall reimburse Id
Software for the full out-of-pocket costs of the audit including
reasonable travel costs and expenses; provided, however, that the
amount of reimbursement paid by Licensee shall not exceed U.S.
Fifteen Thousand Dollars ($15,000.00) for any audit.
 
d. Payment of the Royalty. Licensee assumes all risks
associated with fluctuations in foreign currency exchange rates.
Licensee shall pay and agrees to pay all sums due Id Software in
United States Dollars. With respect to Royalties due for
commercial use outside the United States, other currencies shall be
exchanged at the expense of Licensee into United States Dollars
using the bid price quoted at the Citibank, N.A. of New York, New
York, for the purchase of United States Dollars at the close of
business on the last day of the calendar quarter during which any
amounts accrue. Payment of the Royalties shall be made in Dallas
County, Texas.
 
e. Interest. If Id Software does not receive the
applicable Royalty payment on or before the due date of such
payment, Licensee agrees to pay and shall pay interest on Royalties
owed to Id Software from such date as specified in the following
sentence at a rate per annum equal to the Index Rate. For purposes
of clarification, the interest will begin to accrue on the first
(1st) day following the due date of the Royalty payment, unless the
Royalty payment is paid timely. The "Index Rate" shall be the
prime rate as published in The Wall Street Journal's "Money Rates"
table. If multiple prime rates are quoted in the table, then the
highest prime rate will be the Index Rate. In the event that the
prime rate is no longer published in the "Money Rates" table, then
Id Software will choose a substitute Index Rate which is based upon
comparable information. The applicable interest rate will be
determined and take effect on the first day of each month.
 
NOTHING HEREIN SHALL BE CONSTRUED AS A REQUEST OR DEMAND BY
ID SOFTWARE OF INTEREST AT A RATE HIGHER THAN ALLOWED BY APPLICABLE
LAW. IT IS THE INTENT OF THE PARTIES HERETO THAT NO INTEREST BE
CHARGED HEREUNDER WHICH EXCEEDS THE MAXIMUM RATE ALLOWED BY
APPLICABLE LAW. IF THE RATE REFERENCED ABOVE EXCEEDS THE MAXIMUM
RATE ALLOWED BY APPLICABLE LAW, THEN THE INTEREST RATE MADE
APPLICABLE HEREIN SHALL BE THE MAXIMUM RATE ALLOWED BY APPLICABLE
LAW.
 
13. SUBLICENSE. Licensee shall not be entitled to
sublicense any of its rights under this Agreement.
 
14. GOODWILL. Licensee recognizes the great value of
the goodwill associated with the Subject Game and the Trademark,
and acknowledges that such goodwill, now existing and hereafter
created, exclusively belongs to Id Software and that the Trademark
has acquired a secondary meaning in the mind of the public.
 
15. REMEDIES. In the event of a breach of this
Agreement by Id Software, Licensee's sole remedy shall be to
terminate this Agreement. In the event of a breach by Licensee of
this Agreement, Id Software may pursue the remedies to which it is
entitled under applicable law, including, but not limited to,
termination of this Agreement. Licensee agrees that its failure to
comply with the terms of this Agreement upon expiration or earlier
termination hereof or Licensee's unauthorized use of the Authorized
Copy may result in immediate and irreparable damage to Id Software
for which there is no adequate remedy at law, and in the event of
such failure by Licensee, Id Software shall be entitled to
injunctive relief. Pursuit of any remedy by Id Software shall not
constitute a waiver of any other right or remedy of Id Software
under this Agreement or under applicable law. Termination of this
Agreement shall not be a pre-condition to Id Software pursuing its
other remedies for breach.
 
16. LICENSEE'S WARRANTIES. Licensee warrants and
represents that it has full legal rights to enter into this
Agreement and to perform its obligations hereunder and that it will
comply, at all times during the terms of this Agreement, with all
applicable laws, as set forth hereinabove.
 
17. BANKRUPTCY. If Licensee's liabilities exceed its
assets, or if Licensee becomes unable to pay its debts as they
become due or if Licensee files for voluntary bankruptcy, or is
placed in bankruptcy which is not dissolved or dismissed after
thirty (30) days from the petition filing date, or if Licensee
becomes insolvent, or makes an assignment for the benefit of its
creditors or an arrangement pursuant to any bankruptcy laws or if
Licensee discontinues its business or if a receiver is appointed
for its business, this Agreement shall automatically terminate,
without notice, and become null and void; provided, however, all
duties of Licensee upon termination or expiration of this Agreement
shall continue in full force and effect.
 
18. ENTIRE AGREEMENT AND ASSIGNMENT. This Agreement
constitutes the entire understanding between Licensee and Id
Software regarding the Subject Game. Each and every clause of this
Agreement is severable from the whole and shall survive unless the
entire Agreement is declared unenforceable. No prior or present
agreements or representations shall be binding upon any of the
parties hereto unless incorporated in this Agreement. No
modification or change in this Agreement shall be valid or binding
upon the parties unless in writing, executed by the parties to be
bound thereby. This Agreement shall bind and inure to the benefit
of Id Software, its successors and assigns, and Id Software may
assign its rights hereunder, in Id Software's sole discretion.
This Agreement is personal to Licensee, and Licensee shall not
sublicense, assign, transfer, convey nor franchise its rights
granted hereunder.
 
19. CHOICE OF LAW, VENUE AND SERVICE OF PROCESS. This
Agreement shall be construed in accordance with the laws of the
State of Texas and applicable U.S. federal law and all claims
and/or lawsuits in connection with this Agreement must be brought
in Dallas County, Texas. Licensee hereby agrees that service of
process by certified mail to the address set forth below, with
return receipt requested, shall constitute valid service of process
upon Licensee. If for any reason Licensee has moved or cannot be
validly served, then Licensee appoints the Secretary of State of
the state of Texas to accept service of process on Licensee's
behalf.
 
20. EXCUSED PERFORMANCE. Neither party shall be deemed
to be in default of any provision of this Agreement nor be liable
for any delay, failure in performance or interruption of service,
resulting directly or indirectly from acts of God, civil or
military authority, civil disturbance, military action, war,
strikes, other catastrophes or any other similar cause beyond its
reasonable control. Written notice to the non-affected party of any
such condition shall be given by the affected party within ten (10)
days of the event.
 
21. DELIVERY OF NOTICES, AND DELIVERY OF PAYMENTS.
Unless otherwise directed in writing by the parties, all notices
given hereunder and all payments made hereunder shall be sent to
the addresses set forth on the signature page hereof. All
notices, requests, consents and other communications under this
Agreement shall be in writing and shall be deemed to have been
delivered on the date personally delivered or on the date deposited
in the United States Postal Service, postage prepaid, by certified
mail, return receipt requested, or telegraphed and confirmed, or
delivered by electronic facsimile and confirmed. Any notice to Id
Software shall also be sent to its counsel: D. Wade Cloud, Jr.,
Hiersche, Martens, Hayward, Drakeley & Urbach, P.C., 15303 Dallas
Parkway, Suite 700, LB 17, Dallas, Texas 75248.
 
22. NO PARTNERSHIP, ETC. This Agreement does not
constitute and shall not be construed as constituting a partnership
or joint venture between Id Software and Licensee. Neither party
shall have any right to obligate or bind the other party in any
manner whatsoever, and nothing herein contained shall give, or is
intended to give, any rights of any kind to any third persons.
 
23. COUNTERPARTS. This Agreement may be executed in
several counterparts, each of which will be deemed to be an
original, and each of which alone and all of which together, shall
constitute one and the same instrument, but in making proof of this
Agreement it shall not be necessary to produce or account for each
copy of any counterpart other than the counterpart signed by the
party against whom this Agreement is to be enforced. This
Agreement may be transmitted by facsimile, and it is the intent of
the parties for the facsimile of any autograph printed by a
receiving facsimile machine to be an original signature and for the
facsimile and any complete photocopy of the Agreement to be deemed
an original counterpart.
 
24. MEDIATION. If a dispute arises out of or relates to
this Agreement, or a breach of this Agreement, and if the dispute
cannot be settled through direct discussion, then the parties agree
to endeavor to settle the dispute in an amicable manner by
mediation, under the applicable provisions of Section 154.00 et
seq., Texas Civil Practices and Remedies Code, as supplemented by
the rules of the Association of Attorney Mediators.
 
25. SURVIVAL. The following provisions shall survive
the expiration or earlier termination of this Agreement:
paragraphs 4., 7., 8., and the audit rights of Id Software in
paragraph 12.c.
 
26. MISCELLANEOUS.
 
a. All captions in this Agreement are intended solely
for the convenience of the parties, and none shall effect the
meaning or construction of any provision.
 
b. The terms and conditions of this Agreement have been
negotiated fully and freely among the parties. Accordingly, the
preparation of this Agreement by counsel for a given party will not
be material to the construction hereof, and the terms of this
Agreement shall not be strictly construed against such party.
 
By signing in the spaces provided below, the parties have
agreed to all of the terms and conditions set forth in this
Agreement.
 
 
AGREED:
 
LICENSEE:
 
 
Signed:_______________________________
Printed Name:_________________________
Title:________________________________
Address:______________________________
______________________________________
______________________________________
Telephone #: _________________________
Fax #:________________________________
E-Mail Address:_______________________
Date: ________________________________
 
 
AGREED:
 
ID SOFTWARE, INC.
 
 
Signed:_______________________________
Printed Name:_________________________
Title:________________________________
Address:______________________________
______________________________________
______________________________________
Telephone #: _________________________
Fax #:________________________________
E-Mail Address:_______________________
Date: ________________________________
 
 
 
June 10, 1996
 
 
 
COMMERCIAL EXPLOITATION LICENSE AGREEMENT FOR QUAKE
(DWC:dw:3406.0299:dwc\doc:5017)
 
 
/contrib/other/sdlquake-1.0.9/data/HELP.TXT
0,0 → 1,119
TECH SUPPORT
Any of the information listed below could change. Check the id software
Web Site, at www.idsoftware.com, for updates.
 
A. Tech Support Options
id Software does charge for technical support, but we strive to offer
this service at the lowest cost possible. Because volume on the support
lines dictate costs, we periodically adjust our rates for Voice Tech
Support. Check our web site for current pricing.
 
Paying for Voice or Automated Support
1 -- You can get Voice Support using a major credit card for a one-time
shot. The system asks for your credit card number and expiration date,
then pre-authorizes your credit card for the tech support call. You will
only be billed for the number of minutes actually used.
 
2 -- You can assign yourself a rechargeable PIN account. The system prompts
you for your credit card information, and assigns you a PIN account number.
You can use the PIN to access Voice Support, Automated Support and the
Game Hints Line. Once your account runs out, you can charge it up again.
 
3 -- You may also charge up a PIN account using the number 1 (900) call-2-id.
Then call back at 1(800)ID-GAMES (1(800)434-3627), and use your new PIN to
receive all the support and hints you wish.
 
4 -- id Software's Game Hints Line is accessible either using a PIN account
via 1 (800) ID-GAMES (see above), or by calling 1 (900) CALL2-ID, which
places the call on your phone bill.
 
1. Voice Support
Telephone -- 1 (800) id-games
 
Lines Open from 12 noon to 10pm Central Time, 7 Days a
week ($1.75 per minute). Closed some holidays
 
Please have the following information handy.
1. Game title and version number. (The version
number can be found on the end text screen.)
2. Your operating system, processor, processor
speed and amount of RAM.
3. If you are having a sound, video or modem
problem, we need to know the device brand name
and model.
 
2. Automated Support
Telephone -- 1 (800) id-games
 
Lines Open 24 hours a day, 365 days a year, or 366 days
in Leap years ($0.25 per minute)
 
Please have pencil and paper handy.
 
3. E-mail Support
Just send your e-mail to support@idsoftware.com
 
We will do our best to respond within 48 hours after
receiving your e-mail.
 
When sending e-mail, cut and paste the following into your
e-mail message and fill in the blanks:
 
Date:
Name:
Phone number:
E-mail address: (please include this, we redirect tons of mail)
Game Title:
Version #:
Operating system (eg., DOS 6.0 or Windows 95):
Computer type:
Processor type:
Processor speed:
Video card brand and model: (only if video problem)
Audio card brand and model: (only if audio problem)
Modem brand and model: (only if modem problem)
Network card brand and model: (only if netgame problem)
Network configuration (eg., NET.CFG file): (only if netgame problem)
Drivers, protocol stacks, and versions: (eg., lsl v2.14, exp16odi
v2.33, and ipxodi v3.01) (only if netgame problem)
If there were any error messages or fault information, report them
here:
Please state the problem you encountered:
Please state how to reproduce the problem:
 
4. Web Support
Found at www.idsoftware.com
 
Our web support pages provide the same information that's
available via Automated Support, except it's free!
 
5. News Sites
For information, FAQ, or announcements:
rec.games.computer.quake.announce
For editing and hecking Quake-related files:
rec.games.computer.quake.editing
For general Quake discussion:
rec.games.computer.quake.misc
 
6. Game Hints Line
Telephone -- 1 (800) id-games or 1 (900) call-2-id
 
Lines Open 24 hours a day, 365 days a year, or 366 days
in Leap years ($0.85 per minute)
You must be 18 years of age or have parental permission
to call 1 (900) call-2-id.
 
B. In Europe
The help lines in Europe are open 7:30am - 5:00pm GMT,
Monday - Friday.
 
English: +44 01923 209145
German: +44 (0)1923 209151
French: +44 (0)1923 209148
 
C. Problems
If you have an unfavorable experience using our services, please
send e-mail to 911@idsoftware.com. We would also like to hear
from you if you have something positive to share with us. Kindly
include your full name, address, phone number, and the problem
encountered or information you'd like to tell us about.
/contrib/other/sdlquake-1.0.9/data/LICINFO.TXT
0,0 → 1,97
Here is a brief explanation of all the legal mumbo jumbo contained in the
various license agreements that may or may not be part of this package.
 
(This document was designed to be a quick overview of our license terms.
You must refer to the full text of the license for a complete listing of
terms and conditions.)
 
QUAKE SHAREWARE END USER LICENSE (slicnse.txt) or
What You Can and Cannot Do With the Shareware Version of Quake.
 
CAN DO:
-- Play & Enjoy the single player game
-- Setup a shareware version based server on a not-for-profit basis
 
CANNOT DO:
-- Run the game with user developed levels.
-- You may not commercially exploit the shareware version in any way
This specifically excludes retail distribution of the shareware
version. Do not call or e-mail to ask if you can be a retail
distributor of the shareware version -- the answer is no!
-- Commercially exploit any id copyrighted and/or trademarked property.
Example: Game names, logos, graphics, etc.
 
 
QUAKE REGISTERED VERSION END USER LICENSE (rlicnse.txt) or
What You Can and Cannot Do With the Registered Version of Quake.
 
CAN DO:
-- Play & Enjoy the single player game
-- Setup a registered version based server on a not-for-profit basis
-- Develop new levels and/or level creation utilities.
-- Play the game and/or setup a Registered Version based server using
a user-developed level.
 
CANNOT DO:
-- Commercially exploit the Registered Version of Quake in any way;
see commercially exploitation license info below.
-- Commercially exploit any id copyrighted and/or trademarked
property.
Example: Game names, logos, game graphics, etc.
-- Sell user-developed levels and/or tools
 
COMMERCIAL EXPLOITATION LICENSE (comexp.txt -- accompanies Quake
registered version only)
 
If you are interested in trying to make money using the registered version
of Quake (this sort of thing is not allowed using the shareware version) you
must sign our easy-to-digest Commercial Exploitation License.
 
This is a royalty free license that allows you to run Quake for a profit
through a certain monthly gross profit range. If your Quake-related business
becomes successful the agreement brings id into the revenue stream.
 
Basic terms of the commercial exploitation license:
 
-- License grants a royalty free commercial exploitation right for the
registered version of Quake as a whole so long as Quake's monthly gross
revenue is below $5,000.00
 
-- License provides for a 12.5% royalty to be paid to id Software in months
where the licensee's Quake related monthly gross revenue is above $5,000.00
 
-- Royalty is based off net income. Net income is defined as Quake-related
gross income less Quake-related expenses.
 
-- License expressly prohibits commercial exploitation via the sale (retail
or otherwise) of the shareware or registered versions of Quake.
 
-- License expressly prohibits advertising/marketing use of our copyrighted
and/or trademarked properties.
 
To get into bed with us on this deal you must print two (2) copies of the
document named comexp.txt. (You should find comexp.txt somewhere on the
registered version CD.) Sign/fill in the blanks of both copies where
indicated and mail both to:
 
id Software
18601 LBJ #666
Mesquite, TX 75150
Attn: ComExp License
 
We will then countersign the documents and mail one back to you.
 
Two items worth noting here:
 
1. It is VERY IMPORTANT that the information you enter in the signature
block be legible. We prefer it if you enter the info into the blanks before
printing your two copies. If we cannot read your information we will not be
able to return the documents to you.
 
2. The terms of this document are not subject to negotiation. If you cannot
live with the terms spelled out in the agreement do not engage in any
commercial exploitation of Quake and do not sign the document.
 
 
 
/contrib/other/sdlquake-1.0.9/data/MANUAL.TXT
0,0 → 1,1034
Table of Contents
I. THE STORY
A. Background
B. Prelude to Destruction
 
II. INSTALLING QUAKE
A. Installation
B. README.TXT
C. MANUAL.TXT
D. TECHINFO.TXT
 
III. THE BASICS OF PLAY
A. Goal of the Game
B. Skill
C. Episode
D. Getting About
E. Finding Things
 
IV. CONTROLS
A. Keyboard Commands
B. The Main Menu
C. Console
D. Command Line
E. Cheat Codes
 
V. THE GAME
A. The Screen
B. Messages
C Ending a Level
D. Ending a Dimension
 
VI. YOUR NEW ENVIRONMENT
A. Firepower
B. Ammo
C. Power-ups
D. Bad Guys
E. Environmental Hazards and Effects
 
VII. MULTIPLAYER ACTION
A. Cooperative
B. Deathmatch
C. Team Games
 
VIII. COMMONLY ASKED QUESTIONS
 
IX. TECH SUPPORT
A. Tech Support Options
B. In Europe
C. Problems
 
X. LEVELS AND DESIGNERS
 
XI. LEGAL BOILERPLATE
****************
I. THE STORY
A. Background
You get the phone call at 4 a.m. By 5:30 you're in the secret
installation. The commander explains tersely, "It's about the Slipgate
device. Once we perfect these, we'll be able to use them to transport
people and cargo from one place to another instantly.
 
"An enemy codenamed Quake, is using his own slipgates to insert death
squads inside our bases to kill, steal, and kidnap..
 
"The hell of it is we have no idea where he's from. Our top scientists
think Quake's not from Earth, but another dimension. They say Quake's
preparing to unleash his real army, whatever that is.
 
"You're our best man. This is Operation Counterstrike and you're in
charge. Find Quake, and stop him ... or it ... You have full authority
to requisition anything you need. If the eggheads are right, all our
lives are expendable.."
 
B. Prelude to Destruction
While scouting the neighborhood, you hear shots back at the base Damn,
that Quake bastard works fast! He heard about Operation Counterstrike,
and hit first. Racing back, you see the place is overrun. You are almost
certainly the only survivor. Operation Counterstrike is over. Except for
you.
 
You know that the heart of the installation holds a slipgate.
Since Quake's killers came through, it is still set to his dimension.
You can use it to get loose in his hometown. Maybe you can get to the
asshole personally. You pump a round into your shotgun, and get moving.
II. INSTALLING QUAKE
A. Installation
You must install Quake before you can play it. It will not run off the
CD-ROM. Place the CD-ROM into your drive, log on to that drive, and type
'INSTALL'. If you have downloaded Quake via modem, simply go to the
directory you've placed Quake in, unzip it, and type 'INSTALL'.
 
B. README.TXT
After you install Quake, you go right into the README.TXT file, which is
henceforth available in your Quake directory. This is a full listing of
Quake's technical parameters, and is constantly updated with new versions
of Quake. We strongly recommend that after you install Quake, you glance
through README.TXT.
 
You may wish to print this file out, so you can have a copy of it on hand
while playing Quake.
 
C. MANUAL.TXT
Also available in your Quake directory is a file labeled MANUAL.TXT.
This is the file you are now reading.
 
D. TECHINFO.TXT
For those who are more technically inclined, or to fill out a bug report,
check out TECHINFO.TXT. Information on filling out a bug report is located
at the end of TECHINFO.TXT.
 
 
III. THE BASICS OF PLAY
A. Goal of the Game
Quake has two basic goals. First, stay alive. Second, get out of the
place you're in. The first level of each episode ends in a slipgate --
these signify that
you're entering another dimension. When you complete
an entire
dimension (this takes six to eight levels), you'll find a
Rune and another slipgate, which returns you to the start.
 
B. Skill
The start area has three short hallways. The one you go down selects
the Skill you wish to play at.
Easy -- This is meant for little kids and grandmas.
Medium -- Most people should start Quake at Medium skill.
Hard -- Here at id, we play Hard skill, and we think you should too,
once you're ready.
(Nightmare) -- This is so bad that the entry is hidden, so people
won't wander in by accident. If you find it, don't say we didn't warn
you.
 
C. Episode
After the Skill halls, you're in a room with four exits. Each exit
leads to a different military complex, at the end of which is a
slipgate leading to a new dimension. If you have not registered, the
first episode, Dimension of the Doomed, is the only place you can go.
After registration, all four episodes are available. The other three
episodes, in order from second to fourth, are Realm of Black Magic,
Netherworld, and The Elder World.
 
=============================================================================
== TIP -- From episode 1 to episode 4, the dimensions become progressively ==
== more difficult. We suggest you play the episodes in the proper order to ==
== get the maximum fun out of Quake. ==
=============================================================================
 
D. Getting About
The specific keys named below can be changed by using the Configure Keys
Menu. If you have renamed Run as the R key, for instance, then the Shift
key will not double your speed.
Walk
Use the arrow keys or the mouse. To walk steadily forward, hold down
the Forward key (up arrow or center mouse button). Turn left or right
with the left or right arrow keys or sliding your mouse to the left or
right.
Run
Hold down Run (the Shift key) to double your speed.
Jumping
Tap the Jump key (the space bar or Enter key). You jump further if
you're moving forward, and you jump higher if you're moving up a slope at
the time. You'll be surprised at the spots you can reach in a jump. You
can even avoid some attacks by jumping at the right time.
Swimming
When underwater, aim yourself in the direction you wish to go, and
move forward. You have full three-dimensional freedom. Unfortunately,
as in real life, you may lose your bearings while underwater. Use
jump (the space bar or Enter key) to kick straight up towards the
surface. Once on the surface, tread water by holding down jump.
To get out of the drink, swim towards the shore. Once there, use jump
to clamber up. If you're down a well or you can't get a grip, you may
not be able to climb out. There is always another way out, but you may
have to submerge to find it.
Shooting
Tap the Shoot key (the Ctrl key or left mousebutton) to fire. Hold it
down to
keep firing.
Use
Quake has no "Use" function. To push a button or open a door, walk up
to it. To ride a platform up or down, step atop it. If a door won't open
or a platform won't lower, you may need to do something special to
activate it.
Picking up stuff
To pick up items, weapons, and power-ups, walk over them. If you can't
pick up something, it means you already have the maximum possible of
that thing. If it is armor, it means the stuff you're trying to get is
worse than what you now have.
 
E. Finding Things
Buttons and Floorplates
Buttons activate with a touch, and floorplates must be stepped on.
If you see a distinctive-looking button in a spot you cannot reach,
it's probably a shootable button-- fire at it.
Doors
Most doors open at your approach. If one doesn't, seek a button,
floorplate, or key.
Secret Doors
Some doors are camouflaged. Almost all secret doors open when they are
shot or hit with an axe. The rest are opened by hidden pressure plates
or buttons.
Platforms
Most platforms only go up and down, while some follow tracks around
rooms or levels. When you step atop of a platform, it rises to its
full height, and usually only lowers when you step off. Some platforms
must be activated via button or pressure plate.
Pressure Plates & Motion Detectors
Invisible or visible sensors which open doors, unleash traps, warn
monsters, etc.
Uncovering Secrets
Secrets are hidden lots of ways. You might need to shoot a button, kill
a monster, walk through a secret motion detector, etc.
The Secret of Secrets
All secrets in Quake are indicated by clues. Don't waste your time
hacking at every wall. It's much more productive (and fun) to use your
brain and your eyes. Look up. An angled texture, a light shining under
a wall, a strange sound -- anything -- might be the clue. Something
prominent in a room might be decoration ... or it might be the clue.
 
=============================================================================
== TIP -- Bouncing a grenade off a shootable button or secret door won't ==
== open it, but if the grenade's explosion goes off nearby, this may ==
== activate such secrets. ==
=============================================================================
 
IV. CONTROLS
A. Keyboard Commands
By using the key configuration option from the Main Menu, you can
customize the keyboard to suit your fancy, except for the Function keys,
the Escape key, and the ~ (tilde) key.
 
FUNCTION KEYS
Help F1
Save Game F2
Load Game F3
Options Menu F4
Multiplayer Menu F5
Quicksave F6
Quickload F9
Quit to operating system F10
Screenshot F12
 
WEAPONS
Axe 1
Shotgun 2
Double Barrelled Shotgun 3
Nailgun 4
Supernailgun 5
Grenade Launcher 6
Rocket Launcher 7
Thunderbolt 8
Change to next weapon /
 
MOVEMENT
Move / Turn arrow keys
Jump / Swim Space bar or Enter
Run Shift
Sidestep Left . or >
Sidestep Right , or <
Strafe * Alt
Swim Up D
Swim Down C
 
OTHER CONTROLS
Main Menu Escape
Console ~ (tilde)
Look Up A or PgDn
Look Down Z or Del
Center View X or End
Mouse Look ** \ or center mouse button
Keyboard Look *** Ins
 
* Turning right or left sidesteps instead while the Strafe key is pressed.
** Sliding your mouse forward and back looks up and down while the Mouse
Look key is pressed.
*** The walk forward/backpedal arrows will look up and down while the
Keyboard Look key is pressed.
 
B. The Main Menu
Tap the Escape key to pop up the Main Menu. While you are in the menu,
the game is paused.
Use the arrow keys to move the Quake icon up and down the menu. Place
the icon before the desired option, and tap the Enter key. To return to the
Main Menu, tap the Escape key again. To exit the menu and return to the
game, tap the Escape key when you are on the Main Menu.
 
NEW GAME
Discards the game you're playing, and starts anew.
 
MULTIPLAYER
Controls multiplayer game starting and details...
Name
Type your name or alias here, and all messages about you will use
this. So the computer says stuff like, "Josephine rides Bad Bill's
rocket."
Shirt Color
Lets you select your character's uniform color from 14 different
options (numbered 0-13).
Pants Color
As above, but your pants color also determines what team you're on,
if in team play. (After all, pants are more important than shirts.)
Communications Configuration
Takes you to a separate menu on which you can change communications
settings.
Com Port
Selects the COM Port to use for Communications. A null modem or
modem must be connected to this port.
Baud Rate
Selects the COM port baud rate (9600-57600bps). This is NOT the
same as setting the modem speed. The COM port speed must be AT
LEAST the same speed as the modem speed.
Device
Selects the type of connection, either direct (null-modem) or
modem.
Modem Init String
The Initialization string for the modem.
Start a Multiplayer Game
If you want your machine to be the host for a multiplayer game
(Note: if you are starting a listen server, id Software strongly
recommends that the fastest machine act as the host! If you are
playing a game with more than 4 players, we suggest using a
dedicated server as the host!), select this option, and you'll get
the following menu ...
Begin Game
Starts up the game. Now all your friends have to do is log on,
using either "search for local network games" or "join a
running game at..." Multiplayer options (see below).
Maximum Players
You can have up to 16 players. You need at least 2, or it's not
"multiplayer", right?
Game Type
Toggles between cooperative and deathmatch.
Team Color Rules
Toggles between "none" and "no friendly fire". In the latter mode,
your shots won't injure someone wearing the exact same color
pants as you.
Skill
Chooses skill level. Only applicable in a cooperative game.
Frag Limit
From none to 100, in ten-frag increments. When someone reaches
the frag limit, by killing the 40th (or whatever) person, then
the game ends immediately, and final scores are printed. If your
frag limit is none, the game won't end till someone exits the
level or the time limit expires.
Time Limit
From none to 60 minutes, in 10 minute increments. When the time
limit is up, the game ends immediately, and final scores are
printed. If your time limit is none, the game won't end till
someone exits the level or the frag limit is reached.
Start Map
Lets you choose what map you'd like to play on. The top line
gives you the episode name, and the lower line is the level's
name. Note that all levels in Quake are fun to play, but the
episode Deathmatch Arena is composed of special levels that are
solely-designed for deathmatch play. Try them, you'll like them.
Search For Local Network Games
Has your computer look through your network. It will list all the
games it finds on the console, and you can choose to join one of
them by typing connect <server>.
Join A Running Game At ...
Lets you join a game either by typing its net address (for a net
game) or your friend's modem phone number (for a modem game).
If necessary, ensure your modem and network connections are operative
by checking your Communications Configuration menu.
 
SAVE
Brings up a list of saved games. Highlight the desired slot, and tap the
Enter key. Each saved game is identified by the level's name, plus the
proportion of kills you have achieved so far.
LOAD
Brings up a list of saved games. Highlight the desired slot, and tap the
Enter key.
OPTIONS
Miscellaneous game options ...
Configure Keys
Permits you to customize Quake so every action is linked to the
button or key that you prefer.
First, move the cursor (via the arrow keys) to the action you
wish to change. Then tap the Enter key. Now press the key or
button you want to bind to that action. For instance, if you wish
to use the Alt key for Jump, move the cursor to Jump / Swim, tap
the Enter key, then press the Alt key.
Each action can have two different keys assigned to it. If you
already have two keys in an entry, you cannot add more from this
menu.
To clear the keys bound to an action, move the cursor to that
action and tap the Backspace or Delete key instead of the Enter
key. This will clear the keys formerly bound to that action,
leaving it blank.
You can bind any key to an action except Function keys, the
Escape key, and the ~ (tilde) key. "Weird" keys such as Scroll
Lock, Print Screen, etc. may or may not work, depending on your
machine, but why bother?
Attack
Fires your weapon
Change Weapon
Switches to the weapon "above" the one you're now using. Wraps
around to the axe.
Jump / Swim Up
If you're on land, jumps. If you're underwater, kicks you
towards the surface. If you're right at the water's edge, pops
you up out of the water, if you combine it with forward
movement.
Walk Forward
Backpedal
Turn Left
Turn Right
Run
Press this while moving, and you move at double speed.
Step Left
Sidesteps (strafes) left
Step Right
Sidesteps (strafes) right
Sidestep
Press this when using turn left or turn right and you sidestep
(strafe) instead.
Look Up
Lets you angle your view upwards. Your view returns to
horizontal when you start walking forward.
Look Down
Lets you angle your view upwards. Your view returns to
horizontal when you start walking forward.
Center View
If you're looking up or down, returns your view to dead
center.
Mouse Look
Press this to allow your mouse to look up or down (by
sliding it forward and back), and to remain looking up or
down even if you move forward.
Keyboard Look
Press this to use your movement keys to look up or down.
Go To Console
Brings down the Console. Also possible by tapping the
~ (tilde) key.
Reset To Defaults
Everything you've changed in the options menu is reset by
this option. Consider it an "Oops" key.
Screen Size
A slider which enlarges or shrinks your view area. All
Quake's sliders use the right and left arrow keys.
Brightness
Pretty much self-explanatory. Choose a brightness which
doesn't strain your eyes.
Mouse Speed
Adjusts mouse sensitivity. The further you set the slider
to the right, the quicker your mouse reacts.
Music Volume
Self-explanatory
Sound Effects Volume
Self-explanatory
Always Run
When this is selected, you do not need the Run key -- you
are always at double speed.
Invert Mouse Up / Down
This gives your mouse "airplane-style" controls. This means
that pushing the mouse forward "noses down", and pulling it
back "noses up". Some people prefer this control technique.
Lookspring
Returns your view immediately to straight ahead when you
release the look up / down key. Otherwise, you must move
forward for a step or two before your view snaps back.
Lookspring does not work while you are underwater.
Lookstrafe
If you are using the look up / down key, then this option
causes you to sidestep instead of turn when you try to move
left or right.
 
HELP / ORDERING
Lists the default keyboard and mouse commands. Also contains the
information you need to register Quake.
QUIT
Exits Quake at once.
 
=============================================================================
== TIP -- Quake saves your current key configuration when you quit, so ==
== next time you play, you have the same configuration. ==
=============================================================================
 
C. Console
Tap the ~ (tilde) key to bring down the console. As with the Main Menu,
when the console is down, a singleplayer game is paused. A wide variety of
esoteric commands can be entered at the console. If your keyboard has no
~ (tilde), the Options Menu (inside the Main Menu) has a "Console" option.
 
D. Command Line
For special command line parameters, see README.TXT.
 
E. Cheat Codes
id Software, as in our previous games, has removed all cheat codes from
Quake.
 
V. THE GAME
A. The Screen
The large top part of the screen is the view area, in which you see
monsters and architecture. Immediately below is the Inventory, beneath
which is the Status Bar. You can enlarge the viewing area (tap the + key),
so much that it engulfs first the Inventory Bar and then the Status Bar.
The - key shrinks the view area.
 
Inventory Bar
Lists ammo, weapons, deathmatch scores, and power-ups.
The active weapon is lit up. Each weapon has a number by it -- type
the appropriate number key to switch to that weapon.
In addition, this gives the amount of ammo you have of each type,
any keys you possess, and any power=ups currently active. Plus it shows
how many and which of the four Runes you possess.
In Deathmatch, it shows the top four scores in the game.
 
Status Bar
A vital part of the screen. When your armor, hit points, or ammo get
low, the number turns red.
From left to right, the big numbers represent: Armor Points, Health,
and Ammo (of the current weapon). Icons show the Armor Type (green,
yellow, or red), your adorable face, and your Ammo Type).
 
Score Bar
Hold down theTab key to replace the Status Bar with the Score Bar.
This lists the proportion of monsters you've killed, secrets you've
found, and time you've spent, along with the level name.
In Deathmatch, the Score bar lists the top six scorers, along with
their names.
 
B. Messages
Quake talks to you from time to time. Some messages appear at the top of
the screen. These are non-critical, and tell you that you've picked up an
object, or you've died in an interesting fashion. Ignore these messages if
you please.
Certain messages appear inconveniently in the middle of your view. These
are always important, and you do not want to ignore them!
 
D Ending a Level
Once you finish a level, you'll find a slipgate or a distinctive archway
leading to the next level. Pass through to emerge onto a new level.
You start the new level with the same armor, weapons, and ammo you had at
the end of the previous one. If a power-up was active at the end of the
previous level, it is now, sadly, gone. Make the best of it. If your hit
points were over 100 or under 50, they are altered to 100 or 50,
respectively. Otherwise, your hit points are unchanged.
 
D. Ending a Dimension
Once you've finished all the levels in a particular dimension, you return
to the starting hall. New dimensions are started from scratch -- you, your
shotgun, and axe.
 
VI. Your New Environment
A. Firepower
You are blessed with eight different Means o' Mass Destruction. Each has
its place in a balanced diet.
 
Axe
The last resort. Face it -- going toe-to-toe with the uglies in Quake
demonstrates all the good sense of a man parachuting into an alligator
farm.
 
Shotgun
The basic gun, to which all other guns compare favorably.
 
Double-barrelled Shotgun
A worthy weapon with three minor drawbacks: first, it uses up 2 shells
per blast; second, it's slow; third, its shot pattern is very loose at
long range. But in general, once you find this puppy, the other shotgun
starts rusting from disuse.
 
Nailgun
A two-barrel dingus that prickles bad guys with armor-piercing darts,
technically termed "nails".
 
Supernailgun
The great equalizer. Four cyclic barrels that hose out spikes like
crazy. Pro: foes drop like flies. Con: eats ammo like popcorn.
 
Grenade Launcher
Thumps neat exploding bombs into the air. You can even bounce a grenade
off the wall or floor.. When a grenade hits someone, it explodes.
If it misses, the bomb sits on the floor for a moment, then explodes.
Even though I sometimes bounce grenades into myself, this gun's still
my favorite.
 
Rocket Launcher
For when a grenade positively, absolutely, has to be there on time.
 
Thunderbolt
Try it. You'll like it. Use the same technique as watering your
rosebush.
 
Switching Between Weapons
If you are firing a weapon and run out of ammo, Quake automatically
switches you to another weapon. It will never switch to the grenade
launcher or rocket launcher, however, for reasons that ought to be
obvious. So if you're firing away happily and suddenly switch to the
axe, it doesn't mean you're out of all ammo -- you may still have
grenades. But Quake requires you to select such dangerous
explosives on your own.
 
=============================================================================
== TIP -- If you shoot the Thunderbolt underwater, it discharges all its ==
== cells in every direction in a single gigantic KA-ZAP, with you at the ==
== center. Don't try this at home. ==
=============================================================================
 
B. Ammo
The eight weapons use four types of ammo. Each ammo type comes in two
flavors -- small and large. The large boxes carry twice as much as the
small.
 
Shells
For shotguns and double-barrelled shotguns. A small box holds 20.
 
Flechettes
For nailguns and supernailgunss. A small box holds 25.
 
Grenades
For grenade launchers and rocket launchers. A small crate holds 5.
 
Cells
For Mr. Thunderbolt. A small battery has 6 charges, lasting a little
over a second.
 
C. Power-ups
All power-ups except armor burn out after a while, so smoke 'em while you
got 'em.
 
Armor
Comes in three flavors; green, yellow, and red, from weakest to most
powerful.
 
Megahealth
Gives you 100 additional hit points. After a few seconds, all hit points
over 100 start slowing draining away, because it's too much for the human
frame to hold. Still, it's nice while it lasts.
 
Biosuit
lets you breathe underwater and swim through slime without harm. Does
not protect against lava.
 
Ring of Shadows
Renders you almost totally invisible. Only your eyes can be seen.
Monsters don't detect you unless you do something stupid. Like shoot.
 
Pentagram of Protection
Renders you invulnerable.
 
Quad Damage
Magnum upgrade! You now deliver four times the pain!
 
=============================================================================
== TIP -- When quad damage is activated, use the grenade or rocket ==
== launcher with care -- their bursts are four times as deadly to you, as ==
== well as your enemies. ==
=============================================================================
 
D. Bad Guys
Quake critters are extremely tough, but you have the firepower to vent
your grievances on them anyway. Good hunting.
 
Rottweiler
Bad, bad doggie! Play dead! -- blam! -- yipe! Good dog!
 
Grunt
Goons with probes inserted into their pleasure centers; wired up so
when they kill someone, they get paroxysms of ecstasy. In essence,
customized serial killers. Easy to kill, and they tote shotgun shells.
It's like a little Christmas each time you blow a Grunt away!
 
Enforcer (registered only)
Grunt, Mark Two. Recruits who are surlier and beefier than the rest get
outfitted in combat armor and built-in blasters.
 
Knight
Canned meat. Open 'er up and see if it's still fresh.
 
Death Knight (registered only)
This particular canned meat tends to open you up instead.
 
Rotfish (registered only)
Disgusting little critters who dish it out, but can't take it.
 
Zombie
Thou canst not kill that which doth not live. But you can blast it
into chunky kibbles.
 
Scrag
Floats like a butterfly, stings like a bee. Ugly as hell. They're not
real tough, but like to bushwhack you.
 
Ogre
What's worse than a cannibal monster eight feet tall? One with a
chainsaw. And a sack of grenades.
 
Spawn (registered)
A merrily bouncing blob as dangerous to kill as to ignore. Blech.
 
Fiend
In essence, organic buzzsaws, rife with pummeling power!
 
Vore (registered)
A spideresque hybrid horror. Keep your eye on the energy pod he hurls.
 
Shambler
Even other monsters fear him, so expect a clobbering. He shrugs off
explosions. Good luck.
 
=============================================================================
== TIP -- Some weapons are better vs. particular monsters than others. If ==
== a new monster seems real tough, switch weapons. ==
=============================================================================
 
E. Environmental Hazards and Effects
 
Explosions
Radioactive containers are in some military bases. Shooting these
things unleashes a big boom, so be careful -- you may not want to
stand too close in a firefight.
Your own grenades and rockets cause explosions too, of course -- the
blast can hurt you if you're too close.
 
Water
Safe enough unless you stay under so long you start to drown. Come up
for air periodically to prevent this.
 
Slime
Hurts you instantly and keeps on hurting. Stay out of slime unless you
have a very good reason to take a dip.
 
Lava
If you're quick and the lava's shallow, you might escape before you're
burnt to a crisp, but don't bet on it.
 
Traps
Quake has many different traps. Don't be paranoid, because traps aren't
really very common, but be aware of their existence. Traps can't be
classified because they come in many varieties -- monsters in ambush,
spike shooters, crushing walls, trapdoors, etc.
 
Teleporters
These are distinctive in appearance and emit a unique sound. When you
step into a teleporter, you're instantly transported to another
teleporter, or atop a teleport pad. If you teleport directly right atop
of somebody else, he or she is killed instantly.
 
=============================================================================
== TIP -- Monsters are smart enough not to activate their own traps, but ==
== if you activate the traps, the monsters can get caught by them. ==
=============================================================================
 
VII. Multiplayer Action
Quake can be even more fun when you're playing with friends than when
you're playing by yourself.
When you are using the console or Main Menu in multiplayer, the game does
not pause. Irresponsible players and monsters can freely shoot you, and
your only recourse is bloodthirsty vengeance.
The Talk function is useful here. When you talk, the message appears at
the top of all players' screens, preceded by the speaker's name.
To talk, press 'T' and start typing your message. Press ENTER to set
the message to everyone.
To set up, run, or join a multiplayer game, use the Main Menu Multiplayer
option. README.TXT contains details that may be useful if your network or
modem need special configurations.
 
A. Cooperative
In a co-op game, you and your friends work together to finish the level.
When one person exits, everyone else exits too, wherever they might be. If
you are killed in co-op, you reappear at the start area, and have to catch
up to your buddies. Use Talk to find out where they are. See the
Multiplayer options on the Main Menu for more info.
 
B. Deathmatch
In a deathmatch, play is totally cutthroat. No monsters exist, and when
you are killed, you reappear in a random spot. After you pick up an item,
it respawns (i.e. pops back into existence) after a while. (Some items
take longer to respawn than others.) Every time you kill someone, you get
a Frag. The person with the most Frags wins, so wreak slaughter amongst
your pals!
If you kill yourself, whether intentionally or by accident, you lose a
Frag. This includes drowning, getting crushed, and so forth. See the
Multiplayer options on the Main Menu for more info.
 
C. Team Games
Team play is a cool combination of co-op and deathmatch. Each team picks
a "uniform" and everyone on that team changes their color to the team
color. The team with the most Frags wins. See README.TXT or the Main Menu
for details.
 
=============================================================================
== TIP -- if you have the Team Color Rules set to No Friendly Fire, your ==
== weapons won't hurt other players wearing the same color pants as you. ==
== (You can still have differently-colored shirts.) Your shots still wear ==
== down their armor, and your own grenade and rocket explosions still hurt ==
== YOU, just not them. ==
=============================================================================
 
VIII. Commonly Asked Questions
 
Q. I'm stuck. How do I get through the level?
A. Take a stroll around and look for a place you haven't been yet. Sometimes
you have to kill a particular monster in order to progress, so exterminate
them all!
 
Q. How can I find all the secrets?
A. Don't worry about it. You never have to find a secret to finish a level..
Also, some secrets are intentionally hard to find.
 
Q. I've cleared out the whole level, but my monster kill score isn't 100%.
Where are they hiding?
A. Some monsters hide inside secrets, or are released by them. You won't be
able to kill those monsters until you find their secrets. Also, some monsters
might lurk underwater. Good fishing.
 
Q. Don't you worry that Quake teaches people that all problems can be solved
by the misuse of deadly force?
A. No.
 
Q. Did I really see two monsters fighting each other?
A. Probably. Some monsters hate one another almost as much as they hate you.
You can use this to your advantage (exercise left up to the reader).
 
Q. How do I prevent motion sickness when watching Quake?
A. If you're one of the unlucky sufferers from motion sickness in Quake,
we're sorry to say the answer seems to differs from person to person. Try
sitting closer to the screen, or further away. Dim the lights in your room,
or turn them up high. Adjust screen brightness up or down. Take a break from
Quake and rest your eyes every hour or so. One or more of these tricks, or a
combination, ought to work.
 
Q. Are you guys Satan-worshipers?
A. No.
 
IX. Tech Support
Any of the information listed below could change. Check the id software Web
Site, at www.idsoftware.com, for updates.
 
A. Tech Support Options
id Software does charge for technical support, but we strive to offer this
service at the lowest cost possible. Because volume on the support lines
dictates costs, we periodically adjust our rates for Voice Tech Support.
Check our web site for current pricing.
 
Paying for Voice or Automated Support
1 -- You can get Voice Support using a major credit card for a one-time
shot. The system asks for your credit card number and expiration date, then
pre-authorizes your credit card for the tech support call. You will only be
billed for the number of minutes actually used.
 
2 -- You can assign yourself a rechargeable PIN account. The system
prompts you for your credit card information, and assigns you a PIN account
number. You can use the PIN to access Voice Support, Automated Support and
the Game Hints Line. Once your account runs out, you can charge it up
again.
 
3 -- You may also charge up a PIN account using the number
1 (900) call-2-id. Then call back at 1 (800) id-games, and use your
new PIN to receive all the support and hints you wish.
 
Voice Support
Telephone -- 1 (800) id-games
Lines Open from 12 noon to 10pm Central Time
7 Days a week ($1.75 per minute maximum as of this printing)
Closed some holidays
Please have the following information handy.
1. Game title and version number. (The version number can be found in the
lower right-hand corner of the console.)
2. Your operating system, processor, processor speed and amount of RAM.
3. If you are having a sound, video or modem problem, we need to know the
device brand name and model.
 
Automated Support
Telephone -- 1 (800) id-games
Lines Open 24 hours a day, 365 days a year (366 in Leap year)
($0.25 per minute)
Please have pencil and paper handy
 
E-mail Support
Just send your e-mail to support@idsoftware.com
We will respond within 48 hours after receiving your e-mail. When sending
e-mail, cut and paste the following into your e-mail message and fill
in the blanks --
 
Date:
Name:
Phone number:
E-mail address: (please include this, we redirect tons of mail)
Game Title:
Version #:
Operating system (eg., DOS 6.0 or Windows 95):
Computer type:
Processor type:
Processor speed:
Video card brand and model: (only if video problem)
Audio card brand and model: (only if audio problem)
Modem brand and model: (only if modem problem)
Network card brand and model: (only if netgame problem)
Network configuration (eg., NET.CFG file): (only if netgame problem)
Drivers, protocol stacks, and versions: (eg., lsl v2.14, exp16odi
v2.33, and ipxodi v3.01) (only if netgame problem)
If there were any error messages or fault information, report them
here:
Please state the problem you encountered:
Please state how to reproduce the problem:
 
Web Support
Found at www.idsoftware.com
Our web support pages provide the same information that's available via
Automated Support, except it's free!
 
News Sites
For information, FAQ, or announcements, check out
rec.games.computer.quake.announce
 
For editing and hecking Quake-related files, check out
rec.games.computer.quake.editing
 
For general Quake discussion, check out
rec.games.computer.quake.misc
 
Game Hints Line
Telephone -- 1 (800) id-games or 1 (900) call-2-id
Lines Open 24 hours a day, 365 days a year (366 in Leap year)
($0.85 per minute)
 
B. In Europe
Our help lines in Europe are open 7:30am - 5:00pm GMT, Monday - Friday.
 
English: +44 01923 209145
German: +44 (0)1923 209151
French: +44 (0)1923 209148
 
C. Problems
If you have an unfavorable experience using our services, please send
e-mail to support@idsoftware.com. Kindly include your full name,
address, phone number, and the problem encountered.
 
X. LEVELS & DESIGNERS
 
***************************************
The Beginning
start -- Welcome to Quake -- by John Romero
***************************************
Dimension of the Doomed (shareware episode)
e1m1: Slipgate Complex -- by John Romero
e1m2: Castle of the Damned -- by Tim Willits
e1m3: The Necropolis -- by Tim Willits
e1m4: The Grisly Grotto -- by Tim Willits
e1m5: Gloom Keep -- by Tim Willits
e1m6: The Door To Chthon -- by American McGee
e1m7: The House of Chthon -- by American McGee
***************************************
Realm of Black Magic
e2m1: The Installation -- by John Romero
e2m2: Ogre Citadel -- by John Romero
e2m3: Crypt of Decay -- by John Romero
e2m4: The Ebon Fortress -- by John Romero
e2m5: The Wizard's Manse -- by John Romero
e2m6: The Dismal Oubliette -- by John Romero
***************************************
Netherworld
e3m1: Termination Central -- by John Romero
e3m2: The Vaults of Zin -- by American McGee
e3m3: The Tomb of Terror -- by American McGee
e3m4: Satan's Dark Delight -- by American McGee
e3m5: Wind Tunnels --by Tim Willits
e3m6: Chambers of Torment -- by American McGee & Tim Willits
***************************************
The Elder World
e4m1: The Sewage System -- by Tim Willits
e4m2: The Tower of Despair --by Sandy Petersen
e4m3: The Elder God Shrine --by Sandy Petersen
e4m4: The Palace of Hate --by Sandy Petersen
e4m5: Hell's Atrium --by Sandy Petersen
e4m6: The Pain Maze --by Sandy Petersen
e4m7: Azure Agony --by Sandy Petersen
***************************************
The End
end: Shub-Niggurath's Pit --by John Romero
***************************************
The Deathmatch Arenas
dm1: Place of Two Deaths --by Tim Willits
dm2: Claustrophobopolis --by American McGee
dm3: The Abandoned Base --by John Romero
dm4: The Bad Place --by American McGee
dm5: The Cistern --by Tim Willits
dm6: The Dark Zone --by Tim Willits
***************************************
???
Ziggurat Vertigo --by American McGee
Underearth --by Tim Willits
The Haunted Halls -- by American McGee
The Nameless City -- by Sandy Petersen
***************************************
 
XI. Legal Boilerplate
Quake (tm) (c) id Software, Inc. All rights reserved. All trademarks are
the property of their respective companies. For full information on the
legal issues of owning and using Quake, please refer to the files
LICINFO.TXT and ORDER.TXT.
 
The program you've purchased was produced through the effort of many people.
Don't make copies for others who have not paid for the right to the
registered version of Quake. To report copyright violations to the Software
Publishers Association, call 1 (800) 388-PIR8 or write:
 
Software Publishers Association
Suite 901
1101 Connecticut Avenue NW
Washington, DC 20036
 
XII. MUSIC CREDITS
 
Titles of Songs or Themes (C) 1996 TVT/Interscope Records.
All Rights Reserved.
Written by Trent Reznor (C) 1996 Leaving Hope/TVT Music.
ASCAP All Rights Reserved.
 
Note: music is ONLY available on CD. See your local software retailer
or order Quake today at 1-800-idgames!
 
XIII. Thanks
 
id Software would like to give special thanks to:
 
Sean Barrett
Raymond Chen
DJ Delorie
Andy Glew
Lance Hacking
Chris Hecker
Todd Laney
Terje Mathisen
Charles Sandmann
Jon Vondrak
Billy Zelsnack
The GameTech crew
Syntrillium Software for CoolEdit
/contrib/other/sdlquake-1.0.9/data/ORDER.TXT
0,0 → 1,103
ORDERING INFO
To order the full version of Quake (or any other id Software
product) in North America, call our fulfillment center at 1-800-idgames
(1-800-434-3627). Except as noted by our operators, you can expect
Airborne Express afternoon delivery. The price for the full version
of Quake (available on PC CDROM only) is $45, plus $5 shipping, for a
total of $50. Our fulfillment center accepts Visa, Mastercard, and
American Express. You can also fax, mail, or email your order using
the attached forms. The fax number is (317) 361-3710 and the email
address is idsoftware@stream.com. To prepay and order with a check
by mail, send your check and the order form to:
 
id Software
P.O. Box 4500
Crawfordsville, IN 47933
 
To see an electronic catalog of our software, tshirts, hint books, and
other merchandise available, check out the Shopping Maul section of our
website at www.idsoftware.com.
 
INTERNATIONAL ORDERS
Quake is available worldwide as a full retail product. To find out
which local stores carry Quake and other id products, contact the
following international affiliates:
 
Europe Australia
GT Interactive Software Roadshow New Media
1712 583791 (U.K.) 1 902 962000
 
Taiwan Singapore
U.S. Summit Corporation Summit Co. (Singapore) Pte. Ltd.
706-0660 273-9988
 
Malaysia Honk Kong
Summit Co. (Malaysia) Sdn Bhd Tsun Tsun Trading Company
757-2244 571-4231
 
Thailand Israel/Jordan/Lebanon/Egypt
U.S. Summit Corp. (Overseas) Mirage Mulimedia
374-3956 972 3 510 5764
 
If you are in a territory that cannot access 1(800)idgames, and you
wish to order our products directly, you must place your order in
writing to the fax, mail, or email addresses listed above under
ORDERING INFO.
 
International phone orders will NOT be accepted. Unfortunately, due
to international shipping costs, all international orders are sent
out via US Mail. This means we cannot guarantee timeliness of delivery
due to customs and other delays inherent to international shipping
______________________________________________________________________
ORDER FORM -- USE THIS FORM TO FAX , MAIL OR EMAIL YOUR ORDER.
 
id Software Order Center Date ______________
PO BOX 4500 Phone: 1800 id games
Crawfordsville, IN 47933 Fax: (317) 361-3710
idsoftware@stream.com
 
 
Product List and Prices in U.S. Currency: (check items)
 
Quake (CD ROM only) $45 ____
The Ultimate DOOM (Mac version available – must specify) $25 ____
DOOM II (Mac version available – must specify) $40 ____
Master Levels for DOOM II (CD ROM only) $25 ____
Final DOOM (CD ROM only) $40 ____
DOOM Hint Book $15 ____
Original DOOM Tshirt (S,M.L.XL) $13 ____
The Ultimate DOOM Tshirt (XXL only) $13 ____
Final DOOM Tshirt $13 ____
Heretic:Shadow of the Serpent Riders (CD ROM only) $40 ____
Heretic Hint Book $15 ____
Hexen:Beyond Heretic (Mac version available – must specify) $40 ____
Hexen:Deathkings of the Dark Citadel (CD ROM only) $25 ____
Hexen Hint Book $15 ____
Hexen Tshirt (XXL only) $13 ____
Wolfenstein 3D (PC CD only) $20 ____
Commander Keen (3.5 disk only) $15 ____
 
Order total: $______
 
Name: Age (optional):
 
Form of payment (check, money order, or credit card):
 
Credit card number: Expiration Date:
 
Exact mailing address:______________________________________
_______________________________________
_______________________________________
_______________________________________
 
Phone: Fax: Email:
 
Shipping: US orders-$5.00 first product/$2.00 each additional
(allow 3-5 business days)
 
International shipping for prepaid orders are via US Mail, and
we cannot guarantee the time it will take to arrive.
 
*Prices subject to change
 
 
/contrib/other/sdlquake-1.0.9/data/README.TXT
0,0 → 1,456
Welcome to Quake!
 
This file details how to get Quake running on your system and what to do
if you have problems. We would like to thank Gandalf Technologies, Inc and
MPath Interactive for the use of their technology. We would also like to
thank Trent Reznor and Nine Inch Nails for their tremendous contributions
to Quake's entire audio portion.
 
The NIN logo is a Registered Trademark licensed to Nothing Interactive, Inc.
All Rights Reserved.
 
Quake System Requirements
-------------------------
IBM PC and Compatibles
Pentium processor or better
VGA Compatible Display or better
8MB RAM minimum, 16MB recommended (16 MB required for running under Win95)
CD-ROM drive Required
MS-DOS 5.0 or better or Windows 95 (does NOT run under Windows NT)
Hard Drive (30MB for Shareware, 80 MB for Registered)
 
*** IMPORTANT!: Quake requires a floating point processor.
Systems that do not have an FPU installed will not run Quake -- at all.
 
*** IMPORTANT Video Adapter Note! ***
On some ATI Mach32 cards, Quake can come up with a garbled video display.
This is due to a problem with the card in which 320x200 mode isn't
initialized correctly. Workarounds include:
 
1) If running from Windows, start Quake from an icon, or from a windowed
(not fullscreen) MS-DOS prompt. If Quake is already running and has
the garbled screen, press Alt-Enter twice to switch to the desktop and
back to fullscreen, and the screen will display properly.
 
2) If running from DOS, either put the line
 
vid_mode 1
 
in id1\autoexec.cfg, or, typing blind, press tilde ('~') to bring down
the console, type
 
vid_mode 1<enter>
 
and the screen will display properly.
 
========================================================================
Here are the text files included with the shareware release of Quake and
what they are:
 
README.TXT This file
TECHINFO.TXT Technical information on Quake's subsystems and
their advanced use.
MANUAL.TXT Text version of the printed game manual
LICINFO.TXT Info on the various license files included with Quake
SLICNSE.TXT Shareware Quake end-user license
ORDER.TXT How to order Quake
HELP.TXT How to get help with Quake
 
Here are the text files included with the registered version of Quake and
what they are:
 
README.TXT This file
TECHINFO.TXT Technical information on Quake's subsystems and
their advanced use.
MANUAL.TXT Text version of the printed game manual
LICINFO.TXT Info on the various license files included with Quake
RLICNSE.TXT Registered Quake end-user license
COMEXP.TXT Commercial exploitation agreement
ORDER.TXT How to order Quake
HELP.TXT How to get help with Quake
 
 
Running Quake
-------------
 
DOS: To launch Quake from the DOS Prompt, go to the Quake directory and
simply type "QUAKE" <ENTER>. (no quotes)
 
Windows 95: To launch Quake in single player mode, double click on the file
QUAKE.EXE From Windows Explorer. To run Quake in Multi-Player mode using
the TCP/IP protocol, first check your network settings to ensure the
protocol is installed, then double click on the Q95.BAT file to launch the
game. In this version (v0.91) there is a minor bug that will cause the
Q95.BAT file to exit the first time you run it, without running Quake.
Merely double-click on that file again and it will work.
 
Audio Setup
-----------
 
When using a Sound Card with Quake, there are a few setup steps which must
be taken. First, the "BLASTER" environment variable setting must be in your
autoexec.bat (or you can type it in manually from the MS-DOS command prompt).
Running the Sound Blaster utility diagnose.exe will automatically configure
your sound card and put this statement in your autoexec.bat file for you.
A typical blaster setting looks like this (although yours may vary):
 
SET BLASTER=A220 I5 D1 H5 P330 T6
 
If you want to play the audio track from the CD-ROM while playing Quake,
you must ensure that the audio cable from the CD-ROM is connected to the
sound card.
 
If you think your sound card is setup properly and it STILL doesn't work,
check to make sure that your BLASTER environment variable contains the
high DMA setting (H5 in the above example).
 
If you don't get sound while trying to play the audio track, check to see
if a small cable goes from the back of your CD-ROM player directly to your
sound card. If the CD-ROM audio cable is connected to your sound board (or
the motherboard in some cases) and you STILL don't hear CD Audio coming from
your speakers, make sure the MIXER program has the CD volume turned up.
You will also need to run the CD-ROM driver MSCDEX.EXE. Here is an example
of the files you should see (yours probably will vary) listed in your
CONFIG.SYS and AUTOEXEC.BAT (explanation is in parentheses):
 
CONFIG.SYS:
 
DEVICE=C:\PROSCSI\CDROM.SYS /D:PROCD01 (CD-ROM driver)
 
AUTOEXEC.BAT:
 
SET BLASTER=A220 I5 D1 H5 P330 T6 (sound environment variable setting)
C:\WINDOWS\COMMAND\MSCDEX.EXE /D:PROCD01 /L:D (CD-ROM driver)
 
===================================================
UltraSound MAX and UltraSound PnP Support for Quake
===================================================
 
Before running Quake, make sure that your sound card works and your
environment variables are set correctly.
 
Other UltraSound Cards (ACE & Classic)
--------------------------------------
These drivers are not for the UltraSound ACE or UltraSound Classic
sound cards. We have heard mixed reports that MegaEm or SBOS
have a chance of working with the UltraSound Classic but there is a
short sound F/X delay.
 
UltraSound PnP and PnP Pro
--------------------------
You must make sure that you do NOT have IWSBOS or MegaEm loaded.
 
Setup
-----
Quake will automatically detect that the UltraSound Max or PnP
are installed. It does this by looking at the SET INTERWAVE (PnP)
and SET ULTRA16 (Max) environment variables.
 
Quake will use the settings found on the SET ULTRASND/ULTRA16 (Max)
and in the IW.INI (PnP) file to determine what port settings to use.
 
Troubleshooting Windows 95 (DOS Box)
------------------------------------
We recommend that you restart your computer in MS-DOS Mode. DOS Box
may or may not work, so use at your own risk.
 
CD Audio Input
--------------
If you have not already enabled CD audio output by default you will
need to enable it. For the UltraSound MAX you can run "ULTRINIT -EC".
For the UltraSound PnP you will need to enable the CD audio output
in Win'95 and then restart your computer into MS-DOS.
 
===================================================
Mouse Setup
-----------
 
If you are going to use a mouse when playing Quake, you will need to load
your mouse driver. This should go in the AUTOEXEC.BAT file as well. Here
is an example:
 
C:\LOGITECH\MOUSE\MOUSE.EXE (mouse driver)
 
 
Booting Clean
-------------
 
If you are going to be running Quake with only 8 megabytes of RAM, it is best
to boot clean . You eliminate unwanted utilities or applications from taking
up valuable memory, without having to alter your regular AUTOEXEC.BAT and
CONFIG.SYS. Booting clean can be done in one of two ways. If you have
MS-DOS version 6.xx, booting clean is as simple a pressing the shift key
when you see the words "Starting MS-DOS". If you have MS-DOS ver 5.xx you
will need to make a system disk.
 
To make a boot disk, type the following from the MS-DOS command prompt:
 
FORMAT A: /S
 
1. Make sure that this is a disk you wish to erase.
2. This disk absolutely HAS to be formatted in the A: drive.
 
To use the system disk, place the disk in the A: drive and reset the
computer.
 
NOTE: If your sound card requires a driver to be loaded, or you will be
using a mouse, or you will be using Quake's CD audio feature, the system
disk will need to have a CONFIG.SYS and AUTOEXEC.BAT that load the
appropriate drivers.
 
Creating a Quake Shortcut
 
As an alternative to making a Boot Disk, Windows 95 users can create a
Quake Shortcut. By double clicking onthis shortcut, Windows 95 will reboot
in MS-DOS mode and install only the desired drivers, giving you the same
results as using a Boot Disk. To create a Quake Shortcut, do the following:
 
1. Using Explorer, right click and drag the file QUAKE.EXE, from the Quake
directory, to your desktop. Windows 95 will make an MS-DOS Icon titled
"Shortcut to quake".
2. Right click on the new icon, and from the menu that pops up, choose
"Properties". Then choose the "Program" tab at the top.
3. Now click on the "Advanced..." button near the bottom. The "Advanced
Program Settings" window should appear.
4. Select the "MS-DOS mode" check box and the "Specify a new MS-DOS
configuration" option button.
5. Now simply fill in the "CONFIG.SYS for MS-DOS mode:" and "AUTOEXEC.BAT
for MS-DOS mode:" boxes with the same sound, CD-ROM and mouse settings as
mentioned above in the Boot Disks section.
6. Click on "OK" when you are finished. If you wish, you can change your
Quake Shortcut Icon to something a little more exciting by clicking on
"Change Icon...".
7. To finish, click on "OK" again.
8. You can rename your Quake Shortcut by right clicking on the shortcut
icon, choosing "Rename" and typing in the new name.
 
 
======================================================
== Known Problems ==
======================================================
 
Problem: Zombies sometime get stuck on the ground and connot get back up.
(You can still hear them, but you cannot kill them. This bug makes it
impossible to get 100% kills on whatever level it occurs on.)
Solution: There is no workaround for this bug.
 
Problem: It is sometimes possible for the player to get stuck in a room or
in a wall.
Solution: If you get stuck, use the 'kill' console command. It is a good
idea to save your game often.
 
Problem: View centering problems. Sometimes during a game, the view will not
center properly. The end result is the player view looking up torwards the
ceiling while walking.
Solution: Exit to the next level or use the 'kill' console command..
 
 
======================================================
== Troubleshooting ==
======================================================
 
If Quake fails to start up, or has problems not addressed elsewhere in the
documentation, try the -safe command line switch, which disables a number
of parts of Quake that can be problems if there are hardware or configuration
problems. The -safe command line switch is equivalent to -stdvid, -nosound,
-nonet, and -nocdaudio together. Those four switches do the following:
 
-stdvid: disables VESA video modes.
 
-nosound: disables sound card support.
 
-nonet: disables network card support.
 
-nocdaudio: disables CD audio support.
 
If -safe makes the problem go away, try using each of the switches
individually to isolate the area in which you're experiencing the problem,
then either correct the configuration or hardware problem or play Quake with
that functionality disabled.
 
If you still have problems, try booting clean in conjunction with
the -safe command line parameter. For information on booting clean, refer
to the "Booting Clean" section above.
 
If you experience page faults while running Quarterdeck's QDPMI DPMI server,
this is caused by a bug in QDPMI. Workarounds: Remove QDPMI from CONFIG.SYS,
issue the command QDPMI OFF before running QUAKE, or get the update patch
for QDPMI from Quarterdeck. You may be running QDPMI without knowing it if
you have QEMM installed, because it can be installed as part of the QEMM
installation.
 
 
Technical Support
-----------------
 
If you are having trouble installing or running Quake you can receive
technical support by sending e-mailing to support@idsoftware.com. You can
also refer to our web page, www.idsoftware.com, or call 1-800-idgames.
 
When sending support e-mail, cut and paste the following into your e-mail
message and fill in the blanks:
 
Date:
Name:
Phone number:
E-mail address: (please include this, we redirect tons of mail)
Game Title:
Version #:
Operating system (i.e., DOS 6.0 or Windows 95):
Computer type:
BIOS date:
BIOS version:
Processor type:
Processor speed:
Do you program at school/work?
Do you provide tech. support at school/work?
Please state the problem you encountered:
Please state how to reproduce the problem:
 
If program crashed with nasty undecipherable techno-garbage, please
look for the eight-digit hex number which comes after "eip="
and write it down here:
 
** NOTE: If you are sending a bug report, PLEASE refer to the TECHINFO.TXT
file for the correct form and procedures.
 
 
======================================================
== Version History ==
======================================================
v1.01 -- Bugs fixed
------------------------------------------------------
* Fixed modem code
* Fixed fraglimit & timelimit
* Added NOEXIT cvar (so no one can exit a level)
------------------------------------------------------
v1.00 -- Bugs fixed
------------------------------------------------------
* Gravis Ultrasound audio support (still has bugs)
* More deathmatch start spots on E1M6 and END
* Print server version and PROG CRC on connect
* -dedicated starts start.map if nothing else specified
* fixed lookspring function during net game
* fixed rare crash during long running dedicated server
------------------------------------------------------
v0.94 -- Bugs fixed / Features added -- LIMITED BETA VERSION
------------------------------------------------------
* Totally rewritten menus
* New lighting model with overbrighting
* Parsed lowercase BLASTER parms
* Better Sound Blaster shutdown code
* Rewrote BLASTER initialization
* Fixed DMA channel 0 bugs
* Added SBPro 8 stereo setup
* Fix delayed sound on 8 bit Sound Blasters
* Fixed speed key affecting angle-turning from keyboard
* Fixed "no such Alias frame" bugs
* Fixed Zombie not getting up bug
* Checked for very high joystick values, signalling a failed read
* Unstuck jumping Fiends and Spawn
* Fixed large BModels blinking out in complex areas
* Fixed s_localsound with no sound started
* Saved spawn parms in savegame
* Fixed screenshot save location
* Bind with no arguments no longer clears value
* Allow console in intermission / finale
* Fixed false gib messages
* Full-screen TAB scoreboard in DeathMatch
* Fixed "+playdemo <demo>" from command line
* Trapped overflow in sizebuf messages
* Moveup / movedown in water!
* Fixed-up Talk command
* Added unsupported crosshair option ("crosshair 1" from console)
* Colored chat messages with notify sound
* Fixed "connect during intermission" bug
* Changelevel while demos running no longer crashes
* Fixed changelevel with no map left up loading screen
* Fixed long names entered from the console causing crash
* Stopped demos changing while in the menus
 
* Fixed modem initialization from menu
* Fixed serial reliable stream getting stalled
* Serial/modem code fixes
16550a lost transmit buffer empty interrupts
fixed sometimes processing interrupts from com1 when using com2
added com3/com4 support from menus
fixed first character of modem init not getting sent
saved serial/modem settings in config.cfg
* Fixed name and colors not always sent to server at startup
* Fixed "stopdemo" crashing the system when there wasn't a demo playing
* Added server's TCP/IP and IPX addresses (if available) to status command
 
* In 0.92, an additional check for a usable VESA video mode was added;
the numpages field was verified to be greater than 0, and no mode was
supported that had numpages set to 0 (which indicates that there's not
enough video memory for that mode). ATI's VESA driver, m64vbe,
reports 0 for numpages, so VESA video modes that were available in 0.91
were no longer available in 0.92. This extra numpages check has
been removed.
 
-----------------------------------------------------------------------
v0.93 -- Never officially released; internal testing only.
-----------------------------------------------------------------------
v0.92 -- Bugs fixed
-----------------------------------------------------------------------
Typing long strings in the hostname or modem init field in the menus caused
crashes.
 
Under Win95 IPX was detected but not functional, resulting in the game
exiting to DOS.
 
If -nosound, got "S_LocalSound: can't cache" on every keypress in the menu.
 
When vid_nopageflip was set to 1 in VESA modes, going underwater resulted in
only the upper left corner of the drawing area being updated.
 
The single player scoreboard (tab) printed text incorrectly in all modes
greater than 320 pixels wide.
 
On network connections that dropped packets, the reliable message stream
could get stopped up, resulting in frag counts and talk messages no longer
being delivered, although game movement continued.
 
The com port settings from the menu were getting saved & restored but
not used.
 
Direct serial connections did not work with slist.
 
Quake now checks the vesa information for hardware incabable of page-flipping.
 
Menu sound sometimes didn't play.
 
Q95 (qlaunch.exe) frequently failed to execute on the first attempt.
 
Q95 (quakeudp.dll) was running out of buffers when running a server.
 
Teams were not being set according to pants colors.
 
 
Joystick notes
--------------
Your joystick must be plugged in when Quake is launched.
 
If you have a joystick plugged in, but don't want to use it in Quake
(it slows the game down a few percent), or you have weird hardware that
doesn't like being tested as a joystick add "-nojoy" to your Quake
command line.
 
You can turn off joystick reading during the game by typing "joystick 0" at
the Quake command console.
 
You MUST configure your buttons from the configure keys menu before they will
work. There is no default configuration.
 
If your joystick or interface card improperly sets the third or fourth
joystick buttons, type "joybuttons 2" at the quake console or in your
.CFG file.
 
The "mlook" button command now lets the joystick as well as the mouse control
pitch angles.
 
The "sidestep" buttom command works on joysticks as with mice and keyboard
movement.
 
The "invert mouse up/down" menu option also inverts the joystick pitch
direction.
/contrib/other/sdlquake-1.0.9/data/RLICNSE.TXT
0,0 → 1,204
REGISTERED VERSION: QUAKE
LIMITED USE SOFTWARE LICENSE AGREEMENT
 
This Limited Use Software License Agreement (the
"Agreement") is a legal agreement between you, the end-user, and Id
Software, Inc. ("ID"). By continuing the installation of this game
program, by loading or running the game, or by placing or copying
the game program onto your computer hard drive, you are agreeing to
be bound by the terms of this Agreement. If you do not agree to
the terms of this Agreement, promptly return the game program and
the accompanying items (including all written materials), along
with your receipt to the place from where you obtained them for a
full refund.
 
ID SOFTWARE LICENSE
 
1. Grant of License. ID grants to you the limited
right to use one (1) copy of the enclosed or foregoing game program
(the "Software") on a single computer. You have no ownership or
proprietary rights in or to the Software or the written materials
accompanying the Software. For purposes of this section, "use"
means loading the Software into RAM, as well as installation on a
hard disk or other storage device. You may create a map editor,
modify maps and make your own maps (collectively referenced as the
"Permitted Derivative Works") for the Software. Permitted
Derivative Works may not be sold, whether by you or by any other
person or entity, but you may exchange the Permitted Derivative
Works at no charge amongst other end-users. The Software, together
with any archive copy thereof, shall be either returned to ID or
destroyed when no longer used in accordance with this Agreement, or
when the right to use the Software is terminated. You agree that
the Software will not be shipped, transferred or exported into any
country in violation of the U.S. Export Administration Act (or any
other law governing such matters) and that you will not utilize, in
any other manner, the Software in violation of any applicable law.
 
2. Commercial Use is Prohibited. Except as provided in
paragraph 5. hereinbelow in regard to the Software, under no
circumstances shall you, the end-user, be permitted, allowed or
authorized to commercially exploit the Software, any data
comprising the Software. Neither you nor anyone at your direction
shall do any of the following acts (any such acts shall be deemed
void and a breach of this Agreement) with regard to the Software,
or any portion thereof, such as a screen display or a screenshot:
 
a. Rent the Software;
 
b. Sell the Software;
 
c. Lease or lend the Software;
 
d. Offer the Software on a pay-per-play basis;
 
e. Distribute, by electronic means or otherwise, the
Software for money or any other consideration; or
 
f. In any other manner and through any medium
whatsoever commercially exploit the Software or use
the Software for any commercial purpose.
3. Additional Prohibited Uses. Neither you nor anyone
at your direction shall take the following action in regard to the
Software, or any portion thereof, such as a screen display or a
screenshot:
 
a. Modify, disassemble, reverse engineer or decompile
the Software;
 
b. Translate the Software;
 
c. Reproduce the Software;
 
d. Publicly display the Software;
 
e. Prepare derivative works based upon the Software
(except Permitted Derivative Works); or
 
f. Distribute, by electronic means or otherwise, the
Software.
 
4. Use of Other Material is Prohibited. Use, in any manner, of
the trademarks, such as Quake(tm) and the NIN(r) logo, logos, symbols,
art work, images, screen displays or screenshots, sound effects, music,
and other such material contained within, generated by or relating to
the Software is prohibited.
 
5. To Receive Permission to Commercially Exploit. If
you desire to commercially exploit the Software, you may execute
the Commercial Exploitation License Agreement for QUAKE (the
"License") contained within the QUAKE install package and forward
the original License to Id Software at the address noted therein.
Please note that ID may refuse your request and not sign the
License in ID's sole discretion.
 
6. Restrictions Apply to Third Parties. The
prohibitions and restrictions described herein apply to anyone in
possession of the Software and/or Permitted Derivative Works.
 
7. Copyright. The Software and all copyrights related
thereto (including all characters and other images generated by the
Software or depicted in the Software) is owned by ID and is protected
by United States copyright laws and international treaty provisions.
You must treat the Software like any other copyrighted material,
except that you may either (a) make one copy of the Software solely
for back-up or archival purposes, or (b) transfer the Software to a
single hard disk provided you keep the original solely for back-up or
archival purposes. You may not otherwise reproduce, copy or disclose
to others, in whole or in any part, the Software. You may not copy
the written materials accompanying the Software. The same
restrictions and prohibitions regarding your use of the Software as
provided in this Agreement apply to your use of the written materials
accompanying the Software. The written materials are owned by ID and
are protected by United States copyright laws and international
treaties. You agree to use your best efforts to see that any user of
the Software licensed hereunder complies with this Agreement.
 
8. Limited Warranty. ID warrants that if properly
installed and operated on a computer for which it is designed, the
Software will perform substantially in accordance with the
accompanying written materials for a period of ninety (90) days
from the date of purchase of the Software. ID's entire liability
and your exclusive remedy shall be, at ID's option, either (a)
return of the price paid or (b) repair or replacement of the
Software that does not meet ID's Limited Warranty. To make a
warranty claim, return the Software to the point of purchase,
accompanied by proof of purchase, your name, your address, and a
statement of defect, or return the Software with the above
information to ID. This Limited Warranty is void if failure of the
Software has resulted in whole or in part from accident, abuse,
misapplication or violation of this Agreement. Any replacement
Software will be warranted for the remainder of the original
warranty period or thirty (30) days from your receipt of the
replacement software, whichever is longer. This warranty allocates
risks of product failure between Licensee and ID. ID's product
pricing reflects this allocation of risk and the limitations of
liability contained in this warranty.
 
9. NO OTHER WARRANTIES. ID DISCLAIMS ALL OTHER
WARRANTIES, BOTH EXPRESS IMPLIED, INCLUDING BUT NOT LIMITED TO,
IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
PURPOSE WITH RESPECT TO THE SOFTWARE AND THE ACCOMPANYING WRITTEN
MATERIALS. THIS LIMITED WARRANTY GIVES YOU SPECIFIC LEGAL RIGHTS.
YOU MAY HAVE OTHER RIGHTS WHICH VARY FROM JURISDICTION TO
JURISDICTION. ID DOES NOT WARRANT THAT THE OPERATION OF THE
SOFTWARE WILL BE UNINTERRUPTED, ERROR FREE OR MEET LICENSEE'S
SPECIFIC REQUIREMENTS. THE WARRANTY SET FORTH ABOVE IS IN LIEU OF
ALL OTHER EXPRESS WARRANTIES WHETHER ORAL OR WRITTEN. THE AGENTS,
EMPLOYEES, DISTRIBUTORS, AND DEALERS OF ID ARE NOT AUTHORIZED TO
MAKE MODIFICATIONS TO THIS WARRANTY, OR ADDITIONAL WARRANTIES ON
BEHALF OF ID. ADDITIONAL STATEMENTS SUCH AS DEALER ADVERTISING OR
PRESENTATIONS, WHETHER ORAL OR WRITTEN, DO NOT CONSTITUTE
WARRANTIES BY ID AND SHOULD NOT BE RELIED UPON.
 
10. Exclusive Remedies. You agree that your exclusive
remedy against ID, its affiliates, contractors, suppliers, and
agents for loss or damage caused by any defect or failure in the
Software regardless of the form of action, whether in contract,
tort, including negligence, strict liability or otherwise, shall be
the return of the purchase price paid or replacement of the
Software. This Agreement shall be construed in accordance with and
governed by the laws of the State of Texas. Copyright and other
proprietary matters will be governed by United States laws and
international treaties. IN ANY CASE, ID SHALL NOT BE LIABLE FOR
LOSS OF DATA, LOSS OF PROFITS, LOST SAVINGS, SPECIAL, INCIDENTAL,
CONSEQUENTIAL, INDIRECT OR OTHER SIMILAR DAMAGES ARISING FROM
BREACH OF WARRANTY, BREACH OF CONTRACT, NEGLIGENCE, OR OTHER LEGAL
THEORY EVEN IF ID OR ITS AGENT HAS BEEN ADVISED OF THE POSSIBILITY
OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. Some
jurisdictions do not allow the exclusion or limitation of
incidental or consequential damages, so the above limitation or
exclusion may not apply to you.
 
11. General Provisions. Neither this Agreement nor any
part or portion hereof shall be assigned, sublicensed or otherwise
transferred by you. Should any provision of this Agreement be held
to be void, invalid, unenforceable or illegal by a court, the
validity and enforceability of the other provisions shall not be
affected thereby. If any provision is determined to be
unenforceable, you agree to a modification of such provision to
provide for enforcement of the provision's intent, to the extent
permitted by applicable law. Failure of a party to enforce any
provision of this Agreement shall not constitute or be construed as
a waiver of such provision or of the right to enforce such
provision. If you fail to comply with any terms of this Agreement,
YOUR LICENSE IS AUTOMATICALLY TERMINATED.
 
YOU ACKNOWLEDGE THAT YOU HAVE READ THIS AGREEMENT, THAT YOU
UNDERSTAND THIS AGREEMENT, AND UNDERSTAND THAT BY CONTINUING THE
INSTALLATION OF THE SOFTWARE, BY LOADING OR RUNNING THE SOFTWARE, OR
BY PLACING OR COPYING THE SOFTWARE ONTO YOUR COMPUTER HARD DRIVE, YOU
AGREE TO BE BOUND BY THIS AGREEMENT'S TERMS AND CONDITIONS. YOU
FURTHER AGREE THAT, EXCEPT FOR WRITTEN SEPARATE AGREEMENTS BETWEEN ID
AND YOU, THIS AGREEMENT IS A COMPLETE AND EXCLUSIVE STATEMENT OF THE
RIGHTS AND LIABILITIES OF THE PARTIES. THIS AGREEMENT SUPERSEDES ALL
PRIOR ORAL AGREEMENTS, PROPOSALS OR UNDERSTANDINGS, AND ANY OTHER
COMMUNICATIONS BETWEEN ID AND YOU RELATING TO THE SUBJECT MATTER OF
THIS AGREEMENT.
 
June 21, 1996
 
REGISTERED VERSION: QUAKE LIMITED USE SOFTWARE LICENSE AGREEMENT Page 4
(DWC:dw:3406.0024:DWC\doc:1164)
 
 
/contrib/other/sdlquake-1.0.9/data/SLICNSE.TXT
0,0 → 1,175
SHAREWARE VERSION: QUAKE
LIMITED USE SOFTWARE LICENSE AGREEMENT
 
This Limited Use Software License Agreement (the "Agreement") is a
legal agreement between you, the end-user, and id Software, Inc.
("ID"). By continuing the installation of this game program, by
loading or running the game, or by placing or copying the game
program onto your computer hard drive, you are agreeing to be bound
by the terms of this Agreement.
 
ID SOFTWARE LICENSE
 
1. Grant of License. ID grants to you the limited right to use
one (1) copy of the enclosed or foregoing Id Software game program
(the "Software"), which is the shareware version or episode one of
the game program. For purposes of this section, "use" means loading
the Software into RAM, as well as installation on a hard disk or
other storage device. You agree that the Software will not be
shipped, transferred or exported into any country in violation of
the U.S. Export Administration Act (or any other law governing such
matters) and that you will not utilize, in any other manner, the
Software in violation of any applicable law.
 
2. Commercial Use is Prohibited. Under no circumstances shall
you, the end-user, be permitted, allowed or authorized to
commercially exploit the Software, or any portion thereof, such
as a screen display or a screenshot. Neither you nor anyone at your
direction shall do any of the following acts:
 
a. Rent the Software;
 
b. Sell the Software;
 
c. Lease or lend the Software;
 
d. Offer the Software on a pay-per-play basis;
 
e. Distribute the Software for money or any other
consideration; or
 
f. In any other manner and through any medium
whatsoever commercially exploit the Software or use
the Software for any commercial purpose.
 
3. Additional Prohibited Uses. Neither you, nor anyone at your
direction, shall take the following action in regard to the
Software, or any portion thereof, such as a screen display or
a screenshot:
 
a. Modify, disassemble, reverse engineer or decompile
the Software;
 
b. Translate the Software;
 
c. Reproduce the Software;
 
d. Publicly display the Software; or
 
e. Prepare derivative works based upon the Software.
 
4. Use of Other Material is Prohibited. Use, in any manner, of
the trademarks, such as Quake(tm) and the NIN(r) logo, logos, symbols,
art work, images, screen displays or screenshots, sound effects, music,
and other such material contained within, generated by or relating to
the Software is prohibited.
 
5. Restrictions Apply to Third Parties. The prohibitions and
restrictions described herein apply to anyone in possession of
the Software.
 
6. Permitted Distribution. So long as this Agreement
accompanies the Software at all times, ID grants to Providers the
limited right to distribute, free of charge, except normal access
fees, and by electronic means only, the Software; provided, however,
the Software must be so electronically distributed only in a
compressed format. The term "Providers," as used in the foregoing
sentence, shall mean persons whose business it is to provide
services on the Internet, on commercial online networks, or on the
BBS. Anyone who receives the Software from a Provider shall be
limited to all the terms and conditions of this Agreement. Further,
ID grants to you, the end-user, the limited right to distribute,
free of charge only, the Software as a whole.
 
7. Copyright. The Software is owned by ID and is protected by
United States copyright laws and international treaty provisions.
You must treat the Software like any other copyrighted material,
except that you may make copies of the Software to give to other
persons. You may not charge or receive any consideration from any
other person for the receipt or use of the Software. You agree to
use your best efforts to see that any user of the Software licensed
hereunder complies with this Agreement.
 
8. Limited Warranty. ID warrants that if properly installed and
operated on a computer for which it is designed, the Software will
perform substantially in accordance with its designed purpose for a
period of ninety (90) days from the date the Software is first
obtained by an end-user. ID's entire liability and your exclusive
remedy shall be, at ID's option, either (a) return of the retail
price paid, if any, or (b) repair or replacement of the Software
that does not meet ID's Limited Warranty. To make a warranty claim,
return the Software to the point of purchase, accompanied by proof
of purchase, your name, your address, and a statement of defect, or
return the Software with the above information to ID. This Limited
Warranty is void if failure of the Software has resulted in whole
or in part from accident, abuse, misapplication or violation of this
Agreement. Any replacement Software will be warranted for the
remainder of the original warranty period or thirty (30) days,
whichever is longer. This warranty allocates risks of product
failure between Licensee and ID. ID's product pricing reflects this
allocation of risk and the limitations of liability contained in
this warranty.
 
9. NO OTHER WARRANTIES. ID DISCLAIMS ALL OTHER WARRANTIES,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, IMPLIED
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A pARTICULAR PURPOSE
WITH RESPECT TO THE SOFTWARE AND THE ACCOMPANYING WRITTEN MATERIALS,
IF ANY. THIS LIMITED WARRANTY GIVES YOU SPECIFIC LEGAL RIGHTS. YOU
MAY HAVE OTHERS WHICH VARY FROM JURISDICTION TO JURISDICTION. ID
DOES NOT WARRANT THAT THE OPERATION OF THE SOFTWARE WILL BE
UNINTERRUPTED, ERROR FREE OR MEET LICENSEE'S SPECIFIC REQUIREMENTS.
THE WARRANTY SET FORTH ABOVE IS IN LIEU OF ALL OTHER EXPRESS
WARRANTIES WHETHER ORAL OR WRITTEN. THE AGENTS, EMPLOYEES,
DISTRIBUTORS, AND DEALERS OF ID ARE NOT AUTHORIZED TO MAKE
MODIFICATIONS TO THIS WARRANTY, OR ADDITIONAL WARRANTIES ON BEHALF
OF ID. ADDITIONAL STATEMENTS SUCH AS DEALER ADVERTISING OR
PRESENTATIONS, WHETHER ORAL OR WRITTEN, DO NOT CONSTITUTE WARRANTIES
BY ID AND SHOULD NOT BE RELIED UPON.
 
10. Exclusive Remedies. You agree that your exclusive remedy
against ID, its affiliates, contractors, suppliers, and agents for
loss or damage caused by any defect or failure in the Software
regardless of the form of action, whether in contract,tort,
including negligence, strict liability or otherwise, shall be the
return of the retail purchase price paid, if any, or replacement of
the Software. This Agreement shall be construed in accordance with
and governed by the laws of the State of Texas. Copyright and other
proprietary matters will be governed by United States laws and
international treaties. IN ANY CASE, ID SHALL NOT BE LIABLE FOR LOSS
OF DATA, LOSS OF PROFITS, LOST SAVINGS, SPECIAL, INCIDENTAL,
CONSEQUENTIAL, INDIRECT OR OTHER SIMILAR DAMAGES ARISING FROM BREACH
OF WARRANTY, BREACH OF CONTRACT, NEGLIGENCE, OR OTHER LEGAL THEORY
EVEN IF ID OR ITS AGENT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. Some jurisdictions do
not allow the exclusion or limitation of incidental or consequential
damages, so the above limitation or exclusion may not apply to you.
 
11. General Provisions. Neither this Agreement nor any part or
portion hereof shall be assigned or sublicensed, except as described
herein. Should any provision of this Agreement be held to be void,
invalid, unenforceable or illegal by a court, the validity and
enforceability of the other provisions shall not be affected thereby.
If any provision is determined to be unenforceable, you agree to a
modification of such provision to provide for enforcement of the
provision's intent, to the extent permitted by applicable law. Failure
of a party to enforce any provision of this Agreement shall not
constitute or be construed as a waiver of such provision or of the
right to enforce such provision. If you fail to comply with any terms
of this Agreement, YOUR LICENSE IS AUTOMATICALLY TERMINATED.
 
YOU ACKNOWLEDGE THAT YOU HAVE READ THIS AGREEMENT, YOU UNDERSTAND
THIS AGREEMENT, AND UNDERSTAND THAT BY CONTINUING THE INSTALLATION
OF THE SOFTWARE, BY LOADING OR RUNNING THE SOFTWARE, OR BY PLACING
OR COPYING THE SOFTWARE ONTO YOUR COMPUTER HARD DRIVE, YOU AGREE TO
BE BOUND BY THIS AGREEMENT'S TERMS AND CONDITIONS. YOU FURTHER
AGREE THAT, EXCEPT FOR WRITTEN SEPARATE AGREEMENTS BETWEEN ID AND
YOU, THIS AGREEMENT IS A COMPLETE AND EXCLUSIVE STATEMENT OF THE
RIGHTS AND LIABILITIES OF THE PARTIES. THIS AGREEMENT SUPERSEDES
ALL PRIOR ORAL AGREEMENTS, PROPOSALS OR UNDERSTANDINGS, AND ANY
OTHER COMMUNICATIONS BETWEEN ID AND YOU RELATING TO THE SUBJECT
MATTER OF THIS AGREEMENT.
 
June 21, 1996
 
SHAREWARE VERSION: QUAKE LIMITED USE SOFTWARE LICENSE AGREEMENT
(DWC:dw:3406.0024:DWC\doc:1163)
/contrib/other/sdlquake-1.0.9/data/TECHINFO.TXT
0,0 → 1,1913
Welcome to the Quake Technical Information file!
 
TABLE OF CONTENTS
-----------------
Introduction to the Console..............
Video Subsystem Documentation............
Sound Subsystem Documentation............
CD Audio Subsystem Documentation.........
Network Subsystem Documentation..........
Modem Strings............................
Win95 Documentation......................
Key Binding and Aliases..................
Quake Keys and Common Commands...........
Making a Config File.....................
Demos....................................
Reporting Quake Bugs.....................
 
 
==========================================
== Introduction to the Console ==
==========================================
 
Throughout this document, examples of commands are given, all of which
are typed in at the console. To bring up the console, press the tilde ('~')
key or press ESC to bring up the menu, select Options, and select Console...
from the options menu. To exit the console, press ESC.
 
The console provides a way to change console variables and also accepts
commands that change game settings such as movement keys, video mode, as
well as providing an interface for key binding and command aliasing (more
on that later).
 
The console also has a command history with which you can browse through
previous commands. Use the up and down arrows to navigate through the
command history and press <enter> to re-issue a command.
 
Partially typing a command and then pressing the TAB key will complete the
currently typed text with the first matching console variable or command.
(Yes, this is a good way to look for console commands.)
 
To review previous actions by page, use the PGUP and PGDN keys.
 
 
==========================================
== Video Subsystem Documentation ==
==========================================
 
The Video Modes menu
--------------------
 
Video modes can most easily be selected from the the Video Modes menu, which
is brought up by selecting the Video Options choice in the Options menu.
All the resolutions that Quake can support on the current computer are
displayed.
 
Please note that higher-resolution modes require correspondingly more
system memory in order for Quake to run, and that some high-resolution
modes may not be available when running Quake on 8 Mb machines. Such
modes are not listed in the Video Modes menu. Please do not report
video modes that do not appear in the Video Modes menu as bugs; either
those modes are not supported by your video adapter, or there is not
enough system memory for Quake to support those modes.
 
The video modes listed in the Video Modes menu can be tested, set, and made
the default mode for Quake from the Video menu, as follows:
 
* The arrow keys can be used to move the blinking indicator to any of the
modes listed in the Video menu.
 
* Pressing the 'T' key tests the mode the blinking indicator points to, by
setting the mode, leaving it set for 5 seconds, and returning to the previous
mode. This lets you verify that your computer does in fact support that
mode. We highly recommend that you always test modes with 'T' before setting
them
permanently by pressing the Enter key, in case some sort of hardware or
software glitch causes a mode to function incorrectly and produce a garbled
screen. It is unlikely but possible that testing or setting a mode will
cause your computer to hang or crash; if this happens, there is a serious
hardware or software bug, and you should not attempt to select that mode
again.
 
* Pressing the Enter key sets the mode the blinking indicator points to,
leaving it set so Quake will then run in that mode. We suggest that you
test a mode by pressing the 'T' key before setting it by pressing the Enter
key. Note that a selection made with the Enter key remains in effect only
until Quake is exited (or a new mode is set). You must explictly make a mode
the default mode by pressing the 'D' key in order to automatically set that
mode when you start Quake up in the future.
 
* Pressing the 'D' key makes the current mode the default mode that Quake
starts up with. Note that the current mode is the mode that's displayed in
white in the mode list, not necessarily the mode that the blinking indicator
points to. The current default mode is listed in the description of the 'D'
key at the bottom of the Video Modes menu.
 
* Pressing Esc exits the Video Modes menu.
 
Please see "Bug Reporting," below, for information on how to report any
problems you encounter.
 
 
Video modes from the console: Quick start
------------------------------------------
 
More comprehensive but more complex video control is available through the
Quake console. This section describes the commands necessary to perform
basic mode setting through the console (this is similar to what can be
accomplished through the Video Modes menu), and following sections describe
console video control in detail.
 
To see all the video modes that are available, bring up the console (either
press tilde ('~'), or press Esc to bring up the menu, select Options, and
select Console... from the Options menu).
 
From the console, type vid_describemodes<enter> to see all available modes.
Type vid_mode <mode #> to set a mode, where <mode #> is the mode number
listed for the desired mode by vid_describemodes. Higher-resolution modes
generally require more extra system memory in order to run, and many are
not available in 8 Mb systems; modes that are supported by the video
adapter but are currently unavailable due to system memory limitations
will still show up in
the mode list from vid_describemodes, but will
have "**" in place of a mode number. (Such modes will not show up at
all in the Video Modes menu.) If you try to set a mode for which
there is insufficient system memory, you will receive a message to that
effect, and the video mode will remain unchanged.
 
 
More detail
-----------
 
This version of Quake supports software drawing in a variety of
video modes. It does not support any 3-D hardware accelerators.
Video modes that are built into Quake are:
 
320x200, 360x200, 320x240, 360x240, 320x350, 360x350, 320x400,
360x400, 320x480, 360x480
 
However, the higher-resolution modes on this list require additional
memory, and may not be available in 8 Mb systems.
 
In addition, all VESA 2.0 256-color linear framebuffer modes
supported by the video adapter are supported. Further information
about VESA 2.0 is provided below.
 
 
Video mode reporting and selection
----------------------------------
 
Quake assigns each available video mode a mode number, which can
then be used to query information about the mode or to select the
mode. The first 11 mode numbers are always as follows:
 
0: 320x200
1: 320x200
2: 360x200
3: 320x240
4: 360x240
5: 320x350
6: 360x350
7: 320x400
8: 360x400
9: 320x480
10: 360x480
 
You will notice that modes 0 and 1 are both 320x200; mode 1 is a
Mode X-style version, which may someday allow support of page
flipping for cleaner graphics, but right now it's just slower with
no advantages, so use mode 0 for 320x200 resolution. Modes 2-10
are all higher resolution than mode 0, and look very nice, but are
also all slower than mode 0. Mode 0 is the fastest of the 11
built-in modes.
 
In addition to the built-in modes, Quake checks for the presence
of a VESA version 2.0 driver. If such a driver is detected, the
driver is queried for all 8-bit-per-pixel linear framebuffer (LFB)
modes that are supported; also, if no LFB 320x200 mode is available,
a banked 320x200 VESA mode is queried for. All such modes are added
to the mode list starting at mode 11. The available modes will vary
depending on adapter, graphics chipset, amount of video memory, and VESA
2.0
driver. The higher the resolution, the lower the performance, and
the
higher-resolution modes will often be too slow for good gameplay
on most machines. (Also, higher-resolution modes often need more memory
than is available in an 8 Mb system.) The screen can be sized down to
improve performance in higher-resolution modes, but then of course the
effective resolution of Quake is reduced.
 
At the same resolution, VESA LFB modes are often faster than the non-VESA
modes 0-10, because adapters often have faster memory access in LFB modes.
 
If a given VESA mode can support page flipping, then it defaults to page-
flipped operation. A VESA mode can be forced to non-page-flipped operation
by setting the vid_nopageflip console variable to 1, then setting the mode
 
(note that vid_nopageflip takes operation on the next, not the current, mode
set, and note that it then stays in effect permanently, even when Quake is
exited and restarted, unless it is manually set back to 0). If there is not
enough memory for two pages in a VESA mode, or if the
adapter doesn't support page flipping, then the mode will automatically
be non-page-flipped. Page flipping can have higher visual quality, but may
be either faster or slower, depending on the graphics adapter and other
hardware. (See the discussion of the Pentium Pro, below, for a
discussion of why page flipping can be faster but is sometimes much slower
on that processor.) Page-flipped modes use less system memory than non-
page-flipped modes.
 
Quake's VESA support, including VESA driver detection, can be disabled by
using the -stdvid command-line switch, and can also be disabled, along with
sound, network, and other hardware support, by the -safe command-line switch.
 
The maximum resolution supported by Quake is 1280x1024. Modes with higher
resolutions will not be reported by vid_describemodes, and cannot be set.
 
There is no support for any 3-D accelerator boards in this version of Quake.
Coming soon.
 
Quake always starts up in mode 0, and modes 0-10 are always available, given
enough system memory.
 
 
A note on modes reported in the Video Modes menu
------------------------------------------------
 
The vid_describemodes console command lists all modes with
resolution less than or equal to 1280x1024 that are
supported by the video adapter, although modes for which there
is not enough system memory have "**" for the mode number. VGA,
Mode X-style, and VESA 2.0 modes are listed separately, so a
single resolution can be listed as many as three times, once for
each hardware mode that supports it. For example, mode 0 is
VGA mode 0x13, which supports 320x200 resolution, and mode 1 is
320x200 Mode X-style mode. Quake looks identical in both
modes, although it usually runs faster in mode 0.
 
The Video Modes menu is much simpler. Only modes with resolution
less than or equal to 1280x1024 that are both supported by the
hardware and for which there is sufficient system memory are
listed. Further, a given resolution is listed only once. If a
given resolution is available in multiple hardware modes, then
selecting that resolution will select the appropriate hardware mode
as follows:
 
If the mode is 320x200, then VGA mode 0x13 is selected, and
equivalent Mode X and VESA modes are ignored;
 
Otherwise, the VESA version of the mode is used.
 
You can always see what video mode is selected from the console by typing
the command:
 
vid_mode<enter>
 
command.
 
None of this has any effect on selecting modes through the
console, where all the different versions of each mode are
listed, and the desired version can be selected by using the
appropriate mode number.
 
 
How to get VESA 2.0 support
---------------------------
 
Some video adapters have VESA 2.0 support in ROM. Other video
adapters come with loadable VESA 2.0 TSRs. In the absence of either
of these, UniVBE, a shareware product from SciTech, provides VESA 2.0
support for most video adapters. The latest version of UniVBE can be
obtained from the following locations:
 
www: http://www.scitechsoft.com
ftp: ftp.scitechsoft.com
CIS: GO SCITECH
AOL: Keyword SciTech
 
SciTech can be contacted at:
 
email: sales@scitechsoft.com
 
SciTech Software
5 Governors Lane, Suite D
Chico, CA
95926-1989
 
The current version at this writing is UniVBE 5.2. This version
supports many more adapters than previous versions, and adds
a number of useful low- and medium-resolution modes, such as 400x300
and 512x384.
 
 
Video-related commands
----------------------
 
vid_describecurrentmode
lists the description for the current video mode.
 
vid_describemode <mode #>
lists the description for the specified video mode, where <mode #> is as
reported by vid_describemodes.
 
vid_describemodes
lists descriptions for all available video modes.
 
vid_mode <mode #>
sets the display to the specified mode, where <mode #> is as reported by
vid_describemodes.
 
vid_nopageflip <1|0>
when set to 1, VESA mode sets will always select non-page-flipped
operation. When set to 0, VESA mode sets will select page-flipped
operation whenever possible. All non-VESA modes are always
non-page-flipped. The setting of vid_nopageflip is remembered
when Quake is exited (by being saved in config.cfg), and is reloaded
when Quake is restarted, so once vid_nopageflip is set to 1, all
VESA modes set in all Quake sessions after that point be will non-page-
flipped until vid_nopageflip is set to 0. Note that setting this
variable doesn't affect whether the current video mode is page-flipped,
but rather whether page-flipping can be used by future mode sets.
 
vid_nummodes
reports the total number of modes available.
 
vid_testmode <mode #>
tries to switch Quake to the specified mode, then returns to the current
mode after 5 seconds. This allows you to try an untested mode without
ending up with a black screen if, for example, the monitor can't display
the mode properly. There may still be instances in which, due to VESA
driver or hardware bugs, the machine will hang in certain modes;
vid_testmode can't recover from these situations, but it can recover
from a blank or scrambled screen.
 
vid_wait <wait type>
sets the type of waiting that the video adapter should do, as follows:
0: no waiting
1: wait for vertical sync active
2: wait for display enable active
 
The default state of vid_wait depends on the video mode selected.
(_vid_wait_override can force vid_wait to 1, wait for vertical
sync; see the description of _vid_wait_override below.)
In built-in modes 0-10, the default is always 0, no waiting. You
can set vid_wait to 1 (wait for vertical sync) to eliminate shear
and tearing in these modes (so partially-completed frames are never
drawn, resulting in a rock-solid image). However, waiting for
vertical sync can result in substantial performance loss.
 
In VESA modes, if the adapter is VGA compatible and there's enough
memory for three video pages, then triple-buffering is enabled and
vid_wait is set to 2, wait for display enable. There is little
performance loss to this sort of waiting. If the adapter is not
VGA compatible, or if there's only enough memory for double-buffering,
then vid_wait is set to 1 (wait for vertical sync). This can cause
significant loss of performance, but some sort of wait is generally
necessary to avoid occasional glitching of the screen when
page-flipping; we always choose the lowest-cost wait option that
seems to be safe to use. If there's only enough memory for one
page, or if vid_nopageflip 1 is in effect, then vid_wait is set to 0
(no wait). As with modes 0-10, vid_wait 1 can be used to eliminate
shear, but at a performance cost.
 
We have encountered problems with a few adapters in VESA modes when
vid_wait is set to 2 (wait for display enable). Apparently some adapters
just toggle display enable all the time, rather than only when pixels
are being sent to the screen; this can cause occasional glitches in
which the screen image jumps for one frame. You can fix this by
setting vid_wait to 1 (wait for vertical sync). We would have made
vid_wait 1 the default, but it's slower, and vid_wait 2 works on most
machines.
 
The default setting for vid_wait can be changed from the console
at any time. If you are in a VESA mode that waits for vertical
sync and want to turn it off to get a speed-up, you can do so.
However, changing a vid_wait 1 default in a VESA mode may result
in problems. If vid_wait defaults to 1 (wait for vertical sync)
in a mode, and you force it to 2 (wait for display enable), the
machine may hang, because some VGA-incompatible adapters, such as
some ATI Mach64s, don't support the display enable status. If you
force vid_wait to 0 (no wait), then the screen may glitch periodically
if the page flips at a time that results in a bad flip address,
although some adapters work fine with no wait at all.
 
If you force a new setting for vid_wait and encounter problems, DO
NOT send us a bug report!
 
_vid_wait_override <1|0>
can be used to force wait for vertical sync in all modes. When
_vid_wait_override is set to 0, the type of waiting, if any, for
each video mode that's set thereafter is automatically set to
what appears to be the fastest safe state. However, it is
possible in some cases that automatic setting may result in some
screen glitching, and it is also true that shear can be
eliminated by waiting for vertical sync (although at a cost in
performance), so it may be desirable in some cases to override
the automatic wait selection and always wait for vertical sync.
This can be done by setting _vid_wait_override to 1. Once set,
this remains in effect through all succeeding mode sets, even
when Quake is exited and re-entered; the only way to keep Quake
from waiting for vertical sync once _vid_wait_override is set to
1 is to set _vid_wait_override to 0. Note that changing
_vid_wait_override doesn't affect the current mode, but rather
takes effect on the next mode set. _vid_wait_override is initially
set to 0.
 
_vid_default_mode <mode #>
can be used to force Quake to start up in a particular mode.
The easiest way to select a default mode is by pressing the
'D' key in the Video Modes menu, but you can alternatively
use _vid_default_mode to specify the mode in which you want
Quake to start up in future Quake sessions. _vid_default_mode
is initially set to 0.
 
 
Higher-quality perspective texture mapping
------------------------------------------
 
For maximum speed, perspective correction is performed only every 16
pixels. This is normally fine, but it is possible to see texture ripples
in surfaces that are viewed at sharp angles. For more precise texture
mapping, set the console variable d_subdiv16 to 0. Doing this will result
in somewhat slower performance, however, and the difference in visual
quality will not normally be noticeable.
 
 
Known video problems and workarounds
------------------------------------
 
If you think you've encountered a bug, see "Bug Reporting," below.
As a general rule, go back to mode 0 if you have problems; mode 0
should work properly in all cases.
 
On some ATI Mach64 adapters, the palette is sometimes too dark in
some VESA modes, and is tinted oddly (too red, for example) in other
modes. The workaround is to use different modes, or modes 0-10.
 
In modes 0-10, shear and tearing can occur as partially finished
frames are displayed. Workaround: set vid_wait to 1 (wait for
vertical sync); this can result in a substantial performance loss,
however. An alternative is to use a page-flipped VESA mode.
 
In page-flipped VESA modes, occasional glitched frames may occur with some
VESA driver-hardware combinations. Workaround: set vid_wait to 1 (wait
for vertical sync) (you can set _vid_wait_override to 1 to make waiting
for vertical sync permanent for future Quake sessions), or use a different
mode.
 
The VESA video drivers that come with some video adapters don't
support low-resolution modes such as 320x200; often,
nothing lower than 640x400 is supported. For example,
this is the case with some ATI adapters. There's nothing
Quake can do to provide low-resolution VESA modes in these
cases, because Quake simply supports whatever modes the VESA
driver chooses to report as supported. Unfortunately, 640x400
is too high a resolution for really good performance unless you
have a very fast Pentium or a Pentium Pro, so on machines with
this sort of adapter, the VESA modes aren't very usable.
Workaround: Use UniVBE 5.2, which supports low-resolution modes
on a wide variety of adapters. Note that a few adapters simply can't
support low-resolution modes, in which case you'll have to stick with
the low-resolution VGA and Mode X modes that are built into Quake,
which run fine but may be somewhat slower than VESA modes.
 
A few video adapters are almost but not fully VGA compatible, because
they don't support some unusual VGA video modes. In particular, a few
adapters don't support the 360-wide Mode X-style video modes that are
build into Quake (modes 2, 4, 6, 8, and 10), and display garbage in those
modes. Workaround: use different modes, such as 0, 3, 5, 7, 9, or any
VESA modes that are available.
 
Under Win 95, the palette occasionally gets messed up when switching from
Quake to the desktop and back again. You can restore the palette by
bringing down the console (either press tilde ('~'), or press Esc to bring
up the menu, select Options, and select Console... from the Options menu),
and typing bf and pressing the enter key, to generate a background flash,
which sets the palette. Press Esc to exit the console. Alternatively,
setting the screen brightness, either from the Options menu or via the
gamma console variable, sets the palette.
 
Under Win 95, if the system key (the key with the Win 95 flag on it) is
pressed while Quake is running fullscreen in a VESA mode, Win 95 may be
unable to switch back from the desktop to Quake, in which case it will
notify you of this, then terminate the Quake session. This is a quirk
of Win 95, and normally there is no workaround other than not to press
that key or not to use VESA modes. (Some people go so far as to remove
the system key from their keyboard.) However, you can
disable the system key for Quake with the following utility:
 
http://www.microsoft.com/windows/download/doswinky.exe
 
Switching away from Quake with Alt-Enter, Ctrl-Esc, Alt-Tab, or
Alt-Spacebar all work fine (except that if you disable the system key
with doswinky.exe, Ctrl-Esc will also be disabled).
 
 
Performance
-----------
 
Quake's graphics should be adequately fast in mode 0 (320x200) on all
Pentium-class machines. If you feel Quake is running slowly, set the
showturtle console variable to 1; you will then see a turtle icon
appear in the upper left corner of the screen if the frame rate drops
below 10 frame/second. If you are getting the turtle, you are probably
not getting great gameplay. Performance can be improved in several ways:
 
* size down the screen with the minus key
 
* select a lower-resolution mode, if possible
 
* use a VESA mode
 
* if you're using a VESA mode and vid_wait is set to 1 (wait for
vertical sync) by default (you can check by typing vid_wait<enter>
in the console), you can try setting vid_wait to 0 or 2, as detailed
in the discussion of the vid_wait command above. Be aware that
risks of screen glitching or hung machines are associated with
overriding a default vid_wait 1 setting in VESA modes.
 
To see how exactly fast Quake is running, bring up the console and type
 
host_speeds 1<enter>
 
You will see a display at the top indicating total frame time in
milliseconds, and also server, graphics, and sound frame time in
milliseconds. (Note, though, that unless you also do
 
snd_noextraupdate 1<enter>
 
sound time will actually show up as graphics time. However,
snd_noextraupdate 1 can cause sound to get choppy, so it's not
generally recommended.)
 
Lower numbers are better.
 
Type
 
host_speeds 0<enter>
 
to turn off the frame time display.
 
 
Pentium Pro Performance
-----------------------
 
The Pentium Pro is a very fast Quake platform, but has one weak spot; it is
by default very slow on writes to video memory. This means that in default
hardware configurations, you are usually much better off setting
vid_nopageflip to 1 if you use VESA modes, so drawing is done to system
memory instead of to video memory. Remember that you must set the mode
after setting vid_nopageflip to 1 in order to get vid_nopageflip to take
effect. (vid_nopageflip can sometimes be faster on a Pentium, too, but
not by nearly as much in general, and it's often slower.)
 
The Pentium Pro has some special features that are not turned on by default,
but which can help Quake performance a LOT. These features can be enabled
by John Hinkley's program FASTVID, which can be obtained from
ftp://members.aol.com/JHinkley/fastvid.zip. Performance in 640x480
mode on a Pentium Pro/150 nearly doubled after FASTVID was run; Quake
was very playable (and looked great!) at this resolution.
 
There's the usual caution with FASTVID: It could conceivably make your
system run goofily, or who knows what. FASTVID is not a product of
id Software, and id makes no guarantees regarding FASTVID. In other words,
use FASTVID at your own risk.
 
************************************************************************
IMPORTANT NOTE: FASTVID works only on Pentium Pros!!! Please do NOT
contact either John Hinkley or id with problems concerning FASTVID on
Pentium or 486 machines.
************************************************************************
 
 
Video Bug Reporting
-------------------
 
If you encounter a video-related bug, please fill out the form found at the
end of this file and e-mail it to support@idsoftware.com. There are several
problems that are not bugs, and shouldn't be reported, including:
 
* unavailability of some VESA modes; VESA modes are only supported by
Quake if they are 8-bpp, are LFB modes (except for 320x200), and are
no greater than 1280x1024 in resolution. If you have a VESA mode
that doesn't seem to be working properly, please contact the
manufacturer; we just use the information that the VESA driver
provides us with.
 
* problems that occur when you change vid_wait from a default value
of 1 (wait for vertical sync) in VESA modes
 
* sluggish performance on 486s
 
* the known palette problem on some Mach64s.
 
* the known palette problems switching from fullscreen to the desktop and
back under Win95.
 
* the known problems switching back from the desktop in VESA modes after the
system (Windows flag) key has switched from fullscreen to the desktop.
 
* video modes that are not listed in the Video Modes menu, or that are not
listed or are listed with "**" in the output from vid_describemodes; such
modes are either not supported by your video adapter, or cannot be supported
by Quake in the amount of memory your system has. High-resolution modes will
often not be available in 8 Mb systems.
 
* 360-wide video modes that don't work although other resolutions do work
 
* lack of low-resolution VESA modes; the availability of low-resolution modes
is the responsibility of the VESA driver. UniVBE 5.2 provides low-resolution
modes on most adapters.
 
Apart from these, we would very much like to hear about any video
problems you encounter.
 
 
==========================================
== Sound Subsystem Documentation ==
==========================================
 
Quake's sound subsystem works only with Sound Blaster compatible sound
cards. For Quake to get the correct settings for DMA channel and PORT
address, you must set your BLASTER environment variable (or have it set for
you with the DIAGNOSE utility in your SB16 directory). If you do not have
the BLASTER environment variable set, your sound will not work. If your
sound card supports Sound Blaster compatibility, Windows 95 should set this
variable for you.
 
Note: some sound cards do not have 100% Sound Blaster compatible
hardware, but emulate the Sound Blaster interface. Such cards may
display some inconsistencies relative to an actual sound blaster.
In particular, sound may be delayed on some cards.
 
Note: it is possible for sound to get choppy if the frame rate
drops to a very low level, below 5 frames a second. A frame rate
that low will not provide a good gameplay experience, so if you
do experience choppy sound, your machine is almost certainly not
fast enough to run Quake satisfactorily in general.
 
If (when) you see bugs, please use the form attached to the end
of these docs to submit a bug report.
 
Sound Card Command Line Options, Commands, and Variables
==================================================================
 
The commands and variables below work under any operating system.
Command-Line options are typed on the command line in most any place
but only in operating systems which support command line interfaces,
like DOS's COMMAND.COM, or NEXTSTEP's or Linux's csh, sh, or bash.
For example, under DOS, the NOSOUND option would be used like this:
"C:> quake -nosound".
 
Command-Line Options
--------------------
 
NOSOUND
Syntax: -nosound
Description: This will prevent *any* sound code from being executed. If
you are having technical difficulty with the game and then try
running the game with this option and the problem goes away, then
the problem is probably somewhere in the sound code.
 
SSPEED
Syntax: -sspeed <speed>
Description: This will ask the sound code to set the playback speed
within the constraints of the capabilities of the card. This is
11025 Hz by default and usually from 8000 to 44100. Making this
faster requires more CPU horsepower, and has no actual benefits,
because the sounds only contain 11 KHz data. Making this slower
degrades sound quality, but improves performance and saves memory.
 
Commands
--------
 
SOUNDINFO
Syntax: soundinfo
Description: This prints the "portable" information on your current
audio hardware setting in the game. It specifies whether there is
stereo output (0 or 1), the number of samples in the DMA buffer, the
current sample position (changes each time you run SOUNDINFO and
ranges from 0 to the number of samples), the number of sample bits,
the submission chunk (1 in DOS or Linux w/ mmaped sound, larger in
Linux w/o mmaped sound), playback speed in Hz, the DMA buffer address
in hexadecimal (usually 8 digits after the 0x, starting with 0xf00..
in DOS, starting with 0x400.. in Linux, and less than 8 digits if the
hardware was not initialized successfully), and the number of
channels mixed in software (8 by default, changeable w/NUMCHANNELS
command).
 
STOPSOUNDS
Syntax: stopsounds
Description: Stops any current looping sounds.
 
 
Sound Blaster Sound Card Command-Line Options and Commands
==========================================================
 
The following applies to Sound Blaster cards or compatibles under DOS
or a DOS box.
 
Commands
--------
 
SBINFO
Syntax: sbinfo
Description: This will print information on the Sound Blaster card
in the system. If the version is 4 or greater, then it is some
kind of Sound Blaster 16 or compatible. Version 2 is an 8 bit mono
sound blaster, Version 3 is an 8 bit stereo sound blaster pro.
The port is the I/O port
sensed from the A variable in the BLASTER
environment variable.
The DMA is the DMA channel and is confirmed in
hardware if the
card is version 4 or higher. The mixer port can be
ignored.
 
 
==========================================
== CD Audio Subsystem Documentation ==
==========================================
 
Overview
========
Quake is designed to play background music off of a CD-ROM. The Quake CD has
music tracks on it and each level has been assigned a track that will be
played.
 
Win95 Users: Putting a CD other than the Quake CD into the drive when Quake
is already running will sometimes cause another Windows application to start
and switch you back to Windows with Quake running in the background. You
will probably want to stop whatever was started and switch back to Quake as
quickly as possible... especially if you are playing deathmatch.
 
 
Command Line Parameters
=======================
-nocdaudio
This will prevent the CD audio system from even attempting to initialize.
No CD commands or functions will be available. The game will just run
with no music.
 
-cdmediacheck
This causes the game to periodically check to see if the CD has been
removed and a new one placed in the player. It is off by default since
this operation is very slow on some CD players and is not needed under
Win95. There is normally no reason to enable this option; it would
only be useful if you were going to be changing the CD from within the
game on a regular basis.
 
Commands
========
There is normally no reason you would need to use any of these commands. If
you are playing Quake with the Quake CD in your CD-ROM drive, the appropriate
music track will be played automatically.
 
cd on
Re-enables the CD audio system after a "cd off" command.
 
cd off
Shuts down the CD audio system. No more music will be played unless it
is re-enabled.
 
cd reset
Causes the CD audio to re-initialize. This is useful if you change
CDs or insert the CD after you've already run Quake.
 
cd play <track number>
Plays the specified track one time.
 
cd loop <track number>
Plays the specified track. It will be repeated until either it is
manually stopped or another track is started.
 
cd stop
Stops the currently playing track.
 
cd resume
Will resume playback of a stopped track.
 
cd eject
This is for CD players that do not have a manual eject button.
 
cd remap <track1> <track2> <track3> ...
Allows you to switch what tracks are played. This is especially useful
if you want to play music other than that on the Quake CD. If the CD
audio system is told to play track 1, it will instead play the 1st
track you specified. For example: assuming a CD with 1 data track and
8 music tracks, the command "cd remap 1 9 8 7 6 5 4 3 2" would leave
the data alone and play the audio tracks as if they had been placed on
the CD in the opposite order.
 
cd info
Reports information such as the number and types of tracks on the current
CD, what track (if any) is currently playing, and the playback volume.
 
 
Variables
=========
bgmvolume
The background music volume. Valid values are 0.0 though 1.0. Changes
will normally be made using the options menu.
 
Not all CD-ROM players support variable volume. The 0.0 to 1.0 value
translated to a value from 0 to 255 before it is passed to MSCDEX. How
this value is interpreted varies from drive to drive. The only thing
required by the MSCDEX specification is that 0 is off and anything else
is on. Some CD-ROM drives only have on and off so change to bgmvolume
will have have no effect on volume once it is on.
 
 
Messages
========
CDAudio_Init: MSCDEX version 2.00 or later required.
MSCDEX was either not loaded, or is a version earlier than 2.00.
 
CDAudio_Init: First CD-ROM drive will be used
MSCDEX reported that the system has more than one CD-ROM drive.
Quake will always use the first drive in this case.
 
CDAudio_Init: Unable to allocate low memory.
We were unable to allocate the memory needed to communicate with MSCDEX.
Although the game can still run, this indicates a severe low memory
condition.
 
CD Audio Initialized
Indicates that the CD audio system has successfully initialized.
 
CDAudio_Play: Bad track number N.
We attempted to play a track number that that is outside the range of
tracks recorded on the CD currently in the CD-ROM drive. Probable causes
are that a CD other than Quake is in the player, or a custom level has
specified an invalid track number.
 
CDAudio_Play: Can not play data.
A valid track was requested to be played, but it was a not an audio track.
The probable causes are the same as for a bad track number.
 
CDAudio_Play: track N failed
A valid audio track was going to be played, but the play command to MSCDEX
returned an error.
 
CDAudio: media changed
This is simply a notification. It can only occur if the "-cdmediacheck"
option was specified on the command line.
 
CDAudio: Error - playback stopped N
An error occurred while the CD was playing audio. Playback has been
stopped and no further automatic play will be attempted; the game will
proceed without music.
 
CDAudio_Init: No CD in player.
MSCDEX reported an error while Quake was attempting to get information
about the current CD. There is either no CD in the player, or it was
unable to get the track information. No automatic CD play will be
attempted; the game will proceed without music.
 
 
==========================================
== Network Subsystem Documentation ==
==========================================
 
Overview
========
 
Quake is a client/server game. You are always running over some type of
network. In a standalone game, you are using a loopback network; it just
passes messages back and forth in memory buffers. This readme is talking
about real networks and multiplayer deathmatches. There are three main
sections: commands, LANs, and Serial.
 
Most normal configuration can be done via the game menus.
 
There are two types of Quake servers: dedicated and listen. A listen server
is a machine that is used to play the game and also hosts the game for other
players. A dedicated server only hosts the game; it runs in text mode and
does not let anyone play on that machine. A single player game is really
just a 1 player listen server that doesn't listen for network connections.
 
Dedicated vs Listen. I'll try to make this simple: it is always better to
use a dedicated server. Why? Fairness and playability. With a listen
server, the person on the server always has advantages. They will always be
the first person into a level, they will always have zero latency, and they
will get a server update on each and every frame. On a dedicated server
everyone gets equal treatment. Getting into the server is a first come,
first served proposition; latency is determined by each player's connection;
and everyone is sent the same number of updates. It's about as fair as life
gets. By the way, a good 486 machine works nicely as dedicated server.
 
Another suggestion. Until there is a native Win95 version of Quake, IPX will
usually provide better gameplay on a local area network. This is due to the
delicate balancing act that is required to let a DOS program use the Win95
TCP/IP stack.
 
To start a Dedicated Server, you invoke Quake with the "-dedicated"
command-line parameter. When the server starts, you can type any command
that you would normally type in the Quake Console, such as "map e1m1" to
start the server on a specific map. This can be done from the command-
line as well by typing "quake -dedicated +map e1m1". If a value is entered
after "-dedicated", that is the amount of players allowed to connect, up
to a maximum of 16 players. A dedicated server will quit to the OS whenever
a fraglimit or timelimit is reached. Example: "quake -dedicated 16" will
start a 16-player dedicated server.
 
To start a Listen Server, you invoke Quake with the "-listen" command-
line parameter, or use the Multiplayer menu in the game. Starting a listen
server from the command-line will allow you to handle more than 4 players,
as 4 is the limit when starting a game from the Multiplayer menu. If a
value is used after the "-listen", that is the maximum amount of players
allowed, up to 16 players.
 
Command Line Parameters, Commands, and Variables
================================================
 
Command line parameters
-----------------------
-nolan
Disables IPX, TCP/IP, and serial support.
 
-noudp
Disables support for TCP/IP.
 
-udpport <port#>
Specifies a UDP port to be used other than the default of 26000.
 
-noipx
Disables support for IPX.
 
-ipxport <port#>
Specifies a IPX port to be used other than the default of 26000.
 
-noserial
Disable serial support.
 
-mpath
Enables support for code to use Win95's TCP/IP stack. Do NOT use this
under DOS!
 
-listen [n]
Starts Quake ready to be a non-dedicated server for up to <n>
players. If you do not specify a number <n> after -listen it will
default to 8. The maximum allowed value is 16.
 
-dedicated [n]
Starts Quake ready to be a dedicated server for up to <n> players.
If you do not specify a number <n> after -listen it will default to 8.
The maximum allowed value is 16. A dedicated Quake server stays in
text mode. This is the Quake console with most commands still
available; those that make no sense (like vid_mode) are ommitted.
 
Console Variables
-----------------
 
net_messagetimeout
Specifies how long Quake should wait for a message to arrive before
deciding the connection has died. The default is 3 minutes. For
reference, messages usually arrive at the rate of about 20 per second.
 
hostname
This is the name for your server that will show up on an slist
(see below). The default value is "unnamed".
 
sys_ticrate
Only used by dedicated servers. This determines the rate at which the
server will send out updates to the clients. The default value is 0.05
(20 updatesper second). For servers where bandwidth is limited, using
modems or the internet for example, it is advisable to lower this value
to 0.1 (10 updates per second). This will have a very minor effect on
responsiveness, but will half to outbound bandwitdh required making the
modem players a lot happier.
 
 
Console commands
----------------
 
net_stats
This is for debugging. It displays various network statistics.
 
slist
Looks for Quake servers on a local LAN (or over a null modem
cable). This will NOT go outside the local LAN (will not cross
routers).
 
 
LANs
====
 
Here are the LANs that are supported by the Quake test
release. For each one, you'll be told how to connect to a server
*if it is not on your local network*. If it is, you can use the
"slist" command and connect by hostname. See the main readme for
a discussion of the connect command.
 
IPX
---
 
Quake has been run with Novell's ODI IPX stack under DOS, PDIPX with packet
drivers under DOS, and the Microsoft IPX stack in a Win95 DOS box. When
connecting to a server using IPX, you specify its network:nodeaddress (like
12345678:1234567890AB). If you are on the same network, you can just specify
the node address. If you are doing a connect command from the console, a
full IPX address must be enclosed in quotes.
 
For example, the server's IPX address is "00FADE23:00aa00b9b5b2", you would
enter: connect "00FADE23:00aa00b9b5b2"
 
Win95 TCP/IP
------------
 
Please see the Win95 section of this file for details about playing using
TCP/IP under Win95.
 
Kali
----
 
To Quake, Kali appears to be IPX. Once you've got Kali up and running, run
Quake as if it was on an IPX network.
 
Beame & Whiteside TCP/IP
------------------------
 
This is the only DOS TCP/IP stack supported in the test release.
It is not shareware...it's what we use on our network (in case you
were wondering why this particular stack). This has been "tested"
extensively over ethernet and you should encounter no problems
with it. Their SLIP and PPP have not been tested. When connecting
to a server using TCP/IP (UDP actually), you specifiy it's "dot notation"
address (like 123.45.67.89). You only need to specify the unique portion
of the adress. For example, if your IP address is 123.45.12.34
and the server's is 123.45.56.78, you could use "connect 56.78".
 
Playing over the Internet
-------------------------
Yes, you can play Quake over the Internet. How many people can be in
the game? That depends. How smooth will the game be? That depends.
There are just too many variables (bandwidth, latency, current load,
etc...) for us to make any kind of promises about Internet play.
 
 
Serial/Modem
============
 
The Quake serial driver supports two COM ports. Although they are referred
to as COM1 and COM2, you can configure them to use any normal hardware
COM port (1 thru 4 on most PCs). The com ports are used with interrupts,
so their IRQ may not be used for another purpose (such as a LAN adapter
or sound card). The IRQ may not be shared with another device either;
not even another COM port. A client can only be connected to one server
at a time, so multiple ports are really only useful on a server.
When using modems, the client must originate the call and the server
must answer. This holds true even for a two player, non-dedicated
server configuration.
 
In the Multiplayer menu, the default modem string is "ATZ". If your modem
games are too slow, you can change this string to the appropriate one for
your modem as listed below in the "Modem Strings" section.
 
 
The COMx commands
-----------------
 
Use the menus for serial play whenever possible. The console
interface is only for unusual configurations. It is much more
difficult to understand and use correctly.
 
Those of you who do use the console commands for serial play need to
know that the menus always use the first Quake COM line (COM1); yes,
even for COM2. The names COM1 and COM2 here mean the first and second
serial ports, not necessarily the PC COM1 and COM2 ports (although those
are the default configurations).
 
There are two commands to support serial/modem play for Quake. They
are: COM1 and COM2. Entering one of these commands with no arguments
will display the status of that serial port, similar to this:
 
Settings for COM1
enabled: true
connected: false
uart: 16550
port: 3f8
irq: 4
baud: 57600
CTS: ignored
DSR: ignored
CD: ignored
clear: ATZ
startup:
shutdown: ATH
 
When used with arguments, these commands change the settings and
status of the COM ports. The possible arguments are listed below;
examples follow.
 
enable | disable
"enable" means that your configuration is complete and you want to use
the COM port. "disable" is used to turn off a COM port, usually to
change its settings. The default (initial) state is disabled.
 
 
modem | direct
Use one of these two to let Quake know if you are using a modem or a
direct connection (also called a null modem). Quake uses this to know
if it needs to handles modem initialization strings, dialing sequences,
and hangup procedures.
 
reset
This will reset the COM port to its default settings and state.
 
 
port <n>
irq <n>
These are used to set the I/O Port and IRQ that your serial port uses.
The default values are: port=3f8 irq=4 for COM1 and port=2f8 irq=3 for
COM2. Note that the port number is displayed in hexadecimal; to enter
it you would use something like "COM2 port 0x2f8"; the "0x" preceding
the "2f8" indicates that you are giving the value in hexadecimal
otherwise decimal is assumed.
 
 
baud <n>
Sets the baud rate. Valid values for <n> are: 9600, 14400,
28800, 57600, and 115200. 57600 is the default. Please note that
this is the baud rate used for the uart, not your modem. It is
perfectly valid to use 57600 on a COM port that is connected to a
28.8 modem.
 
8250 | 16550
Specifies the type of uart chip in your system. Normally this is
automatically detected, one of these need only be used if your chip
is incorrectly detected.
 
clear
startup
shutdown
This allows you to specify the clear, startup, and shutdown strings
needed for
a modem for playing Quake. If you've found values that
previously worked
with Doom, use them here. If you are playing over
a null modem cable,
leave these blank.
 
-cts | +cts
-dsr | +dsr
-cd | +cd
These determine if certain serial control lines should be honored or
ignored. The "-" means you want that line ignored, the "+" means to honor
it. "cts" is an abbreviation for "clear to send", "dsr" for
"data set ready", and "cd" for "carrier detect". Do not
change these
values unless you are absolutely positive you need to. The default is to
ignore all 3 lines.
 
Quake always uses no parity, 8 data bits, and 1 stop bit; these
values can not be changed. The baud, port, irq, and uart type can
not be changed on an enabled port, you must disable it first.
 
 
Configuration examples
----------------------
Example1: You have a machine with two serial ports you are going
to use as a Quake server. COM1 will be using a null modem cable and
COM2 will be connected to a 14.4 modem. You would use commands similar
(the startup string would almost certainly be different) to these:
 
COM1 baud 57600 enable
COM2 baud 14400 modem startup AT\N0%C0B8 enable
 
 
Example2: You are going to use your machine to connect to a dial-up
Quake server with your 28.8 modem connected to COM2. You would
use a command something like this:
 
COM2 baud 57600 modem startup AT\N0%C0B8 enable
 
Note the baud rate is not the same as the modem speed. This allows
the modem-to-uart communications to occur at a higher rate than
the modem-to-modem communications.
 
Connecting to a serial Quake server
-----------------------------------
 
Connecting to a Quake server over a serial/modem connection is done
using the "connect" command. The command "connect 5551212" would try to
connect to a Quake server at the phone number 555-1212. Note: your local
phone company would probably appreciate it if you didn't try this number!
 
If you are using a null modem cable, you can type "connect #".
Quake will then attempt to connect to the server.
 
 
Known problems / workarounds
============================
Packet drivers with PDIPX - there is a bug that stops a server running on
this combination from responding to the slist command. Use the patched
version of PDIPX included with Quake to correct this problem.
 
SLIST sees no servers - Some PCMCIA ethernet cards and PPP drivers will
not do the UDP broadcasts needed for the SLIST command (search for local
games from the menu) to function correctly. In these cases you must
connect to a Quake game using either its IP address or hostname
(DNS resolvable hostname, not the hostname variable in Quake).
 
"BW_OpenSocket failed: 5" - This error is specific to the Beame and
Whitesdie TCP/IP stack. This stack uses DOS file handles as it's
socket handles. This error occurs when DOS runs out of file handles.
You need to increase the number specified by "FILES=" in the DOS
config.sys file.
 
Severe lag using TCP/IP under Win95:
- Occasionaly when you first connect in to a Quake game using Win95
TCP/IP you will experience severe lag and not be able to control your
player's actions. This usually clears up in 10 to 15 seconds.
- There is apparently a strange limbo state for Microsoft's File and
Print sharing. This has been seen when it was installed and then later
removed, but it still appears on the menus. For some unknown reason
this causes severe lag for a Quake game. You need to go back and make
sure that it is either completely installed or removed.
 
 
==========================================
== Modem Strings ==
==========================================
 
Boca M1440i (internal):
ATS48=0S37=9S46=136%C0%E0%M0&K0&Q0&R1&C1&D2\G0\N1N0
 
Boca 14.4k (internal):
AT&C0N0S37=9&K0W0&Q0S36=3S48=128%C0
 
Boca 14.4 Fax/Modem
AT S46=0 S37=9 N0 &Q0 &D2 &K4
 
Boca 14.4k (external):
AT &F S0=1 S36=0 &K0 &Q6N0S37=9 &D2
 
Boca 14.4k:
AT S46=0 S37=9 N0 &Q0 &D2 &K0 %C0
 
Cardinal 14.4k v.32bis, v.42bis Fax/Modem:
AT &F N0 S37=9 &Q0 &D2 \N1
 
Digicom Systems (DSI) (softmodem):
AT Z \N0 &D2 &K0 S48=48
 
Digicom Systems Scout Plus:
ATZ*E0*N3*M0*S0*F0&D2
 
Gateway Telepath:
AT &F S37=9 %C0 &K0 &Q6 \G0
 
Gateway Telepath 14.4k:
AT S46=0 S37=9 N0 &Q0 &D2 &K0 %C0
 
Gateway Telepath I:
AT S0=1 &N6 &K0 &M0
 
Gateway Telepath II:
AT S0=1 S37=9 %C0 &Q0 &K0
 
Generic v.32bis 14.4k Fax/Modem:
AT \N0 %C0 B8
 
Generic 14.4k Fax/Modem:
AT S46=0 S37=9 N0 &Q0 &D2 %C0 \G0 &K0
 
GVC 14.4k (internal):
AT &F B8 \Q0
 
Hayes 28.8k V.FAST Modem:
AT &Q6 &K S37=9 N %C0 \N0
 
Infotel 144I:
AT&Q0 S37=9 N0 &D2
 
Infotel 14.4:
&F0 \N1 &D2 S37=F8
 
Intel 14.4k:
AT \N0 %C0 \Q0 B8
 
Intel 14.4k (internal):
AT Z B8 Q1 \C0 \N1 %C0 \V "H
 
Linelink 144e:
AT &F &D1 &K0 &Q6 S36=3 S46=136 %C0
19200
 
Microcom AX:
&F \N1 \Q0 &D2
 
Microcom QX/4232bis:
AT %C0 \N0
 
Netcomm M7F:
AT &E &K0 B0 \V0 X4 &D2 \N1 \Q0 #J0 #Q9 %C0
 
Nokia ECM 4896M Trellis V.32:
AT Z %C0 /N0
 
Nuvotel IFX 14.4 (internal):
&F \N1 &D2
 
Practical Peripherals 14400FX v.32bis:
AT Z S46=0 &Q0 &D2
 
Practical Peripherals 14400FX v.32bis:
AT S46=0 &Q0 &K0 &D2
 
Supra:
AT &F0 S46=136 %C0
 
Supra (external):
AT &K &Q &D \N1
 
Supra 14.4k v.32bis:
AT &F S46=136 &Q0 &D2
 
Supra 14.4k v.32bis:
AT &K &Q &D \N1
 
Supra Fax Modem 14.4K v.32 bis
AT &F %C0 S48=7 Q0 V1 W1
 
Telepath 14.4k:
AT &F&M0&K0&N6&H0 S0=1
 
Twincomm DFi 14.4:
AT&F &Q0 %C0 S37=9 &D2
 
UDS V.3223:
&F \N1 \Q &D2
 
UDS Fastalk 32BX:
&F0 \N1 &D2
 
USR Courier v.32bis:
ATS0=1 S7=60 E1 Q0 V1 &C1 &D2 &H0 &K0 &M0 &N6 &A3
 
USR Courier HST/DS 16.8k:
First reset the modem in a communication program with AT&F&W
AT X4 B0 &A0 &B0 &H2 &I0 &K0 &M0 &N6a
 
USR DS v.32bis v.42bis (external):
AT&m0&n6&a0&r1&h0&k0&i0&s0&b1x1
 
USR Sporster 9600:
AT&M0&K0&N6
 
USR Sportster V.34 28.8 (note: works best at 19200 baud):
AT &F &M0 &I0 &K0 &B0 &N0
 
USR Sportster 14.4k Fax/Modem USING ERROR CORRECTION:
AT S0=1 S7=60 E1 QO V1 &C1 &D2 &K0 &N6 &A3
 
USR Sportster 14.4k Fax/Modem (internal):
AT &F&M0&K0&N6&H0
 
USR Sportster 14.4k (internal):
AT &F &B1 &H0 &I0 &K0 &M0 &N6 &R1
 
USR Sportster 14.4k:
ATS0=1S7=60E1Q0V1&C1&D2&K0&N6&A3
 
USR Sportster 14.4k:
AT &F0 &K0 &M0 &N6 &H0 &I0 &B1 &R1
 
USR Sportster 14,000 Fax Modem:
AT S0=2 &N6 &K0 &M0 &I0 &H0 &R1 &A0 V1 X4
 
USR 14.4k:
AT &F&A0&K0&M0
 
USR 14.4k
AT &K0 &H0 &D0 &I0 &R1
 
USR 14.4k Dual Standard
ATB0&R1&B1&N6Q0X4&A0&D2&H0&I0&K0&M0M1
 
USR (model?):
&F E1 V1 X4 &C1 &D2 &N0
 
ViVa 14.4k:
AT&F&Q6\N0%C0&D2N0S37=9
 
ViVa modem (internal):
&F&Q6\N0%C0&D2N0S37=9
 
Zoltrix model 14/14 VE:
AT S0=Q0 V1 &C1 &D2 W2 &Q0
 
Zoom 14.4k VFX:
AT&Q6S37=9N0%C\N0
 
Zoom 14.4k VFX:
AT&Q6S37=11N0%C&K0
 
Zoom OEM Modem:
AT&Q6S37=9N0&K0
 
Zyxel U-1496E:
AT Z &N4 &K0
 
 
==========================================
== Win95 Documentation ==
==========================================
 
Quake is a DOS application. However, it runs fine from the MS-DOS prompt
under Win95, so long as the Properties for the MS-DOS prompt are set up so
that Quake can run. (See "Set the MS-DOS Prompt Properties", below, for
information about setting MS-DOS Prompt Properties.) Quake will NOT run
under Windows NT. Following are some steps that can help Quake run better
under Win95.
 
 
Have enough memory
------------------
 
Quake requires at least 16 Mb of installed memory in order to run under
Win95.
 
 
Set the MS-DOS Prompt Properties
--------------------------------
 
If Quake won't run, the MS-DOS Prompt Properties may not be set correctly.
To set the Properties for the MS-DOS prompt, bring up a DOS session, and
either click on the MS-DOS icon in the upper left corner or press
Alt-Spacebar, then select Properties from the menu that comes up, and make
sure the following settings are correct.
 
In the Program sheet of MS-DOS Prompt Properties, make sure the "Suggest
MS-DOS mode as necessary" is checked.
 
In the Memory sheet of MS-DOS Prompt Properties, make sure all five fields
are "Auto".
 
In the Screen sheet of MS-DOS Prompt Properties, set "Usage" to Full-screen.
 
In the Misc sheet of MS-DOS Prompt Properties, uncheck the "Allow screen
saver" box, and check the "Always suspend" box.
 
 
Make sure there's enough free disk space
----------------------------------------
 
If you get error messages like "can't lock memory" under Win 95, or if you
get other weird, inexplicable errors, make sure you haven't run out of disk
space; delete some files if necessary. You can see how much disk space is
free by bringing up "My Computer" and clicking on the disk icon; the free
disk space will be shown at the bottom of the window.
 
 
Run fullscreen
--------------
 
Quake can run in a window under Win95--but it will run very slowly. You are
unlikely to get satisfactory performance unless you run Quake fullscreen.
Quake normally comes up fullscreen under Win95; if you have switched it back
to windowed mode, you can get that window back to fullscreen by clicking on
it and then pressing Alt-Enter.
 
 
Shut down other applications
----------------------------
 
Many Win95 apps and DOS apps run even when they're not the foreground
application. Such applications contend for system resources such as memory,
processor cycles, and sound hardware. If Quake seems to be running choppily,
if sound is garbled, or if the disk is going all the time, try shutting down
whatever other applications you have running. For example, some players
have reported that Quake does not run as well when the Office shortcut bar
is running.
 
 
Restore the palette if it gets garbled
--------------------------------------
 
Under Win 95, the palette occasionally gets messed up when switching from
Quake to the desktop and back again. You can restore the palette by
bringing down the console (either press tilde ('~'), or press Esc to bring
up the menu, select Options, and select Console... from the Options menu),
and typing bf and pressing the enter key, to generate a background flash,
which sets the palette. Press Esc to exit the console. Alternatively,
setting the screen brightness, either from the Options menu or via the
gamma console command, sets the palette.
 
 
Avoid the system key
--------------------
 
Under Win 95, if the system key (the key with the Win 95 flag on it) is
pressed while Quake is running fullscreen in a VESA mode, Win 95 may be
unable to switch back from the desktop to Quake, in which case it will
notify you of this, then terminate the Quake session. This is a quirk
of Win 95, and there is no workaround other than not to press that key
or not to use VESA modes. (Some people go so far as to remove the system
key from their keyboard.) Switching away from Quake with Alt-Enter,
Ctrl-Esc, Alt-Tab, or Alt-Spacebar all work fine.
 
 
Give Quake more and/or locked memory
------------------------------------
 
By default, Quake tries to allocate 8 Mb of unlocked memory for heap space
under Win 95. More memory helps Quake run faster; you can allocate more
memory for Quake under Win95 by setting the command-line switch
 
-winmem x
 
where x is the number of megabytes to allocate for Quake. If there's enough
memory in the system, the larger the number, up to about 16, the better the
performance. If, however, there isn't enough memory in the system, or many
other applications are running, the larger number can just cause Quake to
page to disk a lot, and can actually slow performance considerably. Also,
higher numbers can also cause Win 95 to take longer to start Quake and take
longer to return to the desktop afterward. If you have 32 Mb or more in your
machine, -winmem 16 should provide the best performance for Quake. If you
have less than 32 Mb, or a lot of applications running, then you will have
to experiment to find the best amount of memory to allocate for Quake.
 
You may optionally instruct Quake to lock itself in memory by using the
command-line switch
 
-winlock
 
so it won't get paged out by other applications. This can avoid hitches when
parts of Quake get paged into and out of memory, and thus provide a smoother
playing experience. On the other hand, it can cause Quake to take longer to
start, and can make the return to the desktop take longer when Quake ends,
because Quake has been hogging a lot of memory. It is even possible, if most
of the memory in the system is locked by Quake, that it will take many
minutes to switch back to the desktop while Quake is running, so the system
will effectively be nearly frozen. Therefore, use -winlock with caution;
Quake is not as well-behaved a Win95 citizen when -winlock is specified, and
does not share resources particularly well.
 
-winmem can be used in conjunction with -winlock; if -winmem specifies more
memory than is available to be locked, then Quake will lock as much memory
as possible. Being too aggressive about how much memory is locked can
actually slow Quake performance, because unlocked parts of the system like
system CD and sound code and data can then be forced to page, so if you do
lock memory, you will have to experiment to find the sweet spot, unless you
have 32 Mb or more of memory.
 
-winlockunlock can be specified as an alternative to -winlock, to tell Quake
to lock its memory when it starts, then immediately unlock it. The
advantages of doing this are: 1) it forces all of Quake's pages into memory,
so no pages should need to be brought in as Quake runs, making for smoother
running at the start, and 2) it enables Quake to determine whether the
specified amount of memory (if -winmem is also specified) is available in the
machine, so you can be sure Quake won't try to allocate more heap space than
the the amount of physical memory that's actually available. Like -winlock,
-winlockunlock causes Quake to take quite a bit longer to start up, but it
has the advantage of making Quake a good Win95 citizen if you need to switch
back to the desktop, or have other apps running.
 
In general, Quake will run fine without any of the -winxxx switches, but you
may find that one or more of them--particularly -winmem if you have more than
16 Mb--helps Quake performance on your machine.
 
None of this is an issue under DOS itself (as oppsed to a DOS box under
Win95), because Quake just uses all the memory in the machine under DOS.
 
By default, Quake tries to allocate 8 Mb of unlocked memory for heap space
 
 
Watch out for limbo subsystems
------------------------------
Microsoft's File and Print sharing and IPX protocol stack have both been
known to cause strange problems when they are in a limbo state. The limbo
state is seems to be an uninstall that did not complete succesfully. Both
of these cause poor network play performance. If you are experiencing
severe lag, check the File and Print services. If you the warning "IPX
driver send failue: 04", check the IPX protocol stack. They need to be
either completely installed or removed; the problems only occur when they
get into this strange semi-installed state.
 
 
==========================================
== Key Binding and Aliases ==
==========================================
 
Pressing the tilde key ("~") will bring down the console (pressing the
tilde key or ESC while in the console will close the console). From the
console you can adjust your player controls, this is done by "binding"
keys to commands. The format for binding keys is as follows:
 
bind <key> <command>
 
Where <key> is a valid key control and <command> is a valid quake command.
 
Example:
To bind the j key to the 'jump' command, you would type:
bind j +jump
and press enter.
 
Non-printable keys such as 'page up' and buttons from the mouse/joystick are
bound in the same manner as printable characters. A list of bindable keys can
be found at the end of this file.
 
Example:
To bind the page up key to the 'jump' command, you would type:
bind pageup +jump
and press enter.
 
To bind the right mouse button to the attack command, you would type:
bind mouse2 +attack
and press enter.
 
The alias command is used to create a reference to a command or list of
commands. When aliasing multiple commands, or commands that contain
multiple words (such as "fraglimit 50"), you must enclose all the commands
in quotation marks and separate each command with a semi-colon.
 
Example of an alias that changes some Deathmatch server parameters:
 
alias net_game "hostname my_server ; fraglimit 15 ; timelimit 15"
bind INS net_game
 
Once the server is spawned (you must be the one running the -listen server),
you just push the Insert key to set the hostname, frag limit and time limit
of the server. So now the first person to 15 frags, or with the one with the
most frags in 15 minutes, wins.
 
Another example would be to change to the Rocket Launcher, fire one rocket,
and change back to the Double Barrel Shotgun, when you press the "," key:
 
alias rl_dbsg "impulse 7 ; +attack ; wait ; -attack ; impulse 3"
bind , rl_dbsg
 
Aliasing is very powerful, allowing you great flexibility, so you should
experiment by aliasing different commands in various ways.
 
A list of common commands can be found in the next section.
 
 
==========================================
== Quake Keys and Common Commands ==
==========================================
 
The following keys can be bound:
 
A-Z 0-9
*F1-F12 *TAB
ENTER SPACE
BACKSPACE UPARROW
DOWNARROW LEFTARROW
RIGHTARROW ALT
CTRL SHIFT
INS DEL
PGDN PGUP
HOME END
PAUSE SEMICOLON
 
MOUSE1 (mouse button 1)
MOUSE2 (mouse button 2)
MOUSE3 (mouse button 3)
 
*~ (tilde)
 
* Can only be bound on the command line or in a .cfg file.
 
The ESC key cannot be bound.
 
 
==========================================
== Making a Config File ==
==========================================
 
The commands (bindings and aliases) discussed above can be included into a
file containing all of your personal configurations, known as a "config"
file. This file can then be loaded during game play to enable all your
personal bindings and settings.
 
To do this, use your favorite editor to create a new file, such as
"fragmstr.cfg". Your .cfg file MUST be located in the quake\id1 directory
or quake won't find it. Then after launching Quake, you would type "exec
fragmstr.cfg" and press enter, from the console. You can also exec you .cfg
file from the DOS command prompt by typing "quake +exec fragmstr.cfg".
When you exec a config file, it is the same as typing all the lines in your
config file into the console, only Quake does it for you. Here is an
example config file (c:\quake\id1\bear.cfg) and the meaning of all the
bindings, aliases and settings:
 
-------------------------------cut here-------------------------------------
name player1 // Sets player name to player1 (lets your opponent
// know who fragged them)
 
sensitivity 4 // Sets the mouse sensitivity to 4
 
scr_conspeed 5000 // Sets the console raise/lower speed
 
lookspring 0 // Sets Mouse Look Spring to 0 (0=keep looking,
// 1=spring back, when mouse button is released)
 
vid_mode 10 // Sets Video Mode to mode 10 (360X480 resolution)
 
gamma .8 // Sets Gamma Correction to .8 (<1=Lighter, 1=normal
// and >1=darker)
 
viewsize 70 // Sets the Screen View size to 70 degrees
 
bind mouse1 +forward // Binds the left mouse button to Move Forward
 
bind mouse3 +attack // Binds the middle mouse button to Fire
 
bind mouse2 +mlook // Binds the right mouse button to Mouse Look
 
bind HOME "save bear1" // Binds the Home Key to quick save, saves to
// bear1.sav
 
bind ENTER +showscores // Binds the Enter key to show Deathmatch Scores
 
bind SHIFT +speed // Binds the Shift key to Run
 
bind CTRL +jump // Binds the Control key to Jump
 
bind ; +mlook // Binds the ; key to Mouse Look also
 
bind . +moveleft // Binds the . key to Strafe Left
 
bind / +moveright // Binds the / key to Strafe Right
 
color 3 4 // Makes Uniform Top green and Pants Red for Net play
 
alias rl_dbsg "impulse 7 ; +attack ; wait ; -attack ; impulse 3"
 
bind , rl_dbsg // Aliases single rocket attack command and binds
// it to the ',' key.
-------------------------------cut here-------------------------------------
 
 
==========================================
== Demos ==
==========================================
 
The standard Demos
------------------
 
Quake has 3 standard demos that start playing when you first run the game.
It will cycle through these demos until you start or join a game.
 
Recording a Demo
----------------
"record <demoname> <map> [track]" This starts up level <map> and begins
recording a demo into a file name <demoname>.dem. You can specify the
optional <track> to choose a background music from the CD, otherwise the
default selection for that map will be played.
 
Playing a Demo
--------------
"playdemo <demoname>" This command will open the file <demoname>.dem and
play the demo.
 
How to not play the standard demos at startup
---------------------------------------------
 
So you've seen the Necropolis demo 10 billion times now and really don't
ever want to see it again? Here's how.
 
The easy way is to start Quake with a "+map" command. You could do
"quake +map start" and you'll start on the single player start level.
Or you could do "quake +map nonsense" and you'll wind up at the Quake
console since there is no map named nonsense. You can accomplish the
same thing with a "+connect" too. "+connect" by itself will look for
Quake servers on the local network, "+connect 192.12.34.56" or
"+connect host.timbuktu.edu" will try to connect the the specified
Quake server.
 
There is another way to not show the demos; one that also keeps your
customizations in a seperate directory from the data files in the
Quake distribution.
 
Do this in the quake directory (the directory where you installed Quake;
where you find "quake.exe" and "the id1" directory). Create a file named
"quake.rc". Its contents should be:
 
exec default.cfg
exec config.cfg
exec autoexec.cfg
stuffcmds
menu_main
 
Create a batch file to run Quake in the quake directory. "Q.BAT" is a good
name. It's contents should be:
 
quake -game . %1 %2 %3 %4 %5 %6 %7 %8 %9
 
If you normally use the Q95 batch file, just add the "-game ." part to
that file.
 
Now you can run "q" and quake will start off with the main menu displayed
instead of running the demos.
 
You can also make a seperate subdirectory for this if you'd like. For
example, make a directory named "mine" in the quake directory. Create
the "quake.rc" file as specified above in this directory. Use
"-game mine" instead of "-game ." in your batch file.
 
Important note: The directory specified by "-game" is where Quake will
look for config.cfg, load and save games, and record and play
demos.
 
 
==========================================
== Reporting Quake Bugs ==
==========================================
 
How to use the bug report:
 
Where to send bug reports:
E-mail : support@idsoftware.com
FAX : 214-686-9288
 
There are two sections of information - primary and secondary.
 
Primary information contains information such as date, your name, e-mail
address, etc. Secondary information is actual bug information. There are
a few different sections depending on what type of bug you revieced
(sound, video, etc). Only fill out and include information from the section
related to the type of bug you received.
 
If possible, start Quake with the "-condebug" command line parameter
and try to reproduce the bug. Attach the "qconsole.log" file found in the
"id1" directory to the end of the bug report. If the bug is sound related,
while in Quake, execute the SOUNDINFO and SBINFO (DOS only) commands from
the console.
 
Please attach a copy of your CONFIG.SYS and AUTOEXEC.BAT file to the end of
the report.
 
Bugs submitted properly with this form will get attention.
Unformatted ones sent to personal accounts will be ignored.
If you see problems, please take the time to do this.
 
If you do not have all of the information requested in the form,
don't worry. Send what you do have.
 
Please include the version #. THe version # for Quake can be found in the
lower right hand corner of the console. To bring up the console, press the
tilde ('~') key. Press tilde ('~') again or ESC to exit.
 
-------------------------------cut here-------------------------------------
 
 
============================================================================
== Quake Bug Report - Primary information ==
============================================================================
 
Date:
Name:
Phone number:
E-mail address: (please include this, we redirect tons of mail)
Game Title:
Version #:
Operating system (i.e., DOS 6.0 or Windows 95):
Computer type:
BIOS date:
BIOS version:
Processor type:
Processor speed:
Do you program at school/work?
Do you provide tech. support at school/work?
Please state the problem you encountered:
Please state how to reproduce the problem:
 
If program crashed with nasty undecipherable techno-garbage, please
look for the eight-digit hex number which comes after "eip="
and write it down here:
 
 
============================================================================
== Quake Bug Report - Secondary information ==
============================================================================
 
------------------------------ Video Related ------------------------------
 
Video Card Manufacturer:
Video Card Model:
Chipset Used:
BIOS Date:
(If using UniVBE, The above information can be found by running uvconfig)
 
Did the problem occur while in a VESA mode?
 
If so, what is the VESA driver and version? (eg., UniVBE 5.1a,
built into board BIOS, or manufacturer provided TSR)
 
------------------------------ Sound Related ------------------------------
 
Audio card brand and model:
 
If DOS or a DOS box, please run the command "set > set.txt" then
attach "set.txt" to the end of the report.
 
----------------------------- Network Related -----------------------------
 
What type of network connection was established when the error occurred?
(modem, nullmodem, or network)
If modem, Modem brand and model:
 
If network, Network card brand and model:
Network protocol/configuration:
 
---------------------------------------------------------------------------
 
 
 
 
 
 
 
/contrib/other/sdlquake-1.0.9/docs/INSTALL
0,0 → 1,177
INSTALL for Linux Quake
-----------------------
 
Quake for Linux provides several different binary executables to support
different hardware and drivers.
 
Included with Linux Quake are:
- SVGALib Quake (squake)
This is a software renderer Quake that runs at the text console in Linux.
- GLQuake (glquake, glquake.glx and glquake.3dfxgl)
This is a hardware renderer Quake that runs using hardware 3D
acceleration.
- X11 Quake (quake.x11)
Software rendering in a window under X11.
 
Installation
------------
 
Mount the Quake CD as one would usually mount a CDROM, this can be
accomplished by using the command:
 
mount /dev/cdrom /mnt
 
As root. Once the CD is mounted, run the setup script on the CD as root.
 
$ su
Password:
# mount /dev/cdrom /mnt
# /bin/sh /mnt/setup
 
The script will ask some questions about what options you want to install
and automatically install the software into /usr/local/games/quake.
 
Requirements
------------
 
Requirements for SVGALib Quake:
 
- SVGALib 1.20 or later (/lib/libvga.so.1.2.10)
- libc 5.2.18 or later (5.0.9 will not work, /lib/libc.so.5.2.18)
or glibc (libc6) for the glibc version
- CD-ROM for CDAudio
- Soundcard capable of mmap'd buffers. USSLite 3.5.4 was used to build squake
with. Works fine on SoundBlaster 16 and Gravis Ultrasound MAX.
- SVGALib supported mouse (usually if it works with X, it'll work with
squake).
- Kernel 2.0.24 or later
- untested with 2.1 kernels, your mileage may vary
 
Requirements for GLQuake:
 
- 3DFX based card for the GLQuake version, VooDoo, VooDoo Rush or VooDoo2
at this writing. In order to use 3DFX hardware, you must have 3DFX's
GLIDE drivers installed. RPMs for these drivers are available at:
http://glide.xxedgexx.com/3DfxRPMS.html
- For the glX version, an OpenGL implementation that includes hardware
glX support.
- CD-ROM for CDAudio
- Soundcard capable of mmap'd buffers. USSLite 3.5.4 was used to build squake
with. Works fine on SoundBlaster 16 and Gravis Ultrasound MAX.
- SVGALib compatible mouse for glquake or X11 for glquake.glx
- Kernel 2.0.24 or later
- untested with 2.1 kernels, your mileage may vary
 
Requirements for X11 Quake:
 
- X11R5 later, only tested with XFree86, should work with most X Servers
- libc 5.2.18 or later (5.0.9 will not work, /lib/libc.so.5.2.18)
or glibc (libc6) for the glibc version
- CD-ROM for CDAudio
- Soundcard capable of mmap'd buffers. USSLite 3.5.4 was used to build squake
with. Works fine on SoundBlaster 16 and Gravis Ultrasound MAX.
- SVGALib supported mouse (usually if it works with X, it'll work with
squake).
- Kernel 2.0.24 or later
- untested with 2.1 kernels, your mileage may vary
 
Additional notes for SVGALib Quake
----------------------------------
 
SVGALib may not detect a 3-button mouse properly (it
will only use two buttons). Check your /etc/vga/libvga.config
and set it up for your mouse type.
 
Also, newer versions of SVGALib have an mouse_accel_type option. Most
users will want to set this to "off" in /etc/vga/libvga.config.
 
Additional notes for GLQuake
----------------------------
 
There are three different ways to execute GLQuake:
 
1. The binary "glquake" requires Mesa 3-D 2.5 or later installed and compiled
with 3DFX support (fxMesa..() function interface). It also requires
svgalib 1.3.0 or later for keyboard/mouse input. This binary is a console
application. Mesa 3-D requires GLIDE to be installed.
 
2. The shell script "glquake.3dfxgl" runs the "glquake" binary after
preloading the lib3dfxgl.so library. This is a port of 3DFX's Win32
OpenGL MCD (Mini Client Driver) to Linux. It is faster than Mesa 3-D
since it was written specifically with supporting GLQuake in mind.
lib3dfxgl.so requires that GLIDE be installed.
 
3. The binary "glquake.glx" is linked against standard OpenGL libraries.
It should run on many different hardward OpenGL implementations under
Linux and X11. This binary is an X11 application and must be run under
X11. It will work with Mesa 3-D as a standard glX based OpenGL
applications. If the Mesa 3-D library is compiled with 3DFX support,
you can have Mesa 3-D support 3DFX hardware under X11 by setting the
enviroment variable "MESA_GLX_FX" to "fullscreen" for fullscreen mode
and "window" for windowed mode, eg. "export MESA_GLX_FX=fullscreen" for sh
or "setenv MESA_GLX_FX fullscreen" for csh.
 
For glquake, you must also have SVGALib or later installed (1.3.0 or later
prefered). GLQuake uses SVGALib for mouse and keyboard handling.
 
If you have gpm and/or selection running, you will have to terminate them
before running GLQuake since they will not give up the mouse when GLQuake
attempts to run. You can kill gpm by typing 'killall gpm' as root.
 
You must run GLQuake as root or setuid root since it needs to access things
such as sound, keyboard, mouse and the 3DFX video. Future versions may not
require root permissions.
 
Additional notes for X11 Quake
------------------------------
 
This is a windowed version that is generic for X11. It runs in a window
and can be resized. You can specify a starting window size with:
-width <width>
-height <height>
-winsize <width> <height>
Default is 320x200. It works in 16bit modes, but it's slower (twice as many
bytes to copy).
 
No other video modes are supported (just runs windowed). Mouse is read, but
not "grabbed" by default. Go to the Options menu and turn on Use Mouse to grab
the mouse and use it in the game (or type "_windowed_mouse 1" at the console).
 
Command Line Options for Linux Quake
------------------------------------
 
-mem <mb>
Specify memory in megabytes to allocate (default is 8MB, which should be fine
for most needs).
 
-nostdout
Don't do any output to stdout
 
-mdev <device> (SVGALib based versions only)
Mouse device, default is /dev/mouse
 
-mrate <speed> (SVGALib based versions only)
Mouse baud rate, default is 1200
 
-cddev <device>
CD device, default is /dev/cdrom
 
-mode <modenum>
Use indicated video mode
 
-nokdb
Don't initialize keyboard
 
-sndbits <8 or 16>
Set sound bit sample size. Default is 16 if supported.
 
-sndspeed <speed>
Set sound speed. Usual values are 8000, 11025, 22051 and 44100.
Default is 11025.
 
-sndmono
Set mono sound
 
-sndstereo
Set stereo sound (default if supported)
 
/contrib/other/sdlquake-1.0.9/docs/INSTALL.Q2Mission
0,0 → 1,39
INSTALL for Linux Quake2 Mission Packs
--------------------------------------
 
Installation
------------
 
Mount the Quake2 Mission Pack CD as one would usually mount a CDROM, this can
be accomplished by using the command:
 
mount /dev/cdrom /mnt
 
As root. Once the CD is mounted, run the setup script on the CD as root.
 
$ su
Password:
# mount /dev/cdrom /mnt
# /bin/sh /mnt/setup
 
The script will ask some questions about what options you want to install
and automatically install the software into /usr/local/games/quake2.
 
After Installation
------------------
 
To run Quake2 Mission Pack #1: The Reckoning add the following option when
executing Quake2:
 
./quake2 +set game xatrix
 
To run Quake2 Mission Pack #2: Ground Zero add the following:
 
./quake2 +set game rogue
 
Requirements
------------
 
The Quake2 Mission Packs require a previous installation of Quake2.
 
 
/contrib/other/sdlquake-1.0.9/docs/INSTALL.Quake
0,0 → 1,177
INSTALL for Linux Quake
-----------------------
 
Quake for Linux provides several different binary executables to support
different hardware and drivers.
 
Included with Linux Quake are:
- SVGALib Quake (squake)
This is a software renderer Quake that runs at the text console in Linux.
- GLQuake (glquake, glquake.glx and glquake.3dfxgl)
This is a hardware renderer Quake that runs using hardware 3D
acceleration.
- X11 Quake (quake.x11)
Software rendering in a window under X11.
 
Installation
------------
 
Mount the Quake CD as one would usually mount a CDROM, this can be
accomplished by using the command:
 
mount /dev/cdrom /mnt
 
As root. Once the CD is mounted, run the setup script on the CD as root.
 
$ su
Password:
# mount /dev/cdrom /mnt
# /bin/sh /mnt/setup
 
The script will ask some questions about what options you want to install
and automatically install the software into /usr/local/games/quake.
 
Requirements
------------
 
Requirements for SVGALib Quake:
 
- SVGALib 1.20 or later (/lib/libvga.so.1.2.10)
- libc 5.2.18 or later (5.0.9 will not work, /lib/libc.so.5.2.18)
or glibc (libc6) for the glibc version
- CD-ROM for CDAudio
- Soundcard capable of mmap'd buffers. USSLite 3.5.4 was used to build squake
with. Works fine on SoundBlaster 16 and Gravis Ultrasound MAX.
- SVGALib supported mouse (usually if it works with X, it'll work with
squake).
- Kernel 2.0.24 or later
- untested with 2.1 kernels, your mileage may vary
 
Requirements for GLQuake:
 
- 3DFX based card for the GLQuake version, VooDoo, VooDoo Rush or VooDoo2
at this writing. In order to use 3DFX hardware, you must have 3DFX's
GLIDE drivers installed. RPMs for these drivers are available at:
http://glide.xxedgexx.com/3DfxRPMS.html
- For the glX version, an OpenGL implementation that includes hardware
glX support.
- CD-ROM for CDAudio
- Soundcard capable of mmap'd buffers. USSLite 3.5.4 was used to build squake
with. Works fine on SoundBlaster 16 and Gravis Ultrasound MAX.
- SVGALib compatible mouse for glquake or X11 for glquake.glx
- Kernel 2.0.24 or later
- untested with 2.1 kernels, your mileage may vary
 
Requirements for X11 Quake:
 
- X11R5 later, only tested with XFree86, should work with most X Servers
- libc 5.2.18 or later (5.0.9 will not work, /lib/libc.so.5.2.18)
or glibc (libc6) for the glibc version
- CD-ROM for CDAudio
- Soundcard capable of mmap'd buffers. USSLite 3.5.4 was used to build squake
with. Works fine on SoundBlaster 16 and Gravis Ultrasound MAX.
- SVGALib supported mouse (usually if it works with X, it'll work with
squake).
- Kernel 2.0.24 or later
- untested with 2.1 kernels, your mileage may vary
 
Additional notes for SVGALib Quake
----------------------------------
 
SVGALib may not detect a 3-button mouse properly (it
will only use two buttons). Check your /etc/vga/libvga.config
and set it up for your mouse type.
 
Also, newer versions of SVGALib have an mouse_accel_type option. Most
users will want to set this to "off" in /etc/vga/libvga.config.
 
Additional notes for GLQuake
----------------------------
 
There are three different ways to execute GLQuake:
 
1. The binary "glquake" requires Mesa 3-D 2.5 or later installed and compiled
with 3DFX support (fxMesa..() function interface). It also requires
svgalib 1.3.0 or later for keyboard/mouse input. This binary is a console
application. Mesa 3-D requires GLIDE to be installed.
 
2. The shell script "glquake.3dfxgl" runs the "glquake" binary after
preloading the lib3dfxgl.so library. This is a port of 3DFX's Win32
OpenGL MCD (Mini Client Driver) to Linux. It is faster than Mesa 3-D
since it was written specifically with supporting GLQuake in mind.
lib3dfxgl.so requires that GLIDE be installed.
 
3. The binary "glquake.glx" is linked against standard OpenGL libraries.
It should run on many different hardward OpenGL implementations under
Linux and X11. This binary is an X11 application and must be run under
X11. It will work with Mesa 3-D as a standard glX based OpenGL
applications. If the Mesa 3-D library is compiled with 3DFX support,
you can have Mesa 3-D support 3DFX hardware under X11 by setting the
enviroment variable "MESA_GLX_FX" to "fullscreen" for fullscreen mode
and "window" for windowed mode, eg. "export MESA_GLX_FX=fullscreen" for sh
or "setenv MESA_GLX_FX fullscreen" for csh.
 
For glquake, you must also have SVGALib or later installed (1.3.0 or later
prefered). GLQuake uses SVGALib for mouse and keyboard handling.
 
If you have gpm and/or selection running, you will have to terminate them
before running GLQuake since they will not give up the mouse when GLQuake
attempts to run. You can kill gpm by typing 'killall gpm' as root.
 
You must run GLQuake as root or setuid root since it needs to access things
such as sound, keyboard, mouse and the 3DFX video. Future versions may not
require root permissions.
 
Additional notes for X11 Quake
------------------------------
 
This is a windowed version that is generic for X11. It runs in a window
and can be resized. You can specify a starting window size with:
-width <width>
-height <height>
-winsize <width> <height>
Default is 320x200. It works in 16bit modes, but it's slower (twice as many
bytes to copy).
 
No other video modes are supported (just runs windowed). Mouse is read, but
not "grabbed" by default. Go to the Options menu and turn on Use Mouse to grab
the mouse and use it in the game (or type "_windowed_mouse 1" at the console).
 
Command Line Options for Linux Quake
------------------------------------
 
-mem <mb>
Specify memory in megabytes to allocate (default is 8MB, which should be fine
for most needs).
 
-nostdout
Don't do any output to stdout
 
-mdev <device> (SVGALib based versions only)
Mouse device, default is /dev/mouse
 
-mrate <speed> (SVGALib based versions only)
Mouse baud rate, default is 1200
 
-cddev <device>
CD device, default is /dev/cdrom
 
-mode <modenum>
Use indicated video mode
 
-nokdb
Don't initialize keyboard
 
-sndbits <8 or 16>
Set sound bit sample size. Default is 16 if supported.
 
-sndspeed <speed>
Set sound speed. Usual values are 8000, 11025, 22051 and 44100.
Default is 11025.
 
-sndmono
Set mono sound
 
-sndstereo
Set stereo sound (default if supported)
 
/contrib/other/sdlquake-1.0.9/docs/INSTALL.Quake2
0,0 → 1,218
INSTALL for Linux Quake2
------------------------
 
Quake2 for Linux supports the following video subsystems:
 
- SVGALib Console Graphics (ref_soft.so)
- Requires SVGALib 1.2.0 or later
- X11 Window Graphics (ref_softx.so)
- X11R5 or later, XShm shared memory extension supported
- 3DFX fxMesa with Mesa 3-D or 3DFX Miniport (ref_gl.so)
- Mesa 3-D 2.6 or later, specifically compiled for 3DFX support
Mesa 3-D 2.6 compiled with 3DFX support is provided with this archive.
- Generic glX (X11) based OpenGL (ref_glx.so)
- Requires a glX based hardware accelerated OpenGL implementation.
Mesa 3-D 2.6 supports this on 3DFX hardware.
 
Also included is a specific 3DFX mini-OpenGL implementation for running Quake2
on 3DFX hardware.
 
Installation
------------
 
Mount the Quake2 CD as one would usually mount a CDROM, this can be
accomplished by using the command:
 
mount /dev/cdrom /mnt
 
As root. Once the CD is mounted, run the setup script on the CD as root.
 
$ su
Password:
# mount /dev/cdrom /mnt
# /bin/sh /mnt/setup
 
The script will ask some questions about what options you want to install
and automatically install the software into /usr/local/games/quake2.
 
Make sure you have the appropirate hardware, drivers and libraries installed
for the renderer you are going to play on.
 
Quake2 for Linux supports the following renderers:
 
- ref_soft
Software rendering under SVGALib (console only). SVGALib 1.2.10 or later
is required. Note that SVGALib 1.2.11 supports the ability to run a
SVGALib application under X11 as it will automatically allocate a new
console. The default mode is 320x240 (ModeX) since that is the lowest
resolution supported by Quake2. If SVGALib supports your video card, higher
resolution modes such as 640x480 and 800x600 are also supported.
 
Please note that you may need to configure your mouse for SVGALib in
/etc/vga/libvga.config (or /etc/libvga.config).
 
- ref_softx
Software rendering under X11. This uses the MITSHM Extension and should
work will virtually all Linux X Servers. **NOTE: Do not resize the window
under X11. You must use the Video menu to change resolution/window size.
 
By default, the mouse will not be 'tied' to the Quake2 window. To cause
Quake2 to grab the mouse, select 'Windowed Mouse' from the video menu,
or type '_windowed_mouse 0' at the console. Do the reverse to release it.
You can bind keys to grab and release the mouse in the console, like so:
bind i "_windowed_mouse 1"
bind o "_windowed_mouse 0"
Then "i" will grab the mouse and "o" will release it.
 
- ref_gl
This render can be run with two different OpenGL drivers: Mesa 3-D
ontop of Linux GLIDE, or 3DFX's mini-OpenGL Quake driver.
For Mesa 3-D, the necessary libMesaGL.so.2.6 is included with this archive.
You must copy it to /usr/lib or /usr/local/lib and run ldconfig (as root)
in order to use it. You can do this as follows:
tar cf - lib*GL* | (cd /usr/lib; tar xf -)
You should use tar to keep the symlinks intact. Once you copy them over
run ldconfig.
You must also download and install the Linux GLIDE drivers at
http://www.3dfx.com/software/download_glidel.html
And install them as instructed.
RPMs for GLIDE are available at :
http://glide.xxedgexx.com/3DfxRPMS.html
With version 3.20, the GL library is entirely runtime loaded. This means
you can specify what shared object to load for GL display.
To use Mesa 3-D GL (console), run quake with:
./quake2 +set vid_ref gl +set gl_driver libMesaGL.so.2
To use the 3DFX OpenGL Miniport, run the included quake2.3dfxgl:
./quake2 +set vid_ref gl +set gl_driver lib3dfxgl.so
The gl_driver cvar indicates the name of the library to load for GL
functions. It can be in any directory listed in /etc/ld.so.conf
or in /etc/quake2.conf
 
**NOTE: There is a problem on libc5 systems where a vid_restart (causing
a reload of the video system) will crash. There doesn't seem to be a
solution to this yet. It looks to be some sort of ld.so dynamic loading
interaction with SVGALib and ref_gl.so. A work around is to start in
software mode (./quake2 +set vid_ref soft), then use the menu to set your
mode and a vid_restart will work when going from software to GL. Exit
out then and save your video mode settings.
This problem does not occur on libc6 (glibc) based systems; vid_restart
works fine on there.
 
- ref_glx
ref_glx should run on many different hardward OpenGL implementations under
Linux and X11. This binary is an X11 application and must be run under
X11. It will work with Mesa 3-D as a standard glX based OpenGL
applications. If the Mesa 3-D library is compiled with 3DFX support,
you can have Mesa 3-D support 3DFX hardware under X11 by setting the
enviroment variable "MESA_GLX_FX" to "fullscreen" for fullscreen mode
and "window" for windowed mode, eg. "export MESA_GLX_FX=fullscreen" for sh
or "setenv MESA_GLX_FX fullscreen" for csh.
 
As with ref_gl, the "gl_driver" cvar indicates the shared library to load
for OpenGL functions (the glX functions must provided in that library
as well).
 
Permissions
-----------
 
Quake2 requires root permissions to use the software (SVGALib) and GL (MesaGL
w/3dfx) renders. In order to make this secure, some special considerations
must be made.
 
Quake2 should get setuid root:
chown root quake2
chmod 4711 quake2
 
And the ref_soft.so and ref_gl.so files must owned by root.
 
The file /etc/quake2.conf must be installed. This file contains a single
line with the path of where the ref shared libraries can be found.
A sample one is included that lists /usr/games/quake2 as the default
path. The libraries are only loaded out of the directory listed in
/etc/quake2.conf for security considerations.
 
Special permissions are not required for the softx renderer, but quake2 may
still need to be setuid root to open the sound device (quake2 will give up
setuid root permissions before loading softx).
 
NOTE: If you use a setuid quake2 binary and run it as a normal user, it
will NOT be able to switch renderers on the fly because root permissions
are given up after the renderer is loaded. You can switch renderers on the
fly if you run quake2 as root (su or log in as root).
 
NOTE: When the quake2 binary is run in dedicated server mode
(+set dedicated 1), no special permissions are required and
/etc/quake2.conf is not read since no renderer is loaded.
 
----
 
The first time you run Quake2, it will use ref_soft or ref_softx based
on whether a DISPLAY environment variable exists.
 
To force the loading of a specific renderer at load time, use the following
command lines:
 
./quake2 +set vid_ref soft
./quake2 +set vid_ref softx
./quake2 +set vid_ref gl
./quake2 +set vid_ref glx
 
Linux Specific Cvars
--------------------
 
To set this, use +set on the command line, i.e.:
./quake2 +set cd_dev /dev/hdc +set sndmono 1
 
nocdaudio (defaults to 0)
Do not enable cd audio if not zero
 
sndbits (defaults to 16)
Set sound bit sample size.
 
sndspeed (defaults to 0)
Set sound speed. Usual values are 8000, 11025, 22051 and 44100.
If set to zero, causes the sound driver to attempt speeds in the following
order: 11025, 22051, 44100, 8000.
 
sndchannels (defaults to 2)
Indicates stereo or mono sound. Defaults to 2 (stereo). Use 1 for mono.
 
nostdout (defaults to 0)
Whether to output console msgs to standard out. Non-zero is cease output.
 
Dedicated server
----------------
 
To run Linux Quake2 as a dedicated server, just run it as follows:
 
./quake2 +set dedicated 1
 
You can also set dmflags, timelimit, etc. in a config file, like so:
set timelimit 20
set fraglimit 25
set dmflags 532
map fact3
 
Then exec that config file on load, like so:
 
./quake2 +set dedicated 1 +exec server.cfg
 
If you use a config file, you must put a 'map' command in it or the
server won't load a map.
 
To run a dedicated server in the background, use this;
 
nohup ./quake2 +set dedicated 1 +exec server.cfg &
 
A better way is to run Quake2 on a tty via screen. screen can be found
at ftp://prep.ai.mit.edu/pub/gnu/screen-3.7.4.tar.gz, but it comes with
most modern Linux installations now.
 
-----------------------------------------------------------------------------
 
Linux Quake2 is an unsupported product. Usage of this product is bound by
the legal notice found on the distribution Quake2 CDROM.
 
/// Zoid
zoid@idsoftware.com
 
/contrib/other/sdlquake-1.0.9/docs/README
0,0 → 1,157
README for Linux Quake
----------------------
 
This README convers all versions of Quake for Linux:
- SVGALib Quake (squake)
- GLQuake (glquake, glquake.glx and glquake.3dfxgl)
- X11 Quake (quake.x11)
 
Requirements for SVGALib Quake:
 
- SVGALib 1.20 or later (/lib/libvga.so.1.2.10)
- libc 5.2.18 or later (5.0.9 will not work, /lib/libc.so.5.2.18)
or glibc (libc6) for the glibc version
- CD-ROM for CDAudio
- Soundcard capable of mmap'd buffers. USSLite 3.5.4 was used to build squake
with. Works fine on SoundBlaster 16 and Gravis Ultrasound MAX.
- SVGALib supported mouse (usually if it works with X, it'll work with
squake).
- Kernel 2.0.24 or later
- untested with 2.1 kernels, your mileage may vary
 
Requirements for GLQuake:
 
- 3DFX based card for the GLQuake version, VooDoo, VooDoo Rush or VooDoo2
at this writing. In order to use 3DFX hardware, you must have 3DFX's
GLIDE drivers installed. RPMs for these drivers are available at:
http://glide.xxedgexx.com/3DfxRPMS.html
- For the glX version, an OpenGL implementation that includes hardware
glX support.
- CD-ROM for CDAudio
- Soundcard capable of mmap'd buffers. USSLite 3.5.4 was used to build squake
with. Works fine on SoundBlaster 16 and Gravis Ultrasound MAX.
- SVGALib compatible mouse for glquake or X11 for glquake.glx
- Kernel 2.0.24 or later
- untested with 2.1 kernels, your mileage may vary
 
Requirements for X11 Quake:
 
- X11R5 later, only tested with XFree86, should work with most X Servers
- libc 5.2.18 or later (5.0.9 will not work, /lib/libc.so.5.2.18)
or glibc (libc6) for the glibc version
- CD-ROM for CDAudio
- Soundcard capable of mmap'd buffers. USSLite 3.5.4 was used to build squake
with. Works fine on SoundBlaster 16 and Gravis Ultrasound MAX.
- SVGALib supported mouse (usually if it works with X, it'll work with
squake).
- Kernel 2.0.24 or later
- untested with 2.1 kernels, your mileage may vary
 
Additional notes for SVGALib Quake
----------------------------------
 
SVGALib may not detect a 3-button mouse properly (it
will only use two buttons). Check your /etc/vga/libvga.config
and set it up for your mouse type.
 
Additional notes for GLQuake
----------------------------
 
There are three different ways to execute GLQuake:
 
1. The binary "glquake" requires Mesa 3-D 2.5 or later installed and compiled
with 3DFX support (fxMesa..() function interface). It also requires
svgalib 1.3.0 or later for keyboard/mouse input. This binary is a console
application. Mesa 3-D requires GLIDE to be installed.
 
2. The shell script "glquake.3dfxgl" runs the "glquake" binary after
preloading the lib3dfxgl.so library. This is a port of 3DFX's Win32
OpenGL MCD (Mini Client Driver) to Linux. It is faster than Mesa 3-D
since it was written specifically with supporting GLQuake in mind.
lib3dfxgl.so requires that GLIDE be installed.
 
3. The binary "glquake.glx" is linked against standard OpenGL libraries.
It should run on many different hardward OpenGL implementations under
Linux and X11. This binary is an X11 application and must be run under
X11. It will work with Mesa 3-D as a standard glX based OpenGL
applications. If the Mesa 3-D library is compiled with 3DFX support,
you can have Mesa 3-D support 3DFX hardware under X11 by setting the
enviroment variable "MESA_GLX_FX" to "fullscreen" for fullscreen mode
and "window" for windowed mode, eg. "export MESA_GLX_FX=fullscreen" for sh
or "setenv MESA_GLX_FX fullscreen" for csh.
 
For glquake, you must also have SVGALib or later installed (1.3.0 or later
prefered). GLQuake uses SVGALib for mouse and keyboard handling.
 
If you have gpm and/or selection running, you will have to terminate them
before running GLQuake since they will not give up the mouse when GLQuake
attempts to run. You can kill gpm by typing 'killall gpm' as root.
 
You must run GLQuake as root or setuid root since it needs to access things
such as sound, keyboard, mouse and the 3DFX video. Future versions may not
require root permissions.
 
Additional notes for X11 Quake
------------------------------
 
This is a windowed version that is generic for X11. It runs in a window
and can be resized. You can specify a starting window size with:
-width <width>
-height <height>
-winsize <width> <height>
Default is 320x200. It works in 16bit modes, but it's slower (twice as many
bytes to copy).
 
No other video modes are supported (just runs windowed). Mouse is read, but
not "grabbed" by default. Go to the Options menu and turn on Use Mouse to grab
the mouse and use it in the game (or type "_windowed_mouse 1" at the console).
 
Command Line Options for Linux Quake
------------------------------------
 
-mem <mb>
Specify memory in megabytes to allocate (default is 8MB, which should be fine
for most needs).
 
-nostdout
Don't do any output to stdout
 
-mdev <device> (SVGALib based versions only)
Mouse device, default is /dev/mouse
 
-mrate <speed> (SVGALib based versions only)
Mouse baud rate, default is 1200
 
-cddev <device>
CD device, default is /dev/cdrom
 
-mode <modenum>
Use indicated video mode
 
-nokdb
Don't initialize keyboard
 
-sndbits <8 or 16>
Set sound bit sample size. Default is 16 if supported.
 
-sndspeed <speed>
Set sound speed. Usual values are 8000, 11025, 22051 and 44100.
Default is 11025.
 
-sndmono
Set mono sound
 
-sndstereo
Set stereo sound (default if supported)
 
End Notes
---------
 
Linux Quake is *NOT* an officially supported product. Mail about it
will be deleted. Do not email id about this product. If you are having
technical difficultly, you can email me, but make sure you have the correct
kernel, libc, svgalib and other software versions before you email me.
 
Dave 'Zoid' Kirsch
zoid@idsoftware.com
Official Quake Unix Port Administrator
/contrib/other/sdlquake-1.0.9/docs/README.X11
0,0 → 1,107
 
README for Linux SVGALib Quake
------------------------------
 
Requirements:
 
- X11R5 later, only tested with XFree86, should work with most X Servers
- libc 5.2.18 or later (5.0.9 will not work, /lib/libc.so.5.2.18)
- CD-ROM for CDAudio
- Soundcard capable of mmap'd buffers. USSLite 3.5.4 was used to build squake
with. Works fine on SoundBlaster 16 and Gravis Ultrasound MAX.
- SVGALib supported mouse (usually if it works with X, it'll work with
squake).
- Kernel 2.0.24 or later
- untested with 2.1 kernels, your mileage may vary
 
This is a windowed version that is generic for X11. It runs in a window
and can be resized. You can specify a starting window size with:
-width <width>
-height <height>
-winsize <width> <height>
Default is 320x200. It works in 16bit modes, but it's slower (twice as many
bytes to copy).
 
No other video modes are supported (just runs windowed). Mouse is read, but
not "grabbed" by default. Go to the Options menu and turn on Use Mouse to grab
the mouse and use it in the game. If you want to move the mouse out of
QWCL, you have to turn Use Mouse off.
 
Full sound support is included. The default sound rate is 16-bit stereo,
11KHz. You can change this in the options section below.
 
New Command Line Options for Linux SVGAlib Quake
------------------------------------------------
 
-mem <mb>
Specify memory in megabytes to allocate (default is 8MB, which should be fine
for most needs).
 
-nostdout
Don't do any output to stdout
 
-cddev <device>
CD device, default is /dev/cdrom
 
-sndbits <8 or 16>
Set sound bit sample size. Default is 16 if supported.
 
-sndspeed <speed>
Set sound speed. Usual values are 8000, 11025, 22051 and 44100.
Default is 11025.
 
-sndmono
Set mono sound
 
-sndstereo
Set stereo sound (default if supported)
 
Installation
------------
 
Boot DOS (I know, but you need it to run the Quake install program) and
install Quake from your Quake CD to a DOS parition.
 
Boot Linux and make a directory for Quake. Copy everything from the DOS Quake
directory into it. i.e.:
(cd /dos/quake; tar cf - .) | (cd ~/quake; tar xf -)
 
Quake for X11 does not need to be setuid root. Sound can fail if /dev/dsp is
not mode 666.
 
Quake may segfault if it tries to initialize your sound card and their isn't
one. Same with the CDROM. If it dies, try it with -nosound and/or
-nocdaudio. If you have a sound card it died on and you know it is
supported by USSLite (the driver that comes with the Linux kernel), let me
know and I'll take a look at it.
 
It should work with SCSI CDROMs, but is untested.
 
Full TCP/IP network support is in, including listen and dedicated server
modes.
 
All of the options described in TECHINFO.TXT and MANUAL.TXT from the Quake
distribution will work, 'cept for stuff with vid modes and stuff.
 
End Notes
---------
 
Linux Quake is *NOT* an officially supported product. Mail about it
will be deleted. Do not email id about this product. If you are having
technical difficultly, you can email me, but make sure you have the correct
kernel, libc, svgalib and other software versions before you email me.
 
Dave 'Zoid' Kirsch
zoid@idsoftware.com
Official Quake Unix Port Administrator
 
Acks
----
 
Greg Alexander <galexand@sietch.bloomington.in.us> for initial work in SVGALib
support.
Dave Taylor <ddt@crack.com> for basic Linux support.
id Software for Quake and making me port it. :)
 
Lots of people on #linux, #quake for testing.
 
/contrib/other/sdlquake-1.0.9/docs/readme.glquake
0,0 → 1,162
Linux Glquake v0.98, Quake v1.09 release notes
 
Requirements
------------
 
For 3DFX based hardware, you must download and install Linux GLIDE from
http://glide.xxedgexx.com/3DfxRPMS.html and install as per the
instructions.
 
Running GLQuake
---------------
 
There are three different ways to execute GLQuake:
 
1. The binary "glquake" requires Mesa 3-D 2.5 or later installed and compiled
with 3DFX support (fxMesa..() function interface). It also requires
svgalib 1.3.0 or later for keyboard/mouse input. This binary is a console
application. Mesa 3-D requires GLIDE to be installed.
 
2. The shell script "glquake.3dfxgl" runs the "glquake" binary after
preloading the lib3dfxgl.so library. This is a port of 3DFX's Win32
OpenGL MCD (Mini Client Driver) to Linux. It is faster than Mesa 3-D
since it was written specifically with supporting GLQuake in mind.
lib3dfxgl.so requires that GLIDE be installed.
 
3. The binary "glquake.glx" is linked against standard OpenGL libraries.
It should run on many different hardward OpenGL implementations under
Linux and X11. This binary is an X11 application and must be run under
X11. It will work with Mesa 3-D as a standard glX based OpenGL
applications. If the Mesa 3-D library is compiled with 3DFX support,
you can have Mesa 3-D support 3DFX hardware under X11 by setting the
enviroment variable "MESA_GLX_FX" to "fullscreen" for fullscreen mode
and "window" for windowed mode.
 
You must also have SVGALib 1.3.0 or later installed. GLQuake uses SVGALib
for mouse and keyboard handling.
 
If you have gpm and/or selection running, you will have to terminate them
before running GLQuake since they will not give up the mouse when GLQuake
attempts to run. You can kill gpm by typing 'killall gpm' as root.
 
You must run GLQuake as root or setuid root since it needs to access things
such as sound, keyboard, mouse and the 3DFX video. Future versions may not
require root permissions.
 
resolution options
------------------
glquake -width 512 -height 384
Tries to run glquake at the specified resolution.
Only highend VooDoo cards support such high resolutions (most
cards on the market right now do not). Another popular and supported mode
is 512x384 (-width 512 -height 384) which can offer a faster speed than
the default 640x480.
 
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.
 
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.
 
/contrib/other/sdlquake-1.0.9/docs/readme.squake
0,0 → 1,127
 
README for Linux SVGALib Quake
------------------------------
 
Requirements:
 
- SVGALib 1.20 or later (/lib/libvga.so.1.2.10)
- libc 5.2.18 or later (5.0.9 will not work, /lib/libc.so.5.2.18)
- CD-ROM for CDAudio
- Soundcard capable of mmap'd buffers. USSLite 3.5.4 was used to build squake
with. Works fine on SoundBlaster 16 and Gravis Ultrasound MAX.
- SVGALib supported mouse (usually if it works with X, it'll work with
squake).
- Kernel 2.0.24 or later
- untested with 2.1 kernels, your mileage may vary
 
Here's the release you've been waiting for. Linux squake supports
320x200x256, the various modeX modes (320x400, 360x400, etc) as well as high
res modes if your card is supported by SVGALib. Use the Quake console command
vid_describemodes to list supported modes and the command vid_mode <number> to
change modes.
 
Full sound support is included. The default sound rate is 16-bit stereo,
11KHz. You can change this in the options section below.
 
Mouse works great, but SVGALib may not detect a 3-button mouse properly (it
will only use two buttons). Check your /etc/libvga.config (or
/etc/vga/libvga.config for SlackWare users).
 
**Version 1.1 fixes some crash bugs with the mission packs.
 
New Command Line Options for Linux SVGAlib Quake
------------------------------------------------
 
-mem <mb>
Specify memory in megabytes to allocate (default is 8MB, which should be fine
for most needs).
 
-nostdout
Don't do any output to stdout
 
-mdev <device>
Mouse device, default is /dev/mouse
 
-mrate <speed>
Mouse baud rate, default is 1200
 
-cddev <device>
CD device, default is /dev/cdrom
 
-mode <modenum>
Use indicated video mode
 
-nokdb
Don't initialize keyboard
 
-sndbits <8 or 16>
Set sound bit sample size. Default is 16 if supported.
 
-sndspeed <speed>
Set sound speed. Usual values are 8000, 11025, 22051 and 44100.
Default is 11025.
 
-sndmono
Set mono sound
 
-sndstereo
Set stereo sound (default if supported)
 
Installation
------------
 
Boot DOS (I know, but you need it to run the Quake install program) and
install Quake from your Quake CD to a DOS parition.
 
Boot Linux and make a directory for Quake. Copy everything from the DOS Quake
directory into it. i.e.:
(cd /dos/quake; tar cf - .) | (cd ~/quake; tar xf -)
 
Place squake into your Quake directory. You must make it setuid root (since
Quake access stuff like direct video writes, the raw keyboard mode, CD, etc).
Quake will setuid back to the normal user as soon as it opens these files.
Make Quake suid root as follows:
chown root squake
chmod 4755 squake
 
Run squake. I don't recommend running it as root, since all the saved
config.cfg files will be then owned as root. Use your normal account, unless
you do everything as root, then your mileage will vary.
 
squake may segfault if it tries to initialize your sound card and their isn't
one. Same with the CDROM. If it dies, try it with -nosound and/or
-nocdaudio. If you have a sound card it died on and you know it is
supported by USSLite (the driver that comes with the Linux kernel), let me
know and I'll take a look at it.
 
It should work with SCSI CDROMs, but is untested.
 
Full TCP/IP network support is in, including listen and dedicated server
modes. squake makes a nice dedicated server as you don't need the X11
libraries kicking around.
 
All of the options described in TECHINFO.TXT and MANUAL.TXT from the Quake
distribution will work, 'cept for stuff with vid modes and stuff.
 
End Notes
---------
 
Linux SVGALib Quake is *NOT* an officially supported product. Mail about it
will be deleted. Do not email id about this product. If you are having
technical difficultly, you can email me, but make sure you have the correct
kernel, libc, svgalib and other software versions before you email me.
 
Dave 'Zoid' Kirsch
zoid@threewave.com
Official Quake Unix Port Administrator
 
Acks
----
 
Greg Alexander <galexand@sietch.bloomington.in.us> for initial work in SVGALib
support.
Dave Taylor <ddt@crack.com> for basic Linux support.
id Software for Quake and making me port it. :)
 
Lots of people on #linux, #quake for testing.
 
/contrib/other/sdlquake-1.0.9/dos_v2.c
0,0 → 1,257
/*
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 <sys/segments.h>
#include <go32.h>
#include <unistd.h>
#include <sys/nearptr.h>
#include <dos.h>
#include <string.h>
#include <dpmi.h>
// #include <osfcn.h>
#include <bios.h>
 
#include "dosisms.h"
 
_go32_dpmi_registers hmm;
 
// globals
regs_t regs;
void (*dos_error_func)(char *msg, ...);
 
static unsigned conventional_memory = -1;
 
__dpmi_regs callback_regs;
 
void map_in_conventional_memory(void)
{
if (conventional_memory == -1)
{
if (__djgpp_nearptr_enable())
{
conventional_memory = __djgpp_conventional_base;
}
}
}
 
unsigned int ptr2real(void *ptr)
{
map_in_conventional_memory();
return (int)ptr - conventional_memory;
}
 
void *real2ptr(unsigned int real)
{
map_in_conventional_memory();
return (void *) (real + conventional_memory);
}
 
void *far2ptr(unsigned int farptr)
{
return real2ptr(((farptr & ~0xffff) >>12) + (farptr&0xffff));
}
 
unsigned int ptr2far(void *ptr)
{
return ((ptr2real(ptr)&~0xf) << 12) + (ptr2real(ptr) & 0xf);
}
 
int dos_inportb(int port)
{
return inportb(port);
}
 
int dos_inportw(int port)
{
return inportw(port);
}
 
void dos_outportb(int port, int val)
{
outportb(port, val);
}
 
void dos_outportw(int port, int val)
{
outportw(port, val);
}
 
void dos_irqenable(void)
{
enable();
}
 
void dos_irqdisable(void)
{
disable();
}
 
//
// Returns 0 on success
//
 
int dos_int86(int vec)
{
int rc;
regs.x.ss = regs.x.sp = 0;
rc = _go32_dpmi_simulate_int(vec, (_go32_dpmi_registers *) &regs);
return rc || (regs.x.flags & 1);
}
 
int dos_int386(int vec, regs_t *inregs, regs_t *outregs)
{
int rc;
memcpy(outregs, inregs, sizeof(regs_t));
outregs->x.ss = outregs->x.sp = 0;
rc = _go32_dpmi_simulate_int(vec, (_go32_dpmi_registers *) outregs);
return rc || (outregs->x.flags & 1);
}
 
//
// Because of a quirk in dj's alloc-dos-memory wrapper, you need to keep
// the seginfo structure around for when you free the mem.
//
 
static _go32_dpmi_seginfo seginfo[10];
 
void *dos_getmemory(int size)
{
 
int rc;
_go32_dpmi_seginfo info;
static int firsttime=1;
int i;
 
if (firsttime)
{
memset(seginfo, 0, sizeof(seginfo));
firsttime = 0;
}
 
info.size = (size+15) / 16;
rc = _go32_dpmi_allocate_dos_memory(&info);
if (rc)
return 0;
 
for (i=0;i<10;i++)
if (!seginfo[i].rm_segment) break;
seginfo[i] = info;
return real2ptr((int) info.rm_segment << 4);
 
}
 
void dos_freememory(void *ptr)
{
 
int i;
int segment;
 
segment = ptr2real(ptr) >> 4;
for (i=0 ; i<10 ; i++)
if (seginfo[i].rm_segment == segment)
{
_go32_dpmi_free_dos_memory(&seginfo[i]);
seginfo[i].rm_segment = 0;
break;
}
 
}
 
static struct handlerhistory_s
{
int intr;
_go32_dpmi_seginfo pm_oldvec;
} handlerhistory[4];
 
static int handlercount=0;
 
void dos_registerintr(int intr, void (*handler)(void))
{
_go32_dpmi_seginfo info;
struct handlerhistory_s *oldstuff;
 
oldstuff = &handlerhistory[handlercount];
 
// remember old handler
_go32_dpmi_get_protected_mode_interrupt_vector(intr, &oldstuff->pm_oldvec);
oldstuff->intr = intr;
 
info.pm_offset = (int) handler;
_go32_dpmi_allocate_iret_wrapper(&info);
 
// set new protected mode handler
_go32_dpmi_set_protected_mode_interrupt_vector(intr, &info);
 
handlercount++;
 
}
 
void dos_restoreintr(int intr)
{
 
int i;
struct handlerhistory_s *oldstuff;
 
// find and reinstall previous interrupt
for (i=0 ; i<handlercount ; i++)
{
oldstuff = &handlerhistory[i];
if (oldstuff->intr == intr)
{
_go32_dpmi_set_protected_mode_interrupt_vector(intr,
&oldstuff->pm_oldvec);
oldstuff->intr = -1;
break;
}
}
 
}
 
void dos_usleep(int usecs)
{
usleep(usecs);
}
 
int dos_getheapsize(void)
{
return _go32_dpmi_remaining_physical_memory();
}
 
int dos_lockmem(void *addr, int size)
{
__dpmi_meminfo info;
info.address = (long) addr + __djgpp_base_address;
info.size = size;
if (__dpmi_lock_linear_region(&info))
return __dpmi_error;
else
return 0;
}
 
int dos_unlockmem(void *addr, int size)
{
__dpmi_meminfo info;
info.address = (long) addr + __djgpp_base_address;
info.size = size;
if (__dpmi_unlock_linear_region(&info))
return __dpmi_error;
else
return 0;
}
 
/contrib/other/sdlquake-1.0.9/dosasm.S
0,0 → 1,77
#include "asm_i386.h"
 
.data
fpenv: .long 0, 0, 0, 0, 0, 0, 0, 0
 
.text
.globl C(StartMSRInterval)
C(StartMSRInterval):
movl $0x11,%ecx // read the CESR
.byte 0x0F
.byte 0x32 // RDMSR
 
andl $0xFE3FFE3F,%eax // stop both counters
.byte 0x0F
.byte 0x30 // WRMSR
 
movl 4(%esp),%eax // point counter 0 to desired event, with counters
andl $0x3F,%eax // still stopped
movl $0x11,%ecx
.byte 0x0F
.byte 0x30 // WRMSR
 
movl $0x12,%ecx // set counter 0 to the value 0
subl %eax,%eax
subl %edx,%edx
.byte 0x0F
.byte 0x30 // WRMSR
movl 4(%esp),%eax // restart counter 0 with selected event
andl $0x3F,%eax
subl %edx,%edx
orl $0xC0,%eax
movl $0x11,%ecx // control and event select
.byte 0x0F
.byte 0x30 // WRMSR
 
ret
 
.globl C(EndMSRInterval)
C(EndMSRInterval):
movl $0x12,%ecx // counter 0
.byte 0x0F
.byte 0x32 // RDMSR
 
ret // lower 32 bits of count in %eax
 
#if 0
.data
Lxxx: .long 0
 
.text
 
.globl C(setstackcheck)
C(setstackcheck):
 
movl %esp,%eax
subl $0x38000,%eax
movl $0x5A5A5A5A,(%eax)
movl %eax,Lxxx
 
ret
 
 
.globl C(dostackcheck)
C(dostackcheck):
 
movl Lxxx,%edx
movl $0,%eax
 
cmpl $0x5A5A5A5A,(%edx)
jz qqq
incl %eax
qqq:
 
ret
#endif
 
/contrib/other/sdlquake-1.0.9/dosisms.h
0,0 → 1,100
/*
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.
 
*/
 
//
// dosisms.h: I'd call it dos.h, but the name's taken
//
 
#ifndef _DOSISMS_H_
#define _DOSISMS_H_
 
int dos_lockmem(void *addr, int size);
int dos_unlockmem(void *addr, int size);
 
typedef union {
struct {
unsigned long edi;
unsigned long esi;
unsigned long ebp;
unsigned long res;
unsigned long ebx;
unsigned long edx;
unsigned long ecx;
unsigned long eax;
} d;
struct {
unsigned short di, di_hi;
unsigned short si, si_hi;
unsigned short bp, bp_hi;
unsigned short res, res_hi;
unsigned short bx, bx_hi;
unsigned short dx, dx_hi;
unsigned short cx, cx_hi;
unsigned short ax, ax_hi;
unsigned short flags;
unsigned short es;
unsigned short ds;
unsigned short fs;
unsigned short gs;
unsigned short ip;
unsigned short cs;
unsigned short sp;
unsigned short ss;
} x;
struct {
unsigned char edi[4];
unsigned char esi[4];
unsigned char ebp[4];
unsigned char res[4];
unsigned char bl, bh, ebx_b2, ebx_b3;
unsigned char dl, dh, edx_b2, edx_b3;
unsigned char cl, ch, ecx_b2, ecx_b3;
unsigned char al, ah, eax_b2, eax_b3;
} h;
} regs_t;
 
unsigned int ptr2real(void *ptr);
void *real2ptr(unsigned int real);
void *far2ptr(unsigned int farptr);
unsigned int ptr2far(void *ptr);
 
int dos_inportb(int port);
int dos_inportw(int port);
void dos_outportb(int port, int val);
void dos_outportw(int port, int val);
 
void dos_irqenable(void);
void dos_irqdisable(void);
void dos_registerintr(int intr, void (*handler)(void));
void dos_restoreintr(int intr);
 
int dos_int86(int vec);
 
void *dos_getmemory(int size);
void dos_freememory(void *ptr);
 
void dos_usleep(int usecs);
 
int dos_getheapsize(void);
 
extern regs_t regs;
 
#endif // _DOSISMS_H_
 
/contrib/other/sdlquake-1.0.9/draw.c
0,0 → 1,902
/*
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.c -- this is the only file outside the refresh that touches the
// vid buffer
 
#include "quakedef.h"
 
typedef struct {
vrect_t rect;
int width;
int height;
byte *ptexbytes;
int rowbytes;
} rectdesc_t;
 
static rectdesc_t r_rectdesc;
 
byte *draw_chars; // 8*8 graphic characters
qpic_t *draw_disc;
qpic_t *draw_backtile;
 
//=============================================================================
/* Support Routines */
 
typedef struct cachepic_s
{
char name[MAX_QPATH];
cache_user_t cache;
} cachepic_t;
 
#define MAX_CACHED_PICS 128
cachepic_t menu_cachepics[MAX_CACHED_PICS];
int menu_numcachepics;
 
 
qpic_t *Draw_PicFromWad (char *name)
{
return W_GetLumpName (name);
}
 
/*
================
Draw_CachePic
================
*/
qpic_t *Draw_CachePic (char *path)
{
cachepic_t *pic;
int i;
qpic_t *dat;
for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++)
if (!strcmp (path, pic->name))
break;
 
if (i == menu_numcachepics)
{
if (menu_numcachepics == MAX_CACHED_PICS)
Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
menu_numcachepics++;
strcpy (pic->name, path);
}
 
dat = Cache_Check (&pic->cache);
 
if (dat)
return dat;
 
//
// load the pic from disk
//
COM_LoadCacheFile (path, &pic->cache);
dat = (qpic_t *)pic->cache.data;
if (!dat)
{
Sys_Error ("Draw_CachePic: failed to load %s", path);
}
 
SwapPic (dat);
 
return dat;
}
 
 
 
/*
===============
Draw_Init
===============
*/
void Draw_Init (void)
{
int i;
 
draw_chars = W_GetLumpName ("conchars");
draw_disc = W_GetLumpName ("disc");
draw_backtile = W_GetLumpName ("backtile");
 
r_rectdesc.width = draw_backtile->width;
r_rectdesc.height = draw_backtile->height;
r_rectdesc.ptexbytes = draw_backtile->data;
r_rectdesc.rowbytes = draw_backtile->width;
}
 
 
 
/*
================
Draw_Character
 
Draws one 8*8 graphics character with 0 being transparent.
It can be clipped to the top of the screen to allow the console to be
smoothly scrolled off.
================
*/
void Draw_Character (int x, int y, int num)
{
byte *dest;
byte *source;
unsigned short *pusdest;
int drawline;
int row, col;
 
num &= 255;
if (y <= -8)
return; // totally off screen
 
#ifdef PARANOID
if (y > vid.height - 8 || x < 0 || x > vid.width - 8)
Sys_Error ("Con_DrawCharacter: (%i, %i)", x, y);
if (num < 0 || num > 255)
Sys_Error ("Con_DrawCharacter: char %i", num);
#endif
 
row = num>>4;
col = num&15;
source = draw_chars + (row<<10) + (col<<3);
 
if (y < 0)
{ // clipped
drawline = 8 + y;
source -= 128*y;
y = 0;
}
else
drawline = 8;
 
 
if (r_pixbytes == 1)
{
dest = vid.conbuffer + y*vid.conrowbytes + x;
while (drawline--)
{
if (source[0])
dest[0] = source[0];
if (source[1])
dest[1] = source[1];
if (source[2])
dest[2] = source[2];
if (source[3])
dest[3] = source[3];
if (source[4])
dest[4] = source[4];
if (source[5])
dest[5] = source[5];
if (source[6])
dest[6] = source[6];
if (source[7])
dest[7] = source[7];
source += 128;
dest += vid.conrowbytes;
}
}
else
{
// FIXME: pre-expand to native format?
pusdest = (unsigned short *)
((byte *)vid.conbuffer + y*vid.conrowbytes + (x<<1));
 
while (drawline--)
{
if (source[0])
pusdest[0] = d_8to16table[source[0]];
if (source[1])
pusdest[1] = d_8to16table[source[1]];
if (source[2])
pusdest[2] = d_8to16table[source[2]];
if (source[3])
pusdest[3] = d_8to16table[source[3]];
if (source[4])
pusdest[4] = d_8to16table[source[4]];
if (source[5])
pusdest[5] = d_8to16table[source[5]];
if (source[6])
pusdest[6] = d_8to16table[source[6]];
if (source[7])
pusdest[7] = d_8to16table[source[7]];
 
source += 128;
pusdest += (vid.conrowbytes >> 1);
}
}
}
 
/*
================
Draw_String
================
*/
void Draw_String (int x, int y, char *str)
{
while (*str)
{
Draw_Character (x, y, *str);
str++;
x += 8;
}
}
 
/*
================
Draw_DebugChar
 
Draws a single character directly to the upper right corner of the screen.
This is for debugging lockups by drawing different chars in different parts
of the code.
================
*/
void Draw_DebugChar (char num)
{
byte *dest;
byte *source;
int drawline;
extern byte *draw_chars;
int row, col;
 
if (!vid.direct)
return; // don't have direct FB access, so no debugchars...
 
drawline = 8;
 
row = num>>4;
col = num&15;
source = draw_chars + (row<<10) + (col<<3);
 
dest = vid.direct + 312;
 
while (drawline--)
{
dest[0] = source[0];
dest[1] = source[1];
dest[2] = source[2];
dest[3] = source[3];
dest[4] = source[4];
dest[5] = source[5];
dest[6] = source[6];
dest[7] = source[7];
source += 128;
dest += 320;
}
}
 
/*
=============
Draw_Pic
=============
*/
void Draw_Pic (int x, int y, qpic_t *pic)
{
byte *dest, *source;
unsigned short *pusdest;
int v, u;
 
if ((x < 0) ||
(x + pic->width > vid.width) ||
(y < 0) ||
(y + pic->height > vid.height))
{
Sys_Error ("Draw_Pic: bad coordinates");
}
 
source = pic->data;
 
if (r_pixbytes == 1)
{
dest = vid.buffer + y * vid.rowbytes + x;
 
for (v=0 ; v<pic->height ; v++)
{
Q_memcpy (dest, source, pic->width);
dest += vid.rowbytes;
source += pic->width;
}
}
else
{
// FIXME: pretranslate at load time?
pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
 
for (v=0 ; v<pic->height ; v++)
{
for (u=0 ; u<pic->width ; u++)
{
pusdest[u] = d_8to16table[source[u]];
}
 
pusdest += vid.rowbytes >> 1;
source += pic->width;
}
}
}
 
 
/*
=============
Draw_TransPic
=============
*/
void Draw_TransPic (int x, int y, qpic_t *pic)
{
byte *dest, *source, tbyte;
unsigned short *pusdest;
int v, u;
 
if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
(unsigned)(y + pic->height) > vid.height)
{
Sys_Error ("Draw_TransPic: bad coordinates");
}
source = pic->data;
 
if (r_pixbytes == 1)
{
dest = vid.buffer + y * vid.rowbytes + x;
 
if (pic->width & 7)
{ // general
for (v=0 ; v<pic->height ; v++)
{
for (u=0 ; u<pic->width ; u++)
if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
dest[u] = tbyte;
dest += vid.rowbytes;
source += pic->width;
}
}
else
{ // unwound
for (v=0 ; v<pic->height ; v++)
{
for (u=0 ; u<pic->width ; u+=8)
{
if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
dest[u] = tbyte;
if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR)
dest[u+1] = tbyte;
if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR)
dest[u+2] = tbyte;
if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR)
dest[u+3] = tbyte;
if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR)
dest[u+4] = tbyte;
if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR)
dest[u+5] = tbyte;
if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR)
dest[u+6] = tbyte;
if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR)
dest[u+7] = tbyte;
}
dest += vid.rowbytes;
source += pic->width;
}
}
}
else
{
// FIXME: pretranslate at load time?
pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
 
for (v=0 ; v<pic->height ; v++)
{
for (u=0 ; u<pic->width ; u++)
{
tbyte = source[u];
 
if (tbyte != TRANSPARENT_COLOR)
{
pusdest[u] = d_8to16table[tbyte];
}
}
 
pusdest += vid.rowbytes >> 1;
source += pic->width;
}
}
}
 
 
/*
=============
Draw_TransPicTranslate
=============
*/
void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
{
byte *dest, *source, tbyte;
unsigned short *pusdest;
int v, u;
 
if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
(unsigned)(y + pic->height) > vid.height)
{
Sys_Error ("Draw_TransPic: bad coordinates");
}
source = pic->data;
 
if (r_pixbytes == 1)
{
dest = vid.buffer + y * vid.rowbytes + x;
 
if (pic->width & 7)
{ // general
for (v=0 ; v<pic->height ; v++)
{
for (u=0 ; u<pic->width ; u++)
if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
dest[u] = translation[tbyte];
 
dest += vid.rowbytes;
source += pic->width;
}
}
else
{ // unwound
for (v=0 ; v<pic->height ; v++)
{
for (u=0 ; u<pic->width ; u+=8)
{
if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
dest[u] = translation[tbyte];
if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR)
dest[u+1] = translation[tbyte];
if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR)
dest[u+2] = translation[tbyte];
if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR)
dest[u+3] = translation[tbyte];
if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR)
dest[u+4] = translation[tbyte];
if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR)
dest[u+5] = translation[tbyte];
if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR)
dest[u+6] = translation[tbyte];
if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR)
dest[u+7] = translation[tbyte];
}
dest += vid.rowbytes;
source += pic->width;
}
}
}
else
{
// FIXME: pretranslate at load time?
pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
 
for (v=0 ; v<pic->height ; v++)
{
for (u=0 ; u<pic->width ; u++)
{
tbyte = source[u];
 
if (tbyte != TRANSPARENT_COLOR)
{
pusdest[u] = d_8to16table[tbyte];
}
}
 
pusdest += vid.rowbytes >> 1;
source += pic->width;
}
}
}
 
 
void Draw_CharToConback (int num, byte *dest)
{
int row, col;
byte *source;
int drawline;
int x;
 
row = num>>4;
col = num&15;
source = draw_chars + (row<<10) + (col<<3);
 
drawline = 8;
 
while (drawline--)
{
for (x=0 ; x<8 ; x++)
if (source[x])
dest[x] = 0x60 + source[x];
source += 128;
dest += 320;
}
 
}
 
/*
================
Draw_ConsoleBackground
 
================
*/
void Draw_ConsoleBackground (int lines)
{
int x, y, v;
byte *src, *dest;
unsigned short *pusdest;
int f, fstep;
qpic_t *conback;
char ver[100];
 
conback = Draw_CachePic ("gfx/conback.lmp");
 
// hack the version number directly into the pic
#ifdef _WIN32
sprintf (ver, "(WinQuake) %4.2f", (float)VERSION);
dest = conback->data + 320*186 + 320 - 11 - 8*strlen(ver);
#elif defined(X11)
sprintf (ver, "(X11 Quake %2.2f) %4.2f", (float)X11_VERSION, (float)VERSION);
dest = conback->data + 320*186 + 320 - 11 - 8*strlen(ver);
#elif defined(__linux__)
sprintf (ver, "(Linux Quake %2.2f) %4.2f", (float)LINUX_VERSION, (float)VERSION);
dest = conback->data + 320*186 + 320 - 11 - 8*strlen(ver);
#else
dest = conback->data + 320 - 43 + 320*186;
sprintf (ver, "%4.2f", VERSION);
#endif
 
for (x=0 ; x<strlen(ver) ; x++)
Draw_CharToConback (ver[x], dest+(x<<3));
// draw the pic
if (r_pixbytes == 1)
{
dest = vid.conbuffer;
 
for (y=0 ; y<lines ; y++, dest += vid.conrowbytes)
{
v = (vid.conheight - lines + y)*200/vid.conheight;
src = conback->data + v*320;
if (vid.conwidth == 320)
memcpy (dest, src, vid.conwidth);
else
{
f = 0;
fstep = 320*0x10000/vid.conwidth;
for (x=0 ; x<vid.conwidth ; x+=4)
{
dest[x] = src[f>>16];
f += fstep;
dest[x+1] = src[f>>16];
f += fstep;
dest[x+2] = src[f>>16];
f += fstep;
dest[x+3] = src[f>>16];
f += fstep;
}
}
}
}
else
{
pusdest = (unsigned short *)vid.conbuffer;
 
for (y=0 ; y<lines ; y++, pusdest += (vid.conrowbytes >> 1))
{
// FIXME: pre-expand to native format?
// FIXME: does the endian switching go away in production?
v = (vid.conheight - lines + y)*200/vid.conheight;
src = conback->data + v*320;
f = 0;
fstep = 320*0x10000/vid.conwidth;
for (x=0 ; x<vid.conwidth ; x+=4)
{
pusdest[x] = d_8to16table[src[f>>16]];
f += fstep;
pusdest[x+1] = d_8to16table[src[f>>16]];
f += fstep;
pusdest[x+2] = d_8to16table[src[f>>16]];
f += fstep;
pusdest[x+3] = d_8to16table[src[f>>16]];
f += fstep;
}
}
}
}
 
 
/*
==============
R_DrawRect8
==============
*/
void R_DrawRect8 (vrect_t *prect, int rowbytes, byte *psrc,
int transparent)
{
byte t;
int i, j, srcdelta, destdelta;
byte *pdest;
 
pdest = vid.buffer + (prect->y * vid.rowbytes) + prect->x;
 
srcdelta = rowbytes - prect->width;
destdelta = vid.rowbytes - prect->width;
 
if (transparent)
{
for (i=0 ; i<prect->height ; i++)
{
for (j=0 ; j<prect->width ; j++)
{
t = *psrc;
if (t != TRANSPARENT_COLOR)
{
*pdest = t;
}
 
psrc++;
pdest++;
}
 
psrc += srcdelta;
pdest += destdelta;
}
}
else
{
for (i=0 ; i<prect->height ; i++)
{
memcpy (pdest, psrc, prect->width);
psrc += rowbytes;
pdest += vid.rowbytes;
}
}
}
 
 
/*
==============
R_DrawRect16
==============
*/
void R_DrawRect16 (vrect_t *prect, int rowbytes, byte *psrc,
int transparent)
{
byte t;
int i, j, srcdelta, destdelta;
unsigned short *pdest;
 
// FIXME: would it be better to pre-expand native-format versions?
 
pdest = (unsigned short *)vid.buffer +
(prect->y * (vid.rowbytes >> 1)) + prect->x;
 
srcdelta = rowbytes - prect->width;
destdelta = (vid.rowbytes >> 1) - prect->width;
 
if (transparent)
{
for (i=0 ; i<prect->height ; i++)
{
for (j=0 ; j<prect->width ; j++)
{
t = *psrc;
if (t != TRANSPARENT_COLOR)
{
*pdest = d_8to16table[t];
}
 
psrc++;
pdest++;
}
 
psrc += srcdelta;
pdest += destdelta;
}
}
else
{
for (i=0 ; i<prect->height ; i++)
{
for (j=0 ; j<prect->width ; j++)
{
*pdest = d_8to16table[*psrc];
psrc++;
pdest++;
}
 
psrc += srcdelta;
pdest += destdelta;
}
}
}
 
 
/*
=============
Draw_TileClear
 
This repeats a 64*64 tile graphic to fill the screen around a sized down
refresh window.
=============
*/
void Draw_TileClear (int x, int y, int w, int h)
{
int width, height, tileoffsetx, tileoffsety;
byte *psrc;
vrect_t vr;
 
r_rectdesc.rect.x = x;
r_rectdesc.rect.y = y;
r_rectdesc.rect.width = w;
r_rectdesc.rect.height = h;
 
vr.y = r_rectdesc.rect.y;
height = r_rectdesc.rect.height;
 
tileoffsety = vr.y % r_rectdesc.height;
 
while (height > 0)
{
vr.x = r_rectdesc.rect.x;
width = r_rectdesc.rect.width;
 
if (tileoffsety != 0)
vr.height = r_rectdesc.height - tileoffsety;
else
vr.height = r_rectdesc.height;
 
if (vr.height > height)
vr.height = height;
 
tileoffsetx = vr.x % r_rectdesc.width;
 
while (width > 0)
{
if (tileoffsetx != 0)
vr.width = r_rectdesc.width - tileoffsetx;
else
vr.width = r_rectdesc.width;
 
if (vr.width > width)
vr.width = width;
 
psrc = r_rectdesc.ptexbytes +
(tileoffsety * r_rectdesc.rowbytes) + tileoffsetx;
 
if (r_pixbytes == 1)
{
R_DrawRect8 (&vr, r_rectdesc.rowbytes, psrc, 0);
}
else
{
R_DrawRect16 (&vr, r_rectdesc.rowbytes, psrc, 0);
}
 
vr.x += vr.width;
width -= vr.width;
tileoffsetx = 0; // only the left tile can be left-clipped
}
 
vr.y += vr.height;
height -= vr.height;
tileoffsety = 0; // only the top tile can be top-clipped
}
}
 
 
/*
=============
Draw_Fill
 
Fills a box of pixels with a single color
=============
*/
void Draw_Fill (int x, int y, int w, int h, int c)
{
byte *dest;
unsigned short *pusdest;
unsigned uc;
int u, v;
 
if (r_pixbytes == 1)
{
dest = vid.buffer + y*vid.rowbytes + x;
for (v=0 ; v<h ; v++, dest += vid.rowbytes)
for (u=0 ; u<w ; u++)
dest[u] = c;
}
else
{
uc = d_8to16table[c];
 
pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
for (v=0 ; v<h ; v++, pusdest += (vid.rowbytes >> 1))
for (u=0 ; u<w ; u++)
pusdest[u] = uc;
}
}
//=============================================================================
 
/*
================
Draw_FadeScreen
 
================
*/
void Draw_FadeScreen (void)
{
int x,y;
byte *pbuf;
 
VID_UnlockBuffer ();
S_ExtraUpdate ();
VID_LockBuffer ();
 
for (y=0 ; y<vid.height ; y++)
{
int t;
 
pbuf = (byte *)(vid.buffer + vid.rowbytes*y);
t = (y & 1) << 1;
 
for (x=0 ; x<vid.width ; x++)
{
if ((x & 3) != t)
pbuf[x] = 0;
}
}
 
VID_UnlockBuffer ();
S_ExtraUpdate ();
VID_LockBuffer ();
}
 
//=============================================================================
 
/*
================
Draw_BeginDisc
 
Draws the little blue disc in the corner of the screen.
Call before beginning any disc IO.
================
*/
void Draw_BeginDisc (void)
{
 
D_BeginDirectRect (vid.width - 24, 0, draw_disc->data, 24, 24);
}
 
 
/*
================
Draw_EndDisc
 
Erases the disc icon.
Call after completing any disc IO
================
*/
void Draw_EndDisc (void)
{
 
D_EndDirectRect (vid.width - 24, 0, 24, 24);
}
 
/contrib/other/sdlquake-1.0.9/draw.h
0,0 → 1,40
/*
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
 
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);
/contrib/other/sdlquake-1.0.9/gas2masm/gas2masm.c
0,0 → 1,1056
/*
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.
 
*/
//
// gas to MASM source code converter
//
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define MAX_TOKENS 100
#define MAX_TOKEN_LENGTH 1024
#define LF 0x0A
 
typedef enum {NOT_WHITESPACE, WHITESPACE, TOKEN_AVAILABLE, LINE_DONE, FILE_DONE, PARSED_OKAY} tokenstat;
typedef enum {NOSEG, DATASEG, TEXTSEG} segtype;
 
int tokennum;
int inline, outline;
 
char *token;
char tokens[MAX_TOKENS][MAX_TOKEN_LENGTH+1];
 
segtype currentseg = NOSEG;
 
typedef struct {
char *text;
char *emit;
int numtokens;
void (*parsefunc) (void);
} parsefield;
 
 
void errorexit (void);
 
 
//==============================================
 
typedef struct {
char *text;
char *emit;
int len;
} regdesc;
 
regdesc reglist[] = {
{"%eax", "eax", 4},
{"%ebx", "ebx", 4},
{"%ecx", "ecx", 4},
{"%edx", "edx", 4},
{"%esi", "esi", 4},
{"%edi", "edi", 4},
{"%ebp", "ebp", 4},
{"%esp", "esp", 4},
{"%ax", "ax", 3},
{"%bx", "bx", 3},
{"%cx", "cx", 3},
{"%dx", "dx", 3},
{"%si", "si", 3},
{"%di", "di", 3},
{"%bp", "bp", 3},
{"%sp", "sp", 3},
{"%al", "al", 3},
{"%bl", "bl", 3},
{"%cl", "cl", 3},
{"%dl", "dl", 3},
{"%ah", "ah", 3},
{"%bh", "bh", 3},
{"%ch", "ch", 3},
{"%dh", "dh", 3},
{"%st(0)", "st(0)", 6},
{"%st(1)", "st(1)", 6},
{"%st(2)", "st(2)", 6},
{"%st(3)", "st(3)", 6},
{"%st(4)", "st(4)", 6},
{"%st(5)", "st(5)", 6},
{"%st(6)", "st(6)", 6},
{"%st(7)", "st(7)", 6},
};
 
int numregs = sizeof (reglist) / sizeof (reglist[0]);
 
//==============================================
 
 
void emitanoperand (int tnum, char *type, int notdata)
{
int i, index, something_outside_parens, regfound;
int parencount;
char *pt;
char temp[MAX_TOKEN_LENGTH+1];
 
pt = tokens[tnum];
 
if (pt[0] == '%')
{
// register
for (i=0 ; i<numregs ; i++)
{
if (!strcmpi (pt, reglist[i].text))
{
printf ("%s", reglist[i].emit);
return;
}
}
 
fprintf (stderr, "Error: bad register %s\n", pt);
errorexit ();
}
else if (pt[0] == '$')
{
// constant
if (pt[1] == '(')
{
if ((pt[2] > '9') || (pt[2] < '0'))
{
i = 2;
printf ("offset ");
 
parencount = 1;
 
while ((pt[i] != ')') || (parencount > 1))
{
if (!pt[i])
{
fprintf (stderr, "mismatched parens");
errorexit ();
}
 
if (pt[i] == ')')
parencount--;
else if (pt[i] == '(')
parencount++;
 
printf ("%c", pt[i]);
i++;
}
}
else
{
pt++;
 
parencount = 1;
 
for (i=1 ; (pt[i] != ')') || (parencount > 1) ; i++)
{
if (!pt[i])
{
fprintf (stderr, "mismatched parens");
errorexit ();
}
 
if (pt[i] == ')')
parencount--;
else if (pt[i] == '(')
parencount++;
}
 
pt[i] = 0;
 
if ((pt[1] == '0') && ((pt[2] == 'x') || (pt[2] == 'X')))
{
printf ("0%sh", &pt[3]);
}
else
{
printf ("%s", &pt[1]);
}
}
}
else if ((pt[1] == '0') && ((pt[2] == 'x') || (pt[2] == 'X')))
{
printf ("0%sh", &pt[3]);
}
else if ((pt[1] >= '0') && (pt[1] <= '9'))
{
printf ("%s", &pt[1]);
}
else
{
printf ("offset %s", &pt[1]);
}
}
else if (!notdata && ((pt[0] >= '0') && (pt[0] <= '9')))
{
pt--;
 
if ((pt[1] == '0') && ((pt[2] == 'x') || (pt[2] == 'X')))
{
printf ("0%sh", &pt[3]);
}
else
{
printf ("%s", &pt[1]);
}
}
else
{
// must be a memory location
strcpy (temp, type);
index = strlen (temp);
 
if (notdata)
temp[index++] = '[';
 
something_outside_parens = 0;
 
while (*pt)
{
if (index > (MAX_TOKEN_LENGTH - 10))
{
fprintf (stderr, "Error: operand too long %s\n",
tokens[tnum]);
errorexit ();
}
 
if (*pt != ')')
{
if (*pt == '(')
{
if (something_outside_parens)
temp[index++] = '+';
}
else if (*pt == '%')
{
regfound = 0;
 
for (i=0 ; i<numregs ; i++)
{
if (!strnicmp (pt, reglist[i].text,
reglist[i].len))
{
strcpy (&temp[index], reglist[i].emit);
index += strlen (reglist[i].emit);
pt += strlen (reglist[i].text) - 1;
regfound = 1;
break;
}
}
 
if (!regfound)
{
fprintf (stderr, "Error: bad register %s\n", pt);
errorexit ();
}
}
else if (*pt == ',')
{
pt++;
 
if ((*pt >= '1') && (*pt <= '8'))
{
temp[index++] = '*';
temp[index++] = *pt;
}
else if (*pt != ')')
{
if (temp[index-1] != '+')
temp[index++] = '+';
}
}
else
{
something_outside_parens = 1;
 
// handle hexadecimal constants in addresses
if ((*pt == '0') &&
((*(pt+1) == 'x') || (*(pt+1) == 'X')))
{
pt += 2;
 
do
{
temp[index++] = *pt++;
} while (((*pt >= '0') && (*pt <= '9')) ||
((*pt >= 'a') && (*pt <= 'f')) ||
((*pt >= 'A') && (*pt <= 'F')));
 
pt--;
temp[index++] = 'h';
}
else
{
temp[index++] = *pt;
}
}
}
 
pt++;
}
 
if (notdata)
temp[index++] = ']';
 
temp[index] = 0;
printf ("%s", temp);
}
}
 
 
void datasegstart (void)
{
if (currentseg == DATASEG)
return;
 
if (currentseg == TEXTSEG)
printf ("_TEXT ENDS\n");
 
printf ("_DATA SEGMENT");
 
currentseg = DATASEG;
}
 
 
void textsegstart (void)
{
if (currentseg == TEXTSEG)
return;
 
if (currentseg == DATASEG)
printf ("_DATA ENDS\n");
 
printf ("_TEXT SEGMENT");
 
currentseg = TEXTSEG;
}
 
 
void emitdata (void)
{
int i;
 
for (i=1 ; i<(tokennum-1) ; i++)
printf (" %s,", tokens[i]);
 
printf (" %s", tokens[tokennum-1]);
}
 
 
void emitonedata (void)
{
 
printf (" %s", tokens[1]);
}
 
 
void emitonecalldata (void)
{
int i, isaddr, len;
 
if (tokens[1][0] == '*')
{
printf (" dword ptr[%s]", &tokens[1][1]);
}
else
{
isaddr = 0;
len = strlen(tokens[1]);
 
for (i=0 ; i<len ; i++)
{
if (tokens[1][i] == '(')
{
isaddr = 1;
break;
}
}
 
if (!isaddr)
{
printf (" near ptr %s", tokens[1]);
}
else
{
emitanoperand (1, " dword ptr", 1);
}
}
}
 
 
void emitonejumpdata (void)
{
int i, isaddr, len;
 
if (tokens[1][0] == '*')
{
printf (" dword ptr[%s]", &tokens[1][1]);
}
else
{
isaddr = 0;
len = strlen(tokens[1]);
 
for (i=0 ; i<len ; i++)
{
if (tokens[1][i] == '(')
{
isaddr = 1;
break;
}
}
 
if (!isaddr)
{
printf (" %s", tokens[1]);
}
else
{
emitanoperand (1, " dword ptr", 1);
}
}
}
 
 
void emitexterndef (void)
{
 
printf (" %s:dword", tokens[1]);
}
 
 
void nooperands (void)
{
 
}
 
 
void emitoneoperandl (void)
{
 
printf (" ");
emitanoperand (1, "ds:dword ptr", 1);
}
 
 
void emitoneoperandb (void)
{
 
printf (" ");
emitanoperand (1, "ds:byte ptr", 1);
}
 
 
void emitoneoperandw (void)
{
 
printf (" ");
emitanoperand (1, "ds:word ptr", 1);
}
 
 
void emittwooperandsl (void)
{
 
printf (" ");
emitanoperand (2, "ds:dword ptr", 1);
printf (",");
emitanoperand (1, "ds:dword ptr", 1);
}
 
 
void emittwooperandsb (void)
{
 
printf (" ");
emitanoperand (2, "ds:byte ptr", 1);
printf (",");
emitanoperand (1, "ds:byte ptr", 1);
}
 
 
void emittwooperandsw (void)
{
 
printf (" ");
emitanoperand (2, "ds:word ptr", 1);
printf (",");
emitanoperand (1, "ds:word ptr", 1);
}
 
 
void emit_0_or_1_operandsl (void)
{
 
if (tokennum == 2)
{
printf (" ");
emitanoperand (1, "ds:dword ptr", 1);
}
}
 
 
void emit_1_or_2_operandsl (void)
{
int j;
 
if (tokennum == 2)
{
printf (" ");
emitanoperand (1, "ds:dword ptr", 1);
}
else if (tokennum == 3)
{
printf (" ");
emitanoperand (2, "ds:dword ptr", 1);
printf (",");
emitanoperand (1, "ds:dword ptr", 1);
}
else
{
 
fprintf (stderr, "Error: too many operands\n");
 
for (j=0 ; j<tokennum ; j++)
fprintf (stderr, "%s\n", tokens[j]);
 
fprintf (stderr, "\n");
errorexit ();
}
}
 
 
void emit_1_or_2_operandsl_vartext (char *str0, char *str1)
{
int j;
 
if (tokennum == 2)
{
printf (" %s ", str0);
emitanoperand (1, "ds:dword ptr", 1);
}
else if (tokennum == 3)
{
if (!strcmpi (tokens[2], "%st(0)"))
printf (" %s ", str0);
else
printf (" %s ", str1);
 
emitanoperand (2, "ds:dword ptr", 1);
printf (",");
emitanoperand (1, "ds:dword ptr", 1);
}
else
{
 
fprintf (stderr, "Error: too many operands\n");
 
for (j=0 ; j<tokennum ; j++)
fprintf (stderr, "%s\n", tokens[j]);
 
fprintf (stderr, "\n");
errorexit ();
}
}
 
 
void special_fdivl (void)
{
 
emit_1_or_2_operandsl_vartext ("fdiv", "fdivr");
}
 
 
void special_fdivpl (void)
{
 
emit_1_or_2_operandsl_vartext ("fdivp", "fdivrp");
}
 
 
void special_fdivrl (void)
{
 
emit_1_or_2_operandsl_vartext ("fdivr", "fdiv");
}
 
 
void special_fdivrpl (void)
{
 
emit_1_or_2_operandsl_vartext ("fdivrp", "fdivp");
}
 
 
void special_fsubl (void)
{
 
emit_1_or_2_operandsl_vartext ("fsub", "fsubr");
}
 
 
void special_fsubpl (void)
{
 
emit_1_or_2_operandsl_vartext ("fsubp", "fsubrp");
}
 
 
void special_fsubrl (void)
{
 
emit_1_or_2_operandsl_vartext ("fsubr", "fsub");
}
 
 
void special_fsubrpl (void)
{
 
emit_1_or_2_operandsl_vartext ("fsubrp", "fsubp");
}
 
 
void emit_multiple_data (void)
{
int i;
 
printf (" ");
 
for (i=1 ; i<(tokennum-1) ; i++)
{
emitanoperand (i, "", 0);
printf (", ");
}
 
emitanoperand (i, "", 0);
}
 
 
//==============================================
 
parsefield parsedata[] = {
{".align", " align", 2, emitonedata},
{".byte", " db", -2, emit_multiple_data},
{".data", "", 1, datasegstart},
{".extern"," externdef", 2, emitexterndef},
{".globl", " public", -2, emit_multiple_data},
{".long", " dd", -2, emit_multiple_data},
{".single"," dd", -2, emit_multiple_data},
{".text", "", 1, textsegstart},
{"adcl", " adc", 3, emittwooperandsl},
{"addb", " add", 3, emittwooperandsb},
{"addl", " add", 3, emittwooperandsl},
{"andb", " and", 3, emittwooperandsb},
{"andl", " and", 3, emittwooperandsl},
{"call", " call", 2, emitonecalldata},
{"cmpb", " cmp", 3, emittwooperandsb},
{"cmpl", " cmp", 3, emittwooperandsl},
{"cmpw", " cmp", 3, emittwooperandsw},
{"decl", " dec", 2, emitoneoperandl},
{"decw", " dec", 2, emitoneoperandw},
{"divl", " div", 2, emitoneoperandl},
{"fadd", " fadd", -2, emit_1_or_2_operandsl},
{"faddp", " faddp", -2, emit_1_or_2_operandsl},
{"faddps", " faddp", -2, emit_1_or_2_operandsl},
{"fadds", " fadd", -2, emit_1_or_2_operandsl},
{"fcom", " fcom", 2, emitoneoperandl},
{"fcoms", " fcom", 2, emitoneoperandl},
{"fcomp", " fcomp", 2, emitoneoperandl},
{"fcomps", " fcomp", 2, emitoneoperandl},
{"fdiv", "", -2, special_fdivl},
{"fdivp", "", -2, special_fdivpl},
{"fdivr", "", -2, special_fdivrl},
{"fdivrp", "", -2, special_fdivrpl},
{"fdivrs", "", -2, special_fdivrl},
{"fildl", " fild", 2, emitoneoperandl},
{"fistl", " fist", 2, emitoneoperandl},
{"fistpl", " fistp", 2, emitoneoperandl},
{"fld", " fld", 2, emitoneoperandl},
{"fldcw", " fldcw", 2, emitoneoperandw},
{"fldenv", " fldenv", 2, emitoneoperandl},
{"flds", " fld", 2, emitoneoperandl},
{"fmul", " fmul", -2, emit_1_or_2_operandsl},
{"fmulp", " fmulp", -2, emit_1_or_2_operandsl},
{"fmulps", " fmulp", -2, emit_1_or_2_operandsl},
{"fmuls", " fmul", -2, emit_1_or_2_operandsl},
{"fnstcw", " fnstcw", 2, emitoneoperandw},
{"fnstenv"," fnstenv", 2, emitoneoperandl},
{"fnstsw", " fnstsw", 2, emitoneoperandw},
{"fstp", " fstp", 2, emitoneoperandl},
{"fstps", " fstp", 2, emitoneoperandl},
{"fsts", " fst", 2, emitoneoperandl},
{"fsubr", "", -2, special_fsubrl},
{"fsubrp", "", -2, special_fsubrpl},
{"fsubrs", "", -2, special_fsubrl},
{"fsub", "", -2, special_fsubl},
{"fsubp", "", -2, special_fsubpl},
{"fsubps", "", -2, special_fsubpl},
{"fsubs", "", -2, special_fsubl},
{"fxch", " fxch", 2, emitoneoperandl},
{"imull", " imul", -2, emit_1_or_2_operandsl},
{"incl", " inc", 2, emitoneoperandl},
{"ja", " ja", 2, emitonedata},
{"jae", " jae", 2, emitonedata},
{"jb", " jb", 2, emitonedata},
{"jbe", " jbe", 2, emitonedata},
{"jc", " jc", 2, emitonedata},
{"je", " je", 2, emitonedata},
{"jg", " jg", 2, emitonedata},
{"jge", " jge", 2, emitonedata},
{"jl", " jl", 2, emitonedata},
{"jle", " jle", 2, emitonedata},
{"jmp", " jmp", 2, emitonejumpdata},
{"jna", " jna", 2, emitonedata},
{"jnae", " jnae", 2, emitonedata},
{"jnb", " jnb", 2, emitonedata},
{"jnbe", " jnbe", 2, emitonedata},
{"jnc", " jnc", 2, emitonedata},
{"jne", " jne", 2, emitonedata},
{"jng", " jng", 2, emitonedata},
{"jnge", " jnge", 2, emitonedata},
{"jnl", " jnl", 2, emitonedata},
{"jnle", " jnle", 2, emitonedata},
{"jns", " jns", 2, emitonedata},
{"jnz", " jnz", 2, emitonedata},
{"js", " js", 2, emitonedata},
{"jz", " jz", 2, emitonedata},
{"leal", " lea", 3, emittwooperandsl},
{"movb", " mov", 3, emittwooperandsb},
{"movl", " mov", 3, emittwooperandsl},
{"movw", " mov", 3, emittwooperandsw},
{"negl", " neg", 2, emitoneoperandl},
{"orb", " or", 3, emittwooperandsb},
{"orl", " or", 3, emittwooperandsl},
{"popl", " pop", 2, emitoneoperandl},
{"pushl", " push", 2, emitoneoperandl},
{"ret", " ret", -1, emit_0_or_1_operandsl},
{"rorl", " ror", 3, emittwooperandsl},
{"sarl", " sar", 3, emittwooperandsl},
{"sbbl", " sbb", 3, emittwooperandsl},
{"shll", " shl", 3, emittwooperandsl},
{"shrl", " shr", 3, emittwooperandsl},
{"subl", " sub", 3, emittwooperandsl},
{"testb", " test", 3, emittwooperandsb},
{"testl", " test", 3, emittwooperandsl},
{"xorb", " xor", 3, emittwooperandsb},
{"xorl", " xor", 3, emittwooperandsl},
};
 
int numparse = sizeof (parsedata) / sizeof (parsedata[0]);
 
//==============================================
 
void errorexit (void)
{
fprintf (stderr, "In line: %d, out line: %d\n", inline, outline);
exit (1);
}
 
 
tokenstat whitespace (char c)
{
if (c == '\n')
return LINE_DONE;
 
if ((c <= ' ') ||
(c > 127) ||
(c == ','))
{
return WHITESPACE;
}
 
return NOT_WHITESPACE;
}
 
 
int gettoken (void)
{
char c;
int count, parencount;
tokenstat stat;
 
do
{
if ((c = getchar ()) == EOF)
return FILE_DONE;
 
if ((stat = whitespace (c)) == LINE_DONE)
return LINE_DONE;
} while (stat == WHITESPACE);
 
token[0] = c;
count = 1;
 
if (c == '~')
{
count--;
token[count++] = 'n';
token[count++] = 'o';
token[count++] = 't';
token[count++] = ' ';
}
 
if (c == '(')
{
do
{
if ((c = getchar ()) == EOF)
{
fprintf (stderr, "EOF in middle of parentheses\n");
errorexit ();
}
 
token[count++] = c;
 
} while (c != ')');
}
for ( ;; )
{
if ((c = getchar ()) == EOF)
{
token[count] = 0;
return TOKEN_AVAILABLE;
}
 
if (whitespace (c) == LINE_DONE)
{
if (ungetc (c, stdin) == EOF)
{
fprintf (stderr, "Couldn't unget character\n");
errorexit ();
}
 
token[count] = 0;
return TOKEN_AVAILABLE;
}
 
if (whitespace (c) == WHITESPACE)
{
token[count] = 0;
return TOKEN_AVAILABLE;
}
 
if (count >= MAX_TOKEN_LENGTH)
{
fprintf (stderr, "Error: token too long\n");
errorexit ();
}
 
token[count++] = c;
 
if (c == '~')
{
count--;
token[count++] = 'n';
token[count++] = 'o';
token[count++] = 't';
token[count++] = ' ';
}
else if (c == '(')
{
parencount = 1;
 
do
{
if ((c = getchar ()) == EOF)
{
fprintf (stderr, "EOF in middle of parentheses\n");
errorexit ();
}
 
if (c == '(')
parencount++;
else if (c == ')')
parencount--;
 
if (c == '~')
{
token[count++] = 'n';
token[count++] = 'o';
token[count++] = 't';
token[count++] = ' ';
}
else
{
token[count++] = c;
}
 
} while ((c != ')') || (parencount > 0));
}
}
}
 
 
tokenstat parseline (void)
{
tokenstat stat;
int i, j, firsttoken, labelfound;
int mnemfound;
 
firsttoken = 1;
tokennum = 0;
labelfound = 0;
 
for ( ;; )
{
token = tokens[tokennum];
stat = gettoken ();
 
switch (stat)
{
case FILE_DONE:
return FILE_DONE;
 
case LINE_DONE:
if (!firsttoken && tokennum)
{
mnemfound = 0;
 
for (i=0 ; i<numparse; i++)
{
if (!strcmpi (tokens[0], parsedata[i].text))
{
if (((parsedata[i].numtokens > 0) &&
(parsedata[i].numtokens != tokennum)) ||
((parsedata[i].numtokens < 0) &&
(tokennum < -parsedata[i].numtokens)))
{
fprintf (stderr, "mismatched number of tokens\n");
 
for (j=0 ; j<tokennum ; j++)
fprintf (stderr, "%s\n", tokens[j]);
 
fprintf (stderr, "\n");
errorexit ();
}
 
printf ("%s", parsedata[i].emit);
(*parsedata[i].parsefunc) ();
 
mnemfound = 1;
break;
}
}
 
if (!mnemfound)
{
fprintf (stderr, "Error: unknown mnemonic\n");
 
for (j=0 ; j<tokennum ; j++)
fprintf (stderr, "%s\n", tokens[j]);
 
fprintf (stderr, "\n");
errorexit ();
}
}
 
if (!firsttoken)
{
if ((currentseg == DATASEG) && labelfound && !tokennum)
printf (":\n");
else
printf ("\n");
 
outline++;
}
return PARSED_OKAY;
 
case TOKEN_AVAILABLE:
if (firsttoken)
{
if (token[strlen(token) - 1] == ':')
{
labelfound = 1;
 
if (currentseg == DATASEG)
{
token[strlen(token) - 1] = 0;
printf ("%s", token);
}
else if (currentseg == TEXTSEG)
{
printf ("%s", token);
}
else
{
fprintf (stderr, "Error: not in segment block\n");
errorexit ();
}
 
firsttoken = 0;
break;
}
}
 
firsttoken = 0;
 
if (tokennum >= MAX_TOKENS)
{
fprintf (stderr, "Error: too many tokens\n");
exit (0);
}
 
tokennum++;
 
break;
 
default:
fprintf (stderr, "Error: unknown tokenstat %d\n", stat);
exit (0);
}
}
}
 
 
void main (int argc, char **argv)
{
tokenstat stat;
 
printf (" .386P\n"
" .model FLAT\n");
inline = 1;
outline = 3;
 
for ( ;; )
{
stat = parseline ();
inline++;
 
switch (stat)
{
case FILE_DONE:
if (currentseg == TEXTSEG)
printf ("_TEXT ENDS\n");
else if (currentseg == DATASEG)
printf ("_DATA ENDS\n");
 
printf (" END\n");
exit (0);
case PARSED_OKAY:
break;
 
default:
fprintf (stderr, "Error: unknown tokenstat %d\n", stat);
exit (0);
}
}
}
 
/contrib/other/sdlquake-1.0.9/gas2masm/gas2masm.dsp
0,0 → 1,100
# Microsoft Developer Studio Project File - Name="gas2masm" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
 
# TARGTYPE "Win32 (x86) Console Application" 0x0103
 
CFG=gas2masm - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "gas2masm.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "gas2masm.mak" CFG="gas2masm - Win32 Release"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "gas2masm - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "gas2masm - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
 
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
 
!IF "$(CFG)" == "gas2masm - Win32 Release"
 
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir ".\Release"
# PROP BASE Intermediate_Dir ".\Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ".\Release"
# PROP Intermediate_Dir ".\Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
 
!ELSEIF "$(CFG)" == "gas2masm - Win32 Debug"
 
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir ".\Debug"
# PROP BASE Intermediate_Dir ".\Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ".\Debug"
# PROP Intermediate_Dir ".\Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
 
!ENDIF
 
# Begin Target
 
# Name "gas2masm - Win32 Release"
# Name "gas2masm - Win32 Debug"
# Begin Group "Source Files"
 
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
# Begin Source File
 
SOURCE=.\gas2masm.c
# End Source File
# End Group
# Begin Group "Header Files"
 
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
# End Group
# Begin Group "Resource Files"
 
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project
/contrib/other/sdlquake-1.0.9/gas2masm/gas2masm.dsw
0,0 → 1,29
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
 
###############################################################################
 
Project: "gas2masm"=.\gas2masm.dsp - Package Owner=<4>
 
Package=<5>
{{{
}}}
 
Package=<4>
{{{
}}}
 
###############################################################################
 
Global:
 
Package=<5>
{{{
}}}
 
Package=<3>
{{{
}}}
 
###############################################################################
 
/contrib/other/sdlquake-1.0.9/gas2masm/gas2masm.mdp
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/contrib/other/sdlquake-1.0.9/gas2masm/gas2masm.plg
0,0 → 1,32
<html>
<body>
<pre>
<h1>Build Log</h1>
<h3>
--------------------Configuration: gas2masm - Win32 Debug--------------------
</h3>
<h3>Command Lines</h3>
Creating temporary file "C:\TEMP\RSP730.tmp" with contents
[
/nologo /MLd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /Fp".\Debug/gas2masm.pch" /YX /Fo".\Debug/" /Fd".\Debug/" /FD /c
"D:\Work\quake source\WinQuake\gas2masm\gas2masm.c"
]
Creating command line "cl.exe @C:\TEMP\RSP730.tmp"
Creating temporary file "C:\TEMP\RSP731.tmp" with contents
[
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:yes /pdb:".\Debug/gas2masm.pdb" /debug /machine:I386 /out:".\Debug/gas2masm.exe"
".\Debug\gas2masm.obj"
]
Creating command line "link.exe @C:\TEMP\RSP731.tmp"
<h3>Output Window</h3>
Compiling...
gas2masm.c
Linking...
 
 
 
<h3>Results</h3>
gas2masm.exe - 0 error(s), 0 warning(s)
</pre>
</body>
</html>
/contrib/other/sdlquake-1.0.9/gl_draw.c
0,0 → 1,1297
/*
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.c -- this is the only file outside the refresh that touches the
// vid buffer
 
#include "quakedef.h"
 
#define GL_COLOR_INDEX8_EXT 0x80E5
 
extern unsigned char d_15to8table[65536];
 
cvar_t gl_nobind = {"gl_nobind", "0"};
cvar_t gl_max_size = {"gl_max_size", "1024"};
cvar_t gl_picmip = {"gl_picmip", "0"};
 
byte *draw_chars; // 8*8 graphic characters
qpic_t *draw_disc;
qpic_t *draw_backtile;
 
int translate_texture;
int char_texture;
 
typedef struct
{
int texnum;
float sl, tl, sh, th;
} glpic_t;
 
byte conback_buffer[sizeof(qpic_t) + sizeof(glpic_t)];
qpic_t *conback = (qpic_t *)&conback_buffer;
 
int gl_lightmap_format = 4;
int gl_solid_format = 3;
int gl_alpha_format = 4;
 
int gl_filter_min = GL_LINEAR_MIPMAP_NEAREST;
int gl_filter_max = GL_LINEAR;
 
 
int texels;
 
typedef struct
{
int texnum;
char identifier[64];
int width, height;
qboolean mipmap;
} gltexture_t;
 
#define MAX_GLTEXTURES 1024
gltexture_t gltextures[MAX_GLTEXTURES];
int numgltextures;
 
 
void GL_Bind (int texnum)
{
if (gl_nobind.value)
texnum = char_texture;
if (currenttexture == texnum)
return;
currenttexture = texnum;
#ifdef _WIN32
bindTexFunc (GL_TEXTURE_2D, texnum);
#else
glBindTexture(GL_TEXTURE_2D, texnum);
#endif
}
 
 
/*
=============================================================================
 
scrap allocation
 
Allocate all the little status bar obejcts into a single texture
to crutch up stupid hardware / drivers
 
=============================================================================
*/
 
#define MAX_SCRAPS 2
#define BLOCK_WIDTH 256
#define BLOCK_HEIGHT 256
 
int scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH];
byte scrap_texels[MAX_SCRAPS][BLOCK_WIDTH*BLOCK_HEIGHT*4];
qboolean scrap_dirty;
int scrap_texnum;
 
// returns a texture number and the position inside it
int Scrap_AllocBlock (int w, int h, int *x, int *y)
{
int i, j;
int best, best2;
int bestx;
int texnum;
 
for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++)
{
best = BLOCK_HEIGHT;
 
for (i=0 ; i<BLOCK_WIDTH-w ; i++)
{
best2 = 0;
 
for (j=0 ; j<w ; j++)
{
if (scrap_allocated[texnum][i+j] >= best)
break;
if (scrap_allocated[texnum][i+j] > best2)
best2 = scrap_allocated[texnum][i+j];
}
if (j == w)
{ // this is a valid spot
*x = i;
*y = best = best2;
}
}
 
if (best + h > BLOCK_HEIGHT)
continue;
 
for (i=0 ; i<w ; i++)
scrap_allocated[texnum][*x + i] = best + h;
 
return texnum;
}
 
Sys_Error ("Scrap_AllocBlock: full");
}
 
int scrap_uploads;
 
void Scrap_Upload (void)
{
int texnum;
 
scrap_uploads++;
 
for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++) {
GL_Bind(scrap_texnum + texnum);
GL_Upload8 (scrap_texels[texnum], BLOCK_WIDTH, BLOCK_HEIGHT, false, true);
}
scrap_dirty = false;
}
 
//=============================================================================
/* Support Routines */
 
typedef struct cachepic_s
{
char name[MAX_QPATH];
qpic_t pic;
byte padding[32]; // for appended glpic
} cachepic_t;
 
#define MAX_CACHED_PICS 128
cachepic_t menu_cachepics[MAX_CACHED_PICS];
int menu_numcachepics;
 
byte menuplyr_pixels[4096];
 
int pic_texels;
int pic_count;
 
qpic_t *Draw_PicFromWad (char *name)
{
qpic_t *p;
glpic_t *gl;
 
p = W_GetLumpName (name);
gl = (glpic_t *)p->data;
 
// load little ones into the scrap
if (p->width < 64 && p->height < 64)
{
int x, y;
int i, j, k;
int texnum;
 
texnum = Scrap_AllocBlock (p->width, p->height, &x, &y);
scrap_dirty = true;
k = 0;
for (i=0 ; i<p->height ; i++)
for (j=0 ; j<p->width ; j++, k++)
scrap_texels[texnum][(y+i)*BLOCK_WIDTH + x + j] = p->data[k];
texnum += scrap_texnum;
gl->texnum = texnum;
gl->sl = (x+0.01)/(float)BLOCK_WIDTH;
gl->sh = (x+p->width-0.01)/(float)BLOCK_WIDTH;
gl->tl = (y+0.01)/(float)BLOCK_WIDTH;
gl->th = (y+p->height-0.01)/(float)BLOCK_WIDTH;
 
pic_count++;
pic_texels += p->width*p->height;
}
else
{
gl->texnum = GL_LoadPicTexture (p);
gl->sl = 0;
gl->sh = 1;
gl->tl = 0;
gl->th = 1;
}
return p;
}
 
 
/*
================
Draw_CachePic
================
*/
qpic_t *Draw_CachePic (char *path)
{
cachepic_t *pic;
int i;
qpic_t *dat;
glpic_t *gl;
 
for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++)
if (!strcmp (path, pic->name))
return &pic->pic;
 
if (menu_numcachepics == MAX_CACHED_PICS)
Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
menu_numcachepics++;
strcpy (pic->name, path);
 
//
// load the pic from disk
//
dat = (qpic_t *)COM_LoadTempFile (path);
if (!dat)
Sys_Error ("Draw_CachePic: failed to load %s", path);
SwapPic (dat);
 
// HACK HACK HACK --- we need to keep the bytes for
// the translatable player picture just for the menu
// configuration dialog
if (!strcmp (path, "gfx/menuplyr.lmp"))
memcpy (menuplyr_pixels, dat->data, dat->width*dat->height);
 
pic->pic.width = dat->width;
pic->pic.height = dat->height;
 
gl = (glpic_t *)pic->pic.data;
gl->texnum = GL_LoadPicTexture (dat);
gl->sl = 0;
gl->sh = 1;
gl->tl = 0;
gl->th = 1;
 
return &pic->pic;
}
 
 
void Draw_CharToConback (int num, byte *dest)
{
int row, col;
byte *source;
int drawline;
int x;
 
row = num>>4;
col = num&15;
source = draw_chars + (row<<10) + (col<<3);
 
drawline = 8;
 
while (drawline--)
{
for (x=0 ; x<8 ; x++)
if (source[x] != 255)
dest[x] = 0x60 + source[x];
source += 128;
dest += 320;
}
 
}
 
typedef struct
{
char *name;
int minimize, maximize;
} glmode_t;
 
glmode_t modes[] = {
{"GL_NEAREST", GL_NEAREST, GL_NEAREST},
{"GL_LINEAR", GL_LINEAR, GL_LINEAR},
{"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
{"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
{"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
{"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
};
 
/*
===============
Draw_TextureMode_f
===============
*/
void Draw_TextureMode_f (void)
{
int i;
gltexture_t *glt;
 
if (Cmd_Argc() == 1)
{
for (i=0 ; i< 6 ; i++)
if (gl_filter_min == modes[i].minimize)
{
Con_Printf ("%s\n", modes[i].name);
return;
}
Con_Printf ("current filter is unknown???\n");
return;
}
 
for (i=0 ; i< 6 ; i++)
{
if (!Q_strcasecmp (modes[i].name, Cmd_Argv(1) ) )
break;
}
if (i == 6)
{
Con_Printf ("bad filter name\n");
return;
}
 
gl_filter_min = modes[i].minimize;
gl_filter_max = modes[i].maximize;
 
// change all the existing mipmap texture objects
for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
{
if (glt->mipmap)
{
GL_Bind (glt->texnum);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
}
}
}
 
/*
===============
Draw_Init
===============
*/
void Draw_Init (void)
{
int i;
qpic_t *cb;
byte *dest, *src;
int x, y;
char ver[40];
glpic_t *gl;
int start;
byte *ncdata;
int f, fstep;
 
 
Cvar_RegisterVariable (&gl_nobind);
Cvar_RegisterVariable (&gl_max_size);
Cvar_RegisterVariable (&gl_picmip);
 
// 3dfx can only handle 256 wide textures
if (!Q_strncasecmp ((char *)gl_renderer, "3dfx",4) ||
strstr((char *)gl_renderer, "Glide"))
Cvar_Set ("gl_max_size", "256");
 
Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f);
 
// load the console background and the charset
// by hand, because we need to write the version
// string into the background before turning
// it into a texture
draw_chars = W_GetLumpName ("conchars");
for (i=0 ; i<256*64 ; i++)
if (draw_chars[i] == 0)
draw_chars[i] = 255; // proper transparent color
 
// now turn them into textures
char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true);
 
start = Hunk_LowMark();
 
cb = (qpic_t *)COM_LoadTempFile ("gfx/conback.lmp");
if (!cb)
Sys_Error ("Couldn't load gfx/conback.lmp");
SwapPic (cb);
 
// hack the version number directly into the pic
#if defined(__linux__)
sprintf (ver, "(Linux %2.2f, gl %4.2f) %4.2f", (float)LINUX_VERSION, (float)GLQUAKE_VERSION, (float)VERSION);
#else
sprintf (ver, "(gl %4.2f) %4.2f", (float)GLQUAKE_VERSION, (float)VERSION);
#endif
dest = cb->data + 320*186 + 320 - 11 - 8*strlen(ver);
y = strlen(ver);
for (x=0 ; x<y ; x++)
Draw_CharToConback (ver[x], dest+(x<<3));
 
#if 0
conback->width = vid.conwidth;
conback->height = vid.conheight;
 
// scale console to vid size
dest = ncdata = Hunk_AllocName(vid.conwidth * vid.conheight, "conback");
for (y=0 ; y<vid.conheight ; y++, dest += vid.conwidth)
{
src = cb->data + cb->width * (y*cb->height/vid.conheight);
if (vid.conwidth == cb->width)
memcpy (dest, src, vid.conwidth);
else
{
f = 0;
fstep = cb->width*0x10000/vid.conwidth;
for (x=0 ; x<vid.conwidth ; x+=4)
{
dest[x] = src[f>>16];
f += fstep;
dest[x+1] = src[f>>16];
f += fstep;
dest[x+2] = src[f>>16];
f += fstep;
dest[x+3] = src[f>>16];
f += fstep;
}
}
}
#else
conback->width = cb->width;
conback->height = cb->height;
ncdata = cb->data;
#endif
 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
gl = (glpic_t *)conback->data;
gl->texnum = GL_LoadTexture ("conback", conback->width, conback->height, ncdata, false, false);
gl->sl = 0;
gl->sh = 1;
gl->tl = 0;
gl->th = 1;
conback->width = vid.width;
conback->height = vid.height;
 
// free loaded console
Hunk_FreeToLowMark(start);
 
// save a texture slot for translated picture
translate_texture = texture_extension_number++;
 
// save slots for scraps
scrap_texnum = texture_extension_number;
texture_extension_number += MAX_SCRAPS;
 
//
// get the other pics we need
//
draw_disc = Draw_PicFromWad ("disc");
draw_backtile = Draw_PicFromWad ("backtile");
}
 
 
 
/*
================
Draw_Character
 
Draws one 8*8 graphics character with 0 being transparent.
It can be clipped to the top of the screen to allow the console to be
smoothly scrolled off.
================
*/
void Draw_Character (int x, int y, int num)
{
byte *dest;
byte *source;
unsigned short *pusdest;
int drawline;
int row, col;
float frow, fcol, size;
 
if (num == 32)
return; // space
 
num &= 255;
if (y <= -8)
return; // totally off screen
 
row = num>>4;
col = num&15;
 
frow = row*0.0625;
fcol = col*0.0625;
size = 0.0625;
 
GL_Bind (char_texture);
 
glBegin (GL_QUADS);
glTexCoord2f (fcol, frow);
glVertex2f (x, y);
glTexCoord2f (fcol + size, frow);
glVertex2f (x+8, y);
glTexCoord2f (fcol + size, frow + size);
glVertex2f (x+8, y+8);
glTexCoord2f (fcol, frow + size);
glVertex2f (x, y+8);
glEnd ();
}
 
/*
================
Draw_String
================
*/
void Draw_String (int x, int y, char *str)
{
while (*str)
{
Draw_Character (x, y, *str);
str++;
x += 8;
}
}
 
/*
================
Draw_DebugChar
 
Draws a single character directly to the upper right corner of the screen.
This is for debugging lockups by drawing different chars in different parts
of the code.
================
*/
void Draw_DebugChar (char num)
{
}
 
/*
=============
Draw_AlphaPic
=============
*/
void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha)
{
byte *dest, *source;
unsigned short *pusdest;
int v, u;
glpic_t *gl;
 
if (scrap_dirty)
Scrap_Upload ();
gl = (glpic_t *)pic->data;
glDisable(GL_ALPHA_TEST);
glEnable (GL_BLEND);
// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// glCullFace(GL_FRONT);
glColor4f (1,1,1,alpha);
GL_Bind (gl->texnum);
glBegin (GL_QUADS);
glTexCoord2f (gl->sl, gl->tl);
glVertex2f (x, y);
glTexCoord2f (gl->sh, gl->tl);
glVertex2f (x+pic->width, y);
glTexCoord2f (gl->sh, gl->th);
glVertex2f (x+pic->width, y+pic->height);
glTexCoord2f (gl->sl, gl->th);
glVertex2f (x, y+pic->height);
glEnd ();
glColor4f (1,1,1,1);
glEnable(GL_ALPHA_TEST);
glDisable (GL_BLEND);
}
 
 
/*
=============
Draw_Pic
=============
*/
void Draw_Pic (int x, int y, qpic_t *pic)
{
byte *dest, *source;
unsigned short *pusdest;
int v, u;
glpic_t *gl;
 
if (scrap_dirty)
Scrap_Upload ();
gl = (glpic_t *)pic->data;
glColor4f (1,1,1,1);
GL_Bind (gl->texnum);
glBegin (GL_QUADS);
glTexCoord2f (gl->sl, gl->tl);
glVertex2f (x, y);
glTexCoord2f (gl->sh, gl->tl);
glVertex2f (x+pic->width, y);
glTexCoord2f (gl->sh, gl->th);
glVertex2f (x+pic->width, y+pic->height);
glTexCoord2f (gl->sl, gl->th);
glVertex2f (x, y+pic->height);
glEnd ();
}
 
 
/*
=============
Draw_TransPic
=============
*/
void Draw_TransPic (int x, int y, qpic_t *pic)
{
byte *dest, *source, tbyte;
unsigned short *pusdest;
int v, u;
 
if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
(unsigned)(y + pic->height) > vid.height)
{
Sys_Error ("Draw_TransPic: bad coordinates");
}
Draw_Pic (x, y, pic);
}
 
 
/*
=============
Draw_TransPicTranslate
 
Only used for the player color selection menu
=============
*/
void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
{
int v, u, c;
unsigned trans[64*64], *dest;
byte *src;
int p;
 
GL_Bind (translate_texture);
 
c = pic->width * pic->height;
 
dest = trans;
for (v=0 ; v<64 ; v++, dest += 64)
{
src = &menuplyr_pixels[ ((v*pic->height)>>6) *pic->width];
for (u=0 ; u<64 ; u++)
{
p = src[(u*pic->width)>>6];
if (p == 255)
dest[u] = p;
else
dest[u] = d_8to24table[translation[p]];
}
}
 
glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
glColor3f (1,1,1);
glBegin (GL_QUADS);
glTexCoord2f (0, 0);
glVertex2f (x, y);
glTexCoord2f (1, 0);
glVertex2f (x+pic->width, y);
glTexCoord2f (1, 1);
glVertex2f (x+pic->width, y+pic->height);
glTexCoord2f (0, 1);
glVertex2f (x, y+pic->height);
glEnd ();
}
 
 
/*
================
Draw_ConsoleBackground
 
================
*/
void Draw_ConsoleBackground (int lines)
{
int y = (vid.height * 3) >> 2;
 
if (lines > y)
Draw_Pic(0, lines - vid.height, conback);
else
Draw_AlphaPic (0, lines - vid.height, conback, (float)(1.2 * lines)/y);
}
 
 
/*
=============
Draw_TileClear
 
This repeats a 64*64 tile graphic to fill the screen around a sized down
refresh window.
=============
*/
void Draw_TileClear (int x, int y, int w, int h)
{
glColor3f (1,1,1);
GL_Bind (*(int *)draw_backtile->data);
glBegin (GL_QUADS);
glTexCoord2f (x/64.0, y/64.0);
glVertex2f (x, y);
glTexCoord2f ( (x+w)/64.0, y/64.0);
glVertex2f (x+w, y);
glTexCoord2f ( (x+w)/64.0, (y+h)/64.0);
glVertex2f (x+w, y+h);
glTexCoord2f ( x/64.0, (y+h)/64.0 );
glVertex2f (x, y+h);
glEnd ();
}
 
 
/*
=============
Draw_Fill
 
Fills a box of pixels with a single color
=============
*/
void Draw_Fill (int x, int y, int w, int h, int c)
{
glDisable (GL_TEXTURE_2D);
glColor3f (host_basepal[c*3]/255.0,
host_basepal[c*3+1]/255.0,
host_basepal[c*3+2]/255.0);
 
glBegin (GL_QUADS);
 
glVertex2f (x,y);
glVertex2f (x+w, y);
glVertex2f (x+w, y+h);
glVertex2f (x, y+h);
 
glEnd ();
glColor3f (1,1,1);
glEnable (GL_TEXTURE_2D);
}
//=============================================================================
 
/*
================
Draw_FadeScreen
 
================
*/
void Draw_FadeScreen (void)
{
glEnable (GL_BLEND);
glDisable (GL_TEXTURE_2D);
glColor4f (0, 0, 0, 0.8);
glBegin (GL_QUADS);
 
glVertex2f (0,0);
glVertex2f (vid.width, 0);
glVertex2f (vid.width, vid.height);
glVertex2f (0, vid.height);
 
glEnd ();
glColor4f (1,1,1,1);
glEnable (GL_TEXTURE_2D);
glDisable (GL_BLEND);
 
Sbar_Changed();
}
 
//=============================================================================
 
/*
================
Draw_BeginDisc
 
Draws the little blue disc in the corner of the screen.
Call before beginning any disc IO.
================
*/
void Draw_BeginDisc (void)
{
if (!draw_disc)
return;
glDrawBuffer (GL_FRONT);
Draw_Pic (vid.width - 24, 0, draw_disc);
glDrawBuffer (GL_BACK);
}
 
 
/*
================
Draw_EndDisc
 
Erases the disc icon.
Call after completing any disc IO
================
*/
void Draw_EndDisc (void)
{
}
 
/*
================
GL_Set2D
 
Setup as if the screen was 320*200
================
*/
void GL_Set2D (void)
{
glViewport (glx, gly, glwidth, glheight);
 
glMatrixMode(GL_PROJECTION);
glLoadIdentity ();
glOrtho (0, vid.width, vid.height, 0, -99999, 99999);
 
glMatrixMode(GL_MODELVIEW);
glLoadIdentity ();
 
glDisable (GL_DEPTH_TEST);
glDisable (GL_CULL_FACE);
glDisable (GL_BLEND);
glEnable (GL_ALPHA_TEST);
// glDisable (GL_ALPHA_TEST);
 
glColor4f (1,1,1,1);
}
 
//====================================================================
 
/*
================
GL_FindTexture
================
*/
int GL_FindTexture (char *identifier)
{
int i;
gltexture_t *glt;
 
for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
{
if (!strcmp (identifier, glt->identifier))
return gltextures[i].texnum;
}
 
return -1;
}
 
/*
================
GL_ResampleTexture
================
*/
void GL_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight)
{
int i, j;
unsigned *inrow;
unsigned frac, fracstep;
 
fracstep = inwidth*0x10000/outwidth;
for (i=0 ; i<outheight ; i++, out += outwidth)
{
inrow = in + inwidth*(i*inheight/outheight);
frac = fracstep >> 1;
for (j=0 ; j<outwidth ; j+=4)
{
out[j] = inrow[frac>>16];
frac += fracstep;
out[j+1] = inrow[frac>>16];
frac += fracstep;
out[j+2] = inrow[frac>>16];
frac += fracstep;
out[j+3] = inrow[frac>>16];
frac += fracstep;
}
}
}
 
/*
================
GL_Resample8BitTexture -- JACK
================
*/
void GL_Resample8BitTexture (unsigned char *in, int inwidth, int inheight, unsigned char *out, int outwidth, int outheight)
{
int i, j;
unsigned char *inrow;
unsigned frac, fracstep;
 
fracstep = inwidth*0x10000/outwidth;
for (i=0 ; i<outheight ; i++, out += outwidth)
{
inrow = in + inwidth*(i*inheight/outheight);
frac = fracstep >> 1;
for (j=0 ; j<outwidth ; j+=4)
{
out[j] = inrow[frac>>16];
frac += fracstep;
out[j+1] = inrow[frac>>16];
frac += fracstep;
out[j+2] = inrow[frac>>16];
frac += fracstep;
out[j+3] = inrow[frac>>16];
frac += fracstep;
}
}
}
 
 
/*
================
GL_MipMap
 
Operates in place, quartering the size of the texture
================
*/
void GL_MipMap (byte *in, int width, int height)
{
int i, j;
byte *out;
 
width <<=2;
height >>= 1;
out = in;
for (i=0 ; i<height ; i++, in+=width)
{
for (j=0 ; j<width ; j+=8, out+=4, in+=8)
{
out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2;
out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2;
out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2;
out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2;
}
}
}
 
/*
================
GL_MipMap8Bit
 
Mipping for 8 bit textures
================
*/
void GL_MipMap8Bit (byte *in, int width, int height)
{
int i, j;
unsigned short r,g,b;
byte *out, *at1, *at2, *at3, *at4;
 
// width <<=2;
height >>= 1;
out = in;
for (i=0 ; i<height ; i++, in+=width)
{
for (j=0 ; j<width ; j+=2, out+=1, in+=2)
{
at1 = (byte *) (d_8to24table + in[0]);
at2 = (byte *) (d_8to24table + in[1]);
at3 = (byte *) (d_8to24table + in[width+0]);
at4 = (byte *) (d_8to24table + in[width+1]);
 
r = (at1[0]+at2[0]+at3[0]+at4[0]); r>>=5;
g = (at1[1]+at2[1]+at3[1]+at4[1]); g>>=5;
b = (at1[2]+at2[2]+at3[2]+at4[2]); b>>=5;
 
out[0] = d_15to8table[(r<<0) + (g<<5) + (b<<10)];
}
}
}
 
/*
===============
GL_Upload32
===============
*/
void GL_Upload32 (unsigned *data, int width, int height, qboolean mipmap, qboolean alpha)
{
int samples;
static unsigned scaled[1024*512]; // [512*256];
int scaled_width, scaled_height;
 
for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
;
for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
;
 
scaled_width >>= (int)gl_picmip.value;
scaled_height >>= (int)gl_picmip.value;
 
if (scaled_width > gl_max_size.value)
scaled_width = gl_max_size.value;
if (scaled_height > gl_max_size.value)
scaled_height = gl_max_size.value;
 
if (scaled_width * scaled_height > sizeof(scaled)/4)
Sys_Error ("GL_LoadTexture: too big");
 
samples = alpha ? gl_alpha_format : gl_solid_format;
 
#if 0
if (mipmap)
gluBuild2DMipmaps (GL_TEXTURE_2D, samples, width, height, GL_RGBA, GL_UNSIGNED_BYTE, trans);
else if (scaled_width == width && scaled_height == height)
glTexImage2D (GL_TEXTURE_2D, 0, samples, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
else
{
gluScaleImage (GL_RGBA, width, height, GL_UNSIGNED_BYTE, trans,
scaled_width, scaled_height, GL_UNSIGNED_BYTE, scaled);
glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
}
#else
texels += scaled_width * scaled_height;
 
if (scaled_width == width && scaled_height == height)
{
if (!mipmap)
{
glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
goto done;
}
memcpy (scaled, data, width*height*4);
}
else
GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
 
glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
if (mipmap)
{
int miplevel;
 
miplevel = 0;
while (scaled_width > 1 || scaled_height > 1)
{
GL_MipMap ((byte *)scaled, scaled_width, scaled_height);
scaled_width >>= 1;
scaled_height >>= 1;
if (scaled_width < 1)
scaled_width = 1;
if (scaled_height < 1)
scaled_height = 1;
miplevel++;
glTexImage2D (GL_TEXTURE_2D, miplevel, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
}
}
done: ;
#endif
 
 
if (mipmap)
{
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
}
else
{
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
}
}
 
void GL_Upload8_EXT (byte *data, int width, int height, qboolean mipmap, qboolean alpha)
{
int i, s;
qboolean noalpha;
int p;
static unsigned j;
int samples;
static unsigned char scaled[1024*512]; // [512*256];
int scaled_width, scaled_height;
 
s = width*height;
// if there are no transparent pixels, make it a 3 component
// texture even if it was specified as otherwise
if (alpha)
{
noalpha = true;
for (i=0 ; i<s ; i++)
{
if (data[i] == 255)
noalpha = false;
}
 
if (alpha && noalpha)
alpha = false;
}
for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
;
for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
;
 
scaled_width >>= (int)gl_picmip.value;
scaled_height >>= (int)gl_picmip.value;
 
if (scaled_width > gl_max_size.value)
scaled_width = gl_max_size.value;
if (scaled_height > gl_max_size.value)
scaled_height = gl_max_size.value;
 
if (scaled_width * scaled_height > sizeof(scaled))
Sys_Error ("GL_LoadTexture: too big");
 
samples = 1; // alpha ? gl_alpha_format : gl_solid_format;
 
texels += scaled_width * scaled_height;
 
if (scaled_width == width && scaled_height == height)
{
if (!mipmap)
{
glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX , GL_UNSIGNED_BYTE, data);
goto done;
}
memcpy (scaled, data, width*height);
}
else
GL_Resample8BitTexture (data, width, height, scaled, scaled_width, scaled_height);
 
glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
if (mipmap)
{
int miplevel;
 
miplevel = 0;
while (scaled_width > 1 || scaled_height > 1)
{
GL_MipMap8Bit ((byte *)scaled, scaled_width, scaled_height);
scaled_width >>= 1;
scaled_height >>= 1;
if (scaled_width < 1)
scaled_width = 1;
if (scaled_height < 1)
scaled_height = 1;
miplevel++;
glTexImage2D (GL_TEXTURE_2D, miplevel, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
}
}
done: ;
 
 
if (mipmap)
{
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
}
else
{
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
}
}
 
/*
===============
GL_Upload8
===============
*/
void GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean alpha)
{
static unsigned trans[640*480]; // FIXME, temporary
int i, s;
qboolean noalpha;
int p;
 
s = width*height;
// if there are no transparent pixels, make it a 3 component
// texture even if it was specified as otherwise
if (alpha)
{
noalpha = true;
for (i=0 ; i<s ; i++)
{
p = data[i];
if (p == 255)
noalpha = false;
trans[i] = d_8to24table[p];
}
 
if (alpha && noalpha)
alpha = false;
}
else
{
if (s&3)
Sys_Error ("GL_Upload8: s&3");
for (i=0 ; i<s ; i+=4)
{
trans[i] = d_8to24table[data[i]];
trans[i+1] = d_8to24table[data[i+1]];
trans[i+2] = d_8to24table[data[i+2]];
trans[i+3] = d_8to24table[data[i+3]];
}
}
 
if (VID_Is8bit() && !alpha && (data!=scrap_texels[0])) {
GL_Upload8_EXT (data, width, height, mipmap, alpha);
return;
}
GL_Upload32 (trans, width, height, mipmap, alpha);
}
 
/*
================
GL_LoadTexture
================
*/
int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha)
{
qboolean noalpha;
int i, p, s;
gltexture_t *glt;
 
// see if the texture is allready present
if (identifier[0])
{
for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
{
if (!strcmp (identifier, glt->identifier))
{
if (width != glt->width || height != glt->height)
Sys_Error ("GL_LoadTexture: cache mismatch");
return gltextures[i].texnum;
}
}
}
else {
glt = &gltextures[numgltextures];
numgltextures++;
}
 
strcpy (glt->identifier, identifier);
glt->texnum = texture_extension_number;
glt->width = width;
glt->height = height;
glt->mipmap = mipmap;
 
GL_Bind(texture_extension_number );
 
GL_Upload8 (data, width, height, mipmap, alpha);
 
texture_extension_number++;
 
return texture_extension_number-1;
}
 
/*
================
GL_LoadPicTexture
================
*/
int GL_LoadPicTexture (qpic_t *pic)
{
return GL_LoadTexture ("", pic->width, pic->height, pic->data, false, true);
}
 
/****************************************/
 
static GLenum oldtarget = TEXTURE0_SGIS;
 
void GL_SelectTexture (GLenum target)
{
if (!gl_mtexable)
return;
qglSelectTextureSGIS(target);
if (target == oldtarget)
return;
cnttextures[oldtarget-TEXTURE0_SGIS] = currenttexture;
currenttexture = cnttextures[target-TEXTURE0_SGIS];
oldtarget = target;
}
/contrib/other/sdlquake-1.0.9/gl_mesh.c
0,0 → 1,360
/*
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);
 
//
// 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);
}
}
 
 
// 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]];
}
 
/contrib/other/sdlquake-1.0.9/gl_model.c
0,0 → 1,1840
/*
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.
 
*/
// models.c -- model loading and caching
 
// models are the only shared resource between a client and server running
// on the same machine.
 
#include "quakedef.h"
 
model_t *loadmodel;
char loadname[32]; // for hunk tags
 
void Mod_LoadSpriteModel (model_t *mod, void *buffer);
void Mod_LoadBrushModel (model_t *mod, void *buffer);
void Mod_LoadAliasModel (model_t *mod, void *buffer);
model_t *Mod_LoadModel (model_t *mod, qboolean crash);
 
byte mod_novis[MAX_MAP_LEAFS/8];
 
#define MAX_MOD_KNOWN 512
model_t mod_known[MAX_MOD_KNOWN];
int mod_numknown;
 
cvar_t gl_subdivide_size = {"gl_subdivide_size", "128", true};
 
/*
===============
Mod_Init
===============
*/
void Mod_Init (void)
{
Cvar_RegisterVariable (&gl_subdivide_size);
memset (mod_novis, 0xff, sizeof(mod_novis));
}
 
/*
===============
Mod_Init
 
Caches the data if needed
===============
*/
void *Mod_Extradata (model_t *mod)
{
void *r;
r = Cache_Check (&mod->cache);
if (r)
return r;
 
Mod_LoadModel (mod, true);
if (!mod->cache.data)
Sys_Error ("Mod_Extradata: caching failed");
return mod->cache.data;
}
 
/*
===============
Mod_PointInLeaf
===============
*/
mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
{
mnode_t *node;
float d;
mplane_t *plane;
if (!model || !model->nodes)
Sys_Error ("Mod_PointInLeaf: bad model");
 
node = model->nodes;
while (1)
{
if (node->contents < 0)
return (mleaf_t *)node;
plane = node->plane;
d = DotProduct (p,plane->normal) - plane->dist;
if (d > 0)
node = node->children[0];
else
node = node->children[1];
}
return NULL; // never reached
}
 
 
/*
===================
Mod_DecompressVis
===================
*/
byte *Mod_DecompressVis (byte *in, model_t *model)
{
static byte decompressed[MAX_MAP_LEAFS/8];
int c;
byte *out;
int row;
 
row = (model->numleafs+7)>>3;
out = decompressed;
 
#if 0
memcpy (out, in, row);
#else
if (!in)
{ // no vis info, so make all visible
while (row)
{
*out++ = 0xff;
row--;
}
return decompressed;
}
 
do
{
if (*in)
{
*out++ = *in++;
continue;
}
c = in[1];
in += 2;
while (c)
{
*out++ = 0;
c--;
}
} while (out - decompressed < row);
#endif
return decompressed;
}
 
byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model)
{
if (leaf == model->leafs)
return mod_novis;
return Mod_DecompressVis (leaf->compressed_vis, model);
}
 
/*
===================
Mod_ClearAll
===================
*/
void Mod_ClearAll (void)
{
int i;
model_t *mod;
for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
if (mod->type != mod_alias)
mod->needload = true;
}
 
/*
==================
Mod_FindName
 
==================
*/
model_t *Mod_FindName (char *name)
{
int i;
model_t *mod;
if (!name[0])
Sys_Error ("Mod_ForName: NULL name");
//
// search the currently loaded models
//
for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
if (!strcmp (mod->name, name) )
break;
if (i == mod_numknown)
{
if (mod_numknown == MAX_MOD_KNOWN)
Sys_Error ("mod_numknown == MAX_MOD_KNOWN");
strcpy (mod->name, name);
mod->needload = true;
mod_numknown++;
}
 
return mod;
}
 
/*
==================
Mod_TouchModel
 
==================
*/
void Mod_TouchModel (char *name)
{
model_t *mod;
mod = Mod_FindName (name);
if (!mod->needload)
{
if (mod->type == mod_alias)
Cache_Check (&mod->cache);
}
}
 
/*
==================
Mod_LoadModel
 
Loads a model into the cache
==================
*/
model_t *Mod_LoadModel (model_t *mod, qboolean crash)
{
void *d;
unsigned *buf;
byte stackbuf[1024]; // avoid dirtying the cache heap
 
if (!mod->needload)
{
if (mod->type == mod_alias)
{
d = Cache_Check (&mod->cache);
if (d)
return mod;
}
else
return mod; // not cached at all
}
 
//
// because the world is so huge, load it one piece at a time
//
if (!crash)
{
}
//
// load the file
//
buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf));
if (!buf)
{
if (crash)
Sys_Error ("Mod_NumForName: %s not found", mod->name);
return NULL;
}
//
// allocate a new model
//
COM_FileBase (mod->name, loadname);
loadmodel = mod;
 
//
// fill it in
//
 
// call the apropriate loader
mod->needload = false;
switch (LittleLong(*(unsigned *)buf))
{
case IDPOLYHEADER:
Mod_LoadAliasModel (mod, buf);
break;
case IDSPRITEHEADER:
Mod_LoadSpriteModel (mod, buf);
break;
default:
Mod_LoadBrushModel (mod, buf);
break;
}
 
return mod;
}
 
/*
==================
Mod_ForName
 
Loads in a model for the given name
==================
*/
model_t *Mod_ForName (char *name, qboolean crash)
{
model_t *mod;
mod = Mod_FindName (name);
return Mod_LoadModel (mod, crash);
}
 
 
/*
===============================================================================
 
BRUSHMODEL LOADING
 
===============================================================================
*/
 
byte *mod_base;
 
 
/*
=================
Mod_LoadTextures
=================
*/
void Mod_LoadTextures (lump_t *l)
{
int i, j, pixels, num, max, altmax;
miptex_t *mt;
texture_t *tx, *tx2;
texture_t *anims[10];
texture_t *altanims[10];
dmiptexlump_t *m;
 
if (!l->filelen)
{
loadmodel->textures = NULL;
return;
}
m = (dmiptexlump_t *)(mod_base + l->fileofs);
m->nummiptex = LittleLong (m->nummiptex);
loadmodel->numtextures = m->nummiptex;
loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures) , loadname);
 
for (i=0 ; i<m->nummiptex ; i++)
{
m->dataofs[i] = LittleLong(m->dataofs[i]);
if (m->dataofs[i] == -1)
continue;
mt = (miptex_t *)((byte *)m + m->dataofs[i]);
mt->width = LittleLong (mt->width);
mt->height = LittleLong (mt->height);
for (j=0 ; j<MIPLEVELS ; j++)
mt->offsets[j] = LittleLong (mt->offsets[j]);
if ( (mt->width & 15) || (mt->height & 15) )
Sys_Error ("Texture %s is not 16 aligned", mt->name);
pixels = mt->width*mt->height/64*85;
tx = Hunk_AllocName (sizeof(texture_t) +pixels, loadname );
loadmodel->textures[i] = tx;
 
memcpy (tx->name, mt->name, sizeof(tx->name));
tx->width = mt->width;
tx->height = mt->height;
for (j=0 ; j<MIPLEVELS ; j++)
tx->offsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t);
// the pixels immediately follow the structures
memcpy ( tx+1, mt+1, pixels);
 
if (!Q_strncmp(mt->name,"sky",3))
R_InitSky (tx);
else
{
texture_mode = GL_LINEAR_MIPMAP_NEAREST; //_LINEAR;
tx->gl_texturenum = GL_LoadTexture (mt->name, tx->width, tx->height, (byte *)(tx+1), true, false);
texture_mode = GL_LINEAR;
}
}
 
//
// sequence the animations
//
for (i=0 ; i<m->nummiptex ; i++)
{
tx = loadmodel->textures[i];
if (!tx || tx->name[0] != '+')
continue;
if (tx->anim_next)
continue; // allready sequenced
 
// find the number of frames in the animation
memset (anims, 0, sizeof(anims));
memset (altanims, 0, sizeof(altanims));
 
max = tx->name[1];
altmax = 0;
if (max >= 'a' && max <= 'z')
max -= 'a' - 'A';
if (max >= '0' && max <= '9')
{
max -= '0';
altmax = 0;
anims[max] = tx;
max++;
}
else if (max >= 'A' && max <= 'J')
{
altmax = max - 'A';
max = 0;
altanims[altmax] = tx;
altmax++;
}
else
Sys_Error ("Bad animating texture %s", tx->name);
 
for (j=i+1 ; j<m->nummiptex ; j++)
{
tx2 = loadmodel->textures[j];
if (!tx2 || tx2->name[0] != '+')
continue;
if (strcmp (tx2->name+2, tx->name+2))
continue;
 
num = tx2->name[1];
if (num >= 'a' && num <= 'z')
num -= 'a' - 'A';
if (num >= '0' && num <= '9')
{
num -= '0';
anims[num] = tx2;
if (num+1 > max)
max = num + 1;
}
else if (num >= 'A' && num <= 'J')
{
num = num - 'A';
altanims[num] = tx2;
if (num+1 > altmax)
altmax = num+1;
}
else
Sys_Error ("Bad animating texture %s", tx->name);
}
#define ANIM_CYCLE 2
// link them all together
for (j=0 ; j<max ; j++)
{
tx2 = anims[j];
if (!tx2)
Sys_Error ("Missing frame %i of %s",j, tx->name);
tx2->anim_total = max * ANIM_CYCLE;
tx2->anim_min = j * ANIM_CYCLE;
tx2->anim_max = (j+1) * ANIM_CYCLE;
tx2->anim_next = anims[ (j+1)%max ];
if (altmax)
tx2->alternate_anims = altanims[0];
}
for (j=0 ; j<altmax ; j++)
{
tx2 = altanims[j];
if (!tx2)
Sys_Error ("Missing frame %i of %s",j, tx->name);
tx2->anim_total = altmax * ANIM_CYCLE;
tx2->anim_min = j * ANIM_CYCLE;
tx2->anim_max = (j+1) * ANIM_CYCLE;
tx2->anim_next = altanims[ (j+1)%altmax ];
if (max)
tx2->alternate_anims = anims[0];
}
}
}
 
/*
=================
Mod_LoadLighting
=================
*/
void Mod_LoadLighting (lump_t *l)
{
if (!l->filelen)
{
loadmodel->lightdata = NULL;
return;
}
loadmodel->lightdata = Hunk_AllocName ( l->filelen, loadname);
memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
}
 
 
/*
=================
Mod_LoadVisibility
=================
*/
void Mod_LoadVisibility (lump_t *l)
{
if (!l->filelen)
{
loadmodel->visdata = NULL;
return;
}
loadmodel->visdata = Hunk_AllocName ( l->filelen, loadname);
memcpy (loadmodel->visdata, mod_base + l->fileofs, l->filelen);
}
 
 
/*
=================
Mod_LoadEntities
=================
*/
void Mod_LoadEntities (lump_t *l)
{
if (!l->filelen)
{
loadmodel->entities = NULL;
return;
}
loadmodel->entities = Hunk_AllocName ( l->filelen, loadname);
memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen);
}
 
 
/*
=================
Mod_LoadVertexes
=================
*/
void Mod_LoadVertexes (lump_t *l)
{
dvertex_t *in;
mvertex_t *out;
int i, count;
 
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
 
loadmodel->vertexes = out;
loadmodel->numvertexes = count;
 
for ( i=0 ; i<count ; i++, in++, out++)
{
out->position[0] = LittleFloat (in->point[0]);
out->position[1] = LittleFloat (in->point[1]);
out->position[2] = LittleFloat (in->point[2]);
}
}
 
/*
=================
Mod_LoadSubmodels
=================
*/
void Mod_LoadSubmodels (lump_t *l)
{
dmodel_t *in;
dmodel_t *out;
int i, j, count;
 
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
 
loadmodel->submodels = out;
loadmodel->numsubmodels = count;
 
for ( i=0 ; i<count ; i++, in++, out++)
{
for (j=0 ; j<3 ; j++)
{ // spread the mins / maxs by a pixel
out->mins[j] = LittleFloat (in->mins[j]) - 1;
out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
out->origin[j] = LittleFloat (in->origin[j]);
}
for (j=0 ; j<MAX_MAP_HULLS ; j++)
out->headnode[j] = LittleLong (in->headnode[j]);
out->visleafs = LittleLong (in->visleafs);
out->firstface = LittleLong (in->firstface);
out->numfaces = LittleLong (in->numfaces);
}
}
 
/*
=================
Mod_LoadEdges
=================
*/
void Mod_LoadEdges (lump_t *l)
{
dedge_t *in;
medge_t *out;
int i, count;
 
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname);
 
loadmodel->edges = out;
loadmodel->numedges = count;
 
for ( i=0 ; i<count ; i++, in++, out++)
{
out->v[0] = (unsigned short)LittleShort(in->v[0]);
out->v[1] = (unsigned short)LittleShort(in->v[1]);
}
}
 
/*
=================
Mod_LoadTexinfo
=================
*/
void Mod_LoadTexinfo (lump_t *l)
{
texinfo_t *in;
mtexinfo_t *out;
int i, j, count;
int miptex;
float len1, len2;
 
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
 
loadmodel->texinfo = out;
loadmodel->numtexinfo = count;
 
for ( i=0 ; i<count ; i++, in++, out++)
{
for (j=0 ; j<8 ; j++)
out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
len1 = Length (out->vecs[0]);
len2 = Length (out->vecs[1]);
len1 = (len1 + len2)/2;
if (len1 < 0.32)
out->mipadjust = 4;
else if (len1 < 0.49)
out->mipadjust = 3;
else if (len1 < 0.99)
out->mipadjust = 2;
else
out->mipadjust = 1;
#if 0
if (len1 + len2 < 0.001)
out->mipadjust = 1; // don't crash
else
out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 );
#endif
 
miptex = LittleLong (in->miptex);
out->flags = LittleLong (in->flags);
if (!loadmodel->textures)
{
out->texture = r_notexture_mip; // checkerboard texture
out->flags = 0;
}
else
{
if (miptex >= loadmodel->numtextures)
Sys_Error ("miptex >= loadmodel->numtextures");
out->texture = loadmodel->textures[miptex];
if (!out->texture)
{
out->texture = r_notexture_mip; // texture not found
out->flags = 0;
}
}
}
}
 
/*
================
CalcSurfaceExtents
 
Fills in s->texturemins[] and s->extents[]
================
*/
void CalcSurfaceExtents (msurface_t *s)
{
float mins[2], maxs[2], val;
int i,j, e;
mvertex_t *v;
mtexinfo_t *tex;
int bmins[2], bmaxs[2];
 
mins[0] = mins[1] = 999999;
maxs[0] = maxs[1] = -99999;
 
tex = s->texinfo;
for (i=0 ; i<s->numedges ; i++)
{
e = loadmodel->surfedges[s->firstedge+i];
if (e >= 0)
v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
else
v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
for (j=0 ; j<2 ; j++)
{
val = v->position[0] * tex->vecs[j][0] +
v->position[1] * tex->vecs[j][1] +
v->position[2] * tex->vecs[j][2] +
tex->vecs[j][3];
if (val < mins[j])
mins[j] = val;
if (val > maxs[j])
maxs[j] = val;
}
}
 
for (i=0 ; i<2 ; i++)
{
bmins[i] = floor(mins[i]/16);
bmaxs[i] = ceil(maxs[i]/16);
 
s->texturemins[i] = bmins[i] * 16;
s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 512 /* 256 */ )
Sys_Error ("Bad surface extents");
}
}
 
 
/*
=================
Mod_LoadFaces
=================
*/
void Mod_LoadFaces (lump_t *l)
{
dface_t *in;
msurface_t *out;
int i, count, surfnum;
int planenum, side;
 
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
 
loadmodel->surfaces = out;
loadmodel->numsurfaces = count;
 
for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
{
out->firstedge = LittleLong(in->firstedge);
out->numedges = LittleShort(in->numedges);
out->flags = 0;
 
planenum = LittleShort(in->planenum);
side = LittleShort(in->side);
if (side)
out->flags |= SURF_PLANEBACK;
 
out->plane = loadmodel->planes + planenum;
 
out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo);
 
CalcSurfaceExtents (out);
// lighting info
 
for (i=0 ; i<MAXLIGHTMAPS ; i++)
out->styles[i] = in->styles[i];
i = LittleLong(in->lightofs);
if (i == -1)
out->samples = NULL;
else
out->samples = loadmodel->lightdata + i;
// set the drawing flags flag
if (!Q_strncmp(out->texinfo->texture->name,"sky",3)) // sky
{
out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED);
#ifndef QUAKE2
GL_SubdivideSurface (out); // cut up polygon for warps
#endif
continue;
}
if (!Q_strncmp(out->texinfo->texture->name,"*",1)) // turbulent
{
out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
for (i=0 ; i<2 ; i++)
{
out->extents[i] = 16384;
out->texturemins[i] = -8192;
}
GL_SubdivideSurface (out); // cut up polygon for warps
continue;
}
 
}
}
 
 
/*
=================
Mod_SetParent
=================
*/
void Mod_SetParent (mnode_t *node, mnode_t *parent)
{
node->parent = parent;
if (node->contents < 0)
return;
Mod_SetParent (node->children[0], node);
Mod_SetParent (node->children[1], node);
}
 
/*
=================
Mod_LoadNodes
=================
*/
void Mod_LoadNodes (lump_t *l)
{
int i, j, count, p;
dnode_t *in;
mnode_t *out;
 
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
 
loadmodel->nodes = out;
loadmodel->numnodes = count;
 
for ( i=0 ; i<count ; i++, in++, out++)
{
for (j=0 ; j<3 ; j++)
{
out->minmaxs[j] = LittleShort (in->mins[j]);
out->minmaxs[3+j] = LittleShort (in->maxs[j]);
}
p = LittleLong(in->planenum);
out->plane = loadmodel->planes + p;
 
out->firstsurface = LittleShort (in->firstface);
out->numsurfaces = LittleShort (in->numfaces);
for (j=0 ; j<2 ; j++)
{
p = LittleShort (in->children[j]);
if (p >= 0)
out->children[j] = loadmodel->nodes + p;
else
out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
}
}
Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs
}
 
/*
=================
Mod_LoadLeafs
=================
*/
void Mod_LoadLeafs (lump_t *l)
{
dleaf_t *in;
mleaf_t *out;
int i, j, count, p;
 
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
 
loadmodel->leafs = out;
loadmodel->numleafs = count;
 
for ( i=0 ; i<count ; i++, in++, out++)
{
for (j=0 ; j<3 ; j++)
{
out->minmaxs[j] = LittleShort (in->mins[j]);
out->minmaxs[3+j] = LittleShort (in->maxs[j]);
}
 
p = LittleLong(in->contents);
out->contents = p;
 
out->firstmarksurface = loadmodel->marksurfaces +
LittleShort(in->firstmarksurface);
out->nummarksurfaces = LittleShort(in->nummarksurfaces);
p = LittleLong(in->visofs);
if (p == -1)
out->compressed_vis = NULL;
else
out->compressed_vis = loadmodel->visdata + p;
out->efrags = NULL;
for (j=0 ; j<4 ; j++)
out->ambient_sound_level[j] = in->ambient_level[j];
 
// gl underwater warp
if (out->contents != CONTENTS_EMPTY)
{
for (j=0 ; j<out->nummarksurfaces ; j++)
out->firstmarksurface[j]->flags |= SURF_UNDERWATER;
}
}
}
 
/*
=================
Mod_LoadClipnodes
=================
*/
void Mod_LoadClipnodes (lump_t *l)
{
dclipnode_t *in, *out;
int i, count;
hull_t *hull;
 
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
 
loadmodel->clipnodes = out;
loadmodel->numclipnodes = count;
 
hull = &loadmodel->hulls[1];
hull->clipnodes = out;
hull->firstclipnode = 0;
hull->lastclipnode = count-1;
hull->planes = loadmodel->planes;
hull->clip_mins[0] = -16;
hull->clip_mins[1] = -16;
hull->clip_mins[2] = -24;
hull->clip_maxs[0] = 16;
hull->clip_maxs[1] = 16;
hull->clip_maxs[2] = 32;
 
hull = &loadmodel->hulls[2];
hull->clipnodes = out;
hull->firstclipnode = 0;
hull->lastclipnode = count-1;
hull->planes = loadmodel->planes;
hull->clip_mins[0] = -32;
hull->clip_mins[1] = -32;
hull->clip_mins[2] = -24;
hull->clip_maxs[0] = 32;
hull->clip_maxs[1] = 32;
hull->clip_maxs[2] = 64;
 
for (i=0 ; i<count ; i++, out++, in++)
{
out->planenum = LittleLong(in->planenum);
out->children[0] = LittleShort(in->children[0]);
out->children[1] = LittleShort(in->children[1]);
}
}
 
/*
=================
Mod_MakeHull0
 
Deplicate the drawing hull structure as a clipping hull
=================
*/
void Mod_MakeHull0 (void)
{
mnode_t *in, *child;
dclipnode_t *out;
int i, j, count;
hull_t *hull;
hull = &loadmodel->hulls[0];
in = loadmodel->nodes;
count = loadmodel->numnodes;
out = Hunk_AllocName ( count*sizeof(*out), loadname);
 
hull->clipnodes = out;
hull->firstclipnode = 0;
hull->lastclipnode = count-1;
hull->planes = loadmodel->planes;
 
for (i=0 ; i<count ; i++, out++, in++)
{
out->planenum = in->plane - loadmodel->planes;
for (j=0 ; j<2 ; j++)
{
child = in->children[j];
if (child->contents < 0)
out->children[j] = child->contents;
else
out->children[j] = child - loadmodel->nodes;
}
}
}
 
/*
=================
Mod_LoadMarksurfaces
=================
*/
void Mod_LoadMarksurfaces (lump_t *l)
{
int i, j, count;
short *in;
msurface_t **out;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
 
loadmodel->marksurfaces = out;
loadmodel->nummarksurfaces = count;
 
for ( i=0 ; i<count ; i++)
{
j = LittleShort(in[i]);
if (j >= loadmodel->numsurfaces)
Sys_Error ("Mod_ParseMarksurfaces: bad surface number");
out[i] = loadmodel->surfaces + j;
}
}
 
/*
=================
Mod_LoadSurfedges
=================
*/
void Mod_LoadSurfedges (lump_t *l)
{
int i, count;
int *in, *out;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
 
loadmodel->surfedges = out;
loadmodel->numsurfedges = count;
 
for ( i=0 ; i<count ; i++)
out[i] = LittleLong (in[i]);
}
 
 
/*
=================
Mod_LoadPlanes
=================
*/
void Mod_LoadPlanes (lump_t *l)
{
int i, j;
mplane_t *out;
dplane_t *in;
int count;
int bits;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*2*sizeof(*out), loadname);
loadmodel->planes = out;
loadmodel->numplanes = count;
 
for ( i=0 ; i<count ; i++, in++, out++)
{
bits = 0;
for (j=0 ; j<3 ; j++)
{
out->normal[j] = LittleFloat (in->normal[j]);
if (out->normal[j] < 0)
bits |= 1<<j;
}
 
out->dist = LittleFloat (in->dist);
out->type = LittleLong (in->type);
out->signbits = bits;
}
}
 
/*
=================
RadiusFromBounds
=================
*/
float RadiusFromBounds (vec3_t mins, vec3_t maxs)
{
int i;
vec3_t corner;
 
for (i=0 ; i<3 ; i++)
{
corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
}
 
return Length (corner);
}
 
/*
=================
Mod_LoadBrushModel
=================
*/
void Mod_LoadBrushModel (model_t *mod, void *buffer)
{
int i, j;
dheader_t *header;
dmodel_t *bm;
loadmodel->type = mod_brush;
header = (dheader_t *)buffer;
 
i = LittleLong (header->version);
if (i != BSPVERSION)
Sys_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION);
 
// swap all the lumps
mod_base = (byte *)header;
 
for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
((int *)header)[i] = LittleLong ( ((int *)header)[i]);
 
// load into heap
Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]);
Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
Mod_LoadFaces (&header->lumps[LUMP_FACES]);
Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]);
Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
Mod_LoadNodes (&header->lumps[LUMP_NODES]);
Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]);
Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
 
Mod_MakeHull0 ();
mod->numframes = 2; // regular and alternate animation
//
// set up the submodels (FIXME: this is confusing)
//
for (i=0 ; i<mod->numsubmodels ; i++)
{
bm = &mod->submodels[i];
 
mod->hulls[0].firstclipnode = bm->headnode[0];
for (j=1 ; j<MAX_MAP_HULLS ; j++)
{
mod->hulls[j].firstclipnode = bm->headnode[j];
mod->hulls[j].lastclipnode = mod->numclipnodes-1;
}
mod->firstmodelsurface = bm->firstface;
mod->nummodelsurfaces = bm->numfaces;
VectorCopy (bm->maxs, mod->maxs);
VectorCopy (bm->mins, mod->mins);
 
mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
 
mod->numleafs = bm->visleafs;
 
if (i < mod->numsubmodels-1)
{ // duplicate the basic information
char name[10];
 
sprintf (name, "*%i", i+1);
loadmodel = Mod_FindName (name);
*loadmodel = *mod;
strcpy (loadmodel->name, name);
mod = loadmodel;
}
}
}
 
/*
==============================================================================
 
ALIAS MODELS
 
==============================================================================
*/
 
aliashdr_t *pheader;
 
stvert_t stverts[MAXALIASVERTS];
mtriangle_t triangles[MAXALIASTRIS];
 
// a pose is a single set of vertexes. a frame may be
// an animating sequence of poses
trivertx_t *poseverts[MAXALIASFRAMES];
int posenum;
 
byte **player_8bit_texels_tbl;
byte *player_8bit_texels;
 
/*
=================
Mod_LoadAliasFrame
=================
*/
void * Mod_LoadAliasFrame (void * pin, maliasframedesc_t *frame)
{
trivertx_t *pframe, *pinframe;
int i, j;
daliasframe_t *pdaliasframe;
pdaliasframe = (daliasframe_t *)pin;
 
strcpy (frame->name, pdaliasframe->name);
frame->firstpose = posenum;
frame->numposes = 1;
 
for (i=0 ; i<3 ; i++)
{
// these are byte values, so we don't have to worry about
// endianness
frame->bboxmin.v[i] = pdaliasframe->bboxmin.v[i];
frame->bboxmin.v[i] = pdaliasframe->bboxmax.v[i];
}
 
pinframe = (trivertx_t *)(pdaliasframe + 1);
 
poseverts[posenum] = pinframe;
posenum++;
 
pinframe += pheader->numverts;
 
return (void *)pinframe;
}
 
 
/*
=================
Mod_LoadAliasGroup
=================
*/
void *Mod_LoadAliasGroup (void * pin, maliasframedesc_t *frame)
{
daliasgroup_t *pingroup;
int i, numframes;
daliasinterval_t *pin_intervals;
void *ptemp;
pingroup = (daliasgroup_t *)pin;
 
numframes = LittleLong (pingroup->numframes);
 
frame->firstpose = posenum;
frame->numposes = numframes;
 
for (i=0 ; i<3 ; i++)
{
// these are byte values, so we don't have to worry about endianness
frame->bboxmin.v[i] = pingroup->bboxmin.v[i];
frame->bboxmin.v[i] = pingroup->bboxmax.v[i];
}
 
pin_intervals = (daliasinterval_t *)(pingroup + 1);
 
frame->interval = LittleFloat (pin_intervals->interval);
 
pin_intervals += numframes;
 
ptemp = (void *)pin_intervals;
 
for (i=0 ; i<numframes ; i++)
{
poseverts[posenum] = (trivertx_t *)((daliasframe_t *)ptemp + 1);
posenum++;
 
ptemp = (trivertx_t *)((daliasframe_t *)ptemp + 1) + pheader->numverts;
}
 
return ptemp;
}
 
//=========================================================
 
/*
=================
Mod_FloodFillSkin
 
Fill background pixels so mipmapping doesn't have haloes - Ed
=================
*/
 
typedef struct
{
short x, y;
} floodfill_t;
 
extern unsigned d_8to24table[];
 
// must be a power of 2
#define FLOODFILL_FIFO_SIZE 0x1000
#define FLOODFILL_FIFO_MASK (FLOODFILL_FIFO_SIZE - 1)
 
#define FLOODFILL_STEP( off, dx, dy ) \
{ \
if (pos[off] == fillcolor) \
{ \
pos[off] = 255; \
fifo[inpt].x = x + (dx), fifo[inpt].y = y + (dy); \
inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; \
} \
else if (pos[off] != 255) fdc = pos[off]; \
}
 
void Mod_FloodFillSkin( byte *skin, int skinwidth, int skinheight )
{
byte fillcolor = *skin; // assume this is the pixel to fill
floodfill_t fifo[FLOODFILL_FIFO_SIZE];
int inpt = 0, outpt = 0;
int filledcolor = -1;
int i;
 
if (filledcolor == -1)
{
filledcolor = 0;
// attempt to find opaque black
for (i = 0; i < 256; ++i)
if (d_8to24table[i] == (255 << 0)) // alpha 1.0
{
filledcolor = i;
break;
}
}
 
// can't fill to filled color or to transparent color (used as visited marker)
if ((fillcolor == filledcolor) || (fillcolor == 255))
{
//printf( "not filling skin from %d to %d\n", fillcolor, filledcolor );
return;
}
 
fifo[inpt].x = 0, fifo[inpt].y = 0;
inpt = (inpt + 1) & FLOODFILL_FIFO_MASK;
 
while (outpt != inpt)
{
int x = fifo[outpt].x, y = fifo[outpt].y;
int fdc = filledcolor;
byte *pos = &skin[x + skinwidth * y];
 
outpt = (outpt + 1) & FLOODFILL_FIFO_MASK;
 
if (x > 0) FLOODFILL_STEP( -1, -1, 0 );
if (x < skinwidth - 1) FLOODFILL_STEP( 1, 1, 0 );
if (y > 0) FLOODFILL_STEP( -skinwidth, 0, -1 );
if (y < skinheight - 1) FLOODFILL_STEP( skinwidth, 0, 1 );
skin[x + skinwidth * y] = fdc;
}
}
 
/*
===============
Mod_LoadAllSkins
===============
*/
void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype)
{
int i, j, k;
char name[32];
int s;
byte *copy;
byte *skin;
byte *texels;
daliasskingroup_t *pinskingroup;
int groupskins;
daliasskininterval_t *pinskinintervals;
skin = (byte *)(pskintype + 1);
 
if (numskins < 1 || numskins > MAX_SKINS)
Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins);
 
s = pheader->skinwidth * pheader->skinheight;
 
for (i=0 ; i<numskins ; i++)
{
if (pskintype->type == ALIAS_SKIN_SINGLE) {
Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
 
// save 8 bit texels for the player model to remap
// if (!strcmp(loadmodel->name,"progs/player.mdl")) {
texels = Hunk_AllocName(s, loadname);
pheader->texels[i] = texels - (byte *)pheader;
memcpy (texels, (byte *)(pskintype + 1), s);
// }
sprintf (name, "%s_%i", loadmodel->name, i);
pheader->gl_texturenum[i][0] =
pheader->gl_texturenum[i][1] =
pheader->gl_texturenum[i][2] =
pheader->gl_texturenum[i][3] =
GL_LoadTexture (name, pheader->skinwidth,
pheader->skinheight, (byte *)(pskintype + 1), true, false);
pskintype = (daliasskintype_t *)((byte *)(pskintype+1) + s);
} else {
// animating skin group. yuck.
pskintype++;
pinskingroup = (daliasskingroup_t *)pskintype;
groupskins = LittleLong (pinskingroup->numskins);
pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
 
pskintype = (void *)(pinskinintervals + groupskins);
 
for (j=0 ; j<groupskins ; j++)
{
Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
if (j == 0) {
texels = Hunk_AllocName(s, loadname);
pheader->texels[i] = texels - (byte *)pheader;
memcpy (texels, (byte *)(pskintype), s);
}
sprintf (name, "%s_%i_%i", loadmodel->name, i,j);
pheader->gl_texturenum[i][j&3] =
GL_LoadTexture (name, pheader->skinwidth,
pheader->skinheight, (byte *)(pskintype), true, false);
pskintype = (daliasskintype_t *)((byte *)(pskintype) + s);
}
k = j;
for (/* */; j < 4; j++)
pheader->gl_texturenum[i][j&3] =
pheader->gl_texturenum[i][j - k];
}
}
 
return (void *)pskintype;
}
 
//=========================================================================
 
/*
=================
Mod_LoadAliasModel
=================
*/
void Mod_LoadAliasModel (model_t *mod, void *buffer)
{
int i, j;
mdl_t *pinmodel;
stvert_t *pinstverts;
dtriangle_t *pintriangles;
int version, numframes, numskins;
int size;
daliasframetype_t *pframetype;
daliasskintype_t *pskintype;
int start, end, total;
start = Hunk_LowMark ();
 
pinmodel = (mdl_t *)buffer;
 
version = LittleLong (pinmodel->version);
if (version != ALIAS_VERSION)
Sys_Error ("%s has wrong version number (%i should be %i)",
mod->name, version, ALIAS_VERSION);
 
//
// allocate space for a working header, plus all the data except the frames,
// skin and group info
//
size = sizeof (aliashdr_t)
+ (LittleLong (pinmodel->numframes) - 1) *
sizeof (pheader->frames[0]);
pheader = Hunk_AllocName (size, loadname);
mod->flags = LittleLong (pinmodel->flags);
 
//
// endian-adjust and copy the data, starting with the alias model header
//
pheader->boundingradius = LittleFloat (pinmodel->boundingradius);
pheader->numskins = LittleLong (pinmodel->numskins);
pheader->skinwidth = LittleLong (pinmodel->skinwidth);
pheader->skinheight = LittleLong (pinmodel->skinheight);
 
if (pheader->skinheight > MAX_LBM_HEIGHT)
Sys_Error ("model %s has a skin taller than %d", mod->name,
MAX_LBM_HEIGHT);
 
pheader->numverts = LittleLong (pinmodel->numverts);
 
if (pheader->numverts <= 0)
Sys_Error ("model %s has no vertices", mod->name);
 
if (pheader->numverts > MAXALIASVERTS)
Sys_Error ("model %s has too many vertices", mod->name);
 
pheader->numtris = LittleLong (pinmodel->numtris);
 
if (pheader->numtris <= 0)
Sys_Error ("model %s has no triangles", mod->name);
 
pheader->numframes = LittleLong (pinmodel->numframes);
numframes = pheader->numframes;
if (numframes < 1)
Sys_Error ("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes);
 
pheader->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO;
mod->synctype = LittleLong (pinmodel->synctype);
mod->numframes = pheader->numframes;
 
for (i=0 ; i<3 ; i++)
{
pheader->scale[i] = LittleFloat (pinmodel->scale[i]);
pheader->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]);
pheader->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]);
}
 
 
//
// load the skins
//
pskintype = (daliasskintype_t *)&pinmodel[1];
pskintype = Mod_LoadAllSkins (pheader->numskins, pskintype);
 
//
// load base s and t vertices
//
pinstverts = (stvert_t *)pskintype;
 
for (i=0 ; i<pheader->numverts ; i++)
{
stverts[i].onseam = LittleLong (pinstverts[i].onseam);
stverts[i].s = LittleLong (pinstverts[i].s);
stverts[i].t = LittleLong (pinstverts[i].t);
}
 
//
// load triangle lists
//
pintriangles = (dtriangle_t *)&pinstverts[pheader->numverts];
 
for (i=0 ; i<pheader->numtris ; i++)
{
triangles[i].facesfront = LittleLong (pintriangles[i].facesfront);
 
for (j=0 ; j<3 ; j++)
{
triangles[i].vertindex[j] =
LittleLong (pintriangles[i].vertindex[j]);
}
}
 
//
// load the frames
//
posenum = 0;
pframetype = (daliasframetype_t *)&pintriangles[pheader->numtris];
 
for (i=0 ; i<numframes ; i++)
{
aliasframetype_t frametype;
 
frametype = LittleLong (pframetype->type);
 
if (frametype == ALIAS_SINGLE)
{
pframetype = (daliasframetype_t *)
Mod_LoadAliasFrame (pframetype + 1, &pheader->frames[i]);
}
else
{
pframetype = (daliasframetype_t *)
Mod_LoadAliasGroup (pframetype + 1, &pheader->frames[i]);
}
}
 
pheader->numposes = posenum;
 
mod->type = mod_alias;
 
// FIXME: do this right
mod->mins[0] = mod->mins[1] = mod->mins[2] = -16;
mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16;
 
//
// build the draw lists
//
GL_MakeAliasModelDisplayLists (mod, pheader);
 
//
// move the complete, relocatable alias model to the cache
//
end = Hunk_LowMark ();
total = end - start;
Cache_Alloc (&mod->cache, total, loadname);
if (!mod->cache.data)
return;
memcpy (mod->cache.data, pheader, total);
 
Hunk_FreeToLowMark (start);
}
 
//=============================================================================
 
/*
=================
Mod_LoadSpriteFrame
=================
*/
void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum)
{
dspriteframe_t *pinframe;
mspriteframe_t *pspriteframe;
int i, width, height, size, origin[2];
unsigned short *ppixout;
byte *ppixin;
char name[64];
 
pinframe = (dspriteframe_t *)pin;
 
width = LittleLong (pinframe->width);
height = LittleLong (pinframe->height);
size = width * height;
 
pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t),loadname);
 
Q_memset (pspriteframe, 0, sizeof (mspriteframe_t));
 
*ppframe = pspriteframe;
 
pspriteframe->width = width;
pspriteframe->height = height;
origin[0] = LittleLong (pinframe->origin[0]);
origin[1] = LittleLong (pinframe->origin[1]);
 
pspriteframe->up = origin[1];
pspriteframe->down = origin[1] - height;
pspriteframe->left = origin[0];
pspriteframe->right = width + origin[0];
 
sprintf (name, "%s_%i", loadmodel->name, framenum);
pspriteframe->gl_texturenum = GL_LoadTexture (name, width, height, (byte *)(pinframe + 1), true, true);
 
return (void *)((byte *)pinframe + sizeof (dspriteframe_t) + size);
}
 
 
/*
=================
Mod_LoadSpriteGroup
=================
*/
void * Mod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe, int framenum)
{
dspritegroup_t *pingroup;
mspritegroup_t *pspritegroup;
int i, numframes;
dspriteinterval_t *pin_intervals;
float *poutintervals;
void *ptemp;
 
pingroup = (dspritegroup_t *)pin;
 
numframes = LittleLong (pingroup->numframes);
 
pspritegroup = Hunk_AllocName (sizeof (mspritegroup_t) +
(numframes - 1) * sizeof (pspritegroup->frames[0]), loadname);
 
pspritegroup->numframes = numframes;
 
*ppframe = (mspriteframe_t *)pspritegroup;
 
pin_intervals = (dspriteinterval_t *)(pingroup + 1);
 
poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname);
 
pspritegroup->intervals = poutintervals;
 
for (i=0 ; i<numframes ; i++)
{
*poutintervals = LittleFloat (pin_intervals->interval);
if (*poutintervals <= 0.0)
Sys_Error ("Mod_LoadSpriteGroup: interval<=0");
 
poutintervals++;
pin_intervals++;
}
 
ptemp = (void *)pin_intervals;
 
for (i=0 ; i<numframes ; i++)
{
ptemp = Mod_LoadSpriteFrame (ptemp, &pspritegroup->frames[i], framenum * 100 + i);
}
 
return ptemp;
}
 
 
/*
=================
Mod_LoadSpriteModel
=================
*/
void Mod_LoadSpriteModel (model_t *mod, void *buffer)
{
int i;
int version;
dsprite_t *pin;
msprite_t *psprite;
int numframes;
int size;
dspriteframetype_t *pframetype;
pin = (dsprite_t *)buffer;
 
version = LittleLong (pin->version);
if (version != SPRITE_VERSION)
Sys_Error ("%s has wrong version number "
"(%i should be %i)", mod->name, version, SPRITE_VERSION);
 
numframes = LittleLong (pin->numframes);
 
size = sizeof (msprite_t) + (numframes - 1) * sizeof (psprite->frames);
 
psprite = Hunk_AllocName (size, loadname);
 
mod->cache.data = psprite;
 
psprite->type = LittleLong (pin->type);
psprite->maxwidth = LittleLong (pin->width);
psprite->maxheight = LittleLong (pin->height);
psprite->beamlength = LittleFloat (pin->beamlength);
mod->synctype = LittleLong (pin->synctype);
psprite->numframes = numframes;
 
mod->mins[0] = mod->mins[1] = -psprite->maxwidth/2;
mod->maxs[0] = mod->maxs[1] = psprite->maxwidth/2;
mod->mins[2] = -psprite->maxheight/2;
mod->maxs[2] = psprite->maxheight/2;
//
// load the frames
//
if (numframes < 1)
Sys_Error ("Mod_LoadSpriteModel: Invalid # of frames: %d\n", numframes);
 
mod->numframes = numframes;
 
pframetype = (dspriteframetype_t *)(pin + 1);
 
for (i=0 ; i<numframes ; i++)
{
spriteframetype_t frametype;
 
frametype = LittleLong (pframetype->type);
psprite->frames[i].type = frametype;
 
if (frametype == SPR_SINGLE)
{
pframetype = (dspriteframetype_t *)
Mod_LoadSpriteFrame (pframetype + 1,
&psprite->frames[i].frameptr, i);
}
else
{
pframetype = (dspriteframetype_t *)
Mod_LoadSpriteGroup (pframetype + 1,
&psprite->frames[i].frameptr, i);
}
}
 
mod->type = mod_sprite;
}
 
//=============================================================================
 
/*
================
Mod_Print
================
*/
void Mod_Print (void)
{
int i;
model_t *mod;
 
Con_Printf ("Cached models:\n");
for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++)
{
Con_Printf ("%8p : %s\n",mod->cache.data, mod->name);
}
}
 
 
/contrib/other/sdlquake-1.0.9/gl_model.h
0,0 → 1,430
/*
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;
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;
// lighting info
int dlightframe;
int dlightbits;
 
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]
} 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
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__
/contrib/other/sdlquake-1.0.9/gl_refrag.c
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);
}
}
}
 
 
/contrib/other/sdlquake-1.0.9/gl_rlight.c
0,0 → 1,354
/*
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
 
=============================================================================
*/
 
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;
}
 
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 ();
}
 
/*
=============
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);
}
 
 
/*
=============================================================================
 
DYNAMIC LIGHTS
 
=============================================================================
*/
 
/*
=============
R_MarkLights
=============
*/
void R_MarkLights (dlight_t *light, int bit, mnode_t *node)
{
mplane_t *splitplane;
float dist;
msurface_t *surf;
int i;
if (node->contents < 0)
return;
 
splitplane = node->plane;
dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist;
if (dist > light->radius)
{
R_MarkLights (light, bit, node->children[0]);
return;
}
if (dist < -light->radius)
{
R_MarkLights (light, bit, node->children[1]);
return;
}
// mark the polygons
surf = cl.worldmodel->surfaces + node->firstsurface;
for (i=0 ; i<node->numsurfaces ; i++, surf++)
{
if (surf->dlightframe != r_dlightframecount)
{
surf->dlightbits = 0;
surf->dlightframe = r_dlightframecount;
}
surf->dlightbits |= bit;
}
 
R_MarkLights (light, bit, node->children[0]);
R_MarkLights (light, bit, node->children[1]);
}
 
 
/*
=============
R_PushDlights
=============
*/
void R_PushDlights (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
l = cl_dlights;
 
for (i=0 ; i<MAX_DLIGHTS ; i++, l++)
{
if (l->die < cl.time || !l->radius)
continue;
R_MarkLights ( l, 1<<i, cl.worldmodel->nodes );
}
}
 
 
/*
=============================================================================
 
LIGHT SAMPLING
 
=============================================================================
*/
 
mplane_t *lightplane;
vec3_t lightspot;
 
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);
}
 
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;
}
 
/contrib/other/sdlquake-1.0.9/gl_rmain.c
0,0 → 1,1159
/*
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_main.c
 
#include "quakedef.h"
 
entity_t r_worldentity;
 
qboolean r_cache_thrash; // compatability
 
vec3_t modelorg, r_entorigin;
entity_t *currententity;
 
int r_visframecount; // bumped when going to a new PVS
int r_framecount; // used for dlight push checking
 
mplane_t frustum[4];
 
int c_brush_polys, c_alias_polys;
 
qboolean envmap; // true during envmap command capture
 
int currenttexture = -1; // to avoid unnecessary texture sets
 
int cnttextures[2] = {-1, -1}; // cached
 
int particletexture; // little dot for particles
int playertextures; // up to 16 color translated skins
 
int mirrortexturenum; // quake texturenum, not gltexturenum
qboolean mirror;
mplane_t *mirror_plane;
 
//
// view origin
//
vec3_t vup;
vec3_t vpn;
vec3_t vright;
vec3_t r_origin;
 
float r_world_matrix[16];
float r_base_world_matrix[16];
 
//
// screen size info
//
refdef_t r_refdef;
 
mleaf_t *r_viewleaf, *r_oldviewleaf;
 
texture_t *r_notexture_mip;
 
int d_lightstylevalue[256]; // 8.8 fraction of base light value
 
 
void R_MarkLeaves (void);
 
cvar_t r_norefresh = {"r_norefresh","0"};
cvar_t r_drawentities = {"r_drawentities","1"};
cvar_t r_drawviewmodel = {"r_drawviewmodel","1"};
cvar_t r_speeds = {"r_speeds","0"};
cvar_t r_fullbright = {"r_fullbright","0"};
cvar_t r_lightmap = {"r_lightmap","0"};
cvar_t r_shadows = {"r_shadows","0"};
cvar_t r_mirroralpha = {"r_mirroralpha","1"};
cvar_t r_wateralpha = {"r_wateralpha","1"};
cvar_t r_dynamic = {"r_dynamic","1"};
cvar_t r_novis = {"r_novis","0"};
 
cvar_t gl_finish = {"gl_finish","0"};
cvar_t gl_clear = {"gl_clear","0"};
cvar_t gl_cull = {"gl_cull","1"};
cvar_t gl_texsort = {"gl_texsort","1"};
cvar_t gl_smoothmodels = {"gl_smoothmodels","1"};
cvar_t gl_affinemodels = {"gl_affinemodels","0"};
cvar_t gl_polyblend = {"gl_polyblend","1"};
cvar_t gl_flashblend = {"gl_flashblend","1"};
cvar_t gl_playermip = {"gl_playermip","0"};
cvar_t gl_nocolors = {"gl_nocolors","0"};
cvar_t gl_keeptjunctions = {"gl_keeptjunctions","0"};
cvar_t gl_reporttjunctions = {"gl_reporttjunctions","0"};
cvar_t gl_doubleeyes = {"gl_doubleeys", "1"};
 
extern cvar_t gl_ztrick;
 
/*
=================
R_CullBox
 
Returns true if the box is completely outside the frustom
=================
*/
qboolean R_CullBox (vec3_t mins, vec3_t maxs)
{
int i;
 
for (i=0 ; i<4 ; i++)
if (BoxOnPlaneSide (mins, maxs, &frustum[i]) == 2)
return true;
return false;
}
 
 
void R_RotateForEntity (entity_t *e)
{
glTranslatef (e->origin[0], e->origin[1], e->origin[2]);
 
glRotatef (e->angles[1], 0, 0, 1);
glRotatef (-e->angles[0], 0, 1, 0);
glRotatef (e->angles[2], 1, 0, 0);
}
 
/*
=============================================================
 
SPRITE MODELS
 
=============================================================
*/
 
/*
================
R_GetSpriteFrame
================
*/
mspriteframe_t *R_GetSpriteFrame (entity_t *currententity)
{
msprite_t *psprite;
mspritegroup_t *pspritegroup;
mspriteframe_t *pspriteframe;
int i, numframes, frame;
float *pintervals, fullinterval, targettime, time;
 
psprite = currententity->model->cache.data;
frame = currententity->frame;
 
if ((frame >= psprite->numframes) || (frame < 0))
{
Con_Printf ("R_DrawSprite: no such frame %d\n", frame);
frame = 0;
}
 
if (psprite->frames[frame].type == SPR_SINGLE)
{
pspriteframe = psprite->frames[frame].frameptr;
}
else
{
pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
pintervals = pspritegroup->intervals;
numframes = pspritegroup->numframes;
fullinterval = pintervals[numframes-1];
 
time = cl.time + currententity->syncbase;
 
// when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
// are positive, so we don't have to worry about division by 0
targettime = time - ((int)(time / fullinterval)) * fullinterval;
 
for (i=0 ; i<(numframes-1) ; i++)
{
if (pintervals[i] > targettime)
break;
}
 
pspriteframe = pspritegroup->frames[i];
}
 
return pspriteframe;
}
 
 
/*
=================
R_DrawSpriteModel
 
=================
*/
void R_DrawSpriteModel (entity_t *e)
{
vec3_t point;
mspriteframe_t *frame;
float *up, *right;
vec3_t v_forward, v_right, v_up;
msprite_t *psprite;
 
// don't even bother culling, because it's just a single
// polygon without a surface cache
frame = R_GetSpriteFrame (e);
psprite = currententity->model->cache.data;
 
if (psprite->type == SPR_ORIENTED)
{ // bullet marks on walls
AngleVectors (currententity->angles, v_forward, v_right, v_up);
up = v_up;
right = v_right;
}
else
{ // normal sprite
up = vup;
right = vright;
}
 
glColor3f (1,1,1);
 
GL_DisableMultitexture();
 
GL_Bind(frame->gl_texturenum);
 
glEnable (GL_ALPHA_TEST);
glBegin (GL_QUADS);
 
glTexCoord2f (0, 1);
VectorMA (e->origin, frame->down, up, point);
VectorMA (point, frame->left, right, point);
glVertex3fv (point);
 
glTexCoord2f (0, 0);
VectorMA (e->origin, frame->up, up, point);
VectorMA (point, frame->left, right, point);
glVertex3fv (point);
 
glTexCoord2f (1, 0);
VectorMA (e->origin, frame->up, up, point);
VectorMA (point, frame->right, right, point);
glVertex3fv (point);
 
glTexCoord2f (1, 1);
VectorMA (e->origin, frame->down, up, point);
VectorMA (point, frame->right, right, point);
glVertex3fv (point);
glEnd ();
 
glDisable (GL_ALPHA_TEST);
}
 
/*
=============================================================
 
ALIAS MODELS
 
=============================================================
*/
 
 
#define NUMVERTEXNORMALS 162
 
float r_avertexnormals[NUMVERTEXNORMALS][3] = {
#include "anorms.h"
};
 
vec3_t shadevector;
float shadelight, ambientlight;
 
// precalculated dot products for quantized angles
#define SHADEDOT_QUANT 16
float r_avertexnormal_dots[SHADEDOT_QUANT][256] =
#include "anorm_dots.h"
;
 
float *shadedots = r_avertexnormal_dots[0];
 
int lastposenum;
 
/*
=============
GL_DrawAliasFrame
=============
*/
void GL_DrawAliasFrame (aliashdr_t *paliashdr, int posenum)
{
float s, t;
float l;
int i, j;
int index;
trivertx_t *v, *verts;
int list;
int *order;
vec3_t point;
float *normal;
int count;
 
lastposenum = posenum;
 
verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
verts += posenum * paliashdr->poseverts;
order = (int *)((byte *)paliashdr + paliashdr->commands);
 
while (1)
{
// get the vertex count and primitive type
count = *order++;
if (!count)
break; // done
if (count < 0)
{
count = -count;
glBegin (GL_TRIANGLE_FAN);
}
else
glBegin (GL_TRIANGLE_STRIP);
 
do
{
// texture coordinates come from the draw list
glTexCoord2f (((float *)order)[0], ((float *)order)[1]);
order += 2;
 
// normals and vertexes come from the frame list
l = shadedots[verts->lightnormalindex] * shadelight;
glColor3f (l, l, l);
glVertex3f (verts->v[0], verts->v[1], verts->v[2]);
verts++;
} while (--count);
 
glEnd ();
}
}
 
 
/*
=============
GL_DrawAliasShadow
=============
*/
extern vec3_t lightspot;
 
void GL_DrawAliasShadow (aliashdr_t *paliashdr, int posenum)
{
float s, t, l;
int i, j;
int index;
trivertx_t *v, *verts;
int list;
int *order;
vec3_t point;
float *normal;
float height, lheight;
int count;
 
lheight = currententity->origin[2] - lightspot[2];
 
height = 0;
verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
verts += posenum * paliashdr->poseverts;
order = (int *)((byte *)paliashdr + paliashdr->commands);
 
height = -lheight + 1.0;
 
while (1)
{
// get the vertex count and primitive type
count = *order++;
if (!count)
break; // done
if (count < 0)
{
count = -count;
glBegin (GL_TRIANGLE_FAN);
}
else
glBegin (GL_TRIANGLE_STRIP);
 
do
{
// texture coordinates come from the draw list
// (skipped for shadows) glTexCoord2fv ((float *)order);
order += 2;
 
// normals and vertexes come from the frame list
point[0] = verts->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0];
point[1] = verts->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1];
point[2] = verts->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2];
 
point[0] -= shadevector[0]*(point[2]+lheight);
point[1] -= shadevector[1]*(point[2]+lheight);
point[2] = height;
// height -= 0.001;
glVertex3fv (point);
 
verts++;
} while (--count);
 
glEnd ();
}
}
 
 
 
/*
=================
R_SetupAliasFrame
 
=================
*/
void R_SetupAliasFrame (int frame, aliashdr_t *paliashdr)
{
int pose, numposes;
float interval;
 
if ((frame >= paliashdr->numframes) || (frame < 0))
{
Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
frame = 0;
}
 
pose = paliashdr->frames[frame].firstpose;
numposes = paliashdr->frames[frame].numposes;
 
if (numposes > 1)
{
interval = paliashdr->frames[frame].interval;
pose += (int)(cl.time / interval) % numposes;
}
 
GL_DrawAliasFrame (paliashdr, pose);
}
 
 
 
/*
=================
R_DrawAliasModel
 
=================
*/
void R_DrawAliasModel (entity_t *e)
{
int i, j;
int lnum;
vec3_t dist;
float add;
model_t *clmodel;
vec3_t mins, maxs;
aliashdr_t *paliashdr;
trivertx_t *verts, *v;
int index;
float s, t, an;
int anim;
 
clmodel = currententity->model;
 
VectorAdd (currententity->origin, clmodel->mins, mins);
VectorAdd (currententity->origin, clmodel->maxs, maxs);
 
if (R_CullBox (mins, maxs))
return;
 
 
VectorCopy (currententity->origin, r_entorigin);
VectorSubtract (r_origin, r_entorigin, modelorg);
 
//
// get lighting information
//
 
ambientlight = shadelight = R_LightPoint (currententity->origin);
 
// allways give the gun some light
if (e == &cl.viewent && ambientlight < 24)
ambientlight = shadelight = 24;
 
for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
{
if (cl_dlights[lnum].die >= cl.time)
{
VectorSubtract (currententity->origin,
cl_dlights[lnum].origin,
dist);
add = cl_dlights[lnum].radius - Length(dist);
 
if (add > 0) {
ambientlight += add;
//ZOID models should be affected by dlights as well
shadelight += add;
}
}
}
 
// clamp lighting so it doesn't overbright as much
if (ambientlight > 128)
ambientlight = 128;
if (ambientlight + shadelight > 192)
shadelight = 192 - ambientlight;
 
// ZOID: never allow players to go totally black
i = currententity - cl_entities;
if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */)
if (ambientlight < 8)
ambientlight = shadelight = 8;
 
// HACK HACK HACK -- no fullbright colors, so make torches full light
if (!strcmp (clmodel->name, "progs/flame2.mdl")
|| !strcmp (clmodel->name, "progs/flame.mdl") )
ambientlight = shadelight = 256;
 
shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
shadelight = shadelight / 200.0;
an = e->angles[1]/180*M_PI;
shadevector[0] = cos(-an);
shadevector[1] = sin(-an);
shadevector[2] = 1;
VectorNormalize (shadevector);
 
//
// locate the proper data
//
paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model);
 
c_alias_polys += paliashdr->numtris;
 
//
// draw all the triangles
//
 
GL_DisableMultitexture();
 
glPushMatrix ();
R_RotateForEntity (e);
 
if (!strcmp (clmodel->name, "progs/eyes.mdl") && gl_doubleeyes.value) {
glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2] - (22 + 8));
// double size of eyes, since they are really hard to see in gl
glScalef (paliashdr->scale[0]*2, paliashdr->scale[1]*2, paliashdr->scale[2]*2);
} else {
glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]);
glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]);
}
 
anim = (int)(cl.time*10) & 3;
GL_Bind(paliashdr->gl_texturenum[currententity->skinnum][anim]);
 
// we can't dynamically colormap textures, so they are cached
// seperately for the players. Heads are just uncolored.
if (currententity->colormap != vid.colormap && !gl_nocolors.value)
{
i = currententity - cl_entities;
if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */)
GL_Bind(playertextures - 1 + i);
}
 
if (gl_smoothmodels.value)
glShadeModel (GL_SMOOTH);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 
if (gl_affinemodels.value)
glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
 
R_SetupAliasFrame (currententity->frame, paliashdr);
 
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 
glShadeModel (GL_FLAT);
if (gl_affinemodels.value)
glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
 
glPopMatrix ();
 
if (r_shadows.value)
{
glPushMatrix ();
R_RotateForEntity (e);
glDisable (GL_TEXTURE_2D);
glEnable (GL_BLEND);
glColor4f (0,0,0,0.5);
GL_DrawAliasShadow (paliashdr, lastposenum);
glEnable (GL_TEXTURE_2D);
glDisable (GL_BLEND);
glColor4f (1,1,1,1);
glPopMatrix ();
}
 
}
 
//==================================================================================
 
/*
=============
R_DrawEntitiesOnList
=============
*/
void R_DrawEntitiesOnList (void)
{
int i;
 
if (!r_drawentities.value)
return;
 
// draw sprites seperately, because of alpha blending
for (i=0 ; i<cl_numvisedicts ; i++)
{
currententity = cl_visedicts[i];
 
switch (currententity->model->type)
{
case mod_alias:
R_DrawAliasModel (currententity);
break;
 
case mod_brush:
R_DrawBrushModel (currententity);
break;
 
default:
break;
}
}
 
for (i=0 ; i<cl_numvisedicts ; i++)
{
currententity = cl_visedicts[i];
 
switch (currententity->model->type)
{
case mod_sprite:
R_DrawSpriteModel (currententity);
break;
}
}
}
 
/*
=============
R_DrawViewModel
=============
*/
void R_DrawViewModel (void)
{
float ambient[4], diffuse[4];
int j;
int lnum;
vec3_t dist;
float add;
dlight_t *dl;
int ambientlight, shadelight;
 
if (!r_drawviewmodel.value)
return;
 
if (chase_active.value)
return;
 
if (envmap)
return;
 
if (!r_drawentities.value)
return;
 
if (cl.items & IT_INVISIBILITY)
return;
 
if (cl.stats[STAT_HEALTH] <= 0)
return;
 
currententity = &cl.viewent;
if (!currententity->model)
return;
 
j = R_LightPoint (currententity->origin);
 
if (j < 24)
j = 24; // allways give some light on gun
ambientlight = j;
shadelight = j;
 
// add dynamic lights
for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
{
dl = &cl_dlights[lnum];
if (!dl->radius)
continue;
if (!dl->radius)
continue;
if (dl->die < cl.time)
continue;
 
VectorSubtract (currententity->origin, dl->origin, dist);
add = dl->radius - Length(dist);
if (add > 0)
ambientlight += add;
}
 
ambient[0] = ambient[1] = ambient[2] = ambient[3] = (float)ambientlight / 128;
diffuse[0] = diffuse[1] = diffuse[2] = diffuse[3] = (float)shadelight / 128;
 
// hack the depth range to prevent view model from poking into walls
glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
R_DrawAliasModel (currententity);
glDepthRange (gldepthmin, gldepthmax);
}
 
 
/*
============
R_PolyBlend
============
*/
void R_PolyBlend (void)
{
if (!gl_polyblend.value)
return;
if (!v_blend[3])
return;
 
GL_DisableMultitexture();
 
glDisable (GL_ALPHA_TEST);
glEnable (GL_BLEND);
glDisable (GL_DEPTH_TEST);
glDisable (GL_TEXTURE_2D);
 
glLoadIdentity ();
 
glRotatef (-90, 1, 0, 0); // put Z going up
glRotatef (90, 0, 0, 1); // put Z going up
 
glColor4fv (v_blend);
 
glBegin (GL_QUADS);
 
glVertex3f (10, 100, 100);
glVertex3f (10, -100, 100);
glVertex3f (10, -100, -100);
glVertex3f (10, 100, -100);
glEnd ();
 
glDisable (GL_BLEND);
glEnable (GL_TEXTURE_2D);
glEnable (GL_ALPHA_TEST);
}
 
 
int SignbitsForPlane (mplane_t *out)
{
int bits, j;
 
// for fast box on planeside test
 
bits = 0;
for (j=0 ; j<3 ; j++)
{
if (out->normal[j] < 0)
bits |= 1<<j;
}
return bits;
}
 
 
void R_SetFrustum (void)
{
int i;
 
if (r_refdef.fov_x == 90)
{
// front side is visible
 
VectorAdd (vpn, vright, frustum[0].normal);
VectorSubtract (vpn, vright, frustum[1].normal);
 
VectorAdd (vpn, vup, frustum[2].normal);
VectorSubtract (vpn, vup, frustum[3].normal);
}
else
{
// rotate VPN right by FOV_X/2 degrees
RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x / 2 ) );
// rotate VPN left by FOV_X/2 degrees
RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_refdef.fov_x / 2 );
// rotate VPN up by FOV_X/2 degrees
RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y / 2 );
// rotate VPN down by FOV_X/2 degrees
RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y / 2 ) );
}
 
for (i=0 ; i<4 ; i++)
{
frustum[i].type = PLANE_ANYZ;
frustum[i].dist = DotProduct (r_origin, frustum[i].normal);
frustum[i].signbits = SignbitsForPlane (&frustum[i]);
}
}
 
 
 
/*
===============
R_SetupFrame
===============
*/
void R_SetupFrame (void)
{
int edgecount;
vrect_t vrect;
float w, h;
 
// don't allow cheats in multiplayer
if (cl.maxclients > 1)
Cvar_Set ("r_fullbright", "0");
 
R_AnimateLight ();
 
r_framecount++;
 
// build the transformation matrix for the given view angles
VectorCopy (r_refdef.vieworg, r_origin);
 
AngleVectors (r_refdef.viewangles, vpn, vright, vup);
 
// current viewleaf
r_oldviewleaf = r_viewleaf;
r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel);
 
V_SetContentsColor (r_viewleaf->contents);
V_CalcBlend ();
 
r_cache_thrash = false;
 
c_brush_polys = 0;
c_alias_polys = 0;
 
}
 
 
void MYgluPerspective( GLdouble fovy, GLdouble aspect,
GLdouble zNear, GLdouble zFar )
{
GLdouble xmin, xmax, ymin, ymax;
 
ymax = zNear * tan( fovy * M_PI / 360.0 );
ymin = -ymax;
 
xmin = ymin * aspect;
xmax = ymax * aspect;
 
glFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
}
 
 
/*
=============
R_SetupGL
=============
*/
void R_SetupGL (void)
{
float screenaspect;
float yfov;
int i;
extern int glwidth, glheight;
int x, x2, y2, y, w, h;
 
//
// set up viewpoint
//
glMatrixMode(GL_PROJECTION);
glLoadIdentity ();
x = r_refdef.vrect.x * glwidth/vid.width;
x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/vid.width;
y = (vid.height-r_refdef.vrect.y) * glheight/vid.height;
y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * glheight/vid.height;
 
// fudge around because of frac screen scale
if (x > 0)
x--;
if (x2 < glwidth)
x2++;
if (y2 < 0)
y2--;
if (y < glheight)
y++;
 
w = x2 - x;
h = y - y2;
 
if (envmap)
{
x = y2 = 0;
w = h = 256;
}
 
glViewport (glx + x, gly + y2, w, h);
screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height;
// yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI;
MYgluPerspective (r_refdef.fov_y, screenaspect, 4, 4096);
 
if (mirror)
{
if (mirror_plane->normal[2])
glScalef (1, -1, 1);
else
glScalef (-1, 1, 1);
glCullFace(GL_BACK);
}
else
glCullFace(GL_FRONT);
 
glMatrixMode(GL_MODELVIEW);
glLoadIdentity ();
 
glRotatef (-90, 1, 0, 0); // put Z going up
glRotatef (90, 0, 0, 1); // put Z going up
glRotatef (-r_refdef.viewangles[2], 1, 0, 0);
glRotatef (-r_refdef.viewangles[0], 0, 1, 0);
glRotatef (-r_refdef.viewangles[1], 0, 0, 1);
glTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]);
 
glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
 
//
// set drawing parms
//
if (gl_cull.value)
glEnable(GL_CULL_FACE);
else
glDisable(GL_CULL_FACE);
 
glDisable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
glEnable(GL_DEPTH_TEST);
}
 
/*
================
R_RenderScene
 
r_refdef must be set before the first call
================
*/
void R_RenderScene (void)
{
R_SetupFrame ();
 
R_SetFrustum ();
 
R_SetupGL ();
 
R_MarkLeaves (); // done here so we know if we're in water
 
R_DrawWorld (); // adds static entities to the list
 
S_ExtraUpdate (); // don't let sound get messed up if going slow
 
R_DrawEntitiesOnList ();
 
GL_DisableMultitexture();
 
R_RenderDlights ();
 
R_DrawParticles ();
 
#ifdef GLTEST
Test_Draw ();
#endif
 
}
 
 
/*
=============
R_Clear
=============
*/
void R_Clear (void)
{
if (r_mirroralpha.value != 1.0)
{
if (gl_clear.value)
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
else
glClear (GL_DEPTH_BUFFER_BIT);
gldepthmin = 0;
gldepthmax = 0.5;
glDepthFunc (GL_LEQUAL);
}
else if (gl_ztrick.value)
{
static int trickframe;
 
if (gl_clear.value)
glClear (GL_COLOR_BUFFER_BIT);
 
trickframe++;
if (trickframe & 1)
{
gldepthmin = 0;
gldepthmax = 0.49999;
glDepthFunc (GL_LEQUAL);
}
else
{
gldepthmin = 1;
gldepthmax = 0.5;
glDepthFunc (GL_GEQUAL);
}
}
else
{
if (gl_clear.value)
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
else
glClear (GL_DEPTH_BUFFER_BIT);
gldepthmin = 0;
gldepthmax = 1;
glDepthFunc (GL_LEQUAL);
}
 
glDepthRange (gldepthmin, gldepthmax);
}
 
/*
=============
R_Mirror
=============
*/
void R_Mirror (void)
{
float d;
msurface_t *s;
entity_t *ent;
 
if (!mirror)
return;
 
memcpy (r_base_world_matrix, r_world_matrix, sizeof(r_base_world_matrix));
 
d = DotProduct (r_refdef.vieworg, mirror_plane->normal) - mirror_plane->dist;
VectorMA (r_refdef.vieworg, -2*d, mirror_plane->normal, r_refdef.vieworg);
 
d = DotProduct (vpn, mirror_plane->normal);
VectorMA (vpn, -2*d, mirror_plane->normal, vpn);
 
r_refdef.viewangles[0] = -asin (vpn[2])/M_PI*180;
r_refdef.viewangles[1] = atan2 (vpn[1], vpn[0])/M_PI*180;
r_refdef.viewangles[2] = -r_refdef.viewangles[2];
 
ent = &cl_entities[cl.viewentity];
if (cl_numvisedicts < MAX_VISEDICTS)
{
cl_visedicts[cl_numvisedicts] = ent;
cl_numvisedicts++;
}
 
gldepthmin = 0.5;
gldepthmax = 1;
glDepthRange (gldepthmin, gldepthmax);
glDepthFunc (GL_LEQUAL);
 
R_RenderScene ();
R_DrawWaterSurfaces ();
 
gldepthmin = 0;
gldepthmax = 0.5;
glDepthRange (gldepthmin, gldepthmax);
glDepthFunc (GL_LEQUAL);
 
// blend on top
glEnable (GL_BLEND);
glMatrixMode(GL_PROJECTION);
if (mirror_plane->normal[2])
glScalef (1,-1,1);
else
glScalef (-1,1,1);
glCullFace(GL_FRONT);
glMatrixMode(GL_MODELVIEW);
 
glLoadMatrixf (r_base_world_matrix);
 
glColor4f (1,1,1,r_mirroralpha.value);
s = cl.worldmodel->textures[mirrortexturenum]->texturechain;
for ( ; s ; s=s->texturechain)
R_RenderBrushPoly (s);
cl.worldmodel->textures[mirrortexturenum]->texturechain = NULL;
glDisable (GL_BLEND);
glColor4f (1,1,1,1);
}
 
/*
================
R_RenderView
 
r_refdef must be set before the first call
================
*/
void R_RenderView (void)
{
double time1, time2;
GLfloat colors[4] = {(GLfloat) 0.0, (GLfloat) 0.0, (GLfloat) 1, (GLfloat) 0.20};
 
if (r_norefresh.value)
return;
 
if (!r_worldentity.model || !cl.worldmodel)
Sys_Error ("R_RenderView: NULL worldmodel");
 
if (r_speeds.value)
{
glFinish ();
time1 = Sys_FloatTime ();
c_brush_polys = 0;
c_alias_polys = 0;
}
 
mirror = false;
 
if (gl_finish.value)
glFinish ();
 
R_Clear ();
 
// render normal view
 
/***** Experimental silly looking fog ******
****** Use r_fullbright if you enable ******
glFogi(GL_FOG_MODE, GL_LINEAR);
glFogfv(GL_FOG_COLOR, colors);
glFogf(GL_FOG_END, 512.0);
glEnable(GL_FOG);
********************************************/
 
R_RenderScene ();
R_DrawViewModel ();
R_DrawWaterSurfaces ();
 
// More fog right here :)
// glDisable(GL_FOG);
// End of all fog code...
 
// render mirror view
R_Mirror ();
 
R_PolyBlend ();
 
if (r_speeds.value)
{
// glFinish ();
time2 = Sys_FloatTime ();
Con_Printf ("%3i ms %4i wpoly %4i epoly\n", (int)((time2-time1)*1000), c_brush_polys, c_alias_polys);
}
}
/contrib/other/sdlquake-1.0.9/gl_rmisc.c
0,0 → 1,455
/*
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},
};
void R_InitParticleTexture (void)
{
int x,y;
byte data[8][8][4];
 
//
// particle texture
//
particletexture = texture_extension_number++;
GL_Bind(particletexture);
 
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);
}
 
/*
===============
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;
extern cvar_t 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);
Cvar_RegisterVariable (&r_mirroralpha);
Cvar_RegisterVariable (&r_wateralpha);
Cvar_RegisterVariable (&r_dynamic);
Cvar_RegisterVariable (&r_novis);
Cvar_RegisterVariable (&r_speeds);
 
Cvar_RegisterVariable (&gl_finish);
Cvar_RegisterVariable (&gl_clear);
Cvar_RegisterVariable (&gl_texsort);
 
if (gl_mtexable)
Cvar_SetValue ("gl_texsort", 0.0);
 
Cvar_RegisterVariable (&gl_cull);
Cvar_RegisterVariable (&gl_smoothmodels);
Cvar_RegisterVariable (&gl_affinemodels);
Cvar_RegisterVariable (&gl_polyblend);
Cvar_RegisterVariable (&gl_flashblend);
Cvar_RegisterVariable (&gl_playermip);
Cvar_RegisterVariable (&gl_nocolors);
 
Cvar_RegisterVariable (&gl_keeptjunctions);
Cvar_RegisterVariable (&gl_reporttjunctions);
 
Cvar_RegisterVariable (&gl_doubleeyes);
 
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;
 
GL_DisableMultitexture();
 
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;
 
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;
}
 
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
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)
{
}
 
 
/contrib/other/sdlquake-1.0.9/gl_rsurf.c
0,0 → 1,1694
/*
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_surf.c: surface-related refresh code
 
#include "quakedef.h"
 
int skytexturenum;
 
#ifndef GL_RGBA4
#define GL_RGBA4 0
#endif
 
 
int lightmap_bytes; // 1, 2, or 4
 
int lightmap_textures;
 
unsigned blocklights[18*18];
 
#define BLOCK_WIDTH 128
#define BLOCK_HEIGHT 128
 
#define MAX_LIGHTMAPS 64
int active_lightmaps;
 
typedef struct glRect_s {
unsigned char l,t,w,h;
} glRect_t;
 
glpoly_t *lightmap_polys[MAX_LIGHTMAPS];
qboolean lightmap_modified[MAX_LIGHTMAPS];
glRect_t lightmap_rectchange[MAX_LIGHTMAPS];
 
int allocated[MAX_LIGHTMAPS][BLOCK_WIDTH];
 
// the lightmap texture data needs to be kept in
// main memory so texsubimage can update properly
byte lightmaps[4*MAX_LIGHTMAPS*BLOCK_WIDTH*BLOCK_HEIGHT];
 
// For gl_texsort 0
msurface_t *skychain = NULL;
msurface_t *waterchain = NULL;
 
void R_RenderDynamicLightmaps (msurface_t *fa);
 
/*
===============
R_AddDynamicLights
===============
*/
void R_AddDynamicLights (msurface_t *surf)
{
int lnum;
int sd, td;
float dist, rad, minlight;
vec3_t impact, local;
int s, t;
int i;
int smax, tmax;
mtexinfo_t *tex;
 
smax = (surf->extents[0]>>4)+1;
tmax = (surf->extents[1]>>4)+1;
tex = surf->texinfo;
 
for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
{
if ( !(surf->dlightbits & (1<<lnum) ) )
continue; // not lit by this light
 
rad = cl_dlights[lnum].radius;
dist = DotProduct (cl_dlights[lnum].origin, surf->plane->normal) -
surf->plane->dist;
rad -= fabs(dist);
minlight = cl_dlights[lnum].minlight;
if (rad < minlight)
continue;
minlight = rad - minlight;
 
for (i=0 ; i<3 ; i++)
{
impact[i] = cl_dlights[lnum].origin[i] -
surf->plane->normal[i]*dist;
}
 
local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3];
local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3];
 
local[0] -= surf->texturemins[0];
local[1] -= surf->texturemins[1];
for (t = 0 ; t<tmax ; t++)
{
td = local[1] - t*16;
if (td < 0)
td = -td;
for (s=0 ; s<smax ; s++)
{
sd = local[0] - s*16;
if (sd < 0)
sd = -sd;
if (sd > td)
dist = sd + (td>>1);
else
dist = td + (sd>>1);
if (dist < minlight)
blocklights[t*smax + s] += (rad - dist)*256;
}
}
}
}
 
 
/*
===============
R_BuildLightMap
 
Combine and scale multiple lightmaps into the 8.8 format in blocklights
===============
*/
void R_BuildLightMap (msurface_t *surf, byte *dest, int stride)
{
int smax, tmax;
int t;
int i, j, size;
byte *lightmap;
unsigned scale;
int maps;
int lightadj[4];
unsigned *bl;
 
surf->cached_dlight = (surf->dlightframe == r_framecount);
 
smax = (surf->extents[0]>>4)+1;
tmax = (surf->extents[1]>>4)+1;
size = smax*tmax;
lightmap = surf->samples;
 
// set to full bright if no light data
if (r_fullbright.value || !cl.worldmodel->lightdata)
{
for (i=0 ; i<size ; i++)
blocklights[i] = 255*256;
goto store;
}
 
// clear to no light
for (i=0 ; i<size ; i++)
blocklights[i] = 0;
 
// add all the lightmaps
if (lightmap)
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
maps++)
{
scale = d_lightstylevalue[surf->styles[maps]];
surf->cached_light[maps] = scale; // 8.8 fraction
for (i=0 ; i<size ; i++)
blocklights[i] += lightmap[i] * scale;
lightmap += size; // skip to next lightmap
}
 
// add all the dynamic lights
if (surf->dlightframe == r_framecount)
R_AddDynamicLights (surf);
 
// bound, invert, and shift
store:
switch (gl_lightmap_format)
{
case GL_RGBA:
stride -= (smax<<2);
bl = blocklights;
for (i=0 ; i<tmax ; i++, dest += stride)
{
for (j=0 ; j<smax ; j++)
{
t = *bl++;
t >>= 7;
if (t > 255)
t = 255;
dest[3] = 255-t;
dest += 4;
}
}
break;
case GL_ALPHA:
case GL_LUMINANCE:
case GL_INTENSITY:
bl = blocklights;
for (i=0 ; i<tmax ; i++, dest += stride)
{
for (j=0 ; j<smax ; j++)
{
t = *bl++;
t >>= 7;
if (t > 255)
t = 255;
dest[j] = 255-t;
}
}
break;
default:
Sys_Error ("Bad lightmap format");
}
}
 
 
/*
===============
R_TextureAnimation
 
Returns the proper texture for a given time and base texture
===============
*/
texture_t *R_TextureAnimation (texture_t *base)
{
int reletive;
int count;
 
if (currententity->frame)
{
if (base->alternate_anims)
base = base->alternate_anims;
}
if (!base->anim_total)
return base;
 
reletive = (int)(cl.time*10) % base->anim_total;
 
count = 0;
while (base->anim_min > reletive || base->anim_max <= reletive)
{
base = base->anim_next;
if (!base)
Sys_Error ("R_TextureAnimation: broken cycle");
if (++count > 100)
Sys_Error ("R_TextureAnimation: infinite cycle");
}
 
return base;
}
 
 
/*
=============================================================
 
BRUSH MODELS
 
=============================================================
*/
 
 
extern int solidskytexture;
extern int alphaskytexture;
extern float speedscale; // for top sky and bottom sky
 
void DrawGLWaterPoly (glpoly_t *p);
void DrawGLWaterPolyLightmap (glpoly_t *p);
 
lpMTexFUNC qglMTexCoord2fSGIS = NULL;
lpSelTexFUNC qglSelectTextureSGIS = NULL;
 
qboolean mtexenabled = false;
 
void GL_SelectTexture (GLenum target);
 
void GL_DisableMultitexture(void)
{
if (mtexenabled) {
glDisable(GL_TEXTURE_2D);
GL_SelectTexture(TEXTURE0_SGIS);
mtexenabled = false;
}
}
 
void GL_EnableMultitexture(void)
{
if (gl_mtexable) {
GL_SelectTexture(TEXTURE1_SGIS);
glEnable(GL_TEXTURE_2D);
mtexenabled = true;
}
}
 
#if 0
/*
================
R_DrawSequentialPoly
 
Systems that have fast state and texture changes can
just do everything as it passes with no need to sort
================
*/
void R_DrawSequentialPoly (msurface_t *s)
{
glpoly_t *p;
float *v;
int i;
texture_t *t;
 
//
// normal lightmaped poly
//
if (! (s->flags & (SURF_DRAWSKY|SURF_DRAWTURB|SURF_UNDERWATER) ) )
{
p = s->polys;
 
t = R_TextureAnimation (s->texinfo->texture);
GL_Bind (t->gl_texturenum);
glBegin (GL_POLYGON);
v = p->verts[0];
for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
{
glTexCoord2f (v[3], v[4]);
glVertex3fv (v);
}
glEnd ();
 
GL_Bind (lightmap_textures + s->lightmaptexturenum);
glEnable (GL_BLEND);
glBegin (GL_POLYGON);
v = p->verts[0];
for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
{
glTexCoord2f (v[5], v[6]);
glVertex3fv (v);
}
glEnd ();
 
glDisable (GL_BLEND);
 
return;
}
 
//
// subdivided water surface warp
//
if (s->flags & SURF_DRAWTURB)
{
GL_Bind (s->texinfo->texture->gl_texturenum);
EmitWaterPolys (s);
return;
}
 
//
// subdivided sky warp
//
if (s->flags & SURF_DRAWSKY)
{
GL_Bind (solidskytexture);
speedscale = realtime*8;
speedscale -= (int)speedscale;
 
EmitSkyPolys (s);
 
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GL_Bind (alphaskytexture);
speedscale = realtime*16;
speedscale -= (int)speedscale;
EmitSkyPolys (s);
if (gl_lightmap_format == GL_LUMINANCE)
glBlendFunc (GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
 
glDisable (GL_BLEND);
}
 
//
// underwater warped with lightmap
//
p = s->polys;
 
t = R_TextureAnimation (s->texinfo->texture);
GL_Bind (t->gl_texturenum);
DrawGLWaterPoly (p);
 
GL_Bind (lightmap_textures + s->lightmaptexturenum);
glEnable (GL_BLEND);
DrawGLWaterPolyLightmap (p);
glDisable (GL_BLEND);
}
#else
/*
================
R_DrawSequentialPoly
 
Systems that have fast state and texture changes can
just do everything as it passes with no need to sort
================
*/
void R_DrawSequentialPoly (msurface_t *s)
{
glpoly_t *p;
float *v;
int i;
texture_t *t;
vec3_t nv, dir;
float ss, ss2, length;
float s1, t1;
glRect_t *theRect;
 
//
// normal lightmaped poly
//
 
if (! (s->flags & (SURF_DRAWSKY|SURF_DRAWTURB|SURF_UNDERWATER) ) )
{
R_RenderDynamicLightmaps (s);
if (gl_mtexable) {
p = s->polys;
 
t = R_TextureAnimation (s->texinfo->texture);
// Binds world to texture env 0
GL_SelectTexture(TEXTURE0_SGIS);
GL_Bind (t->gl_texturenum);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
// Binds lightmap to texenv 1
GL_EnableMultitexture(); // Same as SelectTexture (TEXTURE1)
GL_Bind (lightmap_textures + s->lightmaptexturenum);
i = s->lightmaptexturenum;
if (lightmap_modified[i])
{
lightmap_modified[i] = false;
theRect = &lightmap_rectchange[i];
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t,
BLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE,
lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes);
theRect->l = BLOCK_WIDTH;
theRect->t = BLOCK_HEIGHT;
theRect->h = 0;
theRect->w = 0;
}
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
glBegin(GL_POLYGON);
v = p->verts[0];
for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
{
qglMTexCoord2fSGIS (TEXTURE0_SGIS, v[3], v[4]);
qglMTexCoord2fSGIS (TEXTURE1_SGIS, v[5], v[6]);
glVertex3fv (v);
}
glEnd ();
return;
} else {
p = s->polys;
 
t = R_TextureAnimation (s->texinfo->texture);
GL_Bind (t->gl_texturenum);
glBegin (GL_POLYGON);
v = p->verts[0];
for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
{
glTexCoord2f (v[3], v[4]);
glVertex3fv (v);
}
glEnd ();
 
GL_Bind (lightmap_textures + s->lightmaptexturenum);
glEnable (GL_BLEND);
glBegin (GL_POLYGON);
v = p->verts[0];
for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
{
glTexCoord2f (v[5], v[6]);
glVertex3fv (v);
}
glEnd ();
 
glDisable (GL_BLEND);
}
 
return;
}
 
//
// subdivided water surface warp
//
 
if (s->flags & SURF_DRAWTURB)
{
GL_DisableMultitexture();
GL_Bind (s->texinfo->texture->gl_texturenum);
EmitWaterPolys (s);
return;
}
 
//
// subdivided sky warp
//
if (s->flags & SURF_DRAWSKY)
{
GL_DisableMultitexture();
GL_Bind (solidskytexture);
speedscale = realtime*8;
speedscale -= (int)speedscale & ~127;
 
EmitSkyPolys (s);
 
glEnable (GL_BLEND);
GL_Bind (alphaskytexture);
speedscale = realtime*16;
speedscale -= (int)speedscale & ~127;
EmitSkyPolys (s);
 
glDisable (GL_BLEND);
return;
}
 
//
// underwater warped with lightmap
//
R_RenderDynamicLightmaps (s);
if (gl_mtexable) {
p = s->polys;
 
t = R_TextureAnimation (s->texinfo->texture);
GL_SelectTexture(TEXTURE0_SGIS);
GL_Bind (t->gl_texturenum);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
GL_EnableMultitexture();
GL_Bind (lightmap_textures + s->lightmaptexturenum);
i = s->lightmaptexturenum;
if (lightmap_modified[i])
{
lightmap_modified[i] = false;
theRect = &lightmap_rectchange[i];
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t,
BLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE,
lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes);
theRect->l = BLOCK_WIDTH;
theRect->t = BLOCK_HEIGHT;
theRect->h = 0;
theRect->w = 0;
}
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
glBegin (GL_TRIANGLE_FAN);
v = p->verts[0];
for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
{
qglMTexCoord2fSGIS (TEXTURE0_SGIS, v[3], v[4]);
qglMTexCoord2fSGIS (TEXTURE1_SGIS, v[5], v[6]);
 
nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime);
nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime);
nv[2] = v[2];
 
glVertex3fv (nv);
}
glEnd ();
 
} else {
p = s->polys;
 
t = R_TextureAnimation (s->texinfo->texture);
GL_Bind (t->gl_texturenum);
DrawGLWaterPoly (p);
 
GL_Bind (lightmap_textures + s->lightmaptexturenum);
glEnable (GL_BLEND);
DrawGLWaterPolyLightmap (p);
glDisable (GL_BLEND);
}
}
#endif
 
 
/*
================
DrawGLWaterPoly
 
Warp the vertex coordinates
================
*/
void DrawGLWaterPoly (glpoly_t *p)
{
int i;
float *v;
float s, t, os, ot;
vec3_t nv;
 
GL_DisableMultitexture();
 
glBegin (GL_TRIANGLE_FAN);
v = p->verts[0];
for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
{
glTexCoord2f (v[3], v[4]);
 
nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime);
nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime);
nv[2] = v[2];
 
glVertex3fv (nv);
}
glEnd ();
}
 
void DrawGLWaterPolyLightmap (glpoly_t *p)
{
int i;
float *v;
float s, t, os, ot;
vec3_t nv;
 
GL_DisableMultitexture();
 
glBegin (GL_TRIANGLE_FAN);
v = p->verts[0];
for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
{
glTexCoord2f (v[5], v[6]);
 
nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime);
nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime);
nv[2] = v[2];
 
glVertex3fv (nv);
}
glEnd ();
}
 
/*
================
DrawGLPoly
================
*/
void DrawGLPoly (glpoly_t *p)
{
int i;
float *v;
 
glBegin (GL_POLYGON);
v = p->verts[0];
for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
{
glTexCoord2f (v[3], v[4]);
glVertex3fv (v);
}
glEnd ();
}
 
 
/*
================
R_BlendLightmaps
================
*/
void R_BlendLightmaps (void)
{
int i, j;
glpoly_t *p;
float *v;
glRect_t *theRect;
 
if (r_fullbright.value)
return;
if (!gl_texsort.value)
return;
 
glDepthMask (0); // don't bother writing Z
 
if (gl_lightmap_format == GL_LUMINANCE)
glBlendFunc (GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
else if (gl_lightmap_format == GL_INTENSITY)
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glColor4f (0,0,0,1);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
 
if (!r_lightmap.value)
{
glEnable (GL_BLEND);
}
 
for (i=0 ; i<MAX_LIGHTMAPS ; i++)
{
p = lightmap_polys[i];
if (!p)
continue;
GL_Bind(lightmap_textures+i);
if (lightmap_modified[i])
{
lightmap_modified[i] = false;
theRect = &lightmap_rectchange[i];
// glTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes
// , BLOCK_WIDTH, BLOCK_HEIGHT, 0,
// gl_lightmap_format, GL_UNSIGNED_BYTE, lightmaps+i*BLOCK_WIDTH*BLOCK_HEIGHT*lightmap_bytes);
// glTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes
// , BLOCK_WIDTH, theRect->h, 0,
// gl_lightmap_format, GL_UNSIGNED_BYTE, lightmaps+(i*BLOCK_HEIGHT+theRect->t)*BLOCK_WIDTH*lightmap_bytes);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t,
BLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE,
lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes);
theRect->l = BLOCK_WIDTH;
theRect->t = BLOCK_HEIGHT;
theRect->h = 0;
theRect->w = 0;
}
for ( ; p ; p=p->chain)
{
if (p->flags & SURF_UNDERWATER)
DrawGLWaterPolyLightmap (p);
else
{
glBegin (GL_POLYGON);
v = p->verts[0];
for (j=0 ; j<p->numverts ; j++, v+= VERTEXSIZE)
{
glTexCoord2f (v[5], v[6]);
glVertex3fv (v);
}
glEnd ();
}
}
}
 
glDisable (GL_BLEND);
if (gl_lightmap_format == GL_LUMINANCE)
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
else if (gl_lightmap_format == GL_INTENSITY)
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glColor4f (1,1,1,1);
}
 
glDepthMask (1); // back to normal Z buffering
}
 
/*
================
R_RenderBrushPoly
================
*/
void R_RenderBrushPoly (msurface_t *fa)
{
texture_t *t;
byte *base;
int maps;
glRect_t *theRect;
int smax, tmax;
 
c_brush_polys++;
 
if (fa->flags & SURF_DRAWSKY)
{ // warp texture, no lightmaps
EmitBothSkyLayers (fa);
return;
}
t = R_TextureAnimation (fa->texinfo->texture);
GL_Bind (t->gl_texturenum);
 
if (fa->flags & SURF_DRAWTURB)
{ // warp texture, no lightmaps
EmitWaterPolys (fa);
return;
}
 
if (fa->flags & SURF_UNDERWATER)
DrawGLWaterPoly (fa->polys);
else
DrawGLPoly (fa->polys);
 
// add the poly to the proper lightmap chain
 
fa->polys->chain = lightmap_polys[fa->lightmaptexturenum];
lightmap_polys[fa->lightmaptexturenum] = fa->polys;
 
// check for lightmap modification
for (maps = 0 ; maps < MAXLIGHTMAPS && fa->styles[maps] != 255 ;
maps++)
if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps])
goto dynamic;
 
if (fa->dlightframe == r_framecount // dynamic this frame
|| fa->cached_dlight) // dynamic previously
{
dynamic:
if (r_dynamic.value)
{
lightmap_modified[fa->lightmaptexturenum] = true;
theRect = &lightmap_rectchange[fa->lightmaptexturenum];
if (fa->light_t < theRect->t) {
if (theRect->h)
theRect->h += theRect->t - fa->light_t;
theRect->t = fa->light_t;
}
if (fa->light_s < theRect->l) {
if (theRect->w)
theRect->w += theRect->l - fa->light_s;
theRect->l = fa->light_s;
}
smax = (fa->extents[0]>>4)+1;
tmax = (fa->extents[1]>>4)+1;
if ((theRect->w + theRect->l) < (fa->light_s + smax))
theRect->w = (fa->light_s-theRect->l)+smax;
if ((theRect->h + theRect->t) < (fa->light_t + tmax))
theRect->h = (fa->light_t-theRect->t)+tmax;
base = lightmaps + fa->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT;
base += fa->light_t * BLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes;
R_BuildLightMap (fa, base, BLOCK_WIDTH*lightmap_bytes);
}
}
}
 
/*
================
R_RenderDynamicLightmaps
Multitexture
================
*/
void R_RenderDynamicLightmaps (msurface_t *fa)
{
texture_t *t;
byte *base;
int maps;
glRect_t *theRect;
int smax, tmax;
 
c_brush_polys++;
 
if (fa->flags & ( SURF_DRAWSKY | SURF_DRAWTURB) )
return;
fa->polys->chain = lightmap_polys[fa->lightmaptexturenum];
lightmap_polys[fa->lightmaptexturenum] = fa->polys;
 
// check for lightmap modification
for (maps = 0 ; maps < MAXLIGHTMAPS && fa->styles[maps] != 255 ;
maps++)
if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps])
goto dynamic;
 
if (fa->dlightframe == r_framecount // dynamic this frame
|| fa->cached_dlight) // dynamic previously
{
dynamic:
if (r_dynamic.value)
{
lightmap_modified[fa->lightmaptexturenum] = true;
theRect = &lightmap_rectchange[fa->lightmaptexturenum];
if (fa->light_t < theRect->t) {
if (theRect->h)
theRect->h += theRect->t - fa->light_t;
theRect->t = fa->light_t;
}
if (fa->light_s < theRect->l) {
if (theRect->w)
theRect->w += theRect->l - fa->light_s;
theRect->l = fa->light_s;
}
smax = (fa->extents[0]>>4)+1;
tmax = (fa->extents[1]>>4)+1;
if ((theRect->w + theRect->l) < (fa->light_s + smax))
theRect->w = (fa->light_s-theRect->l)+smax;
if ((theRect->h + theRect->t) < (fa->light_t + tmax))
theRect->h = (fa->light_t-theRect->t)+tmax;
base = lightmaps + fa->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT;
base += fa->light_t * BLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes;
R_BuildLightMap (fa, base, BLOCK_WIDTH*lightmap_bytes);
}
}
}
 
/*
================
R_MirrorChain
================
*/
void R_MirrorChain (msurface_t *s)
{
if (mirror)
return;
mirror = true;
mirror_plane = s->plane;
}
 
 
#if 0
/*
================
R_DrawWaterSurfaces
================
*/
void R_DrawWaterSurfaces (void)
{
int i;
msurface_t *s;
texture_t *t;
 
if (r_wateralpha.value == 1.0)
return;
 
//
// go back to the world matrix
//
glLoadMatrixf (r_world_matrix);
 
glEnable (GL_BLEND);
glColor4f (1,1,1,r_wateralpha.value);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 
for (i=0 ; i<cl.worldmodel->numtextures ; i++)
{
t = cl.worldmodel->textures[i];
if (!t)
continue;
s = t->texturechain;
if (!s)
continue;
if ( !(s->flags & SURF_DRAWTURB) )
continue;
 
// set modulate mode explicitly
GL_Bind (t->gl_texturenum);
 
for ( ; s ; s=s->texturechain)
R_RenderBrushPoly (s);
 
t->texturechain = NULL;
}
 
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 
glColor4f (1,1,1,1);
glDisable (GL_BLEND);
}
#else
/*
================
R_DrawWaterSurfaces
================
*/
void R_DrawWaterSurfaces (void)
{
int i;
msurface_t *s;
texture_t *t;
 
if (r_wateralpha.value == 1.0 && gl_texsort.value)
return;
 
//
// go back to the world matrix
//
 
glLoadMatrixf (r_world_matrix);
 
if (r_wateralpha.value < 1.0) {
glEnable (GL_BLEND);
glColor4f (1,1,1,r_wateralpha.value);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
 
if (!gl_texsort.value) {
if (!waterchain)
return;
 
for ( s = waterchain ; s ; s=s->texturechain) {
GL_Bind (s->texinfo->texture->gl_texturenum);
EmitWaterPolys (s);
}
waterchain = NULL;
} else {
 
for (i=0 ; i<cl.worldmodel->numtextures ; i++)
{
t = cl.worldmodel->textures[i];
if (!t)
continue;
s = t->texturechain;
if (!s)
continue;
if ( !(s->flags & SURF_DRAWTURB ) )
continue;
 
// set modulate mode explicitly
GL_Bind (t->gl_texturenum);
 
for ( ; s ; s=s->texturechain)
EmitWaterPolys (s);
t->texturechain = NULL;
}
 
}
 
if (r_wateralpha.value < 1.0) {
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 
glColor4f (1,1,1,1);
glDisable (GL_BLEND);
}
 
}
 
#endif
 
/*
================
DrawTextureChains
================
*/
void DrawTextureChains (void)
{
int i;
msurface_t *s;
texture_t *t;
 
if (!gl_texsort.value) {
GL_DisableMultitexture();
 
if (skychain) {
R_DrawSkyChain(skychain);
skychain = NULL;
}
 
return;
}
 
for (i=0 ; i<cl.worldmodel->numtextures ; i++)
{
t = cl.worldmodel->textures[i];
if (!t)
continue;
s = t->texturechain;
if (!s)
continue;
if (i == skytexturenum)
R_DrawSkyChain (s);
else if (i == mirrortexturenum && r_mirroralpha.value != 1.0)
{
R_MirrorChain (s);
continue;
}
else
{
if ((s->flags & SURF_DRAWTURB) && r_wateralpha.value != 1.0)
continue; // draw translucent water later
for ( ; s ; s=s->texturechain)
R_RenderBrushPoly (s);
}
 
t->texturechain = NULL;
}
}
 
/*
=================
R_DrawBrushModel
=================
*/
void R_DrawBrushModel (entity_t *e)
{
int j, k;
vec3_t mins, maxs;
int i, numsurfaces;
msurface_t *psurf;
float dot;
mplane_t *pplane;
model_t *clmodel;
qboolean rotated;
 
currententity = e;
currenttexture = -1;
 
clmodel = e->model;
 
if (e->angles[0] || e->angles[1] || e->angles[2])
{
rotated = true;
for (i=0 ; i<3 ; i++)
{
mins[i] = e->origin[i] - clmodel->radius;
maxs[i] = e->origin[i] + clmodel->radius;
}
}
else
{
rotated = false;
VectorAdd (e->origin, clmodel->mins, mins);
VectorAdd (e->origin, clmodel->maxs, maxs);
}
 
if (R_CullBox (mins, maxs))
return;
 
glColor3f (1,1,1);
memset (lightmap_polys, 0, sizeof(lightmap_polys));
 
VectorSubtract (r_refdef.vieworg, e->origin, modelorg);
if (rotated)
{
vec3_t temp;
vec3_t forward, right, up;
 
VectorCopy (modelorg, temp);
AngleVectors (e->angles, forward, right, up);
modelorg[0] = DotProduct (temp, forward);
modelorg[1] = -DotProduct (temp, right);
modelorg[2] = DotProduct (temp, up);
}
 
psurf = &clmodel->surfaces[clmodel->firstmodelsurface];
 
// calculate dynamic lighting for bmodel if it's not an
// instanced model
if (clmodel->firstmodelsurface != 0 && !gl_flashblend.value)
{
for (k=0 ; k<MAX_DLIGHTS ; k++)
{
if ((cl_dlights[k].die < cl.time) ||
(!cl_dlights[k].radius))
continue;
 
R_MarkLights (&cl_dlights[k], 1<<k,
clmodel->nodes + clmodel->hulls[0].firstclipnode);
}
}
 
glPushMatrix ();
e->angles[0] = -e->angles[0]; // stupid quake bug
R_RotateForEntity (e);
e->angles[0] = -e->angles[0]; // stupid quake bug
 
//
// draw texture
//
for (i=0 ; i<clmodel->nummodelsurfaces ; i++, psurf++)
{
// find which side of the node we are on
pplane = psurf->plane;
 
dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
 
// draw the polygon
if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
{
if (gl_texsort.value)
R_RenderBrushPoly (psurf);
else
R_DrawSequentialPoly (psurf);
}
}
 
R_BlendLightmaps ();
 
glPopMatrix ();
}
 
/*
=============================================================
 
WORLD MODEL
 
=============================================================
*/
 
/*
================
R_RecursiveWorldNode
================
*/
void R_RecursiveWorldNode (mnode_t *node)
{
int i, c, side, *pindex;
vec3_t acceptpt, rejectpt;
mplane_t *plane;
msurface_t *surf, **mark;
mleaf_t *pleaf;
double d, dot;
vec3_t mins, maxs;
 
if (node->contents == CONTENTS_SOLID)
return; // solid
 
if (node->visframe != r_visframecount)
return;
if (R_CullBox (node->minmaxs, node->minmaxs+3))
return;
// if a leaf node, draw stuff
if (node->contents < 0)
{
pleaf = (mleaf_t *)node;
 
mark = pleaf->firstmarksurface;
c = pleaf->nummarksurfaces;
 
if (c)
{
do
{
(*mark)->visframe = r_framecount;
mark++;
} while (--c);
}
 
// deal with model fragments in this leaf
if (pleaf->efrags)
R_StoreEfrags (&pleaf->efrags);
 
return;
}
 
// node is just a decision point, so go down the apropriate sides
 
// find which side of the node we are on
plane = node->plane;
 
switch (plane->type)
{
case PLANE_X:
dot = modelorg[0] - plane->dist;
break;
case PLANE_Y:
dot = modelorg[1] - plane->dist;
break;
case PLANE_Z:
dot = modelorg[2] - plane->dist;
break;
default:
dot = DotProduct (modelorg, plane->normal) - plane->dist;
break;
}
 
if (dot >= 0)
side = 0;
else
side = 1;
 
// recurse down the children, front side first
R_RecursiveWorldNode (node->children[side]);
 
// draw stuff
c = node->numsurfaces;
 
if (c)
{
surf = cl.worldmodel->surfaces + node->firstsurface;
 
if (dot < 0 -BACKFACE_EPSILON)
side = SURF_PLANEBACK;
else if (dot > BACKFACE_EPSILON)
side = 0;
{
for ( ; c ; c--, surf++)
{
if (surf->visframe != r_framecount)
continue;
 
// don't backface underwater surfaces, because they warp
if ( !(surf->flags & SURF_UNDERWATER) && ( (dot < 0) ^ !!(surf->flags & SURF_PLANEBACK)) )
continue; // wrong side
 
// if sorting by texture, just store it out
if (gl_texsort.value)
{
if (!mirror
|| surf->texinfo->texture != cl.worldmodel->textures[mirrortexturenum])
{
surf->texturechain = surf->texinfo->texture->texturechain;
surf->texinfo->texture->texturechain = surf;
}
} else if (surf->flags & SURF_DRAWSKY) {
surf->texturechain = skychain;
skychain = surf;
} else if (surf->flags & SURF_DRAWTURB) {
surf->texturechain = waterchain;
waterchain = surf;
} else
R_DrawSequentialPoly (surf);
 
}
}
 
}
 
// recurse down the back side
R_RecursiveWorldNode (node->children[!side]);
}
 
 
 
/*
=============
R_DrawWorld
=============
*/
void R_DrawWorld (void)
{
entity_t ent;
int i;
 
memset (&ent, 0, sizeof(ent));
ent.model = cl.worldmodel;
 
VectorCopy (r_refdef.vieworg, modelorg);
 
currententity = &ent;
currenttexture = -1;
 
glColor3f (1,1,1);
memset (lightmap_polys, 0, sizeof(lightmap_polys));
#ifdef QUAKE2
R_ClearSkyBox ();
#endif
 
R_RecursiveWorldNode (cl.worldmodel->nodes);
 
DrawTextureChains ();
 
R_BlendLightmaps ();
 
#ifdef QUAKE2
R_DrawSkyBox ();
#endif
}
 
 
/*
===============
R_MarkLeaves
===============
*/
void R_MarkLeaves (void)
{
byte *vis;
mnode_t *node;
int i;
byte solid[4096];
 
if (r_oldviewleaf == r_viewleaf && !r_novis.value)
return;
if (mirror)
return;
 
r_visframecount++;
r_oldviewleaf = r_viewleaf;
 
if (r_novis.value)
{
vis = solid;
memset (solid, 0xff, (cl.worldmodel->numleafs+7)>>3);
}
else
vis = Mod_LeafPVS (r_viewleaf, cl.worldmodel);
for (i=0 ; i<cl.worldmodel->numleafs ; i++)
{
if (vis[i>>3] & (1<<(i&7)))
{
node = (mnode_t *)&cl.worldmodel->leafs[i+1];
do
{
if (node->visframe == r_visframecount)
break;
node->visframe = r_visframecount;
node = node->parent;
} while (node);
}
}
}
 
 
 
/*
=============================================================================
 
LIGHTMAP ALLOCATION
 
=============================================================================
*/
 
// returns a texture number and the position inside it
int AllocBlock (int w, int h, int *x, int *y)
{
int i, j;
int best, best2;
int bestx;
int texnum;
 
for (texnum=0 ; texnum<MAX_LIGHTMAPS ; texnum++)
{
best = BLOCK_HEIGHT;
 
for (i=0 ; i<BLOCK_WIDTH-w ; i++)
{
best2 = 0;
 
for (j=0 ; j<w ; j++)
{
if (allocated[texnum][i+j] >= best)
break;
if (allocated[texnum][i+j] > best2)
best2 = allocated[texnum][i+j];
}
if (j == w)
{ // this is a valid spot
*x = i;
*y = best = best2;
}
}
 
if (best + h > BLOCK_HEIGHT)
continue;
 
for (i=0 ; i<w ; i++)
allocated[texnum][*x + i] = best + h;
 
return texnum;
}
 
Sys_Error ("AllocBlock: full");
}
 
 
mvertex_t *r_pcurrentvertbase;
model_t *currentmodel;
 
int nColinElim;
 
/*
================
BuildSurfaceDisplayList
================
*/
void BuildSurfaceDisplayList (msurface_t *fa)
{
int i, lindex, lnumverts, s_axis, t_axis;
float dist, lastdist, lzi, scale, u, v, frac;
unsigned mask;
vec3_t local, transformed;
medge_t *pedges, *r_pedge;
mplane_t *pplane;
int vertpage, newverts, newpage, lastvert;
qboolean visible;
float *vec;
float s, t;
glpoly_t *poly;
 
// reconstruct the polygon
pedges = currentmodel->edges;
lnumverts = fa->numedges;
vertpage = 0;
 
//
// draw texture
//
poly = Hunk_Alloc (sizeof(glpoly_t) + (lnumverts-4) * VERTEXSIZE*sizeof(float));
poly->next = fa->polys;
poly->flags = fa->flags;
fa->polys = poly;
poly->numverts = lnumverts;
 
for (i=0 ; i<lnumverts ; i++)
{
lindex = currentmodel->surfedges[fa->firstedge + i];
 
if (lindex > 0)
{
r_pedge = &pedges[lindex];
vec = r_pcurrentvertbase[r_pedge->v[0]].position;
}
else
{
r_pedge = &pedges[-lindex];
vec = r_pcurrentvertbase[r_pedge->v[1]].position;
}
s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
s /= fa->texinfo->texture->width;
 
t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
t /= fa->texinfo->texture->height;
 
VectorCopy (vec, poly->verts[i]);
poly->verts[i][3] = s;
poly->verts[i][4] = t;
 
//
// lightmap texture coordinates
//
s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
s -= fa->texturemins[0];
s += fa->light_s*16;
s += 8;
s /= BLOCK_WIDTH*16; //fa->texinfo->texture->width;
 
t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
t -= fa->texturemins[1];
t += fa->light_t*16;
t += 8;
t /= BLOCK_HEIGHT*16; //fa->texinfo->texture->height;
 
poly->verts[i][5] = s;
poly->verts[i][6] = t;
}
 
//
// remove co-linear points - Ed
//
if (!gl_keeptjunctions.value && !(fa->flags & SURF_UNDERWATER) )
{
for (i = 0 ; i < lnumverts ; ++i)
{
vec3_t v1, v2;
float *prev, *this, *next;
float f;
 
prev = poly->verts[(i + lnumverts - 1) % lnumverts];
this = poly->verts[i];
next = poly->verts[(i + 1) % lnumverts];
 
VectorSubtract( this, prev, v1 );
VectorNormalize( v1 );
VectorSubtract( next, prev, v2 );
VectorNormalize( v2 );
 
// skip co-linear points
#define COLINEAR_EPSILON 0.001
if ((fabs( v1[0] - v2[0] ) <= COLINEAR_EPSILON) &&
(fabs( v1[1] - v2[1] ) <= COLINEAR_EPSILON) &&
(fabs( v1[2] - v2[2] ) <= COLINEAR_EPSILON))
{
int j;
for (j = i + 1; j < lnumverts; ++j)
{
int k;
for (k = 0; k < VERTEXSIZE; ++k)
poly->verts[j - 1][k] = poly->verts[j][k];
}
--lnumverts;
++nColinElim;
// retry next vertex next time, which is now current vertex
--i;
}
}
}
poly->numverts = lnumverts;
 
}
 
/*
========================
GL_CreateSurfaceLightmap
========================
*/
void GL_CreateSurfaceLightmap (msurface_t *surf)
{
int smax, tmax, s, t, l, i;
byte *base;
 
if (surf->flags & (SURF_DRAWSKY|SURF_DRAWTURB))
return;
 
smax = (surf->extents[0]>>4)+1;
tmax = (surf->extents[1]>>4)+1;
 
surf->lightmaptexturenum = AllocBlock (smax, tmax, &surf->light_s, &surf->light_t);
base = lightmaps + surf->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT;
base += (surf->light_t * BLOCK_WIDTH + surf->light_s) * lightmap_bytes;
R_BuildLightMap (surf, base, BLOCK_WIDTH*lightmap_bytes);
}
 
 
/*
==================
GL_BuildLightmaps
 
Builds the lightmap texture
with all the surfaces from all brush models
==================
*/
void GL_BuildLightmaps (void)
{
int i, j;
model_t *m;
extern qboolean isPermedia;
 
memset (allocated, 0, sizeof(allocated));
 
r_framecount = 1; // no dlightcache
 
if (!lightmap_textures)
{
lightmap_textures = texture_extension_number;
texture_extension_number += MAX_LIGHTMAPS;
}
 
gl_lightmap_format = GL_LUMINANCE;
// default differently on the Permedia
if (isPermedia)
gl_lightmap_format = GL_RGBA;
 
if (COM_CheckParm ("-lm_1"))
gl_lightmap_format = GL_LUMINANCE;
if (COM_CheckParm ("-lm_a"))
gl_lightmap_format = GL_ALPHA;
if (COM_CheckParm ("-lm_i"))
gl_lightmap_format = GL_INTENSITY;
if (COM_CheckParm ("-lm_2"))
gl_lightmap_format = GL_RGBA4;
if (COM_CheckParm ("-lm_4"))
gl_lightmap_format = GL_RGBA;
 
switch (gl_lightmap_format)
{
case GL_RGBA:
lightmap_bytes = 4;
break;
case GL_RGBA4:
lightmap_bytes = 2;
break;
case GL_LUMINANCE:
case GL_INTENSITY:
case GL_ALPHA:
lightmap_bytes = 1;
break;
}
 
for (j=1 ; j<MAX_MODELS ; j++)
{
m = cl.model_precache[j];
if (!m)
break;
if (m->name[0] == '*')
continue;
r_pcurrentvertbase = m->vertexes;
currentmodel = m;
for (i=0 ; i<m->numsurfaces ; i++)
{
GL_CreateSurfaceLightmap (m->surfaces + i);
if ( m->surfaces[i].flags & SURF_DRAWTURB )
continue;
#ifndef QUAKE2
if ( m->surfaces[i].flags & SURF_DRAWSKY )
continue;
#endif
BuildSurfaceDisplayList (m->surfaces + i);
}
}
 
if (!gl_texsort.value)
GL_SelectTexture(TEXTURE1_SGIS);
 
//
// upload all lightmaps that were filled
//
for (i=0 ; i<MAX_LIGHTMAPS ; i++)
{
if (!allocated[i][0])
break; // no more used
lightmap_modified[i] = false;
lightmap_rectchange[i].l = BLOCK_WIDTH;
lightmap_rectchange[i].t = BLOCK_HEIGHT;
lightmap_rectchange[i].w = 0;
lightmap_rectchange[i].h = 0;
GL_Bind(lightmap_textures + i);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes
, BLOCK_WIDTH, BLOCK_HEIGHT, 0,
gl_lightmap_format, GL_UNSIGNED_BYTE, lightmaps+i*BLOCK_WIDTH*BLOCK_HEIGHT*lightmap_bytes);
}
 
if (!gl_texsort.value)
GL_SelectTexture(TEXTURE0_SGIS);
 
}
 
/contrib/other/sdlquake-1.0.9/gl_screen.c
0,0 → 1,923
/*
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.c -- master for refresh, status bar, console, chat, notify, etc
 
#include "quakedef.h"
 
/*
 
background clear
rendering
turtle/net/ram icons
sbar
centerprint / slow centerprint
notify lines
intermission / finale overlay
loading plaque
console
menu
 
required background clears
required update regions
 
 
syncronous draw mode or async
One off screen buffer, with updates either copied or xblited
Need to double buffer?
 
 
async draw will require the refresh area to be cleared, because it will be
xblited, but sync draw can just ignore it.
 
sync
draw
 
CenterPrint ()
SlowPrint ()
Screen_Update ();
Con_Printf ();
 
net
turn off messages option
 
the refresh is allways rendered, unless the console is full screen
 
 
console is:
notify lines
half
full
 
*/
 
 
int glx, gly, glwidth, glheight;
 
// only the refresh window will be updated unless these variables are flagged
int scr_copytop;
int scr_copyeverything;
 
float scr_con_current;
float scr_conlines; // lines of console to display
 
float oldscreensize, oldfov;
cvar_t scr_viewsize = {"viewsize","100", true};
cvar_t scr_fov = {"fov","90"}; // 10 - 170
cvar_t scr_conspeed = {"scr_conspeed","300"};
cvar_t scr_centertime = {"scr_centertime","2"};
cvar_t scr_showram = {"showram","1"};
cvar_t scr_showturtle = {"showturtle","0"};
cvar_t scr_showpause = {"showpause","1"};
cvar_t scr_printspeed = {"scr_printspeed","8"};
cvar_t gl_triplebuffer = {"gl_triplebuffer", "1", true };
 
extern cvar_t crosshair;
 
qboolean scr_initialized; // ready to draw
 
qpic_t *scr_ram;
qpic_t *scr_net;
qpic_t *scr_turtle;
 
int scr_fullupdate;
 
int clearconsole;
int clearnotify;
 
int sb_lines;
 
viddef_t vid; // global video state
 
vrect_t scr_vrect;
 
qboolean scr_disabled_for_loading;
qboolean scr_drawloading;
float scr_disabled_time;
 
qboolean block_drawing;
 
void SCR_ScreenShot_f (void);
 
/*
===============================================================================
 
CENTER PRINTING
 
===============================================================================
*/
 
char scr_centerstring[1024];
float scr_centertime_start; // for slow victory printing
float scr_centertime_off;
int scr_center_lines;
int scr_erase_lines;
int scr_erase_center;
 
/*
==============
SCR_CenterPrint
 
Called for important messages that should stay in the center of the screen
for a few moments
==============
*/
void SCR_CenterPrint (char *str)
{
strncpy (scr_centerstring, str, sizeof(scr_centerstring)-1);
scr_centertime_off = scr_centertime.value;
scr_centertime_start = cl.time;
 
// count the number of lines for centering
scr_center_lines = 1;
while (*str)
{
if (*str == '\n')
scr_center_lines++;
str++;
}
}
 
 
void SCR_DrawCenterString (void)
{
char *start;
int l;
int j;
int x, y;
int remaining;
 
// the finale prints the characters one at a time
if (cl.intermission)
remaining = scr_printspeed.value * (cl.time - scr_centertime_start);
else
remaining = 9999;
 
scr_erase_center = 0;
start = scr_centerstring;
 
if (scr_center_lines <= 4)
y = vid.height*0.35;
else
y = 48;
 
do
{
// scan the width of the line
for (l=0 ; l<40 ; l++)
if (start[l] == '\n' || !start[l])
break;
x = (vid.width - l*8)/2;
for (j=0 ; j<l ; j++, x+=8)
{
Draw_Character (x, y, start[j]);
if (!remaining--)
return;
}
y += 8;
 
while (*start && *start != '\n')
start++;
 
if (!*start)
break;
start++; // skip the \n
} while (1);
}
 
void SCR_CheckDrawCenterString (void)
{
scr_copytop = 1;
if (scr_center_lines > scr_erase_lines)
scr_erase_lines = scr_center_lines;
 
scr_centertime_off -= host_frametime;
if (scr_centertime_off <= 0 && !cl.intermission)
return;
if (key_dest != key_game)
return;
 
SCR_DrawCenterString ();
}
 
//=============================================================================
 
/*
====================
CalcFov
====================
*/
float CalcFov (float fov_x, float width, float height)
{
float a;
float x;
 
if (fov_x < 1 || fov_x > 179)
Sys_Error ("Bad fov: %f", fov_x);
 
x = width/tan(fov_x/360*M_PI);
 
a = atan (height/x);
 
a = a*360/M_PI;
 
return a;
}
 
/*
=================
SCR_CalcRefdef
 
Must be called whenever vid changes
Internal use only
=================
*/
static void SCR_CalcRefdef (void)
{
vrect_t vrect;
float size;
int h;
qboolean full = false;
 
 
scr_fullupdate = 0; // force a background redraw
vid.recalc_refdef = 0;
 
// force the status bar to redraw
Sbar_Changed ();
 
//========================================
// bound viewsize
if (scr_viewsize.value < 30)
Cvar_Set ("viewsize","30");
if (scr_viewsize.value > 120)
Cvar_Set ("viewsize","120");
 
// bound field of view
if (scr_fov.value < 10)
Cvar_Set ("fov","10");
if (scr_fov.value > 170)
Cvar_Set ("fov","170");
 
// intermission is always full screen
if (cl.intermission)
size = 120;
else
size = scr_viewsize.value;
 
if (size >= 120)
sb_lines = 0; // no status bar at all
else if (size >= 110)
sb_lines = 24; // no inventory
else
sb_lines = 24+16+8;
 
if (scr_viewsize.value >= 100.0) {
full = true;
size = 100.0;
} else
size = scr_viewsize.value;
if (cl.intermission)
{
full = true;
size = 100;
sb_lines = 0;
}
size /= 100.0;
 
h = vid.height - sb_lines;
 
r_refdef.vrect.width = vid.width * size;
if (r_refdef.vrect.width < 96)
{
size = 96.0 / r_refdef.vrect.width;
r_refdef.vrect.width = 96; // min for icons
}
 
r_refdef.vrect.height = vid.height * size;
if (r_refdef.vrect.height > vid.height - sb_lines)
r_refdef.vrect.height = vid.height - sb_lines;
if (r_refdef.vrect.height > vid.height)
r_refdef.vrect.height = vid.height;
r_refdef.vrect.x = (vid.width - r_refdef.vrect.width)/2;
if (full)
r_refdef.vrect.y = 0;
else
r_refdef.vrect.y = (h - r_refdef.vrect.height)/2;
 
r_refdef.fov_x = scr_fov.value;
r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height);
 
scr_vrect = r_refdef.vrect;
}
 
 
/*
=================
SCR_SizeUp_f
 
Keybinding command
=================
*/
void SCR_SizeUp_f (void)
{
Cvar_SetValue ("viewsize",scr_viewsize.value+10);
vid.recalc_refdef = 1;
}
 
 
/*
=================
SCR_SizeDown_f
 
Keybinding command
=================
*/
void SCR_SizeDown_f (void)
{
Cvar_SetValue ("viewsize",scr_viewsize.value-10);
vid.recalc_refdef = 1;
}
 
//============================================================================
 
/*
==================
SCR_Init
==================
*/
void SCR_Init (void)
{
 
Cvar_RegisterVariable (&scr_fov);
Cvar_RegisterVariable (&scr_viewsize);
Cvar_RegisterVariable (&scr_conspeed);
Cvar_RegisterVariable (&scr_showram);
Cvar_RegisterVariable (&scr_showturtle);
Cvar_RegisterVariable (&scr_showpause);
Cvar_RegisterVariable (&scr_centertime);
Cvar_RegisterVariable (&scr_printspeed);
Cvar_RegisterVariable (&gl_triplebuffer);
 
//
// register our commands
//
Cmd_AddCommand ("screenshot",SCR_ScreenShot_f);
Cmd_AddCommand ("sizeup",SCR_SizeUp_f);
Cmd_AddCommand ("sizedown",SCR_SizeDown_f);
 
scr_ram = Draw_PicFromWad ("ram");
scr_net = Draw_PicFromWad ("net");
scr_turtle = Draw_PicFromWad ("turtle");
 
scr_initialized = true;
}
 
 
 
/*
==============
SCR_DrawRam
==============
*/
void SCR_DrawRam (void)
{
if (!scr_showram.value)
return;
 
if (!r_cache_thrash)
return;
 
Draw_Pic (scr_vrect.x+32, scr_vrect.y, scr_ram);
}
 
/*
==============
SCR_DrawTurtle
==============
*/
void SCR_DrawTurtle (void)
{
static int count;
if (!scr_showturtle.value)
return;
 
if (host_frametime < 0.1)
{
count = 0;
return;
}
 
count++;
if (count < 3)
return;
 
Draw_Pic (scr_vrect.x, scr_vrect.y, scr_turtle);
}
 
/*
==============
SCR_DrawNet
==============
*/
void SCR_DrawNet (void)
{
if (realtime - cl.last_received_message < 0.3)
return;
if (cls.demoplayback)
return;
 
Draw_Pic (scr_vrect.x+64, scr_vrect.y, scr_net);
}
 
/*
==============
DrawPause
==============
*/
void SCR_DrawPause (void)
{
qpic_t *pic;
 
if (!scr_showpause.value) // turn off for screenshots
return;
 
if (!cl.paused)
return;
 
pic = Draw_CachePic ("gfx/pause.lmp");
Draw_Pic ( (vid.width - pic->width)/2,
(vid.height - 48 - pic->height)/2, pic);
}
 
 
 
/*
==============
SCR_DrawLoading
==============
*/
void SCR_DrawLoading (void)
{
qpic_t *pic;
 
if (!scr_drawloading)
return;
pic = Draw_CachePic ("gfx/loading.lmp");
Draw_Pic ( (vid.width - pic->width)/2,
(vid.height - 48 - pic->height)/2, pic);
}
 
 
 
//=============================================================================
 
 
/*
==================
SCR_SetUpToDrawConsole
==================
*/
void SCR_SetUpToDrawConsole (void)
{
Con_CheckResize ();
if (scr_drawloading)
return; // never a console with loading plaque
// decide on the height of the console
con_forcedup = !cl.worldmodel || cls.signon != SIGNONS;
 
if (con_forcedup)
{
scr_conlines = vid.height; // full screen
scr_con_current = scr_conlines;
}
else if (key_dest == key_console)
scr_conlines = vid.height/2; // half screen
else
scr_conlines = 0; // none visible
if (scr_conlines < scr_con_current)
{
scr_con_current -= scr_conspeed.value*host_frametime;
if (scr_conlines > scr_con_current)
scr_con_current = scr_conlines;
 
}
else if (scr_conlines > scr_con_current)
{
scr_con_current += scr_conspeed.value*host_frametime;
if (scr_conlines < scr_con_current)
scr_con_current = scr_conlines;
}
 
if (clearconsole++ < vid.numpages)
{
Sbar_Changed ();
}
else if (clearnotify++ < vid.numpages)
{
}
else
con_notifylines = 0;
}
/*
==================
SCR_DrawConsole
==================
*/
void SCR_DrawConsole (void)
{
if (scr_con_current)
{
scr_copyeverything = 1;
Con_DrawConsole (scr_con_current, true);
clearconsole = 0;
}
else
{
if (key_dest == key_game || key_dest == key_message)
Con_DrawNotify (); // only draw notify in game
}
}
 
 
/*
==============================================================================
SCREEN SHOTS
==============================================================================
*/
 
typedef struct _TargaHeader {
unsigned char id_length, colormap_type, image_type;
unsigned short colormap_index, colormap_length;
unsigned char colormap_size;
unsigned short x_origin, y_origin, width, height;
unsigned char pixel_size, attributes;
} TargaHeader;
 
 
/*
==================
SCR_ScreenShot_f
==================
*/
void SCR_ScreenShot_f (void)
{
byte *buffer;
char pcxname[80];
char checkname[MAX_OSPATH];
int i, c, temp;
//
// find a file name to save it to
//
strcpy(pcxname,"quake00.tga");
for (i=0 ; i<=99 ; i++)
{
pcxname[5] = i/10 + '0';
pcxname[6] = i%10 + '0';
sprintf (checkname, "%s/%s", com_gamedir, pcxname);
if (Sys_FileTime(checkname) == -1)
break; // file doesn't exist
}
if (i==100)
{
Con_Printf ("SCR_ScreenShot_f: Couldn't create a PCX file\n");
return;
}
 
 
buffer = malloc(glwidth*glheight*3 + 18);
memset (buffer, 0, 18);
buffer[2] = 2; // uncompressed type
buffer[12] = glwidth&255;
buffer[13] = glwidth>>8;
buffer[14] = glheight&255;
buffer[15] = glheight>>8;
buffer[16] = 24; // pixel size
 
glReadPixels (glx, gly, glwidth, glheight, GL_RGB, GL_UNSIGNED_BYTE, buffer+18 );
 
// swap rgb to bgr
c = 18+glwidth*glheight*3;
for (i=18 ; i<c ; i+=3)
{
temp = buffer[i];
buffer[i] = buffer[i+2];
buffer[i+2] = temp;
}
COM_WriteFile (pcxname, buffer, glwidth*glheight*3 + 18 );
 
free (buffer);
Con_Printf ("Wrote %s\n", pcxname);
}
 
 
//=============================================================================
 
 
/*
===============
SCR_BeginLoadingPlaque
 
================
*/
void SCR_BeginLoadingPlaque (void)
{
S_StopAllSounds (true);
 
if (cls.state != ca_connected)
return;
if (cls.signon != SIGNONS)
return;
// redraw with no console and the loading plaque
Con_ClearNotify ();
scr_centertime_off = 0;
scr_con_current = 0;
 
scr_drawloading = true;
scr_fullupdate = 0;
Sbar_Changed ();
SCR_UpdateScreen ();
scr_drawloading = false;
 
scr_disabled_for_loading = true;
scr_disabled_time = realtime;
scr_fullupdate = 0;
}
 
/*
===============
SCR_EndLoadingPlaque
 
================
*/
void SCR_EndLoadingPlaque (void)
{
scr_disabled_for_loading = false;
scr_fullupdate = 0;
Con_ClearNotify ();
}
 
//=============================================================================
 
char *scr_notifystring;
qboolean scr_drawdialog;
 
void SCR_DrawNotifyString (void)
{
char *start;
int l;
int j;
int x, y;
 
start = scr_notifystring;
 
y = vid.height*0.35;
 
do
{
// scan the width of the line
for (l=0 ; l<40 ; l++)
if (start[l] == '\n' || !start[l])
break;
x = (vid.width - l*8)/2;
for (j=0 ; j<l ; j++, x+=8)
Draw_Character (x, y, start[j]);
y += 8;
 
while (*start && *start != '\n')
start++;
 
if (!*start)
break;
start++; // skip the \n
} while (1);
}
 
/*
==================
SCR_ModalMessage
 
Displays a text string in the center of the screen and waits for a Y or N
keypress.
==================
*/
int SCR_ModalMessage (char *text)
{
if (cls.state == ca_dedicated)
return true;
 
scr_notifystring = text;
// draw a fresh screen
scr_fullupdate = 0;
scr_drawdialog = true;
SCR_UpdateScreen ();
scr_drawdialog = false;
S_ClearBuffer (); // so dma doesn't loop current sound
 
do
{
key_count = -1; // wait for a key down and up
Sys_SendKeyEvents ();
} while (key_lastpress != 'y' && key_lastpress != 'n' && key_lastpress != K_ESCAPE);
 
scr_fullupdate = 0;
SCR_UpdateScreen ();
 
return key_lastpress == 'y';
}
 
 
//=============================================================================
 
/*
===============
SCR_BringDownConsole
 
Brings the console down and fades the palettes back to normal
================
*/
void SCR_BringDownConsole (void)
{
int i;
scr_centertime_off = 0;
for (i=0 ; i<20 && scr_conlines != scr_con_current ; i++)
SCR_UpdateScreen ();
 
cl.cshifts[0].percent = 0; // no area contents palette on next frame
VID_SetPalette (host_basepal);
}
 
void SCR_TileClear (void)
{
if (r_refdef.vrect.x > 0) {
// left
Draw_TileClear (0, 0, r_refdef.vrect.x, vid.height - sb_lines);
// right
Draw_TileClear (r_refdef.vrect.x + r_refdef.vrect.width, 0,
vid.width - r_refdef.vrect.x + r_refdef.vrect.width,
vid.height - sb_lines);
}
if (r_refdef.vrect.y > 0) {
// top
Draw_TileClear (r_refdef.vrect.x, 0,
r_refdef.vrect.x + r_refdef.vrect.width,
r_refdef.vrect.y);
// bottom
Draw_TileClear (r_refdef.vrect.x,
r_refdef.vrect.y + r_refdef.vrect.height,
r_refdef.vrect.width,
vid.height - sb_lines -
(r_refdef.vrect.height + r_refdef.vrect.y));
}
}
 
/*
==================
SCR_UpdateScreen
 
This is called every frame, and can also be called explicitly to flush
text to the screen.
 
WARNING: be very careful calling this from elsewhere, because the refresh
needs almost the entire 256k of stack space!
==================
*/
void SCR_UpdateScreen (void)
{
static float oldscr_viewsize;
vrect_t vrect;
 
if (block_drawing)
return;
 
vid.numpages = 2 + gl_triplebuffer.value;
 
scr_copytop = 0;
scr_copyeverything = 0;
 
if (scr_disabled_for_loading)
{
if (realtime - scr_disabled_time > 60)
{
scr_disabled_for_loading = false;
Con_Printf ("load failed.\n");
}
else
return;
}
 
if (!scr_initialized || !con_initialized)
return; // not initialized yet
 
 
GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
//
// determine size of refresh window
//
if (oldfov != scr_fov.value)
{
oldfov = scr_fov.value;
vid.recalc_refdef = true;
}
 
if (oldscreensize != scr_viewsize.value)
{
oldscreensize = scr_viewsize.value;
vid.recalc_refdef = true;
}
 
if (vid.recalc_refdef)
SCR_CalcRefdef ();
 
//
// do 3D refresh drawing, and then update the screen
//
SCR_SetUpToDrawConsole ();
V_RenderView ();
 
GL_Set2D ();
 
//
// draw any areas not covered by the refresh
//
SCR_TileClear ();
 
if (scr_drawdialog)
{
Sbar_Draw ();
Draw_FadeScreen ();
SCR_DrawNotifyString ();
scr_copyeverything = true;
}
else if (scr_drawloading)
{
SCR_DrawLoading ();
Sbar_Draw ();
}
else if (cl.intermission == 1 && key_dest == key_game)
{
Sbar_IntermissionOverlay ();
}
else if (cl.intermission == 2 && key_dest == key_game)
{
Sbar_FinaleOverlay ();
SCR_CheckDrawCenterString ();
}
else
{
if (crosshair.value)
Draw_Character (scr_vrect.x + scr_vrect.width/2, scr_vrect.y + scr_vrect.height/2, '+');
SCR_DrawRam ();
SCR_DrawNet ();
SCR_DrawTurtle ();
SCR_DrawPause ();
SCR_CheckDrawCenterString ();
Sbar_Draw ();
SCR_DrawConsole ();
M_Draw ();
}
 
V_UpdatePalette ();
 
GL_EndRendering ();
}
 
/contrib/other/sdlquake-1.0.9/gl_test.c
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
/contrib/other/sdlquake-1.0.9/gl_vidlinux.c
0,0 → 1,866
/*
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 <termios.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/vt.h>
#include <stdarg.h>
#include <stdio.h>
#include <signal.h>
 
#include <asm/io.h>
#include <dlfcn.h>
 
/*#include "vga.h" */
#include "vgakeyboard.h"
#include "vgamouse.h"
 
#include "quakedef.h"
#include "GL/fxmesa.h"
 
#define WARP_WIDTH 320
#define WARP_HEIGHT 200
 
static fxMesaContext fc = NULL;
#define stringify(m) { #m, m }
 
unsigned short d_8to16table[256];
unsigned d_8to24table[256];
unsigned char d_15to8table[65536];
 
int num_shades=32;
 
struct
{
char *name;
int num;
} mice[] =
{
stringify(MOUSE_MICROSOFT),
stringify(MOUSE_MOUSESYSTEMS),
stringify(MOUSE_MMSERIES),
stringify(MOUSE_LOGITECH),
stringify(MOUSE_BUSMOUSE),
stringify(MOUSE_PS2),
};
 
static unsigned char scantokey[128];
 
int num_mice = sizeof (mice) / sizeof(mice[0]);
 
int d_con_indirect = 0;
 
int svgalib_inited=0;
int UseMouse = 1;
int UseKeyboard = 1;
 
int mouserate = MOUSE_DEFAULTSAMPLERATE;
 
cvar_t vid_mode = {"vid_mode","5",false};
cvar_t vid_redrawfull = {"vid_redrawfull","0",false};
cvar_t vid_waitforrefresh = {"vid_waitforrefresh","0",true};
char *framebuffer_ptr;
 
cvar_t mouse_button_commands[3] =
{
{"mouse1","+attack"},
{"mouse2","+strafe"},
{"mouse3","+forward"},
};
 
int mouse_buttons;
int mouse_buttonstate;
int mouse_oldbuttonstate;
float mouse_x, mouse_y;
float old_mouse_x, old_mouse_y;
int mx, my;
 
cvar_t m_filter = {"m_filter","1"};
 
int scr_width, scr_height;
 
/*-----------------------------------------------------------------------*/
 
//int texture_mode = GL_NEAREST;
//int texture_mode = GL_NEAREST_MIPMAP_NEAREST;
//int texture_mode = GL_NEAREST_MIPMAP_LINEAR;
int texture_mode = GL_LINEAR;
//int texture_mode = GL_LINEAR_MIPMAP_NEAREST;
//int texture_mode = GL_LINEAR_MIPMAP_LINEAR;
 
int texture_extension_number = 1;
 
float gldepthmin, gldepthmax;
 
cvar_t gl_ztrick = {"gl_ztrick","1"};
 
const char *gl_vendor;
const char *gl_renderer;
const char *gl_version;
const char *gl_extensions;
 
void (*qgl3DfxSetPaletteEXT) (GLuint *);
void (*qglColorTableEXT) (int, int, int, int, int, const void *);
 
static float vid_gamma = 1.0;
 
qboolean is8bit = false;
qboolean isPermedia = false;
qboolean gl_mtexable = false;
 
/*-----------------------------------------------------------------------*/
void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
{
}
 
void D_EndDirectRect (int x, int y, int width, int height)
{
}
 
int matchmouse(int mouse, char *name)
{
int i;
for (i=0 ; i<num_mice ; i++)
if (!strcmp(mice[i].name, name))
return i;
return mouse;
}
 
#if 0
 
void vtswitch(int newconsole)
{
 
int fd;
struct vt_stat x;
 
// switch consoles and wait until reactivated
fd = open("/dev/console", O_RDONLY);
ioctl(fd, VT_GETSTATE, &x);
ioctl(fd, VT_ACTIVATE, newconsole);
ioctl(fd, VT_WAITACTIVE, x.v_active);
close(fd);
 
}
 
#endif
 
void keyhandler(int scancode, int state)
{
int sc;
 
sc = scancode & 0x7f;
 
Key_Event(scantokey[sc], state == KEY_EVENTPRESS);
 
}
 
void VID_Shutdown(void)
{
if (!fc)
return;
 
fxMesaDestroyContext(fc);
 
if (UseKeyboard)
keyboard_close();
}
 
void signal_handler(int sig)
{
printf("Received signal %d, exiting...\n", sig);
Sys_Quit();
exit(0);
}
 
void InitSig(void)
{
signal(SIGHUP, signal_handler);
signal(SIGINT, signal_handler);
signal(SIGQUIT, signal_handler);
signal(SIGILL, signal_handler);
signal(SIGTRAP, signal_handler);
signal(SIGIOT, signal_handler);
signal(SIGBUS, signal_handler);
signal(SIGFPE, signal_handler);
signal(SIGSEGV, signal_handler);
signal(SIGTERM, signal_handler);
}
 
void VID_ShiftPalette(unsigned char *p)
{
// VID_SetPalette(p);
}
 
void VID_SetPalette (unsigned char *palette)
{
byte *pal;
unsigned r,g,b;
unsigned v;
int r1,g1,b1;
int j,k,l,m;
unsigned short i;
unsigned *table;
FILE *f;
char s[255];
int dist, bestdist;
static qboolean palflag = false;
 
//
// 8 8 8 encoding
//
pal = palette;
table = d_8to24table;
for (i=0 ; i<256 ; i++)
{
r = pal[0];
g = pal[1];
b = pal[2];
pal += 3;
v = (255<<24) + (r<<0) + (g<<8) + (b<<16);
*table++ = v;
}
d_8to24table[255] &= 0xffffff; // 255 is transparent
 
// JACK: 3D distance calcs - k is last closest, l is the distance.
for (i=0; i < (1<<15); i++) {
/* Maps
000000000000000
000000000011111 = Red = 0x1F
000001111100000 = Blue = 0x03E0
111110000000000 = Grn = 0x7C00
*/
r = ((i & 0x1F) << 3)+4;
g = ((i & 0x03E0) >> 2)+4;
b = ((i & 0x7C00) >> 7)+4;
pal = (unsigned char *)d_8to24table;
for (v=0,k=0,bestdist=10000*10000; v<256; v++,pal+=4) {
r1 = (int)r - (int)pal[0];
g1 = (int)g - (int)pal[1];
b1 = (int)b - (int)pal[2];
dist = (r1*r1)+(g1*g1)+(b1*b1);
if (dist < bestdist) {
k=v;
bestdist = dist;
}
}
d_15to8table[i]=k;
}
}
 
void CheckMultiTextureExtensions(void)
{
void *prjobj;
 
if (strstr(gl_extensions, "GL_SGIS_multitexture ") && !COM_CheckParm("-nomtex")) {
Con_Printf("Found GL_SGIS_multitexture...\n");
 
if ((prjobj = dlopen(NULL, RTLD_LAZY)) == NULL) {
Con_Printf("Unable to open symbol list for main program.\n");
return;
}
 
qglMTexCoord2fSGIS = (void *) dlsym(prjobj, "glMTexCoord2fSGIS");
qglSelectTextureSGIS = (void *) dlsym(prjobj, "glSelectTextureSGIS");
 
if (qglMTexCoord2fSGIS && qglSelectTextureSGIS) {
Con_Printf("Multitexture extensions found.\n");
gl_mtexable = true;
} else
Con_Printf("Symbol not found, disabled.\n");
 
dlclose(prjobj);
}
}
 
/*
===============
GL_Init
===============
*/
void GL_Init (void)
{
gl_vendor = glGetString (GL_VENDOR);
Con_Printf ("GL_VENDOR: %s\n", gl_vendor);
gl_renderer = glGetString (GL_RENDERER);
Con_Printf ("GL_RENDERER: %s\n", gl_renderer);
 
gl_version = glGetString (GL_VERSION);
Con_Printf ("GL_VERSION: %s\n", gl_version);
gl_extensions = glGetString (GL_EXTENSIONS);
Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions);
 
// Con_Printf ("%s %s\n", gl_renderer, gl_version);
 
CheckMultiTextureExtensions ();
 
glClearColor (1,0,0,0);
glCullFace(GL_FRONT);
glEnable(GL_TEXTURE_2D);
 
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.666);
 
glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
glShadeModel (GL_FLAT);
 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
 
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
}
 
/*
=================
GL_BeginRendering
 
=================
*/
void GL_BeginRendering (int *x, int *y, int *width, int *height)
{
extern cvar_t gl_clear;
 
*x = *y = 0;
*width = scr_width;
*height = scr_height;
 
// if (!wglMakeCurrent( maindc, baseRC ))
// Sys_Error ("wglMakeCurrent failed");
 
// glViewport (*x, *y, *width, *height);
}
 
 
void GL_EndRendering (void)
{
glFlush();
fxMesaSwapBuffers();
}
 
void Init_KBD(void)
{
int i;
 
if (COM_CheckParm("-nokbd")) UseKeyboard = 0;
 
if (UseKeyboard)
{
for (i=0 ; i<128 ; i++)
scantokey[i] = ' ';
 
scantokey[42] = K_SHIFT;
scantokey[54] = K_SHIFT;
scantokey[72] = K_UPARROW;
scantokey[103] = K_UPARROW;
scantokey[80] = K_DOWNARROW;
scantokey[108] = K_DOWNARROW;
scantokey[75] = K_LEFTARROW;
scantokey[105] = K_LEFTARROW;
scantokey[77] = K_RIGHTARROW;
scantokey[106] = K_RIGHTARROW;
scantokey[29] = K_CTRL;
scantokey[97] = K_CTRL;
scantokey[56] = K_ALT;
scantokey[100] = K_ALT;
// scantokey[58] = JK_CAPS;
// scantokey[69] = JK_NUM_LOCK;
scantokey[71] = K_HOME;
scantokey[73] = K_PGUP;
scantokey[79] = K_END;
scantokey[81] = K_PGDN;
scantokey[82] = K_INS;
scantokey[83] = K_DEL;
scantokey[1 ] = K_ESCAPE;
scantokey[28] = K_ENTER;
scantokey[15] = K_TAB;
scantokey[14] = K_BACKSPACE;
scantokey[119] = K_PAUSE;
scantokey[57] = ' ';
 
scantokey[102] = K_HOME;
scantokey[104] = K_PGUP;
scantokey[107] = K_END;
scantokey[109] = K_PGDN;
scantokey[110] = K_INS;
scantokey[111] = K_DEL;
 
scantokey[2] = '1';
scantokey[3] = '2';
scantokey[4] = '3';
scantokey[5] = '4';
scantokey[6] = '5';
scantokey[7] = '6';
scantokey[8] = '7';
scantokey[9] = '8';
scantokey[10] = '9';
scantokey[11] = '0';
scantokey[12] = '-';
scantokey[13] = '=';
scantokey[41] = '`';
scantokey[26] = '[';
scantokey[27] = ']';
scantokey[39] = ';';
scantokey[40] = '\'';
scantokey[51] = ',';
scantokey[52] = '.';
scantokey[53] = '/';
scantokey[43] = '\\';
 
scantokey[59] = K_F1;
scantokey[60] = K_F2;
scantokey[61] = K_F3;
scantokey[62] = K_F4;
scantokey[63] = K_F5;
scantokey[64] = K_F6;
scantokey[65] = K_F7;
scantokey[66] = K_F8;
scantokey[67] = K_F9;
scantokey[68] = K_F10;
scantokey[87] = K_F11;
scantokey[88] = K_F12;
scantokey[30] = 'a';
scantokey[48] = 'b';
scantokey[46] = 'c';
scantokey[32] = 'd';
scantokey[18] = 'e';
scantokey[33] = 'f';
scantokey[34] = 'g';
scantokey[35] = 'h';
scantokey[23] = 'i';
scantokey[36] = 'j';
scantokey[37] = 'k';
scantokey[38] = 'l';
scantokey[50] = 'm';
scantokey[49] = 'n';
scantokey[24] = 'o';
scantokey[25] = 'p';
scantokey[16] = 'q';
scantokey[19] = 'r';
scantokey[31] = 's';
scantokey[20] = 't';
scantokey[22] = 'u';
scantokey[47] = 'v';
scantokey[17] = 'w';
scantokey[45] = 'x';
scantokey[21] = 'y';
scantokey[44] = 'z';
 
scantokey[78] = '+';
scantokey[74] = '-';
 
if (keyboard_init())
Sys_Error("keyboard_init() failed");
keyboard_seteventhandler(keyhandler);
}
}
 
#define NUM_RESOLUTIONS 16
 
static int resolutions[NUM_RESOLUTIONS][3]={
320,200, GR_RESOLUTION_320x200,
320,240, GR_RESOLUTION_320x240,
400,256, GR_RESOLUTION_400x256,
400,300, GR_RESOLUTION_400x300,
512,384, GR_RESOLUTION_512x384,
640,200, GR_RESOLUTION_640x200,
640,350, GR_RESOLUTION_640x350,
640,400, GR_RESOLUTION_640x400,
640,480, GR_RESOLUTION_640x480,
800,600, GR_RESOLUTION_800x600,
960,720, GR_RESOLUTION_960x720,
856,480, GR_RESOLUTION_856x480,
512,256, GR_RESOLUTION_512x256,
1024,768, GR_RESOLUTION_1024x768,
1280,1024,GR_RESOLUTION_1280x1024,
1600,1200,GR_RESOLUTION_1600x1200
};
 
int findres(int *width, int *height)
{
int i;
 
for(i=0;i<NUM_RESOLUTIONS;i++)
if((*width<=resolutions[i][0]) && (*height<=resolutions[i][1])) {
*width = resolutions[i][0];
*height = resolutions[i][1];
return resolutions[i][2];
}
*width = 640;
*height = 480;
return GR_RESOLUTION_640x480;
}
 
qboolean VID_Is8bit(void)
{
return is8bit;
}
 
void VID_Init8bitPalette(void)
{
// Check for 8bit Extensions and initialize them.
int i;
void *prjobj;
 
if (COM_CheckParm("-no8bit"))
return;
 
if ((prjobj = dlopen(NULL, RTLD_LAZY)) == NULL) {
Con_Printf("Unable to open symbol list for main program.\n");
return;
}
 
if (strstr(gl_extensions, "3DFX_set_global_palette") &&
(qgl3DfxSetPaletteEXT = dlsym(prjobj, "gl3DfxSetPaletteEXT")) != NULL) {
GLubyte table[256][4];
char *oldpal;
 
Con_SafePrintf("... Using 3DFX_set_global_palette\n");
glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
oldpal = (char *) d_8to24table; //d_8to24table3dfx;
for (i=0;i<256;i++) {
table[i][2] = *oldpal++;
table[i][1] = *oldpal++;
table[i][0] = *oldpal++;
table[i][3] = 255;
oldpal++;
}
qgl3DfxSetPaletteEXT((GLuint *)table);
is8bit = true;
 
} else if (strstr(gl_extensions, "GL_EXT_shared_texture_palette") &&
(qglColorTableEXT = dlsym(prjobj, "glColorTableEXT")) != NULL) {
char thePalette[256*3];
char *oldPalette, *newPalette;
 
Con_SafePrintf("... Using GL_EXT_shared_texture_palette\n");
glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
oldPalette = (char *) d_8to24table; //d_8to24table3dfx;
newPalette = thePalette;
for (i=0;i<256;i++) {
*newPalette++ = *oldPalette++;
*newPalette++ = *oldPalette++;
*newPalette++ = *oldPalette++;
oldPalette++;
}
qglColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE, (void *) thePalette);
is8bit = true;
}
 
dlclose(prjobj);
}
 
static void Check_Gamma (unsigned char *pal)
{
float f, inf;
unsigned char palette[768];
int i;
 
if ((i = COM_CheckParm("-gamma")) == 0) {
if ((gl_renderer && strstr(gl_renderer, "Voodoo")) ||
(gl_vendor && strstr(gl_vendor, "3Dfx")))
vid_gamma = 1;
else
vid_gamma = 0.7; // default to 0.7 on non-3dfx hardware
} else
vid_gamma = Q_atof(com_argv[i+1]);
 
for (i=0 ; i<768 ; i++)
{
f = pow ( (pal[i]+1)/256.0 , vid_gamma );
inf = f*255 + 0.5;
if (inf < 0)
inf = 0;
if (inf > 255)
inf = 255;
palette[i] = inf;
}
 
memcpy (pal, palette, sizeof(palette));
}
 
void VID_Init(unsigned char *palette)
{
int i;
GLint attribs[32];
char gldir[MAX_OSPATH];
int width = 640, height = 480;
 
Init_KBD();
 
Cvar_RegisterVariable (&vid_mode);
Cvar_RegisterVariable (&vid_redrawfull);
Cvar_RegisterVariable (&vid_waitforrefresh);
Cvar_RegisterVariable (&gl_ztrick);
vid.maxwarpwidth = WARP_WIDTH;
vid.maxwarpheight = WARP_HEIGHT;
vid.colormap = host_colormap;
vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
 
// interpret command-line params
 
// set vid parameters
attribs[0] = FXMESA_DOUBLEBUFFER;
attribs[1] = FXMESA_ALPHA_SIZE;
attribs[2] = 1;
attribs[3] = FXMESA_DEPTH_SIZE;
attribs[4] = 1;
attribs[5] = FXMESA_NONE;
 
if ((i = COM_CheckParm("-width")) != 0)
width = atoi(com_argv[i+1]);
if ((i = COM_CheckParm("-height")) != 0)
height = atoi(com_argv[i+1]);
 
if ((i = COM_CheckParm("-conwidth")) != 0)
vid.conwidth = Q_atoi(com_argv[i+1]);
else
vid.conwidth = 640;
 
vid.conwidth &= 0xfff8; // make it a multiple of eight
 
if (vid.conwidth < 320)
vid.conwidth = 320;
 
// pick a conheight that matches with correct aspect
vid.conheight = vid.conwidth*3 / 4;
 
if ((i = COM_CheckParm("-conheight")) != 0)
vid.conheight = Q_atoi(com_argv[i+1]);
if (vid.conheight < 200)
vid.conheight = 200;
 
fc = fxMesaCreateContext(0, findres(&width, &height), GR_REFRESH_75Hz,
attribs);
if (!fc)
Sys_Error("Unable to create 3DFX context.\n");
 
InitSig(); // trap evil signals
 
scr_width = width;
scr_height = height;
 
fxMesaMakeCurrent(fc);
 
if (vid.conheight > height)
vid.conheight = height;
if (vid.conwidth > width)
vid.conwidth = width;
vid.width = vid.conwidth;
vid.height = vid.conheight;
 
vid.aspect = ((float)vid.height / (float)vid.width) *
(320.0 / 240.0);
vid.numpages = 2;
 
GL_Init();
 
sprintf (gldir, "%s/glquake", com_gamedir);
Sys_mkdir (gldir);
 
Check_Gamma(palette);
VID_SetPalette(palette);
 
// Check for 3DFX Extensions and initialize them.
VID_Init8bitPalette();
 
Con_SafePrintf ("Video mode %dx%d initialized.\n", width, height);
 
vid.recalc_refdef = 1; // force a surface cache flush
}
 
void Sys_SendKeyEvents(void)
{
if (UseKeyboard)
while (keyboard_update());
}
 
void Force_CenterView_f (void)
{
cl.viewangles[PITCH] = 0;
}
 
 
void mousehandler(int buttonstate, int dx, int dy)
{
mouse_buttonstate = buttonstate;
mx += dx;
my += dy;
}
 
void IN_Init(void)
{
 
int mtype;
char *mousedev;
int mouserate;
 
if (UseMouse)
{
 
Cvar_RegisterVariable (&mouse_button_commands[0]);
Cvar_RegisterVariable (&mouse_button_commands[1]);
Cvar_RegisterVariable (&mouse_button_commands[2]);
Cmd_AddCommand ("force_centerview", Force_CenterView_f);
 
mouse_buttons = 3;
 
mtype = vga_getmousetype();
 
mousedev = "/dev/mouse";
if (getenv("MOUSEDEV")) mousedev = getenv("MOUSEDEV");
if (COM_CheckParm("-mdev"))
mousedev = com_argv[COM_CheckParm("-mdev")+1];
 
mouserate = 1200;
if (getenv("MOUSERATE")) mouserate = atoi(getenv("MOUSERATE"));
if (COM_CheckParm("-mrate"))
mouserate = atoi(com_argv[COM_CheckParm("-mrate")+1]);
 
if (mouse_init(mousedev, mtype, mouserate))
{
Con_Printf("No mouse found\n");
UseMouse = 0;
}
else
mouse_seteventhandler(mousehandler);
 
}
 
}
 
void IN_Shutdown(void)
{
if (UseMouse)
mouse_close();
}
 
/*
===========
IN_Commands
===========
*/
void IN_Commands (void)
{
if (UseMouse && cls.state != ca_dedicated)
{
// poll mouse values
while (mouse_update())
;
 
// perform button actions
if ((mouse_buttonstate & MOUSE_LEFTBUTTON) &&
!(mouse_oldbuttonstate & MOUSE_LEFTBUTTON))
Key_Event (K_MOUSE1, true);
else if (!(mouse_buttonstate & MOUSE_LEFTBUTTON) &&
(mouse_oldbuttonstate & MOUSE_LEFTBUTTON))
Key_Event (K_MOUSE1, false);
 
if ((mouse_buttonstate & MOUSE_RIGHTBUTTON) &&
!(mouse_oldbuttonstate & MOUSE_RIGHTBUTTON))
Key_Event (K_MOUSE2, true);
else if (!(mouse_buttonstate & MOUSE_RIGHTBUTTON) &&
(mouse_oldbuttonstate & MOUSE_RIGHTBUTTON))
Key_Event (K_MOUSE2, false);
 
if ((mouse_buttonstate & MOUSE_MIDDLEBUTTON) &&
!(mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON))
Key_Event (K_MOUSE3, true);
else if (!(mouse_buttonstate & MOUSE_MIDDLEBUTTON) &&
(mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON))
Key_Event (K_MOUSE3, false);
 
mouse_oldbuttonstate = mouse_buttonstate;
}
}
 
/*
===========
IN_Move
===========
*/
void IN_MouseMove (usercmd_t *cmd)
{
if (!UseMouse)
return;
 
// poll mouse values
while (mouse_update())
;
 
if (m_filter.value)
{
mouse_x = (mx + old_mouse_x) * 0.5;
mouse_y = (my + old_mouse_y) * 0.5;
}
else
{
mouse_x = mx;
mouse_y = my;
}
old_mouse_x = mx;
old_mouse_y = my;
mx = my = 0; // clear for next update
 
mouse_x *= sensitivity.value;
mouse_y *= sensitivity.value;
 
// add mouse X/Y movement to cmd
if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
cmd->sidemove += m_side.value * mouse_x;
else
cl.viewangles[YAW] -= m_yaw.value * mouse_x;
if (in_mlook.state & 1)
V_StopPitchDrift ();
if ( (in_mlook.state & 1) && !(in_strafe.state & 1))
{
cl.viewangles[PITCH] += m_pitch.value * mouse_y;
if (cl.viewangles[PITCH] > 80)
cl.viewangles[PITCH] = 80;
if (cl.viewangles[PITCH] < -70)
cl.viewangles[PITCH] = -70;
}
else
{
if ((in_strafe.state & 1) && noclip_anglehack)
cmd->upmove -= m_forward.value * mouse_y;
else
cmd->forwardmove -= m_forward.value * mouse_y;
}
}
 
void IN_Move (usercmd_t *cmd)
{
IN_MouseMove(cmd);
}
 
 
/contrib/other/sdlquake-1.0.9/gl_vidlinuxglx.c
0,0 → 1,997
/*
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 <termios.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/vt.h>
#include <stdarg.h>
#include <stdio.h>
#include <signal.h>
 
#include <dlfcn.h>
 
#include "quakedef.h"
 
#include <GL/glx.h>
 
#include <X11/keysym.h>
#include <X11/cursorfont.h>
 
#include <X11/extensions/xf86dga.h>
#include <X11/extensions/xf86vmode.h>
 
#define WARP_WIDTH 320
#define WARP_HEIGHT 200
 
static Display *dpy = NULL;
static int scrnum;
static Window win;
static GLXContext ctx = NULL;
 
#define KEY_MASK (KeyPressMask | KeyReleaseMask)
#define MOUSE_MASK (ButtonPressMask | ButtonReleaseMask | \
PointerMotionMask | ButtonMotionMask )
#define X_MASK (KEY_MASK | MOUSE_MASK | VisibilityChangeMask | StructureNotifyMask )
 
 
unsigned short d_8to16table[256];
unsigned d_8to24table[256];
unsigned char d_15to8table[65536];
 
cvar_t vid_mode = {"vid_mode","0",false};
static qboolean mouse_avail;
static qboolean mouse_active;
static int mx, my;
static int old_mouse_x, old_mouse_y;
 
static cvar_t in_mouse = {"in_mouse", "1", false};
static cvar_t in_dgamouse = {"in_dgamouse", "1", false};
static cvar_t m_filter = {"m_filter", "0"};
 
qboolean dgamouse = false;
qboolean vidmode_ext = false;
 
static int win_x, win_y;
 
static int scr_width, scr_height;
 
static XF86VidModeModeInfo **vidmodes;
static int default_dotclock_vidmode;
static int num_vidmodes;
static qboolean vidmode_active = false;
 
/*-----------------------------------------------------------------------*/
 
//int texture_mode = GL_NEAREST;
//int texture_mode = GL_NEAREST_MIPMAP_NEAREST;
//int texture_mode = GL_NEAREST_MIPMAP_LINEAR;
int texture_mode = GL_LINEAR;
//int texture_mode = GL_LINEAR_MIPMAP_NEAREST;
//int texture_mode = GL_LINEAR_MIPMAP_LINEAR;
 
int texture_extension_number = 1;
 
float gldepthmin, gldepthmax;
 
cvar_t gl_ztrick = {"gl_ztrick","1"};
 
const char *gl_vendor;
const char *gl_renderer;
const char *gl_version;
const char *gl_extensions;
 
void (*qglColorTableEXT) (int, int, int, int, int, const void*);
void (*qgl3DfxSetPaletteEXT) (GLuint *);
 
static float vid_gamma = 1.0;
 
qboolean is8bit = false;
qboolean isPermedia = false;
qboolean gl_mtexable = false;
 
/*-----------------------------------------------------------------------*/
void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
{
}
 
void D_EndDirectRect (int x, int y, int width, int height)
{
}
 
static int XLateKey(XKeyEvent *ev)
{
 
int key;
char buf[64];
KeySym keysym;
 
key = 0;
 
XLookupString(ev, buf, sizeof buf, &keysym, 0);
 
switch(keysym)
{
case XK_KP_Page_Up:
case XK_Page_Up: key = K_PGUP; break;
 
case XK_KP_Page_Down:
case XK_Page_Down: key = K_PGDN; break;
 
case XK_KP_Home:
case XK_Home: key = K_HOME; break;
 
case XK_KP_End:
case XK_End: key = K_END; break;
 
case XK_KP_Left:
case XK_Left: key = K_LEFTARROW; break;
 
case XK_KP_Right:
case XK_Right: key = K_RIGHTARROW; break;
 
case XK_KP_Down:
case XK_Down: key = K_DOWNARROW; break;
 
case XK_KP_Up:
case XK_Up: key = K_UPARROW; break;
 
case XK_Escape: key = K_ESCAPE; break;
 
case XK_KP_Enter:
case XK_Return: key = K_ENTER; break;
 
case XK_Tab: key = K_TAB; break;
 
case XK_F1: key = K_F1; break;
 
case XK_F2: key = K_F2; break;
 
case XK_F3: key = K_F3; break;
 
case XK_F4: key = K_F4; break;
 
case XK_F5: key = K_F5; break;
 
case XK_F6: key = K_F6; break;
 
case XK_F7: key = K_F7; break;
 
case XK_F8: key = K_F8; break;
 
case XK_F9: key = K_F9; break;
 
case XK_F10: key = K_F10; break;
 
case XK_F11: key = K_F11; break;
 
case XK_F12: key = K_F12; break;
 
case XK_BackSpace: key = K_BACKSPACE; break;
 
case XK_KP_Delete:
case XK_Delete: key = K_DEL; break;
 
case XK_Pause: key = K_PAUSE; break;
 
case XK_Shift_L:
case XK_Shift_R: key = K_SHIFT; break;
 
case XK_Execute:
case XK_Control_L:
case XK_Control_R: key = K_CTRL; break;
 
case XK_Alt_L:
case XK_Meta_L:
case XK_Alt_R:
case XK_Meta_R: key = K_ALT; break;
 
case XK_KP_Begin: key = '5'; break;
 
case XK_KP_Insert:
case XK_Insert:key = K_INS; break;
 
case XK_KP_Multiply: key = '*'; break;
case XK_KP_Add: key = '+'; break;
case XK_KP_Subtract: key = '-'; break;
case XK_KP_Divide: key = '/'; break;
 
#if 0
case 0x021: key = '1';break;/* [!] */
case 0x040: key = '2';break;/* [@] */
case 0x023: key = '3';break;/* [#] */
case 0x024: key = '4';break;/* [$] */
case 0x025: key = '5';break;/* [%] */
case 0x05e: key = '6';break;/* [^] */
case 0x026: key = '7';break;/* [&] */
case 0x02a: key = '8';break;/* [*] */
case 0x028: key = '9';;break;/* [(] */
case 0x029: key = '0';break;/* [)] */
case 0x05f: key = '-';break;/* [_] */
case 0x02b: key = '=';break;/* [+] */
case 0x07c: key = '\'';break;/* [|] */
case 0x07d: key = '[';break;/* [}] */
case 0x07b: key = ']';break;/* [{] */
case 0x022: key = '\'';break;/* ["] */
case 0x03a: key = ';';break;/* [:] */
case 0x03f: key = '/';break;/* [?] */
case 0x03e: key = '.';break;/* [>] */
case 0x03c: key = ',';break;/* [<] */
#endif
 
default:
key = *(unsigned char*)buf;
if (key >= 'A' && key <= 'Z')
key = key - 'A' + 'a';
break;
}
 
return key;
}
 
static Cursor CreateNullCursor(Display *display, Window root)
{
Pixmap cursormask;
XGCValues xgc;
GC gc;
XColor dummycolour;
Cursor cursor;
 
cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
xgc.function = GXclear;
gc = XCreateGC(display, cursormask, GCFunction, &xgc);
XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
dummycolour.pixel = 0;
dummycolour.red = 0;
dummycolour.flags = 04;
cursor = XCreatePixmapCursor(display, cursormask, cursormask,
&dummycolour,&dummycolour, 0,0);
XFreePixmap(display,cursormask);
XFreeGC(display,gc);
return cursor;
}
 
static void install_grabs(void)
{
 
// inviso cursor
XDefineCursor(dpy, win, CreateNullCursor(dpy, win));
 
XGrabPointer(dpy, win,
True,
0,
GrabModeAsync, GrabModeAsync,
win,
None,
CurrentTime);
 
if (in_dgamouse.value) {
int MajorVersion, MinorVersion;
 
if (!XF86DGAQueryVersion(dpy, &MajorVersion, &MinorVersion)) {
// unable to query, probalby not supported
Con_Printf( "Failed to detect XF86DGA Mouse\n" );
in_dgamouse.value = 0;
} else {
dgamouse = true;
XF86DGADirectVideo(dpy, DefaultScreen(dpy), XF86DGADirectMouse);
XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0);
}
} else {
XWarpPointer(dpy, None, win,
0, 0, 0, 0,
vid.width / 2, vid.height / 2);
}
 
XGrabKeyboard(dpy, win,
False,
GrabModeAsync, GrabModeAsync,
CurrentTime);
 
mouse_active = true;
 
// XSync(dpy, True);
}
 
static void uninstall_grabs(void)
{
if (!dpy || !win)
return;
 
if (dgamouse) {
dgamouse = false;
XF86DGADirectVideo(dpy, DefaultScreen(dpy), 0);
}
 
XUngrabPointer(dpy, CurrentTime);
XUngrabKeyboard(dpy, CurrentTime);
 
// inviso cursor
XUndefineCursor(dpy, win);
 
mouse_active = false;
}
 
static void HandleEvents(void)
{
XEvent event;
KeySym ks;
int b;
qboolean dowarp = false;
int mwx = vid.width/2;
int mwy = vid.height/2;
 
if (!dpy)
return;
 
while (XPending(dpy)) {
XNextEvent(dpy, &event);
 
switch (event.type) {
case KeyPress:
case KeyRelease:
Key_Event(XLateKey(&event.xkey), event.type == KeyPress);
break;
 
case MotionNotify:
if (mouse_active) {
if (dgamouse) {
mx += (event.xmotion.x + win_x) * 2;
my += (event.xmotion.y + win_y) * 2;
}
else
{
mx += ((int)event.xmotion.x - mwx) * 2;
my += ((int)event.xmotion.y - mwy) * 2;
mwx = event.xmotion.x;
mwy = event.xmotion.y;
 
if (mx || my)
dowarp = true;
}
}
break;
 
break;
 
case ButtonPress:
b=-1;
if (event.xbutton.button == 1)
b = 0;
else if (event.xbutton.button == 2)
b = 2;
else if (event.xbutton.button == 3)
b = 1;
if (b>=0)
Key_Event(K_MOUSE1 + b, true);
break;
 
case ButtonRelease:
b=-1;
if (event.xbutton.button == 1)
b = 0;
else if (event.xbutton.button == 2)
b = 2;
else if (event.xbutton.button == 3)
b = 1;
if (b>=0)
Key_Event(K_MOUSE1 + b, false);
break;
 
case CreateNotify :
win_x = event.xcreatewindow.x;
win_y = event.xcreatewindow.y;
break;
 
case ConfigureNotify :
win_x = event.xconfigure.x;
win_y = event.xconfigure.y;
break;
}
}
 
if (dowarp) {
/* move the mouse to the window center again */
XWarpPointer(dpy, None, win, 0, 0, 0, 0, vid.width / 2, vid.height / 2);
}
 
}
 
static void IN_DeactivateMouse( void )
{
if (!mouse_avail || !dpy || !win)
return;
 
if (mouse_active) {
uninstall_grabs();
mouse_active = false;
}
}
 
static void IN_ActivateMouse( void )
{
if (!mouse_avail || !dpy || !win)
return;
 
if (!mouse_active) {
mx = my = 0; // don't spazz
install_grabs();
mouse_active = true;
}
}
 
 
void VID_Shutdown(void)
{
if (!ctx || !dpy)
return;
IN_DeactivateMouse();
if (dpy) {
if (ctx)
glXDestroyContext(dpy, ctx);
if (win)
XDestroyWindow(dpy, win);
if (vidmode_active)
XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[0]);
XCloseDisplay(dpy);
}
vidmode_active = false;
dpy = NULL;
win = 0;
ctx = NULL;
}
 
void signal_handler(int sig)
{
printf("Received signal %d, exiting...\n", sig);
Sys_Quit();
exit(0);
}
 
void InitSig(void)
{
signal(SIGHUP, signal_handler);
signal(SIGINT, signal_handler);
signal(SIGQUIT, signal_handler);
signal(SIGILL, signal_handler);
signal(SIGTRAP, signal_handler);
signal(SIGIOT, signal_handler);
signal(SIGBUS, signal_handler);
signal(SIGFPE, signal_handler);
signal(SIGSEGV, signal_handler);
signal(SIGTERM, signal_handler);
}
 
void VID_ShiftPalette(unsigned char *p)
{
// VID_SetPalette(p);
}
 
void VID_SetPalette (unsigned char *palette)
{
byte *pal;
unsigned r,g,b;
unsigned v;
int r1,g1,b1;
int j,k,l,m;
unsigned short i;
unsigned *table;
FILE *f;
char s[255];
int dist, bestdist;
 
//
// 8 8 8 encoding
//
pal = palette;
table = d_8to24table;
for (i=0 ; i<256 ; i++)
{
r = pal[0];
g = pal[1];
b = pal[2];
pal += 3;
v = (255<<24) + (r<<0) + (g<<8) + (b<<16);
*table++ = v;
}
d_8to24table[255] &= 0xffffff; // 255 is transparent
 
for (i=0; i < (1<<15); i++) {
/* Maps
000000000000000
000000000011111 = Red = 0x1F
000001111100000 = Blue = 0x03E0
111110000000000 = Grn = 0x7C00
*/
r = ((i & 0x1F) << 3)+4;
g = ((i & 0x03E0) >> 2)+4;
b = ((i & 0x7C00) >> 7)+4;
pal = (unsigned char *)d_8to24table;
for (v=0,k=0,bestdist=10000*10000; v<256; v++,pal+=4) {
r1 = (int)r - (int)pal[0];
g1 = (int)g - (int)pal[1];
b1 = (int)b - (int)pal[2];
dist = (r1*r1)+(g1*g1)+(b1*b1);
if (dist < bestdist) {
k=v;
bestdist = dist;
}
}
d_15to8table[i]=k;
}
}
 
void CheckMultiTextureExtensions(void)
{
void *prjobj;
 
if (strstr(gl_extensions, "GL_SGIS_multitexture ") && !COM_CheckParm("-nomtex")) {
Con_Printf("Found GL_SGIS_multitexture...\n");
 
if ((prjobj = dlopen(NULL, RTLD_LAZY)) == NULL) {
Con_Printf("Unable to open symbol list for main program.\n");
return;
}
 
qglMTexCoord2fSGIS = (void *) dlsym(prjobj, "glMTexCoord2fSGIS");
qglSelectTextureSGIS = (void *) dlsym(prjobj, "glSelectTextureSGIS");
 
if (qglMTexCoord2fSGIS && qglSelectTextureSGIS) {
Con_Printf("Multitexture extensions found.\n");
gl_mtexable = true;
} else
Con_Printf("Symbol not found, disabled.\n");
 
dlclose(prjobj);
}
}
 
/*
===============
GL_Init
===============
*/
void GL_Init (void)
{
gl_vendor = glGetString (GL_VENDOR);
Con_Printf ("GL_VENDOR: %s\n", gl_vendor);
gl_renderer = glGetString (GL_RENDERER);
Con_Printf ("GL_RENDERER: %s\n", gl_renderer);
 
gl_version = glGetString (GL_VERSION);
Con_Printf ("GL_VERSION: %s\n", gl_version);
gl_extensions = glGetString (GL_EXTENSIONS);
Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions);
 
// Con_Printf ("%s %s\n", gl_renderer, gl_version);
 
CheckMultiTextureExtensions ();
 
glClearColor (1,0,0,0);
glCullFace(GL_FRONT);
glEnable(GL_TEXTURE_2D);
 
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.666);
 
glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
glShadeModel (GL_FLAT);
 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
 
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
}
 
/*
=================
GL_BeginRendering
 
=================
*/
void GL_BeginRendering (int *x, int *y, int *width, int *height)
{
extern cvar_t gl_clear;
 
*x = *y = 0;
*width = scr_width;
*height = scr_height;
 
// if (!wglMakeCurrent( maindc, baseRC ))
// Sys_Error ("wglMakeCurrent failed");
 
// glViewport (*x, *y, *width, *height);
}
 
 
void GL_EndRendering (void)
{
glFlush();
glXSwapBuffers(dpy, win);
}
 
qboolean VID_Is8bit(void)
{
return is8bit;
}
 
void VID_Init8bitPalette(void)
{
// Check for 8bit Extensions and initialize them.
int i;
void *prjobj;
 
if ((prjobj = dlopen(NULL, RTLD_LAZY)) == NULL) {
Con_Printf("Unable to open symbol list for main program.\n");
return;
}
 
if (strstr(gl_extensions, "3DFX_set_global_palette") &&
(qgl3DfxSetPaletteEXT = dlsym(prjobj, "gl3DfxSetPaletteEXT")) != NULL) {
GLubyte table[256][4];
char *oldpal;
 
Con_SafePrintf("8-bit GL extensions enabled.\n");
glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
oldpal = (char *) d_8to24table; //d_8to24table3dfx;
for (i=0;i<256;i++) {
table[i][2] = *oldpal++;
table[i][1] = *oldpal++;
table[i][0] = *oldpal++;
table[i][3] = 255;
oldpal++;
}
qgl3DfxSetPaletteEXT((GLuint *)table);
is8bit = true;
 
} else if (strstr(gl_extensions, "GL_EXT_shared_texture_palette") &&
(qglColorTableEXT = dlsym(prjobj, "glColorTableEXT")) != NULL) {
char thePalette[256*3];
char *oldPalette, *newPalette;
 
Con_SafePrintf("8-bit GL extensions enabled.\n");
glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
oldPalette = (char *) d_8to24table; //d_8to24table3dfx;
newPalette = thePalette;
for (i=0;i<256;i++) {
*newPalette++ = *oldPalette++;
*newPalette++ = *oldPalette++;
*newPalette++ = *oldPalette++;
oldPalette++;
}
qglColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE, (void *) thePalette);
is8bit = true;
}
dlclose(prjobj);
}
 
static void Check_Gamma (unsigned char *pal)
{
float f, inf;
unsigned char palette[768];
int i;
 
if ((i = COM_CheckParm("-gamma")) == 0) {
if ((gl_renderer && strstr(gl_renderer, "Voodoo")) ||
(gl_vendor && strstr(gl_vendor, "3Dfx")))
vid_gamma = 1;
else
vid_gamma = 0.7; // default to 0.7 on non-3dfx hardware
} else
vid_gamma = Q_atof(com_argv[i+1]);
 
for (i=0 ; i<768 ; i++)
{
f = pow ( (pal[i]+1)/256.0 , vid_gamma );
inf = f*255 + 0.5;
if (inf < 0)
inf = 0;
if (inf > 255)
inf = 255;
palette[i] = inf;
}
 
memcpy (pal, palette, sizeof(palette));
}
 
void VID_Init(unsigned char *palette)
{
int i;
int attrib[] = {
GLX_RGBA,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_DOUBLEBUFFER,
GLX_DEPTH_SIZE, 1,
None
};
char gldir[MAX_OSPATH];
int width = 640, height = 480;
XSetWindowAttributes attr;
unsigned long mask;
Window root;
XVisualInfo *visinfo;
qboolean fullscreen = true;
int MajorVersion, MinorVersion;
int actualWidth, actualHeight;
 
Cvar_RegisterVariable (&vid_mode);
Cvar_RegisterVariable (&in_mouse);
Cvar_RegisterVariable (&in_dgamouse);
Cvar_RegisterVariable (&m_filter);
Cvar_RegisterVariable (&gl_ztrick);
vid.maxwarpwidth = WARP_WIDTH;
vid.maxwarpheight = WARP_HEIGHT;
vid.colormap = host_colormap;
vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
 
// interpret command-line params
 
// set vid parameters
if ((i = COM_CheckParm("-window")) != 0)
fullscreen = false;
 
if ((i = COM_CheckParm("-width")) != 0)
width = atoi(com_argv[i+1]);
 
if ((i = COM_CheckParm("-height")) != 0)
height = atoi(com_argv[i+1]);
 
if ((i = COM_CheckParm("-conwidth")) != 0)
vid.conwidth = Q_atoi(com_argv[i+1]);
else
vid.conwidth = 640;
 
vid.conwidth &= 0xfff8; // make it a multiple of eight
 
if (vid.conwidth < 320)
vid.conwidth = 320;
 
// pick a conheight that matches with correct aspect
vid.conheight = vid.conwidth*3 / 4;
 
if ((i = COM_CheckParm("-conheight")) != 0)
vid.conheight = Q_atoi(com_argv[i+1]);
if (vid.conheight < 200)
vid.conheight = 200;
 
if (!(dpy = XOpenDisplay(NULL))) {
fprintf(stderr, "Error couldn't open the X display\n");
exit(1);
}
 
scrnum = DefaultScreen(dpy);
root = RootWindow(dpy, scrnum);
 
// Get video mode list
MajorVersion = MinorVersion = 0;
if (!XF86VidModeQueryVersion(dpy, &MajorVersion, &MinorVersion)) {
vidmode_ext = false;
} else {
Con_Printf("Using XFree86-VidModeExtension Version %d.%d\n", MajorVersion, MinorVersion);
vidmode_ext = true;
}
 
visinfo = glXChooseVisual(dpy, scrnum, attrib);
if (!visinfo) {
fprintf(stderr, "qkHack: Error couldn't get an RGB, Double-buffered, Depth visual\n");
exit(1);
}
 
if (vidmode_ext) {
int best_fit, best_dist, dist, x, y;
XF86VidModeGetAllModeLines(dpy, scrnum, &num_vidmodes, &vidmodes);
 
// Are we going fullscreen? If so, let's change video mode
if (fullscreen) {
best_dist = 9999999;
best_fit = -1;
 
for (i = 0; i < num_vidmodes; i++) {
if (width > vidmodes[i]->hdisplay ||
height > vidmodes[i]->vdisplay)
continue;
 
x = width - vidmodes[i]->hdisplay;
y = height - vidmodes[i]->vdisplay;
dist = (x * x) + (y * y);
if (dist < best_dist) {
best_dist = dist;
best_fit = i;
}
}
 
if (best_fit != -1) {
actualWidth = vidmodes[best_fit]->hdisplay;
actualHeight = vidmodes[best_fit]->vdisplay;
 
// change to the mode
XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[best_fit]);
vidmode_active = true;
 
// Move the viewport to top left
XF86VidModeSetViewPort(dpy, scrnum, 0, 0);
} else
fullscreen = 0;
}
}
 
/* window attributes */
attr.background_pixel = 0;
attr.border_pixel = 0;
attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
attr.event_mask = X_MASK;
if (vidmode_active) {
mask = CWBackPixel | CWColormap | CWSaveUnder | CWBackingStore |
CWEventMask | CWOverrideRedirect;
attr.override_redirect = True;
attr.backing_store = NotUseful;
attr.save_under = False;
} else
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
 
win = XCreateWindow(dpy, root, 0, 0, width, height,
0, visinfo->depth, InputOutput,
visinfo->visual, mask, &attr);
XMapWindow(dpy, win);
 
if (vidmode_active) {
XMoveWindow(dpy, win, 0, 0);
XRaiseWindow(dpy, win);
XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0);
XFlush(dpy);
// Move the viewport to top left
XF86VidModeSetViewPort(dpy, scrnum, 0, 0);
}
 
XFlush(dpy);
 
ctx = glXCreateContext(dpy, visinfo, NULL, True);
 
glXMakeCurrent(dpy, win, ctx);
 
scr_width = width;
scr_height = height;
 
if (vid.conheight > height)
vid.conheight = height;
if (vid.conwidth > width)
vid.conwidth = width;
vid.width = vid.conwidth;
vid.height = vid.conheight;
 
vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0);
vid.numpages = 2;
 
InitSig(); // trap evil signals
 
GL_Init();
 
sprintf (gldir, "%s/glquake", com_gamedir);
Sys_mkdir (gldir);
 
VID_SetPalette(palette);
 
// Check for 3DFX Extensions and initialize them.
VID_Init8bitPalette();
 
Con_SafePrintf ("Video mode %dx%d initialized.\n", width, height);
 
vid.recalc_refdef = 1; // force a surface cache flush
}
 
void Sys_SendKeyEvents(void)
{
HandleEvents();
}
 
void Force_CenterView_f (void)
{
cl.viewangles[PITCH] = 0;
}
 
void IN_Init(void)
{
}
 
void IN_Shutdown(void)
{
}
 
/*
===========
IN_Commands
===========
*/
void IN_Commands (void)
{
if (!dpy || !win)
return;
 
if (vidmode_active || key_dest == key_game)
IN_ActivateMouse();
else
IN_DeactivateMouse ();
}
 
/*
===========
IN_Move
===========
*/
void IN_MouseMove (usercmd_t *cmd)
{
if (!mouse_avail)
return;
if (m_filter.value)
{
mx = (mx + old_mouse_x) * 0.5;
my = (my + old_mouse_y) * 0.5;
}
old_mouse_x = mx;
old_mouse_y = my;
 
mx *= sensitivity.value;
my *= sensitivity.value;
 
// add mouse X/Y movement to cmd
if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
cmd->sidemove += m_side.value * mx;
else
cl.viewangles[YAW] -= m_yaw.value * mx;
if (in_mlook.state & 1)
V_StopPitchDrift ();
if ( (in_mlook.state & 1) && !(in_strafe.state & 1))
{
cl.viewangles[PITCH] += m_pitch.value * my;
if (cl.viewangles[PITCH] > 80)
cl.viewangles[PITCH] = 80;
if (cl.viewangles[PITCH] < -70)
cl.viewangles[PITCH] = -70;
}
else
{
if ((in_strafe.state & 1) && noclip_anglehack)
cmd->upmove -= m_forward.value * my;
else
cmd->forwardmove -= m_forward.value * my;
}
mx = my = 0;
}
 
void IN_Move (usercmd_t *cmd)
{
IN_MouseMove(cmd);
}
 
 
/contrib/other/sdlquake-1.0.9/gl_vidnt.c
0,0 → 1,1949
/*
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_vidnt.c -- NT GL vid component
 
#include "quakedef.h"
#include "winquake.h"
#include "resource.h"
#include <commctrl.h>
 
#define MAX_MODE_LIST 30
#define VID_ROW_SIZE 3
#define WARP_WIDTH 320
#define WARP_HEIGHT 200
#define MAXWIDTH 10000
#define MAXHEIGHT 10000
#define BASEWIDTH 320
#define BASEHEIGHT 200
 
#define MODE_WINDOWED 0
#define NO_MODE (MODE_WINDOWED - 1)
#define MODE_FULLSCREEN_DEFAULT (MODE_WINDOWED + 1)
 
typedef struct {
modestate_t type;
int width;
int height;
int modenum;
int dib;
int fullscreen;
int bpp;
int halfscreen;
char modedesc[17];
} vmode_t;
 
typedef struct {
int width;
int height;
} lmode_t;
 
lmode_t lowresmodes[] = {
{320, 200},
{320, 240},
{400, 300},
{512, 384},
};
 
const char *gl_vendor;
const char *gl_renderer;
const char *gl_version;
const char *gl_extensions;
 
qboolean DDActive;
qboolean scr_skipupdate;
 
static vmode_t modelist[MAX_MODE_LIST];
static int nummodes;
static vmode_t *pcurrentmode;
static vmode_t badmode;
 
static DEVMODE gdevmode;
static qboolean vid_initialized = false;
static qboolean windowed, leavecurrentmode;
static qboolean vid_canalttab = false;
static qboolean vid_wassuspended = false;
static int windowed_mouse;
extern qboolean mouseactive; // from in_win.c
static HICON hIcon;
 
int DIBWidth, DIBHeight;
RECT WindowRect;
DWORD WindowStyle, ExWindowStyle;
 
HWND mainwindow, dibwindow;
 
int vid_modenum = NO_MODE;
int vid_realmode;
int vid_default = MODE_WINDOWED;
static int windowed_default;
unsigned char vid_curpal[256*3];
static qboolean fullsbardraw = false;
 
static float vid_gamma = 1.0;
 
HGLRC baseRC;
HDC maindc;
 
glvert_t glv;
 
cvar_t gl_ztrick = {"gl_ztrick","1"};
 
HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow);
 
viddef_t vid; // global video state
 
unsigned short d_8to16table[256];
unsigned d_8to24table[256];
unsigned char d_15to8table[65536];
 
float gldepthmin, gldepthmax;
 
modestate_t modestate = MS_UNINIT;
 
void VID_MenuDraw (void);
void VID_MenuKey (int key);
 
LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void AppActivate(BOOL fActive, BOOL minimize);
char *VID_GetModeDescription (int mode);
void ClearAllStates (void);
void VID_UpdateWindowStatus (void);
void GL_Init (void);
 
PROC glArrayElementEXT;
PROC glColorPointerEXT;
PROC glTexCoordPointerEXT;
PROC glVertexPointerEXT;
 
typedef void (APIENTRY *lp3DFXFUNC) (int, int, int, int, int, const void*);
lp3DFXFUNC glColorTableEXT;
qboolean is8bit = false;
qboolean isPermedia = false;
qboolean gl_mtexable = false;
 
//====================================
 
cvar_t vid_mode = {"vid_mode","0", false};
// Note that 0 is MODE_WINDOWED
cvar_t _vid_default_mode = {"_vid_default_mode","0", true};
// Note that 3 is MODE_FULLSCREEN_DEFAULT
cvar_t _vid_default_mode_win = {"_vid_default_mode_win","3", true};
cvar_t vid_wait = {"vid_wait","0"};
cvar_t vid_nopageflip = {"vid_nopageflip","0", true};
cvar_t _vid_wait_override = {"_vid_wait_override", "0", true};
cvar_t vid_config_x = {"vid_config_x","800", true};
cvar_t vid_config_y = {"vid_config_y","600", true};
cvar_t vid_stretch_by_2 = {"vid_stretch_by_2","1", true};
cvar_t _windowed_mouse = {"_windowed_mouse","1", true};
 
int window_center_x, window_center_y, window_x, window_y, window_width, window_height;
RECT window_rect;
 
// direct draw software compatability stuff
 
void VID_HandlePause (qboolean pause)
{
}
 
void VID_ForceLockState (int lk)
{
}
 
void VID_LockBuffer (void)
{
}
 
void VID_UnlockBuffer (void)
{
}
 
int VID_ForceUnlockedAndReturnState (void)
{
return 0;
}
 
void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
{
}
 
void D_EndDirectRect (int x, int y, int width, int height)
{
}
 
 
void CenterWindow(HWND hWndCenter, int width, int height, BOOL lefttopjustify)
{
RECT rect;
int CenterX, CenterY;
 
CenterX = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
CenterY = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
if (CenterX > CenterY*2)
CenterX >>= 1; // dual screens
CenterX = (CenterX < 0) ? 0: CenterX;
CenterY = (CenterY < 0) ? 0: CenterY;
SetWindowPos (hWndCenter, NULL, CenterX, CenterY, 0, 0,
SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME);
}
 
qboolean VID_SetWindowedMode (int modenum)
{
HDC hdc;
int lastmodestate, width, height;
RECT rect;
 
lastmodestate = modestate;
 
WindowRect.top = WindowRect.left = 0;
 
WindowRect.right = modelist[modenum].width;
WindowRect.bottom = modelist[modenum].height;
 
DIBWidth = modelist[modenum].width;
DIBHeight = modelist[modenum].height;
 
WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU |
WS_MINIMIZEBOX;
ExWindowStyle = 0;
 
rect = WindowRect;
AdjustWindowRectEx(&rect, WindowStyle, FALSE, 0);
 
width = rect.right - rect.left;
height = rect.bottom - rect.top;
 
// Create the DIB window
dibwindow = CreateWindowEx (
ExWindowStyle,
"WinQuake",
"GLQuake",
WindowStyle,
rect.left, rect.top,
width,
height,
NULL,
NULL,
global_hInstance,
NULL);
 
if (!dibwindow)
Sys_Error ("Couldn't create DIB window");
 
// Center and show the DIB window
CenterWindow(dibwindow, WindowRect.right - WindowRect.left,
WindowRect.bottom - WindowRect.top, false);
 
ShowWindow (dibwindow, SW_SHOWDEFAULT);
UpdateWindow (dibwindow);
 
modestate = MS_WINDOWED;
 
// because we have set the background brush for the window to NULL
// (to avoid flickering when re-sizing the window on the desktop),
// we clear the window to black when created, otherwise it will be
// empty while Quake starts up.
hdc = GetDC(dibwindow);
PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS);
ReleaseDC(dibwindow, hdc);
 
if (vid.conheight > modelist[modenum].height)
vid.conheight = modelist[modenum].height;
if (vid.conwidth > modelist[modenum].width)
vid.conwidth = modelist[modenum].width;
vid.width = vid.conwidth;
vid.height = vid.conheight;
 
vid.numpages = 2;
 
mainwindow = dibwindow;
 
SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon);
SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon);
 
return true;
}
 
 
qboolean VID_SetFullDIBMode (int modenum)
{
HDC hdc;
int lastmodestate, width, height;
RECT rect;
 
if (!leavecurrentmode)
{
gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
gdevmode.dmBitsPerPel = modelist[modenum].bpp;
gdevmode.dmPelsWidth = modelist[modenum].width <<
modelist[modenum].halfscreen;
gdevmode.dmPelsHeight = modelist[modenum].height;
gdevmode.dmSize = sizeof (gdevmode);
 
if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
Sys_Error ("Couldn't set fullscreen DIB mode");
}
 
lastmodestate = modestate;
modestate = MS_FULLDIB;
 
WindowRect.top = WindowRect.left = 0;
 
WindowRect.right = modelist[modenum].width;
WindowRect.bottom = modelist[modenum].height;
 
DIBWidth = modelist[modenum].width;
DIBHeight = modelist[modenum].height;
 
WindowStyle = WS_POPUP;
ExWindowStyle = 0;
 
rect = WindowRect;
AdjustWindowRectEx(&rect, WindowStyle, FALSE, 0);
 
width = rect.right - rect.left;
height = rect.bottom - rect.top;
 
// Create the DIB window
dibwindow = CreateWindowEx (
ExWindowStyle,
"WinQuake",
"GLQuake",
WindowStyle,
rect.left, rect.top,
width,
height,
NULL,
NULL,
global_hInstance,
NULL);
 
if (!dibwindow)
Sys_Error ("Couldn't create DIB window");
 
ShowWindow (dibwindow, SW_SHOWDEFAULT);
UpdateWindow (dibwindow);
 
// Because we have set the background brush for the window to NULL
// (to avoid flickering when re-sizing the window on the desktop), we
// clear the window to black when created, otherwise it will be
// empty while Quake starts up.
hdc = GetDC(dibwindow);
PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS);
ReleaseDC(dibwindow, hdc);
 
if (vid.conheight > modelist[modenum].height)
vid.conheight = modelist[modenum].height;
if (vid.conwidth > modelist[modenum].width)
vid.conwidth = modelist[modenum].width;
vid.width = vid.conwidth;
vid.height = vid.conheight;
 
vid.numpages = 2;
 
// needed because we're not getting WM_MOVE messages fullscreen on NT
window_x = 0;
window_y = 0;
 
mainwindow = dibwindow;
 
SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon);
SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon);
 
return true;
}
 
 
int VID_SetMode (int modenum, unsigned char *palette)
{
int original_mode, temp;
qboolean stat;
MSG msg;
HDC hdc;
 
if ((windowed && (modenum != 0)) ||
(!windowed && (modenum < 1)) ||
(!windowed && (modenum >= nummodes)))
{
Sys_Error ("Bad video mode\n");
}
 
// so Con_Printfs don't mess us up by forcing vid and snd updates
temp = scr_disabled_for_loading;
scr_disabled_for_loading = true;
 
CDAudio_Pause ();
 
if (vid_modenum == NO_MODE)
original_mode = windowed_default;
else
original_mode = vid_modenum;
 
// Set either the fullscreen or windowed mode
if (modelist[modenum].type == MS_WINDOWED)
{
if (_windowed_mouse.value && key_dest == key_game)
{
stat = VID_SetWindowedMode(modenum);
IN_ActivateMouse ();
IN_HideMouse ();
}
else
{
IN_DeactivateMouse ();
IN_ShowMouse ();
stat = VID_SetWindowedMode(modenum);
}
}
else if (modelist[modenum].type == MS_FULLDIB)
{
stat = VID_SetFullDIBMode(modenum);
IN_ActivateMouse ();
IN_HideMouse ();
}
else
{
Sys_Error ("VID_SetMode: Bad mode type in modelist");
}
 
window_width = DIBWidth;
window_height = DIBHeight;
VID_UpdateWindowStatus ();
 
CDAudio_Resume ();
scr_disabled_for_loading = temp;
 
if (!stat)
{
Sys_Error ("Couldn't set video mode");
}
 
// now we try to make sure we get the focus on the mode switch, because
// sometimes in some systems we don't. We grab the foreground, then
// finish setting up, pump all our messages, and sleep for a little while
// to let messages finish bouncing around the system, then we put
// ourselves at the top of the z order, then grab the foreground again,
// Who knows if it helps, but it probably doesn't hurt
SetForegroundWindow (mainwindow);
VID_SetPalette (palette);
vid_modenum = modenum;
Cvar_SetValue ("vid_mode", (float)vid_modenum);
 
while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
 
Sleep (100);
 
SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0,
SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW |
SWP_NOCOPYBITS);
 
SetForegroundWindow (mainwindow);
 
// fix the leftover Alt from any Alt-Tab or the like that switched us away
ClearAllStates ();
 
if (!msg_suppress_1)
Con_SafePrintf ("Video mode %s initialized.\n", VID_GetModeDescription (vid_modenum));
 
VID_SetPalette (palette);
 
vid.recalc_refdef = 1;
 
return true;
}
 
 
/*
================
VID_UpdateWindowStatus
================
*/
void VID_UpdateWindowStatus (void)
{
 
window_rect.left = window_x;
window_rect.top = window_y;
window_rect.right = window_x + window_width;
window_rect.bottom = window_y + window_height;
window_center_x = (window_rect.left + window_rect.right) / 2;
window_center_y = (window_rect.top + window_rect.bottom) / 2;
 
IN_UpdateClipCursor ();
}
 
 
//====================================
 
BINDTEXFUNCPTR bindTexFunc;
 
#define TEXTURE_EXT_STRING "GL_EXT_texture_object"
 
 
void CheckTextureExtensions (void)
{
char *tmp;
qboolean texture_ext;
HINSTANCE hInstGL;
 
texture_ext = FALSE;
/* check for texture extension */
tmp = (unsigned char *)glGetString(GL_EXTENSIONS);
while (*tmp)
{
if (strncmp((const char*)tmp, TEXTURE_EXT_STRING, strlen(TEXTURE_EXT_STRING)) == 0)
texture_ext = TRUE;
tmp++;
}
 
if (!texture_ext || COM_CheckParm ("-gl11") )
{
hInstGL = LoadLibrary("opengl32.dll");
if (hInstGL == NULL)
Sys_Error ("Couldn't load opengl32.dll\n");
 
bindTexFunc = (void *)GetProcAddress(hInstGL,"glBindTexture");
 
if (!bindTexFunc)
Sys_Error ("No texture objects!");
return;
}
 
/* load library and get procedure adresses for texture extension API */
if ((bindTexFunc = (BINDTEXFUNCPTR)
wglGetProcAddress((LPCSTR) "glBindTextureEXT")) == NULL)
{
Sys_Error ("GetProcAddress for BindTextureEXT failed");
return;
}
}
 
void CheckArrayExtensions (void)
{
char *tmp;
 
/* check for texture extension */
tmp = (unsigned char *)glGetString(GL_EXTENSIONS);
while (*tmp)
{
if (strncmp((const char*)tmp, "GL_EXT_vertex_array", strlen("GL_EXT_vertex_array")) == 0)
{
if (
((glArrayElementEXT = wglGetProcAddress("glArrayElementEXT")) == NULL) ||
((glColorPointerEXT = wglGetProcAddress("glColorPointerEXT")) == NULL) ||
((glTexCoordPointerEXT = wglGetProcAddress("glTexCoordPointerEXT")) == NULL) ||
((glVertexPointerEXT = wglGetProcAddress("glVertexPointerEXT")) == NULL) )
{
Sys_Error ("GetProcAddress for vertex extension failed");
return;
}
return;
}
tmp++;
}
 
Sys_Error ("Vertex array extension not present");
}
 
//int texture_mode = GL_NEAREST;
//int texture_mode = GL_NEAREST_MIPMAP_NEAREST;
//int texture_mode = GL_NEAREST_MIPMAP_LINEAR;
int texture_mode = GL_LINEAR;
//int texture_mode = GL_LINEAR_MIPMAP_NEAREST;
//int texture_mode = GL_LINEAR_MIPMAP_LINEAR;
 
int texture_extension_number = 1;
 
#ifdef _WIN32
void CheckMultiTextureExtensions(void)
{
if (strstr(gl_extensions, "GL_SGIS_multitexture ") && !COM_CheckParm("-nomtex")) {
Con_Printf("Multitexture extensions found.\n");
qglMTexCoord2fSGIS = (void *) wglGetProcAddress("glMTexCoord2fSGIS");
qglSelectTextureSGIS = (void *) wglGetProcAddress("glSelectTextureSGIS");
gl_mtexable = true;
}
}
#else
void CheckMultiTextureExtensions(void)
{
gl_mtexable = true;
}
#endif
 
/*
===============
GL_Init
===============
*/
void GL_Init (void)
{
gl_vendor = glGetString (GL_VENDOR);
Con_Printf ("GL_VENDOR: %s\n", gl_vendor);
gl_renderer = glGetString (GL_RENDERER);
Con_Printf ("GL_RENDERER: %s\n", gl_renderer);
 
gl_version = glGetString (GL_VERSION);
Con_Printf ("GL_VERSION: %s\n", gl_version);
gl_extensions = glGetString (GL_EXTENSIONS);
Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions);
 
// Con_Printf ("%s %s\n", gl_renderer, gl_version);
 
if (strnicmp(gl_renderer,"PowerVR",7)==0)
fullsbardraw = true;
 
if (strnicmp(gl_renderer,"Permedia",8)==0)
isPermedia = true;
 
CheckTextureExtensions ();
CheckMultiTextureExtensions ();
 
glClearColor (1,0,0,0);
glCullFace(GL_FRONT);
glEnable(GL_TEXTURE_2D);
 
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.666);
 
glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
glShadeModel (GL_FLAT);
 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
 
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 
#if 0
CheckArrayExtensions ();
 
glEnable (GL_VERTEX_ARRAY_EXT);
glEnable (GL_TEXTURE_COORD_ARRAY_EXT);
glVertexPointerEXT (3, GL_FLOAT, 0, 0, &glv.x);
glTexCoordPointerEXT (2, GL_FLOAT, 0, 0, &glv.s);
glColorPointerEXT (3, GL_FLOAT, 0, 0, &glv.r);
#endif
}
 
/*
=================
GL_BeginRendering
 
=================
*/
void GL_BeginRendering (int *x, int *y, int *width, int *height)
{
extern cvar_t gl_clear;
 
*x = *y = 0;
*width = WindowRect.right - WindowRect.left;
*height = WindowRect.bottom - WindowRect.top;
 
// if (!wglMakeCurrent( maindc, baseRC ))
// Sys_Error ("wglMakeCurrent failed");
 
// glViewport (*x, *y, *width, *height);
}
 
 
void GL_EndRendering (void)
{
if (!scr_skipupdate || block_drawing)
SwapBuffers(maindc);
 
// handle the mouse state when windowed if that's changed
if (modestate == MS_WINDOWED)
{
if (!_windowed_mouse.value) {
if (windowed_mouse) {
IN_DeactivateMouse ();
IN_ShowMouse ();
windowed_mouse = false;
}
} else {
windowed_mouse = true;
if (key_dest == key_game && !mouseactive && ActiveApp) {
IN_ActivateMouse ();
IN_HideMouse ();
} else if (mouseactive && key_dest != key_game) {
IN_DeactivateMouse ();
IN_ShowMouse ();
}
}
}
if (fullsbardraw)
Sbar_Changed();
}
 
void VID_SetPalette (unsigned char *palette)
{
byte *pal;
unsigned r,g,b;
unsigned v;
int r1,g1,b1;
int j,k,l,m;
unsigned short i;
unsigned *table;
FILE *f;
char s[255];
HWND hDlg, hProgress;
float gamma;
 
//
// 8 8 8 encoding
//
pal = palette;
table = d_8to24table;
for (i=0 ; i<256 ; i++)
{
r = pal[0];
g = pal[1];
b = pal[2];
pal += 3;
// v = (255<<24) + (r<<16) + (g<<8) + (b<<0);
// v = (255<<0) + (r<<8) + (g<<16) + (b<<24);
v = (255<<24) + (r<<0) + (g<<8) + (b<<16);
*table++ = v;
}
d_8to24table[255] &= 0xffffff; // 255 is transparent
 
// JACK: 3D distance calcs - k is last closest, l is the distance.
// FIXME: Precalculate this and cache to disk.
for (i=0; i < (1<<15); i++) {
/* Maps
000000000000000
000000000011111 = Red = 0x1F
000001111100000 = Blue = 0x03E0
111110000000000 = Grn = 0x7C00
*/
r = ((i & 0x1F) << 3)+4;
g = ((i & 0x03E0) >> 2)+4;
b = ((i & 0x7C00) >> 7)+4;
pal = (unsigned char *)d_8to24table;
for (v=0,k=0,l=10000*10000; v<256; v++,pal+=4) {
r1 = r-pal[0];
g1 = g-pal[1];
b1 = b-pal[2];
j = (r1*r1)+(g1*g1)+(b1*b1);
if (j<l) {
k=v;
l=j;
}
}
d_15to8table[i]=k;
}
}
 
BOOL gammaworks;
 
void VID_ShiftPalette (unsigned char *palette)
{
extern byte ramps[3][256];
// VID_SetPalette (palette);
 
// gammaworks = SetDeviceGammaRamp (maindc, ramps);
}
 
 
void VID_SetDefaultMode (void)
{
IN_DeactivateMouse ();
}
 
 
void VID_Shutdown (void)
{
HGLRC hRC;
HDC hDC;
 
if (vid_initialized)
{
vid_canalttab = false;
hRC = wglGetCurrentContext();
hDC = wglGetCurrentDC();
 
wglMakeCurrent(NULL, NULL);
 
if (hRC)
wglDeleteContext(hRC);
 
if (hDC && dibwindow)
ReleaseDC(dibwindow, hDC);
 
if (modestate == MS_FULLDIB)
ChangeDisplaySettings (NULL, 0);
 
if (maindc && dibwindow)
ReleaseDC (dibwindow, maindc);
 
AppActivate(false, false);
}
}
 
 
//==========================================================================
 
 
BOOL bSetupPixelFormat(HDC hDC)
{
static PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
1, // version number
PFD_DRAW_TO_WINDOW // support window
| PFD_SUPPORT_OPENGL // support OpenGL
| PFD_DOUBLEBUFFER , // double buffered
PFD_TYPE_RGBA, // RGBA type
24, // 24-bit color depth
0, 0, 0, 0, 0, 0, // color bits ignored
0, // no alpha buffer
0, // shift bit ignored
0, // no accumulation buffer
0, 0, 0, 0, // accum bits ignored
32, // 32-bit z-buffer
0, // no stencil buffer
0, // no auxiliary buffer
PFD_MAIN_PLANE, // main layer
0, // reserved
0, 0, 0 // layer masks ignored
};
int pixelformat;
 
if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 )
{
MessageBox(NULL, "ChoosePixelFormat failed", "Error", MB_OK);
return FALSE;
}
 
if (SetPixelFormat(hDC, pixelformat, &pfd) == FALSE)
{
MessageBox(NULL, "SetPixelFormat failed", "Error", MB_OK);
return FALSE;
}
 
return TRUE;
}
 
 
 
byte scantokey[128] =
{
// 0 1 2 3 4 5 6 7
// 8 9 A B C D E F
0 , 27, '1', '2', '3', '4', '5', '6',
'7', '8', '9', '0', '-', '=', K_BACKSPACE, 9, // 0
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
'o', 'p', '[', ']', 13 , K_CTRL,'a', 's', // 1
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
'\'' , '`', K_SHIFT,'\\', 'z', 'x', 'c', 'v', // 2
'b', 'n', 'm', ',', '.', '/', K_SHIFT,'*',
K_ALT,' ', 0 , K_F1, K_F2, K_F3, K_F4, K_F5, // 3
K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE , 0 , K_HOME,
K_UPARROW,K_PGUP,'-',K_LEFTARROW,'5',K_RIGHTARROW,'+',K_END, //4
K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0, 0, K_F11,
K_F12,0 , 0 , 0 , 0 , 0 , 0 , 0, // 5
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, // 6
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7
};
 
byte shiftscantokey[128] =
{
// 0 1 2 3 4 5 6 7
// 8 9 A B C D E F
0 , 27, '!', '@', '#', '$', '%', '^',
'&', '*', '(', ')', '_', '+', K_BACKSPACE, 9, // 0
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
'O', 'P', '{', '}', 13 , K_CTRL,'A', 'S', // 1
'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
'"' , '~', K_SHIFT,'|', 'Z', 'X', 'C', 'V', // 2
'B', 'N', 'M', '<', '>', '?', K_SHIFT,'*',
K_ALT,' ', 0 , K_F1, K_F2, K_F3, K_F4, K_F5, // 3
K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE , 0 , K_HOME,
K_UPARROW,K_PGUP,'_',K_LEFTARROW,'%',K_RIGHTARROW,'+',K_END, //4
K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0, 0, K_F11,
K_F12,0 , 0 , 0 , 0 , 0 , 0 , 0, // 5
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, // 6
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7
};
 
 
/*
=======
MapKey
 
Map from windows to quake keynums
=======
*/
int MapKey (int key)
{
key = (key>>16)&255;
if (key > 127)
return 0;
if (scantokey[key] == 0)
Con_DPrintf("key 0x%02x has no translation\n", key);
return scantokey[key];
}
 
/*
===================================================================
 
MAIN WINDOW
 
===================================================================
*/
 
/*
================
ClearAllStates
================
*/
void ClearAllStates (void)
{
int i;
// send an up event for each key, to make sure the server clears them all
for (i=0 ; i<256 ; i++)
{
Key_Event (i, false);
}
 
Key_ClearStates ();
IN_ClearStates ();
}
 
void AppActivate(BOOL fActive, BOOL minimize)
/****************************************************************************
*
* Function: AppActivate
* Parameters: fActive - True if app is activating
*
* Description: If the application is activating, then swap the system
* into SYSPAL_NOSTATIC mode so that our palettes will display
* correctly.
*
****************************************************************************/
{
MSG msg;
HDC hdc;
int i, t;
static BOOL sound_active;
 
ActiveApp = fActive;
Minimized = minimize;
 
// enable/disable sound on focus gain/loss
if (!ActiveApp && sound_active)
{
S_BlockSound ();
sound_active = false;
}
else if (ActiveApp && !sound_active)
{
S_UnblockSound ();
sound_active = true;
}
 
if (fActive)
{
if (modestate == MS_FULLDIB)
{
IN_ActivateMouse ();
IN_HideMouse ();
if (vid_canalttab && vid_wassuspended) {
vid_wassuspended = false;
ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN);
ShowWindow(mainwindow, SW_SHOWNORMAL);
}
}
else if ((modestate == MS_WINDOWED) && _windowed_mouse.value && key_dest == key_game)
{
IN_ActivateMouse ();
IN_HideMouse ();
}
}
 
if (!fActive)
{
if (modestate == MS_FULLDIB)
{
IN_DeactivateMouse ();
IN_ShowMouse ();
if (vid_canalttab) {
ChangeDisplaySettings (NULL, 0);
vid_wassuspended = true;
}
}
else if ((modestate == MS_WINDOWED) && _windowed_mouse.value)
{
IN_DeactivateMouse ();
IN_ShowMouse ();
}
}
}
 
 
/* main window procedure */
LONG WINAPI MainWndProc (
HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
LONG lRet = 1;
int fwKeys, xPos, yPos, fActive, fMinimized, temp;
extern unsigned int uiWheelMessage;
 
if ( uMsg == uiWheelMessage )
uMsg = WM_MOUSEWHEEL;
 
switch (uMsg)
{
case WM_KILLFOCUS:
if (modestate == MS_FULLDIB)
ShowWindow(mainwindow, SW_SHOWMINNOACTIVE);
break;
 
case WM_CREATE:
break;
 
case WM_MOVE:
window_x = (int) LOWORD(lParam);
window_y = (int) HIWORD(lParam);
VID_UpdateWindowStatus ();
break;
 
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
Key_Event (MapKey(lParam), true);
break;
case WM_KEYUP:
case WM_SYSKEYUP:
Key_Event (MapKey(lParam), false);
break;
 
case WM_SYSCHAR:
// keep Alt-Space from happening
break;
 
// this is complicated because Win32 seems to pack multiple mouse events into
// one update sometimes, so we always check all states and look for events
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
case WM_MOUSEMOVE:
temp = 0;
 
if (wParam & MK_LBUTTON)
temp |= 1;
 
if (wParam & MK_RBUTTON)
temp |= 2;
 
if (wParam & MK_MBUTTON)
temp |= 4;
 
IN_MouseEvent (temp);
 
break;
 
// JACK: This is the mouse wheel with the Intellimouse
// Its delta is either positive or neg, and we generate the proper
// Event.
case WM_MOUSEWHEEL:
if ((short) HIWORD(wParam) > 0) {
Key_Event(K_MWHEELUP, true);
Key_Event(K_MWHEELUP, false);
} else {
Key_Event(K_MWHEELDOWN, true);
Key_Event(K_MWHEELDOWN, false);
}
break;
 
case WM_SIZE:
break;
 
case WM_CLOSE:
if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit",
MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES)
{
Sys_Quit ();
}
 
break;
 
case WM_ACTIVATE:
fActive = LOWORD(wParam);
fMinimized = (BOOL) HIWORD(wParam);
AppActivate(!(fActive == WA_INACTIVE), fMinimized);
 
// fix the leftover Alt from any Alt-Tab or the like that switched us away
ClearAllStates ();
 
break;
 
case WM_DESTROY:
{
if (dibwindow)
DestroyWindow (dibwindow);
 
PostQuitMessage (0);
}
break;
 
case MM_MCINOTIFY:
lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam);
break;
 
default:
/* pass all unhandled messages to DefWindowProc */
lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
break;
}
 
/* return 1 if handled message, 0 if not */
return lRet;
}
 
 
/*
=================
VID_NumModes
=================
*/
int VID_NumModes (void)
{
return nummodes;
}
 
/*
=================
VID_GetModePtr
=================
*/
vmode_t *VID_GetModePtr (int modenum)
{
 
if ((modenum >= 0) && (modenum < nummodes))
return &modelist[modenum];
else
return &badmode;
}
 
 
/*
=================
VID_GetModeDescription
=================
*/
char *VID_GetModeDescription (int mode)
{
char *pinfo;
vmode_t *pv;
static char temp[100];
 
if ((mode < 0) || (mode >= nummodes))
return NULL;
 
if (!leavecurrentmode)
{
pv = VID_GetModePtr (mode);
pinfo = pv->modedesc;
}
else
{
sprintf (temp, "Desktop resolution (%dx%d)",
modelist[MODE_FULLSCREEN_DEFAULT].width,
modelist[MODE_FULLSCREEN_DEFAULT].height);
pinfo = temp;
}
 
return pinfo;
}
 
 
// KJB: Added this to return the mode driver name in description for console
 
char *VID_GetExtModeDescription (int mode)
{
static char pinfo[40];
vmode_t *pv;
 
if ((mode < 0) || (mode >= nummodes))
return NULL;
 
pv = VID_GetModePtr (mode);
if (modelist[mode].type == MS_FULLDIB)
{
if (!leavecurrentmode)
{
sprintf(pinfo,"%s fullscreen", pv->modedesc);
}
else
{
sprintf (pinfo, "Desktop resolution (%dx%d)",
modelist[MODE_FULLSCREEN_DEFAULT].width,
modelist[MODE_FULLSCREEN_DEFAULT].height);
}
}
else
{
if (modestate == MS_WINDOWED)
sprintf(pinfo, "%s windowed", pv->modedesc);
else
sprintf(pinfo, "windowed");
}
 
return pinfo;
}
 
 
/*
=================
VID_DescribeCurrentMode_f
=================
*/
void VID_DescribeCurrentMode_f (void)
{
Con_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum));
}
 
 
/*
=================
VID_NumModes_f
=================
*/
void VID_NumModes_f (void)
{
 
if (nummodes == 1)
Con_Printf ("%d video mode is available\n", nummodes);
else
Con_Printf ("%d video modes are available\n", nummodes);
}
 
 
/*
=================
VID_DescribeMode_f
=================
*/
void VID_DescribeMode_f (void)
{
int t, modenum;
modenum = Q_atoi (Cmd_Argv(1));
 
t = leavecurrentmode;
leavecurrentmode = 0;
 
Con_Printf ("%s\n", VID_GetExtModeDescription (modenum));
 
leavecurrentmode = t;
}
 
 
/*
=================
VID_DescribeModes_f
=================
*/
void VID_DescribeModes_f (void)
{
int i, lnummodes, t;
char *pinfo;
vmode_t *pv;
 
lnummodes = VID_NumModes ();
 
t = leavecurrentmode;
leavecurrentmode = 0;
 
for (i=1 ; i<lnummodes ; i++)
{
pv = VID_GetModePtr (i);
pinfo = VID_GetExtModeDescription (i);
Con_Printf ("%2d: %s\n", i, pinfo);
}
 
leavecurrentmode = t;
}
 
 
void VID_InitDIB (HINSTANCE hInstance)
{
WNDCLASS wc;
HDC hdc;
int i;
 
/* Register the frame class */
wc.style = 0;
wc.lpfnWndProc = (WNDPROC)MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = 0;
wc.hCursor = LoadCursor (NULL,IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = 0;
wc.lpszClassName = "WinQuake";
 
if (!RegisterClass (&wc) )
Sys_Error ("Couldn't register window class");
 
modelist[0].type = MS_WINDOWED;
 
if (COM_CheckParm("-width"))
modelist[0].width = Q_atoi(com_argv[COM_CheckParm("-width")+1]);
else
modelist[0].width = 640;
 
if (modelist[0].width < 320)
modelist[0].width = 320;
 
if (COM_CheckParm("-height"))
modelist[0].height= Q_atoi(com_argv[COM_CheckParm("-height")+1]);
else
modelist[0].height = modelist[0].width * 240/320;
 
if (modelist[0].height < 240)
modelist[0].height = 240;
 
sprintf (modelist[0].modedesc, "%dx%d",
modelist[0].width, modelist[0].height);
 
modelist[0].modenum = MODE_WINDOWED;
modelist[0].dib = 1;
modelist[0].fullscreen = 0;
modelist[0].halfscreen = 0;
modelist[0].bpp = 0;
 
nummodes = 1;
}
 
 
/*
=================
VID_InitFullDIB
=================
*/
void VID_InitFullDIB (HINSTANCE hInstance)
{
DEVMODE devmode;
int i, modenum, cmodes, originalnummodes, existingmode, numlowresmodes;
int j, bpp, done;
BOOL stat;
 
// enumerate >8 bpp modes
originalnummodes = nummodes;
modenum = 0;
 
do
{
stat = EnumDisplaySettings (NULL, modenum, &devmode);
 
if ((devmode.dmBitsPerPel >= 15) &&
(devmode.dmPelsWidth <= MAXWIDTH) &&
(devmode.dmPelsHeight <= MAXHEIGHT) &&
(nummodes < MAX_MODE_LIST))
{
devmode.dmFields = DM_BITSPERPEL |
DM_PELSWIDTH |
DM_PELSHEIGHT;
 
if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
DISP_CHANGE_SUCCESSFUL)
{
modelist[nummodes].type = MS_FULLDIB;
modelist[nummodes].width = devmode.dmPelsWidth;
modelist[nummodes].height = devmode.dmPelsHeight;
modelist[nummodes].modenum = 0;
modelist[nummodes].halfscreen = 0;
modelist[nummodes].dib = 1;
modelist[nummodes].fullscreen = 1;
modelist[nummodes].bpp = devmode.dmBitsPerPel;
sprintf (modelist[nummodes].modedesc, "%dx%dx%d",
devmode.dmPelsWidth, devmode.dmPelsHeight,
devmode.dmBitsPerPel);
 
// if the width is more than twice the height, reduce it by half because this
// is probably a dual-screen monitor
if (!COM_CheckParm("-noadjustaspect"))
{
if (modelist[nummodes].width > (modelist[nummodes].height << 1))
{
modelist[nummodes].width >>= 1;
modelist[nummodes].halfscreen = 1;
sprintf (modelist[nummodes].modedesc, "%dx%dx%d",
modelist[nummodes].width,
modelist[nummodes].height,
modelist[nummodes].bpp);
}
}
 
for (i=originalnummodes, existingmode = 0 ; i<nummodes ; i++)
{
if ((modelist[nummodes].width == modelist[i].width) &&
(modelist[nummodes].height == modelist[i].height) &&
(modelist[nummodes].bpp == modelist[i].bpp))
{
existingmode = 1;
break;
}
}
 
if (!existingmode)
{
nummodes++;
}
}
}
 
modenum++;
} while (stat);
 
// see if there are any low-res modes that aren't being reported
numlowresmodes = sizeof(lowresmodes) / sizeof(lowresmodes[0]);
bpp = 16;
done = 0;
 
do
{
for (j=0 ; (j<numlowresmodes) && (nummodes < MAX_MODE_LIST) ; j++)
{
devmode.dmBitsPerPel = bpp;
devmode.dmPelsWidth = lowresmodes[j].width;
devmode.dmPelsHeight = lowresmodes[j].height;
devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
 
if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
DISP_CHANGE_SUCCESSFUL)
{
modelist[nummodes].type = MS_FULLDIB;
modelist[nummodes].width = devmode.dmPelsWidth;
modelist[nummodes].height = devmode.dmPelsHeight;
modelist[nummodes].modenum = 0;
modelist[nummodes].halfscreen = 0;
modelist[nummodes].dib = 1;
modelist[nummodes].fullscreen = 1;
modelist[nummodes].bpp = devmode.dmBitsPerPel;
sprintf (modelist[nummodes].modedesc, "%dx%dx%d",
devmode.dmPelsWidth, devmode.dmPelsHeight,
devmode.dmBitsPerPel);
 
for (i=originalnummodes, existingmode = 0 ; i<nummodes ; i++)
{
if ((modelist[nummodes].width == modelist[i].width) &&
(modelist[nummodes].height == modelist[i].height) &&
(modelist[nummodes].bpp == modelist[i].bpp))
{
existingmode = 1;
break;
}
}
 
if (!existingmode)
{
nummodes++;
}
}
}
switch (bpp)
{
case 16:
bpp = 32;
break;
 
case 32:
bpp = 24;
break;
 
case 24:
done = 1;
break;
}
} while (!done);
 
if (nummodes == originalnummodes)
Con_SafePrintf ("No fullscreen DIB modes found\n");
}
 
qboolean VID_Is8bit() {
return is8bit;
}
 
#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB
 
void VID_Init8bitPalette()
{
// Check for 8bit Extensions and initialize them.
int i;
char thePalette[256*3];
char *oldPalette, *newPalette;
 
glColorTableEXT = (void *)wglGetProcAddress("glColorTableEXT");
if (!glColorTableEXT || strstr(gl_extensions, "GL_EXT_shared_texture_palette") ||
COM_CheckParm("-no8bit"))
return;
 
Con_SafePrintf("8-bit GL extensions enabled.\n");
glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
oldPalette = (char *) d_8to24table; //d_8to24table3dfx;
newPalette = thePalette;
for (i=0;i<256;i++) {
*newPalette++ = *oldPalette++;
*newPalette++ = *oldPalette++;
*newPalette++ = *oldPalette++;
oldPalette++;
}
glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE,
(void *) thePalette);
is8bit = TRUE;
}
 
static void Check_Gamma (unsigned char *pal)
{
float f, inf;
unsigned char palette[768];
int i;
 
if ((i = COM_CheckParm("-gamma")) == 0) {
if ((gl_renderer && strstr(gl_renderer, "Voodoo")) ||
(gl_vendor && strstr(gl_vendor, "3Dfx")))
vid_gamma = 1;
else
vid_gamma = 0.7; // default to 0.7 on non-3dfx hardware
} else
vid_gamma = Q_atof(com_argv[i+1]);
 
for (i=0 ; i<768 ; i++)
{
f = pow ( (pal[i]+1)/256.0 , vid_gamma );
inf = f*255 + 0.5;
if (inf < 0)
inf = 0;
if (inf > 255)
inf = 255;
palette[i] = inf;
}
 
memcpy (pal, palette, sizeof(palette));
}
 
/*
===================
VID_Init
===================
*/
void VID_Init (unsigned char *palette)
{
int i, existingmode;
int basenummodes, width, height, bpp, findbpp, done;
byte *ptmp;
char gldir[MAX_OSPATH];
HDC hdc;
DEVMODE devmode;
 
memset(&devmode, 0, sizeof(devmode));
 
Cvar_RegisterVariable (&vid_mode);
Cvar_RegisterVariable (&vid_wait);
Cvar_RegisterVariable (&vid_nopageflip);
Cvar_RegisterVariable (&_vid_wait_override);
Cvar_RegisterVariable (&_vid_default_mode);
Cvar_RegisterVariable (&_vid_default_mode_win);
Cvar_RegisterVariable (&vid_config_x);
Cvar_RegisterVariable (&vid_config_y);
Cvar_RegisterVariable (&vid_stretch_by_2);
Cvar_RegisterVariable (&_windowed_mouse);
Cvar_RegisterVariable (&gl_ztrick);
 
Cmd_AddCommand ("vid_nummodes", VID_NumModes_f);
Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f);
Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f);
Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f);
 
hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON2));
 
InitCommonControls();
 
VID_InitDIB (global_hInstance);
basenummodes = nummodes = 1;
 
VID_InitFullDIB (global_hInstance);
 
if (COM_CheckParm("-window"))
{
hdc = GetDC (NULL);
 
if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
{
Sys_Error ("Can't run in non-RGB mode");
}
 
ReleaseDC (NULL, hdc);
 
windowed = true;
 
vid_default = MODE_WINDOWED;
}
else
{
if (nummodes == 1)
Sys_Error ("No RGB fullscreen modes available");
 
windowed = false;
 
if (COM_CheckParm("-mode"))
{
vid_default = Q_atoi(com_argv[COM_CheckParm("-mode")+1]);
}
else
{
if (COM_CheckParm("-current"))
{
modelist[MODE_FULLSCREEN_DEFAULT].width =
GetSystemMetrics (SM_CXSCREEN);
modelist[MODE_FULLSCREEN_DEFAULT].height =
GetSystemMetrics (SM_CYSCREEN);
vid_default = MODE_FULLSCREEN_DEFAULT;
leavecurrentmode = 1;
}
else
{
if (COM_CheckParm("-width"))
{
width = Q_atoi(com_argv[COM_CheckParm("-width")+1]);
}
else
{
width = 640;
}
 
if (COM_CheckParm("-bpp"))
{
bpp = Q_atoi(com_argv[COM_CheckParm("-bpp")+1]);
findbpp = 0;
}
else
{
bpp = 15;
findbpp = 1;
}
 
if (COM_CheckParm("-height"))
height = Q_atoi(com_argv[COM_CheckParm("-height")+1]);
 
// if they want to force it, add the specified mode to the list
if (COM_CheckParm("-force") && (nummodes < MAX_MODE_LIST))
{
modelist[nummodes].type = MS_FULLDIB;
modelist[nummodes].width = width;
modelist[nummodes].height = height;
modelist[nummodes].modenum = 0;
modelist[nummodes].halfscreen = 0;
modelist[nummodes].dib = 1;
modelist[nummodes].fullscreen = 1;
modelist[nummodes].bpp = bpp;
sprintf (modelist[nummodes].modedesc, "%dx%dx%d",
devmode.dmPelsWidth, devmode.dmPelsHeight,
devmode.dmBitsPerPel);
 
for (i=nummodes, existingmode = 0 ; i<nummodes ; i++)
{
if ((modelist[nummodes].width == modelist[i].width) &&
(modelist[nummodes].height == modelist[i].height) &&
(modelist[nummodes].bpp == modelist[i].bpp))
{
existingmode = 1;
break;
}
}
 
if (!existingmode)
{
nummodes++;
}
}
 
done = 0;
 
do
{
if (COM_CheckParm("-height"))
{
height = Q_atoi(com_argv[COM_CheckParm("-height")+1]);
 
for (i=1, vid_default=0 ; i<nummodes ; i++)
{
if ((modelist[i].width == width) &&
(modelist[i].height == height) &&
(modelist[i].bpp == bpp))
{
vid_default = i;
done = 1;
break;
}
}
}
else
{
for (i=1, vid_default=0 ; i<nummodes ; i++)
{
if ((modelist[i].width == width) && (modelist[i].bpp == bpp))
{
vid_default = i;
done = 1;
break;
}
}
}
 
if (!done)
{
if (findbpp)
{
switch (bpp)
{
case 15:
bpp = 16;
break;
case 16:
bpp = 32;
break;
case 32:
bpp = 24;
break;
case 24:
done = 1;
break;
}
}
else
{
done = 1;
}
}
} while (!done);
 
if (!vid_default)
{
Sys_Error ("Specified video mode not available");
}
}
}
}
 
vid_initialized = true;
 
if ((i = COM_CheckParm("-conwidth")) != 0)
vid.conwidth = Q_atoi(com_argv[i+1]);
else
vid.conwidth = 640;
 
vid.conwidth &= 0xfff8; // make it a multiple of eight
 
if (vid.conwidth < 320)
vid.conwidth = 320;
 
// pick a conheight that matches with correct aspect
vid.conheight = vid.conwidth*3 / 4;
 
if ((i = COM_CheckParm("-conheight")) != 0)
vid.conheight = Q_atoi(com_argv[i+1]);
if (vid.conheight < 200)
vid.conheight = 200;
 
vid.maxwarpwidth = WARP_WIDTH;
vid.maxwarpheight = WARP_HEIGHT;
vid.colormap = host_colormap;
vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
 
DestroyWindow (hwnd_dialog);
 
Check_Gamma(palette);
VID_SetPalette (palette);
 
VID_SetMode (vid_default, palette);
 
maindc = GetDC(mainwindow);
bSetupPixelFormat(maindc);
 
baseRC = wglCreateContext( maindc );
if (!baseRC)
Sys_Error ("Could not initialize GL (wglCreateContext failed).\n\nMake sure you in are 65535 color mode, and try running -window.");
if (!wglMakeCurrent( maindc, baseRC ))
Sys_Error ("wglMakeCurrent failed");
 
GL_Init ();
 
sprintf (gldir, "%s/glquake", com_gamedir);
Sys_mkdir (gldir);
 
vid_realmode = vid_modenum;
 
// Check for 3DFX Extensions and initialize them.
VID_Init8bitPalette();
 
vid_menudrawfn = VID_MenuDraw;
vid_menukeyfn = VID_MenuKey;
 
strcpy (badmode.modedesc, "Bad mode");
vid_canalttab = true;
 
if (COM_CheckParm("-fullsbar"))
fullsbardraw = true;
}
 
 
//========================================================
// Video menu stuff
//========================================================
 
extern void M_Menu_Options_f (void);
extern void M_Print (int cx, int cy, char *str);
extern void M_PrintWhite (int cx, int cy, char *str);
extern void M_DrawCharacter (int cx, int line, int num);
extern void M_DrawTransPic (int x, int y, qpic_t *pic);
extern void M_DrawPic (int x, int y, qpic_t *pic);
 
static int vid_line, vid_wmodes;
 
typedef struct
{
int modenum;
char *desc;
int iscur;
} modedesc_t;
 
#define MAX_COLUMN_SIZE 9
#define MODE_AREA_HEIGHT (MAX_COLUMN_SIZE + 2)
#define MAX_MODEDESCS (MAX_COLUMN_SIZE*3)
 
static modedesc_t modedescs[MAX_MODEDESCS];
 
/*
================
VID_MenuDraw
================
*/
void VID_MenuDraw (void)
{
qpic_t *p;
char *ptr;
int lnummodes, i, j, k, column, row, dup, dupmode;
char temp[100];
vmode_t *pv;
 
p = Draw_CachePic ("gfx/vidmodes.lmp");
M_DrawPic ( (320-p->width)/2, 4, p);
 
vid_wmodes = 0;
lnummodes = VID_NumModes ();
for (i=1 ; (i<lnummodes) && (vid_wmodes < MAX_MODEDESCS) ; i++)
{
ptr = VID_GetModeDescription (i);
pv = VID_GetModePtr (i);
 
k = vid_wmodes;
 
modedescs[k].modenum = i;
modedescs[k].desc = ptr;
modedescs[k].iscur = 0;
 
if (i == vid_modenum)
modedescs[k].iscur = 1;
 
vid_wmodes++;
 
}
 
if (vid_wmodes > 0)
{
M_Print (2*8, 36+0*8, "Fullscreen Modes (WIDTHxHEIGHTxBPP)");
 
column = 8;
row = 36+2*8;
 
for (i=0 ; i<vid_wmodes ; i++)
{
if (modedescs[i].iscur)
M_PrintWhite (column, row, modedescs[i].desc);
else
M_Print (column, row, modedescs[i].desc);
 
column += 13*8;
 
if ((i % VID_ROW_SIZE) == (VID_ROW_SIZE - 1))
{
column = 8;
row += 8;
}
}
}
 
M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*2,
"Video modes must be set from the");
M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*3,
"command line with -width <width>");
M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*4,
"and -bpp <bits-per-pixel>");
M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*6,
"Select windowed mode with -window");
}
 
 
/*
================
VID_MenuKey
================
*/
void VID_MenuKey (int key)
{
switch (key)
{
case K_ESCAPE:
S_LocalSound ("misc/menu1.wav");
M_Menu_Options_f ();
break;
 
default:
break;
}
}
/contrib/other/sdlquake-1.0.9/gl_warp.c
0,0 → 1,1092
/*
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_warp.c -- sky and water polygons
 
#include "quakedef.h"
 
extern model_t *loadmodel;
 
int skytexturenum;
 
int solidskytexture;
int alphaskytexture;
float speedscale; // for top sky and bottom sky
 
msurface_t *warpface;
 
extern cvar_t gl_subdivide_size;
 
void BoundPoly (int numverts, float *verts, vec3_t mins, vec3_t maxs)
{
int i, j;
float *v;
 
mins[0] = mins[1] = mins[2] = 9999;
maxs[0] = maxs[1] = maxs[2] = -9999;
v = verts;
for (i=0 ; i<numverts ; i++)
for (j=0 ; j<3 ; j++, v++)
{
if (*v < mins[j])
mins[j] = *v;
if (*v > maxs[j])
maxs[j] = *v;
}
}
 
void SubdividePolygon (int numverts, float *verts)
{
int i, j, k;
vec3_t mins, maxs;
float m;
float *v;
vec3_t front[64], back[64];
int f, b;
float dist[64];
float frac;
glpoly_t *poly;
float s, t;
 
if (numverts > 60)
Sys_Error ("numverts = %i", numverts);
 
BoundPoly (numverts, verts, mins, maxs);
 
for (i=0 ; i<3 ; i++)
{
m = (mins[i] + maxs[i]) * 0.5;
m = gl_subdivide_size.value * floor (m/gl_subdivide_size.value + 0.5);
if (maxs[i] - m < 8)
continue;
if (m - mins[i] < 8)
continue;
 
// cut it
v = verts + i;
for (j=0 ; j<numverts ; j++, v+= 3)
dist[j] = *v - m;
 
// wrap cases
dist[j] = dist[0];
v-=i;
VectorCopy (verts, v);
 
f = b = 0;
v = verts;
for (j=0 ; j<numverts ; j++, v+= 3)
{
if (dist[j] >= 0)
{
VectorCopy (v, front[f]);
f++;
}
if (dist[j] <= 0)
{
VectorCopy (v, back[b]);
b++;
}
if (dist[j] == 0 || dist[j+1] == 0)
continue;
if ( (dist[j] > 0) != (dist[j+1] > 0) )
{
// clip point
frac = dist[j] / (dist[j] - dist[j+1]);
for (k=0 ; k<3 ; k++)
front[f][k] = back[b][k] = v[k] + frac*(v[3+k] - v[k]);
f++;
b++;
}
}
 
SubdividePolygon (f, front[0]);
SubdividePolygon (b, back[0]);
return;
}
 
poly = Hunk_Alloc (sizeof(glpoly_t) + (numverts-4) * VERTEXSIZE*sizeof(float));
poly->next = warpface->polys;
warpface->polys = poly;
poly->numverts = numverts;
for (i=0 ; i<numverts ; i++, verts+= 3)
{
VectorCopy (verts, poly->verts[i]);
s = DotProduct (verts, warpface->texinfo->vecs[0]);
t = DotProduct (verts, warpface->texinfo->vecs[1]);
poly->verts[i][3] = s;
poly->verts[i][4] = t;
}
}
 
/*
================
GL_SubdivideSurface
 
Breaks a polygon up along axial 64 unit
boundaries so that turbulent and sky warps
can be done reasonably.
================
*/
void GL_SubdivideSurface (msurface_t *fa)
{
vec3_t verts[64];
int numverts;
int i;
int lindex;
float *vec;
texture_t *t;
 
warpface = fa;
 
//
// convert edges back to a normal polygon
//
numverts = 0;
for (i=0 ; i<fa->numedges ; i++)
{
lindex = loadmodel->surfedges[fa->firstedge + i];
 
if (lindex > 0)
vec = loadmodel->vertexes[loadmodel->edges[lindex].v[0]].position;
else
vec = loadmodel->vertexes[loadmodel->edges[-lindex].v[1]].position;
VectorCopy (vec, verts[numverts]);
numverts++;
}
 
SubdividePolygon (numverts, verts[0]);
}
 
//=========================================================
 
 
 
// speed up sin calculations - Ed
float turbsin[] =
{
#include "gl_warp_sin.h"
};
#define TURBSCALE (256.0 / (2 * M_PI))
 
/*
=============
EmitWaterPolys
 
Does a water warp on the pre-fragmented glpoly_t chain
=============
*/
void EmitWaterPolys (msurface_t *fa)
{
glpoly_t *p;
float *v;
int i;
float s, t, os, ot;
 
 
for (p=fa->polys ; p ; p=p->next)
{
glBegin (GL_POLYGON);
for (i=0,v=p->verts[0] ; i<p->numverts ; i++, v+=VERTEXSIZE)
{
os = v[3];
ot = v[4];
 
s = os + turbsin[(int)((ot*0.125+realtime) * TURBSCALE) & 255];
s *= (1.0/64);
 
t = ot + turbsin[(int)((os*0.125+realtime) * TURBSCALE) & 255];
t *= (1.0/64);
 
glTexCoord2f (s, t);
glVertex3fv (v);
}
glEnd ();
}
}
 
 
 
 
/*
=============
EmitSkyPolys
=============
*/
void EmitSkyPolys (msurface_t *fa)
{
glpoly_t *p;
float *v;
int i;
float s, t;
vec3_t dir;
float length;
 
for (p=fa->polys ; p ; p=p->next)
{
glBegin (GL_POLYGON);
for (i=0,v=p->verts[0] ; i<p->numverts ; i++, v+=VERTEXSIZE)
{
VectorSubtract (v, r_origin, dir);
dir[2] *= 3; // flatten the sphere
 
length = dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2];
length = sqrt (length);
length = 6*63/length;
 
dir[0] *= length;
dir[1] *= length;
 
s = (speedscale + dir[0]) * (1.0/128);
t = (speedscale + dir[1]) * (1.0/128);
 
glTexCoord2f (s, t);
glVertex3fv (v);
}
glEnd ();
}
}
 
/*
===============
EmitBothSkyLayers
 
Does a sky warp on the pre-fragmented glpoly_t chain
This will be called for brushmodels, the world
will have them chained together.
===============
*/
void EmitBothSkyLayers (msurface_t *fa)
{
int i;
int lindex;
float *vec;
 
GL_DisableMultitexture();
 
GL_Bind (solidskytexture);
speedscale = realtime*8;
speedscale -= (int)speedscale & ~127 ;
 
EmitSkyPolys (fa);
 
glEnable (GL_BLEND);
GL_Bind (alphaskytexture);
speedscale = realtime*16;
speedscale -= (int)speedscale & ~127 ;
 
EmitSkyPolys (fa);
 
glDisable (GL_BLEND);
}
 
#ifndef QUAKE2
/*
=================
R_DrawSkyChain
=================
*/
void R_DrawSkyChain (msurface_t *s)
{
msurface_t *fa;
 
GL_DisableMultitexture();
 
// used when gl_texsort is on
GL_Bind(solidskytexture);
speedscale = realtime*8;
speedscale -= (int)speedscale & ~127 ;
 
for (fa=s ; fa ; fa=fa->texturechain)
EmitSkyPolys (fa);
 
glEnable (GL_BLEND);
GL_Bind (alphaskytexture);
speedscale = realtime*16;
speedscale -= (int)speedscale & ~127 ;
 
for (fa=s ; fa ; fa=fa->texturechain)
EmitSkyPolys (fa);
 
glDisable (GL_BLEND);
}
 
#endif
 
/*
=================================================================
 
Quake 2 environment sky
 
=================================================================
*/
 
#ifdef QUAKE2
 
 
#define SKY_TEX 2000
 
/*
=================================================================
 
PCX Loading
 
=================================================================
*/
 
typedef struct
{
char manufacturer;
char version;
char encoding;
char bits_per_pixel;
unsigned short xmin,ymin,xmax,ymax;
unsigned short hres,vres;
unsigned char palette[48];
char reserved;
char color_planes;
unsigned short bytes_per_line;
unsigned short palette_type;
char filler[58];
unsigned data; // unbounded
} pcx_t;
 
byte *pcx_rgb;
 
/*
============
LoadPCX
============
*/
void LoadPCX (FILE *f)
{
pcx_t *pcx, pcxbuf;
byte palette[768];
byte *pix;
int x, y;
int dataByte, runLength;
int count;
 
//
// parse the PCX file
//
fread (&pcxbuf, 1, sizeof(pcxbuf), f);
 
pcx = &pcxbuf;
 
if (pcx->manufacturer != 0x0a
|| pcx->version != 5
|| pcx->encoding != 1
|| pcx->bits_per_pixel != 8
|| pcx->xmax >= 320
|| pcx->ymax >= 256)
{
Con_Printf ("Bad pcx file\n");
return;
}
 
// seek to palette
fseek (f, -768, SEEK_END);
fread (palette, 1, 768, f);
 
fseek (f, sizeof(pcxbuf) - 4, SEEK_SET);
 
count = (pcx->xmax+1) * (pcx->ymax+1);
pcx_rgb = malloc( count * 4);
 
for (y=0 ; y<=pcx->ymax ; y++)
{
pix = pcx_rgb + 4*y*(pcx->xmax+1);
for (x=0 ; x<=pcx->ymax ; )
{
dataByte = fgetc(f);
 
if((dataByte & 0xC0) == 0xC0)
{
runLength = dataByte & 0x3F;
dataByte = fgetc(f);
}
else
runLength = 1;
 
while(runLength-- > 0)
{
pix[0] = palette[dataByte*3];
pix[1] = palette[dataByte*3+1];
pix[2] = palette[dataByte*3+2];
pix[3] = 255;
pix += 4;
x++;
}
}
}
}
 
/*
=========================================================
 
TARGA LOADING
 
=========================================================
*/
 
typedef struct _TargaHeader {
unsigned char id_length, colormap_type, image_type;
unsigned short colormap_index, colormap_length;
unsigned char colormap_size;
unsigned short x_origin, y_origin, width, height;
unsigned char pixel_size, attributes;
} TargaHeader;
 
 
TargaHeader targa_header;
byte *targa_rgba;
 
int fgetLittleShort (FILE *f)
{
byte b1, b2;
 
b1 = fgetc(f);
b2 = fgetc(f);
 
return (short)(b1 + b2*256);
}
 
int fgetLittleLong (FILE *f)
{
byte b1, b2, b3, b4;
 
b1 = fgetc(f);
b2 = fgetc(f);
b3 = fgetc(f);
b4 = fgetc(f);
 
return b1 + (b2<<8) + (b3<<16) + (b4<<24);
}
 
 
/*
=============
LoadTGA
=============
*/
void LoadTGA (FILE *fin)
{
int columns, rows, numPixels;
byte *pixbuf;
int row, column;
 
targa_header.id_length = fgetc(fin);
targa_header.colormap_type = fgetc(fin);
targa_header.image_type = fgetc(fin);
targa_header.colormap_index = fgetLittleShort(fin);
targa_header.colormap_length = fgetLittleShort(fin);
targa_header.colormap_size = fgetc(fin);
targa_header.x_origin = fgetLittleShort(fin);
targa_header.y_origin = fgetLittleShort(fin);
targa_header.width = fgetLittleShort(fin);
targa_header.height = fgetLittleShort(fin);
targa_header.pixel_size = fgetc(fin);
targa_header.attributes = fgetc(fin);
 
if (targa_header.image_type!=2
&& targa_header.image_type!=10)
Sys_Error ("LoadTGA: Only type 2 and 10 targa RGB images supported\n");
 
if (targa_header.colormap_type !=0
|| (targa_header.pixel_size!=32 && targa_header.pixel_size!=24))
Sys_Error ("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
 
columns = targa_header.width;
rows = targa_header.height;
numPixels = columns * rows;
 
targa_rgba = malloc (numPixels*4);
if (targa_header.id_length != 0)
fseek(fin, targa_header.id_length, SEEK_CUR); // skip TARGA image comment
if (targa_header.image_type==2) { // Uncompressed, RGB images
for(row=rows-1; row>=0; row--) {
pixbuf = targa_rgba + row*columns*4;
for(column=0; column<columns; column++) {
unsigned char red,green,blue,alphabyte;
switch (targa_header.pixel_size) {
case 24:
blue = getc(fin);
green = getc(fin);
red = getc(fin);
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = 255;
break;
case 32:
blue = getc(fin);
green = getc(fin);
red = getc(fin);
alphabyte = getc(fin);
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = alphabyte;
break;
}
}
}
}
else if (targa_header.image_type==10) { // Runlength encoded RGB images
unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
for(row=rows-1; row>=0; row--) {
pixbuf = targa_rgba + row*columns*4;
for(column=0; column<columns; ) {
packetHeader=getc(fin);
packetSize = 1 + (packetHeader & 0x7f);
if (packetHeader & 0x80) { // run-length packet
switch (targa_header.pixel_size) {
case 24:
blue = getc(fin);
green = getc(fin);
red = getc(fin);
alphabyte = 255;
break;
case 32:
blue = getc(fin);
green = getc(fin);
red = getc(fin);
alphabyte = getc(fin);
break;
}
for(j=0;j<packetSize;j++) {
*pixbuf++=red;
*pixbuf++=green;
*pixbuf++=blue;
*pixbuf++=alphabyte;
column++;
if (column==columns) { // run spans across rows
column=0;
if (row>0)
row--;
else
goto breakOut;
pixbuf = targa_rgba + row*columns*4;
}
}
}
else { // non run-length packet
for(j=0;j<packetSize;j++) {
switch (targa_header.pixel_size) {
case 24:
blue = getc(fin);
green = getc(fin);
red = getc(fin);
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = 255;
break;
case 32:
blue = getc(fin);
green = getc(fin);
red = getc(fin);
alphabyte = getc(fin);
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = alphabyte;
break;
}
column++;
if (column==columns) { // pixel packet run spans across rows
column=0;
if (row>0)
row--;
else
goto breakOut;
pixbuf = targa_rgba + row*columns*4;
}
}
}
}
breakOut:;
}
}
fclose(fin);
}
 
/*
==================
R_LoadSkys
==================
*/
char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
void R_LoadSkys (void)
{
int i;
FILE *f;
char name[64];
 
for (i=0 ; i<6 ; i++)
{
GL_Bind (SKY_TEX + i);
sprintf (name, "gfx/env/bkgtst%s.tga", suf[i]);
COM_FOpenFile (name, &f);
if (!f)
{
Con_Printf ("Couldn't load %s\n", name);
continue;
}
LoadTGA (f);
// LoadPCX (f);
 
glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, targa_rgba);
// glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, pcx_rgb);
 
free (targa_rgba);
// free (pcx_rgb);
 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
}
 
 
vec3_t skyclip[6] = {
{1,1,0},
{1,-1,0},
{0,-1,1},
{0,1,1},
{1,0,1},
{-1,0,1}
};
int c_sky;
 
// 1 = s, 2 = t, 3 = 2048
int st_to_vec[6][3] =
{
{3,-1,2},
{-3,1,2},
 
{1,3,2},
{-1,-3,2},
 
{-2,-1,3}, // 0 degrees yaw, look straight up
{2,-1,-3} // look straight down
 
// {-1,2,3},
// {1,2,-3}
};
 
// s = [0]/[2], t = [1]/[2]
int vec_to_st[6][3] =
{
{-2,3,1},
{2,3,-1},
 
{1,3,2},
{-1,3,-2},
 
{-2,-1,3},
{-2,1,-3}
 
// {-1,2,3},
// {1,2,-3}
};
 
float skymins[2][6], skymaxs[2][6];
 
void DrawSkyPolygon (int nump, vec3_t vecs)
{
int i,j;
vec3_t v, av;
float s, t, dv;
int axis;
float *vp;
 
c_sky++;
#if 0
glBegin (GL_POLYGON);
for (i=0 ; i<nump ; i++, vecs+=3)
{
VectorAdd(vecs, r_origin, v);
glVertex3fv (v);
}
glEnd();
return;
#endif
// decide which face it maps to
VectorCopy (vec3_origin, v);
for (i=0, vp=vecs ; i<nump ; i++, vp+=3)
{
VectorAdd (vp, v, v);
}
av[0] = fabs(v[0]);
av[1] = fabs(v[1]);
av[2] = fabs(v[2]);
if (av[0] > av[1] && av[0] > av[2])
{
if (v[0] < 0)
axis = 1;
else
axis = 0;
}
else if (av[1] > av[2] && av[1] > av[0])
{
if (v[1] < 0)
axis = 3;
else
axis = 2;
}
else
{
if (v[2] < 0)
axis = 5;
else
axis = 4;
}
 
// project new texture coords
for (i=0 ; i<nump ; i++, vecs+=3)
{
j = vec_to_st[axis][2];
if (j > 0)
dv = vecs[j - 1];
else
dv = -vecs[-j - 1];
 
j = vec_to_st[axis][0];
if (j < 0)
s = -vecs[-j -1] / dv;
else
s = vecs[j-1] / dv;
j = vec_to_st[axis][1];
if (j < 0)
t = -vecs[-j -1] / dv;
else
t = vecs[j-1] / dv;
 
if (s < skymins[0][axis])
skymins[0][axis] = s;
if (t < skymins[1][axis])
skymins[1][axis] = t;
if (s > skymaxs[0][axis])
skymaxs[0][axis] = s;
if (t > skymaxs[1][axis])
skymaxs[1][axis] = t;
}
}
 
#define MAX_CLIP_VERTS 64
void ClipSkyPolygon (int nump, vec3_t vecs, int stage)
{
float *norm;
float *v;
qboolean front, back;
float d, e;
float dists[MAX_CLIP_VERTS];
int sides[MAX_CLIP_VERTS];
vec3_t newv[2][MAX_CLIP_VERTS];
int newc[2];
int i, j;
 
if (nump > MAX_CLIP_VERTS-2)
Sys_Error ("ClipSkyPolygon: MAX_CLIP_VERTS");
if (stage == 6)
{ // fully clipped, so draw it
DrawSkyPolygon (nump, vecs);
return;
}
 
front = back = false;
norm = skyclip[stage];
for (i=0, v = vecs ; i<nump ; i++, v+=3)
{
d = DotProduct (v, norm);
if (d > ON_EPSILON)
{
front = true;
sides[i] = SIDE_FRONT;
}
else if (d < ON_EPSILON)
{
back = true;
sides[i] = SIDE_BACK;
}
else
sides[i] = SIDE_ON;
dists[i] = d;
}
 
if (!front || !back)
{ // not clipped
ClipSkyPolygon (nump, vecs, stage+1);
return;
}
 
// clip it
sides[i] = sides[0];
dists[i] = dists[0];
VectorCopy (vecs, (vecs+(i*3)) );
newc[0] = newc[1] = 0;
 
for (i=0, v = vecs ; i<nump ; i++, v+=3)
{
switch (sides[i])
{
case SIDE_FRONT:
VectorCopy (v, newv[0][newc[0]]);
newc[0]++;
break;
case SIDE_BACK:
VectorCopy (v, newv[1][newc[1]]);
newc[1]++;
break;
case SIDE_ON:
VectorCopy (v, newv[0][newc[0]]);
newc[0]++;
VectorCopy (v, newv[1][newc[1]]);
newc[1]++;
break;
}
 
if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
continue;
 
d = dists[i] / (dists[i] - dists[i+1]);
for (j=0 ; j<3 ; j++)
{
e = v[j] + d*(v[j+3] - v[j]);
newv[0][newc[0]][j] = e;
newv[1][newc[1]][j] = e;
}
newc[0]++;
newc[1]++;
}
 
// continue
ClipSkyPolygon (newc[0], newv[0][0], stage+1);
ClipSkyPolygon (newc[1], newv[1][0], stage+1);
}
 
/*
=================
R_DrawSkyChain
=================
*/
void R_DrawSkyChain (msurface_t *s)
{
msurface_t *fa;
 
int i;
vec3_t verts[MAX_CLIP_VERTS];
glpoly_t *p;
 
c_sky = 0;
GL_Bind(solidskytexture);
 
// calculate vertex values for sky box
 
for (fa=s ; fa ; fa=fa->texturechain)
{
for (p=fa->polys ; p ; p=p->next)
{
for (i=0 ; i<p->numverts ; i++)
{
VectorSubtract (p->verts[i], r_origin, verts[i]);
}
ClipSkyPolygon (p->numverts, verts[0], 0);
}
}
}
 
 
/*
==============
R_ClearSkyBox
==============
*/
void R_ClearSkyBox (void)
{
int i;
 
for (i=0 ; i<6 ; i++)
{
skymins[0][i] = skymins[1][i] = 9999;
skymaxs[0][i] = skymaxs[1][i] = -9999;
}
}
 
 
void MakeSkyVec (float s, float t, int axis)
{
vec3_t v, b;
int j, k;
 
b[0] = s*2048;
b[1] = t*2048;
b[2] = 2048;
 
for (j=0 ; j<3 ; j++)
{
k = st_to_vec[axis][j];
if (k < 0)
v[j] = -b[-k - 1];
else
v[j] = b[k - 1];
v[j] += r_origin[j];
}
 
// avoid bilerp seam
s = (s+1)*0.5;
t = (t+1)*0.5;
 
if (s < 1.0/512)
s = 1.0/512;
else if (s > 511.0/512)
s = 511.0/512;
if (t < 1.0/512)
t = 1.0/512;
else if (t > 511.0/512)
t = 511.0/512;
 
t = 1.0 - t;
glTexCoord2f (s, t);
glVertex3fv (v);
}
 
/*
==============
R_DrawSkyBox
==============
*/
int skytexorder[6] = {0,2,1,3,4,5};
void R_DrawSkyBox (void)
{
int i, j, k;
vec3_t v;
float s, t;
 
#if 0
glEnable (GL_BLEND);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glColor4f (1,1,1,0.5);
glDisable (GL_DEPTH_TEST);
#endif
for (i=0 ; i<6 ; i++)
{
if (skymins[0][i] >= skymaxs[0][i]
|| skymins[1][i] >= skymaxs[1][i])
continue;
 
GL_Bind (SKY_TEX+skytexorder[i]);
#if 0
skymins[0][i] = -1;
skymins[1][i] = -1;
skymaxs[0][i] = 1;
skymaxs[1][i] = 1;
#endif
glBegin (GL_QUADS);
MakeSkyVec (skymins[0][i], skymins[1][i], i);
MakeSkyVec (skymins[0][i], skymaxs[1][i], i);
MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i);
MakeSkyVec (skymaxs[0][i], skymins[1][i], i);
glEnd ();
}
#if 0
glDisable (GL_BLEND);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glColor4f (1,1,1,0.5);
glEnable (GL_DEPTH_TEST);
#endif
}
 
 
#endif
 
//===============================================================
 
/*
=============
R_InitSky
 
A sky texture is 256*128, with the right side being a masked overlay
==============
*/
void R_InitSky (texture_t *mt)
{
int i, j, p;
byte *src;
unsigned trans[128*128];
unsigned transpix;
int r, g, b;
unsigned *rgba;
extern int skytexturenum;
 
src = (byte *)mt + mt->offsets[0];
 
// make an average value for the back to avoid
// a fringe on the top level
 
r = g = b = 0;
for (i=0 ; i<128 ; i++)
for (j=0 ; j<128 ; j++)
{
p = src[i*256 + j + 128];
rgba = &d_8to24table[p];
trans[(i*128) + j] = *rgba;
r += ((byte *)rgba)[0];
g += ((byte *)rgba)[1];
b += ((byte *)rgba)[2];
}
 
((byte *)&transpix)[0] = r/(128*128);
((byte *)&transpix)[1] = g/(128*128);
((byte *)&transpix)[2] = b/(128*128);
((byte *)&transpix)[3] = 0;
 
 
if (!solidskytexture)
solidskytexture = texture_extension_number++;
GL_Bind (solidskytexture );
glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
 
for (i=0 ; i<128 ; i++)
for (j=0 ; j<128 ; j++)
{
p = src[i*256 + j];
if (p == 0)
trans[(i*128) + j] = transpix;
else
trans[(i*128) + j] = d_8to24table[p];
}
 
if (!alphaskytexture)
alphaskytexture = texture_extension_number++;
GL_Bind(alphaskytexture);
glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
 
/contrib/other/sdlquake-1.0.9/gl_warp_sin.h
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,
/contrib/other/sdlquake-1.0.9/glqnotes.txt
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.
 
/contrib/other/sdlquake-1.0.9/glquake.h
0,0 → 1,251
/*
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>
 
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
 
extern int texture_extension_number;
extern int texture_mode;
 
extern float gldepthmin, gldepthmax;
 
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);
int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha);
int GL_FindTexture (char *identifier);
 
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;
 
#ifdef _WIN32
extern PROC glArrayElementEXT;
extern PROC glColorPointerEXT;
extern PROC glTexturePointerEXT;
extern PROC glVertexPointerEXT;
#endif
 
// 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];
extern int particletexture;
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;
extern cvar_t r_mirroralpha;
extern cvar_t r_wateralpha;
extern cvar_t r_dynamic;
extern cvar_t r_novis;
 
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;
extern cvar_t gl_keeptjunctions;
extern cvar_t gl_reporttjunctions;
extern cvar_t gl_flashblend;
extern cvar_t gl_nocolors;
extern cvar_t gl_doubleeyes;
 
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;
 
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
#define TEXTURE0_SGIS 0x835E
#define TEXTURE1_SGIS 0x835F
 
#ifndef _WIN32
#define APIENTRY /* */
#endif
 
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);
/contrib/other/sdlquake-1.0.9/glquake2.h
0,0 → 1,209
/*
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
#include <windows.h>
 
#include <gl\gl.h>
#include <gl\glu.h>
 
void GL_BeginRendering (int *x, int *y, int *width, int *height);
void GL_EndRendering (void);
 
 
// 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;
 
extern int texture_extension_number;
extern int texture_mode;
 
extern float gldepthmin, gldepthmax;
 
void GL_Upload32 (unsigned *data, int width, int height, qboolean mipmap, qboolean alpha, qboolean modulate);
void GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean alpha, qboolean modulate);
int GL_LoadTexture (char *identifier, int width, int height, byte *data, int mipmap, int alpha, int modulate);
int GL_FindTexture (char *identifier);
 
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;
 
extern PROC glArrayElementEXT;
extern PROC glColorPointerEXT;
extern PROC glTexturePointerEXT;
extern PROC glVertexPointerEXT;
 
 
// r_local.h -- private refresh defs
 
#define MAXALIASVERTS 2000 // TODO: tune this
 
#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 particletexture;
extern int playertextures;
 
extern int skytexturenum; // index in cl.loadmodel, not gl texture object
 
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;
extern cvar_t r_dynamic;
 
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_fogblend;
extern cvar_t gl_polyblend;
extern cvar_t gl_keeptjunctions;
extern cvar_t gl_reporttjunctions;
 
extern int gl_lightmap_format;
extern int gl_solid_format;
extern int gl_alpha_format;
 
void R_TranslatePlayerSkin (int playernum);
void GL_Bind (int texnum);
/contrib/other/sdlquake-1.0.9/host.c
0,0 → 1,958
/*
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.
 
*/
// host.c -- coordinates spawning and killing of local servers
 
#include "quakedef.h"
#include "r_local.h"
 
/*
 
A server can allways be started, even if the system started out as a client
to a remote system.
 
A client can NOT be started if the system started as a dedicated server.
 
Memory is cleared / released when a server or client begins, not when they end.
 
*/
 
quakeparms_t host_parms;
 
qboolean host_initialized; // true if into command execution
 
double host_frametime;
double host_time;
double realtime; // without any filtering or bounding
double oldrealtime; // last frame run
int host_framecount;
 
int host_hunklevel;
 
int minimum_memory;
 
client_t *host_client; // current client
 
jmp_buf host_abortserver;
 
byte *host_basepal;
byte *host_colormap;
 
cvar_t host_framerate = {"host_framerate","0"}; // set for slow motion
cvar_t host_speeds = {"host_speeds","0"}; // set for running times
 
cvar_t sys_ticrate = {"sys_ticrate","0.05"};
cvar_t serverprofile = {"serverprofile","0"};
 
cvar_t fraglimit = {"fraglimit","0",false,true};
cvar_t timelimit = {"timelimit","0",false,true};
cvar_t teamplay = {"teamplay","0",false,true};
 
cvar_t samelevel = {"samelevel","0"};
cvar_t noexit = {"noexit","0",false,true};
 
#ifdef QUAKE2
cvar_t developer = {"developer","1"}; // should be 0 for release!
#else
cvar_t developer = {"developer","0"};
#endif
 
cvar_t skill = {"skill","1"}; // 0 - 3
cvar_t deathmatch = {"deathmatch","0"}; // 0, 1, or 2
cvar_t coop = {"coop","0"}; // 0 or 1
 
cvar_t pausable = {"pausable","1"};
 
cvar_t temp1 = {"temp1","0"};
 
 
/*
================
Host_EndGame
================
*/
void Host_EndGame (char *message, ...)
{
va_list argptr;
char string[1024];
va_start (argptr,message);
vsprintf (string,message,argptr);
va_end (argptr);
Con_DPrintf ("Host_EndGame: %s\n",string);
if (sv.active)
Host_ShutdownServer (false);
 
if (cls.state == ca_dedicated)
Sys_Error ("Host_EndGame: %s\n",string); // dedicated servers exit
if (cls.demonum != -1)
CL_NextDemo ();
else
CL_Disconnect ();
 
longjmp (host_abortserver, 1);
}
 
/*
================
Host_Error
 
This shuts down both the client and server
================
*/
void Host_Error (char *error, ...)
{
va_list argptr;
char string[1024];
static qboolean inerror = false;
if (inerror)
Sys_Error ("Host_Error: recursively entered");
inerror = true;
SCR_EndLoadingPlaque (); // reenable screen updates
 
va_start (argptr,error);
vsprintf (string,error,argptr);
va_end (argptr);
Con_Printf ("Host_Error: %s\n",string);
if (sv.active)
Host_ShutdownServer (false);
 
if (cls.state == ca_dedicated)
Sys_Error ("Host_Error: %s\n",string); // dedicated servers exit
 
CL_Disconnect ();
cls.demonum = -1;
 
inerror = false;
 
longjmp (host_abortserver, 1);
}
 
/*
================
Host_FindMaxClients
================
*/
void Host_FindMaxClients (void)
{
int i;
 
svs.maxclients = 1;
i = COM_CheckParm ("-dedicated");
if (i)
{
cls.state = ca_dedicated;
if (i != (com_argc - 1))
{
svs.maxclients = Q_atoi (com_argv[i+1]);
}
else
svs.maxclients = 8;
}
else
cls.state = ca_disconnected;
 
i = COM_CheckParm ("-listen");
if (i)
{
if (cls.state == ca_dedicated)
Sys_Error ("Only one of -dedicated or -listen can be specified");
if (i != (com_argc - 1))
svs.maxclients = Q_atoi (com_argv[i+1]);
else
svs.maxclients = 8;
}
if (svs.maxclients < 1)
svs.maxclients = 8;
else if (svs.maxclients > MAX_SCOREBOARD)
svs.maxclients = MAX_SCOREBOARD;
 
svs.maxclientslimit = svs.maxclients;
if (svs.maxclientslimit < 4)
svs.maxclientslimit = 4;
svs.clients = Hunk_AllocName (svs.maxclientslimit*sizeof(client_t), "clients");
 
if (svs.maxclients > 1)
Cvar_SetValue ("deathmatch", 1.0);
else
Cvar_SetValue ("deathmatch", 0.0);
}
 
 
/*
=======================
Host_InitLocal
======================
*/
void Host_InitLocal (void)
{
Host_InitCommands ();
Cvar_RegisterVariable (&host_framerate);
Cvar_RegisterVariable (&host_speeds);
 
Cvar_RegisterVariable (&sys_ticrate);
Cvar_RegisterVariable (&serverprofile);
 
Cvar_RegisterVariable (&fraglimit);
Cvar_RegisterVariable (&timelimit);
Cvar_RegisterVariable (&teamplay);
Cvar_RegisterVariable (&samelevel);
Cvar_RegisterVariable (&noexit);
Cvar_RegisterVariable (&skill);
Cvar_RegisterVariable (&developer);
Cvar_RegisterVariable (&deathmatch);
Cvar_RegisterVariable (&coop);
 
Cvar_RegisterVariable (&pausable);
 
Cvar_RegisterVariable (&temp1);
 
Host_FindMaxClients ();
host_time = 1.0; // so a think at time 0 won't get called
}
 
 
/*
===============
Host_WriteConfiguration
 
Writes key bindings and archived cvars to config.cfg
===============
*/
void Host_WriteConfiguration (void)
{
FILE *f;
 
// dedicated servers initialize the host but don't parse and set the
// config.cfg cvars
if (host_initialized & !isDedicated)
{
f = fopen (va("%s/config.cfg",com_gamedir), "w");
if (!f)
{
Con_Printf ("Couldn't write config.cfg.\n");
return;
}
Key_WriteBindings (f);
Cvar_WriteVariables (f);
 
fclose (f);
}
}
 
 
/*
=================
SV_ClientPrintf
 
Sends text across to be displayed
FIXME: make this just a stuffed echo?
=================
*/
void SV_ClientPrintf (char *fmt, ...)
{
va_list argptr;
char string[1024];
va_start (argptr,fmt);
vsprintf (string, fmt,argptr);
va_end (argptr);
MSG_WriteByte (&host_client->message, svc_print);
MSG_WriteString (&host_client->message, string);
}
 
/*
=================
SV_BroadcastPrintf
 
Sends text to all active clients
=================
*/
void SV_BroadcastPrintf (char *fmt, ...)
{
va_list argptr;
char string[1024];
int i;
va_start (argptr,fmt);
vsprintf (string, fmt,argptr);
va_end (argptr);
for (i=0 ; i<svs.maxclients ; i++)
if (svs.clients[i].active && svs.clients[i].spawned)
{
MSG_WriteByte (&svs.clients[i].message, svc_print);
MSG_WriteString (&svs.clients[i].message, string);
}
}
 
/*
=================
Host_ClientCommands
 
Send text over to the client to be executed
=================
*/
void Host_ClientCommands (char *fmt, ...)
{
va_list argptr;
char string[1024];
va_start (argptr,fmt);
vsprintf (string, fmt,argptr);
va_end (argptr);
MSG_WriteByte (&host_client->message, svc_stufftext);
MSG_WriteString (&host_client->message, string);
}
 
/*
=====================
SV_DropClient
 
Called when the player is getting totally kicked off the host
if (crash = true), don't bother sending signofs
=====================
*/
void SV_DropClient (qboolean crash)
{
int saveSelf;
int i;
client_t *client;
 
if (!crash)
{
// send any final messages (don't check for errors)
if (NET_CanSendMessage (host_client->netconnection))
{
MSG_WriteByte (&host_client->message, svc_disconnect);
NET_SendMessage (host_client->netconnection, &host_client->message);
}
if (host_client->edict && host_client->spawned)
{
// call the prog function for removing a client
// this will set the body to a dead frame, among other things
saveSelf = pr_global_struct->self;
pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
PR_ExecuteProgram (pr_global_struct->ClientDisconnect);
pr_global_struct->self = saveSelf;
}
 
Sys_Printf ("Client %s removed\n",host_client->name);
}
 
// break the net connection
NET_Close (host_client->netconnection);
host_client->netconnection = NULL;
 
// free the client (the body stays around)
host_client->active = false;
host_client->name[0] = 0;
host_client->old_frags = -999999;
net_activeconnections--;
 
// send notification to all clients
for (i=0, client = svs.clients ; i<svs.maxclients ; i++, client++)
{
if (!client->active)
continue;
MSG_WriteByte (&client->message, svc_updatename);
MSG_WriteByte (&client->message, host_client - svs.clients);
MSG_WriteString (&client->message, "");
MSG_WriteByte (&client->message, svc_updatefrags);
MSG_WriteByte (&client->message, host_client - svs.clients);
MSG_WriteShort (&client->message, 0);
MSG_WriteByte (&client->message, svc_updatecolors);
MSG_WriteByte (&client->message, host_client - svs.clients);
MSG_WriteByte (&client->message, 0);
}
}
 
/*
==================
Host_ShutdownServer
 
This only happens at the end of a game, not between levels
==================
*/
void Host_ShutdownServer(qboolean crash)
{
int i;
int count;
sizebuf_t buf;
char message[4];
double start;
 
if (!sv.active)
return;
 
sv.active = false;
 
// stop all client sounds immediately
if (cls.state == ca_connected)
CL_Disconnect ();
 
// flush any pending messages - like the score!!!
start = Sys_FloatTime();
do
{
count = 0;
for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
{
if (host_client->active && host_client->message.cursize)
{
if (NET_CanSendMessage (host_client->netconnection))
{
NET_SendMessage(host_client->netconnection, &host_client->message);
SZ_Clear (&host_client->message);
}
else
{
NET_GetMessage(host_client->netconnection);
count++;
}
}
}
if ((Sys_FloatTime() - start) > 3.0)
break;
}
while (count);
 
// make sure all the clients know we're disconnecting
buf.data = message;
buf.maxsize = 4;
buf.cursize = 0;
MSG_WriteByte(&buf, svc_disconnect);
count = NET_SendToAll(&buf, 5);
if (count)
Con_Printf("Host_ShutdownServer: NET_SendToAll failed for %u clients\n", count);
 
for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
if (host_client->active)
SV_DropClient(crash);
 
//
// clear structures
//
memset (&sv, 0, sizeof(sv));
memset (svs.clients, 0, svs.maxclientslimit*sizeof(client_t));
}
 
 
/*
================
Host_ClearMemory
 
This clears all the memory used by both the client and server, but does
not reinitialize anything.
================
*/
void Host_ClearMemory (void)
{
Con_DPrintf ("Clearing memory\n");
D_FlushCaches ();
Mod_ClearAll ();
if (host_hunklevel)
Hunk_FreeToLowMark (host_hunklevel);
 
cls.signon = 0;
memset (&sv, 0, sizeof(sv));
memset (&cl, 0, sizeof(cl));
}
 
 
//============================================================================
 
 
/*
===================
Host_FilterTime
 
Returns false if the time is too short to run a frame
===================
*/
qboolean Host_FilterTime (float time)
{
realtime += time;
 
if (!cls.timedemo && realtime - oldrealtime < 1.0/72.0)
return false; // framerate is too high
 
host_frametime = realtime - oldrealtime;
oldrealtime = realtime;
 
if (host_framerate.value > 0)
host_frametime = host_framerate.value;
else
{ // don't allow really long or short frames
if (host_frametime > 0.1)
host_frametime = 0.1;
if (host_frametime < 0.001)
host_frametime = 0.001;
}
return true;
}
 
 
/*
===================
Host_GetConsoleCommands
 
Add them exactly as if they had been typed at the console
===================
*/
void Host_GetConsoleCommands (void)
{
char *cmd;
 
while (1)
{
cmd = Sys_ConsoleInput ();
if (!cmd)
break;
Cbuf_AddText (cmd);
}
}
 
 
/*
==================
Host_ServerFrame
 
==================
*/
#ifdef FPS_20
 
void _Host_ServerFrame (void)
{
// run the world state
pr_global_struct->frametime = host_frametime;
 
// read client messages
SV_RunClients ();
// move things around and think
// always pause in single player if in console or menus
if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game) )
SV_Physics ();
}
 
void Host_ServerFrame (void)
{
float save_host_frametime;
float temp_host_frametime;
 
// run the world state
pr_global_struct->frametime = host_frametime;
 
// set the time and clear the general datagram
SV_ClearDatagram ();
// check for new clients
SV_CheckForNewClients ();
 
temp_host_frametime = save_host_frametime = host_frametime;
while(temp_host_frametime > (1.0/72.0))
{
if (temp_host_frametime > 0.05)
host_frametime = 0.05;
else
host_frametime = temp_host_frametime;
temp_host_frametime -= host_frametime;
_Host_ServerFrame ();
}
host_frametime = save_host_frametime;
 
// send all messages to the clients
SV_SendClientMessages ();
}
 
#else
 
void Host_ServerFrame (void)
{
// run the world state
pr_global_struct->frametime = host_frametime;
 
// set the time and clear the general datagram
SV_ClearDatagram ();
// check for new clients
SV_CheckForNewClients ();
 
// read client messages
SV_RunClients ();
// move things around and think
// always pause in single player if in console or menus
if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game) )
SV_Physics ();
 
// send all messages to the clients
SV_SendClientMessages ();
}
 
#endif
 
 
/*
==================
Host_Frame
 
Runs all active servers
==================
*/
void _Host_Frame (float time)
{
static double time1 = 0;
static double time2 = 0;
static double time3 = 0;
int pass1, pass2, pass3;
 
if (setjmp (host_abortserver) )
return; // something bad happened, or the server disconnected
 
// keep the random time dependent
rand ();
// decide the simulation time
if (!Host_FilterTime (time))
return; // don't run too fast, or packets will flood out
// get new key events
Sys_SendKeyEvents ();
 
// allow mice or other external controllers to add commands
IN_Commands ();
 
// process console commands
Cbuf_Execute ();
 
NET_Poll();
 
// if running the server locally, make intentions now
if (sv.active)
CL_SendCmd ();
//-------------------
//
// server operations
//
//-------------------
 
// check for commands typed to the host
Host_GetConsoleCommands ();
if (sv.active)
Host_ServerFrame ();
 
//-------------------
//
// client operations
//
//-------------------
 
// if running the server remotely, send intentions now after
// the incoming messages have been read
if (!sv.active)
CL_SendCmd ();
 
host_time += host_frametime;
 
// fetch results from server
if (cls.state == ca_connected)
{
CL_ReadFromServer ();
}
 
// update video
if (host_speeds.value)
time1 = Sys_FloatTime ();
SCR_UpdateScreen ();
 
if (host_speeds.value)
time2 = Sys_FloatTime ();
// update audio
if (cls.signon == SIGNONS)
{
S_Update (r_origin, vpn, vright, vup);
CL_DecayLights ();
}
else
S_Update (vec3_origin, vec3_origin, vec3_origin, vec3_origin);
CDAudio_Update();
 
if (host_speeds.value)
{
pass1 = (time1 - time3)*1000;
time3 = Sys_FloatTime ();
pass2 = (time2 - time1)*1000;
pass3 = (time3 - time2)*1000;
Con_Printf ("%3i tot %3i server %3i gfx %3i snd\n",
pass1+pass2+pass3, pass1, pass2, pass3);
}
host_framecount++;
}
 
void Host_Frame (float time)
{
double time1, time2;
static double timetotal;
static int timecount;
int i, c, m;
 
if (!serverprofile.value)
{
_Host_Frame (time);
return;
}
time1 = Sys_FloatTime ();
_Host_Frame (time);
time2 = Sys_FloatTime ();
timetotal += time2 - time1;
timecount++;
if (timecount < 1000)
return;
 
m = timetotal*1000/timecount;
timecount = 0;
timetotal = 0;
c = 0;
for (i=0 ; i<svs.maxclients ; i++)
{
if (svs.clients[i].active)
c++;
}
 
Con_Printf ("serverprofile: %2i clients %2i msec\n", c, m);
}
 
//============================================================================
 
 
extern int vcrFile;
#define VCR_SIGNATURE 0x56435231
// "VCR1"
 
void Host_InitVCR (quakeparms_t *parms)
{
int i, len, n;
char *p;
if (COM_CheckParm("-playback"))
{
if (com_argc != 2)
Sys_Error("No other parameters allowed with -playback\n");
 
Sys_FileOpenRead("quake.vcr", &vcrFile);
if (vcrFile == -1)
Sys_Error("playback file not found\n");
 
Sys_FileRead (vcrFile, &i, sizeof(int));
if (i != VCR_SIGNATURE)
Sys_Error("Invalid signature in vcr file\n");
 
Sys_FileRead (vcrFile, &com_argc, sizeof(int));
com_argv = malloc(com_argc * sizeof(char *));
com_argv[0] = parms->argv[0];
for (i = 0; i < com_argc; i++)
{
Sys_FileRead (vcrFile, &len, sizeof(int));
p = malloc(len);
Sys_FileRead (vcrFile, p, len);
com_argv[i+1] = p;
}
com_argc++; /* add one for arg[0] */
parms->argc = com_argc;
parms->argv = com_argv;
}
 
if ( (n = COM_CheckParm("-record")) != 0)
{
vcrFile = Sys_FileOpenWrite("quake.vcr");
 
i = VCR_SIGNATURE;
Sys_FileWrite(vcrFile, &i, sizeof(int));
i = com_argc - 1;
Sys_FileWrite(vcrFile, &i, sizeof(int));
for (i = 1; i < com_argc; i++)
{
if (i == n)
{
len = 10;
Sys_FileWrite(vcrFile, &len, sizeof(int));
Sys_FileWrite(vcrFile, "-playback", len);
continue;
}
len = Q_strlen(com_argv[i]) + 1;
Sys_FileWrite(vcrFile, &len, sizeof(int));
Sys_FileWrite(vcrFile, com_argv[i], len);
}
}
}
 
/*
====================
Host_Init
====================
*/
void Host_Init (quakeparms_t *parms)
{
 
if (standard_quake)
minimum_memory = MINIMUM_MEMORY;
else
minimum_memory = MINIMUM_MEMORY_LEVELPAK;
 
if (COM_CheckParm ("-minmemory"))
parms->memsize = minimum_memory;
 
host_parms = *parms;
 
if (parms->memsize < minimum_memory)
Sys_Error ("Only %4.1f megs of memory available, can't execute game", parms->memsize / (float)0x100000);
 
com_argc = parms->argc;
com_argv = parms->argv;
 
Memory_Init (parms->membase, parms->memsize);
Cbuf_Init ();
Cmd_Init ();
V_Init ();
Chase_Init ();
Host_InitVCR (parms);
COM_Init (parms->basedir);
Host_InitLocal ();
W_LoadWadFile ("gfx.wad");
Key_Init ();
Con_Init ();
M_Init ();
PR_Init ();
Mod_Init ();
NET_Init ();
SV_Init ();
 
Con_Printf ("Exe: "__TIME__" "__DATE__"\n");
Con_Printf ("%4.1f megabyte heap\n",parms->memsize/ (1024*1024.0));
R_InitTextures (); // needed even for dedicated servers
if (cls.state != ca_dedicated)
{
host_basepal = (byte *)COM_LoadHunkFile ("gfx/palette.lmp");
if (!host_basepal)
Sys_Error ("Couldn't load gfx/palette.lmp");
host_colormap = (byte *)COM_LoadHunkFile ("gfx/colormap.lmp");
if (!host_colormap)
Sys_Error ("Couldn't load gfx/colormap.lmp");
 
#ifndef _WIN32 // on non win32, mouse comes before video for security reasons
IN_Init ();
#endif
VID_Init (host_basepal);
 
Draw_Init ();
SCR_Init ();
R_Init ();
#ifndef _WIN32
// on Win32, sound initialization has to come before video initialization, so we
// can put up a popup if the sound hardware is in use
S_Init ();
#else
 
#ifdef GLQUAKE
// FIXME: doesn't use the new one-window approach yet
S_Init ();
#endif
 
#endif // _WIN32
CDAudio_Init ();
Sbar_Init ();
CL_Init ();
#ifdef _WIN32 // on non win32, mouse comes before video for security reasons
IN_Init ();
#endif
}
 
Cbuf_InsertText ("exec quake.rc\n");
 
Hunk_AllocName (0, "-HOST_HUNKLEVEL-");
host_hunklevel = Hunk_LowMark ();
 
host_initialized = true;
Sys_Printf ("========Quake Initialized=========\n");
}
 
 
/*
===============
Host_Shutdown
 
FIXME: this is a callback from Sys_Quit and Sys_Error. It would be better
to run quit through here before the final handoff to the sys code.
===============
*/
void Host_Shutdown(void)
{
static qboolean isdown = false;
if (isdown)
{
printf ("recursive shutdown\n");
return;
}
isdown = true;
 
// keep Con_Printf from trying to update the screen
scr_disabled_for_loading = true;
 
Host_WriteConfiguration ();
 
CDAudio_Shutdown ();
NET_Shutdown ();
S_Shutdown();
IN_Shutdown ();
 
if (cls.state != ca_dedicated)
{
VID_Shutdown();
}
}
 
/contrib/other/sdlquake-1.0.9/host_cmd.c
0,0 → 1,1925
/*
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"
 
extern cvar_t pausable;
 
int current_skill;
 
void Mod_Print (void);
 
/*
==================
Host_Quit_f
==================
*/
 
extern void M_Menu_Quit_f (void);
 
void Host_Quit_f (void)
{
if (key_dest != key_console && cls.state != ca_dedicated)
{
M_Menu_Quit_f ();
return;
}
CL_Disconnect ();
Host_ShutdownServer(false);
 
Sys_Quit ();
}
 
 
/*
==================
Host_Status_f
==================
*/
void Host_Status_f (void)
{
client_t *client;
int seconds;
int minutes;
int hours = 0;
int j;
void (*print) (char *fmt, ...);
if (cmd_source == src_command)
{
if (!sv.active)
{
Cmd_ForwardToServer ();
return;
}
print = Con_Printf;
}
else
print = SV_ClientPrintf;
 
print ("host: %s\n", Cvar_VariableString ("hostname"));
print ("version: %4.2f\n", VERSION);
if (tcpipAvailable)
print ("tcp/ip: %s\n", my_tcpip_address);
if (ipxAvailable)
print ("ipx: %s\n", my_ipx_address);
print ("map: %s\n", sv.name);
print ("players: %i active (%i max)\n\n", net_activeconnections, svs.maxclients);
for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
{
if (!client->active)
continue;
seconds = (int)(net_time - client->netconnection->connecttime);
minutes = seconds / 60;
if (minutes)
{
seconds -= (minutes * 60);
hours = minutes / 60;
if (hours)
minutes -= (hours * 60);
}
else
hours = 0;
print ("#%-2u %-16.16s %3i %2i:%02i:%02i\n", j+1, client->name, (int)client->edict->v.frags, hours, minutes, seconds);
print (" %s\n", client->netconnection->address);
}
}
 
 
/*
==================
Host_God_f
 
Sets client to godmode
==================
*/
void Host_God_f (void)
{
if (cmd_source == src_command)
{
Cmd_ForwardToServer ();
return;
}
 
if (pr_global_struct->deathmatch && !host_client->privileged)
return;
 
sv_player->v.flags = (int)sv_player->v.flags ^ FL_GODMODE;
if (!((int)sv_player->v.flags & FL_GODMODE) )
SV_ClientPrintf ("godmode OFF\n");
else
SV_ClientPrintf ("godmode ON\n");
}
 
void Host_Notarget_f (void)
{
if (cmd_source == src_command)
{
Cmd_ForwardToServer ();
return;
}
 
if (pr_global_struct->deathmatch && !host_client->privileged)
return;
 
sv_player->v.flags = (int)sv_player->v.flags ^ FL_NOTARGET;
if (!((int)sv_player->v.flags & FL_NOTARGET) )
SV_ClientPrintf ("notarget OFF\n");
else
SV_ClientPrintf ("notarget ON\n");
}
 
qboolean noclip_anglehack;
 
void Host_Noclip_f (void)
{
if (cmd_source == src_command)
{
Cmd_ForwardToServer ();
return;
}
 
if (pr_global_struct->deathmatch && !host_client->privileged)
return;
 
if (sv_player->v.movetype != MOVETYPE_NOCLIP)
{
noclip_anglehack = true;
sv_player->v.movetype = MOVETYPE_NOCLIP;
SV_ClientPrintf ("noclip ON\n");
}
else
{
noclip_anglehack = false;
sv_player->v.movetype = MOVETYPE_WALK;
SV_ClientPrintf ("noclip OFF\n");
}
}
 
/*
==================
Host_Fly_f
 
Sets client to flymode
==================
*/
void Host_Fly_f (void)
{
if (cmd_source == src_command)
{
Cmd_ForwardToServer ();
return;
}
 
if (pr_global_struct->deathmatch && !host_client->privileged)
return;
 
if (sv_player->v.movetype != MOVETYPE_FLY)
{
sv_player->v.movetype = MOVETYPE_FLY;
SV_ClientPrintf ("flymode ON\n");
}
else
{
sv_player->v.movetype = MOVETYPE_WALK;
SV_ClientPrintf ("flymode OFF\n");
}
}
 
 
/*
==================
Host_Ping_f
 
==================
*/
void Host_Ping_f (void)
{
int i, j;
float total;
client_t *client;
if (cmd_source == src_command)
{
Cmd_ForwardToServer ();
return;
}
 
SV_ClientPrintf ("Client ping times:\n");
for (i=0, client = svs.clients ; i<svs.maxclients ; i++, client++)
{
if (!client->active)
continue;
total = 0;
for (j=0 ; j<NUM_PING_TIMES ; j++)
total+=client->ping_times[j];
total /= NUM_PING_TIMES;
SV_ClientPrintf ("%4i %s\n", (int)(total*1000), client->name);
}
}
 
/*
===============================================================================
 
SERVER TRANSITIONS
 
===============================================================================
*/
 
 
/*
======================
Host_Map_f
 
handle a
map <servername>
command from the console. Active clients are kicked off.
======================
*/
void Host_Map_f (void)
{
int i;
char name[MAX_QPATH];
 
if (cmd_source != src_command)
return;
 
cls.demonum = -1; // stop demo loop in case this fails
 
CL_Disconnect ();
Host_ShutdownServer(false);
 
key_dest = key_game; // remove console or menu
SCR_BeginLoadingPlaque ();
 
cls.mapstring[0] = 0;
for (i=0 ; i<Cmd_Argc() ; i++)
{
strcat (cls.mapstring, Cmd_Argv(i));
strcat (cls.mapstring, " ");
}
strcat (cls.mapstring, "\n");
 
svs.serverflags = 0; // haven't completed an episode yet
strcpy (name, Cmd_Argv(1));
#ifdef QUAKE2
SV_SpawnServer (name, NULL);
#else
SV_SpawnServer (name);
#endif
if (!sv.active)
return;
if (cls.state != ca_dedicated)
{
strcpy (cls.spawnparms, "");
 
for (i=2 ; i<Cmd_Argc() ; i++)
{
strcat (cls.spawnparms, Cmd_Argv(i));
strcat (cls.spawnparms, " ");
}
Cmd_ExecuteString ("connect local", src_command);
}
}
 
/*
==================
Host_Changelevel_f
 
Goes to a new map, taking all clients along
==================
*/
void Host_Changelevel_f (void)
{
#ifdef QUAKE2
char level[MAX_QPATH];
char _startspot[MAX_QPATH];
char *startspot;
 
if (Cmd_Argc() < 2)
{
Con_Printf ("changelevel <levelname> : continue game on a new level\n");
return;
}
if (!sv.active || cls.demoplayback)
{
Con_Printf ("Only the server may changelevel\n");
return;
}
 
strcpy (level, Cmd_Argv(1));
if (Cmd_Argc() == 2)
startspot = NULL;
else
{
strcpy (_startspot, Cmd_Argv(2));
startspot = _startspot;
}
 
SV_SaveSpawnparms ();
SV_SpawnServer (level, startspot);
#else
char level[MAX_QPATH];
 
if (Cmd_Argc() != 2)
{
Con_Printf ("changelevel <levelname> : continue game on a new level\n");
return;
}
if (!sv.active || cls.demoplayback)
{
Con_Printf ("Only the server may changelevel\n");
return;
}
SV_SaveSpawnparms ();
strcpy (level, Cmd_Argv(1));
SV_SpawnServer (level);
#endif
}
 
/*
==================
Host_Restart_f
 
Restarts the current server for a dead player
==================
*/
void Host_Restart_f (void)
{
char mapname[MAX_QPATH];
#ifdef QUAKE2
char startspot[MAX_QPATH];
#endif
 
if (cls.demoplayback || !sv.active)
return;
 
if (cmd_source != src_command)
return;
strcpy (mapname, sv.name); // must copy out, because it gets cleared
// in sv_spawnserver
#ifdef QUAKE2
strcpy(startspot, sv.startspot);
SV_SpawnServer (mapname, startspot);
#else
SV_SpawnServer (mapname);
#endif
}
 
/*
==================
Host_Reconnect_f
 
This command causes the client to wait for the signon messages again.
This is sent just before a server changes levels
==================
*/
void Host_Reconnect_f (void)
{
SCR_BeginLoadingPlaque ();
cls.signon = 0; // need new connection messages
}
 
/*
=====================
Host_Connect_f
 
User command to connect to server
=====================
*/
void Host_Connect_f (void)
{
char name[MAX_QPATH];
cls.demonum = -1; // stop demo loop in case this fails
if (cls.demoplayback)
{
CL_StopPlayback ();
CL_Disconnect ();
}
strcpy (name, Cmd_Argv(1));
CL_EstablishConnection (name);
Host_Reconnect_f ();
}
 
 
/*
===============================================================================
 
LOAD / SAVE GAME
 
===============================================================================
*/
 
#define SAVEGAME_VERSION 5
 
/*
===============
Host_SavegameComment
 
Writes a SAVEGAME_COMMENT_LENGTH character comment describing the current
===============
*/
void Host_SavegameComment (char *text)
{
int i;
char kills[20];
 
for (i=0 ; i<SAVEGAME_COMMENT_LENGTH ; i++)
text[i] = ' ';
memcpy (text, cl.levelname, strlen(cl.levelname));
sprintf (kills,"kills:%3i/%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
memcpy (text+22, kills, strlen(kills));
// convert space to _ to make stdio happy
for (i=0 ; i<SAVEGAME_COMMENT_LENGTH ; i++)
if (text[i] == ' ')
text[i] = '_';
text[SAVEGAME_COMMENT_LENGTH] = '\0';
}
 
 
/*
===============
Host_Savegame_f
===============
*/
void Host_Savegame_f (void)
{
char name[256];
FILE *f;
int i;
char comment[SAVEGAME_COMMENT_LENGTH+1];
 
if (cmd_source != src_command)
return;
 
if (!sv.active)
{
Con_Printf ("Not playing a local game.\n");
return;
}
 
if (cl.intermission)
{
Con_Printf ("Can't save in intermission.\n");
return;
}
 
if (svs.maxclients != 1)
{
Con_Printf ("Can't save multiplayer games.\n");
return;
}
 
if (Cmd_Argc() != 2)
{
Con_Printf ("save <savename> : save a game\n");
return;
}
 
if (strstr(Cmd_Argv(1), ".."))
{
Con_Printf ("Relative pathnames are not allowed.\n");
return;
}
for (i=0 ; i<svs.maxclients ; i++)
{
if (svs.clients[i].active && (svs.clients[i].edict->v.health <= 0) )
{
Con_Printf ("Can't savegame with a dead player\n");
return;
}
}
 
sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1));
COM_DefaultExtension (name, ".sav");
Con_Printf ("Saving game to %s...\n", name);
f = fopen (name, "w");
if (!f)
{
Con_Printf ("ERROR: couldn't open.\n");
return;
}
fprintf (f, "%i\n", SAVEGAME_VERSION);
Host_SavegameComment (comment);
fprintf (f, "%s\n", comment);
for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
fprintf (f, "%f\n", svs.clients->spawn_parms[i]);
fprintf (f, "%d\n", current_skill);
fprintf (f, "%s\n", sv.name);
fprintf (f, "%f\n",sv.time);
 
// write the light styles
 
for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
{
if (sv.lightstyles[i])
fprintf (f, "%s\n", sv.lightstyles[i]);
else
fprintf (f,"m\n");
}
 
 
ED_WriteGlobals (f);
for (i=0 ; i<sv.num_edicts ; i++)
{
ED_Write (f, EDICT_NUM(i));
fflush (f);
}
fclose (f);
Con_Printf ("done.\n");
}
 
 
/*
===============
Host_Loadgame_f
===============
*/
void Host_Loadgame_f (void)
{
char name[MAX_OSPATH];
FILE *f;
char mapname[MAX_QPATH];
float time, tfloat;
char str[32768], *start;
int i, r;
edict_t *ent;
int entnum;
int version;
float spawn_parms[NUM_SPAWN_PARMS];
 
if (cmd_source != src_command)
return;
 
if (Cmd_Argc() != 2)
{
Con_Printf ("load <savename> : load a game\n");
return;
}
 
cls.demonum = -1; // stop demo loop in case this fails
 
sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1));
COM_DefaultExtension (name, ".sav");
// we can't call SCR_BeginLoadingPlaque, because too much stack space has
// been used. The menu calls it before stuffing loadgame command
// SCR_BeginLoadingPlaque ();
 
Con_Printf ("Loading game from %s...\n", name);
f = fopen (name, "r");
if (!f)
{
Con_Printf ("ERROR: couldn't open.\n");
return;
}
 
fscanf (f, "%i\n", &version);
if (version != SAVEGAME_VERSION)
{
fclose (f);
Con_Printf ("Savegame is version %i, not %i\n", version, SAVEGAME_VERSION);
return;
}
fscanf (f, "%s\n", str);
for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
fscanf (f, "%f\n", &spawn_parms[i]);
// this silliness is so we can load 1.06 save files, which have float skill values
fscanf (f, "%f\n", &tfloat);
current_skill = (int)(tfloat + 0.1);
Cvar_SetValue ("skill", (float)current_skill);
 
#ifdef QUAKE2
Cvar_SetValue ("deathmatch", 0);
Cvar_SetValue ("coop", 0);
Cvar_SetValue ("teamplay", 0);
#endif
 
fscanf (f, "%s\n",mapname);
fscanf (f, "%f\n",&time);
 
CL_Disconnect_f ();
#ifdef QUAKE2
SV_SpawnServer (mapname, NULL);
#else
SV_SpawnServer (mapname);
#endif
if (!sv.active)
{
Con_Printf ("Couldn't load map\n");
return;
}
sv.paused = true; // pause until all clients connect
sv.loadgame = true;
 
// load the light styles
 
for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
{
fscanf (f, "%s\n", str);
sv.lightstyles[i] = Hunk_Alloc (strlen(str)+1);
strcpy (sv.lightstyles[i], str);
}
 
// load the edicts out of the savegame file
entnum = -1; // -1 is the globals
while (!feof(f))
{
for (i=0 ; i<sizeof(str)-1 ; i++)
{
r = fgetc (f);
if (r == EOF || !r)
break;
str[i] = r;
if (r == '}')
{
i++;
break;
}
}
if (i == sizeof(str)-1)
Sys_Error ("Loadgame buffer overflow");
str[i] = 0;
start = str;
start = COM_Parse(str);
if (!com_token[0])
break; // end of file
if (strcmp(com_token,"{"))
Sys_Error ("First token isn't a brace");
if (entnum == -1)
{ // parse the global vars
ED_ParseGlobals (start);
}
else
{ // parse an edict
 
ent = EDICT_NUM(entnum);
memset (&ent->v, 0, progs->entityfields * 4);
ent->free = false;
ED_ParseEdict (start, ent);
// link it into the bsp tree
if (!ent->free)
SV_LinkEdict (ent, false);
}
 
entnum++;
}
sv.num_edicts = entnum;
sv.time = time;
 
fclose (f);
 
for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
svs.clients->spawn_parms[i] = spawn_parms[i];
 
if (cls.state != ca_dedicated)
{
CL_EstablishConnection ("local");
Host_Reconnect_f ();
}
}
 
#ifdef QUAKE2
void SaveGamestate()
{
char name[256];
FILE *f;
int i;
char comment[SAVEGAME_COMMENT_LENGTH+1];
edict_t *ent;
 
sprintf (name, "%s/%s.gip", com_gamedir, sv.name);
Con_Printf ("Saving game to %s...\n", name);
f = fopen (name, "w");
if (!f)
{
Con_Printf ("ERROR: couldn't open.\n");
return;
}
fprintf (f, "%i\n", SAVEGAME_VERSION);
Host_SavegameComment (comment);
fprintf (f, "%s\n", comment);
// for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
// fprintf (f, "%f\n", svs.clients->spawn_parms[i]);
fprintf (f, "%f\n", skill.value);
fprintf (f, "%s\n", sv.name);
fprintf (f, "%f\n", sv.time);
 
// write the light styles
 
for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
{
if (sv.lightstyles[i])
fprintf (f, "%s\n", sv.lightstyles[i]);
else
fprintf (f,"m\n");
}
 
 
for (i=svs.maxclients+1 ; i<sv.num_edicts ; i++)
{
ent = EDICT_NUM(i);
if ((int)ent->v.flags & FL_ARCHIVE_OVERRIDE)
continue;
fprintf (f, "%i\n",i);
ED_Write (f, ent);
fflush (f);
}
fclose (f);
Con_Printf ("done.\n");
}
 
int LoadGamestate(char *level, char *startspot)
{
char name[MAX_OSPATH];
FILE *f;
char mapname[MAX_QPATH];
float time, sk;
char str[32768], *start;
int i, r;
edict_t *ent;
int entnum;
int version;
// float spawn_parms[NUM_SPAWN_PARMS];
 
sprintf (name, "%s/%s.gip", com_gamedir, level);
Con_Printf ("Loading game from %s...\n", name);
f = fopen (name, "r");
if (!f)
{
Con_Printf ("ERROR: couldn't open.\n");
return -1;
}
 
fscanf (f, "%i\n", &version);
if (version != SAVEGAME_VERSION)
{
fclose (f);
Con_Printf ("Savegame is version %i, not %i\n", version, SAVEGAME_VERSION);
return -1;
}
fscanf (f, "%s\n", str);
// for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
// fscanf (f, "%f\n", &spawn_parms[i]);
fscanf (f, "%f\n", &sk);
Cvar_SetValue ("skill", sk);
 
fscanf (f, "%s\n",mapname);
fscanf (f, "%f\n",&time);
 
SV_SpawnServer (mapname, startspot);
 
if (!sv.active)
{
Con_Printf ("Couldn't load map\n");
return -1;
}
 
// load the light styles
for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
{
fscanf (f, "%s\n", str);
sv.lightstyles[i] = Hunk_Alloc (strlen(str)+1);
strcpy (sv.lightstyles[i], str);
}
 
// load the edicts out of the savegame file
while (!feof(f))
{
fscanf (f, "%i\n",&entnum);
for (i=0 ; i<sizeof(str)-1 ; i++)
{
r = fgetc (f);
if (r == EOF || !r)
break;
str[i] = r;
if (r == '}')
{
i++;
break;
}
}
if (i == sizeof(str)-1)
Sys_Error ("Loadgame buffer overflow");
str[i] = 0;
start = str;
start = COM_Parse(str);
if (!com_token[0])
break; // end of file
if (strcmp(com_token,"{"))
Sys_Error ("First token isn't a brace");
// parse an edict
 
ent = EDICT_NUM(entnum);
memset (&ent->v, 0, progs->entityfields * 4);
ent->free = false;
ED_ParseEdict (start, ent);
// link it into the bsp tree
if (!ent->free)
SV_LinkEdict (ent, false);
}
// sv.num_edicts = entnum;
sv.time = time;
fclose (f);
 
// for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
// svs.clients->spawn_parms[i] = spawn_parms[i];
 
return 0;
}
 
// changing levels within a unit
void Host_Changelevel2_f (void)
{
char level[MAX_QPATH];
char _startspot[MAX_QPATH];
char *startspot;
 
if (Cmd_Argc() < 2)
{
Con_Printf ("changelevel2 <levelname> : continue game on a new level in the unit\n");
return;
}
if (!sv.active || cls.demoplayback)
{
Con_Printf ("Only the server may changelevel\n");
return;
}
 
strcpy (level, Cmd_Argv(1));
if (Cmd_Argc() == 2)
startspot = NULL;
else
{
strcpy (_startspot, Cmd_Argv(2));
startspot = _startspot;
}
 
SV_SaveSpawnparms ();
 
// save the current level's state
SaveGamestate ();
 
// try to restore the new level
if (LoadGamestate (level, startspot))
SV_SpawnServer (level, startspot);
}
#endif
 
 
//============================================================================
 
/*
======================
Host_Name_f
======================
*/
void Host_Name_f (void)
{
char *newName;
 
if (Cmd_Argc () == 1)
{
Con_Printf ("\"name\" is \"%s\"\n", cl_name.string);
return;
}
if (Cmd_Argc () == 2)
newName = Cmd_Argv(1);
else
newName = Cmd_Args();
newName[15] = 0;
 
if (cmd_source == src_command)
{
if (Q_strcmp(cl_name.string, newName) == 0)
return;
Cvar_Set ("_cl_name", newName);
if (cls.state == ca_connected)
Cmd_ForwardToServer ();
return;
}
 
if (host_client->name[0] && strcmp(host_client->name, "unconnected") )
if (Q_strcmp(host_client->name, newName) != 0)
Con_Printf ("%s renamed to %s\n", host_client->name, newName);
Q_strcpy (host_client->name, newName);
host_client->edict->v.netname = host_client->name - pr_strings;
// send notification to all clients
MSG_WriteByte (&sv.reliable_datagram, svc_updatename);
MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients);
MSG_WriteString (&sv.reliable_datagram, host_client->name);
}
 
void Host_Version_f (void)
{
Con_Printf ("Version %4.2f\n", VERSION);
Con_Printf ("Exe: "__TIME__" "__DATE__"\n");
}
 
#ifdef IDGODS
void Host_Please_f (void)
{
client_t *cl;
int j;
if (cmd_source != src_command)
return;
 
if ((Cmd_Argc () == 3) && Q_strcmp(Cmd_Argv(1), "#") == 0)
{
j = Q_atof(Cmd_Argv(2)) - 1;
if (j < 0 || j >= svs.maxclients)
return;
if (!svs.clients[j].active)
return;
cl = &svs.clients[j];
if (cl->privileged)
{
cl->privileged = false;
cl->edict->v.flags = (int)cl->edict->v.flags & ~(FL_GODMODE|FL_NOTARGET);
cl->edict->v.movetype = MOVETYPE_WALK;
noclip_anglehack = false;
}
else
cl->privileged = true;
}
 
if (Cmd_Argc () != 2)
return;
 
for (j=0, cl = svs.clients ; j<svs.maxclients ; j++, cl++)
{
if (!cl->active)
continue;
if (Q_strcasecmp(cl->name, Cmd_Argv(1)) == 0)
{
if (cl->privileged)
{
cl->privileged = false;
cl->edict->v.flags = (int)cl->edict->v.flags & ~(FL_GODMODE|FL_NOTARGET);
cl->edict->v.movetype = MOVETYPE_WALK;
noclip_anglehack = false;
}
else
cl->privileged = true;
break;
}
}
}
#endif
 
 
void Host_Say(qboolean teamonly)
{
client_t *client;
client_t *save;
int j;
char *p;
unsigned char text[64];
qboolean fromServer = false;
 
if (cmd_source == src_command)
{
if (cls.state == ca_dedicated)
{
fromServer = true;
teamonly = false;
}
else
{
Cmd_ForwardToServer ();
return;
}
}
 
if (Cmd_Argc () < 2)
return;
 
save = host_client;
 
p = Cmd_Args();
// remove quotes if present
if (*p == '"')
{
p++;
p[Q_strlen(p)-1] = 0;
}
 
// turn on color set 1
if (!fromServer)
sprintf (text, "%c%s: ", 1, save->name);
else
sprintf (text, "%c<%s> ", 1, hostname.string);
 
j = sizeof(text) - 2 - Q_strlen(text); // -2 for /n and null terminator
if (Q_strlen(p) > j)
p[j] = 0;
 
strcat (text, p);
strcat (text, "\n");
 
for (j = 0, client = svs.clients; j < svs.maxclients; j++, client++)
{
if (!client || !client->active || !client->spawned)
continue;
if (teamplay.value && teamonly && client->edict->v.team != save->edict->v.team)
continue;
host_client = client;
SV_ClientPrintf("%s", text);
}
host_client = save;
 
Sys_Printf("%s", &text[1]);
}
 
 
void Host_Say_f(void)
{
Host_Say(false);
}
 
 
void Host_Say_Team_f(void)
{
Host_Say(true);
}
 
 
void Host_Tell_f(void)
{
client_t *client;
client_t *save;
int j;
char *p;
char text[64];
 
if (cmd_source == src_command)
{
Cmd_ForwardToServer ();
return;
}
 
if (Cmd_Argc () < 3)
return;
 
Q_strcpy(text, host_client->name);
Q_strcat(text, ": ");
 
p = Cmd_Args();
 
// remove quotes if present
if (*p == '"')
{
p++;
p[Q_strlen(p)-1] = 0;
}
 
// check length & truncate if necessary
j = sizeof(text) - 2 - Q_strlen(text); // -2 for /n and null terminator
if (Q_strlen(p) > j)
p[j] = 0;
 
strcat (text, p);
strcat (text, "\n");
 
save = host_client;
for (j = 0, client = svs.clients; j < svs.maxclients; j++, client++)
{
if (!client->active || !client->spawned)
continue;
if (Q_strcasecmp(client->name, Cmd_Argv(1)))
continue;
host_client = client;
SV_ClientPrintf("%s", text);
break;
}
host_client = save;
}
 
 
/*
==================
Host_Color_f
==================
*/
void Host_Color_f(void)
{
int top, bottom;
int playercolor;
if (Cmd_Argc() == 1)
{
Con_Printf ("\"color\" is \"%i %i\"\n", ((int)cl_color.value) >> 4, ((int)cl_color.value) & 0x0f);
Con_Printf ("color <0-13> [0-13]\n");
return;
}
 
if (Cmd_Argc() == 2)
top = bottom = atoi(Cmd_Argv(1));
else
{
top = atoi(Cmd_Argv(1));
bottom = atoi(Cmd_Argv(2));
}
top &= 15;
if (top > 13)
top = 13;
bottom &= 15;
if (bottom > 13)
bottom = 13;
playercolor = top*16 + bottom;
 
if (cmd_source == src_command)
{
Cvar_SetValue ("_cl_color", playercolor);
if (cls.state == ca_connected)
Cmd_ForwardToServer ();
return;
}
 
host_client->colors = playercolor;
host_client->edict->v.team = bottom + 1;
 
// send notification to all clients
MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients);
MSG_WriteByte (&sv.reliable_datagram, host_client->colors);
}
 
/*
==================
Host_Kill_f
==================
*/
void Host_Kill_f (void)
{
if (cmd_source == src_command)
{
Cmd_ForwardToServer ();
return;
}
 
if (sv_player->v.health <= 0)
{
SV_ClientPrintf ("Can't suicide -- allready dead!\n");
return;
}
pr_global_struct->time = sv.time;
pr_global_struct->self = EDICT_TO_PROG(sv_player);
PR_ExecuteProgram (pr_global_struct->ClientKill);
}
 
 
/*
==================
Host_Pause_f
==================
*/
void Host_Pause_f (void)
{
if (cmd_source == src_command)
{
Cmd_ForwardToServer ();
return;
}
if (!pausable.value)
SV_ClientPrintf ("Pause not allowed.\n");
else
{
sv.paused ^= 1;
 
if (sv.paused)
{
SV_BroadcastPrintf ("%s paused the game\n", pr_strings + sv_player->v.netname);
}
else
{
SV_BroadcastPrintf ("%s unpaused the game\n",pr_strings + sv_player->v.netname);
}
 
// send notification to all clients
MSG_WriteByte (&sv.reliable_datagram, svc_setpause);
MSG_WriteByte (&sv.reliable_datagram, sv.paused);
}
}
 
//===========================================================================
 
 
/*
==================
Host_PreSpawn_f
==================
*/
void Host_PreSpawn_f (void)
{
if (cmd_source == src_command)
{
Con_Printf ("prespawn is not valid from the console\n");
return;
}
 
if (host_client->spawned)
{
Con_Printf ("prespawn not valid -- allready spawned\n");
return;
}
SZ_Write (&host_client->message, sv.signon.data, sv.signon.cursize);
MSG_WriteByte (&host_client->message, svc_signonnum);
MSG_WriteByte (&host_client->message, 2);
host_client->sendsignon = true;
}
 
/*
==================
Host_Spawn_f
==================
*/
void Host_Spawn_f (void)
{
int i;
client_t *client;
edict_t *ent;
 
if (cmd_source == src_command)
{
Con_Printf ("spawn is not valid from the console\n");
return;
}
 
if (host_client->spawned)
{
Con_Printf ("Spawn not valid -- allready spawned\n");
return;
}
 
// run the entrance script
if (sv.loadgame)
{ // loaded games are fully inited allready
// if this is the last client to be connected, unpause
sv.paused = false;
}
else
{
// set up the edict
ent = host_client->edict;
 
memset (&ent->v, 0, progs->entityfields * 4);
ent->v.colormap = NUM_FOR_EDICT(ent);
ent->v.team = (host_client->colors & 15) + 1;
ent->v.netname = host_client->name - pr_strings;
 
// copy spawn parms out of the client_t
 
for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
(&pr_global_struct->parm1)[i] = host_client->spawn_parms[i];
 
// call the spawn function
 
pr_global_struct->time = sv.time;
pr_global_struct->self = EDICT_TO_PROG(sv_player);
PR_ExecuteProgram (pr_global_struct->ClientConnect);
 
if ((Sys_FloatTime() - host_client->netconnection->connecttime) <= sv.time)
Sys_Printf ("%s entered the game\n", host_client->name);
 
PR_ExecuteProgram (pr_global_struct->PutClientInServer);
}
 
 
// send all current names, colors, and frag counts
SZ_Clear (&host_client->message);
 
// send time of update
MSG_WriteByte (&host_client->message, svc_time);
MSG_WriteFloat (&host_client->message, sv.time);
 
for (i=0, client = svs.clients ; i<svs.maxclients ; i++, client++)
{
MSG_WriteByte (&host_client->message, svc_updatename);
MSG_WriteByte (&host_client->message, i);
MSG_WriteString (&host_client->message, client->name);
MSG_WriteByte (&host_client->message, svc_updatefrags);
MSG_WriteByte (&host_client->message, i);
MSG_WriteShort (&host_client->message, client->old_frags);
MSG_WriteByte (&host_client->message, svc_updatecolors);
MSG_WriteByte (&host_client->message, i);
MSG_WriteByte (&host_client->message, client->colors);
}
// send all current light styles
for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
{
MSG_WriteByte (&host_client->message, svc_lightstyle);
MSG_WriteByte (&host_client->message, (char)i);
MSG_WriteString (&host_client->message, sv.lightstyles[i]);
}
 
//
// send some stats
//
MSG_WriteByte (&host_client->message, svc_updatestat);
MSG_WriteByte (&host_client->message, STAT_TOTALSECRETS);
MSG_WriteLong (&host_client->message, pr_global_struct->total_secrets);
 
MSG_WriteByte (&host_client->message, svc_updatestat);
MSG_WriteByte (&host_client->message, STAT_TOTALMONSTERS);
MSG_WriteLong (&host_client->message, pr_global_struct->total_monsters);
 
MSG_WriteByte (&host_client->message, svc_updatestat);
MSG_WriteByte (&host_client->message, STAT_SECRETS);
MSG_WriteLong (&host_client->message, pr_global_struct->found_secrets);
 
MSG_WriteByte (&host_client->message, svc_updatestat);
MSG_WriteByte (&host_client->message, STAT_MONSTERS);
MSG_WriteLong (&host_client->message, pr_global_struct->killed_monsters);
 
//
// send a fixangle
// Never send a roll angle, because savegames can catch the server
// in a state where it is expecting the client to correct the angle
// and it won't happen if the game was just loaded, so you wind up
// with a permanent head tilt
ent = EDICT_NUM( 1 + (host_client - svs.clients) );
MSG_WriteByte (&host_client->message, svc_setangle);
for (i=0 ; i < 2 ; i++)
MSG_WriteAngle (&host_client->message, ent->v.angles[i] );
MSG_WriteAngle (&host_client->message, 0 );
 
SV_WriteClientdataToMessage (sv_player, &host_client->message);
 
MSG_WriteByte (&host_client->message, svc_signonnum);
MSG_WriteByte (&host_client->message, 3);
host_client->sendsignon = true;
}
 
/*
==================
Host_Begin_f
==================
*/
void Host_Begin_f (void)
{
if (cmd_source == src_command)
{
Con_Printf ("begin is not valid from the console\n");
return;
}
 
host_client->spawned = true;
}
 
//===========================================================================
 
 
/*
==================
Host_Kick_f
 
Kicks a user off of the server
==================
*/
void Host_Kick_f (void)
{
char *who;
char *message = NULL;
client_t *save;
int i;
qboolean byNumber = false;
 
if (cmd_source == src_command)
{
if (!sv.active)
{
Cmd_ForwardToServer ();
return;
}
}
else if (pr_global_struct->deathmatch && !host_client->privileged)
return;
 
save = host_client;
 
if (Cmd_Argc() > 2 && Q_strcmp(Cmd_Argv(1), "#") == 0)
{
i = Q_atof(Cmd_Argv(2)) - 1;
if (i < 0 || i >= svs.maxclients)
return;
if (!svs.clients[i].active)
return;
host_client = &svs.clients[i];
byNumber = true;
}
else
{
for (i = 0, host_client = svs.clients; i < svs.maxclients; i++, host_client++)
{
if (!host_client->active)
continue;
if (Q_strcasecmp(host_client->name, Cmd_Argv(1)) == 0)
break;
}
}
 
if (i < svs.maxclients)
{
if (cmd_source == src_command)
if (cls.state == ca_dedicated)
who = "Console";
else
who = cl_name.string;
else
who = save->name;
 
// can't kick yourself!
if (host_client == save)
return;
 
if (Cmd_Argc() > 2)
{
message = COM_Parse(Cmd_Args());
if (byNumber)
{
message++; // skip the #
while (*message == ' ') // skip white space
message++;
message += Q_strlen(Cmd_Argv(2)); // skip the number
}
while (*message && *message == ' ')
message++;
}
if (message)
SV_ClientPrintf ("Kicked by %s: %s\n", who, message);
else
SV_ClientPrintf ("Kicked by %s\n", who);
SV_DropClient (false);
}
 
host_client = save;
}
 
/*
===============================================================================
 
DEBUGGING TOOLS
 
===============================================================================
*/
 
/*
==================
Host_Give_f
==================
*/
void Host_Give_f (void)
{
char *t;
int v, w;
eval_t *val;
 
if (cmd_source == src_command)
{
Cmd_ForwardToServer ();
return;
}
 
if (pr_global_struct->deathmatch && !host_client->privileged)
return;
 
t = Cmd_Argv(1);
v = atoi (Cmd_Argv(2));
switch (t[0])
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
// MED 01/04/97 added hipnotic give stuff
if (hipnotic)
{
if (t[0] == '6')
{
if (t[1] == 'a')
sv_player->v.items = (int)sv_player->v.items | HIT_PROXIMITY_GUN;
else
sv_player->v.items = (int)sv_player->v.items | IT_GRENADE_LAUNCHER;
}
else if (t[0] == '9')
sv_player->v.items = (int)sv_player->v.items | HIT_LASER_CANNON;
else if (t[0] == '0')
sv_player->v.items = (int)sv_player->v.items | HIT_MJOLNIR;
else if (t[0] >= '2')
sv_player->v.items = (int)sv_player->v.items | (IT_SHOTGUN << (t[0] - '2'));
}
else
{
if (t[0] >= '2')
sv_player->v.items = (int)sv_player->v.items | (IT_SHOTGUN << (t[0] - '2'));
}
break;
case 's':
if (rogue)
{
val = GetEdictFieldValue(sv_player, "ammo_shells1");
if (val)
val->_float = v;
}
 
sv_player->v.ammo_shells = v;
break;
case 'n':
if (rogue)
{
val = GetEdictFieldValue(sv_player, "ammo_nails1");
if (val)
{
val->_float = v;
if (sv_player->v.weapon <= IT_LIGHTNING)
sv_player->v.ammo_nails = v;
}
}
else
{
sv_player->v.ammo_nails = v;
}
break;
case 'l':
if (rogue)
{
val = GetEdictFieldValue(sv_player, "ammo_lava_nails");
if (val)
{
val->_float = v;
if (sv_player->v.weapon > IT_LIGHTNING)
sv_player->v.ammo_nails = v;
}
}
break;
case 'r':
if (rogue)
{
val = GetEdictFieldValue(sv_player, "ammo_rockets1");
if (val)
{
val->_float = v;
if (sv_player->v.weapon <= IT_LIGHTNING)
sv_player->v.ammo_rockets = v;
}
}
else
{
sv_player->v.ammo_rockets = v;
}
break;
case 'm':
if (rogue)
{
val = GetEdictFieldValue(sv_player, "ammo_multi_rockets");
if (val)
{
val->_float = v;
if (sv_player->v.weapon > IT_LIGHTNING)
sv_player->v.ammo_rockets = v;
}
}
break;
case 'h':
sv_player->v.health = v;
break;
case 'c':
if (rogue)
{
val = GetEdictFieldValue(sv_player, "ammo_cells1");
if (val)
{
val->_float = v;
if (sv_player->v.weapon <= IT_LIGHTNING)
sv_player->v.ammo_cells = v;
}
}
else
{
sv_player->v.ammo_cells = v;
}
break;
case 'p':
if (rogue)
{
val = GetEdictFieldValue(sv_player, "ammo_plasma");
if (val)
{
val->_float = v;
if (sv_player->v.weapon > IT_LIGHTNING)
sv_player->v.ammo_cells = v;
}
}
break;
}
}
 
edict_t *FindViewthing (void)
{
int i;
edict_t *e;
for (i=0 ; i<sv.num_edicts ; i++)
{
e = EDICT_NUM(i);
if ( !strcmp (pr_strings + e->v.classname, "viewthing") )
return e;
}
Con_Printf ("No viewthing on map\n");
return NULL;
}
 
/*
==================
Host_Viewmodel_f
==================
*/
void Host_Viewmodel_f (void)
{
edict_t *e;
model_t *m;
 
e = FindViewthing ();
if (!e)
return;
 
m = Mod_ForName (Cmd_Argv(1), false);
if (!m)
{
Con_Printf ("Can't load %s\n", Cmd_Argv(1));
return;
}
e->v.frame = 0;
cl.model_precache[(int)e->v.modelindex] = m;
}
 
/*
==================
Host_Viewframe_f
==================
*/
void Host_Viewframe_f (void)
{
edict_t *e;
int f;
model_t *m;
 
e = FindViewthing ();
if (!e)
return;
m = cl.model_precache[(int)e->v.modelindex];
 
f = atoi(Cmd_Argv(1));
if (f >= m->numframes)
f = m->numframes-1;
 
e->v.frame = f;
}
 
 
void PrintFrameName (model_t *m, int frame)
{
aliashdr_t *hdr;
maliasframedesc_t *pframedesc;
 
hdr = (aliashdr_t *)Mod_Extradata (m);
if (!hdr)
return;
pframedesc = &hdr->frames[frame];
Con_Printf ("frame %i: %s\n", frame, pframedesc->name);
}
 
/*
==================
Host_Viewnext_f
==================
*/
void Host_Viewnext_f (void)
{
edict_t *e;
model_t *m;
e = FindViewthing ();
if (!e)
return;
m = cl.model_precache[(int)e->v.modelindex];
 
e->v.frame = e->v.frame + 1;
if (e->v.frame >= m->numframes)
e->v.frame = m->numframes - 1;
 
PrintFrameName (m, e->v.frame);
}
 
/*
==================
Host_Viewprev_f
==================
*/
void Host_Viewprev_f (void)
{
edict_t *e;
model_t *m;
 
e = FindViewthing ();
if (!e)
return;
 
m = cl.model_precache[(int)e->v.modelindex];
 
e->v.frame = e->v.frame - 1;
if (e->v.frame < 0)
e->v.frame = 0;
 
PrintFrameName (m, e->v.frame);
}
 
/*
===============================================================================
 
DEMO LOOP CONTROL
 
===============================================================================
*/
 
 
/*
==================
Host_Startdemos_f
==================
*/
void Host_Startdemos_f (void)
{
int i, c;
 
if (cls.state == ca_dedicated)
{
if (!sv.active)
Cbuf_AddText ("map start\n");
return;
}
 
c = Cmd_Argc() - 1;
if (c > MAX_DEMOS)
{
Con_Printf ("Max %i demos in demoloop\n", MAX_DEMOS);
c = MAX_DEMOS;
}
Con_Printf ("%i demo(s) in loop\n", c);
 
for (i=1 ; i<c+1 ; i++)
strncpy (cls.demos[i-1], Cmd_Argv(i), sizeof(cls.demos[0])-1);
 
if (!sv.active && cls.demonum != -1 && !cls.demoplayback)
{
cls.demonum = 0;
CL_NextDemo ();
}
else
cls.demonum = -1;
}
 
 
/*
==================
Host_Demos_f
 
Return to looping demos
==================
*/
void Host_Demos_f (void)
{
if (cls.state == ca_dedicated)
return;
if (cls.demonum == -1)
cls.demonum = 1;
CL_Disconnect_f ();
CL_NextDemo ();
}
 
/*
==================
Host_Stopdemo_f
 
Return to looping demos
==================
*/
void Host_Stopdemo_f (void)
{
if (cls.state == ca_dedicated)
return;
if (!cls.demoplayback)
return;
CL_StopPlayback ();
CL_Disconnect ();
}
 
//=============================================================================
 
/*
==================
Host_InitCommands
==================
*/
void Host_InitCommands (void)
{
Cmd_AddCommand ("status", Host_Status_f);
Cmd_AddCommand ("quit", Host_Quit_f);
Cmd_AddCommand ("god", Host_God_f);
Cmd_AddCommand ("notarget", Host_Notarget_f);
Cmd_AddCommand ("fly", Host_Fly_f);
Cmd_AddCommand ("map", Host_Map_f);
Cmd_AddCommand ("restart", Host_Restart_f);
Cmd_AddCommand ("changelevel", Host_Changelevel_f);
#ifdef QUAKE2
Cmd_AddCommand ("changelevel2", Host_Changelevel2_f);
#endif
Cmd_AddCommand ("connect", Host_Connect_f);
Cmd_AddCommand ("reconnect", Host_Reconnect_f);
Cmd_AddCommand ("name", Host_Name_f);
Cmd_AddCommand ("noclip", Host_Noclip_f);
Cmd_AddCommand ("version", Host_Version_f);
#ifdef IDGODS
Cmd_AddCommand ("please", Host_Please_f);
#endif
Cmd_AddCommand ("say", Host_Say_f);
Cmd_AddCommand ("say_team", Host_Say_Team_f);
Cmd_AddCommand ("tell", Host_Tell_f);
Cmd_AddCommand ("color", Host_Color_f);
Cmd_AddCommand ("kill", Host_Kill_f);
Cmd_AddCommand ("pause", Host_Pause_f);
Cmd_AddCommand ("spawn", Host_Spawn_f);
Cmd_AddCommand ("begin", Host_Begin_f);
Cmd_AddCommand ("prespawn", Host_PreSpawn_f);
Cmd_AddCommand ("kick", Host_Kick_f);
Cmd_AddCommand ("ping", Host_Ping_f);
Cmd_AddCommand ("load", Host_Loadgame_f);
Cmd_AddCommand ("save", Host_Savegame_f);
Cmd_AddCommand ("give", Host_Give_f);
 
Cmd_AddCommand ("startdemos", Host_Startdemos_f);
Cmd_AddCommand ("demos", Host_Demos_f);
Cmd_AddCommand ("stopdemo", Host_Stopdemo_f);
 
Cmd_AddCommand ("viewmodel", Host_Viewmodel_f);
Cmd_AddCommand ("viewframe", Host_Viewframe_f);
Cmd_AddCommand ("viewnext", Host_Viewnext_f);
Cmd_AddCommand ("viewprev", Host_Viewprev_f);
 
Cmd_AddCommand ("mcache", Mod_Print);
}
/contrib/other/sdlquake-1.0.9/in_dos.c
0,0 → 1,615
/*
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.
 
*/
// in_mouse.c -- dos mouse code
 
#include "quakedef.h"
#include "dosisms.h"
 
#define AUX_FLAG_FREELOOK 0x00000001
 
typedef struct
{
long interruptVector;
char deviceName[16];
long numAxes;
long numButtons;
long flags;
vec3_t viewangles;
 
// intended velocities
float forwardmove;
float sidemove;
float upmove;
 
long buttons;
} externControl_t;
 
/*
#define AUX_FLAG_FORCEFREELOOK 0x00000001 // r/o
#define AUX_FLAG_EXTENDED 0x00000002 // r/o
#define AUX_FLAG_RUN 0x00000004 // w/o
#define AUX_FLAG_STRAFE 0x00000008 // w/o
#define AUX_FLAG_FREELOOK 0x00000010 // w/o
 
#define AUX_MAP_UNDEFINED 0
#define AUX_MAP_PITCH 1
#define AUX_MAP_YAW 2
#define AUX_MAP_ROLL 3
#define AUX_MAP_FORWARD 4
#define AUX_MAP_SIDE 5
#define AUX_MAP_UP 6
 
typedef struct
{
long interruptVector;
// r/o
char deviceName[16];
// r/o
long numAxes;
// r/o 1-6
long numButtons; // r/o 0-32
long flags; // see above
byte axisMapping[6]; // w/o default = p,y,r,f,s,u
float axisValue[6]; // r/w
float sensitivity[6]; // w/o default = 1.0
long buttons; // r/o
float last_frame_time; // w/o
} externControl_t;
*/
 
cvar_t m_filter = {"m_filter","1"};
 
qboolean mouse_avail;
int mouse_buttons;
int mouse_oldbuttonstate;
int mouse_buttonstate;
float mouse_x, mouse_y;
float old_mouse_x, old_mouse_y;
 
 
cvar_t in_joystick = {"joystick","1"};
cvar_t joy_numbuttons = {"joybuttons","4", true};
 
qboolean joy_avail;
int joy_oldbuttonstate;
int joy_buttonstate;
 
int joyxl, joyxh, joyyl, joyyh;
int joystickx, joysticky;
 
qboolean need_center;
 
qboolean extern_avail;
int extern_buttons;
int extern_oldbuttonstate;
int extern_buttonstate;
cvar_t aux_look = {"auxlook","1", true};
externControl_t *extern_control;
void IN_StartupExternal (void);
void IN_ExternalMove (usercmd_t *cmd);
 
void IN_StartupJoystick (void);
qboolean IN_ReadJoystick (void);
 
 
void Toggle_AuxLook_f (void)
{
if (aux_look.value)
Cvar_Set ("auxlook","0");
else
Cvar_Set ("auxlook","1");
}
 
 
void Force_CenterView_f (void)
{
cl.viewangles[PITCH] = 0;
}
 
 
/*
===========
IN_StartupMouse
===========
*/
void IN_StartupMouse (void)
{
if ( COM_CheckParm ("-nomouse") )
return;
// check for mouse
regs.x.ax = 0;
dos_int86(0x33);
mouse_avail = regs.x.ax;
if (!mouse_avail)
{
Con_Printf ("No mouse found\n");
return;
}
mouse_buttons = regs.x.bx;
if (mouse_buttons > 3)
mouse_buttons = 3;
Con_Printf("%d-button mouse available\n", mouse_buttons);
}
 
/*
===========
IN_Init
===========
*/
void IN_Init (void)
{
int i;
 
Cvar_RegisterVariable (&m_filter);
Cvar_RegisterVariable (&in_joystick);
Cvar_RegisterVariable (&joy_numbuttons);
Cvar_RegisterVariable (&aux_look);
Cmd_AddCommand ("toggle_auxlook", Toggle_AuxLook_f);
Cmd_AddCommand ("force_centerview", Force_CenterView_f);
 
IN_StartupMouse ();
IN_StartupJoystick ();
 
i = COM_CheckParm ("-control");
if (i)
{
extern_control = real2ptr(Q_atoi (com_argv[i+1]));
IN_StartupExternal ();
}
}
 
/*
===========
IN_Shutdown
===========
*/
void IN_Shutdown (void)
{
 
}
 
 
/*
===========
IN_Commands
===========
*/
void IN_Commands (void)
{
int i;
 
if (mouse_avail)
{
regs.x.ax = 3; // read buttons
dos_int86(0x33);
mouse_buttonstate = regs.x.bx;
// perform button actions
for (i=0 ; i<mouse_buttons ; i++)
{
if ( (mouse_buttonstate & (1<<i)) &&
!(mouse_oldbuttonstate & (1<<i)) )
{
Key_Event (K_MOUSE1 + i, true);
}
if ( !(mouse_buttonstate & (1<<i)) &&
(mouse_oldbuttonstate & (1<<i)) )
{
Key_Event (K_MOUSE1 + i, false);
}
}
mouse_oldbuttonstate = mouse_buttonstate;
}
if (joy_avail)
{
joy_buttonstate = ((dos_inportb(0x201) >> 4)&15)^15;
// perform button actions
for (i=0 ; i<joy_numbuttons.value ; i++)
{
if ( (joy_buttonstate & (1<<i)) &&
!(joy_oldbuttonstate & (1<<i)) )
{
Key_Event (K_JOY1 + i, true);
}
if ( !(joy_buttonstate & (1<<i)) &&
(joy_oldbuttonstate & (1<<i)) )
{
Key_Event (K_JOY1 + i, false);
}
}
joy_oldbuttonstate = joy_buttonstate;
}
 
if (extern_avail)
{
extern_buttonstate = extern_control->buttons;
// perform button actions
for (i=0 ; i<extern_buttons ; i++)
{
if ( (extern_buttonstate & (1<<i)) &&
!(extern_oldbuttonstate & (1<<i)) )
{
Key_Event (K_AUX1 + i, true);
}
if ( !(extern_buttonstate & (1<<i)) &&
(extern_oldbuttonstate & (1<<i)) )
{
Key_Event (K_AUX1 + i, false);
}
}
extern_oldbuttonstate = extern_buttonstate;
}
}
 
 
/*
===========
IN_Move
===========
*/
void IN_MouseMove (usercmd_t *cmd)
{
int mx, my;
 
if (!mouse_avail)
return;
 
regs.x.ax = 11; // read move
dos_int86(0x33);
mx = (short)regs.x.cx;
my = (short)regs.x.dx;
if (m_filter.value)
{
mouse_x = (mx + old_mouse_x) * 0.5;
mouse_y = (my + old_mouse_y) * 0.5;
}
else
{
mouse_x = mx;
mouse_y = my;
}
old_mouse_x = mx;
old_mouse_y = my;
 
mouse_x *= sensitivity.value;
mouse_y *= sensitivity.value;
 
// add mouse X/Y movement to cmd
if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
cmd->sidemove += m_side.value * mouse_x;
else
cl.viewangles[YAW] -= m_yaw.value * mouse_x;
if (in_mlook.state & 1)
V_StopPitchDrift ();
if ( (in_mlook.state & 1) && !(in_strafe.state & 1))
{
cl.viewangles[PITCH] += m_pitch.value * mouse_y;
if (cl.viewangles[PITCH] > 80)
cl.viewangles[PITCH] = 80;
if (cl.viewangles[PITCH] < -70)
cl.viewangles[PITCH] = -70;
}
else
{
if ((in_strafe.state & 1) && noclip_anglehack)
cmd->upmove -= m_forward.value * mouse_y;
else
cmd->forwardmove -= m_forward.value * mouse_y;
}
}
 
/*
===========
IN_JoyMove
===========
*/
void IN_JoyMove (usercmd_t *cmd)
{
float speed, aspeed;
 
if (!joy_avail || !in_joystick.value)
return;
IN_ReadJoystick ();
if (joysticky > joyyh*2 || joystickx > joyxh*2)
return; // assume something jumped in and messed up the joystick
// reading time (win 95)
 
if (in_speed.state & 1)
speed = cl_movespeedkey.value;
else
speed = 1;
aspeed = speed*host_frametime;
 
if (in_strafe.state & 1)
{
if (joystickx < joyxl)
cmd->sidemove -= speed*cl_sidespeed.value;
else if (joystickx > joyxh)
cmd->sidemove += speed*cl_sidespeed.value;
}
else
{
if (joystickx < joyxl)
cl.viewangles[YAW] += aspeed*cl_yawspeed.value;
else if (joystickx > joyxh)
cl.viewangles[YAW] -= aspeed*cl_yawspeed.value;
cl.viewangles[YAW] = anglemod(cl.viewangles[YAW]);
}
 
if (in_mlook.state & 1)
{
if (m_pitch.value < 0)
speed *= -1;
if (joysticky < joyyl)
cl.viewangles[PITCH] += aspeed*cl_pitchspeed.value;
else if (joysticky > joyyh)
cl.viewangles[PITCH] -= aspeed*cl_pitchspeed.value;
}
else
{
if (joysticky < joyyl)
cmd->forwardmove += speed*cl_forwardspeed.value;
else if (joysticky > joyyh)
cmd->forwardmove -= speed*cl_backspeed.value;
}
}
 
/*
===========
IN_Move
===========
*/
void IN_Move (usercmd_t *cmd)
{
IN_MouseMove (cmd);
IN_JoyMove (cmd);
IN_ExternalMove (cmd);
}
 
/*
============================================================================
JOYSTICK
============================================================================
*/
 
 
 
qboolean IN_ReadJoystick (void)
{
int b;
int count;
 
joystickx = 0;
joysticky = 0;
 
count = 0;
 
b = dos_inportb(0x201);
dos_outportb(0x201, b);
 
// clear counters
while (++count < 10000)
{
b = dos_inportb(0x201);
 
joystickx += b&1;
joysticky += (b&2)>>1;
if ( !(b&3) )
return true;
}
Con_Printf ("IN_ReadJoystick: no response\n");
joy_avail = false;
return false;
}
 
/*
=============
WaitJoyButton
=============
*/
qboolean WaitJoyButton (void)
{
int oldbuttons, buttons;
oldbuttons = 0;
do
{
key_count = -1;
Sys_SendKeyEvents ();
key_count = 0;
if (key_lastpress == K_ESCAPE)
{
Con_Printf ("aborted.\n");
return false;
}
key_lastpress = 0;
SCR_UpdateScreen ();
buttons = ((dos_inportb(0x201) >> 4)&1)^1;
if (buttons != oldbuttons)
{
oldbuttons = buttons;
continue;
}
} while ( !buttons);
do
{
key_count = -1;
Sys_SendKeyEvents ();
key_count = 0;
if (key_lastpress == K_ESCAPE)
{
Con_Printf ("aborted.\n");
return false;
}
key_lastpress = 0;
SCR_UpdateScreen ();
buttons = ((dos_inportb(0x201) >> 4)&1)^1;
if (buttons != oldbuttons)
{
oldbuttons = buttons;
continue;
}
} while ( buttons);
return true;
}
/*
===============
IN_StartupJoystick
===============
*/
void IN_StartupJoystick (void)
{
int centerx, centery;
Con_Printf ("\n");
 
joy_avail = false;
if ( COM_CheckParm ("-nojoy") )
return;
if (!IN_ReadJoystick ())
{
joy_avail = false;
Con_Printf ("joystick not found\n");
return;
}
 
Con_Printf ("joystick found\n");
Con_Printf ("CENTER the joystick\nand press button 1 (ESC to skip):\n");
if (!WaitJoyButton ())
return;
IN_ReadJoystick ();
centerx = joystickx;
centery = joysticky;
Con_Printf ("Push the joystick to the UPPER LEFT\nand press button 1 (ESC to skip):\n");
if (!WaitJoyButton ())
return;
IN_ReadJoystick ();
joyxl = (centerx + joystickx)/2;
joyyl = (centerx + joysticky)/2;
Con_Printf ("Push the joystick to the LOWER RIGHT\nand press button 1 (ESC to skip):\n");
if (!WaitJoyButton ())
return;
IN_ReadJoystick ();
joyxh = (centerx + joystickx)/2;
joyyh = (centery + joysticky)/2;
 
joy_avail = true;
Con_Printf ("joystick configured.\n");
 
Con_Printf ("\n");
}
/*
============================================================================
EXTERNAL
============================================================================
*/
 
 
/*
===============
IN_StartupExternal
===============
*/
void IN_StartupExternal (void)
{
if (extern_control->numButtons > 32)
extern_control->numButtons = 32;
 
Con_Printf("%s Initialized\n", extern_control->deviceName);
Con_Printf(" %u axes %u buttons\n", extern_control->numAxes, extern_control->numButtons);
 
extern_avail = true;
extern_buttons = extern_control->numButtons;
}
 
 
/*
===========
IN_ExternalMove
===========
*/
void IN_ExternalMove (usercmd_t *cmd)
{
qboolean freelook;
 
if (! extern_avail)
return;
 
extern_control->viewangles[YAW] = cl.viewangles[YAW];
extern_control->viewangles[PITCH] = cl.viewangles[PITCH];
extern_control->viewangles[ROLL] = cl.viewangles[ROLL];
extern_control->forwardmove = cmd->forwardmove;
extern_control->sidemove = cmd->sidemove;
extern_control->upmove = cmd->upmove;
 
Con_DPrintf("IN: y:%f p:%f r:%f f:%f s:%f u:%f\n", extern_control->viewangles[YAW], extern_control->viewangles[PITCH], extern_control->viewangles[ROLL], extern_control->forwardmove, extern_control->sidemove, extern_control->upmove);
 
dos_int86(extern_control->interruptVector);
 
Con_DPrintf("OUT: y:%f p:%f r:%f f:%f s:%f u:%f\n", extern_control->viewangles[YAW], extern_control->viewangles[PITCH], extern_control->viewangles[ROLL], extern_control->forwardmove, extern_control->sidemove, extern_control->upmove);
 
cl.viewangles[YAW] = extern_control->viewangles[YAW];
cl.viewangles[PITCH] = extern_control->viewangles[PITCH];
cl.viewangles[ROLL] = extern_control->viewangles[ROLL];
cmd->forwardmove = extern_control->forwardmove;
cmd->sidemove = extern_control->sidemove;
cmd->upmove = extern_control->upmove;
 
if (cl.viewangles[PITCH] > 80)
cl.viewangles[PITCH] = 80;
if (cl.viewangles[PITCH] < -70)
cl.viewangles[PITCH] = -70;
 
freelook = (extern_control->flags & AUX_FLAG_FREELOOK || aux_look.value || in_mlook.state & 1);
 
if (freelook)
V_StopPitchDrift ();
}
 
/contrib/other/sdlquake-1.0.9/in_null.c
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.
 
*/
// in_null.c -- for systems without a mouse
 
#include "quakedef.h"
 
void IN_Init (void)
{
}
 
void IN_Shutdown (void)
{
}
 
void IN_Commands (void)
{
}
 
void IN_Move (usercmd_t *cmd)
{
}
 
/contrib/other/sdlquake-1.0.9/in_sun.c
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.
 
*/
// in_sun.c -- SUN/X mouse input handler
 
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
 
#include "quakedef.h"
 
 
//
// typedefs and defines
//
 
#define MOUSE_SCALE 4
 
//
// externs
//
 
extern Display *x_disp;
extern int x_screen, x_screen_width, x_screen_height;
extern int x_center_height, x_center_width;
extern int x_std_event_mask;
extern Window x_win, x_root_win;
extern qboolean x_fullscreen;
extern qboolean x_focus;
extern int global_dx, global_dy;
//
// globals
//
 
cvar_t _windowed_mouse = {"_windowed_mouse","1", true};
int x_root, y_root;
int x_root_old, y_root_old;
//
// locals
//
 
static int x_mouse_num, x_mouse_denom, x_mouse_thresh;
 
 
static qboolean x_grabbed = false;
 
//
// IN_CenterMouse - center the mouse in the screen
//
 
void IN_CenterMouse( void )
{
CheckMouseState();
 
if (!x_grabbed)
return;
 
XSelectInput( x_disp, x_win, x_std_event_mask & ~PointerMotionMask );
XWarpPointer( x_disp, None, x_root_win, 0, 0, 0, 0, x_center_width,
x_center_height );
XSelectInput( x_disp, x_win, x_std_event_mask );
}
 
//
// Check to see if we have grabbed the mouse or not and deal with it
// appropriately
//
static void CheckMouseState(void)
{
if (x_focus && _windowed_mouse.value && !x_grabbed) {
x_grabbed = true;
printf("fooling with mouse!\n");
if (XGetPointerControl( x_disp, &x_mouse_num, &x_mouse_denom, &x_mouse_thresh ))
printf( "XGetPointerControl failed!\n" );
//printf( "mouse %d/%d thresh %d\n", x_mouse_num, x_mouse_denom, x_mouse_thresh );
 
// make input rawer
XAutoRepeatOff(x_disp);
XGrabKeyboard(x_disp, x_win, True, GrabModeAsync, GrabModeAsync, CurrentTime);
XGrabPointer(x_disp, x_win, True,
PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
 
// if (XChangePointerControl( x_disp, True, True, 1, MOUSE_SCALE, x_mouse_thresh ))
// printf( "XChangePointerControl failed!\n" );
 
IN_CenterMouse();
 
// safe initial values
x_root = x_root_old = vid.width >> 1;
y_root = y_root_old = vid.height >> 1;
} else if (x_grabbed && (!_windowed_mouse.value || !x_focus)) {
printf("fooling with mouse!\n");
x_grabbed = false;
// undo mouse warp
if (XChangePointerControl( x_disp, True, True, x_mouse_num, x_mouse_denom, x_mouse_thresh ))
printf( "XChangePointerControl failed!\n" );
 
XUngrabPointer( x_disp, CurrentTime );
XUngrabKeyboard( x_disp, CurrentTime );
XAutoRepeatOn( x_disp );
}
}
 
 
//
// IN_Init - setup mouse input
//
 
void IN_Init (void)
{
if (!x_disp) Sys_Error( "X display not open!\n" );
 
Cvar_RegisterVariable (&_windowed_mouse);
 
// we really really want to clean these up...
atexit( IN_Shutdown );
}
 
//
// IN_Shutdown - clean up mouse settings (must be done from signal handler too!)
//
 
void IN_Shutdown (void)
{
if (!x_disp) return;
 
// undo mouse warp
if (XChangePointerControl( x_disp, True, True, x_mouse_num, x_mouse_denom, x_mouse_thresh ))
printf( "XChangePointerControl failed!\n" );
 
XUngrabPointer( x_disp, CurrentTime );
XUngrabKeyboard( x_disp, CurrentTime );
XAutoRepeatOn( x_disp );
}
 
//
// IN_Commands - process buttons
//
 
void IN_Commands (void)
{
// done in X event handler
}
 
//
// IN_Move - process mouse moves
//
 
void
IN_Move (usercmd_t *cmd)
{
static int last_dx, last_dy;
static long long last_movement;
long long now, gethrtime();
 
int dx, dy;
 
CheckMouseState();
 
 
if (!x_grabbed)
return; // no mouse movement
 
now = gethrtime();
 
dx = global_dx;
global_dx = 0;
 
dy = global_dy;
global_dy = 0;
// printf("GOT: dx %d dy %d\n", dx, dy);
 
dx *= sensitivity.value;
dy *= sensitivity.value;
 
//
// implement low pass filter to smooth motion a bit
//
if (now - last_movement > 100000000) {
dx = .6 * dx;
dy = .6 * dy;
}
last_movement = now;
 
dx = .6 * dx + .4 * last_dx;
dy = .6 * dy + .4 * last_dy;
 
 
last_dx = dx;
last_dy = dy;
 
if (!dx && !dy) {
if (in_mlook.state & 1)
V_StopPitchDrift ();
return;
}
// add mouse X/Y movement to cmd
if ((in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1)))
cmd->sidemove += m_side.value * dx;
else
cl.viewangles[YAW] -= m_yaw.value * dx;
 
if (in_mlook.state & 1)
V_StopPitchDrift ();
if ((in_mlook.state & 1) && !(in_strafe.state & 1)) {
cl.viewangles[PITCH] += m_pitch.value * dy;
if (cl.viewangles[PITCH] > 80) cl.viewangles[PITCH] = 80;
if (cl.viewangles[PITCH] < -70) cl.viewangles[PITCH] = -70;
}
else {
if ((in_strafe.state & 1) && noclip_anglehack) cmd->upmove -= m_forward.value * dy;
else cmd->forwardmove -= m_forward.value * dy;
}
}
/contrib/other/sdlquake-1.0.9/in_win.c
0,0 → 1,1239
/*
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.
 
*/
// in_win.c -- windows 95 mouse and joystick code
// 02/21/97 JCB Added extended DirectInput code to support external controllers.
 
#include <dinput.h>
#include "quakedef.h"
#include "winquake.h"
#include "dosisms.h"
 
#define DINPUT_BUFFERSIZE 16
#define iDirectInputCreate(a,b,c,d) pDirectInputCreate(a,b,c,d)
 
HRESULT (WINAPI *pDirectInputCreate)(HINSTANCE hinst, DWORD dwVersion,
LPDIRECTINPUT * lplpDirectInput, LPUNKNOWN punkOuter);
 
// mouse variables
cvar_t m_filter = {"m_filter","0"};
 
int mouse_buttons;
int mouse_oldbuttonstate;
POINT current_pos;
int mouse_x, mouse_y, old_mouse_x, old_mouse_y, mx_accum, my_accum;
 
static qboolean restore_spi;
static int originalmouseparms[3], newmouseparms[3] = {0, 0, 1};
 
unsigned int uiWheelMessage;
qboolean mouseactive;
qboolean mouseinitialized;
static qboolean mouseparmsvalid, mouseactivatetoggle;
static qboolean mouseshowtoggle = 1;
static qboolean dinput_acquired;
 
static unsigned int mstate_di;
 
// joystick defines and variables
// where should defines be moved?
#define JOY_ABSOLUTE_AXIS 0x00000000 // control like a joystick
#define JOY_RELATIVE_AXIS 0x00000010 // control like a mouse, spinner, trackball
#define JOY_MAX_AXES 6 // X, Y, Z, R, U, V
#define JOY_AXIS_X 0
#define JOY_AXIS_Y 1
#define JOY_AXIS_Z 2
#define JOY_AXIS_R 3
#define JOY_AXIS_U 4
#define JOY_AXIS_V 5
 
enum _ControlList
{
AxisNada = 0, AxisForward, AxisLook, AxisSide, AxisTurn
};
 
DWORD dwAxisFlags[JOY_MAX_AXES] =
{
JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ, JOY_RETURNR, JOY_RETURNU, JOY_RETURNV
};
 
DWORD dwAxisMap[JOY_MAX_AXES];
DWORD dwControlMap[JOY_MAX_AXES];
PDWORD pdwRawValue[JOY_MAX_AXES];
 
// none of these cvars are saved over a session
// this means that advanced controller configuration needs to be executed
// each time. this avoids any problems with getting back to a default usage
// or when changing from one controller to another. this way at least something
// works.
cvar_t in_joystick = {"joystick","0", true};
cvar_t joy_name = {"joyname", "joystick"};
cvar_t joy_advanced = {"joyadvanced", "0"};
cvar_t joy_advaxisx = {"joyadvaxisx", "0"};
cvar_t joy_advaxisy = {"joyadvaxisy", "0"};
cvar_t joy_advaxisz = {"joyadvaxisz", "0"};
cvar_t joy_advaxisr = {"joyadvaxisr", "0"};
cvar_t joy_advaxisu = {"joyadvaxisu", "0"};
cvar_t joy_advaxisv = {"joyadvaxisv", "0"};
cvar_t joy_forwardthreshold = {"joyforwardthreshold", "0.15"};
cvar_t joy_sidethreshold = {"joysidethreshold", "0.15"};
cvar_t joy_pitchthreshold = {"joypitchthreshold", "0.15"};
cvar_t joy_yawthreshold = {"joyyawthreshold", "0.15"};
cvar_t joy_forwardsensitivity = {"joyforwardsensitivity", "-1.0"};
cvar_t joy_sidesensitivity = {"joysidesensitivity", "-1.0"};
cvar_t joy_pitchsensitivity = {"joypitchsensitivity", "1.0"};
cvar_t joy_yawsensitivity = {"joyyawsensitivity", "-1.0"};
cvar_t joy_wwhack1 = {"joywwhack1", "0.0"};
cvar_t joy_wwhack2 = {"joywwhack2", "0.0"};
 
qboolean joy_avail, joy_advancedinit, joy_haspov;
DWORD joy_oldbuttonstate, joy_oldpovstate;
 
int joy_id;
DWORD joy_flags;
DWORD joy_numbuttons;
 
static LPDIRECTINPUT g_pdi;
static LPDIRECTINPUTDEVICE g_pMouse;
 
static JOYINFOEX ji;
 
static HINSTANCE hInstDI;
 
static qboolean dinput;
 
typedef struct MYDATA {
LONG lX; // X axis goes here
LONG lY; // Y axis goes here
LONG lZ; // Z axis goes here
BYTE bButtonA; // One button goes here
BYTE bButtonB; // Another button goes here
BYTE bButtonC; // Another button goes here
BYTE bButtonD; // Another button goes here
} MYDATA;
 
static DIOBJECTDATAFORMAT rgodf[] = {
{ &GUID_XAxis, FIELD_OFFSET(MYDATA, lX), DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,},
{ &GUID_YAxis, FIELD_OFFSET(MYDATA, lY), DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,},
{ &GUID_ZAxis, FIELD_OFFSET(MYDATA, lZ), 0x80000000 | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,},
{ 0, FIELD_OFFSET(MYDATA, bButtonA), DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,},
{ 0, FIELD_OFFSET(MYDATA, bButtonB), DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,},
{ 0, FIELD_OFFSET(MYDATA, bButtonC), 0x80000000 | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,},
{ 0, FIELD_OFFSET(MYDATA, bButtonD), 0x80000000 | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,},
};
 
#define NUM_OBJECTS (sizeof(rgodf) / sizeof(rgodf[0]))
 
static DIDATAFORMAT df = {
sizeof(DIDATAFORMAT), // this structure
sizeof(DIOBJECTDATAFORMAT), // size of object data format
DIDF_RELAXIS, // absolute axis coordinates
sizeof(MYDATA), // device data size
NUM_OBJECTS, // number of objects
rgodf, // and here they are
};
 
// forward-referenced functions
void IN_StartupJoystick (void);
void Joy_AdvancedUpdate_f (void);
void IN_JoyMove (usercmd_t *cmd);
 
 
/*
===========
Force_CenterView_f
===========
*/
void Force_CenterView_f (void)
{
cl.viewangles[PITCH] = 0;
}
 
 
/*
===========
IN_UpdateClipCursor
===========
*/
void IN_UpdateClipCursor (void)
{
 
if (mouseinitialized && mouseactive && !dinput)
{
ClipCursor (&window_rect);
}
}
 
 
/*
===========
IN_ShowMouse
===========
*/
void IN_ShowMouse (void)
{
 
if (!mouseshowtoggle)
{
ShowCursor (TRUE);
mouseshowtoggle = 1;
}
}
 
 
/*
===========
IN_HideMouse
===========
*/
void IN_HideMouse (void)
{
 
if (mouseshowtoggle)
{
ShowCursor (FALSE);
mouseshowtoggle = 0;
}
}
 
 
/*
===========
IN_ActivateMouse
===========
*/
void IN_ActivateMouse (void)
{
 
mouseactivatetoggle = true;
 
if (mouseinitialized)
{
if (dinput)
{
if (g_pMouse)
{
if (!dinput_acquired)
{
IDirectInputDevice_Acquire(g_pMouse);
dinput_acquired = true;
}
}
else
{
return;
}
}
else
{
if (mouseparmsvalid)
restore_spi = SystemParametersInfo (SPI_SETMOUSE, 0, newmouseparms, 0);
 
SetCursorPos (window_center_x, window_center_y);
SetCapture (mainwindow);
ClipCursor (&window_rect);
}
 
mouseactive = true;
}
}
 
 
/*
===========
IN_SetQuakeMouseState
===========
*/
void IN_SetQuakeMouseState (void)
{
if (mouseactivatetoggle)
IN_ActivateMouse ();
}
 
 
/*
===========
IN_DeactivateMouse
===========
*/
void IN_DeactivateMouse (void)
{
 
mouseactivatetoggle = false;
 
if (mouseinitialized)
{
if (dinput)
{
if (g_pMouse)
{
if (dinput_acquired)
{
IDirectInputDevice_Unacquire(g_pMouse);
dinput_acquired = false;
}
}
}
else
{
if (restore_spi)
SystemParametersInfo (SPI_SETMOUSE, 0, originalmouseparms, 0);
 
ClipCursor (NULL);
ReleaseCapture ();
}
 
mouseactive = false;
}
}
 
 
/*
===========
IN_RestoreOriginalMouseState
===========
*/
void IN_RestoreOriginalMouseState (void)
{
if (mouseactivatetoggle)
{
IN_DeactivateMouse ();
mouseactivatetoggle = true;
}
 
// try to redraw the cursor so it gets reinitialized, because sometimes it
// has garbage after the mode switch
ShowCursor (TRUE);
ShowCursor (FALSE);
}
 
 
/*
===========
IN_InitDInput
===========
*/
qboolean IN_InitDInput (void)
{
HRESULT hr;
DIPROPDWORD dipdw = {
{
sizeof(DIPROPDWORD), // diph.dwSize
sizeof(DIPROPHEADER), // diph.dwHeaderSize
0, // diph.dwObj
DIPH_DEVICE, // diph.dwHow
},
DINPUT_BUFFERSIZE, // dwData
};
 
if (!hInstDI)
{
hInstDI = LoadLibrary("dinput.dll");
if (hInstDI == NULL)
{
Con_SafePrintf ("Couldn't load dinput.dll\n");
return false;
}
}
 
if (!pDirectInputCreate)
{
pDirectInputCreate = (void *)GetProcAddress(hInstDI,"DirectInputCreateA");
 
if (!pDirectInputCreate)
{
Con_SafePrintf ("Couldn't get DI proc addr\n");
return false;
}
}
 
// register with DirectInput and get an IDirectInput to play with.
hr = iDirectInputCreate(global_hInstance, DIRECTINPUT_VERSION, &g_pdi, NULL);
 
if (FAILED(hr))
{
return false;
}
 
// obtain an interface to the system mouse device.
hr = IDirectInput_CreateDevice(g_pdi, &GUID_SysMouse, &g_pMouse, NULL);
 
if (FAILED(hr))
{
Con_SafePrintf ("Couldn't open DI mouse device\n");
return false;
}
 
// set the data format to "mouse format".
hr = IDirectInputDevice_SetDataFormat(g_pMouse, &df);
 
if (FAILED(hr))
{
Con_SafePrintf ("Couldn't set DI mouse format\n");
return false;
}
 
// set the cooperativity level.
hr = IDirectInputDevice_SetCooperativeLevel(g_pMouse, mainwindow,
DISCL_EXCLUSIVE | DISCL_FOREGROUND);
 
if (FAILED(hr))
{
Con_SafePrintf ("Couldn't set DI coop level\n");
return false;
}
 
 
// set the buffer size to DINPUT_BUFFERSIZE elements.
// the buffer size is a DWORD property associated with the device
hr = IDirectInputDevice_SetProperty(g_pMouse, DIPROP_BUFFERSIZE, &dipdw.diph);
 
if (FAILED(hr))
{
Con_SafePrintf ("Couldn't set DI buffersize\n");
return false;
}
 
return true;
}
 
 
/*
===========
IN_StartupMouse
===========
*/
void IN_StartupMouse (void)
{
HDC hdc;
 
if ( COM_CheckParm ("-nomouse") )
return;
 
mouseinitialized = true;
 
if (COM_CheckParm ("-dinput"))
{
dinput = IN_InitDInput ();
 
if (dinput)
{
Con_SafePrintf ("DirectInput initialized\n");
}
else
{
Con_SafePrintf ("DirectInput not initialized\n");
}
}
 
if (!dinput)
{
mouseparmsvalid = SystemParametersInfo (SPI_GETMOUSE, 0, originalmouseparms, 0);
 
if (mouseparmsvalid)
{
if ( COM_CheckParm ("-noforcemspd") )
newmouseparms[2] = originalmouseparms[2];
 
if ( COM_CheckParm ("-noforcemaccel") )
{
newmouseparms[0] = originalmouseparms[0];
newmouseparms[1] = originalmouseparms[1];
}
 
if ( COM_CheckParm ("-noforcemparms") )
{
newmouseparms[0] = originalmouseparms[0];
newmouseparms[1] = originalmouseparms[1];
newmouseparms[2] = originalmouseparms[2];
}
}
}
 
mouse_buttons = 3;
 
// if a fullscreen video mode was set before the mouse was initialized,
// set the mouse state appropriately
if (mouseactivatetoggle)
IN_ActivateMouse ();
}
 
 
/*
===========
IN_Init
===========
*/
void IN_Init (void)
{
// mouse variables
Cvar_RegisterVariable (&m_filter);
 
// joystick variables
Cvar_RegisterVariable (&in_joystick);
Cvar_RegisterVariable (&joy_name);
Cvar_RegisterVariable (&joy_advanced);
Cvar_RegisterVariable (&joy_advaxisx);
Cvar_RegisterVariable (&joy_advaxisy);
Cvar_RegisterVariable (&joy_advaxisz);
Cvar_RegisterVariable (&joy_advaxisr);
Cvar_RegisterVariable (&joy_advaxisu);
Cvar_RegisterVariable (&joy_advaxisv);
Cvar_RegisterVariable (&joy_forwardthreshold);
Cvar_RegisterVariable (&joy_sidethreshold);
Cvar_RegisterVariable (&joy_pitchthreshold);
Cvar_RegisterVariable (&joy_yawthreshold);
Cvar_RegisterVariable (&joy_forwardsensitivity);
Cvar_RegisterVariable (&joy_sidesensitivity);
Cvar_RegisterVariable (&joy_pitchsensitivity);
Cvar_RegisterVariable (&joy_yawsensitivity);
Cvar_RegisterVariable (&joy_wwhack1);
Cvar_RegisterVariable (&joy_wwhack2);
 
Cmd_AddCommand ("force_centerview", Force_CenterView_f);
Cmd_AddCommand ("joyadvancedupdate", Joy_AdvancedUpdate_f);
 
uiWheelMessage = RegisterWindowMessage ( "MSWHEEL_ROLLMSG" );
 
IN_StartupMouse ();
IN_StartupJoystick ();
}
 
/*
===========
IN_Shutdown
===========
*/
void IN_Shutdown (void)
{
 
IN_DeactivateMouse ();
IN_ShowMouse ();
 
if (g_pMouse)
{
IDirectInputDevice_Release(g_pMouse);
g_pMouse = NULL;
}
 
if (g_pdi)
{
IDirectInput_Release(g_pdi);
g_pdi = NULL;
}
}
 
 
/*
===========
IN_MouseEvent
===========
*/
void IN_MouseEvent (int mstate)
{
int i;
 
if (mouseactive && !dinput)
{
// perform button actions
for (i=0 ; i<mouse_buttons ; i++)
{
if ( (mstate & (1<<i)) &&
!(mouse_oldbuttonstate & (1<<i)) )
{
Key_Event (K_MOUSE1 + i, true);
}
 
if ( !(mstate & (1<<i)) &&
(mouse_oldbuttonstate & (1<<i)) )
{
Key_Event (K_MOUSE1 + i, false);
}
}
mouse_oldbuttonstate = mstate;
}
}
 
 
/*
===========
IN_MouseMove
===========
*/
void IN_MouseMove (usercmd_t *cmd)
{
int mx, my;
HDC hdc;
int i;
DIDEVICEOBJECTDATA od;
DWORD dwElements;
HRESULT hr;
 
if (!mouseactive)
return;
 
if (dinput)
{
mx = 0;
my = 0;
 
for (;;)
{
dwElements = 1;
 
hr = IDirectInputDevice_GetDeviceData(g_pMouse,
sizeof(DIDEVICEOBJECTDATA), &od, &dwElements, 0);
 
if ((hr == DIERR_INPUTLOST) || (hr == DIERR_NOTACQUIRED))
{
dinput_acquired = true;
IDirectInputDevice_Acquire(g_pMouse);
break;
}
 
/* Unable to read data or no data available */
if (FAILED(hr) || dwElements == 0)
{
break;
}
 
/* Look at the element to see what happened */
 
switch (od.dwOfs)
{
case DIMOFS_X:
mx += od.dwData;
break;
 
case DIMOFS_Y:
my += od.dwData;
break;
 
case DIMOFS_BUTTON0:
if (od.dwData & 0x80)
mstate_di |= 1;
else
mstate_di &= ~1;
break;
 
case DIMOFS_BUTTON1:
if (od.dwData & 0x80)
mstate_di |= (1<<1);
else
mstate_di &= ~(1<<1);
break;
case DIMOFS_BUTTON2:
if (od.dwData & 0x80)
mstate_di |= (1<<2);
else
mstate_di &= ~(1<<2);
break;
}
}
 
// perform button actions
for (i=0 ; i<mouse_buttons ; i++)
{
if ( (mstate_di & (1<<i)) &&
!(mouse_oldbuttonstate & (1<<i)) )
{
Key_Event (K_MOUSE1 + i, true);
}
 
if ( !(mstate_di & (1<<i)) &&
(mouse_oldbuttonstate & (1<<i)) )
{
Key_Event (K_MOUSE1 + i, false);
}
}
mouse_oldbuttonstate = mstate_di;
}
else
{
GetCursorPos (&current_pos);
mx = current_pos.x - window_center_x + mx_accum;
my = current_pos.y - window_center_y + my_accum;
mx_accum = 0;
my_accum = 0;
}
 
//if (mx || my)
// Con_DPrintf("mx=%d, my=%d\n", mx, my);
 
if (m_filter.value)
{
mouse_x = (mx + old_mouse_x) * 0.5;
mouse_y = (my + old_mouse_y) * 0.5;
}
else
{
mouse_x = mx;
mouse_y = my;
}
 
old_mouse_x = mx;
old_mouse_y = my;
 
mouse_x *= sensitivity.value;
mouse_y *= sensitivity.value;
 
// add mouse X/Y movement to cmd
if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
cmd->sidemove += m_side.value * mouse_x;
else
cl.viewangles[YAW] -= m_yaw.value * mouse_x;
 
if (in_mlook.state & 1)
V_StopPitchDrift ();
if ( (in_mlook.state & 1) && !(in_strafe.state & 1))
{
cl.viewangles[PITCH] += m_pitch.value * mouse_y;
if (cl.viewangles[PITCH] > 80)
cl.viewangles[PITCH] = 80;
if (cl.viewangles[PITCH] < -70)
cl.viewangles[PITCH] = -70;
}
else
{
if ((in_strafe.state & 1) && noclip_anglehack)
cmd->upmove -= m_forward.value * mouse_y;
else
cmd->forwardmove -= m_forward.value * mouse_y;
}
 
// if the mouse has moved, force it to the center, so there's room to move
if (mx || my)
{
SetCursorPos (window_center_x, window_center_y);
}
}
 
 
/*
===========
IN_Move
===========
*/
void IN_Move (usercmd_t *cmd)
{
 
if (ActiveApp && !Minimized)
{
IN_MouseMove (cmd);
IN_JoyMove (cmd);
}
}
 
 
/*
===========
IN_Accumulate
===========
*/
void IN_Accumulate (void)
{
int mx, my;
HDC hdc;
 
if (mouseactive)
{
if (!dinput)
{
GetCursorPos (&current_pos);
 
mx_accum += current_pos.x - window_center_x;
my_accum += current_pos.y - window_center_y;
 
// force the mouse to the center, so there's room to move
SetCursorPos (window_center_x, window_center_y);
}
}
}
 
 
/*
===================
IN_ClearStates
===================
*/
void IN_ClearStates (void)
{
 
if (mouseactive)
{
mx_accum = 0;
my_accum = 0;
mouse_oldbuttonstate = 0;
}
}
 
 
/*
===============
IN_StartupJoystick
===============
*/
void IN_StartupJoystick (void)
{
int i, numdevs;
JOYCAPS jc;
MMRESULT mmr;
// assume no joystick
joy_avail = false;
 
// abort startup if user requests no joystick
if ( COM_CheckParm ("-nojoy") )
return;
// verify joystick driver is present
if ((numdevs = joyGetNumDevs ()) == 0)
{
Con_Printf ("\njoystick not found -- driver not present\n\n");
return;
}
 
// cycle through the joystick ids for the first valid one
for (joy_id=0 ; joy_id<numdevs ; joy_id++)
{
memset (&ji, 0, sizeof(ji));
ji.dwSize = sizeof(ji);
ji.dwFlags = JOY_RETURNCENTERED;
 
if ((mmr = joyGetPosEx (joy_id, &ji)) == JOYERR_NOERROR)
break;
}
 
// abort startup if we didn't find a valid joystick
if (mmr != JOYERR_NOERROR)
{
Con_Printf ("\njoystick not found -- no valid joysticks (%x)\n\n", mmr);
return;
}
 
// get the capabilities of the selected joystick
// abort startup if command fails
memset (&jc, 0, sizeof(jc));
if ((mmr = joyGetDevCaps (joy_id, &jc, sizeof(jc))) != JOYERR_NOERROR)
{
Con_Printf ("\njoystick not found -- invalid joystick capabilities (%x)\n\n", mmr);
return;
}
 
// save the joystick's number of buttons and POV status
joy_numbuttons = jc.wNumButtons;
joy_haspov = jc.wCaps & JOYCAPS_HASPOV;
 
// old button and POV states default to no buttons pressed
joy_oldbuttonstate = joy_oldpovstate = 0;
 
// mark the joystick as available and advanced initialization not completed
// this is needed as cvars are not available during initialization
 
joy_avail = true;
joy_advancedinit = false;
 
Con_Printf ("\njoystick detected\n\n");
}
 
 
/*
===========
RawValuePointer
===========
*/
PDWORD RawValuePointer (int axis)
{
switch (axis)
{
case JOY_AXIS_X:
return &ji.dwXpos;
case JOY_AXIS_Y:
return &ji.dwYpos;
case JOY_AXIS_Z:
return &ji.dwZpos;
case JOY_AXIS_R:
return &ji.dwRpos;
case JOY_AXIS_U:
return &ji.dwUpos;
case JOY_AXIS_V:
return &ji.dwVpos;
}
}
 
 
/*
===========
Joy_AdvancedUpdate_f
===========
*/
void Joy_AdvancedUpdate_f (void)
{
 
// called once by IN_ReadJoystick and by user whenever an update is needed
// cvars are now available
int i;
DWORD dwTemp;
 
// initialize all the maps
for (i = 0; i < JOY_MAX_AXES; i++)
{
dwAxisMap[i] = AxisNada;
dwControlMap[i] = JOY_ABSOLUTE_AXIS;
pdwRawValue[i] = RawValuePointer(i);
}
 
if( joy_advanced.value == 0.0)
{
// default joystick initialization
// 2 axes only with joystick control
dwAxisMap[JOY_AXIS_X] = AxisTurn;
// dwControlMap[JOY_AXIS_X] = JOY_ABSOLUTE_AXIS;
dwAxisMap[JOY_AXIS_Y] = AxisForward;
// dwControlMap[JOY_AXIS_Y] = JOY_ABSOLUTE_AXIS;
}
else
{
if (Q_strcmp (joy_name.string, "joystick") != 0)
{
// notify user of advanced controller
Con_Printf ("\n%s configured\n\n", joy_name.string);
}
 
// advanced initialization here
// data supplied by user via joy_axisn cvars
dwTemp = (DWORD) joy_advaxisx.value;
dwAxisMap[JOY_AXIS_X] = dwTemp & 0x0000000f;
dwControlMap[JOY_AXIS_X] = dwTemp & JOY_RELATIVE_AXIS;
dwTemp = (DWORD) joy_advaxisy.value;
dwAxisMap[JOY_AXIS_Y] = dwTemp & 0x0000000f;
dwControlMap[JOY_AXIS_Y] = dwTemp & JOY_RELATIVE_AXIS;
dwTemp = (DWORD) joy_advaxisz.value;
dwAxisMap[JOY_AXIS_Z] = dwTemp & 0x0000000f;
dwControlMap[JOY_AXIS_Z] = dwTemp & JOY_RELATIVE_AXIS;
dwTemp = (DWORD) joy_advaxisr.value;
dwAxisMap[JOY_AXIS_R] = dwTemp & 0x0000000f;
dwControlMap[JOY_AXIS_R] = dwTemp & JOY_RELATIVE_AXIS;
dwTemp = (DWORD) joy_advaxisu.value;
dwAxisMap[JOY_AXIS_U] = dwTemp & 0x0000000f;
dwControlMap[JOY_AXIS_U] = dwTemp & JOY_RELATIVE_AXIS;
dwTemp = (DWORD) joy_advaxisv.value;
dwAxisMap[JOY_AXIS_V] = dwTemp & 0x0000000f;
dwControlMap[JOY_AXIS_V] = dwTemp & JOY_RELATIVE_AXIS;
}
 
// compute the axes to collect from DirectInput
joy_flags = JOY_RETURNCENTERED | JOY_RETURNBUTTONS | JOY_RETURNPOV;
for (i = 0; i < JOY_MAX_AXES; i++)
{
if (dwAxisMap[i] != AxisNada)
{
joy_flags |= dwAxisFlags[i];
}
}
}
 
 
/*
===========
IN_Commands
===========
*/
void IN_Commands (void)
{
int i, key_index;
DWORD buttonstate, povstate;
 
if (!joy_avail)
{
return;
}
 
// loop through the joystick buttons
// key a joystick event or auxillary event for higher number buttons for each state change
buttonstate = ji.dwButtons;
for (i=0 ; i < joy_numbuttons ; i++)
{
if ( (buttonstate & (1<<i)) && !(joy_oldbuttonstate & (1<<i)) )
{
key_index = (i < 4) ? K_JOY1 : K_AUX1;
Key_Event (key_index + i, true);
}
 
if ( !(buttonstate & (1<<i)) && (joy_oldbuttonstate & (1<<i)) )
{
key_index = (i < 4) ? K_JOY1 : K_AUX1;
Key_Event (key_index + i, false);
}
}
joy_oldbuttonstate = buttonstate;
 
if (joy_haspov)
{
// convert POV information into 4 bits of state information
// this avoids any potential problems related to moving from one
// direction to another without going through the center position
povstate = 0;
if(ji.dwPOV != JOY_POVCENTERED)
{
if (ji.dwPOV == JOY_POVFORWARD)
povstate |= 0x01;
if (ji.dwPOV == JOY_POVRIGHT)
povstate |= 0x02;
if (ji.dwPOV == JOY_POVBACKWARD)
povstate |= 0x04;
if (ji.dwPOV == JOY_POVLEFT)
povstate |= 0x08;
}
// determine which bits have changed and key an auxillary event for each change
for (i=0 ; i < 4 ; i++)
{
if ( (povstate & (1<<i)) && !(joy_oldpovstate & (1<<i)) )
{
Key_Event (K_AUX29 + i, true);
}
 
if ( !(povstate & (1<<i)) && (joy_oldpovstate & (1<<i)) )
{
Key_Event (K_AUX29 + i, false);
}
}
joy_oldpovstate = povstate;
}
}
 
 
/*
===============
IN_ReadJoystick
===============
*/
qboolean IN_ReadJoystick (void)
{
 
memset (&ji, 0, sizeof(ji));
ji.dwSize = sizeof(ji);
ji.dwFlags = joy_flags;
 
if (joyGetPosEx (joy_id, &ji) == JOYERR_NOERROR)
{
// this is a hack -- there is a bug in the Logitech WingMan Warrior DirectInput Driver
// rather than having 32768 be the zero point, they have the zero point at 32668
// go figure -- anyway, now we get the full resolution out of the device
if (joy_wwhack1.value != 0.0)
{
ji.dwUpos += 100;
}
return true;
}
else
{
// read error occurred
// turning off the joystick seems too harsh for 1 read error,\
// but what should be done?
// Con_Printf ("IN_ReadJoystick: no response\n");
// joy_avail = false;
return false;
}
}
 
 
/*
===========
IN_JoyMove
===========
*/
void IN_JoyMove (usercmd_t *cmd)
{
float speed, aspeed;
float fAxisValue, fTemp;
int i;
 
// complete initialization if first time in
// this is needed as cvars are not available at initialization time
if( joy_advancedinit != true )
{
Joy_AdvancedUpdate_f();
joy_advancedinit = true;
}
 
// verify joystick is available and that the user wants to use it
if (!joy_avail || !in_joystick.value)
{
return;
}
// collect the joystick data, if possible
if (IN_ReadJoystick () != true)
{
return;
}
 
if (in_speed.state & 1)
speed = cl_movespeedkey.value;
else
speed = 1;
aspeed = speed * host_frametime;
 
// loop through the axes
for (i = 0; i < JOY_MAX_AXES; i++)
{
// get the floating point zero-centered, potentially-inverted data for the current axis
fAxisValue = (float) *pdwRawValue[i];
// move centerpoint to zero
fAxisValue -= 32768.0;
 
if (joy_wwhack2.value != 0.0)
{
if (dwAxisMap[i] == AxisTurn)
{
// this is a special formula for the Logitech WingMan Warrior
// y=ax^b; where a = 300 and b = 1.3
// also x values are in increments of 800 (so this is factored out)
// then bounds check result to level out excessively high spin rates
fTemp = 300.0 * pow(abs(fAxisValue) / 800.0, 1.3);
if (fTemp > 14000.0)
fTemp = 14000.0;
// restore direction information
fAxisValue = (fAxisValue > 0.0) ? fTemp : -fTemp;
}
}
 
// convert range from -32768..32767 to -1..1
fAxisValue /= 32768.0;
 
switch (dwAxisMap[i])
{
case AxisForward:
if ((joy_advanced.value == 0.0) && (in_mlook.state & 1))
{
// user wants forward control to become look control
if (fabs(fAxisValue) > joy_pitchthreshold.value)
{
// if mouse invert is on, invert the joystick pitch value
// only absolute control support here (joy_advanced is false)
if (m_pitch.value < 0.0)
{
cl.viewangles[PITCH] -= (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value;
}
else
{
cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value;
}
V_StopPitchDrift();
}
else
{
// no pitch movement
// disable pitch return-to-center unless requested by user
// *** this code can be removed when the lookspring bug is fixed
// *** the bug always has the lookspring feature on
if(lookspring.value == 0.0)
V_StopPitchDrift();
}
}
else
{
// user wants forward control to be forward control
if (fabs(fAxisValue) > joy_forwardthreshold.value)
{
cmd->forwardmove += (fAxisValue * joy_forwardsensitivity.value) * speed * cl_forwardspeed.value;
}
}
break;
 
case AxisSide:
if (fabs(fAxisValue) > joy_sidethreshold.value)
{
cmd->sidemove += (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value;
}
break;
 
case AxisTurn:
if ((in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1)))
{
// user wants turn control to become side control
if (fabs(fAxisValue) > joy_sidethreshold.value)
{
cmd->sidemove -= (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value;
}
}
else
{
// user wants turn control to be turn control
if (fabs(fAxisValue) > joy_yawthreshold.value)
{
if(dwControlMap[i] == JOY_ABSOLUTE_AXIS)
{
cl.viewangles[YAW] += (fAxisValue * joy_yawsensitivity.value) * aspeed * cl_yawspeed.value;
}
else
{
cl.viewangles[YAW] += (fAxisValue * joy_yawsensitivity.value) * speed * 180.0;
}
 
}
}
break;
 
case AxisLook:
if (in_mlook.state & 1)
{
if (fabs(fAxisValue) > joy_pitchthreshold.value)
{
// pitch movement detected and pitch movement desired by user
if(dwControlMap[i] == JOY_ABSOLUTE_AXIS)
{
cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value;
}
else
{
cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity.value) * speed * 180.0;
}
V_StopPitchDrift();
}
else
{
// no pitch movement
// disable pitch return-to-center unless requested by user
// *** this code can be removed when the lookspring bug is fixed
// *** the bug always has the lookspring feature on
if(lookspring.value == 0.0)
V_StopPitchDrift();
}
}
break;
 
default:
break;
}
}
 
// bounds check pitch
if (cl.viewangles[PITCH] > 80.0)
cl.viewangles[PITCH] = 80.0;
if (cl.viewangles[PITCH] < -70.0)
cl.viewangles[PITCH] = -70.0;
}
/contrib/other/sdlquake-1.0.9/input.h
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
 
/contrib/other/sdlquake-1.0.9/install-sh
0,0 → 1,251
#!/bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5 (mit/util/scripts/install.sh).
#
# Copyright 1991 by the Massachusetts Institute of Technology
#
# Permission to use, copy, modify, distribute, and sell this software and its
# documentation for any purpose is hereby granted without fee, provided that
# the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation, and that the name of M.I.T. not be used in advertising or
# publicity pertaining to distribution of the software without specific,
# written prior permission. M.I.T. makes no representations about the
# suitability of this software for any purpose. It is provided "as is"
# without express or implied warranty.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
 
 
# set DOITPROG to echo to test this script
 
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
 
 
# put in absolute paths if you don't have them in your path; or use env. vars.
 
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
 
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
 
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
 
-d) dir_arg=true
shift
continue;;
 
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
 
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
 
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
 
-s) stripcmd="$stripprog"
shift
continue;;
 
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
 
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
 
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
 
if [ x"$src" = x ]
then
echo "install: no input file specified"
exit 1
else
true
fi
 
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d $dst ]; then
instcmd=:
chmodcmd=""
else
instcmd=mkdir
fi
else
 
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
 
if [ -f $src -o -d $src ]
then
true
else
echo "install: $src does not exist"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
else
true
fi
 
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
 
if [ -d $dst ]
then
dst="$dst"/`basename $src`
else
true
fi
fi
 
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
 
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
 
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
 
oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
 
pathcomp=''
 
while [ $# -ne 0 ] ; do
pathcomp="${pathcomp}${1}"
shift
 
if [ ! -d "${pathcomp}" ] ;
then
$mkdirprog "${pathcomp}"
else
true
fi
 
pathcomp="${pathcomp}/"
done
fi
 
if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
 
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
else
 
# If we're going to rename the final executable, determine the name now.
 
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
 
# don't allow the sed command to completely eliminate the filename
 
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
true
fi
 
# Make a temp file name in the proper directory.
 
dsttmp=$dstdir/#inst.$$#
 
# Move or copy the file name to the temp name
 
$doit $instcmd $src $dsttmp &&
 
trap "rm -f ${dsttmp}" 0 &&
 
# and set any options; do chmod last to preserve setuid bits
 
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
 
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
 
# Now rename the file to the real destination.
 
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
 
fi &&
 
 
exit 0
/contrib/other/sdlquake-1.0.9/keys.c
0,0 → 1,759
/*
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},
 
{"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;
}
}
 
/contrib/other/sdlquake-1.0.9/keys.h
0,0 → 1,133
/*
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
 
 
 
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);
 
/contrib/other/sdlquake-1.0.9/makezip.bat
0,0 → 1,0
zip -9 -r code * -x *.obj -x *.sbr -x *.pch -x *.pdb -x *.o -x *.exe -x *.dll -x *.map -x *.bsc -x *.lib -x *.ilk -x *.exp -x *.idb -x *.zip
/contrib/other/sdlquake-1.0.9/math.S
0,0 → 1,418
/*
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.
 
*/
//
// math.s
// x86 assembly-language math routines.
 
#define GLQUAKE 1 // don't include unneeded defs
#include "asm_i386.h"
#include "quakeasm.h"
 
 
#if id386
 
.data
 
.align 4
Ljmptab: .long Lcase0, Lcase1, Lcase2, Lcase3
.long Lcase4, Lcase5, Lcase6, Lcase7
 
.text
 
// TODO: rounding needed?
// stack parameter offset
#define val 4
 
.globl C(Invert24To16)
C(Invert24To16):
 
movl val(%esp),%ecx
movl $0x100,%edx // 0x10000000000 as dividend
cmpl %edx,%ecx
jle LOutOfRange
 
subl %eax,%eax
divl %ecx
 
ret
 
LOutOfRange:
movl $0xFFFFFFFF,%eax
ret
 
#define in 4
#define out 8
 
.align 2
.globl C(TransformVector)
C(TransformVector):
movl in(%esp),%eax
movl out(%esp),%edx
 
flds (%eax) // in[0]
fmuls C(vright) // in[0]*vright[0]
flds (%eax) // in[0] | in[0]*vright[0]
fmuls C(vup) // in[0]*vup[0] | in[0]*vright[0]
flds (%eax) // in[0] | in[0]*vup[0] | in[0]*vright[0]
fmuls C(vpn) // in[0]*vpn[0] | in[0]*vup[0] | in[0]*vright[0]
 
flds 4(%eax) // in[1] | ...
fmuls C(vright)+4 // in[1]*vright[1] | ...
flds 4(%eax) // in[1] | in[1]*vright[1] | ...
fmuls C(vup)+4 // in[1]*vup[1] | in[1]*vright[1] | ...
flds 4(%eax) // in[1] | in[1]*vup[1] | in[1]*vright[1] | ...
fmuls C(vpn)+4 // in[1]*vpn[1] | in[1]*vup[1] | in[1]*vright[1] | ...
fxch %st(2) // in[1]*vright[1] | in[1]*vup[1] | in[1]*vpn[1] | ...
 
faddp %st(0),%st(5) // in[1]*vup[1] | in[1]*vpn[1] | ...
faddp %st(0),%st(3) // in[1]*vpn[1] | ...
faddp %st(0),%st(1) // vpn_accum | vup_accum | vright_accum
 
flds 8(%eax) // in[2] | ...
fmuls C(vright)+8 // in[2]*vright[2] | ...
flds 8(%eax) // in[2] | in[2]*vright[2] | ...
fmuls C(vup)+8 // in[2]*vup[2] | in[2]*vright[2] | ...
flds 8(%eax) // in[2] | in[2]*vup[2] | in[2]*vright[2] | ...
fmuls C(vpn)+8 // in[2]*vpn[2] | in[2]*vup[2] | in[2]*vright[2] | ...
fxch %st(2) // in[2]*vright[2] | in[2]*vup[2] | in[2]*vpn[2] | ...
 
faddp %st(0),%st(5) // in[2]*vup[2] | in[2]*vpn[2] | ...
faddp %st(0),%st(3) // in[2]*vpn[2] | ...
faddp %st(0),%st(1) // vpn_accum | vup_accum | vright_accum
 
fstps 8(%edx) // out[2]
fstps 4(%edx) // out[1]
fstps (%edx) // out[0]
 
ret
 
 
#define EMINS 4+4
#define EMAXS 4+8
#define P 4+12
 
.align 2
.globl C(BoxOnPlaneSide)
C(BoxOnPlaneSide):
pushl %ebx
 
movl P(%esp),%edx
movl EMINS(%esp),%ecx
xorl %eax,%eax
movl EMAXS(%esp),%ebx
movb pl_signbits(%edx),%al
cmpb $8,%al
jge Lerror
flds pl_normal(%edx) // p->normal[0]
fld %st(0) // p->normal[0] | p->normal[0]
jmp Ljmptab(,%eax,4)
 
 
//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];
Lcase0:
fmuls (%ebx) // p->normal[0]*emaxs[0] | p->normal[0]
flds pl_normal+4(%edx) // p->normal[1] | p->normal[0]*emaxs[0] |
// p->normal[0]
fxch %st(2) // p->normal[0] | p->normal[0]*emaxs[0] |
// p->normal[1]
fmuls (%ecx) // p->normal[0]*emins[0] |
// p->normal[0]*emaxs[0] | p->normal[1]
fxch %st(2) // p->normal[1] | p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
fld %st(0) // p->normal[1] | p->normal[1] |
// p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
fmuls 4(%ebx) // p->normal[1]*emaxs[1] | p->normal[1] |
// p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
flds pl_normal+8(%edx) // p->normal[2] | p->normal[1]*emaxs[1] |
// p->normal[1] | p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
fxch %st(2) // p->normal[1] | p->normal[1]*emaxs[1] |
// p->normal[2] | p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
fmuls 4(%ecx) // p->normal[1]*emins[1] |
// p->normal[1]*emaxs[1] |
// p->normal[2] | p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
fxch %st(2) // p->normal[2] | p->normal[1]*emaxs[1] |
// p->normal[1]*emins[1] |
// p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
fld %st(0) // p->normal[2] | p->normal[2] |
// p->normal[1]*emaxs[1] |
// p->normal[1]*emins[1] |
// p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
fmuls 8(%ebx) // p->normal[2]*emaxs[2] |
// p->normal[2] |
// p->normal[1]*emaxs[1] |
// p->normal[1]*emins[1] |
// p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
fxch %st(5) // p->normal[0]*emins[0] |
// p->normal[2] |
// p->normal[1]*emaxs[1] |
// p->normal[1]*emins[1] |
// p->normal[0]*emaxs[0] |
// p->normal[2]*emaxs[2]
faddp %st(0),%st(3) //p->normal[2] |
// p->normal[1]*emaxs[1] |
// p->normal[1]*emins[1]+p->normal[0]*emins[0]|
// p->normal[0]*emaxs[0] |
// p->normal[2]*emaxs[2]
fmuls 8(%ecx) //p->normal[2]*emins[2] |
// p->normal[1]*emaxs[1] |
// p->normal[1]*emins[1]+p->normal[0]*emins[0]|
// p->normal[0]*emaxs[0] |
// p->normal[2]*emaxs[2]
fxch %st(1) //p->normal[1]*emaxs[1] |
// p->normal[2]*emins[2] |
// p->normal[1]*emins[1]+p->normal[0]*emins[0]|
// p->normal[0]*emaxs[0] |
// p->normal[2]*emaxs[2]
faddp %st(0),%st(3) //p->normal[2]*emins[2] |
// p->normal[1]*emins[1]+p->normal[0]*emins[0]|
// p->normal[0]*emaxs[0]+p->normal[1]*emaxs[1]|
// p->normal[2]*emaxs[2]
fxch %st(3) //p->normal[2]*emaxs[2] +
// p->normal[1]*emins[1]+p->normal[0]*emins[0]|
// p->normal[0]*emaxs[0]+p->normal[1]*emaxs[1]|
// p->normal[2]*emins[2]
faddp %st(0),%st(2) //p->normal[1]*emins[1]+p->normal[0]*emins[0]|
// dist1 | p->normal[2]*emins[2]
 
jmp LSetSides
 
//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];
Lcase1:
fmuls (%ecx) // emins[0]
flds pl_normal+4(%edx)
fxch %st(2)
fmuls (%ebx) // emaxs[0]
fxch %st(2)
fld %st(0)
fmuls 4(%ebx) // emaxs[1]
flds pl_normal+8(%edx)
fxch %st(2)
fmuls 4(%ecx) // emins[1]
fxch %st(2)
fld %st(0)
fmuls 8(%ebx) // emaxs[2]
fxch %st(5)
faddp %st(0),%st(3)
fmuls 8(%ecx) // emins[2]
fxch %st(1)
faddp %st(0),%st(3)
fxch %st(3)
faddp %st(0),%st(2)
 
jmp LSetSides
 
//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];
Lcase2:
fmuls (%ebx) // emaxs[0]
flds pl_normal+4(%edx)
fxch %st(2)
fmuls (%ecx) // emins[0]
fxch %st(2)
fld %st(0)
fmuls 4(%ecx) // emins[1]
flds pl_normal+8(%edx)
fxch %st(2)
fmuls 4(%ebx) // emaxs[1]
fxch %st(2)
fld %st(0)
fmuls 8(%ebx) // emaxs[2]
fxch %st(5)
faddp %st(0),%st(3)
fmuls 8(%ecx) // emins[2]
fxch %st(1)
faddp %st(0),%st(3)
fxch %st(3)
faddp %st(0),%st(2)
 
jmp LSetSides
 
//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];
Lcase3:
fmuls (%ecx) // emins[0]
flds pl_normal+4(%edx)
fxch %st(2)
fmuls (%ebx) // emaxs[0]
fxch %st(2)
fld %st(0)
fmuls 4(%ecx) // emins[1]
flds pl_normal+8(%edx)
fxch %st(2)
fmuls 4(%ebx) // emaxs[1]
fxch %st(2)
fld %st(0)
fmuls 8(%ebx) // emaxs[2]
fxch %st(5)
faddp %st(0),%st(3)
fmuls 8(%ecx) // emins[2]
fxch %st(1)
faddp %st(0),%st(3)
fxch %st(3)
faddp %st(0),%st(2)
 
jmp LSetSides
 
//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];
Lcase4:
fmuls (%ebx) // emaxs[0]
flds pl_normal+4(%edx)
fxch %st(2)
fmuls (%ecx) // emins[0]
fxch %st(2)
fld %st(0)
fmuls 4(%ebx) // emaxs[1]
flds pl_normal+8(%edx)
fxch %st(2)
fmuls 4(%ecx) // emins[1]
fxch %st(2)
fld %st(0)
fmuls 8(%ecx) // emins[2]
fxch %st(5)
faddp %st(0),%st(3)
fmuls 8(%ebx) // emaxs[2]
fxch %st(1)
faddp %st(0),%st(3)
fxch %st(3)
faddp %st(0),%st(2)
 
jmp LSetSides
 
//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];
Lcase5:
fmuls (%ecx) // emins[0]
flds pl_normal+4(%edx)
fxch %st(2)
fmuls (%ebx) // emaxs[0]
fxch %st(2)
fld %st(0)
fmuls 4(%ebx) // emaxs[1]
flds pl_normal+8(%edx)
fxch %st(2)
fmuls 4(%ecx) // emins[1]
fxch %st(2)
fld %st(0)
fmuls 8(%ecx) // emins[2]
fxch %st(5)
faddp %st(0),%st(3)
fmuls 8(%ebx) // emaxs[2]
fxch %st(1)
faddp %st(0),%st(3)
fxch %st(3)
faddp %st(0),%st(2)
 
jmp LSetSides
 
//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];
Lcase6:
fmuls (%ebx) // emaxs[0]
flds pl_normal+4(%edx)
fxch %st(2)
fmuls (%ecx) // emins[0]
fxch %st(2)
fld %st(0)
fmuls 4(%ecx) // emins[1]
flds pl_normal+8(%edx)
fxch %st(2)
fmuls 4(%ebx) // emaxs[1]
fxch %st(2)
fld %st(0)
fmuls 8(%ecx) // emins[2]
fxch %st(5)
faddp %st(0),%st(3)
fmuls 8(%ebx) // emaxs[2]
fxch %st(1)
faddp %st(0),%st(3)
fxch %st(3)
faddp %st(0),%st(2)
 
jmp LSetSides
 
//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];
Lcase7:
fmuls (%ecx) // emins[0]
flds pl_normal+4(%edx)
fxch %st(2)
fmuls (%ebx) // emaxs[0]
fxch %st(2)
fld %st(0)
fmuls 4(%ecx) // emins[1]
flds pl_normal+8(%edx)
fxch %st(2)
fmuls 4(%ebx) // emaxs[1]
fxch %st(2)
fld %st(0)
fmuls 8(%ecx) // emins[2]
fxch %st(5)
faddp %st(0),%st(3)
fmuls 8(%ebx) // emaxs[2]
fxch %st(1)
faddp %st(0),%st(3)
fxch %st(3)
faddp %st(0),%st(2)
 
LSetSides:
 
// sides = 0;
// if (dist1 >= p->dist)
// sides = 1;
// if (dist2 < p->dist)
// sides |= 2;
 
faddp %st(0),%st(2) // dist1 | dist2
fcomps pl_dist(%edx)
xorl %ecx,%ecx
fnstsw %ax
fcomps pl_dist(%edx)
andb $1,%ah
xorb $1,%ah
addb %ah,%cl
 
fnstsw %ax
andb $1,%ah
addb %ah,%ah
addb %ah,%cl
 
// return sides;
 
popl %ebx
movl %ecx,%eax // return status
 
ret
 
 
Lerror:
call C(BOPS_Error)
 
#endif // id386
/contrib/other/sdlquake-1.0.9/mathlib.c
0,0 → 1,585
/*
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;
 
/*-----------------------------------------------------------------*/
 
#define DEG2RAD( a ) ( a * M_PI ) / 180.0F
 
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
/contrib/other/sdlquake-1.0.9/mathlib.h
0,0 → 1,89
/*
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
 
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];}
 
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)))
/contrib/other/sdlquake-1.0.9/menu.c
0,0 → 1,3231
/*
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 _WIN32
#include "winquake.h"
#endif
 
void (*vid_menudrawfn)(void);
void (*vid_menukeyfn)(int key);
 
enum {m_none, m_main, m_singleplayer, m_load, m_save, m_multiplayer, m_setup, m_net, m_options, m_video, m_keys, m_help, m_quit, m_serialconfig, m_modemconfig, m_lanconfig, m_gameoptions, m_search, m_slist} m_state;
 
void M_Menu_Main_f (void);
void M_Menu_SinglePlayer_f (void);
void M_Menu_Load_f (void);
void M_Menu_Save_f (void);
void M_Menu_MultiPlayer_f (void);
void M_Menu_Setup_f (void);
void M_Menu_Net_f (void);
void M_Menu_Options_f (void);
void M_Menu_Keys_f (void);
void M_Menu_Video_f (void);
void M_Menu_Help_f (void);
void M_Menu_Quit_f (void);
void M_Menu_SerialConfig_f (void);
void M_Menu_ModemConfig_f (void);
void M_Menu_LanConfig_f (void);
void M_Menu_GameOptions_f (void);
void M_Menu_Search_f (void);
void M_Menu_ServerList_f (void);
 
void M_Main_Draw (void);
void M_SinglePlayer_Draw (void);
void M_Load_Draw (void);
void M_Save_Draw (void);
void M_MultiPlayer_Draw (void);
void M_Setup_Draw (void);
void M_Net_Draw (void);
void M_Options_Draw (void);
void M_Keys_Draw (void);
void M_Video_Draw (void);
void M_Help_Draw (void);
void M_Quit_Draw (void);
void M_SerialConfig_Draw (void);
void M_ModemConfig_Draw (void);
void M_LanConfig_Draw (void);
void M_GameOptions_Draw (void);
void M_Search_Draw (void);
void M_ServerList_Draw (void);
 
void M_Main_Key (int key);
void M_SinglePlayer_Key (int key);
void M_Load_Key (int key);
void M_Save_Key (int key);
void M_MultiPlayer_Key (int key);
void M_Setup_Key (int key);
void M_Net_Key (int key);
void M_Options_Key (int key);
void M_Keys_Key (int key);
void M_Video_Key (int key);
void M_Help_Key (int key);
void M_Quit_Key (int key);
void M_SerialConfig_Key (int key);
void M_ModemConfig_Key (int key);
void M_LanConfig_Key (int key);
void M_GameOptions_Key (int key);
void M_Search_Key (int key);
void M_ServerList_Key (int key);
 
qboolean m_entersound; // play after drawing a frame, so caching
// won't disrupt the sound
qboolean m_recursiveDraw;
 
int m_return_state;
qboolean m_return_onerror;
char m_return_reason [32];
 
#define StartingGame (m_multiplayer_cursor == 1)
#define JoiningGame (m_multiplayer_cursor == 0)
#define SerialConfig (m_net_cursor == 0)
#define DirectConfig (m_net_cursor == 1)
#define IPXConfig (m_net_cursor == 2)
#define TCPIPConfig (m_net_cursor == 3)
 
void M_ConfigureNetSubsystem(void);
 
/*
================
M_DrawCharacter
 
Draws one solid graphics character
================
*/
void M_DrawCharacter (int cx, int line, int num)
{
Draw_Character ( cx + ((vid.width - 320)>>1), line, num);
}
 
void M_Print (int cx, int cy, char *str)
{
while (*str)
{
M_DrawCharacter (cx, cy, (*str)+128);
str++;
cx += 8;
}
}
 
void M_PrintWhite (int cx, int cy, char *str)
{
while (*str)
{
M_DrawCharacter (cx, cy, *str);
str++;
cx += 8;
}
}
 
void M_DrawTransPic (int x, int y, qpic_t *pic)
{
Draw_TransPic (x + ((vid.width - 320)>>1), y, pic);
}
 
void M_DrawPic (int x, int y, qpic_t *pic)
{
Draw_Pic (x + ((vid.width - 320)>>1), y, pic);
}
 
byte identityTable[256];
byte translationTable[256];
 
void M_BuildTranslationTable(int top, int bottom)
{
int j;
byte *dest, *source;
 
for (j = 0; j < 256; j++)
identityTable[j] = j;
dest = translationTable;
source = identityTable;
memcpy (dest, source, 256);
 
if (top < 128) // the artists made some backwards ranges. sigh.
memcpy (dest + TOP_RANGE, source + top, 16);
else
for (j=0 ; j<16 ; j++)
dest[TOP_RANGE+j] = source[top+15-j];
 
if (bottom < 128)
memcpy (dest + BOTTOM_RANGE, source + bottom, 16);
else
for (j=0 ; j<16 ; j++)
dest[BOTTOM_RANGE+j] = source[bottom+15-j];
}
 
 
void M_DrawTransPicTranslate (int x, int y, qpic_t *pic)
{
Draw_TransPicTranslate (x + ((vid.width - 320)>>1), y, pic, translationTable);
}
 
 
void M_DrawTextBox (int x, int y, int width, int lines)
{
qpic_t *p;
int cx, cy;
int n;
 
// draw left side
cx = x;
cy = y;
p = Draw_CachePic ("gfx/box_tl.lmp");
M_DrawTransPic (cx, cy, p);
p = Draw_CachePic ("gfx/box_ml.lmp");
for (n = 0; n < lines; n++)
{
cy += 8;
M_DrawTransPic (cx, cy, p);
}
p = Draw_CachePic ("gfx/box_bl.lmp");
M_DrawTransPic (cx, cy+8, p);
 
// draw middle
cx += 8;
while (width > 0)
{
cy = y;
p = Draw_CachePic ("gfx/box_tm.lmp");
M_DrawTransPic (cx, cy, p);
p = Draw_CachePic ("gfx/box_mm.lmp");
for (n = 0; n < lines; n++)
{
cy += 8;
if (n == 1)
p = Draw_CachePic ("gfx/box_mm2.lmp");
M_DrawTransPic (cx, cy, p);
}
p = Draw_CachePic ("gfx/box_bm.lmp");
M_DrawTransPic (cx, cy+8, p);
width -= 2;
cx += 16;
}
 
// draw right side
cy = y;
p = Draw_CachePic ("gfx/box_tr.lmp");
M_DrawTransPic (cx, cy, p);
p = Draw_CachePic ("gfx/box_mr.lmp");
for (n = 0; n < lines; n++)
{
cy += 8;
M_DrawTransPic (cx, cy, p);
}
p = Draw_CachePic ("gfx/box_br.lmp");
M_DrawTransPic (cx, cy+8, p);
}
 
//=============================================================================
 
int m_save_demonum;
 
/*
================
M_ToggleMenu_f
================
*/
void M_ToggleMenu_f (void)
{
m_entersound = true;
 
if (key_dest == key_menu)
{
if (m_state != m_main)
{
M_Menu_Main_f ();
return;
}
key_dest = key_game;
m_state = m_none;
return;
}
if (key_dest == key_console)
{
Con_ToggleConsole_f ();
}
else
{
M_Menu_Main_f ();
}
}
 
 
//=============================================================================
/* MAIN MENU */
 
int m_main_cursor;
#define MAIN_ITEMS 5
 
 
void M_Menu_Main_f (void)
{
if (key_dest != key_menu)
{
m_save_demonum = cls.demonum;
cls.demonum = -1;
}
key_dest = key_menu;
m_state = m_main;
m_entersound = true;
}
 
 
void M_Main_Draw (void)
{
int f;
qpic_t *p;
 
M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
p = Draw_CachePic ("gfx/ttl_main.lmp");
M_DrawPic ( (320-p->width)/2, 4, p);
M_DrawTransPic (72, 32, Draw_CachePic ("gfx/mainmenu.lmp") );
 
f = (int)(host_time * 10)%6;
 
M_DrawTransPic (54, 32 + m_main_cursor * 20,Draw_CachePic( va("gfx/menudot%i.lmp", f+1 ) ) );
}
 
 
void M_Main_Key (int key)
{
switch (key)
{
case K_ESCAPE:
key_dest = key_game;
m_state = m_none;
cls.demonum = m_save_demonum;
if (cls.demonum != -1 && !cls.demoplayback && cls.state != ca_connected)
CL_NextDemo ();
break;
 
case K_DOWNARROW:
S_LocalSound ("misc/menu1.wav");
if (++m_main_cursor >= MAIN_ITEMS)
m_main_cursor = 0;
break;
 
case K_UPARROW:
S_LocalSound ("misc/menu1.wav");
if (--m_main_cursor < 0)
m_main_cursor = MAIN_ITEMS - 1;
break;
 
case K_ENTER:
m_entersound = true;
 
switch (m_main_cursor)
{
case 0:
M_Menu_SinglePlayer_f ();
break;
 
case 1:
M_Menu_MultiPlayer_f ();
break;
 
case 2:
M_Menu_Options_f ();
break;
 
case 3:
M_Menu_Help_f ();
break;
 
case 4:
M_Menu_Quit_f ();
break;
}
}
}
 
//=============================================================================
/* SINGLE PLAYER MENU */
 
int m_singleplayer_cursor;
#define SINGLEPLAYER_ITEMS 3
 
 
void M_Menu_SinglePlayer_f (void)
{
key_dest = key_menu;
m_state = m_singleplayer;
m_entersound = true;
}
 
 
void M_SinglePlayer_Draw (void)
{
int f;
qpic_t *p;
 
M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
p = Draw_CachePic ("gfx/ttl_sgl.lmp");
M_DrawPic ( (320-p->width)/2, 4, p);
M_DrawTransPic (72, 32, Draw_CachePic ("gfx/sp_menu.lmp") );
 
f = (int)(host_time * 10)%6;
 
M_DrawTransPic (54, 32 + m_singleplayer_cursor * 20,Draw_CachePic( va("gfx/menudot%i.lmp", f+1 ) ) );
}
 
 
void M_SinglePlayer_Key (int key)
{
switch (key)
{
case K_ESCAPE:
M_Menu_Main_f ();
break;
 
case K_DOWNARROW:
S_LocalSound ("misc/menu1.wav");
if (++m_singleplayer_cursor >= SINGLEPLAYER_ITEMS)
m_singleplayer_cursor = 0;
break;
 
case K_UPARROW:
S_LocalSound ("misc/menu1.wav");
if (--m_singleplayer_cursor < 0)
m_singleplayer_cursor = SINGLEPLAYER_ITEMS - 1;
break;
 
case K_ENTER:
m_entersound = true;
 
switch (m_singleplayer_cursor)
{
case 0:
if (sv.active)
if (!SCR_ModalMessage("Are you sure you want to\nstart a new game?\n"))
break;
key_dest = key_game;
if (sv.active)
Cbuf_AddText ("disconnect\n");
Cbuf_AddText ("maxplayers 1\n");
Cbuf_AddText ("map start\n");
break;
 
case 1:
M_Menu_Load_f ();
break;
 
case 2:
M_Menu_Save_f ();
break;
}
}
}
 
//=============================================================================
/* LOAD/SAVE MENU */
 
int load_cursor; // 0 < load_cursor < MAX_SAVEGAMES
 
#define MAX_SAVEGAMES 12
char m_filenames[MAX_SAVEGAMES][SAVEGAME_COMMENT_LENGTH+1];
int loadable[MAX_SAVEGAMES];
 
void M_ScanSaves (void)
{
int i, j;
char name[MAX_OSPATH];
FILE *f;
int version;
 
for (i=0 ; i<MAX_SAVEGAMES ; i++)
{
strcpy (m_filenames[i], "--- UNUSED SLOT ---");
loadable[i] = false;
sprintf (name, "%s/s%i.sav", com_gamedir, i);
f = fopen (name, "r");
if (!f)
continue;
fscanf (f, "%i\n", &version);
fscanf (f, "%79s\n", name);
strncpy (m_filenames[i], name, sizeof(m_filenames[i])-1);
 
// change _ back to space
for (j=0 ; j<SAVEGAME_COMMENT_LENGTH ; j++)
if (m_filenames[i][j] == '_')
m_filenames[i][j] = ' ';
loadable[i] = true;
fclose (f);
}
}
 
void M_Menu_Load_f (void)
{
m_entersound = true;
m_state = m_load;
key_dest = key_menu;
M_ScanSaves ();
}
 
 
void M_Menu_Save_f (void)
{
if (!sv.active)
return;
if (cl.intermission)
return;
if (svs.maxclients != 1)
return;
m_entersound = true;
m_state = m_save;
key_dest = key_menu;
M_ScanSaves ();
}
 
 
void M_Load_Draw (void)
{
int i;
qpic_t *p;
 
p = Draw_CachePic ("gfx/p_load.lmp");
M_DrawPic ( (320-p->width)/2, 4, p);
 
for (i=0 ; i< MAX_SAVEGAMES; i++)
M_Print (16, 32 + 8*i, m_filenames[i]);
 
// line cursor
M_DrawCharacter (8, 32 + load_cursor*8, 12+((int)(realtime*4)&1));
}
 
 
void M_Save_Draw (void)
{
int i;
qpic_t *p;
 
p = Draw_CachePic ("gfx/p_save.lmp");
M_DrawPic ( (320-p->width)/2, 4, p);
 
for (i=0 ; i<MAX_SAVEGAMES ; i++)
M_Print (16, 32 + 8*i, m_filenames[i]);
 
// line cursor
M_DrawCharacter (8, 32 + load_cursor*8, 12+((int)(realtime*4)&1));
}
 
 
void M_Load_Key (int k)
{
switch (k)
{
case K_ESCAPE:
M_Menu_SinglePlayer_f ();
break;
 
case K_ENTER:
S_LocalSound ("misc/menu2.wav");
if (!loadable[load_cursor])
return;
m_state = m_none;
key_dest = key_game;
 
// Host_Loadgame_f can't bring up the loading plaque because too much
// stack space has been used, so do it now
SCR_BeginLoadingPlaque ();
 
// issue the load command
Cbuf_AddText (va ("load s%i\n", load_cursor) );
return;
 
case K_UPARROW:
case K_LEFTARROW:
S_LocalSound ("misc/menu1.wav");
load_cursor--;
if (load_cursor < 0)
load_cursor = MAX_SAVEGAMES-1;
break;
 
case K_DOWNARROW:
case K_RIGHTARROW:
S_LocalSound ("misc/menu1.wav");
load_cursor++;
if (load_cursor >= MAX_SAVEGAMES)
load_cursor = 0;
break;
}
}
 
 
void M_Save_Key (int k)
{
switch (k)
{
case K_ESCAPE:
M_Menu_SinglePlayer_f ();
break;
 
case K_ENTER:
m_state = m_none;
key_dest = key_game;
Cbuf_AddText (va("save s%i\n", load_cursor));
return;
 
case K_UPARROW:
case K_LEFTARROW:
S_LocalSound ("misc/menu1.wav");
load_cursor--;
if (load_cursor < 0)
load_cursor = MAX_SAVEGAMES-1;
break;
 
case K_DOWNARROW:
case K_RIGHTARROW:
S_LocalSound ("misc/menu1.wav");
load_cursor++;
if (load_cursor >= MAX_SAVEGAMES)
load_cursor = 0;
break;
}
}
 
//=============================================================================
/* MULTIPLAYER MENU */
 
int m_multiplayer_cursor;
#define MULTIPLAYER_ITEMS 3
 
 
void M_Menu_MultiPlayer_f (void)
{
key_dest = key_menu;
m_state = m_multiplayer;
m_entersound = true;
}
 
 
void M_MultiPlayer_Draw (void)
{
int f;
qpic_t *p;
 
M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
p = Draw_CachePic ("gfx/p_multi.lmp");
M_DrawPic ( (320-p->width)/2, 4, p);
M_DrawTransPic (72, 32, Draw_CachePic ("gfx/mp_menu.lmp") );
 
f = (int)(host_time * 10)%6;
 
M_DrawTransPic (54, 32 + m_multiplayer_cursor * 20,Draw_CachePic( va("gfx/menudot%i.lmp", f+1 ) ) );
 
if (serialAvailable || ipxAvailable || tcpipAvailable)
return;
M_PrintWhite ((320/2) - ((27*8)/2), 148, "No Communications Available");
}
 
 
void M_MultiPlayer_Key (int key)
{
switch (key)
{
case K_ESCAPE:
M_Menu_Main_f ();
break;
 
case K_DOWNARROW:
S_LocalSound ("misc/menu1.wav");
if (++m_multiplayer_cursor >= MULTIPLAYER_ITEMS)
m_multiplayer_cursor = 0;
break;
 
case K_UPARROW:
S_LocalSound ("misc/menu1.wav");
if (--m_multiplayer_cursor < 0)
m_multiplayer_cursor = MULTIPLAYER_ITEMS - 1;
break;
 
case K_ENTER:
m_entersound = true;
switch (m_multiplayer_cursor)
{
case 0:
if (serialAvailable || ipxAvailable || tcpipAvailable)
M_Menu_Net_f ();
break;
 
case 1:
if (serialAvailable || ipxAvailable || tcpipAvailable)
M_Menu_Net_f ();
break;
 
case 2:
M_Menu_Setup_f ();
break;
}
}
}
 
//=============================================================================
/* SETUP MENU */
 
int setup_cursor = 4;
int setup_cursor_table[] = {40, 56, 80, 104, 140};
 
char setup_hostname[16];
char setup_myname[16];
int setup_oldtop;
int setup_oldbottom;
int setup_top;
int setup_bottom;
 
#define NUM_SETUP_CMDS 5
 
void M_Menu_Setup_f (void)
{
key_dest = key_menu;
m_state = m_setup;
m_entersound = true;
Q_strcpy(setup_myname, cl_name.string);
Q_strcpy(setup_hostname, hostname.string);
setup_top = setup_oldtop = ((int)cl_color.value) >> 4;
setup_bottom = setup_oldbottom = ((int)cl_color.value) & 15;
}
 
 
void M_Setup_Draw (void)
{
qpic_t *p;
 
M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
p = Draw_CachePic ("gfx/p_multi.lmp");
M_DrawPic ( (320-p->width)/2, 4, p);
 
M_Print (64, 40, "Hostname");
M_DrawTextBox (160, 32, 16, 1);
M_Print (168, 40, setup_hostname);
 
M_Print (64, 56, "Your name");
M_DrawTextBox (160, 48, 16, 1);
M_Print (168, 56, setup_myname);
 
M_Print (64, 80, "Shirt color");
M_Print (64, 104, "Pants color");
 
M_DrawTextBox (64, 140-8, 14, 1);
M_Print (72, 140, "Accept Changes");
 
p = Draw_CachePic ("gfx/bigbox.lmp");
M_DrawTransPic (160, 64, p);
p = Draw_CachePic ("gfx/menuplyr.lmp");
M_BuildTranslationTable(setup_top*16, setup_bottom*16);
M_DrawTransPicTranslate (172, 72, p);
 
M_DrawCharacter (56, setup_cursor_table [setup_cursor], 12+((int)(realtime*4)&1));
 
if (setup_cursor == 0)
M_DrawCharacter (168 + 8*strlen(setup_hostname), setup_cursor_table [setup_cursor], 10+((int)(realtime*4)&1));
 
if (setup_cursor == 1)
M_DrawCharacter (168 + 8*strlen(setup_myname), setup_cursor_table [setup_cursor], 10+((int)(realtime*4)&1));
}
 
 
void M_Setup_Key (int k)
{
int l;
 
switch (k)
{
case K_ESCAPE:
M_Menu_MultiPlayer_f ();
break;
 
case K_UPARROW:
S_LocalSound ("misc/menu1.wav");
setup_cursor--;
if (setup_cursor < 0)
setup_cursor = NUM_SETUP_CMDS-1;
break;
 
case K_DOWNARROW:
S_LocalSound ("misc/menu1.wav");
setup_cursor++;
if (setup_cursor >= NUM_SETUP_CMDS)
setup_cursor = 0;
break;
 
case K_LEFTARROW:
if (setup_cursor < 2)
return;
S_LocalSound ("misc/menu3.wav");
if (setup_cursor == 2)
setup_top = setup_top - 1;
if (setup_cursor == 3)
setup_bottom = setup_bottom - 1;
break;
case K_RIGHTARROW:
if (setup_cursor < 2)
return;
forward:
S_LocalSound ("misc/menu3.wav");
if (setup_cursor == 2)
setup_top = setup_top + 1;
if (setup_cursor == 3)
setup_bottom = setup_bottom + 1;
break;
 
case K_ENTER:
if (setup_cursor == 0 || setup_cursor == 1)
return;
 
if (setup_cursor == 2 || setup_cursor == 3)
goto forward;
 
// setup_cursor == 4 (OK)
if (Q_strcmp(cl_name.string, setup_myname) != 0)
Cbuf_AddText ( va ("name \"%s\"\n", setup_myname) );
if (Q_strcmp(hostname.string, setup_hostname) != 0)
Cvar_Set("hostname", setup_hostname);
if (setup_top != setup_oldtop || setup_bottom != setup_oldbottom)
Cbuf_AddText( va ("color %i %i\n", setup_top, setup_bottom) );
m_entersound = true;
M_Menu_MultiPlayer_f ();
break;
 
case K_BACKSPACE:
if (setup_cursor == 0)
{
if (strlen(setup_hostname))
setup_hostname[strlen(setup_hostname)-1] = 0;
}
 
if (setup_cursor == 1)
{
if (strlen(setup_myname))
setup_myname[strlen(setup_myname)-1] = 0;
}
break;
 
default:
if (k < 32 || k > 127)
break;
if (setup_cursor == 0)
{
l = strlen(setup_hostname);
if (l < 15)
{
setup_hostname[l+1] = 0;
setup_hostname[l] = k;
}
}
if (setup_cursor == 1)
{
l = strlen(setup_myname);
if (l < 15)
{
setup_myname[l+1] = 0;
setup_myname[l] = k;
}
}
}
 
if (setup_top > 13)
setup_top = 0;
if (setup_top < 0)
setup_top = 13;
if (setup_bottom > 13)
setup_bottom = 0;
if (setup_bottom < 0)
setup_bottom = 13;
}
 
//=============================================================================
/* NET MENU */
 
int m_net_cursor;
int m_net_items;
int m_net_saveHeight;
 
char *net_helpMessage [] =
{
/* .........1.........2.... */
" ",
" Two computers connected",
" through two modems. ",
" ",
 
" ",
" Two computers connected",
" by a null-modem cable. ",
" ",
 
" Novell network LANs ",
" or Windows 95 DOS-box. ",
" ",
"(LAN=Local Area Network)",
 
" Commonly used to play ",
" over the Internet, but ",
" also used on a Local ",
" Area Network. "
};
 
void M_Menu_Net_f (void)
{
key_dest = key_menu;
m_state = m_net;
m_entersound = true;
m_net_items = 4;
 
if (m_net_cursor >= m_net_items)
m_net_cursor = 0;
m_net_cursor--;
M_Net_Key (K_DOWNARROW);
}
 
 
void M_Net_Draw (void)
{
int f;
qpic_t *p;
 
M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
p = Draw_CachePic ("gfx/p_multi.lmp");
M_DrawPic ( (320-p->width)/2, 4, p);
 
f = 32;
 
if (serialAvailable)
{
p = Draw_CachePic ("gfx/netmen1.lmp");
}
else
{
#ifdef _WIN32
p = NULL;
#else
p = Draw_CachePic ("gfx/dim_modm.lmp");
#endif
}
 
if (p)
M_DrawTransPic (72, f, p);
 
f += 19;
 
if (serialAvailable)
{
p = Draw_CachePic ("gfx/netmen2.lmp");
}
else
{
#ifdef _WIN32
p = NULL;
#else
p = Draw_CachePic ("gfx/dim_drct.lmp");
#endif
}
 
if (p)
M_DrawTransPic (72, f, p);
 
f += 19;
if (ipxAvailable)
p = Draw_CachePic ("gfx/netmen3.lmp");
else
p = Draw_CachePic ("gfx/dim_ipx.lmp");
M_DrawTransPic (72, f, p);
 
f += 19;
if (tcpipAvailable)
p = Draw_CachePic ("gfx/netmen4.lmp");
else
p = Draw_CachePic ("gfx/dim_tcp.lmp");
M_DrawTransPic (72, f, p);
 
if (m_net_items == 5) // JDC, could just be removed
{
f += 19;
p = Draw_CachePic ("gfx/netmen5.lmp");
M_DrawTransPic (72, f, p);
}
 
f = (320-26*8)/2;
M_DrawTextBox (f, 134, 24, 4);
f += 8;
M_Print (f, 142, net_helpMessage[m_net_cursor*4+0]);
M_Print (f, 150, net_helpMessage[m_net_cursor*4+1]);
M_Print (f, 158, net_helpMessage[m_net_cursor*4+2]);
M_Print (f, 166, net_helpMessage[m_net_cursor*4+3]);
 
f = (int)(host_time * 10)%6;
M_DrawTransPic (54, 32 + m_net_cursor * 20,Draw_CachePic( va("gfx/menudot%i.lmp", f+1 ) ) );
}
 
 
void M_Net_Key (int k)
{
again:
switch (k)
{
case K_ESCAPE:
M_Menu_MultiPlayer_f ();
break;
 
case K_DOWNARROW:
S_LocalSound ("misc/menu1.wav");
if (++m_net_cursor >= m_net_items)
m_net_cursor = 0;
break;
 
case K_UPARROW:
S_LocalSound ("misc/menu1.wav");
if (--m_net_cursor < 0)
m_net_cursor = m_net_items - 1;
break;
 
case K_ENTER:
m_entersound = true;
 
switch (m_net_cursor)
{
case 0:
M_Menu_SerialConfig_f ();
break;
 
case 1:
M_Menu_SerialConfig_f ();
break;
 
case 2:
M_Menu_LanConfig_f ();
break;
 
case 3:
M_Menu_LanConfig_f ();
break;
 
case 4:
// multiprotocol
break;
}
}
 
if (m_net_cursor == 0 && !serialAvailable)
goto again;
if (m_net_cursor == 1 && !serialAvailable)
goto again;
if (m_net_cursor == 2 && !ipxAvailable)
goto again;
if (m_net_cursor == 3 && !tcpipAvailable)
goto again;
}
 
//=============================================================================
/* OPTIONS MENU */
 
#ifdef _WIN32
#define OPTIONS_ITEMS 14
#else
#define OPTIONS_ITEMS 13
#endif
 
#define SLIDER_RANGE 10
 
int options_cursor;
 
void M_Menu_Options_f (void)
{
key_dest = key_menu;
m_state = m_options;
m_entersound = true;
 
#ifdef _WIN32
if ((options_cursor == 13) && (modestate != MS_WINDOWED))
{
options_cursor = 0;
}
#endif
}
 
 
void M_AdjustSliders (int dir)
{
S_LocalSound ("misc/menu3.wav");
 
switch (options_cursor)
{
case 3: // screen size
scr_viewsize.value += dir * 10;
if (scr_viewsize.value < 30)
scr_viewsize.value = 30;
if (scr_viewsize.value > 120)
scr_viewsize.value = 120;
Cvar_SetValue ("viewsize", scr_viewsize.value);
break;
case 4: // gamma
v_gamma.value -= dir * 0.05;
if (v_gamma.value < 0.5)
v_gamma.value = 0.5;
if (v_gamma.value > 1)
v_gamma.value = 1;
Cvar_SetValue ("gamma", v_gamma.value);
break;
case 5: // mouse speed
sensitivity.value += dir * 0.5;
if (sensitivity.value < 1)
sensitivity.value = 1;
if (sensitivity.value > 11)
sensitivity.value = 11;
Cvar_SetValue ("sensitivity", sensitivity.value);
break;
case 6: // music volume
#ifdef _WIN32
bgmvolume.value += dir * 1.0;
#else
bgmvolume.value += dir * 0.1;
#endif
if (bgmvolume.value < 0)
bgmvolume.value = 0;
if (bgmvolume.value > 1)
bgmvolume.value = 1;
Cvar_SetValue ("bgmvolume", bgmvolume.value);
break;
case 7: // sfx volume
volume.value += dir * 0.1;
if (volume.value < 0)
volume.value = 0;
if (volume.value > 1)
volume.value = 1;
Cvar_SetValue ("volume", volume.value);
break;
 
case 8: // allways run
if (cl_forwardspeed.value > 200)
{
Cvar_SetValue ("cl_forwardspeed", 200);
Cvar_SetValue ("cl_backspeed", 200);
}
else
{
Cvar_SetValue ("cl_forwardspeed", 400);
Cvar_SetValue ("cl_backspeed", 400);
}
break;
 
case 9: // invert mouse
Cvar_SetValue ("m_pitch", -m_pitch.value);
break;
 
case 10: // lookspring
Cvar_SetValue ("lookspring", !lookspring.value);
break;
 
case 11: // lookstrafe
Cvar_SetValue ("lookstrafe", !lookstrafe.value);
break;
 
#ifdef _WIN32
case 13: // _windowed_mouse
Cvar_SetValue ("_windowed_mouse", !_windowed_mouse.value);
break;
#endif
}
}
 
 
void M_DrawSlider (int x, int y, float range)
{
int i;
 
if (range < 0)
range = 0;
if (range > 1)
range = 1;
M_DrawCharacter (x-8, y, 128);
for (i=0 ; i<SLIDER_RANGE ; i++)
M_DrawCharacter (x + i*8, y, 129);
M_DrawCharacter (x+i*8, y, 130);
M_DrawCharacter (x + (SLIDER_RANGE-1)*8 * range, y, 131);
}
 
void M_DrawCheckbox (int x, int y, int on)
{
#if 0
if (on)
M_DrawCharacter (x, y, 131);
else
M_DrawCharacter (x, y, 129);
#endif
if (on)
M_Print (x, y, "on");
else
M_Print (x, y, "off");
}
 
void M_Options_Draw (void)
{
float r;
qpic_t *p;
 
M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
p = Draw_CachePic ("gfx/p_option.lmp");
M_DrawPic ( (320-p->width)/2, 4, p);
 
M_Print (16, 32, " Customize controls");
M_Print (16, 40, " Go to console");
M_Print (16, 48, " Reset to defaults");
 
M_Print (16, 56, " Screen size");
r = (scr_viewsize.value - 30) / (120 - 30);
M_DrawSlider (220, 56, r);
 
M_Print (16, 64, " Brightness");
r = (1.0 - v_gamma.value) / 0.5;
M_DrawSlider (220, 64, r);
 
M_Print (16, 72, " Mouse Speed");
r = (sensitivity.value - 1)/10;
M_DrawSlider (220, 72, r);
 
M_Print (16, 80, " CD Music Volume");
r = bgmvolume.value;
M_DrawSlider (220, 80, r);
 
M_Print (16, 88, " Sound Volume");
r = volume.value;
M_DrawSlider (220, 88, r);
 
M_Print (16, 96, " Always Run");
M_DrawCheckbox (220, 96, cl_forwardspeed.value > 200);
 
M_Print (16, 104, " Invert Mouse");
M_DrawCheckbox (220, 104, m_pitch.value < 0);
 
M_Print (16, 112, " Lookspring");
M_DrawCheckbox (220, 112, lookspring.value);
 
M_Print (16, 120, " Lookstrafe");
M_DrawCheckbox (220, 120, lookstrafe.value);
 
if (vid_menudrawfn)
M_Print (16, 128, " Video Options");
 
#ifdef _WIN32
if (modestate == MS_WINDOWED)
{
M_Print (16, 136, " Use Mouse");
M_DrawCheckbox (220, 136, _windowed_mouse.value);
}
#endif
 
// cursor
M_DrawCharacter (200, 32 + options_cursor*8, 12+((int)(realtime*4)&1));
}
 
 
void M_Options_Key (int k)
{
switch (k)
{
case K_ESCAPE:
M_Menu_Main_f ();
break;
 
case K_ENTER:
m_entersound = true;
switch (options_cursor)
{
case 0:
M_Menu_Keys_f ();
break;
case 1:
m_state = m_none;
Con_ToggleConsole_f ();
break;
case 2:
Cbuf_AddText ("exec default.cfg\n");
break;
case 12:
M_Menu_Video_f ();
break;
default:
M_AdjustSliders (1);
break;
}
return;
 
case K_UPARROW:
S_LocalSound ("misc/menu1.wav");
options_cursor--;
if (options_cursor < 0)
options_cursor = OPTIONS_ITEMS-1;
break;
 
case K_DOWNARROW:
S_LocalSound ("misc/menu1.wav");
options_cursor++;
if (options_cursor >= OPTIONS_ITEMS)
options_cursor = 0;
break;
 
case K_LEFTARROW:
M_AdjustSliders (-1);
break;
 
case K_RIGHTARROW:
M_AdjustSliders (1);
break;
}
 
if (options_cursor == 12 && vid_menudrawfn == NULL)
{
if (k == K_UPARROW)
options_cursor = 11;
else
options_cursor = 0;
}
 
#ifdef _WIN32
if ((options_cursor == 13) && (modestate != MS_WINDOWED))
{
if (k == K_UPARROW)
options_cursor = 12;
else
options_cursor = 0;
}
#endif
}
 
//=============================================================================
/* KEYS MENU */
 
char *bindnames[][2] =
{
{"+attack", "attack"},
{"impulse 10", "change weapon"},
{"+jump", "jump / swim up"},
{"+forward", "walk forward"},
{"+back", "backpedal"},
{"+left", "turn left"},
{"+right", "turn right"},
{"+speed", "run"},
{"+moveleft", "step left"},
{"+moveright", "step right"},
{"+strafe", "sidestep"},
{"+lookup", "look up"},
{"+lookdown", "look down"},
{"centerview", "center view"},
{"+mlook", "mouse look"},
{"+klook", "keyboard look"},
{"+moveup", "swim up"},
{"+movedown", "swim down"}
};
 
#define NUMCOMMANDS (sizeof(bindnames)/sizeof(bindnames[0]))
 
int keys_cursor;
int bind_grab;
 
void M_Menu_Keys_f (void)
{
key_dest = key_menu;
m_state = m_keys;
m_entersound = true;
}
 
 
void M_FindKeysForCommand (char *command, int *twokeys)
{
int count;
int j;
int l;
char *b;
 
twokeys[0] = twokeys[1] = -1;
l = strlen(command);
count = 0;
 
for (j=0 ; j<256 ; j++)
{
b = keybindings[j];
if (!b)
continue;
if (!strncmp (b, command, l) )
{
twokeys[count] = j;
count++;
if (count == 2)
break;
}
}
}
 
void M_UnbindCommand (char *command)
{
int j;
int l;
char *b;
 
l = strlen(command);
 
for (j=0 ; j<256 ; j++)
{
b = keybindings[j];
if (!b)
continue;
if (!strncmp (b, command, l) )
Key_SetBinding (j, "");
}
}
 
 
void M_Keys_Draw (void)
{
int i, l;
int keys[2];
char *name;
int x, y;
qpic_t *p;
 
p = Draw_CachePic ("gfx/ttl_cstm.lmp");
M_DrawPic ( (320-p->width)/2, 4, p);
 
if (bind_grab)
M_Print (12, 32, "Press a key or button for this action");
else
M_Print (18, 32, "Enter to change, backspace to clear");
 
// search for known bindings
for (i=0 ; i<NUMCOMMANDS ; i++)
{
y = 48 + 8*i;
 
M_Print (16, y, bindnames[i][1]);
 
l = strlen (bindnames[i][0]);
 
M_FindKeysForCommand (bindnames[i][0], keys);
 
if (keys[0] == -1)
{
M_Print (140, y, "???");
}
else
{
name = Key_KeynumToString (keys[0]);
M_Print (140, y, name);
x = strlen(name) * 8;
if (keys[1] != -1)
{
M_Print (140 + x + 8, y, "or");
M_Print (140 + x + 32, y, Key_KeynumToString (keys[1]));
}
}
}
 
if (bind_grab)
M_DrawCharacter (130, 48 + keys_cursor*8, '=');
else
M_DrawCharacter (130, 48 + keys_cursor*8, 12+((int)(realtime*4)&1));
}
 
 
void M_Keys_Key (int k)
{
char cmd[80];
int keys[2];
 
if (bind_grab)
{ // defining a key
S_LocalSound ("misc/menu1.wav");
if (k == K_ESCAPE)
{
bind_grab = false;
}
else if (k != '`')
{
sprintf (cmd, "bind \"%s\" \"%s\"\n", Key_KeynumToString (k), bindnames[keys_cursor][0]);
Cbuf_InsertText (cmd);
}
 
bind_grab = false;
return;
}
 
switch (k)
{
case K_ESCAPE:
M_Menu_Options_f ();
break;
 
case K_LEFTARROW:
case K_UPARROW:
S_LocalSound ("misc/menu1.wav");
keys_cursor--;
if (keys_cursor < 0)
keys_cursor = NUMCOMMANDS-1;
break;
 
case K_DOWNARROW:
case K_RIGHTARROW:
S_LocalSound ("misc/menu1.wav");
keys_cursor++;
if (keys_cursor >= NUMCOMMANDS)
keys_cursor = 0;
break;
 
case K_ENTER: // go into bind mode
M_FindKeysForCommand (bindnames[keys_cursor][0], keys);
S_LocalSound ("misc/menu2.wav");
if (keys[1] != -1)
M_UnbindCommand (bindnames[keys_cursor][0]);
bind_grab = true;
break;
 
case K_BACKSPACE: // delete bindings
case K_DEL: // delete bindings
S_LocalSound ("misc/menu2.wav");
M_UnbindCommand (bindnames[keys_cursor][0]);
break;
}
}
 
//=============================================================================
/* VIDEO MENU */
 
void M_Menu_Video_f (void)
{
key_dest = key_menu;
m_state = m_video;
m_entersound = true;
}
 
 
void M_Video_Draw (void)
{
(*vid_menudrawfn) ();
}
 
 
void M_Video_Key (int key)
{
(*vid_menukeyfn) (key);
}
 
//=============================================================================
/* HELP MENU */
 
int help_page;
#define NUM_HELP_PAGES 6
 
 
void M_Menu_Help_f (void)
{
key_dest = key_menu;
m_state = m_help;
m_entersound = true;
help_page = 0;
}
 
 
 
void M_Help_Draw (void)
{
M_DrawPic (0, 0, Draw_CachePic ( va("gfx/help%i.lmp", help_page)) );
}
 
 
void M_Help_Key (int key)
{
switch (key)
{
case K_ESCAPE:
M_Menu_Main_f ();
break;
 
case K_UPARROW:
case K_RIGHTARROW:
m_entersound = true;
if (++help_page >= NUM_HELP_PAGES)
help_page = 0;
break;
 
case K_DOWNARROW:
case K_LEFTARROW:
m_entersound = true;
if (--help_page < 0)
help_page = NUM_HELP_PAGES-1;
break;
}
 
}
 
//=============================================================================
/* QUIT MENU */
 
int msgNumber;
int m_quit_prevstate;
qboolean wasInMenus;
 
#ifndef _WIN32
char *quitMessage [] =
{
/* .........1.........2.... */
" Are you gonna quit ",
" this game just like ",
" everything else? ",
" ",
" Milord, methinks that ",
" thou art a lowly ",
" quitter. Is this true? ",
" ",
 
" Do I need to bust your ",
" face open for trying ",
" to quit? ",
" ",
 
" Man, I oughta smack you",
" for trying to quit! ",
" Press Y to get ",
" smacked out. ",
" Press Y to quit like a ",
" big loser in life. ",
" Press N to stay proud ",
" and successful! ",
" If you press Y to ",
" quit, I will summon ",
" Satan all over your ",
" hard drive! ",
" Um, Asmodeus dislikes ",
" his children trying to ",
" quit. Press Y to return",
" to your Tinkertoys. ",
" If you quit now, I'll ",
" throw a blanket-party ",
" for you next time! ",
" "
};
#endif
 
void M_Menu_Quit_f (void)
{
if (m_state == m_quit)
return;
wasInMenus = (key_dest == key_menu);
key_dest = key_menu;
m_quit_prevstate = m_state;
m_state = m_quit;
m_entersound = true;
msgNumber = rand()&7;
}
 
 
void M_Quit_Key (int key)
{
switch (key)
{
case K_ESCAPE:
case 'n':
case 'N':
if (wasInMenus)
{
m_state = m_quit_prevstate;
m_entersound = true;
}
else
{
key_dest = key_game;
m_state = m_none;
}
break;
 
case 'Y':
case 'y':
key_dest = key_console;
Host_Quit_f ();
break;
 
default:
break;
}
 
}
 
 
void M_Quit_Draw (void)
{
if (wasInMenus)
{
m_state = m_quit_prevstate;
m_recursiveDraw = true;
M_Draw ();
m_state = m_quit;
}
 
#ifdef _WIN32
M_DrawTextBox (0, 0, 38, 23);
M_PrintWhite (16, 12, " Quake version 1.09 by id Software\n\n");
M_PrintWhite (16, 28, "Programming Art \n");
M_Print (16, 36, " John Carmack Adrian Carmack\n");
M_Print (16, 44, " Michael Abrash Kevin Cloud\n");
M_Print (16, 52, " John Cash Paul Steed\n");
M_Print (16, 60, " Dave 'Zoid' Kirsch\n");
M_PrintWhite (16, 68, "Design Biz\n");
M_Print (16, 76, " John Romero Jay Wilbur\n");
M_Print (16, 84, " Sandy Petersen Mike Wilson\n");
M_Print (16, 92, " American McGee Donna Jackson\n");
M_Print (16, 100, " Tim Willits Todd Hollenshead\n");
M_PrintWhite (16, 108, "Support Projects\n");
M_Print (16, 116, " Barrett Alexander Shawn Green\n");
M_PrintWhite (16, 124, "Sound Effects\n");
M_Print (16, 132, " Trent Reznor and Nine Inch Nails\n\n");
M_PrintWhite (16, 140, "Quake is a trademark of Id Software,\n");
M_PrintWhite (16, 148, "inc., (c)1996 Id Software, inc. All\n");
M_PrintWhite (16, 156, "rights reserved. NIN logo is a\n");
M_PrintWhite (16, 164, "registered trademark licensed to\n");
M_PrintWhite (16, 172, "Nothing Interactive, Inc. All rights\n");
M_PrintWhite (16, 180, "reserved. Press y to exit\n");
#else
M_DrawTextBox (56, 76, 24, 4);
M_Print (64, 84, quitMessage[msgNumber*4+0]);
M_Print (64, 92, quitMessage[msgNumber*4+1]);
M_Print (64, 100, quitMessage[msgNumber*4+2]);
M_Print (64, 108, quitMessage[msgNumber*4+3]);
#endif
}
 
//=============================================================================
 
/* SERIAL CONFIG MENU */
 
int serialConfig_cursor;
int serialConfig_cursor_table[] = {48, 64, 80, 96, 112, 132};
#define NUM_SERIALCONFIG_CMDS 6
 
static int ISA_uarts[] = {0x3f8,0x2f8,0x3e8,0x2e8};
static int ISA_IRQs[] = {4,3,4,3};
int serialConfig_baudrate[] = {9600,14400,19200,28800,38400,57600};
 
int serialConfig_comport;
int serialConfig_irq ;
int serialConfig_baud;
char serialConfig_phone[16];
 
void M_Menu_SerialConfig_f (void)
{
int n;
int port;
int baudrate;
qboolean useModem;
 
key_dest = key_menu;
m_state = m_serialconfig;
m_entersound = true;
if (JoiningGame && SerialConfig)
serialConfig_cursor = 4;
else
serialConfig_cursor = 5;
 
(*GetComPortConfig) (0, &port, &serialConfig_irq, &baudrate, &useModem);
 
// map uart's port to COMx
for (n = 0; n < 4; n++)
if (ISA_uarts[n] == port)
break;
if (n == 4)
{
n = 0;
serialConfig_irq = 4;
}
serialConfig_comport = n + 1;
 
// map baudrate to index
for (n = 0; n < 6; n++)
if (serialConfig_baudrate[n] == baudrate)
break;
if (n == 6)
n = 5;
serialConfig_baud = n;
 
m_return_onerror = false;
m_return_reason[0] = 0;
}
 
 
void M_SerialConfig_Draw (void)
{
qpic_t *p;
int basex;
char *startJoin;
char *directModem;
 
M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
p = Draw_CachePic ("gfx/p_multi.lmp");
basex = (320-p->width)/2;
M_DrawPic (basex, 4, p);
 
if (StartingGame)
startJoin = "New Game";
else
startJoin = "Join Game";
if (SerialConfig)
directModem = "Modem";
else
directModem = "Direct Connect";
M_Print (basex, 32, va ("%s - %s", startJoin, directModem));
basex += 8;
 
M_Print (basex, serialConfig_cursor_table[0], "Port");
M_DrawTextBox (160, 40, 4, 1);
M_Print (168, serialConfig_cursor_table[0], va("COM%u", serialConfig_comport));
 
M_Print (basex, serialConfig_cursor_table[1], "IRQ");
M_DrawTextBox (160, serialConfig_cursor_table[1]-8, 1, 1);
M_Print (168, serialConfig_cursor_table[1], va("%u", serialConfig_irq));
 
M_Print (basex, serialConfig_cursor_table[2], "Baud");
M_DrawTextBox (160, serialConfig_cursor_table[2]-8, 5, 1);
M_Print (168, serialConfig_cursor_table[2], va("%u", serialConfig_baudrate[serialConfig_baud]));
 
if (SerialConfig)
{
M_Print (basex, serialConfig_cursor_table[3], "Modem Setup...");
if (JoiningGame)
{
M_Print (basex, serialConfig_cursor_table[4], "Phone number");
M_DrawTextBox (160, serialConfig_cursor_table[4]-8, 16, 1);
M_Print (168, serialConfig_cursor_table[4], serialConfig_phone);
}
}
 
if (JoiningGame)
{
M_DrawTextBox (basex, serialConfig_cursor_table[5]-8, 7, 1);
M_Print (basex+8, serialConfig_cursor_table[5], "Connect");
}
else
{
M_DrawTextBox (basex, serialConfig_cursor_table[5]-8, 2, 1);
M_Print (basex+8, serialConfig_cursor_table[5], "OK");
}
 
M_DrawCharacter (basex-8, serialConfig_cursor_table [serialConfig_cursor], 12+((int)(realtime*4)&1));
 
if (serialConfig_cursor == 4)
M_DrawCharacter (168 + 8*strlen(serialConfig_phone), serialConfig_cursor_table [serialConfig_cursor], 10+((int)(realtime*4)&1));
 
if (*m_return_reason)
M_PrintWhite (basex, 148, m_return_reason);
}
 
 
void M_SerialConfig_Key (int key)
{
int l;
 
switch (key)
{
case K_ESCAPE:
M_Menu_Net_f ();
break;
 
case K_UPARROW:
S_LocalSound ("misc/menu1.wav");
serialConfig_cursor--;
if (serialConfig_cursor < 0)
serialConfig_cursor = NUM_SERIALCONFIG_CMDS-1;
break;
 
case K_DOWNARROW:
S_LocalSound ("misc/menu1.wav");
serialConfig_cursor++;
if (serialConfig_cursor >= NUM_SERIALCONFIG_CMDS)
serialConfig_cursor = 0;
break;
 
case K_LEFTARROW:
if (serialConfig_cursor > 2)
break;
S_LocalSound ("misc/menu3.wav");
 
if (serialConfig_cursor == 0)
{
serialConfig_comport--;
if (serialConfig_comport == 0)
serialConfig_comport = 4;
serialConfig_irq = ISA_IRQs[serialConfig_comport-1];
}
 
if (serialConfig_cursor == 1)
{
serialConfig_irq--;
if (serialConfig_irq == 6)
serialConfig_irq = 5;
if (serialConfig_irq == 1)
serialConfig_irq = 7;
}
 
if (serialConfig_cursor == 2)
{
serialConfig_baud--;
if (serialConfig_baud < 0)
serialConfig_baud = 5;
}
 
break;
 
case K_RIGHTARROW:
if (serialConfig_cursor > 2)
break;
forward:
S_LocalSound ("misc/menu3.wav");
 
if (serialConfig_cursor == 0)
{
serialConfig_comport++;
if (serialConfig_comport > 4)
serialConfig_comport = 1;
serialConfig_irq = ISA_IRQs[serialConfig_comport-1];
}
 
if (serialConfig_cursor == 1)
{
serialConfig_irq++;
if (serialConfig_irq == 6)
serialConfig_irq = 7;
if (serialConfig_irq == 8)
serialConfig_irq = 2;
}
 
if (serialConfig_cursor == 2)
{
serialConfig_baud++;
if (serialConfig_baud > 5)
serialConfig_baud = 0;
}
 
break;
 
case K_ENTER:
if (serialConfig_cursor < 3)
goto forward;
 
m_entersound = true;
 
if (serialConfig_cursor == 3)
{
(*SetComPortConfig) (0, ISA_uarts[serialConfig_comport-1], serialConfig_irq, serialConfig_baudrate[serialConfig_baud], SerialConfig);
 
M_Menu_ModemConfig_f ();
break;
}
 
if (serialConfig_cursor == 4)
{
serialConfig_cursor = 5;
break;
}
 
// serialConfig_cursor == 5 (OK/CONNECT)
(*SetComPortConfig) (0, ISA_uarts[serialConfig_comport-1], serialConfig_irq, serialConfig_baudrate[serialConfig_baud], SerialConfig);
 
M_ConfigureNetSubsystem ();
 
if (StartingGame)
{
M_Menu_GameOptions_f ();
break;
}
 
m_return_state = m_state;
m_return_onerror = true;
key_dest = key_game;
m_state = m_none;
 
if (SerialConfig)
Cbuf_AddText (va ("connect \"%s\"\n", serialConfig_phone));
else
Cbuf_AddText ("connect\n");
break;
 
case K_BACKSPACE:
if (serialConfig_cursor == 4)
{
if (strlen(serialConfig_phone))
serialConfig_phone[strlen(serialConfig_phone)-1] = 0;
}
break;
 
default:
if (key < 32 || key > 127)
break;
if (serialConfig_cursor == 4)
{
l = strlen(serialConfig_phone);
if (l < 15)
{
serialConfig_phone[l+1] = 0;
serialConfig_phone[l] = key;
}
}
}
 
if (DirectConfig && (serialConfig_cursor == 3 || serialConfig_cursor == 4))
if (key == K_UPARROW)
serialConfig_cursor = 2;
else
serialConfig_cursor = 5;
 
if (SerialConfig && StartingGame && serialConfig_cursor == 4)
if (key == K_UPARROW)
serialConfig_cursor = 3;
else
serialConfig_cursor = 5;
}
 
//=============================================================================
/* MODEM CONFIG MENU */
 
int modemConfig_cursor;
int modemConfig_cursor_table [] = {40, 56, 88, 120, 156};
#define NUM_MODEMCONFIG_CMDS 5
 
char modemConfig_dialing;
char modemConfig_clear [16];
char modemConfig_init [32];
char modemConfig_hangup [16];
 
void M_Menu_ModemConfig_f (void)
{
key_dest = key_menu;
m_state = m_modemconfig;
m_entersound = true;
(*GetModemConfig) (0, &modemConfig_dialing, modemConfig_clear, modemConfig_init, modemConfig_hangup);
}
 
 
void M_ModemConfig_Draw (void)
{
qpic_t *p;
int basex;
 
M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
p = Draw_CachePic ("gfx/p_multi.lmp");
basex = (320-p->width)/2;
M_DrawPic (basex, 4, p);
basex += 8;
 
if (modemConfig_dialing == 'P')
M_Print (basex, modemConfig_cursor_table[0], "Pulse Dialing");
else
M_Print (basex, modemConfig_cursor_table[0], "Touch Tone Dialing");
 
M_Print (basex, modemConfig_cursor_table[1], "Clear");
M_DrawTextBox (basex, modemConfig_cursor_table[1]+4, 16, 1);
M_Print (basex+8, modemConfig_cursor_table[1]+12, modemConfig_clear);
if (modemConfig_cursor == 1)
M_DrawCharacter (basex+8 + 8*strlen(modemConfig_clear), modemConfig_cursor_table[1]+12, 10+((int)(realtime*4)&1));
 
M_Print (basex, modemConfig_cursor_table[2], "Init");
M_DrawTextBox (basex, modemConfig_cursor_table[2]+4, 30, 1);
M_Print (basex+8, modemConfig_cursor_table[2]+12, modemConfig_init);
if (modemConfig_cursor == 2)
M_DrawCharacter (basex+8 + 8*strlen(modemConfig_init), modemConfig_cursor_table[2]+12, 10+((int)(realtime*4)&1));
 
M_Print (basex, modemConfig_cursor_table[3], "Hangup");
M_DrawTextBox (basex, modemConfig_cursor_table[3]+4, 16, 1);
M_Print (basex+8, modemConfig_cursor_table[3]+12, modemConfig_hangup);
if (modemConfig_cursor == 3)
M_DrawCharacter (basex+8 + 8*strlen(modemConfig_hangup), modemConfig_cursor_table[3]+12, 10+((int)(realtime*4)&1));
 
M_DrawTextBox (basex, modemConfig_cursor_table[4]-8, 2, 1);
M_Print (basex+8, modemConfig_cursor_table[4], "OK");
 
M_DrawCharacter (basex-8, modemConfig_cursor_table [modemConfig_cursor], 12+((int)(realtime*4)&1));
}
 
 
void M_ModemConfig_Key (int key)
{
int l;
 
switch (key)
{
case K_ESCAPE:
M_Menu_SerialConfig_f ();
break;
 
case K_UPARROW:
S_LocalSound ("misc/menu1.wav");
modemConfig_cursor--;
if (modemConfig_cursor < 0)
modemConfig_cursor = NUM_MODEMCONFIG_CMDS-1;
break;
 
case K_DOWNARROW:
S_LocalSound ("misc/menu1.wav");
modemConfig_cursor++;
if (modemConfig_cursor >= NUM_MODEMCONFIG_CMDS)
modemConfig_cursor = 0;
break;
 
case K_LEFTARROW:
case K_RIGHTARROW:
if (modemConfig_cursor == 0)
{
if (modemConfig_dialing == 'P')
modemConfig_dialing = 'T';
else
modemConfig_dialing = 'P';
S_LocalSound ("misc/menu1.wav");
}
break;
 
case K_ENTER:
if (modemConfig_cursor == 0)
{
if (modemConfig_dialing == 'P')
modemConfig_dialing = 'T';
else
modemConfig_dialing = 'P';
m_entersound = true;
}
 
if (modemConfig_cursor == 4)
{
(*SetModemConfig) (0, va ("%c", modemConfig_dialing), modemConfig_clear, modemConfig_init, modemConfig_hangup);
m_entersound = true;
M_Menu_SerialConfig_f ();
}
break;
 
case K_BACKSPACE:
if (modemConfig_cursor == 1)
{
if (strlen(modemConfig_clear))
modemConfig_clear[strlen(modemConfig_clear)-1] = 0;
}
 
if (modemConfig_cursor == 2)
{
if (strlen(modemConfig_init))
modemConfig_init[strlen(modemConfig_init)-1] = 0;
}
 
if (modemConfig_cursor == 3)
{
if (strlen(modemConfig_hangup))
modemConfig_hangup[strlen(modemConfig_hangup)-1] = 0;
}
break;
 
default:
if (key < 32 || key > 127)
break;
 
if (modemConfig_cursor == 1)
{
l = strlen(modemConfig_clear);
if (l < 15)
{
modemConfig_clear[l+1] = 0;
modemConfig_clear[l] = key;
}
}
 
if (modemConfig_cursor == 2)
{
l = strlen(modemConfig_init);
if (l < 29)
{
modemConfig_init[l+1] = 0;
modemConfig_init[l] = key;
}
}
 
if (modemConfig_cursor == 3)
{
l = strlen(modemConfig_hangup);
if (l < 15)
{
modemConfig_hangup[l+1] = 0;
modemConfig_hangup[l] = key;
}
}
}
}
 
//=============================================================================
/* LAN CONFIG MENU */
 
int lanConfig_cursor = -1;
int lanConfig_cursor_table [] = {72, 92, 124};
#define NUM_LANCONFIG_CMDS 3
 
int lanConfig_port;
char lanConfig_portname[6];
char lanConfig_joinname[22];
 
void M_Menu_LanConfig_f (void)
{
key_dest = key_menu;
m_state = m_lanconfig;
m_entersound = true;
if (lanConfig_cursor == -1)
{
if (JoiningGame && TCPIPConfig)
lanConfig_cursor = 2;
else
lanConfig_cursor = 1;
}
if (StartingGame && lanConfig_cursor == 2)
lanConfig_cursor = 1;
lanConfig_port = DEFAULTnet_hostport;
sprintf(lanConfig_portname, "%u", lanConfig_port);
 
m_return_onerror = false;
m_return_reason[0] = 0;
}
 
 
void M_LanConfig_Draw (void)
{
qpic_t *p;
int basex;
char *startJoin;
char *protocol;
 
M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
p = Draw_CachePic ("gfx/p_multi.lmp");
basex = (320-p->width)/2;
M_DrawPic (basex, 4, p);
 
if (StartingGame)
startJoin = "New Game";
else
startJoin = "Join Game";
if (IPXConfig)
protocol = "IPX";
else
protocol = "TCP/IP";
M_Print (basex, 32, va ("%s - %s", startJoin, protocol));
basex += 8;
 
M_Print (basex, 52, "Address:");
if (IPXConfig)
M_Print (basex+9*8, 52, my_ipx_address);
else
M_Print (basex+9*8, 52, my_tcpip_address);
 
M_Print (basex, lanConfig_cursor_table[0], "Port");
M_DrawTextBox (basex+8*8, lanConfig_cursor_table[0]-8, 6, 1);
M_Print (basex+9*8, lanConfig_cursor_table[0], lanConfig_portname);
 
if (JoiningGame)
{
M_Print (basex, lanConfig_cursor_table[1], "Search for local games...");
M_Print (basex, 108, "Join game at:");
M_DrawTextBox (basex+8, lanConfig_cursor_table[2]-8, 22, 1);
M_Print (basex+16, lanConfig_cursor_table[2], lanConfig_joinname);
}
else
{
M_DrawTextBox (basex, lanConfig_cursor_table[1]-8, 2, 1);
M_Print (basex+8, lanConfig_cursor_table[1], "OK");
}
 
M_DrawCharacter (basex-8, lanConfig_cursor_table [lanConfig_cursor], 12+((int)(realtime*4)&1));
 
if (lanConfig_cursor == 0)
M_DrawCharacter (basex+9*8 + 8*strlen(lanConfig_portname), lanConfig_cursor_table [0], 10+((int)(realtime*4)&1));
 
if (lanConfig_cursor == 2)
M_DrawCharacter (basex+16 + 8*strlen(lanConfig_joinname), lanConfig_cursor_table [2], 10+((int)(realtime*4)&1));
 
if (*m_return_reason)
M_PrintWhite (basex, 148, m_return_reason);
}
 
 
void M_LanConfig_Key (int key)
{
int l;
 
switch (key)
{
case K_ESCAPE:
M_Menu_Net_f ();
break;
 
case K_UPARROW:
S_LocalSound ("misc/menu1.wav");
lanConfig_cursor--;
if (lanConfig_cursor < 0)
lanConfig_cursor = NUM_LANCONFIG_CMDS-1;
break;
 
case K_DOWNARROW:
S_LocalSound ("misc/menu1.wav");
lanConfig_cursor++;
if (lanConfig_cursor >= NUM_LANCONFIG_CMDS)
lanConfig_cursor = 0;
break;
 
case K_ENTER:
if (lanConfig_cursor == 0)
break;
 
m_entersound = true;
 
M_ConfigureNetSubsystem ();
 
if (lanConfig_cursor == 1)
{
if (StartingGame)
{
M_Menu_GameOptions_f ();
break;
}
M_Menu_Search_f();
break;
}
 
if (lanConfig_cursor == 2)
{
m_return_state = m_state;
m_return_onerror = true;
key_dest = key_game;
m_state = m_none;
Cbuf_AddText ( va ("connect \"%s\"\n", lanConfig_joinname) );
break;
}
 
break;
 
case K_BACKSPACE:
if (lanConfig_cursor == 0)
{
if (strlen(lanConfig_portname))
lanConfig_portname[strlen(lanConfig_portname)-1] = 0;
}
 
if (lanConfig_cursor == 2)
{
if (strlen(lanConfig_joinname))
lanConfig_joinname[strlen(lanConfig_joinname)-1] = 0;
}
break;
 
default:
if (key < 32 || key > 127)
break;
 
if (lanConfig_cursor == 2)
{
l = strlen(lanConfig_joinname);
if (l < 21)
{
lanConfig_joinname[l+1] = 0;
lanConfig_joinname[l] = key;
}
}
 
if (key < '0' || key > '9')
break;
if (lanConfig_cursor == 0)
{
l = strlen(lanConfig_portname);
if (l < 5)
{
lanConfig_portname[l+1] = 0;
lanConfig_portname[l] = key;
}
}
}
 
if (StartingGame && lanConfig_cursor == 2)
if (key == K_UPARROW)
lanConfig_cursor = 1;
else
lanConfig_cursor = 0;
 
l = Q_atoi(lanConfig_portname);
if (l > 65535)
l = lanConfig_port;
else
lanConfig_port = l;
sprintf(lanConfig_portname, "%u", lanConfig_port);
}
 
//=============================================================================
/* GAME OPTIONS MENU */
 
typedef struct
{
char *name;
char *description;
} level_t;
 
level_t levels[] =
{
{"start", "Entrance"}, // 0
 
{"e1m1", "Slipgate Complex"}, // 1
{"e1m2", "Castle of the Damned"},
{"e1m3", "The Necropolis"},
{"e1m4", "The Grisly Grotto"},
{"e1m5", "Gloom Keep"},
{"e1m6", "The Door To Chthon"},
{"e1m7", "The House of Chthon"},
{"e1m8", "Ziggurat Vertigo"},
 
{"e2m1", "The Installation"}, // 9
{"e2m2", "Ogre Citadel"},
{"e2m3", "Crypt of Decay"},
{"e2m4", "The Ebon Fortress"},
{"e2m5", "The Wizard's Manse"},
{"e2m6", "The Dismal Oubliette"},
{"e2m7", "Underearth"},
 
{"e3m1", "Termination Central"}, // 16
{"e3m2", "The Vaults of Zin"},
{"e3m3", "The Tomb of Terror"},
{"e3m4", "Satan's Dark Delight"},
{"e3m5", "Wind Tunnels"},
{"e3m6", "Chambers of Torment"},
{"e3m7", "The Haunted Halls"},
 
{"e4m1", "The Sewage System"}, // 23
{"e4m2", "The Tower of Despair"},
{"e4m3", "The Elder God Shrine"},
{"e4m4", "The Palace of Hate"},
{"e4m5", "Hell's Atrium"},
{"e4m6", "The Pain Maze"},
{"e4m7", "Azure Agony"},
{"e4m8", "The Nameless City"},
 
{"end", "Shub-Niggurath's Pit"}, // 31
 
{"dm1", "Place of Two Deaths"}, // 32
{"dm2", "Claustrophobopolis"},
{"dm3", "The Abandoned Base"},
{"dm4", "The Bad Place"},
{"dm5", "The Cistern"},
{"dm6", "The Dark Zone"}
};
 
//MED 01/06/97 added hipnotic levels
level_t hipnoticlevels[] =
{
{"start", "Command HQ"}, // 0
 
{"hip1m1", "The Pumping Station"}, // 1
{"hip1m2", "Storage Facility"},
{"hip1m3", "The Lost Mine"},
{"hip1m4", "Research Facility"},
{"hip1m5", "Military Complex"},
 
{"hip2m1", "Ancient Realms"}, // 6
{"hip2m2", "The Black Cathedral"},
{"hip2m3", "The Catacombs"},
{"hip2m4", "The Crypt"},
{"hip2m5", "Mortum's Keep"},
{"hip2m6", "The Gremlin's Domain"},
 
{"hip3m1", "Tur Torment"}, // 12
{"hip3m2", "Pandemonium"},
{"hip3m3", "Limbo"},
{"hip3m4", "The Gauntlet"},
 
{"hipend", "Armagon's Lair"}, // 16
 
{"hipdm1", "The Edge of Oblivion"} // 17
};
 
//PGM 01/07/97 added rogue levels
//PGM 03/02/97 added dmatch level
level_t roguelevels[] =
{
{"start", "Split Decision"},
{"r1m1", "Deviant's Domain"},
{"r1m2", "Dread Portal"},
{"r1m3", "Judgement Call"},
{"r1m4", "Cave of Death"},
{"r1m5", "Towers of Wrath"},
{"r1m6", "Temple of Pain"},
{"r1m7", "Tomb of the Overlord"},
{"r2m1", "Tempus Fugit"},
{"r2m2", "Elemental Fury I"},
{"r2m3", "Elemental Fury II"},
{"r2m4", "Curse of Osiris"},
{"r2m5", "Wizard's Keep"},
{"r2m6", "Blood Sacrifice"},
{"r2m7", "Last Bastion"},
{"r2m8", "Source of Evil"},
{"ctf1", "Division of Change"}
};
 
typedef struct
{
char *description;
int firstLevel;
int levels;
} episode_t;
 
episode_t episodes[] =
{
{"Welcome to Quake", 0, 1},
{"Doomed Dimension", 1, 8},
{"Realm of Black Magic", 9, 7},
{"Netherworld", 16, 7},
{"The Elder World", 23, 8},
{"Final Level", 31, 1},
{"Deathmatch Arena", 32, 6}
};
 
//MED 01/06/97 added hipnotic episodes
episode_t hipnoticepisodes[] =
{
{"Scourge of Armagon", 0, 1},
{"Fortress of the Dead", 1, 5},
{"Dominion of Darkness", 6, 6},
{"The Rift", 12, 4},
{"Final Level", 16, 1},
{"Deathmatch Arena", 17, 1}
};
 
//PGM 01/07/97 added rogue episodes
//PGM 03/02/97 added dmatch episode
episode_t rogueepisodes[] =
{
{"Introduction", 0, 1},
{"Hell's Fortress", 1, 7},
{"Corridors of Time", 8, 8},
{"Deathmatch Arena", 16, 1}
};
 
int startepisode;
int startlevel;
int maxplayers;
qboolean m_serverInfoMessage = false;
double m_serverInfoMessageTime;
 
void M_Menu_GameOptions_f (void)
{
key_dest = key_menu;
m_state = m_gameoptions;
m_entersound = true;
if (maxplayers == 0)
maxplayers = svs.maxclients;
if (maxplayers < 2)
maxplayers = svs.maxclientslimit;
}
 
 
int gameoptions_cursor_table[] = {40, 56, 64, 72, 80, 88, 96, 112, 120};
#define NUM_GAMEOPTIONS 9
int gameoptions_cursor;
 
void M_GameOptions_Draw (void)
{
qpic_t *p;
int x;
 
M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
p = Draw_CachePic ("gfx/p_multi.lmp");
M_DrawPic ( (320-p->width)/2, 4, p);
 
M_DrawTextBox (152, 32, 10, 1);
M_Print (160, 40, "begin game");
 
M_Print (0, 56, " Max players");
M_Print (160, 56, va("%i", maxplayers) );
 
M_Print (0, 64, " Game Type");
if (coop.value)
M_Print (160, 64, "Cooperative");
else
M_Print (160, 64, "Deathmatch");
 
M_Print (0, 72, " Teamplay");
if (rogue)
{
char *msg;
 
switch((int)teamplay.value)
{
case 1: msg = "No Friendly Fire"; break;
case 2: msg = "Friendly Fire"; break;
case 3: msg = "Tag"; break;
case 4: msg = "Capture the Flag"; break;
case 5: msg = "One Flag CTF"; break;
case 6: msg = "Three Team CTF"; break;
default: msg = "Off"; break;
}
M_Print (160, 72, msg);
}
else
{
char *msg;
 
switch((int)teamplay.value)
{
case 1: msg = "No Friendly Fire"; break;
case 2: msg = "Friendly Fire"; break;
default: msg = "Off"; break;
}
M_Print (160, 72, msg);
}
 
M_Print (0, 80, " Skill");
if (skill.value == 0)
M_Print (160, 80, "Easy difficulty");
else if (skill.value == 1)
M_Print (160, 80, "Normal difficulty");
else if (skill.value == 2)
M_Print (160, 80, "Hard difficulty");
else
M_Print (160, 80, "Nightmare difficulty");
 
M_Print (0, 88, " Frag Limit");
if (fraglimit.value == 0)
M_Print (160, 88, "none");
else
M_Print (160, 88, va("%i frags", (int)fraglimit.value));
 
M_Print (0, 96, " Time Limit");
if (timelimit.value == 0)
M_Print (160, 96, "none");
else
M_Print (160, 96, va("%i minutes", (int)timelimit.value));
 
M_Print (0, 112, " Episode");
//MED 01/06/97 added hipnotic episodes
if (hipnotic)
M_Print (160, 112, hipnoticepisodes[startepisode].description);
//PGM 01/07/97 added rogue episodes
else if (rogue)
M_Print (160, 112, rogueepisodes[startepisode].description);
else
M_Print (160, 112, episodes[startepisode].description);
 
M_Print (0, 120, " Level");
//MED 01/06/97 added hipnotic episodes
if (hipnotic)
{
M_Print (160, 120, hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].description);
M_Print (160, 128, hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].name);
}
//PGM 01/07/97 added rogue episodes
else if (rogue)
{
M_Print (160, 120, roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].description);
M_Print (160, 128, roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].name);
}
else
{
M_Print (160, 120, levels[episodes[startepisode].firstLevel + startlevel].description);
M_Print (160, 128, levels[episodes[startepisode].firstLevel + startlevel].name);
}
 
// line cursor
M_DrawCharacter (144, gameoptions_cursor_table[gameoptions_cursor], 12+((int)(realtime*4)&1));
 
if (m_serverInfoMessage)
{
if ((realtime - m_serverInfoMessageTime) < 5.0)
{
x = (320-26*8)/2;
M_DrawTextBox (x, 138, 24, 4);
x += 8;
M_Print (x, 146, " More than 4 players ");
M_Print (x, 154, " requires using command ");
M_Print (x, 162, "line parameters; please ");
M_Print (x, 170, " see techinfo.txt. ");
}
else
{
m_serverInfoMessage = false;
}
}
}
 
 
void M_NetStart_Change (int dir)
{
int count;
 
switch (gameoptions_cursor)
{
case 1:
maxplayers += dir;
if (maxplayers > svs.maxclientslimit)
{
maxplayers = svs.maxclientslimit;
m_serverInfoMessage = true;
m_serverInfoMessageTime = realtime;
}
if (maxplayers < 2)
maxplayers = 2;
break;
 
case 2:
Cvar_SetValue ("coop", coop.value ? 0 : 1);
break;
 
case 3:
if (rogue)
count = 6;
else
count = 2;
 
Cvar_SetValue ("teamplay", teamplay.value + dir);
if (teamplay.value > count)
Cvar_SetValue ("teamplay", 0);
else if (teamplay.value < 0)
Cvar_SetValue ("teamplay", count);
break;
 
case 4:
Cvar_SetValue ("skill", skill.value + dir);
if (skill.value > 3)
Cvar_SetValue ("skill", 0);
if (skill.value < 0)
Cvar_SetValue ("skill", 3);
break;
 
case 5:
Cvar_SetValue ("fraglimit", fraglimit.value + dir*10);
if (fraglimit.value > 100)
Cvar_SetValue ("fraglimit", 0);
if (fraglimit.value < 0)
Cvar_SetValue ("fraglimit", 100);
break;
 
case 6:
Cvar_SetValue ("timelimit", timelimit.value + dir*5);
if (timelimit.value > 60)
Cvar_SetValue ("timelimit", 0);
if (timelimit.value < 0)
Cvar_SetValue ("timelimit", 60);
break;
 
case 7:
startepisode += dir;
//MED 01/06/97 added hipnotic count
if (hipnotic)
count = 6;
//PGM 01/07/97 added rogue count
//PGM 03/02/97 added 1 for dmatch episode
else if (rogue)
count = 4;
else if (registered.value)
count = 7;
else
count = 2;
 
if (startepisode < 0)
startepisode = count - 1;
 
if (startepisode >= count)
startepisode = 0;
 
startlevel = 0;
break;
 
case 8:
startlevel += dir;
//MED 01/06/97 added hipnotic episodes
if (hipnotic)
count = hipnoticepisodes[startepisode].levels;
//PGM 01/06/97 added hipnotic episodes
else if (rogue)
count = rogueepisodes[startepisode].levels;
else
count = episodes[startepisode].levels;
 
if (startlevel < 0)
startlevel = count - 1;
 
if (startlevel >= count)
startlevel = 0;
break;
}
}
 
void M_GameOptions_Key (int key)
{
switch (key)
{
case K_ESCAPE:
M_Menu_Net_f ();
break;
 
case K_UPARROW:
S_LocalSound ("misc/menu1.wav");
gameoptions_cursor--;
if (gameoptions_cursor < 0)
gameoptions_cursor = NUM_GAMEOPTIONS-1;
break;
 
case K_DOWNARROW:
S_LocalSound ("misc/menu1.wav");
gameoptions_cursor++;
if (gameoptions_cursor >= NUM_GAMEOPTIONS)
gameoptions_cursor = 0;
break;
 
case K_LEFTARROW:
if (gameoptions_cursor == 0)
break;
S_LocalSound ("misc/menu3.wav");
M_NetStart_Change (-1);
break;
 
case K_RIGHTARROW:
if (gameoptions_cursor == 0)
break;
S_LocalSound ("misc/menu3.wav");
M_NetStart_Change (1);
break;
 
case K_ENTER:
S_LocalSound ("misc/menu2.wav");
if (gameoptions_cursor == 0)
{
if (sv.active)
Cbuf_AddText ("disconnect\n");
Cbuf_AddText ("listen 0\n"); // so host_netport will be re-examined
Cbuf_AddText ( va ("maxplayers %u\n", maxplayers) );
SCR_BeginLoadingPlaque ();
 
if (hipnotic)
Cbuf_AddText ( va ("map %s\n", hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].name) );
else if (rogue)
Cbuf_AddText ( va ("map %s\n", roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].name) );
else
Cbuf_AddText ( va ("map %s\n", levels[episodes[startepisode].firstLevel + startlevel].name) );
 
return;
}
 
M_NetStart_Change (1);
break;
}
}
 
//=============================================================================
/* SEARCH MENU */
 
qboolean searchComplete = false;
double searchCompleteTime;
 
void M_Menu_Search_f (void)
{
key_dest = key_menu;
m_state = m_search;
m_entersound = false;
slistSilent = true;
slistLocal = false;
searchComplete = false;
NET_Slist_f();
 
}
 
 
void M_Search_Draw (void)
{
qpic_t *p;
int x;
 
p = Draw_CachePic ("gfx/p_multi.lmp");
M_DrawPic ( (320-p->width)/2, 4, p);
x = (320/2) - ((12*8)/2) + 4;
M_DrawTextBox (x-8, 32, 12, 1);
M_Print (x, 40, "Searching...");
 
if(slistInProgress)
{
NET_Poll();
return;
}
 
if (! searchComplete)
{
searchComplete = true;
searchCompleteTime = realtime;
}
 
if (hostCacheCount)
{
M_Menu_ServerList_f ();
return;
}
 
M_PrintWhite ((320/2) - ((22*8)/2), 64, "No Quake servers found");
if ((realtime - searchCompleteTime) < 3.0)
return;
 
M_Menu_LanConfig_f ();
}
 
 
void M_Search_Key (int key)
{
}
 
//=============================================================================
/* SLIST MENU */
 
int slist_cursor;
qboolean slist_sorted;
 
void M_Menu_ServerList_f (void)
{
key_dest = key_menu;
m_state = m_slist;
m_entersound = true;
slist_cursor = 0;
m_return_onerror = false;
m_return_reason[0] = 0;
slist_sorted = false;
}
 
 
void M_ServerList_Draw (void)
{
int n;
char string [64];
qpic_t *p;
 
if (!slist_sorted)
{
if (hostCacheCount > 1)
{
int i,j;
hostcache_t temp;
for (i = 0; i < hostCacheCount; i++)
for (j = i+1; j < hostCacheCount; j++)
if (strcmp(hostcache[j].name, hostcache[i].name) < 0)
{
Q_memcpy(&temp, &hostcache[j], sizeof(hostcache_t));
Q_memcpy(&hostcache[j], &hostcache[i], sizeof(hostcache_t));
Q_memcpy(&hostcache[i], &temp, sizeof(hostcache_t));
}
}
slist_sorted = true;
}
 
p = Draw_CachePic ("gfx/p_multi.lmp");
M_DrawPic ( (320-p->width)/2, 4, p);
for (n = 0; n < hostCacheCount; n++)
{
if (hostcache[n].maxusers)
sprintf(string, "%-15.15s %-15.15s %2u/%2u\n", hostcache[n].name, hostcache[n].map, hostcache[n].users, hostcache[n].maxusers);
else
sprintf(string, "%-15.15s %-15.15s\n", hostcache[n].name, hostcache[n].map);
M_Print (16, 32 + 8*n, string);
}
M_DrawCharacter (0, 32 + slist_cursor*8, 12+((int)(realtime*4)&1));
 
if (*m_return_reason)
M_PrintWhite (16, 148, m_return_reason);
}
 
 
void M_ServerList_Key (int k)
{
switch (k)
{
case K_ESCAPE:
M_Menu_LanConfig_f ();
break;
 
case K_SPACE:
M_Menu_Search_f ();
break;
 
case K_UPARROW:
case K_LEFTARROW:
S_LocalSound ("misc/menu1.wav");
slist_cursor--;
if (slist_cursor < 0)
slist_cursor = hostCacheCount - 1;
break;
 
case K_DOWNARROW:
case K_RIGHTARROW:
S_LocalSound ("misc/menu1.wav");
slist_cursor++;
if (slist_cursor >= hostCacheCount)
slist_cursor = 0;
break;
 
case K_ENTER:
S_LocalSound ("misc/menu2.wav");
m_return_state = m_state;
m_return_onerror = true;
slist_sorted = false;
key_dest = key_game;
m_state = m_none;
Cbuf_AddText ( va ("connect \"%s\"\n", hostcache[slist_cursor].cname) );
break;
 
default:
break;
}
 
}
 
//=============================================================================
/* Menu Subsystem */
 
 
void M_Init (void)
{
Cmd_AddCommand ("togglemenu", M_ToggleMenu_f);
 
Cmd_AddCommand ("menu_main", M_Menu_Main_f);
Cmd_AddCommand ("menu_singleplayer", M_Menu_SinglePlayer_f);
Cmd_AddCommand ("menu_load", M_Menu_Load_f);
Cmd_AddCommand ("menu_save", M_Menu_Save_f);
Cmd_AddCommand ("menu_multiplayer", M_Menu_MultiPlayer_f);
Cmd_AddCommand ("menu_setup", M_Menu_Setup_f);
Cmd_AddCommand ("menu_options", M_Menu_Options_f);
Cmd_AddCommand ("menu_keys", M_Menu_Keys_f);
Cmd_AddCommand ("menu_video", M_Menu_Video_f);
Cmd_AddCommand ("help", M_Menu_Help_f);
Cmd_AddCommand ("menu_quit", M_Menu_Quit_f);
}
 
 
void M_Draw (void)
{
if (m_state == m_none || key_dest != key_menu)
return;
 
if (!m_recursiveDraw)
{
scr_copyeverything = 1;
 
if (scr_con_current)
{
Draw_ConsoleBackground (vid.height);
VID_UnlockBuffer ();
S_ExtraUpdate ();
VID_LockBuffer ();
}
else
Draw_FadeScreen ();
 
scr_fullupdate = 0;
}
else
{
m_recursiveDraw = false;
}
 
switch (m_state)
{
case m_none:
break;
 
case m_main:
M_Main_Draw ();
break;
 
case m_singleplayer:
M_SinglePlayer_Draw ();
break;
 
case m_load:
M_Load_Draw ();
break;
 
case m_save:
M_Save_Draw ();
break;
 
case m_multiplayer:
M_MultiPlayer_Draw ();
break;
 
case m_setup:
M_Setup_Draw ();
break;
 
case m_net:
M_Net_Draw ();
break;
 
case m_options:
M_Options_Draw ();
break;
 
case m_keys:
M_Keys_Draw ();
break;
 
case m_video:
M_Video_Draw ();
break;
 
case m_help:
M_Help_Draw ();
break;
 
case m_quit:
M_Quit_Draw ();
break;
 
case m_serialconfig:
M_SerialConfig_Draw ();
break;
 
case m_modemconfig:
M_ModemConfig_Draw ();
break;
 
case m_lanconfig:
M_LanConfig_Draw ();
break;
 
case m_gameoptions:
M_GameOptions_Draw ();
break;
 
case m_search:
M_Search_Draw ();
break;
 
case m_slist:
M_ServerList_Draw ();
break;
}
 
if (m_entersound)
{
S_LocalSound ("misc/menu2.wav");
m_entersound = false;
}
 
VID_UnlockBuffer ();
S_ExtraUpdate ();
VID_LockBuffer ();
}
 
 
void M_Keydown (int key)
{
switch (m_state)
{
case m_none:
return;
 
case m_main:
M_Main_Key (key);
return;
 
case m_singleplayer:
M_SinglePlayer_Key (key);
return;
 
case m_load:
M_Load_Key (key);
return;
 
case m_save:
M_Save_Key (key);
return;
 
case m_multiplayer:
M_MultiPlayer_Key (key);
return;
 
case m_setup:
M_Setup_Key (key);
return;
 
case m_net:
M_Net_Key (key);
return;
 
case m_options:
M_Options_Key (key);
return;
 
case m_keys:
M_Keys_Key (key);
return;
 
case m_video:
M_Video_Key (key);
return;
 
case m_help:
M_Help_Key (key);
return;
 
case m_quit:
M_Quit_Key (key);
return;
 
case m_serialconfig:
M_SerialConfig_Key (key);
return;
 
case m_modemconfig:
M_ModemConfig_Key (key);
return;
 
case m_lanconfig:
M_LanConfig_Key (key);
return;
 
case m_gameoptions:
M_GameOptions_Key (key);
return;
 
case m_search:
M_Search_Key (key);
break;
 
case m_slist:
M_ServerList_Key (key);
return;
}
}
 
 
void M_ConfigureNetSubsystem(void)
{
// enable/disable net systems to match desired config
 
Cbuf_AddText ("stopdemo\n");
if (SerialConfig || DirectConfig)
{
Cbuf_AddText ("com1 enable\n");
}
 
if (IPXConfig || TCPIPConfig)
net_hostport = lanConfig_port;
}
/contrib/other/sdlquake-1.0.9/menu.h
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);
 
 
/contrib/other/sdlquake-1.0.9/missing
0,0 → 1,190
#! /bin/sh
# Common stub for a few missing GNU programs while installing.
# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
# Franc,ois Pinard <pinard@iro.umontreal.ca>, 1996.
 
# 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, 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.
 
if test $# -eq 0; then
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
fi
 
case "$1" in
 
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
 
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
error status if there is no known handling for PROGRAM.
 
Options:
-h, --help display this help and exit
-v, --version output version information and exit
 
Supported PROGRAM values:
aclocal touch file \`aclocal.m4'
autoconf touch file \`configure'
autoheader touch file \`config.h.in'
automake touch all \`Makefile.in' files
bison create \`y.tab.[ch]', if possible, from existing .[ch]
flex create \`lex.yy.c', if possible, from existing .c
lex create \`lex.yy.c', if possible, from existing .c
makeinfo touch the output file
yacc create \`y.tab.[ch]', if possible, from existing .[ch]"
;;
 
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing - GNU libit 0.0"
;;
 
-*)
echo 1>&2 "$0: Unknown \`$1' option"
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
;;
 
aclocal)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`acinclude.m4' or \`configure.in'. You might want
to install the \`Automake' and \`Perl' packages. Grab them from
any GNU archive site."
touch aclocal.m4
;;
 
autoconf)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`configure.in'. You might want to install the
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
archive site."
touch configure
;;
 
autoheader)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`acconfig.h' or \`configure.in'. You might want
to install the \`Autoconf' and \`GNU m4' packages. Grab them
from any GNU archive site."
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' configure.in`
test -z "$files" && files="config.h"
touch_files=
for f in $files; do
case "$f" in
*:*) touch_files="$touch_files "`echo "$f" |
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
*) touch_files="$touch_files $f.in";;
esac
done
touch $touch_files
;;
 
automake)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'.
You might want to install the \`Automake' and \`Perl' packages.
Grab them from any GNU archive site."
find . -type f -name Makefile.am -print |
sed 's/\.am$/.in/' |
while read f; do touch "$f"; done
;;
 
bison|yacc)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a \`.y' file. You may need the \`Bison' package
in order for those modifications to take effect. You can get
\`Bison' from any GNU archive site."
rm -f y.tab.c y.tab.h
if [ $# -ne 1 ]; then
eval LASTARG="\${$#}"
case "$LASTARG" in
*.y)
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" y.tab.c
fi
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" y.tab.h
fi
;;
esac
fi
if [ ! -f y.tab.h ]; then
echo >y.tab.h
fi
if [ ! -f y.tab.c ]; then
echo 'main() { return 0; }' >y.tab.c
fi
;;
 
lex|flex)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a \`.l' file. You may need the \`Flex' package
in order for those modifications to take effect. You can get
\`Flex' from any GNU archive site."
rm -f lex.yy.c
if [ $# -ne 1 ]; then
eval LASTARG="\${$#}"
case "$LASTARG" in
*.l)
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" lex.yy.c
fi
;;
esac
fi
if [ ! -f lex.yy.c ]; then
echo 'main() { return 0; }' >lex.yy.c
fi
;;
 
makeinfo)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a \`.texi' or \`.texinfo' file, or any other file
indirectly affecting the aspect of the manual. The spurious
call might also be the consequence of using a buggy \`make' (AIX,
DU, IRIX). You might want to install the \`Texinfo' package or
the \`GNU make' package. Grab either from any GNU archive site."
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
if test -z "$file"; then
file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
fi
touch $file
;;
 
*)
echo 1>&2 "\
WARNING: \`$1' is needed, and you do not seem to have it handy on your
system. You might have modified some files without having the
proper tools for further handling them. Check the \`README' file,
it often tells you about the needed prerequirements for installing
this package. You may also peek at any GNU archive site, in case
some other package would contain this missing \`$1' program."
exit 1
;;
esac
 
exit 0
/contrib/other/sdlquake-1.0.9/mkinstalldirs
0,0 → 1,40
#! /bin/sh
# mkinstalldirs --- make directory hierarchy
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
# Created: 1993-05-16
# Public domain
 
# $Id: mkinstalldirs,v 1.13 1999/01/05 03:18:55 bje Exp $
 
errstatus=0
 
for file
do
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
shift
 
pathcomp=
for d
do
pathcomp="$pathcomp$d"
case "$pathcomp" in
-* ) pathcomp=./$pathcomp ;;
esac
 
if test ! -d "$pathcomp"; then
echo "mkdir $pathcomp"
 
mkdir "$pathcomp" || lasterr=$?
 
if test ! -d "$pathcomp"; then
errstatus=$lasterr
fi
fi
 
pathcomp="$pathcomp/"
done
done
 
exit $errstatus
 
# mkinstalldirs ends here
/contrib/other/sdlquake-1.0.9/model.c
0,0 → 1,1874
/*
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.
 
*/
// models.c -- model loading and caching
 
// models are the only shared resource between a client and server running
// on the same machine.
 
#include "quakedef.h"
#include "r_local.h"
 
model_t *loadmodel;
char loadname[32]; // for hunk tags
 
void Mod_LoadSpriteModel (model_t *mod, void *buffer);
void Mod_LoadBrushModel (model_t *mod, void *buffer);
void Mod_LoadAliasModel (model_t *mod, void *buffer);
model_t *Mod_LoadModel (model_t *mod, qboolean crash);
 
byte mod_novis[MAX_MAP_LEAFS/8];
 
#define MAX_MOD_KNOWN 256
model_t mod_known[MAX_MOD_KNOWN];
int mod_numknown;
 
// values for model_t's needload
#define NL_PRESENT 0
#define NL_NEEDS_LOADED 1
#define NL_UNREFERENCED 2
 
/*
===============
Mod_Init
===============
*/
void Mod_Init (void)
{
memset (mod_novis, 0xff, sizeof(mod_novis));
}
 
/*
===============
Mod_Extradata
 
Caches the data if needed
===============
*/
void *Mod_Extradata (model_t *mod)
{
void *r;
r = Cache_Check (&mod->cache);
if (r)
return r;
 
Mod_LoadModel (mod, true);
if (!mod->cache.data)
Sys_Error ("Mod_Extradata: caching failed");
return mod->cache.data;
}
 
/*
===============
Mod_PointInLeaf
===============
*/
mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
{
mnode_t *node;
float d;
mplane_t *plane;
if (!model || !model->nodes)
Sys_Error ("Mod_PointInLeaf: bad model");
 
node = model->nodes;
while (1)
{
if (node->contents < 0)
return (mleaf_t *)node;
plane = node->plane;
d = DotProduct (p,plane->normal) - plane->dist;
if (d > 0)
node = node->children[0];
else
node = node->children[1];
}
return NULL; // never reached
}
 
 
/*
===================
Mod_DecompressVis
===================
*/
byte *Mod_DecompressVis (byte *in, model_t *model)
{
static byte decompressed[MAX_MAP_LEAFS/8];
int c;
byte *out;
int row;
 
row = (model->numleafs+7)>>3;
out = decompressed;
 
if (!in)
{ // no vis info, so make all visible
while (row)
{
*out++ = 0xff;
row--;
}
return decompressed;
}
 
do
{
if (*in)
{
*out++ = *in++;
continue;
}
c = in[1];
in += 2;
while (c)
{
*out++ = 0;
c--;
}
} while (out - decompressed < row);
return decompressed;
}
 
byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model)
{
if (leaf == model->leafs)
return mod_novis;
return Mod_DecompressVis (leaf->compressed_vis, model);
}
 
/*
===================
Mod_ClearAll
===================
*/
void Mod_ClearAll (void)
{
int i;
model_t *mod;
 
 
for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++) {
mod->needload = NL_UNREFERENCED;
//FIX FOR CACHE_ALLOC ERRORS:
if (mod->type == mod_sprite) mod->cache.data = NULL;
}
}
 
/*
==================
Mod_FindName
 
==================
*/
model_t *Mod_FindName (char *name)
{
int i;
model_t *mod;
model_t *avail = NULL;
 
if (!name[0])
Sys_Error ("Mod_ForName: NULL name");
//
// search the currently loaded models
//
for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
{
if (!strcmp (mod->name, name) )
break;
if (mod->needload == NL_UNREFERENCED)
if (!avail || mod->type != mod_alias)
avail = mod;
}
if (i == mod_numknown)
{
if (mod_numknown == MAX_MOD_KNOWN)
{
if (avail)
{
mod = avail;
if (mod->type == mod_alias)
if (Cache_Check (&mod->cache))
Cache_Free (&mod->cache);
}
else
Sys_Error ("mod_numknown == MAX_MOD_KNOWN");
}
else
mod_numknown++;
strcpy (mod->name, name);
mod->needload = NL_NEEDS_LOADED;
}
 
return mod;
}
 
/*
==================
Mod_TouchModel
 
==================
*/
void Mod_TouchModel (char *name)
{
model_t *mod;
mod = Mod_FindName (name);
if (mod->needload == NL_PRESENT)
{
if (mod->type == mod_alias)
Cache_Check (&mod->cache);
}
}
 
/*
==================
Mod_LoadModel
 
Loads a model into the cache
==================
*/
model_t *Mod_LoadModel (model_t *mod, qboolean crash)
{
unsigned *buf;
byte stackbuf[1024]; // avoid dirtying the cache heap
 
if (mod->type == mod_alias)
{
if (Cache_Check (&mod->cache))
{
mod->needload = NL_PRESENT;
return mod;
}
}
else
{
if (mod->needload == NL_PRESENT)
return mod;
}
 
//
// because the world is so huge, load it one piece at a time
//
//
// load the file
//
buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf));
if (!buf)
{
if (crash)
Sys_Error ("Mod_NumForName: %s not found", mod->name);
return NULL;
}
//
// allocate a new model
//
COM_FileBase (mod->name, loadname);
loadmodel = mod;
 
//
// fill it in
//
 
// call the apropriate loader
mod->needload = NL_PRESENT;
 
switch (LittleLong(*(unsigned *)buf))
{
case IDPOLYHEADER:
Mod_LoadAliasModel (mod, buf);
break;
case IDSPRITEHEADER:
Mod_LoadSpriteModel (mod, buf);
break;
default:
Mod_LoadBrushModel (mod, buf);
break;
}
 
return mod;
}
 
/*
==================
Mod_ForName
 
Loads in a model for the given name
==================
*/
model_t *Mod_ForName (char *name, qboolean crash)
{
model_t *mod;
 
mod = Mod_FindName (name);
 
return Mod_LoadModel (mod, crash);
}
 
 
/*
===============================================================================
 
BRUSHMODEL LOADING
 
===============================================================================
*/
 
byte *mod_base;
 
 
/*
=================
Mod_LoadTextures
=================
*/
void Mod_LoadTextures (lump_t *l)
{
int i, j, pixels, num, max, altmax;
miptex_t *mt;
texture_t *tx, *tx2;
texture_t *anims[10];
texture_t *altanims[10];
dmiptexlump_t *m;
 
if (!l->filelen)
{
loadmodel->textures = NULL;
return;
}
m = (dmiptexlump_t *)(mod_base + l->fileofs);
m->nummiptex = LittleLong (m->nummiptex);
loadmodel->numtextures = m->nummiptex;
loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures) , loadname);
 
for (i=0 ; i<m->nummiptex ; i++)
{
m->dataofs[i] = LittleLong(m->dataofs[i]);
if (m->dataofs[i] == -1)
continue;
mt = (miptex_t *)((byte *)m + m->dataofs[i]);
mt->width = LittleLong (mt->width);
mt->height = LittleLong (mt->height);
for (j=0 ; j<MIPLEVELS ; j++)
mt->offsets[j] = LittleLong (mt->offsets[j]);
if ( (mt->width & 15) || (mt->height & 15) )
Sys_Error ("Texture %s is not 16 aligned", mt->name);
pixels = mt->width*mt->height/64*85;
tx = Hunk_AllocName (sizeof(texture_t) +pixels, loadname );
loadmodel->textures[i] = tx;
 
memcpy (tx->name, mt->name, sizeof(tx->name));
tx->width = mt->width;
tx->height = mt->height;
for (j=0 ; j<MIPLEVELS ; j++)
tx->offsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t);
// the pixels immediately follow the structures
memcpy ( tx+1, mt+1, pixels);
if (!Q_strncmp(mt->name,"sky",3))
R_InitSky (tx);
}
 
//
// sequence the animations
//
for (i=0 ; i<m->nummiptex ; i++)
{
tx = loadmodel->textures[i];
if (!tx || tx->name[0] != '+')
continue;
if (tx->anim_next)
continue; // allready sequenced
 
// find the number of frames in the animation
memset (anims, 0, sizeof(anims));
memset (altanims, 0, sizeof(altanims));
 
max = tx->name[1];
altmax = 0;
if (max >= 'a' && max <= 'z')
max -= 'a' - 'A';
if (max >= '0' && max <= '9')
{
max -= '0';
altmax = 0;
anims[max] = tx;
max++;
}
else if (max >= 'A' && max <= 'J')
{
altmax = max - 'A';
max = 0;
altanims[altmax] = tx;
altmax++;
}
else
Sys_Error ("Bad animating texture %s", tx->name);
 
for (j=i+1 ; j<m->nummiptex ; j++)
{
tx2 = loadmodel->textures[j];
if (!tx2 || tx2->name[0] != '+')
continue;
if (strcmp (tx2->name+2, tx->name+2))
continue;
 
num = tx2->name[1];
if (num >= 'a' && num <= 'z')
num -= 'a' - 'A';
if (num >= '0' && num <= '9')
{
num -= '0';
anims[num] = tx2;
if (num+1 > max)
max = num + 1;
}
else if (num >= 'A' && num <= 'J')
{
num = num - 'A';
altanims[num] = tx2;
if (num+1 > altmax)
altmax = num+1;
}
else
Sys_Error ("Bad animating texture %s", tx->name);
}
#define ANIM_CYCLE 2
// link them all together
for (j=0 ; j<max ; j++)
{
tx2 = anims[j];
if (!tx2)
Sys_Error ("Missing frame %i of %s",j, tx->name);
tx2->anim_total = max * ANIM_CYCLE;
tx2->anim_min = j * ANIM_CYCLE;
tx2->anim_max = (j+1) * ANIM_CYCLE;
tx2->anim_next = anims[ (j+1)%max ];
if (altmax)
tx2->alternate_anims = altanims[0];
}
for (j=0 ; j<altmax ; j++)
{
tx2 = altanims[j];
if (!tx2)
Sys_Error ("Missing frame %i of %s",j, tx->name);
tx2->anim_total = altmax * ANIM_CYCLE;
tx2->anim_min = j * ANIM_CYCLE;
tx2->anim_max = (j+1) * ANIM_CYCLE;
tx2->anim_next = altanims[ (j+1)%altmax ];
if (max)
tx2->alternate_anims = anims[0];
}
}
}
 
/*
=================
Mod_LoadLighting
=================
*/
void Mod_LoadLighting (lump_t *l)
{
if (!l->filelen)
{
loadmodel->lightdata = NULL;
return;
}
loadmodel->lightdata = Hunk_AllocName ( l->filelen, loadname);
memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
}
 
 
/*
=================
Mod_LoadVisibility
=================
*/
void Mod_LoadVisibility (lump_t *l)
{
if (!l->filelen)
{
loadmodel->visdata = NULL;
return;
}
loadmodel->visdata = Hunk_AllocName ( l->filelen, loadname);
memcpy (loadmodel->visdata, mod_base + l->fileofs, l->filelen);
}
 
 
/*
=================
Mod_LoadEntities
=================
*/
void Mod_LoadEntities (lump_t *l)
{
if (!l->filelen)
{
loadmodel->entities = NULL;
return;
}
loadmodel->entities = Hunk_AllocName ( l->filelen, loadname);
memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen);
}
 
 
/*
=================
Mod_LoadVertexes
=================
*/
void Mod_LoadVertexes (lump_t *l)
{
dvertex_t *in;
mvertex_t *out;
int i, count;
 
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
 
loadmodel->vertexes = out;
loadmodel->numvertexes = count;
 
for ( i=0 ; i<count ; i++, in++, out++)
{
out->position[0] = LittleFloat (in->point[0]);
out->position[1] = LittleFloat (in->point[1]);
out->position[2] = LittleFloat (in->point[2]);
}
}
 
/*
=================
Mod_LoadSubmodels
=================
*/
void Mod_LoadSubmodels (lump_t *l)
{
dmodel_t *in;
dmodel_t *out;
int i, j, count;
 
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
 
loadmodel->submodels = out;
loadmodel->numsubmodels = count;
 
for ( i=0 ; i<count ; i++, in++, out++)
{
for (j=0 ; j<3 ; j++)
{ // spread the mins / maxs by a pixel
out->mins[j] = LittleFloat (in->mins[j]) - 1;
out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
out->origin[j] = LittleFloat (in->origin[j]);
}
for (j=0 ; j<MAX_MAP_HULLS ; j++)
out->headnode[j] = LittleLong (in->headnode[j]);
out->visleafs = LittleLong (in->visleafs);
out->firstface = LittleLong (in->firstface);
out->numfaces = LittleLong (in->numfaces);
}
}
 
/*
=================
Mod_LoadEdges
=================
*/
void Mod_LoadEdges (lump_t *l)
{
dedge_t *in;
medge_t *out;
int i, count;
 
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname);
 
loadmodel->edges = out;
loadmodel->numedges = count;
 
for ( i=0 ; i<count ; i++, in++, out++)
{
out->v[0] = (unsigned short)LittleShort(in->v[0]);
out->v[1] = (unsigned short)LittleShort(in->v[1]);
}
}
 
/*
=================
Mod_LoadTexinfo
=================
*/
void Mod_LoadTexinfo (lump_t *l)
{
texinfo_t *in;
mtexinfo_t *out;
int i, j, count;
int miptex;
float len1, len2;
 
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
 
loadmodel->texinfo = out;
loadmodel->numtexinfo = count;
 
for ( i=0 ; i<count ; i++, in++, out++)
{
for (j=0 ; j<8 ; j++)
*(&out->vecs[0][0] + j) = LittleFloat (*(&in->vecs[0][0] + j));
len1 = Length (out->vecs[0]);
len2 = Length (out->vecs[1]);
len1 = (len1 + len2)/2;
if (len1 < 0.32)
out->mipadjust = 4;
else if (len1 < 0.49)
out->mipadjust = 3;
else if (len1 < 0.99)
out->mipadjust = 2;
else
out->mipadjust = 1;
#if 0
if (len1 + len2 < 0.001)
out->mipadjust = 1; // don't crash
else
out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 );
#endif
 
miptex = LittleLong (in->miptex);
out->flags = LittleLong (in->flags);
if (!loadmodel->textures)
{
out->texture = r_notexture_mip; // checkerboard texture
out->flags = 0;
}
else
{
if (miptex >= loadmodel->numtextures)
Sys_Error ("miptex >= loadmodel->numtextures");
out->texture = loadmodel->textures[miptex];
if (!out->texture)
{
out->texture = r_notexture_mip; // texture not found
out->flags = 0;
}
}
}
}
 
/*
================
CalcSurfaceExtents
 
Fills in s->texturemins[] and s->extents[]
================
*/
void CalcSurfaceExtents (msurface_t *s)
{
float mins[2], maxs[2], val;
int i,j, e;
mvertex_t *v;
mtexinfo_t *tex;
int bmins[2], bmaxs[2];
 
mins[0] = mins[1] = 999999;
maxs[0] = maxs[1] = -99999;
 
tex = s->texinfo;
for (i=0 ; i<s->numedges ; i++)
{
e = loadmodel->surfedges[s->firstedge+i];
if (e >= 0)
v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
else
v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
for (j=0 ; j<2 ; j++)
{
val = v->position[0] * tex->vecs[j][0] +
v->position[1] * tex->vecs[j][1] +
v->position[2] * tex->vecs[j][2] +
tex->vecs[j][3];
if (val < mins[j])
mins[j] = val;
if (val > maxs[j])
maxs[j] = val;
}
}
 
for (i=0 ; i<2 ; i++)
{
bmins[i] = floor(mins[i]/16);
bmaxs[i] = ceil(maxs[i]/16);
 
s->texturemins[i] = bmins[i] * 16;
s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 256)
Sys_Error ("Bad surface extents");
}
}
 
 
/*
=================
Mod_LoadFaces
=================
*/
void Mod_LoadFaces (lump_t *l)
{
dface_t *in;
msurface_t *out;
int i, count, surfnum;
int planenum, side;
 
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
 
loadmodel->surfaces = out;
loadmodel->numsurfaces = count;
 
for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
{
out->firstedge = LittleLong(in->firstedge);
out->numedges = LittleShort(in->numedges);
out->flags = 0;
 
planenum = LittleShort(in->planenum);
side = LittleShort(in->side);
if (side)
out->flags |= SURF_PLANEBACK;
 
out->plane = loadmodel->planes + planenum;
 
out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo);
 
CalcSurfaceExtents (out);
// lighting info
 
for (i=0 ; i<MAXLIGHTMAPS ; i++)
out->styles[i] = in->styles[i];
i = LittleLong(in->lightofs);
if (i == -1)
out->samples = NULL;
else
out->samples = loadmodel->lightdata + i;
// set the drawing flags flag
if (!Q_strncmp(out->texinfo->texture->name,"sky",3)) // sky
{
out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED);
continue;
}
if (!Q_strncmp(out->texinfo->texture->name,"*",1)) // turbulent
{
out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
for (i=0 ; i<2 ; i++)
{
out->extents[i] = 16384;
out->texturemins[i] = -8192;
}
continue;
}
}
}
 
 
/*
=================
Mod_SetParent
=================
*/
void Mod_SetParent (mnode_t *node, mnode_t *parent)
{
node->parent = parent;
if (node->contents < 0)
return;
Mod_SetParent (node->children[0], node);
Mod_SetParent (node->children[1], node);
}
 
/*
=================
Mod_LoadNodes
=================
*/
void Mod_LoadNodes (lump_t *l)
{
int i, j, count, p;
dnode_t *in;
mnode_t *out;
 
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
 
loadmodel->nodes = out;
loadmodel->numnodes = count;
 
for ( i=0 ; i<count ; i++, in++, out++)
{
for (j=0 ; j<3 ; j++)
{
out->minmaxs[j] = LittleShort (in->mins[j]);
out->minmaxs[3+j] = LittleShort (in->maxs[j]);
}
p = LittleLong(in->planenum);
out->plane = loadmodel->planes + p;
 
out->firstsurface = LittleShort (in->firstface);
out->numsurfaces = LittleShort (in->numfaces);
for (j=0 ; j<2 ; j++)
{
p = LittleShort (in->children[j]);
if (p >= 0)
out->children[j] = loadmodel->nodes + p;
else
out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
}
}
Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs
}
 
/*
=================
Mod_LoadLeafs
=================
*/
void Mod_LoadLeafs (lump_t *l)
{
dleaf_t *in;
mleaf_t *out;
int i, j, count, p;
 
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
 
loadmodel->leafs = out;
loadmodel->numleafs = count;
 
for ( i=0 ; i<count ; i++, in++, out++)
{
for (j=0 ; j<3 ; j++)
{
out->minmaxs[j] = LittleShort (in->mins[j]);
out->minmaxs[3+j] = LittleShort (in->maxs[j]);
}
 
p = LittleLong(in->contents);
out->contents = p;
 
out->firstmarksurface = loadmodel->marksurfaces +
LittleShort(in->firstmarksurface);
out->nummarksurfaces = LittleShort(in->nummarksurfaces);
p = LittleLong(in->visofs);
if (p == -1)
out->compressed_vis = NULL;
else
out->compressed_vis = loadmodel->visdata + p;
out->efrags = NULL;
for (j=0 ; j<4 ; j++)
out->ambient_sound_level[j] = in->ambient_level[j];
}
}
 
/*
=================
Mod_LoadClipnodes
=================
*/
void Mod_LoadClipnodes (lump_t *l)
{
dclipnode_t *in, *out;
int i, count;
hull_t *hull;
 
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
 
loadmodel->clipnodes = out;
loadmodel->numclipnodes = count;
 
hull = &loadmodel->hulls[1];
hull->clipnodes = out;
hull->firstclipnode = 0;
hull->lastclipnode = count-1;
hull->planes = loadmodel->planes;
hull->clip_mins[0] = -16;
hull->clip_mins[1] = -16;
hull->clip_mins[2] = -24;
hull->clip_maxs[0] = 16;
hull->clip_maxs[1] = 16;
hull->clip_maxs[2] = 32;
 
hull = &loadmodel->hulls[2];
hull->clipnodes = out;
hull->firstclipnode = 0;
hull->lastclipnode = count-1;
hull->planes = loadmodel->planes;
hull->clip_mins[0] = -32;
hull->clip_mins[1] = -32;
hull->clip_mins[2] = -24;
hull->clip_maxs[0] = 32;
hull->clip_maxs[1] = 32;
hull->clip_maxs[2] = 64;
 
for (i=0 ; i<count ; i++, out++, in++)
{
out->planenum = LittleLong(in->planenum);
out->children[0] = LittleShort(in->children[0]);
out->children[1] = LittleShort(in->children[1]);
}
}
 
/*
=================
Mod_MakeHull0
 
Deplicate the drawing hull structure as a clipping hull
=================
*/
void Mod_MakeHull0 (void)
{
mnode_t *in, *child;
dclipnode_t *out;
int i, j, count;
hull_t *hull;
hull = &loadmodel->hulls[0];
in = loadmodel->nodes;
count = loadmodel->numnodes;
out = Hunk_AllocName ( count*sizeof(*out), loadname);
 
hull->clipnodes = out;
hull->firstclipnode = 0;
hull->lastclipnode = count-1;
hull->planes = loadmodel->planes;
 
for (i=0 ; i<count ; i++, out++, in++)
{
out->planenum = in->plane - loadmodel->planes;
for (j=0 ; j<2 ; j++)
{
child = in->children[j];
if (child->contents < 0)
out->children[j] = child->contents;
else
out->children[j] = child - loadmodel->nodes;
}
}
}
 
/*
=================
Mod_LoadMarksurfaces
=================
*/
void Mod_LoadMarksurfaces (lump_t *l)
{
int i, j, count;
short *in;
msurface_t **out;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
 
loadmodel->marksurfaces = out;
loadmodel->nummarksurfaces = count;
 
for ( i=0 ; i<count ; i++)
{
j = LittleShort(in[i]);
if (j >= loadmodel->numsurfaces)
Sys_Error ("Mod_ParseMarksurfaces: bad surface number");
out[i] = loadmodel->surfaces + j;
}
}
 
/*
=================
Mod_LoadSurfedges
=================
*/
void Mod_LoadSurfedges (lump_t *l)
{
int i, count;
int *in, *out;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
 
loadmodel->surfedges = out;
loadmodel->numsurfedges = count;
 
for ( i=0 ; i<count ; i++)
out[i] = LittleLong (in[i]);
}
 
/*
=================
Mod_LoadPlanes
=================
*/
void Mod_LoadPlanes (lump_t *l)
{
int i, j;
mplane_t *out;
dplane_t *in;
int count;
int bits;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*2*sizeof(*out), loadname);
loadmodel->planes = out;
loadmodel->numplanes = count;
 
for ( i=0 ; i<count ; i++, in++, out++)
{
bits = 0;
for (j=0 ; j<3 ; j++)
{
out->normal[j] = LittleFloat (in->normal[j]);
if (out->normal[j] < 0)
bits |= 1<<j;
}
 
out->dist = LittleFloat (in->dist);
out->type = LittleLong (in->type);
out->signbits = bits;
}
}
 
/*
=================
RadiusFromBounds
=================
*/
float RadiusFromBounds (vec3_t mins, vec3_t maxs)
{
int i;
vec3_t corner;
 
for (i=0 ; i<3 ; i++)
{
corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
}
 
return Length (corner);
}
 
/*
=================
Mod_LoadBrushModel
=================
*/
void Mod_LoadBrushModel (model_t *mod, void *buffer)
{
int i, j;
dheader_t *header;
dmodel_t *bm;
loadmodel->type = mod_brush;
header = (dheader_t *)buffer;
 
i = LittleLong (header->version);
if (i != BSPVERSION)
Sys_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION);
 
// swap all the lumps
mod_base = (byte *)header;
 
for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
((int *)header)[i] = LittleLong ( ((int *)header)[i]);
 
// load into heap
Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]);
Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
Mod_LoadFaces (&header->lumps[LUMP_FACES]);
Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]);
Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
Mod_LoadNodes (&header->lumps[LUMP_NODES]);
Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]);
Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
 
Mod_MakeHull0 ();
mod->numframes = 2; // regular and alternate animation
mod->flags = 0;
//
// set up the submodels (FIXME: this is confusing)
//
for (i=0 ; i<mod->numsubmodels ; i++)
{
bm = &mod->submodels[i];
 
mod->hulls[0].firstclipnode = bm->headnode[0];
for (j=1 ; j<MAX_MAP_HULLS ; j++)
{
mod->hulls[j].firstclipnode = bm->headnode[j];
mod->hulls[j].lastclipnode = mod->numclipnodes-1;
}
mod->firstmodelsurface = bm->firstface;
mod->nummodelsurfaces = bm->numfaces;
VectorCopy (bm->maxs, mod->maxs);
VectorCopy (bm->mins, mod->mins);
mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
mod->numleafs = bm->visleafs;
 
if (i < mod->numsubmodels-1)
{ // duplicate the basic information
char name[10];
 
sprintf (name, "*%i", i+1);
loadmodel = Mod_FindName (name);
*loadmodel = *mod;
strcpy (loadmodel->name, name);
mod = loadmodel;
}
}
}
 
/*
==============================================================================
 
ALIAS MODELS
 
==============================================================================
*/
 
/*
=================
Mod_LoadAliasFrame
=================
*/
void * Mod_LoadAliasFrame (void * pin, int *pframeindex, int numv,
trivertx_t *pbboxmin, trivertx_t *pbboxmax, aliashdr_t *pheader, char *name)
{
trivertx_t *pframe, *pinframe;
int i, j;
daliasframe_t *pdaliasframe;
 
pdaliasframe = (daliasframe_t *)pin;
 
strcpy (name, pdaliasframe->name);
 
for (i=0 ; i<3 ; i++)
{
// these are byte values, so we don't have to worry about
// endianness
pbboxmin->v[i] = pdaliasframe->bboxmin.v[i];
pbboxmax->v[i] = pdaliasframe->bboxmax.v[i];
}
 
pinframe = (trivertx_t *)(pdaliasframe + 1);
pframe = Hunk_AllocName (numv * sizeof(*pframe), loadname);
 
*pframeindex = (byte *)pframe - (byte *)pheader;
 
for (j=0 ; j<numv ; j++)
{
int k;
 
// these are all byte values, so no need to deal with endianness
pframe[j].lightnormalindex = pinframe[j].lightnormalindex;
 
for (k=0 ; k<3 ; k++)
{
pframe[j].v[k] = pinframe[j].v[k];
}
}
 
pinframe += numv;
 
return (void *)pinframe;
}
 
 
/*
=================
Mod_LoadAliasGroup
=================
*/
void * Mod_LoadAliasGroup (void * pin, int *pframeindex, int numv,
trivertx_t *pbboxmin, trivertx_t *pbboxmax, aliashdr_t *pheader, char *name)
{
daliasgroup_t *pingroup;
maliasgroup_t *paliasgroup;
int i, numframes;
daliasinterval_t *pin_intervals;
float *poutintervals;
void *ptemp;
pingroup = (daliasgroup_t *)pin;
 
numframes = LittleLong (pingroup->numframes);
 
paliasgroup = Hunk_AllocName (sizeof (maliasgroup_t) +
(numframes - 1) * sizeof (paliasgroup->frames[0]), loadname);
 
paliasgroup->numframes = numframes;
 
for (i=0 ; i<3 ; i++)
{
// these are byte values, so we don't have to worry about endianness
pbboxmin->v[i] = pingroup->bboxmin.v[i];
pbboxmax->v[i] = pingroup->bboxmax.v[i];
}
 
*pframeindex = (byte *)paliasgroup - (byte *)pheader;
 
pin_intervals = (daliasinterval_t *)(pingroup + 1);
 
poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname);
 
paliasgroup->intervals = (byte *)poutintervals - (byte *)pheader;
 
for (i=0 ; i<numframes ; i++)
{
*poutintervals = LittleFloat (pin_intervals->interval);
if (*poutintervals <= 0.0)
Sys_Error ("Mod_LoadAliasGroup: interval<=0");
 
poutintervals++;
pin_intervals++;
}
 
ptemp = (void *)pin_intervals;
 
for (i=0 ; i<numframes ; i++)
{
ptemp = Mod_LoadAliasFrame (ptemp,
&paliasgroup->frames[i].frame,
numv,
&paliasgroup->frames[i].bboxmin,
&paliasgroup->frames[i].bboxmax,
pheader, name);
}
 
return ptemp;
}
 
 
/*
=================
Mod_LoadAliasSkin
=================
*/
void * Mod_LoadAliasSkin (void * pin, int *pskinindex, int skinsize,
aliashdr_t *pheader)
{
int i;
byte *pskin, *pinskin;
unsigned short *pusskin;
 
pskin = Hunk_AllocName (skinsize * r_pixbytes, loadname);
pinskin = (byte *)pin;
*pskinindex = (byte *)pskin - (byte *)pheader;
 
if (r_pixbytes == 1)
{
Q_memcpy (pskin, pinskin, skinsize);
}
else if (r_pixbytes == 2)
{
pusskin = (unsigned short *)pskin;
 
for (i=0 ; i<skinsize ; i++)
pusskin[i] = d_8to16table[pinskin[i]];
}
else
{
Sys_Error ("Mod_LoadAliasSkin: driver set invalid r_pixbytes: %d\n",
r_pixbytes);
}
 
pinskin += skinsize;
 
return ((void *)pinskin);
}
 
 
/*
=================
Mod_LoadAliasSkinGroup
=================
*/
void * Mod_LoadAliasSkinGroup (void * pin, int *pskinindex, int skinsize,
aliashdr_t *pheader)
{
daliasskingroup_t *pinskingroup;
maliasskingroup_t *paliasskingroup;
int i, numskins;
daliasskininterval_t *pinskinintervals;
float *poutskinintervals;
void *ptemp;
 
pinskingroup = (daliasskingroup_t *)pin;
 
numskins = LittleLong (pinskingroup->numskins);
 
paliasskingroup = Hunk_AllocName (sizeof (maliasskingroup_t) +
(numskins - 1) * sizeof (paliasskingroup->skindescs[0]),
loadname);
 
paliasskingroup->numskins = numskins;
 
*pskinindex = (byte *)paliasskingroup - (byte *)pheader;
 
pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
 
poutskinintervals = Hunk_AllocName (numskins * sizeof (float),loadname);
 
paliasskingroup->intervals = (byte *)poutskinintervals - (byte *)pheader;
 
for (i=0 ; i<numskins ; i++)
{
*poutskinintervals = LittleFloat (pinskinintervals->interval);
if (*poutskinintervals <= 0)
Sys_Error ("Mod_LoadAliasSkinGroup: interval<=0");
 
poutskinintervals++;
pinskinintervals++;
}
 
ptemp = (void *)pinskinintervals;
 
for (i=0 ; i<numskins ; i++)
{
ptemp = Mod_LoadAliasSkin (ptemp,
&paliasskingroup->skindescs[i].skin, skinsize, pheader);
}
 
return ptemp;
}
 
 
/*
=================
Mod_LoadAliasModel
=================
*/
void Mod_LoadAliasModel (model_t *mod, void *buffer)
{
int i;
mdl_t *pmodel, *pinmodel;
stvert_t *pstverts, *pinstverts;
aliashdr_t *pheader;
mtriangle_t *ptri;
dtriangle_t *pintriangles;
int version, numframes, numskins;
int size;
daliasframetype_t *pframetype;
daliasskintype_t *pskintype;
maliasskindesc_t *pskindesc;
int skinsize;
int start, end, total;
start = Hunk_LowMark ();
 
pinmodel = (mdl_t *)buffer;
 
version = LittleLong (pinmodel->version);
if (version != ALIAS_VERSION)
Sys_Error ("%s has wrong version number (%i should be %i)",
mod->name, version, ALIAS_VERSION);
 
//
// allocate space for a working header, plus all the data except the frames,
// skin and group info
//
size = sizeof (aliashdr_t) + (LittleLong (pinmodel->numframes) - 1) *
sizeof (pheader->frames[0]) +
sizeof (mdl_t) +
LittleLong (pinmodel->numverts) * sizeof (stvert_t) +
LittleLong (pinmodel->numtris) * sizeof (mtriangle_t);
 
pheader = Hunk_AllocName (size, loadname);
pmodel = (mdl_t *) ((byte *)&pheader[1] +
(LittleLong (pinmodel->numframes) - 1) *
sizeof (pheader->frames[0]));
// mod->cache.data = pheader;
mod->flags = LittleLong (pinmodel->flags);
 
//
// endian-adjust and copy the data, starting with the alias model header
//
pmodel->boundingradius = LittleFloat (pinmodel->boundingradius);
pmodel->numskins = LittleLong (pinmodel->numskins);
pmodel->skinwidth = LittleLong (pinmodel->skinwidth);
pmodel->skinheight = LittleLong (pinmodel->skinheight);
 
if (pmodel->skinheight > MAX_LBM_HEIGHT)
Sys_Error ("model %s has a skin taller than %d", mod->name,
MAX_LBM_HEIGHT);
 
pmodel->numverts = LittleLong (pinmodel->numverts);
 
if (pmodel->numverts <= 0)
Sys_Error ("model %s has no vertices", mod->name);
 
if (pmodel->numverts > MAXALIASVERTS)
Sys_Error ("model %s has too many vertices", mod->name);
 
pmodel->numtris = LittleLong (pinmodel->numtris);
 
if (pmodel->numtris <= 0)
Sys_Error ("model %s has no triangles", mod->name);
 
pmodel->numframes = LittleLong (pinmodel->numframes);
pmodel->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO;
mod->synctype = LittleLong (pinmodel->synctype);
mod->numframes = pmodel->numframes;
 
for (i=0 ; i<3 ; i++)
{
pmodel->scale[i] = LittleFloat (pinmodel->scale[i]);
pmodel->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]);
pmodel->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]);
}
 
numskins = pmodel->numskins;
numframes = pmodel->numframes;
 
if (pmodel->skinwidth & 0x03)
Sys_Error ("Mod_LoadAliasModel: skinwidth not multiple of 4");
 
pheader->model = (byte *)pmodel - (byte *)pheader;
 
//
// load the skins
//
skinsize = pmodel->skinheight * pmodel->skinwidth;
 
if (numskins < 1)
Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins);
 
pskintype = (daliasskintype_t *)&pinmodel[1];
 
pskindesc = Hunk_AllocName (numskins * sizeof (maliasskindesc_t),
loadname);
 
pheader->skindesc = (byte *)pskindesc - (byte *)pheader;
 
for (i=0 ; i<numskins ; i++)
{
aliasskintype_t skintype;
 
skintype = LittleLong (pskintype->type);
pskindesc[i].type = skintype;
 
if (skintype == ALIAS_SKIN_SINGLE)
{
pskintype = (daliasskintype_t *)
Mod_LoadAliasSkin (pskintype + 1,
&pskindesc[i].skin,
skinsize, pheader);
}
else
{
pskintype = (daliasskintype_t *)
Mod_LoadAliasSkinGroup (pskintype + 1,
&pskindesc[i].skin,
skinsize, pheader);
}
}
 
//
// set base s and t vertices
//
pstverts = (stvert_t *)&pmodel[1];
pinstverts = (stvert_t *)pskintype;
 
pheader->stverts = (byte *)pstverts - (byte *)pheader;
 
for (i=0 ; i<pmodel->numverts ; i++)
{
pstverts[i].onseam = LittleLong (pinstverts[i].onseam);
// put s and t in 16.16 format
pstverts[i].s = LittleLong (pinstverts[i].s) << 16;
pstverts[i].t = LittleLong (pinstverts[i].t) << 16;
}
 
//
// set up the triangles
//
ptri = (mtriangle_t *)&pstverts[pmodel->numverts];
pintriangles = (dtriangle_t *)&pinstverts[pmodel->numverts];
 
pheader->triangles = (byte *)ptri - (byte *)pheader;
 
for (i=0 ; i<pmodel->numtris ; i++)
{
int j;
 
ptri[i].facesfront = LittleLong (pintriangles[i].facesfront);
 
for (j=0 ; j<3 ; j++)
{
ptri[i].vertindex[j] =
LittleLong (pintriangles[i].vertindex[j]);
}
}
 
//
// load the frames
//
if (numframes < 1)
Sys_Error ("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes);
 
pframetype = (daliasframetype_t *)&pintriangles[pmodel->numtris];
 
for (i=0 ; i<numframes ; i++)
{
aliasframetype_t frametype;
 
frametype = LittleLong (pframetype->type);
pheader->frames[i].type = frametype;
 
if (frametype == ALIAS_SINGLE)
{
pframetype = (daliasframetype_t *)
Mod_LoadAliasFrame (pframetype + 1,
&pheader->frames[i].frame,
pmodel->numverts,
&pheader->frames[i].bboxmin,
&pheader->frames[i].bboxmax,
pheader, pheader->frames[i].name);
}
else
{
pframetype = (daliasframetype_t *)
Mod_LoadAliasGroup (pframetype + 1,
&pheader->frames[i].frame,
pmodel->numverts,
&pheader->frames[i].bboxmin,
&pheader->frames[i].bboxmax,
pheader, pheader->frames[i].name);
}
}
 
mod->type = mod_alias;
 
// FIXME: do this right
mod->mins[0] = mod->mins[1] = mod->mins[2] = -16;
mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16;
 
//
// move the complete, relocatable alias model to the cache
//
end = Hunk_LowMark ();
total = end - start;
Cache_Alloc (&mod->cache, total, loadname);
if (!mod->cache.data)
return;
memcpy (mod->cache.data, pheader, total);
 
Hunk_FreeToLowMark (start);
}
 
//=============================================================================
 
/*
=================
Mod_LoadSpriteFrame
=================
*/
void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe)
{
dspriteframe_t *pinframe;
mspriteframe_t *pspriteframe;
int i, width, height, size, origin[2];
unsigned short *ppixout;
byte *ppixin;
 
pinframe = (dspriteframe_t *)pin;
 
width = LittleLong (pinframe->width);
height = LittleLong (pinframe->height);
size = width * height;
 
pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t) + size*r_pixbytes,
loadname);
 
Q_memset (pspriteframe, 0, sizeof (mspriteframe_t) + size);
*ppframe = pspriteframe;
 
pspriteframe->width = width;
pspriteframe->height = height;
origin[0] = LittleLong (pinframe->origin[0]);
origin[1] = LittleLong (pinframe->origin[1]);
 
pspriteframe->up = origin[1];
pspriteframe->down = origin[1] - height;
pspriteframe->left = origin[0];
pspriteframe->right = width + origin[0];
 
if (r_pixbytes == 1)
{
Q_memcpy (&pspriteframe->pixels[0], (byte *)(pinframe + 1), size);
}
else if (r_pixbytes == 2)
{
ppixin = (byte *)(pinframe + 1);
ppixout = (unsigned short *)&pspriteframe->pixels[0];
 
for (i=0 ; i<size ; i++)
ppixout[i] = d_8to16table[ppixin[i]];
}
else
{
Sys_Error ("Mod_LoadSpriteFrame: driver set invalid r_pixbytes: %d\n",
r_pixbytes);
}
 
return (void *)((byte *)pinframe + sizeof (dspriteframe_t) + size);
}
 
 
/*
=================
Mod_LoadSpriteGroup
=================
*/
void * Mod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe)
{
dspritegroup_t *pingroup;
mspritegroup_t *pspritegroup;
int i, numframes;
dspriteinterval_t *pin_intervals;
float *poutintervals;
void *ptemp;
 
pingroup = (dspritegroup_t *)pin;
 
numframes = LittleLong (pingroup->numframes);
 
pspritegroup = Hunk_AllocName (sizeof (mspritegroup_t) +
(numframes - 1) * sizeof (pspritegroup->frames[0]), loadname);
 
pspritegroup->numframes = numframes;
 
*ppframe = (mspriteframe_t *)pspritegroup;
 
pin_intervals = (dspriteinterval_t *)(pingroup + 1);
 
poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname);
 
pspritegroup->intervals = poutintervals;
 
for (i=0 ; i<numframes ; i++)
{
*poutintervals = LittleFloat (pin_intervals->interval);
if (*poutintervals <= 0.0)
Sys_Error ("Mod_LoadSpriteGroup: interval<=0");
 
poutintervals++;
pin_intervals++;
}
 
ptemp = (void *)pin_intervals;
 
for (i=0 ; i<numframes ; i++)
{
ptemp = Mod_LoadSpriteFrame (ptemp, &pspritegroup->frames[i]);
}
 
return ptemp;
}
 
 
/*
=================
Mod_LoadSpriteModel
=================
*/
void Mod_LoadSpriteModel (model_t *mod, void *buffer)
{
int i;
int version;
dsprite_t *pin;
msprite_t *psprite;
int numframes;
int size;
dspriteframetype_t *pframetype;
pin = (dsprite_t *)buffer;
 
version = LittleLong (pin->version);
if (version != SPRITE_VERSION)
Sys_Error ("%s has wrong version number "
"(%i should be %i)", mod->name, version, SPRITE_VERSION);
 
numframes = LittleLong (pin->numframes);
 
size = sizeof (msprite_t) + (numframes - 1) * sizeof (psprite->frames);
 
psprite = Hunk_AllocName (size, loadname);
 
mod->cache.data = psprite;
 
psprite->type = LittleLong (pin->type);
psprite->maxwidth = LittleLong (pin->width);
psprite->maxheight = LittleLong (pin->height);
psprite->beamlength = LittleFloat (pin->beamlength);
mod->synctype = LittleLong (pin->synctype);
psprite->numframes = numframes;
 
mod->mins[0] = mod->mins[1] = -psprite->maxwidth/2;
mod->maxs[0] = mod->maxs[1] = psprite->maxwidth/2;
mod->mins[2] = -psprite->maxheight/2;
mod->maxs[2] = psprite->maxheight/2;
//
// load the frames
//
if (numframes < 1)
Sys_Error ("Mod_LoadSpriteModel: Invalid # of frames: %d\n", numframes);
 
mod->numframes = numframes;
mod->flags = 0;
 
pframetype = (dspriteframetype_t *)(pin + 1);
 
for (i=0 ; i<numframes ; i++)
{
spriteframetype_t frametype;
 
frametype = LittleLong (pframetype->type);
psprite->frames[i].type = frametype;
 
if (frametype == SPR_SINGLE)
{
pframetype = (dspriteframetype_t *)
Mod_LoadSpriteFrame (pframetype + 1,
&psprite->frames[i].frameptr);
}
else
{
pframetype = (dspriteframetype_t *)
Mod_LoadSpriteGroup (pframetype + 1,
&psprite->frames[i].frameptr);
}
}
 
mod->type = mod_sprite;
}
 
//=============================================================================
 
/*
================
Mod_Print
================
*/
void Mod_Print (void)
{
int i;
model_t *mod;
 
Con_Printf ("Cached models:\n");
for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++)
{
Con_Printf ("%8p : %s",mod->cache.data, mod->name);
if (mod->needload & NL_UNREFERENCED)
Con_Printf (" (!R)");
if (mod->needload & NL_NEEDS_LOADED)
Con_Printf (" (!P)");
Con_Printf ("\n");
}
}
 
 
/contrib/other/sdlquake-1.0.9/model.h
0,0 → 1,382
/*
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
 
*/
 
/*
==============================================================================
 
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 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
 
// !!! 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;
 
typedef struct msurface_s
{
int visframe; // should be drawn when node is crossed
 
int dlightframe;
int dlightbits;
 
mplane_t *plane;
int flags;
 
int firstedge; // look up in model->surfedges[], negative numbers
int numedges; // are backwards edges
// surface generation data
struct surfcache_s *cachespots[MIPLEVELS];
 
short texturemins[2];
short extents[2];
 
mtexinfo_t *texinfo;
// lighting info
byte styles[MAXLIGHTMAPS];
byte *samples; // [numstyles*surfsize]
} 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
short 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
 
short 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;
void *pcachespot; // remove?
float up, down, left, right;
byte pixels[4];
} 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
{
aliasframetype_t type;
trivertx_t bboxmin;
trivertx_t bboxmax;
int frame;
char name[16];
} maliasframedesc_t;
 
typedef struct
{
aliasskintype_t type;
void *pcachespot;
int skin;
} maliasskindesc_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;
 
typedef struct
{
int numskins;
int intervals;
maliasskindesc_t skindescs[1];
} maliasskingroup_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;
 
typedef struct {
int model;
int stverts;
int skindesc;
int triangles;
maliasframedesc_t frames[1];
} aliashdr_t;
 
//===================================================================
 
//
// 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
//
vec3_t mins, maxs;
float radius;
 
//
// 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__
/contrib/other/sdlquake-1.0.9/modelgen.h
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"
 
/contrib/other/sdlquake-1.0.9/mpdosock.h
0,0 → 1,797
/* WINSOCK.H--definitions to be used with the WINSOCK.DLL
* Copyright (c) 1993-1995, Microsoft Corp. All rights reserved.
*
* This header file corresponds to version 1.1 of the Windows Sockets specification.
*
* This file includes parts which are Copyright (c) 1982-1986 Regents
* of the University of California. All rights reserved. The
* Berkeley Software License Agreement specifies the terms and
* conditions for redistribution.
*
*/
 
#ifndef _WINSOCKAPI_
#define _WINSOCKAPI_
 
#define FAR
#define PASCAL
 
/*
* Basic system type definitions, taken from the BSD file sys/types.h.
*/
typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned int u_int;
typedef unsigned long u_long;
 
/*
* The new type to be used in all
* instances which refer to sockets.
*/
typedef u_int SOCKET;
 
// FIXME
#if 0
/*
* Select uses arrays of SOCKETs. These macros manipulate such
* arrays. FD_SETSIZE may be defined by the user before including
* this file, but the default here should be >= 64.
*
* CAVEAT IMPLEMENTOR and USER: THESE MACROS AND TYPES MUST BE
* INCLUDED IN WINSOCK.H EXACTLY AS SHOWN HERE.
*/
#ifndef FD_SETSIZE
#define FD_SETSIZE 64
#endif /* FD_SETSIZE */
 
typedef struct fd_set {
u_int fd_count; /* how many are SET? */
SOCKET fd_array[FD_SETSIZE]; /* an array of SOCKETs */
} fd_set;
 
#ifdef __cplusplus
extern "C" {
#endif
 
extern int PASCAL FAR __WSAFDIsSet(SOCKET, fd_set FAR *);
 
#ifdef __cplusplus
}
#endif
 
 
#define FD_CLR(fd, set) do { \
u_int __i; \
for (__i = 0; __i < ((fd_set FAR *)(set))->fd_count ; __i++) { \
if (((fd_set FAR *)(set))->fd_array[__i] == fd) { \
while (__i < ((fd_set FAR *)(set))->fd_count-1) { \
((fd_set FAR *)(set))->fd_array[__i] = \
((fd_set FAR *)(set))->fd_array[__i+1]; \
__i++; \
} \
((fd_set FAR *)(set))->fd_count--; \
break; \
} \
} \
} while(0)
 
#define FD_SET(fd, set) do { \
if (((fd_set FAR *)(set))->fd_count < FD_SETSIZE) \
((fd_set FAR *)(set))->fd_array[((fd_set FAR *)(set))->fd_count++]=(fd);\
} while(0)
 
#define FD_ZERO(set) (((fd_set FAR *)(set))->fd_count=0)
 
#define FD_ISSET(fd, set) __WSAFDIsSet((SOCKET)(fd), (fd_set FAR *)(set))
 
/*
* Structure used in select() call, taken from the BSD file sys/time.h.
*/
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* and microseconds */
};
 
/*
* Operations on timevals.
*
* NB: timercmp does not work for >= or <=.
*/
#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
#define timercmp(tvp, uvp, cmp) \
((tvp)->tv_sec cmp (uvp)->tv_sec || \
(tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec cmp (uvp)->tv_usec)
#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0
#endif
 
/*
* Commands for ioctlsocket(), taken from the BSD file fcntl.h.
*
*
* Ioctl's have the command encoded in the lower word,
* and the size of any in or out parameters in the upper
* word. The high 2 bits of the upper word are used
* to encode the in/out status of the parameter; for now
* we restrict parameters to at most 128 bytes.
*/
#define IOCPARM_MASK 0x7f /* parameters must be < 128 bytes */
#define IOC_VOID 0x20000000 /* no parameters */
#define IOC_OUT 0x40000000 /* copy out parameters */
#define IOC_IN 0x80000000 /* copy in parameters */
#define IOC_INOUT (IOC_IN|IOC_OUT)
/* 0x20000000 distinguishes new &
old ioctl's */
#define _IO(x,y) (IOC_VOID|((x)<<8)|(y))
 
#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y))
 
#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y))
 
#define FIONREAD _IOR('f', 127, u_long) /* get # bytes to read */
#define FIONBIO _IOW('f', 126, u_long) /* set/clear non-blocking i/o */
#define FIOASYNC _IOW('f', 125, u_long) /* set/clear async i/o */
 
/* Socket I/O Controls */
#define SIOCSHIWAT _IOW('s', 0, u_long) /* set high watermark */
#define SIOCGHIWAT _IOR('s', 1, u_long) /* get high watermark */
#define SIOCSLOWAT _IOW('s', 2, u_long) /* set low watermark */
#define SIOCGLOWAT _IOR('s', 3, u_long) /* get low watermark */
#define SIOCATMARK _IOR('s', 7, u_long) /* at oob mark? */
 
/*
* Structures returned by network data base library, taken from the
* BSD file netdb.h. All addresses are supplied in host order, and
* returned in network order (suitable for use in system calls).
*/
 
struct hostent {
char FAR * h_name; /* official name of host */
char FAR * FAR * h_aliases; /* alias list */
short h_addrtype; /* host address type */
short h_length; /* length of address */
char FAR * FAR * h_addr_list; /* list of addresses */
#define h_addr h_addr_list[0] /* address, for backward compat */
};
 
/*
* It is assumed here that a network number
* fits in 32 bits.
*/
struct netent {
char FAR * n_name; /* official name of net */
char FAR * FAR * n_aliases; /* alias list */
short n_addrtype; /* net address type */
u_long n_net; /* network # */
};
 
struct servent {
char FAR * s_name; /* official service name */
char FAR * FAR * s_aliases; /* alias list */
short s_port; /* port # */
char FAR * s_proto; /* protocol to use */
};
 
struct protoent {
char FAR * p_name; /* official protocol name */
char FAR * FAR * p_aliases; /* alias list */
short p_proto; /* protocol # */
};
 
/*
* Constants and structures defined by the internet system,
* Per RFC 790, September 1981, taken from the BSD file netinet/in.h.
*/
 
/*
* Protocols
*/
#define IPPROTO_IP 0 /* dummy for IP */
#define IPPROTO_ICMP 1 /* control message protocol */
#define IPPROTO_GGP 2 /* gateway^2 (deprecated) */
#define IPPROTO_TCP 6 /* tcp */
#define IPPROTO_PUP 12 /* pup */
#define IPPROTO_UDP 17 /* user datagram protocol */
#define IPPROTO_IDP 22 /* xns idp */
#define IPPROTO_ND 77 /* UNOFFICIAL net disk proto */
 
#define IPPROTO_RAW 255 /* raw IP packet */
#define IPPROTO_MAX 256
 
/*
* Port/socket numbers: network standard functions
*/
#define IPPORT_ECHO 7
#define IPPORT_DISCARD 9
#define IPPORT_SYSTAT 11
#define IPPORT_DAYTIME 13
#define IPPORT_NETSTAT 15
#define IPPORT_FTP 21
#define IPPORT_TELNET 23
#define IPPORT_SMTP 25
#define IPPORT_TIMESERVER 37
#define IPPORT_NAMESERVER 42
#define IPPORT_WHOIS 43
#define IPPORT_MTP 57
 
/*
* Port/socket numbers: host specific functions
*/
#define IPPORT_TFTP 69
#define IPPORT_RJE 77
#define IPPORT_FINGER 79
#define IPPORT_TTYLINK 87
#define IPPORT_SUPDUP 95
 
/*
* UNIX TCP sockets
*/
#define IPPORT_EXECSERVER 512
#define IPPORT_LOGINSERVER 513
#define IPPORT_CMDSERVER 514
#define IPPORT_EFSSERVER 520
 
/*
* UNIX UDP sockets
*/
#define IPPORT_BIFFUDP 512
#define IPPORT_WHOSERVER 513
#define IPPORT_ROUTESERVER 520
/* 520+1 also used */
 
/*
* Ports < IPPORT_RESERVED are reserved for
* privileged processes (e.g. root).
*/
#define IPPORT_RESERVED 1024
 
/*
* Link numbers
*/
#define IMPLINK_IP 155
#define IMPLINK_LOWEXPER 156
#define IMPLINK_HIGHEXPER 158
 
/*
* Internet address (old style... should be updated)
*/
struct in_addr {
union {
struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { u_short s_w1,s_w2; } S_un_w;
u_long S_addr;
} S_un;
#define s_addr S_un.S_addr
/* can be used for most tcp & ip code */
#define s_host S_un.S_un_b.s_b2
/* host on imp */
#define s_net S_un.S_un_b.s_b1
/* network */
#define s_imp S_un.S_un_w.s_w2
/* imp */
#define s_impno S_un.S_un_b.s_b4
/* imp # */
#define s_lh S_un.S_un_b.s_b3
/* logical host */
};
 
/*
* Definitions of bits in internet address integers.
* On subnets, the decomposition of addresses to host and net parts
* is done according to subnet mask, not the masks here.
*/
#define IN_CLASSA(i) (((long)(i) & 0x80000000) == 0)
#define IN_CLASSA_NET 0xff000000
#define IN_CLASSA_NSHIFT 24
#define IN_CLASSA_HOST 0x00ffffff
#define IN_CLASSA_MAX 128
 
#define IN_CLASSB(i) (((long)(i) & 0xc0000000) == 0x80000000)
#define IN_CLASSB_NET 0xffff0000
#define IN_CLASSB_NSHIFT 16
#define IN_CLASSB_HOST 0x0000ffff
#define IN_CLASSB_MAX 65536
 
#define IN_CLASSC(i) (((long)(i) & 0xe0000000) == 0xc0000000)
#define IN_CLASSC_NET 0xffffff00
#define IN_CLASSC_NSHIFT 8
#define IN_CLASSC_HOST 0x000000ff
 
#define INADDR_ANY (u_long)0x00000000
#define INADDR_LOOPBACK 0x7f000001
#define INADDR_BROADCAST (u_long)0xffffffff
#define INADDR_NONE 0xffffffff
 
/*
* Socket address, internet style.
*/
struct sockaddr_in {
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
 
#define WSADESCRIPTION_LEN 256
#define WSASYS_STATUS_LEN 128
 
 
/*
* Options for use with [gs]etsockopt at the IP level.
*/
#define IP_OPTIONS 1 /* set/get IP per-packet options */
#define IP_MULTICAST_IF 2 /* set/get IP multicast interface */
#define IP_MULTICAST_TTL 3 /* set/get IP multicast timetolive */
#define IP_MULTICAST_LOOP 4 /* set/get IP multicast loopback */
#define IP_ADD_MEMBERSHIP 5 /* add an IP group membership */
#define IP_DROP_MEMBERSHIP 6 /* drop an IP group membership */
 
#define IP_DEFAULT_MULTICAST_TTL 1 /* normally limit m'casts to 1 hop */
#define IP_DEFAULT_MULTICAST_LOOP 1 /* normally hear sends if a member */
#define IP_MAX_MEMBERSHIPS 20 /* per socket; must fit in one mbuf */
 
/*
* Argument structure for IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP.
*/
struct ip_mreq {
struct in_addr imr_multiaddr; /* IP multicast address of group */
struct in_addr imr_interface; /* local IP address of interface */
};
 
/*
* Definitions related to sockets: types, address families, options,
* taken from the BSD file sys/socket.h.
*/
 
/*
* This is used instead of -1, since the
* SOCKET type is unsigned.
*/
#define INVALID_SOCKET (SOCKET)(~0)
#define SOCKET_ERROR (-1)
 
/*
* Types
*/
#define SOCK_STREAM 1 /* stream socket */
#define SOCK_DGRAM 2 /* datagram socket */
#define SOCK_RAW 3 /* raw-protocol interface */
#define SOCK_RDM 4 /* reliably-delivered message */
#define SOCK_SEQPACKET 5 /* sequenced packet stream */
 
/*
* Option flags per-socket.
*/
#define SO_DEBUG 0x0001 /* turn on debugging info recording */
#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */
#define SO_REUSEADDR 0x0004 /* allow local address reuse */
#define SO_KEEPALIVE 0x0008 /* keep connections alive */
#define SO_DONTROUTE 0x0010 /* just use interface addresses */
#define SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */
#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */
#define SO_LINGER 0x0080 /* linger on close if data present */
#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */
 
#define SO_DONTLINGER (u_int)(~SO_LINGER)
 
/*
* Additional options.
*/
#define SO_SNDBUF 0x1001 /* send buffer size */
#define SO_RCVBUF 0x1002 /* receive buffer size */
#define SO_SNDLOWAT 0x1003 /* send low-water mark */
#define SO_RCVLOWAT 0x1004 /* receive low-water mark */
#define SO_SNDTIMEO 0x1005 /* send timeout */
#define SO_RCVTIMEO 0x1006 /* receive timeout */
#define SO_ERROR 0x1007 /* get error status and clear */
#define SO_TYPE 0x1008 /* get socket type */
 
/*
* Options for connect and disconnect data and options. Used only by
* non-TCP/IP transports such as DECNet, OSI TP4, etc.
*/
#define SO_CONNDATA 0x7000
#define SO_CONNOPT 0x7001
#define SO_DISCDATA 0x7002
#define SO_DISCOPT 0x7003
#define SO_CONNDATALEN 0x7004
#define SO_CONNOPTLEN 0x7005
#define SO_DISCDATALEN 0x7006
#define SO_DISCOPTLEN 0x7007
 
/*
* Option for opening sockets for synchronous access.
*/
#define SO_OPENTYPE 0x7008
 
#define SO_SYNCHRONOUS_ALERT 0x10
#define SO_SYNCHRONOUS_NONALERT 0x20
 
/*
* Other NT-specific options.
*/
#define SO_MAXDG 0x7009
#define SO_MAXPATHDG 0x700A
 
/*
* TCP options.
*/
#define TCP_NODELAY 0x0001
#define TCP_BSDURGENT 0x7000
 
/*
* Address families.
*/
#define AF_UNSPEC 0 /* unspecified */
#define AF_UNIX 1 /* local to host (pipes, portals) */
#define AF_INET 2 /* internetwork: UDP, TCP, etc. */
#define AF_IMPLINK 3 /* arpanet imp addresses */
#define AF_PUP 4 /* pup protocols: e.g. BSP */
#define AF_CHAOS 5 /* mit CHAOS protocols */
#define AF_IPX 6 /* IPX and SPX */
#define AF_NS 6 /* XEROX NS protocols */
#define AF_ISO 7 /* ISO protocols */
#define AF_OSI AF_ISO /* OSI is ISO */
#define AF_ECMA 8 /* european computer manufacturers */
#define AF_DATAKIT 9 /* datakit protocols */
#define AF_CCITT 10 /* CCITT protocols, X.25 etc */
#define AF_SNA 11 /* IBM SNA */
#define AF_DECnet 12 /* DECnet */
#define AF_DLI 13 /* Direct data link interface */
#define AF_LAT 14 /* LAT */
#define AF_HYLINK 15 /* NSC Hyperchannel */
#define AF_APPLETALK 16 /* AppleTalk */
#define AF_NETBIOS 17 /* NetBios-style addresses */
#define AF_VOICEVIEW 18 /* VoiceView */
 
#define AF_MAX 19
 
/*
* Structure used by kernel to store most
* addresses.
*/
struct sockaddr {
u_short sa_family; /* address family */
char sa_data[14]; /* up to 14 bytes of direct address */
};
 
/*
* Structure used by kernel to pass protocol
* information in raw sockets.
*/
struct sockproto {
u_short sp_family; /* address family */
u_short sp_protocol; /* protocol */
};
 
/*
* Protocol families, same as address families for now.
*/
#define PF_UNSPEC AF_UNSPEC
#define PF_UNIX AF_UNIX
#define PF_INET AF_INET
#define PF_IMPLINK AF_IMPLINK
#define PF_PUP AF_PUP
#define PF_CHAOS AF_CHAOS
#define PF_NS AF_NS
#define PF_IPX AF_IPX
#define PF_ISO AF_ISO
#define PF_OSI AF_OSI
#define PF_ECMA AF_ECMA
#define PF_DATAKIT AF_DATAKIT
#define PF_CCITT AF_CCITT
#define PF_SNA AF_SNA
#define PF_DECnet AF_DECnet
#define PF_DLI AF_DLI
#define PF_LAT AF_LAT
#define PF_HYLINK AF_HYLINK
#define PF_APPLETALK AF_APPLETALK
#define PF_VOICEVIEW AF_VOICEVIEW
 
#define PF_MAX AF_MAX
 
/*
* Structure used for manipulating linger option.
*/
struct linger {
u_short l_onoff; /* option on/off */
u_short l_linger; /* linger time */
};
 
/*
* Level number for (get/set)sockopt() to apply to socket itself.
*/
#define SOL_SOCKET 0xffff /* options for socket level */
 
/*
* Maximum queue length specifiable by listen.
*/
#define SOMAXCONN 5
 
#define MSG_OOB 0x1 /* process out-of-band data */
#define MSG_PEEK 0x2 /* peek at incoming message */
#define MSG_DONTROUTE 0x4 /* send without using routing tables */
 
#define MSG_MAXIOVLEN 16
 
#define MSG_PARTIAL 0x8000 /* partial send or recv for message xport */
 
/*
* Define constant based on rfc883, used by gethostbyxxxx() calls.
*/
#define MAXGETHOSTSTRUCT 1024
 
/*
* Define flags to be used with the WSAAsyncSelect() call.
*/
#define FD_READ 0x01
#define FD_WRITE 0x02
#define FD_OOB 0x04
#define FD_ACCEPT 0x08
#define FD_CONNECT 0x10
#define FD_CLOSE 0x20
 
/*
* All Windows Sockets error constants are biased by WSABASEERR from
* the "normal"
*/
#define WSABASEERR 10000
/*
* Windows Sockets definitions of regular Microsoft C error constants
*/
#define WSAEINTR (WSABASEERR+4)
#define WSAEBADF (WSABASEERR+9)
#define WSAEACCES (WSABASEERR+13)
#define WSAEFAULT (WSABASEERR+14)
#define WSAEINVAL (WSABASEERR+22)
#define WSAEMFILE (WSABASEERR+24)
 
/*
* Windows Sockets definitions of regular Berkeley error constants
*/
#define WSAEWOULDBLOCK (WSABASEERR+35)
#define WSAEINPROGRESS (WSABASEERR+36)
#define WSAEALREADY (WSABASEERR+37)
#define WSAENOTSOCK (WSABASEERR+38)
#define WSAEDESTADDRREQ (WSABASEERR+39)
#define WSAEMSGSIZE (WSABASEERR+40)
#define WSAEPROTOTYPE (WSABASEERR+41)
#define WSAENOPROTOOPT (WSABASEERR+42)
#define WSAEPROTONOSUPPORT (WSABASEERR+43)
#define WSAESOCKTNOSUPPORT (WSABASEERR+44)
#define WSAEOPNOTSUPP (WSABASEERR+45)
#define WSAEPFNOSUPPORT (WSABASEERR+46)
#define WSAEAFNOSUPPORT (WSABASEERR+47)
#define WSAEADDRINUSE (WSABASEERR+48)
#define WSAEADDRNOTAVAIL (WSABASEERR+49)
#define WSAENETDOWN (WSABASEERR+50)
#define WSAENETUNREACH (WSABASEERR+51)
#define WSAENETRESET (WSABASEERR+52)
#define WSAECONNABORTED (WSABASEERR+53)
#define WSAECONNRESET (WSABASEERR+54)
#define WSAENOBUFS (WSABASEERR+55)
#define WSAEISCONN (WSABASEERR+56)
#define WSAENOTCONN (WSABASEERR+57)
#define WSAESHUTDOWN (WSABASEERR+58)
#define WSAETOOMANYREFS (WSABASEERR+59)
#define WSAETIMEDOUT (WSABASEERR+60)
#define WSAECONNREFUSED (WSABASEERR+61)
#define WSAELOOP (WSABASEERR+62)
#define WSAENAMETOOLONG (WSABASEERR+63)
#define WSAEHOSTDOWN (WSABASEERR+64)
#define WSAEHOSTUNREACH (WSABASEERR+65)
#define WSAENOTEMPTY (WSABASEERR+66)
#define WSAEPROCLIM (WSABASEERR+67)
#define WSAEUSERS (WSABASEERR+68)
#define WSAEDQUOT (WSABASEERR+69)
#define WSAESTALE (WSABASEERR+70)
#define WSAEREMOTE (WSABASEERR+71)
 
#define WSAEDISCON (WSABASEERR+101)
 
/*
* Extended Windows Sockets error constant definitions
*/
#define WSASYSNOTREADY (WSABASEERR+91)
#define WSAVERNOTSUPPORTED (WSABASEERR+92)
#define WSANOTINITIALISED (WSABASEERR+93)
 
/*
* Error return codes from gethostbyname() and gethostbyaddr()
* (when using the resolver). Note that these errors are
* retrieved via WSAGetLastError() and must therefore follow
* the rules for avoiding clashes with error numbers from
* specific implementations or language run-time systems.
* For this reason the codes are based at WSABASEERR+1001.
* Note also that [WSA]NO_ADDRESS is defined only for
* compatibility purposes.
*/
 
#define h_errno WSAGetLastError()
 
/* Authoritative Answer: Host not found */
#define WSAHOST_NOT_FOUND (WSABASEERR+1001)
#define HOST_NOT_FOUND WSAHOST_NOT_FOUND
 
/* Non-Authoritative: Host not found, or SERVERFAIL */
#define WSATRY_AGAIN (WSABASEERR+1002)
#define TRY_AGAIN WSATRY_AGAIN
 
/* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
#define WSANO_RECOVERY (WSABASEERR+1003)
#define NO_RECOVERY WSANO_RECOVERY
 
/* Valid name, no data record of requested type */
#define WSANO_DATA (WSABASEERR+1004)
#define NO_DATA WSANO_DATA
 
/* no address, look for MX record */
#define WSANO_ADDRESS WSANO_DATA
#define NO_ADDRESS WSANO_ADDRESS
 
/*
* Windows Sockets errors redefined as regular Berkeley error constants.
* These are commented out in Windows NT to avoid conflicts with errno.h.
* Use the WSA constants instead.
*/
#if 0
#define EWOULDBLOCK WSAEWOULDBLOCK
#define EINPROGRESS WSAEINPROGRESS
#define EALREADY WSAEALREADY
#define ENOTSOCK WSAENOTSOCK
#define EDESTADDRREQ WSAEDESTADDRREQ
#define EMSGSIZE WSAEMSGSIZE
#define EPROTOTYPE WSAEPROTOTYPE
#define ENOPROTOOPT WSAENOPROTOOPT
#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
#define EOPNOTSUPP WSAEOPNOTSUPP
#define EPFNOSUPPORT WSAEPFNOSUPPORT
#define EAFNOSUPPORT WSAEAFNOSUPPORT
#define EADDRINUSE WSAEADDRINUSE
#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
#define ENETDOWN WSAENETDOWN
#define ENETUNREACH WSAENETUNREACH
#define ENETRESET WSAENETRESET
#define ECONNABORTED WSAECONNABORTED
#define ECONNRESET WSAECONNRESET
#define ENOBUFS WSAENOBUFS
#define EISCONN WSAEISCONN
#define ENOTCONN WSAENOTCONN
#define ESHUTDOWN WSAESHUTDOWN
#define ETOOMANYREFS WSAETOOMANYREFS
#define ETIMEDOUT WSAETIMEDOUT
#define ECONNREFUSED WSAECONNREFUSED
#define ELOOP WSAELOOP
#define ENAMETOOLONG WSAENAMETOOLONG
#define EHOSTDOWN WSAEHOSTDOWN
#define EHOSTUNREACH WSAEHOSTUNREACH
#define ENOTEMPTY WSAENOTEMPTY
#define EPROCLIM WSAEPROCLIM
#define EUSERS WSAEUSERS
#define EDQUOT WSAEDQUOT
#define ESTALE WSAESTALE
#define EREMOTE WSAEREMOTE
#endif
 
/* Socket function prototypes */
 
#ifdef __cplusplus
extern "C" {
#endif
 
SOCKET PASCAL FAR accept (SOCKET s, struct sockaddr FAR *addr,
int FAR *addrlen);
 
int PASCAL FAR bind (SOCKET s, const struct sockaddr FAR *addr, int namelen);
 
int PASCAL FAR closesocket (SOCKET s);
 
int PASCAL FAR connect (SOCKET s, const struct sockaddr FAR *name, int namelen);
 
int PASCAL FAR ioctlsocket (SOCKET s, long cmd, u_long FAR *argp);
 
int PASCAL FAR getpeername (SOCKET s, struct sockaddr FAR *name,
int FAR * namelen);
 
int PASCAL FAR getsockname (SOCKET s, struct sockaddr FAR *name,
int FAR * namelen);
 
int PASCAL FAR getsockopt (SOCKET s, int level, int optname,
char FAR * optval, int FAR *optlen);
 
u_long PASCAL FAR htonl (u_long hostlong);
 
u_short PASCAL FAR htons (u_short hostshort);
 
unsigned long PASCAL FAR inet_addr (const char FAR * cp);
 
char FAR * PASCAL FAR inet_ntoa (struct in_addr in);
 
int PASCAL FAR listen (SOCKET s, int backlog);
 
u_long PASCAL FAR ntohl (u_long netlong);
 
u_short PASCAL FAR ntohs (u_short netshort);
 
int PASCAL FAR recv (SOCKET s, char FAR * buf, int len, int flags);
 
int PASCAL FAR recvfrom (SOCKET s, char FAR * buf, int len, int flags,
struct sockaddr FAR *from, int FAR * fromlen);
 
#if 0
int PASCAL FAR select (int nfds, fd_set FAR *readfds, fd_set FAR *writefds,
fd_set FAR *exceptfds, const struct timeval FAR *timeout);
#endif
 
int PASCAL FAR send (SOCKET s, const char FAR * buf, int len, int flags);
 
int PASCAL FAR sendto (SOCKET s, const char FAR * buf, int len, int flags,
const struct sockaddr FAR *to, int tolen);
 
int PASCAL FAR setsockopt (SOCKET s, int level, int optname,
const char FAR * optval, int optlen);
 
int PASCAL FAR shutdown (SOCKET s, int how);
 
SOCKET PASCAL FAR socket (int af, int type, int protocol);
 
/* Database function prototypes */
 
struct hostent FAR * PASCAL FAR gethostbyaddr(const char FAR * addr,
int len, int type);
 
struct hostent FAR * PASCAL FAR gethostbyname(const char FAR * name);
 
int PASCAL FAR gethostname (char FAR * name, int namelen);
 
struct servent FAR * PASCAL FAR getservbyport(int port, const char FAR * proto);
 
struct servent FAR * PASCAL FAR getservbyname(const char FAR * name,
const char FAR * proto);
 
struct protoent FAR * PASCAL FAR getprotobynumber(int proto);
 
struct protoent FAR * PASCAL FAR getprotobyname(const char FAR * name);
 
#ifdef __cplusplus
}
#endif
 
/* Microsoft Windows Extended data types */
typedef struct sockaddr SOCKADDR;
typedef struct sockaddr *PSOCKADDR;
typedef struct sockaddr FAR *LPSOCKADDR;
 
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr_in *PSOCKADDR_IN;
typedef struct sockaddr_in FAR *LPSOCKADDR_IN;
 
typedef struct linger LINGER;
typedef struct linger *PLINGER;
typedef struct linger FAR *LPLINGER;
 
typedef struct in_addr IN_ADDR;
typedef struct in_addr *PIN_ADDR;
typedef struct in_addr FAR *LPIN_ADDR;
 
typedef struct fd_set FD_SET;
typedef struct fd_set *PFD_SET;
typedef struct fd_set FAR *LPFD_SET;
 
typedef struct hostent HOSTENT;
typedef struct hostent *PHOSTENT;
typedef struct hostent FAR *LPHOSTENT;
 
typedef struct servent SERVENT;
typedef struct servent *PSERVENT;
typedef struct servent FAR *LPSERVENT;
 
typedef struct protoent PROTOENT;
typedef struct protoent *PPROTOENT;
typedef struct protoent FAR *LPPROTOENT;
 
typedef struct timeval TIMEVAL;
typedef struct timeval *PTIMEVAL;
typedef struct timeval FAR *LPTIMEVAL;
 
#endif /* _WINSOCKAPI_ */
/contrib/other/sdlquake-1.0.9/mplib.c
0,0 → 1,222
/*
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 <dpmi.h>
 
//#include "types.h"
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
 
//#include "mgenord.h"
#define MGENVXD_REGISTER_ORD 1
#define MGENVXD_GETMEM_ORD 2
#define MGENVXD_DEREGISTER_ORD 3
#define MGENVXD_WAKEUP_ORD 4
#define MGENVXD_MAKEDQS_ORD 5
 
 
// Virtual 8086 API Ordinals
#define V86API_GETSELECTOR16_ORD (1)
#define V86API_GETSELECTOR32_ORD (2)
#define V86API_GETFLAT32_ORD (3)
#define V86API_MOVERP_ORD (6)
#define V86API_MOVEPR_ORD (7)
#define V86API_POST_ORD (8)
#define V86API_INIT_ORD (9)
#define V86API_UNINIT_ORD (10)
#define V86API_INSERTKEY_ORD (11)
#define V86API_REMOVEHOTKEY_ORD (12)
#define V86API_INSTALLHOTKEY_ORD (13)
#define V86API_HOOKINT48_ORD (14)
#define V86API_WAKEUPDLL_ORD (15)
 
#define DPMIAPI_GETFLAT32_ORD (1)
#define DPMIAPI_POST_WINDOWS_ORD (2)
// these are DPMI functions. Make sure they don't clash with the
// other MGENVXD_XXXX functions above, or the DPMI functions!
#define MGENVXD_GETQUEUECTR_ORD 6
#define MGENVXD_MOVENODE_ORD 7
#define MGENVXD_GETNODE_ORD 8
#define MGENVXD_FLUSHNODE_ORD 9
#define MGENVXD_MCOUNT_ORD 10
#define MGENVXD_MASTERNODE_ORD 11
#define MGENVXD_SANITYCHECK_ORD 12
#define MGENVXD_WAKEUPDLL_ORD 13
#define MGENVXD_WAIT_ORD 14
 
//
#define HWND_OFFSET (0)
#define UMSG_OFFSET (1)
#define SIZEREQUEST_OFFSET (2)
#define HVXD_OFFSET (3)
#define DATUM_OFFSET (4)
#define SLOT_OFFSET (5)
#define SIZEGIVEN_OFFSET (6)
#define SELECTOR32_OFFSET (7)
#define SELECTOR16_OFFSET (8)
 
//#include "magic.h"
#define MGENVXD_DEVICE_ID 0x18AA
 
//#include "rtq.h"
#define RTQ_NODE struct rtq_node
 
RTQ_NODE
{
RTQ_NODE *self; // Ring zero address of this node
RTQ_NODE *left; // Ring zero address of preceding node
RTQ_NODE *right; // Ring zero address of succeding node
BYTE * rtqDatum; // Ring 3 Datum of Buffer (start of preface)
BYTE * rtqInsert; // Ring 3 insertion position
WORD rtqLen; // Length of buffer, excluding preface
WORD rtqUpCtr; // Up Counter of bytes used so far
WORD rtqQCtr; // number of nodes attached
WORD padding; // DWORD alignment
};
 
#define RTQ_PARAM_MOVENODE struct rtq_param_movenode
RTQ_PARAM_MOVENODE
{
WORD rtqFromDQ;
WORD rtqToDQ;
};
 
RTQ_NODE* rtq_fetch(RTQ_NODE*, RTQ_NODE*); // To, From
 
int _int86(int vector, __dpmi_regs *iregs, __dpmi_regs *oregs);
 
#define CHUNNEL_INT 0x48
 
#define int386 _int86
#define REGISTERS __dpmi_regs
 
void
Yield(void)
{
__dpmi_yield();
}
 
void
PostWindowsMessage(void)
{
REGISTERS regs;
 
regs.d.eax = DPMIAPI_POST_WINDOWS_ORD << 16 | MGENVXD_DEVICE_ID;
regs.d.ebx = 0;
regs.d.ecx = 0;
int386(CHUNNEL_INT, &regs, &regs);
}
 
int
MGenWait(void)
{
REGISTERS regs;
 
regs.d.eax = MGENVXD_WAIT_ORD << 16 | MGENVXD_DEVICE_ID;
int386(CHUNNEL_INT, &regs, &regs);
return regs.d.eax;
}
 
int MGenGetQueueCtr(int qNo)
{
REGISTERS regs;
 
regs.d.eax = MGENVXD_GETQUEUECTR_ORD << 16 | MGENVXD_DEVICE_ID;
regs.d.ebx = qNo;
int386(CHUNNEL_INT, &regs, &regs);
 
return regs.d.eax;
}
 
RTQ_NODE *MGenMoveTo(int qFrom, int qTo)
{
REGISTERS regs;
 
regs.d.eax = MGENVXD_MOVENODE_ORD << 16 | MGENVXD_DEVICE_ID;
regs.d.ebx = qFrom;
regs.d.ecx = qTo;
int386(CHUNNEL_INT, &regs, &regs);
 
return (RTQ_NODE *) regs.d.eax;
}
 
RTQ_NODE *MGenGetNode(int q)
{
REGISTERS regs;
 
regs.d.eax = MGENVXD_GETNODE_ORD << 16 | MGENVXD_DEVICE_ID;
regs.d.ebx = q;
int386(CHUNNEL_INT, &regs, &regs);
 
return (RTQ_NODE *) regs.d.eax;
}
 
RTQ_NODE *MGenGetMasterNode(unsigned *size)
{
REGISTERS regs;
 
regs.d.eax = MGENVXD_MASTERNODE_ORD << 16 | MGENVXD_DEVICE_ID;
int386(CHUNNEL_INT, &regs, &regs);
*size = regs.d.ecx;
 
return (RTQ_NODE *) regs.d.eax;
}
 
RTQ_NODE *MGenFlushNodes(int qFrom, int qTo)
{
REGISTERS regs;
 
regs.d.eax = MGENVXD_FLUSHNODE_ORD << 16 | MGENVXD_DEVICE_ID;
regs.d.ebx = qFrom;
regs.d.ecx = qTo;
int386(CHUNNEL_INT, &regs, &regs);
 
return (RTQ_NODE *) regs.d.eax;
}
 
int MGenMCount(unsigned lowerOrderBits, unsigned upperOrderBits)
{
REGISTERS regs;
 
regs.d.eax = MGENVXD_MCOUNT_ORD << 16 | MGENVXD_DEVICE_ID;
regs.d.ebx = lowerOrderBits;
regs.d.ecx = upperOrderBits;
int386(CHUNNEL_INT, &regs, &regs);
 
return regs.d.eax;
}
 
int MGenSanityCheck(void)
{
REGISTERS regs;
 
regs.d.eax = MGENVXD_SANITYCHECK_ORD << 16 | MGENVXD_DEVICE_ID;
int386(CHUNNEL_INT, &regs, &regs);
 
return regs.d.eax;
}
 
void MGenWakeupDll(void)
{
REGISTERS regs;
 
regs.d.eax = MGENVXD_WAKEUPDLL_ORD << 16 | MGENVXD_DEVICE_ID;
int386(CHUNNEL_INT, &regs, &regs);
}
/contrib/other/sdlquake-1.0.9/mplpc.c
0,0 → 1,1001
/*
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 <go32.h>
#include "mpdosock.h"
 
//#include "types.h"
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
 
//#include "lpc.h"
typedef struct {
short version; // version of LPC requested
short sizeOfArgs; // size of arguments
short service; // service # requested
char Data[1]; // data
} LPCData;
 
typedef struct {
short version; // LPC version
short sizeOfReturn; // return data size
short error; // any error codes
short noRet; // number of returns
char Data[1]; // data
} LPCReturn;
 
//#include "services.h"
#define MAXSOCKETS 20
 
// services
#define LPC_SOCKBIND 4
#define LPC_SOCKGETHOSTBYNAME 5
#define LPC_SOCKGETHOSTNAME 6
#define LPC_SOCKGETHOSTBYADDR 7
#define LPC_SOCKCLOSE 8
#define LPC_SOCKSOCKET 9
#define LPC_SOCKRECVFROM 10
#define LPC_SOCKSENDTO 11
#define LPC_SOCKIOCTL 12
#define LPC_SOCKGETSOCKNAME 13
#define LPC_SOCKFLUSH 14
#define LPC_SOCKSETOPT 15
#define LPC_SOCKGETLASTERROR 16
#define LPC_SOCKINETADDR 17
 
// htons, ntohs, htonl, ntohl implemented locally
 
// errors
#define LPC_UNRECOGNIZED_SERVICE -1
#define LPC_NOERROR 0
 
// structures for support
typedef struct {
SOCKET s;
int namelen;
char name[1];
} BindArgs;
 
typedef struct {
SOCKET s;
long cmd;
char data[1];
} IoctlArgs;
 
typedef struct {
int retVal;
int namelen;
char name[1];
} GetSockNameRet;
 
typedef GetSockNameRet GetHostNameRet;
 
typedef struct {
int retVal;
int h_addr_0; // that's the only important value
} GetHostByNameRet;
 
typedef struct {
int len;
int type;
char addr[1];
} GetHostByAddrArgs;
 
typedef struct {
int retVal;
char h_name[1]; // h_name is the only important value
} GetHostByAddrRet;
 
typedef struct {
SOCKET s;
int flags;
} RecvFromArgs;
 
typedef struct {
int retVal;
int errCode;
int len; // message len
struct sockaddr sockaddr;
int sockaddrlen;
char Data[1];
} RecvFromRet;
 
typedef struct {
SOCKET s;
int flags;
int len;
struct sockaddr sockaddr;
int sockaddrlen;
char Data[1];
} SendToArgs;
 
typedef struct {
int retVal;
int errCode;
} SendToRet;
 
typedef struct {
int bufflen;
SOCKET s;
int len;
int sockaddrlen;
struct sockaddr address;
char data[1];
} SocketChannelData;
 
typedef struct {
int af;
int type;
int protocol;
} SocketArgs;
 
typedef struct {
SOCKET s;
int len;
int flags;
int addrlen;
struct sockaddr addr;
char data[1];
} WinSockData;
 
typedef struct {
SOCKET s;
int level;
int optname;
int optlen;
char optval[1];
} SetSockOptArgs;
 
typedef struct {
SOCKET sock[MAXSOCKETS];
} SocketMap;
 
//#include "rtq.h"
#define RTQ_NODE struct rtq_node
 
RTQ_NODE
{
RTQ_NODE *self; // Ring zero address of this node
RTQ_NODE *left; // Ring zero address of preceding node
RTQ_NODE *right; // Ring zero address of succeding node
BYTE * rtqDatum; // Ring 3 Datum of Buffer (start of preface)
BYTE * rtqInsert; // Ring 3 insertion position
WORD rtqLen; // Length of buffer, excluding preface
WORD rtqUpCtr; // Up Counter of bytes used so far
WORD rtqQCtr; // number of nodes attached
WORD padding; // DWORD alignment
};
 
#define RTQ_PARAM_MOVENODE struct rtq_param_movenode
RTQ_PARAM_MOVENODE
{
WORD rtqFromDQ;
WORD rtqToDQ;
};
 
RTQ_NODE* rtq_fetch(RTQ_NODE*, RTQ_NODE*); // To, From
 
//#include "mplib.h"
// give up time slice
void Yield(void);
void MGenWakeupDll(void);
 
// post a message to win32 side
void PostWindowsMessage(void);
 
// get # of items on qNo
int MGenGetQueueCtr(int qNo);
 
// move first node from qFrom to qTo
RTQ_NODE *MGenMoveTo(int qFrom, int qTo);
 
// get first node from q
RTQ_NODE *MGenGetNode(int q);
 
// get master node, returning size of RTQ_NODE for size verification
RTQ_NODE *MGenGetMasterNode(unsigned *size);
 
// move all nodes from qFrom to qTo
RTQ_NODE *MGenFlushNodes(int qFrom, int qTo);
 
// count number of nodes in queues designated by bitmask
// lowerOrderBits == 0..31, upperOrderBits == 32-63
int MGenMCount(unsigned lowerOrderBits, unsigned upperOrderBits);
 
// perform consistency check on chunnel address space
int MGenSanityCheck(void);
 
#include <stdio.h>
#include <sys/farptr.h>
 
extern short flat_selector;
 
#define SOCKET_MAP_QUEUE 41
 
#define IDLE_QUEUE 44
#define REC_QUEUE 45
#define SEND_QUEUE 46
 
// queue sizes
#define FREEQBASE 58
#define FREEQ64 58
#define FREEQ128 59
#define FREEQ256 60
#define FREEQ512 61
#define FREEQ1024 62
#define FREEQ2048 63
 
#define NFREEQ 6
 
#define QLIMIT 10
 
#define PRIVATEQ 50
 
#define FARPKL(x) (_farnspeekl((unsigned long) x))
#define FARPKB(x) (_farnspeekb((unsigned long) x))
#define FARPKS(x) (_farnspeekw((unsigned long) x))
 
#define FARPOKL(x, y) (_farnspokel((unsigned long) x, (unsigned long) y))
#define FARPOKB(x, y) (_farnspokeb((unsigned long) x, (unsigned char) y))
 
int Qsizes[] = { 64, 128, 256, 512, 1024, 2048 };
 
int SocketError = 0;
 
SocketMap *SockMap;
 
#define HOSTENT_ALIAS_LIMIT 5
#define HOSTENT_STRLEN_LIMIT 50
#define HOSTENT_ADDR_LIST_LIMIT 5
 
struct hostent HostEnt;
 
char HostEnt_hname[HOSTENT_STRLEN_LIMIT];
char *HostEnt_h_aliases[HOSTENT_ALIAS_LIMIT];
char HostEnt_names[HOSTENT_ALIAS_LIMIT][HOSTENT_STRLEN_LIMIT];
struct in_addr* HostEnt_addr_list[HOSTENT_ADDR_LIST_LIMIT];
struct in_addr HostEnt_addrs[HOSTENT_ADDR_LIST_LIMIT];
 
void
fmemcpyto(void *to, const void *from, int length)
{
movedata(_my_ds(), (unsigned)from, flat_selector, (unsigned)to, length);
}
 
void
fmemcpyfrom(void *to, const void *from, int length)
{
movedata(flat_selector, (unsigned)from, _my_ds(), (unsigned)to, length);
}
 
void
fstrcpyto(char *to, const char *from)
{
while (*from) {
FARPOKB(to, *from);
to++; from++;
}
FARPOKB(to, 0);
}
 
void
fstrncpyto(char *to, const char *from, int len)
{
while (*from && len) {
FARPOKB(to, *from);
to++; from++; len--;
}
FARPOKB(to, 0);
}
 
void
fstrcpyfrom(char *to, const char *from)
{
while (FARPKB(from)) {
*to = FARPKB(from);
from++; to++;
}
*to = 0;
}
 
void
fstrncpyfrom(char *to, const char *from, int len)
{
while (FARPKB(from) && len) {
*to = FARPKB(from);
from++; to++; len--;
}
*to = 0;
}
 
void
GetSocketMap(void)
{
RTQ_NODE *n = MGenGetNode(SOCKET_MAP_QUEUE);
 
SockMap = (SocketMap *) FARPKL(&n->rtqDatum);
}
 
void *
GetFreeBufferToQueue(int q, int bufSize)
{
int i;
 
for (i = 0; i < NFREEQ; i++) {
if (Qsizes[i] >= bufSize && MGenGetQueueCtr(i+FREEQBASE)) {
RTQ_NODE *n = MGenMoveTo(i+FREEQBASE, q);
if (!n)
continue;
FARPOKL(&n->rtqUpCtr, bufSize);
return (void *) FARPKL(&n->rtqDatum);
}
}
 
return 0;
}
 
void
FreeBufferFromQueue(int q)
{
int i;
RTQ_NODE *n = MGenGetNode(q);
 
for (i = 0; i < NFREEQ; i++) {
if (Qsizes[i] == FARPKS(&n->rtqLen)) {
MGenMoveTo(q, i+FREEQBASE);
return;
}
}
}
 
void
SetLPCData(LPCData *lpc)
{
 
FARPOKL(&(lpc->version), 1);
FARPOKL(&(lpc->sizeOfArgs), 0);
FARPOKL(&(lpc->service), 0);
}
 
int
bind(SOCKET s, const struct sockaddr *name, int namelen)
{
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
LPCData *p;
LPCReturn *r;
BindArgs *bargs;
int retVal;
 
_farsetsel(flat_selector);
SocketError = 0;
p = (LPCData *) FARPKL(&n->rtqDatum);
SetLPCData(p);
FARPOKL(&p->service, LPC_SOCKBIND);
bargs = (BindArgs *) p->Data;
FARPOKL(&bargs->s, s);
FARPOKL(&bargs->namelen, namelen);
fmemcpyto(bargs->name, name, namelen);
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
PostWindowsMessage();
 
while ((n = MGenGetNode(REC_QUEUE)) == 0)
Yield();
 
r = (LPCReturn *) FARPKL(&n->rtqDatum);
 
if (FARPKS(&r->error) != LPC_NOERROR) {
return -1;
}
 
retVal = FARPKL(r->Data);
 
// get ready for next call
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
 
return retVal;
}
 
int
closesocket(SOCKET s)
{
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
LPCData *p;
LPCReturn *r;
int retVal;
 
_farsetsel(flat_selector);
SocketError = 0;
p = (LPCData *) FARPKL(&n->rtqDatum);
SetLPCData(p);
FARPOKL(&p->service, LPC_SOCKCLOSE);
FARPOKL(p->Data, s);
 
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
PostWindowsMessage();
 
while ((n = MGenGetNode(REC_QUEUE)) == 0)
Yield();
 
r = (LPCReturn *) FARPKL(&n->rtqDatum);
 
if (FARPKS(&r->error) != LPC_NOERROR) {
return -1;
}
 
retVal = FARPKL(r->Data);
 
// get ready for next call
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
 
return retVal;
}
 
void
ZapHostEnt()
{
// do nothing
}
 
void
ReconstructHostEnt(struct hostent *s, void *flattened)
{
struct hostent *old = (struct hostent *) flattened;
int i;
char **ptr;
 
 
s->h_name = HostEnt_hname;
fstrncpyfrom(s->h_name, (char *) FARPKL(&old->h_name), HOSTENT_STRLEN_LIMIT-1);
s->h_name[HOSTENT_STRLEN_LIMIT-1] = 0;
 
s->h_aliases = HostEnt_h_aliases;
ptr = (char **) FARPKL(&old->h_aliases);
for (i = 0; i < (HOSTENT_ALIAS_LIMIT-1) && FARPKL(ptr); i++, ptr++) {
s->h_aliases[i] = HostEnt_names[i];
// fstrncpyfrom(s->h_aliases[i], (void *) FARPKL(ptr), HOSTENT_STRLEN_LIMIT-1);
s->h_aliases[i][HOSTENT_STRLEN_LIMIT-1] = 0;
}
s->h_aliases[i] = 0;
 
s->h_addrtype = FARPKS(&old->h_addrtype);
s->h_length = FARPKS(&old->h_length);
 
if (FARPKS(&old->h_length) != sizeof(struct in_addr)) {
printf("Error!\n");
exit(0);
}
 
s->h_addr_list = (char **) HostEnt_addr_list;
ptr = (char **) FARPKL(&old->h_addr_list);
for (i = 0; i < (HOSTENT_ADDR_LIST_LIMIT - 1) && FARPKL(ptr); i++, ptr++) {
s->h_addr_list[i] = (char *) &(HostEnt_addrs[i]);
fmemcpyfrom(s->h_addr_list[i], (void *) FARPKL(ptr), s->h_length);
}
s->h_addr_list[i] = 0;
}
 
 
int
getsockname(SOCKET s, struct sockaddr *name, int *namelen)
{
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
LPCData *p;
LPCReturn *r;
GetSockNameRet *ret;
int retVal;
 
SocketError = 0;
_farsetsel(flat_selector);
p = (LPCData *) FARPKL(&n->rtqDatum);
SetLPCData(p);
FARPOKL(&p->service, LPC_SOCKGETSOCKNAME);
FARPOKL(p->Data, s);
 
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
PostWindowsMessage();
 
while ((n = MGenGetNode(REC_QUEUE)) == 0)
Yield();
 
 
r = (LPCReturn *) FARPKL(&n->rtqDatum);
 
if (FARPKS(&r->error) != LPC_NOERROR) {
return -1;
}
 
ret = (GetSockNameRet *) r->Data;
retVal = FARPKL(&ret->retVal);
fmemcpyfrom(name, ret->name, FARPKL(&ret->namelen));
*namelen = FARPKL(&ret->namelen);
 
// get ready for next call
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
 
return retVal;
}
 
int
gethostname(char *name, int namelen)
{
RTQ_NODE *n;
LPCData *p;
LPCReturn *r;
GetHostNameRet *ret;
int retVal;
char *s;
 
_farsetsel(flat_selector);
SocketError = 0;
n = (RTQ_NODE *) MGenGetNode(IDLE_QUEUE);
p = (LPCData *) FARPKL(&n->rtqDatum);
SetLPCData(p);
FARPOKL(&p->service,LPC_SOCKGETHOSTNAME);
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
PostWindowsMessage();
 
while ((n = (RTQ_NODE *) (MGenGetNode(REC_QUEUE))) == 0)
Yield();
 
r = (LPCReturn *) FARPKL(&n->rtqDatum);
 
if (FARPKS(&r->error) != LPC_NOERROR) {
return -1;
}
 
ret = (GetHostNameRet *) r->Data;
 
retVal = FARPKL(&ret->retVal);
 
s = ret->name;
 
fstrncpyfrom(name, s, namelen);
 
#if 0
len = strlen(ret->name);
 
if (len > namelen)
memcpy(name, ret->name, ret->namelen);
else
strcpy(name, ret->name);
#endif
 
// get ready for next call
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
 
return retVal;
}
 
struct hostent *
gethostbyname(const char *name)
{
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
LPCData *p;
LPCReturn *r;
struct hostent *retVal;
 
_farsetsel(flat_selector);
SocketError = 0;
p = (LPCData *) FARPKL(&n->rtqDatum);
SetLPCData(p);
FARPOKL(&p->service, LPC_SOCKGETHOSTBYNAME);
fstrcpyto(p->Data, name);
 
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
PostWindowsMessage();
 
while ((n = MGenGetNode(REC_QUEUE)) == 0)
Yield();
 
r = (LPCReturn *) FARPKL(&n->rtqDatum);
retVal = (struct hostent *) r->Data;
 
if (FARPKL(&retVal->h_name) == 0) {
retVal = 0;
} else {
ZapHostEnt();
ReconstructHostEnt(&HostEnt, (void *) retVal);
retVal = &HostEnt;
}
 
// get ready for next call
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
 
return retVal;
}
 
struct hostent *
gethostbyaddr(const char *addr, int len, int type)
{
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
LPCData *p;
LPCReturn *r;
GetHostByAddrArgs *args;
struct hostent *retVal;
 
SocketError = 0;
_farsetsel(flat_selector);
p = (LPCData *) FARPKL(&n->rtqDatum);
SetLPCData(p);
FARPOKL(&p->service, LPC_SOCKGETHOSTBYADDR);
args = (GetHostByAddrArgs *) p->Data;
FARPOKL(&args->len, len);
FARPOKL(&args->type, type);
fmemcpyto(args->addr, addr, len);
 
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
PostWindowsMessage();
 
while ((n = MGenGetNode(REC_QUEUE)) == 0)
Yield();
r = (LPCReturn *) FARPKL(&n->rtqDatum);
retVal = (struct hostent *) r->Data;
 
if (FARPKL(&retVal->h_name) == 0) {
retVal = 0;
} else {
ZapHostEnt();
 
ReconstructHostEnt(&HostEnt, (void *) retVal);
retVal = &HostEnt;
}
 
// get ready for next call
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
 
return retVal;
}
 
 
SOCKET
socket(int af, int type, int protocol)
{
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
LPCData *p;
LPCReturn *r;
SocketArgs *args;
int retVal;
 
_farsetsel(flat_selector);
SocketError = 0;
p = (LPCData *) FARPKL(&n->rtqDatum);
SetLPCData(p);
FARPOKL(&p->service, LPC_SOCKSOCKET);
args = (SocketArgs *) p->Data;
FARPOKL(&args->af, af);
FARPOKL(&args->type, type);
FARPOKL(&args->protocol, protocol);
 
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
PostWindowsMessage();
 
while ((n = MGenGetNode(REC_QUEUE)) == 0)
Yield();
 
r = (LPCReturn *) FARPKL(&n->rtqDatum);
 
 
if (FARPKS(&r->error) != LPC_NOERROR) {
return -1;
}
 
retVal = FARPKL(r->Data);
 
// get ready for next call
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
 
return retVal;
}
 
void
sockets_flush(void)
{
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
LPCData *p;
 
SocketError = 0;
p = (LPCData *) FARPKL(&n->rtqDatum);
SetLPCData(p);
FARPOKL(&p->service, LPC_SOCKFLUSH);
 
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
PostWindowsMessage();
 
while ((n = MGenGetNode(REC_QUEUE)) == 0)
Yield();
 
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
}
 
int
recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from,
int *fromlen)
{
int i;
RTQ_NODE *n;
WinSockData *data;
int bytesRead;
 
SocketError = 0;
_farsetsel(flat_selector);
if (!SockMap)
GetSocketMap();
 
for (i = 0; i < MAXSOCKETS; i++) {
if (FARPKL(&(SockMap->sock[i])) == s)
break;
}
 
if (i == MAXSOCKETS)
return SOCKET_ERROR;
 
// pick up node
n = MGenGetNode(i);
if (n == 0) {
SocketError = WSAEWOULDBLOCK;
return -1;
}
 
data = (WinSockData *) FARPKL(&n->rtqDatum);
bytesRead = FARPKL(&data->len);
 
if (from) {
fmemcpyfrom(from, &data->addr, sizeof(struct sockaddr));
}
 
if (fromlen) {
*fromlen = FARPKL(&data->addrlen);
}
 
fmemcpyfrom(buf, data->data, len > bytesRead ? bytesRead : len);
 
if ((flags & MSG_PEEK) == 0) {
FreeBufferFromQueue(i);
}
 
return bytesRead;
}
 
int
sendto(SOCKET s, const char *buf, int len, int flags, const struct sockaddr *to, int tolen)
{
int i;
int outQ;
WinSockData *data;
 
SocketError = 0;
_farsetsel(flat_selector);
if (!SockMap)
GetSocketMap();
 
for (i = 0; i < MAXSOCKETS; i++) {
if (FARPKL(&SockMap->sock[i]) == s) {
break;
}
}
 
if (i == MAXSOCKETS) {
SocketError = WSAENOTSOCK;
return SOCKET_ERROR;
}
 
outQ = i + MAXSOCKETS;
 
if (MGenGetQueueCtr(outQ) >= QLIMIT) {
SocketError = WSAEWOULDBLOCK;
return SOCKET_ERROR;
}
 
data = GetFreeBufferToQueue(PRIVATEQ, len + sizeof(WinSockData));
 
if (!data) {
SocketError = WSAEWOULDBLOCK;
return SOCKET_ERROR;
}
 
FARPOKL(&data->s, s);
FARPOKL(&data->len, len);
if (to) {
fmemcpyto(&data->addr, to, tolen);
FARPOKL(&data->addrlen, tolen);
} else {
FARPOKL(&data->addrlen, 0);
}
 
FARPOKL(&data->flags, flags);
 
fmemcpyto(data->data, buf, len);
 
MGenMoveTo(PRIVATEQ, outQ);
 
return len;
}
 
int
ioctlsocket(SOCKET s, long cmd, unsigned long *argp)
{
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
LPCData *p;
LPCReturn *r;
IoctlArgs *args;
int retVal;
 
SocketError = 0;
_farsetsel(flat_selector);
p = (LPCData *) FARPKL(&n->rtqDatum);
SetLPCData(p);
FARPOKL(&p->service, LPC_SOCKIOCTL);
args = (IoctlArgs *) p->Data;
FARPOKL(&args->s, s);
FARPOKL(&args->cmd, cmd);
 
switch(cmd) {
case FIONBIO:
FARPOKL(args->data, *argp);
break;
default:
return SOCKET_ERROR;
}
 
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
PostWindowsMessage();
 
while ((n = MGenGetNode(REC_QUEUE)) == 0)
Yield();
 
r = (LPCReturn *) FARPKL(&n->rtqDatum);
 
 
retVal = FARPKL(r->Data);
 
// get ready for next call
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
 
return retVal;
}
 
int
setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen)
{
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
LPCData *p;
LPCReturn *r;
SetSockOptArgs *args;
int retVal;
 
SocketError = 0;
_farsetsel(flat_selector);
p = (LPCData *) FARPKL(&n->rtqDatum);
SetLPCData(p);
FARPOKL(&p->service, LPC_SOCKSETOPT);
args = (SetSockOptArgs *) p->Data;
FARPOKL(&args->s, s);
FARPOKL(&args->level, level);
FARPOKL(&args->optname, optname);
FARPOKL(&args->optlen, optlen);
fmemcpyto(args->optval, optval, optlen);
 
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
PostWindowsMessage();
 
while ((n = MGenGetNode(REC_QUEUE)) == 0)
Yield();
 
r = (LPCReturn *) FARPKL(&n->rtqDatum);
 
retVal = FARPKL(r->Data);
 
// get ready for next call
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
 
return retVal;
}
 
int
WSAGetLastError(void)
{
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
LPCData *p;
LPCReturn *r;
int retVal;
 
 
_farsetsel(flat_selector);
if (SocketError) {
int err = SocketError;
 
SocketError = 0;
return err;
}
 
p = (LPCData *) FARPKL(&n->rtqDatum);
SetLPCData(p);
FARPOKL(&p->service, LPC_SOCKGETLASTERROR);
 
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
PostWindowsMessage();
 
while ((n = MGenGetNode(REC_QUEUE)) == 0)
Yield();
 
r = (LPCReturn *) FARPKL(&n->rtqDatum);
 
 
retVal = FARPKL(r->Data);
 
// get ready for next call
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
 
return retVal;
}
 
unsigned long inet_addr(const char *cp)
{
int ret;
unsigned int ha1, ha2, ha3, ha4;
unsigned long ipaddr;
 
ret = sscanf(cp, "%d.%d.%d.%d", &ha1, &ha2, &ha3, &ha4);
if (ret != 4)
return -1;
ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
return ipaddr;
#if 0
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
LPCData *p;
LPCReturn *r;
int retVal;
 
SocketError = 0;
_farsetsel(flat_selector);
p = (LPCData *) FARPKL(&n->rtqDatum);
SetLPCData(p);
FARPOKL(&p->service, LPC_SOCKINETADDR);
 
fstrcpyto(p->Data, cp);
 
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
PostWindowsMessage();
 
while ((n = MGenGetNode(REC_QUEUE)) == 0)
Yield();
 
r = (LPCReturn *) FARPKL(&n->rtqDatum);
 
if (FARPKS(&r->error) != LPC_NOERROR) {
return -1;
}
 
retVal = FARPKL(r->Data);
 
// get ready for next call
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
 
return retVal;
#endif
}
 
char *inet_ntoa (struct in_addr in)
{
static char buf [32];
 
sprintf(buf, "%u.%u.%u.%u", in.S_un.S_un_b.s_b1, in.S_un.S_un_b.s_b2, in.S_un.S_un_b.s_b3, in.S_un.S_un_b.s_b4);
return buf;
}
/contrib/other/sdlquake-1.0.9/net.h
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);
/contrib/other/sdlquake-1.0.9/net_bsd.c
0,0 → 1,93
/*
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"
 
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_udp.h"
 
net_landriver_t net_landrivers[MAX_NET_DRIVERS] =
{
{
"UDP",
false,
0,
UDP_Init,
UDP_Shutdown,
UDP_Listen,
UDP_OpenSocket,
UDP_CloseSocket,
UDP_Connect,
UDP_CheckNewConnections,
UDP_Read,
UDP_Write,
UDP_Broadcast,
UDP_AddrToString,
UDP_StringToAddr,
UDP_GetSocketAddr,
UDP_GetNameFromAddr,
UDP_GetAddrFromName,
UDP_AddrCompare,
UDP_GetSocketPort,
UDP_SetSocketPort
}
};
 
int net_numlandrivers = 1;
/contrib/other/sdlquake-1.0.9/net_bw.c
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.
 
*/
// net_bw.c
 
#include <stdio.h>
#include <stdlib.h>
#include <dpmi.h>
 
#include "quakedef.h"
#include "dosisms.h"
 
 
// this section is general Unix stuff that we need
 
#define EIO 5 /* I/O error */
#define EBADS 9
#define EWOULDBLOCK 35 /* function would block */
#define EMSGSIZE 40 /* message to big for buffers */
#define EPROTONOSUPPORT 43 /* Protocol not supported */
#define ESOCKTNOSUPPORT 44 /* Socket type not supported */
#define EPFNOSUPPORT 46 /* Protocol family not supported */
#define EAFNOSUPPORT 47 /* Address family not supported */
#define ECONNABORTED 53 /* User requested hangup */
#define ENOBUFS 55 /* No buffers available */
#define EISCONN 56 /* Socket has closed */
#define ENOTCONN 57 /* Socket is not connected */
#define ESHUTDOWN 58 /* Socket is closed */
#define ETOOMANYREFS 59 /* Too many sockets open */
#define ETIMEDOUT 60 /* Connection timed out */
#define ECONNREFUSED 61 /* Connection refused */
 
#define AF_INET 2 /* internet */
 
#define PF_INET AF_INET
 
#define SOCK_STREAM 1 /* stream */
#define SOCK_DGRAM 2 /* datagram */
 
#define IPPROTO_TCP 6
#define IPPROTO_UDP 17
 
#define INADDR_ANY 0
 
#define SIOCDONE 0x7300
#define FIONREAD 0x667f
#define FIONBIO 0x667e
#define FIONWIN 0x1000
#define FIONTIN 0x2000
 
#define BRDINIT 0
#define BRDADDR 10
 
#define MAXHOSTNAMELEN 256
 
#define SOL_SOCKET 0xffff /* options for socket level */
 
/*
* Option flags per-socket.
*/
#define SO_DEBUG 0x0001 /* turn on debugging info recording */
#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */
#define SO_REUSEADDR 0x0004 /* allow local address reuse */
#define SO_KEEPALIVE 0x0008 /* keep connections alive */
#define SO_DONTROUTE 0x0010 /* just use interface addresses */
#define SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */
#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */
#define SO_LINGER 0x0080 /* linger on close if data present */
#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */
#define SO_USEPRIV 0x4000 /* allocate from privileged port area */
#define SO_CANTSIG 0x8000 /* prevent SIGPIPE on SS_CANTSENDMORE */
 
/*
* Additional options, not kept in so_options.
*/
#define SO_SNDBUF 0x1001 /* send buffer size */
#define SO_RCVBUF 0x1002 /* receive buffer size */
#define SO_SNDLOWAT 0x1003 /* send low-water mark */
#define SO_RCVLOWAT 0x1004 /* receive low-water mark */
#define SO_SNDTIMEO 0x1005 /* send timeout */
#define SO_RCVTIMEO 0x1006 /* receive timeout */
#define SO_ERROR 0x1007 /* get error status and clear */
#define SO_TYPE 0x1008 /* get socket type */
 
 
struct in_addr
{
union
{
struct { unsigned char s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { unsigned short s_w1,s_w2; } S_un_w;
unsigned long S_addr;
} S_un;
};
#define s_addr S_un.S_addr /* can be used for most tcp & ip code */
#define s_host S_un.S_un_b.s_b2 /* host on imp */
#define s_net S_un.S_un_b.s_b1 /* network */
#define s_imp S_un.S_un_w.s_w2 /* imp */
#define s_impno S_un.S_un_b.s_b4 /* imp # */
#define s_lh S_un.S_un_b.s_b3 /* logical host */
 
struct sockaddr_in
{
short sin_family;
unsigned short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
 
struct hostent {
char *h_name; /* official name of host */
char **h_aliases; /* alias list */
int h_addrtype; /* host address type */
int h_length; /* length of address */
char **h_addr_list; /* list of addresses from name server */
#define h_addr h_addr_list[0] /* address, for backward compatiblity */
};
 
char *inet_ntoa(struct in_addr in);
 
 
// this section is B&W specific constants & structures
 
#define BW_IOCTL_BIND 0
#define BW_IOCTL_CLEAROPTIONS 5
#define BW_IOCTL_SETOPTIONS 6
#define BW_IOCTL_PEEK 7
#define BW_IOCTL_SETWINMASK 8
 
#define BW_OPTION_BLOCKING 0x01
#define BW_OPTION_REUSEBUFFERS 0x80
 
#define BW_ERR_USR_HANGUP 50
#define BW_ERR_HANGUP 51
#define BW_ERR_NET_ERR 52
#define BW_ERR_IS_CLOSED 53
#define BW_ERR_TIME_OUT 54
#define BW_ERR_RESET 55
#define BW_ERR_FULL 56
#define BW_ERR_BLOCK 57
#define BW_ERR_SHUTDOWN 58
 
#pragma pack(1)
 
typedef struct
{
char state; // always 1
short localPort;
struct in_addr localAddr;
char reason; // always 0
char options;
short dataAvailable;
} BW_UDPinfo_t;
 
typedef struct
{
char reserved1 [6];
unsigned short info2Offset;
char reserved2 [18];
struct in_addr remoteAddr;
} BW_UDPreadInfo1_t;
 
typedef struct
{
short remotePort;
char reserved1 [2];
unsigned short dataLenPlus8;
char reserved2 [2];
char data[1]; // actual size is <dataLenPlus8> - 8
} BW_UDPreadInfo2_t;
 
typedef struct
{
char reserved1 [2];
short remotePort;
unsigned short dataLen;
struct in_addr remoteAddr;
char reserved2 [42];
char data[1]; // actual size is <datalen>
} BW_writeInfo_t;
 
typedef struct
{
short ioport;
byte dma;
byte vector;
byte irq;
short bufferSize;
short maxWindow;
short timeZone;
byte myType;
int inetAddr;
short value;
byte subnetMask;
short etherPointer;
short logserverPointer;
short nameserverPointer;
short printserverPointer;
short timeserverPointer;
short gatewayPointer;
short driverSegment;
byte transferSize;
char cardName [9];
} BW_ethdevinfo_t;
 
#pragma pack()
 
#define LOWMEM_SIZE 4096
 
static unsigned char *lowmem_buffer;
static int lowmem_bufseg;
static int lowmem_bufoff;
static BW_ethdevinfo_t ethdevinfo;
static int netmask;
static struct in_addr bcastaddr;
 
extern regs_t regs;
 
static int net_acceptsocket = -1; // socket for fielding new connections
static int net_controlsocket = 0;
 
#include "net_bw.h"
 
//=============================================================================
 
static int BW_ioctl(int s, char *msg, int msglen)
{
Q_memcpy(lowmem_buffer, msg, msglen);
 
regs.x.ax = 0x4403;
regs.x.bx = s;
regs.x.cx = msglen;
regs.x.dx = lowmem_bufoff;
regs.x.ds = lowmem_bufseg;
if (dos_int86(0x21))
return regs.x.ax;
return 0;
}
 
//=============================================================================
 
static int BW_TranslateError(int error)
{
switch(error)
{
case BW_ERR_USR_HANGUP: return ECONNABORTED;
case BW_ERR_HANGUP: return EISCONN;
case BW_ERR_NET_ERR: return ENOTCONN;
case BW_ERR_IS_CLOSED: return ENOTCONN;
case BW_ERR_TIME_OUT: return ETIMEDOUT;
case BW_ERR_RESET: return ECONNREFUSED;
case BW_ERR_FULL: return ETOOMANYREFS;
case BW_ERR_BLOCK: return EWOULDBLOCK;
case BW_ERR_SHUTDOWN: return ESHUTDOWN;
}
return EIO;
}
 
//=============================================================================
 
static int GetEthdevinfo(void)
{
int fd;
 
Q_strcpy((char *)lowmem_buffer, "ETHDEV27");
regs.x.ax = 0x3d42;
regs.x.ds = lowmem_bufseg;
regs.x.dx = lowmem_bufoff;
if (dos_int86(0x21))
return -1;
fd = regs.x.ax;
 
regs.x.ax = 0x4401;
regs.x.bx = fd;
regs.x.dx = 0x60;
dos_int86(0x21);
 
regs.h.ah = 0x3f;
regs.x.cx = sizeof(ethdevinfo);
regs.x.es = regs.x.ds = lowmem_bufseg;
regs.x.dx = lowmem_bufoff;
regs.x.bx = fd;
if (dos_int86(0x21))
return -1;
Q_memcpy(&ethdevinfo, lowmem_buffer, regs.x.ax);
 
regs.h.ah = 0x3e;
regs.x.bx = fd;
dos_int86(0x21);
 
return 0;
}
 
//=============================================================================
 
int BW_Init(void)
{
struct qsockaddr addr;
char *colon;
 
if (COM_CheckParm ("-noudp"))
return -1;
 
lowmem_buffer = dos_getmemory(LOWMEM_SIZE);
if (!lowmem_buffer)
Sys_Error("not enough low memory\n");
lowmem_bufoff = ptr2real(lowmem_buffer) & 0xf;
lowmem_bufseg = ptr2real(lowmem_buffer) >> 4;
 
if (GetEthdevinfo())
{
Con_DPrintf("Beame & Whiteside TCP/IP not detected\n");
dos_freememory(lowmem_buffer);
return -1;
}
netmask = 0xffffffff >> (32 - ethdevinfo.subnetMask);
bcastaddr.s_addr = (ethdevinfo.inetAddr & netmask) | (~netmask);
 
if ((net_controlsocket = BW_OpenSocket (0)) == -1)
{
dos_freememory(lowmem_buffer);
Con_DPrintf ("BW_Init unable to open control socket; disabled\n");
return -1;
}
 
BW_GetSocketAddr (net_controlsocket, &addr);
Q_strcpy(my_tcpip_address, BW_AddrToString (&addr));
colon = Q_strrchr (my_tcpip_address, ':');
if (colon)
*colon = 0;
 
Con_Printf("BW_Init: UDP initialized\n");
tcpipAvailable = true;
 
return net_controlsocket;
}
 
//=============================================================================
 
void BW_Shutdown(void)
{
BW_Listen (false);
BW_CloseSocket (net_controlsocket);
dos_freememory(lowmem_buffer);
}
 
//=============================================================================
 
void BW_Listen (qboolean state)
{
// enable listening
if (state)
{
if (net_acceptsocket != -1)
return;
if ((net_acceptsocket = BW_OpenSocket (net_hostport)) == -1)
Sys_Error ("BW_Listen: Unable to open accept socket\n");
return;
}
 
// disable listening
if (net_acceptsocket == -1)
return;
BW_CloseSocket (net_acceptsocket);
net_acceptsocket = -1;
}
 
 
//=============================================================================
 
/*
OpenSocket returns a handle to a network socket that has been opened,
set to nonblocking, and bound to <port>. Additional socket options
should be set here if they are needed. -1 is returned on failure.
*/
 
int BW_OpenSocket(int port)
{
int s;
int ret;
int deadman = 3 * 1024;
static int dynamic = 1024;
static char reuse_msg[2] = {BW_IOCTL_SETOPTIONS, BW_OPTION_REUSEBUFFERS};
static char bind_msg[3] = {BW_IOCTL_BIND, 0, 0};
static char nonblock_msg[2] = {BW_IOCTL_CLEAROPTIONS, BW_OPTION_BLOCKING};
 
// allocate a UDP socket
Q_strcpy((char *)lowmem_buffer, "UDP-IP10");
regs.x.ax = 0x3d42;
regs.x.ds = lowmem_bufseg;
regs.x.dx = lowmem_bufoff;
if (dos_int86(0x21))
{
Con_Printf("BW_OpenSocket failed: %u\n", BW_TranslateError(regs.x.ax));
return -1;
}
s = regs.x.ax;
 
// set file descriptor to raw mode
regs.x.ax = 0x4401;
regs.x.bx = s;
regs.x.dx = 0x60;
dos_int86(0x21);
 
if (BW_ioctl(s, reuse_msg, 2))
{
Con_Printf("BW_OpenSocket ioctl(reuse) failed\n");
return -1;
}
 
if (BW_ioctl(s, nonblock_msg, 2))
{
Con_Printf("BW_OpenSocket ioctl(nonblocking) failed\n");
return -1;
}
 
// if a socket was specified, bind to it and return
if (port)
{
*(short *)&bind_msg[1] = port;
if (BW_ioctl(s, bind_msg, 3))
{
BW_CloseSocket(s);
return -1;
}
return s;
}
 
// B&W does NOT do dynamic allocation, so if port == 0 we must fake it
do
{
port = dynamic++;
if (dynamic == 4096)
dynamic = 1024;
deadman--;
*(short *)&bind_msg[1] = port;
ret = BW_ioctl(s, bind_msg, 3);
}
while (ret && deadman);
if (ret)
return -1;
return s;
}
 
//=============================================================================
 
int BW_CloseSocket(int socket)
{
regs.h.ah = 0x3e;
regs.x.bx = socket;
if(dos_int86(0x21))
{
Con_Printf("BW_CloseSocket %u failed: %u\n", socket, BW_TranslateError(regs.x.ax));
return -1;
}
return 0;
}
 
//=============================================================================
 
int BW_Connect (int socket, struct qsockaddr *hostaddr)
{
return 0;
}
 
//=============================================================================
 
int BW_CheckNewConnections(void)
{
if (net_acceptsocket == 0)
return -1;
 
// see if there's anything waiting
regs.x.ax = 0x4406;
regs.x.bx = net_acceptsocket;
dos_int86(0x21);
if (regs.x.ax == 0)
return -1;
return net_acceptsocket;
}
 
//=============================================================================
 
int BW_Read(int s, byte *buf, int len, struct qsockaddr *from)
{
BW_UDPreadInfo1_t *info1;
BW_UDPreadInfo2_t *info2;
 
// ask if there's anything waiting
regs.x.ax = 0x4406;
regs.x.bx = s;
dos_int86(0x21);
if (regs.x.ax == 0)
return 0;
 
// there was, so let's get it
regs.h.ah = 0x3f;
regs.x.cx = /* len + 53 */ LOWMEM_SIZE;
regs.x.es = regs.x.ds = lowmem_bufseg;
regs.x.dx = lowmem_bufoff;
regs.x.bx = s;
if (dos_int86(0x21))
{
Con_Printf("BW UDP read error: %u\n", BW_TranslateError(regs.x.ax));
return -1;
}
 
info1 = (BW_UDPreadInfo1_t *)lowmem_buffer;
info2 = (BW_UDPreadInfo2_t *)(lowmem_buffer + info1->info2Offset);
 
if (from)
{
from->sa_family = AF_INET;
((struct sockaddr_in *)from)->sin_addr = info1->remoteAddr;
((struct sockaddr_in *)from)->sin_port = htons(info2->remotePort);
}
 
len = info2->dataLenPlus8 - 8;
if (len > NET_DATAGRAMSIZE)
{
Con_Printf("BW UDP read packet too large: %u\n", len);
return -1;
}
Q_memcpy(buf, info2->data, len);
 
return len;
}
 
//=============================================================================
 
int BW_Broadcast(int s, byte *msg, int len)
{
BW_writeInfo_t *writeInfo;
 
// ask if we're clear to send
regs.x.ax = 0x4407;
regs.x.bx = s;
dos_int86(0x21);
if (regs.x.ax == 0)
return 0;
 
// yes, let's do it
writeInfo = (BW_writeInfo_t *)lowmem_buffer;
writeInfo->remoteAddr = bcastaddr;
writeInfo->remotePort = net_hostport;
writeInfo->dataLen = len;
if (len > NET_DATAGRAMSIZE)
Sys_Error("BW UDP write packet too large: %u\n", len);
Q_memcpy(writeInfo->data, msg, len);
writeInfo->data[len] = 0;
regs.h.ah = 0x40;
regs.x.bx = s;
regs.x.cx = len + sizeof(BW_writeInfo_t);
regs.x.es = regs.x.ds = lowmem_bufseg;
regs.x.dx = lowmem_bufoff;
if (dos_int86(0x21))
{
Con_Printf("BW_Broadcast failed: %u\n", BW_TranslateError(regs.x.ax));
return -1;
}
 
return len;
}
 
//=============================================================================
 
int BW_Write(int s, byte *msg, int len, struct qsockaddr *to)
{
BW_writeInfo_t *writeInfo;
 
// ask if we're clear to send
regs.x.ax = 0x4407;
regs.x.bx = s;
dos_int86(0x21);
if (regs.x.ax == 0)
return 0;
 
// yes, let's do it
writeInfo = (BW_writeInfo_t *)lowmem_buffer;
writeInfo->remoteAddr = ((struct sockaddr_in *)to)->sin_addr;
writeInfo->remotePort = ntohs(((struct sockaddr_in *)to)->sin_port);
writeInfo->dataLen = len;
if (len > NET_DATAGRAMSIZE)
Sys_Error("BW UDP write packet too large: %u\n", len);
Q_memcpy(writeInfo->data, msg, len);
writeInfo->data[len] = 0;
regs.h.ah = 0x40;
regs.x.bx = s;
regs.x.cx = len + sizeof(BW_writeInfo_t);
regs.x.es = regs.x.ds = lowmem_bufseg;
regs.x.dx = lowmem_bufoff;
if (dos_int86(0x21))
{
Con_Printf("BW_Write failed: %u\n", BW_TranslateError(regs.x.ax));
return -1;
}
 
return len;
}
 
//=============================================================================
 
 
char *BW_AddrToString (struct qsockaddr *addr)
{
static char buffer[22];
 
sprintf(buffer, "%d.%d.%d.%d:%d",
((struct sockaddr_in *)addr)->sin_addr.s_net,
((struct sockaddr_in *)addr)->sin_addr.s_host,
((struct sockaddr_in *)addr)->sin_addr.s_lh,
((struct sockaddr_in *)addr)->sin_addr.s_impno,
ntohs(((struct sockaddr_in *)addr)->sin_port)
);
return buffer;
}
 
//=============================================================================
 
int BW_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((short)hp);
return 0;
}
 
//=============================================================================
 
int BW_GetSocketAddr (int socket, struct qsockaddr *addr)
{
regs.x.ax = 0x4402;
regs.x.bx = socket;
regs.x.cx = sizeof(BW_UDPinfo_t);
regs.x.dx = lowmem_bufoff;
regs.x.ds = lowmem_bufseg;
dos_int86(0x21);
 
addr->sa_family = AF_INET;
((struct sockaddr_in *)addr)->sin_addr.s_addr = ((BW_UDPinfo_t *)lowmem_buffer)->localAddr.s_addr;
((struct sockaddr_in *)addr)->sin_port = htons(((BW_UDPinfo_t *)lowmem_buffer)->localPort);
 
return 0;
}
 
//=============================================================================
 
int BW_GetNameFromAddr (struct qsockaddr *addr, char *name)
{
Q_strcpy(name, BW_AddrToString(addr));
return 0;
}
 
///=============================================================================
 
int BW_GetAddrFromName (char *name, struct qsockaddr *hostaddr)
{
char buff[MAXHOSTNAMELEN];
char *b;
int addr;
int num;
int mask;
int run;
int port;
 
if (name[0] < '0' || name[0] > '9')
return -1;
 
buff[0] = '.';
b = buff;
Q_strcpy(buff+1, name);
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;
}
addr = htonl(addr);
mask = htonl(mask);
 
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 =
((ethdevinfo.inetAddr & mask) | addr);
 
return 0;
}
 
//=============================================================================
 
int BW_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 BW_GetSocketPort (struct qsockaddr *addr)
{
return ntohs(((struct sockaddr_in *)addr)->sin_port);
}
 
 
int BW_SetSocketPort (struct qsockaddr *addr, int port)
{
((struct sockaddr_in *)addr)->sin_port = htons(port);
return 0;
}
 
//=============================================================================
/contrib/other/sdlquake-1.0.9/net_bw.h
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_bw.h
 
int BW_Init (void);
void BW_Shutdown (void);
void BW_Listen (qboolean state);
int BW_OpenSocket (int port);
int BW_CloseSocket (int socket);
int BW_Connect (int socket, struct qsockaddr *addr);
int BW_CheckNewConnections (void);
int BW_Read (int socket, byte *buf, int len, struct qsockaddr *addr);
int BW_Write (int socket, byte *buf, int len, struct qsockaddr *addr);
int BW_Broadcast (int socket, byte *buf, int len);
char *BW_AddrToString (struct qsockaddr *addr);
int BW_StringToAddr (char *string, struct qsockaddr *addr);
int BW_GetSocketAddr (int socket, struct qsockaddr *addr);
int BW_GetNameFromAddr (struct qsockaddr *addr, char *name);
int BW_GetAddrFromName (char *name, struct qsockaddr *addr);
int BW_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2);
int BW_GetSocketPort (struct qsockaddr *addr);
int BW_SetSocketPort (struct qsockaddr *addr, int port);
/contrib/other/sdlquake-1.0.9/net_comx.c
0,0 → 1,1285
/*
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_comx.c
 
#include <dos.h>
#include <dpmi.h>
 
#define NUM_COM_PORTS 2
 
#define ERR_TTY_LINE_STATUS -1
#define ERR_TTY_MODEM_STATUS -2
#define ERR_TTY_NODATA -3
 
#define QUEUESIZE 8192
#define QUEUEMASK (QUEUESIZE - 1)
 
typedef struct
{
volatile int head;
volatile int tail;
volatile byte data[QUEUESIZE];
} queue;
 
#define FULL(q) (q.head == ((q.tail-1) & QUEUEMASK))
#define EMPTY(q) (q.tail == q.head)
#define ENQUEUE(q,b) (q.data[q.head] = b, q.head = (q.head + 1) & QUEUEMASK)
#define DEQUEUE(q,b) (b = q.data[q.tail], q.tail = (q.tail + 1) & QUEUEMASK)
 
extern cvar_t config_com_port;
extern cvar_t config_com_irq;
extern cvar_t config_com_baud;
extern cvar_t config_com_modem;
extern cvar_t config_modem_dialtype;
extern cvar_t config_modem_clear;
extern cvar_t config_modem_init;
extern cvar_t config_modem_hangup;
 
extern int m_return_state;
extern int m_state;
extern qboolean m_return_onerror;
extern char m_return_reason[32];
 
// 8250, 16550 definitions
#define TRANSMIT_HOLDING_REGISTER 0x00
#define RECEIVE_BUFFER_REGISTER 0x00
#define INTERRUPT_ENABLE_REGISTER 0x01
#define IER_RX_DATA_READY 0x01
#define IER_TX_HOLDING_REGISTER_EMPTY 0x02
#define IER_LINE_STATUS 0x04
#define IER_MODEM_STATUS 0x08
#define INTERRUPT_ID_REGISTER 0x02
#define IIR_MODEM_STATUS_INTERRUPT 0x00
#define IIR_TX_HOLDING_REGISTER_INTERRUPT 0x02
#define IIR_RX_DATA_READY_INTERRUPT 0x04
#define IIR_LINE_STATUS_INTERRUPT 0x06
#define IIR_FIFO_TIMEOUT 0x0c
#define IIR_FIFO_ENABLED 0xc0
#define FIFO_CONTROL_REGISTER 0x02
#define FCR_FIFO_ENABLE 0x01
#define FCR_RCVR_FIFO_RESET 0x02
#define FCR_XMIT_FIFO_RESET 0x04
#define FCR_TRIGGER_01 0x00
#define FCR_TRIGGER_04 0x40
#define FCR_TRIGGER_08 0x80
#define FCR_TRIGGER_16 0xc0
#define LINE_CONTROL_REGISTER 0x03
#define LCR_DATA_BITS_5 0x00
#define LCR_DATA_BITS_6 0x01
#define LCR_DATA_BITS_7 0x02
#define LCR_DATA_BITS_8 0x03
#define LCR_STOP_BITS_1 0x00
#define LCR_STOP_BITS_2 0x04
#define LCR_PARITY_NONE 0x00
#define LCR_PARITY_ODD 0x08
#define LCR_PARITY_EVEN 0x18
#define LCR_PARITY_MARK 0x28
#define LCR_PARITY_SPACE 0x38
#define LCR_SET_BREAK 0x40
#define LCR_DLAB 0x80
#define MODEM_CONTROL_REGISTER 0x04
#define MCR_DTR 0x01
#define MCR_RTS 0x02
#define MCR_OUT1 0x04
#define MCR_OUT2 0x08
#define MCR_LOOPBACK 0x10
#define LINE_STATUS_REGISTER 0x05
#define LSR_DATA_READY 0x01
#define LSR_OVERRUN_ERROR 0x02
#define LSR_PARITY_ERROR 0x04
#define LSR_FRAMING_ERROR 0x08
#define LSR_BREAK_DETECT 0x10
#define LSR_TRANSMITTER_BUFFER_EMPTY 0x20
#define LSR_TRANSMITTER_EMPTY 0x40
#define LSR_FIFO_DIRTY 0x80
#define MODEM_STATUS_REGISTER 0x06
#define MSR_DELTA_CTS 0x01
#define MSR_DELTA_DSR 0x02
#define MSR_DELTA_RI 0x04
#define MSR_DELTA_CD 0x08
#define MSR_CTS 0x10
#define MSR_DSR 0x20
#define MSR_RI 0x40
#define MSR_CD 0x80
#define DIVISOR_LATCH_LOW 0x00
#define DIVISOR_LATCH_HIGH 0x01
 
#define MODEM_STATUS_MASK (MSR_CTS | MSR_DSR | MSR_CD)
 
#define UART_AUTO 0
#define UART_8250 1
#define UART_16550 2
 
static int ISA_uarts[] = {0x3f8,0x2f8,0x3e8,0x2e8};
static int ISA_IRQs[] = {4,3,4,3};
 
typedef struct ComPort_s
{
struct ComPort_s *next;
_go32_dpmi_seginfo protectedModeInfo;
_go32_dpmi_seginfo protectedModeSaveInfo;
int uart;
volatile byte modemStatus;
byte modemStatusIgnore;
byte lineStatus;
byte bufferUsed;
qboolean enabled;
volatile qboolean statusUpdated;
qboolean useModem;
qboolean modemInitialized;
qboolean modemRang;
qboolean modemConnected;
queue inputQueue;
queue outputQueue;
char clear[16];
char startup[32];
char shutdown[16];
char buffer[128];
PollProcedure poll;
double timestamp;
byte uartType;
byte irq;
byte baudBits;
byte lineControl;
byte portNumber;
char dialType;
char name[4];
} ComPort;
 
ComPort *portList = NULL;
ComPort *handleToPort [NUM_COM_PORTS];
 
static int Modem_Command(ComPort *p, char *commandString);
static char *Modem_Response(ComPort *p);
static void Modem_Hangup(ComPort *p);
 
int TTY_Init(void);
void TTY_Shutdown(void);
int TTY_Open(int serialPortNumber);
void TTY_Close(int handle);
int TTY_ReadByte(int handle);
int TTY_WriteByte(int handle, byte data);
void TTY_Flush(int handle);
int TTY_Connect(int handle, char *host);
void TTY_Disconnect(int handle);
qboolean TTY_CheckForConnection(int handle);
qboolean TTY_IsEnabled(int serialPortNumber);
qboolean TTY_IsModem(int serialPortNumber);
qboolean TTY_OutputQueueIsEmpty(int handle);
 
static void ISR_8250 (ComPort *p)
{
byte source = 0;
byte b;
 
disable();
 
while((source = inportb (p->uart + INTERRUPT_ID_REGISTER) & 0x07) != 1)
{
switch (source)
{
case IIR_RX_DATA_READY_INTERRUPT:
b = inportb (p->uart + RECEIVE_BUFFER_REGISTER);
if (! FULL(p->inputQueue))
{
ENQUEUE (p->inputQueue, b);
}
else
{
p->lineStatus |= LSR_OVERRUN_ERROR;
p->statusUpdated = true;
}
break;
 
case IIR_TX_HOLDING_REGISTER_INTERRUPT:
if (! EMPTY(p->outputQueue))
{
DEQUEUE (p->outputQueue, b);
outportb (p->uart + TRANSMIT_HOLDING_REGISTER, b);
}
break;
 
case IIR_MODEM_STATUS_INTERRUPT:
p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore;
p->statusUpdated = true;
break;
 
case IIR_LINE_STATUS_INTERRUPT:
p->lineStatus = inportb (p->uart + LINE_STATUS_REGISTER);
p->statusUpdated = true;
break;
}
source = inportb (p->uart + INTERRUPT_ID_REGISTER) & 0x07;
}
outportb (0x20, 0x20);
}
 
static void COM1_ISR_8250 (void)
{
ISR_8250 (handleToPort[0]);
}
 
static void COM2_ISR_8250 (void)
{
ISR_8250 (handleToPort[1]);
}
 
 
 
static void ISR_16550 (ComPort *p)
{
int count;
byte source;
byte b;
 
disable();
while((source = inportb (p->uart + INTERRUPT_ID_REGISTER) & 0x07) != 1)
{
switch (source)
{
case IIR_RX_DATA_READY_INTERRUPT:
do
{
b = inportb (p->uart + RECEIVE_BUFFER_REGISTER);
if (!FULL(p->inputQueue))
{
ENQUEUE (p->inputQueue, b);
}
else
{
p->lineStatus |= LSR_OVERRUN_ERROR;
p->statusUpdated = true;
}
} while (inportb (p->uart + LINE_STATUS_REGISTER) & LSR_DATA_READY);
break;
 
case IIR_TX_HOLDING_REGISTER_INTERRUPT:
count = 16;
while ((! EMPTY(p->outputQueue)) && count--)
{
DEQUEUE (p->outputQueue, b);
outportb (p->uart + TRANSMIT_HOLDING_REGISTER, b);
}
break;
 
case IIR_MODEM_STATUS_INTERRUPT:
p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore;
p->statusUpdated = true;
break;
 
case IIR_LINE_STATUS_INTERRUPT:
p->lineStatus = inportb (p->uart + LINE_STATUS_REGISTER);
p->statusUpdated = true;
break;
}
source = inportb (p->uart + INTERRUPT_ID_REGISTER) & 0x07;
}
 
// check for lost IIR_TX_HOLDING_REGISTER_INTERRUPT on 16550a!
if (inportb (p->uart + LINE_STATUS_REGISTER ) & LSR_TRANSMITTER_EMPTY)
{
count = 16;
while ((! EMPTY(p->outputQueue)) && count--)
{
DEQUEUE (p->outputQueue, b);
outportb (p->uart + TRANSMIT_HOLDING_REGISTER, b);
}
}
 
outportb (0x20, 0x20);
}
 
static void COM1_ISR_16550 (void)
{
ISR_16550 (handleToPort[0]);
}
 
static void COM2_ISR_16550 (void)
{
ISR_16550 (handleToPort[1]);
}
 
 
void TTY_GetComPortConfig (int portNumber, int *port, int *irq, int *baud, qboolean *useModem)
{
ComPort *p;
 
p = handleToPort[portNumber];
*port = p->uart;
*irq = p->irq;
*baud = 115200 / p->baudBits;
*useModem = p->useModem;
}
 
void TTY_SetComPortConfig (int portNumber, int port, int irq, int baud, qboolean useModem)
{
ComPort *p;
float temp;
 
if (useModem)
{
if (baud == 14400)
baud = 19200;
if (baud == 28800)
baud = 38400;
}
 
p = handleToPort[portNumber];
p->uart = port;
p->irq = irq;
p->baudBits = 115200 / baud;
p->useModem = useModem;
 
if (useModem)
temp = 1.0;
else
temp = 0.0;
 
Cvar_SetValue ("_config_com_port", (float)port);
Cvar_SetValue ("_config_com_irq", (float)irq);
Cvar_SetValue ("_config_com_baud", (float)baud);
Cvar_SetValue ("_config_com_modem", temp);
}
 
void TTY_GetModemConfig (int portNumber, char *dialType, char *clear, char *init, char *hangup)
{
ComPort *p;
 
p = handleToPort[portNumber];
*dialType = p->dialType;
Q_strcpy(clear, p->clear);
Q_strcpy(init, p->startup);
Q_strcpy(hangup, p->shutdown);
}
 
void TTY_SetModemConfig (int portNumber, char *dialType, char *clear, char *init, char *hangup)
{
ComPort *p;
 
p = handleToPort[portNumber];
p->dialType = dialType[0];
Q_strcpy(p->clear, clear);
Q_strcpy(p->startup, init);
Q_strcpy(p->shutdown, hangup);
 
p->modemInitialized = false;
 
Cvar_Set ("_config_modem_dialtype", dialType);
Cvar_Set ("_config_modem_clear", clear);
Cvar_Set ("_config_modem_init", init);
Cvar_Set ("_config_modem_hangup", hangup);
}
 
 
static void ResetComPortConfig (ComPort *p)
{
p->useModem = false;
p->uartType = UART_AUTO;
p->uart = ISA_uarts[p->portNumber];
p->irq = ISA_IRQs[p->portNumber];
p->modemStatusIgnore = MSR_CD | MSR_CTS | MSR_DSR;
p->baudBits = 115200 / 57600;
p->lineControl = LCR_DATA_BITS_8 | LCR_STOP_BITS_1 | LCR_PARITY_NONE;
Q_strcpy(p->clear, "ATZ");
Q_strcpy(p->startup, "");
Q_strcpy(p->shutdown, "AT H");
p->modemRang = false;
p->modemConnected = false;
p->statusUpdated = false;
p->outputQueue.head = p->outputQueue.tail = 0;
p->inputQueue.head = p->inputQueue.tail = 0;
}
 
 
static void ComPort_Enable(ComPort *p)
{
void (*isr)(void);
int n;
byte b;
 
if (p->enabled)
{
Con_Printf("Already enabled\n");
return;
}
 
// disable all UART interrupts
outportb (p->uart + INTERRUPT_ENABLE_REGISTER, 0);
 
// clear out any buffered uncoming data
while((inportb (p->uart + LINE_STATUS_REGISTER)) & LSR_DATA_READY)
inportb (p->uart + RECEIVE_BUFFER_REGISTER);
 
// get the current line and modem status
p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore;
p->lineStatus = inportb (p->uart + LINE_STATUS_REGISTER);
 
// clear any UART interrupts
do
{
n = inportb (p->uart + INTERRUPT_ID_REGISTER) & 7;
if (n == IIR_RX_DATA_READY_INTERRUPT)
inportb (p->uart + RECEIVE_BUFFER_REGISTER);
} while (!(n & 1));
 
if (p->uartType == UART_AUTO)
{
outportb (p->uart + FIFO_CONTROL_REGISTER, FCR_FIFO_ENABLE);
b = inportb (p->uart + INTERRUPT_ID_REGISTER);
if ((b & IIR_FIFO_ENABLED) == IIR_FIFO_ENABLED)
p->uartType = UART_16550;
else
p->uartType = UART_8250;
}
 
// save the old interrupt handler
_go32_dpmi_get_protected_mode_interrupt_vector(p->irq + 8, &p->protectedModeSaveInfo);
 
if (p->uartType == UART_8250)
{
outportb (p->uart + FIFO_CONTROL_REGISTER, 0);
if (p == handleToPort[0])
isr = COM1_ISR_8250;
else
isr = COM2_ISR_8250;
}
else
{
outportb (p->uart + FIFO_CONTROL_REGISTER, FCR_FIFO_ENABLE | FCR_RCVR_FIFO_RESET | FCR_XMIT_FIFO_RESET | FCR_TRIGGER_08);
if (p == handleToPort[0])
isr = COM1_ISR_16550;
else
isr = COM2_ISR_16550;
}
 
p->protectedModeInfo.pm_offset = (int)isr;
 
n = _go32_dpmi_allocate_iret_wrapper(&p->protectedModeInfo);
if (n)
{
Con_Printf("serial: protected mode callback allocation failed\n");
return;
}
 
// disable interrupts at the processor
disable();
 
// install our interrupt handlers now
_go32_dpmi_set_protected_mode_interrupt_vector(p->irq + 8, &p->protectedModeInfo);
 
// enable our interrupt at the PIC
outportb (0x21, inportb (0x21) & ~(1<<p->irq));
 
// enable interrupts at the processor
enable();
 
// enable interrupts at the PIC
outportb (0x20, 0xc2);
 
// set baud rate & line control
outportb (p->uart + LINE_CONTROL_REGISTER, LCR_DLAB | p->lineControl);
outportb (p->uart, p->baudBits);
outportb (p->uart + 1, 0);
outportb (p->uart + LINE_CONTROL_REGISTER, p->lineControl);
 
// set modem control register & enable uart interrupt generation
outportb(p->uart + MODEM_CONTROL_REGISTER, MCR_OUT2 | MCR_RTS | MCR_DTR);
 
// enable the individual interrupts at the uart
outportb (p->uart + INTERRUPT_ENABLE_REGISTER, IER_RX_DATA_READY | IER_TX_HOLDING_REGISTER_EMPTY | IER_LINE_STATUS | IER_MODEM_STATUS);
 
p->enabled = true;
}
 
 
static void ComPort_Disable(ComPort *p)
{
if (!p->enabled)
{
Con_Printf("Already disabled\n");
return;
}
 
// disable interrupts at the uart
outportb (p->uart + INTERRUPT_ENABLE_REGISTER, 0);
 
// disable our interrupt at the PIC
outportb (0x21, inportb (0x21) | (1<<p->irq));
 
// disable interrupts at the processor
disable();
 
// restore the old interrupt handler
_go32_dpmi_set_protected_mode_interrupt_vector(p->irq + 8, &p->protectedModeSaveInfo);
_go32_dpmi_free_iret_wrapper(&p->protectedModeInfo);
 
// enable interrupts at the processor
enable();
 
p->enabled = false;
}
 
 
static int CheckStatus (ComPort *p)
{
int ret = 0;
 
if (p->statusUpdated)
{
p->statusUpdated = false;
 
if (p->lineStatus & (LSR_OVERRUN_ERROR | LSR_PARITY_ERROR | LSR_FRAMING_ERROR | LSR_BREAK_DETECT))
{
if (p->lineStatus & LSR_OVERRUN_ERROR)
Con_DPrintf ("Serial overrun error\n");
if (p->lineStatus & LSR_PARITY_ERROR)
Con_DPrintf ("Serial parity error\n");
if (p->lineStatus & LSR_FRAMING_ERROR)
Con_DPrintf ("Serial framing error\n");
if (p->lineStatus & LSR_BREAK_DETECT)
Con_DPrintf ("Serial break detect\n");
ret = ERR_TTY_LINE_STATUS;
}
 
if ((p->modemStatus & MODEM_STATUS_MASK) != MODEM_STATUS_MASK)
{
if (!(p->modemStatus & MSR_CTS))
Con_Printf ("Serial lost CTS\n");
if (!(p->modemStatus & MSR_DSR))
Con_Printf ("Serial lost DSR\n");
if (!(p->modemStatus & MSR_CD))
Con_Printf ("Serial lost Carrier\n");
ret = ERR_TTY_MODEM_STATUS;
}
}
 
return ret;
}
 
 
static void Modem_Init(ComPort *p)
{
double start;
char *response;
 
Con_Printf ("Initializing modem...\n");
 
// write 0 to MCR, wait 1/2 sec, then write the real value back again
// I got this from the guys at head-to-head who say it's necessary.
outportb(p->uart + MODEM_CONTROL_REGISTER, 0);
start = Sys_FloatTime();
while ((Sys_FloatTime() - start) < 0.5)
;
outportb(p->uart + MODEM_CONTROL_REGISTER, MCR_OUT2 | MCR_RTS | MCR_DTR);
start = Sys_FloatTime();
while ((Sys_FloatTime() - start) < 0.25)
;
 
if (*p->clear)
{
Modem_Command (p, p->clear);
start = Sys_FloatTime();
while(1)
{
if ((Sys_FloatTime() - start) > 3.0)
{
Con_Printf("No response - clear failed\n");
p->enabled = false;
goto failed;
}
response = Modem_Response(p);
if (!response)
continue;
if (Q_strncmp(response, "OK", 2) == 0)
break;
if (Q_strncmp(response, "ERROR", 5) == 0)
{
p->enabled = false;
goto failed;
}
}
}
 
if (*p->startup)
{
Modem_Command (p, p->startup);
start = Sys_FloatTime();
while(1)
{
if ((Sys_FloatTime() - start) > 3.0)
{
Con_Printf("No response - init failed\n");
p->enabled = false;
goto failed;
}
response = Modem_Response(p);
if (!response)
continue;
if (Q_strncmp(response, "OK", 2) == 0)
break;
if (Q_strncmp(response, "ERROR", 5) == 0)
{
p->enabled = false;
goto failed;
}
}
}
 
p->modemInitialized = true;
return;
 
failed:
if (m_return_onerror)
{
key_dest = key_menu;
m_state = m_return_state;
m_return_onerror = false;
Q_strcpy(m_return_reason, "Initialization Failed");
}
return;
}
 
 
void TTY_Enable(int handle)
{
ComPort *p;
 
p = handleToPort [handle];
if (p->enabled)
return;
 
ComPort_Enable(p);
 
if (p->useModem && !p->modemInitialized)
Modem_Init (p);
}
 
 
int TTY_Open(int serialPortNumber)
{
return serialPortNumber;
}
 
 
void TTY_Close(int handle)
{
ComPort *p;
double startTime;
 
p = handleToPort [handle];
 
startTime = Sys_FloatTime();
while ((Sys_FloatTime() - startTime) < 1.0)
if (EMPTY(p->outputQueue))
break;
 
if (p->useModem)
{
if (p->modemConnected)
Modem_Hangup(p);
}
}
 
 
int TTY_ReadByte(int handle)
{
int ret;
ComPort *p;
 
p = handleToPort [handle];
 
if ((ret = CheckStatus (p)) != 0)
return ret;
if (EMPTY (p->inputQueue))
return ERR_TTY_NODATA;
 
DEQUEUE (p->inputQueue, ret);
return (ret & 0xff);
}
 
 
int TTY_WriteByte(int handle, byte data)
{
ComPort *p;
 
p = handleToPort [handle];
if (FULL(p->outputQueue))
return -1;
 
ENQUEUE (p->outputQueue, data);
return 0;
}
 
 
void TTY_Flush(int handle)
{
byte b;
ComPort *p;
 
p = handleToPort [handle];
 
if (inportb (p->uart + LINE_STATUS_REGISTER ) & LSR_TRANSMITTER_EMPTY)
{
DEQUEUE (p->outputQueue, b);
outportb(p->uart, b);
}
}
 
 
int TTY_Connect(int handle, char *host)
{
double start;
ComPort *p;
char *response = NULL;
keydest_t save_key_dest;
byte dialstring[64];
byte b;
 
p = handleToPort[handle];
 
if ((p->modemStatus & MODEM_STATUS_MASK) != MODEM_STATUS_MASK)
{
Con_Printf ("Serial: line not ready (");
if ((p->modemStatus & MSR_CTS) == 0)
Con_Printf(" CTS");
if ((p->modemStatus & MSR_DSR) == 0)
Con_Printf(" DSR");
if ((p->modemStatus & MSR_CD) == 0)
Con_Printf(" CD");
Con_Printf(" )");
return -1;
}
 
// discard any scraps in the input buffer
while (! EMPTY (p->inputQueue))
DEQUEUE (p->inputQueue, b);
 
CheckStatus (p);
 
if (p->useModem)
{
save_key_dest = key_dest;
key_dest = key_console;
key_count = -2;
 
Con_Printf ("Dialing...\n");
sprintf(dialstring, "AT D%c %s\r", p->dialType, host);
Modem_Command (p, dialstring);
start = Sys_FloatTime();
while(1)
{
if ((Sys_FloatTime() - start) > 60.0)
{
Con_Printf("Dialing failure!\n");
break;
}
 
Sys_SendKeyEvents ();
if (key_count == 0)
{
if (key_lastpress != K_ESCAPE)
{
key_count = -2;
continue;
}
Con_Printf("Aborting...\n");
while ((Sys_FloatTime() - start) < 5.0)
;
disable();
p->outputQueue.head = p->outputQueue.tail = 0;
p->inputQueue.head = p->inputQueue.tail = 0;
outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) & ~MCR_DTR);
enable();
start = Sys_FloatTime();
while ((Sys_FloatTime() - start) < 0.75)
;
outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) | MCR_DTR);
response = "Aborted";
break;
}
 
response = Modem_Response(p);
if (!response)
continue;
if (Q_strncmp(response, "CONNECT", 7) == 0)
{
disable();
p->modemRang = true;
p->modemConnected = true;
p->outputQueue.head = p->outputQueue.tail = 0;
p->inputQueue.head = p->inputQueue.tail = 0;
enable();
key_dest = save_key_dest;
key_count = 0;
m_return_onerror = false;
return 0;
}
if (Q_strncmp(response, "NO CARRIER", 10) == 0)
break;
if (Q_strncmp(response, "NO DIALTONE", 11) == 0)
break;
if (Q_strncmp(response, "NO DIAL TONE", 12) == 0)
break;
if (Q_strncmp(response, "NO ANSWER", 9) == 0)
break;
if (Q_strncmp(response, "BUSY", 4) == 0)
break;
if (Q_strncmp(response, "ERROR", 5) == 0)
break;
}
key_dest = save_key_dest;
key_count = 0;
if (m_return_onerror)
{
key_dest = key_menu;
m_state = m_return_state;
m_return_onerror = false;
Q_strncpy(m_return_reason, response, 31);
}
return -1;
}
m_return_onerror = false;
return 0;
}
 
 
void TTY_Disconnect(int handle)
{
ComPort *p;
 
p = handleToPort[handle];
 
if (p->useModem && p->modemConnected)
Modem_Hangup(p);
}
 
 
qboolean TTY_CheckForConnection(int handle)
{
ComPort *p;
 
p = handleToPort[handle];
 
CheckStatus (p);
 
if (p->useModem)
{
if (!p->modemRang)
{
if (!Modem_Response(p))
return false;
 
if (Q_strncmp(p->buffer, "RING", 4) == 0)
{
Modem_Command (p, "ATA");
p->modemRang = true;
p->timestamp = net_time;
}
return false;
}
if (!p->modemConnected)
{
if ((net_time - p->timestamp) > 35.0)
{
Con_Printf("Unable to establish modem connection\n");
p->modemRang = false;
return false;
}
 
if (!Modem_Response(p))
return false;
 
if (Q_strncmp (p->buffer, "CONNECT", 7) != 0)
return false;
 
disable();
p->modemConnected = true;
p->outputQueue.head = p->outputQueue.tail = 0;
p->inputQueue.head = p->inputQueue.tail = 0;
enable();
Con_Printf("Modem Connect\n");
return true;
}
return true;
}
 
// direct connect case
if (EMPTY (p->inputQueue))
return false;
return true;
}
 
 
qboolean TTY_IsEnabled(int serialPortNumber)
{
return handleToPort[serialPortNumber]->enabled;
}
 
 
qboolean TTY_IsModem(int serialPortNumber)
{
return handleToPort[serialPortNumber]->useModem;
}
 
 
qboolean TTY_OutputQueueIsEmpty(int handle)
{
return EMPTY(handleToPort[handle]->outputQueue);
}
 
 
void Com_f (void)
{
ComPort *p;
int portNumber;
int i;
int n;
 
// first, determine which port they're messing with
portNumber = Q_atoi(Cmd_Argv (0) + 3) - 1;
if (portNumber > 1)
return;
p = handleToPort[portNumber];
 
if (Cmd_Argc() == 1)
{
Con_Printf("Settings for COM%i\n", portNumber + 1);
Con_Printf("enabled: %s\n", p->enabled ? "true" : "false");
Con_Printf("uart: ");
if (p->uartType == UART_AUTO)
Con_Printf("auto\n");
else if (p->uartType == UART_8250)
Con_Printf("8250\n");
else
Con_Printf("16550\n");
Con_Printf("port: %x\n", p->uart);
Con_Printf("irq: %i\n", p->irq);
Con_Printf("baud: %i\n", 115200 / p->baudBits);
Con_Printf("CTS: %s\n", (p->modemStatusIgnore & MSR_CTS) ? "ignored" : "honored");
Con_Printf("DSR: %s\n", (p->modemStatusIgnore & MSR_DSR) ? "ignored" : "honored");
Con_Printf("CD: %s\n", (p->modemStatusIgnore & MSR_CD) ? "ignored" : "honored");
if (p->useModem)
{
Con_Printf("type: Modem\n");
Con_Printf("clear: %s\n", p->clear);
Con_Printf("startup: %s\n", p->startup);
Con_Printf("shutdown: %s\n", p->shutdown);
}
else
Con_Printf("type: Direct connect\n");
 
return;
}
 
 
if (Cmd_CheckParm ("disable"))
{
if (p->enabled)
ComPort_Disable(p);
p->modemInitialized = false;
return;
}
 
if (Cmd_CheckParm ("reset"))
{
ComPort_Disable(p);
ResetComPortConfig (p);
return;
}
 
if ((i = Cmd_CheckParm ("port")) != 0)
{
if (p->enabled)
{
Con_Printf("COM port must be disabled to change port\n");
return;
}
p->uart = Q_atoi (Cmd_Argv (i+1));
}
 
if ((i = Cmd_CheckParm ("irq")) != 0)
{
if (p->enabled)
{
Con_Printf("COM port must be disabled to change irq\n");
return;
}
p->irq = Q_atoi (Cmd_Argv (i+1));
}
 
if ((i = Cmd_CheckParm ("baud")) != 0)
{
if (p->enabled)
{
Con_Printf("COM port must be disabled to change baud\n");
return;
}
n = Q_atoi (Cmd_Argv (i+1));
if (n == 0)
Con_Printf("Invalid baud rate specified\n");
else
p->baudBits = 115200 / n;
}
 
if (Cmd_CheckParm ("8250"))
{
if (p->enabled)
{
Con_Printf("COM port must be disabled to change uart\n");
return;
}
p->uartType = UART_8250;
}
if (Cmd_CheckParm ("16550"))
{
if (p->enabled)
{
Con_Printf("COM port must be disabled to change uart\n");
return;
}
p->uartType = UART_16550;
}
if (Cmd_CheckParm ("auto"))
{
if (p->enabled)
{
Con_Printf("COM port must be disabled to change uart\n");
return;
}
p->uartType = UART_AUTO;
}
 
if (Cmd_CheckParm ("pulse"))
p->dialType = 'P';
if (Cmd_CheckParm ("tone"))
p->dialType = 'T';
 
if (Cmd_CheckParm ("direct"))
p->useModem = false;
if (Cmd_CheckParm ("modem"))
p->useModem = true;
 
if ((i = Cmd_CheckParm ("clear")) != 0)
{
Q_strncpy (p->clear, Cmd_Argv (i+1), 16);
}
 
if ((i = Cmd_CheckParm ("startup")) != 0)
{
Q_strncpy (p->startup, Cmd_Argv (i+1), 32);
p->modemInitialized = false;
}
 
if ((i = Cmd_CheckParm ("shutdown")) != 0)
{
Q_strncpy (p->shutdown, Cmd_Argv (i+1), 16);
}
 
if (Cmd_CheckParm ("-cts"))
{
p->modemStatusIgnore |= MSR_CTS;
p->modemStatus |= MSR_CTS;
}
 
if (Cmd_CheckParm ("+cts"))
{
p->modemStatusIgnore &= (~MSR_CTS);
p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore;
}
 
if (Cmd_CheckParm ("-dsr"))
{
p->modemStatusIgnore |= MSR_DSR;
p->modemStatus |= MSR_DSR;
}
 
if (Cmd_CheckParm ("+dsr"))
{
p->modemStatusIgnore &= (~MSR_DSR);
p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore;
}
 
if (Cmd_CheckParm ("-cd"))
{
p->modemStatusIgnore |= MSR_CD;
p->modemStatus |= MSR_CD;
}
 
if (Cmd_CheckParm ("+cd"))
{
p->modemStatusIgnore &= (~MSR_CD);
p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore;
}
 
if (Cmd_CheckParm ("enable"))
{
if (!p->enabled)
ComPort_Enable(p);
if (p->useModem && !p->modemInitialized)
Modem_Init (p);
}
}
 
 
int TTY_Init(void)
{
int n;
ComPort *p;
 
for (n = 0; n < NUM_COM_PORTS; n++)
{
p = (ComPort *)Hunk_AllocName(sizeof(ComPort), "comport");
if (p == NULL)
Sys_Error("Hunk alloc failed for com port\n");
p->next = portList;
portList = p;
handleToPort[n] = p;
p->portNumber = n;
p->dialType = 'T';
sprintf(p->name, "com%u", n+1);
Cmd_AddCommand (p->name, Com_f);
ResetComPortConfig (p);
}
 
GetComPortConfig = TTY_GetComPortConfig;
SetComPortConfig = TTY_SetComPortConfig;
GetModemConfig = TTY_GetModemConfig;
SetModemConfig = TTY_SetModemConfig;
 
return 0;
}
 
 
void TTY_Shutdown(void)
{
int n;
ComPort *p;
 
for (n = 0; n < NUM_COM_PORTS; n++)
{
p = handleToPort[n];
if (p->enabled)
{
while (p->modemConnected)
NET_Poll();
ComPort_Disable (p);
}
}
}
 
 
static int Modem_Command(ComPort *p, char *commandString)
{
byte b;
 
if (CheckStatus (p))
return -1;
 
disable();
p->outputQueue.head = p->outputQueue.tail = 0;
p->inputQueue.head = p->inputQueue.tail = 0;
enable();
p->bufferUsed = 0;
 
while (*commandString)
ENQUEUE (p->outputQueue, *commandString++);
ENQUEUE (p->outputQueue, '\r');
 
// get the transmit rolling
DEQUEUE (p->outputQueue, b);
outportb(p->uart, b);
 
return 0;
}
 
 
static char *Modem_Response(ComPort *p)
{
byte b;
 
if (CheckStatus (p))
return NULL;
 
while (! EMPTY(p->inputQueue))
{
DEQUEUE (p->inputQueue, b);
 
if (p->bufferUsed == (sizeof(p->buffer) - 1))
b = '\r';
 
if (b == '\r' && p->bufferUsed)
{
p->buffer[p->bufferUsed] = 0;
Con_Printf("%s\n", p->buffer);
SCR_UpdateScreen ();
p->bufferUsed = 0;
return p->buffer;
}
 
if (b < ' ' || b > 'z')
continue;
p->buffer[p->bufferUsed] = b;
p->bufferUsed++;
}
 
return NULL;
}
 
 
static void Modem_Hangup2(ComPort *p);
static void Modem_Hangup3(ComPort *p);
static void Modem_Hangup4(ComPort *p);
 
static void Modem_Hangup(ComPort *p)
{
Con_Printf("Hanging up modem...\n");
disable();
p->modemRang = false;
p->outputQueue.head = p->outputQueue.tail = 0;
p->inputQueue.head = p->inputQueue.tail = 0;
outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) & ~MCR_DTR);
enable();
p->poll.procedure = Modem_Hangup2;
p->poll.arg = p;
SchedulePollProcedure(&p->poll, 1.5);
}
 
static void Modem_Hangup2(ComPort *p)
{
outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) | MCR_DTR);
Modem_Command(p, "+++");
p->poll.procedure = Modem_Hangup3;
SchedulePollProcedure(&p->poll, 1.5);
}
 
static void Modem_Hangup3(ComPort *p)
{
Modem_Command(p, p->shutdown);
p->poll.procedure = Modem_Hangup4;
SchedulePollProcedure(&p->poll, 1.5);
}
 
static void Modem_Hangup4(ComPort *p)
{
Modem_Response(p);
Con_Printf("Hangup complete\n");
p->modemConnected = false;
}
/contrib/other/sdlquake-1.0.9/net_dgrm.c
0,0 → 1,1390
/*
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.c
 
// This is enables a simple IP banning mechanism
#define BAN_TEST
 
#ifdef BAN_TEST
#if defined(_WIN32)
#include <windows.h>
#elif defined (NeXT)
#include <sys/socket.h>
#include <arpa/inet.h>
#else
#define AF_INET 2 /* internet */
struct in_addr
{
union
{
struct { unsigned char s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { unsigned short s_w1,s_w2; } S_un_w;
unsigned long S_addr;
} S_un;
};
#define s_addr S_un.S_addr /* can be used for most tcp & ip code */
struct sockaddr_in
{
short sin_family;
unsigned short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
char *inet_ntoa(struct in_addr in);
unsigned long inet_addr(const char *cp);
#endif
#endif // BAN_TEST
 
#include "quakedef.h"
#include "net_dgrm.h"
 
// these two macros are to make the code more readable
#define sfunc net_landrivers[sock->landriver]
#define dfunc net_landrivers[net_landriverlevel]
 
static int net_landriverlevel;
 
/* statistic counters */
int packetsSent = 0;
int packetsReSent = 0;
int packetsReceived = 0;
int receivedDuplicateCount = 0;
int shortPacketCount = 0;
int droppedDatagrams;
 
static int myDriverLevel;
 
struct
{
unsigned int length;
unsigned int sequence;
byte data[MAX_DATAGRAM];
} packetBuffer;
 
extern int m_return_state;
extern int m_state;
extern qboolean m_return_onerror;
extern char m_return_reason[32];
 
 
#ifdef DEBUG
char *StrAddr (struct qsockaddr *addr)
{
static char buf[34];
byte *p = (byte *)addr;
int n;
 
for (n = 0; n < 16; n++)
sprintf (buf + n * 2, "%02x", *p++);
return buf;
}
#endif
 
 
#ifdef BAN_TEST
unsigned long banAddr = 0x00000000;
unsigned long banMask = 0xffffffff;
 
void NET_Ban_f (void)
{
char addrStr [32];
char maskStr [32];
void (*print) (char *fmt, ...);
 
if (cmd_source == src_command)
{
if (!sv.active)
{
Cmd_ForwardToServer ();
return;
}
print = Con_Printf;
}
else
{
if (pr_global_struct->deathmatch && !host_client->privileged)
return;
print = SV_ClientPrintf;
}
 
switch (Cmd_Argc ())
{
case 1:
if (((struct in_addr *)&banAddr)->s_addr)
{
Q_strcpy(addrStr, inet_ntoa(*(struct in_addr *)&banAddr));
Q_strcpy(maskStr, inet_ntoa(*(struct in_addr *)&banMask));
print("Banning %s [%s]\n", addrStr, maskStr);
}
else
print("Banning not active\n");
break;
 
case 2:
if (Q_strcasecmp(Cmd_Argv(1), "off") == 0)
banAddr = 0x00000000;
else
banAddr = inet_addr(Cmd_Argv(1));
banMask = 0xffffffff;
break;
 
case 3:
banAddr = inet_addr(Cmd_Argv(1));
banMask = inet_addr(Cmd_Argv(2));
break;
 
default:
print("BAN ip_address [mask]\n");
break;
}
}
#endif
 
 
int Datagram_SendMessage (qsocket_t *sock, sizebuf_t *data)
{
unsigned int packetLen;
unsigned int dataLen;
unsigned int eom;
 
#ifdef DEBUG
if (data->cursize == 0)
Sys_Error("Datagram_SendMessage: zero length message\n");
 
if (data->cursize > NET_MAXMESSAGE)
Sys_Error("Datagram_SendMessage: message too big %u\n", data->cursize);
 
if (sock->canSend == false)
Sys_Error("SendMessage: called with canSend == false\n");
#endif
 
Q_memcpy(sock->sendMessage, data->data, data->cursize);
sock->sendMessageLength = data->cursize;
 
if (data->cursize <= MAX_DATAGRAM)
{
dataLen = data->cursize;
eom = NETFLAG_EOM;
}
else
{
dataLen = MAX_DATAGRAM;
eom = 0;
}
packetLen = NET_HEADERSIZE + dataLen;
 
packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom));
packetBuffer.sequence = BigLong(sock->sendSequence++);
Q_memcpy (packetBuffer.data, sock->sendMessage, dataLen);
 
sock->canSend = false;
 
if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1)
return -1;
 
sock->lastSendTime = net_time;
packetsSent++;
return 1;
}
 
 
int SendMessageNext (qsocket_t *sock)
{
unsigned int packetLen;
unsigned int dataLen;
unsigned int eom;
 
if (sock->sendMessageLength <= MAX_DATAGRAM)
{
dataLen = sock->sendMessageLength;
eom = NETFLAG_EOM;
}
else
{
dataLen = MAX_DATAGRAM;
eom = 0;
}
packetLen = NET_HEADERSIZE + dataLen;
 
packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom));
packetBuffer.sequence = BigLong(sock->sendSequence++);
Q_memcpy (packetBuffer.data, sock->sendMessage, dataLen);
 
sock->sendNext = false;
 
if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1)
return -1;
 
sock->lastSendTime = net_time;
packetsSent++;
return 1;
}
 
 
int ReSendMessage (qsocket_t *sock)
{
unsigned int packetLen;
unsigned int dataLen;
unsigned int eom;
 
if (sock->sendMessageLength <= MAX_DATAGRAM)
{
dataLen = sock->sendMessageLength;
eom = NETFLAG_EOM;
}
else
{
dataLen = MAX_DATAGRAM;
eom = 0;
}
packetLen = NET_HEADERSIZE + dataLen;
 
packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom));
packetBuffer.sequence = BigLong(sock->sendSequence - 1);
Q_memcpy (packetBuffer.data, sock->sendMessage, dataLen);
 
sock->sendNext = false;
 
if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1)
return -1;
 
sock->lastSendTime = net_time;
packetsReSent++;
return 1;
}
 
 
qboolean Datagram_CanSendMessage (qsocket_t *sock)
{
if (sock->sendNext)
SendMessageNext (sock);
 
return sock->canSend;
}
 
 
qboolean Datagram_CanSendUnreliableMessage (qsocket_t *sock)
{
return true;
}
 
 
int Datagram_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data)
{
int packetLen;
 
#ifdef DEBUG
if (data->cursize == 0)
Sys_Error("Datagram_SendUnreliableMessage: zero length message\n");
 
if (data->cursize > MAX_DATAGRAM)
Sys_Error("Datagram_SendUnreliableMessage: message too big %u\n", data->cursize);
#endif
 
packetLen = NET_HEADERSIZE + data->cursize;
 
packetBuffer.length = BigLong(packetLen | NETFLAG_UNRELIABLE);
packetBuffer.sequence = BigLong(sock->unreliableSendSequence++);
Q_memcpy (packetBuffer.data, data->data, data->cursize);
 
if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1)
return -1;
 
packetsSent++;
return 1;
}
 
 
int Datagram_GetMessage (qsocket_t *sock)
{
unsigned int length;
unsigned int flags;
int ret = 0;
struct qsockaddr readaddr;
unsigned int sequence;
unsigned int count;
 
if (!sock->canSend)
if ((net_time - sock->lastSendTime) > 1.0)
ReSendMessage (sock);
 
while(1)
{
length = sfunc.Read (sock->socket, (byte *)&packetBuffer, NET_DATAGRAMSIZE, &readaddr);
 
// if ((rand() & 255) > 220)
// continue;
 
if (length == 0)
break;
 
if (length == -1)
{
Con_Printf("Read error\n");
return -1;
}
 
if (sfunc.AddrCompare(&readaddr, &sock->addr) != 0)
{
#ifdef DEBUG
Con_DPrintf("Forged packet received\n");
Con_DPrintf("Expected: %s\n", StrAddr (&sock->addr));
Con_DPrintf("Received: %s\n", StrAddr (&readaddr));
#endif
continue;
}
 
if (length < NET_HEADERSIZE)
{
shortPacketCount++;
continue;
}
 
length = BigLong(packetBuffer.length);
flags = length & (~NETFLAG_LENGTH_MASK);
length &= NETFLAG_LENGTH_MASK;
 
if (flags & NETFLAG_CTL)
continue;
 
sequence = BigLong(packetBuffer.sequence);
packetsReceived++;
 
if (flags & NETFLAG_UNRELIABLE)
{
if (sequence < sock->unreliableReceiveSequence)
{
Con_DPrintf("Got a stale datagram\n");
ret = 0;
break;
}
if (sequence != sock->unreliableReceiveSequence)
{
count = sequence - sock->unreliableReceiveSequence;
droppedDatagrams += count;
Con_DPrintf("Dropped %u datagram(s)\n", count);
}
sock->unreliableReceiveSequence = sequence + 1;
 
length -= NET_HEADERSIZE;
 
SZ_Clear (&net_message);
SZ_Write (&net_message, packetBuffer.data, length);
 
ret = 2;
break;
}
 
if (flags & NETFLAG_ACK)
{
if (sequence != (sock->sendSequence - 1))
{
Con_DPrintf("Stale ACK received\n");
continue;
}
if (sequence == sock->ackSequence)
{
sock->ackSequence++;
if (sock->ackSequence != sock->sendSequence)
Con_DPrintf("ack sequencing error\n");
}
else
{
Con_DPrintf("Duplicate ACK received\n");
continue;
}
sock->sendMessageLength -= MAX_DATAGRAM;
if (sock->sendMessageLength > 0)
{
Q_memcpy(sock->sendMessage, sock->sendMessage+MAX_DATAGRAM, sock->sendMessageLength);
sock->sendNext = true;
}
else
{
sock->sendMessageLength = 0;
sock->canSend = true;
}
continue;
}
 
if (flags & NETFLAG_DATA)
{
packetBuffer.length = BigLong(NET_HEADERSIZE | NETFLAG_ACK);
packetBuffer.sequence = BigLong(sequence);
sfunc.Write (sock->socket, (byte *)&packetBuffer, NET_HEADERSIZE, &readaddr);
 
if (sequence != sock->receiveSequence)
{
receivedDuplicateCount++;
continue;
}
sock->receiveSequence++;
 
length -= NET_HEADERSIZE;
 
if (flags & NETFLAG_EOM)
{
SZ_Clear(&net_message);
SZ_Write(&net_message, sock->receiveMessage, sock->receiveMessageLength);
SZ_Write(&net_message, packetBuffer.data, length);
sock->receiveMessageLength = 0;
 
ret = 1;
break;
}
 
Q_memcpy(sock->receiveMessage + sock->receiveMessageLength, packetBuffer.data, length);
sock->receiveMessageLength += length;
continue;
}
}
 
if (sock->sendNext)
SendMessageNext (sock);
 
return ret;
}
 
 
void PrintStats(qsocket_t *s)
{
Con_Printf("canSend = %4u \n", s->canSend);
Con_Printf("sendSeq = %4u ", s->sendSequence);
Con_Printf("recvSeq = %4u \n", s->receiveSequence);
Con_Printf("\n");
}
 
void NET_Stats_f (void)
{
qsocket_t *s;
 
if (Cmd_Argc () == 1)
{
Con_Printf("unreliable messages sent = %i\n", unreliableMessagesSent);
Con_Printf("unreliable messages recv = %i\n", unreliableMessagesReceived);
Con_Printf("reliable messages sent = %i\n", messagesSent);
Con_Printf("reliable messages received = %i\n", messagesReceived);
Con_Printf("packetsSent = %i\n", packetsSent);
Con_Printf("packetsReSent = %i\n", packetsReSent);
Con_Printf("packetsReceived = %i\n", packetsReceived);
Con_Printf("receivedDuplicateCount = %i\n", receivedDuplicateCount);
Con_Printf("shortPacketCount = %i\n", shortPacketCount);
Con_Printf("droppedDatagrams = %i\n", droppedDatagrams);
}
else if (Q_strcmp(Cmd_Argv(1), "*") == 0)
{
for (s = net_activeSockets; s; s = s->next)
PrintStats(s);
for (s = net_freeSockets; s; s = s->next)
PrintStats(s);
}
else
{
for (s = net_activeSockets; s; s = s->next)
if (Q_strcasecmp(Cmd_Argv(1), s->address) == 0)
break;
if (s == NULL)
for (s = net_freeSockets; s; s = s->next)
if (Q_strcasecmp(Cmd_Argv(1), s->address) == 0)
break;
if (s == NULL)
return;
PrintStats(s);
}
}
 
 
static qboolean testInProgress = false;
static int testPollCount;
static int testDriver;
static int testSocket;
 
static void Test_Poll(void);
PollProcedure testPollProcedure = {NULL, 0.0, Test_Poll};
 
static void Test_Poll(void)
{
struct qsockaddr clientaddr;
int control;
int len;
char name[32];
char address[64];
int colors;
int frags;
int connectTime;
byte playerNumber;
 
net_landriverlevel = testDriver;
 
while (1)
{
len = dfunc.Read (testSocket, net_message.data, net_message.maxsize, &clientaddr);
if (len < sizeof(int))
break;
 
net_message.cursize = len;
 
MSG_BeginReading ();
control = BigLong(*((int *)net_message.data));
MSG_ReadLong();
if (control == -1)
break;
if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL)
break;
if ((control & NETFLAG_LENGTH_MASK) != len)
break;
 
if (MSG_ReadByte() != CCREP_PLAYER_INFO)
Sys_Error("Unexpected repsonse to Player Info request\n");
 
playerNumber = MSG_ReadByte();
Q_strcpy(name, MSG_ReadString());
colors = MSG_ReadLong();
frags = MSG_ReadLong();
connectTime = MSG_ReadLong();
Q_strcpy(address, MSG_ReadString());
 
Con_Printf("%s\n frags:%3i colors:%u %u time:%u\n %s\n", name, frags, colors >> 4, colors & 0x0f, connectTime / 60, address);
}
 
testPollCount--;
if (testPollCount)
{
SchedulePollProcedure(&testPollProcedure, 0.1);
}
else
{
dfunc.CloseSocket(testSocket);
testInProgress = false;
}
}
 
static void Test_f (void)
{
char *host;
int n;
int max = MAX_SCOREBOARD;
struct qsockaddr sendaddr;
 
if (testInProgress)
return;
 
host = Cmd_Argv (1);
 
if (host && hostCacheCount)
{
for (n = 0; n < hostCacheCount; n++)
if (Q_strcasecmp (host, hostcache[n].name) == 0)
{
if (hostcache[n].driver != myDriverLevel)
continue;
net_landriverlevel = hostcache[n].ldriver;
max = hostcache[n].maxusers;
Q_memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr));
break;
}
if (n < hostCacheCount)
goto JustDoIt;
}
 
for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
{
if (!net_landrivers[net_landriverlevel].initialized)
continue;
 
// see if we can resolve the host name
if (dfunc.GetAddrFromName(host, &sendaddr) != -1)
break;
}
if (net_landriverlevel == net_numlandrivers)
return;
 
JustDoIt:
testSocket = dfunc.OpenSocket(0);
if (testSocket == -1)
return;
 
testInProgress = true;
testPollCount = 20;
testDriver = net_landriverlevel;
 
for (n = 0; n < max; n++)
{
SZ_Clear(&net_message);
// save space for the header, filled in later
MSG_WriteLong(&net_message, 0);
MSG_WriteByte(&net_message, CCREQ_PLAYER_INFO);
MSG_WriteByte(&net_message, n);
*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
dfunc.Write (testSocket, net_message.data, net_message.cursize, &sendaddr);
}
SZ_Clear(&net_message);
SchedulePollProcedure(&testPollProcedure, 0.1);
}
 
 
static qboolean test2InProgress = false;
static int test2Driver;
static int test2Socket;
 
static void Test2_Poll(void);
PollProcedure test2PollProcedure = {NULL, 0.0, Test2_Poll};
 
static void Test2_Poll(void)
{
struct qsockaddr clientaddr;
int control;
int len;
char name[256];
char value[256];
 
net_landriverlevel = test2Driver;
name[0] = 0;
 
len = dfunc.Read (test2Socket, net_message.data, net_message.maxsize, &clientaddr);
if (len < sizeof(int))
goto Reschedule;
 
net_message.cursize = len;
 
MSG_BeginReading ();
control = BigLong(*((int *)net_message.data));
MSG_ReadLong();
if (control == -1)
goto Error;
if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL)
goto Error;
if ((control & NETFLAG_LENGTH_MASK) != len)
goto Error;
 
if (MSG_ReadByte() != CCREP_RULE_INFO)
goto Error;
 
Q_strcpy(name, MSG_ReadString());
if (name[0] == 0)
goto Done;
Q_strcpy(value, MSG_ReadString());
 
Con_Printf("%-16.16s %-16.16s\n", name, value);
 
SZ_Clear(&net_message);
// save space for the header, filled in later
MSG_WriteLong(&net_message, 0);
MSG_WriteByte(&net_message, CCREQ_RULE_INFO);
MSG_WriteString(&net_message, name);
*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
dfunc.Write (test2Socket, net_message.data, net_message.cursize, &clientaddr);
SZ_Clear(&net_message);
 
Reschedule:
SchedulePollProcedure(&test2PollProcedure, 0.05);
return;
 
Error:
Con_Printf("Unexpected repsonse to Rule Info request\n");
Done:
dfunc.CloseSocket(test2Socket);
test2InProgress = false;
return;
}
 
static void Test2_f (void)
{
char *host;
int n;
struct qsockaddr sendaddr;
 
if (test2InProgress)
return;
 
host = Cmd_Argv (1);
 
if (host && hostCacheCount)
{
for (n = 0; n < hostCacheCount; n++)
if (Q_strcasecmp (host, hostcache[n].name) == 0)
{
if (hostcache[n].driver != myDriverLevel)
continue;
net_landriverlevel = hostcache[n].ldriver;
Q_memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr));
break;
}
if (n < hostCacheCount)
goto JustDoIt;
}
 
for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
{
if (!net_landrivers[net_landriverlevel].initialized)
continue;
 
// see if we can resolve the host name
if (dfunc.GetAddrFromName(host, &sendaddr) != -1)
break;
}
if (net_landriverlevel == net_numlandrivers)
return;
 
JustDoIt:
test2Socket = dfunc.OpenSocket(0);
if (test2Socket == -1)
return;
 
test2InProgress = true;
test2Driver = net_landriverlevel;
 
SZ_Clear(&net_message);
// save space for the header, filled in later
MSG_WriteLong(&net_message, 0);
MSG_WriteByte(&net_message, CCREQ_RULE_INFO);
MSG_WriteString(&net_message, "");
*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
dfunc.Write (test2Socket, net_message.data, net_message.cursize, &sendaddr);
SZ_Clear(&net_message);
SchedulePollProcedure(&test2PollProcedure, 0.05);
}
 
 
int Datagram_Init (void)
{
int i;
int csock;
 
myDriverLevel = net_driverlevel;
Cmd_AddCommand ("net_stats", NET_Stats_f);
 
if (COM_CheckParm("-nolan"))
return -1;
 
for (i = 0; i < net_numlandrivers; i++)
{
csock = net_landrivers[i].Init ();
if (csock == -1)
continue;
net_landrivers[i].initialized = true;
net_landrivers[i].controlSock = csock;
}
 
#ifdef BAN_TEST
Cmd_AddCommand ("ban", NET_Ban_f);
#endif
Cmd_AddCommand ("test", Test_f);
Cmd_AddCommand ("test2", Test2_f);
 
return 0;
}
 
 
void Datagram_Shutdown (void)
{
int i;
 
//
// shutdown the lan drivers
//
for (i = 0; i < net_numlandrivers; i++)
{
if (net_landrivers[i].initialized)
{
net_landrivers[i].Shutdown ();
net_landrivers[i].initialized = false;
}
}
}
 
 
void Datagram_Close (qsocket_t *sock)
{
sfunc.CloseSocket(sock->socket);
}
 
 
void Datagram_Listen (qboolean state)
{
int i;
 
for (i = 0; i < net_numlandrivers; i++)
if (net_landrivers[i].initialized)
net_landrivers[i].Listen (state);
}
 
 
static qsocket_t *_Datagram_CheckNewConnections (void)
{
struct qsockaddr clientaddr;
struct qsockaddr newaddr;
int newsock;
int acceptsock;
qsocket_t *sock;
qsocket_t *s;
int len;
int command;
int control;
int ret;
 
acceptsock = dfunc.CheckNewConnections();
if (acceptsock == -1)
return NULL;
 
SZ_Clear(&net_message);
 
len = dfunc.Read (acceptsock, net_message.data, net_message.maxsize, &clientaddr);
if (len < sizeof(int))
return NULL;
net_message.cursize = len;
 
MSG_BeginReading ();
control = BigLong(*((int *)net_message.data));
MSG_ReadLong();
if (control == -1)
return NULL;
if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL)
return NULL;
if ((control & NETFLAG_LENGTH_MASK) != len)
return NULL;
 
command = MSG_ReadByte();
if (command == CCREQ_SERVER_INFO)
{
if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0)
return NULL;
 
SZ_Clear(&net_message);
// save space for the header, filled in later
MSG_WriteLong(&net_message, 0);
MSG_WriteByte(&net_message, CCREP_SERVER_INFO);
dfunc.GetSocketAddr(acceptsock, &newaddr);
MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr));
MSG_WriteString(&net_message, hostname.string);
MSG_WriteString(&net_message, sv.name);
MSG_WriteByte(&net_message, net_activeconnections);
MSG_WriteByte(&net_message, svs.maxclients);
MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
SZ_Clear(&net_message);
return NULL;
}
 
if (command == CCREQ_PLAYER_INFO)
{
int playerNumber;
int activeNumber;
int clientNumber;
client_t *client;
playerNumber = MSG_ReadByte();
activeNumber = -1;
for (clientNumber = 0, client = svs.clients; clientNumber < svs.maxclients; clientNumber++, client++)
{
if (client->active)
{
activeNumber++;
if (activeNumber == playerNumber)
break;
}
}
if (clientNumber == svs.maxclients)
return NULL;
 
SZ_Clear(&net_message);
// save space for the header, filled in later
MSG_WriteLong(&net_message, 0);
MSG_WriteByte(&net_message, CCREP_PLAYER_INFO);
MSG_WriteByte(&net_message, playerNumber);
MSG_WriteString(&net_message, client->name);
MSG_WriteLong(&net_message, client->colors);
MSG_WriteLong(&net_message, (int)client->edict->v.frags);
MSG_WriteLong(&net_message, (int)(net_time - client->netconnection->connecttime));
MSG_WriteString(&net_message, client->netconnection->address);
*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
SZ_Clear(&net_message);
 
return NULL;
}
 
if (command == CCREQ_RULE_INFO)
{
char *prevCvarName;
cvar_t *var;
 
// find the search start location
prevCvarName = MSG_ReadString();
if (*prevCvarName)
{
var = Cvar_FindVar (prevCvarName);
if (!var)
return NULL;
var = var->next;
}
else
var = cvar_vars;
 
// search for the next server cvar
while (var)
{
if (var->server)
break;
var = var->next;
}
 
// send the response
 
SZ_Clear(&net_message);
// save space for the header, filled in later
MSG_WriteLong(&net_message, 0);
MSG_WriteByte(&net_message, CCREP_RULE_INFO);
if (var)
{
MSG_WriteString(&net_message, var->name);
MSG_WriteString(&net_message, var->string);
}
*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
SZ_Clear(&net_message);
 
return NULL;
}
 
if (command != CCREQ_CONNECT)
return NULL;
 
if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0)
return NULL;
 
if (MSG_ReadByte() != NET_PROTOCOL_VERSION)
{
SZ_Clear(&net_message);
// save space for the header, filled in later
MSG_WriteLong(&net_message, 0);
MSG_WriteByte(&net_message, CCREP_REJECT);
MSG_WriteString(&net_message, "Incompatible version.\n");
*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
SZ_Clear(&net_message);
return NULL;
}
 
#ifdef BAN_TEST
// check for a ban
if (clientaddr.sa_family == AF_INET)
{
unsigned long testAddr;
testAddr = ((struct sockaddr_in *)&clientaddr)->sin_addr.s_addr;
if ((testAddr & banMask) == banAddr)
{
SZ_Clear(&net_message);
// save space for the header, filled in later
MSG_WriteLong(&net_message, 0);
MSG_WriteByte(&net_message, CCREP_REJECT);
MSG_WriteString(&net_message, "You have been banned.\n");
*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
SZ_Clear(&net_message);
return NULL;
}
}
#endif
 
// see if this guy is already connected
for (s = net_activeSockets; s; s = s->next)
{
if (s->driver != net_driverlevel)
continue;
ret = dfunc.AddrCompare(&clientaddr, &s->addr);
if (ret >= 0)
{
// is this a duplicate connection reqeust?
if (ret == 0 && net_time - s->connecttime < 2.0)
{
// yes, so send a duplicate reply
SZ_Clear(&net_message);
// save space for the header, filled in later
MSG_WriteLong(&net_message, 0);
MSG_WriteByte(&net_message, CCREP_ACCEPT);
dfunc.GetSocketAddr(s->socket, &newaddr);
MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr));
*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
SZ_Clear(&net_message);
return NULL;
}
// it's somebody coming back in from a crash/disconnect
// so close the old qsocket and let their retry get them back in
NET_Close(s);
return NULL;
}
}
 
// allocate a QSocket
sock = NET_NewQSocket ();
if (sock == NULL)
{
// no room; try to let him know
SZ_Clear(&net_message);
// save space for the header, filled in later
MSG_WriteLong(&net_message, 0);
MSG_WriteByte(&net_message, CCREP_REJECT);
MSG_WriteString(&net_message, "Server is full.\n");
*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
SZ_Clear(&net_message);
return NULL;
}
 
// allocate a network socket
newsock = dfunc.OpenSocket(0);
if (newsock == -1)
{
NET_FreeQSocket(sock);
return NULL;
}
 
// connect to the client
if (dfunc.Connect (newsock, &clientaddr) == -1)
{
dfunc.CloseSocket(newsock);
NET_FreeQSocket(sock);
return NULL;
}
 
// everything is allocated, just fill in the details
sock->socket = newsock;
sock->landriver = net_landriverlevel;
sock->addr = clientaddr;
Q_strcpy(sock->address, dfunc.AddrToString(&clientaddr));
 
// send him back the info about the server connection he has been allocated
SZ_Clear(&net_message);
// save space for the header, filled in later
MSG_WriteLong(&net_message, 0);
MSG_WriteByte(&net_message, CCREP_ACCEPT);
dfunc.GetSocketAddr(newsock, &newaddr);
MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr));
// MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr));
*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
SZ_Clear(&net_message);
 
return sock;
}
 
qsocket_t *Datagram_CheckNewConnections (void)
{
qsocket_t *ret = NULL;
 
for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
if (net_landrivers[net_landriverlevel].initialized)
if ((ret = _Datagram_CheckNewConnections ()) != NULL)
break;
return ret;
}
 
 
static void _Datagram_SearchForHosts (qboolean xmit)
{
int ret;
int n;
int i;
struct qsockaddr readaddr;
struct qsockaddr myaddr;
int control;
 
dfunc.GetSocketAddr (dfunc.controlSock, &myaddr);
if (xmit)
{
SZ_Clear(&net_message);
// save space for the header, filled in later
MSG_WriteLong(&net_message, 0);
MSG_WriteByte(&net_message, CCREQ_SERVER_INFO);
MSG_WriteString(&net_message, "QUAKE");
MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
dfunc.Broadcast(dfunc.controlSock, net_message.data, net_message.cursize);
SZ_Clear(&net_message);
}
 
while ((ret = dfunc.Read (dfunc.controlSock, net_message.data, net_message.maxsize, &readaddr)) > 0)
{
if (ret < sizeof(int))
continue;
net_message.cursize = ret;
 
// don't answer our own query
if (dfunc.AddrCompare(&readaddr, &myaddr) >= 0)
continue;
 
// is the cache full?
if (hostCacheCount == HOSTCACHESIZE)
continue;
 
MSG_BeginReading ();
control = BigLong(*((int *)net_message.data));
MSG_ReadLong();
if (control == -1)
continue;
if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL)
continue;
if ((control & NETFLAG_LENGTH_MASK) != ret)
continue;
 
if (MSG_ReadByte() != CCREP_SERVER_INFO)
continue;
 
dfunc.GetAddrFromName(MSG_ReadString(), &readaddr);
// search the cache for this server
for (n = 0; n < hostCacheCount; n++)
if (dfunc.AddrCompare(&readaddr, &hostcache[n].addr) == 0)
break;
 
// is it already there?
if (n < hostCacheCount)
continue;
 
// add it
hostCacheCount++;
Q_strcpy(hostcache[n].name, MSG_ReadString());
Q_strcpy(hostcache[n].map, MSG_ReadString());
hostcache[n].users = MSG_ReadByte();
hostcache[n].maxusers = MSG_ReadByte();
if (MSG_ReadByte() != NET_PROTOCOL_VERSION)
{
Q_strcpy(hostcache[n].cname, hostcache[n].name);
hostcache[n].cname[14] = 0;
Q_strcpy(hostcache[n].name, "*");
Q_strcat(hostcache[n].name, hostcache[n].cname);
}
Q_memcpy(&hostcache[n].addr, &readaddr, sizeof(struct qsockaddr));
hostcache[n].driver = net_driverlevel;
hostcache[n].ldriver = net_landriverlevel;
Q_strcpy(hostcache[n].cname, dfunc.AddrToString(&readaddr));
 
// check for a name conflict
for (i = 0; i < hostCacheCount; i++)
{
if (i == n)
continue;
if (Q_strcasecmp (hostcache[n].name, hostcache[i].name) == 0)
{
i = Q_strlen(hostcache[n].name);
if (i < 15 && hostcache[n].name[i-1] > '8')
{
hostcache[n].name[i] = '0';
hostcache[n].name[i+1] = 0;
}
else
hostcache[n].name[i-1]++;
i = -1;
}
}
}
}
 
void Datagram_SearchForHosts (qboolean xmit)
{
for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
{
if (hostCacheCount == HOSTCACHESIZE)
break;
if (net_landrivers[net_landriverlevel].initialized)
_Datagram_SearchForHosts (xmit);
}
}
 
 
static qsocket_t *_Datagram_Connect (char *host)
{
struct qsockaddr sendaddr;
struct qsockaddr readaddr;
qsocket_t *sock;
int newsock;
int ret;
int reps;
double start_time;
int control;
char *reason;
 
// see if we can resolve the host name
if (dfunc.GetAddrFromName(host, &sendaddr) == -1)
return NULL;
 
newsock = dfunc.OpenSocket (0);
if (newsock == -1)
return NULL;
 
sock = NET_NewQSocket ();
if (sock == NULL)
goto ErrorReturn2;
sock->socket = newsock;
sock->landriver = net_landriverlevel;
 
// connect to the host
if (dfunc.Connect (newsock, &sendaddr) == -1)
goto ErrorReturn;
 
// send the connection request
Con_Printf("trying...\n"); SCR_UpdateScreen ();
start_time = net_time;
 
for (reps = 0; reps < 3; reps++)
{
SZ_Clear(&net_message);
// save space for the header, filled in later
MSG_WriteLong(&net_message, 0);
MSG_WriteByte(&net_message, CCREQ_CONNECT);
MSG_WriteString(&net_message, "QUAKE");
MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
dfunc.Write (newsock, net_message.data, net_message.cursize, &sendaddr);
SZ_Clear(&net_message);
do
{
ret = dfunc.Read (newsock, net_message.data, net_message.maxsize, &readaddr);
// if we got something, validate it
if (ret > 0)
{
// is it from the right place?
if (sfunc.AddrCompare(&readaddr, &sendaddr) != 0)
{
#ifdef DEBUG
Con_Printf("wrong reply address\n");
Con_Printf("Expected: %s\n", StrAddr (&sendaddr));
Con_Printf("Received: %s\n", StrAddr (&readaddr));
SCR_UpdateScreen ();
#endif
ret = 0;
continue;
}
 
if (ret < sizeof(int))
{
ret = 0;
continue;
}
 
net_message.cursize = ret;
MSG_BeginReading ();
 
control = BigLong(*((int *)net_message.data));
MSG_ReadLong();
if (control == -1)
{
ret = 0;
continue;
}
if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL)
{
ret = 0;
continue;
}
if ((control & NETFLAG_LENGTH_MASK) != ret)
{
ret = 0;
continue;
}
}
}
while (ret == 0 && (SetNetTime() - start_time) < 2.5);
if (ret)
break;
Con_Printf("still trying...\n"); SCR_UpdateScreen ();
start_time = SetNetTime();
}
 
if (ret == 0)
{
reason = "No Response";
Con_Printf("%s\n", reason);
Q_strcpy(m_return_reason, reason);
goto ErrorReturn;
}
 
if (ret == -1)
{
reason = "Network Error";
Con_Printf("%s\n", reason);
Q_strcpy(m_return_reason, reason);
goto ErrorReturn;
}
 
ret = MSG_ReadByte();
if (ret == CCREP_REJECT)
{
reason = MSG_ReadString();
Con_Printf(reason);
Q_strncpy(m_return_reason, reason, 31);
goto ErrorReturn;
}
 
if (ret == CCREP_ACCEPT)
{
Q_memcpy(&sock->addr, &sendaddr, sizeof(struct qsockaddr));
dfunc.SetSocketPort (&sock->addr, MSG_ReadLong());
}
else
{
reason = "Bad Response";
Con_Printf("%s\n", reason);
Q_strcpy(m_return_reason, reason);
goto ErrorReturn;
}
 
dfunc.GetNameFromAddr (&sendaddr, sock->address);
 
Con_Printf ("Connection accepted\n");
sock->lastMessageTime = SetNetTime();
 
// switch the connection to the specified address
if (dfunc.Connect (newsock, &sock->addr) == -1)
{
reason = "Connect to Game failed";
Con_Printf("%s\n", reason);
Q_strcpy(m_return_reason, reason);
goto ErrorReturn;
}
 
m_return_onerror = false;
return sock;
 
ErrorReturn:
NET_FreeQSocket(sock);
ErrorReturn2:
dfunc.CloseSocket(newsock);
if (m_return_onerror)
{
key_dest = key_menu;
m_state = m_return_state;
m_return_onerror = false;
}
return NULL;
}
 
qsocket_t *Datagram_Connect (char *host)
{
qsocket_t *ret = NULL;
 
for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
if (net_landrivers[net_landriverlevel].initialized)
if ((ret = _Datagram_Connect (host)) != NULL)
break;
return ret;
}
/contrib/other/sdlquake-1.0.9/net_dgrm.h
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);
/contrib/other/sdlquake-1.0.9/net_dos.c
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.
 
*/
#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
}
,
{
"Serial",
false,
Serial_Init,
Serial_Listen,
Serial_SearchForHosts,
Serial_Connect,
Serial_CheckNewConnections,
Serial_GetMessage,
Serial_SendMessage,
Serial_SendUnreliableMessage,
Serial_CanSendMessage,
Serial_CanSendUnreliableMessage,
Serial_Close,
Serial_Shutdown
}
};
 
int net_numdrivers = 3;
 
 
#include "net_bw.h"
#include "net_ipx.h"
#include "net_mp.h"
 
net_landriver_t net_landrivers[MAX_NET_DRIVERS] =
{
{
"Beame & Whiteside TCP/IP",
false,
0,
BW_Init,
BW_Shutdown,
BW_Listen,
BW_OpenSocket,
BW_CloseSocket,
BW_Connect,
BW_CheckNewConnections,
BW_Read,
BW_Write,
BW_Broadcast,
BW_AddrToString,
BW_StringToAddr,
BW_GetSocketAddr,
BW_GetNameFromAddr,
BW_GetAddrFromName,
BW_AddrCompare,
BW_GetSocketPort,
BW_SetSocketPort
}
,
{
"IPX",
false,
0,
IPX_Init,
IPX_Shutdown,
IPX_Listen,
IPX_OpenSocket,
IPX_CloseSocket,
IPX_Connect,
IPX_CheckNewConnections,
IPX_Read,
IPX_Write,
IPX_Broadcast,
IPX_AddrToString,
IPX_StringToAddr,
IPX_GetSocketAddr,
IPX_GetNameFromAddr,
IPX_GetAddrFromName,
IPX_AddrCompare,
IPX_GetSocketPort,
IPX_SetSocketPort
}
,
{
"Win95 TCP/IP",
false,
0,
MPATH_Init,
MPATH_Shutdown,
MPATH_Listen,
MPATH_OpenSocket,
MPATH_CloseSocket,
MPATH_Connect,
MPATH_CheckNewConnections,
MPATH_Read,
MPATH_Write,
MPATH_Broadcast,
MPATH_AddrToString,
MPATH_StringToAddr,
MPATH_GetSocketAddr,
MPATH_GetNameFromAddr,
MPATH_GetAddrFromName,
MPATH_AddrCompare,
MPATH_GetSocketPort,
MPATH_SetSocketPort
}
};
 
int net_numlandrivers = 3;
/contrib/other/sdlquake-1.0.9/net_ipx.c
0,0 → 1,706
/*
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_ipx.c
 
#include <stdio.h>
#include <stdlib.h>
#include <dpmi.h>
 
#include "quakedef.h"
#include "dosisms.h"
#include "net_ipx.h"
 
#define EIO 5 /* I/O error */
 
#define AF_NETWARE 64
 
#define IPX_OPEN 0
#define IPX_CLOSE 1
#define IPX_GETROUTE 2
#define IPX_SEND 3
#define IPX_LISTEN 4
#define IPX_SCHEDULEEVENT 5
#define IPX_CANCEL 6
#define IPX_SCHEDULESPECIALEVENT 7
#define IPX_GETINTERVALMARKER 8
#define IPX_GETADDRESS 9
#define IPX_RELINQUISH 10
 
#define PTYPE_UNKNOWN 0
#define PTYPE_RIP 1
#define PTYPE_ECHO 2
#define PTYPE_ERROR 3
#define PTYPE_IPX 4
#define PTYPE_SPX 5
 
#pragma pack(1)
 
typedef struct
{
byte network[4];
byte node[6];
short socket;
} IPXaddr;
 
struct sockaddr_ipx
{
short sipx_family;
IPXaddr sipx_addr;
char sipx_zero[2];
};
#define sipx_port sipx_addr.socket
 
typedef struct
{
short checkSum;
short length;
byte transportControl;
byte type;
IPXaddr destination;
IPXaddr source;
} IPXheader;
 
typedef struct ECBStructure
{
struct ECBStructure *link;
unsigned short ESR_off;
unsigned short ESR_seg;
byte inUse;
byte completionCode;
short socket;
byte IPXWorkspace[4];
byte driverWorkspace[12];
byte immediateAddress[6];
short fragCount;
short fragOff;
short fragSeg;
short fragSize;
} ECB;
 
#pragma pack()
 
typedef struct
{
ECB ecb;
IPXheader header;
int sequence;
char data[NET_DATAGRAMSIZE];
} ipx_lowmem_buffer_t;
 
#define LOWMEMSIZE (100 * 1024)
#define LOWMEMSAVE 256
#define IPXBUFFERS ((LOWMEMSIZE - LOWMEMSAVE)/ sizeof(ipx_lowmem_buffer_t))
#define IPXSOCKBUFFERS 5
#define IPXSOCKETS (IPXBUFFERS / IPXSOCKBUFFERS)
 
// each socket's socketbuffer 0 is used for sending, the others for listening
 
typedef struct
{
char reserved[LOWMEMSAVE];
ipx_lowmem_buffer_t socketbuffer[IPXSOCKETS][IPXSOCKBUFFERS];
} ipx_lowmem_area_t;
 
 
static int ipxsocket[IPXSOCKETS];
static ECB *readlist[IPXSOCKETS];
static int sequence[IPXSOCKETS];
static int handlesInUse;
static ipx_lowmem_area_t *lma;
static char *lowmem_buffer;
static int lowmem_bufseg;
static int lowmem_bufoff;
static unsigned short ipx_cs;
static unsigned short ipx_ip;
static int net_acceptsocket = -1;
static int net_controlsocket;
 
static void IPX_PollProcedure(void);
static PollProcedure pollProcedure = {NULL, 0.0, IPX_PollProcedure};
 
//=============================================================================
 
static void IPX_GetLocalAddress(IPXaddr *addr)
{
regs.x.cs = ipx_cs;
regs.x.ip = ipx_ip;
regs.x.bx = IPX_GETADDRESS;
regs.x.es = lowmem_bufseg;
regs.x.si = lowmem_bufoff;
__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
Q_memcpy(addr, lowmem_buffer, 10);
}
 
//=============================================================================
 
static int IPX_GetLocalTarget(IPXaddr *addr, byte *localTarget)
{
regs.x.cs = ipx_cs;
regs.x.ip = ipx_ip;
regs.x.bx = IPX_GETROUTE;
regs.x.es = lowmem_bufseg;
regs.x.si = lowmem_bufoff;
regs.x.di = lowmem_bufoff + sizeof(IPXaddr);
Q_memcpy(lowmem_buffer, addr, sizeof(IPXaddr));
__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
if (regs.h.al)
return -1;
Q_memcpy(localTarget, lowmem_buffer + sizeof(IPXaddr), 6);
return 0;
}
 
//=============================================================================
 
static void IPX_ListenForPacket(ECB *ecb)
{
regs.x.cs = ipx_cs;
regs.x.ip = ipx_ip;
regs.x.bx = IPX_LISTEN;
regs.x.es = ptr2real(ecb) >> 4;
regs.x.si = ptr2real(ecb) & 0xf;
__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
}
 
//=============================================================================
 
static void IPX_RelinquishControl(void)
{
regs.x.cs = ipx_cs;
regs.x.ip = ipx_ip;
regs.x.bx = IPX_RELINQUISH;
__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
}
 
 
void IPX_PollProcedure(void)
{
IPX_RelinquishControl();
SchedulePollProcedure(&pollProcedure, 0.01);
}
 
//=============================================================================
 
static void ProcessReadyList(int s)
{
int n;
ECB *ecb;
ECB *prev;
 
for (n = 1; n < IPXSOCKBUFFERS; n++)
{
if (lma->socketbuffer[s][n].ecb.inUse == 0)
{
for (ecb = readlist[s], prev = NULL; ecb; ecb = ecb->link)
{
if (lma->socketbuffer[s][n].sequence < ((ipx_lowmem_buffer_t *) ecb)->sequence)
break;
prev = ecb;
}
if (ecb)
lma->socketbuffer[s][n].ecb.link = ecb;
else
lma->socketbuffer[s][n].ecb.link = NULL;
if (prev)
prev->link = &lma->socketbuffer[s][n].ecb;
else
readlist[s] = &lma->socketbuffer[s][n].ecb;
lma->socketbuffer[s][n].ecb.inUse = 0xff;
}
}
}
 
//=============================================================================
 
int IPX_Init(void)
{
int s;
int n;
struct qsockaddr addr;
char *colon;
 
if (COM_CheckParm ("-noipx"))
return -1;
 
// find the IPX far call entry point
regs.x.ax = 0x7a00;
__dpmi_simulate_real_mode_interrupt (0x2f, (__dpmi_regs *)&regs);
if (regs.h.al != 0xff)
{
Con_Printf("IPX not detected\n");
return -1;
}
ipx_cs = regs.x.es;
ipx_ip = regs.x.di;
 
// grab a chunk of memory down in DOS land
lowmem_buffer = dos_getmemory(LOWMEMSIZE);
if (!lowmem_buffer)
{
Con_Printf("IPX_Init: Not enough low memory\n");
return -1;
}
lowmem_bufoff = ptr2real(lowmem_buffer) & 0xf;
lowmem_bufseg = ptr2real(lowmem_buffer) >> 4;
 
// init socket handles & buffers
handlesInUse = 0;
lma = (ipx_lowmem_area_t *)lowmem_buffer;
for (s = 0; s < IPXSOCKETS; s++)
{
ipxsocket[s] = 0;
for (n = 0; n < IPXSOCKBUFFERS; n++)
{
lma->socketbuffer[s][n].ecb.link = NULL;
lma->socketbuffer[s][n].ecb.ESR_off = 0;
lma->socketbuffer[s][n].ecb.ESR_seg = 0;
lma->socketbuffer[s][n].ecb.socket = 0;
lma->socketbuffer[s][n].ecb.inUse = 0xff;
lma->socketbuffer[s][n].ecb.completionCode = 0;
lma->socketbuffer[s][n].ecb.fragCount = 1;
lma->socketbuffer[s][n].ecb.fragOff = ptr2real(&lma->socketbuffer[s][n].header) & 0xf;
lma->socketbuffer[s][n].ecb.fragSeg = ptr2real(&lma->socketbuffer[s][n].header) >> 4;
lma->socketbuffer[s][n].ecb.fragSize = sizeof(IPXheader) + sizeof(int) + NET_DATAGRAMSIZE;
}
}
 
if ((net_controlsocket = IPX_OpenSocket (0)) == -1)
{
dos_freememory(lowmem_buffer);
Con_DPrintf ("IPX_Init: Unable to open control socket\n");
return -1;
}
 
SchedulePollProcedure(&pollProcedure, 0.01);
 
IPX_GetSocketAddr (net_controlsocket, &addr);
Q_strcpy(my_ipx_address, IPX_AddrToString (&addr));
colon = Q_strrchr (my_ipx_address, ':');
if (colon)
*colon = 0;
 
Con_Printf("IPX initialized\n");
ipxAvailable = true;
return net_controlsocket;
}
 
//=============================================================================
 
void IPX_Shutdown(void)
{
IPX_Listen (false);
IPX_CloseSocket (net_controlsocket);
dos_freememory(lowmem_buffer);
}
 
//=============================================================================
 
void IPX_Listen (qboolean state)
{
// enable listening
if (state)
{
if (net_acceptsocket != -1)
return;
if ((net_acceptsocket = IPX_OpenSocket (net_hostport)) == -1)
Sys_Error ("IPX_Listen: Unable to open accept socket\n");
return;
}
 
// disable listening
if (net_acceptsocket == -1)
return;
IPX_CloseSocket (net_acceptsocket);
net_acceptsocket = -1;
}
 
//=============================================================================
 
int IPX_OpenSocket(int port)
{
int handle;
int n;
unsigned short socket;
 
if (handlesInUse == IPXSOCKETS)
return -1;
 
// open the IPX socket
regs.x.cs = ipx_cs;
regs.x.ip = ipx_ip;
regs.x.bx = IPX_OPEN;
regs.h.al = 0;
regs.x.dx = htons(port);
__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
if (regs.h.al == 0xfe)
{
Con_DPrintf("IPX_OpenSocket: all sockets in use\n");
return -1;
}
if (regs.h.al == 0xff)
{
Con_DPrintf("IPX_OpenSocket: socket already open\n");
return -1;
}
if (regs.h.al != 0)
{
Con_DPrintf("IPX_OpenSocket: error %02x\n", regs.h.al);
return -1;
}
socket = regs.x.dx;
 
// grab a handle; fill in the ECBs, and get them listening
for (handle = 0; handle < IPXSOCKETS; handle++)
{
if (ipxsocket[handle] == 0)
{
ipxsocket[handle] = socket;
readlist[handle] = NULL;
sequence[handle] = 0;
for (n = 0; n < IPXSOCKBUFFERS; n ++)
{
lma->socketbuffer[handle][n].ecb.socket = socket;
lma->socketbuffer[handle][n].ecb.inUse = 0;
if (n)
IPX_ListenForPacket(&lma->socketbuffer[handle][n].ecb);
}
handlesInUse++;
return handle;
}
}
 
// "this will NEVER happen"
Sys_Error("IPX_OpenSocket: handle allocation failed\n");
return -1;
}
 
//=============================================================================
 
int IPX_CloseSocket(int handle)
{
// if there's a send in progress, give it one last chance
if (lma->socketbuffer[handle][0].ecb.inUse != 0)
IPX_RelinquishControl();
 
// close the socket (all pending sends/received are cancelled)
regs.x.cs = ipx_cs;
regs.x.ip = ipx_ip;
regs.x.bx = IPX_CLOSE;
regs.x.dx = ipxsocket[handle];
__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
 
ipxsocket[handle] = 0;
handlesInUse--;
 
return 0;
}
 
//=============================================================================
 
int IPX_Connect (int handle, struct qsockaddr *addr)
{
IPXaddr ipxaddr;
 
Q_memcpy(&ipxaddr, &((struct sockaddr_ipx *)addr)->sipx_addr, sizeof(IPXaddr));
if (IPX_GetLocalTarget(&ipxaddr, lma->socketbuffer[handle][0].ecb.immediateAddress) != 0)
{
Con_Printf("Get Local Target failed\n");
return -1;
}
 
return 0;
}
 
//=============================================================================
 
int IPX_CheckNewConnections (void)
{
int n;
 
if (net_acceptsocket == -1)
return -1;
 
for (n = 1; n < IPXSOCKBUFFERS; n ++)
if (lma->socketbuffer[net_acceptsocket][n].ecb.inUse == 0)
return net_acceptsocket;
return -1;
}
 
//=============================================================================
 
int IPX_Read (int handle, byte *buf, int len, struct qsockaddr *addr)
{
ECB *ecb;
ipx_lowmem_buffer_t *rcvbuf;
int copylen;
 
ProcessReadyList(handle);
tryagain:
if (readlist[handle] == NULL)
return 0;
ecb = readlist[handle];
readlist[handle] = ecb->link;
 
if (ecb->completionCode != 0)
{
Con_Printf("Warning: IPX_Read error %02x\n", ecb->completionCode);
ecb->fragSize = sizeof(IPXheader) + sizeof(int) + NET_DATAGRAMSIZE;
IPX_ListenForPacket(ecb);
goto tryagain;
}
 
rcvbuf = (ipx_lowmem_buffer_t *)ecb;
 
// copy the data up to the buffer
copylen = ntohs(rcvbuf->header.length) - (sizeof(int) + sizeof(IPXheader));
if (len < copylen)
Sys_Error("IPX_Read: buffer too small (%d vs %d)\n", len, copylen);
Q_memcpy(buf, rcvbuf->data, copylen);
 
// fill in the addr if they want it
if (addr)
{
((struct sockaddr_ipx *)addr)->sipx_family = AF_NETWARE;
Q_memcpy(&((struct sockaddr_ipx *)addr)->sipx_addr, rcvbuf->header.source.network, sizeof(IPXaddr));
((struct sockaddr_ipx *)addr)->sipx_zero[0] = 0;
((struct sockaddr_ipx *)addr)->sipx_zero[1] = 0;
}
 
// update the send ecb's immediate address
Q_memcpy(lma->socketbuffer[handle][0].ecb.immediateAddress, rcvbuf->ecb.immediateAddress, 6);
 
// get this ecb listening again
rcvbuf->ecb.fragSize = sizeof(IPXheader) + sizeof(int) + NET_DATAGRAMSIZE;
IPX_ListenForPacket(&rcvbuf->ecb);
return copylen;
}
 
//=============================================================================
 
int IPX_Broadcast (int handle, byte *buf, int len)
{
struct sockaddr_ipx addr;
int ret;
 
Q_memset(addr.sipx_addr.network, 0x00, 4);
Q_memset(addr.sipx_addr.node, 0xff, 6);
addr.sipx_port = htons(net_hostport);
Q_memset(lma->socketbuffer[handle][0].ecb.immediateAddress, 0xff, 6);
ret = IPX_Write (handle, buf, len, (struct qsockaddr *)&addr);
return ret;
}
 
//=============================================================================
 
int IPX_Write (int handle, byte *buf, int len, struct qsockaddr *addr)
{
// has the previous send completed?
while (lma->socketbuffer[handle][0].ecb.inUse != 0)
IPX_RelinquishControl();
 
switch (lma->socketbuffer[handle][0].ecb.completionCode)
{
case 0x00: // success
case 0xfc: // request cancelled
break;
 
case 0xfd: // malformed packet
default:
Con_Printf("IPX driver send failure: %02x\n", lma->socketbuffer[handle][0].ecb.completionCode);
break;
 
case 0xfe: // packet undeliverable
case 0xff: // unable to send packet
Con_Printf("IPX lost route, trying to re-establish\n");
 
// look for a new route
if (IPX_GetLocalTarget (&lma->socketbuffer[handle][0].header.destination, lma->socketbuffer[handle][0].ecb.immediateAddress) != 0)
return -1;
 
// re-send the one that failed
regs.x.cs = ipx_cs;
regs.x.ip = ipx_ip;
regs.x.bx = IPX_SEND;
regs.x.es = ptr2real(&lma->socketbuffer[handle][0].ecb) >> 4;
regs.x.si = ptr2real(&lma->socketbuffer[handle][0].ecb) & 0xf;
__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
 
// report that we did not send the current one
return 0;
}
 
// ecb : length
lma->socketbuffer[handle][0].ecb.fragSize = sizeof(IPXheader) + sizeof(int) + len;
 
// ipx header : type
lma->socketbuffer[handle][0].header.type = PTYPE_IPX;
 
// ipx header : destination
Q_memcpy(&lma->socketbuffer[handle][0].header.destination, &((struct sockaddr_ipx *)addr)->sipx_addr, sizeof(IPXaddr));
 
// sequence number
lma->socketbuffer[handle][0].sequence = sequence[handle];
sequence[handle]++;
 
// copy down the data
Q_memcpy(lma->socketbuffer[handle][0].data, buf, len);
 
regs.x.cs = ipx_cs;
regs.x.ip = ipx_ip;
regs.x.bx = IPX_SEND;
regs.x.es = ptr2real(&lma->socketbuffer[handle][0].ecb) >> 4;
regs.x.si = ptr2real(&lma->socketbuffer[handle][0].ecb) & 0xf;
__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
 
return len;
}
 
//=============================================================================
 
char *IPX_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)->sipx_addr.network[0],
((struct sockaddr_ipx *)addr)->sipx_addr.network[1],
((struct sockaddr_ipx *)addr)->sipx_addr.network[2],
((struct sockaddr_ipx *)addr)->sipx_addr.network[3],
((struct sockaddr_ipx *)addr)->sipx_addr.node[0],
((struct sockaddr_ipx *)addr)->sipx_addr.node[1],
((struct sockaddr_ipx *)addr)->sipx_addr.node[2],
((struct sockaddr_ipx *)addr)->sipx_addr.node[3],
((struct sockaddr_ipx *)addr)->sipx_addr.node[4],
((struct sockaddr_ipx *)addr)->sipx_addr.node[5],
ntohs(((struct sockaddr_ipx *)addr)->sipx_port)
);
return buf;
}
 
//=============================================================================
 
int IPX_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_NETWARE;
 
#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)->sipx_addr.dest = val
 
DO(0, network[0]);
DO(2, network[1]);
DO(4, network[2]);
DO(6, network[3]);
DO(9, node[0]);
DO(11, node[1]);
DO(13, node[2]);
DO(15, node[3]);
DO(17, node[4]);
DO(19, node[5]);
#undef DO
 
sscanf (&string[22], "%u", &val);
((struct sockaddr_ipx *)addr)->sipx_port = htons(val);
 
return 0;
}
 
//=============================================================================
 
int IPX_GetSocketAddr (int handle, struct qsockaddr *addr)
{
Q_memset(addr, 0, sizeof(struct qsockaddr));
addr->sa_family = AF_NETWARE;
IPX_GetLocalAddress(&((struct sockaddr_ipx *)addr)->sipx_addr);
((struct sockaddr_ipx *)addr)->sipx_port = ipxsocket[handle];
return 0;
}
 
//=============================================================================
 
int IPX_GetNameFromAddr (struct qsockaddr *addr, char *name)
{
Q_strcpy(name, IPX_AddrToString(addr));
return 0;
}
 
//=============================================================================
 
int IPX_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 IPX_StringToAddr (buf, addr);
}
if (n == 21)
{
sprintf(buf, "%s:%u", name, net_hostport);
return IPX_StringToAddr (buf, addr);
}
if (n > 21 && n <= 27)
return IPX_StringToAddr (name, addr);
 
return -1;
}
 
//=============================================================================
 
int IPX_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
{
if (addr1->sa_family != addr2->sa_family)
return -1;
 
if(Q_memcmp(&((struct sockaddr_ipx *)addr1)->sipx_addr, &((struct sockaddr_ipx *)addr2)->sipx_addr, 10))
return -1;
 
if (((struct sockaddr_ipx *)addr1)->sipx_port != ((struct sockaddr_ipx *)addr2)->sipx_port)
return 1;
 
return 0;
}
 
//=============================================================================
 
int IPX_GetSocketPort (struct qsockaddr *addr)
{
return ntohs(((struct sockaddr_ipx *)addr)->sipx_port);
}
 
 
int IPX_SetSocketPort (struct qsockaddr *addr, int port)
{
((struct sockaddr_ipx *)addr)->sipx_port = htons(port);
return 0;
}
 
//=============================================================================
/contrib/other/sdlquake-1.0.9/net_ipx.h
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_ipx.h
 
int IPX_Init (void);
void IPX_Shutdown (void);
void IPX_Listen (qboolean state);
int IPX_OpenSocket (int port);
int IPX_CloseSocket (int socket);
int IPX_Connect (int socket, struct qsockaddr *addr);
int IPX_CheckNewConnections (void);
int IPX_Read (int socket, byte *buf, int len, struct qsockaddr *addr);
int IPX_Write (int socket, byte *buf, int len, struct qsockaddr *addr);
int IPX_Broadcast (int socket, byte *buf, int len);
char *IPX_AddrToString (struct qsockaddr *addr);
int IPX_StringToAddr (char *string, struct qsockaddr *addr);
int IPX_GetSocketAddr (int socket, struct qsockaddr *addr);
int IPX_GetNameFromAddr (struct qsockaddr *addr, char *name);
int IPX_GetAddrFromName (char *name, struct qsockaddr *addr);
int IPX_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2);
int IPX_GetSocketPort (struct qsockaddr *addr);
int IPX_SetSocketPort (struct qsockaddr *addr, int port);
/contrib/other/sdlquake-1.0.9/net_loop.c
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;
}
/contrib/other/sdlquake-1.0.9/net_loop.h
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);
/contrib/other/sdlquake-1.0.9/net_main.c
0,0 → 1,997
/*
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_main.c
 
#include "quakedef.h"
#include "net_vcr.h"
 
qsocket_t *net_activeSockets = NULL;
qsocket_t *net_freeSockets = NULL;
int net_numsockets = 0;
 
qboolean serialAvailable = false;
qboolean ipxAvailable = false;
qboolean tcpipAvailable = false;
 
int net_hostport;
int DEFAULTnet_hostport = 26000;
 
char my_ipx_address[NET_NAMELEN];
char my_tcpip_address[NET_NAMELEN];
 
void (*GetComPortConfig) (int portNumber, int *port, int *irq, int *baud, qboolean *useModem);
void (*SetComPortConfig) (int portNumber, int port, int irq, int baud, qboolean useModem);
void (*GetModemConfig) (int portNumber, char *dialType, char *clear, char *init, char *hangup);
void (*SetModemConfig) (int portNumber, char *dialType, char *clear, char *init, char *hangup);
 
static qboolean listening = false;
 
qboolean slistInProgress = false;
qboolean slistSilent = false;
qboolean slistLocal = true;
static double slistStartTime;
static int slistLastShown;
 
static void Slist_Send(void);
static void Slist_Poll(void);
PollProcedure slistSendProcedure = {NULL, 0.0, Slist_Send};
PollProcedure slistPollProcedure = {NULL, 0.0, Slist_Poll};
 
 
sizebuf_t net_message;
int net_activeconnections = 0;
 
int messagesSent = 0;
int messagesReceived = 0;
int unreliableMessagesSent = 0;
int unreliableMessagesReceived = 0;
 
cvar_t net_messagetimeout = {"net_messagetimeout","300"};
cvar_t hostname = {"hostname", "UNNAMED"};
 
qboolean configRestored = false;
cvar_t config_com_port = {"_config_com_port", "0x3f8", true};
cvar_t config_com_irq = {"_config_com_irq", "4", true};
cvar_t config_com_baud = {"_config_com_baud", "57600", true};
cvar_t config_com_modem = {"_config_com_modem", "1", true};
cvar_t config_modem_dialtype = {"_config_modem_dialtype", "T", true};
cvar_t config_modem_clear = {"_config_modem_clear", "ATZ", true};
cvar_t config_modem_init = {"_config_modem_init", "", true};
cvar_t config_modem_hangup = {"_config_modem_hangup", "AT H", true};
 
#ifdef IDGODS
cvar_t idgods = {"idgods", "0"};
#endif
 
int vcrFile = -1;
qboolean recording = false;
 
// these two macros are to make the code more readable
#define sfunc net_drivers[sock->driver]
#define dfunc net_drivers[net_driverlevel]
 
int net_driverlevel;
 
 
double net_time;
 
double SetNetTime(void)
{
net_time = Sys_FloatTime();
return net_time;
}
 
 
/*
===================
NET_NewQSocket
 
Called by drivers when a new communications endpoint is required
The sequence and buffer fields will be filled in properly
===================
*/
qsocket_t *NET_NewQSocket (void)
{
qsocket_t *sock;
 
if (net_freeSockets == NULL)
return NULL;
 
if (net_activeconnections >= svs.maxclients)
return NULL;
 
// get one from free list
sock = net_freeSockets;
net_freeSockets = sock->next;
 
// add it to active list
sock->next = net_activeSockets;
net_activeSockets = sock;
 
sock->disconnected = false;
sock->connecttime = net_time;
Q_strcpy (sock->address,"UNSET ADDRESS");
sock->driver = net_driverlevel;
sock->socket = 0;
sock->driverdata = NULL;
sock->canSend = true;
sock->sendNext = false;
sock->lastMessageTime = net_time;
sock->ackSequence = 0;
sock->sendSequence = 0;
sock->unreliableSendSequence = 0;
sock->sendMessageLength = 0;
sock->receiveSequence = 0;
sock->unreliableReceiveSequence = 0;
sock->receiveMessageLength = 0;
 
return sock;
}
 
 
void NET_FreeQSocket(qsocket_t *sock)
{
qsocket_t *s;
 
// remove it from active list
if (sock == net_activeSockets)
net_activeSockets = net_activeSockets->next;
else
{
for (s = net_activeSockets; s; s = s->next)
if (s->next == sock)
{
s->next = sock->next;
break;
}
if (!s)
Sys_Error ("NET_FreeQSocket: not active\n");
}
 
// add it to free list
sock->next = net_freeSockets;
net_freeSockets = sock;
sock->disconnected = true;
}
 
 
static void NET_Listen_f (void)
{
if (Cmd_Argc () != 2)
{
Con_Printf ("\"listen\" is \"%u\"\n", listening ? 1 : 0);
return;
}
 
listening = Q_atoi(Cmd_Argv(1)) ? true : false;
 
for (net_driverlevel=0 ; net_driverlevel<net_numdrivers; net_driverlevel++)
{
if (net_drivers[net_driverlevel].initialized == false)
continue;
dfunc.Listen (listening);
}
}
 
 
static void MaxPlayers_f (void)
{
int n;
 
if (Cmd_Argc () != 2)
{
Con_Printf ("\"maxplayers\" is \"%u\"\n", svs.maxclients);
return;
}
 
if (sv.active)
{
Con_Printf ("maxplayers can not be changed while a server is running.\n");
return;
}
 
n = Q_atoi(Cmd_Argv(1));
if (n < 1)
n = 1;
if (n > svs.maxclientslimit)
{
n = svs.maxclientslimit;
Con_Printf ("\"maxplayers\" set to \"%u\"\n", n);
}
 
if ((n == 1) && listening)
Cbuf_AddText ("listen 0\n");
 
if ((n > 1) && (!listening))
Cbuf_AddText ("listen 1\n");
 
svs.maxclients = n;
if (n == 1)
Cvar_Set ("deathmatch", "0");
else
Cvar_Set ("deathmatch", "1");
}
 
 
static void NET_Port_f (void)
{
int n;
 
if (Cmd_Argc () != 2)
{
Con_Printf ("\"port\" is \"%u\"\n", net_hostport);
return;
}
 
n = Q_atoi(Cmd_Argv(1));
if (n < 1 || n > 65534)
{
Con_Printf ("Bad value, must be between 1 and 65534\n");
return;
}
 
DEFAULTnet_hostport = n;
net_hostport = n;
 
if (listening)
{
// force a change to the new port
Cbuf_AddText ("listen 0\n");
Cbuf_AddText ("listen 1\n");
}
}
 
 
static void PrintSlistHeader(void)
{
Con_Printf("Server Map Users\n");
Con_Printf("--------------- --------------- -----\n");
slistLastShown = 0;
}
 
 
static void PrintSlist(void)
{
int n;
 
for (n = slistLastShown; n < hostCacheCount; n++)
{
if (hostcache[n].maxusers)
Con_Printf("%-15.15s %-15.15s %2u/%2u\n", hostcache[n].name, hostcache[n].map, hostcache[n].users, hostcache[n].maxusers);
else
Con_Printf("%-15.15s %-15.15s\n", hostcache[n].name, hostcache[n].map);
}
slistLastShown = n;
}
 
 
static void PrintSlistTrailer(void)
{
if (hostCacheCount)
Con_Printf("== end list ==\n\n");
else
Con_Printf("No Quake servers found.\n\n");
}
 
 
void NET_Slist_f (void)
{
if (slistInProgress)
return;
 
if (! slistSilent)
{
Con_Printf("Looking for Quake servers...\n");
PrintSlistHeader();
}
 
slistInProgress = true;
slistStartTime = Sys_FloatTime();
 
SchedulePollProcedure(&slistSendProcedure, 0.0);
SchedulePollProcedure(&slistPollProcedure, 0.1);
 
hostCacheCount = 0;
}
 
 
static void Slist_Send(void)
{
for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++)
{
if (!slistLocal && net_driverlevel == 0)
continue;
if (net_drivers[net_driverlevel].initialized == false)
continue;
dfunc.SearchForHosts (true);
}
 
if ((Sys_FloatTime() - slistStartTime) < 0.5)
SchedulePollProcedure(&slistSendProcedure, 0.75);
}
 
 
static void Slist_Poll(void)
{
for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++)
{
if (!slistLocal && net_driverlevel == 0)
continue;
if (net_drivers[net_driverlevel].initialized == false)
continue;
dfunc.SearchForHosts (false);
}
 
if (! slistSilent)
PrintSlist();
 
if ((Sys_FloatTime() - slistStartTime) < 1.5)
{
SchedulePollProcedure(&slistPollProcedure, 0.1);
return;
}
 
if (! slistSilent)
PrintSlistTrailer();
slistInProgress = false;
slistSilent = false;
slistLocal = true;
}
 
 
/*
===================
NET_Connect
===================
*/
 
int hostCacheCount = 0;
hostcache_t hostcache[HOSTCACHESIZE];
 
qsocket_t *NET_Connect (char *host)
{
qsocket_t *ret;
int n;
int numdrivers = net_numdrivers;
 
SetNetTime();
 
if (host && *host == 0)
host = NULL;
 
if (host)
{
if (Q_strcasecmp (host, "local") == 0)
{
numdrivers = 1;
goto JustDoIt;
}
 
if (hostCacheCount)
{
for (n = 0; n < hostCacheCount; n++)
if (Q_strcasecmp (host, hostcache[n].name) == 0)
{
host = hostcache[n].cname;
break;
}
if (n < hostCacheCount)
goto JustDoIt;
}
}
 
slistSilent = host ? true : false;
NET_Slist_f ();
 
while(slistInProgress)
NET_Poll();
 
if (host == NULL)
{
if (hostCacheCount != 1)
return NULL;
host = hostcache[0].cname;
Con_Printf("Connecting to...\n%s @ %s\n\n", hostcache[0].name, host);
}
 
if (hostCacheCount)
for (n = 0; n < hostCacheCount; n++)
if (Q_strcasecmp (host, hostcache[n].name) == 0)
{
host = hostcache[n].cname;
break;
}
 
JustDoIt:
for (net_driverlevel=0 ; net_driverlevel<numdrivers; net_driverlevel++)
{
if (net_drivers[net_driverlevel].initialized == false)
continue;
ret = dfunc.Connect (host);
if (ret)
return ret;
}
 
if (host)
{
Con_Printf("\n");
PrintSlistHeader();
PrintSlist();
PrintSlistTrailer();
}
return NULL;
}
 
 
/*
===================
NET_CheckNewConnections
===================
*/
 
struct
{
double time;
int op;
long session;
} vcrConnect;
 
qsocket_t *NET_CheckNewConnections (void)
{
qsocket_t *ret;
 
SetNetTime();
 
for (net_driverlevel=0 ; net_driverlevel<net_numdrivers; net_driverlevel++)
{
if (net_drivers[net_driverlevel].initialized == false)
continue;
if (net_driverlevel && listening == false)
continue;
ret = dfunc.CheckNewConnections ();
if (ret)
{
if (recording)
{
vcrConnect.time = host_time;
vcrConnect.op = VCR_OP_CONNECT;
vcrConnect.session = (long)ret;
Sys_FileWrite (vcrFile, &vcrConnect, sizeof(vcrConnect));
Sys_FileWrite (vcrFile, ret->address, NET_NAMELEN);
}
return ret;
}
}
if (recording)
{
vcrConnect.time = host_time;
vcrConnect.op = VCR_OP_CONNECT;
vcrConnect.session = 0;
Sys_FileWrite (vcrFile, &vcrConnect, sizeof(vcrConnect));
}
 
return NULL;
}
 
/*
===================
NET_Close
===================
*/
void NET_Close (qsocket_t *sock)
{
if (!sock)
return;
 
if (sock->disconnected)
return;
 
SetNetTime();
 
// call the driver_Close function
sfunc.Close (sock);
 
NET_FreeQSocket(sock);
}
 
 
/*
=================
NET_GetMessage
 
If there is a complete message, return it in net_message
 
returns 0 if no data is waiting
returns 1 if a message was received
returns -1 if connection is invalid
=================
*/
 
struct
{
double time;
int op;
long session;
int ret;
int len;
} vcrGetMessage;
 
extern void PrintStats(qsocket_t *s);
 
int NET_GetMessage (qsocket_t *sock)
{
int ret;
 
if (!sock)
return -1;
 
if (sock->disconnected)
{
Con_Printf("NET_GetMessage: disconnected socket\n");
return -1;
}
 
SetNetTime();
 
ret = sfunc.QGetMessage(sock);
 
// see if this connection has timed out
if (ret == 0 && sock->driver)
{
if (net_time - sock->lastMessageTime > net_messagetimeout.value)
{
NET_Close(sock);
return -1;
}
}
 
 
if (ret > 0)
{
if (sock->driver)
{
sock->lastMessageTime = net_time;
if (ret == 1)
messagesReceived++;
else if (ret == 2)
unreliableMessagesReceived++;
}
 
if (recording)
{
vcrGetMessage.time = host_time;
vcrGetMessage.op = VCR_OP_GETMESSAGE;
vcrGetMessage.session = (long)sock;
vcrGetMessage.ret = ret;
vcrGetMessage.len = net_message.cursize;
Sys_FileWrite (vcrFile, &vcrGetMessage, 24);
Sys_FileWrite (vcrFile, net_message.data, net_message.cursize);
}
}
else
{
if (recording)
{
vcrGetMessage.time = host_time;
vcrGetMessage.op = VCR_OP_GETMESSAGE;
vcrGetMessage.session = (long)sock;
vcrGetMessage.ret = ret;
Sys_FileWrite (vcrFile, &vcrGetMessage, 20);
}
}
 
return ret;
}
 
 
/*
==================
NET_SendMessage
 
Try to send a complete length+message unit over the reliable stream.
returns 0 if the message cannot be delivered reliably, but the connection
is still considered valid
returns 1 if the message was sent properly
returns -1 if the connection died
==================
*/
struct
{
double time;
int op;
long session;
int r;
} vcrSendMessage;
 
int NET_SendMessage (qsocket_t *sock, sizebuf_t *data)
{
int r;
if (!sock)
return -1;
 
if (sock->disconnected)
{
Con_Printf("NET_SendMessage: disconnected socket\n");
return -1;
}
 
SetNetTime();
r = sfunc.QSendMessage(sock, data);
if (r == 1 && sock->driver)
messagesSent++;
 
if (recording)
{
vcrSendMessage.time = host_time;
vcrSendMessage.op = VCR_OP_SENDMESSAGE;
vcrSendMessage.session = (long)sock;
vcrSendMessage.r = r;
Sys_FileWrite (vcrFile, &vcrSendMessage, 20);
}
return r;
}
 
 
int NET_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data)
{
int r;
if (!sock)
return -1;
 
if (sock->disconnected)
{
Con_Printf("NET_SendMessage: disconnected socket\n");
return -1;
}
 
SetNetTime();
r = sfunc.SendUnreliableMessage(sock, data);
if (r == 1 && sock->driver)
unreliableMessagesSent++;
 
if (recording)
{
vcrSendMessage.time = host_time;
vcrSendMessage.op = VCR_OP_SENDMESSAGE;
vcrSendMessage.session = (long)sock;
vcrSendMessage.r = r;
Sys_FileWrite (vcrFile, &vcrSendMessage, 20);
}
return r;
}
 
 
/*
==================
NET_CanSendMessage
 
Returns true or false if the given qsocket can currently accept a
message to be transmitted.
==================
*/
qboolean NET_CanSendMessage (qsocket_t *sock)
{
int r;
if (!sock)
return false;
 
if (sock->disconnected)
return false;
 
SetNetTime();
 
r = sfunc.CanSendMessage(sock);
if (recording)
{
vcrSendMessage.time = host_time;
vcrSendMessage.op = VCR_OP_CANSENDMESSAGE;
vcrSendMessage.session = (long)sock;
vcrSendMessage.r = r;
Sys_FileWrite (vcrFile, &vcrSendMessage, 20);
}
return r;
}
 
 
int NET_SendToAll(sizebuf_t *data, int blocktime)
{
double start;
int i;
int count = 0;
qboolean state1 [MAX_SCOREBOARD];
qboolean state2 [MAX_SCOREBOARD];
 
for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
{
if (!host_client->netconnection)
continue;
if (host_client->active)
{
if (host_client->netconnection->driver == 0)
{
NET_SendMessage(host_client->netconnection, data);
state1[i] = true;
state2[i] = true;
continue;
}
count++;
state1[i] = false;
state2[i] = false;
}
else
{
state1[i] = true;
state2[i] = true;
}
}
 
start = Sys_FloatTime();
while (count)
{
count = 0;
for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
{
if (! state1[i])
{
if (NET_CanSendMessage (host_client->netconnection))
{
state1[i] = true;
NET_SendMessage(host_client->netconnection, data);
}
else
{
NET_GetMessage (host_client->netconnection);
}
count++;
continue;
}
 
if (! state2[i])
{
if (NET_CanSendMessage (host_client->netconnection))
{
state2[i] = true;
}
else
{
NET_GetMessage (host_client->netconnection);
}
count++;
continue;
}
}
if ((Sys_FloatTime() - start) > blocktime)
break;
}
return count;
}
 
 
//=============================================================================
 
/*
====================
NET_Init
====================
*/
 
void NET_Init (void)
{
int i;
int controlSocket;
qsocket_t *s;
 
if (COM_CheckParm("-playback"))
{
net_numdrivers = 1;
net_drivers[0].Init = VCR_Init;
}
 
if (COM_CheckParm("-record"))
recording = true;
 
i = COM_CheckParm ("-port");
if (!i)
i = COM_CheckParm ("-udpport");
if (!i)
i = COM_CheckParm ("-ipxport");
 
if (i)
{
if (i < com_argc-1)
DEFAULTnet_hostport = Q_atoi (com_argv[i+1]);
else
Sys_Error ("NET_Init: you must specify a number after -port");
}
net_hostport = DEFAULTnet_hostport;
 
if (COM_CheckParm("-listen") || cls.state == ca_dedicated)
listening = true;
net_numsockets = svs.maxclientslimit;
if (cls.state != ca_dedicated)
net_numsockets++;
 
SetNetTime();
 
for (i = 0; i < net_numsockets; i++)
{
s = (qsocket_t *)Hunk_AllocName(sizeof(qsocket_t), "qsocket");
s->next = net_freeSockets;
net_freeSockets = s;
s->disconnected = true;
}
 
// allocate space for network message buffer
SZ_Alloc (&net_message, NET_MAXMESSAGE);
 
Cvar_RegisterVariable (&net_messagetimeout);
Cvar_RegisterVariable (&hostname);
Cvar_RegisterVariable (&config_com_port);
Cvar_RegisterVariable (&config_com_irq);
Cvar_RegisterVariable (&config_com_baud);
Cvar_RegisterVariable (&config_com_modem);
Cvar_RegisterVariable (&config_modem_dialtype);
Cvar_RegisterVariable (&config_modem_clear);
Cvar_RegisterVariable (&config_modem_init);
Cvar_RegisterVariable (&config_modem_hangup);
#ifdef IDGODS
Cvar_RegisterVariable (&idgods);
#endif
 
Cmd_AddCommand ("slist", NET_Slist_f);
Cmd_AddCommand ("listen", NET_Listen_f);
Cmd_AddCommand ("maxplayers", MaxPlayers_f);
Cmd_AddCommand ("port", NET_Port_f);
 
// initialize all the drivers
for (net_driverlevel=0 ; net_driverlevel<net_numdrivers ; net_driverlevel++)
{
controlSocket = net_drivers[net_driverlevel].Init();
if (controlSocket == -1)
continue;
net_drivers[net_driverlevel].initialized = true;
net_drivers[net_driverlevel].controlSock = controlSocket;
if (listening)
net_drivers[net_driverlevel].Listen (true);
}
 
if (*my_ipx_address)
Con_DPrintf("IPX address %s\n", my_ipx_address);
if (*my_tcpip_address)
Con_DPrintf("TCP/IP address %s\n", my_tcpip_address);
}
 
/*
====================
NET_Shutdown
====================
*/
 
void NET_Shutdown (void)
{
qsocket_t *sock;
 
SetNetTime();
 
for (sock = net_activeSockets; sock; sock = sock->next)
NET_Close(sock);
 
//
// shutdown the drivers
//
for (net_driverlevel = 0; net_driverlevel < net_numdrivers; net_driverlevel++)
{
if (net_drivers[net_driverlevel].initialized == true)
{
net_drivers[net_driverlevel].Shutdown ();
net_drivers[net_driverlevel].initialized = false;
}
}
 
if (vcrFile != -1)
{
Con_Printf ("Closing vcrfile.\n");
Sys_FileClose(vcrFile);
}
}
 
 
static PollProcedure *pollProcedureList = NULL;
 
void NET_Poll(void)
{
PollProcedure *pp;
qboolean useModem;
 
if (!configRestored)
{
if (serialAvailable)
{
if (config_com_modem.value == 1.0)
useModem = true;
else
useModem = false;
SetComPortConfig (0, (int)config_com_port.value, (int)config_com_irq.value, (int)config_com_baud.value, useModem);
SetModemConfig (0, config_modem_dialtype.string, config_modem_clear.string, config_modem_init.string, config_modem_hangup.string);
}
configRestored = true;
}
 
SetNetTime();
 
for (pp = pollProcedureList; pp; pp = pp->next)
{
if (pp->nextTime > net_time)
break;
pollProcedureList = pp->next;
pp->procedure(pp->arg);
}
}
 
 
void SchedulePollProcedure(PollProcedure *proc, double timeOffset)
{
PollProcedure *pp, *prev;
 
proc->nextTime = Sys_FloatTime() + timeOffset;
for (pp = pollProcedureList, prev = NULL; pp; pp = pp->next)
{
if (pp->nextTime >= proc->nextTime)
break;
prev = pp;
}
 
if (prev == NULL)
{
proc->next = pollProcedureList;
pollProcedureList = proc;
return;
}
 
proc->next = pp;
prev->next = proc;
}
 
 
#ifdef IDGODS
#define IDNET 0xc0f62800
 
qboolean IsID(struct qsockaddr *addr)
{
if (idgods.value == 0.0)
return false;
 
if (addr->sa_family != 2)
return false;
 
if ((BigLong(*(int *)&addr->sa_data[2]) & 0xffffff00) == IDNET)
return true;
return false;
}
#endif
/contrib/other/sdlquake-1.0.9/net_mp.c
0,0 → 1,443
/*
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_mpath.c
 
#include <dpmi.h>
#include "quakedef.h"
#include "mpdosock.h"
 
short flat_selector;
 
int WSAGetLastError(void);
void sockets_flush(void);
 
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 qboolean ifbcastinit = false;
static struct qsockaddr broadcastaddr;
 
static unsigned long myAddr;
 
#include "net_mp.h"
 
 
//=============================================================================
 
int MPATH_Init (void)
{
int i;
struct hostent *local = NULL;
char buff[MAXHOSTNAMELEN];
struct qsockaddr addr;
char *p;
 
if (COM_CheckParm ("-mpath") == 0)
return -1;
 
flat_selector = __dpmi_allocate_ldt_descriptors(1);
if (flat_selector == -1) {
Con_Printf("MPATH_Init: Can't get flat selector\n");
return -1;
}
if (__dpmi_set_segment_base_address(flat_selector, 0) == -1) {
Con_Printf("MPATH_Init: Can't seg flat base!\n");
return -1;
}
if (__dpmi_set_segment_limit(flat_selector, 0xffffffff) == -1) {
Con_Printf("MPATH_Init: Can't set segment limit\n");
return -1;
}
// determine my name & address
if (gethostname(buff, MAXHOSTNAMELEN) == 0)
local = gethostbyname(buff);
if (local)
{
myAddr = *(int *)local->h_addr_list[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 = MPATH_OpenSocket (0)) == -1)
Sys_Error("MPATH_Init: Unable to open control socket\n");
 
((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(net_hostport);
 
MPATH_GetSocketAddr (net_controlsocket, &addr);
Q_strcpy(my_tcpip_address, MPATH_AddrToString (&addr));
p = Q_strrchr (my_tcpip_address, ':');
if (p)
*p = 0;
 
Con_Printf("MPath Initialized\n");
tcpipAvailable = true;
 
return net_controlsocket;
}
 
//=============================================================================
 
void MPATH_Shutdown (void)
{
MPATH_Listen (false);
MPATH_CloseSocket (net_controlsocket);
}
 
//=============================================================================
 
void MPATH_Listen (qboolean state)
{
// enable listening
if (state)
{
if (net_acceptsocket != -1)
return;
if ((net_acceptsocket = MPATH_OpenSocket (net_hostport)) == -1)
Sys_Error ("MPATH_Listen: Unable to open accept socket\n");
return;
}
 
// disable listening
if (net_acceptsocket == -1)
return;
MPATH_CloseSocket (net_acceptsocket);
net_acceptsocket = -1;
}
 
//=============================================================================
 
int MPATH_OpenSocket (int port)
{
int newsocket;
struct sockaddr_in address;
u_long _true = 1;
 
if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
return -1;
 
if (ioctlsocket (newsocket, FIONBIO, &_true) == -1)
goto ErrorReturn;
 
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(port);
if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
goto ErrorReturn;
 
return newsocket;
 
ErrorReturn:
closesocket (newsocket);
return -1;
}
 
//=============================================================================
 
int MPATH_CloseSocket (int socket)
{
if (socket == net_broadcastsocket)
net_broadcastsocket = 0;
return closesocket (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 MPATH_Connect (int socket, struct qsockaddr *addr)
{
return 0;
}
 
//=============================================================================
 
int MPATH_CheckNewConnections (void)
{
char buf[4];
 
if (net_acceptsocket == -1)
return -1;
 
if (recvfrom (net_acceptsocket, buf, 4, MSG_PEEK, NULL, NULL) > 0)
return net_acceptsocket;
return -1;
}
 
//=============================================================================
 
int MPATH_Read (int socket, byte *buf, int len, struct qsockaddr *addr)
{
int addrlen = sizeof (struct qsockaddr);
int ret;
 
ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen);
if (ret == -1)
{
int errno = WSAGetLastError();
 
if (errno == WSAEWOULDBLOCK || errno == WSAECONNREFUSED)
return 0;
 
}
return ret;
}
 
//=============================================================================
 
int MPATH_MakeSocketBroadcastCapable (int socket)
{
int i = 1;
 
// make this socket broadcast capable
if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0)
return -1;
net_broadcastsocket = socket;
 
return 0;
}
 
//=============================================================================
 
int MPATH_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");
ret = MPATH_MakeSocketBroadcastCapable (socket);
if (ret == -1)
{
Con_Printf("Unable to make socket broadcast capable\n");
return ret;
}
}
 
return MPATH_Write (socket, buf, len, &broadcastaddr);
}
 
//=============================================================================
 
int MPATH_Write (int socket, byte *buf, int len, struct qsockaddr *addr)
{
int ret;
 
ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr));
if (ret == -1)
if (WSAGetLastError() == WSAEWOULDBLOCK)
return 0;
 
sockets_flush();
 
return ret;
}
 
//=============================================================================
 
char *MPATH_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 MPATH_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(hp);
return 0;
}
 
//=============================================================================
 
int MPATH_GetSocketAddr (int socket, struct qsockaddr *addr)
{
int addrlen = sizeof(struct qsockaddr);
unsigned int a;
 
Q_memset(addr, 0, sizeof(struct qsockaddr));
getsockname(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 MPATH_GetNameFromAddr (struct qsockaddr *addr, char *name)
{
struct hostent *hostentry;
 
hostentry = gethostbyaddr ((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, MPATH_AddrToString (addr));
return 0;
}
 
//=============================================================================
 
int MPATH_GetAddrFromName(char *name, struct qsockaddr *addr)
{
struct hostent *hostentry;
 
if (name[0] >= '0' && name[0] <= '9')
return PartialIPAddress (name, addr);
hostentry = gethostbyname (name);
if (!hostentry)
return -1;
 
addr->sa_family = AF_INET;
((struct sockaddr_in *)addr)->sin_port = htons(net_hostport);
((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
 
return 0;
}
 
//=============================================================================
 
int MPATH_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 MPATH_GetSocketPort (struct qsockaddr *addr)
{
return ntohs(((struct sockaddr_in *)addr)->sin_port);
}
 
 
int MPATH_SetSocketPort (struct qsockaddr *addr, int port)
{
((struct sockaddr_in *)addr)->sin_port = htons(port);
return 0;
}
 
//=============================================================================
/contrib/other/sdlquake-1.0.9/net_mp.h
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_mpath.h
 
int MPATH_Init (void);
void MPATH_Shutdown (void);
void MPATH_Listen (qboolean state);
int MPATH_OpenSocket (int port);
int MPATH_CloseSocket (int socket);
int MPATH_Connect (int socket, struct qsockaddr *addr);
int MPATH_CheckNewConnections (void);
int MPATH_Read (int socket, byte *buf, int len, struct qsockaddr *addr);
int MPATH_Write (int socket, byte *buf, int len, struct qsockaddr *addr);
int MPATH_Broadcast (int socket, byte *buf, int len);
char *MPATH_AddrToString (struct qsockaddr *addr);
int MPATH_StringToAddr (char *string, struct qsockaddr *addr);
int MPATH_GetSocketAddr (int socket, struct qsockaddr *addr);
int MPATH_GetNameFromAddr (struct qsockaddr *addr, char *name);
int MPATH_GetAddrFromName (char *name, struct qsockaddr *addr);
int MPATH_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2);
int MPATH_GetSocketPort (struct qsockaddr *addr);
int MPATH_SetSocketPort (struct qsockaddr *addr, int port);
/contrib/other/sdlquake-1.0.9/net_none.c
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.
 
*/
#include "quakedef.h"
 
#include "net_loop.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
}
};
int net_numdrivers = 1;
 
net_landriver_t net_landrivers[MAX_NET_DRIVERS];
int net_numlandrivers = 0;
/contrib/other/sdlquake-1.0.9/net_ser.c
0,0 → 1,951
/*
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_ser.c
 
#include "quakedef.h"
#include "net_ser.h"
#include "dosisms.h"
#include "crc.h"
 
#include "net_comx.c"
 
// serial protocol
 
#define SERIAL_PROTOCOL_VERSION 3
 
// The serial protocol is message oriented. The high level message format is
// a one byte message type (MTYPE_xxx), data, and a 16-bit checksum. All
// multi-byte fields are sent in network byte order. There are currently 4
// MTYPEs defined. Their formats are as follows:
//
// MTYPE_RELIABLE sequence data_length data checksum eom
// MTYPE_UNRELIABLE sequence data_length data checksum eom
// MTYPE_ACK sequence checksum eom
// MTYPE_CONTROL data_length data checksum eom
//
// sequence is an 8-bit unsigned value starting from 0
// data_length is a 16-bit unsigned value; it is the length of the data only
// the checksum is a 16-bit value. the CRC formula used is defined in crc.h.
// the checksum covers the entire messages, excluding itself
// eom is a special 2 byte sequence used to mark the End Of Message. This is
// needed for error recovery.
//
// A lot of behavior is based on knowledge of the upper level Quake network
// layer. For example, only one reliable message can be outstanding (pending
// reception of an MTYPE_ACK) at a time.
//
// The low level routines used to communicate with the modem are not part of
// this protocol.
//
// The CONTROL messages are only used for session establishment. They are
// not reliable or sequenced.
 
#define MTYPE_RELIABLE 0x01
#define MTYPE_UNRELIABLE 0x02
#define MTYPE_CONTROL 0x03
#define MTYPE_ACK 0x04
#define MTYPE_CLIENT 0x80
 
#define ESCAPE_COMMAND 0xe0
#define ESCAPE_EOM 0x19
 
static qboolean listening = false;
 
 
typedef struct SerialLine_s
{
struct SerialLine_s *next;
qsocket_t *sock;
int lengthStated;
int lengthFound;
int tty;
qboolean connected;
qboolean connecting;
qboolean client;
double connect_time;
unsigned short crcStated;
unsigned short crcValue;
byte currState;
byte prevState;
byte mtype;
byte sequence;
} SerialLine;
 
#define STATE_READY 0
#define STATE_SEQUENCE 1
#define STATE_LENGTH1 2
#define STATE_LENGTH2 3
#define STATE_DATA 4
#define STATE_CRC1 5
#define STATE_CRC2 6
#define STATE_EOM 7
#define STATE_ESCAPE 8
#define STATE_ABORT 9
 
SerialLine serialLine[NUM_COM_PORTS];
 
int myDriverLevel;
 
static void Serial_SendACK (SerialLine *p, byte sequence);
 
 
static void ResetSerialLineProtocol (SerialLine *p)
{
p->connected = false;
p->connecting = false;
p->currState = STATE_READY;
p->prevState = STATE_READY;
p->lengthFound = 0;
}
 
 
static int ProcessInQueue(SerialLine *p)
{
int b;
 
while (1)
{
b = TTY_ReadByte(p->tty);
if (b == ERR_TTY_NODATA)
break;
 
if (b == ERR_TTY_LINE_STATUS)
{
p->currState = STATE_ABORT;
continue;
}
if (b == ERR_TTY_MODEM_STATUS)
{
p->currState = STATE_ABORT;
return -1;
}
 
if (b == ESCAPE_COMMAND)
if (p->currState != STATE_ESCAPE)
{
p->prevState = p->currState;
p->currState = STATE_ESCAPE;
continue;
}
 
if (p->currState == STATE_ESCAPE)
{
if (b == ESCAPE_EOM)
{
if (p->prevState == STATE_ABORT)
{
p->currState = STATE_READY;
p->lengthFound = 0;
continue;
}
 
if (p->prevState != STATE_EOM)
{
p->currState = STATE_READY;
p->lengthFound = 0;
Con_DPrintf("Serial: premature EOM\n");
continue;
}
 
switch (p->mtype)
{
case MTYPE_RELIABLE:
Con_DPrintf("Serial: sending ack %u\n", p->sequence);
Serial_SendACK (p, p->sequence);
if (p->sequence == p->sock->receiveSequence)
{
p->sock->receiveSequence = (p->sequence + 1) & 0xff;
p->sock->receiveMessageLength += p->lengthFound;
}
else
Con_DPrintf("Serial: reliable out of order; got %u wanted %u\n", p->sequence, p->sock->receiveSequence);
break;
 
case MTYPE_UNRELIABLE:
p->sock->unreliableReceiveSequence = (p->sequence + 1) & 0xff;
p->sock->receiveMessageLength += p->lengthFound;
break;
 
case MTYPE_ACK:
Con_DPrintf("Serial: got ack %u\n", p->sequence);
if (p->sequence == p->sock->sendSequence)
{
p->sock->sendSequence = (p->sock->sendSequence + 1) & 0xff;
p->sock->canSend = true;
}
else
Con_DPrintf("Serial: ack out of order; got %u wanted %u\n",p->sequence, p->sock->sendSequence);
break;
 
case MTYPE_CONTROL:
p->sock->receiveMessageLength += p->lengthFound;
break;
}
 
p->currState = STATE_READY;
p->lengthFound = 0;
continue;
}
 
 
if (b != ESCAPE_COMMAND)
{
p->currState = STATE_ABORT;
Con_DPrintf("Serial: Bad escape sequence\n");
continue;
}
 
// b == ESCAPE_COMMAND
p->currState = p->prevState;
}
 
p->prevState = p->currState;
 
//DEBUG
if (p->sock->receiveMessageLength + p->lengthFound > NET_MAXMESSAGE)
{
Con_DPrintf("Serial blew out receive buffer: %u\n", p->sock->receiveMessageLength + p->lengthFound);
p->currState = STATE_ABORT;
}
if (p->sock->receiveMessageLength + p->lengthFound == NET_MAXMESSAGE)
{
Con_DPrintf("Serial hit receive buffer limit: %u\n", p->sock->receiveMessageLength + p->lengthFound);
p->currState = STATE_ABORT;
}
//end DEBUG
 
switch (p->currState)
{
case STATE_READY:
CRC_Init(&p->crcValue);
CRC_ProcessByte(&p->crcValue, b);
if (p->client)
{
if ((b & MTYPE_CLIENT) != 0)
{
p->currState = STATE_ABORT;
Con_DPrintf("Serial: client got own message\n");
break;
}
}
else
{
if ((b & MTYPE_CLIENT) == 0)
{
p->currState = STATE_ABORT;
Con_DPrintf("Serial: server got own message\n");
break;
}
b &= 0x7f;
}
p->mtype = b;
if (b != MTYPE_CONTROL)
p->currState = STATE_SEQUENCE;
else
p->currState = STATE_LENGTH1;
if (p->mtype < MTYPE_ACK)
{
p->sock->receiveMessage[p->sock->receiveMessageLength] = b;
p->lengthFound++;
}
break;
 
case STATE_SEQUENCE:
p->sequence = b;
CRC_ProcessByte(&p->crcValue, b);
if (p->mtype != MTYPE_ACK)
p->currState = STATE_LENGTH1;
else
p->currState = STATE_CRC1;
break;
 
case STATE_LENGTH1:
p->lengthStated = b * 256;
CRC_ProcessByte(&p->crcValue, b);
p->currState = STATE_LENGTH2;
break;
 
case STATE_LENGTH2:
p->lengthStated += b;
CRC_ProcessByte(&p->crcValue, b);
if (p->mtype == MTYPE_RELIABLE && p->lengthStated > MAX_MSGLEN)
{
p->currState = STATE_ABORT;
Con_DPrintf("Serial: bad reliable message length %u\n", p->lengthStated);
}
else if (p->mtype == MTYPE_UNRELIABLE && p->lengthStated > MAX_DATAGRAM)
{
p->currState = STATE_ABORT;
Con_DPrintf("Serial: bad unreliable message length %u\n", p->lengthStated);
}
else
{
p->currState = STATE_DATA;
if (p->mtype < MTYPE_ACK)
{
*(short *)&p->sock->receiveMessage [p->sock->receiveMessageLength + 1] = p->lengthStated;
p->lengthFound += 2;
}
}
break;
 
case STATE_DATA:
p->sock->receiveMessage[p->sock->receiveMessageLength + p->lengthFound] = b;
p->lengthFound++;
CRC_ProcessByte(&p->crcValue, b);
if (p->lengthFound == p->lengthStated + 3)
p->currState = STATE_CRC1;
break;
 
case STATE_CRC1:
p->crcStated = b * 256;
p->currState = STATE_CRC2;
break;
 
case STATE_CRC2:
p->crcStated += b;
if (p->crcStated == CRC_Value(p->crcValue))
{
p->currState = STATE_EOM;
}
else
{
p->currState = STATE_ABORT;
Con_DPrintf("Serial: Bad crc\n");
}
break;
 
case STATE_EOM:
p->currState = STATE_ABORT;
Con_DPrintf("Serial: Bad message format\n");
break;
 
case STATE_ABORT:
break;
}
}
return 0;
}
 
 
int Serial_Init (void)
{
int n;
 
// LATER do Win32 serial support
#ifdef _WIN32
return -1;
#endif
 
if (COM_CheckParm("-nolan"))
return -1;
if (COM_CheckParm ("-noserial"))
return -1;
 
myDriverLevel = net_driverlevel;
 
if (TTY_Init())
return -1;
 
for (n = 0; n < NUM_COM_PORTS; n++)
{
serialLine[n].tty = TTY_Open(n);
ResetSerialLineProtocol (&serialLine[n]);
}
 
Con_Printf("Serial driver initialized\n");
serialAvailable = true;
 
return 0;
}
 
 
void Serial_Shutdown (void)
{
int n;
 
for (n = 0; n < NUM_COM_PORTS; n++)
{
if (serialLine[n].connected)
Serial_Close(serialLine[n].sock);
}
 
TTY_Shutdown();
}
 
 
void Serial_Listen (qboolean state)
{
listening = state;
}
 
 
qboolean Serial_CanSendMessage (qsocket_t *sock)
{
return sock->canSend;
}
 
 
qboolean Serial_CanSendUnreliableMessage (qsocket_t *sock)
{
return TTY_OutputQueueIsEmpty(((SerialLine *)sock->driverdata)->tty);
}
 
 
int Serial_SendMessage (qsocket_t *sock, sizebuf_t *message)
{
SerialLine *p;
int n;
unsigned short crc;
byte b;
 
p = (SerialLine *)sock->driverdata;
CRC_Init (&crc);
 
// message type
b = MTYPE_RELIABLE;
if (p->client)
b |= MTYPE_CLIENT;
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
 
// sequence
b = p->sock->sendSequence;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
 
// data length
b = message->cursize >> 8;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
b = message->cursize & 0xff;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
 
// data
for (n = 0; n < message->cursize; n++)
{
b = message->data[n];
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
}
 
// checksum
b = CRC_Value (crc) >> 8;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
b = CRC_Value (crc) & 0xff;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
 
// end of message
TTY_WriteByte(p->tty, ESCAPE_COMMAND);
TTY_WriteByte(p->tty, ESCAPE_EOM);
 
TTY_Flush(p->tty);
 
// mark sock as busy and save the message for possible retransmit
sock->canSend = false;
Q_memcpy(sock->sendMessage, message->data, message->cursize);
sock->sendMessageLength = message->cursize;
sock->lastSendTime = net_time;
 
return 1;
}
 
 
static void ReSendMessage (qsocket_t *sock)
{
sizebuf_t temp;
 
Con_DPrintf("Serial: re-sending reliable\n");
temp.data = sock->sendMessage;
temp.maxsize = sock->sendMessageLength;
temp.cursize = sock->sendMessageLength;
Serial_SendMessage (sock, &temp);
}
 
 
int Serial_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *message)
{
SerialLine *p;
int n;
unsigned short crc;
byte b;
 
p = (SerialLine *)sock->driverdata;
 
if (!TTY_OutputQueueIsEmpty(p->tty))
{
TTY_Flush(p->tty);
return 1;
}
 
CRC_Init (&crc);
 
// message type
b = MTYPE_UNRELIABLE;
if (p->client)
b |= MTYPE_CLIENT;
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
 
// sequence
b = p->sock->unreliableSendSequence;
p->sock->unreliableSendSequence = (b + 1) & 0xff;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
 
// data length
b = message->cursize >> 8;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
b = message->cursize & 0xff;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
 
// data
for (n = 0; n < message->cursize; n++)
{
b = message->data[n];
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
}
 
// checksum
b = CRC_Value (crc) >> 8;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
b = CRC_Value (crc) & 0xff;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
 
// end of message
TTY_WriteByte(p->tty, ESCAPE_COMMAND);
TTY_WriteByte(p->tty, ESCAPE_EOM);
 
TTY_Flush(p->tty);
 
return 1;
}
 
 
static void Serial_SendACK (SerialLine *p, byte sequence)
{
unsigned short crc;
byte b;
 
CRC_Init (&crc);
 
// message type
b = MTYPE_ACK;
if (p->client)
b |= MTYPE_CLIENT;
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
 
// sequence
b = sequence;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
 
// checksum
b = CRC_Value (crc) >> 8;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
b = CRC_Value (crc) & 0xff;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
 
// end of message
TTY_WriteByte(p->tty, ESCAPE_COMMAND);
TTY_WriteByte(p->tty, ESCAPE_EOM);
 
TTY_Flush(p->tty);
}
 
 
static void Serial_SendControlMessage (SerialLine *p, sizebuf_t *message)
{
unsigned short crc;
int n;
byte b;
 
CRC_Init (&crc);
 
// message type
b = MTYPE_CONTROL;
if (p->client)
b |= MTYPE_CLIENT;
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
 
// data length
b = message->cursize >> 8;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
b = message->cursize & 0xff;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
 
// data
for (n = 0; n < message->cursize; n++)
{
b = message->data[n];
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
}
 
// checksum
b = CRC_Value (crc) >> 8;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
b = CRC_Value (crc) & 0xff;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
 
// end of message
TTY_WriteByte(p->tty, ESCAPE_COMMAND);
TTY_WriteByte(p->tty, ESCAPE_EOM);
 
TTY_Flush(p->tty);
}
 
 
static int _Serial_GetMessage (SerialLine *p)
{
byte ret;
short length;
 
if (ProcessInQueue(p))
return -1;
 
if (p->sock->receiveMessageLength == 0)
return 0;
 
ret = p->sock->receiveMessage[0];
length = *(short *)&p->sock->receiveMessage[1];
if (ret == MTYPE_CONTROL)
ret = 1;
 
SZ_Clear (&net_message);
SZ_Write (&net_message, &p->sock->receiveMessage[3], length);
 
length += 3;
p->sock->receiveMessageLength -= length;
 
if (p->sock->receiveMessageLength + p->lengthFound)
Q_memcpy(p->sock->receiveMessage, &p->sock->receiveMessage[length], p->sock->receiveMessageLength + p->lengthFound);
 
return ret;
}
 
int Serial_GetMessage (qsocket_t *sock)
{
SerialLine *p;
int ret;
 
p = (SerialLine *)sock->driverdata;
 
ret = _Serial_GetMessage (p);
 
if (ret == 1)
messagesReceived++;
 
if (!sock->canSend)
if ((net_time - sock->lastSendTime) > 1.0)
{
ReSendMessage (sock);
sock->lastSendTime = net_time;
}
 
return ret;
}
 
 
void Serial_Close (qsocket_t *sock)
{
SerialLine *p = (SerialLine *)sock->driverdata;
TTY_Close(p->tty);
ResetSerialLineProtocol (p);
}
 
 
char *com_types[] = {"direct", "modem"};
unsigned com_bauds[] = {9600, 14400, 19200, 28800, 57600};
 
void Serial_SearchForHosts (qboolean xmit)
{
int n;
SerialLine *p;
 
if (sv.active)
return;
 
if (hostCacheCount == HOSTCACHESIZE)
return;
 
// see if we've already answered
for (n = 0; n < hostCacheCount; n++)
if (Q_strcmp (hostcache[n].cname, "#") == 0)
return;
 
for (n = 0; n < NUM_COM_PORTS; n++)
if (TTY_IsEnabled(n))
break;
if (n == NUM_COM_PORTS)
return;
p = &serialLine[n];
 
if (TTY_IsModem(p->tty))
return;
 
sprintf(hostcache[hostCacheCount].name, "COM%u", n+1);
Q_strcpy(hostcache[hostCacheCount].map, "");
hostcache[hostCacheCount].users = 0;
hostcache[hostCacheCount].maxusers = 0;
hostcache[hostCacheCount].driver = net_driverlevel;
Q_strcpy(hostcache[hostCacheCount].cname, "#");
hostCacheCount++;
 
return;
}
 
 
static qsocket_t *_Serial_Connect (char *host, SerialLine *p)
{
int ret;
double start_time;
double last_time;
 
p->client = true;
if (TTY_Connect(p->tty, host))
return NULL;
 
p->sock = NET_NewQSocket ();
p->sock->driver = myDriverLevel;
if (p->sock == NULL)
{
Con_Printf("No sockets available\n");
return NULL;
}
p->sock->driverdata = p;
 
// send the connection request
start_time = SetNetTime();
last_time = 0.0;
 
SZ_Clear(&net_message);
MSG_WriteByte(&net_message, CCREQ_CONNECT);
MSG_WriteString(&net_message, "QUAKE");
do
{
SetNetTime();
if ((net_time - last_time) >= 1.0)
{
Serial_SendControlMessage (p, &net_message);
last_time = net_time;
Con_Printf("trying...\n"); SCR_UpdateScreen ();
}
ret = _Serial_GetMessage (p);
}
while (ret == 0 && (net_time - start_time) < 5.0);
 
if (ret == 0)
{
Con_Printf("Unable to connect, no response\n");
goto ErrorReturn;
}
 
if (ret == -1)
{
Con_Printf("Connection request error\n");
goto ErrorReturn;
}
 
MSG_BeginReading ();
ret = MSG_ReadByte();
if (ret == CCREP_REJECT)
{
Con_Printf(MSG_ReadString());
goto ErrorReturn;
}
if (ret != CCREP_ACCEPT)
{
Con_Printf("Unknown connection response\n");
goto ErrorReturn;
}
 
p->connected = true;
p->sock->lastMessageTime = net_time;
 
Con_Printf ("Connection accepted\n");
 
return p->sock;
 
ErrorReturn:
TTY_Disconnect(p->tty);
return NULL;
}
 
qsocket_t *Serial_Connect (char *host)
{
int n;
qsocket_t *ret = NULL;
 
// see if this looks like a phone number
if (*host == '#')
host++;
for (n = 0; n < Q_strlen(host); n++)
if (host[n] == '.' || host[n] == ':')
return NULL;
 
for (n = 0; n < NUM_COM_PORTS; n++)
if (TTY_IsEnabled(n) && !serialLine[n].connected)
if ((ret = _Serial_Connect (host, &serialLine[n])))
break;
return ret;
}
 
 
static qsocket_t *_Serial_CheckNewConnections (SerialLine *p)
{
int command;
 
p->client = false;
if (!TTY_CheckForConnection(p->tty))
return NULL;
 
if (TTY_IsModem(p->tty))
{
if (!p->connecting)
{
p->connecting = true;
p->connect_time = net_time;
}
else if ((net_time - p->connect_time) > 15.0)
{
p->connecting = false;
TTY_Disconnect(p->tty);
return NULL;
}
}
 
p->sock = NET_NewQSocket ();
p->sock->driver = myDriverLevel;
if (p->sock == NULL)
{
Con_Printf("No sockets available\n");
return NULL;
}
p->sock->driverdata = p;
 
SZ_Clear(&net_message);
if (_Serial_GetMessage(p) != 1)
{
NET_FreeQSocket(p->sock);
return NULL;
}
 
MSG_BeginReading ();
command = MSG_ReadByte();
 
if (command == CCREQ_SERVER_INFO)
{
if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0)
return NULL;
 
if (MSG_ReadByte() != SERIAL_PROTOCOL_VERSION)
return NULL;
 
SZ_Clear(&net_message);
MSG_WriteByte(&net_message, CCREP_SERVER_INFO);
MSG_WriteString(&net_message, hostname.string);
MSG_WriteString(&net_message, sv.name);
MSG_WriteByte(&net_message, net_activeconnections);
MSG_WriteByte(&net_message, svs.maxclients);
Serial_SendControlMessage (p, &net_message);
SZ_Clear(&net_message);
return NULL;
}
 
if (command != CCREQ_CONNECT)
return NULL;
 
if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0)
return NULL;
 
// send him back the info about the server connection he has been allocated
SZ_Clear(&net_message);
MSG_WriteByte(&net_message, CCREP_ACCEPT);
Serial_SendControlMessage (p, &net_message);
SZ_Clear(&net_message);
 
p->connected = true;
p->connecting = false;
p->sock->lastMessageTime = net_time;
sprintf(p->sock->address, "COM%u", (int)((p - serialLine) + 1));
 
return p->sock;
}
 
qsocket_t *Serial_CheckNewConnections (void)
{
int n;
qsocket_t *ret = NULL;
 
for (n = 0; n < NUM_COM_PORTS; n++)
if (TTY_IsEnabled(n) && !serialLine[n].connected)
if ((ret = _Serial_CheckNewConnections (&serialLine[n])))
break;
return ret;
}
/contrib/other/sdlquake-1.0.9/net_ser.h
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_ser.h
 
int Serial_Init (void);
void Serial_Listen (qboolean state);
void Serial_SearchForHosts (qboolean xmit);
qsocket_t *Serial_Connect (char *host);
qsocket_t *Serial_CheckNewConnections (void);
int Serial_GetMessage (qsocket_t *sock);
int Serial_SendMessage (qsocket_t *sock, sizebuf_t *data);
int Serial_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data);
qboolean Serial_CanSendMessage (qsocket_t *sock);
qboolean Serial_CanSendUnreliableMessage (qsocket_t *sock);
void Serial_Close (qsocket_t *sock);
void Serial_Shutdown (void);
/contrib/other/sdlquake-1.0.9/net_udp.c
0,0 → 1,415
/*
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_udp.c
 
#include "quakedef.h"
 
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <errno.h>
 
#ifdef __sun__
#include <sys/filio.h>
#endif
 
#ifdef NeXT
#include <libc.h>
#endif
 
extern int gethostname (char *, int);
extern int close (int);
 
extern cvar_t hostname;
 
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;
 
#include "net_udp.h"
 
//=============================================================================
 
int UDP_Init (void)
{
struct hostent *local;
char buff[MAXHOSTNAMELEN];
struct qsockaddr addr;
char *colon;
if (COM_CheckParm ("-noudp"))
return -1;
 
// determine my name & address
gethostname(buff, MAXHOSTNAMELEN);
local = gethostbyname(buff);
myAddr = *(int *)local->h_addr_list[0];
 
// if the quake hostname isn't set, set it to the machine name
if (Q_strcmp(hostname.string, "UNNAMED") == 0)
{
buff[15] = 0;
Cvar_Set ("hostname", buff);
}
 
if ((net_controlsocket = UDP_OpenSocket (0)) == -1)
Sys_Error("UDP_Init: Unable to open control socket\n");
 
((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(net_hostport);
 
UDP_GetSocketAddr (net_controlsocket, &addr);
Q_strcpy(my_tcpip_address, UDP_AddrToString (&addr));
colon = Q_strrchr (my_tcpip_address, ':');
if (colon)
*colon = 0;
 
Con_Printf("UDP Initialized\n");
tcpipAvailable = true;
 
return net_controlsocket;
}
 
//=============================================================================
 
void UDP_Shutdown (void)
{
UDP_Listen (false);
UDP_CloseSocket (net_controlsocket);
}
 
//=============================================================================
 
void UDP_Listen (qboolean state)
{
// enable listening
if (state)
{
if (net_acceptsocket != -1)
return;
if ((net_acceptsocket = UDP_OpenSocket (net_hostport)) == -1)
Sys_Error ("UDP_Listen: Unable to open accept socket\n");
return;
}
 
// disable listening
if (net_acceptsocket == -1)
return;
UDP_CloseSocket (net_acceptsocket);
net_acceptsocket = -1;
}
 
//=============================================================================
 
int UDP_OpenSocket (int port)
{
int newsocket;
struct sockaddr_in address;
qboolean _true = true;
 
if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
return -1;
 
#if 0
if (ioctl (newsocket, FIONBIO, (char *)&_true) == -1)
goto ErrorReturn;
#endif
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(port);
if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
goto ErrorReturn;
 
return newsocket;
 
ErrorReturn:
close (newsocket);
return -1;
}
 
//=============================================================================
 
int UDP_CloseSocket (int socket)
{
if (socket == net_broadcastsocket)
net_broadcastsocket = 0;
return close (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 UDP_Connect (int socket, struct qsockaddr *addr)
{
return 0;
}
 
//=============================================================================
 
int UDP_CheckNewConnections (void)
{
unsigned long available;
 
if (net_acceptsocket == -1)
return -1;
 
if (ioctl (net_acceptsocket, FIONREAD, &available) == -1)
Sys_Error ("UDP: ioctlsocket (FIONREAD) failed\n");
if (available)
return net_acceptsocket;
return -1;
}
 
//=============================================================================
 
int UDP_Read (int socket, byte *buf, int len, struct qsockaddr *addr)
{
int addrlen = sizeof (struct qsockaddr);
int ret;
 
ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen);
if (ret == -1 && (errno == EWOULDBLOCK || errno == ECONNREFUSED))
return 0;
return ret;
}
 
//=============================================================================
 
int UDP_MakeSocketBroadcastCapable (int socket)
{
int i = 1;
 
// make this socket broadcast capable
if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0)
return -1;
net_broadcastsocket = socket;
 
return 0;
}
 
//=============================================================================
 
int UDP_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");
ret = UDP_MakeSocketBroadcastCapable (socket);
if (ret == -1)
{
Con_Printf("Unable to make socket broadcast capable\n");
return ret;
}
}
 
return UDP_Write (socket, buf, len, &broadcastaddr);
}
 
//=============================================================================
 
int UDP_Write (int socket, byte *buf, int len, struct qsockaddr *addr)
{
int ret;
 
ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr));
if (ret == -1 && errno == EWOULDBLOCK)
return 0;
return ret;
}
 
//=============================================================================
 
char *UDP_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 UDP_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(hp);
return 0;
}
 
//=============================================================================
 
int UDP_GetSocketAddr (int socket, struct qsockaddr *addr)
{
int addrlen = sizeof(struct qsockaddr);
unsigned int a;
 
Q_memset(addr, 0, sizeof(struct qsockaddr));
getsockname(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 UDP_GetNameFromAddr (struct qsockaddr *addr, char *name)
{
struct hostent *hostentry;
 
hostentry = gethostbyaddr ((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, UDP_AddrToString (addr));
return 0;
}
 
//=============================================================================
 
int UDP_GetAddrFromName(char *name, struct qsockaddr *addr)
{
struct hostent *hostentry;
 
if (name[0] >= '0' && name[0] <= '9')
return PartialIPAddress (name, addr);
hostentry = gethostbyname (name);
if (!hostentry)
return -1;
 
addr->sa_family = AF_INET;
((struct sockaddr_in *)addr)->sin_port = htons(net_hostport);
((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
 
return 0;
}
 
//=============================================================================
 
int UDP_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 UDP_GetSocketPort (struct qsockaddr *addr)
{
return ntohs(((struct sockaddr_in *)addr)->sin_port);
}
 
 
int UDP_SetSocketPort (struct qsockaddr *addr, int port)
{
((struct sockaddr_in *)addr)->sin_port = htons(port);
return 0;
}
 
//=============================================================================
/contrib/other/sdlquake-1.0.9/net_udp.h
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_udp.h
 
int UDP_Init (void);
void UDP_Shutdown (void);
void UDP_Listen (qboolean state);
int UDP_OpenSocket (int port);
int UDP_CloseSocket (int socket);
int UDP_Connect (int socket, struct qsockaddr *addr);
int UDP_CheckNewConnections (void);
int UDP_Read (int socket, byte *buf, int len, struct qsockaddr *addr);
int UDP_Write (int socket, byte *buf, int len, struct qsockaddr *addr);
int UDP_Broadcast (int socket, byte *buf, int len);
char *UDP_AddrToString (struct qsockaddr *addr);
int UDP_StringToAddr (char *string, struct qsockaddr *addr);
int UDP_GetSocketAddr (int socket, struct qsockaddr *addr);
int UDP_GetNameFromAddr (struct qsockaddr *addr, char *name);
int UDP_GetAddrFromName (char *name, struct qsockaddr *addr);
int UDP_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2);
int UDP_GetSocketPort (struct qsockaddr *addr);
int UDP_SetSocketPort (struct qsockaddr *addr, int port);
/contrib/other/sdlquake-1.0.9/net_vcr.c
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;
}
/contrib/other/sdlquake-1.0.9/net_vcr.h
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);
/contrib/other/sdlquake-1.0.9/net_win.c
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;
/contrib/other/sdlquake-1.0.9/net_wins.c
0,0 → 1,575
/*
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)
{
int errno = pWSAGetLastError();
 
if (errno == WSAEWOULDBLOCK || errno == WSAECONNREFUSED)
return 0;
 
}
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;
}
 
//=============================================================================
/contrib/other/sdlquake-1.0.9/net_wins.h
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);
/contrib/other/sdlquake-1.0.9/net_wipx.c
0,0 → 1,432
/*
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)
{
int errno = pWSAGetLastError();
 
if (errno == WSAEWOULDBLOCK || errno == WSAECONNREFUSED)
return 0;
 
}
 
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)
{
int errno = pWSAGetLastError();
}
 
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;
}
 
//=============================================================================
/contrib/other/sdlquake-1.0.9/net_wipx.h
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);
/contrib/other/sdlquake-1.0.9/net_wso.c
--- nonintel.c (nonexistent)
+++ nonintel.c (revision 5131)
@@ -0,0 +1,64 @@
+/*
+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.
+
+*/
+//
+// nonintel.c: code for non-Intel processors only
+//
+
+#include "quakedef.h"
+#include "r_local.h"
+#include "d_local.h"
+
+#if !id386
+
+/*
+================
+R_Surf8Patch
+================
+*/
+void R_Surf8Patch ()
+{
+ // we only patch code on Intel
+}
+
+
+/*
+================
+R_Surf16Patch
+================
+*/
+void R_Surf16Patch ()
+{
+ // we only patch code on Intel
+}
+
+
+/*
+================
+R_SurfacePatch
+================
+*/
+void R_SurfacePatch (void)
+{
+ // we only patch code on Intel
+}
+
+
+#endif // !id386
+
/contrib/other/sdlquake-1.0.9/pr_cmds.c
0,0 → 1,1934
/*
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"
 
#define RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e))
 
/*
===============================================================================
 
BUILT-IN FUNCTIONS
 
===============================================================================
*/
 
char *PF_VarString (int first)
{
int i;
static char out[256];
out[0] = 0;
for (i=first ; i<pr_argc ; i++)
{
strcat (out, G_STRING((OFS_PARM0+i*3)));
}
return out;
}
 
 
/*
=================
PF_errror
 
This is a TERMINAL error, which will kill off the entire server.
Dumps self.
 
error(value)
=================
*/
void PF_error (void)
{
char *s;
edict_t *ed;
s = PF_VarString(0);
Con_Printf ("======SERVER ERROR in %s:\n%s\n"
,pr_strings + pr_xfunction->s_name,s);
ed = PROG_TO_EDICT(pr_global_struct->self);
ED_Print (ed);
 
Host_Error ("Program error");
}
 
/*
=================
PF_objerror
 
Dumps out self, then an error message. The program is aborted and self is
removed, but the level can continue.
 
objerror(value)
=================
*/
void PF_objerror (void)
{
char *s;
edict_t *ed;
s = PF_VarString(0);
Con_Printf ("======OBJECT ERROR in %s:\n%s\n"
,pr_strings + pr_xfunction->s_name,s);
ed = PROG_TO_EDICT(pr_global_struct->self);
ED_Print (ed);
ED_Free (ed);
Host_Error ("Program error");
}
 
 
 
/*
==============
PF_makevectors
 
Writes new values for v_forward, v_up, and v_right based on angles
makevectors(vector)
==============
*/
void PF_makevectors (void)
{
AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
}
 
/*
=================
PF_setorigin
 
This is the only valid way to move an object without using the physics of the world (setting velocity and waiting). Directly changing origin will not set internal links correctly, so clipping would be messed up. This should be called when an object is spawned, and then only if it is teleported.
 
setorigin (entity, origin)
=================
*/
void PF_setorigin (void)
{
edict_t *e;
float *org;
e = G_EDICT(OFS_PARM0);
org = G_VECTOR(OFS_PARM1);
VectorCopy (org, e->v.origin);
SV_LinkEdict (e, false);
}
 
 
void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
{
float *angles;
vec3_t rmin, rmax;
float bounds[2][3];
float xvector[2], yvector[2];
float a;
vec3_t base, transformed;
int i, j, k, l;
for (i=0 ; i<3 ; i++)
if (min[i] > max[i])
PR_RunError ("backwards mins/maxs");
 
rotate = false; // FIXME: implement rotation properly again
 
if (!rotate)
{
VectorCopy (min, rmin);
VectorCopy (max, rmax);
}
else
{
// find min / max for rotations
angles = e->v.angles;
a = angles[1]/180 * M_PI;
xvector[0] = cos(a);
xvector[1] = sin(a);
yvector[0] = -sin(a);
yvector[1] = cos(a);
VectorCopy (min, bounds[0]);
VectorCopy (max, bounds[1]);
rmin[0] = rmin[1] = rmin[2] = 9999;
rmax[0] = rmax[1] = rmax[2] = -9999;
for (i=0 ; i<= 1 ; i++)
{
base[0] = bounds[i][0];
for (j=0 ; j<= 1 ; j++)
{
base[1] = bounds[j][1];
for (k=0 ; k<= 1 ; k++)
{
base[2] = bounds[k][2];
// transform the point
transformed[0] = xvector[0]*base[0] + yvector[0]*base[1];
transformed[1] = xvector[1]*base[0] + yvector[1]*base[1];
transformed[2] = base[2];
for (l=0 ; l<3 ; l++)
{
if (transformed[l] < rmin[l])
rmin[l] = transformed[l];
if (transformed[l] > rmax[l])
rmax[l] = transformed[l];
}
}
}
}
}
// set derived values
VectorCopy (rmin, e->v.mins);
VectorCopy (rmax, e->v.maxs);
VectorSubtract (max, min, e->v.size);
SV_LinkEdict (e, false);
}
 
/*
=================
PF_setsize
 
the size box is rotated by the current angle
 
setsize (entity, minvector, maxvector)
=================
*/
void PF_setsize (void)
{
edict_t *e;
float *min, *max;
e = G_EDICT(OFS_PARM0);
min = G_VECTOR(OFS_PARM1);
max = G_VECTOR(OFS_PARM2);
SetMinMaxSize (e, min, max, false);
}
 
 
/*
=================
PF_setmodel
 
setmodel(entity, model)
=================
*/
void PF_setmodel (void)
{
edict_t *e;
char *m, **check;
model_t *mod;
int i;
 
e = G_EDICT(OFS_PARM0);
m = G_STRING(OFS_PARM1);
 
// check to see if model was properly precached
for (i=0, check = sv.model_precache ; *check ; i++, check++)
if (!strcmp(*check, m))
break;
if (!*check)
PR_RunError ("no precache: %s\n", m);
 
e->v.model = m - pr_strings;
e->v.modelindex = i; //SV_ModelIndex (m);
 
mod = sv.models[ (int)e->v.modelindex]; // Mod_ForName (m, true);
if (mod)
SetMinMaxSize (e, mod->mins, mod->maxs, true);
else
SetMinMaxSize (e, vec3_origin, vec3_origin, true);
}
 
/*
=================
PF_bprint
 
broadcast print to everyone on server
 
bprint(value)
=================
*/
void PF_bprint (void)
{
char *s;
 
s = PF_VarString(0);
SV_BroadcastPrintf ("%s", s);
}
 
/*
=================
PF_sprint
 
single print to a specific client
 
sprint(clientent, value)
=================
*/
void PF_sprint (void)
{
char *s;
client_t *client;
int entnum;
entnum = G_EDICTNUM(OFS_PARM0);
s = PF_VarString(1);
if (entnum < 1 || entnum > svs.maxclients)
{
Con_Printf ("tried to sprint to a non-client\n");
return;
}
client = &svs.clients[entnum-1];
MSG_WriteChar (&client->message,svc_print);
MSG_WriteString (&client->message, s );
}
 
 
/*
=================
PF_centerprint
 
single print to a specific client
 
centerprint(clientent, value)
=================
*/
void PF_centerprint (void)
{
char *s;
client_t *client;
int entnum;
entnum = G_EDICTNUM(OFS_PARM0);
s = PF_VarString(1);
if (entnum < 1 || entnum > svs.maxclients)
{
Con_Printf ("tried to sprint to a non-client\n");
return;
}
client = &svs.clients[entnum-1];
MSG_WriteChar (&client->message,svc_centerprint);
MSG_WriteString (&client->message, s );
}
 
 
/*
=================
PF_normalize
 
vector normalize(vector)
=================
*/
void PF_normalize (void)
{
float *value1;
vec3_t newvalue;
float new;
value1 = G_VECTOR(OFS_PARM0);
 
new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
new = sqrt(new);
if (new == 0)
newvalue[0] = newvalue[1] = newvalue[2] = 0;
else
{
new = 1/new;
newvalue[0] = value1[0] * new;
newvalue[1] = value1[1] * new;
newvalue[2] = value1[2] * new;
}
VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
}
 
/*
=================
PF_vlen
 
scalar vlen(vector)
=================
*/
void PF_vlen (void)
{
float *value1;
float new;
value1 = G_VECTOR(OFS_PARM0);
 
new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
new = sqrt(new);
G_FLOAT(OFS_RETURN) = new;
}
 
/*
=================
PF_vectoyaw
 
float vectoyaw(vector)
=================
*/
void PF_vectoyaw (void)
{
float *value1;
float yaw;
value1 = G_VECTOR(OFS_PARM0);
 
if (value1[1] == 0 && value1[0] == 0)
yaw = 0;
else
{
yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
if (yaw < 0)
yaw += 360;
}
 
G_FLOAT(OFS_RETURN) = yaw;
}
 
 
/*
=================
PF_vectoangles
 
vector vectoangles(vector)
=================
*/
void PF_vectoangles (void)
{
float *value1;
float forward;
float yaw, pitch;
value1 = G_VECTOR(OFS_PARM0);
 
if (value1[1] == 0 && value1[0] == 0)
{
yaw = 0;
if (value1[2] > 0)
pitch = 90;
else
pitch = 270;
}
else
{
yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
if (yaw < 0)
yaw += 360;
 
forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]);
pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
if (pitch < 0)
pitch += 360;
}
 
G_FLOAT(OFS_RETURN+0) = pitch;
G_FLOAT(OFS_RETURN+1) = yaw;
G_FLOAT(OFS_RETURN+2) = 0;
}
 
/*
=================
PF_Random
 
Returns a number from 0<= num < 1
 
random()
=================
*/
void PF_random (void)
{
float num;
num = (rand ()&0x7fff) / ((float)0x7fff);
G_FLOAT(OFS_RETURN) = num;
}
 
/*
=================
PF_particle
 
particle(origin, color, count)
=================
*/
void PF_particle (void)
{
float *org, *dir;
float color;
float count;
org = G_VECTOR(OFS_PARM0);
dir = G_VECTOR(OFS_PARM1);
color = G_FLOAT(OFS_PARM2);
count = G_FLOAT(OFS_PARM3);
SV_StartParticle (org, dir, color, count);
}
 
 
/*
=================
PF_ambientsound
 
=================
*/
void PF_ambientsound (void)
{
char **check;
char *samp;
float *pos;
float vol, attenuation;
int i, soundnum;
 
pos = G_VECTOR (OFS_PARM0);
samp = G_STRING(OFS_PARM1);
vol = G_FLOAT(OFS_PARM2);
attenuation = G_FLOAT(OFS_PARM3);
// check to see if samp was properly precached
for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
if (!strcmp(*check,samp))
break;
if (!*check)
{
Con_Printf ("no precache: %s\n", samp);
return;
}
 
// add an svc_spawnambient command to the level signon packet
 
MSG_WriteByte (&sv.signon,svc_spawnstaticsound);
for (i=0 ; i<3 ; i++)
MSG_WriteCoord(&sv.signon, pos[i]);
 
MSG_WriteByte (&sv.signon, soundnum);
 
MSG_WriteByte (&sv.signon, vol*255);
MSG_WriteByte (&sv.signon, attenuation*64);
 
}
 
/*
=================
PF_sound
 
Each entity can have eight independant sound sources, like voice,
weapon, feet, etc.
 
Channel 0 is an auto-allocate channel, the others override anything
allready running on that entity/channel pair.
 
An attenuation of 0 will play full volume everywhere in the level.
Larger attenuations will drop off.
 
=================
*/
void PF_sound (void)
{
char *sample;
int channel;
edict_t *entity;
int volume;
float attenuation;
entity = G_EDICT(OFS_PARM0);
channel = G_FLOAT(OFS_PARM1);
sample = G_STRING(OFS_PARM2);
volume = G_FLOAT(OFS_PARM3) * 255;
attenuation = G_FLOAT(OFS_PARM4);
if (volume < 0 || volume > 255)
Sys_Error ("SV_StartSound: volume = %i", volume);
 
if (attenuation < 0 || attenuation > 4)
Sys_Error ("SV_StartSound: attenuation = %f", attenuation);
 
if (channel < 0 || channel > 7)
Sys_Error ("SV_StartSound: channel = %i", channel);
 
SV_StartSound (entity, channel, sample, volume, attenuation);
}
 
/*
=================
PF_break
 
break()
=================
*/
void PF_break (void)
{
Con_Printf ("break statement\n");
*(int *)-4 = 0; // dump to debugger
// PR_RunError ("break statement");
}
 
/*
=================
PF_traceline
 
Used for use tracing and shot targeting
Traces are blocked by bbox and exact bsp entityes, and also slide box entities
if the tryents flag is set.
 
traceline (vector1, vector2, tryents)
=================
*/
void PF_traceline (void)
{
float *v1, *v2;
trace_t trace;
int nomonsters;
edict_t *ent;
 
v1 = G_VECTOR(OFS_PARM0);
v2 = G_VECTOR(OFS_PARM1);
nomonsters = G_FLOAT(OFS_PARM2);
ent = G_EDICT(OFS_PARM3);
 
trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters, ent);
 
pr_global_struct->trace_allsolid = trace.allsolid;
pr_global_struct->trace_startsolid = trace.startsolid;
pr_global_struct->trace_fraction = trace.fraction;
pr_global_struct->trace_inwater = trace.inwater;
pr_global_struct->trace_inopen = trace.inopen;
VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
pr_global_struct->trace_plane_dist = trace.plane.dist;
if (trace.ent)
pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
else
pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
}
 
 
#ifdef QUAKE2
extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore);
 
void PF_TraceToss (void)
{
trace_t trace;
edict_t *ent;
edict_t *ignore;
 
ent = G_EDICT(OFS_PARM0);
ignore = G_EDICT(OFS_PARM1);
 
trace = SV_Trace_Toss (ent, ignore);
 
pr_global_struct->trace_allsolid = trace.allsolid;
pr_global_struct->trace_startsolid = trace.startsolid;
pr_global_struct->trace_fraction = trace.fraction;
pr_global_struct->trace_inwater = trace.inwater;
pr_global_struct->trace_inopen = trace.inopen;
VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
pr_global_struct->trace_plane_dist = trace.plane.dist;
if (trace.ent)
pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
else
pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
}
#endif
 
 
/*
=================
PF_checkpos
 
Returns true if the given entity can move to the given position from it's
current position by walking or rolling.
FIXME: make work...
scalar checkpos (entity, vector)
=================
*/
void PF_checkpos (void)
{
}
 
//============================================================================
 
byte checkpvs[MAX_MAP_LEAFS/8];
 
int PF_newcheckclient (int check)
{
int i;
byte *pvs;
edict_t *ent;
mleaf_t *leaf;
vec3_t org;
 
// cycle to the next one
 
if (check < 1)
check = 1;
if (check > svs.maxclients)
check = svs.maxclients;
 
if (check == svs.maxclients)
i = 1;
else
i = check + 1;
 
for ( ; ; i++)
{
if (i == svs.maxclients+1)
i = 1;
 
ent = EDICT_NUM(i);
 
if (i == check)
break; // didn't find anything else
 
if (ent->free)
continue;
if (ent->v.health <= 0)
continue;
if ((int)ent->v.flags & FL_NOTARGET)
continue;
 
// anything that is a client, or has a client as an enemy
break;
}
 
// get the PVS for the entity
VectorAdd (ent->v.origin, ent->v.view_ofs, org);
leaf = Mod_PointInLeaf (org, sv.worldmodel);
pvs = Mod_LeafPVS (leaf, sv.worldmodel);
memcpy (checkpvs, pvs, (sv.worldmodel->numleafs+7)>>3 );
 
return i;
}
 
/*
=================
PF_checkclient
 
Returns a client (or object that has a client enemy) that would be a
valid target.
 
If there are more than one valid options, they are cycled each frame
 
If (self.origin + self.viewofs) is not in the PVS of the current target,
it is not returned at all.
 
name checkclient ()
=================
*/
#define MAX_CHECK 16
int c_invis, c_notvis;
void PF_checkclient (void)
{
edict_t *ent, *self;
mleaf_t *leaf;
int l;
vec3_t view;
// find a new check if on a new frame
if (sv.time - sv.lastchecktime >= 0.1)
{
sv.lastcheck = PF_newcheckclient (sv.lastcheck);
sv.lastchecktime = sv.time;
}
 
// return check if it might be visible
ent = EDICT_NUM(sv.lastcheck);
if (ent->free || ent->v.health <= 0)
{
RETURN_EDICT(sv.edicts);
return;
}
 
// if current entity can't possibly see the check entity, return 0
self = PROG_TO_EDICT(pr_global_struct->self);
VectorAdd (self->v.origin, self->v.view_ofs, view);
leaf = Mod_PointInLeaf (view, sv.worldmodel);
l = (leaf - sv.worldmodel->leafs) - 1;
if ( (l<0) || !(checkpvs[l>>3] & (1<<(l&7)) ) )
{
c_notvis++;
RETURN_EDICT(sv.edicts);
return;
}
 
// might be able to see it
c_invis++;
RETURN_EDICT(ent);
}
 
//============================================================================
 
 
/*
=================
PF_stuffcmd
 
Sends text over to the client's execution buffer
 
stuffcmd (clientent, value)
=================
*/
void PF_stuffcmd (void)
{
int entnum;
char *str;
client_t *old;
entnum = G_EDICTNUM(OFS_PARM0);
if (entnum < 1 || entnum > svs.maxclients)
PR_RunError ("Parm 0 not a client");
str = G_STRING(OFS_PARM1);
old = host_client;
host_client = &svs.clients[entnum-1];
Host_ClientCommands ("%s", str);
host_client = old;
}
 
/*
=================
PF_localcmd
 
Sends text over to the client's execution buffer
 
localcmd (string)
=================
*/
void PF_localcmd (void)
{
char *str;
str = G_STRING(OFS_PARM0);
Cbuf_AddText (str);
}
 
/*
=================
PF_cvar
 
float cvar (string)
=================
*/
void PF_cvar (void)
{
char *str;
str = G_STRING(OFS_PARM0);
G_FLOAT(OFS_RETURN) = Cvar_VariableValue (str);
}
 
/*
=================
PF_cvar_set
 
float cvar (string)
=================
*/
void PF_cvar_set (void)
{
char *var, *val;
var = G_STRING(OFS_PARM0);
val = G_STRING(OFS_PARM1);
Cvar_Set (var, val);
}
 
/*
=================
PF_findradius
 
Returns a chain of entities that have origins within a spherical area
 
findradius (origin, radius)
=================
*/
void PF_findradius (void)
{
edict_t *ent, *chain;
float rad;
float *org;
vec3_t eorg;
int i, j;
 
chain = (edict_t *)sv.edicts;
org = G_VECTOR(OFS_PARM0);
rad = G_FLOAT(OFS_PARM1);
 
ent = NEXT_EDICT(sv.edicts);
for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
{
if (ent->free)
continue;
if (ent->v.solid == SOLID_NOT)
continue;
for (j=0 ; j<3 ; j++)
eorg[j] = org[j] - (ent->v.origin[j] + (ent->v.mins[j] + ent->v.maxs[j])*0.5);
if (Length(eorg) > rad)
continue;
ent->v.chain = EDICT_TO_PROG(chain);
chain = ent;
}
 
RETURN_EDICT(chain);
}
 
 
/*
=========
PF_dprint
=========
*/
void PF_dprint (void)
{
Con_DPrintf ("%s",PF_VarString(0));
}
 
char pr_string_temp[128];
 
void PF_ftos (void)
{
float v;
v = G_FLOAT(OFS_PARM0);
if (v == (int)v)
sprintf (pr_string_temp, "%d",(int)v);
else
sprintf (pr_string_temp, "%5.1f",v);
G_INT(OFS_RETURN) = pr_string_temp - pr_strings;
}
 
void PF_fabs (void)
{
float v;
v = G_FLOAT(OFS_PARM0);
G_FLOAT(OFS_RETURN) = fabs(v);
}
 
void PF_vtos (void)
{
sprintf (pr_string_temp, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
G_INT(OFS_RETURN) = pr_string_temp - pr_strings;
}
 
#ifdef QUAKE2
void PF_etos (void)
{
sprintf (pr_string_temp, "entity %i", G_EDICTNUM(OFS_PARM0));
G_INT(OFS_RETURN) = pr_string_temp - pr_strings;
}
#endif
 
void PF_Spawn (void)
{
edict_t *ed;
ed = ED_Alloc();
RETURN_EDICT(ed);
}
 
void PF_Remove (void)
{
edict_t *ed;
ed = G_EDICT(OFS_PARM0);
ED_Free (ed);
}
 
 
// entity (entity start, .string field, string match) find = #5;
void PF_Find (void)
#ifdef QUAKE2
{
int e;
int f;
char *s, *t;
edict_t *ed;
edict_t *first;
edict_t *second;
edict_t *last;
 
first = second = last = (edict_t *)sv.edicts;
e = G_EDICTNUM(OFS_PARM0);
f = G_INT(OFS_PARM1);
s = G_STRING(OFS_PARM2);
if (!s)
PR_RunError ("PF_Find: bad search string");
for (e++ ; e < sv.num_edicts ; e++)
{
ed = EDICT_NUM(e);
if (ed->free)
continue;
t = E_STRING(ed,f);
if (!t)
continue;
if (!strcmp(t,s))
{
if (first == (edict_t *)sv.edicts)
first = ed;
else if (second == (edict_t *)sv.edicts)
second = ed;
ed->v.chain = EDICT_TO_PROG(last);
last = ed;
}
}
 
if (first != last)
{
if (last != second)
first->v.chain = last->v.chain;
else
first->v.chain = EDICT_TO_PROG(last);
last->v.chain = EDICT_TO_PROG((edict_t *)sv.edicts);
if (second && second != last)
second->v.chain = EDICT_TO_PROG(last);
}
RETURN_EDICT(first);
}
#else
{
int e;
int f;
char *s, *t;
edict_t *ed;
 
e = G_EDICTNUM(OFS_PARM0);
f = G_INT(OFS_PARM1);
s = G_STRING(OFS_PARM2);
if (!s)
PR_RunError ("PF_Find: bad search string");
for (e++ ; e < sv.num_edicts ; e++)
{
ed = EDICT_NUM(e);
if (ed->free)
continue;
t = E_STRING(ed,f);
if (!t)
continue;
if (!strcmp(t,s))
{
RETURN_EDICT(ed);
return;
}
}
 
RETURN_EDICT(sv.edicts);
}
#endif
 
void PR_CheckEmptyString (char *s)
{
if (s[0] <= ' ')
PR_RunError ("Bad string");
}
 
void PF_precache_file (void)
{ // precache_file is only used to copy files with qcc, it does nothing
G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
}
 
void PF_precache_sound (void)
{
char *s;
int i;
if (sv.state != ss_loading)
PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
s = G_STRING(OFS_PARM0);
G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
PR_CheckEmptyString (s);
for (i=0 ; i<MAX_SOUNDS ; i++)
{
if (!sv.sound_precache[i])
{
sv.sound_precache[i] = s;
return;
}
if (!strcmp(sv.sound_precache[i], s))
return;
}
PR_RunError ("PF_precache_sound: overflow");
}
 
void PF_precache_model (void)
{
char *s;
int i;
if (sv.state != ss_loading)
PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
s = G_STRING(OFS_PARM0);
G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
PR_CheckEmptyString (s);
 
for (i=0 ; i<MAX_MODELS ; i++)
{
if (!sv.model_precache[i])
{
sv.model_precache[i] = s;
sv.models[i] = Mod_ForName (s, true);
return;
}
if (!strcmp(sv.model_precache[i], s))
return;
}
PR_RunError ("PF_precache_model: overflow");
}
 
 
void PF_coredump (void)
{
ED_PrintEdicts ();
}
 
void PF_traceon (void)
{
pr_trace = true;
}
 
void PF_traceoff (void)
{
pr_trace = false;
}
 
void PF_eprint (void)
{
ED_PrintNum (G_EDICTNUM(OFS_PARM0));
}
 
/*
===============
PF_walkmove
 
float(float yaw, float dist) walkmove
===============
*/
void PF_walkmove (void)
{
edict_t *ent;
float yaw, dist;
vec3_t move;
dfunction_t *oldf;
int oldself;
ent = PROG_TO_EDICT(pr_global_struct->self);
yaw = G_FLOAT(OFS_PARM0);
dist = G_FLOAT(OFS_PARM1);
if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
{
G_FLOAT(OFS_RETURN) = 0;
return;
}
 
yaw = yaw*M_PI*2 / 360;
move[0] = cos(yaw)*dist;
move[1] = sin(yaw)*dist;
move[2] = 0;
 
// save program state, because SV_movestep may call other progs
oldf = pr_xfunction;
oldself = pr_global_struct->self;
G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
// restore program state
pr_xfunction = oldf;
pr_global_struct->self = oldself;
}
 
/*
===============
PF_droptofloor
 
void() droptofloor
===============
*/
void PF_droptofloor (void)
{
edict_t *ent;
vec3_t end;
trace_t trace;
ent = PROG_TO_EDICT(pr_global_struct->self);
 
VectorCopy (ent->v.origin, end);
end[2] -= 256;
trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent);
 
if (trace.fraction == 1 || trace.allsolid)
G_FLOAT(OFS_RETURN) = 0;
else
{
VectorCopy (trace.endpos, ent->v.origin);
SV_LinkEdict (ent, false);
ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
ent->v.groundentity = EDICT_TO_PROG(trace.ent);
G_FLOAT(OFS_RETURN) = 1;
}
}
 
/*
===============
PF_lightstyle
 
void(float style, string value) lightstyle
===============
*/
void PF_lightstyle (void)
{
int style;
char *val;
client_t *client;
int j;
style = G_FLOAT(OFS_PARM0);
val = G_STRING(OFS_PARM1);
 
// change the string in sv
sv.lightstyles[style] = val;
// send message to all clients on this server
if (sv.state != ss_active)
return;
for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
if (client->active || client->spawned)
{
MSG_WriteChar (&client->message, svc_lightstyle);
MSG_WriteChar (&client->message,style);
MSG_WriteString (&client->message, val);
}
}
 
void PF_rint (void)
{
float f;
f = G_FLOAT(OFS_PARM0);
if (f > 0)
G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
else
G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
}
void PF_floor (void)
{
G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
}
void PF_ceil (void)
{
G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
}
 
 
/*
=============
PF_checkbottom
=============
*/
void PF_checkbottom (void)
{
edict_t *ent;
ent = G_EDICT(OFS_PARM0);
 
G_FLOAT(OFS_RETURN) = SV_CheckBottom (ent);
}
 
/*
=============
PF_pointcontents
=============
*/
void PF_pointcontents (void)
{
float *v;
v = G_VECTOR(OFS_PARM0);
 
G_FLOAT(OFS_RETURN) = SV_PointContents (v);
}
 
/*
=============
PF_nextent
 
entity nextent(entity)
=============
*/
void PF_nextent (void)
{
int i;
edict_t *ent;
i = G_EDICTNUM(OFS_PARM0);
while (1)
{
i++;
if (i == sv.num_edicts)
{
RETURN_EDICT(sv.edicts);
return;
}
ent = EDICT_NUM(i);
if (!ent->free)
{
RETURN_EDICT(ent);
return;
}
}
}
 
/*
=============
PF_aim
 
Pick a vector for the player to shoot along
vector aim(entity, missilespeed)
=============
*/
cvar_t sv_aim = {"sv_aim", "0.93"};
void PF_aim (void)
{
edict_t *ent, *check, *bestent;
vec3_t start, dir, end, bestdir;
int i, j;
trace_t tr;
float dist, bestdist;
float speed;
ent = G_EDICT(OFS_PARM0);
speed = G_FLOAT(OFS_PARM1);
 
VectorCopy (ent->v.origin, start);
start[2] += 20;
 
// try sending a trace straight
VectorCopy (pr_global_struct->v_forward, dir);
VectorMA (start, 2048, dir, end);
tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent);
if (tr.ent && tr.ent->v.takedamage == DAMAGE_AIM
&& (!teamplay.value || ent->v.team <=0 || ent->v.team != tr.ent->v.team) )
{
VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
return;
}
 
 
// try all possible entities
VectorCopy (dir, bestdir);
bestdist = sv_aim.value;
bestent = NULL;
check = NEXT_EDICT(sv.edicts);
for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
{
if (check->v.takedamage != DAMAGE_AIM)
continue;
if (check == ent)
continue;
if (teamplay.value && ent->v.team > 0 && ent->v.team == check->v.team)
continue; // don't aim at teammate
for (j=0 ; j<3 ; j++)
end[j] = check->v.origin[j]
+ 0.5*(check->v.mins[j] + check->v.maxs[j]);
VectorSubtract (end, start, dir);
VectorNormalize (dir);
dist = DotProduct (dir, pr_global_struct->v_forward);
if (dist < bestdist)
continue; // to far to turn
tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent);
if (tr.ent == check)
{ // can shoot at this one
bestdist = dist;
bestent = check;
}
}
if (bestent)
{
VectorSubtract (bestent->v.origin, ent->v.origin, dir);
dist = DotProduct (dir, pr_global_struct->v_forward);
VectorScale (pr_global_struct->v_forward, dist, end);
end[2] = dir[2];
VectorNormalize (end);
VectorCopy (end, G_VECTOR(OFS_RETURN));
}
else
{
VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
}
}
 
/*
==============
PF_changeyaw
 
This was a major timewaster in progs, so it was converted to C
==============
*/
void PF_changeyaw (void)
{
edict_t *ent;
float ideal, current, move, speed;
ent = PROG_TO_EDICT(pr_global_struct->self);
current = anglemod( ent->v.angles[1] );
ideal = ent->v.ideal_yaw;
speed = ent->v.yaw_speed;
if (current == ideal)
return;
move = ideal - current;
if (ideal > current)
{
if (move >= 180)
move = move - 360;
}
else
{
if (move <= -180)
move = move + 360;
}
if (move > 0)
{
if (move > speed)
move = speed;
}
else
{
if (move < -speed)
move = -speed;
}
ent->v.angles[1] = anglemod (current + move);
}
 
#ifdef QUAKE2
/*
==============
PF_changepitch
==============
*/
void PF_changepitch (void)
{
edict_t *ent;
float ideal, current, move, speed;
ent = G_EDICT(OFS_PARM0);
current = anglemod( ent->v.angles[0] );
ideal = ent->v.idealpitch;
speed = ent->v.pitch_speed;
if (current == ideal)
return;
move = ideal - current;
if (ideal > current)
{
if (move >= 180)
move = move - 360;
}
else
{
if (move <= -180)
move = move + 360;
}
if (move > 0)
{
if (move > speed)
move = speed;
}
else
{
if (move < -speed)
move = -speed;
}
ent->v.angles[0] = anglemod (current + move);
}
#endif
 
/*
===============================================================================
 
MESSAGE WRITING
 
===============================================================================
*/
 
#define MSG_BROADCAST 0 // unreliable to all
#define MSG_ONE 1 // reliable to one (msg_entity)
#define MSG_ALL 2 // reliable to all
#define MSG_INIT 3 // write to the init string
 
sizebuf_t *WriteDest (void)
{
int entnum;
int dest;
edict_t *ent;
 
dest = G_FLOAT(OFS_PARM0);
switch (dest)
{
case MSG_BROADCAST:
return &sv.datagram;
case MSG_ONE:
ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
entnum = NUM_FOR_EDICT(ent);
if (entnum < 1 || entnum > svs.maxclients)
PR_RunError ("WriteDest: not a client");
return &svs.clients[entnum-1].message;
case MSG_ALL:
return &sv.reliable_datagram;
case MSG_INIT:
return &sv.signon;
 
default:
PR_RunError ("WriteDest: bad destination");
break;
}
return NULL;
}
 
void PF_WriteByte (void)
{
MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
}
 
void PF_WriteChar (void)
{
MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
}
 
void PF_WriteShort (void)
{
MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
}
 
void PF_WriteLong (void)
{
MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
}
 
void PF_WriteAngle (void)
{
MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
}
 
void PF_WriteCoord (void)
{
MSG_WriteCoord (WriteDest(), G_FLOAT(OFS_PARM1));
}
 
void PF_WriteString (void)
{
MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
}
 
 
void PF_WriteEntity (void)
{
MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
}
 
//=============================================================================
 
int SV_ModelIndex (char *name);
 
void PF_makestatic (void)
{
edict_t *ent;
int i;
ent = G_EDICT(OFS_PARM0);
 
MSG_WriteByte (&sv.signon,svc_spawnstatic);
 
MSG_WriteByte (&sv.signon, SV_ModelIndex(pr_strings + ent->v.model));
 
MSG_WriteByte (&sv.signon, ent->v.frame);
MSG_WriteByte (&sv.signon, ent->v.colormap);
MSG_WriteByte (&sv.signon, ent->v.skin);
for (i=0 ; i<3 ; i++)
{
MSG_WriteCoord(&sv.signon, ent->v.origin[i]);
MSG_WriteAngle(&sv.signon, ent->v.angles[i]);
}
 
// throw the entity away now
ED_Free (ent);
}
 
//=============================================================================
 
/*
==============
PF_setspawnparms
==============
*/
void PF_setspawnparms (void)
{
edict_t *ent;
int i;
client_t *client;
 
ent = G_EDICT(OFS_PARM0);
i = NUM_FOR_EDICT(ent);
if (i < 1 || i > svs.maxclients)
PR_RunError ("Entity is not a client");
 
// copy spawn parms out of the client_t
client = svs.clients + (i-1);
 
for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
(&pr_global_struct->parm1)[i] = client->spawn_parms[i];
}
 
/*
==============
PF_changelevel
==============
*/
void PF_changelevel (void)
{
#ifdef QUAKE2
char *s1, *s2;
 
if (svs.changelevel_issued)
return;
svs.changelevel_issued = true;
 
s1 = G_STRING(OFS_PARM0);
s2 = G_STRING(OFS_PARM1);
 
if ((int)pr_global_struct->serverflags & (SFL_NEW_UNIT | SFL_NEW_EPISODE))
Cbuf_AddText (va("changelevel %s %s\n",s1, s2));
else
Cbuf_AddText (va("changelevel2 %s %s\n",s1, s2));
#else
char *s;
 
// make sure we don't issue two changelevels
if (svs.changelevel_issued)
return;
svs.changelevel_issued = true;
s = G_STRING(OFS_PARM0);
Cbuf_AddText (va("changelevel %s\n",s));
#endif
}
 
 
#ifdef QUAKE2
 
#define CONTENT_WATER -3
#define CONTENT_SLIME -4
#define CONTENT_LAVA -5
 
#define FL_IMMUNE_WATER 131072
#define FL_IMMUNE_SLIME 262144
#define FL_IMMUNE_LAVA 524288
 
#define CHAN_VOICE 2
#define CHAN_BODY 4
 
#define ATTN_NORM 1
 
void PF_WaterMove (void)
{
edict_t *self;
int flags;
int waterlevel;
int watertype;
float drownlevel;
float damage = 0.0;
 
self = PROG_TO_EDICT(pr_global_struct->self);
 
if (self->v.movetype == MOVETYPE_NOCLIP)
{
self->v.air_finished = sv.time + 12;
G_FLOAT(OFS_RETURN) = damage;
return;
}
 
if (self->v.health < 0)
{
G_FLOAT(OFS_RETURN) = damage;
return;
}
 
if (self->v.deadflag == DEAD_NO)
drownlevel = 3;
else
drownlevel = 1;
 
flags = (int)self->v.flags;
waterlevel = (int)self->v.waterlevel;
watertype = (int)self->v.watertype;
 
if (!(flags & (FL_IMMUNE_WATER + FL_GODMODE)))
if (((flags & FL_SWIM) && (waterlevel < drownlevel)) || (waterlevel >= drownlevel))
{
if (self->v.air_finished < sv.time)
if (self->v.pain_finished < sv.time)
{
self->v.dmg = self->v.dmg + 2;
if (self->v.dmg > 15)
self->v.dmg = 10;
// T_Damage (self, world, world, self.dmg, 0, FALSE);
damage = self->v.dmg;
self->v.pain_finished = sv.time + 1.0;
}
}
else
{
if (self->v.air_finished < sv.time)
// sound (self, CHAN_VOICE, "player/gasp2.wav", 1, ATTN_NORM);
SV_StartSound (self, CHAN_VOICE, "player/gasp2.wav", 255, ATTN_NORM);
else if (self->v.air_finished < sv.time + 9)
// sound (self, CHAN_VOICE, "player/gasp1.wav", 1, ATTN_NORM);
SV_StartSound (self, CHAN_VOICE, "player/gasp1.wav", 255, ATTN_NORM);
self->v.air_finished = sv.time + 12.0;
self->v.dmg = 2;
}
if (!waterlevel)
{
if (flags & FL_INWATER)
{
// play leave water sound
// sound (self, CHAN_BODY, "misc/outwater.wav", 1, ATTN_NORM);
SV_StartSound (self, CHAN_BODY, "misc/outwater.wav", 255, ATTN_NORM);
self->v.flags = (float)(flags &~FL_INWATER);
}
self->v.air_finished = sv.time + 12.0;
G_FLOAT(OFS_RETURN) = damage;
return;
}
 
if (watertype == CONTENT_LAVA)
{ // do damage
if (!(flags & (FL_IMMUNE_LAVA + FL_GODMODE)))
if (self->v.dmgtime < sv.time)
{
if (self->v.radsuit_finished < sv.time)
self->v.dmgtime = sv.time + 0.2;
else
self->v.dmgtime = sv.time + 1.0;
// T_Damage (self, world, world, 10*self.waterlevel, 0, TRUE);
damage = (float)(10*waterlevel);
}
}
else if (watertype == CONTENT_SLIME)
{ // do damage
if (!(flags & (FL_IMMUNE_SLIME + FL_GODMODE)))
if (self->v.dmgtime < sv.time && self->v.radsuit_finished < sv.time)
{
self->v.dmgtime = sv.time + 1.0;
// T_Damage (self, world, world, 4*self.waterlevel, 0, TRUE);
damage = (float)(4*waterlevel);
}
}
if ( !(flags & FL_INWATER) )
{
 
// player enter water sound
if (watertype == CONTENT_LAVA)
// sound (self, CHAN_BODY, "player/inlava.wav", 1, ATTN_NORM);
SV_StartSound (self, CHAN_BODY, "player/inlava.wav", 255, ATTN_NORM);
if (watertype == CONTENT_WATER)
// sound (self, CHAN_BODY, "player/inh2o.wav", 1, ATTN_NORM);
SV_StartSound (self, CHAN_BODY, "player/inh2o.wav", 255, ATTN_NORM);
if (watertype == CONTENT_SLIME)
// sound (self, CHAN_BODY, "player/slimbrn2.wav", 1, ATTN_NORM);
SV_StartSound (self, CHAN_BODY, "player/slimbrn2.wav", 255, ATTN_NORM);
 
self->v.flags = (float)(flags | FL_INWATER);
self->v.dmgtime = 0;
}
if (! (flags & FL_WATERJUMP) )
{
// self.velocity = self.velocity - 0.8*self.waterlevel*frametime*self.velocity;
VectorMA (self->v.velocity, -0.8 * self->v.waterlevel * host_frametime, self->v.velocity, self->v.velocity);
}
 
G_FLOAT(OFS_RETURN) = damage;
}
 
 
void PF_sin (void)
{
G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0));
}
 
void PF_cos (void)
{
G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0));
}
 
void PF_sqrt (void)
{
G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0));
}
#endif
 
void PF_Fixme (void)
{
PR_RunError ("unimplemented bulitin");
}
 
 
 
builtin_t pr_builtin[] =
{
PF_Fixme,
PF_makevectors, // void(entity e) makevectors = #1;
PF_setorigin, // void(entity e, vector o) setorigin = #2;
PF_setmodel, // void(entity e, string m) setmodel = #3;
PF_setsize, // void(entity e, vector min, vector max) setsize = #4;
PF_Fixme, // void(entity e, vector min, vector max) setabssize = #5;
PF_break, // void() break = #6;
PF_random, // float() random = #7;
PF_sound, // void(entity e, float chan, string samp) sound = #8;
PF_normalize, // vector(vector v) normalize = #9;
PF_error, // void(string e) error = #10;
PF_objerror, // void(string e) objerror = #11;
PF_vlen, // float(vector v) vlen = #12;
PF_vectoyaw, // float(vector v) vectoyaw = #13;
PF_Spawn, // entity() spawn = #14;
PF_Remove, // void(entity e) remove = #15;
PF_traceline, // float(vector v1, vector v2, float tryents) traceline = #16;
PF_checkclient, // entity() clientlist = #17;
PF_Find, // entity(entity start, .string fld, string match) find = #18;
PF_precache_sound, // void(string s) precache_sound = #19;
PF_precache_model, // void(string s) precache_model = #20;
PF_stuffcmd, // void(entity client, string s)stuffcmd = #21;
PF_findradius, // entity(vector org, float rad) findradius = #22;
PF_bprint, // void(string s) bprint = #23;
PF_sprint, // void(entity client, string s) sprint = #24;
PF_dprint, // void(string s) dprint = #25;
PF_ftos, // void(string s) ftos = #26;
PF_vtos, // void(string s) vtos = #27;
PF_coredump,
PF_traceon,
PF_traceoff,
PF_eprint, // void(entity e) debug print an entire entity
PF_walkmove, // float(float yaw, float dist) walkmove
PF_Fixme, // float(float yaw, float dist) walkmove
PF_droptofloor,
PF_lightstyle,
PF_rint,
PF_floor,
PF_ceil,
PF_Fixme,
PF_checkbottom,
PF_pointcontents,
PF_Fixme,
PF_fabs,
PF_aim,
PF_cvar,
PF_localcmd,
PF_nextent,
PF_particle,
PF_changeyaw,
PF_Fixme,
PF_vectoangles,
 
PF_WriteByte,
PF_WriteChar,
PF_WriteShort,
PF_WriteLong,
PF_WriteCoord,
PF_WriteAngle,
PF_WriteString,
PF_WriteEntity,
 
#ifdef QUAKE2
PF_sin,
PF_cos,
PF_sqrt,
PF_changepitch,
PF_TraceToss,
PF_etos,
PF_WaterMove,
#else
PF_Fixme,
PF_Fixme,
PF_Fixme,
PF_Fixme,
PF_Fixme,
PF_Fixme,
PF_Fixme,
#endif
 
SV_MoveToGoal,
PF_precache_file,
PF_makestatic,
 
PF_changelevel,
PF_Fixme,
 
PF_cvar_set,
PF_centerprint,
 
PF_ambientsound,
 
PF_precache_model,
PF_precache_sound, // precache_sound2 is different only for qcc
PF_precache_file,
 
PF_setspawnparms
};
 
builtin_t *pr_builtins = pr_builtin;
int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
 
/contrib/other/sdlquake-1.0.9/pr_comp.h
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;
 
/contrib/other/sdlquake-1.0.9/pr_edict.c
0,0 → 1,1106
/*
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.
 
*/
// sv_edict.c -- entity dictionary
 
#include "quakedef.h"
 
dprograms_t *progs;
dfunction_t *pr_functions;
char *pr_strings;
ddef_t *pr_fielddefs;
ddef_t *pr_globaldefs;
dstatement_t *pr_statements;
globalvars_t *pr_global_struct;
float *pr_globals; // same as pr_global_struct
int pr_edict_size; // in bytes
 
unsigned short pr_crc;
 
int type_size[8] = {1,sizeof(string_t)/4,1,3,1,1,sizeof(func_t)/4,sizeof(void *)/4};
 
ddef_t *ED_FieldAtOfs (int ofs);
qboolean ED_ParseEpair (void *base, ddef_t *key, char *s);
 
cvar_t nomonsters = {"nomonsters", "0"};
cvar_t gamecfg = {"gamecfg", "0"};
cvar_t scratch1 = {"scratch1", "0"};
cvar_t scratch2 = {"scratch2", "0"};
cvar_t scratch3 = {"scratch3", "0"};
cvar_t scratch4 = {"scratch4", "0"};
cvar_t savedgamecfg = {"savedgamecfg", "0", true};
cvar_t saved1 = {"saved1", "0", true};
cvar_t saved2 = {"saved2", "0", true};
cvar_t saved3 = {"saved3", "0", true};
cvar_t saved4 = {"saved4", "0", true};
 
#define MAX_FIELD_LEN 64
#define GEFV_CACHESIZE 2
 
typedef struct {
ddef_t *pcache;
char field[MAX_FIELD_LEN];
} gefv_cache;
 
static gefv_cache gefvCache[GEFV_CACHESIZE] = {{NULL, ""}, {NULL, ""}};
 
/*
=================
ED_ClearEdict
 
Sets everything to NULL
=================
*/
void ED_ClearEdict (edict_t *e)
{
memset (&e->v, 0, progs->entityfields * 4);
e->free = false;
}
 
/*
=================
ED_Alloc
 
Either finds a free edict, or allocates a new one.
Try to avoid reusing an entity that was recently freed, because it
can cause the client to think the entity morphed into something else
instead of being removed and recreated, which can cause interpolated
angles and bad trails.
=================
*/
edict_t *ED_Alloc (void)
{
int i;
edict_t *e;
 
for ( i=svs.maxclients+1 ; i<sv.num_edicts ; i++)
{
e = EDICT_NUM(i);
// the first couple seconds of server time can involve a lot of
// freeing and allocating, so relax the replacement policy
if (e->free && ( e->freetime < 2 || sv.time - e->freetime > 0.5 ) )
{
ED_ClearEdict (e);
return e;
}
}
if (i == MAX_EDICTS)
Sys_Error ("ED_Alloc: no free edicts");
sv.num_edicts++;
e = EDICT_NUM(i);
ED_ClearEdict (e);
 
return e;
}
 
/*
=================
ED_Free
 
Marks the edict as free
FIXME: walk all entities and NULL out references to this entity
=================
*/
void ED_Free (edict_t *ed)
{
SV_UnlinkEdict (ed); // unlink from world bsp
 
ed->free = true;
ed->v.model = 0;
ed->v.takedamage = 0;
ed->v.modelindex = 0;
ed->v.colormap = 0;
ed->v.skin = 0;
ed->v.frame = 0;
VectorCopy (vec3_origin, ed->v.origin);
VectorCopy (vec3_origin, ed->v.angles);
ed->v.nextthink = -1;
ed->v.solid = 0;
ed->freetime = sv.time;
}
 
//===========================================================================
 
/*
============
ED_GlobalAtOfs
============
*/
ddef_t *ED_GlobalAtOfs (int ofs)
{
ddef_t *def;
int i;
for (i=0 ; i<progs->numglobaldefs ; i++)
{
def = &pr_globaldefs[i];
if (def->ofs == ofs)
return def;
}
return NULL;
}
 
/*
============
ED_FieldAtOfs
============
*/
ddef_t *ED_FieldAtOfs (int ofs)
{
ddef_t *def;
int i;
for (i=0 ; i<progs->numfielddefs ; i++)
{
def = &pr_fielddefs[i];
if (def->ofs == ofs)
return def;
}
return NULL;
}
 
/*
============
ED_FindField
============
*/
ddef_t *ED_FindField (char *name)
{
ddef_t *def;
int i;
for (i=0 ; i<progs->numfielddefs ; i++)
{
def = &pr_fielddefs[i];
if (!strcmp(pr_strings + def->s_name,name) )
return def;
}
return NULL;
}
 
 
/*
============
ED_FindGlobal
============
*/
ddef_t *ED_FindGlobal (char *name)
{
ddef_t *def;
int i;
for (i=0 ; i<progs->numglobaldefs ; i++)
{
def = &pr_globaldefs[i];
if (!strcmp(pr_strings + def->s_name,name) )
return def;
}
return NULL;
}
 
 
/*
============
ED_FindFunction
============
*/
dfunction_t *ED_FindFunction (char *name)
{
dfunction_t *func;
int i;
for (i=0 ; i<progs->numfunctions ; i++)
{
func = &pr_functions[i];
if (!strcmp(pr_strings + func->s_name,name) )
return func;
}
return NULL;
}
 
 
eval_t *GetEdictFieldValue(edict_t *ed, char *field)
{
ddef_t *def = NULL;
int i;
static int rep = 0;
 
for (i=0 ; i<GEFV_CACHESIZE ; i++)
{
if (!strcmp(field, gefvCache[i].field))
{
def = gefvCache[i].pcache;
goto Done;
}
}
 
def = ED_FindField (field);
 
if (strlen(field) < MAX_FIELD_LEN)
{
gefvCache[rep].pcache = def;
strcpy (gefvCache[rep].field, field);
rep ^= 1;
}
 
Done:
if (!def)
return NULL;
 
return (eval_t *)((char *)&ed->v + def->ofs*4);
}
 
 
/*
============
PR_ValueString
 
Returns a string describing *data in a type specific manner
=============
*/
char *PR_ValueString (etype_t type, eval_t *val)
{
static char line[256];
ddef_t *def;
dfunction_t *f;
type &= ~DEF_SAVEGLOBAL;
 
switch (type)
{
case ev_string:
sprintf (line, "%s", pr_strings + val->string);
break;
case ev_entity:
sprintf (line, "entity %i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)) );
break;
case ev_function:
f = pr_functions + val->function;
sprintf (line, "%s()", pr_strings + f->s_name);
break;
case ev_field:
def = ED_FieldAtOfs ( val->_int );
sprintf (line, ".%s", pr_strings + def->s_name);
break;
case ev_void:
sprintf (line, "void");
break;
case ev_float:
sprintf (line, "%5.1f", val->_float);
break;
case ev_vector:
sprintf (line, "'%5.1f %5.1f %5.1f'", val->vector[0], val->vector[1], val->vector[2]);
break;
case ev_pointer:
sprintf (line, "pointer");
break;
default:
sprintf (line, "bad type %i", type);
break;
}
return line;
}
 
/*
============
PR_UglyValueString
 
Returns a string describing *data in a type specific manner
Easier to parse than PR_ValueString
=============
*/
char *PR_UglyValueString (etype_t type, eval_t *val)
{
static char line[256];
ddef_t *def;
dfunction_t *f;
type &= ~DEF_SAVEGLOBAL;
 
switch (type)
{
case ev_string:
sprintf (line, "%s", pr_strings + val->string);
break;
case ev_entity:
sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
break;
case ev_function:
f = pr_functions + val->function;
sprintf (line, "%s", pr_strings + f->s_name);
break;
case ev_field:
def = ED_FieldAtOfs ( val->_int );
sprintf (line, "%s", pr_strings + def->s_name);
break;
case ev_void:
sprintf (line, "void");
break;
case ev_float:
sprintf (line, "%f", val->_float);
break;
case ev_vector:
sprintf (line, "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
break;
default:
sprintf (line, "bad type %i", type);
break;
}
return line;
}
 
/*
============
PR_GlobalString
 
Returns a string with a description and the contents of a global,
padded to 20 field width
============
*/
char *PR_GlobalString (int ofs)
{
char *s;
int i;
ddef_t *def;
void *val;
static char line[128];
val = (void *)&pr_globals[ofs];
def = ED_GlobalAtOfs(ofs);
if (!def)
sprintf (line,"%i(???)", ofs);
else
{
s = PR_ValueString (def->type, val);
sprintf (line,"%i(%s)%s", ofs, pr_strings + def->s_name, s);
}
i = strlen(line);
for ( ; i<20 ; i++)
strcat (line," ");
strcat (line," ");
return line;
}
 
char *PR_GlobalStringNoContents (int ofs)
{
int i;
ddef_t *def;
static char line[128];
def = ED_GlobalAtOfs(ofs);
if (!def)
sprintf (line,"%i(???)", ofs);
else
sprintf (line,"%i(%s)", ofs, pr_strings + def->s_name);
i = strlen(line);
for ( ; i<20 ; i++)
strcat (line," ");
strcat (line," ");
return line;
}
 
 
/*
=============
ED_Print
 
For debugging
=============
*/
void ED_Print (edict_t *ed)
{
int l;
ddef_t *d;
int *v;
int i, j;
char *name;
int type;
 
if (ed->free)
{
Con_Printf ("FREE\n");
return;
}
 
Con_Printf("\nEDICT %i:\n", NUM_FOR_EDICT(ed));
for (i=1 ; i<progs->numfielddefs ; i++)
{
d = &pr_fielddefs[i];
name = pr_strings + d->s_name;
if (name[strlen(name)-2] == '_')
continue; // skip _x, _y, _z vars
v = (int *)((char *)&ed->v + d->ofs*4);
 
// if the value is still all 0, skip the field
type = d->type & ~DEF_SAVEGLOBAL;
for (j=0 ; j<type_size[type] ; j++)
if (v[j])
break;
if (j == type_size[type])
continue;
Con_Printf ("%s",name);
l = strlen (name);
while (l++ < 15)
Con_Printf (" ");
 
Con_Printf ("%s\n", PR_ValueString(d->type, (eval_t *)v));
}
}
 
/*
=============
ED_Write
 
For savegames
=============
*/
void ED_Write (FILE *f, edict_t *ed)
{
ddef_t *d;
int *v;
int i, j;
char *name;
int type;
 
fprintf (f, "{\n");
 
if (ed->free)
{
fprintf (f, "}\n");
return;
}
for (i=1 ; i<progs->numfielddefs ; i++)
{
d = &pr_fielddefs[i];
name = pr_strings + d->s_name;
if (name[strlen(name)-2] == '_')
continue; // skip _x, _y, _z vars
v = (int *)((char *)&ed->v + d->ofs*4);
 
// if the value is still all 0, skip the field
type = d->type & ~DEF_SAVEGLOBAL;
for (j=0 ; j<type_size[type] ; j++)
if (v[j])
break;
if (j == type_size[type])
continue;
fprintf (f,"\"%s\" ",name);
fprintf (f,"\"%s\"\n", PR_UglyValueString(d->type, (eval_t *)v));
}
 
fprintf (f, "}\n");
}
 
void ED_PrintNum (int ent)
{
ED_Print (EDICT_NUM(ent));
}
 
/*
=============
ED_PrintEdicts
 
For debugging, prints all the entities in the current server
=============
*/
void ED_PrintEdicts (void)
{
int i;
Con_Printf ("%i entities\n", sv.num_edicts);
for (i=0 ; i<sv.num_edicts ; i++)
ED_PrintNum (i);
}
 
/*
=============
ED_PrintEdict_f
 
For debugging, prints a single edicy
=============
*/
void ED_PrintEdict_f (void)
{
int i;
i = Q_atoi (Cmd_Argv(1));
if (i >= sv.num_edicts)
{
Con_Printf("Bad edict number\n");
return;
}
ED_PrintNum (i);
}
 
/*
=============
ED_Count
 
For debugging
=============
*/
void ED_Count (void)
{
int i;
edict_t *ent;
int active, models, solid, step;
 
active = models = solid = step = 0;
for (i=0 ; i<sv.num_edicts ; i++)
{
ent = EDICT_NUM(i);
if (ent->free)
continue;
active++;
if (ent->v.solid)
solid++;
if (ent->v.model)
models++;
if (ent->v.movetype == MOVETYPE_STEP)
step++;
}
 
Con_Printf ("num_edicts:%3i\n", sv.num_edicts);
Con_Printf ("active :%3i\n", active);
Con_Printf ("view :%3i\n", models);
Con_Printf ("touch :%3i\n", solid);
Con_Printf ("step :%3i\n", step);
 
}
 
/*
==============================================================================
 
ARCHIVING GLOBALS
 
FIXME: need to tag constants, doesn't really work
==============================================================================
*/
 
/*
=============
ED_WriteGlobals
=============
*/
void ED_WriteGlobals (FILE *f)
{
ddef_t *def;
int i;
char *name;
int type;
 
fprintf (f,"{\n");
for (i=0 ; i<progs->numglobaldefs ; i++)
{
def = &pr_globaldefs[i];
type = def->type;
if ( !(def->type & DEF_SAVEGLOBAL) )
continue;
type &= ~DEF_SAVEGLOBAL;
 
if (type != ev_string
&& type != ev_float
&& type != ev_entity)
continue;
 
name = pr_strings + def->s_name;
fprintf (f,"\"%s\" ", name);
fprintf (f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs]));
}
fprintf (f,"}\n");
}
 
/*
=============
ED_ParseGlobals
=============
*/
void ED_ParseGlobals (char *data)
{
char keyname[64];
ddef_t *key;
 
while (1)
{
// parse key
data = COM_Parse (data);
if (com_token[0] == '}')
break;
if (!data)
Sys_Error ("ED_ParseEntity: EOF without closing brace");
 
strcpy (keyname, com_token);
 
// parse value
data = COM_Parse (data);
if (!data)
Sys_Error ("ED_ParseEntity: EOF without closing brace");
 
if (com_token[0] == '}')
Sys_Error ("ED_ParseEntity: closing brace without data");
 
key = ED_FindGlobal (keyname);
if (!key)
{
Con_Printf ("'%s' is not a global\n", keyname);
continue;
}
 
if (!ED_ParseEpair ((void *)pr_globals, key, com_token))
Host_Error ("ED_ParseGlobals: parse error");
}
}
 
//============================================================================
 
 
/*
=============
ED_NewString
=============
*/
char *ED_NewString (char *string)
{
char *new, *new_p;
int i,l;
l = strlen(string) + 1;
new = Hunk_Alloc (l);
new_p = new;
 
for (i=0 ; i< l ; i++)
{
if (string[i] == '\\' && i < l-1)
{
i++;
if (string[i] == 'n')
*new_p++ = '\n';
else
*new_p++ = '\\';
}
else
*new_p++ = string[i];
}
return new;
}
 
 
/*
=============
ED_ParseEval
 
Can parse either fields or globals
returns false if error
=============
*/
qboolean ED_ParseEpair (void *base, ddef_t *key, char *s)
{
int i;
char string[128];
ddef_t *def;
char *v, *w;
void *d;
dfunction_t *func;
d = (void *)((int *)base + key->ofs);
switch (key->type & ~DEF_SAVEGLOBAL)
{
case ev_string:
*(string_t *)d = ED_NewString (s) - pr_strings;
break;
case ev_float:
*(float *)d = atof (s);
break;
case ev_vector:
strcpy (string, s);
v = string;
w = string;
for (i=0 ; i<3 ; i++)
{
while (*v && *v != ' ')
v++;
*v = 0;
((float *)d)[i] = atof (w);
w = v = v+1;
}
break;
case ev_entity:
*(int *)d = EDICT_TO_PROG(EDICT_NUM(atoi (s)));
break;
case ev_field:
def = ED_FindField (s);
if (!def)
{
Con_Printf ("Can't find field %s\n", s);
return false;
}
*(int *)d = G_INT(def->ofs);
break;
case ev_function:
func = ED_FindFunction (s);
if (!func)
{
Con_Printf ("Can't find function %s\n", s);
return false;
}
*(func_t *)d = func - pr_functions;
break;
default:
break;
}
return true;
}
 
/*
====================
ED_ParseEdict
 
Parses an edict out of the given string, returning the new position
ed should be a properly initialized empty edict.
Used for initial level load and for savegames.
====================
*/
char *ED_ParseEdict (char *data, edict_t *ent)
{
ddef_t *key;
qboolean anglehack;
qboolean init;
char keyname[256];
int n;
 
init = false;
 
// clear it
if (ent != sv.edicts) // hack
memset (&ent->v, 0, progs->entityfields * 4);
 
// go through all the dictionary pairs
while (1)
{
// parse key
data = COM_Parse (data);
if (com_token[0] == '}')
break;
if (!data)
Sys_Error ("ED_ParseEntity: EOF without closing brace");
// anglehack is to allow QuakeEd to write single scalar angles
// and allow them to be turned into vectors. (FIXME...)
if (!strcmp(com_token, "angle"))
{
strcpy (com_token, "angles");
anglehack = true;
}
else
anglehack = false;
 
// FIXME: change light to _light to get rid of this hack
if (!strcmp(com_token, "light"))
strcpy (com_token, "light_lev"); // hack for single light def
 
strcpy (keyname, com_token);
 
// another hack to fix heynames with trailing spaces
n = strlen(keyname);
while (n && keyname[n-1] == ' ')
{
keyname[n-1] = 0;
n--;
}
 
// parse value
data = COM_Parse (data);
if (!data)
Sys_Error ("ED_ParseEntity: EOF without closing brace");
 
if (com_token[0] == '}')
Sys_Error ("ED_ParseEntity: closing brace without data");
 
init = true;
 
// keynames with a leading underscore are used for utility comments,
// and are immediately discarded by quake
if (keyname[0] == '_')
continue;
key = ED_FindField (keyname);
if (!key)
{
Con_Printf ("'%s' is not a field\n", keyname);
continue;
}
 
if (anglehack)
{
char temp[32];
strcpy (temp, com_token);
sprintf (com_token, "0 %s 0", temp);
}
 
if (!ED_ParseEpair ((void *)&ent->v, key, com_token))
Host_Error ("ED_ParseEdict: parse error");
}
 
if (!init)
ent->free = true;
 
return data;
}
 
 
/*
================
ED_LoadFromFile
 
The entities are directly placed in the array, rather than allocated with
ED_Alloc, because otherwise an error loading the map would have entity
number references out of order.
 
Creates a server's entity / program execution context by
parsing textual entity definitions out of an ent file.
 
Used for both fresh maps and savegame loads. A fresh map would also need
to call ED_CallSpawnFunctions () to let the objects initialize themselves.
================
*/
void ED_LoadFromFile (char *data)
{
edict_t *ent;
int inhibit;
dfunction_t *func;
ent = NULL;
inhibit = 0;
pr_global_struct->time = sv.time;
// parse ents
while (1)
{
// parse the opening brace
data = COM_Parse (data);
if (!data)
break;
if (com_token[0] != '{')
Sys_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
 
if (!ent)
ent = EDICT_NUM(0);
else
ent = ED_Alloc ();
data = ED_ParseEdict (data, ent);
 
// remove things from different skill levels or deathmatch
if (deathmatch.value)
{
if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
{
ED_Free (ent);
inhibit++;
continue;
}
}
else if ((current_skill == 0 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_EASY))
|| (current_skill == 1 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_MEDIUM))
|| (current_skill >= 2 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_HARD)) )
{
ED_Free (ent);
inhibit++;
continue;
}
 
//
// immediately call spawn function
//
if (!ent->v.classname)
{
Con_Printf ("No classname for:\n");
ED_Print (ent);
ED_Free (ent);
continue;
}
 
// look for the spawn function
func = ED_FindFunction ( pr_strings + ent->v.classname );
 
if (!func)
{
Con_Printf ("No spawn function for:\n");
ED_Print (ent);
ED_Free (ent);
continue;
}
 
pr_global_struct->self = EDICT_TO_PROG(ent);
PR_ExecuteProgram (func - pr_functions);
}
 
Con_DPrintf ("%i entities inhibited\n", inhibit);
}
 
 
/*
===============
PR_LoadProgs
===============
*/
void PR_LoadProgs (void)
{
int i;
 
// flush the non-C variable lookup cache
for (i=0 ; i<GEFV_CACHESIZE ; i++)
gefvCache[i].field[0] = 0;
 
CRC_Init (&pr_crc);
 
progs = (dprograms_t *)COM_LoadHunkFile ("progs.dat");
if (!progs)
Sys_Error ("PR_LoadProgs: couldn't load progs.dat");
Con_DPrintf ("Programs occupy %iK.\n", com_filesize/1024);
 
for (i=0 ; i<com_filesize ; i++)
CRC_ProcessByte (&pr_crc, ((byte *)progs)[i]);
 
// byte swap the header
for (i=0 ; i<sizeof(*progs)/4 ; i++)
((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
 
if (progs->version != PROG_VERSION)
Sys_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
if (progs->crc != PROGHEADER_CRC)
Sys_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
 
pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions);
pr_strings = (char *)progs + progs->ofs_strings;
pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs);
pr_fielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs);
pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements);
 
pr_global_struct = (globalvars_t *)((byte *)progs + progs->ofs_globals);
pr_globals = (float *)pr_global_struct;
pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t);
// byte swap the lumps
for (i=0 ; i<progs->numstatements ; i++)
{
pr_statements[i].op = LittleShort(pr_statements[i].op);
pr_statements[i].a = LittleShort(pr_statements[i].a);
pr_statements[i].b = LittleShort(pr_statements[i].b);
pr_statements[i].c = LittleShort(pr_statements[i].c);
}
 
for (i=0 ; i<progs->numfunctions; i++)
{
pr_functions[i].first_statement = LittleLong (pr_functions[i].first_statement);
pr_functions[i].parm_start = LittleLong (pr_functions[i].parm_start);
pr_functions[i].s_name = LittleLong (pr_functions[i].s_name);
pr_functions[i].s_file = LittleLong (pr_functions[i].s_file);
pr_functions[i].numparms = LittleLong (pr_functions[i].numparms);
pr_functions[i].locals = LittleLong (pr_functions[i].locals);
}
 
for (i=0 ; i<progs->numglobaldefs ; i++)
{
pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
}
 
for (i=0 ; i<progs->numfielddefs ; i++)
{
pr_fielddefs[i].type = LittleShort (pr_fielddefs[i].type);
if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
Sys_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
pr_fielddefs[i].ofs = LittleShort (pr_fielddefs[i].ofs);
pr_fielddefs[i].s_name = LittleLong (pr_fielddefs[i].s_name);
}
 
for (i=0 ; i<progs->numglobals ; i++)
((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
}
 
 
/*
===============
PR_Init
===============
*/
void PR_Init (void)
{
Cmd_AddCommand ("edict", ED_PrintEdict_f);
Cmd_AddCommand ("edicts", ED_PrintEdicts);
Cmd_AddCommand ("edictcount", ED_Count);
Cmd_AddCommand ("profile", PR_Profile_f);
Cvar_RegisterVariable (&nomonsters);
Cvar_RegisterVariable (&gamecfg);
Cvar_RegisterVariable (&scratch1);
Cvar_RegisterVariable (&scratch2);
Cvar_RegisterVariable (&scratch3);
Cvar_RegisterVariable (&scratch4);
Cvar_RegisterVariable (&savedgamecfg);
Cvar_RegisterVariable (&saved1);
Cvar_RegisterVariable (&saved2);
Cvar_RegisterVariable (&saved3);
Cvar_RegisterVariable (&saved4);
}
 
 
 
edict_t *EDICT_NUM(int n)
{
if (n < 0 || n >= sv.max_edicts)
Sys_Error ("EDICT_NUM: bad number %i", n);
return (edict_t *)((byte *)sv.edicts+ (n)*pr_edict_size);
}
 
int NUM_FOR_EDICT(edict_t *e)
{
int b;
b = (byte *)e - (byte *)sv.edicts;
b = b / pr_edict_size;
if (b < 0 || b >= sv.num_edicts)
Sys_Error ("NUM_FOR_EDICT: bad pointer");
return b;
}
/contrib/other/sdlquake-1.0.9/pr_exec.c
0,0 → 1,668
/*
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;
 
#define MAX_STACK_DEPTH 32
prstack_t pr_stack[MAX_STACK_DEPTH];
int pr_depth;
 
#define LOCALSTACK_SIZE 2048
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);
}
}
 
}
/contrib/other/sdlquake-1.0.9/progdefs.h
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
/contrib/other/sdlquake-1.0.9/progdefs.q1
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
/contrib/other/sdlquake-1.0.9/progdefs.q2
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
/contrib/other/sdlquake-1.0.9/progs.h
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);
 
/contrib/other/sdlquake-1.0.9/protocol.h
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.
 
*/
// 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
 
//
// 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
/contrib/other/sdlquake-1.0.9/q.bat
0,0 → 1,0
dos\quake -basedir /quake -game test_gjc %1 %2 %3 %4 %5 %6 %7 %8 %9
/contrib/other/sdlquake-1.0.9/qa.bat
0,0 → 1,0
dos\quake -nocdaudio -basedir /quake -game test_am %1 %2 %3 %4 %5 %6 %7 %8 %9
/contrib/other/sdlquake-1.0.9/qb.bat
0,0 → 1,0
dos\quake /quake/test_gjc;/quake/id1 %1 %2 %3 %4 %5 %6 %7 %8 %9
/contrib/other/sdlquake-1.0.9/qe3.ico
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/contrib/other/sdlquake-1.0.9/qt.bat
0,0 → 1,0
dos\quake /quake/test_am;/quake/test_jc;/quake/id1 %1 %2 %3 %4 %5 %6 %7 %8 %9
/contrib/other/sdlquake-1.0.9/quake-data.spec.sh
0,0 → 1,60
#!/bin/sh
# Generate quake-data.spec
# $1 is version
# $2 is release
# $3 is install dir (assumed to be in /var/tmp)
cat <<EOF
%define name quake-data
%define version ${1}
%define release ${2}
%define builddir \$RPM_BUILD_DIR/%{name}-%{version}
Name: %{name}
Version: %{version}
Release: %{release}
Vendor: id Software
Packager: Dave "Zoid" Kirsch <zoid@idsoftware.com>
URL: http://www.idsoftware.com/
Source: quake-data-%{version}.tar.gz
BuildArchitectures: noarch
Group: Games
Copyright: Restricted
Icon: quake.gif
BuildRoot: /var/tmp/%{name}-%{version}
Summary: Quake for Linux
 
%description
"Quake is the biggest, baddest, and bloodiest 3-D action game ever
conceived" - PC GAMER
 
"The most important PC game ever" - PC ZONE
 
""Quake": Bloody Amazing" - USA TODAY
 
"The Vanguard of a terrifying new level of immersive interactivity" -
COMPUTER GAMING WORLD
 
From the creators of DOOM and DOOM II comes the most intense, technologically
advanced 3-D experience ever captured on CD ROM. Features free and fluid
motion, ambient sound and lighting, and unmatched multiplayer capabilities
(play with up to 15 others).
 
This package contians the Quake data files needed to play the game.
 
%install
 
%files
%attr(644,root,root) $3/comexp.txt
%attr(644,root,root) $3/help.txt
%attr(644,root,root) $3/licinfo.txt
%attr(644,root,root) $3/manual.txt
%attr(644,root,root) $3/readme.txt
%attr(644,root,root) $3/rlicnse.txt
%attr(644,root,root) $3/techinfo.txt
%attr(644,root,root) $3/id1/pak0.pak
%attr(644,root,root) $3/id1/pak1.pak
 
%post
/sbin/ldconfig
 
EOF
 
/contrib/other/sdlquake-1.0.9/quake-hipnotic.spec.sh
0,0 → 1,113
#!/bin/sh
# Generate quake-hipnotic.spec
# $1 is version
# $2 is release
# $3 is install dir (assumed to be in /var/tmp)
cat <<EOF
%define name quake-hipnotic
%define version ${1}
%define release ${2}
%define builddir \$RPM_BUILD_DIR/%{name}-%{version}
Name: %{name}
Version: %{version}
Release: %{release}
Vendor: id Software/Ritual Entertainment
Packager: Dave "Zoid" Kirsch <zoid@idsoftware.com>
URL: http://www.ritual.com/
Source: quake-hipnotic-%{version}.tar.gz
BuildArchitectures: noarch
Group: Games
Copyright: Restricted
Icon: quake.gif
BuildRoot: /var/tmp/%{name}-%{version}
Summary: Quake Hipnotic Mission Pack #1: Scourge of Armagon
 
%description
 
The Scourge of Armagon is the highly acclaimed mission pack for id Software's
Quake. Scourge offers 3 new episodes that continue off where Quake ended. Add
some incredible new effects such as rotating doors and objects, new creatures
to battle, and new weapons and powerups to assist you in these battles.
 
Looking for a way to breath some new life into Quake? Get Mission Pack #1:
Scourge of Armagon.
 
Here is a breakdown of exactly what you will get inside Scourge of Armagon:
 
18 Beastly Levels
Strafe and slaughter your way through 18 levels contained in three
monster-infested episodes. Fight your way through the intense Military
Base and Research Facilities, sneak around in the Ancient Realm, and dash
into the final domain controlled by Armagon. YouÂ’ll also be able to tear
your friends apart in an all-new DeathMatch level: Edge of Oblivion.
 
All-New Flesh-Ripping Demons
Gremlins: Small, blood-thirsty creatures that attack in swarms and can even
steal your weapons. Watch out or these little bastards will turn them back on
you!
 
Centroids: Armor-plated scorpion cyborgs with two nail guns fused to their
monstrous bodies. These bad boy monsters can shred you to bits in just
seconds.
 
Armagon: This is the father of all monsters. This huge metallic behemoth will
rock your world with rockets and laser fire, so be prepared to die.
 
Never-Before-Seen Weapons
Mjolnir: When this war hammer pounds the floor, it fires an electrical force
along the ground, striking and shocking several enemies with its lethal
current.
 
Laser Cannon: Disintegrate scores of creatures with scorching laser blasts.
Use the rebounding properties of this weapon to tag your enemies around
corners.
 
Proximity Mines: Gameplay reaches new heights with motion sensitive mines.
Plant these nasty toys on walls, floors, or even the ceiling and watch as
unsuspecting foes are blown into little bits.
 
Inventive New Powerups
Empathy Shield: This shield allows you to turn the table on those unwitting
opponents. Whatever damage you take they receive half of it back in kind.
 
Horn of Conjuring: Blow this horn and out of the mystical bowels of eternity
a new ally will appear. This horn allows you to call upon any of the
creatures in the game to come to your aid in the fight against Armagon.
 
Wet Suit: What better way to survive under water longer. Not only that, those
flippers help speed you along as you paddle your way through the dangers that
lucky deep under the surface of those calm waters.
 
Environmental Dangers
Undertake atmospheric nightmares like lightning traps, floating spike mines,
gondolas, outdoor environments and stunning architecture never seen before in
Quake. Travel through the dangerous and treacherous mines under the Military
Base. Creep through the catacombs and dark cathedrals that lie in wait for
you in the Ancient Realms. Swallow your fear as you wind our way through the
immense fortress that protect the Lair of Armagon.
 
System Requirements
 
Full Version of QUAKE required to operate.
CD ROM drive required for Installation
Linux 2.0
16 MB RAM
Hard Disk Space: 40 MB for Mission Pack
VGA & SVGA graphics support
Mouse support (3 Button Mouse recommended)
Supports IP (Internet) play
 
%install
 
%files
%attr(644,root,root) $3/hipnotic/pak0.pak
%attr(644,root,root) $3/hipnotic/config.cfg
%attr(644,root,root) $3/hipnotic/docs/manual.doc
%attr(644,root,root) $3/hipnotic/docs/manual.htm
%attr(644,root,root) $3/hipnotic/docs/manual.txt
%attr(644,root,root) $3/hipnotic/docs/readme.doc
%attr(644,root,root) $3/hipnotic/docs/readme.htm
%attr(644,root,root) $3/hipnotic/docs/readme.txt
 
EOF
 
/contrib/other/sdlquake-1.0.9/quake-rogue.spec.sh
0,0 → 1,108
#!/bin/sh
# Generate quake-rogue.spec
# $1 is version
# $2 is release
# $3 is install dir (assumed to be in /var/tmp)
cat <<EOF
%define name quake-rogue
%define version ${1}
%define release ${2}
%define builddir \$RPM_BUILD_DIR/%{name}-%{version}
Name: %{name}
Version: %{version}
Release: %{release}
Vendor: id Software/Rogue Entertainment
Packager: Dave "Zoid" Kirsch <zoid@idsoftware.com>
URL: http://www.rogue-ent.com/
Source: quake-rogue-%{version}.tar.gz
BuildArchitectures: noarch
Group: Games
Copyright: Restricted
Icon: quake.gif
BuildRoot: /var/tmp/%{name}-%{version}
Summary: Quake Rogue Mission Pack #2: Dissolution of Eternity
 
%description
 
16 entirely new, and totally intense levels! The environmental experience of
Quake is unparalleled. Dissolution of Eternity sustains the same dynamic
sense of reality and dramatic visuals; yet adds an impression of purpose
and continuity. This expansion pack is most definitely not a conglomeration
of clone levels!
 
8 new monsters! Quake is solid, hard-hitting action with a host of evil
enemies. We've made additions to the Quake monster roster to intensify the
action and fill every dimly lit and evil corner of the game.
 
4 new weapons! The Quake weapons are awesome, but we've pushed them beyond
that with the addition of extreme power-ups to make the arsenal more
effective, and more deadly.
 
Oh yeah, the Power-Ups!
 
Single player mode power-ups include:
 
The Anti-Grav Belt. The theory here is simple. It counters the force of
gravity and allows the player to make difficult jumps.
 
The Power Shield. This 'little gem' significantly decreases the damage you
receive from most enemy attacks. If you're feelin' frisky in Deathmatch,
try out the ram attack. It's an added 'weapon' to send your opponents flying.
 
Deathmatch will introduce the player to:
 
The Vengeance Sphere. We'd like you to experience it before we let you in on
what it does. Here's a hint: Ultimate retribution from the grave!
 
Random Respawn. This feature will toss in a bit of Deathmatch variety. Hey,
we can't be responsible for what awesome power up 'pops up' next.
 
Multi-player!
 
Normal Deathmatch. Friend fraggin' action!
Team Play. Bring a friend, to kill a foe.
Tag. You played it as a kid, but nothin' says "Tag!" like a face full of
Plasma.
 
And, a much enhanced version of Capture the Flag!
Capture the Flag. You've seen it on the Internet; now it's in your hands.
Additional value, additional excitement, and additional Deathmatch 'down and
dirty' devastation. CTF is one of the most exciting team multi-player
directions for Quake to date; and the most popular too!
 
Including two brand new CTF features.
 
One Flag - It's a mad race for the flag, the loser gets a rocket up his
privates.
Three Team - Red, Blue, and the new Rogue (pun intended) Grey team. The good
news? You can take either flag and bring to it either Red or Blue base. The
bad news? You don't have your own base!
 
Also, a collection of lethal environmental hazards have been placed at every
turn. They are challenging, and terminal! Here are just a few of them.
 
The Pendulums - Set to slice the player to shreds when he least expects it!
Lightning Shooters - Well, they shoot lightning and can be directed at any
angle to make some rooms extremely hazardous.
Lava Nail Shooters - Well, they shoot, you get the idea here!
Earthquakes - Earthshaking environments! Level areas that tremor with
seismic activity. Now the Quake player can literally quake!
Buzz Saws - Compact. Cordless. And completely gib-o-matic! These dreaded
traps are set in floors and ceilings.
 
%install
 
%files
%attr(644,root,root) $3/rogue/pak0.pak
%attr(644,root,root) $3/rogue/docs/manual.doc
%attr(644,root,root) $3/rogue/docs/manual.htm
%attr(644,root,root) $3/rogue/docs/manual.txt
%attr(644,root,root) $3/rogue/docs/readme.doc
%attr(644,root,root) $3/rogue/docs/readme.htm
%attr(644,root,root) $3/rogue/docs/readme.txt
%attr(644,root,root) $3/rogue/docs/ctf.doc
%attr(644,root,root) $3/rogue/docs/ctf.htm
%attr(644,root,root) $3/rogue/docs/ctf.txt
 
EOF
 
/contrib/other/sdlquake-1.0.9/quake-shareware.spec.sh
0,0 → 1,69
#!/bin/sh
# Generate quake-shareware.spec
# $1 is version
# $2 is release
# $3 is install dir (assumed to be in /var/tmp)
cat <<EOF
%define name quake
%define version ${1}-shareware
%define release ${2}
%define builddir \$RPM_BUILD_DIR/%{name}-%{version}
Name: %{name}
Version: %{version}
Release: %{release}
Vendor: id Software
Packager: Dave "Zoid" Kirsch <zoid@idsoftware.com>
URL: http://www.idsoftware.com/
Source: quake-%{version}.tar.gz
Group: Games
Copyright: Restricted
Icon: quake.gif
BuildRoot: /var/tmp/%{name}-%{version}
Summary: Quake for Linux
 
%description
"Quake is the biggest, baddest, and bloodiest 3-D action game ever
conceived" - PC GAMER
 
"The most important PC game ever" - PC ZONE
 
""Quake": Bloody Amazing" - USA TODAY
 
"The Vanguard of a terrifying new level of immersive interactivity" -
COMPUTER GAMING WORLD
 
From the creators of DOOM and DOOM II comes the most intense, technologically
advanced 3-D experience ever captured on CD ROM. Features free and fluid
motion, ambient sound and lighting, and unmatched multiplayer capabilities
(play with up to 15 others).
 
Included in this archive are several different versions of Quake.
 
- SQuake for SVGALib Console Graphics
- GLQuake for 3DFX and other glX based hardware OpenGL
- Quake.X11 for running Quake under X11
 
%install
 
%files
%attr(644,root,root) $3/README
%attr(4755,root,root) $3/squake
%attr(4755,root,root) $3/glquake
%attr(4755,root,root) $3/glquake.glx
%attr(4755,root,root) $3/glquake.3dfxgl
%attr(755,root,root) $3/quake.x11
%attr(644,root,root) $3/help.txt
%attr(644,root,root) $3/licinfo.txt
%attr(644,root,root) $3/manual.txt
%attr(644,root,root) $3/readme.txt
%attr(644,root,root) $3/slicnse.txt
%attr(644,root,root) $3/techinfo.txt
%attr(644,root,root) $3/id1/pak0.pak
%attr(755,root,root) /usr/lib/lib3dfxgl.so
%attr(755,root,root) /usr/lib/libMesaGL.so.2.6
 
%post
/sbin/ldconfig
 
EOF
 
/contrib/other/sdlquake-1.0.9/quake.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/contrib/other/sdlquake-1.0.9/quake.ico
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/contrib/other/sdlquake-1.0.9/quake.spec.sh
0,0 → 1,61
#!/bin/sh
# Generate quake.spec
# $1 is version
# $2 is release
# $3 is install dir (assumed to be in /var/tmp)
cat <<EOF
%define name quake
%define version ${1}
%define release ${2}
%define builddir \$RPM_BUILD_DIR/%{name}-%{version}
Name: %{name}
Version: %{version}
Release: %{release}
Vendor: id Software
Packager: Dave "Zoid" Kirsch <zoid@idsoftware.com>
URL: http://www.idsoftware.com/
Source: quake-%{version}.tar.gz
Group: Games
Copyright: Restricted
Icon: quake.gif
BuildRoot: /var/tmp/%{name}-%{version}
Summary: Quake for Linux
 
%description
"Quake is the biggest, baddest, and bloodiest 3-D action game ever
conceived" - PC GAMER
 
"The most important PC game ever" - PC ZONE
 
""Quake": Bloody Amazing" - USA TODAY
 
"The Vanguard of a terrifying new level of immersive interactivity" -
COMPUTER GAMING WORLD
 
From the creators of DOOM and DOOM II comes the most intense, technologically
advanced 3-D experience ever captured on CD ROM. Features free and fluid
motion, ambient sound and lighting, and unmatched multiplayer capabilities
(play with up to 15 others).
 
Included in this archive are several different versions of Quake.
 
- SQuake for SVGALib Console Graphics
- GLQuake for 3DFX and other glX based hardware OpenGL
- Quake.X11 for running Quake under X11
 
%install
 
%files
%attr(644,root,root) $3/README
%attr(4755,root,root) $3/squake
%attr(4755,root,root) $3/glquake
%attr(4755,root,root) $3/glquake.glx
%attr(4755,root,root) $3/glquake.3dfxgl
%attr(755,root,root) $3/quake.x11
%attr(755,root,root) /usr/lib/lib3dfxgl.so
%attr(755,root,root) /usr/lib/libMesaGL.so.2.6
 
%post
/sbin/ldconfig
EOF
 
/contrib/other/sdlquake-1.0.9/quakeasm.h
0,0 → 1,280
/*
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.
 
*/
//
// quakeasm.h: general asm header file
//
 
//#define GLQUAKE 1
 
#if defined(_WIN32) && !defined(WINDED)
 
#if defined(_M_IX86)
#define __i386__ 1
#endif
 
#endif
 
#if defined(__i386__) && defined(USE_ASM)
#define id386 1
#else
#define id386 0
#endif
 
// !!! must be kept the same as in d_iface.h !!!
#define TRANSPARENT_COLOR 255
 
#ifndef NeXT
#ifndef GLQUAKE
.extern C(d_zistepu)
.extern C(d_pzbuffer)
.extern C(d_zistepv)
.extern C(d_zrowbytes)
.extern C(d_ziorigin)
.extern C(r_turb_s)
.extern C(r_turb_t)
.extern C(r_turb_pdest)
.extern C(r_turb_spancount)
.extern C(r_turb_turb)
.extern C(r_turb_pbase)
.extern C(r_turb_sstep)
.extern C(r_turb_tstep)
.extern C(r_bmodelactive)
.extern C(d_sdivzstepu)
.extern C(d_tdivzstepu)
.extern C(d_sdivzstepv)
.extern C(d_tdivzstepv)
.extern C(d_sdivzorigin)
.extern C(d_tdivzorigin)
.extern C(sadjust)
.extern C(tadjust)
.extern C(bbextents)
.extern C(bbextentt)
.extern C(cacheblock)
.extern C(d_viewbuffer)
.extern C(cachewidth)
.extern C(d_pzbuffer)
.extern C(d_zrowbytes)
.extern C(d_zwidth)
.extern C(d_scantable)
.extern C(r_lightptr)
.extern C(r_numvblocks)
.extern C(prowdestbase)
.extern C(pbasesource)
.extern C(r_lightwidth)
.extern C(lightright)
.extern C(lightrightstep)
.extern C(lightdeltastep)
.extern C(lightdelta)
.extern C(lightright)
.extern C(lightdelta)
.extern C(sourcetstep)
.extern C(surfrowbytes)
.extern C(lightrightstep)
.extern C(lightdeltastep)
.extern C(r_sourcemax)
.extern C(r_stepback)
.extern C(colormap)
.extern C(blocksize)
.extern C(sourcesstep)
.extern C(lightleft)
.extern C(blockdivshift)
.extern C(blockdivmask)
.extern C(lightleftstep)
.extern C(r_origin)
.extern C(r_ppn)
.extern C(r_pup)
.extern C(r_pright)
.extern C(ycenter)
.extern C(xcenter)
.extern C(d_vrectbottom_particle)
.extern C(d_vrectright_particle)
.extern C(d_vrecty)
.extern C(d_vrectx)
.extern C(d_pix_shift)
.extern C(d_pix_min)
.extern C(d_pix_max)
.extern C(d_y_aspect_shift)
.extern C(screenwidth)
.extern C(r_leftclipped)
.extern C(r_leftenter)
.extern C(r_rightclipped)
.extern C(r_rightenter)
.extern C(modelorg)
.extern C(xscale)
.extern C(r_refdef)
.extern C(yscale)
.extern C(r_leftexit)
.extern C(r_rightexit)
.extern C(r_lastvertvalid)
.extern C(cacheoffset)
.extern C(newedges)
.extern C(removeedges)
.extern C(r_pedge)
.extern C(r_framecount)
.extern C(r_u1)
.extern C(r_emitted)
.extern C(edge_p)
.extern C(surface_p)
.extern C(surfaces)
.extern C(r_lzi1)
.extern C(r_v1)
.extern C(r_ceilv1)
.extern C(r_nearzi)
.extern C(r_nearzionly)
.extern C(edge_aftertail)
.extern C(edge_tail)
.extern C(current_iv)
.extern C(edge_head_u_shift20)
.extern C(span_p)
.extern C(edge_head)
.extern C(fv)
.extern C(edge_tail_u_shift20)
.extern C(r_apverts)
.extern C(r_anumverts)
.extern C(aliastransform)
.extern C(r_avertexnormals)
.extern C(r_plightvec)
.extern C(r_ambientlight)
.extern C(r_shadelight)
.extern C(aliasxcenter)
.extern C(aliasycenter)
.extern C(a_sstepxfrac)
.extern C(r_affinetridesc)
.extern C(acolormap)
.extern C(d_pcolormap)
.extern C(r_affinetridesc)
.extern C(d_sfrac)
.extern C(d_ptex)
.extern C(d_pedgespanpackage)
.extern C(d_tfrac)
.extern C(d_light)
.extern C(d_zi)
.extern C(d_pdest)
.extern C(d_pz)
.extern C(d_aspancount)
.extern C(erroradjustup)
.extern C(errorterm)
.extern C(d_xdenom)
.extern C(r_p0)
.extern C(r_p1)
.extern C(r_p2)
.extern C(a_tstepxfrac)
.extern C(r_sstepx)
.extern C(r_tstepx)
.extern C(a_ststepxwhole)
.extern C(zspantable)
.extern C(skintable)
.extern C(r_zistepx)
.extern C(erroradjustdown)
.extern C(d_countextrastep)
.extern C(ubasestep)
.extern C(a_ststepxwhole)
.extern C(a_tstepxfrac)
.extern C(r_lstepx)
.extern C(a_spans)
.extern C(erroradjustdown)
.extern C(d_pdestextrastep)
.extern C(d_pzextrastep)
.extern C(d_sfracextrastep)
.extern C(d_ptexextrastep)
.extern C(d_countextrastep)
.extern C(d_tfracextrastep)
.extern C(d_lightextrastep)
.extern C(d_ziextrastep)
.extern C(d_pdestbasestep)
.extern C(d_pzbasestep)
.extern C(d_sfracbasestep)
.extern C(d_ptexbasestep)
.extern C(ubasestep)
.extern C(d_tfracbasestep)
.extern C(d_lightbasestep)
.extern C(d_zibasestep)
.extern C(zspantable)
.extern C(r_lstepy)
.extern C(r_sstepy)
.extern C(r_tstepy)
.extern C(r_zistepy)
.extern C(D_PolysetSetEdgeTable)
.extern C(D_RasterizeAliasPolySmooth)
 
.extern float_point5
.extern Float2ToThe31nd
.extern izistep
.extern izi
.extern FloatMinus2ToThe31nd
.extern float_1
.extern float_particle_z_clip
.extern float_minus_1
.extern float_0
.extern fp_16
.extern fp_64k
.extern fp_1m
.extern fp_1m_minus_1
.extern fp_8
.extern entryvec_table
.extern advancetable
.extern sstep
.extern tstep
.extern pspantemp
.extern counttemp
.extern jumptemp
.extern reciprocal_table
.extern DP_Count
.extern DP_u
.extern DP_v
.extern DP_32768
.extern DP_Color
.extern DP_Pix
.extern DP_EntryTable
.extern pbase
.extern s
.extern t
.extern sfracf
.extern tfracf
.extern snext
.extern tnext
.extern spancountminus1
.extern zi16stepu
.extern sdivz16stepu
.extern tdivz16stepu
.extern zi8stepu
.extern sdivz8stepu
.extern tdivz8stepu
.extern reciprocal_table_16
.extern entryvec_table_16
.extern ceil_cw
.extern single_cw
.extern fp_64kx64k
.extern pz
.extern spr8entryvec_table
#endif
 
.extern C(snd_scaletable)
.extern C(paintbuffer)
.extern C(snd_linear_count)
.extern C(snd_p)
.extern C(snd_vol)
.extern C(snd_out)
.extern C(vright)
.extern C(vup)
.extern C(vpn)
.extern C(BOPS_Error)
 
#endif
/contrib/other/sdlquake-1.0.9/quakedef.h
0,0 → 1,336
/*
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
 
#undef 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>
 
#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(USE_ASM)
#define id386 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
#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
 
#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"
#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 "render.h"
#include "client.h"
#include "progs.h"
#include "server.h"
 
#ifdef GLQUAKE
#include "gl_model.h"
#else
#include "model.h"
#include "d_iface.h"
#endif
 
#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
//
extern cvar_t chase_active;
 
void Chase_Init (void);
void Chase_Reset (void);
void Chase_Update (void);
/contrib/other/sdlquake-1.0.9/r_aclip.c
0,0 → 1,350
/*
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_aclip.c: clip routines for drawing Alias models directly to the screen
 
#include "quakedef.h"
#include "r_local.h"
#include "d_local.h"
 
static finalvert_t fv[2][8];
static auxvert_t av[8];
 
void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av);
void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1,
finalvert_t *out);
void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1,
finalvert_t *out);
void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1,
finalvert_t *out);
void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1,
finalvert_t *out);
 
 
/*
================
R_Alias_clip_z
 
pfv0 is the unclipped vertex, pfv1 is the z-clipped vertex
================
*/
void R_Alias_clip_z (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
{
float scale;
auxvert_t *pav0, *pav1, avout;
 
pav0 = &av[pfv0 - &fv[0][0]];
pav1 = &av[pfv1 - &fv[0][0]];
 
if (pfv0->v[1] >= pfv1->v[1])
{
scale = (ALIAS_Z_CLIP_PLANE - pav0->fv[2]) /
(pav1->fv[2] - pav0->fv[2]);
avout.fv[0] = pav0->fv[0] + (pav1->fv[0] - pav0->fv[0]) * scale;
avout.fv[1] = pav0->fv[1] + (pav1->fv[1] - pav0->fv[1]) * scale;
avout.fv[2] = ALIAS_Z_CLIP_PLANE;
out->v[2] = pfv0->v[2] + (pfv1->v[2] - pfv0->v[2]) * scale;
out->v[3] = pfv0->v[3] + (pfv1->v[3] - pfv0->v[3]) * scale;
out->v[4] = pfv0->v[4] + (pfv1->v[4] - pfv0->v[4]) * scale;
}
else
{
scale = (ALIAS_Z_CLIP_PLANE - pav1->fv[2]) /
(pav0->fv[2] - pav1->fv[2]);
avout.fv[0] = pav1->fv[0] + (pav0->fv[0] - pav1->fv[0]) * scale;
avout.fv[1] = pav1->fv[1] + (pav0->fv[1] - pav1->fv[1]) * scale;
avout.fv[2] = ALIAS_Z_CLIP_PLANE;
out->v[2] = pfv1->v[2] + (pfv0->v[2] - pfv1->v[2]) * scale;
out->v[3] = pfv1->v[3] + (pfv0->v[3] - pfv1->v[3]) * scale;
out->v[4] = pfv1->v[4] + (pfv0->v[4] - pfv1->v[4]) * scale;
}
 
R_AliasProjectFinalVert (out, &avout);
 
if (out->v[0] < r_refdef.aliasvrect.x)
out->flags |= ALIAS_LEFT_CLIP;
if (out->v[1] < r_refdef.aliasvrect.y)
out->flags |= ALIAS_TOP_CLIP;
if (out->v[0] > r_refdef.aliasvrectright)
out->flags |= ALIAS_RIGHT_CLIP;
if (out->v[1] > r_refdef.aliasvrectbottom)
out->flags |= ALIAS_BOTTOM_CLIP;
}
 
 
#if !id386
 
void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
{
float scale;
int i;
 
if (pfv0->v[1] >= pfv1->v[1])
{
scale = (float)(r_refdef.aliasvrect.x - pfv0->v[0]) /
(pfv1->v[0] - pfv0->v[0]);
for (i=0 ; i<6 ; i++)
out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5;
}
else
{
scale = (float)(r_refdef.aliasvrect.x - pfv1->v[0]) /
(pfv0->v[0] - pfv1->v[0]);
for (i=0 ; i<6 ; i++)
out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5;
}
}
 
 
void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1,
finalvert_t *out)
{
float scale;
int i;
 
if (pfv0->v[1] >= pfv1->v[1])
{
scale = (float)(r_refdef.aliasvrectright - pfv0->v[0]) /
(pfv1->v[0] - pfv0->v[0]);
for (i=0 ; i<6 ; i++)
out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5;
}
else
{
scale = (float)(r_refdef.aliasvrectright - pfv1->v[0]) /
(pfv0->v[0] - pfv1->v[0]);
for (i=0 ; i<6 ; i++)
out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5;
}
}
 
 
void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
{
float scale;
int i;
 
if (pfv0->v[1] >= pfv1->v[1])
{
scale = (float)(r_refdef.aliasvrect.y - pfv0->v[1]) /
(pfv1->v[1] - pfv0->v[1]);
for (i=0 ; i<6 ; i++)
out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5;
}
else
{
scale = (float)(r_refdef.aliasvrect.y - pfv1->v[1]) /
(pfv0->v[1] - pfv1->v[1]);
for (i=0 ; i<6 ; i++)
out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5;
}
}
 
 
void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1,
finalvert_t *out)
{
float scale;
int i;
 
if (pfv0->v[1] >= pfv1->v[1])
{
scale = (float)(r_refdef.aliasvrectbottom - pfv0->v[1]) /
(pfv1->v[1] - pfv0->v[1]);
 
for (i=0 ; i<6 ; i++)
out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5;
}
else
{
scale = (float)(r_refdef.aliasvrectbottom - pfv1->v[1]) /
(pfv0->v[1] - pfv1->v[1]);
 
for (i=0 ; i<6 ; i++)
out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5;
}
}
 
#endif
 
 
int R_AliasClip (finalvert_t *in, finalvert_t *out, int flag, int count,
void(*clip)(finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) )
{
int i,j,k;
int flags, oldflags;
j = count-1;
k = 0;
for (i=0 ; i<count ; j = i, i++)
{
oldflags = in[j].flags & flag;
flags = in[i].flags & flag;
 
if (flags && oldflags)
continue;
if (oldflags ^ flags)
{
clip (&in[j], &in[i], &out[k]);
out[k].flags = 0;
if (out[k].v[0] < r_refdef.aliasvrect.x)
out[k].flags |= ALIAS_LEFT_CLIP;
if (out[k].v[1] < r_refdef.aliasvrect.y)
out[k].flags |= ALIAS_TOP_CLIP;
if (out[k].v[0] > r_refdef.aliasvrectright)
out[k].flags |= ALIAS_RIGHT_CLIP;
if (out[k].v[1] > r_refdef.aliasvrectbottom)
out[k].flags |= ALIAS_BOTTOM_CLIP;
k++;
}
if (!flags)
{
out[k] = in[i];
k++;
}
}
return k;
}
 
 
/*
================
R_AliasClipTriangle
================
*/
void R_AliasClipTriangle (mtriangle_t *ptri)
{
int i, k, pingpong;
mtriangle_t mtri;
unsigned clipflags;
 
// copy vertexes and fix seam texture coordinates
if (ptri->facesfront)
{
fv[0][0] = pfinalverts[ptri->vertindex[0]];
fv[0][1] = pfinalverts[ptri->vertindex[1]];
fv[0][2] = pfinalverts[ptri->vertindex[2]];
}
else
{
for (i=0 ; i<3 ; i++)
{
fv[0][i] = pfinalverts[ptri->vertindex[i]];
if (!ptri->facesfront && (fv[0][i].flags & ALIAS_ONSEAM) )
fv[0][i].v[2] += r_affinetridesc.seamfixupX16;
}
}
 
// clip
clipflags = fv[0][0].flags | fv[0][1].flags | fv[0][2].flags;
 
if (clipflags & ALIAS_Z_CLIP)
{
for (i=0 ; i<3 ; i++)
av[i] = pauxverts[ptri->vertindex[i]];
 
k = R_AliasClip (fv[0], fv[1], ALIAS_Z_CLIP, 3, R_Alias_clip_z);
if (k == 0)
return;
 
pingpong = 1;
clipflags = fv[1][0].flags | fv[1][1].flags | fv[1][2].flags;
}
else
{
pingpong = 0;
k = 3;
}
 
if (clipflags & ALIAS_LEFT_CLIP)
{
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
ALIAS_LEFT_CLIP, k, R_Alias_clip_left);
if (k == 0)
return;
 
pingpong ^= 1;
}
 
if (clipflags & ALIAS_RIGHT_CLIP)
{
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
ALIAS_RIGHT_CLIP, k, R_Alias_clip_right);
if (k == 0)
return;
 
pingpong ^= 1;
}
 
if (clipflags & ALIAS_BOTTOM_CLIP)
{
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
ALIAS_BOTTOM_CLIP, k, R_Alias_clip_bottom);
if (k == 0)
return;
 
pingpong ^= 1;
}
 
if (clipflags & ALIAS_TOP_CLIP)
{
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
ALIAS_TOP_CLIP, k, R_Alias_clip_top);
if (k == 0)
return;
 
pingpong ^= 1;
}
 
for (i=0 ; i<k ; i++)
{
if (fv[pingpong][i].v[0] < r_refdef.aliasvrect.x)
fv[pingpong][i].v[0] = r_refdef.aliasvrect.x;
else if (fv[pingpong][i].v[0] > r_refdef.aliasvrectright)
fv[pingpong][i].v[0] = r_refdef.aliasvrectright;
 
if (fv[pingpong][i].v[1] < r_refdef.aliasvrect.y)
fv[pingpong][i].v[1] = r_refdef.aliasvrect.y;
else if (fv[pingpong][i].v[1] > r_refdef.aliasvrectbottom)
fv[pingpong][i].v[1] = r_refdef.aliasvrectbottom;
 
fv[pingpong][i].flags = 0;
}
 
// draw triangles
mtri.facesfront = ptri->facesfront;
r_affinetridesc.ptriangles = &mtri;
r_affinetridesc.pfinalverts = fv[pingpong];
 
// FIXME: do all at once as trifan?
mtri.vertindex[0] = 0;
for (i=1 ; i<k-1 ; i++)
{
mtri.vertindex[1] = i;
mtri.vertindex[2] = i+1;
D_PolysetDraw ();
}
}
 
/contrib/other/sdlquake-1.0.9/r_aclipa.S
0,0 → 1,216
/*
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_aliasa.s
// x86 assembly-language Alias model transform and project code.
//
 
#include "asm_i386.h"
#include "quakeasm.h"
#include "asm_draw.h"
#include "d_ifacea.h"
 
#if id386
 
.data
Ltemp0: .long 0
Ltemp1: .long 0
 
.text
 
#define pfv0 8+4
#define pfv1 8+8
#define out 8+12
 
.globl C(R_Alias_clip_bottom)
C(R_Alias_clip_bottom):
pushl %esi
pushl %edi
 
movl pfv0(%esp),%esi
movl pfv1(%esp),%edi
 
movl C(r_refdef)+rd_aliasvrectbottom,%eax
 
LDoForwardOrBackward:
 
movl fv_v+4(%esi),%edx
movl fv_v+4(%edi),%ecx
 
cmpl %ecx,%edx
jl LDoForward
 
movl fv_v+4(%esi),%ecx
movl fv_v+4(%edi),%edx
movl pfv0(%esp),%edi
movl pfv1(%esp),%esi
 
LDoForward:
 
subl %edx,%ecx
subl %edx,%eax
movl %ecx,Ltemp1
movl %eax,Ltemp0
fildl Ltemp1
fildl Ltemp0
movl out(%esp),%edx
movl $2,%eax
 
fdivp %st(0),%st(1) // scale
 
LDo3Forward:
fildl fv_v+0(%esi) // fv0v0 | scale
fildl fv_v+0(%edi) // fv1v0 | fv0v0 | scale
fildl fv_v+4(%esi) // fv0v1 | fv1v0 | fv0v0 | scale
fildl fv_v+4(%edi) // fv1v1 | fv0v1 | fv1v0 | fv0v0 | scale
fildl fv_v+8(%esi) // fv0v2 | fv1v1 | fv0v1 | fv1v0 | fv0v0 | scale
fildl fv_v+8(%edi) // fv1v2 | fv0v2 | fv1v1 | fv0v1 | fv1v0 | fv0v0 |
// scale
fxch %st(5) // fv0v0 | fv0v2 | fv1v1 | fv0v1 | fv1v0 | fv1v2 |
// scale
fsubr %st(0),%st(4) // fv0v0 | fv0v2 | fv1v1 | fv0v1 | fv1v0-fv0v0 |
// fv1v2 | scale
fxch %st(3) // fv0v1 | fv0v2 | fv1v1 | fv0v0 | fv1v0-fv0v0 |
// fv1v2 | scale
fsubr %st(0),%st(2) // fv0v1 | fv0v2 | fv1v1-fv0v1 | fv0v0 |
// fv1v0-fv0v0 | fv1v2 | scale
fxch %st(1) // fv0v2 | fv0v1 | fv1v1-fv0v1 | fv0v0 |
// fv1v0-fv0v0 | fv1v2 | scale
fsubr %st(0),%st(5) // fv0v2 | fv0v1 | fv1v1-fv0v1 | fv0v0 |
// fv1v0-fv0v0 | fv1v2-fv0v2 | scale
fxch %st(6) // scale | fv0v1 | fv1v1-fv0v1 | fv0v0 |
// fv1v0-fv0v0 | fv1v2-fv0v2 | fv0v2
fmul %st(0),%st(4) // scale | fv0v1 | fv1v1-fv0v1 | fv0v0 |
// (fv1v0-fv0v0)*scale | fv1v2-fv0v2 | fv0v2
addl $12,%edi
fmul %st(0),%st(2) // scale | fv0v1 | (fv1v1-fv0v1)*scale | fv0v0 |
// (fv1v0-fv0v0)*scale | fv1v2-fv0v2 | fv0v2
addl $12,%esi
addl $12,%edx
fmul %st(0),%st(5) // scale | fv0v1 | (fv1v1-fv0v1)*scale | fv0v0 |
// (fv1v0-fv0v0)*scale | (fv1v2-fv0v2)*scale |
// fv0v2
fxch %st(3) // fv0v0 | fv0v1 | (fv1v1-fv0v1)*scale | scale |
// (fv1v0-fv0v0)*scale | (fv1v2-fv0v2)*scale |
// fv0v2
faddp %st(0),%st(4) // fv0v1 | (fv1v1-fv0v1)*scale | scale |
// fv0v0+(fv1v0-fv0v0)*scale |
// (fv1v2-fv0v2)*scale | fv0v2
faddp %st(0),%st(1) // fv0v1+(fv1v1-fv0v1)*scale | scale |
// fv0v0+(fv1v0-fv0v0)*scale |
// (fv1v2-fv0v2)*scale | fv0v2
fxch %st(4) // fv0v2 | scale | fv0v0+(fv1v0-fv0v0)*scale |
// (fv1v2-fv0v2)*scale | fv0v1+(fv1v1-fv0v1)*scale
faddp %st(0),%st(3) // scale | fv0v0+(fv1v0-fv0v0)*scale |
// fv0v2+(fv1v2-fv0v2)*scale |
// fv0v1+(fv1v1-fv0v1)*scale
fxch %st(1) // fv0v0+(fv1v0-fv0v0)*scale | scale |
// fv0v2+(fv1v2-fv0v2)*scale |
// fv0v1+(fv1v1-fv0v1)*scale
fadds float_point5
fxch %st(3) // fv0v1+(fv1v1-fv0v1)*scale | scale |
// fv0v2+(fv1v2-fv0v2)*scale |
// fv0v0+(fv1v0-fv0v0)*scale
fadds float_point5
fxch %st(2) // fv0v2+(fv1v2-fv0v2)*scale | scale |
// fv0v1+(fv1v1-fv0v1)*scale |
// fv0v0+(fv1v0-fv0v0)*scale
fadds float_point5
fxch %st(3) // fv0v0+(fv1v0-fv0v0)*scale | scale |
// fv0v1+(fv1v1-fv0v1)*scale |
// fv0v2+(fv1v2-fv0v2)*scale
fistpl fv_v+0-12(%edx) // scale | fv0v1+(fv1v1-fv0v1)*scale |
// fv0v2+(fv1v2-fv0v2)*scale
fxch %st(1) // fv0v1+(fv1v1-fv0v1)*scale | scale |
// fv0v2+(fv1v2-fv0v2)*scale | scale
fistpl fv_v+4-12(%edx) // scale | fv0v2+(fv1v2-fv0v2)*scale
fxch %st(1) // fv0v2+(fv1v2-fv0v2)*sc | scale
fistpl fv_v+8-12(%edx) // scale
 
decl %eax
jnz LDo3Forward
 
fstp %st(0)
 
popl %edi
popl %esi
 
ret
 
 
.globl C(R_Alias_clip_top)
C(R_Alias_clip_top):
pushl %esi
pushl %edi
 
movl pfv0(%esp),%esi
movl pfv1(%esp),%edi
 
movl C(r_refdef)+rd_aliasvrect+4,%eax
jmp LDoForwardOrBackward
 
 
 
.globl C(R_Alias_clip_right)
C(R_Alias_clip_right):
pushl %esi
pushl %edi
 
movl pfv0(%esp),%esi
movl pfv1(%esp),%edi
 
movl C(r_refdef)+rd_aliasvrectright,%eax
 
LRightLeftEntry:
 
 
movl fv_v+4(%esi),%edx
movl fv_v+4(%edi),%ecx
 
cmpl %ecx,%edx
movl fv_v+0(%esi),%edx
 
movl fv_v+0(%edi),%ecx
jl LDoForward2
 
movl fv_v+0(%esi),%ecx
movl fv_v+0(%edi),%edx
movl pfv0(%esp),%edi
movl pfv1(%esp),%esi
 
LDoForward2:
 
jmp LDoForward
 
 
.globl C(R_Alias_clip_left)
C(R_Alias_clip_left):
pushl %esi
pushl %edi
 
movl pfv0(%esp),%esi
movl pfv1(%esp),%edi
 
movl C(r_refdef)+rd_aliasvrect+0,%eax
jmp LRightLeftEntry
 
 
#endif // id386
 
/contrib/other/sdlquake-1.0.9/r_alias.c
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.
 
*/
// r_alias.c: routines for setting up to draw alias models
 
#include "quakedef.h"
#include "r_local.h"
#include "d_local.h" // FIXME: shouldn't be needed (is needed for patch
// right now, but that should move)
 
#define LIGHT_MIN 5 // lowest light value we'll allow, to avoid the
// need for inner-loop light clamping
 
mtriangle_t *ptriangles;
affinetridesc_t r_affinetridesc;
 
void * acolormap; // FIXME: should go away
 
trivertx_t *r_apverts;
 
// TODO: these probably will go away with optimized rasterization
mdl_t *pmdl;
vec3_t r_plightvec;
int r_ambientlight;
float r_shadelight;
aliashdr_t *paliashdr;
finalvert_t *pfinalverts;
auxvert_t *pauxverts;
static float ziscale;
static model_t *pmodel;
 
static vec3_t alias_forward, alias_right, alias_up;
 
static maliasskindesc_t *pskindesc;
 
int r_amodels_drawn;
int a_skinwidth;
int r_anumverts;
 
float aliastransform[3][4];
 
typedef struct {
int index0;
int index1;
} aedge_t;
 
static aedge_t aedges[12] = {
{0, 1}, {1, 2}, {2, 3}, {3, 0},
{4, 5}, {5, 6}, {6, 7}, {7, 4},
{0, 5}, {1, 4}, {2, 7}, {3, 6}
};
 
#define NUMVERTEXNORMALS 162
 
float r_avertexnormals[NUMVERTEXNORMALS][3] = {
#include "anorms.h"
};
 
void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv,
stvert_t *pstverts);
void R_AliasSetUpTransform (int trivial_accept);
void R_AliasTransformVector (vec3_t in, vec3_t out);
void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av,
trivertx_t *pverts, stvert_t *pstverts);
void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av);
 
 
/*
================
R_AliasCheckBBox
================
*/
qboolean R_AliasCheckBBox (void)
{
int i, flags, frame, numv;
aliashdr_t *pahdr;
float zi, basepts[8][3], v0, v1, frac;
finalvert_t *pv0, *pv1, viewpts[16];
auxvert_t *pa0, *pa1, viewaux[16];
maliasframedesc_t *pframedesc;
qboolean zclipped, zfullyclipped;
unsigned anyclip, allclip;
int minz;
// expand, rotate, and translate points into worldspace
 
currententity->trivial_accept = 0;
pmodel = currententity->model;
pahdr = Mod_Extradata (pmodel);
pmdl = (mdl_t *)((byte *)pahdr + pahdr->model);
 
R_AliasSetUpTransform (0);
 
// construct the base bounding box for this frame
frame = currententity->frame;
// TODO: don't repeat this check when drawing?
if ((frame >= pmdl->numframes) || (frame < 0))
{
Con_DPrintf ("No such frame %d %s\n", frame,
pmodel->name);
frame = 0;
}
 
pframedesc = &pahdr->frames[frame];
 
// x worldspace coordinates
basepts[0][0] = basepts[1][0] = basepts[2][0] = basepts[3][0] =
(float)pframedesc->bboxmin.v[0];
basepts[4][0] = basepts[5][0] = basepts[6][0] = basepts[7][0] =
(float)pframedesc->bboxmax.v[0];
 
// y worldspace coordinates
basepts[0][1] = basepts[3][1] = basepts[5][1] = basepts[6][1] =
(float)pframedesc->bboxmin.v[1];
basepts[1][1] = basepts[2][1] = basepts[4][1] = basepts[7][1] =
(float)pframedesc->bboxmax.v[1];
 
// z worldspace coordinates
basepts[0][2] = basepts[1][2] = basepts[4][2] = basepts[5][2] =
(float)pframedesc->bboxmin.v[2];
basepts[2][2] = basepts[3][2] = basepts[6][2] = basepts[7][2] =
(float)pframedesc->bboxmax.v[2];
 
zclipped = false;
zfullyclipped = true;
 
minz = 9999;
for (i=0; i<8 ; i++)
{
R_AliasTransformVector (&basepts[i][0], &viewaux[i].fv[0]);
 
if (viewaux[i].fv[2] < ALIAS_Z_CLIP_PLANE)
{
// we must clip points that are closer than the near clip plane
viewpts[i].flags = ALIAS_Z_CLIP;
zclipped = true;
}
else
{
if (viewaux[i].fv[2] < minz)
minz = viewaux[i].fv[2];
viewpts[i].flags = 0;
zfullyclipped = false;
}
}
 
if (zfullyclipped)
{
return false; // everything was near-z-clipped
}
 
numv = 8;
 
if (zclipped)
{
// organize points by edges, use edges to get new points (possible trivial
// reject)
for (i=0 ; i<12 ; i++)
{
// edge endpoints
pv0 = &viewpts[aedges[i].index0];
pv1 = &viewpts[aedges[i].index1];
pa0 = &viewaux[aedges[i].index0];
pa1 = &viewaux[aedges[i].index1];
 
// if one end is clipped and the other isn't, make a new point
if (pv0->flags ^ pv1->flags)
{
frac = (ALIAS_Z_CLIP_PLANE - pa0->fv[2]) /
(pa1->fv[2] - pa0->fv[2]);
viewaux[numv].fv[0] = pa0->fv[0] +
(pa1->fv[0] - pa0->fv[0]) * frac;
viewaux[numv].fv[1] = pa0->fv[1] +
(pa1->fv[1] - pa0->fv[1]) * frac;
viewaux[numv].fv[2] = ALIAS_Z_CLIP_PLANE;
viewpts[numv].flags = 0;
numv++;
}
}
}
 
// project the vertices that remain after clipping
anyclip = 0;
allclip = ALIAS_XY_CLIP_MASK;
 
// TODO: probably should do this loop in ASM, especially if we use floats
for (i=0 ; i<numv ; i++)
{
// we don't need to bother with vertices that were z-clipped
if (viewpts[i].flags & ALIAS_Z_CLIP)
continue;
 
zi = 1.0 / viewaux[i].fv[2];
 
// FIXME: do with chop mode in ASM, or convert to float
v0 = (viewaux[i].fv[0] * xscale * zi) + xcenter;
v1 = (viewaux[i].fv[1] * yscale * zi) + ycenter;
 
flags = 0;
 
if (v0 < r_refdef.fvrectx)
flags |= ALIAS_LEFT_CLIP;
if (v1 < r_refdef.fvrecty)
flags |= ALIAS_TOP_CLIP;
if (v0 > r_refdef.fvrectright)
flags |= ALIAS_RIGHT_CLIP;
if (v1 > r_refdef.fvrectbottom)
flags |= ALIAS_BOTTOM_CLIP;
 
anyclip |= flags;
allclip &= flags;
}
 
if (allclip)
return false; // trivial reject off one side
 
currententity->trivial_accept = !anyclip & !zclipped;
 
if (currententity->trivial_accept)
{
if (minz > (r_aliastransition + (pmdl->size * r_resfudge)))
{
currententity->trivial_accept |= 2;
}
}
 
return true;
}
 
 
/*
================
R_AliasTransformVector
================
*/
void R_AliasTransformVector (vec3_t in, vec3_t out)
{
out[0] = DotProduct(in, aliastransform[0]) + aliastransform[0][3];
out[1] = DotProduct(in, aliastransform[1]) + aliastransform[1][3];
out[2] = DotProduct(in, aliastransform[2]) + aliastransform[2][3];
}
 
 
/*
================
R_AliasPreparePoints
 
General clipped case
================
*/
void R_AliasPreparePoints (void)
{
int i;
stvert_t *pstverts;
finalvert_t *fv;
auxvert_t *av;
mtriangle_t *ptri;
finalvert_t *pfv[3];
 
pstverts = (stvert_t *)((byte *)paliashdr + paliashdr->stverts);
r_anumverts = pmdl->numverts;
fv = pfinalverts;
av = pauxverts;
 
for (i=0 ; i<r_anumverts ; i++, fv++, av++, r_apverts++, pstverts++)
{
R_AliasTransformFinalVert (fv, av, r_apverts, pstverts);
if (av->fv[2] < ALIAS_Z_CLIP_PLANE)
fv->flags |= ALIAS_Z_CLIP;
else
{
R_AliasProjectFinalVert (fv, av);
 
if (fv->v[0] < r_refdef.aliasvrect.x)
fv->flags |= ALIAS_LEFT_CLIP;
if (fv->v[1] < r_refdef.aliasvrect.y)
fv->flags |= ALIAS_TOP_CLIP;
if (fv->v[0] > r_refdef.aliasvrectright)
fv->flags |= ALIAS_RIGHT_CLIP;
if (fv->v[1] > r_refdef.aliasvrectbottom)
fv->flags |= ALIAS_BOTTOM_CLIP;
}
}
 
//
// clip and draw all triangles
//
r_affinetridesc.numtriangles = 1;
 
ptri = (mtriangle_t *)((byte *)paliashdr + paliashdr->triangles);
for (i=0 ; i<pmdl->numtris ; i++, ptri++)
{
pfv[0] = &pfinalverts[ptri->vertindex[0]];
pfv[1] = &pfinalverts[ptri->vertindex[1]];
pfv[2] = &pfinalverts[ptri->vertindex[2]];
 
if ( pfv[0]->flags & pfv[1]->flags & pfv[2]->flags & (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP) )
continue; // completely clipped
if ( ! ( (pfv[0]->flags | pfv[1]->flags | pfv[2]->flags) &
(ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP) ) )
{ // totally unclipped
r_affinetridesc.pfinalverts = pfinalverts;
r_affinetridesc.ptriangles = ptri;
D_PolysetDraw ();
}
else
{ // partially clipped
R_AliasClipTriangle (ptri);
}
}
}
 
 
/*
================
R_AliasSetUpTransform
================
*/
void R_AliasSetUpTransform (int trivial_accept)
{
int i;
float rotationmatrix[3][4], t2matrix[3][4];
static float tmatrix[3][4];
static float viewmatrix[3][4];
vec3_t angles;
 
// TODO: should really be stored with the entity instead of being reconstructed
// TODO: should use a look-up table
// TODO: could cache lazily, stored in the entity
 
angles[ROLL] = currententity->angles[ROLL];
angles[PITCH] = -currententity->angles[PITCH];
angles[YAW] = currententity->angles[YAW];
AngleVectors (angles, alias_forward, alias_right, alias_up);
 
tmatrix[0][0] = pmdl->scale[0];
tmatrix[1][1] = pmdl->scale[1];
tmatrix[2][2] = pmdl->scale[2];
 
tmatrix[0][3] = pmdl->scale_origin[0];
tmatrix[1][3] = pmdl->scale_origin[1];
tmatrix[2][3] = pmdl->scale_origin[2];
 
// TODO: can do this with simple matrix rearrangement
 
for (i=0 ; i<3 ; i++)
{
t2matrix[i][0] = alias_forward[i];
t2matrix[i][1] = -alias_right[i];
t2matrix[i][2] = alias_up[i];
}
 
t2matrix[0][3] = -modelorg[0];
t2matrix[1][3] = -modelorg[1];
t2matrix[2][3] = -modelorg[2];
 
// FIXME: can do more efficiently than full concatenation
R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix);
 
// TODO: should be global, set when vright, etc., set
VectorCopy (vright, viewmatrix[0]);
VectorCopy (vup, viewmatrix[1]);
VectorInverse (viewmatrix[1]);
VectorCopy (vpn, viewmatrix[2]);
 
// viewmatrix[0][3] = 0;
// viewmatrix[1][3] = 0;
// viewmatrix[2][3] = 0;
 
R_ConcatTransforms (viewmatrix, rotationmatrix, aliastransform);
 
// do the scaling up of x and y to screen coordinates as part of the transform
// for the unclipped case (it would mess up clipping in the clipped case).
// Also scale down z, so 1/z is scaled 31 bits for free, and scale down x and y
// correspondingly so the projected x and y come out right
// FIXME: make this work for clipped case too?
if (trivial_accept)
{
for (i=0 ; i<4 ; i++)
{
aliastransform[0][i] *= aliasxscale *
(1.0 / ((float)0x8000 * 0x10000));
aliastransform[1][i] *= aliasyscale *
(1.0 / ((float)0x8000 * 0x10000));
aliastransform[2][i] *= 1.0 / ((float)0x8000 * 0x10000);
 
}
}
}
 
 
/*
================
R_AliasTransformFinalVert
================
*/
void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av,
trivertx_t *pverts, stvert_t *pstverts)
{
int temp;
float lightcos, *plightnormal;
 
av->fv[0] = DotProduct(pverts->v, aliastransform[0]) +
aliastransform[0][3];
av->fv[1] = DotProduct(pverts->v, aliastransform[1]) +
aliastransform[1][3];
av->fv[2] = DotProduct(pverts->v, aliastransform[2]) +
aliastransform[2][3];
 
fv->v[2] = pstverts->s;
fv->v[3] = pstverts->t;
 
fv->flags = pstverts->onseam;
 
// lighting
plightnormal = r_avertexnormals[pverts->lightnormalindex];
lightcos = DotProduct (plightnormal, r_plightvec);
temp = r_ambientlight;
 
if (lightcos < 0)
{
temp += (int)(r_shadelight * lightcos);
 
// clamp; because we limited the minimum ambient and shading light, we
// don't have to clamp low light, just bright
if (temp < 0)
temp = 0;
}
 
fv->v[4] = temp;
}
 
 
#if !id386
 
/*
================
R_AliasTransformAndProjectFinalVerts
================
*/
void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv, stvert_t *pstverts)
{
int i, temp;
float lightcos, *plightnormal, zi;
trivertx_t *pverts;
 
pverts = r_apverts;
 
for (i=0 ; i<r_anumverts ; i++, fv++, pverts++, pstverts++)
{
// transform and project
zi = 1.0 / (DotProduct(pverts->v, aliastransform[2]) +
aliastransform[2][3]);
 
// x, y, and z are scaled down by 1/2**31 in the transform, so 1/z is
// scaled up by 1/2**31, and the scaling cancels out for x and y in the
// projection
fv->v[5] = zi;
 
fv->v[0] = ((DotProduct(pverts->v, aliastransform[0]) +
aliastransform[0][3]) * zi) + aliasxcenter;
fv->v[1] = ((DotProduct(pverts->v, aliastransform[1]) +
aliastransform[1][3]) * zi) + aliasycenter;
 
fv->v[2] = pstverts->s;
fv->v[3] = pstverts->t;
fv->flags = pstverts->onseam;
 
// lighting
plightnormal = r_avertexnormals[pverts->lightnormalindex];
lightcos = DotProduct (plightnormal, r_plightvec);
temp = r_ambientlight;
 
if (lightcos < 0)
{
temp += (int)(r_shadelight * lightcos);
 
// clamp; because we limited the minimum ambient and shading light, we
// don't have to clamp low light, just bright
if (temp < 0)
temp = 0;
}
 
fv->v[4] = temp;
}
}
 
#endif
 
 
/*
================
R_AliasProjectFinalVert
================
*/
void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av)
{
float zi;
 
// project points
zi = 1.0 / av->fv[2];
 
fv->v[5] = zi * ziscale;
 
fv->v[0] = (av->fv[0] * aliasxscale * zi) + aliasxcenter;
fv->v[1] = (av->fv[1] * aliasyscale * zi) + aliasycenter;
}
 
 
/*
================
R_AliasPrepareUnclippedPoints
================
*/
void R_AliasPrepareUnclippedPoints (void)
{
stvert_t *pstverts;
finalvert_t *fv;
 
pstverts = (stvert_t *)((byte *)paliashdr + paliashdr->stverts);
r_anumverts = pmdl->numverts;
// FIXME: just use pfinalverts directly?
fv = pfinalverts;
 
R_AliasTransformAndProjectFinalVerts (fv, pstverts);
 
if (r_affinetridesc.drawtype)
D_PolysetDrawFinalVerts (fv, r_anumverts);
 
r_affinetridesc.pfinalverts = pfinalverts;
r_affinetridesc.ptriangles = (mtriangle_t *)
((byte *)paliashdr + paliashdr->triangles);
r_affinetridesc.numtriangles = pmdl->numtris;
 
D_PolysetDraw ();
}
 
/*
===============
R_AliasSetupSkin
===============
*/
void R_AliasSetupSkin (void)
{
int skinnum;
int i, numskins;
maliasskingroup_t *paliasskingroup;
float *pskinintervals, fullskininterval;
float skintargettime, skintime;
 
skinnum = currententity->skinnum;
if ((skinnum >= pmdl->numskins) || (skinnum < 0))
{
Con_DPrintf ("R_AliasSetupSkin: no such skin # %d\n", skinnum);
skinnum = 0;
}
 
pskindesc = ((maliasskindesc_t *)
((byte *)paliashdr + paliashdr->skindesc)) + skinnum;
a_skinwidth = pmdl->skinwidth;
 
if (pskindesc->type == ALIAS_SKIN_GROUP)
{
paliasskingroup = (maliasskingroup_t *)((byte *)paliashdr +
pskindesc->skin);
pskinintervals = (float *)
((byte *)paliashdr + paliasskingroup->intervals);
numskins = paliasskingroup->numskins;
fullskininterval = pskinintervals[numskins-1];
skintime = cl.time + currententity->syncbase;
// when loading in Mod_LoadAliasSkinGroup, we guaranteed all interval
// values are positive, so we don't have to worry about division by 0
skintargettime = skintime -
((int)(skintime / fullskininterval)) * fullskininterval;
for (i=0 ; i<(numskins-1) ; i++)
{
if (pskinintervals[i] > skintargettime)
break;
}
pskindesc = &paliasskingroup->skindescs[i];
}
 
r_affinetridesc.pskindesc = pskindesc;
r_affinetridesc.pskin = (void *)((byte *)paliashdr + pskindesc->skin);
r_affinetridesc.skinwidth = a_skinwidth;
r_affinetridesc.seamfixupX16 = (a_skinwidth >> 1) << 16;
r_affinetridesc.skinheight = pmdl->skinheight;
}
 
/*
================
R_AliasSetupLighting
================
*/
void R_AliasSetupLighting (alight_t *plighting)
{
 
// guarantee that no vertex will ever be lit below LIGHT_MIN, so we don't have
// to clamp off the bottom
r_ambientlight = plighting->ambientlight;
 
if (r_ambientlight < LIGHT_MIN)
r_ambientlight = LIGHT_MIN;
 
r_ambientlight = (255 - r_ambientlight) << VID_CBITS;
 
if (r_ambientlight < LIGHT_MIN)
r_ambientlight = LIGHT_MIN;
 
r_shadelight = plighting->shadelight;
 
if (r_shadelight < 0)
r_shadelight = 0;
 
r_shadelight *= VID_GRADES;
 
// rotate the lighting vector into the model's frame of reference
r_plightvec[0] = DotProduct (plighting->plightvec, alias_forward);
r_plightvec[1] = -DotProduct (plighting->plightvec, alias_right);
r_plightvec[2] = DotProduct (plighting->plightvec, alias_up);
}
 
/*
=================
R_AliasSetupFrame
 
set r_apverts
=================
*/
void R_AliasSetupFrame (void)
{
int frame;
int i, numframes;
maliasgroup_t *paliasgroup;
float *pintervals, fullinterval, targettime, time;
 
frame = currententity->frame;
if ((frame >= pmdl->numframes) || (frame < 0))
{
Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
frame = 0;
}
 
if (paliashdr->frames[frame].type == ALIAS_SINGLE)
{
r_apverts = (trivertx_t *)
((byte *)paliashdr + paliashdr->frames[frame].frame);
return;
}
paliasgroup = (maliasgroup_t *)
((byte *)paliashdr + paliashdr->frames[frame].frame);
pintervals = (float *)((byte *)paliashdr + paliasgroup->intervals);
numframes = paliasgroup->numframes;
fullinterval = pintervals[numframes-1];
 
time = cl.time + currententity->syncbase;
 
//
// when loading in Mod_LoadAliasGroup, we guaranteed all interval values
// are positive, so we don't have to worry about division by 0
//
targettime = time - ((int)(time / fullinterval)) * fullinterval;
 
for (i=0 ; i<(numframes-1) ; i++)
{
if (pintervals[i] > targettime)
break;
}
 
r_apverts = (trivertx_t *)
((byte *)paliashdr + paliasgroup->frames[i].frame);
}
 
 
/*
================
R_AliasDrawModel
================
*/
void R_AliasDrawModel (alight_t *plighting)
{
finalvert_t finalverts[MAXALIASVERTS +
((CACHE_SIZE - 1) / sizeof(finalvert_t)) + 1];
auxvert_t auxverts[MAXALIASVERTS];
 
r_amodels_drawn++;
 
// cache align
pfinalverts = (finalvert_t *)
(((long)&finalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
pauxverts = &auxverts[0];
 
paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model);
pmdl = (mdl_t *)((byte *)paliashdr + paliashdr->model);
 
R_AliasSetupSkin ();
R_AliasSetUpTransform (currententity->trivial_accept);
R_AliasSetupLighting (plighting);
R_AliasSetupFrame ();
 
if (!currententity->colormap)
Sys_Error ("R_AliasDrawModel: !currententity->colormap");
 
r_affinetridesc.drawtype = (currententity->trivial_accept == 3) &&
r_recursiveaffinetriangles;
 
if (r_affinetridesc.drawtype)
{
D_PolysetUpdateTables (); // FIXME: precalc...
}
else
{
#if id386
D_Aff8Patch (currententity->colormap);
#endif
}
 
acolormap = currententity->colormap;
 
if (currententity != &cl.viewent)
ziscale = (float)0x8000 * (float)0x10000;
else
ziscale = (float)0x8000 * (float)0x10000 * 3.0;
 
if (currententity->trivial_accept)
R_AliasPrepareUnclippedPoints ();
else
R_AliasPreparePoints ();
}
 
/contrib/other/sdlquake-1.0.9/r_aliasa.S
0,0 → 1,237
/*
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_aliasa.s
// x86 assembly-language Alias model transform and project code.
//
 
#include "asm_i386.h"
#include "quakeasm.h"
#include "asm_draw.h"
#include "d_ifacea.h"
 
#if id386
 
.data
 
Lfloat_1: .single 1.0
Ltemp: .long 0
Lcoords: .long 0, 0, 0
 
.text
 
#define fv 12+4
#define pstverts 12+8
 
.globl C(R_AliasTransformAndProjectFinalVerts)
C(R_AliasTransformAndProjectFinalVerts):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
 
// int i, temp;
// float lightcos, *plightnormal, zi;
// trivertx_t *pverts;
 
// pverts = r_apverts;
movl C(r_apverts),%esi
 
// for (i=0 ; i<r_anumverts ; i++, fv++, pverts++, pstverts++)
// {
movl pstverts(%esp),%ebp
movl fv(%esp),%edi
movl C(r_anumverts),%ecx
subl %edx,%edx
 
Lloop:
 
// // transform and project
// zi = 1.0 / (DotProduct(pverts->v, aliastransform[2]) +
// aliastransform[2][3]);
movb (%esi),%dl
movb %dl,Lcoords
fildl Lcoords // v[0]
movb 1(%esi),%dl
movb %dl,Lcoords+4
fildl Lcoords+4 // v[1] | v[0]
movb 2(%esi),%dl
movb %dl,Lcoords+8
fildl Lcoords+8 // v[2] | v[1] | v[0]
 
fld %st(2) // v[0] | v[2] | v[1] | v[0]
fmuls C(aliastransform)+32 // accum | v[2] | v[1] | v[0]
fld %st(2) // v[1] | accum | v[2] | v[1] | v[0]
fmuls C(aliastransform)+36 // accum2 | accum | v[2] | v[1] | v[0]
fxch %st(1) // accum | accum2 | v[2] | v[1] | v[0]
fadds C(aliastransform)+44 // accum | accum2 | v[2] | v[1] | v[0]
fld %st(2) // v[2] | accum | accum2 | v[2] | v[1] | v[0]
fmuls C(aliastransform)+40 // accum3 | accum | accum2 | v[2] | v[1] |
// v[0]
fxch %st(1) // accum | accum3 | accum2 | v[2] | v[1] | v[0]
faddp %st(0),%st(2) // accum3 | accum | v[2] | v[1] | v[0]
movb tv_lightnormalindex(%esi),%dl
movl stv_s(%ebp),%eax
movl %eax,fv_v+8(%edi)
faddp %st(0),%st(1) // z | v[2] | v[1] | v[0]
 
movl stv_t(%ebp),%eax
movl %eax,fv_v+12(%edi)
 
// // lighting
// plightnormal = r_avertexnormals[pverts->lightnormalindex];
 
fdivrs Lfloat_1 // zi | v[2] | v[1] | v[0]
 
// fv->v[2] = pstverts->s;
// fv->v[3] = pstverts->t;
// fv->flags = pstverts->onseam;
movl stv_onseam(%ebp),%eax
movl %eax,fv_flags(%edi)
 
movl fv_size(%edi),%eax
movl stv_size(%ebp),%eax
movl 4(%esi),%eax
 
leal (%edx,%edx,2),%eax // index*3
 
fxch %st(3) // v[0] | v[2] | v[1] | zi
 
// lightcos = DotProduct (plightnormal, r_plightvec);
flds C(r_avertexnormals)(,%eax,4)
fmuls C(r_plightvec)
flds C(r_avertexnormals)+4(,%eax,4)
fmuls C(r_plightvec)+4
flds C(r_avertexnormals)+8(,%eax,4)
fmuls C(r_plightvec)+8
fxch %st(1)
faddp %st(0),%st(2)
fld %st(2) // v[0] | laccum | laccum2 | v[0] | v[2] |
// v[1] | zi
fmuls C(aliastransform)+0 // xaccum | laccum | laccum2 | v[0] | v[2] |
// v[1] | zi
fxch %st(2) // laccum2 | laccum | xaccum | v[0] | v[2] |
// v[1] | zi
faddp %st(0),%st(1) // laccum | xaccum | v[0] | v[2] | v[1] | zi
 
// temp = r_ambientlight;
// if (lightcos < 0)
// {
fsts Ltemp
movl C(r_ambientlight),%eax
movb Ltemp+3,%dl
testb $0x80,%dl
jz Lsavelight // no need to clamp if only ambient lit, because
// r_ambientlight is preclamped
 
// temp += (int)(r_shadelight * lightcos);
fmuls C(r_shadelight)
// FIXME: fast float->int conversion?
fistpl Ltemp
addl Ltemp,%eax
 
// // clamp; because we limited the minimum ambient and shading light, we
// // don't have to clamp low light, just bright
// if (temp < 0)
// temp = 0;
jns Lp1
subl %eax,%eax
 
// }
 
Lp1:
 
// fv->v[4] = temp;
//
// // x, y, and z are scaled down by 1/2**31 in the transform, so 1/z is
// // scaled up by 1/2**31, and the scaling cancels out for x and y in the
// // projection
// fv->v[0] = ((DotProduct(pverts->v, aliastransform[0]) +
// aliastransform[0][3]) * zi) + aliasxcenter;
// fv->v[1] = ((DotProduct(pverts->v, aliastransform[1]) +
// aliastransform[1][3]) * zi) + aliasycenter;
// fv->v[5] = zi;
fxch %st(1) // v[0] | xaccum | v[2] | v[1] | zi
fmuls C(aliastransform)+16 // yaccum | xaccum | v[2] | v[1] | zi
fxch %st(3) // v[1] | xaccum | v[2] | yaccum | zi
fld %st(0) // v[1] | v[1] | xaccum | v[2] | yaccum | zi
fmuls C(aliastransform)+4 // xaccum2 | v[1] | xaccum | v[2] | yaccum |zi
fxch %st(1) // v[1] | xaccum2 | xaccum | v[2] | yaccum |zi
movl %eax,fv_v+16(%edi)
fmuls C(aliastransform)+20 // yaccum2 | xaccum2 | xaccum | v[2] | yaccum|
// zi
fxch %st(2) // xaccum | xaccum2 | yaccum2 | v[2] | yaccum|
// zi
fadds C(aliastransform)+12 // xaccum | xaccum2 | yaccum2 | v[2] | yaccum|
// zi
fxch %st(4) // yaccum | xaccum2 | yaccum2 | v[2] | xaccum|
// zi
fadds C(aliastransform)+28 // yaccum | xaccum2 | yaccum2 | v[2] | xaccum|
// zi
fxch %st(3) // v[2] | xaccum2 | yaccum2 | yaccum | xaccum|
// zi
fld %st(0) // v[2] | v[2] | xaccum2 | yaccum2 | yaccum |
// xaccum | zi
fmuls C(aliastransform)+8 // xaccum3 | v[2] | xaccum2 | yaccum2 |yaccum|
// xaccum | zi
fxch %st(1) // v[2] | xaccum3 | xaccum2 | yaccum2 |yaccum|
// xaccum | zi
fmuls C(aliastransform)+24 // yaccum3 | xaccum3 | xaccum2 | yaccum2 |
// yaccum | xaccum | zi
fxch %st(5) // xaccum | xaccum3 | xaccum2 | yaccum2 |
// yaccum | yaccum3 | zi
faddp %st(0),%st(2) // xaccum3 | xaccum | yaccum2 | yaccum |
// yaccum3 | zi
fxch %st(3) // yaccum | xaccum | yaccum2 | xaccum3 |
// yaccum3 | zi
faddp %st(0),%st(2) // xaccum | yaccum | xaccum3 | yaccum3 | zi
addl $(tv_size),%esi
faddp %st(0),%st(2) // yaccum | x | yaccum3 | zi
faddp %st(0),%st(2) // x | y | zi
addl $(stv_size),%ebp
fmul %st(2),%st(0) // x/z | y | zi
fxch %st(1) // y | x/z | zi
fmul %st(2),%st(0) // y/z | x/z | zi
fxch %st(1) // x/z | y/z | zi
fadds C(aliasxcenter) // u | y/z | zi
fxch %st(1) // y/z | u | zi
fadds C(aliasycenter) // v | u | zi
fxch %st(2) // zi | u | v
// FIXME: fast float->int conversion?
fistpl fv_v+20(%edi) // u | v
fistpl fv_v+0(%edi) // v
fistpl fv_v+4(%edi)
 
// }
 
addl $(fv_size),%edi
decl %ecx
jnz Lloop
 
popl %esi // restore register variables
popl %edi
popl %ebp // restore the caller's stack frame
ret
 
Lsavelight:
fstp %st(0)
jmp Lp1
 
#endif // id386
 
/contrib/other/sdlquake-1.0.9/r_bsp.c
0,0 → 1,674
/*
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_bsp.c
 
#include "quakedef.h"
#include "r_local.h"
 
//
// current entity info
//
qboolean insubmodel;
entity_t *currententity;
vec3_t modelorg, base_modelorg;
// modelorg is the viewpoint reletive to
// the currently rendering entity
vec3_t r_entorigin; // the currently rendering entity in world
// coordinates
 
float entity_rotation[3][3];
 
vec3_t r_worldmodelorg;
 
int r_currentbkey;
 
typedef enum {touchessolid, drawnode, nodrawnode} solidstate_t;
 
#define MAX_BMODEL_VERTS 500 // 6K
#define MAX_BMODEL_EDGES 1000 // 12K
 
static mvertex_t *pbverts;
static bedge_t *pbedges;
static int numbverts, numbedges;
 
static mvertex_t *pfrontenter, *pfrontexit;
 
static qboolean makeclippededge;
 
 
//===========================================================================
 
/*
================
R_EntityRotate
================
*/
void R_EntityRotate (vec3_t vec)
{
vec3_t tvec;
 
VectorCopy (vec, tvec);
vec[0] = DotProduct (entity_rotation[0], tvec);
vec[1] = DotProduct (entity_rotation[1], tvec);
vec[2] = DotProduct (entity_rotation[2], tvec);
}
 
 
/*
================
R_RotateBmodel
================
*/
void R_RotateBmodel (void)
{
float angle, s, c, temp1[3][3], temp2[3][3], temp3[3][3];
 
// TODO: should use a look-up table
// TODO: should really be stored with the entity instead of being reconstructed
// TODO: could cache lazily, stored in the entity
// TODO: share work with R_SetUpAliasTransform
 
// yaw
angle = currententity->angles[YAW];
angle = angle * M_PI*2 / 360;
s = sin(angle);
c = cos(angle);
 
temp1[0][0] = c;
temp1[0][1] = s;
temp1[0][2] = 0;
temp1[1][0] = -s;
temp1[1][1] = c;
temp1[1][2] = 0;
temp1[2][0] = 0;
temp1[2][1] = 0;
temp1[2][2] = 1;
 
 
// pitch
angle = currententity->angles[PITCH];
angle = angle * M_PI*2 / 360;
s = sin(angle);
c = cos(angle);
 
temp2[0][0] = c;
temp2[0][1] = 0;
temp2[0][2] = -s;
temp2[1][0] = 0;
temp2[1][1] = 1;
temp2[1][2] = 0;
temp2[2][0] = s;
temp2[2][1] = 0;
temp2[2][2] = c;
 
R_ConcatRotations (temp2, temp1, temp3);
 
// roll
angle = currententity->angles[ROLL];
angle = angle * M_PI*2 / 360;
s = sin(angle);
c = cos(angle);
 
temp1[0][0] = 1;
temp1[0][1] = 0;
temp1[0][2] = 0;
temp1[1][0] = 0;
temp1[1][1] = c;
temp1[1][2] = s;
temp1[2][0] = 0;
temp1[2][1] = -s;
temp1[2][2] = c;
 
R_ConcatRotations (temp1, temp3, entity_rotation);
 
//
// rotate modelorg and the transformation matrix
//
R_EntityRotate (modelorg);
R_EntityRotate (vpn);
R_EntityRotate (vright);
R_EntityRotate (vup);
 
R_TransformFrustum ();
}
 
 
/*
================
R_RecursiveClipBPoly
================
*/
void R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf)
{
bedge_t *psideedges[2], *pnextedge, *ptedge;
int i, side, lastside;
float dist, frac, lastdist;
mplane_t *splitplane, tplane;
mvertex_t *pvert, *plastvert, *ptvert;
mnode_t *pn;
 
psideedges[0] = psideedges[1] = NULL;
 
makeclippededge = false;
 
// transform the BSP plane into model space
// FIXME: cache these?
splitplane = pnode->plane;
tplane.dist = splitplane->dist -
DotProduct(r_entorigin, splitplane->normal);
tplane.normal[0] = DotProduct (entity_rotation[0], splitplane->normal);
tplane.normal[1] = DotProduct (entity_rotation[1], splitplane->normal);
tplane.normal[2] = DotProduct (entity_rotation[2], splitplane->normal);
 
// clip edges to BSP plane
for ( ; pedges ; pedges = pnextedge)
{
pnextedge = pedges->pnext;
 
// set the status for the last point as the previous point
// FIXME: cache this stuff somehow?
plastvert = pedges->v[0];
lastdist = DotProduct (plastvert->position, tplane.normal) -
tplane.dist;
 
if (lastdist > 0)
lastside = 0;
else
lastside = 1;
 
pvert = pedges->v[1];
 
dist = DotProduct (pvert->position, tplane.normal) - tplane.dist;
 
if (dist > 0)
side = 0;
else
side = 1;
 
if (side != lastside)
{
// clipped
if (numbverts >= MAX_BMODEL_VERTS)
return;
 
// generate the clipped vertex
frac = lastdist / (lastdist - dist);
ptvert = &pbverts[numbverts++];
ptvert->position[0] = plastvert->position[0] +
frac * (pvert->position[0] -
plastvert->position[0]);
ptvert->position[1] = plastvert->position[1] +
frac * (pvert->position[1] -
plastvert->position[1]);
ptvert->position[2] = plastvert->position[2] +
frac * (pvert->position[2] -
plastvert->position[2]);
 
// split into two edges, one on each side, and remember entering
// and exiting points
// FIXME: share the clip edge by having a winding direction flag?
if (numbedges >= (MAX_BMODEL_EDGES - 1))
{
Con_Printf ("Out of edges for bmodel\n");
return;
}
 
ptedge = &pbedges[numbedges];
ptedge->pnext = psideedges[lastside];
psideedges[lastside] = ptedge;
ptedge->v[0] = plastvert;
ptedge->v[1] = ptvert;
 
ptedge = &pbedges[numbedges + 1];
ptedge->pnext = psideedges[side];
psideedges[side] = ptedge;
ptedge->v[0] = ptvert;
ptedge->v[1] = pvert;
 
numbedges += 2;
 
if (side == 0)
{
// entering for front, exiting for back
pfrontenter = ptvert;
makeclippededge = true;
}
else
{
pfrontexit = ptvert;
makeclippededge = true;
}
}
else
{
// add the edge to the appropriate side
pedges->pnext = psideedges[side];
psideedges[side] = pedges;
}
}
 
// if anything was clipped, reconstitute and add the edges along the clip
// plane to both sides (but in opposite directions)
if (makeclippededge)
{
if (numbedges >= (MAX_BMODEL_EDGES - 2))
{
Con_Printf ("Out of edges for bmodel\n");
return;
}
 
ptedge = &pbedges[numbedges];
ptedge->pnext = psideedges[0];
psideedges[0] = ptedge;
ptedge->v[0] = pfrontexit;
ptedge->v[1] = pfrontenter;
 
ptedge = &pbedges[numbedges + 1];
ptedge->pnext = psideedges[1];
psideedges[1] = ptedge;
ptedge->v[0] = pfrontenter;
ptedge->v[1] = pfrontexit;
 
numbedges += 2;
}
 
// draw or recurse further
for (i=0 ; i<2 ; i++)
{
if (psideedges[i])
{
// draw if we've reached a non-solid leaf, done if all that's left is a
// solid leaf, and continue down the tree if it's not a leaf
pn = pnode->children[i];
 
// we're done with this branch if the node or leaf isn't in the PVS
if (pn->visframe == r_visframecount)
{
if (pn->contents < 0)
{
if (pn->contents != CONTENTS_SOLID)
{
r_currentbkey = ((mleaf_t *)pn)->key;
R_RenderBmodelFace (psideedges[i], psurf);
}
}
else
{
R_RecursiveClipBPoly (psideedges[i], pnode->children[i],
psurf);
}
}
}
}
}
 
 
/*
================
R_DrawSolidClippedSubmodelPolygons
================
*/
void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel)
{
int i, j, lindex;
vec_t dot;
msurface_t *psurf;
int numsurfaces;
mplane_t *pplane;
mvertex_t bverts[MAX_BMODEL_VERTS];
bedge_t bedges[MAX_BMODEL_EDGES], *pbedge;
medge_t *pedge, *pedges;
 
// FIXME: use bounding-box-based frustum clipping info?
 
psurf = &pmodel->surfaces[pmodel->firstmodelsurface];
numsurfaces = pmodel->nummodelsurfaces;
pedges = pmodel->edges;
 
for (i=0 ; i<numsurfaces ; i++, psurf++)
{
// find which side of the node we are on
pplane = psurf->plane;
 
dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
 
// draw the polygon
if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
{
// FIXME: use bounding-box-based frustum clipping info?
 
// copy the edges to bedges, flipping if necessary so always
// clockwise winding
// FIXME: if edges and vertices get caches, these assignments must move
// outside the loop, and overflow checking must be done here
pbverts = bverts;
pbedges = bedges;
numbverts = numbedges = 0;
 
if (psurf->numedges > 0)
{
pbedge = &bedges[numbedges];
numbedges += psurf->numedges;
 
for (j=0 ; j<psurf->numedges ; j++)
{
lindex = pmodel->surfedges[psurf->firstedge+j];
 
if (lindex > 0)
{
pedge = &pedges[lindex];
pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[0]];
pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[1]];
}
else
{
lindex = -lindex;
pedge = &pedges[lindex];
pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[1]];
pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[0]];
}
 
pbedge[j].pnext = &pbedge[j+1];
}
 
pbedge[j-1].pnext = NULL; // mark end of edges
 
R_RecursiveClipBPoly (pbedge, currententity->topnode, psurf);
}
else
{
Sys_Error ("no edges in bmodel");
}
}
}
}
 
 
/*
================
R_DrawSubmodelPolygons
================
*/
void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags)
{
int i;
vec_t dot;
msurface_t *psurf;
int numsurfaces;
mplane_t *pplane;
 
// FIXME: use bounding-box-based frustum clipping info?
 
psurf = &pmodel->surfaces[pmodel->firstmodelsurface];
numsurfaces = pmodel->nummodelsurfaces;
 
for (i=0 ; i<numsurfaces ; i++, psurf++)
{
// find which side of the node we are on
pplane = psurf->plane;
 
dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
 
// draw the polygon
if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
{
r_currentkey = ((mleaf_t *)currententity->topnode)->key;
 
// FIXME: use bounding-box-based frustum clipping info?
R_RenderFace (psurf, clipflags);
}
}
}
 
 
/*
================
R_RecursiveWorldNode
================
*/
void R_RecursiveWorldNode (mnode_t *node, int clipflags)
{
int i, c, side, *pindex;
vec3_t acceptpt, rejectpt;
mplane_t *plane;
msurface_t *surf, **mark;
mleaf_t *pleaf;
double d, dot;
 
if (node->contents == CONTENTS_SOLID)
return; // solid
 
if (node->visframe != r_visframecount)
return;
 
// cull the clipping planes if not trivial accept
// FIXME: the compiler is doing a lousy job of optimizing here; it could be
// twice as fast in ASM
if (clipflags)
{
for (i=0 ; i<4 ; i++)
{
if (! (clipflags & (1<<i)) )
continue; // don't need to clip against it
 
// generate accept and reject points
// FIXME: do with fast look-ups or integer tests based on the sign bit
// of the floating point values
 
pindex = pfrustum_indexes[i];
 
rejectpt[0] = (float)node->minmaxs[pindex[0]];
rejectpt[1] = (float)node->minmaxs[pindex[1]];
rejectpt[2] = (float)node->minmaxs[pindex[2]];
d = DotProduct (rejectpt, view_clipplanes[i].normal);
d -= view_clipplanes[i].dist;
 
if (d <= 0)
return;
 
acceptpt[0] = (float)node->minmaxs[pindex[3+0]];
acceptpt[1] = (float)node->minmaxs[pindex[3+1]];
acceptpt[2] = (float)node->minmaxs[pindex[3+2]];
 
d = DotProduct (acceptpt, view_clipplanes[i].normal);
d -= view_clipplanes[i].dist;
 
if (d >= 0)
clipflags &= ~(1<<i); // node is entirely on screen
}
}
// if a leaf node, draw stuff
if (node->contents < 0)
{
pleaf = (mleaf_t *)node;
 
mark = pleaf->firstmarksurface;
c = pleaf->nummarksurfaces;
 
if (c)
{
do
{
(*mark)->visframe = r_framecount;
mark++;
} while (--c);
}
 
// deal with model fragments in this leaf
if (pleaf->efrags)
{
R_StoreEfrags (&pleaf->efrags);
}
 
pleaf->key = r_currentkey;
r_currentkey++; // all bmodels in a leaf share the same key
}
else
{
// node is just a decision point, so go down the apropriate sides
 
// find which side of the node we are on
plane = node->plane;
 
switch (plane->type)
{
case PLANE_X:
dot = modelorg[0] - plane->dist;
break;
case PLANE_Y:
dot = modelorg[1] - plane->dist;
break;
case PLANE_Z:
dot = modelorg[2] - plane->dist;
break;
default:
dot = DotProduct (modelorg, plane->normal) - plane->dist;
break;
}
if (dot >= 0)
side = 0;
else
side = 1;
 
// recurse down the children, front side first
R_RecursiveWorldNode (node->children[side], clipflags);
 
// draw stuff
c = node->numsurfaces;
 
if (c)
{
surf = cl.worldmodel->surfaces + node->firstsurface;
 
if (dot < -BACKFACE_EPSILON)
{
do
{
if ((surf->flags & SURF_PLANEBACK) &&
(surf->visframe == r_framecount))
{
if (r_drawpolys)
{
if (r_worldpolysbacktofront)
{
if (numbtofpolys < MAX_BTOFPOLYS)
{
pbtofpolys[numbtofpolys].clipflags =
clipflags;
pbtofpolys[numbtofpolys].psurf = surf;
numbtofpolys++;
}
}
else
{
R_RenderPoly (surf, clipflags);
}
}
else
{
R_RenderFace (surf, clipflags);
}
}
 
surf++;
} while (--c);
}
else if (dot > BACKFACE_EPSILON)
{
do
{
if (!(surf->flags & SURF_PLANEBACK) &&
(surf->visframe == r_framecount))
{
if (r_drawpolys)
{
if (r_worldpolysbacktofront)
{
if (numbtofpolys < MAX_BTOFPOLYS)
{
pbtofpolys[numbtofpolys].clipflags =
clipflags;
pbtofpolys[numbtofpolys].psurf = surf;
numbtofpolys++;
}
}
else
{
R_RenderPoly (surf, clipflags);
}
}
else
{
R_RenderFace (surf, clipflags);
}
}
 
surf++;
} while (--c);
}
 
// all surfaces on the same node share the same sequence number
r_currentkey++;
}
 
// recurse down the back side
R_RecursiveWorldNode (node->children[!side], clipflags);
}
}
 
 
 
/*
================
R_RenderWorld
================
*/
void R_RenderWorld (void)
{
int i;
model_t *clmodel;
btofpoly_t btofpolys[MAX_BTOFPOLYS];
 
pbtofpolys = btofpolys;
 
currententity = &cl_entities[0];
VectorCopy (r_origin, modelorg);
clmodel = currententity->model;
r_pcurrentvertbase = clmodel->vertexes;
 
R_RecursiveWorldNode (clmodel->nodes, 15);
 
// if the driver wants the polygons back to front, play the visible ones back
// in that order
if (r_worldpolysbacktofront)
{
for (i=numbtofpolys-1 ; i>=0 ; i--)
{
R_RenderPoly (btofpolys[i].psurf, btofpolys[i].clipflags);
}
}
}
 
 
/contrib/other/sdlquake-1.0.9/r_draw.c
0,0 → 1,908
/*
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_draw.c
 
#include "quakedef.h"
#include "r_local.h"
#include "d_local.h" // FIXME: shouldn't need to include this
 
#define MAXLEFTCLIPEDGES 100
 
// !!! if these are changed, they must be changed in asm_draw.h too !!!
#define FULLY_CLIPPED_CACHED 0x80000000
#define FRAMECOUNT_MASK 0x7FFFFFFF
 
unsigned int cacheoffset;
 
int c_faceclip; // number of faces clipped
 
zpointdesc_t r_zpointdesc;
 
polydesc_t r_polydesc;
 
 
 
clipplane_t *entity_clipplanes;
clipplane_t view_clipplanes[4];
clipplane_t world_clipplanes[16];
 
medge_t *r_pedge;
 
qboolean r_leftclipped, r_rightclipped;
static qboolean makeleftedge, makerightedge;
qboolean r_nearzionly;
 
int sintable[SIN_BUFFER_SIZE];
int intsintable[SIN_BUFFER_SIZE];
 
mvertex_t r_leftenter, r_leftexit;
mvertex_t r_rightenter, r_rightexit;
 
typedef struct
{
float u,v;
int ceilv;
} evert_t;
 
int r_emitted;
float r_nearzi;
float r_u1, r_v1, r_lzi1;
int r_ceilv1;
 
qboolean r_lastvertvalid;
 
 
#if !id386
 
/*
================
R_EmitEdge
================
*/
void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1)
{
edge_t *edge, *pcheck;
int u_check;
float u, u_step;
vec3_t local, transformed;
float *world;
int v, v2, ceilv0;
float scale, lzi0, u0, v0;
int side;
 
if (r_lastvertvalid)
{
u0 = r_u1;
v0 = r_v1;
lzi0 = r_lzi1;
ceilv0 = r_ceilv1;
}
else
{
world = &pv0->position[0];
// transform and project
VectorSubtract (world, modelorg, local);
TransformVector (local, transformed);
if (transformed[2] < NEAR_CLIP)
transformed[2] = NEAR_CLIP;
lzi0 = 1.0 / transformed[2];
// FIXME: build x/yscale into transform?
scale = xscale * lzi0;
u0 = (xcenter + scale*transformed[0]);
if (u0 < r_refdef.fvrectx_adj)
u0 = r_refdef.fvrectx_adj;
if (u0 > r_refdef.fvrectright_adj)
u0 = r_refdef.fvrectright_adj;
scale = yscale * lzi0;
v0 = (ycenter - scale*transformed[1]);
if (v0 < r_refdef.fvrecty_adj)
v0 = r_refdef.fvrecty_adj;
if (v0 > r_refdef.fvrectbottom_adj)
v0 = r_refdef.fvrectbottom_adj;
ceilv0 = (int) ceil(v0);
}
 
world = &pv1->position[0];
 
// transform and project
VectorSubtract (world, modelorg, local);
TransformVector (local, transformed);
 
if (transformed[2] < NEAR_CLIP)
transformed[2] = NEAR_CLIP;
 
r_lzi1 = 1.0 / transformed[2];
 
scale = xscale * r_lzi1;
r_u1 = (xcenter + scale*transformed[0]);
if (r_u1 < r_refdef.fvrectx_adj)
r_u1 = r_refdef.fvrectx_adj;
if (r_u1 > r_refdef.fvrectright_adj)
r_u1 = r_refdef.fvrectright_adj;
 
scale = yscale * r_lzi1;
r_v1 = (ycenter - scale*transformed[1]);
if (r_v1 < r_refdef.fvrecty_adj)
r_v1 = r_refdef.fvrecty_adj;
if (r_v1 > r_refdef.fvrectbottom_adj)
r_v1 = r_refdef.fvrectbottom_adj;
 
if (r_lzi1 > lzi0)
lzi0 = r_lzi1;
 
if (lzi0 > r_nearzi) // for mipmap finding
r_nearzi = lzi0;
 
// for right edges, all we want is the effect on 1/z
if (r_nearzionly)
return;
 
r_emitted = 1;
 
r_ceilv1 = (int) ceil(r_v1);
 
 
// create the edge
if (ceilv0 == r_ceilv1)
{
// we cache unclipped horizontal edges as fully clipped
if (cacheoffset != 0x7FFFFFFF)
{
cacheoffset = FULLY_CLIPPED_CACHED |
(r_framecount & FRAMECOUNT_MASK);
}
 
return; // horizontal edge
}
 
side = ceilv0 > r_ceilv1;
 
edge = edge_p++;
 
edge->owner = r_pedge;
 
edge->nearzi = lzi0;
 
if (side == 0)
{
// trailing edge (go from p1 to p2)
v = ceilv0;
v2 = r_ceilv1 - 1;
 
edge->surfs[0] = surface_p - surfaces;
edge->surfs[1] = 0;
 
u_step = ((r_u1 - u0) / (r_v1 - v0));
u = u0 + ((float)v - v0) * u_step;
}
else
{
// leading edge (go from p2 to p1)
v2 = ceilv0 - 1;
v = r_ceilv1;
 
edge->surfs[0] = 0;
edge->surfs[1] = surface_p - surfaces;
 
u_step = ((u0 - r_u1) / (v0 - r_v1));
u = r_u1 + ((float)v - r_v1) * u_step;
}
 
edge->u_step = u_step*0x100000;
edge->u = u*0x100000 + 0xFFFFF;
 
// we need to do this to avoid stepping off the edges if a very nearly
// horizontal edge is less than epsilon above a scan, and numeric error causes
// it to incorrectly extend to the scan, and the extension of the line goes off
// the edge of the screen
// FIXME: is this actually needed?
if (edge->u < r_refdef.vrect_x_adj_shift20)
edge->u = r_refdef.vrect_x_adj_shift20;
if (edge->u > r_refdef.vrectright_adj_shift20)
edge->u = r_refdef.vrectright_adj_shift20;
 
//
// sort the edge in normally
//
u_check = edge->u;
if (edge->surfs[0])
u_check++; // sort trailers after leaders
 
if (!newedges[v] || newedges[v]->u >= u_check)
{
edge->next = newedges[v];
newedges[v] = edge;
}
else
{
pcheck = newedges[v];
while (pcheck->next && pcheck->next->u < u_check)
pcheck = pcheck->next;
edge->next = pcheck->next;
pcheck->next = edge;
}
 
edge->nextremove = removeedges[v2];
removeedges[v2] = edge;
}
 
 
/*
================
R_ClipEdge
================
*/
void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip)
{
float d0, d1, f;
mvertex_t clipvert;
 
if (clip)
{
do
{
d0 = DotProduct (pv0->position, clip->normal) - clip->dist;
d1 = DotProduct (pv1->position, clip->normal) - clip->dist;
 
if (d0 >= 0)
{
// point 0 is unclipped
if (d1 >= 0)
{
// both points are unclipped
continue;
}
 
// only point 1 is clipped
 
// we don't cache clipped edges
cacheoffset = 0x7FFFFFFF;
 
f = d0 / (d0 - d1);
clipvert.position[0] = pv0->position[0] +
f * (pv1->position[0] - pv0->position[0]);
clipvert.position[1] = pv0->position[1] +
f * (pv1->position[1] - pv0->position[1]);
clipvert.position[2] = pv0->position[2] +
f * (pv1->position[2] - pv0->position[2]);
 
if (clip->leftedge)
{
r_leftclipped = true;
r_leftexit = clipvert;
}
else if (clip->rightedge)
{
r_rightclipped = true;
r_rightexit = clipvert;
}
 
R_ClipEdge (pv0, &clipvert, clip->next);
return;
}
else
{
// point 0 is clipped
if (d1 < 0)
{
// both points are clipped
// we do cache fully clipped edges
if (!r_leftclipped)
cacheoffset = FULLY_CLIPPED_CACHED |
(r_framecount & FRAMECOUNT_MASK);
return;
}
 
// only point 0 is clipped
r_lastvertvalid = false;
 
// we don't cache partially clipped edges
cacheoffset = 0x7FFFFFFF;
 
f = d0 / (d0 - d1);
clipvert.position[0] = pv0->position[0] +
f * (pv1->position[0] - pv0->position[0]);
clipvert.position[1] = pv0->position[1] +
f * (pv1->position[1] - pv0->position[1]);
clipvert.position[2] = pv0->position[2] +
f * (pv1->position[2] - pv0->position[2]);
 
if (clip->leftedge)
{
r_leftclipped = true;
r_leftenter = clipvert;
}
else if (clip->rightedge)
{
r_rightclipped = true;
r_rightenter = clipvert;
}
 
R_ClipEdge (&clipvert, pv1, clip->next);
return;
}
} while ((clip = clip->next) != NULL);
}
 
// add the edge
R_EmitEdge (pv0, pv1);
}
 
#endif // !id386
 
 
/*
================
R_EmitCachedEdge
================
*/
void R_EmitCachedEdge (void)
{
edge_t *pedge_t;
 
pedge_t = (edge_t *)((unsigned long)r_edges + r_pedge->cachededgeoffset);
 
if (!pedge_t->surfs[0])
pedge_t->surfs[0] = surface_p - surfaces;
else
pedge_t->surfs[1] = surface_p - surfaces;
 
if (pedge_t->nearzi > r_nearzi) // for mipmap finding
r_nearzi = pedge_t->nearzi;
 
r_emitted = 1;
}
 
 
/*
================
R_RenderFace
================
*/
void R_RenderFace (msurface_t *fa, int clipflags)
{
int i, lindex;
unsigned mask;
mplane_t *pplane;
float distinv;
vec3_t p_normal;
medge_t *pedges, tedge;
clipplane_t *pclip;
 
// skip out if no more surfs
if ((surface_p) >= surf_max)
{
r_outofsurfaces++;
return;
}
 
// ditto if not enough edges left, or switch to auxedges if possible
if ((edge_p + fa->numedges + 4) >= edge_max)
{
r_outofedges += fa->numedges;
return;
}
 
c_faceclip++;
 
// set up clip planes
pclip = NULL;
 
for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1)
{
if (clipflags & mask)
{
view_clipplanes[i].next = pclip;
pclip = &view_clipplanes[i];
}
}
 
// push the edges through
r_emitted = 0;
r_nearzi = 0;
r_nearzionly = false;
makeleftedge = makerightedge = false;
pedges = currententity->model->edges;
r_lastvertvalid = false;
 
for (i=0 ; i<fa->numedges ; i++)
{
lindex = currententity->model->surfedges[fa->firstedge + i];
 
if (lindex > 0)
{
r_pedge = &pedges[lindex];
 
// if the edge is cached, we can just reuse the edge
if (!insubmodel)
{
if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED)
{
if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) ==
r_framecount)
{
r_lastvertvalid = false;
continue;
}
}
else
{
if ((((unsigned long)edge_p - (unsigned long)r_edges) >
r_pedge->cachededgeoffset) &&
(((edge_t *)((unsigned long)r_edges +
r_pedge->cachededgeoffset))->owner == r_pedge))
{
R_EmitCachedEdge ();
r_lastvertvalid = false;
continue;
}
}
}
 
// assume it's cacheable
cacheoffset = (byte *)edge_p - (byte *)r_edges;
r_leftclipped = r_rightclipped = false;
R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[0]],
&r_pcurrentvertbase[r_pedge->v[1]],
pclip);
r_pedge->cachededgeoffset = cacheoffset;
 
if (r_leftclipped)
makeleftedge = true;
if (r_rightclipped)
makerightedge = true;
r_lastvertvalid = true;
}
else
{
lindex = -lindex;
r_pedge = &pedges[lindex];
// if the edge is cached, we can just reuse the edge
if (!insubmodel)
{
if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED)
{
if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) ==
r_framecount)
{
r_lastvertvalid = false;
continue;
}
}
else
{
// it's cached if the cached edge is valid and is owned
// by this medge_t
if ((((unsigned long)edge_p - (unsigned long)r_edges) >
r_pedge->cachededgeoffset) &&
(((edge_t *)((unsigned long)r_edges +
r_pedge->cachededgeoffset))->owner == r_pedge))
{
R_EmitCachedEdge ();
r_lastvertvalid = false;
continue;
}
}
}
 
// assume it's cacheable
cacheoffset = (byte *)edge_p - (byte *)r_edges;
r_leftclipped = r_rightclipped = false;
R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[1]],
&r_pcurrentvertbase[r_pedge->v[0]],
pclip);
r_pedge->cachededgeoffset = cacheoffset;
 
if (r_leftclipped)
makeleftedge = true;
if (r_rightclipped)
makerightedge = true;
r_lastvertvalid = true;
}
}
 
// if there was a clip off the left edge, add that edge too
// FIXME: faster to do in screen space?
// FIXME: share clipped edges?
if (makeleftedge)
{
r_pedge = &tedge;
r_lastvertvalid = false;
R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next);
}
 
// if there was a clip off the right edge, get the right r_nearzi
if (makerightedge)
{
r_pedge = &tedge;
r_lastvertvalid = false;
r_nearzionly = true;
R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next);
}
 
// if no edges made it out, return without posting the surface
if (!r_emitted)
return;
 
r_polycount++;
 
surface_p->data = (void *)fa;
surface_p->nearzi = r_nearzi;
surface_p->flags = fa->flags;
surface_p->insubmodel = insubmodel;
surface_p->spanstate = 0;
surface_p->entity = currententity;
surface_p->key = r_currentkey++;
surface_p->spans = NULL;
 
pplane = fa->plane;
// FIXME: cache this?
TransformVector (pplane->normal, p_normal);
// FIXME: cache this?
distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal));
 
surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv;
surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv;
surface_p->d_ziorigin = p_normal[2] * distinv -
xcenter * surface_p->d_zistepu -
ycenter * surface_p->d_zistepv;
 
//JDC VectorCopy (r_worldmodelorg, surface_p->modelorg);
surface_p++;
}
 
 
/*
================
R_RenderBmodelFace
================
*/
void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf)
{
int i;
unsigned mask;
mplane_t *pplane;
float distinv;
vec3_t p_normal;
medge_t tedge;
clipplane_t *pclip;
 
// skip out if no more surfs
if (surface_p >= surf_max)
{
r_outofsurfaces++;
return;
}
 
// ditto if not enough edges left, or switch to auxedges if possible
if ((edge_p + psurf->numedges + 4) >= edge_max)
{
r_outofedges += psurf->numedges;
return;
}
 
c_faceclip++;
 
// this is a dummy to give the caching mechanism someplace to write to
r_pedge = &tedge;
 
// set up clip planes
pclip = NULL;
 
for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1)
{
if (r_clipflags & mask)
{
view_clipplanes[i].next = pclip;
pclip = &view_clipplanes[i];
}
}
 
// push the edges through
r_emitted = 0;
r_nearzi = 0;
r_nearzionly = false;
makeleftedge = makerightedge = false;
// FIXME: keep clipped bmodel edges in clockwise order so last vertex caching
// can be used?
r_lastvertvalid = false;
 
for ( ; pedges ; pedges = pedges->pnext)
{
r_leftclipped = r_rightclipped = false;
R_ClipEdge (pedges->v[0], pedges->v[1], pclip);
 
if (r_leftclipped)
makeleftedge = true;
if (r_rightclipped)
makerightedge = true;
}
 
// if there was a clip off the left edge, add that edge too
// FIXME: faster to do in screen space?
// FIXME: share clipped edges?
if (makeleftedge)
{
r_pedge = &tedge;
R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next);
}
 
// if there was a clip off the right edge, get the right r_nearzi
if (makerightedge)
{
r_pedge = &tedge;
r_nearzionly = true;
R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next);
}
 
// if no edges made it out, return without posting the surface
if (!r_emitted)
return;
 
r_polycount++;
 
surface_p->data = (void *)psurf;
surface_p->nearzi = r_nearzi;
surface_p->flags = psurf->flags;
surface_p->insubmodel = true;
surface_p->spanstate = 0;
surface_p->entity = currententity;
surface_p->key = r_currentbkey;
surface_p->spans = NULL;
 
pplane = psurf->plane;
// FIXME: cache this?
TransformVector (pplane->normal, p_normal);
// FIXME: cache this?
distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal));
 
surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv;
surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv;
surface_p->d_ziorigin = p_normal[2] * distinv -
xcenter * surface_p->d_zistepu -
ycenter * surface_p->d_zistepv;
 
//JDC VectorCopy (r_worldmodelorg, surface_p->modelorg);
surface_p++;
}
 
 
/*
================
R_RenderPoly
================
*/
void R_RenderPoly (msurface_t *fa, int clipflags)
{
int i, lindex, lnumverts, s_axis, t_axis;
float dist, lastdist, lzi, scale, u, v, frac;
unsigned mask;
vec3_t local, transformed;
clipplane_t *pclip;
medge_t *pedges;
mplane_t *pplane;
mvertex_t verts[2][100]; //FIXME: do real number
polyvert_t pverts[100]; //FIXME: do real number, safely
int vertpage, newverts, newpage, lastvert;
qboolean visible;
 
// FIXME: clean this up and make it faster
// FIXME: guard against running out of vertices
 
s_axis = t_axis = 0; // keep compiler happy
 
// set up clip planes
pclip = NULL;
 
for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1)
{
if (clipflags & mask)
{
view_clipplanes[i].next = pclip;
pclip = &view_clipplanes[i];
}
}
 
// reconstruct the polygon
// FIXME: these should be precalculated and loaded off disk
pedges = currententity->model->edges;
lnumverts = fa->numedges;
vertpage = 0;
 
for (i=0 ; i<lnumverts ; i++)
{
lindex = currententity->model->surfedges[fa->firstedge + i];
 
if (lindex > 0)
{
r_pedge = &pedges[lindex];
verts[0][i] = r_pcurrentvertbase[r_pedge->v[0]];
}
else
{
r_pedge = &pedges[-lindex];
verts[0][i] = r_pcurrentvertbase[r_pedge->v[1]];
}
}
 
// clip the polygon, done if not visible
while (pclip)
{
lastvert = lnumverts - 1;
lastdist = DotProduct (verts[vertpage][lastvert].position,
pclip->normal) - pclip->dist;
 
visible = false;
newverts = 0;
newpage = vertpage ^ 1;
 
for (i=0 ; i<lnumverts ; i++)
{
dist = DotProduct (verts[vertpage][i].position, pclip->normal) -
pclip->dist;
 
if ((lastdist > 0) != (dist > 0))
{
frac = dist / (dist - lastdist);
verts[newpage][newverts].position[0] =
verts[vertpage][i].position[0] +
((verts[vertpage][lastvert].position[0] -
verts[vertpage][i].position[0]) * frac);
verts[newpage][newverts].position[1] =
verts[vertpage][i].position[1] +
((verts[vertpage][lastvert].position[1] -
verts[vertpage][i].position[1]) * frac);
verts[newpage][newverts].position[2] =
verts[vertpage][i].position[2] +
((verts[vertpage][lastvert].position[2] -
verts[vertpage][i].position[2]) * frac);
newverts++;
}
 
if (dist >= 0)
{
verts[newpage][newverts] = verts[vertpage][i];
newverts++;
visible = true;
}
 
lastvert = i;
lastdist = dist;
}
 
if (!visible || (newverts < 3))
return;
 
lnumverts = newverts;
vertpage ^= 1;
pclip = pclip->next;
}
 
// transform and project, remembering the z values at the vertices and
// r_nearzi, and extract the s and t coordinates at the vertices
pplane = fa->plane;
switch (pplane->type)
{
case PLANE_X:
case PLANE_ANYX:
s_axis = 1;
t_axis = 2;
break;
case PLANE_Y:
case PLANE_ANYY:
s_axis = 0;
t_axis = 2;
break;
case PLANE_Z:
case PLANE_ANYZ:
s_axis = 0;
t_axis = 1;
break;
}
 
r_nearzi = 0;
 
for (i=0 ; i<lnumverts ; i++)
{
// transform and project
VectorSubtract (verts[vertpage][i].position, modelorg, local);
TransformVector (local, transformed);
 
if (transformed[2] < NEAR_CLIP)
transformed[2] = NEAR_CLIP;
 
lzi = 1.0 / transformed[2];
 
if (lzi > r_nearzi) // for mipmap finding
r_nearzi = lzi;
 
// FIXME: build x/yscale into transform?
scale = xscale * lzi;
u = (xcenter + scale*transformed[0]);
if (u < r_refdef.fvrectx_adj)
u = r_refdef.fvrectx_adj;
if (u > r_refdef.fvrectright_adj)
u = r_refdef.fvrectright_adj;
 
scale = yscale * lzi;
v = (ycenter - scale*transformed[1]);
if (v < r_refdef.fvrecty_adj)
v = r_refdef.fvrecty_adj;
if (v > r_refdef.fvrectbottom_adj)
v = r_refdef.fvrectbottom_adj;
 
pverts[i].u = u;
pverts[i].v = v;
pverts[i].zi = lzi;
pverts[i].s = verts[vertpage][i].position[s_axis];
pverts[i].t = verts[vertpage][i].position[t_axis];
}
 
// build the polygon descriptor, including fa, r_nearzi, and u, v, s, t, and z
// for each vertex
r_polydesc.numverts = lnumverts;
r_polydesc.nearzi = r_nearzi;
r_polydesc.pcurrentface = fa;
r_polydesc.pverts = pverts;
 
// draw the polygon
D_DrawPoly ();
}
 
 
/*
================
R_ZDrawSubmodelPolys
================
*/
void R_ZDrawSubmodelPolys (model_t *pmodel)
{
int i, numsurfaces;
msurface_t *psurf;
float dot;
mplane_t *pplane;
 
psurf = &pmodel->surfaces[pmodel->firstmodelsurface];
numsurfaces = pmodel->nummodelsurfaces;
 
for (i=0 ; i<numsurfaces ; i++, psurf++)
{
// find which side of the node we are on
pplane = psurf->plane;
 
dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
 
// draw the polygon
if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
{
// FIXME: use bounding-box-based frustum clipping info?
R_RenderPoly (psurf, 15);
}
}
}
 
/contrib/other/sdlquake-1.0.9/r_drawa.S
0,0 → 1,838
/*
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_drawa.s
// x86 assembly-language edge clipping and emission code
//
 
#include "asm_i386.h"
#include "quakeasm.h"
#include "asm_draw.h"
#include "d_ifacea.h"
 
#if id386
 
// !!! if these are changed, they must be changed in r_draw.c too !!!
#define FULLY_CLIPPED_CACHED 0x80000000
#define FRAMECOUNT_MASK 0x7FFFFFFF
 
.data
 
Ld0: .single 0.0
Ld1: .single 0.0
Lstack: .long 0
Lfp_near_clip: .single NEAR_CLIP
Lceilv0: .long 0
Lv: .long 0
Lu0: .long 0
Lv0: .long 0
Lzi0: .long 0
 
.text
 
//----------------------------------------------------------------------
// edge clipping code
//----------------------------------------------------------------------
 
#define pv0 4+12
#define pv1 8+12
#define clip 12+12
 
.align 4
.globl C(R_ClipEdge)
C(R_ClipEdge):
pushl %esi // preserve register variables
pushl %edi
pushl %ebx
movl %esp,Lstack // for clearing the stack later
 
// float d0, d1, f;
// mvertex_t clipvert;
 
movl clip(%esp),%ebx
movl pv0(%esp),%esi
movl pv1(%esp),%edx
 
// if (clip)
// {
testl %ebx,%ebx
jz Lemit
 
// do
// {
 
Lcliploop:
 
// d0 = DotProduct (pv0->position, clip->normal) - clip->dist;
// d1 = DotProduct (pv1->position, clip->normal) - clip->dist;
flds mv_position+0(%esi)
fmuls cp_normal+0(%ebx)
flds mv_position+4(%esi)
fmuls cp_normal+4(%ebx)
flds mv_position+8(%esi)
fmuls cp_normal+8(%ebx)
fxch %st(1)
faddp %st(0),%st(2) // d0mul2 | d0add0
 
flds mv_position+0(%edx)
fmuls cp_normal+0(%ebx)
flds mv_position+4(%edx)
fmuls cp_normal+4(%ebx)
flds mv_position+8(%edx)
fmuls cp_normal+8(%ebx)
fxch %st(1)
faddp %st(0),%st(2) // d1mul2 | d1add0 | d0mul2 | d0add0
fxch %st(3) // d0add0 | d1add0 | d0mul2 | d1mul2
 
faddp %st(0),%st(2) // d1add0 | dot0 | d1mul2
faddp %st(0),%st(2) // dot0 | dot1
 
fsubs cp_dist(%ebx) // d0 | dot1
fxch %st(1) // dot1 | d0
fsubs cp_dist(%ebx) // d1 | d0
fxch %st(1)
fstps Ld0
fstps Ld1
 
// if (d0 >= 0)
// {
movl Ld0,%eax
movl Ld1,%ecx
orl %eax,%ecx
js Lp2
 
// both points are unclipped
 
Lcontinue:
 
//
// R_ClipEdge (&clipvert, pv1, clip->next);
// return;
// }
// } while ((clip = clip->next) != NULL);
movl cp_next(%ebx),%ebx
testl %ebx,%ebx
jnz Lcliploop
 
// }
 
//// add the edge
// R_EmitEdge (pv0, pv1);
Lemit:
 
//
// set integer rounding to ceil mode, set to single precision
//
// FIXME: do away with by manually extracting integers from floats?
// FIXME: set less often
fldcw ceil_cw
 
// edge_t *edge, *pcheck;
// int u_check;
// float u, u_step;
// vec3_t local, transformed;
// float *world;
// int v, v2, ceilv0;
// float scale, lzi0, u0, v0;
// int side;
 
// if (r_lastvertvalid)
// {
cmpl $0,C(r_lastvertvalid)
jz LCalcFirst
 
// u0 = r_u1;
// v0 = r_v1;
// lzi0 = r_lzi1;
// ceilv0 = r_ceilv1;
movl C(r_lzi1),%eax
movl C(r_u1),%ecx
movl %eax,Lzi0
movl %ecx,Lu0
movl C(r_v1),%ecx
movl C(r_ceilv1),%eax
movl %ecx,Lv0
movl %eax,Lceilv0
jmp LCalcSecond
 
// }
 
LCalcFirst:
 
// else
// {
// world = &pv0->position[0];
 
call LTransformAndProject // v0 | lzi0 | u0
 
fsts Lv0
fxch %st(2) // u0 | lzi0 | v0
fstps Lu0 // lzi0 | v0
fstps Lzi0 // v0
 
// ceilv0 = (int)(v0 - 2000) + 2000; // ceil(v0);
fistpl Lceilv0
 
// }
 
LCalcSecond:
 
// world = &pv1->position[0];
movl %edx,%esi
 
call LTransformAndProject // v1 | lzi1 | u1
 
flds Lu0 // u0 | v1 | lzi1 | u1
fxch %st(3) // u1 | v1 | lzi1 | u0
flds Lzi0 // lzi0 | u1 | v1 | lzi1 | u0
fxch %st(3) // lzi1 | u1 | v1 | lzi0 | u0
flds Lv0 // v0 | lzi1 | u1 | v1 | lzi0 | u0
fxch %st(3) // v1 | lzi1 | u1 | v0 | lzi0 | u0
 
// r_ceilv1 = (int)(r_v1 - 2000) + 2000; // ceil(r_v1);
fistl C(r_ceilv1)
 
fldcw single_cw // put back normal floating-point state
 
fsts C(r_v1)
fxch %st(4) // lzi0 | lzi1 | u1 | v0 | v1 | u0
 
// if (r_lzi1 > lzi0)
// lzi0 = r_lzi1;
fcom %st(1)
fnstsw %ax
testb $1,%ah
jz LP0
fstp %st(0)
fld %st(0)
LP0:
 
fxch %st(1) // lzi1 | lzi0 | u1 | v0 | v1 | u0
fstps C(r_lzi1) // lzi0 | u1 | v0 | v1 | u0
fxch %st(1)
fsts C(r_u1)
fxch %st(1)
 
// if (lzi0 > r_nearzi) // for mipmap finding
// r_nearzi = lzi0;
fcoms C(r_nearzi)
fnstsw %ax
testb $0x45,%ah
jnz LP1
fsts C(r_nearzi)
LP1:
 
// // for right edges, all we want is the effect on 1/z
// if (r_nearzionly)
// return;
movl C(r_nearzionly),%eax
testl %eax,%eax
jz LP2
LPop5AndDone:
movl C(cacheoffset),%eax
movl C(r_framecount),%edx
cmpl $0x7FFFFFFF,%eax
jz LDoPop
andl $(FRAMECOUNT_MASK),%edx
orl $(FULLY_CLIPPED_CACHED),%edx
movl %edx,C(cacheoffset)
 
LDoPop:
fstp %st(0) // u1 | v0 | v1 | u0
fstp %st(0) // v0 | v1 | u0
fstp %st(0) // v1 | u0
fstp %st(0) // u0
fstp %st(0)
jmp Ldone
 
LP2:
 
// // create the edge
// if (ceilv0 == r_ceilv1)
// return; // horizontal edge
movl Lceilv0,%ebx
movl C(edge_p),%edi
movl C(r_ceilv1),%ecx
movl %edi,%edx
movl C(r_pedge),%esi
addl $(et_size),%edx
cmpl %ecx,%ebx
jz LPop5AndDone
 
movl C(r_pedge),%eax
movl %eax,et_owner(%edi)
 
// side = ceilv0 > r_ceilv1;
//
// edge->nearzi = lzi0;
fstps et_nearzi(%edi) // u1 | v0 | v1 | u0
 
// if (side == 1)
// {
jc LSide0
 
LSide1:
 
// // leading edge (go from p2 to p1)
 
// u_step = ((u0 - r_u1) / (v0 - r_v1));
fsubrp %st(0),%st(3) // v0 | v1 | u0-u1
fsub %st(1),%st(0) // v0-v1 | v1 | u0-u1
fdivrp %st(0),%st(2) // v1 | ustep
 
// r_emitted = 1;
movl $1,C(r_emitted)
 
// edge = edge_p++;
movl %edx,C(edge_p)
 
// pretouch next edge
movl (%edx),%eax
 
// v2 = ceilv0 - 1;
// v = r_ceilv1;
movl %ecx,%eax
leal -1(%ebx),%ecx
movl %eax,%ebx
 
// edge->surfs[0] = 0;
// edge->surfs[1] = surface_p - surfaces;
movl C(surface_p),%eax
movl C(surfaces),%esi
subl %edx,%edx
subl %esi,%eax
shrl $(SURF_T_SHIFT),%eax
movl %edx,et_surfs(%edi)
movl %eax,et_surfs+2(%edi)
 
subl %esi,%esi
 
// u = r_u1 + ((float)v - r_v1) * u_step;
movl %ebx,Lv
fildl Lv // v | v1 | ustep
fsubp %st(0),%st(1) // v-v1 | ustep
fmul %st(1),%st(0) // (v-v1)*ustep | ustep
fadds C(r_u1) // u | ustep
 
jmp LSideDone
 
// }
 
LSide0:
 
// else
// {
// // trailing edge (go from p1 to p2)
 
// u_step = ((r_u1 - u0) / (r_v1 - v0));
fsub %st(3),%st(0) // u1-u0 | v0 | v1 | u0
fxch %st(2) // v1 | v0 | u1-u0 | u0
fsub %st(1),%st(0) // v1-v0 | v0 | u1-u0 | u0
fdivrp %st(0),%st(2) // v0 | ustep | u0
 
// r_emitted = 1;
movl $1,C(r_emitted)
 
// edge = edge_p++;
movl %edx,C(edge_p)
 
// pretouch next edge
movl (%edx),%eax
 
// v = ceilv0;
// v2 = r_ceilv1 - 1;
decl %ecx
 
// edge->surfs[0] = surface_p - surfaces;
// edge->surfs[1] = 0;
movl C(surface_p),%eax
movl C(surfaces),%esi
subl %edx,%edx
subl %esi,%eax
shrl $(SURF_T_SHIFT),%eax
movl %edx,et_surfs+2(%edi)
movl %eax,et_surfs(%edi)
 
movl $1,%esi
 
// u = u0 + ((float)v - v0) * u_step;
movl %ebx,Lv
fildl Lv // v | v0 | ustep | u0
fsubp %st(0),%st(1) // v-v0 | ustep | u0
fmul %st(1),%st(0) // (v-v0)*ustep | ustep | u0
faddp %st(0),%st(2) // ustep | u
fxch %st(1) // u | ustep
 
// }
 
LSideDone:
 
// edge->u_step = u_step*0x100000;
// edge->u = u*0x100000 + 0xFFFFF;
 
fmuls fp_1m // u*0x100000 | ustep
fxch %st(1) // ustep | u*0x100000
fmuls fp_1m // ustep*0x100000 | u*0x100000
fxch %st(1) // u*0x100000 | ustep*0x100000
fadds fp_1m_minus_1 // u*0x100000 + 0xFFFFF | ustep*0x100000
fxch %st(1) // ustep*0x100000 | u*0x100000 + 0xFFFFF
fistpl et_u_step(%edi) // u*0x100000 + 0xFFFFF
fistpl et_u(%edi)
 
// // we need to do this to avoid stepping off the edges if a very nearly
// // horizontal edge is less than epsilon above a scan, and numeric error
// // causes it to incorrectly extend to the scan, and the extension of the
// // line goes off the edge of the screen
// // FIXME: is this actually needed?
// if (edge->u < r_refdef.vrect_x_adj_shift20)
// edge->u = r_refdef.vrect_x_adj_shift20;
// if (edge->u > r_refdef.vrectright_adj_shift20)
// edge->u = r_refdef.vrectright_adj_shift20;
movl et_u(%edi),%eax
movl C(r_refdef)+rd_vrect_x_adj_shift20,%edx
cmpl %edx,%eax
jl LP4
movl C(r_refdef)+rd_vrectright_adj_shift20,%edx
cmpl %edx,%eax
jng LP5
LP4:
movl %edx,et_u(%edi)
movl %edx,%eax
LP5:
 
// // sort the edge in normally
// u_check = edge->u;
//
// if (edge->surfs[0])
// u_check++; // sort trailers after leaders
addl %esi,%eax
 
// if (!newedges[v] || newedges[v]->u >= u_check)
// {
movl C(newedges)(,%ebx,4),%esi
testl %esi,%esi
jz LDoFirst
cmpl %eax,et_u(%esi)
jl LNotFirst
LDoFirst:
 
// edge->next = newedges[v];
// newedges[v] = edge;
movl %esi,et_next(%edi)
movl %edi,C(newedges)(,%ebx,4)
 
jmp LSetRemove
 
// }
 
LNotFirst:
 
// else
// {
// pcheck = newedges[v];
//
// while (pcheck->next && pcheck->next->u < u_check)
// pcheck = pcheck->next;
LFindInsertLoop:
movl %esi,%edx
movl et_next(%esi),%esi
testl %esi,%esi
jz LInsertFound
cmpl %eax,et_u(%esi)
jl LFindInsertLoop
 
LInsertFound:
 
// edge->next = pcheck->next;
// pcheck->next = edge;
movl %esi,et_next(%edi)
movl %edi,et_next(%edx)
 
// }
 
LSetRemove:
 
// edge->nextremove = removeedges[v2];
// removeedges[v2] = edge;
movl C(removeedges)(,%ecx,4),%eax
movl %edi,C(removeedges)(,%ecx,4)
movl %eax,et_nextremove(%edi)
 
Ldone:
movl Lstack,%esp // clear temporary variables from stack
 
popl %ebx // restore register variables
popl %edi
popl %esi
ret
 
// at least one point is clipped
 
Lp2:
testl %eax,%eax
jns Lp1
 
// else
// {
// // point 0 is clipped
 
// if (d1 < 0)
// {
movl Ld1,%eax
testl %eax,%eax
jns Lp3
 
// // both points are clipped
// // we do cache fully clipped edges
// if (!leftclipped)
movl C(r_leftclipped),%eax
movl C(r_pedge),%ecx
testl %eax,%eax
jnz Ldone
 
// r_pedge->framecount = r_framecount;
movl C(r_framecount),%eax
andl $(FRAMECOUNT_MASK),%eax
orl $(FULLY_CLIPPED_CACHED),%eax
movl %eax,C(cacheoffset)
 
// return;
jmp Ldone
 
// }
 
Lp1:
 
// // point 0 is unclipped
// if (d1 >= 0)
// {
// // both points are unclipped
// continue;
 
// // only point 1 is clipped
 
// f = d0 / (d0 - d1);
flds Ld0
flds Ld1
fsubr %st(1),%st(0)
 
// // we don't cache partially clipped edges
movl $0x7FFFFFFF,C(cacheoffset)
 
fdivrp %st(0),%st(1)
 
subl $(mv_size),%esp // allocate space for clipvert
 
// clipvert.position[0] = pv0->position[0] +
// f * (pv1->position[0] - pv0->position[0]);
// clipvert.position[1] = pv0->position[1] +
// f * (pv1->position[1] - pv0->position[1]);
// clipvert.position[2] = pv0->position[2] +
// f * (pv1->position[2] - pv0->position[2]);
flds mv_position+8(%edx)
fsubs mv_position+8(%esi)
flds mv_position+4(%edx)
fsubs mv_position+4(%esi)
flds mv_position+0(%edx)
fsubs mv_position+0(%esi) // 0 | 1 | 2
 
// replace pv1 with the clip point
movl %esp,%edx
movl cp_leftedge(%ebx),%eax
testb %al,%al
 
fmul %st(3),%st(0)
fxch %st(1) // 1 | 0 | 2
fmul %st(3),%st(0)
fxch %st(2) // 2 | 0 | 1
fmulp %st(0),%st(3) // 0 | 1 | 2
fadds mv_position+0(%esi)
fxch %st(1) // 1 | 0 | 2
fadds mv_position+4(%esi)
fxch %st(2) // 2 | 0 | 1
fadds mv_position+8(%esi)
fxch %st(1) // 0 | 2 | 1
fstps mv_position+0(%esp) // 2 | 1
fstps mv_position+8(%esp) // 1
fstps mv_position+4(%esp)
 
// if (clip->leftedge)
// {
jz Ltestright
 
// r_leftclipped = true;
// r_leftexit = clipvert;
movl $1,C(r_leftclipped)
movl mv_position+0(%esp),%eax
movl %eax,C(r_leftexit)+mv_position+0
movl mv_position+4(%esp),%eax
movl %eax,C(r_leftexit)+mv_position+4
movl mv_position+8(%esp),%eax
movl %eax,C(r_leftexit)+mv_position+8
 
jmp Lcontinue
 
// }
 
Ltestright:
// else if (clip->rightedge)
// {
testb %ah,%ah
jz Lcontinue
 
// r_rightclipped = true;
// r_rightexit = clipvert;
movl $1,C(r_rightclipped)
movl mv_position+0(%esp),%eax
movl %eax,C(r_rightexit)+mv_position+0
movl mv_position+4(%esp),%eax
movl %eax,C(r_rightexit)+mv_position+4
movl mv_position+8(%esp),%eax
movl %eax,C(r_rightexit)+mv_position+8
 
// }
//
// R_ClipEdge (pv0, &clipvert, clip->next);
// return;
// }
jmp Lcontinue
 
// }
 
Lp3:
 
// // only point 0 is clipped
// r_lastvertvalid = false;
 
movl $0,C(r_lastvertvalid)
 
// f = d0 / (d0 - d1);
flds Ld0
flds Ld1
fsubr %st(1),%st(0)
 
// // we don't cache partially clipped edges
movl $0x7FFFFFFF,C(cacheoffset)
 
fdivrp %st(0),%st(1)
 
subl $(mv_size),%esp // allocate space for clipvert
 
// clipvert.position[0] = pv0->position[0] +
// f * (pv1->position[0] - pv0->position[0]);
// clipvert.position[1] = pv0->position[1] +
// f * (pv1->position[1] - pv0->position[1]);
// clipvert.position[2] = pv0->position[2] +
// f * (pv1->position[2] - pv0->position[2]);
flds mv_position+8(%edx)
fsubs mv_position+8(%esi)
flds mv_position+4(%edx)
fsubs mv_position+4(%esi)
flds mv_position+0(%edx)
fsubs mv_position+0(%esi) // 0 | 1 | 2
 
movl cp_leftedge(%ebx),%eax
testb %al,%al
 
fmul %st(3),%st(0)
fxch %st(1) // 1 | 0 | 2
fmul %st(3),%st(0)
fxch %st(2) // 2 | 0 | 1
fmulp %st(0),%st(3) // 0 | 1 | 2
fadds mv_position+0(%esi)
fxch %st(1) // 1 | 0 | 2
fadds mv_position+4(%esi)
fxch %st(2) // 2 | 0 | 1
fadds mv_position+8(%esi)
fxch %st(1) // 0 | 2 | 1
fstps mv_position+0(%esp) // 2 | 1
fstps mv_position+8(%esp) // 1
fstps mv_position+4(%esp)
 
// replace pv0 with the clip point
movl %esp,%esi
 
// if (clip->leftedge)
// {
jz Ltestright2
 
// r_leftclipped = true;
// r_leftenter = clipvert;
movl $1,C(r_leftclipped)
movl mv_position+0(%esp),%eax
movl %eax,C(r_leftenter)+mv_position+0
movl mv_position+4(%esp),%eax
movl %eax,C(r_leftenter)+mv_position+4
movl mv_position+8(%esp),%eax
movl %eax,C(r_leftenter)+mv_position+8
 
jmp Lcontinue
 
// }
 
Ltestright2:
// else if (clip->rightedge)
// {
testb %ah,%ah
jz Lcontinue
 
// r_rightclipped = true;
// r_rightenter = clipvert;
movl $1,C(r_rightclipped)
movl mv_position+0(%esp),%eax
movl %eax,C(r_rightenter)+mv_position+0
movl mv_position+4(%esp),%eax
movl %eax,C(r_rightenter)+mv_position+4
movl mv_position+8(%esp),%eax
movl %eax,C(r_rightenter)+mv_position+8
 
// }
jmp Lcontinue
 
// %esi = vec3_t point to transform and project
// %edx preserved
LTransformAndProject:
 
// // transform and project
// VectorSubtract (world, modelorg, local);
flds mv_position+0(%esi)
fsubs C(modelorg)+0
flds mv_position+4(%esi)
fsubs C(modelorg)+4
flds mv_position+8(%esi)
fsubs C(modelorg)+8
fxch %st(2) // local[0] | local[1] | local[2]
 
// TransformVector (local, transformed);
//
// if (transformed[2] < NEAR_CLIP)
// transformed[2] = NEAR_CLIP;
//
// lzi0 = 1.0 / transformed[2];
fld %st(0) // local[0] | local[0] | local[1] | local[2]
fmuls C(vpn)+0 // zm0 | local[0] | local[1] | local[2]
fld %st(1) // local[0] | zm0 | local[0] | local[1] |
// local[2]
fmuls C(vright)+0 // xm0 | zm0 | local[0] | local[1] | local[2]
fxch %st(2) // local[0] | zm0 | xm0 | local[1] | local[2]
fmuls C(vup)+0 // ym0 | zm0 | xm0 | local[1] | local[2]
fld %st(3) // local[1] | ym0 | zm0 | xm0 | local[1] |
// local[2]
fmuls C(vpn)+4 // zm1 | ym0 | zm0 | xm0 | local[1] |
// local[2]
fld %st(4) // local[1] | zm1 | ym0 | zm0 | xm0 |
// local[1] | local[2]
fmuls C(vright)+4 // xm1 | zm1 | ym0 | zm0 | xm0 |
// local[1] | local[2]
fxch %st(5) // local[1] | zm1 | ym0 | zm0 | xm0 |
// xm1 | local[2]
fmuls C(vup)+4 // ym1 | zm1 | ym0 | zm0 | xm0 |
// xm1 | local[2]
fxch %st(1) // zm1 | ym1 | ym0 | zm0 | xm0 |
// xm1 | local[2]
faddp %st(0),%st(3) // ym1 | ym0 | zm2 | xm0 | xm1 | local[2]
fxch %st(3) // xm0 | ym0 | zm2 | ym1 | xm1 | local[2]
faddp %st(0),%st(4) // ym0 | zm2 | ym1 | xm2 | local[2]
faddp %st(0),%st(2) // zm2 | ym2 | xm2 | local[2]
fld %st(3) // local[2] | zm2 | ym2 | xm2 | local[2]
fmuls C(vpn)+8 // zm3 | zm2 | ym2 | xm2 | local[2]
fld %st(4) // local[2] | zm3 | zm2 | ym2 | xm2 | local[2]
fmuls C(vright)+8 // xm3 | zm3 | zm2 | ym2 | xm2 | local[2]
fxch %st(5) // local[2] | zm3 | zm2 | ym2 | xm2 | xm3
fmuls C(vup)+8 // ym3 | zm3 | zm2 | ym2 | xm2 | xm3
fxch %st(1) // zm3 | ym3 | zm2 | ym2 | xm2 | xm3
faddp %st(0),%st(2) // ym3 | zm4 | ym2 | xm2 | xm3
fxch %st(4) // xm3 | zm4 | ym2 | xm2 | ym3
faddp %st(0),%st(3) // zm4 | ym2 | xm4 | ym3
fxch %st(1) // ym2 | zm4 | xm4 | ym3
faddp %st(0),%st(3) // zm4 | xm4 | ym4
 
fcoms Lfp_near_clip
fnstsw %ax
testb $1,%ah
jz LNoClip
fstp %st(0)
flds Lfp_near_clip
 
LNoClip:
 
fdivrs float_1 // lzi0 | x | y
fxch %st(1) // x | lzi0 | y
 
// // FIXME: build x/yscale into transform?
// scale = xscale * lzi0;
// u0 = (xcenter + scale*transformed[0]);
flds C(xscale) // xscale | x | lzi0 | y
fmul %st(2),%st(0) // scale | x | lzi0 | y
fmulp %st(0),%st(1) // scale*x | lzi0 | y
fadds C(xcenter) // u0 | lzi0 | y
 
// if (u0 < r_refdef.fvrectx_adj)
// u0 = r_refdef.fvrectx_adj;
// if (u0 > r_refdef.fvrectright_adj)
// u0 = r_refdef.fvrectright_adj;
// FIXME: use integer compares of floats?
fcoms C(r_refdef)+rd_fvrectx_adj
fnstsw %ax
testb $1,%ah
jz LClampP0
fstp %st(0)
flds C(r_refdef)+rd_fvrectx_adj
LClampP0:
fcoms C(r_refdef)+rd_fvrectright_adj
fnstsw %ax
testb $0x45,%ah
jnz LClampP1
fstp %st(0)
flds C(r_refdef)+rd_fvrectright_adj
LClampP1:
 
fld %st(1) // lzi0 | u0 | lzi0 | y
 
// scale = yscale * lzi0;
// v0 = (ycenter - scale*transformed[1]);
fmuls C(yscale) // scale | u0 | lzi0 | y
fmulp %st(0),%st(3) // u0 | lzi0 | scale*y
fxch %st(2) // scale*y | lzi0 | u0
fsubrs C(ycenter) // v0 | lzi0 | u0
 
// if (v0 < r_refdef.fvrecty_adj)
// v0 = r_refdef.fvrecty_adj;
// if (v0 > r_refdef.fvrectbottom_adj)
// v0 = r_refdef.fvrectbottom_adj;
// FIXME: use integer compares of floats?
fcoms C(r_refdef)+rd_fvrecty_adj
fnstsw %ax
testb $1,%ah
jz LClampP2
fstp %st(0)
flds C(r_refdef)+rd_fvrecty_adj
LClampP2:
fcoms C(r_refdef)+rd_fvrectbottom_adj
fnstsw %ax
testb $0x45,%ah
jnz LClampP3
fstp %st(0)
flds C(r_refdef)+rd_fvrectbottom_adj
LClampP3:
ret
 
#endif // id386
 
/contrib/other/sdlquake-1.0.9/r_edge.c
0,0 → 1,774
/*
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_edge.c
 
#include "quakedef.h"
#include "r_local.h"
 
#if 0
// FIXME
the complex cases add new polys on most lines, so dont optimize for keeping them the same
have multiple free span lists to try to get better coherence?
low depth complexity -- 1 to 3 or so
 
this breaks spans at every edge, even hidden ones (bad)
 
have a sentinal at both ends?
#endif
 
 
edge_t *auxedges;
edge_t *r_edges, *edge_p, *edge_max;
 
surf_t *surfaces, *surface_p, *surf_max;
 
// surfaces are generated in back to front order by the bsp, so if a surf
// pointer is greater than another one, it should be drawn in front
// surfaces[1] is the background, and is used as the active surface stack
 
edge_t *newedges[MAXHEIGHT];
edge_t *removeedges[MAXHEIGHT];
 
espan_t *span_p, *max_span_p;
 
int r_currentkey;
 
extern int screenwidth;
 
int current_iv;
 
int edge_head_u_shift20, edge_tail_u_shift20;
 
static void (*pdrawfunc)(void);
 
edge_t edge_head;
edge_t edge_tail;
edge_t edge_aftertail;
edge_t edge_sentinel;
 
float fv;
 
void R_GenerateSpans (void);
void R_GenerateSpansBackward (void);
 
void R_LeadingEdge (edge_t *edge);
void R_LeadingEdgeBackwards (edge_t *edge);
void R_TrailingEdge (surf_t *surf, edge_t *edge);
 
 
//=============================================================================
 
 
/*
==============
R_DrawCulledPolys
==============
*/
void R_DrawCulledPolys (void)
{
surf_t *s;
msurface_t *pface;
 
currententity = &cl_entities[0];
 
if (r_worldpolysbacktofront)
{
for (s=surface_p-1 ; s>&surfaces[1] ; s--)
{
if (!s->spans)
continue;
 
if (!(s->flags & SURF_DRAWBACKGROUND))
{
pface = (msurface_t *)s->data;
R_RenderPoly (pface, 15);
}
}
}
else
{
for (s = &surfaces[1] ; s<surface_p ; s++)
{
if (!s->spans)
continue;
 
if (!(s->flags & SURF_DRAWBACKGROUND))
{
pface = (msurface_t *)s->data;
R_RenderPoly (pface, 15);
}
}
}
}
 
 
/*
==============
R_BeginEdgeFrame
==============
*/
void R_BeginEdgeFrame (void)
{
int v;
 
edge_p = r_edges;
edge_max = &r_edges[r_numallocatededges];
 
surface_p = &surfaces[2]; // background is surface 1,
// surface 0 is a dummy
surfaces[1].spans = NULL; // no background spans yet
surfaces[1].flags = SURF_DRAWBACKGROUND;
 
// put the background behind everything in the world
if (r_draworder.value)
{
pdrawfunc = R_GenerateSpansBackward;
surfaces[1].key = 0;
r_currentkey = 1;
}
else
{
pdrawfunc = R_GenerateSpans;
surfaces[1].key = 0x7FFFFFFF;
r_currentkey = 0;
}
 
// FIXME: set with memset
for (v=r_refdef.vrect.y ; v<r_refdef.vrectbottom ; v++)
{
newedges[v] = removeedges[v] = NULL;
}
}
 
 
#if !id386
 
/*
==============
R_InsertNewEdges
 
Adds the edges in the linked list edgestoadd, adding them to the edges in the
linked list edgelist. edgestoadd is assumed to be sorted on u, and non-empty (this is actually newedges[v]). edgelist is assumed to be sorted on u, with a
sentinel at the end (actually, this is the active edge table starting at
edge_head.next).
==============
*/
void R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist)
{
edge_t *next_edge;
 
do
{
next_edge = edgestoadd->next;
edgesearch:
if (edgelist->u >= edgestoadd->u)
goto addedge;
edgelist=edgelist->next;
if (edgelist->u >= edgestoadd->u)
goto addedge;
edgelist=edgelist->next;
if (edgelist->u >= edgestoadd->u)
goto addedge;
edgelist=edgelist->next;
if (edgelist->u >= edgestoadd->u)
goto addedge;
edgelist=edgelist->next;
goto edgesearch;
 
// insert edgestoadd before edgelist
addedge:
edgestoadd->next = edgelist;
edgestoadd->prev = edgelist->prev;
edgelist->prev->next = edgestoadd;
edgelist->prev = edgestoadd;
} while ((edgestoadd = next_edge) != NULL);
}
 
#endif // !id386
 
#if !id386
 
/*
==============
R_RemoveEdges
==============
*/
void R_RemoveEdges (edge_t *pedge)
{
 
do
{
pedge->next->prev = pedge->prev;
pedge->prev->next = pedge->next;
} while ((pedge = pedge->nextremove) != NULL);
}
 
#endif // !id386
 
 
#if !id386
 
/*
==============
R_StepActiveU
==============
*/
void R_StepActiveU (edge_t *pedge)
{
edge_t *pnext_edge, *pwedge;
 
while (1)
{
nextedge:
pedge->u += pedge->u_step;
if (pedge->u < pedge->prev->u)
goto pushback;
pedge = pedge->next;
pedge->u += pedge->u_step;
if (pedge->u < pedge->prev->u)
goto pushback;
pedge = pedge->next;
pedge->u += pedge->u_step;
if (pedge->u < pedge->prev->u)
goto pushback;
pedge = pedge->next;
pedge->u += pedge->u_step;
if (pedge->u < pedge->prev->u)
goto pushback;
pedge = pedge->next;
goto nextedge;
pushback:
if (pedge == &edge_aftertail)
return;
// push it back to keep it sorted
pnext_edge = pedge->next;
 
// pull the edge out of the edge list
pedge->next->prev = pedge->prev;
pedge->prev->next = pedge->next;
 
// find out where the edge goes in the edge list
pwedge = pedge->prev->prev;
 
while (pwedge->u > pedge->u)
{
pwedge = pwedge->prev;
}
 
// put the edge back into the edge list
pedge->next = pwedge->next;
pedge->prev = pwedge;
pedge->next->prev = pedge;
pwedge->next = pedge;
 
pedge = pnext_edge;
if (pedge == &edge_tail)
return;
}
}
 
#endif // !id386
 
 
/*
==============
R_CleanupSpan
==============
*/
void R_CleanupSpan ()
{
surf_t *surf;
int iu;
espan_t *span;
 
// now that we've reached the right edge of the screen, we're done with any
// unfinished surfaces, so emit a span for whatever's on top
surf = surfaces[1].next;
iu = edge_tail_u_shift20;
if (iu > surf->last_u)
{
span = span_p++;
span->u = surf->last_u;
span->count = iu - span->u;
span->v = current_iv;
span->pnext = surf->spans;
surf->spans = span;
}
 
// reset spanstate for all surfaces in the surface stack
do
{
surf->spanstate = 0;
surf = surf->next;
} while (surf != &surfaces[1]);
}
 
 
/*
==============
R_LeadingEdgeBackwards
==============
*/
void R_LeadingEdgeBackwards (edge_t *edge)
{
espan_t *span;
surf_t *surf, *surf2;
int iu;
 
// it's adding a new surface in, so find the correct place
surf = &surfaces[edge->surfs[1]];
 
// don't start a span if this is an inverted span, with the end
// edge preceding the start edge (that is, we've already seen the
// end edge)
if (++surf->spanstate == 1)
{
surf2 = surfaces[1].next;
 
if (surf->key > surf2->key)
goto newtop;
 
// if it's two surfaces on the same plane, the one that's already
// active is in front, so keep going unless it's a bmodel
if (surf->insubmodel && (surf->key == surf2->key))
{
// must be two bmodels in the same leaf; don't care, because they'll
// never be farthest anyway
goto newtop;
}
 
continue_search:
 
do
{
surf2 = surf2->next;
} while (surf->key < surf2->key);
 
if (surf->key == surf2->key)
{
// if it's two surfaces on the same plane, the one that's already
// active is in front, so keep going unless it's a bmodel
if (!surf->insubmodel)
goto continue_search;
 
// must be two bmodels in the same leaf; don't care which is really
// in front, because they'll never be farthest anyway
}
 
goto gotposition;
 
newtop:
// emit a span (obscures current top)
iu = edge->u >> 20;
 
if (iu > surf2->last_u)
{
span = span_p++;
span->u = surf2->last_u;
span->count = iu - span->u;
span->v = current_iv;
span->pnext = surf2->spans;
surf2->spans = span;
}
 
// set last_u on the new span
surf->last_u = iu;
gotposition:
// insert before surf2
surf->next = surf2;
surf->prev = surf2->prev;
surf2->prev->next = surf;
surf2->prev = surf;
}
}
 
 
/*
==============
R_TrailingEdge
==============
*/
void R_TrailingEdge (surf_t *surf, edge_t *edge)
{
espan_t *span;
int iu;
 
// don't generate a span if this is an inverted span, with the end
// edge preceding the start edge (that is, we haven't seen the
// start edge yet)
if (--surf->spanstate == 0)
{
if (surf->insubmodel)
r_bmodelactive--;
 
if (surf == surfaces[1].next)
{
// emit a span (current top going away)
iu = edge->u >> 20;
if (iu > surf->last_u)
{
span = span_p++;
span->u = surf->last_u;
span->count = iu - span->u;
span->v = current_iv;
span->pnext = surf->spans;
surf->spans = span;
}
 
// set last_u on the surface below
surf->next->last_u = iu;
}
 
surf->prev->next = surf->next;
surf->next->prev = surf->prev;
}
}
 
 
#if !id386
 
/*
==============
R_LeadingEdge
==============
*/
void R_LeadingEdge (edge_t *edge)
{
espan_t *span;
surf_t *surf, *surf2;
int iu;
double fu, newzi, testzi, newzitop, newzibottom;
 
if (edge->surfs[1])
{
// it's adding a new surface in, so find the correct place
surf = &surfaces[edge->surfs[1]];
 
// don't start a span if this is an inverted span, with the end
// edge preceding the start edge (that is, we've already seen the
// end edge)
if (++surf->spanstate == 1)
{
if (surf->insubmodel)
r_bmodelactive++;
 
surf2 = surfaces[1].next;
 
if (surf->key < surf2->key)
goto newtop;
 
// if it's two surfaces on the same plane, the one that's already
// active is in front, so keep going unless it's a bmodel
if (surf->insubmodel && (surf->key == surf2->key))
{
// must be two bmodels in the same leaf; sort on 1/z
fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000);
newzi = surf->d_ziorigin + fv*surf->d_zistepv +
fu*surf->d_zistepu;
newzibottom = newzi * 0.99;
 
testzi = surf2->d_ziorigin + fv*surf2->d_zistepv +
fu*surf2->d_zistepu;
 
if (newzibottom >= testzi)
{
goto newtop;
}
 
newzitop = newzi * 1.01;
if (newzitop >= testzi)
{
if (surf->d_zistepu >= surf2->d_zistepu)
{
goto newtop;
}
}
}
 
continue_search:
 
do
{
surf2 = surf2->next;
} while (surf->key > surf2->key);
 
if (surf->key == surf2->key)
{
// if it's two surfaces on the same plane, the one that's already
// active is in front, so keep going unless it's a bmodel
if (!surf->insubmodel)
goto continue_search;
 
// must be two bmodels in the same leaf; sort on 1/z
fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000);
newzi = surf->d_ziorigin + fv*surf->d_zistepv +
fu*surf->d_zistepu;
newzibottom = newzi * 0.99;
 
testzi = surf2->d_ziorigin + fv*surf2->d_zistepv +
fu*surf2->d_zistepu;
 
if (newzibottom >= testzi)
{
goto gotposition;
}
 
newzitop = newzi * 1.01;
if (newzitop >= testzi)
{
if (surf->d_zistepu >= surf2->d_zistepu)
{
goto gotposition;
}
}
 
goto continue_search;
}
 
goto gotposition;
 
newtop:
// emit a span (obscures current top)
iu = edge->u >> 20;
 
if (iu > surf2->last_u)
{
span = span_p++;
span->u = surf2->last_u;
span->count = iu - span->u;
span->v = current_iv;
span->pnext = surf2->spans;
surf2->spans = span;
}
 
// set last_u on the new span
surf->last_u = iu;
gotposition:
// insert before surf2
surf->next = surf2;
surf->prev = surf2->prev;
surf2->prev->next = surf;
surf2->prev = surf;
}
}
}
 
 
/*
==============
R_GenerateSpans
==============
*/
void R_GenerateSpans (void)
{
edge_t *edge;
surf_t *surf;
 
r_bmodelactive = 0;
 
// clear active surfaces to just the background surface
surfaces[1].next = surfaces[1].prev = &surfaces[1];
surfaces[1].last_u = edge_head_u_shift20;
 
// generate spans
for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next)
{
if (edge->surfs[0])
{
// it has a left surface, so a surface is going away for this span
surf = &surfaces[edge->surfs[0]];
 
R_TrailingEdge (surf, edge);
 
if (!edge->surfs[1])
continue;
}
 
R_LeadingEdge (edge);
}
 
R_CleanupSpan ();
}
 
#endif // !id386
 
 
/*
==============
R_GenerateSpansBackward
==============
*/
void R_GenerateSpansBackward (void)
{
edge_t *edge;
 
r_bmodelactive = 0;
 
// clear active surfaces to just the background surface
surfaces[1].next = surfaces[1].prev = &surfaces[1];
surfaces[1].last_u = edge_head_u_shift20;
 
// generate spans
for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next)
{
if (edge->surfs[0])
R_TrailingEdge (&surfaces[edge->surfs[0]], edge);
 
if (edge->surfs[1])
R_LeadingEdgeBackwards (edge);
}
 
R_CleanupSpan ();
}
 
 
/*
==============
R_ScanEdges
 
Input:
newedges[] array
this has links to edges, which have links to surfaces
 
Output:
Each surface has a linked list of its visible spans
==============
*/
void R_ScanEdges (void)
{
int iv, bottom;
byte basespans[MAXSPANS*sizeof(espan_t)+CACHE_SIZE];
espan_t *basespan_p;
surf_t *s;
 
basespan_p = (espan_t *)
((long)(basespans + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
max_span_p = &basespan_p[MAXSPANS - r_refdef.vrect.width];
 
span_p = basespan_p;
 
// clear active edges to just the background edges around the whole screen
// FIXME: most of this only needs to be set up once
edge_head.u = r_refdef.vrect.x << 20;
edge_head_u_shift20 = edge_head.u >> 20;
edge_head.u_step = 0;
edge_head.prev = NULL;
edge_head.next = &edge_tail;
edge_head.surfs[0] = 0;
edge_head.surfs[1] = 1;
edge_tail.u = (r_refdef.vrectright << 20) + 0xFFFFF;
edge_tail_u_shift20 = edge_tail.u >> 20;
edge_tail.u_step = 0;
edge_tail.prev = &edge_head;
edge_tail.next = &edge_aftertail;
edge_tail.surfs[0] = 1;
edge_tail.surfs[1] = 0;
edge_aftertail.u = -1; // force a move
edge_aftertail.u_step = 0;
edge_aftertail.next = &edge_sentinel;
edge_aftertail.prev = &edge_tail;
 
// FIXME: do we need this now that we clamp x in r_draw.c?
edge_sentinel.u = 2000 << 24; // make sure nothing sorts past this
edge_sentinel.prev = &edge_aftertail;
 
//
// process all scan lines
//
bottom = r_refdef.vrectbottom - 1;
 
for (iv=r_refdef.vrect.y ; iv<bottom ; iv++)
{
current_iv = iv;
fv = (float)iv;
 
// mark that the head (background start) span is pre-included
surfaces[1].spanstate = 1;
 
if (newedges[iv])
{
R_InsertNewEdges (newedges[iv], edge_head.next);
}
 
(*pdrawfunc) ();
 
// flush the span list if we can't be sure we have enough spans left for
// the next scan
if (span_p >= max_span_p)
{
VID_UnlockBuffer ();
S_ExtraUpdate (); // don't let sound get messed up if going slow
VID_LockBuffer ();
if (r_drawculledpolys)
{
R_DrawCulledPolys ();
}
else
{
D_DrawSurfaces ();
}
 
// clear the surface span pointers
for (s = &surfaces[1] ; s<surface_p ; s++)
s->spans = NULL;
 
span_p = basespan_p;
}
 
if (removeedges[iv])
R_RemoveEdges (removeedges[iv]);
 
if (edge_head.next != &edge_tail)
R_StepActiveU (edge_head.next);
}
 
// do the last scan (no need to step or sort or remove on the last scan)
 
current_iv = iv;
fv = (float)iv;
 
// mark that the head (background start) span is pre-included
surfaces[1].spanstate = 1;
 
if (newedges[iv])
R_InsertNewEdges (newedges[iv], edge_head.next);
 
(*pdrawfunc) ();
 
// draw whatever's left in the span list
if (r_drawculledpolys)
R_DrawCulledPolys ();
else
D_DrawSurfaces ();
}
 
 
/contrib/other/sdlquake-1.0.9/r_edgea.S
0,0 → 1,750
/*
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_edgea.s
// x86 assembly-language edge-processing code.
//
 
#include "asm_i386.h"
#include "quakeasm.h"
#include "asm_draw.h"
 
#if id386
 
.data
Ltemp: .long 0
float_1_div_0100000h: .long 0x35800000 // 1.0/(float)0x100000
float_point_999: .single 0.999
float_1_point_001: .single 1.001
 
.text
 
//--------------------------------------------------------------------
 
#define edgestoadd 4+8 // note odd stack offsets because of interleaving
#define edgelist 8+12 // with pushes
 
.globl C(R_EdgeCodeStart)
C(R_EdgeCodeStart):
 
.globl C(R_InsertNewEdges)
C(R_InsertNewEdges):
pushl %edi
pushl %esi // preserve register variables
movl edgestoadd(%esp),%edx
pushl %ebx
movl edgelist(%esp),%ecx
 
LDoNextEdge:
movl et_u(%edx),%eax
movl %edx,%edi
 
LContinueSearch:
movl et_u(%ecx),%ebx
movl et_next(%ecx),%esi
cmpl %ebx,%eax
jle LAddedge
movl et_u(%esi),%ebx
movl et_next(%esi),%ecx
cmpl %ebx,%eax
jle LAddedge2
movl et_u(%ecx),%ebx
movl et_next(%ecx),%esi
cmpl %ebx,%eax
jle LAddedge
movl et_u(%esi),%ebx
movl et_next(%esi),%ecx
cmpl %ebx,%eax
jg LContinueSearch
 
LAddedge2:
movl et_next(%edx),%edx
movl et_prev(%esi),%ebx
movl %esi,et_next(%edi)
movl %ebx,et_prev(%edi)
movl %edi,et_next(%ebx)
movl %edi,et_prev(%esi)
movl %esi,%ecx
 
cmpl $0,%edx
jnz LDoNextEdge
jmp LDone
 
.align 4
LAddedge:
movl et_next(%edx),%edx
movl et_prev(%ecx),%ebx
movl %ecx,et_next(%edi)
movl %ebx,et_prev(%edi)
movl %edi,et_next(%ebx)
movl %edi,et_prev(%ecx)
 
cmpl $0,%edx
jnz LDoNextEdge
 
LDone:
popl %ebx // restore register variables
popl %esi
popl %edi
 
ret
 
//--------------------------------------------------------------------
 
#define predge 4+4
 
.globl C(R_RemoveEdges)
C(R_RemoveEdges):
pushl %ebx
movl predge(%esp),%eax
 
Lre_loop:
movl et_next(%eax),%ecx
movl et_nextremove(%eax),%ebx
movl et_prev(%eax),%edx
testl %ebx,%ebx
movl %edx,et_prev(%ecx)
jz Lre_done
movl %ecx,et_next(%edx)
 
movl et_next(%ebx),%ecx
movl et_prev(%ebx),%edx
movl et_nextremove(%ebx),%eax
movl %edx,et_prev(%ecx)
testl %eax,%eax
movl %ecx,et_next(%edx)
jnz Lre_loop
 
popl %ebx
ret
 
Lre_done:
movl %ecx,et_next(%edx)
popl %ebx
 
ret
 
//--------------------------------------------------------------------
 
#define pedgelist 4+4 // note odd stack offset because of interleaving
// with pushes
 
.globl C(R_StepActiveU)
C(R_StepActiveU):
pushl %edi
movl pedgelist(%esp),%edx
pushl %esi // preserve register variables
pushl %ebx
 
movl et_prev(%edx),%esi
 
LNewEdge:
movl et_u(%esi),%edi
 
LNextEdge:
movl et_u(%edx),%eax
movl et_u_step(%edx),%ebx
addl %ebx,%eax
movl et_next(%edx),%esi
movl %eax,et_u(%edx)
cmpl %edi,%eax
jl LPushBack
 
movl et_u(%esi),%edi
movl et_u_step(%esi),%ebx
addl %ebx,%edi
movl et_next(%esi),%edx
movl %edi,et_u(%esi)
cmpl %eax,%edi
jl LPushBack2
 
movl et_u(%edx),%eax
movl et_u_step(%edx),%ebx
addl %ebx,%eax
movl et_next(%edx),%esi
movl %eax,et_u(%edx)
cmpl %edi,%eax
jl LPushBack
 
movl et_u(%esi),%edi
movl et_u_step(%esi),%ebx
addl %ebx,%edi
movl et_next(%esi),%edx
movl %edi,et_u(%esi)
cmpl %eax,%edi
jnl LNextEdge
 
LPushBack2:
movl %edx,%ebx
movl %edi,%eax
movl %esi,%edx
movl %ebx,%esi
 
LPushBack:
// push it back to keep it sorted
movl et_prev(%edx),%ecx
movl et_next(%edx),%ebx
 
// done if the -1 in edge_aftertail triggered this
cmpl $(C(edge_aftertail)),%edx
jz LUDone
 
// pull the edge out of the edge list
movl et_prev(%ecx),%edi
movl %ecx,et_prev(%esi)
movl %ebx,et_next(%ecx)
 
// find out where the edge goes in the edge list
LPushBackLoop:
movl et_prev(%edi),%ecx
movl et_u(%edi),%ebx
cmpl %ebx,%eax
jnl LPushBackFound
 
movl et_prev(%ecx),%edi
movl et_u(%ecx),%ebx
cmpl %ebx,%eax
jl LPushBackLoop
 
movl %ecx,%edi
 
// put the edge back into the edge list
LPushBackFound:
movl et_next(%edi),%ebx
movl %edi,et_prev(%edx)
movl %ebx,et_next(%edx)
movl %edx,et_next(%edi)
movl %edx,et_prev(%ebx)
 
movl %esi,%edx
movl et_prev(%esi),%esi
 
cmpl $(C(edge_tail)),%edx
jnz LNewEdge
 
LUDone:
popl %ebx // restore register variables
popl %esi
popl %edi
 
ret
 
//--------------------------------------------------------------------
 
#define surf 4 // note this is loaded before any pushes
 
.align 4
TrailingEdge:
movl st_spanstate(%esi),%eax // check for edge inversion
decl %eax
jnz LInverted
 
movl %eax,st_spanstate(%esi)
movl st_insubmodel(%esi),%ecx
movl 0x12345678,%edx // surfaces[1].st_next
LPatch0:
movl C(r_bmodelactive),%eax
subl %ecx,%eax
cmpl %esi,%edx
movl %eax,C(r_bmodelactive)
jnz LNoEmit // surface isn't on top, just remove
 
// emit a span (current top going away)
movl et_u(%ebx),%eax
shrl $20,%eax // iu = integral pixel u
movl st_last_u(%esi),%edx
movl st_next(%esi),%ecx
cmpl %edx,%eax
jle LNoEmit2 // iu <= surf->last_u, so nothing to emit
 
movl %eax,st_last_u(%ecx) // surf->next->last_u = iu;
subl %edx,%eax
movl %edx,espan_t_u(%ebp) // span->u = surf->last_u;
 
movl %eax,espan_t_count(%ebp) // span->count = iu - span->u;
movl C(current_iv),%eax
movl %eax,espan_t_v(%ebp) // span->v = current_iv;
movl st_spans(%esi),%eax
movl %eax,espan_t_pnext(%ebp) // span->pnext = surf->spans;
movl %ebp,st_spans(%esi) // surf->spans = span;
addl $(espan_t_size),%ebp
 
movl st_next(%esi),%edx // remove the surface from the surface
movl st_prev(%esi),%esi // stack
 
movl %edx,st_next(%esi)
movl %esi,st_prev(%edx)
ret
 
LNoEmit2:
movl %eax,st_last_u(%ecx) // surf->next->last_u = iu;
movl st_next(%esi),%edx // remove the surface from the surface
movl st_prev(%esi),%esi // stack
 
movl %edx,st_next(%esi)
movl %esi,st_prev(%edx)
ret
 
LNoEmit:
movl st_next(%esi),%edx // remove the surface from the surface
movl st_prev(%esi),%esi // stack
 
movl %edx,st_next(%esi)
movl %esi,st_prev(%edx)
ret
 
LInverted:
movl %eax,st_spanstate(%esi)
ret
 
//--------------------------------------------------------------------
 
// trailing edge only
Lgs_trailing:
pushl $Lgs_nextedge
jmp TrailingEdge
 
 
.globl C(R_GenerateSpans)
C(R_GenerateSpans):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
 
// clear active surfaces to just the background surface
movl C(surfaces),%eax
movl C(edge_head_u_shift20),%edx
addl $(st_size),%eax
// %ebp = span_p throughout
movl C(span_p),%ebp
 
movl $0,C(r_bmodelactive)
 
movl %eax,st_next(%eax)
movl %eax,st_prev(%eax)
movl %edx,st_last_u(%eax)
movl C(edge_head)+et_next,%ebx // edge=edge_head.next
 
// generate spans
cmpl $(C(edge_tail)),%ebx // done if empty list
jz Lgs_lastspan
 
Lgs_edgeloop:
 
movl et_surfs(%ebx),%edi
movl C(surfaces),%eax
movl %edi,%esi
andl $0xFFFF0000,%edi
andl $0xFFFF,%esi
jz Lgs_leading // not a trailing edge
 
// it has a left surface, so a surface is going away for this span
shll $(SURF_T_SHIFT),%esi
addl %eax,%esi
testl %edi,%edi
jz Lgs_trailing
 
// both leading and trailing
call TrailingEdge
movl C(surfaces),%eax
 
// ---------------------------------------------------------------
// handle a leading edge
// ---------------------------------------------------------------
 
Lgs_leading:
shrl $16-SURF_T_SHIFT,%edi
movl C(surfaces),%eax
addl %eax,%edi
movl 0x12345678,%esi // surf2 = surfaces[1].next;
LPatch2:
movl st_spanstate(%edi),%edx
movl st_insubmodel(%edi),%eax
testl %eax,%eax
jnz Lbmodel_leading
 
// handle a leading non-bmodel edge
 
// don't start a span if this is an inverted span, with the end edge preceding
// the start edge (that is, we've already seen the end edge)
testl %edx,%edx
jnz Lxl_done
 
 
// if (surf->key < surf2->key)
// goto newtop;
incl %edx
movl st_key(%edi),%eax
movl %edx,st_spanstate(%edi)
movl st_key(%esi),%ecx
cmpl %ecx,%eax
jl Lnewtop
 
// main sorting loop to search through surface stack until insertion point
// found. Always terminates because background surface is sentinel
// do
// {
// surf2 = surf2->next;
// } while (surf->key >= surf2->key);
Lsortloopnb:
movl st_next(%esi),%esi
movl st_key(%esi),%ecx
cmpl %ecx,%eax
jge Lsortloopnb
 
jmp LInsertAndExit
 
 
// handle a leading bmodel edge
.align 4
Lbmodel_leading:
 
// don't start a span if this is an inverted span, with the end edge preceding
// the start edge (that is, we've already seen the end edge)
testl %edx,%edx
jnz Lxl_done
 
movl C(r_bmodelactive),%ecx
incl %edx
incl %ecx
movl %edx,st_spanstate(%edi)
movl %ecx,C(r_bmodelactive)
 
// if (surf->key < surf2->key)
// goto newtop;
movl st_key(%edi),%eax
movl st_key(%esi),%ecx
cmpl %ecx,%eax
jl Lnewtop
 
// if ((surf->key == surf2->key) && surf->insubmodel)
// {
jz Lzcheck_for_newtop
 
// main sorting loop to search through surface stack until insertion point
// found. Always terminates because background surface is sentinel
// do
// {
// surf2 = surf2->next;
// } while (surf->key > surf2->key);
Lsortloop:
movl st_next(%esi),%esi
movl st_key(%esi),%ecx
cmpl %ecx,%eax
jg Lsortloop
 
jne LInsertAndExit
 
// Do 1/z sorting to see if we've arrived in the right position
movl et_u(%ebx),%eax
subl $0xFFFFF,%eax
movl %eax,Ltemp
fildl Ltemp
 
fmuls float_1_div_0100000h // fu = (float)(edge->u - 0xFFFFF) *
// (1.0 / 0x100000);
 
fld %st(0) // fu | fu
fmuls st_d_zistepu(%edi) // fu*surf->d_zistepu | fu
flds C(fv) // fv | fu*surf->d_zistepu | fu
fmuls st_d_zistepv(%edi) // fv*surf->d_zistepv | fu*surf->d_zistepu | fu
fxch %st(1) // fu*surf->d_zistepu | fv*surf->d_zistepv | fu
fadds st_d_ziorigin(%edi) // fu*surf->d_zistepu + surf->d_ziorigin |
// fv*surf->d_zistepv | fu
 
flds st_d_zistepu(%esi) // surf2->d_zistepu |
// fu*surf->d_zistepu + surf->d_ziorigin |
// fv*surf->d_zistepv | fu
fmul %st(3),%st(0) // fu*surf2->d_zistepu |
// fu*surf->d_zistepu + surf->d_ziorigin |
// fv*surf->d_zistepv | fu
fxch %st(1) // fu*surf->d_zistepu + surf->d_ziorigin |
// fu*surf2->d_zistepu |
// fv*surf->d_zistepv | fu
faddp %st(0),%st(2) // fu*surf2->d_zistepu | newzi | fu
 
flds C(fv) // fv | fu*surf2->d_zistepu | newzi | fu
fmuls st_d_zistepv(%esi) // fv*surf2->d_zistepv |
// fu*surf2->d_zistepu | newzi | fu
fld %st(2) // newzi | fv*surf2->d_zistepv |
// fu*surf2->d_zistepu | newzi | fu
fmuls float_point_999 // newzibottom | fv*surf2->d_zistepv |
// fu*surf2->d_zistepu | newzi | fu
 
fxch %st(2) // fu*surf2->d_zistepu | fv*surf2->d_zistepv |
// newzibottom | newzi | fu
fadds st_d_ziorigin(%esi) // fu*surf2->d_zistepu + surf2->d_ziorigin |
// fv*surf2->d_zistepv | newzibottom | newzi |
// fu
faddp %st(0),%st(1) // testzi | newzibottom | newzi | fu
fxch %st(1) // newzibottom | testzi | newzi | fu
 
// if (newzibottom >= testzi)
// goto Lgotposition;
 
fcomp %st(1) // testzi | newzi | fu
 
fxch %st(1) // newzi | testzi | fu
fmuls float_1_point_001 // newzitop | testzi | fu
fxch %st(1) // testzi | newzitop | fu
 
fnstsw %ax
testb $0x01,%ah
jz Lgotposition_fpop3
 
// if (newzitop >= testzi)
// {
 
fcomp %st(1) // newzitop | fu
fnstsw %ax
testb $0x45,%ah
jz Lsortloop_fpop2
 
// if (surf->d_zistepu >= surf2->d_zistepu)
// goto newtop;
 
flds st_d_zistepu(%edi) // surf->d_zistepu | newzitop| fu
fcomps st_d_zistepu(%esi) // newzitop | fu
fnstsw %ax
testb $0x01,%ah
jz Lgotposition_fpop2
 
fstp %st(0) // clear the FPstack
fstp %st(0)
movl st_key(%edi),%eax
jmp Lsortloop
 
 
Lgotposition_fpop3:
fstp %st(0)
Lgotposition_fpop2:
fstp %st(0)
fstp %st(0)
jmp LInsertAndExit
 
 
// emit a span (obscures current top)
 
Lnewtop_fpop3:
fstp %st(0)
Lnewtop_fpop2:
fstp %st(0)
fstp %st(0)
movl st_key(%edi),%eax // reload the sorting key
 
Lnewtop:
movl et_u(%ebx),%eax
movl st_last_u(%esi),%edx
shrl $20,%eax // iu = integral pixel u
movl %eax,st_last_u(%edi) // surf->last_u = iu;
cmpl %edx,%eax
jle LInsertAndExit // iu <= surf->last_u, so nothing to emit
 
subl %edx,%eax
movl %edx,espan_t_u(%ebp) // span->u = surf->last_u;
 
movl %eax,espan_t_count(%ebp) // span->count = iu - span->u;
movl C(current_iv),%eax
movl %eax,espan_t_v(%ebp) // span->v = current_iv;
movl st_spans(%esi),%eax
movl %eax,espan_t_pnext(%ebp) // span->pnext = surf->spans;
movl %ebp,st_spans(%esi) // surf->spans = span;
addl $(espan_t_size),%ebp
 
LInsertAndExit:
// insert before surf2
movl %esi,st_next(%edi) // surf->next = surf2;
movl st_prev(%esi),%eax
movl %eax,st_prev(%edi) // surf->prev = surf2->prev;
movl %edi,st_prev(%esi) // surf2->prev = surf;
movl %edi,st_next(%eax) // surf2->prev->next = surf;
 
// ---------------------------------------------------------------
// leading edge done
// ---------------------------------------------------------------
 
// ---------------------------------------------------------------
// see if there are any more edges
// ---------------------------------------------------------------
 
Lgs_nextedge:
movl et_next(%ebx),%ebx
cmpl $(C(edge_tail)),%ebx
jnz Lgs_edgeloop
 
// clean up at the right edge
Lgs_lastspan:
 
// now that we've reached the right edge of the screen, we're done with any
// unfinished surfaces, so emit a span for whatever's on top
movl 0x12345678,%esi // surfaces[1].st_next
LPatch3:
movl C(edge_tail_u_shift20),%eax
xorl %ecx,%ecx
movl st_last_u(%esi),%edx
subl %edx,%eax
jle Lgs_resetspanstate
 
movl %edx,espan_t_u(%ebp)
movl %eax,espan_t_count(%ebp)
movl C(current_iv),%eax
movl %eax,espan_t_v(%ebp)
movl st_spans(%esi),%eax
movl %eax,espan_t_pnext(%ebp)
movl %ebp,st_spans(%esi)
addl $(espan_t_size),%ebp
 
// reset spanstate for all surfaces in the surface stack
Lgs_resetspanstate:
movl %ecx,st_spanstate(%esi)
movl st_next(%esi),%esi
cmpl $0x12345678,%esi // &surfaces[1]
LPatch4:
jnz Lgs_resetspanstate
 
// store the final span_p
movl %ebp,C(span_p)
 
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
 
 
// ---------------------------------------------------------------
// 1/z sorting for bmodels in the same leaf
// ---------------------------------------------------------------
.align 4
Lxl_done:
incl %edx
movl %edx,st_spanstate(%edi)
 
jmp Lgs_nextedge
 
 
.align 4
Lzcheck_for_newtop:
movl et_u(%ebx),%eax
subl $0xFFFFF,%eax
movl %eax,Ltemp
fildl Ltemp
 
fmuls float_1_div_0100000h // fu = (float)(edge->u - 0xFFFFF) *
// (1.0 / 0x100000);
 
fld %st(0) // fu | fu
fmuls st_d_zistepu(%edi) // fu*surf->d_zistepu | fu
flds C(fv) // fv | fu*surf->d_zistepu | fu
fmuls st_d_zistepv(%edi) // fv*surf->d_zistepv | fu*surf->d_zistepu | fu
fxch %st(1) // fu*surf->d_zistepu | fv*surf->d_zistepv | fu
fadds st_d_ziorigin(%edi) // fu*surf->d_zistepu + surf->d_ziorigin |
// fv*surf->d_zistepv | fu
 
flds st_d_zistepu(%esi) // surf2->d_zistepu |
// fu*surf->d_zistepu + surf->d_ziorigin |
// fv*surf->d_zistepv | fu
fmul %st(3),%st(0) // fu*surf2->d_zistepu |
// fu*surf->d_zistepu + surf->d_ziorigin |
// fv*surf->d_zistepv | fu
fxch %st(1) // fu*surf->d_zistepu + surf->d_ziorigin |
// fu*surf2->d_zistepu |
// fv*surf->d_zistepv | fu
faddp %st(0),%st(2) // fu*surf2->d_zistepu | newzi | fu
 
flds C(fv) // fv | fu*surf2->d_zistepu | newzi | fu
fmuls st_d_zistepv(%esi) // fv*surf2->d_zistepv |
// fu*surf2->d_zistepu | newzi | fu
fld %st(2) // newzi | fv*surf2->d_zistepv |
// fu*surf2->d_zistepu | newzi | fu
fmuls float_point_999 // newzibottom | fv*surf2->d_zistepv |
// fu*surf2->d_zistepu | newzi | fu
 
fxch %st(2) // fu*surf2->d_zistepu | fv*surf2->d_zistepv |
// newzibottom | newzi | fu
fadds st_d_ziorigin(%esi) // fu*surf2->d_zistepu + surf2->d_ziorigin |
// fv*surf2->d_zistepv | newzibottom | newzi |
// fu
faddp %st(0),%st(1) // testzi | newzibottom | newzi | fu
fxch %st(1) // newzibottom | testzi | newzi | fu
 
// if (newzibottom >= testzi)
// goto newtop;
 
fcomp %st(1) // testzi | newzi | fu
 
fxch %st(1) // newzi | testzi | fu
fmuls float_1_point_001 // newzitop | testzi | fu
fxch %st(1) // testzi | newzitop | fu
 
fnstsw %ax
testb $0x01,%ah
jz Lnewtop_fpop3
 
// if (newzitop >= testzi)
// {
 
fcomp %st(1) // newzitop | fu
fnstsw %ax
testb $0x45,%ah
jz Lsortloop_fpop2
 
// if (surf->d_zistepu >= surf2->d_zistepu)
// goto newtop;
 
flds st_d_zistepu(%edi) // surf->d_zistepu | newzitop | fu
fcomps st_d_zistepu(%esi) // newzitop | fu
fnstsw %ax
testb $0x01,%ah
jz Lnewtop_fpop2
 
Lsortloop_fpop2:
fstp %st(0) // clear the FP stack
fstp %st(0)
movl st_key(%edi),%eax
jmp Lsortloop
 
 
.globl C(R_EdgeCodeEnd)
C(R_EdgeCodeEnd):
 
 
//----------------------------------------------------------------------
// Surface array address code patching routine
//----------------------------------------------------------------------
 
.align 4
.globl C(R_SurfacePatch)
C(R_SurfacePatch):
 
movl C(surfaces),%eax
addl $(st_size),%eax
movl %eax,LPatch4-4
 
addl $(st_next),%eax
movl %eax,LPatch0-4
movl %eax,LPatch2-4
movl %eax,LPatch3-4
 
ret
 
#endif // id386
 
/contrib/other/sdlquake-1.0.9/r_efrag.c
0,0 → 1,276
/*
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"
#include "r_local.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_SplitEntityOnNode2
===================
*/
void R_SplitEntityOnNode2 (mnode_t *node)
{
mplane_t *splitplane;
int sides;
 
if (node->visframe != r_visframecount)
return;
if (node->contents < 0)
{
if (node->contents != CONTENTS_SOLID)
r_pefragtopnode = node; // we've reached a non-solid leaf, so it's
// visible and not BSP clipped
return;
}
splitplane = node->plane;
sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane);
if (sides == 3)
{
// remember first splitter
r_pefragtopnode = node;
return;
}
// not split yet; recurse down the contacted side
if (sides & 1)
R_SplitEntityOnNode2 (node->children[0]);
else
R_SplitEntityOnNode2 (node->children[1]);
}
 
 
/*
===========
R_AddEfrags
===========
*/
void R_AddEfrags (entity_t *ent)
{
model_t *entmodel;
int i;
if (!ent->model)
return;
 
if (ent == cl_entities)
return; // never add the world
 
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);
}
}
}
 
 
/contrib/other/sdlquake-1.0.9/r_light.c
0,0 → 1,260
/*
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"
#include "r_local.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
 
=============================================================================
*/
 
/*
=============
R_MarkLights
=============
*/
void R_MarkLights (dlight_t *light, int bit, mnode_t *node)
{
mplane_t *splitplane;
float dist;
msurface_t *surf;
int i;
if (node->contents < 0)
return;
 
splitplane = node->plane;
dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist;
if (dist > light->radius)
{
R_MarkLights (light, bit, node->children[0]);
return;
}
if (dist < -light->radius)
{
R_MarkLights (light, bit, node->children[1]);
return;
}
// mark the polygons
surf = cl.worldmodel->surfaces + node->firstsurface;
for (i=0 ; i<node->numsurfaces ; i++, surf++)
{
if (surf->dlightframe != r_dlightframecount)
{
surf->dlightbits = 0;
surf->dlightframe = r_dlightframecount;
}
surf->dlightbits |= bit;
}
 
R_MarkLights (light, bit, node->children[0]);
R_MarkLights (light, bit, node->children[1]);
}
 
 
/*
=============
R_PushDlights
=============
*/
void R_PushDlights (void)
{
int i;
dlight_t *l;
 
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;
R_MarkLights ( l, 1<<i, cl.worldmodel->nodes );
}
}
 
 
/*
=============================================================================
 
LIGHT SAMPLING
 
=============================================================================
*/
 
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
 
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);
}
 
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;
 
if (r < r_refdef.ambientlight)
r = r_refdef.ambientlight;
 
return r;
}
 
/contrib/other/sdlquake-1.0.9/r_local.h
0,0 → 1,316
/*
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_local.h -- private refresh defs
 
#ifndef GLQUAKE
#include "r_shared.h"
 
#define ALIAS_BASE_SIZE_RATIO (1.0 / 11.0)
// normalizing factor so player model works out to about
// 1 pixel per triangle
 
#define BMODEL_FULLY_CLIPPED 0x10 // value returned by R_BmodelCheckBBox ()
// if bbox is trivially rejected
 
//===========================================================================
// viewmodel lighting
 
typedef struct {
int ambientlight;
int shadelight;
float *plightvec;
} alight_t;
 
//===========================================================================
// clipped bmodel edges
 
typedef struct bedge_s
{
mvertex_t *v[2];
struct bedge_s *pnext;
} bedge_t;
 
typedef struct {
float fv[3]; // viewspace x, y
} auxvert_t;
 
//===========================================================================
 
extern cvar_t r_draworder;
extern cvar_t r_speeds;
extern cvar_t r_timegraph;
extern cvar_t r_graphheight;
extern cvar_t r_clearcolor;
extern cvar_t r_waterwarp;
extern cvar_t r_fullbright;
extern cvar_t r_drawentities;
extern cvar_t r_aliasstats;
extern cvar_t r_dspeeds;
extern cvar_t r_drawflat;
extern cvar_t r_ambient;
extern cvar_t r_reportsurfout;
extern cvar_t r_maxsurfs;
extern cvar_t r_numsurfs;
extern cvar_t r_reportedgeout;
extern cvar_t r_maxedges;
extern cvar_t r_numedges;
 
#define XCENTERING (1.0 / 2.0)
#define YCENTERING (1.0 / 2.0)
 
#define CLIP_EPSILON 0.001
 
#define BACKFACE_EPSILON 0.01
 
//===========================================================================
 
#define DIST_NOT_SET 98765
 
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct clipplane_s
{
vec3_t normal;
float dist;
struct clipplane_s *next;
byte leftedge;
byte rightedge;
byte reserved[2];
} clipplane_t;
 
extern clipplane_t view_clipplanes[4];
 
//=============================================================================
 
void R_RenderWorld (void);
 
//=============================================================================
 
extern mplane_t screenedge[4];
 
extern vec3_t r_origin;
 
extern vec3_t r_entorigin;
 
extern float screenAspect;
extern float verticalFieldOfView;
extern float xOrigin, yOrigin;
 
extern int r_visframecount;
 
//=============================================================================
 
extern int vstartscan;
 
 
void R_ClearPolyList (void);
void R_DrawPolyList (void);
 
//
// current entity info
//
extern qboolean insubmodel;
extern vec3_t r_worldmodelorg;
 
 
void R_DrawSprite (void);
void R_RenderFace (msurface_t *fa, int clipflags);
void R_RenderPoly (msurface_t *fa, int clipflags);
void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf);
void R_TransformPlane (mplane_t *p, float *normal, float *dist);
void R_TransformFrustum (void);
void R_SetSkyFrame (void);
void R_DrawSurfaceBlock16 (void);
void R_DrawSurfaceBlock8 (void);
texture_t *R_TextureAnimation (texture_t *base);
 
#if id386
 
void R_DrawSurfaceBlock8_mip0 (void);
void R_DrawSurfaceBlock8_mip1 (void);
void R_DrawSurfaceBlock8_mip2 (void);
void R_DrawSurfaceBlock8_mip3 (void);
 
#endif
 
void R_GenSkyTile (void *pdest);
void R_GenSkyTile16 (void *pdest);
void R_Surf8Patch (void);
void R_Surf16Patch (void);
void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags);
void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel);
 
void R_AddPolygonEdges (emitpoint_t *pverts, int numverts, int miplevel);
surf_t *R_GetSurf (void);
void R_AliasDrawModel (alight_t *plighting);
void R_BeginEdgeFrame (void);
void R_ScanEdges (void);
void D_DrawSurfaces (void);
void R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist);
void R_StepActiveU (edge_t *pedge);
void R_RemoveEdges (edge_t *pedge);
 
extern void R_Surf8Start (void);
extern void R_Surf8End (void);
extern void R_Surf16Start (void);
extern void R_Surf16End (void);
extern void R_EdgeCodeStart (void);
extern void R_EdgeCodeEnd (void);
 
extern void R_RotateBmodel (void);
 
extern int c_faceclip;
extern int r_polycount;
extern int r_wholepolycount;
 
extern model_t *cl_worldmodel;
 
extern int *pfrustum_indexes[4];
 
// !!! if this is changed, it must be changed in asm_draw.h too !!!
#define NEAR_CLIP 0.01
 
extern int ubasestep, errorterm, erroradjustup, erroradjustdown;
extern int vstartscan;
 
extern fixed16_t sadjust, tadjust;
extern fixed16_t bbextents, bbextentt;
 
#define MAXBVERTINDEXES 1000 // new clipped vertices when clipping bmodels
// to the world BSP
extern mvertex_t *r_ptverts, *r_ptvertsmax;
 
extern vec3_t sbaseaxis[3], tbaseaxis[3];
extern float entity_rotation[3][3];
 
extern int reinit_surfcache;
 
extern int r_currentkey;
extern int r_currentbkey;
 
typedef struct btofpoly_s {
int clipflags;
msurface_t *psurf;
} btofpoly_t;
 
#define MAX_BTOFPOLYS 5000 // FIXME: tune this
 
extern int numbtofpolys;
extern btofpoly_t *pbtofpolys;
 
void R_InitTurb (void);
void R_ZDrawSubmodelPolys (model_t *clmodel);
 
//=========================================================
// Alias models
//=========================================================
 
#define MAXALIASVERTS 2000 // TODO: tune this
#define ALIAS_Z_CLIP_PLANE 5
 
extern int numverts;
extern int a_skinwidth;
extern mtriangle_t *ptriangles;
extern int numtriangles;
extern aliashdr_t *paliashdr;
extern mdl_t *pmdl;
extern float leftclip, topclip, rightclip, bottomclip;
extern int r_acliptype;
extern finalvert_t *pfinalverts;
extern auxvert_t *pauxverts;
 
qboolean R_AliasCheckBBox (void);
 
//=========================================================
// turbulence stuff
 
#define AMP 8*0x10000
#define AMP2 3
#define SPEED 20
 
//=========================================================
// particle stuff
 
void R_DrawParticles (void);
void R_InitParticles (void);
void R_ClearParticles (void);
void R_ReadPointFile_f (void);
void R_SurfacePatch (void);
 
extern int r_amodels_drawn;
extern edge_t *auxedges;
extern int r_numallocatededges;
extern edge_t *r_edges, *edge_p, *edge_max;
 
extern edge_t *newedges[MAXHEIGHT];
extern edge_t *removeedges[MAXHEIGHT];
 
extern int screenwidth;
 
// FIXME: make stack vars when debugging done
extern edge_t edge_head;
extern edge_t edge_tail;
extern edge_t edge_aftertail;
extern int r_bmodelactive;
extern vrect_t *pconupdate;
 
extern float aliasxscale, aliasyscale, aliasxcenter, aliasycenter;
extern float r_aliastransition, r_resfudge;
 
extern int r_outofsurfaces;
extern int r_outofedges;
 
extern mvertex_t *r_pcurrentvertbase;
extern int r_maxvalidedgeoffset;
 
void R_AliasClipTriangle (mtriangle_t *ptri);
 
extern float r_time1;
extern float dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2;
extern float se_time1, se_time2, de_time1, de_time2, dv_time1, dv_time2;
extern int r_frustum_indexes[4*6];
extern int r_maxsurfsseen, r_maxedgesseen, r_cnumsurfs;
extern qboolean r_surfsonstack;
extern cshift_t cshift_water;
extern qboolean r_dowarpold, r_viewchanged;
 
extern mleaf_t *r_viewleaf, *r_oldviewleaf;
 
extern vec3_t r_emins, r_emaxs;
extern mnode_t *r_pefragtopnode;
extern int r_clipflags;
extern int r_dlightframecount;
extern qboolean r_fov_greater_than_90;
 
void R_StoreEfrags (efrag_t **ppefrag);
void R_TimeRefresh_f (void);
void R_TimeGraph (void);
void R_PrintAliasStats (void);
void R_PrintTimes (void);
void R_PrintDSpeeds (void);
void R_AnimateLight (void);
int R_LightPoint (vec3_t p);
void R_SetupFrame (void);
void R_cshift_f (void);
void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1);
void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip);
void R_SplitEntityOnNode2 (mnode_t *node);
void R_MarkLights (dlight_t *light, int bit, mnode_t *node);
 
#endif
/contrib/other/sdlquake-1.0.9/r_main.c
0,0 → 1,1085
/*
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_main.c
 
#include "quakedef.h"
#include "r_local.h"
 
//define PASSAGES
 
void *colormap;
vec3_t viewlightvec;
alight_t r_viewlighting = {128, 192, viewlightvec};
float r_time1;
int r_numallocatededges;
qboolean r_drawpolys;
qboolean r_drawculledpolys;
qboolean r_worldpolysbacktofront;
qboolean r_recursiveaffinetriangles = true;
int r_pixbytes = 1;
float r_aliasuvscale = 1.0;
int r_outofsurfaces;
int r_outofedges;
 
qboolean r_dowarp, r_dowarpold, r_viewchanged;
 
int numbtofpolys;
btofpoly_t *pbtofpolys;
mvertex_t *r_pcurrentvertbase;
 
int c_surf;
int r_maxsurfsseen, r_maxedgesseen, r_cnumsurfs;
qboolean r_surfsonstack;
int r_clipflags;
 
byte *r_warpbuffer;
 
byte *r_stack_start;
 
qboolean r_fov_greater_than_90;
 
//
// view origin
//
vec3_t vup, base_vup;
vec3_t vpn, base_vpn;
vec3_t vright, base_vright;
vec3_t r_origin;
 
//
// screen size info
//
refdef_t r_refdef;
float xcenter, ycenter;
float xscale, yscale;
float xscaleinv, yscaleinv;
float xscaleshrink, yscaleshrink;
float aliasxscale, aliasyscale, aliasxcenter, aliasycenter;
 
int screenwidth;
 
float pixelAspect;
float screenAspect;
float verticalFieldOfView;
float xOrigin, yOrigin;
 
mplane_t screenedge[4];
 
//
// refresh flags
//
int r_framecount = 1; // so frame counts initialized to 0 don't match
int r_visframecount;
int d_spanpixcount;
int r_polycount;
int r_drawnpolycount;
int r_wholepolycount;
 
#define VIEWMODNAME_LENGTH 256
char viewmodname[VIEWMODNAME_LENGTH+1];
int modcount;
 
int *pfrustum_indexes[4];
int r_frustum_indexes[4*6];
 
int reinit_surfcache = 1; // if 1, surface cache is currently empty and
// must be reinitialized for current cache size
 
mleaf_t *r_viewleaf, *r_oldviewleaf;
 
texture_t *r_notexture_mip;
 
float r_aliastransition, r_resfudge;
 
int d_lightstylevalue[256]; // 8.8 fraction of base light value
 
float dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2;
float se_time1, se_time2, de_time1, de_time2, dv_time1, dv_time2;
 
void R_MarkLeaves (void);
 
cvar_t r_draworder = {"r_draworder","0"};
cvar_t r_speeds = {"r_speeds","0"};
cvar_t r_timegraph = {"r_timegraph","0"};
cvar_t r_graphheight = {"r_graphheight","10"};
cvar_t r_clearcolor = {"r_clearcolor","2"};
cvar_t r_waterwarp = {"r_waterwarp","1"};
cvar_t r_fullbright = {"r_fullbright","0"};
cvar_t r_drawentities = {"r_drawentities","1"};
cvar_t r_drawviewmodel = {"r_drawviewmodel","1"};
cvar_t r_aliasstats = {"r_polymodelstats","0"};
cvar_t r_dspeeds = {"r_dspeeds","0"};
cvar_t r_drawflat = {"r_drawflat", "0"};
cvar_t r_ambient = {"r_ambient", "0"};
cvar_t r_reportsurfout = {"r_reportsurfout", "0"};
cvar_t r_maxsurfs = {"r_maxsurfs", "0"};
cvar_t r_numsurfs = {"r_numsurfs", "0"};
cvar_t r_reportedgeout = {"r_reportedgeout", "0"};
cvar_t r_maxedges = {"r_maxedges", "0"};
cvar_t r_numedges = {"r_numedges", "0"};
cvar_t r_aliastransbase = {"r_aliastransbase", "200"};
cvar_t r_aliastransadj = {"r_aliastransadj", "100"};
 
extern cvar_t scr_fov;
 
void CreatePassages (void);
void SetVisibilityByPassages (void);
 
/*
==================
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;
}
}
}
 
/*
===============
R_Init
===============
*/
void R_Init (void)
{
int dummy;
// get stack position so we can guess if we are going to overflow
r_stack_start = (byte *)&dummy;
R_InitTurb ();
Cmd_AddCommand ("timerefresh", R_TimeRefresh_f);
Cmd_AddCommand ("pointfile", R_ReadPointFile_f);
 
Cvar_RegisterVariable (&r_draworder);
Cvar_RegisterVariable (&r_speeds);
Cvar_RegisterVariable (&r_timegraph);
Cvar_RegisterVariable (&r_graphheight);
Cvar_RegisterVariable (&r_drawflat);
Cvar_RegisterVariable (&r_ambient);
Cvar_RegisterVariable (&r_clearcolor);
Cvar_RegisterVariable (&r_waterwarp);
Cvar_RegisterVariable (&r_fullbright);
Cvar_RegisterVariable (&r_drawentities);
Cvar_RegisterVariable (&r_drawviewmodel);
Cvar_RegisterVariable (&r_aliasstats);
Cvar_RegisterVariable (&r_dspeeds);
Cvar_RegisterVariable (&r_reportsurfout);
Cvar_RegisterVariable (&r_maxsurfs);
Cvar_RegisterVariable (&r_numsurfs);
Cvar_RegisterVariable (&r_reportedgeout);
Cvar_RegisterVariable (&r_maxedges);
Cvar_RegisterVariable (&r_numedges);
Cvar_RegisterVariable (&r_aliastransbase);
Cvar_RegisterVariable (&r_aliastransadj);
 
Cvar_SetValue ("r_maxedges", (float)NUMSTACKEDGES);
Cvar_SetValue ("r_maxsurfs", (float)NUMSTACKSURFACES);
 
view_clipplanes[0].leftedge = true;
view_clipplanes[1].rightedge = true;
view_clipplanes[1].leftedge = view_clipplanes[2].leftedge =
view_clipplanes[3].leftedge = false;
view_clipplanes[0].rightedge = view_clipplanes[2].rightedge =
view_clipplanes[3].rightedge = false;
 
r_refdef.xOrigin = XCENTERING;
r_refdef.yOrigin = YCENTERING;
 
R_InitParticles ();
 
// TODO: collect 386-specific code in one place
#if id386
Sys_MakeCodeWriteable ((long)R_EdgeCodeStart,
(long)R_EdgeCodeEnd - (long)R_EdgeCodeStart);
#endif // id386
 
D_Init ();
}
 
/*
===============
R_NewMap
===============
*/
void R_NewMap (void)
{
int i;
// 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 ();
 
r_cnumsurfs = r_maxsurfs.value;
 
if (r_cnumsurfs <= MINSURFACES)
r_cnumsurfs = MINSURFACES;
 
if (r_cnumsurfs > NUMSTACKSURFACES)
{
surfaces = Hunk_AllocName (r_cnumsurfs * sizeof(surf_t), "surfaces");
surface_p = surfaces;
surf_max = &surfaces[r_cnumsurfs];
r_surfsonstack = false;
// surface 0 doesn't really exist; it's just a dummy because index 0
// is used to indicate no edge attached to surface
surfaces--;
R_SurfacePatch ();
}
else
{
r_surfsonstack = true;
}
 
r_maxedgesseen = 0;
r_maxsurfsseen = 0;
 
r_numallocatededges = r_maxedges.value;
 
if (r_numallocatededges < MINEDGES)
r_numallocatededges = MINEDGES;
 
if (r_numallocatededges <= NUMSTACKEDGES)
{
auxedges = NULL;
}
else
{
auxedges = Hunk_AllocName (r_numallocatededges * sizeof(edge_t),
"edges");
}
 
r_dowarpold = false;
r_viewchanged = false;
#ifdef PASSAGES
CreatePassages ();
#endif
}
 
 
/*
===============
R_SetVrect
===============
*/
void R_SetVrect (vrect_t *pvrectin, vrect_t *pvrect, int lineadj)
{
int h;
float size;
 
size = scr_viewsize.value > 100 ? 100 : scr_viewsize.value;
if (cl.intermission)
{
size = 100;
lineadj = 0;
}
size /= 100;
 
h = pvrectin->height - lineadj;
pvrect->width = pvrectin->width * size;
if (pvrect->width < 96)
{
size = 96.0 / pvrectin->width;
pvrect->width = 96; // min for icons
}
pvrect->width &= ~7;
pvrect->height = pvrectin->height * size;
if (pvrect->height > pvrectin->height - lineadj)
pvrect->height = pvrectin->height - lineadj;
 
pvrect->height &= ~1;
 
pvrect->x = (pvrectin->width - pvrect->width)/2;
pvrect->y = (h - pvrect->height)/2;
 
{
if (lcd_x.value)
{
pvrect->y >>= 1;
pvrect->height >>= 1;
}
}
}
 
 
/*
===============
R_ViewChanged
 
Called every time the vid structure or r_refdef changes.
Guaranteed to be called before the first refresh
===============
*/
void R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect)
{
int i;
float res_scale;
 
r_viewchanged = true;
 
R_SetVrect (pvrect, &r_refdef.vrect, lineadj);
 
r_refdef.horizontalFieldOfView = 2.0 * tan (r_refdef.fov_x/360*M_PI);
r_refdef.fvrectx = (float)r_refdef.vrect.x;
r_refdef.fvrectx_adj = (float)r_refdef.vrect.x - 0.5;
r_refdef.vrect_x_adj_shift20 = (r_refdef.vrect.x<<20) + (1<<19) - 1;
r_refdef.fvrecty = (float)r_refdef.vrect.y;
r_refdef.fvrecty_adj = (float)r_refdef.vrect.y - 0.5;
r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width;
r_refdef.vrectright_adj_shift20 = (r_refdef.vrectright<<20) + (1<<19) - 1;
r_refdef.fvrectright = (float)r_refdef.vrectright;
r_refdef.fvrectright_adj = (float)r_refdef.vrectright - 0.5;
r_refdef.vrectrightedge = (float)r_refdef.vrectright - 0.99;
r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height;
r_refdef.fvrectbottom = (float)r_refdef.vrectbottom;
r_refdef.fvrectbottom_adj = (float)r_refdef.vrectbottom - 0.5;
 
r_refdef.aliasvrect.x = (int)(r_refdef.vrect.x * r_aliasuvscale);
r_refdef.aliasvrect.y = (int)(r_refdef.vrect.y * r_aliasuvscale);
r_refdef.aliasvrect.width = (int)(r_refdef.vrect.width * r_aliasuvscale);
r_refdef.aliasvrect.height = (int)(r_refdef.vrect.height * r_aliasuvscale);
r_refdef.aliasvrectright = r_refdef.aliasvrect.x +
r_refdef.aliasvrect.width;
r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y +
r_refdef.aliasvrect.height;
 
pixelAspect = aspect;
xOrigin = r_refdef.xOrigin;
yOrigin = r_refdef.yOrigin;
screenAspect = r_refdef.vrect.width*pixelAspect /
r_refdef.vrect.height;
// 320*200 1.0 pixelAspect = 1.6 screenAspect
// 320*240 1.0 pixelAspect = 1.3333 screenAspect
// proper 320*200 pixelAspect = 0.8333333
 
verticalFieldOfView = r_refdef.horizontalFieldOfView / screenAspect;
 
// values for perspective projection
// if math were exact, the values would range from 0.5 to to range+0.5
// hopefully they wll be in the 0.000001 to range+.999999 and truncate
// the polygon rasterization will never render in the first row or column
// but will definately render in the [range] row and column, so adjust the
// buffer origin to get an exact edge to edge fill
xcenter = ((float)r_refdef.vrect.width * XCENTERING) +
r_refdef.vrect.x - 0.5;
aliasxcenter = xcenter * r_aliasuvscale;
ycenter = ((float)r_refdef.vrect.height * YCENTERING) +
r_refdef.vrect.y - 0.5;
aliasycenter = ycenter * r_aliasuvscale;
 
xscale = r_refdef.vrect.width / r_refdef.horizontalFieldOfView;
aliasxscale = xscale * r_aliasuvscale;
xscaleinv = 1.0 / xscale;
yscale = xscale * pixelAspect;
aliasyscale = yscale * r_aliasuvscale;
yscaleinv = 1.0 / yscale;
xscaleshrink = (r_refdef.vrect.width-6)/r_refdef.horizontalFieldOfView;
yscaleshrink = xscaleshrink*pixelAspect;
 
// left side clip
screenedge[0].normal[0] = -1.0 / (xOrigin*r_refdef.horizontalFieldOfView);
screenedge[0].normal[1] = 0;
screenedge[0].normal[2] = 1;
screenedge[0].type = PLANE_ANYZ;
// right side clip
screenedge[1].normal[0] =
1.0 / ((1.0-xOrigin)*r_refdef.horizontalFieldOfView);
screenedge[1].normal[1] = 0;
screenedge[1].normal[2] = 1;
screenedge[1].type = PLANE_ANYZ;
// top side clip
screenedge[2].normal[0] = 0;
screenedge[2].normal[1] = -1.0 / (yOrigin*verticalFieldOfView);
screenedge[2].normal[2] = 1;
screenedge[2].type = PLANE_ANYZ;
// bottom side clip
screenedge[3].normal[0] = 0;
screenedge[3].normal[1] = 1.0 / ((1.0-yOrigin)*verticalFieldOfView);
screenedge[3].normal[2] = 1;
screenedge[3].type = PLANE_ANYZ;
for (i=0 ; i<4 ; i++)
VectorNormalize (screenedge[i].normal);
 
res_scale = sqrt ((double)(r_refdef.vrect.width * r_refdef.vrect.height) /
(320.0 * 152.0)) *
(2.0 / r_refdef.horizontalFieldOfView);
r_aliastransition = r_aliastransbase.value * res_scale;
r_resfudge = r_aliastransadj.value * res_scale;
 
if (scr_fov.value <= 90.0)
r_fov_greater_than_90 = false;
else
r_fov_greater_than_90 = true;
 
// TODO: collect 386-specific code in one place
#if id386
if (r_pixbytes == 1)
{
Sys_MakeCodeWriteable ((long)R_Surf8Start,
(long)R_Surf8End - (long)R_Surf8Start);
colormap = vid.colormap;
R_Surf8Patch ();
}
else
{
Sys_MakeCodeWriteable ((long)R_Surf16Start,
(long)R_Surf16End - (long)R_Surf16Start);
colormap = vid.colormap16;
R_Surf16Patch ();
}
#endif // id386
 
D_ViewChanged ();
}
 
 
/*
===============
R_MarkLeaves
===============
*/
void R_MarkLeaves (void)
{
byte *vis;
mnode_t *node;
int i;
 
if (r_oldviewleaf == r_viewleaf)
return;
r_visframecount++;
r_oldviewleaf = r_viewleaf;
 
vis = Mod_LeafPVS (r_viewleaf, cl.worldmodel);
for (i=0 ; i<cl.worldmodel->numleafs ; i++)
{
if (vis[i>>3] & (1<<(i&7)))
{
node = (mnode_t *)&cl.worldmodel->leafs[i+1];
do
{
if (node->visframe == r_visframecount)
break;
node->visframe = r_visframecount;
node = node->parent;
} while (node);
}
}
}
 
 
/*
=============
R_DrawEntitiesOnList
=============
*/
void R_DrawEntitiesOnList (void)
{
int i, j;
int lnum;
alight_t lighting;
// FIXME: remove and do real lighting
float lightvec[3] = {-1, 0, 0};
vec3_t dist;
float add;
 
if (!r_drawentities.value)
return;
 
for (i=0 ; i<cl_numvisedicts ; i++)
{
currententity = cl_visedicts[i];
 
if (currententity == &cl_entities[cl.viewentity])
continue; // don't draw the player
 
switch (currententity->model->type)
{
case mod_sprite:
VectorCopy (currententity->origin, r_entorigin);
VectorSubtract (r_origin, r_entorigin, modelorg);
R_DrawSprite ();
break;
 
case mod_alias:
VectorCopy (currententity->origin, r_entorigin);
VectorSubtract (r_origin, r_entorigin, modelorg);
 
// see if the bounding box lets us trivially reject, also sets
// trivial accept status
if (R_AliasCheckBBox ())
{
j = R_LightPoint (currententity->origin);
lighting.ambientlight = j;
lighting.shadelight = j;
 
lighting.plightvec = lightvec;
 
for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
{
if (cl_dlights[lnum].die >= cl.time)
{
VectorSubtract (currententity->origin,
cl_dlights[lnum].origin,
dist);
add = cl_dlights[lnum].radius - Length(dist);
if (add > 0)
lighting.ambientlight += add;
}
}
// clamp lighting so it doesn't overbright as much
if (lighting.ambientlight > 128)
lighting.ambientlight = 128;
if (lighting.ambientlight + lighting.shadelight > 192)
lighting.shadelight = 192 - lighting.ambientlight;
 
R_AliasDrawModel (&lighting);
}
 
break;
 
default:
break;
}
}
}
 
/*
=============
R_DrawViewModel
=============
*/
void R_DrawViewModel (void)
{
// FIXME: remove and do real lighting
float lightvec[3] = {-1, 0, 0};
int j;
int lnum;
vec3_t dist;
float add;
dlight_t *dl;
if (!r_drawviewmodel.value || r_fov_greater_than_90)
return;
 
if (cl.items & IT_INVISIBILITY)
return;
 
if (cl.stats[STAT_HEALTH] <= 0)
return;
 
currententity = &cl.viewent;
if (!currententity->model)
return;
 
VectorCopy (currententity->origin, r_entorigin);
VectorSubtract (r_origin, r_entorigin, modelorg);
 
VectorCopy (vup, viewlightvec);
VectorInverse (viewlightvec);
 
j = R_LightPoint (currententity->origin);
 
if (j < 24)
j = 24; // allways give some light on gun
r_viewlighting.ambientlight = j;
r_viewlighting.shadelight = j;
 
// add dynamic lights
for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
{
dl = &cl_dlights[lnum];
if (!dl->radius)
continue;
if (!dl->radius)
continue;
if (dl->die < cl.time)
continue;
 
VectorSubtract (currententity->origin, dl->origin, dist);
add = dl->radius - Length(dist);
if (add > 0)
r_viewlighting.ambientlight += add;
}
 
// clamp lighting so it doesn't overbright as much
if (r_viewlighting.ambientlight > 128)
r_viewlighting.ambientlight = 128;
if (r_viewlighting.ambientlight + r_viewlighting.shadelight > 192)
r_viewlighting.shadelight = 192 - r_viewlighting.ambientlight;
 
r_viewlighting.plightvec = lightvec;
 
#ifdef QUAKE2
cl.light_level = r_viewlighting.ambientlight;
#endif
 
R_AliasDrawModel (&r_viewlighting);
}
 
 
/*
=============
R_BmodelCheckBBox
=============
*/
int R_BmodelCheckBBox (model_t *clmodel, float *minmaxs)
{
int i, *pindex, clipflags;
vec3_t acceptpt, rejectpt;
double d;
 
clipflags = 0;
 
if (currententity->angles[0] || currententity->angles[1]
|| currententity->angles[2])
{
for (i=0 ; i<4 ; i++)
{
d = DotProduct (currententity->origin, view_clipplanes[i].normal);
d -= view_clipplanes[i].dist;
 
if (d <= -clmodel->radius)
return BMODEL_FULLY_CLIPPED;
 
if (d <= clmodel->radius)
clipflags |= (1<<i);
}
}
else
{
for (i=0 ; i<4 ; i++)
{
// generate accept and reject points
// FIXME: do with fast look-ups or integer tests based on the sign bit
// of the floating point values
 
pindex = pfrustum_indexes[i];
 
rejectpt[0] = minmaxs[pindex[0]];
rejectpt[1] = minmaxs[pindex[1]];
rejectpt[2] = minmaxs[pindex[2]];
d = DotProduct (rejectpt, view_clipplanes[i].normal);
d -= view_clipplanes[i].dist;
 
if (d <= 0)
return BMODEL_FULLY_CLIPPED;
 
acceptpt[0] = minmaxs[pindex[3+0]];
acceptpt[1] = minmaxs[pindex[3+1]];
acceptpt[2] = minmaxs[pindex[3+2]];
 
d = DotProduct (acceptpt, view_clipplanes[i].normal);
d -= view_clipplanes[i].dist;
 
if (d <= 0)
clipflags |= (1<<i);
}
}
 
return clipflags;
}
 
 
/*
=============
R_DrawBEntitiesOnList
=============
*/
void R_DrawBEntitiesOnList (void)
{
int i, j, k, clipflags;
vec3_t oldorigin;
model_t *clmodel;
float minmaxs[6];
 
if (!r_drawentities.value)
return;
 
VectorCopy (modelorg, oldorigin);
insubmodel = true;
r_dlightframecount = r_framecount;
 
for (i=0 ; i<cl_numvisedicts ; i++)
{
currententity = cl_visedicts[i];
 
switch (currententity->model->type)
{
case mod_brush:
 
clmodel = currententity->model;
 
// see if the bounding box lets us trivially reject, also sets
// trivial accept status
for (j=0 ; j<3 ; j++)
{
minmaxs[j] = currententity->origin[j] +
clmodel->mins[j];
minmaxs[3+j] = currententity->origin[j] +
clmodel->maxs[j];
}
 
clipflags = R_BmodelCheckBBox (clmodel, minmaxs);
 
if (clipflags != BMODEL_FULLY_CLIPPED)
{
VectorCopy (currententity->origin, r_entorigin);
VectorSubtract (r_origin, r_entorigin, modelorg);
// FIXME: is this needed?
VectorCopy (modelorg, r_worldmodelorg);
r_pcurrentvertbase = clmodel->vertexes;
// FIXME: stop transforming twice
R_RotateBmodel ();
 
// calculate dynamic lighting for bmodel if it's not an
// instanced model
if (clmodel->firstmodelsurface != 0)
{
for (k=0 ; k<MAX_DLIGHTS ; k++)
{
if ((cl_dlights[k].die < cl.time) ||
(!cl_dlights[k].radius))
{
continue;
}
 
R_MarkLights (&cl_dlights[k], 1<<k,
clmodel->nodes + clmodel->hulls[0].firstclipnode);
}
}
 
// if the driver wants polygons, deliver those. Z-buffering is on
// at this point, so no clipping to the world tree is needed, just
// frustum clipping
if (r_drawpolys | r_drawculledpolys)
{
R_ZDrawSubmodelPolys (clmodel);
}
else
{
r_pefragtopnode = NULL;
 
for (j=0 ; j<3 ; j++)
{
r_emins[j] = minmaxs[j];
r_emaxs[j] = minmaxs[3+j];
}
 
R_SplitEntityOnNode2 (cl.worldmodel->nodes);
 
if (r_pefragtopnode)
{
currententity->topnode = r_pefragtopnode;
if (r_pefragtopnode->contents >= 0)
{
// not a leaf; has to be clipped to the world BSP
r_clipflags = clipflags;
R_DrawSolidClippedSubmodelPolygons (clmodel);
}
else
{
// falls entirely in one leaf, so we just put all the
// edges in the edge list and let 1/z sorting handle
// drawing order
R_DrawSubmodelPolygons (clmodel, clipflags);
}
currententity->topnode = NULL;
}
}
 
// put back world rotation and frustum clipping
// FIXME: R_RotateBmodel should just work off base_vxx
VectorCopy (base_vpn, vpn);
VectorCopy (base_vup, vup);
VectorCopy (base_vright, vright);
VectorCopy (base_modelorg, modelorg);
VectorCopy (oldorigin, modelorg);
R_TransformFrustum ();
}
 
break;
 
default:
break;
}
}
 
insubmodel = false;
}
 
 
/*
================
R_EdgeDrawing
================
*/
void R_EdgeDrawing (void)
{
edge_t ledges[NUMSTACKEDGES +
((CACHE_SIZE - 1) / sizeof(edge_t)) + 1];
surf_t lsurfs[NUMSTACKSURFACES +
((CACHE_SIZE - 1) / sizeof(surf_t)) + 1];
 
if (auxedges)
{
r_edges = auxedges;
}
else
{
r_edges = (edge_t *)
(((long)&ledges[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
}
 
if (r_surfsonstack)
{
surfaces = (surf_t *)
(((long)&lsurfs[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
surf_max = &surfaces[r_cnumsurfs];
// surface 0 doesn't really exist; it's just a dummy because index 0
// is used to indicate no edge attached to surface
surfaces--;
R_SurfacePatch ();
}
 
R_BeginEdgeFrame ();
 
if (r_dspeeds.value)
{
rw_time1 = Sys_FloatTime ();
}
 
R_RenderWorld ();
 
if (r_drawculledpolys)
R_ScanEdges ();
 
// only the world can be drawn back to front with no z reads or compares, just
// z writes, so have the driver turn z compares on now
D_TurnZOn ();
 
if (r_dspeeds.value)
{
rw_time2 = Sys_FloatTime ();
db_time1 = rw_time2;
}
 
R_DrawBEntitiesOnList ();
 
if (r_dspeeds.value)
{
db_time2 = Sys_FloatTime ();
se_time1 = db_time2;
}
 
if (!r_dspeeds.value)
{
VID_UnlockBuffer ();
S_ExtraUpdate (); // don't let sound get messed up if going slow
VID_LockBuffer ();
}
if (!(r_drawpolys | r_drawculledpolys))
R_ScanEdges ();
}
 
 
/*
================
R_RenderView
 
r_refdef must be set before the first call
================
*/
void R_RenderView_ (void)
{
byte warpbuffer[WARP_WIDTH * WARP_HEIGHT];
 
r_warpbuffer = warpbuffer;
 
if (r_timegraph.value || r_speeds.value || r_dspeeds.value)
r_time1 = Sys_FloatTime ();
 
R_SetupFrame ();
 
#ifdef PASSAGES
SetVisibilityByPassages ();
#else
R_MarkLeaves (); // done here so we know if we're in water
#endif
 
// make FDIV fast. This reduces timing precision after we've been running for a
// while, so we don't do it globally. This also sets chop mode, and we do it
// here so that setup stuff like the refresh area calculations match what's
// done in screen.c
Sys_LowFPPrecision ();
 
if (!cl_entities[0].model || !cl.worldmodel)
Sys_Error ("R_RenderView: NULL worldmodel");
if (!r_dspeeds.value)
{
VID_UnlockBuffer ();
S_ExtraUpdate (); // don't let sound get messed up if going slow
VID_LockBuffer ();
}
R_EdgeDrawing ();
 
if (!r_dspeeds.value)
{
VID_UnlockBuffer ();
S_ExtraUpdate (); // don't let sound get messed up if going slow
VID_LockBuffer ();
}
if (r_dspeeds.value)
{
se_time2 = Sys_FloatTime ();
de_time1 = se_time2;
}
 
R_DrawEntitiesOnList ();
 
if (r_dspeeds.value)
{
de_time2 = Sys_FloatTime ();
dv_time1 = de_time2;
}
 
R_DrawViewModel ();
 
if (r_dspeeds.value)
{
dv_time2 = Sys_FloatTime ();
dp_time1 = Sys_FloatTime ();
}
 
R_DrawParticles ();
 
if (r_dspeeds.value)
dp_time2 = Sys_FloatTime ();
 
if (r_dowarp)
D_WarpScreen ();
 
V_SetContentsColor (r_viewleaf->contents);
 
if (r_timegraph.value)
R_TimeGraph ();
 
if (r_aliasstats.value)
R_PrintAliasStats ();
if (r_speeds.value)
R_PrintTimes ();
 
if (r_dspeeds.value)
R_PrintDSpeeds ();
 
if (r_reportsurfout.value && r_outofsurfaces)
Con_Printf ("Short %d surfaces\n", r_outofsurfaces);
 
if (r_reportedgeout.value && r_outofedges)
Con_Printf ("Short roughly %d edges\n", r_outofedges * 2 / 3);
 
// back to high floating-point precision
Sys_HighFPPrecision ();
}
 
void R_RenderView (void)
{
int dummy;
int delta;
delta = (byte *)&dummy - r_stack_start;
if (delta < -10000 || delta > 10000)
Sys_Error ("R_RenderView: called without enough stack");
 
if ( Hunk_LowMark() & 3 )
Sys_Error ("Hunk is missaligned");
 
if ( (long)(&dummy) & 3 )
Sys_Error ("Stack is missaligned");
 
if ( (long)(&r_warpbuffer) & 3 )
Sys_Error ("Globals are missaligned");
 
R_RenderView_ ();
}
 
/*
================
R_InitTurb
================
*/
void R_InitTurb (void)
{
int i;
for (i=0 ; i<(SIN_BUFFER_SIZE) ; i++)
{
sintable[i] = AMP + sin(i*3.14159*2/CYCLE)*AMP;
intsintable[i] = AMP2 + sin(i*3.14159*2/CYCLE)*AMP2; // AMP2, not 20
}
}
 
/contrib/other/sdlquake-1.0.9/r_misc.c
0,0 → 1,523
/*
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"
#include "r_local.h"
 
 
/*
===============
R_CheckVariables
===============
*/
void R_CheckVariables (void)
{
static float oldbright;
 
if (r_fullbright.value != oldbright)
{
oldbright = r_fullbright.value;
D_FlushCaches (); // so all lighting changes
}
}
 
 
/*
============
Show
 
Debugging use
============
*/
void Show (void)
{
vrect_t vr;
 
vr.x = vr.y = 0;
vr.width = vid.width;
vr.height = vid.height;
vr.pnext = NULL;
VID_Update (&vr);
}
 
 
/*
====================
R_TimeRefresh_f
 
For program optimization
====================
*/
void R_TimeRefresh_f (void)
{
int i;
float start, stop, time;
int startangle;
vrect_t vr;
 
startangle = r_refdef.viewangles[1];
start = Sys_FloatTime ();
for (i=0 ; i<128 ; i++)
{
r_refdef.viewangles[1] = i/128.0*360.0;
 
VID_LockBuffer ();
 
R_RenderView ();
 
VID_UnlockBuffer ();
 
vr.x = r_refdef.vrect.x;
vr.y = r_refdef.vrect.y;
vr.width = r_refdef.vrect.width;
vr.height = r_refdef.vrect.height;
vr.pnext = NULL;
VID_Update (&vr);
}
stop = Sys_FloatTime ();
time = stop-start;
Con_Printf ("%f seconds (%f fps)\n", time, 128/time);
r_refdef.viewangles[1] = startangle;
}
 
 
/*
================
R_LineGraph
 
Only called by R_DisplayTime
================
*/
void R_LineGraph (int x, int y, int h)
{
int i;
byte *dest;
int s;
 
// FIXME: should be disabled on no-buffer adapters, or should be in the driver
x += r_refdef.vrect.x;
y += r_refdef.vrect.y;
dest = vid.buffer + vid.rowbytes*y + x;
s = r_graphheight.value;
if (h>s)
h = s;
for (i=0 ; i<h ; i++, dest -= vid.rowbytes*2)
{
dest[0] = 0xff;
*(dest-vid.rowbytes) = 0x30;
}
for ( ; i<s ; i++, dest -= vid.rowbytes*2)
{
dest[0] = 0x30;
*(dest-vid.rowbytes) = 0x30;
}
}
 
/*
==============
R_TimeGraph
 
Performance monitoring tool
==============
*/
#define MAX_TIMINGS 100
extern float mouse_x, mouse_y;
void R_TimeGraph (void)
{
static int timex;
int a;
float r_time2;
static byte r_timings[MAX_TIMINGS];
int x;
r_time2 = Sys_FloatTime ();
 
a = (r_time2-r_time1)/0.01;
//a = fabs(mouse_y * 0.05);
//a = (int)((r_refdef.vieworg[2] + 1024)/1)%(int)r_graphheight.value;
//a = fabs(velocity[0])/20;
//a = ((int)fabs(origin[0])/8)%20;
//a = (cl.idealpitch + 30)/5;
r_timings[timex] = a;
a = timex;
 
if (r_refdef.vrect.width <= MAX_TIMINGS)
x = r_refdef.vrect.width-1;
else
x = r_refdef.vrect.width -
(r_refdef.vrect.width - MAX_TIMINGS)/2;
do
{
R_LineGraph (x, r_refdef.vrect.height-2, r_timings[a]);
if (x==0)
break; // screen too small to hold entire thing
x--;
a--;
if (a == -1)
a = MAX_TIMINGS-1;
} while (a != timex);
 
timex = (timex+1)%MAX_TIMINGS;
}
 
 
/*
=============
R_PrintTimes
=============
*/
void R_PrintTimes (void)
{
float r_time2;
float ms;
 
r_time2 = Sys_FloatTime ();
 
ms = 1000* (r_time2 - r_time1);
Con_Printf ("%5.1f ms %3i/%3i/%3i poly %3i surf\n",
ms, c_faceclip, r_polycount, r_drawnpolycount, c_surf);
c_surf = 0;
}
 
 
/*
=============
R_PrintDSpeeds
=============
*/
void R_PrintDSpeeds (void)
{
float ms, dp_time, r_time2, rw_time, db_time, se_time, de_time, dv_time;
 
r_time2 = Sys_FloatTime ();
 
dp_time = (dp_time2 - dp_time1) * 1000;
rw_time = (rw_time2 - rw_time1) * 1000;
db_time = (db_time2 - db_time1) * 1000;
se_time = (se_time2 - se_time1) * 1000;
de_time = (de_time2 - de_time1) * 1000;
dv_time = (dv_time2 - dv_time1) * 1000;
ms = (r_time2 - r_time1) * 1000;
 
Con_Printf ("%3i %4.1fp %3iw %4.1fb %3is %4.1fe %4.1fv\n",
(int)ms, dp_time, (int)rw_time, db_time, (int)se_time, de_time,
dv_time);
}
 
 
/*
=============
R_PrintAliasStats
=============
*/
void R_PrintAliasStats (void)
{
Con_Printf ("%3i polygon model drawn\n", r_amodels_drawn);
}
 
 
void WarpPalette (void)
{
int i,j;
byte newpalette[768];
int basecolor[3];
basecolor[0] = 130;
basecolor[1] = 80;
basecolor[2] = 50;
 
// pull the colors halfway to bright brown
for (i=0 ; i<256 ; i++)
{
for (j=0 ; j<3 ; j++)
{
newpalette[i*3+j] = (host_basepal[i*3+j] + basecolor[j])/2;
}
}
VID_ShiftPalette (newpalette);
}
 
 
/*
===================
R_TransformFrustum
===================
*/
void R_TransformFrustum (void)
{
int i;
vec3_t v, v2;
for (i=0 ; i<4 ; i++)
{
v[0] = screenedge[i].normal[2];
v[1] = -screenedge[i].normal[0];
v[2] = screenedge[i].normal[1];
 
v2[0] = v[1]*vright[0] + v[2]*vup[0] + v[0]*vpn[0];
v2[1] = v[1]*vright[1] + v[2]*vup[1] + v[0]*vpn[1];
v2[2] = v[1]*vright[2] + v[2]*vup[2] + v[0]*vpn[2];
 
VectorCopy (v2, view_clipplanes[i].normal);
 
view_clipplanes[i].dist = DotProduct (modelorg, v2);
}
}
 
 
#if !id386
 
/*
================
TransformVector
================
*/
void TransformVector (vec3_t in, vec3_t out)
{
out[0] = DotProduct(in,vright);
out[1] = DotProduct(in,vup);
out[2] = DotProduct(in,vpn);
}
 
#endif
 
 
/*
================
R_TransformPlane
================
*/
void R_TransformPlane (mplane_t *p, float *normal, float *dist)
{
float d;
d = DotProduct (r_origin, p->normal);
*dist = p->dist - d;
// TODO: when we have rotating entities, this will need to use the view matrix
TransformVector (p->normal, normal);
}
 
 
/*
===============
R_SetUpFrustumIndexes
===============
*/
void R_SetUpFrustumIndexes (void)
{
int i, j, *pindex;
 
pindex = r_frustum_indexes;
 
for (i=0 ; i<4 ; i++)
{
for (j=0 ; j<3 ; j++)
{
if (view_clipplanes[i].normal[j] < 0)
{
pindex[j] = j;
pindex[j+3] = j+3;
}
else
{
pindex[j] = j+3;
pindex[j+3] = j;
}
}
 
// FIXME: do just once at start
pfrustum_indexes[i] = pindex;
pindex += 6;
}
}
 
 
/*
===============
R_SetupFrame
===============
*/
void R_SetupFrame (void)
{
int edgecount;
vrect_t vrect;
float w, h;
 
// don't allow cheats in multiplayer
if (cl.maxclients > 1)
{
Cvar_Set ("r_draworder", "0");
Cvar_Set ("r_fullbright", "0");
Cvar_Set ("r_ambient", "0");
Cvar_Set ("r_drawflat", "0");
}
 
if (r_numsurfs.value)
{
if ((surface_p - surfaces) > r_maxsurfsseen)
r_maxsurfsseen = surface_p - surfaces;
 
Con_Printf ("Used %d of %d surfs; %d max\n", surface_p - surfaces,
surf_max - surfaces, r_maxsurfsseen);
}
 
if (r_numedges.value)
{
edgecount = edge_p - r_edges;
 
if (edgecount > r_maxedgesseen)
r_maxedgesseen = edgecount;
 
Con_Printf ("Used %d of %d edges; %d max\n", edgecount,
r_numallocatededges, r_maxedgesseen);
}
 
r_refdef.ambientlight = r_ambient.value;
 
if (r_refdef.ambientlight < 0)
r_refdef.ambientlight = 0;
 
if (!sv.active)
r_draworder.value = 0; // don't let cheaters look behind walls
R_CheckVariables ();
R_AnimateLight ();
 
r_framecount++;
 
numbtofpolys = 0;
 
// debugging
#if 0
r_refdef.vieworg[0]= 80;
r_refdef.vieworg[1]= 64;
r_refdef.vieworg[2]= 40;
r_refdef.viewangles[0]= 0;
r_refdef.viewangles[1]= 46.763641357;
r_refdef.viewangles[2]= 0;
#endif
 
// build the transformation matrix for the given view angles
VectorCopy (r_refdef.vieworg, modelorg);
VectorCopy (r_refdef.vieworg, r_origin);
 
AngleVectors (r_refdef.viewangles, vpn, vright, vup);
 
// current viewleaf
r_oldviewleaf = r_viewleaf;
r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel);
 
r_dowarpold = r_dowarp;
r_dowarp = r_waterwarp.value && (r_viewleaf->contents <= CONTENTS_WATER);
 
if ((r_dowarp != r_dowarpold) || r_viewchanged || lcd_x.value)
{
if (r_dowarp)
{
if ((vid.width <= vid.maxwarpwidth) &&
(vid.height <= vid.maxwarpheight))
{
vrect.x = 0;
vrect.y = 0;
vrect.width = vid.width;
vrect.height = vid.height;
 
R_ViewChanged (&vrect, sb_lines, vid.aspect);
}
else
{
w = vid.width;
h = vid.height;
 
if (w > vid.maxwarpwidth)
{
h *= (float)vid.maxwarpwidth / w;
w = vid.maxwarpwidth;
}
 
if (h > vid.maxwarpheight)
{
h = vid.maxwarpheight;
w *= (float)vid.maxwarpheight / h;
}
 
vrect.x = 0;
vrect.y = 0;
vrect.width = (int)w;
vrect.height = (int)h;
 
R_ViewChanged (&vrect,
(int)((float)sb_lines * (h/(float)vid.height)),
vid.aspect * (h / w) *
((float)vid.width / (float)vid.height));
}
}
else
{
vrect.x = 0;
vrect.y = 0;
vrect.width = vid.width;
vrect.height = vid.height;
 
R_ViewChanged (&vrect, sb_lines, vid.aspect);
}
 
r_viewchanged = false;
}
 
// start off with just the four screen edge clip planes
R_TransformFrustum ();
 
// save base values
VectorCopy (vpn, base_vpn);
VectorCopy (vright, base_vright);
VectorCopy (vup, base_vup);
VectorCopy (modelorg, base_modelorg);
 
R_SetSkyFrame ();
 
R_SetUpFrustumIndexes ();
 
r_cache_thrash = false;
 
// clear frame counts
c_faceclip = 0;
d_spanpixcount = 0;
r_polycount = 0;
r_drawnpolycount = 0;
r_wholepolycount = 0;
r_amodels_drawn = 0;
r_outofsurfaces = 0;
r_outofedges = 0;
 
D_SetupFrame ();
}
 
/contrib/other/sdlquake-1.0.9/r_part.c
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.
 
*/
 
#include "quakedef.h"
#include "r_local.h"
 
#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][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;
 
GL_Bind(particletexture);
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
}
 
/contrib/other/sdlquake-1.0.9/r_shared.h
0,0 → 1,157
/*
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 GLQUAKE
// r_shared.h: general refresh-related stuff shared between the refresh and the
// driver
 
// FIXME: clean up and move into d_iface.h
 
#ifndef _R_SHARED_H_
#define _R_SHARED_H_
 
#define MAXVERTS 16 // max points in a surface polygon
#define MAXWORKINGVERTS (MAXVERTS+4) // max points in an intermediate
// polygon (while processing)
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
#define MAXHEIGHT 1024
#define MAXWIDTH 1280
#define MAXDIMENSION ((MAXHEIGHT > MAXWIDTH) ? MAXHEIGHT : MAXWIDTH)
 
#define SIN_BUFFER_SIZE (MAXDIMENSION+CYCLE)
 
#define INFINITE_DISTANCE 0x10000 // distance that's always guaranteed to
// be farther away than anything in
// the scene
 
//===================================================================
 
extern void R_DrawLine (polyvert_t *polyvert0, polyvert_t *polyvert1);
 
extern int cachewidth;
extern pixel_t *cacheblock;
extern int screenwidth;
 
extern float pixelAspect;
 
extern int r_drawnpolycount;
 
extern cvar_t r_clearcolor;
 
extern int sintable[SIN_BUFFER_SIZE];
extern int intsintable[SIN_BUFFER_SIZE];
 
extern vec3_t vup, base_vup;
extern vec3_t vpn, base_vpn;
extern vec3_t vright, base_vright;
extern entity_t *currententity;
 
#define NUMSTACKEDGES 2400
#define MINEDGES NUMSTACKEDGES
#define NUMSTACKSURFACES 800
#define MINSURFACES NUMSTACKSURFACES
#define MAXSPANS 3000
 
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct espan_s
{
int u, v, count;
struct espan_s *pnext;
} espan_t;
 
// FIXME: compress, make a union if that will help
// insubmodel is only 1, flags is fewer than 32, spanstate could be a byte
typedef struct surf_s
{
struct surf_s *next; // active surface stack in r_edge.c
struct surf_s *prev; // used in r_edge.c for active surf stack
struct espan_s *spans; // pointer to linked list of spans to draw
int key; // sorting key (BSP order)
int last_u; // set during tracing
int spanstate; // 0 = not in span
// 1 = in span
// -1 = in inverted span (end before
// start)
int flags; // currentface flags
void *data; // associated data like msurface_t
entity_t *entity;
float nearzi; // nearest 1/z on surface, for mipmapping
qboolean insubmodel;
float d_ziorigin, d_zistepu, d_zistepv;
 
int pad[2]; // to 64 bytes
} surf_t;
 
extern surf_t *surfaces, *surface_p, *surf_max;
 
// surfaces are generated in back to front order by the bsp, so if a surf
// pointer is greater than another one, it should be drawn in front
// surfaces[1] is the background, and is used as the active surface stack.
// surfaces[0] is a dummy, because index 0 is used to indicate no surface
// attached to an edge_t
 
//===================================================================
 
extern vec3_t sxformaxis[4]; // s axis transformed into viewspace
extern vec3_t txformaxis[4]; // t axis transformed into viewspac
 
extern vec3_t modelorg, base_modelorg;
 
extern float xcenter, ycenter;
extern float xscale, yscale;
extern float xscaleinv, yscaleinv;
extern float xscaleshrink, yscaleshrink;
 
extern int d_lightstylevalue[256]; // 8.8 frac of base light value
 
extern void TransformVector (vec3_t in, vec3_t out);
extern void SetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv,
fixed8_t endvertu, fixed8_t endvertv);
 
extern int r_skymade;
extern void R_MakeSky (void);
 
extern int ubasestep, errorterm, erroradjustup, erroradjustdown;
 
// flags in finalvert_t.flags
#define ALIAS_LEFT_CLIP 0x0001
#define ALIAS_TOP_CLIP 0x0002
#define ALIAS_RIGHT_CLIP 0x0004
#define ALIAS_BOTTOM_CLIP 0x0008
#define ALIAS_Z_CLIP 0x0010
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
#define ALIAS_ONSEAM 0x0020 // also defined in modelgen.h;
// must be kept in sync
#define ALIAS_XY_CLIP_MASK 0x000F
 
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct edge_s
{
fixed16_t u;
fixed16_t u_step;
struct edge_s *prev, *next;
unsigned short surfs[2];
struct edge_s *nextremove;
float nearzi;
medge_t *owner;
} edge_t;
 
#endif // _R_SHARED_H_
 
#endif // GLQUAKE
/contrib/other/sdlquake-1.0.9/r_sky.c
0,0 → 1,280
/*
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_sky.c
 
#include "quakedef.h"
#include "r_local.h"
#include "d_local.h"
 
 
int iskyspeed = 8;
int iskyspeed2 = 2;
float skyspeed, skyspeed2;
 
float skytime;
 
byte *r_skysource;
 
int r_skymade;
int r_skydirect; // not used?
 
 
// TODO: clean up these routines
 
byte bottomsky[128*131];
byte bottommask[128*131];
byte newsky[128*256]; // newsky and topsky both pack in here, 128 bytes
// of newsky on the left of each scan, 128 bytes
// of topsky on the right, because the low-level
// drawers need 256-byte scan widths
 
 
/*
=============
R_InitSky
 
A sky texture is 256*128, with the right side being a masked overlay
==============
*/
void R_InitSky (texture_t *mt)
{
int i, j;
byte *src;
 
src = (byte *)mt + mt->offsets[0];
 
for (i=0 ; i<128 ; i++)
{
for (j=0 ; j<128 ; j++)
{
newsky[(i*256) + j + 128] = src[i*256 + j + 128];
}
}
 
for (i=0 ; i<128 ; i++)
{
for (j=0 ; j<131 ; j++)
{
if (src[i*256 + (j & 0x7F)])
{
bottomsky[(i*131) + j] = src[i*256 + (j & 0x7F)];
bottommask[(i*131) + j] = 0;
}
else
{
bottomsky[(i*131) + j] = 0;
bottommask[(i*131) + j] = 0xff;
}
}
}
r_skysource = newsky;
}
 
 
/*
=================
R_MakeSky
=================
*/
void R_MakeSky (void)
{
int x, y;
int ofs, baseofs;
int xshift, yshift;
unsigned *pnewsky;
static int xlast = -1, ylast = -1;
 
xshift = skytime*skyspeed;
yshift = skytime*skyspeed;
 
if ((xshift == xlast) && (yshift == ylast))
return;
 
xlast = xshift;
ylast = yshift;
pnewsky = (unsigned *)&newsky[0];
 
for (y=0 ; y<SKYSIZE ; y++)
{
baseofs = ((y+yshift) & SKYMASK) * 131;
 
// FIXME: clean this up
#if UNALIGNED_OK
 
for (x=0 ; x<SKYSIZE ; x += 4)
{
ofs = baseofs + ((x+xshift) & SKYMASK);
 
// PORT: unaligned dword access to bottommask and bottomsky
 
*pnewsky = (*(pnewsky + (128 / sizeof (unsigned))) &
*(unsigned *)&bottommask[ofs]) |
*(unsigned *)&bottomsky[ofs];
pnewsky++;
}
 
#else
 
for (x=0 ; x<SKYSIZE ; x++)
{
ofs = baseofs + ((x+xshift) & SKYMASK);
 
*(byte *)pnewsky = (*((byte *)pnewsky + 128) &
*(byte *)&bottommask[ofs]) |
*(byte *)&bottomsky[ofs];
pnewsky = (unsigned *)((byte *)pnewsky + 1);
}
 
#endif
 
pnewsky += 128 / sizeof (unsigned);
}
 
r_skymade = 1;
}
 
 
/*
=================
R_GenSkyTile
=================
*/
void R_GenSkyTile (void *pdest)
{
int x, y;
int ofs, baseofs;
int xshift, yshift;
unsigned *pnewsky;
unsigned *pd;
 
xshift = skytime*skyspeed;
yshift = skytime*skyspeed;
 
pnewsky = (unsigned *)&newsky[0];
pd = (unsigned *)pdest;
 
for (y=0 ; y<SKYSIZE ; y++)
{
baseofs = ((y+yshift) & SKYMASK) * 131;
 
// FIXME: clean this up
#if UNALIGNED_OK
 
for (x=0 ; x<SKYSIZE ; x += 4)
{
ofs = baseofs + ((x+xshift) & SKYMASK);
 
// PORT: unaligned dword access to bottommask and bottomsky
 
*pd = (*(pnewsky + (128 / sizeof (unsigned))) &
*(unsigned *)&bottommask[ofs]) |
*(unsigned *)&bottomsky[ofs];
pnewsky++;
pd++;
}
 
#else
 
for (x=0 ; x<SKYSIZE ; x++)
{
ofs = baseofs + ((x+xshift) & SKYMASK);
 
*(byte *)pd = (*((byte *)pnewsky + 128) &
*(byte *)&bottommask[ofs]) |
*(byte *)&bottomsky[ofs];
pnewsky = (unsigned *)((byte *)pnewsky + 1);
pd = (unsigned *)((byte *)pd + 1);
}
 
#endif
 
pnewsky += 128 / sizeof (unsigned);
}
}
 
 
/*
=================
R_GenSkyTile16
=================
*/
void R_GenSkyTile16 (void *pdest)
{
int x, y;
int ofs, baseofs;
int xshift, yshift;
byte *pnewsky;
unsigned short *pd;
 
xshift = skytime * skyspeed;
yshift = skytime * skyspeed;
 
pnewsky = (byte *)&newsky[0];
pd = (unsigned short *)pdest;
 
for (y=0 ; y<SKYSIZE ; y++)
{
baseofs = ((y+yshift) & SKYMASK) * 131;
 
// FIXME: clean this up
// FIXME: do faster unaligned version?
for (x=0 ; x<SKYSIZE ; x++)
{
ofs = baseofs + ((x+xshift) & SKYMASK);
 
*pd = d_8to16table[(*(pnewsky + 128) &
*(byte *)&bottommask[ofs]) |
*(byte *)&bottomsky[ofs]];
pnewsky++;
pd++;
}
 
pnewsky += TILE_SIZE;
}
}
 
 
/*
=============
R_SetSkyFrame
==============
*/
void R_SetSkyFrame (void)
{
int g, s1, s2;
float temp;
 
skyspeed = iskyspeed;
skyspeed2 = iskyspeed2;
 
g = GreatestCommonDivisor (iskyspeed, iskyspeed2);
s1 = iskyspeed / g;
s2 = iskyspeed2 / g;
temp = SKYSIZE * s1 * s2;
 
skytime = cl.time - ((int)(cl.time / temp) * temp);
 
r_skymade = 0;
}
 
 
/contrib/other/sdlquake-1.0.9/r_sprite.c
0,0 → 1,401
/*
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_sprite.c
 
#include "quakedef.h"
#include "r_local.h"
 
static int clip_current;
static vec5_t clip_verts[2][MAXWORKINGVERTS];
static int sprite_width, sprite_height;
 
spritedesc_t r_spritedesc;
 
/*
================
R_RotateSprite
================
*/
void R_RotateSprite (float beamlength)
{
vec3_t vec;
if (beamlength == 0.0)
return;
 
VectorScale (r_spritedesc.vpn, -beamlength, vec);
VectorAdd (r_entorigin, vec, r_entorigin);
VectorSubtract (modelorg, vec, modelorg);
}
 
 
/*
=============
R_ClipSpriteFace
 
Clips the winding at clip_verts[clip_current] and changes clip_current
Throws out the back side
==============
*/
int R_ClipSpriteFace (int nump, clipplane_t *pclipplane)
{
int i, outcount;
float dists[MAXWORKINGVERTS+1];
float frac, clipdist, *pclipnormal;
float *in, *instep, *outstep, *vert2;
 
clipdist = pclipplane->dist;
pclipnormal = pclipplane->normal;
// calc dists
if (clip_current)
{
in = clip_verts[1][0];
outstep = clip_verts[0][0];
clip_current = 0;
}
else
{
in = clip_verts[0][0];
outstep = clip_verts[1][0];
clip_current = 1;
}
instep = in;
for (i=0 ; i<nump ; i++, instep += sizeof (vec5_t) / sizeof (float))
{
dists[i] = DotProduct (instep, pclipnormal) - clipdist;
}
// handle wraparound case
dists[nump] = dists[0];
Q_memcpy (instep, in, sizeof (vec5_t));
 
 
// clip the winding
instep = in;
outcount = 0;
 
for (i=0 ; i<nump ; i++, instep += sizeof (vec5_t) / sizeof (float))
{
if (dists[i] >= 0)
{
Q_memcpy (outstep, instep, sizeof (vec5_t));
outstep += sizeof (vec5_t) / sizeof (float);
outcount++;
}
 
if (dists[i] == 0 || dists[i+1] == 0)
continue;
 
if ( (dists[i] > 0) == (dists[i+1] > 0) )
continue;
// split it into a new vertex
frac = dists[i] / (dists[i] - dists[i+1]);
vert2 = instep + sizeof (vec5_t) / sizeof (float);
outstep[0] = instep[0] + frac*(vert2[0] - instep[0]);
outstep[1] = instep[1] + frac*(vert2[1] - instep[1]);
outstep[2] = instep[2] + frac*(vert2[2] - instep[2]);
outstep[3] = instep[3] + frac*(vert2[3] - instep[3]);
outstep[4] = instep[4] + frac*(vert2[4] - instep[4]);
 
outstep += sizeof (vec5_t) / sizeof (float);
outcount++;
}
return outcount;
}
 
 
/*
================
R_SetupAndDrawSprite
================
*/
void R_SetupAndDrawSprite ()
{
int i, nump;
float dot, scale, *pv;
vec5_t *pverts;
vec3_t left, up, right, down, transformed, local;
emitpoint_t outverts[MAXWORKINGVERTS+1], *pout;
 
dot = DotProduct (r_spritedesc.vpn, modelorg);
 
// backface cull
if (dot >= 0)
return;
 
// build the sprite poster in worldspace
VectorScale (r_spritedesc.vright, r_spritedesc.pspriteframe->right, right);
VectorScale (r_spritedesc.vup, r_spritedesc.pspriteframe->up, up);
VectorScale (r_spritedesc.vright, r_spritedesc.pspriteframe->left, left);
VectorScale (r_spritedesc.vup, r_spritedesc.pspriteframe->down, down);
 
pverts = clip_verts[0];
 
pverts[0][0] = r_entorigin[0] + up[0] + left[0];
pverts[0][1] = r_entorigin[1] + up[1] + left[1];
pverts[0][2] = r_entorigin[2] + up[2] + left[2];
pverts[0][3] = 0;
pverts[0][4] = 0;
 
pverts[1][0] = r_entorigin[0] + up[0] + right[0];
pverts[1][1] = r_entorigin[1] + up[1] + right[1];
pverts[1][2] = r_entorigin[2] + up[2] + right[2];
pverts[1][3] = sprite_width;
pverts[1][4] = 0;
 
pverts[2][0] = r_entorigin[0] + down[0] + right[0];
pverts[2][1] = r_entorigin[1] + down[1] + right[1];
pverts[2][2] = r_entorigin[2] + down[2] + right[2];
pverts[2][3] = sprite_width;
pverts[2][4] = sprite_height;
 
pverts[3][0] = r_entorigin[0] + down[0] + left[0];
pverts[3][1] = r_entorigin[1] + down[1] + left[1];
pverts[3][2] = r_entorigin[2] + down[2] + left[2];
pverts[3][3] = 0;
pverts[3][4] = sprite_height;
 
// clip to the frustum in worldspace
nump = 4;
clip_current = 0;
 
for (i=0 ; i<4 ; i++)
{
nump = R_ClipSpriteFace (nump, &view_clipplanes[i]);
if (nump < 3)
return;
if (nump >= MAXWORKINGVERTS)
Sys_Error("R_SetupAndDrawSprite: too many points");
}
 
// transform vertices into viewspace and project
pv = &clip_verts[clip_current][0][0];
r_spritedesc.nearzi = -999999;
 
for (i=0 ; i<nump ; i++)
{
VectorSubtract (pv, r_origin, local);
TransformVector (local, transformed);
 
if (transformed[2] < NEAR_CLIP)
transformed[2] = NEAR_CLIP;
 
pout = &outverts[i];
pout->zi = 1.0 / transformed[2];
if (pout->zi > r_spritedesc.nearzi)
r_spritedesc.nearzi = pout->zi;
 
pout->s = pv[3];
pout->t = pv[4];
scale = xscale * pout->zi;
pout->u = (xcenter + scale * transformed[0]);
 
scale = yscale * pout->zi;
pout->v = (ycenter - scale * transformed[1]);
 
pv += sizeof (vec5_t) / sizeof (*pv);
}
 
// draw it
r_spritedesc.nump = nump;
r_spritedesc.pverts = outverts;
D_DrawSprite ();
}
 
 
/*
================
R_GetSpriteframe
================
*/
mspriteframe_t *R_GetSpriteframe (msprite_t *psprite)
{
mspritegroup_t *pspritegroup;
mspriteframe_t *pspriteframe;
int i, numframes, frame;
float *pintervals, fullinterval, targettime, time;
 
frame = currententity->frame;
 
if ((frame >= psprite->numframes) || (frame < 0))
{
Con_Printf ("R_DrawSprite: no such frame %d\n", frame);
frame = 0;
}
 
if (psprite->frames[frame].type == SPR_SINGLE)
{
pspriteframe = psprite->frames[frame].frameptr;
}
else
{
pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
pintervals = pspritegroup->intervals;
numframes = pspritegroup->numframes;
fullinterval = pintervals[numframes-1];
 
time = cl.time + currententity->syncbase;
 
// when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
// are positive, so we don't have to worry about division by 0
targettime = time - ((int)(time / fullinterval)) * fullinterval;
 
for (i=0 ; i<(numframes-1) ; i++)
{
if (pintervals[i] > targettime)
break;
}
 
pspriteframe = pspritegroup->frames[i];
}
 
return pspriteframe;
}
 
 
/*
================
R_DrawSprite
================
*/
void R_DrawSprite (void)
{
int i;
msprite_t *psprite;
vec3_t tvec;
float dot, angle, sr, cr;
 
psprite = currententity->model->cache.data;
 
r_spritedesc.pspriteframe = R_GetSpriteframe (psprite);
 
sprite_width = r_spritedesc.pspriteframe->width;
sprite_height = r_spritedesc.pspriteframe->height;
 
// TODO: make this caller-selectable
if (psprite->type == SPR_FACING_UPRIGHT)
{
// generate the sprite's axes, with vup straight up in worldspace, and
// r_spritedesc.vright perpendicular to modelorg.
// This will not work if the view direction is very close to straight up or
// down, because the cross product will be between two nearly parallel
// vectors and starts to approach an undefined state, so we don't draw if
// the two vectors are less than 1 degree apart
tvec[0] = -modelorg[0];
tvec[1] = -modelorg[1];
tvec[2] = -modelorg[2];
VectorNormalize (tvec);
dot = tvec[2]; // same as DotProduct (tvec, r_spritedesc.vup) because
// r_spritedesc.vup is 0, 0, 1
if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) = 0.999848
return;
r_spritedesc.vup[0] = 0;
r_spritedesc.vup[1] = 0;
r_spritedesc.vup[2] = 1;
r_spritedesc.vright[0] = tvec[1];
// CrossProduct(r_spritedesc.vup, -modelorg,
r_spritedesc.vright[1] = -tvec[0];
// r_spritedesc.vright)
r_spritedesc.vright[2] = 0;
VectorNormalize (r_spritedesc.vright);
r_spritedesc.vpn[0] = -r_spritedesc.vright[1];
r_spritedesc.vpn[1] = r_spritedesc.vright[0];
r_spritedesc.vpn[2] = 0;
// CrossProduct (r_spritedesc.vright, r_spritedesc.vup,
// r_spritedesc.vpn)
}
else if (psprite->type == SPR_VP_PARALLEL)
{
// generate the sprite's axes, completely parallel to the viewplane. There
// are no problem situations, because the sprite is always in the same
// position relative to the viewer
for (i=0 ; i<3 ; i++)
{
r_spritedesc.vup[i] = vup[i];
r_spritedesc.vright[i] = vright[i];
r_spritedesc.vpn[i] = vpn[i];
}
}
else if (psprite->type == SPR_VP_PARALLEL_UPRIGHT)
{
// generate the sprite's axes, with vup straight up in worldspace, and
// r_spritedesc.vright parallel to the viewplane.
// This will not work if the view direction is very close to straight up or
// down, because the cross product will be between two nearly parallel
// vectors and starts to approach an undefined state, so we don't draw if
// the two vectors are less than 1 degree apart
dot = vpn[2]; // same as DotProduct (vpn, r_spritedesc.vup) because
// r_spritedesc.vup is 0, 0, 1
if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) = 0.999848
return;
r_spritedesc.vup[0] = 0;
r_spritedesc.vup[1] = 0;
r_spritedesc.vup[2] = 1;
r_spritedesc.vright[0] = vpn[1];
// CrossProduct (r_spritedesc.vup, vpn,
r_spritedesc.vright[1] = -vpn[0]; // r_spritedesc.vright)
r_spritedesc.vright[2] = 0;
VectorNormalize (r_spritedesc.vright);
r_spritedesc.vpn[0] = -r_spritedesc.vright[1];
r_spritedesc.vpn[1] = r_spritedesc.vright[0];
r_spritedesc.vpn[2] = 0;
// CrossProduct (r_spritedesc.vright, r_spritedesc.vup,
// r_spritedesc.vpn)
}
else if (psprite->type == SPR_ORIENTED)
{
// generate the sprite's axes, according to the sprite's world orientation
AngleVectors (currententity->angles, r_spritedesc.vpn,
r_spritedesc.vright, r_spritedesc.vup);
}
else if (psprite->type == SPR_VP_PARALLEL_ORIENTED)
{
// generate the sprite's axes, parallel to the viewplane, but rotated in
// that plane around the center according to the sprite entity's roll
// angle. So vpn stays the same, but vright and vup rotate
angle = currententity->angles[ROLL] * (M_PI*2 / 360);
sr = sin(angle);
cr = cos(angle);
 
for (i=0 ; i<3 ; i++)
{
r_spritedesc.vpn[i] = vpn[i];
r_spritedesc.vright[i] = vright[i] * cr + vup[i] * sr;
r_spritedesc.vup[i] = vright[i] * -sr + vup[i] * cr;
}
}
else
{
Sys_Error ("R_DrawSprite: Bad sprite type %d", psprite->type);
}
 
R_RotateSprite (psprite->beamlength);
 
R_SetupAndDrawSprite ();
}
 
/contrib/other/sdlquake-1.0.9/r_surf.c
0,0 → 1,678
/*
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_surf.c: surface-related refresh code
 
#include "quakedef.h"
#include "r_local.h"
 
drawsurf_t r_drawsurf;
 
int lightleft, sourcesstep, blocksize, sourcetstep;
int lightdelta, lightdeltastep;
int lightright, lightleftstep, lightrightstep, blockdivshift;
unsigned blockdivmask;
void *prowdestbase;
unsigned char *pbasesource;
int surfrowbytes; // used by ASM files
unsigned *r_lightptr;
int r_stepback;
int r_lightwidth;
int r_numhblocks, r_numvblocks;
unsigned char *r_source, *r_sourcemax;
 
void R_DrawSurfaceBlock8_mip0 (void);
void R_DrawSurfaceBlock8_mip1 (void);
void R_DrawSurfaceBlock8_mip2 (void);
void R_DrawSurfaceBlock8_mip3 (void);
 
static void (*surfmiptable[4])(void) = {
R_DrawSurfaceBlock8_mip0,
R_DrawSurfaceBlock8_mip1,
R_DrawSurfaceBlock8_mip2,
R_DrawSurfaceBlock8_mip3
};
 
 
 
unsigned blocklights[18*18];
 
/*
===============
R_AddDynamicLights
===============
*/
void R_AddDynamicLights (void)
{
msurface_t *surf;
int lnum;
int sd, td;
float dist, rad, minlight;
vec3_t impact, local;
int s, t;
int i;
int smax, tmax;
mtexinfo_t *tex;
 
surf = r_drawsurf.surf;
smax = (surf->extents[0]>>4)+1;
tmax = (surf->extents[1]>>4)+1;
tex = surf->texinfo;
 
for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
{
if ( !(surf->dlightbits & (1<<lnum) ) )
continue; // not lit by this light
 
rad = cl_dlights[lnum].radius;
dist = DotProduct (cl_dlights[lnum].origin, surf->plane->normal) -
surf->plane->dist;
rad -= fabs(dist);
minlight = cl_dlights[lnum].minlight;
if (rad < minlight)
continue;
minlight = rad - minlight;
 
for (i=0 ; i<3 ; i++)
{
impact[i] = cl_dlights[lnum].origin[i] -
surf->plane->normal[i]*dist;
}
 
local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3];
local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3];
 
local[0] -= surf->texturemins[0];
local[1] -= surf->texturemins[1];
for (t = 0 ; t<tmax ; t++)
{
td = local[1] - t*16;
if (td < 0)
td = -td;
for (s=0 ; s<smax ; s++)
{
sd = local[0] - s*16;
if (sd < 0)
sd = -sd;
if (sd > td)
dist = sd + (td>>1);
else
dist = td + (sd>>1);
if (dist < minlight)
#ifdef QUAKE2
{
unsigned temp;
temp = (rad - dist)*256;
i = t*smax + s;
if (!cl_dlights[lnum].dark)
blocklights[i] += temp;
else
{
if (blocklights[i] > temp)
blocklights[i] -= temp;
else
blocklights[i] = 0;
}
}
#else
blocklights[t*smax + s] += (rad - dist)*256;
#endif
}
}
}
}
 
/*
===============
R_BuildLightMap
 
Combine and scale multiple lightmaps into the 8.8 format in blocklights
===============
*/
void R_BuildLightMap (void)
{
int smax, tmax;
int t;
int i, size;
byte *lightmap;
unsigned scale;
int maps;
msurface_t *surf;
 
surf = r_drawsurf.surf;
 
smax = (surf->extents[0]>>4)+1;
tmax = (surf->extents[1]>>4)+1;
size = smax*tmax;
lightmap = surf->samples;
 
if (r_fullbright.value || !cl.worldmodel->lightdata)
{
for (i=0 ; i<size ; i++)
blocklights[i] = 0;
return;
}
 
// clear to ambient
for (i=0 ; i<size ; i++)
blocklights[i] = r_refdef.ambientlight<<8;
 
 
// add all the lightmaps
if (lightmap)
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
maps++)
{
scale = r_drawsurf.lightadj[maps]; // 8.8 fraction
for (i=0 ; i<size ; i++)
blocklights[i] += lightmap[i] * scale;
lightmap += size; // skip to next lightmap
}
 
// add all the dynamic lights
if (surf->dlightframe == r_framecount)
R_AddDynamicLights ();
 
// bound, invert, and shift
for (i=0 ; i<size ; i++)
{
t = (255*256 - (int)blocklights[i]) >> (8 - VID_CBITS);
 
if (t < (1 << 6))
t = (1 << 6);
 
blocklights[i] = t;
}
}
 
 
/*
===============
R_TextureAnimation
 
Returns the proper texture for a given time and base texture
===============
*/
texture_t *R_TextureAnimation (texture_t *base)
{
int reletive;
int count;
 
if (currententity->frame)
{
if (base->alternate_anims)
base = base->alternate_anims;
}
if (!base->anim_total)
return base;
 
reletive = (int)(cl.time*10) % base->anim_total;
 
count = 0;
while (base->anim_min > reletive || base->anim_max <= reletive)
{
base = base->anim_next;
if (!base)
Sys_Error ("R_TextureAnimation: broken cycle");
if (++count > 100)
Sys_Error ("R_TextureAnimation: infinite cycle");
}
 
return base;
}
 
 
/*
===============
R_DrawSurface
===============
*/
void R_DrawSurface (void)
{
unsigned char *basetptr;
int smax, tmax, twidth;
int u;
int soffset, basetoffset, texwidth;
int horzblockstep;
unsigned char *pcolumndest;
void (*pblockdrawer)(void);
texture_t *mt;
 
// calculate the lightings
R_BuildLightMap ();
surfrowbytes = r_drawsurf.rowbytes;
 
mt = r_drawsurf.texture;
r_source = (byte *)mt + mt->offsets[r_drawsurf.surfmip];
// the fractional light values should range from 0 to (VID_GRADES - 1) << 16
// from a source range of 0 - 255
texwidth = mt->width >> r_drawsurf.surfmip;
 
blocksize = 16 >> r_drawsurf.surfmip;
blockdivshift = 4 - r_drawsurf.surfmip;
blockdivmask = (1 << blockdivshift) - 1;
r_lightwidth = (r_drawsurf.surf->extents[0]>>4)+1;
 
r_numhblocks = r_drawsurf.surfwidth >> blockdivshift;
r_numvblocks = r_drawsurf.surfheight >> blockdivshift;
 
//==============================
 
if (r_pixbytes == 1)
{
pblockdrawer = surfmiptable[r_drawsurf.surfmip];
// TODO: only needs to be set when there is a display settings change
horzblockstep = blocksize;
}
else
{
pblockdrawer = R_DrawSurfaceBlock16;
// TODO: only needs to be set when there is a display settings change
horzblockstep = blocksize << 1;
}
 
smax = mt->width >> r_drawsurf.surfmip;
twidth = texwidth;
tmax = mt->height >> r_drawsurf.surfmip;
sourcetstep = texwidth;
r_stepback = tmax * twidth;
 
r_sourcemax = r_source + (tmax * smax);
 
soffset = r_drawsurf.surf->texturemins[0];
basetoffset = r_drawsurf.surf->texturemins[1];
 
// << 16 components are to guarantee positive values for %
soffset = ((soffset >> r_drawsurf.surfmip) + (smax << 16)) % smax;
basetptr = &r_source[((((basetoffset >> r_drawsurf.surfmip)
+ (tmax << 16)) % tmax) * twidth)];
 
pcolumndest = r_drawsurf.surfdat;
 
for (u=0 ; u<r_numhblocks; u++)
{
r_lightptr = blocklights + u;
 
prowdestbase = pcolumndest;
 
pbasesource = basetptr + soffset;
 
(*pblockdrawer)();
 
soffset = soffset + blocksize;
if (soffset >= smax)
soffset = 0;
 
pcolumndest += horzblockstep;
}
}
 
 
//=============================================================================
 
#if !id386
 
/*
================
R_DrawSurfaceBlock8_mip0
================
*/
void R_DrawSurfaceBlock8_mip0 (void)
{
int v, i, b, lightstep, lighttemp, light;
unsigned char pix, *psource, *prowdest;
 
psource = pbasesource;
prowdest = prowdestbase;
 
for (v=0 ; v<r_numvblocks ; v++)
{
// FIXME: make these locals?
// FIXME: use delta rather than both right and left, like ASM?
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> 4;
lightrightstep = (r_lightptr[1] - lightright) >> 4;
 
for (i=0 ; i<16 ; i++)
{
lighttemp = lightleft - lightright;
lightstep = lighttemp >> 4;
 
light = lightright;
 
for (b=15; b>=0; b--)
{
pix = psource[b];
prowdest[b] = ((unsigned char *)vid.colormap)
[(light & 0xFF00) + pix];
light += lightstep;
}
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += surfrowbytes;
}
 
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
 
 
/*
================
R_DrawSurfaceBlock8_mip1
================
*/
void R_DrawSurfaceBlock8_mip1 (void)
{
int v, i, b, lightstep, lighttemp, light;
unsigned char pix, *psource, *prowdest;
 
psource = pbasesource;
prowdest = prowdestbase;
 
for (v=0 ; v<r_numvblocks ; v++)
{
// FIXME: make these locals?
// FIXME: use delta rather than both right and left, like ASM?
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> 3;
lightrightstep = (r_lightptr[1] - lightright) >> 3;
 
for (i=0 ; i<8 ; i++)
{
lighttemp = lightleft - lightright;
lightstep = lighttemp >> 3;
 
light = lightright;
 
for (b=7; b>=0; b--)
{
pix = psource[b];
prowdest[b] = ((unsigned char *)vid.colormap)
[(light & 0xFF00) + pix];
light += lightstep;
}
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += surfrowbytes;
}
 
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
 
 
/*
================
R_DrawSurfaceBlock8_mip2
================
*/
void R_DrawSurfaceBlock8_mip2 (void)
{
int v, i, b, lightstep, lighttemp, light;
unsigned char pix, *psource, *prowdest;
 
psource = pbasesource;
prowdest = prowdestbase;
 
for (v=0 ; v<r_numvblocks ; v++)
{
// FIXME: make these locals?
// FIXME: use delta rather than both right and left, like ASM?
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> 2;
lightrightstep = (r_lightptr[1] - lightright) >> 2;
 
for (i=0 ; i<4 ; i++)
{
lighttemp = lightleft - lightright;
lightstep = lighttemp >> 2;
 
light = lightright;
 
for (b=3; b>=0; b--)
{
pix = psource[b];
prowdest[b] = ((unsigned char *)vid.colormap)
[(light & 0xFF00) + pix];
light += lightstep;
}
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += surfrowbytes;
}
 
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
 
 
/*
================
R_DrawSurfaceBlock8_mip3
================
*/
void R_DrawSurfaceBlock8_mip3 (void)
{
int v, i, b, lightstep, lighttemp, light;
unsigned char pix, *psource, *prowdest;
 
psource = pbasesource;
prowdest = prowdestbase;
 
for (v=0 ; v<r_numvblocks ; v++)
{
// FIXME: make these locals?
// FIXME: use delta rather than both right and left, like ASM?
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> 1;
lightrightstep = (r_lightptr[1] - lightright) >> 1;
 
for (i=0 ; i<2 ; i++)
{
lighttemp = lightleft - lightright;
lightstep = lighttemp >> 1;
 
light = lightright;
 
for (b=1; b>=0; b--)
{
pix = psource[b];
prowdest[b] = ((unsigned char *)vid.colormap)
[(light & 0xFF00) + pix];
light += lightstep;
}
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += surfrowbytes;
}
 
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
 
 
/*
================
R_DrawSurfaceBlock16
 
FIXME: make this work
================
*/
void R_DrawSurfaceBlock16 (void)
{
int k;
unsigned char *psource;
int lighttemp, lightstep, light;
unsigned short *prowdest;
 
prowdest = (unsigned short *)prowdestbase;
 
for (k=0 ; k<blocksize ; k++)
{
unsigned short *pdest;
unsigned char pix;
int b;
 
psource = pbasesource;
lighttemp = lightright - lightleft;
lightstep = lighttemp >> blockdivshift;
 
light = lightleft;
pdest = prowdest;
 
for (b=0; b<blocksize; b++)
{
pix = *psource;
*pdest = vid.colormap16[(light & 0xFF00) + pix];
psource += sourcesstep;
pdest++;
light += lightstep;
}
 
pbasesource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest = (unsigned short *)((long)prowdest + surfrowbytes);
}
 
prowdestbase = prowdest;
}
 
#endif
 
 
//============================================================================
 
/*
================
R_GenTurbTile
================
*/
void R_GenTurbTile (pixel_t *pbasetex, void *pdest)
{
int *turb;
int i, j, s, t;
byte *pd;
turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
pd = (byte *)pdest;
 
for (i=0 ; i<TILE_SIZE ; i++)
{
for (j=0 ; j<TILE_SIZE ; j++)
{
s = (((j << 16) + turb[i & (CYCLE-1)]) >> 16) & 63;
t = (((i << 16) + turb[j & (CYCLE-1)]) >> 16) & 63;
*pd++ = *(pbasetex + (t<<6) + s);
}
}
}
 
 
/*
================
R_GenTurbTile16
================
*/
void R_GenTurbTile16 (pixel_t *pbasetex, void *pdest)
{
int *turb;
int i, j, s, t;
unsigned short *pd;
 
turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
pd = (unsigned short *)pdest;
 
for (i=0 ; i<TILE_SIZE ; i++)
{
for (j=0 ; j<TILE_SIZE ; j++)
{
s = (((j << 16) + turb[i & (CYCLE-1)]) >> 16) & 63;
t = (((i << 16) + turb[j & (CYCLE-1)]) >> 16) & 63;
*pd++ = d_8to16table[*(pbasetex + (t<<6) + s)];
}
}
}
 
 
/*
================
R_GenTile
================
*/
void R_GenTile (msurface_t *psurf, void *pdest)
{
if (psurf->flags & SURF_DRAWTURB)
{
if (r_pixbytes == 1)
{
R_GenTurbTile ((pixel_t *)
((byte *)psurf->texinfo->texture + psurf->texinfo->texture->offsets[0]), pdest);
}
else
{
R_GenTurbTile16 ((pixel_t *)
((byte *)psurf->texinfo->texture + psurf->texinfo->texture->offsets[0]), pdest);
}
}
else if (psurf->flags & SURF_DRAWSKY)
{
if (r_pixbytes == 1)
{
R_GenSkyTile (pdest);
}
else
{
R_GenSkyTile16 (pdest);
}
}
else
{
Sys_Error ("Unknown tile type");
}
}
 
/contrib/other/sdlquake-1.0.9/r_vars.c
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.
 
*/
// r_vars.c: global refresh variables
 
#include "quakedef.h"
 
#if !id386
 
// all global and static refresh variables are collected in a contiguous block
// to avoid cache conflicts.
 
//-------------------------------------------------------
// global refresh variables
//-------------------------------------------------------
 
// FIXME: make into one big structure, like cl or sv
// FIXME: do separately for refresh engine and driver
 
int r_bmodelactive;
 
#endif // !id386
 
/contrib/other/sdlquake-1.0.9/r_varsa.S
0,0 → 1,64
/*
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_varsa.s
//
 
#include "asm_i386.h"
#include "quakeasm.h"
#include "asm_draw.h"
#include "d_ifacea.h"
 
#if id386
 
.data
 
//-------------------------------------------------------
// ASM-only variables
//-------------------------------------------------------
.globl float_1, float_particle_z_clip, float_point5
.globl float_minus_1, float_0
float_0: .single 0.0
float_1: .single 1.0
float_minus_1: .single -1.0
float_particle_z_clip: .single PARTICLE_Z_CLIP
float_point5: .single 0.5
 
.globl fp_16, fp_64k, fp_1m, fp_64kx64k
.globl fp_1m_minus_1
.globl fp_8
fp_1m: .single 1048576.0
fp_1m_minus_1: .single 1048575.0
fp_64k: .single 65536.0
fp_8: .single 8.0
fp_16: .single 16.0
fp_64kx64k: .long 0x4f000000 // (float)0x8000*0x10000
 
 
.globl FloatZero, Float2ToThe31nd, FloatMinus2ToThe31nd
FloatZero: .long 0
Float2ToThe31nd: .long 0x4f000000
FloatMinus2ToThe31nd: .long 0xcf000000
 
.globl C(r_bmodelactive)
C(r_bmodelactive): .long 0
 
#endif // id386
 
/contrib/other/sdlquake-1.0.9/render.h
0,0 → 1,158
/*
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
 
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);
 
/contrib/other/sdlquake-1.0.9/resource.h
0,0 → 1,20
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by winquake.rc
//
#define IDS_STRING1 1
#define IDI_ICON2 1
#define IDD_DIALOG1 108
#define IDD_PROGRESS 109
#define IDC_PROGRESS 1000
 
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 111
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1004
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
/contrib/other/sdlquake-1.0.9/sbar.c
0,0 → 1,1323
/*
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.
 
*/
// sbar.c -- status bar code
 
#include "quakedef.h"
 
 
int sb_updates; // if >= vid.numpages, no update needed
 
#define STAT_MINUS 10 // num frame for '-' stats digit
qpic_t *sb_nums[2][11];
qpic_t *sb_colon, *sb_slash;
qpic_t *sb_ibar;
qpic_t *sb_sbar;
qpic_t *sb_scorebar;
 
qpic_t *sb_weapons[7][8]; // 0 is active, 1 is owned, 2-5 are flashes
qpic_t *sb_ammo[4];
qpic_t *sb_sigil[4];
qpic_t *sb_armor[3];
qpic_t *sb_items[32];
 
qpic_t *sb_faces[7][2]; // 0 is gibbed, 1 is dead, 2-6 are alive
// 0 is static, 1 is temporary animation
qpic_t *sb_face_invis;
qpic_t *sb_face_quad;
qpic_t *sb_face_invuln;
qpic_t *sb_face_invis_invuln;
 
qboolean sb_showscores;
 
int sb_lines; // scan lines to draw
 
qpic_t *rsb_invbar[2];
qpic_t *rsb_weapons[5];
qpic_t *rsb_items[2];
qpic_t *rsb_ammo[3];
qpic_t *rsb_teambord; // PGM 01/19/97 - team color border
 
//MED 01/04/97 added two more weapons + 3 alternates for grenade launcher
qpic_t *hsb_weapons[7][5]; // 0 is active, 1 is owned, 2-5 are flashes
//MED 01/04/97 added array to simplify weapon parsing
int hipweapons[4] = {HIT_LASER_CANNON_BIT,HIT_MJOLNIR_BIT,4,HIT_PROXIMITY_GUN_BIT};
//MED 01/04/97 added hipnotic items array
qpic_t *hsb_items[2];
 
void Sbar_MiniDeathmatchOverlay (void);
void Sbar_DeathmatchOverlay (void);
void M_DrawPic (int x, int y, qpic_t *pic);
 
/*
===============
Sbar_ShowScores
 
Tab key down
===============
*/
void Sbar_ShowScores (void)
{
if (sb_showscores)
return;
sb_showscores = true;
sb_updates = 0;
}
 
/*
===============
Sbar_DontShowScores
 
Tab key up
===============
*/
void Sbar_DontShowScores (void)
{
sb_showscores = false;
sb_updates = 0;
}
 
/*
===============
Sbar_Changed
===============
*/
void Sbar_Changed (void)
{
sb_updates = 0; // update next frame
}
 
/*
===============
Sbar_Init
===============
*/
void Sbar_Init (void)
{
int i;
 
for (i=0 ; i<10 ; i++)
{
sb_nums[0][i] = Draw_PicFromWad (va("num_%i",i));
sb_nums[1][i] = Draw_PicFromWad (va("anum_%i",i));
}
 
sb_nums[0][10] = Draw_PicFromWad ("num_minus");
sb_nums[1][10] = Draw_PicFromWad ("anum_minus");
 
sb_colon = Draw_PicFromWad ("num_colon");
sb_slash = Draw_PicFromWad ("num_slash");
 
sb_weapons[0][0] = Draw_PicFromWad ("inv_shotgun");
sb_weapons[0][1] = Draw_PicFromWad ("inv_sshotgun");
sb_weapons[0][2] = Draw_PicFromWad ("inv_nailgun");
sb_weapons[0][3] = Draw_PicFromWad ("inv_snailgun");
sb_weapons[0][4] = Draw_PicFromWad ("inv_rlaunch");
sb_weapons[0][5] = Draw_PicFromWad ("inv_srlaunch");
sb_weapons[0][6] = Draw_PicFromWad ("inv_lightng");
 
sb_weapons[1][0] = Draw_PicFromWad ("inv2_shotgun");
sb_weapons[1][1] = Draw_PicFromWad ("inv2_sshotgun");
sb_weapons[1][2] = Draw_PicFromWad ("inv2_nailgun");
sb_weapons[1][3] = Draw_PicFromWad ("inv2_snailgun");
sb_weapons[1][4] = Draw_PicFromWad ("inv2_rlaunch");
sb_weapons[1][5] = Draw_PicFromWad ("inv2_srlaunch");
sb_weapons[1][6] = Draw_PicFromWad ("inv2_lightng");
 
for (i=0 ; i<5 ; i++)
{
sb_weapons[2+i][0] = Draw_PicFromWad (va("inva%i_shotgun",i+1));
sb_weapons[2+i][1] = Draw_PicFromWad (va("inva%i_sshotgun",i+1));
sb_weapons[2+i][2] = Draw_PicFromWad (va("inva%i_nailgun",i+1));
sb_weapons[2+i][3] = Draw_PicFromWad (va("inva%i_snailgun",i+1));
sb_weapons[2+i][4] = Draw_PicFromWad (va("inva%i_rlaunch",i+1));
sb_weapons[2+i][5] = Draw_PicFromWad (va("inva%i_srlaunch",i+1));
sb_weapons[2+i][6] = Draw_PicFromWad (va("inva%i_lightng",i+1));
}
 
sb_ammo[0] = Draw_PicFromWad ("sb_shells");
sb_ammo[1] = Draw_PicFromWad ("sb_nails");
sb_ammo[2] = Draw_PicFromWad ("sb_rocket");
sb_ammo[3] = Draw_PicFromWad ("sb_cells");
 
sb_armor[0] = Draw_PicFromWad ("sb_armor1");
sb_armor[1] = Draw_PicFromWad ("sb_armor2");
sb_armor[2] = Draw_PicFromWad ("sb_armor3");
 
sb_items[0] = Draw_PicFromWad ("sb_key1");
sb_items[1] = Draw_PicFromWad ("sb_key2");
sb_items[2] = Draw_PicFromWad ("sb_invis");
sb_items[3] = Draw_PicFromWad ("sb_invuln");
sb_items[4] = Draw_PicFromWad ("sb_suit");
sb_items[5] = Draw_PicFromWad ("sb_quad");
 
sb_sigil[0] = Draw_PicFromWad ("sb_sigil1");
sb_sigil[1] = Draw_PicFromWad ("sb_sigil2");
sb_sigil[2] = Draw_PicFromWad ("sb_sigil3");
sb_sigil[3] = Draw_PicFromWad ("sb_sigil4");
 
sb_faces[4][0] = Draw_PicFromWad ("face1");
sb_faces[4][1] = Draw_PicFromWad ("face_p1");
sb_faces[3][0] = Draw_PicFromWad ("face2");
sb_faces[3][1] = Draw_PicFromWad ("face_p2");
sb_faces[2][0] = Draw_PicFromWad ("face3");
sb_faces[2][1] = Draw_PicFromWad ("face_p3");
sb_faces[1][0] = Draw_PicFromWad ("face4");
sb_faces[1][1] = Draw_PicFromWad ("face_p4");
sb_faces[0][0] = Draw_PicFromWad ("face5");
sb_faces[0][1] = Draw_PicFromWad ("face_p5");
 
sb_face_invis = Draw_PicFromWad ("face_invis");
sb_face_invuln = Draw_PicFromWad ("face_invul2");
sb_face_invis_invuln = Draw_PicFromWad ("face_inv2");
sb_face_quad = Draw_PicFromWad ("face_quad");
 
Cmd_AddCommand ("+showscores", Sbar_ShowScores);
Cmd_AddCommand ("-showscores", Sbar_DontShowScores);
 
sb_sbar = Draw_PicFromWad ("sbar");
sb_ibar = Draw_PicFromWad ("ibar");
sb_scorebar = Draw_PicFromWad ("scorebar");
 
//MED 01/04/97 added new hipnotic weapons
if (hipnotic)
{
hsb_weapons[0][0] = Draw_PicFromWad ("inv_laser");
hsb_weapons[0][1] = Draw_PicFromWad ("inv_mjolnir");
hsb_weapons[0][2] = Draw_PicFromWad ("inv_gren_prox");
hsb_weapons[0][3] = Draw_PicFromWad ("inv_prox_gren");
hsb_weapons[0][4] = Draw_PicFromWad ("inv_prox");
 
hsb_weapons[1][0] = Draw_PicFromWad ("inv2_laser");
hsb_weapons[1][1] = Draw_PicFromWad ("inv2_mjolnir");
hsb_weapons[1][2] = Draw_PicFromWad ("inv2_gren_prox");
hsb_weapons[1][3] = Draw_PicFromWad ("inv2_prox_gren");
hsb_weapons[1][4] = Draw_PicFromWad ("inv2_prox");
 
for (i=0 ; i<5 ; i++)
{
hsb_weapons[2+i][0] = Draw_PicFromWad (va("inva%i_laser",i+1));
hsb_weapons[2+i][1] = Draw_PicFromWad (va("inva%i_mjolnir",i+1));
hsb_weapons[2+i][2] = Draw_PicFromWad (va("inva%i_gren_prox",i+1));
hsb_weapons[2+i][3] = Draw_PicFromWad (va("inva%i_prox_gren",i+1));
hsb_weapons[2+i][4] = Draw_PicFromWad (va("inva%i_prox",i+1));
}
 
hsb_items[0] = Draw_PicFromWad ("sb_wsuit");
hsb_items[1] = Draw_PicFromWad ("sb_eshld");
}
 
if (rogue)
{
rsb_invbar[0] = Draw_PicFromWad ("r_invbar1");
rsb_invbar[1] = Draw_PicFromWad ("r_invbar2");
 
rsb_weapons[0] = Draw_PicFromWad ("r_lava");
rsb_weapons[1] = Draw_PicFromWad ("r_superlava");
rsb_weapons[2] = Draw_PicFromWad ("r_gren");
rsb_weapons[3] = Draw_PicFromWad ("r_multirock");
rsb_weapons[4] = Draw_PicFromWad ("r_plasma");
 
rsb_items[0] = Draw_PicFromWad ("r_shield1");
rsb_items[1] = Draw_PicFromWad ("r_agrav1");
 
// PGM 01/19/97 - team color border
rsb_teambord = Draw_PicFromWad ("r_teambord");
// PGM 01/19/97 - team color border
 
rsb_ammo[0] = Draw_PicFromWad ("r_ammolava");
rsb_ammo[1] = Draw_PicFromWad ("r_ammomulti");
rsb_ammo[2] = Draw_PicFromWad ("r_ammoplasma");
}
}
 
 
//=============================================================================
 
// drawing routines are relative to the status bar location
 
/*
=============
Sbar_DrawPic
=============
*/
void Sbar_DrawPic (int x, int y, qpic_t *pic)
{
if (cl.gametype == GAME_DEATHMATCH)
Draw_Pic (x /* + ((vid.width - 320)>>1)*/, y + (vid.height-SBAR_HEIGHT), pic);
else
Draw_Pic (x + ((vid.width - 320)>>1), y + (vid.height-SBAR_HEIGHT), pic);
}
 
/*
=============
Sbar_DrawTransPic
=============
*/
void Sbar_DrawTransPic (int x, int y, qpic_t *pic)
{
if (cl.gametype == GAME_DEATHMATCH)
Draw_TransPic (x /*+ ((vid.width - 320)>>1)*/, y + (vid.height-SBAR_HEIGHT), pic);
else
Draw_TransPic (x + ((vid.width - 320)>>1), y + (vid.height-SBAR_HEIGHT), pic);
}
 
/*
================
Sbar_DrawCharacter
 
Draws one solid graphics character
================
*/
void Sbar_DrawCharacter (int x, int y, int num)
{
if (cl.gametype == GAME_DEATHMATCH)
Draw_Character ( x /*+ ((vid.width - 320)>>1) */ + 4 , y + vid.height-SBAR_HEIGHT, num);
else
Draw_Character ( x + ((vid.width - 320)>>1) + 4 , y + vid.height-SBAR_HEIGHT, num);
}
 
/*
================
Sbar_DrawString
================
*/
void Sbar_DrawString (int x, int y, char *str)
{
if (cl.gametype == GAME_DEATHMATCH)
Draw_String (x /*+ ((vid.width - 320)>>1)*/, y+ vid.height-SBAR_HEIGHT, str);
else
Draw_String (x + ((vid.width - 320)>>1), y+ vid.height-SBAR_HEIGHT, str);
}
 
/*
=============
Sbar_itoa
=============
*/
int Sbar_itoa (int num, char *buf)
{
char *str;
int pow10;
int dig;
 
str = buf;
 
if (num < 0)
{
*str++ = '-';
num = -num;
}
 
for (pow10 = 10 ; num >= pow10 ; pow10 *= 10)
;
 
do
{
pow10 /= 10;
dig = num/pow10;
*str++ = '0'+dig;
num -= dig*pow10;
} while (pow10 != 1);
 
*str = 0;
 
return str-buf;
}
 
 
/*
=============
Sbar_DrawNum
=============
*/
void Sbar_DrawNum (int x, int y, int num, int digits, int color)
{
char str[12];
char *ptr;
int l, frame;
 
l = Sbar_itoa (num, str);
ptr = str;
if (l > digits)
ptr += (l-digits);
if (l < digits)
x += (digits-l)*24;
 
while (*ptr)
{
if (*ptr == '-')
frame = STAT_MINUS;
else
frame = *ptr -'0';
 
Sbar_DrawTransPic (x,y,sb_nums[color][frame]);
x += 24;
ptr++;
}
}
 
//=============================================================================
 
int fragsort[MAX_SCOREBOARD];
 
char scoreboardtext[MAX_SCOREBOARD][20];
int scoreboardtop[MAX_SCOREBOARD];
int scoreboardbottom[MAX_SCOREBOARD];
int scoreboardcount[MAX_SCOREBOARD];
int scoreboardlines;
 
/*
===============
Sbar_SortFrags
===============
*/
void Sbar_SortFrags (void)
{
int i, j, k;
 
// sort by frags
scoreboardlines = 0;
for (i=0 ; i<cl.maxclients ; i++)
{
if (cl.scores[i].name[0])
{
fragsort[scoreboardlines] = i;
scoreboardlines++;
}
}
 
for (i=0 ; i<scoreboardlines ; i++)
for (j=0 ; j<scoreboardlines-1-i ; j++)
if (cl.scores[fragsort[j]].frags < cl.scores[fragsort[j+1]].frags)
{
k = fragsort[j];
fragsort[j] = fragsort[j+1];
fragsort[j+1] = k;
}
}
 
int Sbar_ColorForMap (int m)
{
return m < 128 ? m + 8 : m + 8;
}
 
/*
===============
Sbar_UpdateScoreboard
===============
*/
void Sbar_UpdateScoreboard (void)
{
int i, k;
int top, bottom;
scoreboard_t *s;
 
Sbar_SortFrags ();
 
// draw the text
memset (scoreboardtext, 0, sizeof(scoreboardtext));
 
for (i=0 ; i<scoreboardlines; i++)
{
k = fragsort[i];
s = &cl.scores[k];
sprintf (&scoreboardtext[i][1], "%3i %s", s->frags, s->name);
 
top = s->colors & 0xf0;
bottom = (s->colors & 15) <<4;
scoreboardtop[i] = Sbar_ColorForMap (top);
scoreboardbottom[i] = Sbar_ColorForMap (bottom);
}
}
 
 
 
/*
===============
Sbar_SoloScoreboard
===============
*/
void Sbar_SoloScoreboard (void)
{
char str[80];
int minutes, seconds, tens, units;
int l;
 
sprintf (str,"Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
Sbar_DrawString (8, 4, str);
 
sprintf (str,"Secrets :%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]);
Sbar_DrawString (8, 12, str);
 
// time
minutes = cl.time / 60;
seconds = cl.time - 60*minutes;
tens = seconds / 10;
units = seconds - 10*tens;
sprintf (str,"Time :%3i:%i%i", minutes, tens, units);
Sbar_DrawString (184, 4, str);
 
// draw level name
l = strlen (cl.levelname);
Sbar_DrawString (232 - l*4, 12, cl.levelname);
}
 
/*
===============
Sbar_DrawScoreboard
===============
*/
void Sbar_DrawScoreboard (void)
{
Sbar_SoloScoreboard ();
if (cl.gametype == GAME_DEATHMATCH)
Sbar_DeathmatchOverlay ();
#if 0
int i, j, c;
int x, y;
int l;
int top, bottom;
scoreboard_t *s;
 
if (cl.gametype != GAME_DEATHMATCH)
{
Sbar_SoloScoreboard ();
return;
}
 
Sbar_UpdateScoreboard ();
 
l = scoreboardlines <= 6 ? scoreboardlines : 6;
 
for (i=0 ; i<l ; i++)
{
x = 20*(i&1);
y = i/2 * 8;
 
s = &cl.scores[fragsort[i]];
if (!s->name[0])
continue;
 
// draw background
top = s->colors & 0xf0;
bottom = (s->colors & 15)<<4;
top = Sbar_ColorForMap (top);
bottom = Sbar_ColorForMap (bottom);
 
Draw_Fill ( x*8+10 + ((vid.width - 320)>>1), y + vid.height - SBAR_HEIGHT, 28, 4, top);
Draw_Fill ( x*8+10 + ((vid.width - 320)>>1), y+4 + vid.height - SBAR_HEIGHT, 28, 4, bottom);
 
// draw text
for (j=0 ; j<20 ; j++)
{
c = scoreboardtext[i][j];
if (c == 0 || c == ' ')
continue;
Sbar_DrawCharacter ( (x+j)*8, y, c);
}
}
#endif
}
 
//=============================================================================
 
/*
===============
Sbar_DrawInventory
===============
*/
void Sbar_DrawInventory (void)
{
int i;
char num[6];
float time;
int flashon;
 
if (rogue)
{
if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
Sbar_DrawPic (0, -24, rsb_invbar[0]);
else
Sbar_DrawPic (0, -24, rsb_invbar[1]);
}
else
{
Sbar_DrawPic (0, -24, sb_ibar);
}
 
// weapons
for (i=0 ; i<7 ; i++)
{
if (cl.items & (IT_SHOTGUN<<i) )
{
time = cl.item_gettime[i];
flashon = (int)((cl.time - time)*10);
if (flashon >= 10)
{
if ( cl.stats[STAT_ACTIVEWEAPON] == (IT_SHOTGUN<<i) )
flashon = 1;
else
flashon = 0;
}
else
flashon = (flashon%5) + 2;
 
Sbar_DrawPic (i*24, -16, sb_weapons[flashon][i]);
 
if (flashon > 1)
sb_updates = 0; // force update to remove flash
}
}
 
// MED 01/04/97
// hipnotic weapons
if (hipnotic)
{
int grenadeflashing=0;
for (i=0 ; i<4 ; i++)
{
if (cl.items & (1<<hipweapons[i]) )
{
time = cl.item_gettime[hipweapons[i]];
flashon = (int)((cl.time - time)*10);
if (flashon >= 10)
{
if ( cl.stats[STAT_ACTIVEWEAPON] == (1<<hipweapons[i]) )
flashon = 1;
else
flashon = 0;
}
else
flashon = (flashon%5) + 2;
 
// check grenade launcher
if (i==2)
{
if (cl.items & HIT_PROXIMITY_GUN)
{
if (flashon)
{
grenadeflashing = 1;
Sbar_DrawPic (96, -16, hsb_weapons[flashon][2]);
}
}
}
else if (i==3)
{
if (cl.items & (IT_SHOTGUN<<4))
{
if (flashon && !grenadeflashing)
{
Sbar_DrawPic (96, -16, hsb_weapons[flashon][3]);
}
else if (!grenadeflashing)
{
Sbar_DrawPic (96, -16, hsb_weapons[0][3]);
}
}
else
Sbar_DrawPic (96, -16, hsb_weapons[flashon][4]);
}
else
Sbar_DrawPic (176 + (i*24), -16, hsb_weapons[flashon][i]);
if (flashon > 1)
sb_updates = 0; // force update to remove flash
}
}
}
 
if (rogue)
{
// check for powered up weapon.
if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
{
for (i=0;i<5;i++)
{
if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i))
{
Sbar_DrawPic ((i+2)*24, -16, rsb_weapons[i]);
}
}
}
}
 
// ammo counts
for (i=0 ; i<4 ; i++)
{
sprintf (num, "%3i",cl.stats[STAT_SHELLS+i] );
if (num[0] != ' ')
Sbar_DrawCharacter ( (6*i+1)*8 - 2, -24, 18 + num[0] - '0');
if (num[1] != ' ')
Sbar_DrawCharacter ( (6*i+2)*8 - 2, -24, 18 + num[1] - '0');
if (num[2] != ' ')
Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[2] - '0');
}
 
flashon = 0;
// items
for (i=0 ; i<6 ; i++)
if (cl.items & (1<<(17+i)))
{
time = cl.item_gettime[17+i];
if (time && time > cl.time - 2 && flashon )
{ // flash frame
sb_updates = 0;
}
else
{
//MED 01/04/97 changed keys
if (!hipnotic || (i>1))
{
Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
}
}
if (time && time > cl.time - 2)
sb_updates = 0;
}
//MED 01/04/97 added hipnotic items
// hipnotic items
if (hipnotic)
{
for (i=0 ; i<2 ; i++)
if (cl.items & (1<<(24+i)))
{
time = cl.item_gettime[24+i];
if (time && time > cl.time - 2 && flashon )
{ // flash frame
sb_updates = 0;
}
else
{
Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
}
if (time && time > cl.time - 2)
sb_updates = 0;
}
}
 
if (rogue)
{
// new rogue items
for (i=0 ; i<2 ; i++)
{
if (cl.items & (1<<(29+i)))
{
time = cl.item_gettime[29+i];
 
if (time && time > cl.time - 2 && flashon )
{ // flash frame
sb_updates = 0;
}
else
{
Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
}
 
if (time && time > cl.time - 2)
sb_updates = 0;
}
}
}
else
{
// sigils
for (i=0 ; i<4 ; i++)
{
if (cl.items & (1<<(28+i)))
{
time = cl.item_gettime[28+i];
if (time && time > cl.time - 2 && flashon )
{ // flash frame
sb_updates = 0;
}
else
Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
if (time && time > cl.time - 2)
sb_updates = 0;
}
}
}
}
 
//=============================================================================
 
/*
===============
Sbar_DrawFrags
===============
*/
void Sbar_DrawFrags (void)
{
int i, k, l;
int top, bottom;
int x, y, f;
int xofs;
char num[12];
scoreboard_t *s;
 
Sbar_SortFrags ();
 
// draw the text
l = scoreboardlines <= 4 ? scoreboardlines : 4;
 
x = 23;
if (cl.gametype == GAME_DEATHMATCH)
xofs = 0;
else
xofs = (vid.width - 320)>>1;
y = vid.height - SBAR_HEIGHT - 23;
 
for (i=0 ; i<l ; i++)
{
k = fragsort[i];
s = &cl.scores[k];
if (!s->name[0])
continue;
 
// draw background
top = s->colors & 0xf0;
bottom = (s->colors & 15)<<4;
top = Sbar_ColorForMap (top);
bottom = Sbar_ColorForMap (bottom);
 
Draw_Fill (xofs + x*8 + 10, y, 28, 4, top);
Draw_Fill (xofs + x*8 + 10, y+4, 28, 3, bottom);
 
// draw number
f = s->frags;
sprintf (num, "%3i",f);
 
Sbar_DrawCharacter ( (x+1)*8 , -24, num[0]);
Sbar_DrawCharacter ( (x+2)*8 , -24, num[1]);
Sbar_DrawCharacter ( (x+3)*8 , -24, num[2]);
 
if (k == cl.viewentity - 1)
{
Sbar_DrawCharacter (x*8+2, -24, 16);
Sbar_DrawCharacter ( (x+4)*8-4, -24, 17);
}
x+=4;
}
}
 
//=============================================================================
 
 
/*
===============
Sbar_DrawFace
===============
*/
void Sbar_DrawFace (void)
{
int f, anim;
 
// PGM 01/19/97 - team color drawing
// PGM 03/02/97 - fixed so color swatch only appears in CTF modes
if (rogue &&
(cl.maxclients != 1) &&
(teamplay.value>3) &&
(teamplay.value<7))
{
int top, bottom;
int xofs;
char num[12];
scoreboard_t *s;
s = &cl.scores[cl.viewentity - 1];
// draw background
top = s->colors & 0xf0;
bottom = (s->colors & 15)<<4;
top = Sbar_ColorForMap (top);
bottom = Sbar_ColorForMap (bottom);
 
if (cl.gametype == GAME_DEATHMATCH)
xofs = 113;
else
xofs = ((vid.width - 320)>>1) + 113;
 
Sbar_DrawPic (112, 0, rsb_teambord);
Draw_Fill (xofs, vid.height-SBAR_HEIGHT+3, 22, 9, top);
Draw_Fill (xofs, vid.height-SBAR_HEIGHT+12, 22, 9, bottom);
 
// draw number
f = s->frags;
sprintf (num, "%3i",f);
 
if (top==8)
{
if (num[0] != ' ')
Sbar_DrawCharacter(109, 3, 18 + num[0] - '0');
if (num[1] != ' ')
Sbar_DrawCharacter(116, 3, 18 + num[1] - '0');
if (num[2] != ' ')
Sbar_DrawCharacter(123, 3, 18 + num[2] - '0');
}
else
{
Sbar_DrawCharacter ( 109, 3, num[0]);
Sbar_DrawCharacter ( 116, 3, num[1]);
Sbar_DrawCharacter ( 123, 3, num[2]);
}
return;
}
// PGM 01/19/97 - team color drawing
 
if ( (cl.items & (IT_INVISIBILITY | IT_INVULNERABILITY) )
== (IT_INVISIBILITY | IT_INVULNERABILITY) )
{
Sbar_DrawPic (112, 0, sb_face_invis_invuln);
return;
}
if (cl.items & IT_QUAD)
{
Sbar_DrawPic (112, 0, sb_face_quad );
return;
}
if (cl.items & IT_INVISIBILITY)
{
Sbar_DrawPic (112, 0, sb_face_invis );
return;
}
if (cl.items & IT_INVULNERABILITY)
{
Sbar_DrawPic (112, 0, sb_face_invuln);
return;
}
 
if (cl.stats[STAT_HEALTH] >= 100)
f = 4;
else
f = cl.stats[STAT_HEALTH] / 20;
 
if (cl.time <= cl.faceanimtime)
{
anim = 1;
sb_updates = 0; // make sure the anim gets drawn over
}
else
anim = 0;
Sbar_DrawPic (112, 0, sb_faces[f][anim]);
}
 
/*
===============
Sbar_Draw
===============
*/
void Sbar_Draw (void)
{
if (scr_con_current == vid.height)
return; // console is full screen
 
if (sb_updates >= vid.numpages)
return;
 
scr_copyeverything = 1;
 
sb_updates++;
 
if (sb_lines && vid.width > 320)
Draw_TileClear (0, vid.height - sb_lines, vid.width, sb_lines);
 
if (sb_lines > 24)
{
Sbar_DrawInventory ();
if (cl.maxclients != 1)
Sbar_DrawFrags ();
}
 
if (sb_showscores || cl.stats[STAT_HEALTH] <= 0)
{
Sbar_DrawPic (0, 0, sb_scorebar);
Sbar_DrawScoreboard ();
sb_updates = 0;
}
else if (sb_lines)
{
Sbar_DrawPic (0, 0, sb_sbar);
 
// keys (hipnotic only)
//MED 01/04/97 moved keys here so they would not be overwritten
if (hipnotic)
{
if (cl.items & IT_KEY1)
Sbar_DrawPic (209, 3, sb_items[0]);
if (cl.items & IT_KEY2)
Sbar_DrawPic (209, 12, sb_items[1]);
}
// armor
if (cl.items & IT_INVULNERABILITY)
{
Sbar_DrawNum (24, 0, 666, 3, 1);
Sbar_DrawPic (0, 0, draw_disc);
}
else
{
if (rogue)
{
Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3,
cl.stats[STAT_ARMOR] <= 25);
if (cl.items & RIT_ARMOR3)
Sbar_DrawPic (0, 0, sb_armor[2]);
else if (cl.items & RIT_ARMOR2)
Sbar_DrawPic (0, 0, sb_armor[1]);
else if (cl.items & RIT_ARMOR1)
Sbar_DrawPic (0, 0, sb_armor[0]);
}
else
{
Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3
, cl.stats[STAT_ARMOR] <= 25);
if (cl.items & IT_ARMOR3)
Sbar_DrawPic (0, 0, sb_armor[2]);
else if (cl.items & IT_ARMOR2)
Sbar_DrawPic (0, 0, sb_armor[1]);
else if (cl.items & IT_ARMOR1)
Sbar_DrawPic (0, 0, sb_armor[0]);
}
}
 
// face
Sbar_DrawFace ();
 
// health
Sbar_DrawNum (136, 0, cl.stats[STAT_HEALTH], 3
, cl.stats[STAT_HEALTH] <= 25);
 
// ammo icon
if (rogue)
{
if (cl.items & RIT_SHELLS)
Sbar_DrawPic (224, 0, sb_ammo[0]);
else if (cl.items & RIT_NAILS)
Sbar_DrawPic (224, 0, sb_ammo[1]);
else if (cl.items & RIT_ROCKETS)
Sbar_DrawPic (224, 0, sb_ammo[2]);
else if (cl.items & RIT_CELLS)
Sbar_DrawPic (224, 0, sb_ammo[3]);
else if (cl.items & RIT_LAVA_NAILS)
Sbar_DrawPic (224, 0, rsb_ammo[0]);
else if (cl.items & RIT_PLASMA_AMMO)
Sbar_DrawPic (224, 0, rsb_ammo[1]);
else if (cl.items & RIT_MULTI_ROCKETS)
Sbar_DrawPic (224, 0, rsb_ammo[2]);
}
else
{
if (cl.items & IT_SHELLS)
Sbar_DrawPic (224, 0, sb_ammo[0]);
else if (cl.items & IT_NAILS)
Sbar_DrawPic (224, 0, sb_ammo[1]);
else if (cl.items & IT_ROCKETS)
Sbar_DrawPic (224, 0, sb_ammo[2]);
else if (cl.items & IT_CELLS)
Sbar_DrawPic (224, 0, sb_ammo[3]);
}
 
Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3,
cl.stats[STAT_AMMO] <= 10);
}
 
if (vid.width > 320) {
if (cl.gametype == GAME_DEATHMATCH)
Sbar_MiniDeathmatchOverlay ();
}
}
 
//=============================================================================
 
/*
==================
Sbar_IntermissionNumber
 
==================
*/
void Sbar_IntermissionNumber (int x, int y, int num, int digits, int color)
{
char str[12];
char *ptr;
int l, frame;
 
l = Sbar_itoa (num, str);
ptr = str;
if (l > digits)
ptr += (l-digits);
if (l < digits)
x += (digits-l)*24;
 
while (*ptr)
{
if (*ptr == '-')
frame = STAT_MINUS;
else
frame = *ptr -'0';
 
Draw_TransPic (x,y,sb_nums[color][frame]);
x += 24;
ptr++;
}
}
 
/*
==================
Sbar_DeathmatchOverlay
 
==================
*/
void Sbar_DeathmatchOverlay (void)
{
qpic_t *pic;
int i, k, l;
int top, bottom;
int x, y, f;
char num[12];
scoreboard_t *s;
 
scr_copyeverything = 1;
scr_fullupdate = 0;
 
pic = Draw_CachePic ("gfx/ranking.lmp");
M_DrawPic ((320-pic->width)/2, 8, pic);
 
// scores
Sbar_SortFrags ();
 
// draw the text
l = scoreboardlines;
 
x = 80 + ((vid.width - 320)>>1);
y = 40;
for (i=0 ; i<l ; i++)
{
k = fragsort[i];
s = &cl.scores[k];
if (!s->name[0])
continue;
 
// draw background
top = s->colors & 0xf0;
bottom = (s->colors & 15)<<4;
top = Sbar_ColorForMap (top);
bottom = Sbar_ColorForMap (bottom);
 
Draw_Fill ( x, y, 40, 4, top);
Draw_Fill ( x, y+4, 40, 4, bottom);
 
// draw number
f = s->frags;
sprintf (num, "%3i",f);
 
Draw_Character ( x+8 , y, num[0]);
Draw_Character ( x+16 , y, num[1]);
Draw_Character ( x+24 , y, num[2]);
 
if (k == cl.viewentity - 1)
Draw_Character ( x - 8, y, 12);
 
#if 0
{
int total;
int n, minutes, tens, units;
 
// draw time
total = cl.completed_time - s->entertime;
minutes = (int)total/60;
n = total - minutes*60;
tens = n/10;
units = n%10;
 
sprintf (num, "%3i:%i%i", minutes, tens, units);
 
Draw_String ( x+48 , y, num);
}
#endif
 
// draw name
Draw_String (x+64, y, s->name);
 
y += 10;
}
}
 
/*
==================
Sbar_DeathmatchOverlay
 
==================
*/
void Sbar_MiniDeathmatchOverlay (void)
{
qpic_t *pic;
int i, k, l;
int top, bottom;
int x, y, f;
char num[12];
scoreboard_t *s;
int numlines;
 
if (vid.width < 512 || !sb_lines)
return;
 
scr_copyeverything = 1;
scr_fullupdate = 0;
 
// scores
Sbar_SortFrags ();
 
// draw the text
l = scoreboardlines;
y = vid.height - sb_lines;
numlines = sb_lines/8;
if (numlines < 3)
return;
 
//find us
for (i = 0; i < scoreboardlines; i++)
if (fragsort[i] == cl.viewentity - 1)
break;
 
if (i == scoreboardlines) // we're not there
i = 0;
else // figure out start
i = i - numlines/2;
 
if (i > scoreboardlines - numlines)
i = scoreboardlines - numlines;
if (i < 0)
i = 0;
 
x = 324;
for (/* */; i < scoreboardlines && y < vid.height - 8 ; i++)
{
k = fragsort[i];
s = &cl.scores[k];
if (!s->name[0])
continue;
 
// draw background
top = s->colors & 0xf0;
bottom = (s->colors & 15)<<4;
top = Sbar_ColorForMap (top);
bottom = Sbar_ColorForMap (bottom);
 
Draw_Fill ( x, y+1, 40, 3, top);
Draw_Fill ( x, y+4, 40, 4, bottom);
 
// draw number
f = s->frags;
sprintf (num, "%3i",f);
 
Draw_Character ( x+8 , y, num[0]);
Draw_Character ( x+16 , y, num[1]);
Draw_Character ( x+24 , y, num[2]);
 
if (k == cl.viewentity - 1) {
Draw_Character ( x, y, 16);
Draw_Character ( x + 32, y, 17);
}
 
#if 0
{
int total;
int n, minutes, tens, units;
 
// draw time
total = cl.completed_time - s->entertime;
minutes = (int)total/60;
n = total - minutes*60;
tens = n/10;
units = n%10;
 
sprintf (num, "%3i:%i%i", minutes, tens, units);
 
Draw_String ( x+48 , y, num);
}
#endif
 
// draw name
Draw_String (x+48, y, s->name);
 
y += 8;
}
}
 
/*
==================
Sbar_IntermissionOverlay
 
==================
*/
void Sbar_IntermissionOverlay (void)
{
qpic_t *pic;
int dig;
int num;
 
scr_copyeverything = 1;
scr_fullupdate = 0;
 
if (cl.gametype == GAME_DEATHMATCH)
{
Sbar_DeathmatchOverlay ();
return;
}
 
pic = Draw_CachePic ("gfx/complete.lmp");
Draw_Pic (64, 24, pic);
 
pic = Draw_CachePic ("gfx/inter.lmp");
Draw_TransPic (0, 56, pic);
 
// time
dig = cl.completed_time/60;
Sbar_IntermissionNumber (160, 64, dig, 3, 0);
num = cl.completed_time - dig*60;
Draw_TransPic (234,64,sb_colon);
Draw_TransPic (246,64,sb_nums[0][num/10]);
Draw_TransPic (266,64,sb_nums[0][num%10]);
 
Sbar_IntermissionNumber (160, 104, cl.stats[STAT_SECRETS], 3, 0);
Draw_TransPic (232,104,sb_slash);
Sbar_IntermissionNumber (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
 
Sbar_IntermissionNumber (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
Draw_TransPic (232,144,sb_slash);
Sbar_IntermissionNumber (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
 
}
 
 
/*
==================
Sbar_FinaleOverlay
 
==================
*/
void Sbar_FinaleOverlay (void)
{
qpic_t *pic;
 
scr_copyeverything = 1;
 
pic = Draw_CachePic ("gfx/finale.lmp");
Draw_TransPic ( (vid.width-pic->width)/2, 16, pic);
}
/contrib/other/sdlquake-1.0.9/sbar.h
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.
 
*/
 
// 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);
 
void Sbar_Changed (void);
// call whenever any of the client stats represented on the sbar changes
 
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);
/contrib/other/sdlquake-1.0.9/scitech/INCLUDE/DEBUG.H
0,0 → 1,290
/****************************************************************************
*
* Copyright (C) 1996 SciTech Software
* All rights reserved.
*
* Filename: $Workfile: debug.h $
* Version: $Revision: 1.17 $
*
* Language: ANSI C
* Environment: any
*
* Description: General header file for operating system portable code.
*
* $Date: 04 Mar 1997 11:34:08 $ $Author: KendallB $
*
****************************************************************************/
 
#ifndef __DEBUG_H
#define __DEBUG_H
 
/* We have the following defines to identify the compilation environment:
*
* __16BIT__ Compiling for 16 bit code (any environment)
* __32BIT__ Compiling for 32 bit code (any environment)
* __MSDOS__ Compiling for MS-DOS (includes __WINDOWS16__, __WIN386__)
* __REALDOS__ Compiling for MS-DOS (excludes __WINDOWS16__)
* __MSDOS16__ Compiling for 16 bit MS-DOS
* __MSDOS32__ Compiling for 32 bit MS-DOS
* __WINDOWS__ Compiling for Windows
* __WINDOWS16__ Compiling for 16 bit Windows (__MSDOS__ also defined)
* __WINDOWS32__ Compiling for 32 bit Windows
* __WIN386__ Compiling for Watcom C++ Win386 extended Windows
* __OS2__ Compiling for OS/2
* __OS2_16__ Compiling for 16 bit OS/2
* __OS2_32__ Compiling for 32 bit OS/2
* __UNIX__ Compiling for Unix
*
*/
 
#ifdef __SC__
#if __INTSIZE == 4
#define __SC386__
#endif
#endif
 
#ifdef __GNUC__
#define __cdecl /* GCC doesn't know about __cdecl modifiers */
#define __FLAT__ /* GCC is always 32 bit flat model */
#define __HAS_BOOL__ /* Latest GNU C++ has bool type */
#endif
 
#ifdef __BORLANDC__
#if (__BORLANDC__ >= 0x500) || defined(CLASSLIB_DEFS_H)
#define __HAS_BOOL__ /* Borland C++ 5.0 and later define bool type */
#endif
#endif
 
/* For the Metaware High C/C++ compiler, there is no _cdecl calling
* convention. The conventions can be changed, but it is a complicated
* process involving #pragmas, and all externally referenced functions
* will use stack based calling conventions. We also need to change the
* global aliasing conventions to use underscores for external function
* and variables names, so that our assembler routines will link
* correctly (except of course the main function - man what a PAIN!).
*/
 
#ifdef __HIGHC__
#define __cdecl
#define __FLAT__ /* High C is always 32 bit flat model */
#pragma Global_aliasing_convention("_%r")
extern main();
#pragma Alias(main,"main")
#endif
 
#if defined(__MSDOS__) || defined(__DOS__) || defined(__DPMI32__) || (defined(M_I86) && !defined(__SC386__))
#ifndef __MSDOS__
#define __MSDOS__
#endif
#if defined(__386__) || defined(__FLAT__) || defined(__NT__) || defined(__SC386__)
#ifndef __MSDOS32__
#define __MSDOS32__
#endif
#ifndef __32BIT__
#define __32BIT__
#endif
#ifndef __REALDOS__
#define __REALDOS__
#endif
#elif (defined(_Windows) || defined(_WINDOWS)) && !defined(__DPMI16__)
#ifndef __16BIT__
#define __16BIT__
#endif
#ifndef __WINDOWS16__
#define __WINDOWS16__
#endif
#ifndef __WINDOWS__
#define __WINDOWS__
#endif
#ifndef __MSDOS__
#define __MSDOS__
#endif
#else
#ifndef __16BIT__
#define __16BIT__
#endif
#ifndef __MSDOS16__
#define __MSDOS16__
#endif
#ifndef __REALDOS__
#define __REALDOS__
#endif
#endif
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
#ifndef __32BIT__
#define __32BIT__
#endif
#ifndef __WINDOWS32__
#define __WINDOWS32__
#endif
#ifndef _WIN32
#define _WIN32 /* Microsoft Win32 SDK headers use _WIN32 */
#endif
#ifndef WIN32
#define WIN32 /* OpenGL headers use WIN32 */
#endif
#ifndef __WINDOWS__
#define __WINDOWS__
#endif
#elif defined(__WINDOWS_386__)
#ifndef __32BIT__
#define __32BIT__
#endif
#ifndef __WIN386__
#define __WIN386__
#endif
#ifndef __WINDOWS__
#define __WINDOWS__
#endif
#ifndef __MSDOS__
#define __MSDOS__
#endif
#elif defined(__OS2__)
#ifndef __OS2__ /* TODO: to be completed */
#define __OS2__
#define __OS2_32__ /* Default to 32 bit OS/2 */
#endif
#else
#define __UNIX__ /* TODO: to be completed */
#endif
 
/* We have the following defines to define the calling conventions for
* publicly accesible functions:
*
* _PUBAPI - Compiler default calling conventions for all public 'C' functions
* _ASMAPI - Calling conventions for all public assembler functions
* _DLLAPI - Calling conventions for all DLL exported functions
* _DLLVAR - Modifier to export/import globals in 32 bit DLL's
* _EXPORT - Expands to _export when compiling a DLL
* _VARAPI - Modifiers for variables; Watcom C++ mangles C++ globals
*/
 
#define _PUBAPI
#define _ASMAPI __cdecl
 
#if defined(_MSC_VER) && defined(_WIN32) && !defined(__SC__)
#define __PASCAL __stdcall
#define __export
#define __import
#else
#define __PASCAL __pascal
#endif
 
#if defined(__WATCOMC__)
#define _VARAPI __cdecl
#else
#define _VARAPI
#endif
 
#if defined(__WINDOWS__)
#ifdef BUILD_DLL
#define _DLLASM __export __cdecl
#define _EXPORT __export
#ifdef __WINDOWS32__
#define _DLLAPI __export __PASCAL
#define _DLLVAR __export
#else
#define _DLLAPI __export __far __pascal
#define _DLLVAR
#endif
#else
#define _DLLASM __cdecl
#define _EXPORT
#ifdef __WINDOWS32__
#define _DLLAPI __PASCAL
#define _DLLVAR __import
#else
#define _DLLAPI __far __pascal
#define _DLLVAR
#endif
#endif
#else
#define _EXPORT
#define _DLLAPI
#define _DLLVAR
#endif
 
/* Useful macros */
 
#define PRIVATE static
#define PUBLIC
 
#ifdef DEBUG
# define DBG(x) x
#else
# define DBG(x)
#endif
 
#ifndef NULL
# define NULL 0L
#endif
 
#ifndef MAX
# define MAX(a,b) ( ((a) > (b)) ? (a) : (b))
#endif
#ifndef MIN
# define MIN(a,b) ( ((a) < (b)) ? (a) : (b))
#endif
#ifndef ABS
# define ABS(a) ((a) >= 0 ? (a) : -(a))
#endif
#ifndef SIGN
# define SIGN(a) ((a) > 0 ? 1 : -1)
#endif
 
/* General typedefs */
 
#ifndef __GENDEFS
#define __GENDEFS
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef int ibool; /* Integer boolean type */
#ifndef __cplusplus
#define bool ibool /* Standard C */
#else
#ifndef __HAS_BOOL__
#define bool ibool /* Older C++ compilers */
#endif
#endif /* __cplusplus */
#endif /* __GENDEFS */
 
/* Includes Windows headers, as they define TRUE and FALSE */
 
#ifdef __WINDOWS__
#ifndef _WINDOWS_ /* Dont include if already included */
#ifndef __WIN386__
#define STRICT
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#endif
#endif
 
/* Boolean truth values */
 
#undef false
#undef true
#undef NO
#undef YES
#undef FALSE
#undef TRUE
 
#ifdef __cplusplus /* Cast to bool's for C++ code */
#define false ((bool)0)
#define true ((bool)1)
#define NO ((bool)0)
#define YES ((bool)1)
#define FALSE ((bool)0)
#define TRUE ((bool)1)
#else /* Define to 0 and 1 for C code */
#define false 0
#define true 1
#define NO 0
#define YES 1
#define FALSE 0
#define TRUE 1
#endif
 
#endif /* __DEBUG_H */
/contrib/other/sdlquake-1.0.9/scitech/INCLUDE/MGLDOS.H
0,0 → 1,83
/****************************************************************************
*
* MegaGraph Graphics Library
*
* Copyright (C) 1996 SciTech Software.
* All rights reserved.
*
* Filename: $Workfile: mgldos.h $
* Version: $Revision: 1.9 $
*
* Language: ANSI C
* Environment: IBM PC (MS DOS)
*
* Description: Header file for the MGLDOS binding for the MSDOS environment.
*
* $Date: 30 Jan 1997 17:31:58 $ $Author: KendallB $
*
****************************************************************************/
 
#ifndef __MGLDOS_H
#define __MGLDOS_H
 
#ifndef MGLDOS
#define MGLDOS
#endif
 
/*---------------------- Macros and type definitions ----------------------*/
 
typedef void *MGL_HWND;
 
/*------------------------- Function Prototypes ---------------------------*/
 
#ifdef __cplusplus
extern "C" { /* Use "C" linkage when in C++ mode */
#endif
 
/* Initialise the MGL for fullscreen output */
 
bool MGLAPI MGL_init(m_int *driver,m_int *mode,const char *mglpath);
 
/* Change the active display mode. You must destroy all display device
* contexts before calling this function, and re-create them again with
* the new display mode. Does not affect any event handling hooks.
*/
 
bool MGLAPI MGL_changeDisplayMode(m_int mode);
 
/* Disable/enable event handling (call before calling MGL_init */
 
void MGLAPI MGL_useEvents(bool use);
 
/* Device context management */
 
MGLDC * MGLAPI MGL_createDisplayDC(m_int numBuffers);
MGLDC * MGLAPI MGL_createScrollingDC(m_int virtualX,m_int virtualY,m_int numBuffers);
MGLDC * MGLAPI MGL_createOffscreenDC(void);
MGLDC * MGLAPI MGL_createLinearOffscreenDC(void);
MGLDC * MGLAPI MGL_createMemoryDC(m_int xSize,m_int ySize,m_int bitsPerPixel,pixel_format_t *pf);
bool MGLAPI MGL_destroyDC(MGLDC *dc);
 
/* Generic helper functions */
 
ulong MGLAPI MGL_getTicks(void);
ulong MGLAPI MGL_getTickResolution(void);
void MGLAPI MGL_delay(m_int millseconds);
void MGLAPI MGL_beep(m_int freq,m_int milliseconds);
void MGLAPI MGL_suspend(void);
void MGLAPI MGL_resume(void);
 
/* Fullscreen specific routines */
 
void MGLAPI MGL_setPaletteSnowLevel(MGLDC *dc,m_int level);
m_int MGLAPI MGL_getPaletteSnowLevel(MGLDC *dc);
 
/* Determine if a specific scancode'ed key is held down (PC specific) */
 
bool MGLAPI EVT_isKeyDown(uchar scanCode);
 
#ifdef __cplusplus
} /* End of "C" linkage for C++ */
#endif
 
#endif /* __MGLDOS_H */
/contrib/other/sdlquake-1.0.9/scitech/INCLUDE/MGLWIN.H
0,0 → 1,152
/****************************************************************************
*
* MegaGraph Graphics Library
*
* Copyright (C) 1996 SciTech Software.
* All rights reserved.
*
* Filename: $Workfile: mglwin.h $
* Version: $Revision: 1.14 $
*
* Language: ANSI C
* Environment: IBM PC (MS DOS)
*
* Description: Header file for the MGLWIN bindings for MS Windows using
* WinG in a window and WinDirect for full screen. The MGLWIN
* binding only targets Win32 applications, so cannot be used
* for 16 bit Windows development.
*
* $Date: 14 Mar 1997 16:09:34 $ $Author: KendallB $
*
****************************************************************************/
 
#ifndef __MGLWIN_H
#define __MGLWIN_H
 
#ifndef MGLWIN
#define MGLWIN
#endif
 
/*---------------------- Macros and type definitions ----------------------*/
 
typedef HWND MGL_HWND;
typedef HDC MGL_HDC;
typedef HINSTANCE MGL_HINSTANCE;
 
/*------------------------- Function Prototypes ---------------------------*/
 
#ifdef __cplusplus
extern "C" { /* Use "C" linkage when in C++ mode */
#endif
 
/* Initialise the MGL for fullscreen output */
 
bool MGLAPI MGL_init(m_int *driver,m_int *mode,const char *mglpath);
 
/* Initialise the MGL just for Windowed output, not full screen */
 
bool MGLAPI MGL_initWindowed(const char *mglpath);
 
/* Function to register a fullscreen window with the MGL. If you wish
* for the MGL to use your own window for fullscreen modes, you can
* register it with this function. Note that when the MGL goes into
* fullscreen modes, the attributes, size and position of the window are
* modified to make it into a fullscreen Window necessary to cover the
* entire desktop, and the state of the window will be restore to the original
* format on return to normal GDI mode.
*
* Note that if you are using a common window for Windowed mode and fullscreen
* modes of your application, you will need to ensure that certain messages
* that you window normally handles in windowed modes are ignored when in
* fullscreen modes.
*/
 
void MGLAPI MGL_registerFullScreenWindow(HWND hwndFullScreen);
 
/* Function to register a fullscreen event handling window procedure.
* If you wish to do your own event handling, you can register your window
* procedure with the MGL using this function and it will be called
* when there are messages to be handled. You can still call the MGL_event()
* functions even if you have registered an event handling procedure.
*/
 
void MGLAPI MGL_registerEventProc(WNDPROC userWndProc);
 
/* Change the active display mode. You must destroy all display device
* contexts before calling this function, and re-create them again with
* the new display mode. Does not affect any event handling hooks.
*/
 
bool MGLAPI MGL_changeDisplayMode(m_int mode);
 
/* Obtain the handle to the MGL fullscreen window when in fullscreen modes */
 
MGL_HWND MGLAPI MGL_getFullScreenWindow(void);
 
/* Tell the MGL what your applications main window is */
 
void MGLAPI MGL_setMainWindow(MGL_HWND hwnd);
 
/* Tell the MGL your applications instance handle (call before all funcs!) */
 
void MGLAPI MGL_setAppInstance(MGL_HINSTANCE hInstApp);
 
/* Device context management */
 
MGLDC * MGLAPI MGL_createDisplayDC(m_int numBuffers);
MGLDC * MGLAPI MGL_createSrollingDC(m_int virtualX,m_int virtualY,m_int numBuffers);
MGLDC * MGLAPI MGL_createOffscreenDC(void);
MGLDC * MGLAPI MGL_createLinearOffscreenDC(void);
MGLDC * MGLAPI MGL_createWindowedDC(MGL_HWND hwnd);
MGLDC * MGLAPI MGL_createMemoryDC(m_int xSize,m_int ySize,m_int bitsPerPixel,pixel_format_t *pf);
bool MGLAPI MGL_destroyDC(MGLDC *dc);
 
/* Get a Windows HDC for the MGL device context. You can use this returned
* HDC to get GDI to draw to the device context surface, such as rendering
* and using TrueType fonts with the MGL. If a Windows compatible HDC is not
* available, this function will return NULL.
*/
 
HDC MGLAPI MGL_getWinDC(MGLDC *dc);
 
/* Associate a Window manager DC with the MGLDC for painting */
 
bool MGLAPI MGL_setWinDC(MGLDC *dc,MGL_HDC hdc);
 
/* Activate the WindowDC's palette */
 
bool MGLAPI MGL_activatePalette(MGLDC *dc,bool unrealize);
 
/* Let the MGL know when your application is being activated or deactivated.
* This function only needs to be called when running in Windowed modes and
* you have set the system palette to SYSPAL_NOSTATIC mode, to ensure
* that the MGL can properly re-map your application palette when your
* app is not active and allow Windows to re-map your bitmap colors on the
* fly. This function should be passed a pointer to the currently active
* MGL Windowed DC and a flag to indicate whether the app is in the background
* or not.
*/
 
void MGLAPI MGL_appActivate(MGLDC *winDC,bool active);
 
/* Generic helper functions */
 
ulong MGLAPI MGL_getTicks(void);
ulong MGLAPI MGL_getTickResolution(void);
void MGLAPI MGL_delay(m_int millseconds);
void MGLAPI MGL_beep(m_int freq,m_int milliseconds);
 
/* Fullscreen specific routines */
 
void MGLAPI MGL_setPaletteSnowLevel(MGLDC *dc,m_int level);
m_int MGLAPI MGL_getPaletteSnowLevel(MGLDC *dc);
 
/* Determine if a specific scancode'ed key is held down (PC specific) */
 
bool MGLAPI EVT_isKeyDown(uchar scanCode);
 
#ifdef __cplusplus
} /* End of "C" linkage for C++ */
#endif
 
#endif /* __MGLWIN_H */
/contrib/other/sdlquake-1.0.9/scitech/INCLUDE/MGRAPH.H
0,0 → 1,1951
/****************************************************************************
*
* MegaGraph Graphics Library
*
* Copyright (C) 1996 SciTech Software.
* All rights reserved.
*
* Filename: $Workfile: mgraph.h $
* Version: $Revision: 1.29 $
*
* Language: ANSI C
* Environment: IBM PC (MS DOS)
*
* Description: Header file for the MegaGraph Graphics Library. You can
* defined one of the following to specify which MGL API you
* wish to use.
*
* MGL_LITE - Compile for the MGL/Lite API
* MGL_PRO - Compile for the MGL/Pro API
* MGL_FIX3D - Compile for the MGL/3D API (fixed point)
* MGL_FLT3D - Compile for the MGL/3D API (floating point)
*
* If you do not define any of these, MGL_FIX3D will be defined
* automatically for compatibility with older versions of the
* MGL.
*
* $Date: 11 Mar 1997 16:46:42 $ $Author: KendallB $
*
****************************************************************************/
 
#ifndef __MGRAPH_H
#define __MGRAPH_H
 
#include <stdio.h>
 
#ifndef __DEBUG_H
#include "debug.h"
#endif
 
#if !defined(MGL_LITE) && !defined(MGL_PRO) && !defined(MGL_FIX3D) \
&& !defined(MGL_FLT3D)
#define MGL_FIX3D
#endif
 
#if defined(MGL_FIX3D) || defined(MGL_FLT3D)
#define MGL_3D
#endif
 
/*---------------------- Macros and type definitions ----------------------*/
 
#pragma pack(1) /* Pack structures to byte granularity */
 
/* Define the version number for the MGL release */
 
#define MGL_VERSION_STR "3.1"
 
/* Define the calling conventions for all public MGL functions. If we
* are compiling the MGL as a DLL, then all public functions are compiled
* and exported with standard C calling conventions, otherwise we use
* the default calling conventions provided by the compiler.
*
* Note that because Watcom C++ uses register based parameter passing
* by default we also provide special DLL's for watcom that are compiled
* with register parameter passing. This is necessary to work with all
* the extra libraries provided as they are all compiled to call MGL
* functions with arguments in registers whenever possible. You can still
* use the standard DLL but if you do you will need to re-compile all
* of the extra libraries with the MGL_DLL #define to change the calling
* conventions for the MGL functions.
*/
 
#if defined(MGL_DLL)
#define MGLAPI _EXPORT __cdecl
#else
#define MGLAPI _EXPORT _PUBAPI
#endif
#define ASMAPI _EXPORT __cdecl
 
/* Define a type for integers used in the library. For most environments
* we simply define it as a normal integer (16 or 32 bits), however for
* 16 bit Windows it is defined as a 32 bit integer as all the real code
* lives in a 32 bit DLL that uses 32 bit integers.
*/
 
#ifndef __M_INT_DEFINED
#if defined(__WINDOWS16__)
typedef long m_int;
typedef unsigned long m_uint;
#else
typedef int m_int;
typedef unsigned int m_uint;
#endif
#define __M_INT_DEFINED
#endif
 
/* Define the graphics subsystems available */
 
typedef enum {
grDETECT = -1, /* Auto detect the graphics subsystem */
grNONE = 0, /* No graphics hardware detected */
grVGA, /* Standard VGA */
grVESA, /* VESA VBE compliant SuperVGA */
grSVGA, /* Unaccelerated SuperVGA */
grACCEL, /* Accelerated SuperVGA */
grDDRAW, /* Unaccelerated DirectDraw */
grDDRAWACCEL, /* Accelerated DirectDraw */
grDDRAW3D, /* 3D Accelerated DirectDraw */
grMAXDRIVER, /* Maximum driver number */
} MGL_driverType;
 
/* Graphics modes supported - the only video modes supported by this
* graphics library are those that support at least 16 colors per pixel.
*/
 
typedef enum {
/* 16 color VGA video modes */
 
grVGA_320x200x16,
grVGA_640x200x16,
grVGA_640x350x16,
grVGA_640x400x16,
grVGA_640x480x16,
grSVGA_800x600x16,
 
/* 256 color VGA ModeX video modes */
 
grVGAX_320x200x256,
grVGAX_320x240x256,
grVGAX_320x400x256,
grVGAX_320x480x256,
 
/* 256 color VGA video modes */
 
grVGA_320x200x256,
 
/* 256 color VGA/SuperVGA video modes */
 
grSVGA_320x200x256,
grSVGA_320x240x256,
grSVGA_320x400x256,
grSVGA_320x480x256,
grSVGA_400x300x256,
grSVGA_512x384x256,
grSVGA_640x350x256,
grSVGA_640x400x256,
grSVGA_640x480x256,
grSVGA_800x600x256,
grSVGA_1024x768x256,
grSVGA_1152x864x256,
grSVGA_1280x960x256,
grSVGA_1280x1024x256,
grSVGA_1600x1200x256,
 
/* 32,768 color Super VGA video modes */
 
grSVGA_320x200x32k,
grSVGA_320x240x32k,
grSVGA_320x400x32k,
grSVGA_320x480x32k,
grSVGA_400x300x32k,
grSVGA_512x384x32k,
grSVGA_640x350x32k,
grSVGA_640x400x32k,
grSVGA_640x480x32k,
grSVGA_800x600x32k,
grSVGA_1024x768x32k,
grSVGA_1152x864x32k,
grSVGA_1280x960x32k,
grSVGA_1280x1024x32k,
grSVGA_1600x1200x32k,
 
/* 65,536 color Super VGA video modes */
 
grSVGA_320x200x64k,
grSVGA_320x240x64k,
grSVGA_320x400x64k,
grSVGA_320x480x64k,
grSVGA_400x300x64k,
grSVGA_512x384x64k,
grSVGA_640x350x64k,
grSVGA_640x400x64k,
grSVGA_640x480x64k,
grSVGA_800x600x64k,
grSVGA_1024x768x64k,
grSVGA_1152x864x64k,
grSVGA_1280x960x64k,
grSVGA_1280x1024x64k,
grSVGA_1600x1200x64k,
 
/* 16 million color, 24 bits per pixel Super VGA video modes */
 
grSVGA_320x200x16m,
grSVGA_320x240x16m,
grSVGA_320x400x16m,
grSVGA_320x480x16m,
grSVGA_400x300x16m,
grSVGA_512x384x16m,
grSVGA_640x350x16m,
grSVGA_640x400x16m,
grSVGA_640x480x16m,
grSVGA_800x600x16m,
grSVGA_1024x768x16m,
grSVGA_1152x864x16m,
grSVGA_1280x960x16m,
grSVGA_1280x1024x16m,
grSVGA_1600x1200x16m,
 
/* 16 million color, 32 bits per pixel Super VGA video modes */
 
grSVGA_320x200x4G,
grSVGA_320x240x4G,
grSVGA_320x400x4G,
grSVGA_320x480x4G,
grSVGA_400x300x4G,
grSVGA_512x384x4G,
grSVGA_640x350x4G,
grSVGA_640x400x4G,
grSVGA_640x480x4G,
grSVGA_800x600x4G,
grSVGA_1024x768x4G,
grSVGA_1152x864x4G,
grSVGA_1280x960x4G,
grSVGA_1280x1024x4G,
grSVGA_1600x1200x4G,
 
/* Render into Windowing System DC (Windows, OS/2 PM, X11) */
 
grWINDOWED,
 
grMAXMODE, /* Maximum mode number */
} MGL_modeType;
 
/* MGL_result() error codes */
 
typedef enum {
grOK = 0, /* No error */
grNoInit = -1, /* Graphics driver has not been installed */
grNotDetected = -2, /* Graphics hardware was not detected */
grDriverNotFound= -3, /* Graphics driver file not found */
grBadDriver = -4, /* File loaded was not a graphics driver */
grLoadMem = -5, /* Not enough memory to load graphics driver*/
grInvalidMode = -6, /* Invalid graphics mode for selected driver*/
grError = -8, /* General graphics error */
grInvalidName = -9, /* Invalid driver name */
grNoMem = -10, /* Not enough memory to perform operation */
grNoModeSupport = -11, /* Select video mode not supported by hard. */
grInvalidFont = -12, /* Invalid font data */
grBadFontFile = -13, /* File loaded was not a font file */
grFontNotFound = -14, /* Font file was not found */
grOldDriver = -15, /* Driver file is an old version */
grInvalidDevice = -16, /* Invalid device for selected operation */
grInvalidDC = -17, /* Invalid device context */
grInvalidCursor = -18, /* Invalid cursor file */
grCursorNotFound= -19, /* Cursor file was not found */
grInvalidIcon = -20, /* Invalid icon file */
grIconNotFound = -21, /* Icon file was not found */
grInvalidBitmap = -22, /* Invalid bitmap file */
grBitmapNotFound= -23, /* Bitmap file was not found */
grZbufferTooBig = -24, /* Zbuffer allocation is too large */
grNewFontFile = -25, /* Only Windows 2.x font files supported */
grNoDoubleBuff = -26, /* Double buffering is not available */
grNoHardwareBlt = -28, /* No hardware bitBlt for OffscreenDC */
grNoOffscreenMem= -29, /* No available offscreen memory */
grInvalidPF = -30, /* Invalid pixel format for memory DC */
 
grLastError = -31, /* Last error number in list */
} MGL_errorType;
 
#define MGL_CLIPON true
#define MGL_CLIPOFF false
 
/* Color mapped modes */
 
typedef enum {
MGL_CMAP_MODE, /* Normal Color mapped mode */
MGL_DITHER_RGB_MODE, /* 24 bit RGB halftone dithered */
} MGL_colorModes;
 
/* Standard colors - this is the standard set of colors for the IBM PC. The
* default palette will have been programmed to contain these values when a
* graphics modes is started. If the palette has been changed, they will
* not correspond to the actual colors on the screen. Under a Windowing
* manage environment these colors will also not be setup by default.
*/
 
enum MGL_COLORS {
MGL_BLACK, /* dark colors */
MGL_BLUE,
MGL_GREEN,
MGL_CYAN,
MGL_RED,
MGL_MAGENTA,
MGL_BROWN,
MGL_LIGHTGRAY,
MGL_DARKGRAY, /* light colors */
MGL_LIGHTBLUE,
MGL_LIGHTGREEN,
MGL_LIGHTCYAN,
MGL_LIGHTRED,
MGL_LIGHTMAGENTA,
MGL_YELLOW,
MGL_WHITE,
};
 
/* Windows standard color indices for 256 color bitmaps. 8,9,246,247 are
* reserved and you should not count on these colors always being the
* same. For 16 color bitmaps, colors 248-255 map to colors 8-15.
*/
 
enum MGL_WIN_COLORS {
MGL_WIN_BLACK = 0,
MGL_WIN_DARKRED = 1,
MGL_WIN_DARKGREEN = 2,
MGL_WIN_DARKYELLOW = 3,
MGL_WIN_DARKBLUE = 4,
MGL_WIN_DARKMAGENTA = 5,
MGL_WIN_DARKCYAN = 6,
MGL_WIN_LIGHTGRAY = 7,
MGL_WIN_TURQUOISE = 8, /* Reserved; dont count on this */
MGL_WIN_SKYBLUE = 9, /* Reserved; dont count on this */
MGL_WIN_CREAM = 246, /* Reserved; dont count on this */
MGL_WIN_MEDIUMGRAY = 247, /* Reserved; dont count on this */
MGL_WIN_DARKGRAY = 248,
MGL_WIN_LIGHTRED = 249,
MGL_WIN_LIGHTGREEN = 250,
MGL_WIN_LIGHTYELLOW = 251,
MGL_WIN_LIGHTBLUE = 252,
MGL_WIN_LIGHTMAGENTA = 253,
MGL_WIN_LIGHTCYAN = 254,
MGL_WIN_WHITE = 255,
};
 
typedef enum {
MGL_MARKER_SQUARE,
MGL_MARKER_CIRCLE,
MGL_MARKER_X,
} MGL_markerStyleType;
 
typedef enum { /* Write mode operators */
MGL_REPLACE_MODE, /* Replace mode */
MGL_AND_MODE, /* AND mode */
MGL_OR_MODE, /* OR mode */
MGL_XOR_MODE, /* XOR mode */
} MGL_writeModeType;
 
typedef enum {
MGL_BITMAP_SOLID,
MGL_BITMAP_OPAQUE,
MGL_BITMAP_TRANSPARENT,
MGL_PIXMAP,
} MGL_fillStyleType;
 
typedef enum {
MGL_LINE_PENSTYLE, /* Line drawn in current pen style */
MGL_LINE_STIPPLE, /* Line drawn with current stipple */
} MGL_lineStyleType;
 
typedef enum {
MGL_CONVEX_POLYGON, /* Monotone vertical polygon */
MGL_COMPLEX_POLYGON, /* Non-Simple polygons */
MGL_AUTO_POLYGON, /* Auto detect the polygon type */
} MGL_polygonType;
 
/* Text manipulation defines */
 
typedef enum {
MGL_LEFT_TEXT = 0, /* Justify from left */
MGL_TOP_TEXT = 0, /* Justify from top */
MGL_CENTER_TEXT = 1, /* Center the text */
MGL_RIGHT_TEXT = 2, /* Justify from right */
MGL_BOTTOM_TEXT = 2, /* Justify from bottom */
MGL_BASELINE_TEXT = 3, /* Justify from the baseline */
} MGL_textJustType;
 
typedef enum {
MGL_LEFT_DIR = 0, /* Text goes to left */
MGL_UP_DIR = 1, /* Text goes up */
MGL_RIGHT_DIR = 2, /* Text goes right */
MGL_DOWN_DIR = 3, /* Text goes down */
} MGL_textDirType;
 
/* Font types */
 
typedef enum {
MGL_VECTORFONT = 1, /* Vector font */
MGL_FIXEDFONT, /* Fixed width bitmap font */
MGL_PROPFONT, /* Proportional width bitmap font */
} MGL_fontType;
 
/* Palette rotation directions */
 
typedef enum {
MGL_ROTATE_UP, /* Rotate the palette values up */
MGL_ROTATE_DOWN, /* Rotate the palette values down */
} MGL_palRotateType;
 
/* Border drawing routine styles */
 
typedef enum {
MGL_BDR_INSET, /* Interior is inset into screen */
MGL_BDR_OUTSET, /* Interior is outset from screen */
MGL_BDR_OUTLINE, /* Border is 3d outline */
} MGL_bdrStyleType;
 
/* Standard display driver names */
 
#define MGL_VGA4NAME "VGA4.DRV" /* Standard VGA drivers */
#define MGL_VGA8NAME "VGA8.DRV"
#define MGL_VGAXNAME "VGAX.DRV"
 
#define MGL_SVGA4NAME "SVGA4.DRV" /* Generic SuperVGA drivers */
#define MGL_SVGA8NAME "SVGA8.DRV"
#define MGL_SVGA16NAME "SVGA16.DRV"
#define MGL_SVGA24NAME "SVGA24.DRV"
#define MGL_SVGA32NAME "SVGA32.DRV"
 
#define MGL_LINEAR8NAME "LINEAR8.DRV" /* Linear framebuffer drivers */
#define MGL_LINEAR16NAME "LINEAR16.DRV"
#define MGL_LINEAR24NAME "LINEAR24.DRV"
#define MGL_LINEAR32NAME "LINEAR32.DRV"
 
#define MGL_ACCEL8NAME "ACCEL8.DRV" /* VBE/AF Accelerated drivers */
#define MGL_ACCEL16NAME "ACCEL16.DRV"
#define MGL_ACCEL24NAME "ACCEL24.DRV"
#define MGL_ACCEL32NAME "ACCEL32.DRV"
 
#define MGL_DDRAW8NAME "DDRAW8.DRV" /* DirectDraw drivers */
#define MGL_DDRAW16NAME "DDRAW16.DRV"
#define MGL_DDRAW24NAME "DDRAW24.DRV"
#define MGL_DDRAW32NAME "DDRAW32.DRV"
 
/* Standard memory driver names */
 
#define MGL_PACKED1NAME "PACK1.DRV"
#define MGL_PACKED4NAME "PACK4.DRV"
#define MGL_PACKED8NAME "PACK8.DRV"
#define MGL_PACKED16NAME "PACK16.DRV"
#define MGL_PACKED24NAME "PACK24.DRV"
#define MGL_PACKED32NAME "PACK32.DRV"
 
/* Standard bitmap names */
 
#define MGL_EMPTY_FILL _MGL_getEmptyPat()
#define MGL_GRAY_FILL _MGL_getGrayPat()
#define MGL_SOLID_FILL _MGL_getSolidPat()
 
/* Event message masks for keyDown events */
 
#define EVT_ASCIIMASK 0x00FF /* Ascii code of key pressed */
#define EVT_SCANMASK 0xFF00 /* Scan code of key pressed */
#define EVT_COUNTMASK 0x7FFF0000L /* Count for KEYREPEAT's */
 
#define EVT_asciiCode(m) ( (uchar) (m & EVT_ASCIIMASK) )
#define EVT_scanCode(m) ( (uchar) ( (m & EVT_SCANMASK) >> 8 ) )
#define EVT_repeatCount(m) ( (short) ( (m & EVT_COUNTMASK) >> 16 ) )
 
/* Event message masks for mouse events */
 
#define EVT_LEFTBMASK 0x0001 /* Left button is bit 0 */
#define EVT_RIGHTBMASK 0x0004 /* Right button is bit 1 */
#define EVT_BOTHBMASK 0x0005 /* Both left and right together */
#define EVT_ALLBMASK 0x0005 /* All buttons pressed */
 
/* Modifier masks */
 
#define EVT_LEFTBUT 0x0001 /* Set if left button was down */
#define EVT_RIGHTBUT 0x0002 /* Set if right button was down */
#define EVT_RIGHTSHIFT 0x0008 /* Set if right shift down */
#define EVT_LEFTSHIFT 0x0010 /* Set if left shift down */
#define EVT_CTRLSTATE 0x0020 /* Set if ctrl key down */
#define EVT_ALTSTATE 0x0040 /* Set if alt key down */
#define EVT_LEFTCTRL 0x0080 /* Set if left ctrl key down */
#define EVT_LEFTALT 0x0100 /* Set if left alt key down */
#define EVT_SHIFTKEY 0x0018 /* Any shift key */
 
/* Event codes */
 
#define EVT_NULLEVT 0x0000 /* A null event */
#define EVT_KEYDOWN 0x0001 /* Key down event */
#define EVT_KEYREPEAT 0x0002 /* Key repeat event */
#define EVT_KEYUP 0x0004 /* Key up event */
#define EVT_MOUSEDOWN 0x0008 /* Mouse down event */
#define EVT_MOUSEUP 0x0010 /* Mouse up event */
#define EVT_MOUSEMOVE 0x0020 /* Mouse movement event */
#define EVT_TIMERTICK 0x0040 /* Timer tick event */
#define EVT_USEREVT 0x0080 /* First user event */
 
/* Event code masks */
 
#define EVT_KEYEVT (EVT_KEYDOWN | EVT_KEYREPEAT | EVT_KEYUP)
#define EVT_MOUSEEVT (EVT_MOUSEDOWN | EVT_MOUSEUP | EVT_MOUSEMOVE)
#define EVT_MOUSECLICK (EVT_MOUSEDOWN | EVT_MOUSEUP)
#define EVT_EVERYEVT 0xFFFF
 
/* Suspend Application callback type codes. This callback is called
* when the user presses one of the corresponding keys indicating that
* they wish to change the active application. The MGL will catch these
* events and if you have registered a callback, will call the callback to
* save the state of the application so that it can be properly restored
* when the user switches back to your application. The MGL takes care of
* all the details about saving and restoring the state of the hardware,
* and all your application needs to do is save its own state so that you can
* re-draw the application screen upon re-activation.
*
* NOTE: Your application suspend callback may get called twice with the
* MGL_DEACTIVATE flag in order to test whether the switch should
* occur (under both DirectDraw and WinDirect fullscreen modes).
*
* NOTE: When your callback is called with the MGL_DEACTIVATE flag, you
* cannot assume that you have access to the display memory surfaces
* as they may have been lost by the time your callback has been called.
*/
 
#define MGL_DEACTIVATE 0x0001 /* Application losing active focus */
#define MGL_REACTIVATE 0x0002 /* Application regaining active focus */
 
/* Return codes from the suspend application callback. The normal value
* to be returned is MGL_SUSPEND_APP and this will cause the app to be
* suspended while back in GDI mode until the app is re-activated again
* by the user.
*
* MGL_NO_DEACTIVATE signals to WinDirect that the application does not want
* to allow switching to occur, and the switch request will be ignored and
* the app will remain in fullscreen mode.
*
* MGL_NO_SUSPEND_APP can be used to tell WinDirect to switch back to the
* desktop, but not to suspend the application. This must be used with
* care as the suspend application callback is then responsible for setting
* a flag in the application that will stop the application from doing any
* rendering to the framebuffer while the application is in GDI mode. This
* return value is useful for games that need to maintain network
* connectivity while the user has temporarily switched back to GDI mode.
*/
 
#define MGL_NO_DEACTIVATE 0 /* Dont allow app to be deactivated */
#define MGL_SUSPEND_APP 1 /* Suspend application until restored */
#define MGL_NO_SUSPEND_APP 2 /* Dont suspend, but allow switch */
 
/* Here we define the structures used to represent points and rectangles */
 
typedef struct {
m_int x,y;
} point_t;
 
typedef struct {
m_int left;
m_int top;
m_int right;
m_int bottom;
} rect_t;
 
/* All colors are represented as longs by the library. This allows
* code to work correctly with up to 24 bit color device drivers. The
* device drivers themselves expect the color to be a color index if in
* a color mapped mode, or a 15/16/24 bit RGB tuple in a hicolor or truecolor
* mode. You can use the appropriate routines to pack and unpack
* colors into the color_t format.
*/
 
typedef ulong color_t;
 
/* Define the value used to clear the software ZBuffer. The MGL always uses
* a > operator for the z compare, and the smallest value is 0.
*/
 
#define MGL_ZCLEARVAL 0
 
/* Structures for passing vertex information to polygon rendering routines.
* All fixed point coordinates are passed in 16.16 signed fixed point
* format, while zbuffer coordinates are passed in 4.28 signed fixed point
* format. The sign bit is used purely for overflow and arithmetic
* internally, and all user passed zbuffer values should be greater than
* 0. All shaded rendering routines either take a color index in 8.16 fixed
* point format (range 0-255.9) or separate RGB components in 8.16 fixed
* point format (range 0-255.9).
*/
 
#ifdef __FX_FIXED_H
#define fix32_t FXFixed
#else
typedef long fix32_t;
#endif
typedef fix32_t fxcolor_t;
typedef long zfix32_t;
 
typedef struct {
fix32_t x,y;
} fxpoint_t;
 
typedef struct {
fxcolor_t r,g,b;
} fxrgb_t;
 
typedef struct {
fix32_t w,s,t;
} fxtex_t;
 
typedef struct {
fxcolor_t c;
fxpoint_t p;
} fxpointc_t;
 
typedef struct {
fxrgb_t c;
fxpoint_t p;
} fxpointrgb_t;
 
typedef struct {
fxpoint_t p;
zfix32_t z;
} fxpointz_t;
 
typedef struct {
fxcolor_t c;
fxpoint_t p;
zfix32_t z;
} fxpointcz_t;
 
typedef struct {
fxrgb_t c;
fxpoint_t p;
zfix32_t z;
} fxpointrgbz_t;
 
/* Macros to convert between integer and 32 bit fixed point format */
 
#define MGL_FIX_1 0x10000L
#define MGL_FIX_2 0x20000L
#define MGL_FIX_HALF 0x08000L
#define MGL_TOFIX(i) ((long)(i) << 16)
#define MGL_FIXTOINT(f) ((m_int)((f) >> 16))
#define MGL_FIXROUND(f) ((m_int)(((f) + MGL_FIX_HALF) >> 16))
 
#define MGL_ZFIX_1 0x10000000L
#define MGL_ZFIX_HALF 0x08000000L
#define MGL_FIXTOZ(i) ((i) << 12)
#define MGL_ZTOFIX(i) ((i) >> 12)
#define MGL_TOZFIX(i) ((long)(i) << 28)
#define MGL_ZFIXTOINT(f) ((m_int)((f) >> 28))
#define MGL_ZFIXROUND(f) ((m_int)(((f) + MGL_ZFIX_HALF) >> 28))
 
/* Region structure */
 
#ifdef BUILD_MGL
struct _span_t;
typedef struct _span_t span_t;
#else
typedef void span_t;
#endif
 
typedef struct {
rect_t rect; /* Bounding rectangle for region */
span_t *spans; /* Start of span list for region */
} region_t;
 
/* Palette entry structure */
 
typedef struct {
uchar blue; /* Blue component of color */
uchar green; /* Green component of color */
uchar red; /* Blue component of color */
uchar alpha; /* Alpha or alignment byte */
} palette_t;
 
/* Maximum value for each palette entry component */
 
#define PALMAX 255 /* Max value for palette components */
 
/* Pixel format structure */
 
typedef struct {
uchar redMask,greenMask; /* Mask values for pixels */
uchar blueMask,rsvdMask;
m_int redPos,redAdjust; /* Red position and adjustment */
m_int greenPos,greenAdjust; /* Green position and adjustment */
m_int bluePos,blueAdjust; /* Blue position and adjustment */
m_int rsvdPos,rsvdAdjust; /* Reserved position and adjustment */
} pixel_format_t;
 
/* Structure to hold arc coordinate information */
 
typedef struct {
m_int x,y; /* Centre point of the arc */
m_int startX,startY; /* Starting point on arc */
m_int endX,endY; /* Ending point on arc */
} arc_coords_t;
 
/* Mouse cursor structure */
 
typedef struct {
ulong xorMask[32];
ulong andMask[32];
m_int xHotSpot;
m_int yHotSpot;
} cursor_t;
 
/* Bitmap structure - always packed pixel DIB format */
 
typedef struct {
m_int width; /* Width of bitmap in pixels */
m_int height; /* Height of bitmap in pixels */
m_int bitsPerPixel; /* Pixel width */
m_int bytesPerLine; /* Bytes per line value for surface */
uchar *surface; /* Pointer to bitmap surface */
palette_t *pal; /* Palette (NULL if not loaded) */
pixel_format_t *pf; /* Pixel format (NULL if none) */
 
/* ... palette, pixel format and bitmap data are store contiguously */
} bitmap_t;
 
/* Icon structure - can be 32x23, 64x64 or in fact any size */
 
typedef struct {
m_int byteWidth; /* Byte with for AND mask */
uchar *andMask; /* Hold punch mask for icon */
bitmap_t xorMask; /* XOR mask for the icon */
 
/* ... AND mask and bitmap structure are stored contiguously */
} icon_t;
 
/* Default cursor name */
 
#define MGL_DEF_CURSOR _MGL_getDefCursor()
 
/* Generic Font structure */
 
#define _MGL_FNAMESIZE 58
 
typedef struct {
char name[_MGL_FNAMESIZE];/* Name of the font */
short fontType; /* Type of font */
short maxWidth; /* Maximum character width */
short maxKern; /* Maximum character kern */
short fontWidth; /* Font width */
short fontHeight; /* Font height */
short ascent; /* Font ascent value */
short descent; /* Font descent value */
short leading; /* Font leading value */
} font_t;
 
/* Character and font metrics structure */
 
typedef struct {
m_int width; /* Width of character or font */
m_int fontWidth; /* Character width (tightest fit) */
m_int fontHeight; /* Height of the font */
m_int ascent; /* Ascent value */
m_int descent; /* Descent value */
m_int leading; /* Leading value */
m_int kern; /* Kern value */
} metrics_t;
 
/* Text settings structure */
 
typedef struct {
m_int horizJust; /* Horizontal justfication */
m_int vertJust; /* Vertical justification */
m_int dir; /* Text drawing direction */
m_int szNumerx; /* Text x size numerator */
m_int szNumery; /* Text y size numerator */
m_int szDenomx; /* Text x size denominator */
m_int szDenomy; /* Text y size denominator */
m_int spaceExtra; /* Space extra term */
font_t *font; /* Currently selected font */
} text_settings_t;
 
/* Macros to access the (left,top) and (right,bottom) points of a
* rectangle.
*/
 
#define MGL_leftTop(r) (((point_t *) &(r))[0])
#define MGL_rightBottom(r) (((point_t *) &(r))[1])
 
typedef uchar pattern_t[8];
typedef color_t pixpattern_t[8][8];
 
/* Attributes structure */
 
typedef struct {
color_t color; /* Foreground color */
color_t backColor; /* Background color */
m_int colorMode; /* Current color mode */
m_int markerSize; /* Size of markers in pixels */
m_int markerStyle; /* Style of markers */
color_t markerColor; /* Color to draw markers in */
color_t bdrBright; /* Border bright color */
color_t bdrDark; /* Border dark color */
point_t CP; /* Graphics pen position */
m_int writeMode; /* Scan conversion write mode op. */
m_int penStyle; /* Pen style */
m_int penHeight; /* Height of pen */
m_int penWidth; /* Width of pen */
pattern_t penPat; /* Pattern for pen */
pixpattern_t penPixPat; /* Pixmap pattern for pen */
m_int lineStyle; /* Line style */
ushort lineStipple; /* Line stipple */
m_uint stippleCount; /* Current line stipple count */
rect_t viewPort; /* Viewport dimensions */
point_t viewPortOrg; /* Logical viewport origin */
rect_t clipRect; /* Clipping rectangle dimensions */
m_int clip; /* Is clipping on? */
m_int polyType; /* Polygon drawing type */
text_settings_t ts; /* Text drawing attributes */
} attributes_t;
 
/* Mode specific format information. This structrure can be used by
* the device driver to build tables of values for all supported modes
*/
 
typedef struct {
m_int xRes; /* Device x resolution - 1 */
m_int yRes; /* Device y resolution - 1 */
m_int bitsPerPixel; /* Number of bits per pixel */
m_int numberOfPlanes; /* Number of planes in image */
color_t maxColor; /* Maximum number of colors - 1 */
m_int maxPage; /* Maximum number of video pages - 1 */
m_int bytesPerLine; /* Number of bytes in a line */
m_int aspectRatio; /* Mode aspect ratio (horiz/vert * 1000) */
long pageSize; /* Number of bytes in a page */
m_int scratch1; /* Scratch pad value 1 */
m_int scratch2; /* Scratch pad value 2 */
char redMaskSize; /* Size of direct color red mask */
char redFieldPosition; /* Bit posn of lsb of red mask */
char greenMaskSize; /* Size of direct color green mask */
char greenFieldPosition; /* Bit posn of lsb of green mask */
char blueMaskSize; /* Size of direct color blue mask */
char blueFieldPosition; /* Bit posn of lsb of blue mask */
char rsvdMaskSize; /* Size of reserved mask */
char rsvdFieldPosition; /* Bit posn of reserved mask */
} gmode_t;
 
/* Public Device Context Structure. The 'surface' member along with the
* gmode_t information block, provides direct access to the active
* display surface for user applications. The MGL virtualises the surface
* in SuperVGA modes that dont have a real linear framebuffer.
*/
 
typedef struct {
attributes_t a; /* Active device attributes */
void *surface; /* Pointer to active device surface */
void *zbuffer; /* Pointer to Z-buffer if allocated */
m_int zbits; /* Bits per zbuffer element */
m_int zwidth; /* Width of the zbuffer in pixels */
gmode_t mi; /* Mode specific information block */
pixel_format_t pf; /* Current pixel format for device context */
color_t *colorTab; /* Color lookup table cache */
color_t *shadeTab; /* Currently active shade table */
m_int bankOffset; /* Offset of starting bank number */
 
/* Remainder of Device Context structure is private and internal */
} publicDevCtx_t;
 
#ifndef BUILD_MGL
typedef publicDevCtx_t MGLDC;
#else
struct internalDevCtx_t;
typedef struct internalDevCtx_t MGLDC;
#endif
 
typedef struct {
ulong which; /* Which window for window manager code */
m_uint what; /* Event code */
ulong when; /* Clock ticks since midnight */
m_int where_x; /* Mouse location */
m_int where_y;
ulong message; /* Event specific message */
ulong modifiers; /* Modifier flags */
m_int next; /* Next event in queue */
m_int prev; /* Previous event in queue */
} event_t;
 
/* Structure containing file I/O functions allowing the user application to
* completely replace the MGL's file I/O functions with their own. This
* allows the app to store all MGL related files in a single large file,
* with encryption or compression is desired. By default normal file I/O
* functions will be used.
*/
 
typedef struct {
FILE * (*fopen)(const char *filename,const char *mode);
int (*fclose)(FILE *f);
int (*fseek)(FILE *f,long offset,int whence);
long (*ftell)(FILE *f);
size_t (*fread)(void *ptr,size_t size,size_t n,FILE *f);
size_t (*fwrite)(const void *ptr,size_t size,size_t n,FILE *f);
} fileio_t;
 
/* Define the flags for the types of direct surface access provided */
 
#define MGL_NO_ACCESS 0x0 /* Surface cannot be accessed */
#define MGL_VIRTUAL_ACCESS 0x1 /* Surface is virtualised */
#define MGL_LINEAR_ACCESS 0x2 /* Surface can be linearly accessed */
#define MGL_SURFACE_FLAGS 0x3
 
/* Define the flags for the types of direct zbuffer access provided */
 
#define MGL_NO_ZACCESS 0x0 /* Zbuffer cannot be accessed */
#define MGL_VIRTUAL_ZACCESS 0x4 /* Zbuffer is virtualised in */
#define MGL_LINEAR_ZACCESS 0x8 /* Zbuffer can be linearly accessed */
#define MGL_ZBUFFER_FLAGS 0xC
 
/* Define the flags for the types of hardware acceleration supported by
* the device context. This will allow the application to tailor the use of
* MGL functions depending upon whether specific hardware support is
* available. Hence applications can use specialised software rendering
* support if the desired hardware support is not available.
*
* NOTE: If the hardware flags are not MGL_HW_NONE, you *must* call
* the MGL_beginDirectAccess() and MGL_endDirectAccess() functions
* before and after any custom code that does direct framebuffer
* rendering!!
*
* This is not necessary for non-accelerated device context, so you
* might want to optimise these calls out if there is no hardware
* acceleration support.
*/
 
#define MGL_HW_NONE 0x0000 /* No hardware acceleration */
#define MGL_HW_LINE 0x0010 /* Hardware line drawing */
#define MGL_HW_STIPPLE_LINE 0x0020 /* Hardware stippled line drawing */
#define MGL_HW_POLY 0x0040 /* Hardware polygon filling */
#define MGL_HW_RECT 0x0080 /* Hardware rectangle fill */
#define MGL_HW_PATT_RECT 0x0100 /* Hardware pattern rectangle fill */
#define MGL_HW_CLRPATT_RECT 0x0200 /* Hardware color pattern fill */
#define MGL_HW_SCR_BLT 0x0400 /* Hardware screen/screen bitBlt */
#define MGL_HW_SRCTRANS_BLT 0x0800 /* Hardware source transparent blt */
#define MGL_HW_DSTTRANS_BLT 0x1000 /* Hardware dest. transparent blt */
#define MGL_HW_MONO_BLT 0x2000 /* Hardware monochrome blt */
#define MGL_HW_CLIP 0x4000 /* Hardware clipping */
#define MGL_HW_FLAGS 0xFFF0
 
#ifdef __cplusplus
extern "C" { /* Use "C" linkage when in C++ mode */
#endif
 
/*------------------------- Function Prototypes ---------------------------*/
 
/*---------------------------------------------------------------------------
* Routines bound to a specific device context. These routines all take
* an MGLDC as a parmeter for the context to work with and hence dont work
* with the current context. If however the context passed is the currently
* active context, all changes to that context are reflected in the
* currently active context as well.
*-------------------------------------------------------------------------*/
 
/* Environment detection and initialisation */
 
m_int MGLAPI MGL_registerDriver(const char *name,void *driver);
void MGLAPI MGL_unregisterAllDrivers(void);
void MGLAPI MGL_registerAllDispDrivers(bool useLinear,bool useDirectDraw,bool useWinDirect);
void MGLAPI MGL_registerAllMemDrivers(void);
void MGLAPI MGL_detectGraph(m_int *driver,m_int *mode);
uchar * MGLAPI MGL_availableModes(void);
m_int MGLAPI MGL_availablePages(m_int mode);
m_int MGLAPI MGL_modeResolution(m_int mode,m_int *xRes,m_int *yRes,m_int *bitsPerPixel);
bool MGLAPI MGL_isDisplayDC(MGLDC *dc);
bool MGLAPI MGL_isWindowedDC(MGLDC *dc);
bool MGLAPI MGL_isMemoryDC(MGLDC *dc);
void MGLAPI MGL_exit(void);
void MGLAPI MGL_setBufSize(unsigned size);
void MGLAPI MGL_fatalError(const char *msg);
m_int MGLAPI MGL_result(void);
void MGLAPI MGL_setResult(m_int result);
const char * MGLAPI MGL_errorMsg(m_int err);
const char * MGLAPI MGL_modeName(m_int mode);
const char * MGLAPI MGL_modeDriverName(m_int mode);
const char * MGLAPI MGL_driverName(m_int driver);
m_int MGLAPI MGL_getDriver(MGLDC *dc);
m_int MGLAPI MGL_getMode(MGLDC *dc);
m_int MGLAPI MGL_surfaceAccessType(MGLDC *dc);
m_int MGLAPI MGL_zbufferAccessType(MGLDC *dc);
long MGLAPI MGL_getHardwareFlags(MGLDC *dc);
void MGLAPI MGL_defaultAttributes(MGLDC *dc);
void MGLAPI MGL_makeSubDC(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom);
 
/* Viewport and clip rectangle manipulation bound to a specific DC */
 
void MGLAPI MGL_setViewportDC(MGLDC *dc,rect_t view);
void MGLAPI MGL_setRelViewportDC(MGLDC *dc,rect_t view);
void MGLAPI MGL_getViewportDC(MGLDC *dc,rect_t *view);
void MGLAPI MGL_setViewportOrgDC(MGLDC *dc,point_t org);
void MGLAPI MGL_getViewportOrgDC(MGLDC *dc,point_t *org);
void MGLAPI MGL_globalToLocalDC(MGLDC *dc,point_t *p);
void MGLAPI MGL_localToGlobalDC(MGLDC *dc,point_t *p);
m_int MGLAPI MGL_maxxDC(MGLDC *dc);
m_int MGLAPI MGL_maxyDC(MGLDC *dc);
void MGLAPI MGL_setClipRectDC(MGLDC *dc,rect_t clip);
void MGLAPI MGL_getClipRectDC(MGLDC *dc,rect_t *clip);
void MGLAPI MGL_setClipModeDC(MGLDC *dc,bool mode);
bool MGLAPI MGL_getClipModeDC(MGLDC *dc);
 
/* Color and palette manipulation */
 
color_t MGLAPI MGL_realColor(MGLDC *dc,m_int color);
color_t MGLAPI MGL_rgbColor(MGLDC *dc,uchar R,uchar G,uchar B);
void MGLAPI MGL_setPaletteEntry(MGLDC *dc,m_int entry,uchar red,uchar green,uchar blue);
void MGLAPI MGL_getPaletteEntry(MGLDC *dc,m_int entry,uchar *red,uchar *green,uchar *blue);
void MGLAPI MGL_setPalette(MGLDC *dc,palette_t *pal,m_int numColors,m_int startIndex);
void MGLAPI MGL_getPalette(MGLDC *dc,palette_t *pal,m_int numColors,m_int startIndex);
void ASMAPI MGL_rotatePalette(MGLDC *dc,m_int numColors,m_int startIndex,m_int direction);
bool ASMAPI MGL_fadePalette(MGLDC *dc,palette_t *fullIntensity,m_int numColors,m_int startIndex,uchar intensity);
void MGLAPI MGL_realizePalette(MGLDC *dc,m_int numColors,m_int startIndex,m_int waitVRT);
m_int MGLAPI MGL_getPaletteSize(MGLDC *dc);
void MGLAPI MGL_getDefaultPalette(MGLDC *dc,palette_t *pal);
void MGLAPI MGL_setDefaultPalette(MGLDC *dc);
#ifndef MGL_LITE
bool MGLAPI MGL_checkIdentityPalette(bool enable);
void MGLAPI MGL_mapToPalette(MGLDC *dc,palette_t *pal);
#endif
 
/* Generic device context information and manipulation */
 
bool MGLAPI MGL_haveWidePalette(MGLDC *dc);
m_int MGLAPI MGL_getBitsPerPixel(MGLDC *dc);
color_t MGLAPI MGL_maxColor(MGLDC *dc);
m_int MGLAPI MGL_maxPage(MGLDC *dc);
m_int MGLAPI MGL_sizex(MGLDC *dc);
m_int MGLAPI MGL_sizey(MGLDC *dc);
void MGLAPI MGL_getPixelFormat(MGLDC *dc,pixel_format_t *pf);
void * MGLAPI MGL_computePixelAddr(MGLDC *dc,int x,int y);
 
/* Double buffering support */
 
void MGLAPI MGL_setActivePage(MGLDC *dc,m_int page);
m_int MGLAPI MGL_getActivePage(MGLDC *dc);
void MGLAPI MGL_setVisualPage(MGLDC *dc,m_int page,m_int waitVRT);
m_int MGLAPI MGL_getVisualPage(MGLDC *dc);
void MGLAPI MGL_setDisplayStart(MGLDC *dc,m_int x,m_int y,m_int waitFlag);
void MGLAPI MGL_getDisplayStart(MGLDC *dc,m_int *x,m_int *y);
void MGLAPI MGL_vSync(MGLDC *dc);
bool MGLAPI MGL_doubleBuffer(MGLDC *dc);
void MGLAPI MGL_singleBuffer(MGLDC *dc);
void MGLAPI MGL_swapBuffers(MGLDC *dc,m_int waitVRT);
 
/* Zbuffering support */
 
#ifdef MGL_3D
m_int MGLAPI MGL_getHardwareZBufferDepth(MGLDC *dc);
bool ASMAPI MGL_zBegin(MGLDC *dc,m_int zbits);
bool MGLAPI MGL_zShareZBuffer(MGLDC *dc,MGLDC *dcShared,m_int zbits);
#endif
 
/* Event handling support */
 
bool MGLAPI EVT_getNext(event_t *evt,m_uint mask);
bool MGLAPI EVT_peekNext(event_t *evt,m_uint mask);
bool MGLAPI EVT_post(ulong which,m_uint what,ulong message,ulong modifiers);
void MGLAPI EVT_flush(m_uint mask);
void MGLAPI EVT_halt(event_t *evt,m_uint mask);
m_int MGLAPI EVT_setTimerTick(m_int ticks);
 
/*---------------------------------------------------------------------------
* Routines bound to the currently active context. All these routines work
* with the currently active context and do not reflect any changes made
* to the global context to the original user supplied context (because it
* may be cached). The cached DC is automatically flushed back to the
* original DC when a new context is enabled with MGL_makeCurrentDC().
*
* Before destroying a DC that is current, make sure you call
* MGL_makeCurrentDC(NULL) first!
*-------------------------------------------------------------------------*/
 
/* Routines to change the active global device context */
 
MGLDC * MGLAPI MGL_makeCurrentDC(MGLDC *dc);
bool MGLAPI MGL_isCurrentDC(MGLDC *dc);
 
/* Current device context information and manipulation */
 
m_int MGLAPI MGL_getAspectRatio(void);
void MGLAPI MGL_setAspectRatio(m_int aspectRatio);
void ASMAPI MGL_setColor(color_t color);
void MGLAPI MGL_setColorRGB(uchar R,uchar G,uchar B);
void MGLAPI MGL_setColorCI(m_int index);
color_t MGLAPI MGL_getColor(void);
void ASMAPI MGL_setBackColor(color_t color);
color_t MGLAPI MGL_getBackColor(void);
color_t ASMAPI MGL_packColor(pixel_format_t *pf,uchar R,uchar G,uchar B);
void MGLAPI MGL_unpackColor(pixel_format_t *pf,color_t color,uchar *R,uchar *G,uchar *B);
color_t ASMAPI MGL_packColorRGB(uchar R,uchar G,uchar B);
void MGLAPI MGL_unpackColorRGB(color_t color,uchar *R,uchar *G,uchar *B);
color_t MGLAPI MGL_defaultColor(void);
#ifndef MGL_LITE
void MGLAPI MGL_setMarkerSize(m_int size);
m_int MGLAPI MGL_getMarkerSize(void);
void MGLAPI MGL_setMarkerStyle(m_int style);
m_int MGLAPI MGL_getMarkerStyle(void);
void MGLAPI MGL_setMarkerColor(color_t color);
color_t MGLAPI MGL_getMarkerColor(void);
void MGLAPI MGL_setBorderColors(color_t bright,color_t dark);
void MGLAPI MGL_getBorderColors(color_t *bright,color_t *dark);
void ASMAPI MGL_setWriteMode(m_int mode);
m_int MGLAPI MGL_getWriteMode(void);
void ASMAPI MGL_setPenStyle(m_int style);
m_int MGLAPI MGL_getPenStyle(void);
void MGLAPI MGL_setLineStyle(m_int style);
m_int MGLAPI MGL_getLineStyle(void);
void ASMAPI MGL_setLineStipple(ushort stipple);
ushort MGLAPI MGL_getLineStipple(void);
void ASMAPI MGL_setLineStippleCount(m_uint stippleCount);
m_uint MGLAPI MGL_getLineStippleCount(void);
void ASMAPI MGL_setPenBitmapPattern(const pattern_t *pat);
void MGLAPI MGL_getPenBitmapPattern(pattern_t *pat);
void ASMAPI MGL_setPenPixmapPattern(const pixpattern_t *pat);
void MGLAPI MGL_getPenPixmapPattern(pixpattern_t *pat);
void MGLAPI MGL_setPenSize(m_int height,m_int width);
void MGLAPI MGL_getPenSize(m_int *height,m_int *width);
#ifndef MGL_LITE
void MGLAPI MGL_setColorMapMode(m_int mode);
m_int MGLAPI MGL_getColorMapMode(void);
#endif
void MGLAPI MGL_setPolygonType(m_int type);
m_int MGLAPI MGL_getPolygonType(void);
#endif
void MGLAPI MGL_getAttributes(attributes_t *attr);
void MGLAPI MGL_restoreAttributes(attributes_t *attr);
 
/* Device clearing */
 
void ASMAPI MGL_clearDevice(void);
void MGLAPI MGL_clearViewport(void);
 
/* Viewport and clip rectangle manipulation */
 
void MGLAPI MGL_setViewport(rect_t view);
void MGLAPI MGL_setRelViewport(rect_t view);
void MGLAPI MGL_getViewport(rect_t *view);
void MGLAPI MGL_setViewportOrg(point_t org);
void MGLAPI MGL_getViewportOrg(point_t *org);
void MGLAPI MGL_globalToLocal(point_t *p);
void MGLAPI MGL_localToGlobal(point_t *p);
m_int MGLAPI MGL_maxx(void);
m_int MGLAPI MGL_maxy(void);
void MGLAPI MGL_setClipRect(rect_t clip);
void MGLAPI MGL_getClipRect(rect_t *clip);
void MGLAPI MGL_setClipMode(bool mode);
bool MGLAPI MGL_getClipMode(void);
 
/* Pixel plotting */
 
void MGLAPI MGL_pixelCoord(m_int x,m_int y);
color_t MGLAPI MGL_getPixelCoord(m_int x,m_int y);
void ASMAPI MGL_beginPixel(void);
void MGLAPI MGL_pixelCoordFast(m_int x,m_int y);
color_t MGLAPI MGL_getPixelCoordFast(m_int x,m_int y);
void ASMAPI MGL_endPixel(void);
 
/* Line drawing and clipping */
 
void MGLAPI MGL_moveToCoord(m_int x,m_int y);
void MGLAPI MGL_moveRelCoord(m_int dx,m_int dy);
void MGLAPI MGL_lineToCoord(m_int x,m_int y);
void MGLAPI MGL_lineRelCoord(m_int dx,m_int dy);
m_int MGLAPI MGL_getX(void);
m_int MGLAPI MGL_getY(void);
void MGLAPI MGL_getCP(point_t* CP);
void MGLAPI MGL_lineCoord(m_int x1,m_int y1,m_int x2,m_int y2);
void MGLAPI MGL_lineCoordFX(fix32_t x1,fix32_t y1,fix32_t x2,fix32_t y2);
void MGLAPI MGL_lineCoordFast(m_int x1,m_int y1,m_int x2,m_int y2);
void MGLAPI MGL_lineCoordFastFX(fix32_t x1,fix32_t y1,fix32_t x2,fix32_t y2);
void MGLAPI MGL_lineEngine(fix32_t x1,fix32_t y1,fix32_t x2,fix32_t y2,void (ASMAPI *plotPoint)(m_int x,m_int y));
bool MGLAPI MGL_clipLineFX(fix32_t *x1,fix32_t *y1,fix32_t *x2,fix32_t *y2,fix32_t left,fix32_t top,fix32_t right,fix32_t bottom);
#ifndef MGL_LITE
void ASMAPI MGL_scanLine(m_int y,m_int x1,m_int x2);
#endif
 
/* Routines to perform bank switching for banked framebuffers for custom
* rendering code. The first version is callable only from assembler and
* requires the new bank value to be passed in the DL register. The second
* version is callable directly from C. DO NOT CALL THESE FUNCTIONS WHEN
* RUNNING WITH A LINEAR FRAMEBUFFER!!!
*/
 
void _ASMAPI SVGA_setBank(void);
void _ASMAPI SVGA_setBankC(int bank);
 
/* Routines to begin/end direct framebuffer access. You must call these
* functions is you wish to render directly to a hardware accelerated
* device surface.
*/
 
void ASMAPI MGL_beginDirectAccess(void);
void ASMAPI MGL_endDirectAccess(void);
 
/* Routines to begin/end fast rendering of flat shaded lines, scanlines
* and polygons.
*/
 
void ASMAPI MGL_beginDrawing(void);
void ASMAPI MGL_endDrawing(void);
 
/* Routines to begin/end fast rendering of smooth shaded lines, scanlines
* and polygons.
*/
 
#ifdef MGL_3D
void ASMAPI MGL_beginShadedDrawing(void);
void ASMAPI MGL_endShadedDrawing(void);
#endif
 
/* Routines to begin/end fast rendering of flat shaded, zbuffered lines and
* polygons.
*/
 
#ifdef MGL_3D
void ASMAPI MGL_beginZDrawing(void);
void ASMAPI MGL_endZDrawing(void);
#endif
 
/* Routines to begin/end fast rendering of smooth shaded, zbuffered lines and
* polygons.
*/
 
#ifdef MGL_3D
void ASMAPI MGL_beginZShadedDrawing(void);
void ASMAPI MGL_endZShadedDrawing(void);
#endif
 
/* Polygon drawing: Note that the following fast polygon routines
* only work with convex polygons. The integer coordinate versions are
* provided for compatibility only, and convert the coordinates to fixed
* point and call the appropriate fixed point routines below.
*/
 
#ifndef MGL_LITE
void MGLAPI MGL_fillPolygon(m_int count,point_t *vArray,m_int xOffset,m_int yOffset);
void MGLAPI MGL_fillPolygonFast(m_int count,point_t *vArray,m_int xOffset,m_int yOffset);
void ASMAPI MGL_fillPolygonFX(m_int count,fxpoint_t *vArray,m_int vinc,fix32_t xOffset,fix32_t yOffset);
void ASMAPI MGL_fillPolygonFastFX(m_int count,fxpoint_t *vArray,m_int vinc,fix32_t xOffset,fix32_t yOffset);
#endif
 
/* 3D rasterization routines */
 
#ifdef MGL_3D
void MGLAPI MGL_zClearCoord(m_int left,m_int top,m_int right,m_int bottom,zfix32_t clearVal);
#endif
 
#ifdef MGL_FIX3D
void ASMAPI MGL_cLineCoordFast(fix32_t x1,fix32_t y1,fix32_t c1,fix32_t x2,fix32_t y2,fix32_t c2);
void ASMAPI MGL_rgbLineCoordFast(fix32_t x1,fix32_t y1,fix32_t r1,fix32_t g1,fix32_t b1,fix32_t x2,fix32_t y2,fix32_t r2,fix32_t g2,fix32_t b2);
void ASMAPI MGL_zLineCoordFast(fix32_t x1,fix32_t y1,zfix32_t z1,fix32_t x2,fix32_t y2,zfix32_t z2);
void ASMAPI MGL_czLineCoordFast(fix32_t x1,fix32_t y1,zfix32_t z1,fix32_t c1,fix32_t x2,fix32_t y2,zfix32_t z2,fix32_t c2);
void ASMAPI MGL_rgbzLineCoordFast(fix32_t x1,fix32_t y1,zfix32_t z1,fix32_t r1,fix32_t g1,fix32_t b1,fix32_t x2,fix32_t y2,zfix32_t z2,fix32_t r2,fix32_t g2,fix32_t b2);
 
void ASMAPI MGL_triFast(fxpoint_t *v1,fxpoint_t *v2,fxpoint_t *v3,fix32_t xOffset,fix32_t yOffset);
void ASMAPI MGL_cTriFast(fxpointc_t *v1,fxpointc_t *v2,fxpointc_t *v3,fix32_t xOffset,fix32_t yOffset);
void ASMAPI MGL_rgbTriFast(fxpointrgb_t *v1,fxpointrgb_t *v2,fxpointrgb_t *v3,fix32_t xOffset,fix32_t yOffset);
void ASMAPI MGL_zTriFast(fxpointz_t *v1,fxpointz_t *v2,fxpointz_t *v3,fix32_t xOffset,fix32_t yOffset,zfix32_t zOffset);
void ASMAPI MGL_czTriFast(fxpointcz_t *v1,fxpointcz_t *v2,fxpointcz_t *v3,fix32_t xOffset,fix32_t yOffset,zfix32_t zOffset);
void ASMAPI MGL_rgbzTriFast(fxpointrgbz_t *v1,fxpointrgbz_t *v2,fxpointrgbz_t *v3,fix32_t xOffset,fix32_t yOffset,zfix32_t zOffset);
 
void ASMAPI MGL_quadFast(fxpoint_t *v1,fxpoint_t *v2,fxpoint_t *v3,fxpoint_t *v4,fix32_t xOffset,fix32_t yOffset);
void ASMAPI MGL_cQuadFast(fxpointc_t *v1,fxpointc_t *v2,fxpointc_t *v3,fxpointc_t *v4,fix32_t xOffset,fix32_t yOffset);
void ASMAPI MGL_rgbQuadFast(fxpointrgb_t *v1,fxpointrgb_t *v2,fxpointrgb_t *v3,fxpointrgb_t *v4,fix32_t xOffset,fix32_t yOffset);
void ASMAPI MGL_zQuadFast(fxpointz_t *v1,fxpointz_t *v2,fxpointz_t *v3,fxpointz_t *v4,fix32_t xOffset,fix32_t yOffset,zfix32_t zOffset);
void ASMAPI MGL_czQuadFast(fxpointcz_t *v1,fxpointcz_t *v2,fxpointcz_t *v3,fxpointcz_t *v4,fix32_t xOffset,fix32_t yOffset,zfix32_t zOffset);
void ASMAPI MGL_rgbzQuadFast(fxpointrgbz_t *v1,fxpointrgbz_t *v2,fxpointrgbz_t *v3,fxpointrgbz_t *v4,fix32_t xOffset,fix32_t yOffset,zfix32_t zOffset);
#endif
 
/* Routine to set the currently active shade table. In HiColor and TrueColor
* video modes, you must set a valid shadeTable before you call any of the
* color index shaded rendering routines (MGL_cTri() etc). These routines
* will interpolate an index into the current shade table rather than
* each of the RGB color channels, and the appropriate full RGB color is
* extracted directly from the shade table. The shade table can be any size,
* but the application must ensure that the indices passed in are within
* the range of the current shade table.
*/
 
#ifdef MGL_3D
void MGLAPI MGL_setShadeTable(color_t *shadeTab);
#endif
 
/* Polyline drawing */
 
#ifndef MGL_LITE
void MGLAPI MGL_marker(point_t p);
void MGLAPI MGL_polyPoint(m_int count,point_t *vArray);
void MGLAPI MGL_polyMarker(m_int count,point_t *vArray);
void MGLAPI MGL_polyLine(m_int count,point_t *vArray);
#endif
 
/* Rectangle drawing */
 
#ifndef MGL_LITE
void MGLAPI MGL_rectCoord(m_int left,m_int top,m_int right,m_int bottom);
void MGLAPI MGL_fillRectCoord(m_int left,m_int top,m_int right,m_int bottom);
#endif
 
/* Scanline color scanning. Thee routines are primitive, and do not perform
* any clipping or viewport mapping, so can be used to build you own
* high performance floodfilling routines (see the example file ffill.c
* for pre-built high speed floodfill routines).
*/
 
#ifndef MGL_LITE
m_int ASMAPI MGL_scanRightForColor(m_int x,m_int y,color_t color);
m_int ASMAPI MGL_scanLeftForColor(m_int x,m_int y,color_t color);
m_int ASMAPI MGL_scanRightWhileColor(m_int x,m_int y,color_t color);
m_int ASMAPI MGL_scanLeftWhileColor(m_int x,m_int y,color_t color);
#endif
 
/* Psuedo 3D border drawing */
 
#ifndef MGL_LITE
void MGLAPI MGL_drawBorderCoord(m_int left,m_int top,m_int right,m_int bottom,m_int style,m_int thickness);
void MGLAPI MGL_drawHDivider(m_int y,m_int x1,m_int x2);
void MGLAPI MGL_drawVDivider(m_int x,m_int y1,m_int y2);
#endif
 
/* Ellipse drawing */
 
#ifndef MGL_LITE
void MGLAPI MGL_ellipseArc(rect_t extentRect,m_int startAngle,m_int endAngle);
void MGLAPI MGL_ellipseArcCoord(m_int x,m_int y,m_int xradius,m_int yradius,m_int startAngle,m_int endAngle);
void ASMAPI MGL_getArcCoords(arc_coords_t *coords);
void MGLAPI MGL_ellipse(rect_t extentRect);
void MGLAPI MGL_ellipseCoord(m_int x,m_int y,m_int xradius,m_int yradius);
void MGLAPI MGL_fillEllipseArc(rect_t extentRect,m_int startAngle,m_int endAngle);
void MGLAPI MGL_fillEllipseArcCoord(m_int x,m_int y,m_int xradius,m_int yradius,m_int startAngle,m_int endAngle);
void MGLAPI MGL_fillEllipse(rect_t extentRect);
void MGLAPI MGL_fillEllipseCoord(m_int x,m_int y,m_int xradius,m_int yradius);
void MGLAPI MGL_ellipseEngine(rect_t extentRect,void (ASMAPI *setup)(m_int topY,m_int botY,m_int left,m_int right),void (ASMAPI *set4pixels)(bool inc_x,bool inc_y,bool region1),void (ASMAPI *finished)(void));
void MGLAPI MGL_ellipseArcEngine(rect_t extentRect,m_int startAngle,m_int endAngle,arc_coords_t *ac,void (ASMAPI *plotPoint)(m_int x,m_int y));
#endif
 
/* Text attribute manipulation */
 
#ifndef MGL_LITE
void MGLAPI MGL_setTextJustify(m_int horiz,m_int vert);
void MGLAPI MGL_getTextJustify(m_int *horiz,m_int *vert);
void MGLAPI MGL_setTextDirection(m_int direction);
m_int MGLAPI MGL_getTextDirection(void);
void MGLAPI MGL_setTextSize(m_int numerx,m_int denomx,m_int numery,m_int denomy);
void MGLAPI MGL_getTextSize(m_int *numerx,m_int *denomx,m_int *numery,m_int *denomy);
void MGLAPI MGL_setSpaceExtra(m_int extra);
m_int MGLAPI MGL_getSpaceExtra(void);
void MGLAPI MGL_setTextSettings(text_settings_t *settings);
void MGLAPI MGL_getTextSettings(text_settings_t *settings);
m_int MGLAPI MGL_textHeight(void);
m_int MGLAPI MGL_textWidth(const char *str);
void MGLAPI MGL_textBounds(m_int x,m_int y,const char *str,rect_t *bounds);
m_int MGLAPI MGL_charWidth(char ch);
void MGLAPI MGL_getFontMetrics(metrics_t *metrics);
void MGLAPI MGL_getCharMetrics(char ch,metrics_t *metrics);
m_int MGLAPI MGL_maxCharWidth(void);
void MGLAPI MGL_underScoreLocation(m_int *x,m_int *y,const char *str);
#endif
 
/* Text drawing */
 
#ifndef MGL_LITE
void MGLAPI MGL_drawStr(const char *str);
void MGLAPI MGL_drawStrXY(m_int x,m_int y,const char *str);
bool MGLAPI MGL_useFont(font_t *font);
font_t * MGLAPI MGL_getFont(void);
bool MGLAPI MGL_vecFontEngine(m_int x,m_int y,const char *str,void (ASMAPI *move)(m_int x,m_int y),void (ASMAPI *draw)(m_int x,m_int y));
#endif
 
/* BitBlt support */
 
void MGLAPI MGL_bitBltCoord(MGLDC *dst,MGLDC *src,m_int left,m_int top,m_int right,m_int bottom,m_int dstLeft,m_int dstTop,m_int op);
void MGLAPI MGL_stretchBltCoord(MGLDC *dst,MGLDC *src,m_int left,m_int top,m_int right,m_int bottom,m_int dstLeft,m_int dstTop,m_int dstRight,m_int dstBottom);
#ifndef MGL_LITE
void MGLAPI MGL_getDivotCoord(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom,void *divot);
void MGLAPI MGL_putDivot(MGLDC *dc,void *divot);
long MGLAPI MGL_divotSizeCoord(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom);
void MGLAPI MGL_putMonoImage(MGLDC *dc,m_int x,m_int y,m_int byteWidth,m_int height,void *image);
void MGLAPI MGL_putBitmap(MGLDC *dc,m_int x,m_int y,const bitmap_t *bitmap,m_int op);
void MGLAPI MGL_putBitmapSection(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom,m_int dstLeft,m_int dstTop,const bitmap_t *bitmap,m_int op);
void MGLAPI MGL_putBitmapTransparent(MGLDC *dc,m_int x,m_int y,const bitmap_t *bitmap,color_t transparent,bool sourceTrans);
void MGLAPI MGL_putBitmapTransparentSection(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom,m_int dstLeft,m_int dstTop,const bitmap_t *bitmap,color_t transparent,bool sourceTrans);
void MGLAPI MGL_putBitmapMask(MGLDC *dc,m_int x,m_int y,const bitmap_t *mask,color_t color);
void MGLAPI MGL_stretchBitmap(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom,const bitmap_t *bitmap);
void MGLAPI MGL_putIcon(MGLDC *dc,m_int x,m_int y,const icon_t *icon);
void MGLAPI MGL_transBltCoord(MGLDC *dst,MGLDC *src,m_int left,m_int top,m_int right,m_int bottom,m_int dstLeft,m_int dstTop,color_t transparent,bool sourceTrans);
#endif
 
/* Linear offscreen DC BitBlt support */
 
#ifndef MGL_LITE
void MGLAPI MGL_bitBltLinCoord(MGLDC *dst,MGLDC *src,ulong srcOfs,m_int dstLeft,m_int dstTop,m_int dstRight,m_int dstBottom,m_int op);
void MGLAPI MGL_transBltLinCoord(MGLDC *dst,MGLDC *src,ulong srcOfs,m_int dstLeft,m_int dstTop,m_int dstRight,m_int dstBottom,color_t transparent,bool sourceTrans);
#endif
 
/* Monochrome bitmap manipulation */
 
#ifndef MGL_LITE
void MGLAPI MGL_drawGlyph(font_t *g,m_int x,m_int y,uchar glyph);
m_int MGLAPI MGL_getGlyphWidth(font_t *font,uchar glyph);
m_int MGLAPI MGL_getGlyphHeight(font_t *font);
void MGLAPI MGL_rotateGlyph(uchar *dst,uchar *src,m_int *byteWidth,m_int *height,m_int rotation);
void MGLAPI MGL_mirrorGlyph(uchar *dst,uchar *src,m_int byteWidth,m_int height);
#endif
 
/* Region management */
 
#ifndef MGL_LITE
region_t * MGLAPI MGL_newRegion(void);
region_t * MGLAPI MGL_copyRegion(const region_t *s);
void MGLAPI MGL_clearRegion(region_t *r);
void MGLAPI MGL_freeRegion(region_t *r);
void MGLAPI MGL_drawRegion(m_int x,m_int y,const region_t *r);
#endif
 
/* Region generation primitives */
 
#ifndef MGL_LITE
region_t * MGLAPI MGL_rgnLineCoord(m_int x1,m_int y1,m_int x2,m_int y2,const region_t *pen);
region_t * MGLAPI MGL_rgnLineCoordFX(fix32_t x1,fix32_t y1,fix32_t x2,fix32_t y2,const region_t *pen);
/*region_t * MGLAPI MGL_rgnPolygon(m_int count,point_t *vArray);*/
/*region_t * MGLAPI MGL_rgnPolygonFast(m_int count,point_t *vArray);*/
region_t * MGLAPI MGL_rgnSolidRectCoord(m_int left,m_int top,m_int right,m_int bottom);
region_t * MGLAPI MGL_rgnEllipse(rect_t extentRect,const region_t *pen);
region_t * MGLAPI MGL_rgnEllipseArc(rect_t extentRect,m_int startAngle,m_int endAngle,const region_t *pen);
void MGLAPI MGL_rgnGetArcCoords(arc_coords_t *coords);
region_t * MGLAPI MGL_rgnSolidEllipse(rect_t extentRect);
region_t * MGLAPI MGL_rgnSolidEllipseArc(rect_t extentRect,m_int startAngle,m_int endAngle);
#endif
 
/* Region alegbra */
 
#ifndef MGL_LITE
region_t * MGLAPI MGL_sectRegion(const region_t *r1,const region_t *r2);
region_t * MGLAPI MGL_sectRegionRect(const region_t *r1,const rect_t *r2);
bool MGLAPI MGL_unionRegion(region_t *r1,const region_t *r2);
bool MGLAPI MGL_unionRegionRect(region_t *r1,const rect_t *r2);
bool MGLAPI MGL_unionRegionOfs(region_t *r1,const region_t *r2,m_int xOffset,m_int yOffset);
bool MGLAPI MGL_diffRegion(region_t *r1,const region_t *r2);
bool MGLAPI MGL_diffRegionRect(region_t *r1,const rect_t *r2);
void MGLAPI MGL_optimizeRegion(region_t *r);
void MGLAPI MGL_offsetRegion(region_t *r,m_int dx,m_int dy);
bool MGLAPI MGL_emptyRegion(const region_t *r);
bool MGLAPI MGL_equalRegion(const region_t *r1,const region_t *r2);
bool MGLAPI MGL_ptInRegionCoord(m_int x,m_int y,const region_t *r);
#endif
 
/* Region traversal */
 
#ifndef MGL_LITE
typedef void (ASMAPI *rgncallback_t)(const rect_t *r);
 
void MGLAPI MGL_traverseRegion(region_t *rgn,rgncallback_t doRect);
#endif
 
/* RGB to 8 bit halftone dithering routines */
 
#ifndef MGL_LITE
void MGLAPI MGL_getHalfTonePalette(palette_t *pal);
uchar MGLAPI MGL_halfTonePixel(m_int x,m_int y,uchar R,uchar G,uchar B);
#endif
 
/* Resource loading/unloading */
 
font_t * MGLAPI MGL_loadFont(const char *fontname);
bool MGLAPI MGL_availableFont(const char *fontname);
void MGLAPI MGL_unloadFont(font_t *font);
cursor_t * MGLAPI MGL_loadCursor(const char *cursorName);
bool MGLAPI MGL_availableCursor(const char *cursorName);
void MGLAPI MGL_unloadCursor(cursor_t *cursor);
#ifndef MGL_LITE
icon_t * MGLAPI MGL_loadIcon(const char *iconName,bool loadPalette);
bool MGLAPI MGL_availableIcon(const char *iconName);
void MGLAPI MGL_unloadIcon(icon_t *icon);
#endif
 
/* Windows BMP bitmap loading/unloading/saving */
 
#ifndef MGL_LITE
bitmap_t * MGLAPI MGL_loadBitmap(const char *bitmapName,bool loadPalette);
bool MGLAPI MGL_availableBitmap(const char *bitmapName);
void MGLAPI MGL_unloadBitmap(bitmap_t *bitmap);
bool MGLAPI MGL_getBitmapSize(const char *bitmapName,m_int *width,m_int *height,m_int *bitsPerPixel,pixel_format_t *pf);
bool MGLAPI MGL_loadBitmapIntoDC(MGLDC *dc,const char *bitmapName,m_int dstLeft,m_int dstTop,bool loadPalette);
bool MGLAPI MGL_saveBitmapFromDC(MGLDC *dc,const char *bitmapName,m_int left,m_int top,m_int right,m_int bottom);
bitmap_t * MGLAPI MGL_getBitmapFromDC(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom,bool savePalette);
bitmap_t * MGLAPI MGL_buildMonoMask(bitmap_t *bitmap,color_t transparent);
#endif
 
/* PCX bitmap loading/unloading/saving (1/4/8 bpp only) */
 
#ifndef MGL_LITE
bitmap_t * MGLAPI MGL_loadPCX(const char *bitmapName,bool loadPalette);
bool MGLAPI MGL_availablePCX(const char *bitmapName);
bool MGLAPI MGL_getPCXSize(const char *bitmapName,m_int *width,m_int *height,m_int *bitsPerPixel);
bool MGLAPI MGL_loadPCXIntoDC(MGLDC *dc,const char *bitmapName,m_int dstLeft,m_int dstTop,bool loadPalette);
bool MGLAPI MGL_savePCXFromDC(MGLDC *dc,const char *bitmapName,m_int left,m_int top,m_int right,m_int bottom);
#endif
 
/* Random number generation routines for shorts and longs with full range */
 
void ASMAPI MGL_srand(m_uint seed);
ushort ASMAPI MGL_random(ushort max);
ulong ASMAPI MGL_randoml(ulong max);
 
/* Mouse support */
 
bool MGLAPI MS_available(void);
void MGLAPI MS_show(void);
void MGLAPI MS_hide(void);
void MGLAPI MS_obscure(void);
void MGLAPI MS_setCursor(cursor_t *curs);
void MGLAPI MS_setCursorColor(color_t color);
void MGLAPI MS_moveTo(m_int x,m_int y);
void MGLAPI MS_getPos(m_int *x,m_int *y);
void MGLAPI MS_drawCursor(void);
 
/* Rectangle and Point manipulation */
 
rect_t MGLAPI MGL_defRect(m_int left,m_int top,m_int right,m_int bottom);
rect_t MGLAPI MGL_defRectPt(point_t leftTop,point_t rightBottom);
bool MGLAPI MGL_sectRect(rect_t s1,rect_t s2,rect_t *d);
bool MGLAPI MGL_sectRectCoord(m_int left1,m_int top1,m_int right1,m_int bottom1,m_int left2,m_int top2,m_int right2,m_int bottom2,rect_t *d);
void MGLAPI MGL_unionRect(rect_t s1,rect_t s2,rect_t *d);
void MGLAPI MGL_unionRectCoord(m_int left1,m_int top1,m_int right1,m_int bottom1,m_int left2,m_int top2,m_int right2,m_int bottom2,rect_t *d);
 
/* Built-in patterns and mouse cursor */
 
#ifndef MGL_LITE
pattern_t * MGLAPI _MGL_getEmptyPat(void);
pattern_t * MGLAPI _MGL_getGrayPat(void);
pattern_t * MGLAPI _MGL_getSolidPat(void);
#endif
cursor_t * MGLAPI _MGL_getDefCursor(void);
 
/* Fixed point multiplication/divide routines */
 
#if defined(__WATCOMC__) && defined(__386__)
 
/* For Watcom C++ we can use special inline assembler code that is much
* faster than calling the 386 assembler functions. Currently this is the
* the only compiler that will allow inline assembler to be expanded
* directly as inline functions.
*/
 
fix32_t MGL_FixMul(fix32_t a,fix32_t b);
#pragma aux MGL_FixMul = \
"imul edx" \
"add eax,8000h" \
"adc edx,0" \
"shrd eax,edx,16" \
parm [eax] [edx] \
value [eax] \
modify exact [eax edx];
 
fix32_t MGL_FixDiv(fix32_t a,fix32_t b);
#pragma aux MGL_FixDiv = \
"xor eax,eax" \
"shrd eax,edx,16" \
"sar edx,16" \
"idiv ebx" \
parm [edx] [ebx] \
value [eax] \
modify exact [eax edx];
 
fix32_t MGL_FixMulDiv(fix32_t a,fix32_t b,fix32_t c);
#pragma aux MGL_FixMulDiv = \
"imul ebx" \
"idiv ecx" \
parm [eax] [ebx] [ecx] \
value [eax] \
modify exact [eax edx];
 
m_int MGL_backfacing(fix32_t dx1,fix32_t dy1,fix32_t dx2,fix32_t dy2);
#pragma aux MGL_backfacing = \
"imul ebx" \
"mov ebx,eax" \
"mov ecx,edx" \
"mov eax,esi" \
"imul edi" \
"sub eax,ebx" \
"mov eax,1" \
"sbb edx,ecx" \
"jns @@Backfacing" \
"xor eax,eax" \
"@@Backfacing:" \
parm [eax] [esi] [edi] [ebx] \
value [eax] \
modify exact [eax ecx edx];
 
void MGL_memcpy(void *dst,void *src,m_int n);
#pragma aux MGL_memcpy = \
"mov eax,ecx" \
"shr ecx,2" \
"rep movsd" \
"mov cl,al" \
"and cl,3" \
"rep movsb" \
parm [edi] [esi] [ecx] \
modify exact [eax ecx esi edi];
 
#else
 
fix32_t ASMAPI MGL_FixMul(fix32_t a,fix32_t b);
fix32_t ASMAPI MGL_FixDiv(fix32_t a,fix32_t b);
fix32_t ASMAPI MGL_FixMulDiv(fix32_t a,fix32_t b,fix32_t c);
m_int ASMAPI MGL_backfacing(fix32_t dx1,fix32_t dy1,fix32_t dx2,fix32_t dy2);
void ASMAPI MGL_memcpy(void *dst,void *src,m_int n);
 
#endif
 
/* The following are special memcpy routines that properly handler reading
* and writing to virtual linear buffer memory by forcing the proper
* alignment. Note that the copy is extended to use a DWORD copy of speed.
*/
 
void ASMAPI MGL_memcpyVIRTSRC(void *dst,void *src,m_int n);
void ASMAPI MGL_memcpyVIRTDST(void *dst,void *src,m_int n);
 
/* Function to find an MGL system file's full pathname */
 
bool MGLAPI _MGL_findFile(char *validpath,const char *dir, const char *filename, const char *mode);
 
/* Override the internal MGL file I/O functions */
 
void MGLAPI MGL_setFileIO(fileio_t *fio);
 
/* The following dummy symbols are used to link in driver files to be used. A
* driver is not active until it is linked in with the MGL_registerDriver
* call. Because we dont export globals in DLLs, we provide functions to
* get the address of the drivers. However for a static link library we
* need to use globals so that if the driver data is unreferenced, it will
* not be linked in with the code.
*/
 
#ifndef BUILD_MGL
#if defined(MGL_DLL) && !defined(BUILD_MGLDLL)
void * MGLAPI VGA4_getDriverAddr(void);
void * MGLAPI VGAX_getDriverAddr(void);
void * MGLAPI SVGA4_getDriverAddr(void);
void * MGLAPI SVGA8_getDriverAddr(void);
void * MGLAPI SVGA16_getDriverAddr(void);
void * MGLAPI SVGA24_getDriverAddr(void);
void * MGLAPI SVGA32_getDriverAddr(void);
#if !defined(__16BIT__)
void * MGLAPI VGA8_getDriverAddr(void);
void * MGLAPI LINEAR8_getDriverAddr(void);
void * MGLAPI LINEAR16_getDriverAddr(void);
void * MGLAPI LINEAR24_getDriverAddr(void);
void * MGLAPI LINEAR32_getDriverAddr(void);
void * MGLAPI ACCEL8_getDriverAddr(void);
void * MGLAPI ACCEL16_getDriverAddr(void);
void * MGLAPI ACCEL24_getDriverAddr(void);
void * MGLAPI ACCEL32_getDriverAddr(void);
#if defined(MGLWIN) || defined(__WINDOWS__)
void * MGLAPI DDRAW8_getDriverAddr(void);
void * MGLAPI DDRAW16_getDriverAddr(void);
void * MGLAPI DDRAW24_getDriverAddr(void);
void * MGLAPI DDRAW32_getDriverAddr(void);
#endif
#endif
void * MGLAPI PACKED1_getDriverAddr(void);
void * MGLAPI PACKED4_getDriverAddr(void);
void * MGLAPI PACKED8_getDriverAddr(void);
void * MGLAPI PACKED16_getDriverAddr(void);
void * MGLAPI PACKED24_getDriverAddr(void);
void * MGLAPI PACKED32_getDriverAddr(void);
#define VGA4_driver VGA4_getDriverAddr()
#define VGAX_driver VGAX_getDriverAddr()
#define SVGA4_driver SVGA4_getDriverAddr()
#define SVGA8_driver SVGA8_getDriverAddr()
#define SVGA16_driver SVGA16_getDriverAddr()
#define SVGA24_driver SVGA24_getDriverAddr()
#define SVGA32_driver SVGA32_getDriverAddr()
#if !defined(__16BIT__)
#define VGA8_driver VGA8_getDriverAddr()
#define LINEAR8_driver LINEAR8_getDriverAddr()
#define LINEAR16_driver LINEAR16_getDriverAddr()
#define LINEAR24_driver LINEAR24_getDriverAddr()
#define LINEAR32_driver LINEAR32_getDriverAddr()
#define ACCEL8_driver ACCEL8_getDriverAddr()
#define ACCEL16_driver ACCEL16_getDriverAddr()
#define ACCEL24_driver ACCEL24_getDriverAddr()
#define ACCEL32_driver ACCEL32_getDriverAddr()
#if defined(MGLWIN) || defined(__WINDOWS__)
#define DDRAW8_driver DDRAW8_getDriverAddr()
#define DDRAW16_driver DDRAW16_getDriverAddr()
#define DDRAW24_driver DDRAW24_getDriverAddr()
#define DDRAW32_driver DDRAW32_getDriverAddr()
#endif
#endif
#define PACKED1_driver PACKED1_getDriverAddr()
#define PACKED4_driver PACKED4_getDriverAddr()
#define PACKED8_driver PACKED8_getDriverAddr()
#define PACKED16_driver PACKED16_getDriverAddr()
#define PACKED24_driver PACKED24_getDriverAddr()
#define PACKED32_driver PACKED32_getDriverAddr()
#else
extern m_int _VARAPI VGA4_driver[];
extern m_int _VARAPI VGAX_driver[];
extern m_int _VARAPI SVGA4_driver[];
extern m_int _VARAPI SVGA8_driver[];
extern m_int _VARAPI SVGA16_driver[];
extern m_int _VARAPI SVGA24_driver[];
extern m_int _VARAPI SVGA32_driver[];
#if !defined(__16BIT__)
extern m_int _VARAPI VGA8_driver[];
extern m_int _VARAPI LINEAR8_driver[];
extern m_int _VARAPI LINEAR16_driver[];
extern m_int _VARAPI LINEAR24_driver[];
extern m_int _VARAPI LINEAR32_driver[];
extern m_int _VARAPI ACCEL8_driver[];
extern m_int _VARAPI ACCEL16_driver[];
extern m_int _VARAPI ACCEL24_driver[];
extern m_int _VARAPI ACCEL32_driver[];
#if defined(MGLWIN) || defined(__WINDOWS__)
extern m_int _VARAPI DDRAW8_driver[];
extern m_int _VARAPI DDRAW16_driver[];
extern m_int _VARAPI DDRAW24_driver[];
extern m_int _VARAPI DDRAW32_driver[];
#endif
#endif
extern m_int _VARAPI PACKED1_driver[];
extern m_int _VARAPI PACKED4_driver[];
extern m_int _VARAPI PACKED8_driver[];
extern m_int _VARAPI PACKED16_driver[];
extern m_int _VARAPI PACKED24_driver[];
extern m_int _VARAPI PACKED32_driver[];
#endif
#endif
 
/*---------------------------------------------------------------------------
* Memory allocation and utility functions.
*-------------------------------------------------------------------------*/
 
#ifndef __16BIT__
#define _HUGE
#else
#define _HUGE _huge
#endif
 
void MGL_availableMemory(ulong *physical,ulong *total);
void MGL_useLocalMalloc(void _HUGE * (*malloc)(long size),void (*free)(void _HUGE *p));
void * MGLAPI MGL_malloc(long size);
void * MGLAPI MGL_calloc(long size,long n);
void MGLAPI MGL_free(void _HUGE *p);
void MGLAPI MGL_memset(void _HUGE *s,m_int c,long n);
void MGLAPI MGL_memsetw(void _HUGE *s,m_int c,long n);
void MGLAPI MGL_memsetl(void _HUGE *s,long c,long n);
 
/*---------------------------------------------------------------------------
* Set a fullscreen suspend application callback function. This is used in
* fullscreen video modes to allow switching back to the normal operating
* system graphical shell (such as Windows GDI, OS/2 PM etc).
*-------------------------------------------------------------------------*/
 
typedef m_int (ASMAPI *MGL_suspend_cb_t)(MGLDC *dc,m_int flags);
void MGLAPI MGL_setSuspendAppCallback(MGL_suspend_cb_t staveState);
 
/*---------------------------------------------------------------------------
* Tell the MGL to use a pre-loaded ACCEL.DRV driver file. This allows
* you to link with the SciTech WinDirect/Pro and WinDirect/Ultra device
* support libraries and tell the MGL to use the device support drivers.
* If the user has a real ACCEL.DRV driver file in the standard location
* on their machine, this driver file will still be used.
*-------------------------------------------------------------------------*/
 
void MGLAPI MGL_setACCELDriver(void *driver);
 
/*---------------------- Inline functions as Macros -----------------------*/
 
#define MGL_equalPoint(p1,p2) ((p1).x == (p2).x && (p1).y == (p2).y)
 
#define MGL_equalRect(r1,r2) ((r1).left == (r2).left && \
(r1).top == (r2).top && \
(r1).right == (r2).right && \
(r1).bottom == (r2).bottom)
 
#define MGL_emptyRect(r) ((r).bottom <= (r).top || \
(r).right <= (r).left)
 
#define MGL_disjointRect(r1,r2) ((r1).right <= (r2).left || \
(r1).left >= (r2).right || \
(r1).bottom <= (r2).top || \
(r1).top >= (r2).bottom)
 
#define MGL_sectRect(s1,s2,d) \
((d)->left = MAX((s1).left,(s2).left), \
(d)->right = MIN((s1).right,(s2).right), \
(d)->top = MAX((s1).top,(s2).top), \
(d)->bottom = MIN((s1).bottom,(s2).bottom), \
!MGL_emptyRect(*d))
 
#define MGL_sectRectFast(s1,s2,d) \
(d)->left = MAX((s1).left,(s2).left); \
(d)->right = MIN((s1).right,(s2).right); \
(d)->top = MAX((s1).top,(s2).top); \
(d)->bottom = MIN((s1).bottom,(s2).bottom)
 
#define MGL_sectRectCoord(l1,t1,r1,b1,l2,t2,r2,b2,d) \
((d)->left = MAX(l1,l2), \
(d)->right = MIN(r1,r2), \
(d)->top = MAX(t1,t2), \
(d)->bottom = MIN(b1,b2), \
!MGL_emptyRect(*d))
 
#define MGL_sectRectFastCoord(l1,t1,r1,b1,l2,t2,r2,b2,d) \
(d)->left = MAX(l1,l2); \
(d)->right = MIN(r1,r2); \
(d)->top = MAX(t1,t2); \
(d)->bottom = MIN(b1,b2)
 
#define MGL_unionRect(s1,s2,d) \
(d)->left = MIN((s1).left,(s2).left); \
(d)->right = MAX((s1).right,(s2).right); \
(d)->top = MIN((s1).top,(s2).top); \
(d)->bottom = MAX((s1).bottom,(s2).bottom)
 
#define MGL_unionRectCoord(l1,t1,r1,b1,l2,t2,r2,b2,d) \
(d)->left = MIN(l1,l2); \
(d)->right = MAX(r1,r2); \
(d)->top = MIN(t1,t2); \
(d)->bottom = MAX(b1,b2)
 
#define MGL_offsetRect(r,dx,dy) \
{ (r).left += dx; (r).right += dx; \
(r).top += dy; (r).bottom += dy; }
 
#define MGL_insetRect(r,dx,dy) \
{ (r).left += dx; (r).right -= dx; \
(r).top += dy; (r).bottom -= dy; \
if (MGL_emptyRect(r)) \
(r).left = (r).right = (r).top = (r).bottom = 0; }
 
#define MGL_ptInRect(p,r) ((p).x >= (r).left && \
(p).x < (r).right && \
(p).y >= (r).top && \
(p).y < (r).bottom)
 
#define MGL_ptInRectCoord(x,y,r) ((x) >= (r).left && \
(x) < (r).right && \
(y) >= (r).top && \
(y) < (r).bottom)
 
#define MGL_ptInRegion(p,r) MGL_ptInRegionCoord((p).x,(p).y,r)
 
#define MGL_pixel(p) MGL_pixelCoord((p).x,(p).y)
#define MGL_getPixel(p) MGL_getPixelCoord((p).x,(p).y)
#define MGL_pixelFast(p) MGL_pixelCoordFast((p).x,(p).y)
#define MGL_getPixelFast(p) MGL_getPixelCoordFast((p).x,(p).y)
#define MGL_moveTo(p) MGL_moveToCoord((p).x,(p).y)
#define MGL_moveRel(p) MGL_moveRelCoord((p).x,(p).y)
#define MGL_line(p1,p2) MGL_lineCoord((p1).x,(p1).y,(p2).x,(p2).y)
#define MGL_lineFast(p1,p2) MGL_lineCoordFast((p1).x,(p1).y,(p2).x,(p2).y)
#define MGL_lineFX(p1,p2) MGL_lineCoordFX((p1).x,(p1).y,(p2).x,(p2).y)
#define MGL_lineFastFX(p1,p2) MGL_lineCoordFastFX((p1).x,(p1).y,(p2).x,(p2).y)
#define MGL_cLineFast(p1,p2) MGL_cLineCoordFast((p1).p.x,(p1).p.y,(p1).c,(p2).p.x,(p2).p.y,(p2).c)
#define MGL_rgbLineFast(p1,p2) MGL_rgbLineCoordFast((p1).p.x,(p1).p.y,(p1).c.r,(p1).c.g,(p1).c.b,(p2).p.x,(p2).p.y,(p2).c.r,(p2).c.g,(p2).c.b)
#define MGL_zLineFast(p1,p2) MGL_zLineCoordFast((p1).p.x,(p1).p.y,(p1).z,(p2).p.x,(p2).p.y,(p2).z)
#define MGL_czLineFast(p1,p2) MGL_czLineCoordFast((p1).p.x,(p1).p.y,(p1).z,(p1).c,(p2).p.x,(p2).p.y,(p2).z,(p2).c)
#define MGL_rgbzLineFast(p1,p2) MGL_rgbzLineCoordFast((p1).p.x,(p1).p.y,(p1).z,(p1).c.r,(p1).c.g,(p1).c.b,(p2).p.x,(p2).p.y,(p2).z,(p2).c.r,(p2).c.g,(p2).c.b)
 
#define MGL_zClearPt(lt,rb,z) MGL_zClearCoord((lt).x,(lt).y, \
(rb).x,(rb).y,z)
#define MGL_zClear(r,z) MGL_zClearCoord((r).left,(r).top, \
(r).right,(r).bottom,z)
#define MGL_lineTo(p) MGL_lineToCoord((p).x,(p).y)
#define MGL_lineRel(p) MGL_lineRelCoord((p).x,(p).y);
#define MGL_rectPt(lt,rb) MGL_rectCoord((lt).x,(lt).y,(rb).x,(rb).y)
#define MGL_rect(r) MGL_rectCoord((r).left,(r).top, \
(r).right,(r).bottom)
#define MGL_drawBorder(r,s,t) MGL_drawBorderCoord((r).left,(r).top, \
(r).right,(r).bottom,(s),(t))
#define MGL_fillRectPt(lt,rb) MGL_fillRectCoord((lt).x,(lt).y, \
(rb).x,(rb).y)
#define MGL_fillRect(r) MGL_fillRectCoord((r).left,(r).top, \
(r).right,(r).bottom)
#define MGL_bitBlt(d,s,r,dl,dt,op) MGL_bitBltCoord((d),(s),(r).left, \
(r).top,(r).right,(r).bottom,dl,dt,op)
#define MGL_bitBltLin(d,s,so,r,op) MGL_bitBltLinCoord((d),(s),so, \
(r).left,(r).top,(r).right,(r).bottom,op)
#define MGL_stretchBlt(d,s,sr,dr) MGL_stretchBltCoord((d),(s),(sr).left, \
(sr).top,(sr).right,(sr).bottom, \
(dr).left,(dr).top,(dr).right,(dr).bottom)
#define MGL_transBlt(d,s,r,dl,dt,c,st) MGL_transBltCoord((d),(s),(r).left, \
(r).top,(r).right,(r).bottom,dl,dt,c,st)
#define MGL_transBltLin(d,s,so,r,c,st) MGL_transBltLinCoord((d),(s),so, \
(r).left,(r).top,(r).right,(r).bottom,c,st)
#define MGL_getDivot(dc,r,divot) MGL_getDivotCoord(dc,(r).left,(r).top, \
(r).right,(r).bottom,divot)
#define MGL_divotSize(dc,r) MGL_divotSizeCoord(dc,(r).left,(r).top,\
(r).right,(r).bottom)
#define MGL_isSimpleRegion(r) (((region_t*)(r))->spans == NULL)
#define MGL_rgnLine(p1,p2,p) MGL_rgnLineCoord((p1).x,(p1).y,(p2).x,(p2).y,p)
#define MGL_rgnLineFX(p1,p2,p) MGL_rgnLineCoordFX((p1).x,(p1).y,(p2).x,(p2).y,p)
#define MGL_rgnSolidRectPt(lt,rb) MGL_rgnSolidRectCoord((lt).x,(lt).y, \
(rb).x,(rb).y)
#define MGL_rgnSolidRect(r) MGL_rgnSolidRectCoord((r).left,(r).top, \
(r).right,(r).bottom)
 
/* Fast color packing/unpacking routines implemented as macros */
 
#define MGL_packColorFast(pf,R,G,B) \
((ulong)(((uchar)(R) >> (pf)->redAdjust) & (pf)->redMask) << (pf)->redPos) \
| ((ulong)(((uchar)(G) >> (pf)->greenAdjust) & (pf)->greenMask) << (pf)->greenPos) \
| ((ulong)(((uchar)(B) >> (pf)->blueAdjust) & (pf)->blueMask) << (pf)->bluePos)
 
#define MGL_unpackColorFast(pf,c,R,G,B) \
{ \
(R) = (uchar)((((ulong)(c) >> (pf)->redPos) & (pf)->redMask) << (pf)->redAdjust); \
(G) = (uchar)((((ulong)(c) >> (pf)->greenPos) & (pf)->greenMask) << (pf)->greenAdjust);\
(B) = (uchar)((((ulong)(c) >> (pf)->bluePos) & (pf)->blueMask) << (pf)->blueAdjust); \
}
 
/* Macros to access the RGB components in a packed 24 bit RGB tuple */
 
#define MGL_rgbRed(c) (((uchar*)&(c))[2])
#define MGL_rgbGreen(c) (((uchar*)&(c))[1])
#define MGL_rgbBlue(c) (((uchar*)&(c))[0])
 
/* Fast 24 bit color packing/unpacking routines implemented as macros */
 
#define MGL_packColorRGBFast(R,G,B) \
(((ulong)((uchar)(R)) << 16) | ((ulong)((uchar)(G)) << 8) | (uchar)(B))
 
#define MGL_packColorRGBFast2(c,R,G,B) \
{ \
MGL_rgbRed(c) = (uchar)(R); \
MGL_rgbGreen(c) = (uchar)(G); \
MGL_rgbBlue(c) = (uchar)(B); \
}
 
#define MGL_unpackColorRGBFast(c,R,G,B) \
{ \
(R) = MGL_rgbRed(c); \
(G) = MGL_rgbGreen(c); \
(B) = MGL_rgbBlue(c); \
}
 
#ifdef __cplusplus
} /* End of "C" linkage for C++ */
 
#include "mglrect.hpp" /* Include C++ point/rectangle classes */
 
#endif /* __cplusplus */
 
/* Include appropriate platform specific bindings */
 
#if defined(MGLWIN) || defined(__WINDOWS__)
#include "mglwin.h"
#elif defined(MGLPM) || defined(__OS2__)
/*#include "mglpm.h"*/
#elif defined(MGLX) || defined(__UNIX__)
/*#include "mglx.h"*/
#else
#include "mgldos.h"
#endif
 
#pragma pack() /* Return to default packing */
 
#endif /* __MGRAPH_H */
/contrib/other/sdlquake-1.0.9/scitech/LIB/WIN32/VC/MGLLT.LIB
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/contrib/other/sdlquake-1.0.9/screen.c
0,0 → 1,991
/*
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.c -- master for refresh, status bar, console, chat, notify, etc
 
#include "quakedef.h"
#include "r_local.h"
 
// only the refresh window will be updated unless these variables are flagged
int scr_copytop;
int scr_copyeverything;
 
float scr_con_current;
float scr_conlines; // lines of console to display
 
float oldscreensize, oldfov;
cvar_t scr_viewsize = {"viewsize","100", true};
cvar_t scr_fov = {"fov","90"}; // 10 - 170
cvar_t scr_conspeed = {"scr_conspeed","300"};
cvar_t scr_centertime = {"scr_centertime","2"};
cvar_t scr_showram = {"showram","1"};
cvar_t scr_showturtle = {"showturtle","0"};
cvar_t scr_showpause = {"showpause","1"};
cvar_t scr_printspeed = {"scr_printspeed","8"};
 
qboolean scr_initialized; // ready to draw
 
qpic_t *scr_ram;
qpic_t *scr_net;
qpic_t *scr_turtle;
 
int scr_fullupdate;
 
int clearconsole;
int clearnotify;
 
viddef_t vid; // global video state
 
vrect_t *pconupdate;
vrect_t scr_vrect;
 
qboolean scr_disabled_for_loading;
qboolean scr_drawloading;
float scr_disabled_time;
qboolean scr_skipupdate;
 
qboolean block_drawing;
 
void SCR_ScreenShot_f (void);
 
/*
===============================================================================
 
CENTER PRINTING
 
===============================================================================
*/
 
char scr_centerstring[1024];
float scr_centertime_start; // for slow victory printing
float scr_centertime_off;
int scr_center_lines;
int scr_erase_lines;
int scr_erase_center;
 
/*
==============
SCR_CenterPrint
 
Called for important messages that should stay in the center of the screen
for a few moments
==============
*/
void SCR_CenterPrint (char *str)
{
strncpy (scr_centerstring, str, sizeof(scr_centerstring)-1);
scr_centertime_off = scr_centertime.value;
scr_centertime_start = cl.time;
 
// count the number of lines for centering
scr_center_lines = 1;
while (*str)
{
if (*str == '\n')
scr_center_lines++;
str++;
}
}
 
void SCR_EraseCenterString (void)
{
int y;
 
if (scr_erase_center++ > vid.numpages)
{
scr_erase_lines = 0;
return;
}
 
if (scr_center_lines <= 4)
y = vid.height*0.35;
else
y = 48;
 
scr_copytop = 1;
Draw_TileClear (0, y,vid.width, 8*scr_erase_lines);
}
 
void SCR_DrawCenterString (void)
{
char *start;
int l;
int j;
int x, y;
int remaining;
 
// the finale prints the characters one at a time
if (cl.intermission)
remaining = scr_printspeed.value * (cl.time - scr_centertime_start);
else
remaining = 9999;
 
scr_erase_center = 0;
start = scr_centerstring;
 
if (scr_center_lines <= 4)
y = vid.height*0.35;
else
y = 48;
 
do
{
// scan the width of the line
for (l=0 ; l<40 ; l++)
if (start[l] == '\n' || !start[l])
break;
x = (vid.width - l*8)/2;
for (j=0 ; j<l ; j++, x+=8)
{
Draw_Character (x, y, start[j]);
if (!remaining--)
return;
}
y += 8;
 
while (*start && *start != '\n')
start++;
 
if (!*start)
break;
start++; // skip the \n
} while (1);
}
 
void SCR_CheckDrawCenterString (void)
{
scr_copytop = 1;
if (scr_center_lines > scr_erase_lines)
scr_erase_lines = scr_center_lines;
 
scr_centertime_off -= host_frametime;
if (scr_centertime_off <= 0 && !cl.intermission)
return;
if (key_dest != key_game)
return;
 
SCR_DrawCenterString ();
}
 
//=============================================================================
 
/*
====================
CalcFov
====================
*/
float CalcFov (float fov_x, float width, float height)
{
float a;
float x;
 
if (fov_x < 1 || fov_x > 179)
Sys_Error ("Bad fov: %f", fov_x);
 
x = width/tan(fov_x/360*M_PI);
 
a = atan (height/x);
 
a = a*360/M_PI;
 
return a;
}
 
/*
=================
SCR_CalcRefdef
 
Must be called whenever vid changes
Internal use only
=================
*/
static void SCR_CalcRefdef (void)
{
vrect_t vrect;
float size;
 
scr_fullupdate = 0; // force a background redraw
vid.recalc_refdef = 0;
 
// force the status bar to redraw
Sbar_Changed ();
 
//========================================
// bound viewsize
if (scr_viewsize.value < 30)
Cvar_Set ("viewsize","30");
if (scr_viewsize.value > 120)
Cvar_Set ("viewsize","120");
 
// bound field of view
if (scr_fov.value < 10)
Cvar_Set ("fov","10");
if (scr_fov.value > 170)
Cvar_Set ("fov","170");
 
r_refdef.fov_x = scr_fov.value;
r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height);
 
// intermission is always full screen
if (cl.intermission)
size = 120;
else
size = scr_viewsize.value;
 
if (size >= 120)
sb_lines = 0; // no status bar at all
else if (size >= 110)
sb_lines = 24; // no inventory
else
sb_lines = 24+16+8;
 
// these calculations mirror those in R_Init() for r_refdef, but take no
// account of water warping
vrect.x = 0;
vrect.y = 0;
vrect.width = vid.width;
vrect.height = vid.height;
 
R_SetVrect (&vrect, &scr_vrect, sb_lines);
 
// guard against going from one mode to another that's less than half the
// vertical resolution
if (scr_con_current > vid.height)
scr_con_current = vid.height;
 
// notify the refresh of the change
R_ViewChanged (&vrect, sb_lines, vid.aspect);
}
 
 
/*
=================
SCR_SizeUp_f
 
Keybinding command
=================
*/
void SCR_SizeUp_f (void)
{
Cvar_SetValue ("viewsize",scr_viewsize.value+10);
vid.recalc_refdef = 1;
}
 
 
/*
=================
SCR_SizeDown_f
 
Keybinding command
=================
*/
void SCR_SizeDown_f (void)
{
Cvar_SetValue ("viewsize",scr_viewsize.value-10);
vid.recalc_refdef = 1;
}
 
//============================================================================
 
/*
==================
SCR_Init
==================
*/
void SCR_Init (void)
{
Cvar_RegisterVariable (&scr_fov);
Cvar_RegisterVariable (&scr_viewsize);
Cvar_RegisterVariable (&scr_conspeed);
Cvar_RegisterVariable (&scr_showram);
Cvar_RegisterVariable (&scr_showturtle);
Cvar_RegisterVariable (&scr_showpause);
Cvar_RegisterVariable (&scr_centertime);
Cvar_RegisterVariable (&scr_printspeed);
 
//
// register our commands
//
Cmd_AddCommand ("screenshot",SCR_ScreenShot_f);
Cmd_AddCommand ("sizeup",SCR_SizeUp_f);
Cmd_AddCommand ("sizedown",SCR_SizeDown_f);
 
scr_ram = Draw_PicFromWad ("ram");
scr_net = Draw_PicFromWad ("net");
scr_turtle = Draw_PicFromWad ("turtle");
 
scr_initialized = true;
}
 
 
 
/*
==============
SCR_DrawRam
==============
*/
void SCR_DrawRam (void)
{
if (!scr_showram.value)
return;
 
if (!r_cache_thrash)
return;
 
Draw_Pic (scr_vrect.x+32, scr_vrect.y, scr_ram);
}
 
/*
==============
SCR_DrawTurtle
==============
*/
void SCR_DrawTurtle (void)
{
static int count;
if (!scr_showturtle.value)
return;
 
if (host_frametime < 0.1)
{
count = 0;
return;
}
 
count++;
if (count < 3)
return;
 
Draw_Pic (scr_vrect.x, scr_vrect.y, scr_turtle);
}
 
/*
==============
SCR_DrawNet
==============
*/
void SCR_DrawNet (void)
{
if (realtime - cl.last_received_message < 0.3)
return;
if (cls.demoplayback)
return;
 
Draw_Pic (scr_vrect.x+64, scr_vrect.y, scr_net);
}
 
/*
==============
DrawPause
==============
*/
void SCR_DrawPause (void)
{
qpic_t *pic;
 
if (!scr_showpause.value) // turn off for screenshots
return;
 
if (!cl.paused)
return;
 
pic = Draw_CachePic ("gfx/pause.lmp");
Draw_Pic ( (vid.width - pic->width)/2,
(vid.height - 48 - pic->height)/2, pic);
}
 
 
 
/*
==============
SCR_DrawLoading
==============
*/
void SCR_DrawLoading (void)
{
qpic_t *pic;
 
if (!scr_drawloading)
return;
pic = Draw_CachePic ("gfx/loading.lmp");
Draw_Pic ( (vid.width - pic->width)/2,
(vid.height - 48 - pic->height)/2, pic);
}
 
 
 
//=============================================================================
 
 
/*
==================
SCR_SetUpToDrawConsole
==================
*/
void SCR_SetUpToDrawConsole (void)
{
Con_CheckResize ();
if (scr_drawloading)
return; // never a console with loading plaque
// decide on the height of the console
con_forcedup = !cl.worldmodel || cls.signon != SIGNONS;
 
if (con_forcedup)
{
scr_conlines = vid.height; // full screen
scr_con_current = scr_conlines;
}
else if (key_dest == key_console)
scr_conlines = vid.height/2; // half screen
else
scr_conlines = 0; // none visible
if (scr_conlines < scr_con_current)
{
scr_con_current -= scr_conspeed.value*host_frametime;
if (scr_conlines > scr_con_current)
scr_con_current = scr_conlines;
 
}
else if (scr_conlines > scr_con_current)
{
scr_con_current += scr_conspeed.value*host_frametime;
if (scr_conlines < scr_con_current)
scr_con_current = scr_conlines;
}
 
if (clearconsole++ < vid.numpages)
{
scr_copytop = 1;
Draw_TileClear (0,(int)scr_con_current,vid.width, vid.height - (int)scr_con_current);
Sbar_Changed ();
}
else if (clearnotify++ < vid.numpages)
{
scr_copytop = 1;
Draw_TileClear (0,0,vid.width, con_notifylines);
}
else
con_notifylines = 0;
}
/*
==================
SCR_DrawConsole
==================
*/
void SCR_DrawConsole (void)
{
if (scr_con_current)
{
scr_copyeverything = 1;
Con_DrawConsole (scr_con_current, true);
clearconsole = 0;
}
else
{
if (key_dest == key_game || key_dest == key_message)
Con_DrawNotify (); // only draw notify in game
}
}
 
 
/*
==============================================================================
SCREEN SHOTS
==============================================================================
*/
 
typedef struct
{
char manufacturer;
char version;
char encoding;
char bits_per_pixel;
unsigned short xmin,ymin,xmax,ymax;
unsigned short hres,vres;
unsigned char palette[48];
char reserved;
char color_planes;
unsigned short bytes_per_line;
unsigned short palette_type;
char filler[58];
unsigned char data; // unbounded
} pcx_t;
 
/*
==============
WritePCXfile
==============
*/
void WritePCXfile (char *filename, byte *data, int width, int height,
int rowbytes, byte *palette)
{
int i, j, length;
pcx_t *pcx;
byte *pack;
pcx = Hunk_TempAlloc (width*height*2+1000);
if (pcx == NULL)
{
Con_Printf("SCR_ScreenShot_f: not enough memory\n");
return;
}
pcx->manufacturer = 0x0a; // PCX id
pcx->version = 5; // 256 color
pcx->encoding = 1; // uncompressed
pcx->bits_per_pixel = 8; // 256 color
pcx->xmin = 0;
pcx->ymin = 0;
pcx->xmax = LittleShort((short)(width-1));
pcx->ymax = LittleShort((short)(height-1));
pcx->hres = LittleShort((short)width);
pcx->vres = LittleShort((short)height);
Q_memset (pcx->palette,0,sizeof(pcx->palette));
pcx->color_planes = 1; // chunky image
pcx->bytes_per_line = LittleShort((short)width);
pcx->palette_type = LittleShort(2); // not a grey scale
Q_memset (pcx->filler,0,sizeof(pcx->filler));
 
// pack the image
pack = &pcx->data;
for (i=0 ; i<height ; i++)
{
for (j=0 ; j<width ; j++)
{
if ( (*data & 0xc0) != 0xc0)
*pack++ = *data++;
else
{
*pack++ = 0xc1;
*pack++ = *data++;
}
}
 
data += rowbytes - width;
}
// write the palette
*pack++ = 0x0c; // palette ID byte
for (i=0 ; i<768 ; i++)
*pack++ = *palette++;
// write output file
length = pack - (byte *)pcx;
COM_WriteFile (filename, pcx, length);
}
 
 
/*
==================
SCR_ScreenShot_f
==================
*/
void SCR_ScreenShot_f (void)
{
int i;
char pcxname[80];
char checkname[MAX_OSPATH];
 
//
// find a file name to save it to
//
strcpy(pcxname,"quake00.pcx");
for (i=0 ; i<=99 ; i++)
{
pcxname[5] = i/10 + '0';
pcxname[6] = i%10 + '0';
sprintf (checkname, "%s/%s", com_gamedir, pcxname);
if (Sys_FileTime(checkname) == -1)
break; // file doesn't exist
}
if (i==100)
{
Con_Printf ("SCR_ScreenShot_f: Couldn't create a PCX file\n");
return;
}
 
//
// save the pcx file
//
D_EnableBackBufferAccess (); // enable direct drawing of console to back
// buffer
 
WritePCXfile (pcxname, vid.buffer, vid.width, vid.height, vid.rowbytes,
host_basepal);
 
D_DisableBackBufferAccess (); // for adapters that can't stay mapped in
// for linear writes all the time
 
Con_Printf ("Wrote %s\n", pcxname);
}
 
 
//=============================================================================
 
 
/*
===============
SCR_BeginLoadingPlaque
 
================
*/
void SCR_BeginLoadingPlaque (void)
{
S_StopAllSounds (true);
 
if (cls.state != ca_connected)
return;
if (cls.signon != SIGNONS)
return;
// redraw with no console and the loading plaque
Con_ClearNotify ();
scr_centertime_off = 0;
scr_con_current = 0;
 
scr_drawloading = true;
scr_fullupdate = 0;
Sbar_Changed ();
SCR_UpdateScreen ();
scr_drawloading = false;
 
scr_disabled_for_loading = true;
scr_disabled_time = realtime;
scr_fullupdate = 0;
}
 
/*
===============
SCR_EndLoadingPlaque
 
================
*/
void SCR_EndLoadingPlaque (void)
{
scr_disabled_for_loading = false;
scr_fullupdate = 0;
Con_ClearNotify ();
}
 
//=============================================================================
 
char *scr_notifystring;
qboolean scr_drawdialog;
 
void SCR_DrawNotifyString (void)
{
char *start;
int l;
int j;
int x, y;
 
start = scr_notifystring;
 
y = vid.height*0.35;
 
do
{
// scan the width of the line
for (l=0 ; l<40 ; l++)
if (start[l] == '\n' || !start[l])
break;
x = (vid.width - l*8)/2;
for (j=0 ; j<l ; j++, x+=8)
Draw_Character (x, y, start[j]);
y += 8;
 
while (*start && *start != '\n')
start++;
 
if (!*start)
break;
start++; // skip the \n
} while (1);
}
 
/*
==================
SCR_ModalMessage
 
Displays a text string in the center of the screen and waits for a Y or N
keypress.
==================
*/
int SCR_ModalMessage (char *text)
{
if (cls.state == ca_dedicated)
return true;
 
scr_notifystring = text;
// draw a fresh screen
scr_fullupdate = 0;
scr_drawdialog = true;
SCR_UpdateScreen ();
scr_drawdialog = false;
S_ClearBuffer (); // so dma doesn't loop current sound
 
do
{
key_count = -1; // wait for a key down and up
Sys_SendKeyEvents ();
} while (key_lastpress != 'y' && key_lastpress != 'n' && key_lastpress != K_ESCAPE);
 
scr_fullupdate = 0;
SCR_UpdateScreen ();
 
return key_lastpress == 'y';
}
 
 
//=============================================================================
 
/*
===============
SCR_BringDownConsole
 
Brings the console down and fades the palettes back to normal
================
*/
void SCR_BringDownConsole (void)
{
int i;
scr_centertime_off = 0;
for (i=0 ; i<20 && scr_conlines != scr_con_current ; i++)
SCR_UpdateScreen ();
 
cl.cshifts[0].percent = 0; // no area contents palette on next frame
VID_SetPalette (host_basepal);
}
 
 
/*
==================
SCR_UpdateScreen
 
This is called every frame, and can also be called explicitly to flush
text to the screen.
 
WARNING: be very careful calling this from elsewhere, because the refresh
needs almost the entire 256k of stack space!
==================
*/
void SCR_UpdateScreen (void)
{
static float oldscr_viewsize;
static float oldlcd_x;
vrect_t vrect;
if (scr_skipupdate || block_drawing)
return;
 
scr_copytop = 0;
scr_copyeverything = 0;
 
if (scr_disabled_for_loading)
{
if (realtime - scr_disabled_time > 60)
{
scr_disabled_for_loading = false;
Con_Printf ("load failed.\n");
}
else
return;
}
 
if (cls.state == ca_dedicated)
return; // stdout only
 
if (!scr_initialized || !con_initialized)
return; // not initialized yet
 
if (scr_viewsize.value != oldscr_viewsize)
{
oldscr_viewsize = scr_viewsize.value;
vid.recalc_refdef = 1;
}
//
// check for vid changes
//
if (oldfov != scr_fov.value)
{
oldfov = scr_fov.value;
vid.recalc_refdef = true;
}
if (oldlcd_x != lcd_x.value)
{
oldlcd_x = lcd_x.value;
vid.recalc_refdef = true;
}
if (oldscreensize != scr_viewsize.value)
{
oldscreensize = scr_viewsize.value;
vid.recalc_refdef = true;
}
if (vid.recalc_refdef)
{
// something changed, so reorder the screen
SCR_CalcRefdef ();
}
 
//
// do 3D refresh drawing, and then update the screen
//
D_EnableBackBufferAccess (); // of all overlay stuff if drawing directly
 
if (scr_fullupdate++ < vid.numpages)
{ // clear the entire screen
scr_copyeverything = 1;
Draw_TileClear (0,0,vid.width,vid.height);
Sbar_Changed ();
}
 
pconupdate = NULL;
 
 
SCR_SetUpToDrawConsole ();
SCR_EraseCenterString ();
 
D_DisableBackBufferAccess (); // for adapters that can't stay mapped in
// for linear writes all the time
 
VID_LockBuffer ();
 
V_RenderView ();
 
VID_UnlockBuffer ();
 
D_EnableBackBufferAccess (); // of all overlay stuff if drawing directly
 
if (scr_drawdialog)
{
Sbar_Draw ();
Draw_FadeScreen ();
SCR_DrawNotifyString ();
scr_copyeverything = true;
}
else if (scr_drawloading)
{
SCR_DrawLoading ();
Sbar_Draw ();
}
else if (cl.intermission == 1 && key_dest == key_game)
{
Sbar_IntermissionOverlay ();
}
else if (cl.intermission == 2 && key_dest == key_game)
{
Sbar_FinaleOverlay ();
SCR_CheckDrawCenterString ();
}
else if (cl.intermission == 3 && key_dest == key_game)
{
SCR_CheckDrawCenterString ();
}
else
{
SCR_DrawRam ();
SCR_DrawNet ();
SCR_DrawTurtle ();
SCR_DrawPause ();
SCR_CheckDrawCenterString ();
Sbar_Draw ();
SCR_DrawConsole ();
M_Draw ();
}
 
D_DisableBackBufferAccess (); // for adapters that can't stay mapped in
// for linear writes all the time
if (pconupdate)
{
D_UpdateRects (pconupdate);
}
 
V_UpdatePalette ();
 
//
// update one of three areas
//
 
if (scr_copyeverything)
{
vrect.x = 0;
vrect.y = 0;
vrect.width = vid.width;
vrect.height = vid.height;
vrect.pnext = 0;
VID_Update (&vrect);
}
else if (scr_copytop)
{
vrect.x = 0;
vrect.y = 0;
vrect.width = vid.width;
vrect.height = vid.height - sb_lines;
vrect.pnext = 0;
VID_Update (&vrect);
}
else
{
vrect.x = scr_vrect.x;
vrect.y = scr_vrect.y;
vrect.width = scr_vrect.width;
vrect.height = scr_vrect.height;
vrect.pnext = 0;
VID_Update (&vrect);
}
}
 
 
/*
==================
SCR_UpdateWholeScreen
==================
*/
void SCR_UpdateWholeScreen (void)
{
scr_fullupdate = 0;
SCR_UpdateScreen ();
}
/contrib/other/sdlquake-1.0.9/screen.h
0,0 → 1,57
/*
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;
 
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);
/contrib/other/sdlquake-1.0.9/server.h
0,0 → 1,257
/*
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
#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
/contrib/other/sdlquake-1.0.9/snd_dma.c
0,0 → 1,1022
/*
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_dma.c -- main control for any streaming sound output device
 
#include "quakedef.h"
 
#ifdef _WIN32
#include "winquake.h"
#endif
 
void S_Play(void);
void S_PlayVol(void);
void S_SoundList(void);
void S_Update_();
void S_StopAllSounds(qboolean clear);
void S_StopAllSoundsC(void);
 
// =======================================================================
// Internal sound data & structures
// =======================================================================
 
channel_t channels[MAX_CHANNELS];
int total_channels;
 
int snd_blocked = 0;
static qboolean snd_ambient = 1;
qboolean snd_initialized = false;
 
// pointer should go away
volatile dma_t *shm = 0;
volatile dma_t sn;
 
vec3_t listener_origin;
vec3_t listener_forward;
vec3_t listener_right;
vec3_t listener_up;
vec_t sound_nominal_clip_dist=1000.0;
 
int soundtime; // sample PAIRS
int paintedtime; // sample PAIRS
 
 
#define MAX_SFX 512
sfx_t *known_sfx; // hunk allocated [MAX_SFX]
int num_sfx;
 
sfx_t *ambient_sfx[NUM_AMBIENTS];
 
int desired_speed = 11025;
int desired_bits = 16;
 
int sound_started=0;
 
cvar_t bgmvolume = {"bgmvolume", "1", true};
cvar_t volume = {"volume", "0.7", true};
 
cvar_t nosound = {"nosound", "0"};
cvar_t precache = {"precache", "1"};
cvar_t loadas8bit = {"loadas8bit", "0"};
cvar_t bgmbuffer = {"bgmbuffer", "4096"};
cvar_t ambient_level = {"ambient_level", "0.3"};
cvar_t ambient_fade = {"ambient_fade", "100"};
cvar_t snd_noextraupdate = {"snd_noextraupdate", "0"};
cvar_t snd_show = {"snd_show", "0"};
cvar_t _snd_mixahead = {"_snd_mixahead", "0.1", true};
 
 
// ====================================================================
// User-setable variables
// ====================================================================
 
 
//
// 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.
//
 
qboolean fakedma = false;
int fakedma_updates = 15;
 
 
void S_AmbientOff (void)
{
snd_ambient = false;
}
 
 
void S_AmbientOn (void)
{
snd_ambient = true;
}
 
 
void S_SoundInfo_f(void)
{
if (!sound_started || !shm)
{
Con_Printf ("sound system not started\n");
return;
}
Con_Printf("%5d stereo\n", shm->channels - 1);
Con_Printf("%5d samples\n", shm->samples);
Con_Printf("%5d samplepos\n", shm->samplepos);
Con_Printf("%5d samplebits\n", shm->samplebits);
Con_Printf("%5d submission_chunk\n", shm->submission_chunk);
Con_Printf("%5d speed\n", shm->speed);
Con_Printf("0x%x dma buffer\n", shm->buffer);
Con_Printf("%5d total_channels\n", total_channels);
}
 
 
/*
================
S_Startup
================
*/
 
void S_Startup (void)
{
int rc;
 
if (!snd_initialized)
return;
 
if (!fakedma)
{
rc = SNDDMA_Init();
 
if (!rc)
{
#ifndef _WIN32
Con_Printf("S_Startup: SNDDMA_Init failed.\n");
#endif
sound_started = 0;
return;
}
}
 
sound_started = 1;
}
 
 
/*
================
S_Init
================
*/
void S_Init (void)
{
 
Con_Printf("\nSound Initialization\n");
 
if (COM_CheckParm("-nosound"))
return;
 
if (COM_CheckParm("-simsound"))
fakedma = true;
 
Cmd_AddCommand("play", S_Play);
Cmd_AddCommand("playvol", S_PlayVol);
Cmd_AddCommand("stopsound", S_StopAllSoundsC);
Cmd_AddCommand("soundlist", S_SoundList);
Cmd_AddCommand("soundinfo", S_SoundInfo_f);
 
Cvar_RegisterVariable(&nosound);
Cvar_RegisterVariable(&volume);
Cvar_RegisterVariable(&precache);
Cvar_RegisterVariable(&loadas8bit);
Cvar_RegisterVariable(&bgmvolume);
Cvar_RegisterVariable(&bgmbuffer);
Cvar_RegisterVariable(&ambient_level);
Cvar_RegisterVariable(&ambient_fade);
Cvar_RegisterVariable(&snd_noextraupdate);
Cvar_RegisterVariable(&snd_show);
Cvar_RegisterVariable(&_snd_mixahead);
 
if (host_parms.memsize < 0x800000)
{
Cvar_Set ("loadas8bit", "1");
Con_Printf ("loading all sounds as 8bit\n");
}
 
 
 
snd_initialized = true;
 
S_Startup ();
 
SND_InitScaletable ();
 
known_sfx = Hunk_AllocName (MAX_SFX*sizeof(sfx_t), "sfx_t");
num_sfx = 0;
 
// create a piece of DMA memory
 
if (fakedma)
{
shm = (void *) Hunk_AllocName(sizeof(*shm), "shm");
shm->splitbuffer = 0;
shm->samplebits = 16;
shm->speed = 22050;
shm->channels = 2;
shm->samples = 32768;
shm->samplepos = 0;
shm->soundalive = true;
shm->gamealive = true;
shm->submission_chunk = 1;
shm->buffer = Hunk_AllocName(1<<16, "shmbuf");
}
 
if ( shm ) {
Con_Printf ("Sound sampling rate: %i\n", shm->speed);
}
 
// provides a tick sound until washed clean
 
// if (shm->buffer)
// shm->buffer[4] = shm->buffer[5] = 0x7f; // force a pop for debugging
 
ambient_sfx[AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav");
ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav");
 
S_StopAllSounds (true);
}
 
 
// =======================================================================
// Shutdown sound engine
// =======================================================================
 
void S_Shutdown(void)
{
 
if (!sound_started)
return;
 
if (shm)
shm->gamealive = 0;
 
shm = 0;
sound_started = 0;
 
if (!fakedma)
{
SNDDMA_Shutdown();
}
}
 
 
// =======================================================================
// Load a sound
// =======================================================================
 
/*
==================
S_FindName
 
==================
*/
sfx_t *S_FindName (char *name)
{
int i;
sfx_t *sfx;
 
if (!name)
Sys_Error ("S_FindName: NULL\n");
 
if (Q_strlen(name) >= MAX_QPATH)
Sys_Error ("Sound name too long: %s", name);
 
// see if already loaded
for (i=0 ; i < num_sfx ; i++)
if (!Q_strcmp(known_sfx[i].name, name))
{
return &known_sfx[i];
}
 
if (num_sfx == MAX_SFX)
Sys_Error ("S_FindName: out of sfx_t");
sfx = &known_sfx[i];
strcpy (sfx->name, name);
 
num_sfx++;
return sfx;
}
 
 
/*
==================
S_TouchSound
 
==================
*/
void S_TouchSound (char *name)
{
sfx_t *sfx;
if (!sound_started)
return;
 
sfx = S_FindName (name);
Cache_Check (&sfx->cache);
}
 
/*
==================
S_PrecacheSound
 
==================
*/
sfx_t *S_PrecacheSound (char *name)
{
sfx_t *sfx;
 
if (!sound_started || nosound.value)
return NULL;
 
sfx = S_FindName (name);
// cache it in
if (precache.value)
S_LoadSound (sfx);
return sfx;
}
 
 
//=============================================================================
 
/*
=================
SND_PickChannel
=================
*/
channel_t *SND_PickChannel(int entnum, int entchannel)
{
int ch_idx;
int first_to_die;
int life_left;
 
// Check for replacement sound, or find the best one to replace
first_to_die = -1;
life_left = 0x7fffffff;
for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++)
{
if (entchannel != 0 // channel 0 never overrides
&& channels[ch_idx].entnum == entnum
&& (channels[ch_idx].entchannel == entchannel || entchannel == -1) )
{ // allways override sound from same entity
first_to_die = ch_idx;
break;
}
 
// don't let monster sounds override player sounds
if (channels[ch_idx].entnum == cl.viewentity && entnum != cl.viewentity && channels[ch_idx].sfx)
continue;
 
if (channels[ch_idx].end - paintedtime < life_left)
{
life_left = channels[ch_idx].end - paintedtime;
first_to_die = ch_idx;
}
}
 
if (first_to_die == -1)
return NULL;
 
if (channels[first_to_die].sfx)
channels[first_to_die].sfx = NULL;
 
return &channels[first_to_die];
}
 
/*
=================
SND_Spatialize
=================
*/
void SND_Spatialize(channel_t *ch)
{
vec_t dot;
vec_t ldist, rdist, dist;
vec_t lscale, rscale, scale;
vec3_t source_vec;
sfx_t *snd;
 
// anything coming from the view entity will allways be full volume
if (ch->entnum == cl.viewentity)
{
ch->leftvol = ch->master_vol;
ch->rightvol = ch->master_vol;
return;
}
 
// calculate stereo seperation and distance attenuation
 
snd = ch->sfx;
VectorSubtract(ch->origin, listener_origin, source_vec);
dist = VectorNormalize(source_vec) * ch->dist_mult;
dot = DotProduct(listener_right, source_vec);
 
if (shm->channels == 1)
{
rscale = 1.0;
lscale = 1.0;
}
else
{
rscale = 1.0 + dot;
lscale = 1.0 - dot;
}
 
// add in distance effect
scale = (1.0 - dist) * rscale;
ch->rightvol = (int) (ch->master_vol * scale);
if (ch->rightvol < 0)
ch->rightvol = 0;
 
scale = (1.0 - dist) * lscale;
ch->leftvol = (int) (ch->master_vol * scale);
if (ch->leftvol < 0)
ch->leftvol = 0;
}
 
 
// =======================================================================
// Start a sound effect
// =======================================================================
 
void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation)
{
channel_t *target_chan, *check;
sfxcache_t *sc;
int vol;
int ch_idx;
int skip;
 
if (!sound_started)
return;
 
if (!sfx)
return;
 
if (nosound.value)
return;
 
vol = fvol*255;
 
// pick a channel to play on
target_chan = SND_PickChannel(entnum, entchannel);
if (!target_chan)
return;
// spatialize
memset (target_chan, 0, sizeof(*target_chan));
VectorCopy(origin, target_chan->origin);
target_chan->dist_mult = attenuation / sound_nominal_clip_dist;
target_chan->master_vol = vol;
target_chan->entnum = entnum;
target_chan->entchannel = entchannel;
SND_Spatialize(target_chan);
 
if (!target_chan->leftvol && !target_chan->rightvol)
return; // not audible at all
 
// new channel
sc = S_LoadSound (sfx);
if (!sc)
{
target_chan->sfx = NULL;
return; // couldn't load the sound's data
}
 
target_chan->sfx = sfx;
target_chan->pos = 0.0;
target_chan->end = paintedtime + sc->length;
 
// if an identical sound has also been started this frame, offset the pos
// a bit to keep it from just making the first one louder
check = &channels[NUM_AMBIENTS];
for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++, check++)
{
if (check == target_chan)
continue;
if (check->sfx == sfx && !check->pos)
{
skip = rand () % (int)(0.1*shm->speed);
if (skip >= target_chan->end)
skip = target_chan->end - 1;
target_chan->pos += skip;
target_chan->end -= skip;
break;
}
}
}
 
void S_StopSound(int entnum, int entchannel)
{
int i;
 
for (i=0 ; i<MAX_DYNAMIC_CHANNELS ; i++)
{
if (channels[i].entnum == entnum
&& channels[i].entchannel == entchannel)
{
channels[i].end = 0;
channels[i].sfx = NULL;
return;
}
}
}
 
void S_StopAllSounds(qboolean clear)
{
int i;
 
if (!sound_started)
return;
 
total_channels = MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS; // no statics
 
for (i=0 ; i<MAX_CHANNELS ; i++)
if (channels[i].sfx)
channels[i].sfx = NULL;
 
Q_memset(channels, 0, MAX_CHANNELS * sizeof(channel_t));
 
if (clear)
S_ClearBuffer ();
}
 
void S_StopAllSoundsC (void)
{
S_StopAllSounds (true);
}
 
void S_ClearBuffer (void)
{
int clear;
#ifdef _WIN32
if (!sound_started || !shm || (!shm->buffer && !pDSBuf))
#else
if (!sound_started || !shm || !shm->buffer)
#endif
return;
 
if (shm->samplebits == 8)
clear = 0x80;
else
clear = 0;
 
#ifdef _WIN32
if (pDSBuf)
{
DWORD dwSize;
DWORD *pData;
int reps;
HRESULT hresult;
 
reps = 0;
 
while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pData, &dwSize, NULL, NULL, 0)) != DS_OK)
{
if (hresult != DSERR_BUFFERLOST)
{
Con_Printf ("S_ClearBuffer: DS::Lock Sound Buffer Failed\n");
S_Shutdown ();
return;
}
 
if (++reps > 10000)
{
Con_Printf ("S_ClearBuffer: DS: couldn't restore buffer\n");
S_Shutdown ();
return;
}
}
 
Q_memset(pData, clear, shm->samples * shm->samplebits/8);
 
pDSBuf->lpVtbl->Unlock(pDSBuf, pData, dwSize, NULL, 0);
}
else
#endif
{
Q_memset(shm->buffer, clear, shm->samples * shm->samplebits/8);
}
}
 
 
/*
=================
S_StaticSound
=================
*/
void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation)
{
channel_t *ss;
sfxcache_t *sc;
 
if (!sfx)
return;
 
if (total_channels == MAX_CHANNELS)
{
Con_Printf ("total_channels == MAX_CHANNELS\n");
return;
}
 
ss = &channels[total_channels];
total_channels++;
 
sc = S_LoadSound (sfx);
if (!sc)
return;
 
if (sc->loopstart == -1)
{
Con_Printf ("Sound %s not looped\n", sfx->name);
return;
}
ss->sfx = sfx;
VectorCopy (origin, ss->origin);
ss->master_vol = vol;
ss->dist_mult = (attenuation/64) / sound_nominal_clip_dist;
ss->end = paintedtime + sc->length;
SND_Spatialize (ss);
}
 
 
//=============================================================================
 
/*
===================
S_UpdateAmbientSounds
===================
*/
void S_UpdateAmbientSounds (void)
{
mleaf_t *l;
float vol;
int ambient_channel;
channel_t *chan;
 
if (!snd_ambient)
return;
 
// calc ambient sound levels
if (!cl.worldmodel)
return;
 
l = Mod_PointInLeaf (listener_origin, cl.worldmodel);
if (!l || !ambient_level.value)
{
for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++)
channels[ambient_channel].sfx = NULL;
return;
}
 
for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++)
{
chan = &channels[ambient_channel];
chan->sfx = ambient_sfx[ambient_channel];
vol = ambient_level.value * l->ambient_sound_level[ambient_channel];
if (vol < 8)
vol = 0;
 
// don't adjust volume too fast
if (chan->master_vol < vol)
{
chan->master_vol += host_frametime * ambient_fade.value;
if (chan->master_vol > vol)
chan->master_vol = vol;
}
else if (chan->master_vol > vol)
{
chan->master_vol -= host_frametime * ambient_fade.value;
if (chan->master_vol < vol)
chan->master_vol = vol;
}
chan->leftvol = chan->rightvol = chan->master_vol;
}
}
 
 
/*
============
S_Update
 
Called once each time through the main loop
============
*/
void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
{
int i, j;
int total;
channel_t *ch;
channel_t *combine;
 
if (!sound_started || (snd_blocked > 0))
return;
 
VectorCopy(origin, listener_origin);
VectorCopy(forward, listener_forward);
VectorCopy(right, listener_right);
VectorCopy(up, listener_up);
// update general area ambient sound sources
S_UpdateAmbientSounds ();
 
combine = NULL;
 
// update spatialization for static and dynamic sounds
ch = channels+NUM_AMBIENTS;
for (i=NUM_AMBIENTS ; i<total_channels; i++, ch++)
{
if (!ch->sfx)
continue;
SND_Spatialize(ch); // respatialize channel
if (!ch->leftvol && !ch->rightvol)
continue;
 
// try to combine static sounds with a previous channel of the same
// sound effect so we don't mix five torches every frame
if (i >= MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS)
{
// see if it can just use the last one
if (combine && combine->sfx == ch->sfx)
{
combine->leftvol += ch->leftvol;
combine->rightvol += ch->rightvol;
ch->leftvol = ch->rightvol = 0;
continue;
}
// search for one
combine = channels+MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS;
for (j=MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS ; j<i; j++, combine++)
if (combine->sfx == ch->sfx)
break;
if (j == total_channels)
{
combine = NULL;
}
else
{
if (combine != ch)
{
combine->leftvol += ch->leftvol;
combine->rightvol += ch->rightvol;
ch->leftvol = ch->rightvol = 0;
}
continue;
}
}
}
 
//
// debugging output
//
if (snd_show.value)
{
total = 0;
ch = channels;
for (i=0 ; i<total_channels; i++, ch++)
if (ch->sfx && (ch->leftvol || ch->rightvol) )
{
//Con_Printf ("%3i %3i %s\n", ch->leftvol, ch->rightvol, ch->sfx->name);
total++;
}
Con_Printf ("----(%i)----\n", total);
}
 
// mix some sound
S_Update_();
}
 
void GetSoundtime(void)
{
int samplepos;
static int buffers;
static int oldsamplepos;
int fullsamples;
fullsamples = shm->samples / shm->channels;
 
// it is possible to miscount buffers if it has wrapped twice between
// calls to S_Update. Oh well.
#ifdef __sun__
soundtime = SNDDMA_GetSamples();
#else
samplepos = SNDDMA_GetDMAPos();
 
 
if (samplepos < oldsamplepos)
{
buffers++; // buffer wrapped
if (paintedtime > 0x40000000)
{ // time to chop things off to avoid 32 bit limits
buffers = 0;
paintedtime = fullsamples;
S_StopAllSounds (true);
}
}
oldsamplepos = samplepos;
 
soundtime = buffers*fullsamples + samplepos/shm->channels;
#endif
}
 
void S_ExtraUpdate (void)
{
 
#ifdef _WIN32
IN_Accumulate ();
#endif
 
if (snd_noextraupdate.value)
return; // don't pollute timings
S_Update_();
}
 
void S_Update_(void)
{
#ifndef SDL
 
unsigned endtime;
int samps;
if (!sound_started || (snd_blocked > 0))
return;
 
// Updates DMA time
GetSoundtime();
 
// check to make sure that we haven't overshot
if (paintedtime < soundtime)
{
//Con_Printf ("S_Update_ : overflow\n");
paintedtime = soundtime;
}
 
// mix ahead of current position
endtime = soundtime + _snd_mixahead.value * shm->speed;
samps = shm->samples >> (shm->channels-1);
if (endtime - soundtime > samps)
endtime = soundtime + samps;
 
#ifdef _WIN32
// if the buffer was lost or stopped, restore it and/or restart it
{
DWORD dwStatus;
 
if (pDSBuf)
{
if (pDSBuf->lpVtbl->GetStatus (pDSBuf, &dwStatus) != DD_OK)
Con_Printf ("Couldn't get sound buffer status\n");
if (dwStatus & DSBSTATUS_BUFFERLOST)
pDSBuf->lpVtbl->Restore (pDSBuf);
if (!(dwStatus & DSBSTATUS_PLAYING))
pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);
}
}
#endif
 
S_PaintChannels (endtime);
 
SNDDMA_Submit ();
#endif /* ! SDL */
}
 
/*
===============================================================================
 
console functions
 
===============================================================================
*/
 
void S_Play(void)
{
static int hash=345;
int i;
char name[256];
sfx_t *sfx;
i = 1;
while (i<Cmd_Argc())
{
if (!Q_strrchr(Cmd_Argv(i), '.'))
{
Q_strcpy(name, Cmd_Argv(i));
Q_strcat(name, ".wav");
}
else
Q_strcpy(name, Cmd_Argv(i));
sfx = S_PrecacheSound(name);
S_StartSound(hash++, 0, sfx, listener_origin, 1.0, 1.0);
i++;
}
}
 
void S_PlayVol(void)
{
static int hash=543;
int i;
float vol;
char name[256];
sfx_t *sfx;
i = 1;
while (i<Cmd_Argc())
{
if (!Q_strrchr(Cmd_Argv(i), '.'))
{
Q_strcpy(name, Cmd_Argv(i));
Q_strcat(name, ".wav");
}
else
Q_strcpy(name, Cmd_Argv(i));
sfx = S_PrecacheSound(name);
vol = Q_atof(Cmd_Argv(i+1));
S_StartSound(hash++, 0, sfx, listener_origin, vol, 1.0);
i+=2;
}
}
 
void S_SoundList(void)
{
int i;
sfx_t *sfx;
sfxcache_t *sc;
int size, total;
 
total = 0;
for (sfx=known_sfx, i=0 ; i<num_sfx ; i++, sfx++)
{
sc = Cache_Check (&sfx->cache);
if (!sc)
continue;
size = sc->length*sc->width*(sc->stereo+1);
total += size;
if (sc->loopstart >= 0)
Con_Printf ("L");
else
Con_Printf (" ");
Con_Printf("(%2db) %6i : %s\n",sc->width*8, size, sfx->name);
}
Con_Printf ("Total resident: %i\n", total);
}
 
 
void S_LocalSound (char *sound)
{
sfx_t *sfx;
 
if (nosound.value)
return;
if (!sound_started)
return;
sfx = S_PrecacheSound (sound);
if (!sfx)
{
Con_Printf ("S_LocalSound: can't cache %s\n", sound);
return;
}
S_StartSound (cl.viewentity, -1, sfx, vec3_origin, 1, 1);
}
 
 
void S_ClearPrecache (void)
{
}
 
 
void S_BeginPrecaching (void)
{
}
 
 
void S_EndPrecaching (void)
{
}
 
/contrib/other/sdlquake-1.0.9/snd_dos.c
0,0 → 1,653
/*
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 "dosisms.h"
 
int BLASTER_GetDMAPos(void);
 
/*
===============================================================================
GUS SUPPORT
 
===============================================================================
*/
 
qboolean GUS_Init (void);
int GUS_GetDMAPos (void);
void GUS_Shutdown (void);
 
 
/*
===============================================================================
 
BLASTER SUPPORT
 
===============================================================================
*/
 
short *dma_buffer=0;
static int dma_size;
static int dma;
 
static int dsp_port;
static int irq;
static int low_dma;
static int high_dma;
static int mixer_port;
static int mpu401_port;
 
int dsp_version;
int dsp_minor_version;
 
int timeconstant=-1;
 
 
void PrintBits (byte b)
{
int i;
char str[9];
for (i=0 ; i<8 ; i++)
str[i] = '0' + ((b & (1<<(7-i))) > 0);
str[8] = 0;
Con_Printf ("%s (%i)", str, b);
}
 
void SB_Info_f(void)
{
Con_Printf ("BLASTER=%s\n", getenv("BLASTER"));
Con_Printf("dsp version=%d.%d\n", dsp_version, dsp_minor_version);
Con_Printf("dma=%d\n", dma);
if (timeconstant != -1)
Con_Printf("timeconstant=%d\n", timeconstant);
Con_Printf("dma position:%i\n", BLASTER_GetDMAPos ());
}
 
// =======================================================================
// Interprets BLASTER variable
// =======================================================================
 
int GetBLASTER(void)
{
char *BLASTER;
char *param;
 
BLASTER = getenv("BLASTER");
if (!BLASTER)
return 0;
 
param = strchr(BLASTER, 'A');
if (!param)
param = strchr(BLASTER, 'a');
if (!param)
return 0;
sscanf(param+1, "%x", &dsp_port);
 
param = strchr(BLASTER, 'I');
if (!param)
param = strchr(BLASTER, 'i');
if (!param)
return 0;
sscanf(param+1, "%d", &irq);
 
param = strchr(BLASTER, 'D');
if (!param)
param = strchr(BLASTER, 'd');
if (!param)
return 0;
sscanf(param+1, "%d", &low_dma);
 
param = strchr(BLASTER, 'H');
if (!param)
param = strchr(BLASTER, 'h');
if (param)
sscanf(param+1, "%d", &high_dma);
 
param = strchr(BLASTER, 'M');
if (!param)
param = strchr(BLASTER, 'm');
if (param)
sscanf(param+1, "%x", &mixer_port);
else
mixer_port = dsp_port;
 
param = strchr(BLASTER, 'P');
if (!param)
param = strchr(BLASTER, 'p');
if (param)
sscanf(param+1, "%x", &mpu401_port);
 
return 1;
 
}
 
// ==================================================================
// Resets DSP. Returns 0 on success.
// ==================================================================
 
int ResetDSP(void)
{
volatile int i;
 
dos_outportb(dsp_port + 6, 1);
for (i=65536 ; i ; i--) ;
dos_outportb(dsp_port + 6, 0);
for (i=65536 ; i ; i--)
{
if (!(dos_inportb(dsp_port + 0xe) & 0x80)) continue;
if (dos_inportb(dsp_port + 0xa) == 0xaa) break;
}
if (i) return 0;
else return 1;
 
}
 
int ReadDSP(void)
{
while (!(dos_inportb(dsp_port+0xe)&0x80)) ;
return dos_inportb(dsp_port+0xa);
}
 
void WriteDSP(int val)
{
while ((dos_inportb(dsp_port+0xc)&0x80)) ;
dos_outportb(dsp_port+0xc, val);
}
 
int ReadMixer(int addr)
{
dos_outportb(mixer_port+4, addr);
return dos_inportb(mixer_port+5);
}
 
void WriteMixer(int addr, int val)
{
dos_outportb(mixer_port+4, addr);
dos_outportb(mixer_port+5, val);
}
 
int oldmixervalue;
 
/*
================
StartSB
 
================
*/
void StartSB(void)
{
int i;
 
// version 4.xx startup code
if (dsp_version >= 4)
{
Con_Printf("Version 4 SB startup\n");
WriteDSP(0xd1); // turn on speaker
 
WriteDSP(0x41);
 
WriteDSP(shm->speed>>8);
WriteDSP(shm->speed&0xff);
 
WriteDSP(0xb6); // 16-bit output
WriteDSP(0x30); // stereo
WriteDSP((shm->samples-1) & 0xff); // # of samples - 1
WriteDSP((shm->samples-1) >> 8);
}
// version 3.xx startup code
else if (dsp_version == 3)
{
Con_Printf("Version 3 SB startup\n");
WriteDSP(0xd1); // turn on speaker
 
oldmixervalue = ReadMixer (0xe);
WriteMixer (0xe, oldmixervalue | 0x2);// turn on stereo
 
WriteDSP(0x14); // send one byte
WriteDSP(0x0);
WriteDSP(0x0);
 
for (i=0 ; i<0x10000 ; i++)
dos_inportb(dsp_port+0xe); // ack the dsp
timeconstant = 65536-(256000000/(shm->channels*shm->speed));
WriteDSP(0x40);
WriteDSP(timeconstant>>8);
 
WriteMixer (0xe, ReadMixer(0xe) | 0x20);// turn off filter
 
WriteDSP(0x48);
WriteDSP((shm->samples-1) & 0xff); // # of samples - 1
WriteDSP((shm->samples-1) >> 8);
 
WriteDSP(0x90); // high speed 8 bit stereo
}
// normal speed mono
else
{
Con_Printf("Version 2 SB startup\n");
WriteDSP(0xd1); // turn on speaker
 
timeconstant = 65536-(256000000/(shm->channels*shm->speed));
WriteDSP(0x40);
WriteDSP(timeconstant>>8);
 
WriteDSP(0x48);
WriteDSP((shm->samples-1) & 0xff); // # of samples - 1
WriteDSP((shm->samples-1) >> 8);
 
WriteDSP(0x1c); // normal speed 8 bit mono
}
}
 
static int page_reg[] = { 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a };
static int addr_reg[] = { 0, 2, 4, 6, 0xc0, 0xc4, 0xc8, 0xcc };
static int count_reg[] = { 1, 3, 5, 7, 0xc2, 0xc6, 0xca, 0xce };
 
static int mode_reg;
static int flipflop_reg;
static int disable_reg;
static int clear_reg;
 
/*
================
StartDMA
 
================
*/
void StartDMA(void)
{
int mode;
int realaddr;
 
realaddr = ptr2real(dma_buffer);
 
// use a high dma channel if specified
if (high_dma && dsp_version >= 4) // 8 bit snd can never use 16 bit dma
dma = high_dma;
else
dma = low_dma;
 
Con_Printf ("Using DMA channel %i\n", dma);
 
if (dma > 3)
{
mode_reg = 0xd6;
flipflop_reg = 0xd8;
disable_reg = 0xd4;
clear_reg = 0xdc;
}
else
{
mode_reg = 0xb;
flipflop_reg = 0xc;
disable_reg = 0xa;
clear_reg = 0xe;
}
 
dos_outportb(disable_reg, dma|4); // disable channel
// set mode- see "undocumented pc", p.876
mode = (1<<6) // single-cycle
+(0<<5) // address increment
+(1<<4) // auto-init dma
+(2<<2) // read
+(dma&3); // channel #
dos_outportb(mode_reg, mode);
// set address
// set page
dos_outportb(page_reg[dma], realaddr >> 16);
 
if (dma > 3)
{ // address is in words
dos_outportb(flipflop_reg, 0); // prepare to send 16-bit value
dos_outportb(addr_reg[dma], (realaddr>>1) & 0xff);
dos_outportb(addr_reg[dma], (realaddr>>9) & 0xff);
 
dos_outportb(flipflop_reg, 0); // prepare to send 16-bit value
dos_outportb(count_reg[dma], ((dma_size>>1)-1) & 0xff);
dos_outportb(count_reg[dma], ((dma_size>>1)-1) >> 8);
}
else
{ // address is in bytes
dos_outportb(flipflop_reg, 0); // prepare to send 16-bit value
dos_outportb(addr_reg[dma], realaddr & 0xff);
dos_outportb(addr_reg[dma], (realaddr>>8) & 0xff);
 
dos_outportb(flipflop_reg, 0); // prepare to send 16-bit value
dos_outportb(count_reg[dma], (dma_size-1) & 0xff);
dos_outportb(count_reg[dma], (dma_size-1) >> 8);
}
 
dos_outportb(clear_reg, 0); // clear write mask
dos_outportb(disable_reg, dma&~4);
}
 
 
/*
==================
BLASTER_Init
 
Returns false if nothing is found.
==================
*/
qboolean BLASTER_Init(void)
{
int size;
int realaddr;
int rc;
int p;
shm = 0;
rc = 0;
 
//
// must have a blaster variable set
//
if (!GetBLASTER())
{
Con_NotifyBox (
"The BLASTER environment variable\n"
"is not set, sound effects are\n"
"disabled. See README.TXT for help.\n"
);
return 0;
}
 
if (ResetDSP())
{
Con_Printf("Could not reset SB");
return 0;
}
 
//
// get dsp version
//
WriteDSP(0xe1);
dsp_version = ReadDSP();
dsp_minor_version = ReadDSP();
 
// we need at least v2 for auto-init dma
if (dsp_version < 2)
{
Con_Printf ("Sound blaster must be at least v2.0\n");
return 0;
}
 
// allow command line parm to set quality down
p = COM_CheckParm ("-dsp");
if (p && p < com_argc - 1)
{
p = Q_atoi (com_argv[p+1]);
if (p < 2 || p > 4)
Con_Printf ("-dsp parameter can only be 2, 3, or 4\n");
else if (p > dsp_version)
Con_Printf ("Can't -dsp %i on v%i hardware\n", p, dsp_version);
else
dsp_version = p;
}
 
 
// everyone does 11khz sampling rate unless told otherwise
shm = &sn;
shm->speed = 11025;
rc = COM_CheckParm("-sspeed");
if (rc)
shm->speed = Q_atoi(com_argv[rc+1]);
 
// version 4 cards (sb 16) do 16 bit stereo
if (dsp_version >= 4)
{
shm->channels = 2;
shm->samplebits = 16;
}
// version 3 cards (sb pro) do 8 bit stereo
else if (dsp_version == 3)
{
shm->channels = 2;
shm->samplebits = 8;
}
// v2 cards do 8 bit mono
else
{
shm->channels = 1;
shm->samplebits = 8;
}
 
Cmd_AddCommand("sbinfo", SB_Info_f);
size = 4096;
 
// allocate 8k and get a 4k-aligned buffer from it
dma_buffer = dos_getmemory(size*2);
if (!dma_buffer)
{
Con_Printf("Couldn't allocate sound dma buffer");
return false;
}
 
realaddr = ptr2real(dma_buffer);
realaddr = (realaddr + size) & ~(size-1);
dma_buffer = (short *) real2ptr(realaddr);
dma_size = size;
 
memset(dma_buffer, 0, dma_size);
 
shm->soundalive = true;
shm->splitbuffer = false;
 
shm->samples = size/(shm->samplebits/8);
shm->samplepos = 0;
shm->submission_chunk = 1;
shm->buffer = (unsigned char *) dma_buffer;
shm->samples = size/(shm->samplebits/8);
 
StartDMA();
StartSB();
 
return true;
}
 
 
/*
==============
BLASTER_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 BLASTER_GetDMAPos(void)
{
int count;
 
// this function is called often. acknowledge the transfer completions
// all the time so that it loops
if (dsp_version >= 4)
dos_inportb(dsp_port+0xf); // 16 bit audio
else
dos_inportb(dsp_port+0xe); // 8 bit audio
 
// clear 16-bit reg flip-flop
// load the current dma count register
if (dma < 4)
{
dos_outportb(0xc, 0);
count = dos_inportb(dma*2+1);
count += dos_inportb(dma*2+1) << 8;
if (shm->samplebits == 16)
count /= 2;
count = shm->samples - (count+1);
}
else
{
dos_outportb(0xd8, 0);
count = dos_inportb(0xc0+(dma-4)*4+2);
count += dos_inportb(0xc0+(dma-4)*4+2) << 8;
if (shm->samplebits == 8)
count *= 2;
count = shm->samples - (count+1);
}
 
// Con_Printf("DMA pos = 0x%x\n", count);
 
shm->samplepos = count & (shm->samples-1);
return shm->samplepos;
 
}
 
/*
==============
BLASTER_Shutdown
 
Reset the sound device for exiting
===============
*/
void BLASTER_Shutdown(void)
{
if (dsp_version >= 4)
{
}
else if (dsp_version == 3)
{
ResetDSP (); // stop high speed mode
WriteMixer (0xe, oldmixervalue); // turn stereo off and filter on
}
else
{
}
WriteDSP(0xd3); // turn off speaker
ResetDSP ();
 
dos_outportb(disable_reg, dma|4); // disable dma channel
}
 
 
 
/*
===============================================================================
 
INTERFACE
 
===============================================================================
*/
 
typedef enum
{
dma_none,
dma_blaster,
dma_gus
} dmacard_t;
 
dmacard_t dmacard;
 
/*
==================
SNDDM_Init
 
Try to find a sound device to mix for.
Returns false if nothing is found.
Returns true and fills in the "shm" structure with information for the mixer.
==================
*/
qboolean SNDDMA_Init(void)
{
if (GUS_Init ())
{
dmacard = dma_gus;
return true;
}
if (BLASTER_Init ())
{
dmacard = dma_blaster;
return true;
}
dmacard = dma_none;
return false;
}
 
 
/*
==============
SNDDMA_GetDMAPos
 
return the current sample position (in mono samples, not stereo)
inside the recirculating dma buffer, so the mixing code will know
how many sample are required to fill it up.
===============
*/
int SNDDMA_GetDMAPos(void)
{
switch (dmacard)
{
case dma_blaster:
return BLASTER_GetDMAPos ();
case dma_gus:
return GUS_GetDMAPos ();
case dma_none:
break;
}
return 0;
}
 
/*
==============
SNDDMA_Shutdown
 
Reset the sound device for exiting
===============
*/
void SNDDMA_Shutdown(void)
{
switch (dmacard)
{
case dma_blaster:
BLASTER_Shutdown ();
break;
case dma_gus:
GUS_Shutdown ();
break;
case dma_none:
break;
}
 
dmacard = dma_none;
return;
}
 
/*
==============
SNDDMA_Submit
 
Send sound to device if buffer isn't really the dma buffer
===============
*/
void SNDDMA_Submit(void)
{
}
 
/contrib/other/sdlquake-1.0.9/snd_gus.c
0,0 → 1,1293
/*
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.
 
*/
//=============================================================================
// Routines for GUS support in QUAKE
//
// Author(s): Jayeson Lee-Steere
//=============================================================================
 
#include "quakedef.h"
#include "dosisms.h"
 
//=============================================================================
// Author(s): Jayeson Lee-Steere
 
#define INI_STRING_SIZE 0x100
 
FILE *ini_fopen(const char *filename, const char *modes);
int ini_fclose(FILE *f);
void ini_fgets(FILE *f, const char *section, const char *field, char *s);
 
// Routines for reading from .INI files
// The read routines are fairly efficient.
//
// Author(s): Jayeson Lee-Steere
 
#define MAX_SECTION_WIDTH 20
#define MAX_FIELD_WIDTH 20
 
#define NUM_SECTION_BUFFERS 10
#define NUM_FIELD_BUFFERS 20
 
struct section_buffer
{
long offset;
char name[MAX_SECTION_WIDTH+1];
};
 
struct field_buffer
{
long offset;
int section;
char name[MAX_FIELD_WIDTH+1];
};
 
static FILE *current_file=NULL;
static int current_section;
 
static int current_section_buffer=0;
static int current_field_buffer=0;
 
static struct section_buffer section_buffers[NUM_SECTION_BUFFERS];
static struct field_buffer field_buffers[NUM_FIELD_BUFFERS];
//***************************************************************************
// Internal routines
//***************************************************************************
static char toupper(char c)
{
if (c>='a' && c<='z')
c-=('a'-'A');
return(c);
}
 
static void reset_buffer(FILE *f)
{
int i;
 
for (i=0;i<NUM_SECTION_BUFFERS;i++)
section_buffers[i].name[0]=0;
for (i=0;i<NUM_FIELD_BUFFERS;i++)
field_buffers[i].name[0]=0;
 
current_file=f;
}
 
// Sees if the current string is section "name" (i.e. ["name"]).
// If "name"=="*", sees if the current string is any section
// (i.e. [....]). Returns 1 if true else 0 if false.
static int is_section(char *s,const char *name)
{
int wild=0;
 
// See if wild search
if (strcmp("*",name)==0)
wild=1;
 
// Skip leading spaces
while (s[0]==' ')
s++;
// Look for leading "["
if (s[0]!='[')
return(0);
s++;
// Make sure name matches
while (s[0]!=']' && s[0]!=13 && s[0]!=10 && s[0]!=0 && name[0]!=0)
{
if (!wild)
if (toupper(s[0])!=toupper(name[0]))
return(0);
s++;
if (!wild)
name++;
}
if (!wild)
if (name[0]!=0)
return(0);
// Skip trailing spaces
while (s[0]==' ')
s++;
// Make sure we have trailing "]"
if (s[0]!=']')
return(0);
return(1);
}
 
// Sees if the current string is field "name" (i.e. "name"=...).
// If "name"=="*", sees if the current string is any field
// (i.e. ...=...). Returns 1 if true else 0 if false.
static int is_field(char *s,const char *name)
{
int wild=0;
 
// See if wild search
if (strcmp("*",name)==0)
wild=1;
 
// Skip leading spaces
while (s[0]==' ')
s++;
 
// Make sure name matches
while (s[0]!='=' && s[0]!=13 && s[0]!=10 && s[0]!=0 && name[0]!=0)
{
if (!wild)
if (toupper(s[0])!=toupper(name[0]))
return(0);
s++;
if (!wild)
name++;
}
if (!wild)
if (name[0]!=0)
return(0);
// Skip trailing spaces
while (s[0]==' ')
s++;
// Make sure we have an "="
if (s[0]!='=')
return(0);
 
return(1);
}
 
// Extracts the section name from a section heading
// e.g. in="[hey man]" gives out="hey man"
static void get_section_name(char *out, char *in)
{
int i=0;
 
// Skip spaces before '['
while (in[0]==' ')
in++;
// Make sure there is a '['
if (in[0]!='[')
{
out[0]=0;
return;
}
// Skip past '['
in++;
// Copy string if any to output string.
while (in[0]!=']' && in[0]!=13 && in[0]!=10 && in[0]!=0)
{
if (i<MAX_SECTION_WIDTH)
{
out[i]=in[0];
i++;
}
in++;
}
// Make sure string was terminated with ']'
if (in[0]!=']')
{
out[0]=0;
return;
}
// Remove trailing spaces
while (i>0 && out[i-1]==' ')
i--;
// Null terminate the output string.
out[i]=0;
}
 
// Extracts the field name from a field line
// e.g. in="sooty=life be in it" gives out="sooty"
static void get_field_name(char *out, char *in)
{
int i=0;
 
// Skip leading spaces
while (in[0]==' ')
in++;
// Copy name to output string
while (in[0]!='=' && in[0]!=13 && in[0]!=10 && in[0]!=0)
{
if (i<MAX_FIELD_WIDTH)
{
out[i]=in[0];
i++;
}
in++;
}
// Make sure we stopped on "="
if (in[0]!='=')
{
out[0]=0;
return;
}
// Remove trailing spaces
while (i>0 && out[i-1]==' ')
i--;
// Null terminate the output string.
out[i]=0;
}
 
// Returns the field data from string s.
// e.g. in="wally = golly man" gives out="golly man"
static void get_field_string(char *out, char *in)
{
int i=0;
 
// Find '=' if it exists
while (in[0]!='=' && in[0]!=13 && in[0]!=10 && in[0]!=0)
in++;
// If there is an '=', skip past it.
if (in[0]=='=')
in++;
// Skip any spaces between the '=' and string.
while (in[0]==' ' || in[0]=='[')
in++;
// Copy string, if there is one, to the output string.
while (in[0]!=13 && in[0]!=10 && in[0]!=0 && i<(INI_STRING_SIZE-1))
{
out[i]=in[0];
in++;
i++;
}
// Null terminate the output string.
out[i]=0;
}
 
// Adds a section to the buffer
static int add_section(char *instring, long offset)
{
int i;
char section[MAX_SECTION_WIDTH+1];
 
// Extract section name
get_section_name(section,instring);
// See if section already exists.
for (i=0;i<NUM_SECTION_BUFFERS;i++)
if (stricmp(section,section_buffers[i].name)==0)
return(i);
// Increment current_section_buffer
current_section_buffer++;
if (current_section_buffer>NUM_SECTION_BUFFERS)
current_section_buffer=0;
// Delete any field buffers that correspond to this section
for (i=0;i<NUM_FIELD_BUFFERS;i++)
if (field_buffers[i].section==current_section_buffer)
field_buffers[i].name[0]=0;
// Set buffer information
strcpy(section_buffers[current_section_buffer].name,section);
section_buffers[current_section_buffer].offset=offset;
return(current_section_buffer);
}
 
// Adds a field to the buffer
static void add_field(char *instring, int section, long offset)
{
int i;
char field[MAX_FIELD_WIDTH+1];
 
// Extract field name
get_field_name(field,instring);
// See if field already exists
for (i=0;i<NUM_FIELD_BUFFERS;i++)
if (field_buffers[i].section==section)
if (stricmp(field_buffers[i].name,field)==0)
return;
// Increment current_field_buffer
current_field_buffer++;
if (current_field_buffer>NUM_FIELD_BUFFERS)
current_field_buffer=0;
// Set buffer information
strcpy(field_buffers[current_field_buffer].name,field);
field_buffers[current_field_buffer].section=section;
field_buffers[current_field_buffer].offset=offset;
}
 
// Identical to fgets except the string is trucated at the first ';',
// carriage return or line feed.
static char *stripped_fgets(char *s, int n, FILE *f)
{
int i=0;
 
if (fgets(s,n,f)==NULL)
return(NULL);
 
while (s[i]!=';' && s[i]!=13 && s[i]!=10 && s[i]!=0)
i++;
s[i]=0;
 
return(s);
}
 
//***************************************************************************
// Externally accessable routines
//***************************************************************************
// Opens an .INI file. Works like fopen
FILE *ini_fopen(const char *filename, const char *modes)
{
return(fopen(filename,modes));
}
 
// Closes a .INI file. Works like fclose
int ini_fclose(FILE *f)
{
if (f==current_file)
reset_buffer(NULL);
return(fclose(f));
}
 
// Puts "field" from "section" from .ini file "f" into "s".
// If "section" does not exist or "field" does not exist in
// section then s="";
void ini_fgets(FILE *f, const char *section, const char *field, char *s)
{
int i;
long start_pos,string_start_pos;
char ts[INI_STRING_SIZE*2];
 
if (f!=current_file)
reset_buffer(f);
 
// Default to "Not found"
s[0]=0;
 
// See if section is in buffer
for (i=0;i<NUM_SECTION_BUFFERS;i++)
if (strnicmp(section_buffers[i].name,section,MAX_SECTION_WIDTH)==0)
break;
 
// If section is in buffer, seek to it if necessary
if (i<NUM_SECTION_BUFFERS)
{
if (i!=current_section)
{
current_section=i;
fseek(f,section_buffers[i].offset,SEEK_SET);
}
}
// else look through .ini file for it.
else
{
// Make sure we are not at eof or this will cause trouble.
if (feof(f))
rewind(f);
start_pos=ftell(f);
while (1)
{
stripped_fgets(ts,INI_STRING_SIZE*2,f);
// If it is a section, add it to the section buffer
if (is_section(ts,"*"))
current_section=add_section(ts,ftell(f));
// If it is the section we are looking for, break.
if (is_section(ts,section))
break;
// If we reach the end of the file, rewind to the start.
if (feof(f))
rewind(f);
if (ftell(f)==start_pos)
return;
}
}
 
// See if field is in buffer
for (i=0;i<NUM_FIELD_BUFFERS;i++)
if (field_buffers[i].section==current_section)
if (strnicmp(field_buffers[i].name,field,MAX_FIELD_WIDTH)==0)
break;
 
// If field is in buffer, seek to it and read it
if (i<NUM_FIELD_BUFFERS)
{
fseek(f,field_buffers[i].offset,SEEK_SET);
stripped_fgets(ts,INI_STRING_SIZE*2,f);
get_field_string(s,ts);
}
else
// else search through section for field.
{
// Make sure we do not start at eof or this will cause problems.
if (feof(f))
fseek(f,section_buffers[current_section].offset,SEEK_SET);
start_pos=ftell(f);
while (1)
{
string_start_pos=ftell(f);
stripped_fgets(ts,INI_STRING_SIZE*2,f);
// If it is a field, add it to the buffer
if (is_field(ts,"*"))
add_field(ts,current_section,string_start_pos);
// If it is the field we are looking for, save it
if (is_field(ts,field))
{
get_field_string(s,ts);
break;
}
// If we reach the end of the section, start over
if (feof(f) || is_section(ts,"*"))
fseek(f,section_buffers[current_section].offset,SEEK_SET);
if (ftell(f)==start_pos)
return;
}
}
}
 
//=============================================================================
 
#define BYTE unsigned char
#define WORD unsigned short
#define DWORD unsigned long
 
#define BUFFER_SIZE 4096
 
#define CODEC_ADC_INPUT_CONTROL_LEFT 0x00
#define CODEC_ADC_INPUT_CONTROL_RIGHT 0x01
#define CODEC_AUX1_INPUT_CONTROL_LEFT 0x02
#define CODEC_AUX1_INPUT_CONTROL_RIGHT 0x03
#define CODEC_AUX2_INPUT_CONTROL_LEFT 0x04
#define CODEC_AUX2_INPUT_CONTROL_RIGHT 0x05
#define CODEC_DAC_OUTPUT_CONTROL_LEFT 0x06
#define CODEC_DAC_OUTPUT_CONTROL_RIGHT 0x07
#define CODEC_FS_FORMAT 0x08
#define CODEC_INTERFACE_CONFIG 0x09
#define CODEC_PIN_CONTROL 0x0A
#define CODEC_ERROR_STATUS_AND_INIT 0x0B
#define CODEC_MODE_AND_ID 0x0C
#define CODEC_LOOPBACK_CONTROL 0x0D
#define CODEC_PLAYBACK_UPPER_BASE_COUNT 0x0E
#define CODEC_PLAYBACK_LOWER_BASE_COUNT 0x0F
 
#define SET_CONTROL 0x00
#define SET_FREQUENCY 0x01
#define SET_START_HIGH 0x02
#define SET_START_LOW 0x03
#define SET_END_HIGH 0x04
#define SET_END_LOW 0x05
#define SET_VOLUME_RATE 0x06
#define SET_VOLUME_START 0x07
#define SET_VOLUME_END 0x08
#define SET_CURR_VOLUME 0x09
#define SET_VOLUME 0x09
#define SET_ACC_HIGH 0x0A
#define SET_ACC_LOW 0x0B
#define SET_BALANCE 0x0C
#define SET_VOLUME_CONTROL 0x0D
#define SET_VOICES 0x0E
 
#define DMA_CONTROL 0x41
#define SET_DMA_ADDRESS 0x42
#define SET_DRAM_LOW 0x43
#define SET_DRAM_HIGH 0x44
#define ADLIB_CONTROL 0x45
#define ADLIB_TIMER1 0x46
#define ADLIB_TIMER2 0x47
#define SET_RECORD_RATE 0x48
#define RECORD_CONTROL 0x49
#define SET_JOYSTICK 0x4B
#define MASTER_RESET 0x4C
 
#define GET_CONTROL 0x80
#define GET_FREQUENCY 0x81
#define GET_START_HIGH 0x82
#define GET_START_LOW 0x83
#define GET_END_HIGH 0x84
#define GET_END_LOW 0x85
#define GET_VOLUME_RATE 0x86
#define GET_VOLUME_START 0x87
#define GET_VOLUME_END 0x88
#define GET_VOLUME 0x89
#define GET_ACC_HIGH 0x8A
#define GET_ACC_LOW 0x8B
#define GET_BALANCE 0x8C
#define GET_VOLUME_CONTROL 0x8D
#define GET_VOICES 0x8E
#define GET_IRQV 0x8F
 
struct CodecRateStruct
{
WORD Rate;
BYTE FSVal;
};
 
struct Gf1RateStruct
{
WORD Rate;
BYTE Voices;
};
 
//=============================================================================
// Reference variables in SND_DOS.C
//=============================================================================
extern short *dma_buffer;
 
//=============================================================================
// GUS-only variables
//=============================================================================
static BYTE HaveCodec=0;
 
static WORD CodecRegisterSelect;
static WORD CodecData;
static WORD CodecStatus;
static WORD Gf1TimerControl;
static WORD Gf1PageRegister;
static WORD Gf1RegisterSelect;
static WORD Gf1DataLow;
static WORD Gf1DataHigh;
 
static BYTE DmaChannel;
 
static BYTE PageRegs[] = { 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a };
static BYTE AddrRegs[] = { 0, 2, 4, 6, 0xc0, 0xc4, 0xc8, 0xcc };
static BYTE CountRegs[] = { 1, 3, 5, 7, 0xc2, 0xc6, 0xca, 0xce };
 
static WORD AddrReg;
static WORD CountReg;
static WORD ModeReg;
static WORD DisableReg;
static WORD ClearReg;
 
static struct CodecRateStruct CodecRates[]=
{
{ 5512,0x01},
{ 6620,0x0F},
{ 8000,0x00},
{ 9600,0x0E},
{11025,0x03},
{16000,0x02},
{18900,0x05},
{22050,0x07},
{27420,0x04},
{32000,0x06},
{33075,0x0D},
{37800,0x09},
{44100,0x0B},
{48000,0x0C},
{ 0,0x00} // End marker
};
 
static struct Gf1RateStruct Gf1Rates[]=
{
{19293,32},
{19916,31},
{20580,30},
{21289,29},
{22050,28},
{22866,27},
{23746,26},
{24696,25},
{25725,24},
{26843,23},
{28063,22},
{29400,21},
{30870,20},
{32494,19},
{34300,18},
{36317,17},
{38587,16},
{41160,15},
{44100,14},
{0,0}
};
 
//=============================================================================
// Basic GF1 functions
//=============================================================================
void SetGf18(BYTE reg,BYTE data)
{
dos_outportb(Gf1RegisterSelect,reg);
dos_outportb(Gf1DataHigh,data);
}
 
void SetGf116(BYTE reg,WORD data)
{
dos_outportb(Gf1RegisterSelect,reg);
dos_outportw(Gf1DataLow,data);
}
 
BYTE GetGf18(BYTE reg)
{
dos_outportb(Gf1RegisterSelect,reg);
return(dos_inportb(Gf1DataHigh));
}
 
WORD GetGf116(BYTE reg)
{
dos_outportb(Gf1RegisterSelect,reg);
return(dos_inportw(Gf1DataLow));
}
 
void Gf1Delay(void)
{
int i;
 
for (i=0;i<27;i++)
dos_inportb(Gf1TimerControl);
}
 
DWORD ConvertTo16(DWORD Address)
{
return( ((Address>>1) & 0x0001FFFF) | (Address & 0x000C0000L) );
}
 
void ClearGf1Ints(void)
{
int i;
 
SetGf18(DMA_CONTROL,0x00);
SetGf18(ADLIB_CONTROL,0x00);
SetGf18(RECORD_CONTROL,0x00);
GetGf18(DMA_CONTROL);
GetGf18(RECORD_CONTROL);
for (i=0;i<32;i++);
GetGf18(GET_IRQV);
}
 
 
//=============================================================================
// Get Interwave (UltraSound PnP) configuration if any
//=============================================================================
static qboolean GUS_GetIWData(void)
{
char *Interwave,s[INI_STRING_SIZE];
FILE *IwFile;
int CodecBase,CodecDma,i;
 
Interwave=getenv("INTERWAVE");
if (Interwave==NULL)
return(false);
 
// Open IW.INI
IwFile=ini_fopen(Interwave,"rt");
if (IwFile==NULL)
return(false);
 
// Read codec base and codec DMA
ini_fgets(IwFile,"setup 0","CodecBase",s);
sscanf(s,"%X",&CodecBase);
ini_fgets(IwFile,"setup 0","DMA2",s);
sscanf(s,"%i",&CodecDma);
 
ini_fclose(IwFile);
 
// Make sure numbers OK
if (CodecBase==0 || CodecDma==0)
return(false);
 
CodecRegisterSelect=CodecBase;
CodecData=CodecBase+1;
CodecStatus=CodecBase+2;
DmaChannel=CodecDma;
 
// Make sure there is a CODEC at the CODEC base
 
// Clear any pending IRQs
dos_inportb(CodecStatus);
dos_outportb(CodecStatus,0);
 
// Wait for 'INIT' bit to clear
for (i=0;i<0xFFFF;i++)
if ((dos_inportb(CodecRegisterSelect) & 0x80) == 0)
break;
if (i==0xFFFF)
return(false);
 
// Get chip revision - can not be zero
dos_outportb(CodecRegisterSelect,CODEC_MODE_AND_ID);
if ((dos_inportb(CodecRegisterSelect) & 0x7F) != CODEC_MODE_AND_ID)
return(false);
if ((dos_inportb(CodecData) & 0x0F) == 0)
return(false);
 
HaveCodec=1;
Con_Printf("Sound Card is UltraSound PnP\n");
return(true);
}
 
//=============================================================================
// Get UltraSound MAX configuration if any
//=============================================================================
static qboolean GUS_GetMAXData(void)
{
char *Ultrasnd,*Ultra16;
int i;
int GusBase,Dma1,Dma2,Irq1,Irq2;
int CodecBase,CodecDma,CodecIrq,CodecType;
BYTE MaxVal;
 
Ultrasnd=getenv("ULTRASND");
Ultra16=getenv("ULTRA16");
if (Ultrasnd==NULL || Ultra16==NULL)
return(false);
 
sscanf(Ultrasnd,"%x,%i,%i,%i,%i",&GusBase,&Dma1,&Dma2,&Irq1,&Irq2);
sscanf(Ultra16,"%x,%i,%i,%i",&CodecBase,&CodecDma,&CodecIrq,&CodecType);
 
if (CodecType==0 && CodecDma!=0)
DmaChannel=CodecDma & 0x07;
else
DmaChannel=Dma2 & 0x07;
 
// Make sure there is a GUS at GUS base
dos_outportb(GusBase+0x08,0x55);
if (dos_inportb(GusBase+0x0A)!=0x55)
return(false);
dos_outportb(GusBase+0x08,0xAA);
if (dos_inportb(GusBase+0x0A)!=0xAA)
return(false);
 
// Program CODEC control register
MaxVal=((CodecBase & 0xF0)>>4) | 0x40;
if (Dma1 > 3)
MaxVal|=0x10;
if (Dma2 > 3)
MaxVal|=0x20;
dos_outportb(GusBase+0x106,MaxVal);
 
CodecRegisterSelect=CodecBase;
CodecData=CodecBase+1;
CodecStatus=CodecBase+2;
 
// Make sure there is a CODEC at the CODEC base
 
// Clear any pending IRQs
dos_inportb(CodecStatus);
dos_outportb(CodecStatus,0);
 
// Wait for 'INIT' bit to clear
for (i=0;i<0xFFFF;i++)
if ((dos_inportb(CodecRegisterSelect) & 0x80) == 0)
break;
if (i==0xFFFF)
return(false);
 
// Get chip revision - can not be zero
dos_outportb(CodecRegisterSelect,CODEC_MODE_AND_ID);
if ((dos_inportb(CodecRegisterSelect) & 0x7F) != CODEC_MODE_AND_ID)
return(false);
if ((dos_inportb(CodecData) & 0x0F) == 0)
return(false);
 
HaveCodec=1;
Con_Printf("Sound Card is UltraSound MAX\n");
return(true);
}
 
//=============================================================================
// Get regular UltraSound configuration if any
//=============================================================================
static qboolean GUS_GetGUSData(void)
{
char *Ultrasnd;
int GusBase,Dma1,Dma2,Irq1,Irq2,i;
 
Ultrasnd=getenv("ULTRASND");
if (Ultrasnd==NULL)
return(false);
 
sscanf(Ultrasnd,"%x,%i,%i,%i,%i",&GusBase,&Dma1,&Dma2,&Irq1,&Irq2);
 
DmaChannel=Dma1 & 0x07;
 
// Make sure there is a GUS at GUS base
dos_outportb(GusBase+0x08,0x55);
if (dos_inportb(GusBase+0x0A)!=0x55)
return(false);
dos_outportb(GusBase+0x08,0xAA);
if (dos_inportb(GusBase+0x0A)!=0xAA)
return(false);
 
Gf1TimerControl = GusBase+0x008;
Gf1PageRegister = GusBase+0x102;
Gf1RegisterSelect = GusBase+0x103;
Gf1DataLow = GusBase+0x104;
Gf1DataHigh = GusBase+0x105;
 
// Reset the GUS
SetGf18(MASTER_RESET,0x00);
Gf1Delay();
Gf1Delay();
SetGf18(MASTER_RESET,0x01);
Gf1Delay();
Gf1Delay();
 
// Set to max (32) voices
SetGf18(SET_VOICES,0xDF);
 
// Clear any pending IRQ's
ClearGf1Ints();
 
// Set all registers to known values
for (i=0;i<32;i++)
{
dos_outportb(Gf1PageRegister,i);
SetGf18(SET_CONTROL,0x03);
SetGf18(SET_VOLUME_CONTROL,0x03);
Gf1Delay();
SetGf18(SET_CONTROL,0x03);
SetGf18(SET_VOLUME_CONTROL,0x03);
SetGf116(SET_START_HIGH,0);
SetGf116(SET_START_LOW,0);
SetGf116(SET_END_HIGH,0);
SetGf116(SET_END_LOW,0);
SetGf116(SET_ACC_HIGH,0);
SetGf116(SET_ACC_LOW,0);
SetGf18(SET_VOLUME_RATE,63);
SetGf18(SET_VOLUME_START,5);
SetGf18(SET_VOLUME_END,251);
SetGf116(SET_VOLUME,5<<8);
}
 
// Clear any pending IRQ's
ClearGf1Ints();
 
// Enable DAC etc.
SetGf18(MASTER_RESET,0x07);
 
// Enable line output so we can hear something
dos_outportb(GusBase,0x08);
 
HaveCodec=0;
Con_Printf("Sound Card is UltraSound\n");
return(true);
}
 
 
//=============================================================================
// Programs the DMA controller to start DMAing in Auto-init mode
//=============================================================================
static void GUS_StartDMA(BYTE DmaChannel,short *dma_buffer,int count)
{
int mode;
int RealAddr;
 
RealAddr = ptr2real(dma_buffer);
 
if (DmaChannel <= 3)
{
ModeReg = 0x0B;
DisableReg = 0x0A;
ClearReg = 0x0E;
}
else
{
ModeReg = 0xD6;
DisableReg = 0xD4;
ClearReg = 0xDC;
}
CountReg=CountRegs[DmaChannel];
AddrReg=AddrRegs[DmaChannel];
 
dos_outportb(DisableReg, DmaChannel | 4); // disable channel
 
// set mode- see "undocumented pc", p.876
mode = (1<<6) // single-cycle
+(0<<5) // address increment
+(1<<4) // auto-init dma
+(2<<2) // read
+(DmaChannel & 0x03); // channel #
dos_outportb(ModeReg, mode);
 
// set page
dos_outportb(PageRegs[DmaChannel], RealAddr >> 16);
 
if (DmaChannel <= 3)
{ // address is in bytes
dos_outportb(0x0C, 0); // prepare to send 16-bit value
dos_outportb(AddrReg, RealAddr & 0xff);
dos_outportb(AddrReg, (RealAddr>>8) & 0xff);
 
dos_outportb(0x0C, 0); // prepare to send 16-bit value
dos_outportb(CountReg, (count-1) & 0xff);
dos_outportb(CountReg, (count-1) >> 8);
}
else
{ // address is in words
dos_outportb(0xD8, 0); // prepare to send 16-bit value
dos_outportb(AddrReg, (RealAddr>>1) & 0xff);
dos_outportb(AddrReg, (RealAddr>>9) & 0xff);
 
dos_outportb(0xD8, 0); // prepare to send 16-bit value
dos_outportb(CountReg, ((count>>1)-1) & 0xff);
dos_outportb(CountReg, ((count>>1)-1) >> 8);
}
 
dos_outportb(ClearReg, 0); // clear write mask
dos_outportb(DisableReg, DmaChannel & ~4);
}
 
//=============================================================================
// Starts the CODEC playing
//=============================================================================
static void GUS_StartCODEC(int count,BYTE FSVal)
{
int i,j;
 
// Clear any pending IRQs
dos_inportb(CodecStatus);
dos_outportb(CodecStatus,0);
 
// Set mode to 2
dos_outportb(CodecRegisterSelect,CODEC_MODE_AND_ID);
dos_outportb(CodecData,0xC0);
 
// Stop any playback or capture which may be happening
dos_outportb(CodecRegisterSelect,CODEC_INTERFACE_CONFIG);
dos_outportb(CodecData,dos_inportb(CodecData) & 0xFC);
 
// Set FS
dos_outportb(CodecRegisterSelect,CODEC_FS_FORMAT | 0x40);
dos_outportb(CodecData,FSVal | 0x50); // Or in stereo and 16 bit bits
 
// Wait a bit
for (i=0;i<10;i++)
dos_inportb(CodecData);
 
// Routine 1 to counter CODEC bug - wait for init bit to clear and then a
// bit longer (i=min loop count, j=timeout
for (i=0,j=0;i<1000 && j<0x7FFFF;j++)
if ((dos_inportb(CodecRegisterSelect) & 0x80)==0)
i++;
 
// Routine 2 to counter CODEC bug - this is from Forte's code. For me it
// does not seem to cure the problem, but is added security
// Waits till we can modify index register
for (j=0;j<0x7FFFF;j++)
{
dos_outportb(CodecRegisterSelect,CODEC_INTERFACE_CONFIG | 0x40);
if (dos_inportb(CodecRegisterSelect)==(CODEC_INTERFACE_CONFIG | 0x40))
break;
}
 
// Perform ACAL
dos_outportb(CodecRegisterSelect,CODEC_INTERFACE_CONFIG | 0x40);
dos_outportb(CodecData,0x08);
 
// Clear MCE bit - this makes ACAL happen
dos_outportb(CodecRegisterSelect,CODEC_INTERFACE_CONFIG);
 
// Wait for ACAL to finish
for (j=0;j<0x7FFFF;j++)
{
if ((dos_inportb(CodecRegisterSelect) & 0x80) != 0)
continue;
dos_outportb(CodecRegisterSelect,CODEC_ERROR_STATUS_AND_INIT);
if ((dos_inportb(CodecData) & 0x20) == 0)
break;
}
 
// Clear ACAL bit
dos_outportb(CodecRegisterSelect,CODEC_INTERFACE_CONFIG | 0x40);
dos_outportb(CodecData,0x00);
dos_outportb(CodecRegisterSelect,CODEC_INTERFACE_CONFIG);
 
// Set some other junk
dos_outportb(CodecRegisterSelect,CODEC_LOOPBACK_CONTROL);
dos_outportb(CodecData,0x00);
dos_outportb(CodecRegisterSelect,CODEC_PIN_CONTROL);
dos_outportb(CodecData,0x08); // IRQ is disabled in PIN control
 
// Set count (it doesn't really matter what value we stuff in here
dos_outportb(CodecRegisterSelect,CODEC_PLAYBACK_LOWER_BASE_COUNT);
dos_outportb(CodecData,count & 0xFF);
dos_outportb(CodecRegisterSelect,CODEC_PLAYBACK_UPPER_BASE_COUNT);
dos_outportb(CodecData,count >> 8);
 
// Start playback
dos_outportb(CodecRegisterSelect,CODEC_INTERFACE_CONFIG);
dos_outportb(CodecData,0x01);
}
 
//=============================================================================
// Starts the GF1 playing
//=============================================================================
static void GUS_StartGf1(int count,BYTE Voices)
{
DWORD StartAddressL,EndAddressL,StartAddressR,EndAddressR;
 
// Set number of voices to give us the sampling rate we want
SetGf18(SET_VOICES,0xC0 | (Voices-1));
 
// Figure out addresses
StartAddressL=ConvertTo16(0);
EndAddressL=ConvertTo16(count-2-2);
StartAddressR=ConvertTo16(2);
EndAddressR=ConvertTo16(count-2);
 
// Set left voice addresses
dos_outportb(Gf1PageRegister,0);
SetGf116(SET_START_LOW,StartAddressL<<9);
SetGf116(SET_START_HIGH,StartAddressL>>7);
SetGf116(SET_ACC_LOW,StartAddressL<<9);
SetGf116(SET_ACC_HIGH,StartAddressL>>7);
SetGf116(SET_END_LOW,EndAddressL<<9);
SetGf116(SET_END_HIGH,EndAddressL>>7);
// Set balance to full left
SetGf18(SET_BALANCE,0);
// Set volume to full
SetGf116(SET_VOLUME,0xFFF0);
// Set FC to 2 (so we play every second sample)
SetGf116(SET_FREQUENCY,0x0800);
 
// Set right voice addresses
dos_outportb(Gf1PageRegister,1);
SetGf116(SET_START_LOW,StartAddressR<<9);
SetGf116(SET_START_HIGH,StartAddressR>>7);
SetGf116(SET_ACC_LOW,StartAddressR<<9);
SetGf116(SET_ACC_HIGH,StartAddressR>>7);
SetGf116(SET_END_LOW,EndAddressR<<9);
SetGf116(SET_END_HIGH,EndAddressR>>7);
// Set balance to full right
SetGf18(SET_BALANCE,15);
// Set volume to full
SetGf116(SET_VOLUME,0xFFF0);
// Set FC to 2 (so we play every second sample)
SetGf116(SET_FREQUENCY,0x0800);
 
// Start voices
dos_outportb(Gf1PageRegister,0);
SetGf18(SET_CONTROL,0x0C);
dos_outportb(Gf1PageRegister,1);
SetGf18(SET_CONTROL,0x0C);
Gf1Delay();
dos_outportb(Gf1PageRegister,0);
SetGf18(SET_CONTROL,0x0C);
dos_outportb(Gf1PageRegister,1);
SetGf18(SET_CONTROL,0x0C);
}
 
 
//=============================================================================
// Figures out what kind of UltraSound we have, if any, and starts it playing
//=============================================================================
qboolean GUS_Init(void)
{
int rc;
int RealAddr;
BYTE FSVal,Voices;
struct CodecRateStruct *CodecRate;
struct Gf1RateStruct *Gf1Rate;
 
// See what kind of UltraSound we have, if any
if (GUS_GetIWData()==false)
if (GUS_GetMAXData()==false)
if (GUS_GetGUSData()==false)
return(false);
 
shm = &sn;
 
if (HaveCodec)
{
// do 11khz sampling rate unless command line parameter wants different
shm->speed = 11025;
FSVal = 0x03;
rc = COM_CheckParm("-sspeed");
if (rc)
{
shm->speed = Q_atoi(com_argv[rc+1]);
// Make sure rate not too high
if (shm->speed>48000)
shm->speed=48000;
// Adjust speed to match one of the possible CODEC rates
for (CodecRate=CodecRates;CodecRate->Rate!=0;CodecRate++)
{
if (shm->speed <= CodecRate->Rate)
{
shm->speed=CodecRate->Rate;
FSVal=CodecRate->FSVal;
break;
}
}
}
 
// Always do 16 bit stereo
shm->channels = 2;
shm->samplebits = 16;
// allocate buffer twice the size we need so we can get aligned buffer
dma_buffer = dos_getmemory(BUFFER_SIZE*2);
if (dma_buffer==NULL)
{
Con_Printf("Couldn't allocate sound dma buffer");
return false;
}
 
RealAddr = ptr2real(dma_buffer);
RealAddr = (RealAddr + BUFFER_SIZE) & ~(BUFFER_SIZE-1);
dma_buffer = (short *) real2ptr(RealAddr);
 
// Zero off DMA buffer
memset(dma_buffer, 0, BUFFER_SIZE);
 
shm->soundalive = true;
shm->splitbuffer = false;
 
shm->samplepos = 0;
shm->submission_chunk = 1;
shm->buffer = (unsigned char *) dma_buffer;
shm->samples = BUFFER_SIZE/(shm->samplebits/8);
 
GUS_StartDMA(DmaChannel,dma_buffer,BUFFER_SIZE);
GUS_StartCODEC(BUFFER_SIZE,FSVal);
}
else
{
// do 19khz sampling rate unless command line parameter wants different
shm->speed = 19293;
Voices=32;
rc = COM_CheckParm("-sspeed");
if (rc)
{
shm->speed = Q_atoi(com_argv[rc+1]);
 
// Make sure rate not too high
if (shm->speed>44100)
shm->speed=44100;
 
// Adjust speed to match one of the possible GF1 rates
for (Gf1Rate=Gf1Rates;Gf1Rate->Rate!=0;Gf1Rate++)
{
if (shm->speed <= Gf1Rate->Rate)
{
shm->speed=Gf1Rate->Rate;
Voices=Gf1Rate->Voices;
break;
}
}
}
 
// Always do 16 bit stereo
shm->channels = 2;
shm->samplebits = 16;
 
// allocate buffer twice the size we need so we can get aligned buffer
dma_buffer = dos_getmemory(BUFFER_SIZE*2);
if (dma_buffer==NULL)
{
Con_Printf("Couldn't allocate sound dma buffer");
return false;
}
 
RealAddr = ptr2real(dma_buffer);
RealAddr = (RealAddr + BUFFER_SIZE) & ~(BUFFER_SIZE-1);
dma_buffer = (short *) real2ptr(RealAddr);
 
// Zero off DMA buffer
memset(dma_buffer, 0, BUFFER_SIZE);
 
shm->soundalive = true;
shm->splitbuffer = false;
 
shm->samplepos = 0;
shm->submission_chunk = 1;
shm->buffer = (unsigned char *) dma_buffer;
shm->samples = BUFFER_SIZE/(shm->samplebits/8);
 
GUS_StartDMA(DmaChannel,dma_buffer,BUFFER_SIZE);
SetGf116(SET_DMA_ADDRESS,0x0000);
if (DmaChannel<=3)
SetGf18(DMA_CONTROL,0x41);
else
SetGf18(DMA_CONTROL,0x45);
GUS_StartGf1(BUFFER_SIZE,Voices);
}
return(true);
}
 
//=============================================================================
// Returns the current playback position
//=============================================================================
int GUS_GetDMAPos(void)
{
int count;
 
if (HaveCodec)
{
// clear 16-bit reg flip-flop
// load the current dma count register
if (DmaChannel < 4)
{
dos_outportb(0x0C, 0);
count = dos_inportb(CountReg);
count += dos_inportb(CountReg) << 8;
if (shm->samplebits == 16)
count /= 2;
count = shm->samples - (count+1);
}
else
{
dos_outportb(0xD8, 0);
count = dos_inportb(CountReg);
count += dos_inportb(CountReg) << 8;
if (shm->samplebits == 8)
count *= 2;
count = shm->samples - (count+1);
}
 
}
else
{
// Read current position from GF1
dos_outportb(Gf1PageRegister,0);
count=(GetGf116(GET_ACC_HIGH)<<7) & 0xFFFF;
// See which half of buffer we are in. Note that since this is 16 bit
// data we are playing, position is in 16 bit samples
if (GetGf18(DMA_CONTROL) & 0x40)
{
GUS_StartDMA(DmaChannel,dma_buffer,BUFFER_SIZE);
SetGf116(SET_DMA_ADDRESS,0x0000);
if (DmaChannel<=3)
SetGf18(DMA_CONTROL,0x41);
else
SetGf18(DMA_CONTROL,0x45);
}
}
 
shm->samplepos = count & (shm->samples-1);
return(shm->samplepos);
}
 
//=============================================================================
// Stops the UltraSound playback
//=============================================================================
void GUS_Shutdown (void)
{
if (HaveCodec)
{
// Stop CODEC
dos_outportb(CodecRegisterSelect,CODEC_INTERFACE_CONFIG);
dos_outportb(CodecData,0x01);
}
else
{
// Stop Voices
dos_outportb(Gf1PageRegister,0);
SetGf18(SET_CONTROL,0x03);
dos_outportb(Gf1PageRegister,1);
SetGf18(SET_CONTROL,0x03);
Gf1Delay();
dos_outportb(Gf1PageRegister,0);
SetGf18(SET_CONTROL,0x03);
dos_outportb(Gf1PageRegister,1);
SetGf18(SET_CONTROL,0x03);
 
// Stop any DMA
SetGf18(DMA_CONTROL,0x00);
GetGf18(DMA_CONTROL);
}
 
dos_outportb(DisableReg, DmaChannel | 4); // disable dma channel
}
/contrib/other/sdlquake-1.0.9/snd_linux.c
0,0 → 1,269
/*
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 <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <linux/soundcard.h>
#include <stdio.h>
#include "quakedef.h"
 
int audio_fd;
int snd_inited;
 
static int tryrates[] = { 11025, 22051, 44100, 8000 };
 
qboolean SNDDMA_Init(void)
{
 
int rc;
int fmt;
int tmp;
int i;
char *s;
struct audio_buf_info info;
int caps;
 
snd_inited = 0;
 
// open /dev/dsp, confirm capability to mmap, and get size of dma buffer
 
audio_fd = open("/dev/dsp", O_RDWR);
if (audio_fd < 0)
{
perror("/dev/dsp");
Con_Printf("Could not open /dev/dsp\n");
return 0;
}
 
rc = ioctl(audio_fd, SNDCTL_DSP_RESET, 0);
if (rc < 0)
{
perror("/dev/dsp");
Con_Printf("Could not reset /dev/dsp\n");
close(audio_fd);
return 0;
}
 
if (ioctl(audio_fd, SNDCTL_DSP_GETCAPS, &caps)==-1)
{
perror("/dev/dsp");
Con_Printf("Sound driver too old\n");
close(audio_fd);
return 0;
}
 
if (!(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP))
{
Con_Printf("Sorry but your soundcard can't do this\n");
close(audio_fd);
return 0;
}
 
if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info)==-1)
{
perror("GETOSPACE");
Con_Printf("Um, can't do GETOSPACE?\n");
close(audio_fd);
return 0;
}
shm = &sn;
shm->splitbuffer = 0;
 
// set sample bits & speed
 
s = getenv("QUAKE_SOUND_SAMPLEBITS");
if (s) shm->samplebits = atoi(s);
else if ((i = COM_CheckParm("-sndbits")) != 0)
shm->samplebits = atoi(com_argv[i+1]);
if (shm->samplebits != 16 && shm->samplebits != 8)
{
ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &fmt);
if (fmt & AFMT_S16_LE) shm->samplebits = 16;
else if (fmt & AFMT_U8) shm->samplebits = 8;
}
 
s = getenv("QUAKE_SOUND_SPEED");
if (s) shm->speed = atoi(s);
else if ((i = COM_CheckParm("-sndspeed")) != 0)
shm->speed = atoi(com_argv[i+1]);
else
{
for (i=0 ; i<sizeof(tryrates)/4 ; i++)
if (!ioctl(audio_fd, SNDCTL_DSP_SPEED, &tryrates[i])) break;
shm->speed = tryrates[i];
}
 
s = getenv("QUAKE_SOUND_CHANNELS");
if (s) shm->channels = atoi(s);
else if ((i = COM_CheckParm("-sndmono")) != 0)
shm->channels = 1;
else if ((i = COM_CheckParm("-sndstereo")) != 0)
shm->channels = 2;
else shm->channels = 2;
 
shm->samples = info.fragstotal * info.fragsize / (shm->samplebits/8);
shm->submission_chunk = 1;
 
// memory map the dma buffer
 
shm->buffer = (unsigned char *) mmap(NULL, info.fragstotal
* info.fragsize, PROT_WRITE, MAP_FILE|MAP_SHARED, audio_fd, 0);
if (!shm->buffer || shm->buffer == (unsigned char *)-1)
{
perror("/dev/dsp");
Con_Printf("Could not mmap /dev/dsp\n");
close(audio_fd);
return 0;
}
 
tmp = 0;
if (shm->channels == 2)
tmp = 1;
rc = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp);
if (rc < 0)
{
perror("/dev/dsp");
Con_Printf("Could not set /dev/dsp to stereo=%d", shm->channels);
close(audio_fd);
return 0;
}
if (tmp)
shm->channels = 2;
else
shm->channels = 1;
 
rc = ioctl(audio_fd, SNDCTL_DSP_SPEED, &shm->speed);
if (rc < 0)
{
perror("/dev/dsp");
Con_Printf("Could not set /dev/dsp speed to %d", shm->speed);
close(audio_fd);
return 0;
}
 
if (shm->samplebits == 16)
{
rc = AFMT_S16_LE;
rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc);
if (rc < 0)
{
perror("/dev/dsp");
Con_Printf("Could not support 16-bit data. Try 8-bit.\n");
close(audio_fd);
return 0;
}
}
else if (shm->samplebits == 8)
{
rc = AFMT_U8;
rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc);
if (rc < 0)
{
perror("/dev/dsp");
Con_Printf("Could not support 8-bit data.\n");
close(audio_fd);
return 0;
}
}
else
{
perror("/dev/dsp");
Con_Printf("%d-bit sound not supported.", shm->samplebits);
close(audio_fd);
return 0;
}
 
// toggle the trigger & start her up
 
tmp = 0;
rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
if (rc < 0)
{
perror("/dev/dsp");
Con_Printf("Could not toggle.\n");
close(audio_fd);
return 0;
}
tmp = PCM_ENABLE_OUTPUT;
rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
if (rc < 0)
{
perror("/dev/dsp");
Con_Printf("Could not toggle.\n");
close(audio_fd);
return 0;
}
 
shm->samplepos = 0;
 
snd_inited = 1;
return 1;
 
}
 
int SNDDMA_GetDMAPos(void)
{
 
struct count_info count;
 
if (!snd_inited) return 0;
 
if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &count)==-1)
{
perror("/dev/dsp");
Con_Printf("Uh, sound dead.\n");
close(audio_fd);
snd_inited = 0;
return 0;
}
// shm->samplepos = (count.bytes / (shm->samplebits / 8)) & (shm->samples-1);
// fprintf(stderr, "%d \r", count.ptr);
shm->samplepos = count.ptr / (shm->samplebits / 8);
 
return shm->samplepos;
 
}
 
void SNDDMA_Shutdown(void)
{
if (snd_inited)
{
close(audio_fd);
snd_inited = 0;
}
}
 
/*
==============
SNDDMA_Submit
 
Send sound to device if buffer isn't really the dma buffer
===============
*/
void SNDDMA_Submit(void)
{
}
 
/contrib/other/sdlquake-1.0.9/snd_mem.c
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;
}
 
/contrib/other/sdlquake-1.0.9/snd_mix.c
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;
}
 
/contrib/other/sdlquake-1.0.9/snd_mixa.S
0,0 → 1,218
/*
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_mixa.s
// x86 assembly-language sound code
//
 
#include "asm_i386.h"
#include "quakeasm.h"
 
#if id386
 
.text
 
//----------------------------------------------------------------------
// 8-bit sound-mixing code
//----------------------------------------------------------------------
 
#define ch 4+16
#define sc 8+16
#define count 12+16
 
.globl C(SND_PaintChannelFrom8)
C(SND_PaintChannelFrom8):
pushl %esi // preserve register variables
pushl %edi
pushl %ebx
pushl %ebp
 
// int data;
// short *lscale, *rscale;
// unsigned char *sfx;
// int i;
 
movl ch(%esp),%ebx
movl sc(%esp),%esi
 
// if (ch->leftvol > 255)
// ch->leftvol = 255;
// if (ch->rightvol > 255)
// ch->rightvol = 255;
movl ch_leftvol(%ebx),%eax
movl ch_rightvol(%ebx),%edx
cmpl $255,%eax
jna LLeftSet
movl $255,%eax
LLeftSet:
cmpl $255,%edx
jna LRightSet
movl $255,%edx
LRightSet:
 
// lscale = snd_scaletable[ch->leftvol >> 3];
// rscale = snd_scaletable[ch->rightvol >> 3];
// sfx = (signed char *)sc->data + ch->pos;
// ch->pos += count;
andl $0xF8,%eax
addl $(sfxc_data),%esi
andl $0xF8,%edx
movl ch_pos(%ebx),%edi
movl count(%esp),%ecx
addl %edi,%esi
shll $7,%eax
addl %ecx,%edi
shll $7,%edx
movl %edi,ch_pos(%ebx)
addl $(C(snd_scaletable)),%eax
addl $(C(snd_scaletable)),%edx
subl %ebx,%ebx
movb -1(%esi,%ecx,1),%bl
 
testl $1,%ecx
jz LMix8Loop
 
movl (%eax,%ebx,4),%edi
movl (%edx,%ebx,4),%ebp
addl C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size),%edi
addl C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size),%ebp
movl %edi,C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size)
movl %ebp,C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size)
movb -2(%esi,%ecx,1),%bl
 
decl %ecx
jz LDone
 
// for (i=0 ; i<count ; i++)
// {
LMix8Loop:
 
// data = sfx[i];
// paintbuffer[i].left += lscale[data];
// paintbuffer[i].right += rscale[data];
movl (%eax,%ebx,4),%edi
movl (%edx,%ebx,4),%ebp
addl C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size),%edi
addl C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size),%ebp
movb -2(%esi,%ecx,1),%bl
movl %edi,C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size)
movl %ebp,C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size)
 
movl (%eax,%ebx,4),%edi
movl (%edx,%ebx,4),%ebp
movb -3(%esi,%ecx,1),%bl
addl C(paintbuffer)+psp_left-psp_size*2(,%ecx,psp_size),%edi
addl C(paintbuffer)+psp_right-psp_size*2(,%ecx,psp_size),%ebp
movl %edi,C(paintbuffer)+psp_left-psp_size*2(,%ecx,psp_size)
movl %ebp,C(paintbuffer)+psp_right-psp_size*2(,%ecx,psp_size)
 
// }
subl $2,%ecx
jnz LMix8Loop
 
LDone:
popl %ebp
popl %ebx
popl %edi
popl %esi
 
ret
 
 
//----------------------------------------------------------------------
// Transfer of stereo buffer to 16-bit DMA buffer code
//----------------------------------------------------------------------
 
.globl C(Snd_WriteLinearBlastStereo16)
C(Snd_WriteLinearBlastStereo16):
pushl %esi // preserve register variables
pushl %edi
pushl %ebx
 
// int i;
// int val;
movl C(snd_linear_count),%ecx
movl C(snd_p),%ebx
movl C(snd_vol),%esi
movl C(snd_out),%edi
 
// for (i=0 ; i<snd_linear_count ; i+=2)
// {
LWLBLoopTop:
 
// 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;
movl -8(%ebx,%ecx,4),%eax
imull %esi,%eax
sarl $8,%eax
cmpl $0x7FFF,%eax
jg LClampHigh
cmpl $0xFFFF8000,%eax
jnl LClampDone
movl $0xFFFF8000,%eax
jmp LClampDone
LClampHigh:
movl $0x7FFF,%eax
LClampDone:
 
// 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;
movl -4(%ebx,%ecx,4),%edx
imull %esi,%edx
sarl $8,%edx
cmpl $0x7FFF,%edx
jg LClampHigh2
cmpl $0xFFFF8000,%edx
jnl LClampDone2
movl $0xFFFF8000,%edx
jmp LClampDone2
LClampHigh2:
movl $0x7FFF,%edx
LClampDone2:
shll $16,%edx
andl $0xFFFF,%eax
orl %eax,%edx
movl %edx,-4(%edi,%ecx,2)
 
// }
subl $2,%ecx
jnz LWLBLoopTop
 
// snd_p += snd_linear_count;
 
popl %ebx
popl %edi
popl %esi
 
ret
 
 
#endif // id386
 
/contrib/other/sdlquake-1.0.9/snd_next.c
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.
 
*/
 
#include "quakedef.h"
 
extern int desired_speed;
extern int desired_bits;
 
qboolean SNDDMA_Init(void)
{
int size;
 
size = 16384 + sizeof(dma_t);
shm = malloc (size);
memset((void*)shm, 0, size);
 
shm->buffer = (char*)shm + sizeof(dma_t);
shm->channels = 2;
shm->speed = desired_speed;
shm->samplebits = desired_bits;
shm->samples = 16384 / (desired_bits / 8);
shm->submission_chunk = 1;
 
return true;
}
 
// return the current sample position (in mono samples read)
// inside the recirculating dma buffer
int SNDDMA_GetDMAPos(void)
{
shm->samplepos = (int)(realtime*shm->speed*shm->channels) & (shm->samples-1);
return shm->samplepos;
}
 
void SNDDMA_Shutdown(void)
{
}
/contrib/other/sdlquake-1.0.9/snd_null.c
0,0 → 1,97
/*
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_null.c -- include this instead of all the other snd_* files to have
// no sound code whatsoever
 
#include "quakedef.h"
 
cvar_t bgmvolume = {"bgmvolume", "1", true};
cvar_t volume = {"volume", "0.7", true};
 
void S_Init (void)
{
}
 
void S_AmbientOff (void)
{
}
 
void S_AmbientOn (void)
{
}
 
void S_Shutdown (void)
{
}
 
void S_TouchSound (char *sample)
{
}
 
void S_ClearBuffer (void)
{
}
 
void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation)
{
}
 
void S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation)
{
}
 
void S_StopSound (int entnum, int entchannel)
{
}
 
sfx_t *S_PrecacheSound (char *sample)
{
return NULL;
}
 
void S_ClearPrecache (void)
{
}
 
void S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up)
{
}
 
void S_StopAllSounds (qboolean clear)
{
}
 
void S_BeginPrecaching (void)
{
}
 
void S_EndPrecaching (void)
{
}
 
void S_ExtraUpdate (void)
{
}
 
void S_LocalSound (char *s)
{
}
 
/contrib/other/sdlquake-1.0.9/snd_sdl.c
0,0 → 1,112
 
#include <stdio.h>
#include "SDL_audio.h"
#include "SDL_byteorder.h"
#include "quakedef.h"
 
static dma_t the_shm;
static int snd_inited;
 
extern int desired_speed;
extern int desired_bits;
 
static void paint_audio(void *unused, Uint8 *stream, int len)
{
if ( shm ) {
shm->buffer = stream;
shm->samplepos += len/(shm->samplebits/8)/2;
// Check for samplepos overflow?
S_PaintChannels (shm->samplepos);
}
}
 
qboolean SNDDMA_Init(void)
{
SDL_AudioSpec desired, obtained;
 
snd_inited = 0;
 
/* Set up the desired format */
desired.freq = desired_speed;
switch (desired_bits) {
case 8:
desired.format = AUDIO_U8;
break;
case 16:
if ( SDL_BYTEORDER == SDL_BIG_ENDIAN )
desired.format = AUDIO_S16MSB;
else
desired.format = AUDIO_S16LSB;
break;
default:
Con_Printf("Unknown number of audio bits: %d\n",
desired_bits);
return 0;
}
desired.channels = 2;
desired.samples = 512;
desired.callback = paint_audio;
 
/* Open the audio device */
if ( SDL_OpenAudio(&desired, &obtained) < 0 ) {
Con_Printf("Couldn't open SDL audio: %s\n", SDL_GetError());
return 0;
}
 
/* Make sure we can support the audio format */
switch (obtained.format) {
case AUDIO_U8:
/* Supported */
break;
case AUDIO_S16LSB:
case AUDIO_S16MSB:
if ( ((obtained.format == AUDIO_S16LSB) &&
(SDL_BYTEORDER == SDL_LIL_ENDIAN)) ||
((obtained.format == AUDIO_S16MSB) &&
(SDL_BYTEORDER == SDL_BIG_ENDIAN)) ) {
/* Supported */
break;
}
/* Unsupported, fall through */;
default:
/* Not supported -- force SDL to do our bidding */
SDL_CloseAudio();
if ( SDL_OpenAudio(&desired, NULL) < 0 ) {
Con_Printf("Couldn't open SDL audio: %s\n",
SDL_GetError());
return 0;
}
memcpy(&obtained, &desired, sizeof(desired));
break;
}
SDL_PauseAudio(0);
 
/* Fill the audio DMA information block */
shm = &the_shm;
shm->splitbuffer = 0;
shm->samplebits = (obtained.format & 0xFF);
shm->speed = obtained.freq;
shm->channels = obtained.channels;
shm->samples = obtained.samples*shm->channels;
shm->samplepos = 0;
shm->submission_chunk = 1;
shm->buffer = NULL;
 
snd_inited = 1;
return 1;
}
 
int SNDDMA_GetDMAPos(void)
{
return shm->samplepos;
}
 
void SNDDMA_Shutdown(void)
{
if (snd_inited)
{
SDL_CloseAudio();
snd_inited = 0;
}
}
 
/contrib/other/sdlquake-1.0.9/snd_sun.c
0,0 → 1,218
/*
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 <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <stdio.h>
#include <sys/audioio.h>
#include <errno.h>
#include "quakedef.h"
 
int audio_fd;
int snd_inited;
 
static int bufpos;
static int wbufp;
static audio_info_t info;
 
#define BUFFER_SIZE 8192
 
unsigned char dma_buffer[BUFFER_SIZE];
unsigned char pend_buffer[BUFFER_SIZE];
int pending;
 
static int lastwrite = 0;
 
qboolean SNDDMA_Init(void)
{
int rc;
int fmt;
int tmp;
int i;
char *s;
int caps;
 
if (snd_inited) {
printf("Sound already init'd\n");
return;
}
 
shm = &sn;
shm->splitbuffer = 0;
 
audio_fd = open("/dev/audio", O_WRONLY|O_NDELAY);
 
if (audio_fd < 0) {
if (errno == EBUSY) {
Con_Printf("Audio device is being used by another process\n");
}
perror("/dev/audio");
Con_Printf("Could not open /dev/audio\n");
return (0);
}
 
if (ioctl(audio_fd, AUDIO_GETINFO, &info) < 0) {
perror("/dev/audio");
Con_Printf("Could not communicate with audio device.\n");
close(audio_fd);
return 0;
}
 
//
// set to nonblock
//
if (fcntl(audio_fd, F_SETFL, O_NONBLOCK) < 0) {
perror("/dev/audio");
close(audio_fd);
return 0;
}
 
AUDIO_INITINFO(&info);
 
shm->speed = 11025;
 
// try 16 bit stereo
info.play.encoding = AUDIO_ENCODING_LINEAR;
info.play.sample_rate = 11025;
info.play.channels = 2;
info.play.precision = 16;
 
if (ioctl(audio_fd, AUDIO_SETINFO, &info) < 0) {
info.play.encoding = AUDIO_ENCODING_LINEAR;
info.play.sample_rate = 11025;
info.play.channels = 1;
info.play.precision = 16;
if (ioctl(audio_fd, AUDIO_SETINFO, &info) < 0) {
Con_Printf("Incapable sound hardware.\n");
close(audio_fd);
return 0;
}
Con_Printf("16 bit mono sound initialized\n");
shm->samplebits = 16;
shm->channels = 1;
} else { // 16 bit stereo
Con_Printf("16 bit stereo sound initialized\n");
shm->samplebits = 16;
shm->channels = 2;
}
 
shm->soundalive = true;
shm->samples = sizeof(dma_buffer) / (shm->samplebits/8);
shm->samplepos = 0;
shm->submission_chunk = 1;
shm->buffer = (unsigned char *)dma_buffer;
 
snd_inited = 1;
 
return 1;
}
 
int SNDDMA_GetDMAPos(void)
{
if (!snd_inited)
return (0);
 
if (ioctl(audio_fd, AUDIO_GETINFO, &info) < 0) {
perror("/dev/audio");
Con_Printf("Could not communicate with audio device.\n");
close(audio_fd);
snd_inited = 0;
return (0);
}
 
return ((info.play.samples*shm->channels) % shm->samples);
}
 
int SNDDMA_GetSamples(void)
{
if (!snd_inited)
return (0);
 
if (ioctl(audio_fd, AUDIO_GETINFO, &info) < 0) {
perror("/dev/audio");
Con_Printf("Could not communicate with audio device.\n");
close(audio_fd);
snd_inited = 0;
return (0);
}
 
return info.play.samples;
}
 
void SNDDMA_Shutdown(void)
{
if (snd_inited) {
close(audio_fd);
snd_inited = 0;
}
}
 
/*
==============
SNDDMA_Submit
 
Send sound to device if buffer isn't really the dma buffer
===============
*/
void SNDDMA_Submit(void)
{
int samps;
int bsize;
int bytes, b;
static unsigned char writebuf[1024];
unsigned char *p;
int idx;
int stop = paintedtime;
extern int soundtime;
 
if (paintedtime < wbufp)
wbufp = 0; // reset
 
bsize = shm->channels * (shm->samplebits/8);
bytes = (paintedtime - wbufp) * bsize;
 
if (!bytes)
return;
 
if (bytes > sizeof(writebuf)) {
bytes = sizeof(writebuf);
stop = wbufp + bytes/bsize;
}
 
p = writebuf;
idx = (wbufp*bsize) & (BUFFER_SIZE - 1);
 
for (b = bytes; b; b--) {
*p++ = dma_buffer[idx];
idx = (idx + 1) & (BUFFER_SIZE - 1);
}
 
wbufp = stop;
 
if (write(audio_fd, writebuf, bytes) < bytes)
printf("audio can't keep up!\n");
 
}
 
/contrib/other/sdlquake-1.0.9/snd_win.c
0,0 → 1,729
/*
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;
shm->speed = 11025;
 
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;
shm->speed = 11025;
 
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 ();
}
 
/contrib/other/sdlquake-1.0.9/sound.h
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
/contrib/other/sdlquake-1.0.9/spritegn.h
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"
 
/contrib/other/sdlquake-1.0.9/surf16.S
0,0 → 1,172
/*
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.
 
*/
//
// surf16.s
// x86 assembly-language 16 bpp surface block drawing code.
//
 
#include "asm_i386.h"
#include "quakeasm.h"
#include "asm_draw.h"
 
#if id386
 
//----------------------------------------------------------------------
// Surface block drawer
//----------------------------------------------------------------------
 
.data
 
k: .long 0
loopentry: .long 0
 
.align 4
blockjumptable16:
.long LEnter2_16
.long LEnter4_16
.long 0, LEnter8_16
.long 0, 0, 0, LEnter16_16
 
 
.text
 
.align 4
.globl C(R_Surf16Start)
C(R_Surf16Start):
 
.align 4
.globl C(R_DrawSurfaceBlock16)
C(R_DrawSurfaceBlock16):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
 
movl C(blocksize),%eax
movl C(prowdestbase),%edi
movl C(pbasesource),%esi
movl C(sourcesstep),%ebx
movl blockjumptable16-4(,%eax,2),%ecx
movl %eax,k
movl %ecx,loopentry
movl C(lightleft),%edx
movl C(lightright),%ebp
 
Lblockloop16:
 
subl %edx,%ebp
movb C(blockdivshift),%cl
sarl %cl,%ebp
jns Lp1_16
testl C(blockdivmask),%ebp
jz Lp1_16
incl %ebp
Lp1_16:
 
subl %eax,%eax
subl %ecx,%ecx // high words must be 0 in loop for addressing
 
jmp *loopentry
 
.align 4
 
#include "block16.h"
 
movl C(pbasesource),%esi
movl C(lightleft),%edx
movl C(lightright),%ebp
movl C(sourcetstep),%eax
movl C(lightrightstep),%ecx
movl C(prowdestbase),%edi
 
addl %eax,%esi
addl %ecx,%ebp
 
movl C(lightleftstep),%eax
movl C(surfrowbytes),%ecx
 
addl %eax,%edx
addl %ecx,%edi
 
movl %esi,C(pbasesource)
movl %ebp,C(lightright)
movl k,%eax
movl %edx,C(lightleft)
decl %eax
movl %edi,C(prowdestbase)
movl %eax,k
jnz Lblockloop16
 
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
 
.globl C(R_Surf16End)
C(R_Surf16End):
 
//----------------------------------------------------------------------
// Code patching routines
//----------------------------------------------------------------------
.data
 
.align 4
LPatchTable16:
.long LBPatch0-4
.long LBPatch1-4
.long LBPatch2-4
.long LBPatch3-4
.long LBPatch4-4
.long LBPatch5-4
.long LBPatch6-4
.long LBPatch7-4
.long LBPatch8-4
.long LBPatch9-4
.long LBPatch10-4
.long LBPatch11-4
.long LBPatch12-4
.long LBPatch13-4
.long LBPatch14-4
.long LBPatch15-4
 
.text
 
.align 4
.globl C(R_Surf16Patch)
C(R_Surf16Patch):
pushl %ebx
 
movl C(colormap),%eax
movl $LPatchTable16,%ebx
movl $16,%ecx
LPatchLoop16:
movl (%ebx),%edx
addl $4,%ebx
movl %eax,(%edx)
decl %ecx
jnz LPatchLoop16
 
popl %ebx
 
ret
 
 
#endif // id386
/contrib/other/sdlquake-1.0.9/surf8.S
0,0 → 1,783
/*
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.
 
*/
//
// surf8.s
// x86 assembly-language 8 bpp surface block drawing code.
//
 
#include "asm_i386.h"
#include "quakeasm.h"
#include "asm_draw.h"
 
#if id386
 
.data
 
sb_v: .long 0
 
.text
 
.align 4
.globl C(R_Surf8Start)
C(R_Surf8Start):
 
//----------------------------------------------------------------------
// Surface block drawer for mip level 0
//----------------------------------------------------------------------
 
.align 4
.globl C(R_DrawSurfaceBlock8_mip0)
C(R_DrawSurfaceBlock8_mip0):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
 
// for (v=0 ; v<numvblocks ; v++)
// {
movl C(r_lightptr),%ebx
movl C(r_numvblocks),%eax
 
movl %eax,sb_v
movl C(prowdestbase),%edi
 
movl C(pbasesource),%esi
 
Lv_loop_mip0:
 
// lightleft = lightptr[0];
// lightright = lightptr[1];
// lightdelta = (lightleft - lightright) & 0xFFFFF;
movl (%ebx),%eax // lightleft
movl 4(%ebx),%edx // lightright
 
movl %eax,%ebp
movl C(r_lightwidth),%ecx
 
movl %edx,C(lightright)
subl %edx,%ebp
 
andl $0xFFFFF,%ebp
leal (%ebx,%ecx,4),%ebx
 
// lightptr += lightwidth;
movl %ebx,C(r_lightptr)
 
// lightleftstep = (lightptr[0] - lightleft) >> blockdivshift;
// lightrightstep = (lightptr[1] - lightright) >> blockdivshift;
// lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) |
// 0xF0000000;
movl 4(%ebx),%ecx // lightptr[1]
movl (%ebx),%ebx // lightptr[0]
 
subl %eax,%ebx
subl %edx,%ecx
 
sarl $4,%ecx
orl $0xF0000000,%ebp
 
sarl $4,%ebx
movl %ecx,C(lightrightstep)
 
subl %ecx,%ebx
andl $0xFFFFF,%ebx
 
orl $0xF0000000,%ebx
subl %ecx,%ecx // high word must be 0 in loop for addressing
 
movl %ebx,C(lightdeltastep)
subl %ebx,%ebx // high word must be 0 in loop for addressing
 
Lblockloop8_mip0:
movl %ebp,C(lightdelta)
movb 14(%esi),%cl
 
sarl $4,%ebp
movb %dh,%bh
 
movb 15(%esi),%bl
addl %ebp,%edx
 
movb %dh,%ch
addl %ebp,%edx
 
movb 0x12345678(%ebx),%ah
LBPatch0:
movb 13(%esi),%bl
 
movb 0x12345678(%ecx),%al
LBPatch1:
movb 12(%esi),%cl
 
movb %dh,%bh
addl %ebp,%edx
 
rorl $16,%eax
movb %dh,%ch
 
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch2:
 
movb 11(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch3:
 
movb 10(%esi),%cl
movl %eax,12(%edi)
 
movb %dh,%bh
addl %ebp,%edx
 
movb %dh,%ch
addl %ebp,%edx
 
movb 0x12345678(%ebx),%ah
LBPatch4:
movb 9(%esi),%bl
 
movb 0x12345678(%ecx),%al
LBPatch5:
movb 8(%esi),%cl
 
movb %dh,%bh
addl %ebp,%edx
 
rorl $16,%eax
movb %dh,%ch
 
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch6:
 
movb 7(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch7:
 
movb 6(%esi),%cl
movl %eax,8(%edi)
 
movb %dh,%bh
addl %ebp,%edx
 
movb %dh,%ch
addl %ebp,%edx
 
movb 0x12345678(%ebx),%ah
LBPatch8:
movb 5(%esi),%bl
 
movb 0x12345678(%ecx),%al
LBPatch9:
movb 4(%esi),%cl
 
movb %dh,%bh
addl %ebp,%edx
 
rorl $16,%eax
movb %dh,%ch
 
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch10:
 
movb 3(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch11:
 
movb 2(%esi),%cl
movl %eax,4(%edi)
 
movb %dh,%bh
addl %ebp,%edx
 
movb %dh,%ch
addl %ebp,%edx
 
movb 0x12345678(%ebx),%ah
LBPatch12:
movb 1(%esi),%bl
 
movb 0x12345678(%ecx),%al
LBPatch13:
movb (%esi),%cl
 
movb %dh,%bh
addl %ebp,%edx
 
rorl $16,%eax
movb %dh,%ch
 
movb 0x12345678(%ebx),%ah
LBPatch14:
movl C(lightright),%edx
 
movb 0x12345678(%ecx),%al
LBPatch15:
movl C(lightdelta),%ebp
 
movl %eax,(%edi)
 
addl C(sourcetstep),%esi
addl C(surfrowbytes),%edi
 
addl C(lightrightstep),%edx
addl C(lightdeltastep),%ebp
 
movl %edx,C(lightright)
jc Lblockloop8_mip0
 
// if (pbasesource >= r_sourcemax)
// pbasesource -= stepback;
 
cmpl C(r_sourcemax),%esi
jb LSkip_mip0
subl C(r_stepback),%esi
LSkip_mip0:
 
movl C(r_lightptr),%ebx
decl sb_v
 
jnz Lv_loop_mip0
 
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
 
 
//----------------------------------------------------------------------
// Surface block drawer for mip level 1
//----------------------------------------------------------------------
 
.align 4
.globl C(R_DrawSurfaceBlock8_mip1)
C(R_DrawSurfaceBlock8_mip1):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
 
// for (v=0 ; v<numvblocks ; v++)
// {
movl C(r_lightptr),%ebx
movl C(r_numvblocks),%eax
 
movl %eax,sb_v
movl C(prowdestbase),%edi
 
movl C(pbasesource),%esi
 
Lv_loop_mip1:
 
// lightleft = lightptr[0];
// lightright = lightptr[1];
// lightdelta = (lightleft - lightright) & 0xFFFFF;
movl (%ebx),%eax // lightleft
movl 4(%ebx),%edx // lightright
 
movl %eax,%ebp
movl C(r_lightwidth),%ecx
 
movl %edx,C(lightright)
subl %edx,%ebp
 
andl $0xFFFFF,%ebp
leal (%ebx,%ecx,4),%ebx
 
// lightptr += lightwidth;
movl %ebx,C(r_lightptr)
 
// lightleftstep = (lightptr[0] - lightleft) >> blockdivshift;
// lightrightstep = (lightptr[1] - lightright) >> blockdivshift;
// lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) |
// 0xF0000000;
movl 4(%ebx),%ecx // lightptr[1]
movl (%ebx),%ebx // lightptr[0]
 
subl %eax,%ebx
subl %edx,%ecx
 
sarl $3,%ecx
orl $0x70000000,%ebp
 
sarl $3,%ebx
movl %ecx,C(lightrightstep)
 
subl %ecx,%ebx
andl $0xFFFFF,%ebx
 
orl $0xF0000000,%ebx
subl %ecx,%ecx // high word must be 0 in loop for addressing
 
movl %ebx,C(lightdeltastep)
subl %ebx,%ebx // high word must be 0 in loop for addressing
 
Lblockloop8_mip1:
movl %ebp,C(lightdelta)
movb 6(%esi),%cl
 
sarl $3,%ebp
movb %dh,%bh
 
movb 7(%esi),%bl
addl %ebp,%edx
 
movb %dh,%ch
addl %ebp,%edx
 
movb 0x12345678(%ebx),%ah
LBPatch22:
movb 5(%esi),%bl
 
movb 0x12345678(%ecx),%al
LBPatch23:
movb 4(%esi),%cl
 
movb %dh,%bh
addl %ebp,%edx
 
rorl $16,%eax
movb %dh,%ch
 
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch24:
 
movb 3(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch25:
 
movb 2(%esi),%cl
movl %eax,4(%edi)
 
movb %dh,%bh
addl %ebp,%edx
 
movb %dh,%ch
addl %ebp,%edx
 
movb 0x12345678(%ebx),%ah
LBPatch26:
movb 1(%esi),%bl
 
movb 0x12345678(%ecx),%al
LBPatch27:
movb (%esi),%cl
 
movb %dh,%bh
addl %ebp,%edx
 
rorl $16,%eax
movb %dh,%ch
 
movb 0x12345678(%ebx),%ah
LBPatch28:
movl C(lightright),%edx
 
movb 0x12345678(%ecx),%al
LBPatch29:
movl C(lightdelta),%ebp
 
movl %eax,(%edi)
movl C(sourcetstep),%eax
 
addl %eax,%esi
movl C(surfrowbytes),%eax
 
addl %eax,%edi
movl C(lightrightstep),%eax
 
addl %eax,%edx
movl C(lightdeltastep),%eax
 
addl %eax,%ebp
movl %edx,C(lightright)
 
jc Lblockloop8_mip1
 
// if (pbasesource >= r_sourcemax)
// pbasesource -= stepback;
 
cmpl C(r_sourcemax),%esi
jb LSkip_mip1
subl C(r_stepback),%esi
LSkip_mip1:
 
movl C(r_lightptr),%ebx
decl sb_v
 
jnz Lv_loop_mip1
 
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
 
 
//----------------------------------------------------------------------
// Surface block drawer for mip level 2
//----------------------------------------------------------------------
 
.align 4
.globl C(R_DrawSurfaceBlock8_mip2)
C(R_DrawSurfaceBlock8_mip2):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
 
// for (v=0 ; v<numvblocks ; v++)
// {
movl C(r_lightptr),%ebx
movl C(r_numvblocks),%eax
 
movl %eax,sb_v
movl C(prowdestbase),%edi
 
movl C(pbasesource),%esi
 
Lv_loop_mip2:
 
// lightleft = lightptr[0];
// lightright = lightptr[1];
// lightdelta = (lightleft - lightright) & 0xFFFFF;
movl (%ebx),%eax // lightleft
movl 4(%ebx),%edx // lightright
 
movl %eax,%ebp
movl C(r_lightwidth),%ecx
 
movl %edx,C(lightright)
subl %edx,%ebp
 
andl $0xFFFFF,%ebp
leal (%ebx,%ecx,4),%ebx
 
// lightptr += lightwidth;
movl %ebx,C(r_lightptr)
 
// lightleftstep = (lightptr[0] - lightleft) >> blockdivshift;
// lightrightstep = (lightptr[1] - lightright) >> blockdivshift;
// lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) |
// 0xF0000000;
movl 4(%ebx),%ecx // lightptr[1]
movl (%ebx),%ebx // lightptr[0]
 
subl %eax,%ebx
subl %edx,%ecx
 
sarl $2,%ecx
orl $0x30000000,%ebp
 
sarl $2,%ebx
movl %ecx,C(lightrightstep)
 
subl %ecx,%ebx
 
andl $0xFFFFF,%ebx
 
orl $0xF0000000,%ebx
subl %ecx,%ecx // high word must be 0 in loop for addressing
 
movl %ebx,C(lightdeltastep)
subl %ebx,%ebx // high word must be 0 in loop for addressing
 
Lblockloop8_mip2:
movl %ebp,C(lightdelta)
movb 2(%esi),%cl
 
sarl $2,%ebp
movb %dh,%bh
 
movb 3(%esi),%bl
addl %ebp,%edx
 
movb %dh,%ch
addl %ebp,%edx
 
movb 0x12345678(%ebx),%ah
LBPatch18:
movb 1(%esi),%bl
 
movb 0x12345678(%ecx),%al
LBPatch19:
movb (%esi),%cl
 
movb %dh,%bh
addl %ebp,%edx
 
rorl $16,%eax
movb %dh,%ch
 
movb 0x12345678(%ebx),%ah
LBPatch20:
movl C(lightright),%edx
 
movb 0x12345678(%ecx),%al
LBPatch21:
movl C(lightdelta),%ebp
 
movl %eax,(%edi)
movl C(sourcetstep),%eax
 
addl %eax,%esi
movl C(surfrowbytes),%eax
 
addl %eax,%edi
movl C(lightrightstep),%eax
 
addl %eax,%edx
movl C(lightdeltastep),%eax
 
addl %eax,%ebp
movl %edx,C(lightright)
 
jc Lblockloop8_mip2
 
// if (pbasesource >= r_sourcemax)
// pbasesource -= stepback;
 
cmpl C(r_sourcemax),%esi
jb LSkip_mip2
subl C(r_stepback),%esi
LSkip_mip2:
 
movl C(r_lightptr),%ebx
decl sb_v
 
jnz Lv_loop_mip2
 
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
 
 
//----------------------------------------------------------------------
// Surface block drawer for mip level 3
//----------------------------------------------------------------------
 
.align 4
.globl C(R_DrawSurfaceBlock8_mip3)
C(R_DrawSurfaceBlock8_mip3):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
 
// for (v=0 ; v<numvblocks ; v++)
// {
movl C(r_lightptr),%ebx
movl C(r_numvblocks),%eax
 
movl %eax,sb_v
movl C(prowdestbase),%edi
 
movl C(pbasesource),%esi
 
Lv_loop_mip3:
 
// lightleft = lightptr[0];
// lightright = lightptr[1];
// lightdelta = (lightleft - lightright) & 0xFFFFF;
movl (%ebx),%eax // lightleft
movl 4(%ebx),%edx // lightright
 
movl %eax,%ebp
movl C(r_lightwidth),%ecx
 
movl %edx,C(lightright)
subl %edx,%ebp
 
andl $0xFFFFF,%ebp
leal (%ebx,%ecx,4),%ebx
 
movl %ebp,C(lightdelta)
// lightptr += lightwidth;
movl %ebx,C(r_lightptr)
 
// lightleftstep = (lightptr[0] - lightleft) >> blockdivshift;
// lightrightstep = (lightptr[1] - lightright) >> blockdivshift;
// lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) |
// 0xF0000000;
movl 4(%ebx),%ecx // lightptr[1]
movl (%ebx),%ebx // lightptr[0]
 
subl %eax,%ebx
subl %edx,%ecx
 
sarl $1,%ecx
 
sarl $1,%ebx
movl %ecx,C(lightrightstep)
 
subl %ecx,%ebx
andl $0xFFFFF,%ebx
 
sarl $1,%ebp
orl $0xF0000000,%ebx
 
movl %ebx,C(lightdeltastep)
subl %ebx,%ebx // high word must be 0 in loop for addressing
 
movb 1(%esi),%bl
subl %ecx,%ecx // high word must be 0 in loop for addressing
 
movb %dh,%bh
movb (%esi),%cl
 
addl %ebp,%edx
movb %dh,%ch
 
movb 0x12345678(%ebx),%al
LBPatch16:
movl C(lightright),%edx
 
movb %al,1(%edi)
movb 0x12345678(%ecx),%al
LBPatch17:
 
movb %al,(%edi)
movl C(sourcetstep),%eax
 
addl %eax,%esi
movl C(surfrowbytes),%eax
 
addl %eax,%edi
movl C(lightdeltastep),%eax
 
movl C(lightdelta),%ebp
movb (%esi),%cl
 
addl %eax,%ebp
movl C(lightrightstep),%eax
 
sarl $1,%ebp
addl %eax,%edx
 
movb %dh,%bh
movb 1(%esi),%bl
 
addl %ebp,%edx
movb %dh,%ch
 
movb 0x12345678(%ebx),%al
LBPatch30:
movl C(sourcetstep),%edx
 
movb %al,1(%edi)
movb 0x12345678(%ecx),%al
LBPatch31:
 
movb %al,(%edi)
movl C(surfrowbytes),%ebp
 
addl %edx,%esi
addl %ebp,%edi
 
// if (pbasesource >= r_sourcemax)
// pbasesource -= stepback;
 
cmpl C(r_sourcemax),%esi
jb LSkip_mip3
subl C(r_stepback),%esi
LSkip_mip3:
 
movl C(r_lightptr),%ebx
decl sb_v
 
jnz Lv_loop_mip3
 
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
 
 
.globl C(R_Surf8End)
C(R_Surf8End):
 
//----------------------------------------------------------------------
// Code patching routines
//----------------------------------------------------------------------
.data
 
.align 4
LPatchTable8:
.long LBPatch0-4
.long LBPatch1-4
.long LBPatch2-4
.long LBPatch3-4
.long LBPatch4-4
.long LBPatch5-4
.long LBPatch6-4
.long LBPatch7-4
.long LBPatch8-4
.long LBPatch9-4
.long LBPatch10-4
.long LBPatch11-4
.long LBPatch12-4
.long LBPatch13-4
.long LBPatch14-4
.long LBPatch15-4
.long LBPatch16-4
.long LBPatch17-4
.long LBPatch18-4
.long LBPatch19-4
.long LBPatch20-4
.long LBPatch21-4
.long LBPatch22-4
.long LBPatch23-4
.long LBPatch24-4
.long LBPatch25-4
.long LBPatch26-4
.long LBPatch27-4
.long LBPatch28-4
.long LBPatch29-4
.long LBPatch30-4
.long LBPatch31-4
 
.text
 
.align 4
.globl C(R_Surf8Patch)
C(R_Surf8Patch):
pushl %ebx
 
movl C(colormap),%eax
movl $LPatchTable8,%ebx
movl $32,%ecx
LPatchLoop8:
movl (%ebx),%edx
addl $4,%ebx
movl %eax,(%edx)
decl %ecx
jnz LPatchLoop8
 
popl %ebx
 
ret
 
#endif // id386
/contrib/other/sdlquake-1.0.9/sv_main.c
0,0 → 1,1200
/*
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.
 
*/
// sv_main.c -- server main program
 
#include "quakedef.h"
 
server_t sv;
server_static_t svs;
 
char localmodels[MAX_MODELS][5]; // inline model names for precache
 
//============================================================================
 
/*
===============
SV_Init
===============
*/
void SV_Init (void)
{
int i;
extern cvar_t sv_maxvelocity;
extern cvar_t sv_gravity;
extern cvar_t sv_nostep;
extern cvar_t sv_friction;
extern cvar_t sv_edgefriction;
extern cvar_t sv_stopspeed;
extern cvar_t sv_maxspeed;
extern cvar_t sv_accelerate;
extern cvar_t sv_idealpitchscale;
extern cvar_t sv_aim;
 
Cvar_RegisterVariable (&sv_maxvelocity);
Cvar_RegisterVariable (&sv_gravity);
Cvar_RegisterVariable (&sv_friction);
Cvar_RegisterVariable (&sv_edgefriction);
Cvar_RegisterVariable (&sv_stopspeed);
Cvar_RegisterVariable (&sv_maxspeed);
Cvar_RegisterVariable (&sv_accelerate);
Cvar_RegisterVariable (&sv_idealpitchscale);
Cvar_RegisterVariable (&sv_aim);
Cvar_RegisterVariable (&sv_nostep);
 
for (i=0 ; i<MAX_MODELS ; i++)
sprintf (localmodels[i], "*%i", i);
}
 
/*
=============================================================================
 
EVENT MESSAGES
 
=============================================================================
*/
 
/*
==================
SV_StartParticle
 
Make sure the event gets sent to all clients
==================
*/
void SV_StartParticle (vec3_t org, vec3_t dir, int color, int count)
{
int i, v;
 
if (sv.datagram.cursize > MAX_DATAGRAM-16)
return;
MSG_WriteByte (&sv.datagram, svc_particle);
MSG_WriteCoord (&sv.datagram, org[0]);
MSG_WriteCoord (&sv.datagram, org[1]);
MSG_WriteCoord (&sv.datagram, org[2]);
for (i=0 ; i<3 ; i++)
{
v = dir[i]*16;
if (v > 127)
v = 127;
else if (v < -128)
v = -128;
MSG_WriteChar (&sv.datagram, v);
}
MSG_WriteByte (&sv.datagram, count);
MSG_WriteByte (&sv.datagram, color);
}
 
/*
==================
SV_StartSound
 
Each entity can have eight independant sound sources, like voice,
weapon, feet, etc.
 
Channel 0 is an auto-allocate channel, the others override anything
allready running on that entity/channel pair.
 
An attenuation of 0 will play full volume everywhere in the level.
Larger attenuations will drop off. (max 4 attenuation)
 
==================
*/
void SV_StartSound (edict_t *entity, int channel, char *sample, int volume,
float attenuation)
{
int sound_num;
int field_mask;
int i;
int ent;
if (volume < 0 || volume > 255)
Sys_Error ("SV_StartSound: volume = %i", volume);
 
if (attenuation < 0 || attenuation > 4)
Sys_Error ("SV_StartSound: attenuation = %f", attenuation);
 
if (channel < 0 || channel > 7)
Sys_Error ("SV_StartSound: channel = %i", channel);
 
if (sv.datagram.cursize > MAX_DATAGRAM-16)
return;
 
// find precache number for sound
for (sound_num=1 ; sound_num<MAX_SOUNDS
&& sv.sound_precache[sound_num] ; sound_num++)
if (!strcmp(sample, sv.sound_precache[sound_num]))
break;
if ( sound_num == MAX_SOUNDS || !sv.sound_precache[sound_num] )
{
Con_Printf ("SV_StartSound: %s not precacheed\n", sample);
return;
}
ent = NUM_FOR_EDICT(entity);
 
channel = (ent<<3) | channel;
 
field_mask = 0;
if (volume != DEFAULT_SOUND_PACKET_VOLUME)
field_mask |= SND_VOLUME;
if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
field_mask |= SND_ATTENUATION;
 
// directed messages go only to the entity the are targeted on
MSG_WriteByte (&sv.datagram, svc_sound);
MSG_WriteByte (&sv.datagram, field_mask);
if (field_mask & SND_VOLUME)
MSG_WriteByte (&sv.datagram, volume);
if (field_mask & SND_ATTENUATION)
MSG_WriteByte (&sv.datagram, attenuation*64);
MSG_WriteShort (&sv.datagram, channel);
MSG_WriteByte (&sv.datagram, sound_num);
for (i=0 ; i<3 ; i++)
MSG_WriteCoord (&sv.datagram, entity->v.origin[i]+0.5*(entity->v.mins[i]+entity->v.maxs[i]));
}
 
/*
==============================================================================
 
CLIENT SPAWNING
 
==============================================================================
*/
 
/*
================
SV_SendServerinfo
 
Sends the first message from the server to a connected client.
This will be sent on the initial connection and upon each server load.
================
*/
void SV_SendServerinfo (client_t *client)
{
char **s;
char message[2048];
 
MSG_WriteByte (&client->message, svc_print);
sprintf (message, "%c\nVERSION %4.2f SERVER (%i CRC)", 2, VERSION, pr_crc);
MSG_WriteString (&client->message,message);
 
MSG_WriteByte (&client->message, svc_serverinfo);
MSG_WriteLong (&client->message, PROTOCOL_VERSION);
MSG_WriteByte (&client->message, svs.maxclients);
 
if (!coop.value && deathmatch.value)
MSG_WriteByte (&client->message, GAME_DEATHMATCH);
else
MSG_WriteByte (&client->message, GAME_COOP);
 
sprintf (message, pr_strings+sv.edicts->v.message);
 
MSG_WriteString (&client->message,message);
 
for (s = sv.model_precache+1 ; *s ; s++)
MSG_WriteString (&client->message, *s);
MSG_WriteByte (&client->message, 0);
 
for (s = sv.sound_precache+1 ; *s ; s++)
MSG_WriteString (&client->message, *s);
MSG_WriteByte (&client->message, 0);
 
// send music
MSG_WriteByte (&client->message, svc_cdtrack);
MSG_WriteByte (&client->message, sv.edicts->v.sounds);
MSG_WriteByte (&client->message, sv.edicts->v.sounds);
 
// set view
MSG_WriteByte (&client->message, svc_setview);
MSG_WriteShort (&client->message, NUM_FOR_EDICT(client->edict));
 
MSG_WriteByte (&client->message, svc_signonnum);
MSG_WriteByte (&client->message, 1);
 
client->sendsignon = true;
client->spawned = false; // need prespawn, spawn, etc
}
 
/*
================
SV_ConnectClient
 
Initializes a client_t for a new net connection. This will only be called
once for a player each game, not once for each level change.
================
*/
void SV_ConnectClient (int clientnum)
{
edict_t *ent;
client_t *client;
int edictnum;
struct qsocket_s *netconnection;
int i;
float spawn_parms[NUM_SPAWN_PARMS];
 
client = svs.clients + clientnum;
 
Con_DPrintf ("Client %s connected\n", client->netconnection->address);
 
edictnum = clientnum+1;
 
ent = EDICT_NUM(edictnum);
// set up the client_t
netconnection = client->netconnection;
if (sv.loadgame)
memcpy (spawn_parms, client->spawn_parms, sizeof(spawn_parms));
memset (client, 0, sizeof(*client));
client->netconnection = netconnection;
 
strcpy (client->name, "unconnected");
client->active = true;
client->spawned = false;
client->edict = ent;
client->message.data = client->msgbuf;
client->message.maxsize = sizeof(client->msgbuf);
client->message.allowoverflow = true; // we can catch it
 
#ifdef IDGODS
client->privileged = IsID(&client->netconnection->addr);
#else
client->privileged = false;
#endif
 
if (sv.loadgame)
memcpy (client->spawn_parms, spawn_parms, sizeof(spawn_parms));
else
{
// call the progs to get default spawn parms for the new client
PR_ExecuteProgram (pr_global_struct->SetNewParms);
for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
client->spawn_parms[i] = (&pr_global_struct->parm1)[i];
}
 
SV_SendServerinfo (client);
}
 
 
/*
===================
SV_CheckForNewClients
 
===================
*/
void SV_CheckForNewClients (void)
{
struct qsocket_s *ret;
int i;
//
// check for new connections
//
while (1)
{
ret = NET_CheckNewConnections ();
if (!ret)
break;
 
//
// init a new client structure
//
for (i=0 ; i<svs.maxclients ; i++)
if (!svs.clients[i].active)
break;
if (i == svs.maxclients)
Sys_Error ("Host_CheckForNewClients: no free clients");
svs.clients[i].netconnection = ret;
SV_ConnectClient (i);
net_activeconnections++;
}
}
 
 
 
/*
===============================================================================
 
FRAME UPDATES
 
===============================================================================
*/
 
/*
==================
SV_ClearDatagram
 
==================
*/
void SV_ClearDatagram (void)
{
SZ_Clear (&sv.datagram);
}
 
/*
=============================================================================
 
The PVS must include a small area around the client to allow head bobbing
or other small motion on the client side. Otherwise, a bob might cause an
entity that should be visible to not show up, especially when the bob
crosses a waterline.
 
=============================================================================
*/
 
int fatbytes;
byte fatpvs[MAX_MAP_LEAFS/8];
 
void SV_AddToFatPVS (vec3_t org, mnode_t *node)
{
int i;
byte *pvs;
mplane_t *plane;
float d;
 
while (1)
{
// if this is a leaf, accumulate the pvs bits
if (node->contents < 0)
{
if (node->contents != CONTENTS_SOLID)
{
pvs = Mod_LeafPVS ( (mleaf_t *)node, sv.worldmodel);
for (i=0 ; i<fatbytes ; i++)
fatpvs[i] |= pvs[i];
}
return;
}
plane = node->plane;
d = DotProduct (org, plane->normal) - plane->dist;
if (d > 8)
node = node->children[0];
else if (d < -8)
node = node->children[1];
else
{ // go down both
SV_AddToFatPVS (org, node->children[0]);
node = node->children[1];
}
}
}
 
/*
=============
SV_FatPVS
 
Calculates a PVS that is the inclusive or of all leafs within 8 pixels of the
given point.
=============
*/
byte *SV_FatPVS (vec3_t org)
{
fatbytes = (sv.worldmodel->numleafs+31)>>3;
Q_memset (fatpvs, 0, fatbytes);
SV_AddToFatPVS (org, sv.worldmodel->nodes);
return fatpvs;
}
 
//=============================================================================
 
 
/*
=============
SV_WriteEntitiesToClient
 
=============
*/
void SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg)
{
int e, i;
int bits;
byte *pvs;
vec3_t org;
float miss;
edict_t *ent;
 
// find the client's PVS
VectorAdd (clent->v.origin, clent->v.view_ofs, org);
pvs = SV_FatPVS (org);
 
// send over all entities (excpet the client) that touch the pvs
ent = NEXT_EDICT(sv.edicts);
for (e=1 ; e<sv.num_edicts ; e++, ent = NEXT_EDICT(ent))
{
#ifdef QUAKE2
// don't send if flagged for NODRAW and there are no lighting effects
if (ent->v.effects == EF_NODRAW)
continue;
#endif
 
// ignore if not touching a PV leaf
if (ent != clent) // clent is ALLWAYS sent
{
// ignore ents without visible models
if (!ent->v.modelindex || !pr_strings[ent->v.model])
continue;
 
for (i=0 ; i < ent->num_leafs ; i++)
if (pvs[ent->leafnums[i] >> 3] & (1 << (ent->leafnums[i]&7) ))
break;
if (i == ent->num_leafs)
continue; // not visible
}
 
if (msg->maxsize - msg->cursize < 16)
{
Con_Printf ("packet overflow\n");
return;
}
 
// send an update
bits = 0;
for (i=0 ; i<3 ; i++)
{
miss = ent->v.origin[i] - ent->baseline.origin[i];
if ( miss < -0.1 || miss > 0.1 )
bits |= U_ORIGIN1<<i;
}
 
if ( ent->v.angles[0] != ent->baseline.angles[0] )
bits |= U_ANGLE1;
if ( ent->v.angles[1] != ent->baseline.angles[1] )
bits |= U_ANGLE2;
if ( ent->v.angles[2] != ent->baseline.angles[2] )
bits |= U_ANGLE3;
if (ent->v.movetype == MOVETYPE_STEP)
bits |= U_NOLERP; // don't mess up the step animation
if (ent->baseline.colormap != ent->v.colormap)
bits |= U_COLORMAP;
if (ent->baseline.skin != ent->v.skin)
bits |= U_SKIN;
if (ent->baseline.frame != ent->v.frame)
bits |= U_FRAME;
if (ent->baseline.effects != ent->v.effects)
bits |= U_EFFECTS;
if (ent->baseline.modelindex != ent->v.modelindex)
bits |= U_MODEL;
 
if (e >= 256)
bits |= U_LONGENTITY;
if (bits >= 256)
bits |= U_MOREBITS;
 
//
// write the message
//
MSG_WriteByte (msg,bits | U_SIGNAL);
if (bits & U_MOREBITS)
MSG_WriteByte (msg, bits>>8);
if (bits & U_LONGENTITY)
MSG_WriteShort (msg,e);
else
MSG_WriteByte (msg,e);
 
if (bits & U_MODEL)
MSG_WriteByte (msg, ent->v.modelindex);
if (bits & U_FRAME)
MSG_WriteByte (msg, ent->v.frame);
if (bits & U_COLORMAP)
MSG_WriteByte (msg, ent->v.colormap);
if (bits & U_SKIN)
MSG_WriteByte (msg, ent->v.skin);
if (bits & U_EFFECTS)
MSG_WriteByte (msg, ent->v.effects);
if (bits & U_ORIGIN1)
MSG_WriteCoord (msg, ent->v.origin[0]);
if (bits & U_ANGLE1)
MSG_WriteAngle(msg, ent->v.angles[0]);
if (bits & U_ORIGIN2)
MSG_WriteCoord (msg, ent->v.origin[1]);
if (bits & U_ANGLE2)
MSG_WriteAngle(msg, ent->v.angles[1]);
if (bits & U_ORIGIN3)
MSG_WriteCoord (msg, ent->v.origin[2]);
if (bits & U_ANGLE3)
MSG_WriteAngle(msg, ent->v.angles[2]);
}
}
 
/*
=============
SV_CleanupEnts
 
=============
*/
void SV_CleanupEnts (void)
{
int e;
edict_t *ent;
ent = NEXT_EDICT(sv.edicts);
for (e=1 ; e<sv.num_edicts ; e++, ent = NEXT_EDICT(ent))
{
ent->v.effects = (int)ent->v.effects & ~EF_MUZZLEFLASH;
}
 
}
 
/*
==================
SV_WriteClientdataToMessage
 
==================
*/
void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
{
int bits;
int i;
edict_t *other;
int items;
#ifndef QUAKE2
eval_t *val;
#endif
 
//
// send a damage message
//
if (ent->v.dmg_take || ent->v.dmg_save)
{
other = PROG_TO_EDICT(ent->v.dmg_inflictor);
MSG_WriteByte (msg, svc_damage);
MSG_WriteByte (msg, ent->v.dmg_save);
MSG_WriteByte (msg, ent->v.dmg_take);
for (i=0 ; i<3 ; i++)
MSG_WriteCoord (msg, other->v.origin[i] + 0.5*(other->v.mins[i] + other->v.maxs[i]));
ent->v.dmg_take = 0;
ent->v.dmg_save = 0;
}
 
//
// send the current viewpos offset from the view entity
//
SV_SetIdealPitch (); // how much to look up / down ideally
 
// a fixangle might get lost in a dropped packet. Oh well.
if ( ent->v.fixangle )
{
MSG_WriteByte (msg, svc_setangle);
for (i=0 ; i < 3 ; i++)
MSG_WriteAngle (msg, ent->v.angles[i] );
ent->v.fixangle = 0;
}
 
bits = 0;
if (ent->v.view_ofs[2] != DEFAULT_VIEWHEIGHT)
bits |= SU_VIEWHEIGHT;
if (ent->v.idealpitch)
bits |= SU_IDEALPITCH;
 
// stuff the sigil bits into the high bits of items for sbar, or else
// mix in items2
#ifdef QUAKE2
items = (int)ent->v.items | ((int)ent->v.items2 << 23);
#else
val = GetEdictFieldValue(ent, "items2");
 
if (val)
items = (int)ent->v.items | ((int)val->_float << 23);
else
items = (int)ent->v.items | ((int)pr_global_struct->serverflags << 28);
#endif
 
bits |= SU_ITEMS;
if ( (int)ent->v.flags & FL_ONGROUND)
bits |= SU_ONGROUND;
if ( ent->v.waterlevel >= 2)
bits |= SU_INWATER;
for (i=0 ; i<3 ; i++)
{
if (ent->v.punchangle[i])
bits |= (SU_PUNCH1<<i);
if (ent->v.velocity[i])
bits |= (SU_VELOCITY1<<i);
}
if (ent->v.weaponframe)
bits |= SU_WEAPONFRAME;
 
if (ent->v.armorvalue)
bits |= SU_ARMOR;
 
// if (ent->v.weapon)
bits |= SU_WEAPON;
 
// send the data
 
MSG_WriteByte (msg, svc_clientdata);
MSG_WriteShort (msg, bits);
 
if (bits & SU_VIEWHEIGHT)
MSG_WriteChar (msg, ent->v.view_ofs[2]);
 
if (bits & SU_IDEALPITCH)
MSG_WriteChar (msg, ent->v.idealpitch);
 
for (i=0 ; i<3 ; i++)
{
if (bits & (SU_PUNCH1<<i))
MSG_WriteChar (msg, ent->v.punchangle[i]);
if (bits & (SU_VELOCITY1<<i))
MSG_WriteChar (msg, ent->v.velocity[i]/16);
}
 
// [always sent] if (bits & SU_ITEMS)
MSG_WriteLong (msg, items);
 
if (bits & SU_WEAPONFRAME)
MSG_WriteByte (msg, ent->v.weaponframe);
if (bits & SU_ARMOR)
MSG_WriteByte (msg, ent->v.armorvalue);
if (bits & SU_WEAPON)
MSG_WriteByte (msg, SV_ModelIndex(pr_strings+ent->v.weaponmodel));
MSG_WriteShort (msg, ent->v.health);
MSG_WriteByte (msg, ent->v.currentammo);
MSG_WriteByte (msg, ent->v.ammo_shells);
MSG_WriteByte (msg, ent->v.ammo_nails);
MSG_WriteByte (msg, ent->v.ammo_rockets);
MSG_WriteByte (msg, ent->v.ammo_cells);
 
if (standard_quake)
{
MSG_WriteByte (msg, ent->v.weapon);
}
else
{
for(i=0;i<32;i++)
{
if ( ((int)ent->v.weapon) & (1<<i) )
{
MSG_WriteByte (msg, i);
break;
}
}
}
}
 
/*
=======================
SV_SendClientDatagram
=======================
*/
qboolean SV_SendClientDatagram (client_t *client)
{
byte buf[MAX_DATAGRAM];
sizebuf_t msg;
msg.data = buf;
msg.maxsize = sizeof(buf);
msg.cursize = 0;
 
MSG_WriteByte (&msg, svc_time);
MSG_WriteFloat (&msg, sv.time);
 
// add the client specific data to the datagram
SV_WriteClientdataToMessage (client->edict, &msg);
 
SV_WriteEntitiesToClient (client->edict, &msg);
 
// copy the server datagram if there is space
if (msg.cursize + sv.datagram.cursize < msg.maxsize)
SZ_Write (&msg, sv.datagram.data, sv.datagram.cursize);
 
// send the datagram
if (NET_SendUnreliableMessage (client->netconnection, &msg) == -1)
{
SV_DropClient (true);// if the message couldn't send, kick off
return false;
}
return true;
}
 
/*
=======================
SV_UpdateToReliableMessages
=======================
*/
void SV_UpdateToReliableMessages (void)
{
int i, j;
client_t *client;
 
// check for changes to be sent over the reliable streams
for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
{
if (host_client->old_frags != host_client->edict->v.frags)
{
for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
{
if (!client->active)
continue;
MSG_WriteByte (&client->message, svc_updatefrags);
MSG_WriteByte (&client->message, i);
MSG_WriteShort (&client->message, host_client->edict->v.frags);
}
 
host_client->old_frags = host_client->edict->v.frags;
}
}
for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
{
if (!client->active)
continue;
SZ_Write (&client->message, sv.reliable_datagram.data, sv.reliable_datagram.cursize);
}
 
SZ_Clear (&sv.reliable_datagram);
}
 
 
/*
=======================
SV_SendNop
 
Send a nop message without trashing or sending the accumulated client
message buffer
=======================
*/
void SV_SendNop (client_t *client)
{
sizebuf_t msg;
byte buf[4];
msg.data = buf;
msg.maxsize = sizeof(buf);
msg.cursize = 0;
 
MSG_WriteChar (&msg, svc_nop);
 
if (NET_SendUnreliableMessage (client->netconnection, &msg) == -1)
SV_DropClient (true); // if the message couldn't send, kick off
client->last_message = realtime;
}
 
/*
=======================
SV_SendClientMessages
=======================
*/
void SV_SendClientMessages (void)
{
int i;
// update frags, names, etc
SV_UpdateToReliableMessages ();
 
// build individual updates
for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
{
if (!host_client->active)
continue;
 
if (host_client->spawned)
{
if (!SV_SendClientDatagram (host_client))
continue;
}
else
{
// the player isn't totally in the game yet
// send small keepalive messages if too much time has passed
// send a full message when the next signon stage has been requested
// some other message data (name changes, etc) may accumulate
// between signon stages
if (!host_client->sendsignon)
{
if (realtime - host_client->last_message > 5)
SV_SendNop (host_client);
continue; // don't send out non-signon messages
}
}
 
// check for an overflowed message. Should only happen
// on a very fucked up connection that backs up a lot, then
// changes level
if (host_client->message.overflowed)
{
SV_DropClient (true);
host_client->message.overflowed = false;
continue;
}
if (host_client->message.cursize || host_client->dropasap)
{
if (!NET_CanSendMessage (host_client->netconnection))
{
// I_Printf ("can't write\n");
continue;
}
 
if (host_client->dropasap)
SV_DropClient (false); // went to another level
else
{
if (NET_SendMessage (host_client->netconnection
, &host_client->message) == -1)
SV_DropClient (true); // if the message couldn't send, kick off
SZ_Clear (&host_client->message);
host_client->last_message = realtime;
host_client->sendsignon = false;
}
}
}
// clear muzzle flashes
SV_CleanupEnts ();
}
 
 
/*
==============================================================================
 
SERVER SPAWNING
 
==============================================================================
*/
 
/*
================
SV_ModelIndex
 
================
*/
int SV_ModelIndex (char *name)
{
int i;
if (!name || !name[0])
return 0;
 
for (i=0 ; i<MAX_MODELS && sv.model_precache[i] ; i++)
if (!strcmp(sv.model_precache[i], name))
return i;
if (i==MAX_MODELS || !sv.model_precache[i])
Sys_Error ("SV_ModelIndex: model %s not precached", name);
return i;
}
 
/*
================
SV_CreateBaseline
 
================
*/
void SV_CreateBaseline (void)
{
int i;
edict_t *svent;
int entnum;
for (entnum = 0; entnum < sv.num_edicts ; entnum++)
{
// get the current server version
svent = EDICT_NUM(entnum);
if (svent->free)
continue;
if (entnum > svs.maxclients && !svent->v.modelindex)
continue;
 
//
// create entity baseline
//
VectorCopy (svent->v.origin, svent->baseline.origin);
VectorCopy (svent->v.angles, svent->baseline.angles);
svent->baseline.frame = svent->v.frame;
svent->baseline.skin = svent->v.skin;
if (entnum > 0 && entnum <= svs.maxclients)
{
svent->baseline.colormap = entnum;
svent->baseline.modelindex = SV_ModelIndex("progs/player.mdl");
}
else
{
svent->baseline.colormap = 0;
svent->baseline.modelindex =
SV_ModelIndex(pr_strings + svent->v.model);
}
//
// add to the message
//
MSG_WriteByte (&sv.signon,svc_spawnbaseline);
MSG_WriteShort (&sv.signon,entnum);
 
MSG_WriteByte (&sv.signon, svent->baseline.modelindex);
MSG_WriteByte (&sv.signon, svent->baseline.frame);
MSG_WriteByte (&sv.signon, svent->baseline.colormap);
MSG_WriteByte (&sv.signon, svent->baseline.skin);
for (i=0 ; i<3 ; i++)
{
MSG_WriteCoord(&sv.signon, svent->baseline.origin[i]);
MSG_WriteAngle(&sv.signon, svent->baseline.angles[i]);
}
}
}
 
 
/*
================
SV_SendReconnect
 
Tell all the clients that the server is changing levels
================
*/
void SV_SendReconnect (void)
{
char data[128];
sizebuf_t msg;
 
msg.data = data;
msg.cursize = 0;
msg.maxsize = sizeof(data);
 
MSG_WriteChar (&msg, svc_stufftext);
MSG_WriteString (&msg, "reconnect\n");
NET_SendToAll (&msg, 5);
if (cls.state != ca_dedicated)
#ifdef QUAKE2
Cbuf_InsertText ("reconnect\n");
#else
Cmd_ExecuteString ("reconnect\n", src_command);
#endif
}
 
 
/*
================
SV_SaveSpawnparms
 
Grabs the current state of each client for saving across the
transition to another level
================
*/
void SV_SaveSpawnparms (void)
{
int i, j;
 
svs.serverflags = pr_global_struct->serverflags;
 
for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
{
if (!host_client->active)
continue;
 
// call the progs to get default spawn parms for the new client
pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
PR_ExecuteProgram (pr_global_struct->SetChangeParms);
for (j=0 ; j<NUM_SPAWN_PARMS ; j++)
host_client->spawn_parms[j] = (&pr_global_struct->parm1)[j];
}
}
 
 
/*
================
SV_SpawnServer
 
This is called at the start of each level
================
*/
extern float scr_centertime_off;
 
#ifdef QUAKE2
void SV_SpawnServer (char *server, char *startspot)
#else
void SV_SpawnServer (char *server)
#endif
{
edict_t *ent;
int i;
 
// let's not have any servers with no name
if (hostname.string[0] == 0)
Cvar_Set ("hostname", "UNNAMED");
scr_centertime_off = 0;
 
Con_DPrintf ("SpawnServer: %s\n",server);
svs.changelevel_issued = false; // now safe to issue another
 
//
// tell all connected clients that we are going to a new level
//
if (sv.active)
{
SV_SendReconnect ();
}
 
//
// make cvars consistant
//
if (coop.value)
Cvar_SetValue ("deathmatch", 0);
current_skill = (int)(skill.value + 0.5);
if (current_skill < 0)
current_skill = 0;
if (current_skill > 3)
current_skill = 3;
 
Cvar_SetValue ("skill", (float)current_skill);
//
// set up the new server
//
Host_ClearMemory ();
 
memset (&sv, 0, sizeof(sv));
 
strcpy (sv.name, server);
#ifdef QUAKE2
if (startspot)
strcpy(sv.startspot, startspot);
#endif
 
// load progs to get entity field count
PR_LoadProgs ();
 
// allocate server memory
sv.max_edicts = MAX_EDICTS;
sv.edicts = Hunk_AllocName (sv.max_edicts*pr_edict_size, "edicts");
 
sv.datagram.maxsize = sizeof(sv.datagram_buf);
sv.datagram.cursize = 0;
sv.datagram.data = sv.datagram_buf;
sv.reliable_datagram.maxsize = sizeof(sv.reliable_datagram_buf);
sv.reliable_datagram.cursize = 0;
sv.reliable_datagram.data = sv.reliable_datagram_buf;
sv.signon.maxsize = sizeof(sv.signon_buf);
sv.signon.cursize = 0;
sv.signon.data = sv.signon_buf;
// leave slots at start for clients only
sv.num_edicts = svs.maxclients+1;
for (i=0 ; i<svs.maxclients ; i++)
{
ent = EDICT_NUM(i+1);
svs.clients[i].edict = ent;
}
sv.state = ss_loading;
sv.paused = false;
 
sv.time = 1.0;
strcpy (sv.name, server);
sprintf (sv.modelname,"maps/%s.bsp", server);
sv.worldmodel = Mod_ForName (sv.modelname, false);
if (!sv.worldmodel)
{
Con_Printf ("Couldn't spawn server %s\n", sv.modelname);
sv.active = false;
return;
}
sv.models[1] = sv.worldmodel;
//
// clear world interaction links
//
SV_ClearWorld ();
sv.sound_precache[0] = pr_strings;
 
sv.model_precache[0] = pr_strings;
sv.model_precache[1] = sv.modelname;
for (i=1 ; i<sv.worldmodel->numsubmodels ; i++)
{
sv.model_precache[1+i] = localmodels[i];
sv.models[i+1] = Mod_ForName (localmodels[i], false);
}
 
//
// load the rest of the entities
//
ent = EDICT_NUM(0);
memset (&ent->v, 0, progs->entityfields * 4);
ent->free = false;
ent->v.model = sv.worldmodel->name - pr_strings;
ent->v.modelindex = 1; // world model
ent->v.solid = SOLID_BSP;
ent->v.movetype = MOVETYPE_PUSH;
 
if (coop.value)
pr_global_struct->coop = coop.value;
else
pr_global_struct->deathmatch = deathmatch.value;
 
pr_global_struct->mapname = sv.name - pr_strings;
#ifdef QUAKE2
pr_global_struct->startspot = sv.startspot - pr_strings;
#endif
 
// serverflags are for cross level information (sigils)
pr_global_struct->serverflags = svs.serverflags;
ED_LoadFromFile (sv.worldmodel->entities);
 
sv.active = true;
 
// all setup is completed, any further precache statements are errors
sv.state = ss_active;
// run two frames to allow everything to settle
host_frametime = 0.1;
SV_Physics ();
SV_Physics ();
 
// create a baseline for more efficient communications
SV_CreateBaseline ();
 
// send serverinfo to all connected clients
for (i=0,host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
if (host_client->active)
SV_SendServerinfo (host_client);
Con_DPrintf ("Server spawned.\n");
}
 
/contrib/other/sdlquake-1.0.9/sv_move.c
0,0 → 1,427
/*
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.
 
*/
// sv_move.c -- monster movement
 
#include "quakedef.h"
 
#define STEPSIZE 18
 
/*
=============
SV_CheckBottom
 
Returns false if any part of the bottom of the entity is off an edge that
is not a staircase.
 
=============
*/
int c_yes, c_no;
 
qboolean SV_CheckBottom (edict_t *ent)
{
vec3_t mins, maxs, start, stop;
trace_t trace;
int x, y;
float mid, bottom;
VectorAdd (ent->v.origin, ent->v.mins, mins);
VectorAdd (ent->v.origin, ent->v.maxs, maxs);
 
// if all of the points under the corners are solid world, don't bother
// with the tougher checks
// the corners must be within 16 of the midpoint
start[2] = mins[2] - 1;
for (x=0 ; x<=1 ; x++)
for (y=0 ; y<=1 ; y++)
{
start[0] = x ? maxs[0] : mins[0];
start[1] = y ? maxs[1] : mins[1];
if (SV_PointContents (start) != CONTENTS_SOLID)
goto realcheck;
}
 
c_yes++;
return true; // we got out easy
 
realcheck:
c_no++;
//
// check it for real...
//
start[2] = mins[2];
// the midpoint must be within 16 of the bottom
start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
stop[2] = start[2] - 2*STEPSIZE;
trace = SV_Move (start, vec3_origin, vec3_origin, stop, true, ent);
 
if (trace.fraction == 1.0)
return false;
mid = bottom = trace.endpos[2];
// the corners must be within 16 of the midpoint
for (x=0 ; x<=1 ; x++)
for (y=0 ; y<=1 ; y++)
{
start[0] = stop[0] = x ? maxs[0] : mins[0];
start[1] = stop[1] = y ? maxs[1] : mins[1];
trace = SV_Move (start, vec3_origin, vec3_origin, stop, true, ent);
if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
bottom = trace.endpos[2];
if (trace.fraction == 1.0 || mid - trace.endpos[2] > STEPSIZE)
return false;
}
 
c_yes++;
return true;
}
 
 
/*
=============
SV_movestep
 
Called by monster program code.
The move will be adjusted for slopes and stairs, but if the move isn't
possible, no move is done, false is returned, and
pr_global_struct->trace_normal is set to the normal of the blocking wall
=============
*/
qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink)
{
float dz;
vec3_t oldorg, neworg, end;
trace_t trace;
int i;
edict_t *enemy;
 
// try the move
VectorCopy (ent->v.origin, oldorg);
VectorAdd (ent->v.origin, move, neworg);
 
// flying monsters don't step up
if ( (int)ent->v.flags & (FL_SWIM | FL_FLY) )
{
// try one move with vertical motion, then one without
for (i=0 ; i<2 ; i++)
{
VectorAdd (ent->v.origin, move, neworg);
enemy = PROG_TO_EDICT(ent->v.enemy);
if (i == 0 && enemy != sv.edicts)
{
dz = ent->v.origin[2] - PROG_TO_EDICT(ent->v.enemy)->v.origin[2];
if (dz > 40)
neworg[2] -= 8;
if (dz < 30)
neworg[2] += 8;
}
trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, neworg, false, ent);
if (trace.fraction == 1)
{
if ( ((int)ent->v.flags & FL_SWIM) && SV_PointContents(trace.endpos) == CONTENTS_EMPTY )
return false; // swim monster left water
VectorCopy (trace.endpos, ent->v.origin);
if (relink)
SV_LinkEdict (ent, true);
return true;
}
if (enemy == sv.edicts)
break;
}
return false;
}
 
// push down from a step height above the wished position
neworg[2] += STEPSIZE;
VectorCopy (neworg, end);
end[2] -= STEPSIZE*2;
 
trace = SV_Move (neworg, ent->v.mins, ent->v.maxs, end, false, ent);
 
if (trace.allsolid)
return false;
 
if (trace.startsolid)
{
neworg[2] -= STEPSIZE;
trace = SV_Move (neworg, ent->v.mins, ent->v.maxs, end, false, ent);
if (trace.allsolid || trace.startsolid)
return false;
}
if (trace.fraction == 1)
{
// if monster had the ground pulled out, go ahead and fall
if ( (int)ent->v.flags & FL_PARTIALGROUND )
{
VectorAdd (ent->v.origin, move, ent->v.origin);
if (relink)
SV_LinkEdict (ent, true);
ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
// Con_Printf ("fall down\n");
return true;
}
return false; // walked off an edge
}
 
// check point traces down for dangling corners
VectorCopy (trace.endpos, ent->v.origin);
if (!SV_CheckBottom (ent))
{
if ( (int)ent->v.flags & FL_PARTIALGROUND )
{ // entity had floor mostly pulled out from underneath it
// and is trying to correct
if (relink)
SV_LinkEdict (ent, true);
return true;
}
VectorCopy (oldorg, ent->v.origin);
return false;
}
 
if ( (int)ent->v.flags & FL_PARTIALGROUND )
{
// Con_Printf ("back on ground\n");
ent->v.flags = (int)ent->v.flags & ~FL_PARTIALGROUND;
}
ent->v.groundentity = EDICT_TO_PROG(trace.ent);
 
// the move is ok
if (relink)
SV_LinkEdict (ent, true);
return true;
}
 
 
//============================================================================
 
/*
======================
SV_StepDirection
 
Turns to the movement direction, and walks the current distance if
facing it.
 
======================
*/
void PF_changeyaw (void);
qboolean SV_StepDirection (edict_t *ent, float yaw, float dist)
{
vec3_t move, oldorigin;
float delta;
ent->v.ideal_yaw = yaw;
PF_changeyaw();
yaw = yaw*M_PI*2 / 360;
move[0] = cos(yaw)*dist;
move[1] = sin(yaw)*dist;
move[2] = 0;
 
VectorCopy (ent->v.origin, oldorigin);
if (SV_movestep (ent, move, false))
{
delta = ent->v.angles[YAW] - ent->v.ideal_yaw;
if (delta > 45 && delta < 315)
{ // not turned far enough, so don't take the step
VectorCopy (oldorigin, ent->v.origin);
}
SV_LinkEdict (ent, true);
return true;
}
SV_LinkEdict (ent, true);
return false;
}
 
/*
======================
SV_FixCheckBottom
 
======================
*/
void SV_FixCheckBottom (edict_t *ent)
{
// Con_Printf ("SV_FixCheckBottom\n");
ent->v.flags = (int)ent->v.flags | FL_PARTIALGROUND;
}
 
 
 
/*
================
SV_NewChaseDir
 
================
*/
#define DI_NODIR -1
void SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist)
{
float deltax,deltay;
float d[3];
float tdir, olddir, turnaround;
 
olddir = anglemod( (int)(actor->v.ideal_yaw/45)*45 );
turnaround = anglemod(olddir - 180);
 
deltax = enemy->v.origin[0] - actor->v.origin[0];
deltay = enemy->v.origin[1] - actor->v.origin[1];
if (deltax>10)
d[1]= 0;
else if (deltax<-10)
d[1]= 180;
else
d[1]= DI_NODIR;
if (deltay<-10)
d[2]= 270;
else if (deltay>10)
d[2]= 90;
else
d[2]= DI_NODIR;
 
// try direct route
if (d[1] != DI_NODIR && d[2] != DI_NODIR)
{
if (d[1] == 0)
tdir = d[2] == 90 ? 45 : 315;
else
tdir = d[2] == 90 ? 135 : 215;
if (tdir != turnaround && SV_StepDirection(actor, tdir, dist))
return;
}
 
// try other directions
if ( ((rand()&3) & 1) || abs(deltay)>abs(deltax))
{
tdir=d[1];
d[1]=d[2];
d[2]=tdir;
}
 
if (d[1]!=DI_NODIR && d[1]!=turnaround
&& SV_StepDirection(actor, d[1], dist))
return;
 
if (d[2]!=DI_NODIR && d[2]!=turnaround
&& SV_StepDirection(actor, d[2], dist))
return;
 
/* there is no direct path to the player, so pick another direction */
 
if (olddir!=DI_NODIR && SV_StepDirection(actor, olddir, dist))
return;
 
if (rand()&1) /*randomly determine direction of search*/
{
for (tdir=0 ; tdir<=315 ; tdir += 45)
if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) )
return;
}
else
{
for (tdir=315 ; tdir >=0 ; tdir -= 45)
if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) )
return;
}
 
if (turnaround != DI_NODIR && SV_StepDirection(actor, turnaround, dist) )
return;
 
actor->v.ideal_yaw = olddir; // can't move
 
// if a bridge was pulled out from underneath a monster, it may not have
// a valid standing position at all
 
if (!SV_CheckBottom (actor))
SV_FixCheckBottom (actor);
 
}
 
/*
======================
SV_CloseEnough
 
======================
*/
qboolean SV_CloseEnough (edict_t *ent, edict_t *goal, float dist)
{
int i;
for (i=0 ; i<3 ; i++)
{
if (goal->v.absmin[i] > ent->v.absmax[i] + dist)
return false;
if (goal->v.absmax[i] < ent->v.absmin[i] - dist)
return false;
}
return true;
}
 
/*
======================
SV_MoveToGoal
 
======================
*/
void SV_MoveToGoal (void)
{
edict_t *ent, *goal;
float dist;
#ifdef QUAKE2
edict_t *enemy;
#endif
 
ent = PROG_TO_EDICT(pr_global_struct->self);
goal = PROG_TO_EDICT(ent->v.goalentity);
dist = G_FLOAT(OFS_PARM0);
 
if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
{
G_FLOAT(OFS_RETURN) = 0;
return;
}
 
// if the next step hits the enemy, return immediately
#ifdef QUAKE2
enemy = PROG_TO_EDICT(ent->v.enemy);
if (enemy != sv.edicts && SV_CloseEnough (ent, enemy, dist) )
#else
if ( PROG_TO_EDICT(ent->v.enemy) != sv.edicts && SV_CloseEnough (ent, goal, dist) )
#endif
return;
 
// bump around...
if ( (rand()&3)==1 ||
!SV_StepDirection (ent, ent->v.ideal_yaw, dist))
{
SV_NewChaseDir (ent, goal, dist);
}
}
 
/contrib/other/sdlquake-1.0.9/sv_phys.c
0,0 → 1,1617
/*
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.
 
*/
// sv_phys.c
 
#include "quakedef.h"
 
/*
 
 
pushmove objects do not obey gravity, and do not interact with each other or trigger fields, but block normal movement and push normal objects when they move.
 
onground is set for toss objects when they come to a complete rest. it is set for steping or walking objects
 
doors, plats, etc are SOLID_BSP, and MOVETYPE_PUSH
bonus items are SOLID_TRIGGER touch, and MOVETYPE_TOSS
corpses are SOLID_NOT and MOVETYPE_TOSS
crates are SOLID_BBOX and MOVETYPE_TOSS
walking monsters are SOLID_SLIDEBOX and MOVETYPE_STEP
flying/floating monsters are SOLID_SLIDEBOX and MOVETYPE_FLY
 
solid_edge items only clip against bsp models.
 
*/
 
cvar_t sv_friction = {"sv_friction","4",false,true};
cvar_t sv_stopspeed = {"sv_stopspeed","100"};
cvar_t sv_gravity = {"sv_gravity","800",false,true};
cvar_t sv_maxvelocity = {"sv_maxvelocity","2000"};
cvar_t sv_nostep = {"sv_nostep","0"};
 
#ifdef QUAKE2
static vec3_t vec_origin = {0.0, 0.0, 0.0};
#endif
 
#define MOVE_EPSILON 0.01
 
void SV_Physics_Toss (edict_t *ent);
 
/*
================
SV_CheckAllEnts
================
*/
void SV_CheckAllEnts (void)
{
int e;
edict_t *check;
 
// see if any solid entities are inside the final position
check = NEXT_EDICT(sv.edicts);
for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
{
if (check->free)
continue;
if (check->v.movetype == MOVETYPE_PUSH
|| check->v.movetype == MOVETYPE_NONE
#ifdef QUAKE2
|| check->v.movetype == MOVETYPE_FOLLOW
#endif
|| check->v.movetype == MOVETYPE_NOCLIP)
continue;
 
if (SV_TestEntityPosition (check))
Con_Printf ("entity in invalid position\n");
}
}
 
/*
================
SV_CheckVelocity
================
*/
void SV_CheckVelocity (edict_t *ent)
{
int i;
 
//
// bound velocity
//
for (i=0 ; i<3 ; i++)
{
if (IS_NAN(ent->v.velocity[i]))
{
Con_Printf ("Got a NaN velocity on %s\n", pr_strings + ent->v.classname);
ent->v.velocity[i] = 0;
}
if (IS_NAN(ent->v.origin[i]))
{
Con_Printf ("Got a NaN origin on %s\n", pr_strings + ent->v.classname);
ent->v.origin[i] = 0;
}
if (ent->v.velocity[i] > sv_maxvelocity.value)
ent->v.velocity[i] = sv_maxvelocity.value;
else if (ent->v.velocity[i] < -sv_maxvelocity.value)
ent->v.velocity[i] = -sv_maxvelocity.value;
}
}
 
/*
=============
SV_RunThink
 
Runs thinking code if time. There is some play in the exact time the think
function will be called, because it is called before any movement is done
in a frame. Not used for pushmove objects, because they must be exact.
Returns false if the entity removed itself.
=============
*/
qboolean SV_RunThink (edict_t *ent)
{
float thinktime;
 
thinktime = ent->v.nextthink;
if (thinktime <= 0 || thinktime > sv.time + host_frametime)
return true;
if (thinktime < sv.time)
thinktime = sv.time; // don't let things stay in the past.
// it is possible to start that way
// by a trigger with a local time.
ent->v.nextthink = 0;
pr_global_struct->time = thinktime;
pr_global_struct->self = EDICT_TO_PROG(ent);
pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
PR_ExecuteProgram (ent->v.think);
return !ent->free;
}
 
/*
==================
SV_Impact
 
Two entities have touched, so run their touch functions
==================
*/
void SV_Impact (edict_t *e1, edict_t *e2)
{
int old_self, old_other;
old_self = pr_global_struct->self;
old_other = pr_global_struct->other;
pr_global_struct->time = sv.time;
if (e1->v.touch && e1->v.solid != SOLID_NOT)
{
pr_global_struct->self = EDICT_TO_PROG(e1);
pr_global_struct->other = EDICT_TO_PROG(e2);
PR_ExecuteProgram (e1->v.touch);
}
if (e2->v.touch && e2->v.solid != SOLID_NOT)
{
pr_global_struct->self = EDICT_TO_PROG(e2);
pr_global_struct->other = EDICT_TO_PROG(e1);
PR_ExecuteProgram (e2->v.touch);
}
 
pr_global_struct->self = old_self;
pr_global_struct->other = old_other;
}
 
 
/*
==================
ClipVelocity
 
Slide off of the impacting object
returns the blocked flags (1 = floor, 2 = step / wall)
==================
*/
#define STOP_EPSILON 0.1
 
int ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
{
float backoff;
float change;
int i, blocked;
blocked = 0;
if (normal[2] > 0)
blocked |= 1; // floor
if (!normal[2])
blocked |= 2; // step
backoff = DotProduct (in, normal) * overbounce;
 
for (i=0 ; i<3 ; i++)
{
change = normal[i]*backoff;
out[i] = in[i] - change;
if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON)
out[i] = 0;
}
return blocked;
}
 
 
/*
============
SV_FlyMove
 
The basic solid body movement clip that slides along multiple planes
Returns the clipflags if the velocity was modified (hit something solid)
1 = floor
2 = wall / step
4 = dead stop
If steptrace is not NULL, the trace of any vertical wall hit will be stored
============
*/
#define MAX_CLIP_PLANES 5
int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
{
int bumpcount, numbumps;
vec3_t dir;
float d;
int numplanes;
vec3_t planes[MAX_CLIP_PLANES];
vec3_t primal_velocity, original_velocity, new_velocity;
int i, j;
trace_t trace;
vec3_t end;
float time_left;
int blocked;
numbumps = 4;
blocked = 0;
VectorCopy (ent->v.velocity, original_velocity);
VectorCopy (ent->v.velocity, primal_velocity);
numplanes = 0;
time_left = time;
 
for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++)
{
if (!ent->v.velocity[0] && !ent->v.velocity[1] && !ent->v.velocity[2])
break;
 
for (i=0 ; i<3 ; i++)
end[i] = ent->v.origin[i] + time_left * ent->v.velocity[i];
 
trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent);
 
if (trace.allsolid)
{ // entity is trapped in another solid
VectorCopy (vec3_origin, ent->v.velocity);
return 3;
}
 
if (trace.fraction > 0)
{ // actually covered some distance
VectorCopy (trace.endpos, ent->v.origin);
VectorCopy (ent->v.velocity, original_velocity);
numplanes = 0;
}
 
if (trace.fraction == 1)
break; // moved the entire distance
 
if (!trace.ent)
Sys_Error ("SV_FlyMove: !trace.ent");
 
if (trace.plane.normal[2] > 0.7)
{
blocked |= 1; // floor
if (trace.ent->v.solid == SOLID_BSP)
{
ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
ent->v.groundentity = EDICT_TO_PROG(trace.ent);
}
}
if (!trace.plane.normal[2])
{
blocked |= 2; // step
if (steptrace)
*steptrace = trace; // save for player extrafriction
}
 
//
// run the impact function
//
SV_Impact (ent, trace.ent);
if (ent->free)
break; // removed by the impact function
 
time_left -= time_left * trace.fraction;
// cliped to another plane
if (numplanes >= MAX_CLIP_PLANES)
{ // this shouldn't really happen
VectorCopy (vec3_origin, ent->v.velocity);
return 3;
}
 
VectorCopy (trace.plane.normal, planes[numplanes]);
numplanes++;
 
//
// modify original_velocity so it parallels all of the clip planes
//
for (i=0 ; i<numplanes ; i++)
{
ClipVelocity (original_velocity, planes[i], new_velocity, 1);
for (j=0 ; j<numplanes ; j++)
if (j != i)
{
if (DotProduct (new_velocity, planes[j]) < 0)
break; // not ok
}
if (j == numplanes)
break;
}
if (i != numplanes)
{ // go along this plane
VectorCopy (new_velocity, ent->v.velocity);
}
else
{ // go along the crease
if (numplanes != 2)
{
// Con_Printf ("clip velocity, numplanes == %i\n",numplanes);
VectorCopy (vec3_origin, ent->v.velocity);
return 7;
}
CrossProduct (planes[0], planes[1], dir);
d = DotProduct (dir, ent->v.velocity);
VectorScale (dir, d, ent->v.velocity);
}
 
//
// if original velocity is against the original velocity, stop dead
// to avoid tiny occilations in sloping corners
//
if (DotProduct (ent->v.velocity, primal_velocity) <= 0)
{
VectorCopy (vec3_origin, ent->v.velocity);
return blocked;
}
}
 
return blocked;
}
 
 
/*
============
SV_AddGravity
 
============
*/
void SV_AddGravity (edict_t *ent)
{
float ent_gravity;
 
#ifdef QUAKE2
if (ent->v.gravity)
ent_gravity = ent->v.gravity;
else
ent_gravity = 1.0;
#else
eval_t *val;
 
val = GetEdictFieldValue(ent, "gravity");
if (val && val->_float)
ent_gravity = val->_float;
else
ent_gravity = 1.0;
#endif
ent->v.velocity[2] -= ent_gravity * sv_gravity.value * host_frametime;
}
 
 
/*
===============================================================================
 
PUSHMOVE
 
===============================================================================
*/
 
/*
============
SV_PushEntity
 
Does not change the entities velocity at all
============
*/
trace_t SV_PushEntity (edict_t *ent, vec3_t push)
{
trace_t trace;
vec3_t end;
VectorAdd (ent->v.origin, push, end);
 
if (ent->v.movetype == MOVETYPE_FLYMISSILE)
trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_MISSILE, ent);
else if (ent->v.solid == SOLID_TRIGGER || ent->v.solid == SOLID_NOT)
// only clip against bmodels
trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NOMONSTERS, ent);
else
trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent);
VectorCopy (trace.endpos, ent->v.origin);
SV_LinkEdict (ent, true);
 
if (trace.ent)
SV_Impact (ent, trace.ent);
 
return trace;
}
 
 
/*
============
SV_PushMove
 
============
*/
void SV_PushMove (edict_t *pusher, float movetime)
{
int i, e;
edict_t *check, *block;
vec3_t mins, maxs, move;
vec3_t entorig, pushorig;
int num_moved;
edict_t *moved_edict[MAX_EDICTS];
vec3_t moved_from[MAX_EDICTS];
 
if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2])
{
pusher->v.ltime += movetime;
return;
}
 
for (i=0 ; i<3 ; i++)
{
move[i] = pusher->v.velocity[i] * movetime;
mins[i] = pusher->v.absmin[i] + move[i];
maxs[i] = pusher->v.absmax[i] + move[i];
}
 
VectorCopy (pusher->v.origin, pushorig);
// move the pusher to it's final position
 
VectorAdd (pusher->v.origin, move, pusher->v.origin);
pusher->v.ltime += movetime;
SV_LinkEdict (pusher, false);
 
 
// see if any solid entities are inside the final position
num_moved = 0;
check = NEXT_EDICT(sv.edicts);
for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
{
if (check->free)
continue;
if (check->v.movetype == MOVETYPE_PUSH
|| check->v.movetype == MOVETYPE_NONE
#ifdef QUAKE2
|| check->v.movetype == MOVETYPE_FOLLOW
#endif
|| check->v.movetype == MOVETYPE_NOCLIP)
continue;
 
// if the entity is standing on the pusher, it will definately be moved
if ( ! ( ((int)check->v.flags & FL_ONGROUND)
&& PROG_TO_EDICT(check->v.groundentity) == pusher) )
{
if ( check->v.absmin[0] >= maxs[0]
|| check->v.absmin[1] >= maxs[1]
|| check->v.absmin[2] >= maxs[2]
|| check->v.absmax[0] <= mins[0]
|| check->v.absmax[1] <= mins[1]
|| check->v.absmax[2] <= mins[2] )
continue;
 
// see if the ent's bbox is inside the pusher's final position
if (!SV_TestEntityPosition (check))
continue;
}
 
// remove the onground flag for non-players
if (check->v.movetype != MOVETYPE_WALK)
check->v.flags = (int)check->v.flags & ~FL_ONGROUND;
VectorCopy (check->v.origin, entorig);
VectorCopy (check->v.origin, moved_from[num_moved]);
moved_edict[num_moved] = check;
num_moved++;
 
// try moving the contacted entity
pusher->v.solid = SOLID_NOT;
SV_PushEntity (check, move);
pusher->v.solid = SOLID_BSP;
 
// if it is still inside the pusher, block
block = SV_TestEntityPosition (check);
if (block)
{ // fail the move
if (check->v.mins[0] == check->v.maxs[0])
continue;
if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER)
{ // corpse
check->v.mins[0] = check->v.mins[1] = 0;
VectorCopy (check->v.mins, check->v.maxs);
continue;
}
VectorCopy (entorig, check->v.origin);
SV_LinkEdict (check, true);
 
VectorCopy (pushorig, pusher->v.origin);
SV_LinkEdict (pusher, false);
pusher->v.ltime -= movetime;
 
// if the pusher has a "blocked" function, call it
// otherwise, just stay in place until the obstacle is gone
if (pusher->v.blocked)
{
pr_global_struct->self = EDICT_TO_PROG(pusher);
pr_global_struct->other = EDICT_TO_PROG(check);
PR_ExecuteProgram (pusher->v.blocked);
}
// move back any entities we already moved
for (i=0 ; i<num_moved ; i++)
{
VectorCopy (moved_from[i], moved_edict[i]->v.origin);
SV_LinkEdict (moved_edict[i], false);
}
return;
}
}
 
}
 
#ifdef QUAKE2
/*
============
SV_PushRotate
 
============
*/
void SV_PushRotate (edict_t *pusher, float movetime)
{
int i, e;
edict_t *check, *block;
vec3_t move, a, amove;
vec3_t entorig, pushorig;
int num_moved;
edict_t *moved_edict[MAX_EDICTS];
vec3_t moved_from[MAX_EDICTS];
vec3_t org, org2;
vec3_t forward, right, up;
 
if (!pusher->v.avelocity[0] && !pusher->v.avelocity[1] && !pusher->v.avelocity[2])
{
pusher->v.ltime += movetime;
return;
}
 
for (i=0 ; i<3 ; i++)
amove[i] = pusher->v.avelocity[i] * movetime;
 
VectorSubtract (vec3_origin, amove, a);
AngleVectors (a, forward, right, up);
 
VectorCopy (pusher->v.angles, pushorig);
// move the pusher to it's final position
 
VectorAdd (pusher->v.angles, amove, pusher->v.angles);
pusher->v.ltime += movetime;
SV_LinkEdict (pusher, false);
 
 
// see if any solid entities are inside the final position
num_moved = 0;
check = NEXT_EDICT(sv.edicts);
for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
{
if (check->free)
continue;
if (check->v.movetype == MOVETYPE_PUSH
|| check->v.movetype == MOVETYPE_NONE
|| check->v.movetype == MOVETYPE_FOLLOW
|| check->v.movetype == MOVETYPE_NOCLIP)
continue;
 
// if the entity is standing on the pusher, it will definately be moved
if ( ! ( ((int)check->v.flags & FL_ONGROUND)
&& PROG_TO_EDICT(check->v.groundentity) == pusher) )
{
if ( check->v.absmin[0] >= pusher->v.absmax[0]
|| check->v.absmin[1] >= pusher->v.absmax[1]
|| check->v.absmin[2] >= pusher->v.absmax[2]
|| check->v.absmax[0] <= pusher->v.absmin[0]
|| check->v.absmax[1] <= pusher->v.absmin[1]
|| check->v.absmax[2] <= pusher->v.absmin[2] )
continue;
 
// see if the ent's bbox is inside the pusher's final position
if (!SV_TestEntityPosition (check))
continue;
}
 
// remove the onground flag for non-players
if (check->v.movetype != MOVETYPE_WALK)
check->v.flags = (int)check->v.flags & ~FL_ONGROUND;
VectorCopy (check->v.origin, entorig);
VectorCopy (check->v.origin, moved_from[num_moved]);
moved_edict[num_moved] = check;
num_moved++;
 
// calculate destination position
VectorSubtract (check->v.origin, pusher->v.origin, org);
org2[0] = DotProduct (org, forward);
org2[1] = -DotProduct (org, right);
org2[2] = DotProduct (org, up);
VectorSubtract (org2, org, move);
 
// try moving the contacted entity
pusher->v.solid = SOLID_NOT;
SV_PushEntity (check, move);
pusher->v.solid = SOLID_BSP;
 
// if it is still inside the pusher, block
block = SV_TestEntityPosition (check);
if (block)
{ // fail the move
if (check->v.mins[0] == check->v.maxs[0])
continue;
if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER)
{ // corpse
check->v.mins[0] = check->v.mins[1] = 0;
VectorCopy (check->v.mins, check->v.maxs);
continue;
}
VectorCopy (entorig, check->v.origin);
SV_LinkEdict (check, true);
 
VectorCopy (pushorig, pusher->v.angles);
SV_LinkEdict (pusher, false);
pusher->v.ltime -= movetime;
 
// if the pusher has a "blocked" function, call it
// otherwise, just stay in place until the obstacle is gone
if (pusher->v.blocked)
{
pr_global_struct->self = EDICT_TO_PROG(pusher);
pr_global_struct->other = EDICT_TO_PROG(check);
PR_ExecuteProgram (pusher->v.blocked);
}
// move back any entities we already moved
for (i=0 ; i<num_moved ; i++)
{
VectorCopy (moved_from[i], moved_edict[i]->v.origin);
VectorSubtract (moved_edict[i]->v.angles, amove, moved_edict[i]->v.angles);
SV_LinkEdict (moved_edict[i], false);
}
return;
}
else
{
VectorAdd (check->v.angles, amove, check->v.angles);
}
}
 
}
#endif
 
/*
================
SV_Physics_Pusher
 
================
*/
void SV_Physics_Pusher (edict_t *ent)
{
float thinktime;
float oldltime;
float movetime;
 
oldltime = ent->v.ltime;
thinktime = ent->v.nextthink;
if (thinktime < ent->v.ltime + host_frametime)
{
movetime = thinktime - ent->v.ltime;
if (movetime < 0)
movetime = 0;
}
else
movetime = host_frametime;
 
if (movetime)
{
#ifdef QUAKE2
if (ent->v.avelocity[0] || ent->v.avelocity[1] || ent->v.avelocity[2])
SV_PushRotate (ent, movetime);
else
#endif
SV_PushMove (ent, movetime); // advances ent->v.ltime if not blocked
}
if (thinktime > oldltime && thinktime <= ent->v.ltime)
{
ent->v.nextthink = 0;
pr_global_struct->time = sv.time;
pr_global_struct->self = EDICT_TO_PROG(ent);
pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
PR_ExecuteProgram (ent->v.think);
if (ent->free)
return;
}
 
}
 
 
/*
===============================================================================
 
CLIENT MOVEMENT
 
===============================================================================
*/
 
/*
=============
SV_CheckStuck
 
This is a big hack to try and fix the rare case of getting stuck in the world
clipping hull.
=============
*/
void SV_CheckStuck (edict_t *ent)
{
int i, j;
int z;
vec3_t org;
 
if (!SV_TestEntityPosition(ent))
{
VectorCopy (ent->v.origin, ent->v.oldorigin);
return;
}
 
VectorCopy (ent->v.origin, org);
VectorCopy (ent->v.oldorigin, ent->v.origin);
if (!SV_TestEntityPosition(ent))
{
Con_DPrintf ("Unstuck.\n");
SV_LinkEdict (ent, true);
return;
}
for (z=0 ; z< 18 ; z++)
for (i=-1 ; i <= 1 ; i++)
for (j=-1 ; j <= 1 ; j++)
{
ent->v.origin[0] = org[0] + i;
ent->v.origin[1] = org[1] + j;
ent->v.origin[2] = org[2] + z;
if (!SV_TestEntityPosition(ent))
{
Con_DPrintf ("Unstuck.\n");
SV_LinkEdict (ent, true);
return;
}
}
VectorCopy (org, ent->v.origin);
Con_DPrintf ("player is stuck.\n");
}
 
 
/*
=============
SV_CheckWater
=============
*/
qboolean SV_CheckWater (edict_t *ent)
{
vec3_t point;
int cont;
#ifdef QUAKE2
int truecont;
#endif
 
point[0] = ent->v.origin[0];
point[1] = ent->v.origin[1];
point[2] = ent->v.origin[2] + ent->v.mins[2] + 1;
ent->v.waterlevel = 0;
ent->v.watertype = CONTENTS_EMPTY;
cont = SV_PointContents (point);
if (cont <= CONTENTS_WATER)
{
#ifdef QUAKE2
truecont = SV_TruePointContents (point);
#endif
ent->v.watertype = cont;
ent->v.waterlevel = 1;
point[2] = ent->v.origin[2] + (ent->v.mins[2] + ent->v.maxs[2])*0.5;
cont = SV_PointContents (point);
if (cont <= CONTENTS_WATER)
{
ent->v.waterlevel = 2;
point[2] = ent->v.origin[2] + ent->v.view_ofs[2];
cont = SV_PointContents (point);
if (cont <= CONTENTS_WATER)
ent->v.waterlevel = 3;
}
#ifdef QUAKE2
if (truecont <= CONTENTS_CURRENT_0 && truecont >= CONTENTS_CURRENT_DOWN)
{
static vec3_t current_table[] =
{
{1, 0, 0},
{0, 1, 0},
{-1, 0, 0},
{0, -1, 0},
{0, 0, 1},
{0, 0, -1}
};
 
VectorMA (ent->v.basevelocity, 150.0*ent->v.waterlevel/3.0, current_table[CONTENTS_CURRENT_0 - truecont], ent->v.basevelocity);
}
#endif
}
return ent->v.waterlevel > 1;
}
 
/*
============
SV_WallFriction
 
============
*/
void SV_WallFriction (edict_t *ent, trace_t *trace)
{
vec3_t forward, right, up;
float d, i;
vec3_t into, side;
AngleVectors (ent->v.v_angle, forward, right, up);
d = DotProduct (trace->plane.normal, forward);
d += 0.5;
if (d >= 0)
return;
// cut the tangential velocity
i = DotProduct (trace->plane.normal, ent->v.velocity);
VectorScale (trace->plane.normal, i, into);
VectorSubtract (ent->v.velocity, into, side);
ent->v.velocity[0] = side[0] * (1 + d);
ent->v.velocity[1] = side[1] * (1 + d);
}
 
/*
=====================
SV_TryUnstick
 
Player has come to a dead stop, possibly due to the problem with limited
float precision at some angle joins in the BSP hull.
 
Try fixing by pushing one pixel in each direction.
 
This is a hack, but in the interest of good gameplay...
======================
*/
int SV_TryUnstick (edict_t *ent, vec3_t oldvel)
{
int i;
vec3_t oldorg;
vec3_t dir;
int clip;
trace_t steptrace;
VectorCopy (ent->v.origin, oldorg);
VectorCopy (vec3_origin, dir);
 
for (i=0 ; i<8 ; i++)
{
// try pushing a little in an axial direction
switch (i)
{
case 0: dir[0] = 2; dir[1] = 0; break;
case 1: dir[0] = 0; dir[1] = 2; break;
case 2: dir[0] = -2; dir[1] = 0; break;
case 3: dir[0] = 0; dir[1] = -2; break;
case 4: dir[0] = 2; dir[1] = 2; break;
case 5: dir[0] = -2; dir[1] = 2; break;
case 6: dir[0] = 2; dir[1] = -2; break;
case 7: dir[0] = -2; dir[1] = -2; break;
}
SV_PushEntity (ent, dir);
 
// retry the original move
ent->v.velocity[0] = oldvel[0];
ent->v. velocity[1] = oldvel[1];
ent->v. velocity[2] = 0;
clip = SV_FlyMove (ent, 0.1, &steptrace);
 
if ( fabs(oldorg[1] - ent->v.origin[1]) > 4
|| fabs(oldorg[0] - ent->v.origin[0]) > 4 )
{
//Con_DPrintf ("unstuck!\n");
return clip;
}
// go back to the original pos and try again
VectorCopy (oldorg, ent->v.origin);
}
VectorCopy (vec3_origin, ent->v.velocity);
return 7; // still not moving
}
 
/*
=====================
SV_WalkMove
 
Only used by players
======================
*/
#define STEPSIZE 18
void SV_WalkMove (edict_t *ent)
{
vec3_t upmove, downmove;
vec3_t oldorg, oldvel;
vec3_t nosteporg, nostepvel;
int clip;
int oldonground;
trace_t steptrace, downtrace;
//
// do a regular slide move unless it looks like you ran into a step
//
oldonground = (int)ent->v.flags & FL_ONGROUND;
ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
VectorCopy (ent->v.origin, oldorg);
VectorCopy (ent->v.velocity, oldvel);
clip = SV_FlyMove (ent, host_frametime, &steptrace);
 
if ( !(clip & 2) )
return; // move didn't block on a step
 
if (!oldonground && ent->v.waterlevel == 0)
return; // don't stair up while jumping
if (ent->v.movetype != MOVETYPE_WALK)
return; // gibbed by a trigger
if (sv_nostep.value)
return;
if ( (int)sv_player->v.flags & FL_WATERJUMP )
return;
 
VectorCopy (ent->v.origin, nosteporg);
VectorCopy (ent->v.velocity, nostepvel);
 
//
// try moving up and forward to go up a step
//
VectorCopy (oldorg, ent->v.origin); // back to start pos
 
VectorCopy (vec3_origin, upmove);
VectorCopy (vec3_origin, downmove);
upmove[2] = STEPSIZE;
downmove[2] = -STEPSIZE + oldvel[2]*host_frametime;
 
// move up
SV_PushEntity (ent, upmove); // FIXME: don't link?
 
// move forward
ent->v.velocity[0] = oldvel[0];
ent->v. velocity[1] = oldvel[1];
ent->v. velocity[2] = 0;
clip = SV_FlyMove (ent, host_frametime, &steptrace);
 
// check for stuckness, possibly due to the limited precision of floats
// in the clipping hulls
if (clip)
{
if ( fabs(oldorg[1] - ent->v.origin[1]) < 0.03125
&& fabs(oldorg[0] - ent->v.origin[0]) < 0.03125 )
{ // stepping up didn't make any progress
clip = SV_TryUnstick (ent, oldvel);
}
}
// extra friction based on view angle
if ( clip & 2 )
SV_WallFriction (ent, &steptrace);
 
// move down
downtrace = SV_PushEntity (ent, downmove); // FIXME: don't link?
 
if (downtrace.plane.normal[2] > 0.7)
{
if (ent->v.solid == SOLID_BSP)
{
ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
ent->v.groundentity = EDICT_TO_PROG(downtrace.ent);
}
}
else
{
// if the push down didn't end up on good ground, use the move without
// the step up. This happens near wall / slope combinations, and can
// cause the player to hop up higher on a slope too steep to climb
VectorCopy (nosteporg, ent->v.origin);
VectorCopy (nostepvel, ent->v.velocity);
}
}
 
 
/*
================
SV_Physics_Client
 
Player character actions
================
*/
void SV_Physics_Client (edict_t *ent, int num)
{
if ( ! svs.clients[num-1].active )
return; // unconnected slot
 
//
// call standard client pre-think
//
pr_global_struct->time = sv.time;
pr_global_struct->self = EDICT_TO_PROG(ent);
PR_ExecuteProgram (pr_global_struct->PlayerPreThink);
//
// do a move
//
SV_CheckVelocity (ent);
 
//
// decide which move function to call
//
switch ((int)ent->v.movetype)
{
case MOVETYPE_NONE:
if (!SV_RunThink (ent))
return;
break;
 
case MOVETYPE_WALK:
if (!SV_RunThink (ent))
return;
if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) )
SV_AddGravity (ent);
SV_CheckStuck (ent);
#ifdef QUAKE2
VectorAdd (ent->v.velocity, ent->v.basevelocity, ent->v.velocity);
#endif
SV_WalkMove (ent);
 
#ifdef QUAKE2
VectorSubtract (ent->v.velocity, ent->v.basevelocity, ent->v.velocity);
#endif
break;
case MOVETYPE_TOSS:
case MOVETYPE_BOUNCE:
SV_Physics_Toss (ent);
break;
 
case MOVETYPE_FLY:
if (!SV_RunThink (ent))
return;
SV_FlyMove (ent, host_frametime, NULL);
break;
case MOVETYPE_NOCLIP:
if (!SV_RunThink (ent))
return;
VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin);
break;
default:
Sys_Error ("SV_Physics_client: bad movetype %i", (int)ent->v.movetype);
}
 
//
// call standard player post-think
//
SV_LinkEdict (ent, true);
 
pr_global_struct->time = sv.time;
pr_global_struct->self = EDICT_TO_PROG(ent);
PR_ExecuteProgram (pr_global_struct->PlayerPostThink);
}
 
//============================================================================
 
/*
=============
SV_Physics_None
 
Non moving objects can only think
=============
*/
void SV_Physics_None (edict_t *ent)
{
// regular thinking
SV_RunThink (ent);
}
 
#ifdef QUAKE2
/*
=============
SV_Physics_Follow
 
Entities that are "stuck" to another entity
=============
*/
void SV_Physics_Follow (edict_t *ent)
{
// regular thinking
SV_RunThink (ent);
VectorAdd (PROG_TO_EDICT(ent->v.aiment)->v.origin, ent->v.v_angle, ent->v.origin);
SV_LinkEdict (ent, true);
}
#endif
 
/*
=============
SV_Physics_Noclip
 
A moving object that doesn't obey physics
=============
*/
void SV_Physics_Noclip (edict_t *ent)
{
// regular thinking
if (!SV_RunThink (ent))
return;
VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles);
VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin);
 
SV_LinkEdict (ent, false);
}
 
/*
==============================================================================
 
TOSS / BOUNCE
 
==============================================================================
*/
 
/*
=============
SV_CheckWaterTransition
 
=============
*/
void SV_CheckWaterTransition (edict_t *ent)
{
int cont;
#ifdef QUAKE2
vec3_t point;
point[0] = ent->v.origin[0];
point[1] = ent->v.origin[1];
point[2] = ent->v.origin[2] + ent->v.mins[2] + 1;
cont = SV_PointContents (point);
#else
cont = SV_PointContents (ent->v.origin);
#endif
if (!ent->v.watertype)
{ // just spawned here
ent->v.watertype = cont;
ent->v.waterlevel = 1;
return;
}
if (cont <= CONTENTS_WATER)
{
if (ent->v.watertype == CONTENTS_EMPTY)
{ // just crossed into water
SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
}
ent->v.watertype = cont;
ent->v.waterlevel = 1;
}
else
{
if (ent->v.watertype != CONTENTS_EMPTY)
{ // just crossed into water
SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
}
ent->v.watertype = CONTENTS_EMPTY;
ent->v.waterlevel = cont;
}
}
 
/*
=============
SV_Physics_Toss
 
Toss, bounce, and fly movement. When onground, do nothing.
=============
*/
void SV_Physics_Toss (edict_t *ent)
{
trace_t trace;
vec3_t move;
float backoff;
#ifdef QUAKE2
edict_t *groundentity;
 
groundentity = PROG_TO_EDICT(ent->v.groundentity);
if ((int)groundentity->v.flags & FL_CONVEYOR)
VectorScale(groundentity->v.movedir, groundentity->v.speed, ent->v.basevelocity);
else
VectorCopy(vec_origin, ent->v.basevelocity);
SV_CheckWater (ent);
#endif
// regular thinking
if (!SV_RunThink (ent))
return;
 
#ifdef QUAKE2
if (ent->v.velocity[2] > 0)
ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
 
if ( ((int)ent->v.flags & FL_ONGROUND) )
//@@
if (VectorCompare(ent->v.basevelocity, vec_origin))
return;
 
SV_CheckVelocity (ent);
 
// add gravity
if (! ((int)ent->v.flags & FL_ONGROUND)
&& ent->v.movetype != MOVETYPE_FLY
&& ent->v.movetype != MOVETYPE_BOUNCEMISSILE
&& ent->v.movetype != MOVETYPE_FLYMISSILE)
SV_AddGravity (ent);
 
#else
// if onground, return without moving
if ( ((int)ent->v.flags & FL_ONGROUND) )
return;
 
SV_CheckVelocity (ent);
 
// add gravity
if (ent->v.movetype != MOVETYPE_FLY
&& ent->v.movetype != MOVETYPE_FLYMISSILE)
SV_AddGravity (ent);
#endif
 
// move angles
VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles);
 
// move origin
#ifdef QUAKE2
VectorAdd (ent->v.velocity, ent->v.basevelocity, ent->v.velocity);
#endif
VectorScale (ent->v.velocity, host_frametime, move);
trace = SV_PushEntity (ent, move);
#ifdef QUAKE2
VectorSubtract (ent->v.velocity, ent->v.basevelocity, ent->v.velocity);
#endif
if (trace.fraction == 1)
return;
if (ent->free)
return;
if (ent->v.movetype == MOVETYPE_BOUNCE)
backoff = 1.5;
#ifdef QUAKE2
else if (ent->v.movetype == MOVETYPE_BOUNCEMISSILE)
backoff = 2.0;
#endif
else
backoff = 1;
 
ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff);
 
// stop if on ground
if (trace.plane.normal[2] > 0.7)
{
#ifdef QUAKE2
if (ent->v.velocity[2] < 60 || (ent->v.movetype != MOVETYPE_BOUNCE && ent->v.movetype != MOVETYPE_BOUNCEMISSILE))
#else
if (ent->v.velocity[2] < 60 || ent->v.movetype != MOVETYPE_BOUNCE)
#endif
{
ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
ent->v.groundentity = EDICT_TO_PROG(trace.ent);
VectorCopy (vec3_origin, ent->v.velocity);
VectorCopy (vec3_origin, ent->v.avelocity);
}
}
// check for in water
SV_CheckWaterTransition (ent);
}
 
/*
===============================================================================
 
STEPPING MOVEMENT
 
===============================================================================
*/
 
/*
=============
SV_Physics_Step
 
Monsters freefall when they don't have a ground entity, otherwise
all movement is done with discrete steps.
 
This is also used for objects that have become still on the ground, but
will fall if the floor is pulled out from under them.
=============
*/
#ifdef QUAKE2
void SV_Physics_Step (edict_t *ent)
{
qboolean wasonground;
qboolean inwater;
qboolean hitsound = false;
float *vel;
float speed, newspeed, control;
float friction;
edict_t *groundentity;
 
groundentity = PROG_TO_EDICT(ent->v.groundentity);
if ((int)groundentity->v.flags & FL_CONVEYOR)
VectorScale(groundentity->v.movedir, groundentity->v.speed, ent->v.basevelocity);
else
VectorCopy(vec_origin, ent->v.basevelocity);
//@@
pr_global_struct->time = sv.time;
pr_global_struct->self = EDICT_TO_PROG(ent);
PF_WaterMove();
 
SV_CheckVelocity (ent);
 
wasonground = (int)ent->v.flags & FL_ONGROUND;
// ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
 
// add gravity except:
// flying monsters
// swimming monsters who are in the water
inwater = SV_CheckWater(ent);
if (! wasonground)
if (!((int)ent->v.flags & FL_FLY))
if (!(((int)ent->v.flags & FL_SWIM) && (ent->v.waterlevel > 0)))
{
if (ent->v.velocity[2] < sv_gravity.value*-0.1)
hitsound = true;
if (!inwater)
SV_AddGravity (ent);
}
 
if (!VectorCompare(ent->v.velocity, vec_origin) || !VectorCompare(ent->v.basevelocity, vec_origin))
{
ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
// apply friction
// let dead monsters who aren't completely onground slide
if (wasonground)
if (!(ent->v.health <= 0.0 && !SV_CheckBottom(ent)))
{
vel = ent->v.velocity;
speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]);
if (speed)
{
friction = sv_friction.value;
 
control = speed < sv_stopspeed.value ? sv_stopspeed.value : speed;
newspeed = speed - host_frametime*control*friction;
 
if (newspeed < 0)
newspeed = 0;
newspeed /= speed;
 
vel[0] = vel[0] * newspeed;
vel[1] = vel[1] * newspeed;
}
}
 
VectorAdd (ent->v.velocity, ent->v.basevelocity, ent->v.velocity);
SV_FlyMove (ent, host_frametime, NULL);
VectorSubtract (ent->v.velocity, ent->v.basevelocity, ent->v.velocity);
 
// determine if it's on solid ground at all
{
vec3_t mins, maxs, point;
int x, y;
VectorAdd (ent->v.origin, ent->v.mins, mins);
VectorAdd (ent->v.origin, ent->v.maxs, maxs);
 
point[2] = mins[2] - 1;
for (x=0 ; x<=1 ; x++)
for (y=0 ; y<=1 ; y++)
{
point[0] = x ? maxs[0] : mins[0];
point[1] = y ? maxs[1] : mins[1];
if (SV_PointContents (point) == CONTENTS_SOLID)
{
ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
break;
}
}
 
}
 
SV_LinkEdict (ent, true);
 
if ((int)ent->v.flags & FL_ONGROUND)
if (!wasonground)
if (hitsound)
SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1);
}
 
// regular thinking
SV_RunThink (ent);
SV_CheckWaterTransition (ent);
}
#else
void SV_Physics_Step (edict_t *ent)
{
qboolean hitsound;
 
// freefall if not onground
if ( ! ((int)ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM) ) )
{
if (ent->v.velocity[2] < sv_gravity.value*-0.1)
hitsound = true;
else
hitsound = false;
 
SV_AddGravity (ent);
SV_CheckVelocity (ent);
SV_FlyMove (ent, host_frametime, NULL);
SV_LinkEdict (ent, true);
 
if ( (int)ent->v.flags & FL_ONGROUND ) // just hit ground
{
if (hitsound)
SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1);
}
}
 
// regular thinking
SV_RunThink (ent);
SV_CheckWaterTransition (ent);
}
#endif
 
//============================================================================
 
/*
================
SV_Physics
 
================
*/
void SV_Physics (void)
{
int i;
edict_t *ent;
 
// let the progs know that a new frame has started
pr_global_struct->self = EDICT_TO_PROG(sv.edicts);
pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
pr_global_struct->time = sv.time;
PR_ExecuteProgram (pr_global_struct->StartFrame);
 
//SV_CheckAllEnts ();
 
//
// treat each object in turn
//
ent = sv.edicts;
for (i=0 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
{
if (ent->free)
continue;
 
if (pr_global_struct->force_retouch)
{
SV_LinkEdict (ent, true); // force retouch even for stationary
}
 
if (i > 0 && i <= svs.maxclients)
SV_Physics_Client (ent, i);
else if (ent->v.movetype == MOVETYPE_PUSH)
SV_Physics_Pusher (ent);
else if (ent->v.movetype == MOVETYPE_NONE)
SV_Physics_None (ent);
#ifdef QUAKE2
else if (ent->v.movetype == MOVETYPE_FOLLOW)
SV_Physics_Follow (ent);
#endif
else if (ent->v.movetype == MOVETYPE_NOCLIP)
SV_Physics_Noclip (ent);
else if (ent->v.movetype == MOVETYPE_STEP)
SV_Physics_Step (ent);
else if (ent->v.movetype == MOVETYPE_TOSS
|| ent->v.movetype == MOVETYPE_BOUNCE
#ifdef QUAKE2
|| ent->v.movetype == MOVETYPE_BOUNCEMISSILE
#endif
|| ent->v.movetype == MOVETYPE_FLY
|| ent->v.movetype == MOVETYPE_FLYMISSILE)
SV_Physics_Toss (ent);
else
Sys_Error ("SV_Physics: bad movetype %i", (int)ent->v.movetype);
}
if (pr_global_struct->force_retouch)
pr_global_struct->force_retouch--;
 
sv.time += host_frametime;
}
 
 
#ifdef QUAKE2
trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore)
{
edict_t tempent, *tent;
trace_t trace;
vec3_t move;
vec3_t end;
double save_frametime;
// extern particle_t *active_particles, *free_particles;
// particle_t *p;
 
 
save_frametime = host_frametime;
host_frametime = 0.05;
 
memcpy(&tempent, ent, sizeof(edict_t));
tent = &tempent;
 
while (1)
{
SV_CheckVelocity (tent);
SV_AddGravity (tent);
VectorMA (tent->v.angles, host_frametime, tent->v.avelocity, tent->v.angles);
VectorScale (tent->v.velocity, host_frametime, move);
VectorAdd (tent->v.origin, move, end);
trace = SV_Move (tent->v.origin, tent->v.mins, tent->v.maxs, end, MOVE_NORMAL, tent);
VectorCopy (trace.endpos, tent->v.origin);
 
// p = free_particles;
// if (p)
// {
// free_particles = p->next;
// p->next = active_particles;
// active_particles = p;
//
// p->die = 256;
// p->color = 15;
// p->type = pt_static;
// VectorCopy (vec3_origin, p->vel);
// VectorCopy (tent->v.origin, p->org);
// }
 
if (trace.ent)
if (trace.ent != ignore)
break;
}
// p->color = 224;
host_frametime = save_frametime;
return trace;
}
#endif
/contrib/other/sdlquake-1.0.9/sv_user.c
0,0 → 1,629
/*
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.
 
*/
// sv_user.c -- server code for moving users
 
#include "quakedef.h"
 
edict_t *sv_player;
 
extern cvar_t sv_friction;
cvar_t sv_edgefriction = {"edgefriction", "2"};
extern cvar_t sv_stopspeed;
 
static vec3_t forward, right, up;
 
vec3_t wishdir;
float wishspeed;
 
// world
float *angles;
float *origin;
float *velocity;
 
qboolean onground;
 
usercmd_t cmd;
 
cvar_t sv_idealpitchscale = {"sv_idealpitchscale","0.8"};
 
 
/*
===============
SV_SetIdealPitch
===============
*/
#define MAX_FORWARD 6
void SV_SetIdealPitch (void)
{
float angleval, sinval, cosval;
trace_t tr;
vec3_t top, bottom;
float z[MAX_FORWARD];
int i, j;
int step, dir, steps;
 
if (!((int)sv_player->v.flags & FL_ONGROUND))
return;
angleval = sv_player->v.angles[YAW] * M_PI*2 / 360;
sinval = sin(angleval);
cosval = cos(angleval);
 
for (i=0 ; i<MAX_FORWARD ; i++)
{
top[0] = sv_player->v.origin[0] + cosval*(i+3)*12;
top[1] = sv_player->v.origin[1] + sinval*(i+3)*12;
top[2] = sv_player->v.origin[2] + sv_player->v.view_ofs[2];
bottom[0] = top[0];
bottom[1] = top[1];
bottom[2] = top[2] - 160;
tr = SV_Move (top, vec3_origin, vec3_origin, bottom, 1, sv_player);
if (tr.allsolid)
return; // looking at a wall, leave ideal the way is was
 
if (tr.fraction == 1)
return; // near a dropoff
z[i] = top[2] + tr.fraction*(bottom[2]-top[2]);
}
dir = 0;
steps = 0;
for (j=1 ; j<i ; j++)
{
step = z[j] - z[j-1];
if (step > -ON_EPSILON && step < ON_EPSILON)
continue;
 
if (dir && ( step-dir > ON_EPSILON || step-dir < -ON_EPSILON ) )
return; // mixed changes
 
steps++;
dir = step;
}
if (!dir)
{
sv_player->v.idealpitch = 0;
return;
}
if (steps < 2)
return;
sv_player->v.idealpitch = -dir * sv_idealpitchscale.value;
}
 
 
/*
==================
SV_UserFriction
 
==================
*/
void SV_UserFriction (void)
{
float *vel;
float speed, newspeed, control;
vec3_t start, stop;
float friction;
trace_t trace;
vel = velocity;
speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]);
if (!speed)
return;
 
// if the leading edge is over a dropoff, increase friction
start[0] = stop[0] = origin[0] + vel[0]/speed*16;
start[1] = stop[1] = origin[1] + vel[1]/speed*16;
start[2] = origin[2] + sv_player->v.mins[2];
stop[2] = start[2] - 34;
 
trace = SV_Move (start, vec3_origin, vec3_origin, stop, true, sv_player);
 
if (trace.fraction == 1.0)
friction = sv_friction.value*sv_edgefriction.value;
else
friction = sv_friction.value;
 
// apply friction
control = speed < sv_stopspeed.value ? sv_stopspeed.value : speed;
newspeed = speed - host_frametime*control*friction;
if (newspeed < 0)
newspeed = 0;
newspeed /= speed;
 
vel[0] = vel[0] * newspeed;
vel[1] = vel[1] * newspeed;
vel[2] = vel[2] * newspeed;
}
 
/*
==============
SV_Accelerate
==============
*/
cvar_t sv_maxspeed = {"sv_maxspeed", "320", false, true};
cvar_t sv_accelerate = {"sv_accelerate", "10"};
#if 0
void SV_Accelerate (vec3_t wishvel)
{
int i;
float addspeed, accelspeed;
vec3_t pushvec;
 
if (wishspeed == 0)
return;
 
VectorSubtract (wishvel, velocity, pushvec);
addspeed = VectorNormalize (pushvec);
 
accelspeed = sv_accelerate.value*host_frametime*addspeed;
if (accelspeed > addspeed)
accelspeed = addspeed;
for (i=0 ; i<3 ; i++)
velocity[i] += accelspeed*pushvec[i];
}
#endif
void SV_Accelerate (void)
{
int i;
float addspeed, accelspeed, currentspeed;
 
currentspeed = DotProduct (velocity, wishdir);
addspeed = wishspeed - currentspeed;
if (addspeed <= 0)
return;
accelspeed = sv_accelerate.value*host_frametime*wishspeed;
if (accelspeed > addspeed)
accelspeed = addspeed;
for (i=0 ; i<3 ; i++)
velocity[i] += accelspeed*wishdir[i];
}
 
void SV_AirAccelerate (vec3_t wishveloc)
{
int i;
float addspeed, wishspd, accelspeed, currentspeed;
wishspd = VectorNormalize (wishveloc);
if (wishspd > 30)
wishspd = 30;
currentspeed = DotProduct (velocity, wishveloc);
addspeed = wishspd - currentspeed;
if (addspeed <= 0)
return;
// accelspeed = sv_accelerate.value * host_frametime;
accelspeed = sv_accelerate.value*wishspeed * host_frametime;
if (accelspeed > addspeed)
accelspeed = addspeed;
for (i=0 ; i<3 ; i++)
velocity[i] += accelspeed*wishveloc[i];
}
 
 
void DropPunchAngle (void)
{
float len;
len = VectorNormalize (sv_player->v.punchangle);
len -= 10*host_frametime;
if (len < 0)
len = 0;
VectorScale (sv_player->v.punchangle, len, sv_player->v.punchangle);
}
 
/*
===================
SV_WaterMove
 
===================
*/
void SV_WaterMove (void)
{
int i;
vec3_t wishvel;
float speed, newspeed, wishspeed, addspeed, accelspeed;
 
//
// user intentions
//
AngleVectors (sv_player->v.v_angle, forward, right, up);
 
for (i=0 ; i<3 ; i++)
wishvel[i] = forward[i]*cmd.forwardmove + right[i]*cmd.sidemove;
 
if (!cmd.forwardmove && !cmd.sidemove && !cmd.upmove)
wishvel[2] -= 60; // drift towards bottom
else
wishvel[2] += cmd.upmove;
 
wishspeed = Length(wishvel);
if (wishspeed > sv_maxspeed.value)
{
VectorScale (wishvel, sv_maxspeed.value/wishspeed, wishvel);
wishspeed = sv_maxspeed.value;
}
wishspeed *= 0.7;
 
//
// water friction
//
speed = Length (velocity);
if (speed)
{
newspeed = speed - host_frametime * speed * sv_friction.value;
if (newspeed < 0)
newspeed = 0;
VectorScale (velocity, newspeed/speed, velocity);
}
else
newspeed = 0;
//
// water acceleration
//
if (!wishspeed)
return;
 
addspeed = wishspeed - newspeed;
if (addspeed <= 0)
return;
 
VectorNormalize (wishvel);
accelspeed = sv_accelerate.value * wishspeed * host_frametime;
if (accelspeed > addspeed)
accelspeed = addspeed;
 
for (i=0 ; i<3 ; i++)
velocity[i] += accelspeed * wishvel[i];
}
 
void SV_WaterJump (void)
{
if (sv.time > sv_player->v.teleport_time
|| !sv_player->v.waterlevel)
{
sv_player->v.flags = (int)sv_player->v.flags & ~FL_WATERJUMP;
sv_player->v.teleport_time = 0;
}
sv_player->v.velocity[0] = sv_player->v.movedir[0];
sv_player->v.velocity[1] = sv_player->v.movedir[1];
}
 
 
/*
===================
SV_AirMove
 
===================
*/
void SV_AirMove (void)
{
int i;
vec3_t wishvel;
float fmove, smove;
 
AngleVectors (sv_player->v.angles, forward, right, up);
 
fmove = cmd.forwardmove;
smove = cmd.sidemove;
// hack to not let you back into teleporter
if (sv.time < sv_player->v.teleport_time && fmove < 0)
fmove = 0;
for (i=0 ; i<3 ; i++)
wishvel[i] = forward[i]*fmove + right[i]*smove;
 
if ( (int)sv_player->v.movetype != MOVETYPE_WALK)
wishvel[2] = cmd.upmove;
else
wishvel[2] = 0;
 
VectorCopy (wishvel, wishdir);
wishspeed = VectorNormalize(wishdir);
if (wishspeed > sv_maxspeed.value)
{
VectorScale (wishvel, sv_maxspeed.value/wishspeed, wishvel);
wishspeed = sv_maxspeed.value;
}
if ( sv_player->v.movetype == MOVETYPE_NOCLIP)
{ // noclip
VectorCopy (wishvel, velocity);
}
else if ( onground )
{
SV_UserFriction ();
SV_Accelerate ();
}
else
{ // not on ground, so little effect on velocity
SV_AirAccelerate (wishvel);
}
}
 
/*
===================
SV_ClientThink
 
the move fields specify an intended velocity in pix/sec
the angle fields specify an exact angular motion in degrees
===================
*/
void SV_ClientThink (void)
{
vec3_t v_angle;
 
if (sv_player->v.movetype == MOVETYPE_NONE)
return;
onground = (int)sv_player->v.flags & FL_ONGROUND;
 
origin = sv_player->v.origin;
velocity = sv_player->v.velocity;
 
DropPunchAngle ();
//
// if dead, behave differently
//
if (sv_player->v.health <= 0)
return;
 
//
// angles
// show 1/3 the pitch angle and all the roll angle
cmd = host_client->cmd;
angles = sv_player->v.angles;
VectorAdd (sv_player->v.v_angle, sv_player->v.punchangle, v_angle);
angles[ROLL] = V_CalcRoll (sv_player->v.angles, sv_player->v.velocity)*4;
if (!sv_player->v.fixangle)
{
angles[PITCH] = -v_angle[PITCH]/3;
angles[YAW] = v_angle[YAW];
}
 
if ( (int)sv_player->v.flags & FL_WATERJUMP )
{
SV_WaterJump ();
return;
}
//
// walk
//
if ( (sv_player->v.waterlevel >= 2)
&& (sv_player->v.movetype != MOVETYPE_NOCLIP) )
{
SV_WaterMove ();
return;
}
 
SV_AirMove ();
}
 
 
/*
===================
SV_ReadClientMove
===================
*/
void SV_ReadClientMove (usercmd_t *move)
{
int i;
vec3_t angle;
int bits;
// read ping time
host_client->ping_times[host_client->num_pings%NUM_PING_TIMES]
= sv.time - MSG_ReadFloat ();
host_client->num_pings++;
 
// read current angles
for (i=0 ; i<3 ; i++)
angle[i] = MSG_ReadAngle ();
 
VectorCopy (angle, host_client->edict->v.v_angle);
// read movement
move->forwardmove = MSG_ReadShort ();
move->sidemove = MSG_ReadShort ();
move->upmove = MSG_ReadShort ();
// read buttons
bits = MSG_ReadByte ();
host_client->edict->v.button0 = bits & 1;
host_client->edict->v.button2 = (bits & 2)>>1;
 
i = MSG_ReadByte ();
if (i)
host_client->edict->v.impulse = i;
 
#ifdef QUAKE2
// read light level
host_client->edict->v.light_level = MSG_ReadByte ();
#endif
}
 
/*
===================
SV_ReadClientMessage
 
Returns false if the client should be killed
===================
*/
qboolean SV_ReadClientMessage (void)
{
int ret;
int cmd;
char *s;
do
{
nextmsg:
ret = NET_GetMessage (host_client->netconnection);
if (ret == -1)
{
Sys_Printf ("SV_ReadClientMessage: NET_GetMessage failed\n");
return false;
}
if (!ret)
return true;
MSG_BeginReading ();
while (1)
{
if (!host_client->active)
return false; // a command caused an error
 
if (msg_badread)
{
Sys_Printf ("SV_ReadClientMessage: badread\n");
return false;
}
cmd = MSG_ReadChar ();
switch (cmd)
{
case -1:
goto nextmsg; // end of message
default:
Sys_Printf ("SV_ReadClientMessage: unknown command char\n");
return false;
case clc_nop:
// Sys_Printf ("clc_nop\n");
break;
case clc_stringcmd:
s = MSG_ReadString ();
if (host_client->privileged)
ret = 2;
else
ret = 0;
if (Q_strncasecmp(s, "status", 6) == 0)
ret = 1;
else if (Q_strncasecmp(s, "god", 3) == 0)
ret = 1;
else if (Q_strncasecmp(s, "notarget", 8) == 0)
ret = 1;
else if (Q_strncasecmp(s, "fly", 3) == 0)
ret = 1;
else if (Q_strncasecmp(s, "name", 4) == 0)
ret = 1;
else if (Q_strncasecmp(s, "noclip", 6) == 0)
ret = 1;
else if (Q_strncasecmp(s, "say", 3) == 0)
ret = 1;
else if (Q_strncasecmp(s, "say_team", 8) == 0)
ret = 1;
else if (Q_strncasecmp(s, "tell", 4) == 0)
ret = 1;
else if (Q_strncasecmp(s, "color", 5) == 0)
ret = 1;
else if (Q_strncasecmp(s, "kill", 4) == 0)
ret = 1;
else if (Q_strncasecmp(s, "pause", 5) == 0)
ret = 1;
else if (Q_strncasecmp(s, "spawn", 5) == 0)
ret = 1;
else if (Q_strncasecmp(s, "begin", 5) == 0)
ret = 1;
else if (Q_strncasecmp(s, "prespawn", 8) == 0)
ret = 1;
else if (Q_strncasecmp(s, "kick", 4) == 0)
ret = 1;
else if (Q_strncasecmp(s, "ping", 4) == 0)
ret = 1;
else if (Q_strncasecmp(s, "give", 4) == 0)
ret = 1;
else if (Q_strncasecmp(s, "ban", 3) == 0)
ret = 1;
if (ret == 2)
Cbuf_InsertText (s);
else if (ret == 1)
Cmd_ExecuteString (s, src_client);
else
Con_DPrintf("%s tried to %s\n", host_client->name, s);
break;
case clc_disconnect:
// Sys_Printf ("SV_ReadClientMessage: client disconnected\n");
return false;
case clc_move:
SV_ReadClientMove (&host_client->cmd);
break;
}
}
} while (ret == 1);
return true;
}
 
 
/*
==================
SV_RunClients
==================
*/
void SV_RunClients (void)
{
int i;
for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
{
if (!host_client->active)
continue;
sv_player = host_client->edict;
 
if (!SV_ReadClientMessage ())
{
SV_DropClient (false); // client misbehaved...
continue;
}
 
if (!host_client->spawned)
{
// clear client movement until a new packet is received
memset (&host_client->cmd, 0, sizeof(host_client->cmd));
continue;
}
 
// always pause in single player if in console or menus
if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game) )
SV_ClientThink ();
}
}
 
/contrib/other/sdlquake-1.0.9/sys.h
0,0 → 1,71
/*
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.
 
*/
// sys.h -- non-portable functions
 
//
// file IO
//
 
// returns the file size
// return -1 if file is not present
// the file should be in BINARY mode for stupid OSs that care
int Sys_FileOpenRead (char *path, int *hndl);
 
int Sys_FileOpenWrite (char *path);
void Sys_FileClose (int handle);
void Sys_FileSeek (int handle, int position);
int Sys_FileRead (int handle, void *dest, int count);
int Sys_FileWrite (int handle, void *data, int count);
int Sys_FileTime (char *path);
void Sys_mkdir (char *path);
 
//
// memory protection
//
void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length);
 
//
// system IO
//
void Sys_DebugLog(char *file, char *fmt, ...);
 
void Sys_Error (char *error, ...);
// an error will cause the entire program to exit
 
void Sys_Printf (char *fmt, ...);
// send text to the console
 
void Sys_Quit (void);
 
double Sys_FloatTime (void);
 
char *Sys_ConsoleInput (void);
 
void Sys_Sleep (void);
// called to yield for a little bit so as
// not to hog cpu when paused or debugging
 
void Sys_SendKeyEvents (void);
// Perform Key_Event () callbacks until the input que is empty
 
void Sys_LowFPPrecision (void);
void Sys_HighFPPrecision (void);
void Sys_SetFPCW (void);
 
/contrib/other/sdlquake-1.0.9/sys_dos.c
0,0 → 1,953
/*
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 <errno.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/time.h>
#include <sys/types.h>
#include <dir.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <sys/stat.h>
#include <string.h>
#include <dpmi.h>
#include <sys/nearptr.h>
#include <conio.h>
 
#include "quakedef.h"
#include "dosisms.h"
 
#define MINIMUM_WIN_MEMORY 0x800000
#define MINIMUM_WIN_MEMORY_LEVELPAK (MINIMUM_WIN_MEMORY + 0x100000)
 
int end_of_memory;
qboolean lockmem, lockunlockmem, unlockmem;
static int win95;
 
#define STDOUT 1
 
#define KEYBUF_SIZE 256
static unsigned char keybuf[KEYBUF_SIZE];
static int keybuf_head=0;
static int keybuf_tail=0;
 
static quakeparms_t quakeparms;
int sys_checksum;
static double curtime = 0.0;
static double lastcurtime = 0.0;
static double oldtime = 0.0;
 
static qboolean isDedicated;
 
static int minmem;
 
float fptest_temp;
 
extern char start_of_memory __asm__("start");
 
//=============================================================================
 
// this is totally dependent on cwsdpmi putting the stack right after tge
// global data
 
// This does evil things in a Win95 DOS box!!!
#if 0
extern byte end;
#define CHECKBYTE 0xed
void Sys_InitStackCheck (void)
{
int i;
for (i=0 ; i<128*1024 ; i++)
(&end)[i] = CHECKBYTE;
}
 
void Sys_StackCheck (void)
{
int i;
for (i=0 ; i<128*1024 ; i++)
if ( (&end)[i] != CHECKBYTE )
break;
Con_Printf ("%i undisturbed stack bytes\n", i);
if (end != CHECKBYTE)
Sys_Error ("System stack overflow!");
}
#endif
 
//=============================================================================
 
byte scantokey[128] =
{
// 0 1 2 3 4 5 6 7
// 8 9 A B C D E F
0 , 27, '1', '2', '3', '4', '5', '6',
'7', '8', '9', '0', '-', '=', K_BACKSPACE, 9, // 0
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
'o', 'p', '[', ']', 13 , K_CTRL,'a', 's', // 1
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
'\'' , '`', K_SHIFT,'\\', 'z', 'x', 'c', 'v', // 2
'b', 'n', 'm', ',', '.', '/', K_SHIFT,'*',
K_ALT,' ', 0 , K_F1, K_F2, K_F3, K_F4, K_F5, // 3
K_F6, K_F7, K_F8, K_F9, K_F10,0 , 0 , K_HOME,
K_UPARROW,K_PGUP,'-',K_LEFTARROW,'5',K_RIGHTARROW,'+',K_END, //4
K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0, 0, K_F11,
K_F12,0 , 0 , 0 , 0 , 0 , 0 , 0, // 5
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, // 6
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7
};
 
byte shiftscantokey[128] =
{
// 0 1 2 3 4 5 6 7
// 8 9 A B C D E F
0 , 27, '!', '@', '#', '$', '%', '^',
'&', '*', '(', ')', '_', '+', K_BACKSPACE, 9, // 0
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
'O', 'P', '{', '}', 13 , K_CTRL,'A', 'S', // 1
'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
'"' , '~', K_SHIFT,'|', 'Z', 'X', 'C', 'V', // 2
'B', 'N', 'M', '<', '>', '?', K_SHIFT,'*',
K_ALT,' ', 0 , K_F1, K_F2, K_F3, K_F4, K_F5, // 3
K_F6, K_F7, K_F8, K_F9, K_F10,0 , 0 , K_HOME,
K_UPARROW,K_PGUP,'_',K_LEFTARROW,'%',K_RIGHTARROW,'+',K_END, //4
K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0, 0, K_F11,
K_F12,0 , 0 , 0 , 0 , 0 , 0 , 0, // 5
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, // 6
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7
};
 
void TrapKey(void)
{
// static int ctrl=0;
keybuf[keybuf_head] = dos_inportb(0x60);
dos_outportb(0x20, 0x20);
/*
if (scantokey[keybuf[keybuf_head]&0x7f] == K_CTRL)
ctrl=keybuf[keybuf_head]&0x80;
if (ctrl && scantokey[keybuf[keybuf_head]&0x7f] == 'c')
Sys_Error("ctrl-c hit\n");
*/
keybuf_head = (keybuf_head + 1) & (KEYBUF_SIZE-1);
}
 
#define SC_UPARROW 0x48
#define SC_DOWNARROW 0x50
#define SC_LEFTARROW 0x4b
#define SC_RIGHTARROW 0x4d
#define SC_LEFTSHIFT 0x2a
#define SC_RIGHTSHIFT 0x36
#define SC_RIGHTARROW 0x4d
 
void MaskExceptions (void);
void Sys_InitFloatTime (void);
void Sys_PushFPCW_SetHigh (void);
void Sys_PopFPCW (void);
 
#define LEAVE_FOR_CACHE (512*1024) //FIXME: tune
#define LOCKED_FOR_MALLOC (128*1024) //FIXME: tune
 
 
void Sys_DetectWin95 (void)
{
__dpmi_regs r;
 
r.x.ax = 0x160a; /* Get Windows Version */
__dpmi_int(0x2f, &r);
 
if(r.x.ax || r.h.bh < 4) /* Not windows or earlier than Win95 */
{
win95 = 0;
lockmem = true;
lockunlockmem = false;
unlockmem = true;
}
else
{
win95 = 1;
lockunlockmem = COM_CheckParm ("-winlockunlock");
 
if (lockunlockmem)
lockmem = true;
else
lockmem = COM_CheckParm ("-winlock");
 
unlockmem = lockmem && !lockunlockmem;
}
}
 
 
void *dos_getmaxlockedmem(int *size)
{
__dpmi_free_mem_info meminfo;
__dpmi_meminfo info;
int working_size;
void *working_memory;
int last_locked;
int extra, i, j, allocsize;
static char *msg = "Locking data...";
int m, n;
byte *x;
// first lock all the current executing image so the locked count will
// be accurate. It doesn't hurt to lock the memory multiple times
last_locked = __djgpp_selector_limit + 1;
info.size = last_locked - 4096;
info.address = __djgpp_base_address + 4096;
 
if (lockmem)
{
if(__dpmi_lock_linear_region(&info))
{
Sys_Error ("Lock of current memory at 0x%lx for %ldKb failed!\n",
info.address, info.size/1024);
}
}
 
__dpmi_get_free_memory_information(&meminfo);
 
if (!win95) /* Not windows or earlier than Win95 */
{
working_size = meminfo.maximum_locked_page_allocation_in_pages * 4096;
}
else
{
working_size = meminfo.largest_available_free_block_in_bytes -
LEAVE_FOR_CACHE;
}
 
working_size &= ~0xffff; /* Round down to 64K */
working_size += 0x10000;
 
do
{
working_size -= 0x10000; /* Decrease 64K and try again */
working_memory = sbrk(working_size);
} while (working_memory == (void *)-1);
 
extra = 0xfffc - ((unsigned)sbrk(0) & 0xffff);
 
if (extra > 0)
{
sbrk(extra);
working_size += extra;
}
 
// now grab the memory
info.address = last_locked + __djgpp_base_address;
 
if (!win95)
{
info.size = __djgpp_selector_limit + 1 - last_locked;
 
while (info.size > 0 && __dpmi_lock_linear_region(&info))
{
info.size -= 0x1000;
working_size -= 0x1000;
sbrk(-0x1000);
}
}
else
{ /* Win95 section */
j = COM_CheckParm("-winmem");
 
if (standard_quake)
minmem = MINIMUM_WIN_MEMORY;
else
minmem = MINIMUM_WIN_MEMORY_LEVELPAK;
 
if (j)
{
allocsize = ((int)(Q_atoi(com_argv[j+1]))) * 0x100000 +
LOCKED_FOR_MALLOC;
 
if (allocsize < (minmem + LOCKED_FOR_MALLOC))
allocsize = minmem + LOCKED_FOR_MALLOC;
}
else
{
allocsize = minmem + LOCKED_FOR_MALLOC;
}
 
if (!lockmem)
{
// we won't lock, just sbrk the memory
info.size = allocsize;
goto UpdateSbrk;
}
 
// lock the memory down
write (STDOUT, msg, strlen (msg));
 
for (j=allocsize ; j>(minmem + LOCKED_FOR_MALLOC) ;
j -= 0x100000)
{
info.size = j;
if (!__dpmi_lock_linear_region(&info))
goto Locked;
write (STDOUT, ".", 1);
}
 
// finally, try with the absolute minimum amount
for (i=0 ; i<10 ; i++)
{
info.size = minmem + LOCKED_FOR_MALLOC;
 
if (!__dpmi_lock_linear_region(&info))
goto Locked;
}
 
Sys_Error ("Can't lock memory; %d Mb lockable RAM required. "
"Try shrinking smartdrv.", info.size / 0x100000);
 
Locked:
 
UpdateSbrk:
 
info.address += info.size;
info.address -= __djgpp_base_address + 4; // ending point, malloc align
working_size = info.address - (int)working_memory;
sbrk(info.address-(int)sbrk(0)); // negative adjustment
}
 
 
if (lockunlockmem)
{
__dpmi_unlock_linear_region (&info);
printf ("Locked and unlocked %d Mb data\n", working_size / 0x100000);
}
else if (lockmem)
{
printf ("Locked %d Mb data\n", working_size / 0x100000);
}
else
{
printf ("Allocated %d Mb data\n", working_size / 0x100000);
}
 
// touch all the memory to make sure it's there. The 16-page skip is to
// keep Win 95 from thinking we're trying to page ourselves in (we are
// doing that, of course, but there's no reason we shouldn't)
x = (byte *)working_memory;
 
for (n=0 ; n<4 ; n++)
{
for (m=0 ; m<(working_size - 16 * 0x1000) ; m += 4)
{
sys_checksum += *(int *)&x[m];
sys_checksum += *(int *)&x[m + 16 * 0x1000];
}
}
 
// give some of what we locked back for malloc before returning. Done
// by cheating and passing a negative value to sbrk
working_size -= LOCKED_FOR_MALLOC;
sbrk( -(LOCKED_FOR_MALLOC));
*size = working_size;
return working_memory;
}
 
 
/*
============
Sys_FileTime
 
returns -1 if not present
============
*/
int Sys_FileTime (char *path)
{
struct stat buf;
if (stat (path,&buf) == -1)
return -1;
return buf.st_mtime;
}
 
void Sys_mkdir (char *path)
{
mkdir (path, 0777);
}
 
 
void Sys_Sleep(void)
{
}
 
 
char *Sys_ConsoleInput(void)
{
static char text[256];
static int len = 0;
char ch;
 
if (!isDedicated)
return NULL;
 
if (! kbhit())
return NULL;
 
ch = getche();
 
switch (ch)
{
case '\r':
putch('\n');
if (len)
{
text[len] = 0;
len = 0;
return text;
}
break;
 
case '\b':
putch(' ');
if (len)
{
len--;
putch('\b');
}
break;
 
default:
text[len] = ch;
len = (len + 1) & 0xff;
break;
}
 
return NULL;
}
 
void Sys_Init(void)
{
 
MaskExceptions ();
 
Sys_SetFPCW ();
 
dos_outportb(0x43, 0x34); // set system timer to mode 2
dos_outportb(0x40, 0); // for the Sys_FloatTime() function
dos_outportb(0x40, 0);
 
Sys_InitFloatTime ();
 
_go32_interrupt_stack_size = 4 * 1024;;
_go32_rmcb_stack_size = 4 * 1024;
}
 
void Sys_Shutdown(void)
{
if (!isDedicated)
dos_restoreintr(9);
 
if (unlockmem)
{
dos_unlockmem (&start_of_memory,
end_of_memory - (int)&start_of_memory);
dos_unlockmem (quakeparms.membase, quakeparms.memsize);
}
}
 
 
#define SC_RSHIFT 0x36
#define SC_LSHIFT 0x2a
void Sys_SendKeyEvents (void)
{
int k, next;
int outkey;
 
// get key events
 
while (keybuf_head != keybuf_tail)
{
 
k = keybuf[keybuf_tail++];
keybuf_tail &= (KEYBUF_SIZE-1);
 
if (k==0xe0)
continue; // special / pause keys
next = keybuf[(keybuf_tail-2)&(KEYBUF_SIZE-1)];
if (next == 0xe1)
continue; // pause key bullshit
if (k==0xc5 && next == 0x9d)
{
Key_Event (K_PAUSE, true);
continue;
}
 
// extended keyboard shift key bullshit
if ( (k&0x7f)==SC_LSHIFT || (k&0x7f)==SC_RSHIFT )
{
if ( keybuf[(keybuf_tail-2)&(KEYBUF_SIZE-1)]==0xe0 )
continue;
k &= 0x80;
k |= SC_RSHIFT;
}
 
if (k==0xc5 && keybuf[(keybuf_tail-2)&(KEYBUF_SIZE-1)] == 0x9d)
continue; // more pause bullshit
 
outkey = scantokey[k & 0x7f];
 
if (k & 0x80)
Key_Event (outkey, false);
else
Key_Event (outkey, true);
 
}
 
}
 
 
// =======================================================================
// General routines
// =======================================================================
 
/*
================
Sys_Printf
================
*/
 
void Sys_Printf (char *fmt, ...)
{
va_list argptr;
char text[1024];
va_start (argptr,fmt);
vsprintf (text,fmt,argptr);
va_end (argptr);
 
if (cls.state == ca_dedicated)
fprintf(stderr, "%s", text);
}
 
void Sys_AtExit (void)
{
 
// shutdown only once (so Sys_Error can call this function to shutdown, then
// print the error message, then call exit without exit calling this function
// again)
Sys_Shutdown();
}
 
 
void Sys_Quit (void)
{
byte screen[80*25*2];
byte *d;
char ver[6];
int i;
 
// load the sell screen before shuting everything down
if (registered.value)
d = COM_LoadHunkFile ("end2.bin");
else
d = COM_LoadHunkFile ("end1.bin");
if (d)
memcpy (screen, d, sizeof(screen));
 
// write the version number directly to the end screen
sprintf (ver, " v%4.2f", VERSION);
for (i=0 ; i<6 ; i++)
screen[0*80*2 + 72*2 + i*2] = ver[i];
 
Host_Shutdown();
 
// do the text mode sell screen
if (d)
{
memcpy ((void *)real2ptr(0xb8000), screen,80*25*2);
// set text pos
regs.x.ax = 0x0200;
regs.h.bh = 0;
regs.h.dl = 0;
regs.h.dh = 22;
dos_int86 (0x10);
}
else
printf ("couldn't load endscreen.\n");
 
exit(0);
}
 
void Sys_Error (char *error, ...)
{
va_list argptr;
char string[1024];
va_start (argptr,error);
vsprintf (string,error,argptr);
va_end (argptr);
 
Host_Shutdown();
fprintf(stderr, "Error: %s\n", string);
// Sys_AtExit is called by exit to shutdown the system
exit(0);
}
 
 
int Sys_FileOpenRead (char *path, int *handle)
{
int h;
struct stat fileinfo;
h = open (path, O_RDONLY|O_BINARY, 0666);
*handle = h;
if (h == -1)
return -1;
if (fstat (h,&fileinfo) == -1)
Sys_Error ("Error fstating %s", path);
 
return fileinfo.st_size;
}
 
int Sys_FileOpenWrite (char *path)
{
int handle;
 
umask (0);
handle = open(path,O_RDWR | O_BINARY | O_CREAT | O_TRUNC
, 0666);
 
if (handle == -1)
Sys_Error ("Error opening %s: %s", path,strerror(errno));
 
return handle;
}
 
void Sys_FileClose (int handle)
{
close (handle);
}
 
void Sys_FileSeek (int handle, int position)
{
lseek (handle, position, SEEK_SET);
}
 
int Sys_FileRead (int handle, void *dest, int count)
{
return read (handle, dest, count);
}
 
int Sys_FileWrite (int handle, void *data, int count)
{
return write (handle, data, count);
}
 
/*
================
Sys_MakeCodeWriteable
================
*/
void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
{
// it's always writeable
}
 
 
/*
================
Sys_FloatTime
================
*/
double Sys_FloatTime (void)
{
int r;
unsigned t, tick;
double ft, time;
static int sametimecount;
 
Sys_PushFPCW_SetHigh ();
 
//{static float t = 0; t=t+0.05; return t;} // DEBUG
 
t = *(unsigned short*)real2ptr(0x46c) * 65536;
 
dos_outportb(0x43, 0); // latch time
r = dos_inportb(0x40);
r |= dos_inportb(0x40) << 8;
r = (r-1) & 0xffff;
 
tick = *(unsigned short*)real2ptr(0x46c) * 65536;
if ((tick != t) && (r & 0x8000))
t = tick;
 
ft = (double) (t+(65536-r)) / 1193200.0;
time = ft - oldtime;
oldtime = ft;
 
if (time < 0)
{
if (time > -3000.0)
time = 0.0;
else
time += 3600.0;
}
 
curtime += time;
 
if (curtime == lastcurtime)
{
sametimecount++;
 
if (sametimecount > 100000)
{
curtime += 1.0;
sametimecount = 0;
}
}
else
{
sametimecount = 0;
}
 
lastcurtime = curtime;
 
Sys_PopFPCW ();
 
return curtime;
}
 
 
/*
================
Sys_InitFloatTime
================
*/
void Sys_InitFloatTime (void)
{
int j;
 
Sys_FloatTime ();
 
oldtime = curtime;
 
j = COM_CheckParm("-starttime");
 
if (j)
{
curtime = (double) (Q_atof(com_argv[j+1]));
}
else
{
curtime = 0.0;
}
lastcurtime = curtime;
}
 
 
/*
================
Sys_GetMemory
================
*/
void Sys_GetMemory(void)
{
int j, tsize;
 
j = COM_CheckParm("-mem");
if (j)
{
quakeparms.memsize = (int) (Q_atof(com_argv[j+1]) * 1024 * 1024);
quakeparms.membase = malloc (quakeparms.memsize);
}
else
{
quakeparms.membase = dos_getmaxlockedmem (&quakeparms.memsize);
}
 
fprintf(stderr, "malloc'd: %d\n", quakeparms.memsize);
 
if (COM_CheckParm ("-heapsize"))
{
tsize = Q_atoi (com_argv[COM_CheckParm("-heapsize") + 1]) * 1024;
 
if (tsize < quakeparms.memsize)
quakeparms.memsize = tsize;
}
}
 
 
/*
================
Sys_PageInProgram
 
walks the text, data, and bss to make sure it's all paged in so that the
actual physical memory detected by Sys_GetMemory is correct.
================
*/
void Sys_PageInProgram(void)
{
int i, j;
 
end_of_memory = (int)sbrk(0);
 
if (lockmem)
{
if (dos_lockmem ((void *)&start_of_memory,
end_of_memory - (int)&start_of_memory))
Sys_Error ("Couldn't lock text and data");
}
 
if (lockunlockmem)
{
dos_unlockmem((void *)&start_of_memory,
end_of_memory - (int)&start_of_memory);
printf ("Locked and unlocked %d Mb image\n",
(end_of_memory - (int)&start_of_memory) / 0x100000);
}
else if (lockmem)
{
printf ("Locked %d Mb image\n",
(end_of_memory - (int)&start_of_memory) / 0x100000);
}
else
{
printf ("Loaded %d Mb image\n",
(end_of_memory - (int)&start_of_memory) / 0x100000);
}
 
// touch the entire image, doing the 16-page skip so Win95 doesn't think we're
// trying to page ourselves in
for (j=0 ; j<4 ; j++)
{
for(i=(int)&start_of_memory ; i<(end_of_memory - 16 * 0x1000) ; i += 4)
{
sys_checksum += *(int *)i;
sys_checksum += *(int *)(i + 16 * 0x1000);
}
}
}
 
 
/*
================
Sys_NoFPUExceptionHandler
================
*/
void Sys_NoFPUExceptionHandler(int whatever)
{
printf ("\nError: Quake requires a floating-point processor\n");
exit (0);
}
 
 
/*
================
Sys_DefaultExceptionHandler
================
*/
void Sys_DefaultExceptionHandler(int whatever)
{
}
 
 
/*
================
main
================
*/
int main (int c, char **v)
{
double time, oldtime, newtime;
extern void (*dos_error_func)(char *, ...);
static char cwd[1024];
 
printf ("Quake v%4.2f\n", VERSION);
// make sure there's an FPU
signal(SIGNOFP, Sys_NoFPUExceptionHandler);
signal(SIGABRT, Sys_DefaultExceptionHandler);
signal(SIGALRM, Sys_DefaultExceptionHandler);
signal(SIGKILL, Sys_DefaultExceptionHandler);
signal(SIGQUIT, Sys_DefaultExceptionHandler);
signal(SIGINT, Sys_DefaultExceptionHandler);
 
if (fptest_temp >= 0.0)
fptest_temp += 0.1;
 
COM_InitArgv (c, v);
 
quakeparms.argc = com_argc;
quakeparms.argv = com_argv;
 
dos_error_func = Sys_Error;
 
Sys_DetectWin95 ();
Sys_PageInProgram ();
Sys_GetMemory ();
 
atexit (Sys_AtExit); // in case we crash
 
getwd (cwd);
if (cwd[Q_strlen(cwd)-1] == '/') cwd[Q_strlen(cwd)-1] = 0;
quakeparms.basedir = cwd; //"f:/quake";
 
isDedicated = (COM_CheckParm ("-dedicated") != 0);
 
Sys_Init ();
 
if (!isDedicated)
dos_registerintr(9, TrapKey);
 
//Sys_InitStackCheck ();
Host_Init(&quakeparms);
 
//Sys_StackCheck ();
 
//Con_Printf ("Top of stack: 0x%x\n", &time);
oldtime = Sys_FloatTime ();
while (1)
{
newtime = Sys_FloatTime ();
time = newtime - oldtime;
 
if (cls.state == ca_dedicated && (time<sys_ticrate.value))
continue;
 
Host_Frame (time);
 
//Sys_StackCheck ();
 
oldtime = newtime;
}
}
 
 
/contrib/other/sdlquake-1.0.9/sys_dosa.S
0,0 → 1,98
//
// sys_dosa.s
// x86 assembly-language DOS-dependent routines.
 
#include "asm_i386.h"
#include "quakeasm.h"
 
 
#if id386
 
.data
 
.align 4
fpenv:
.long 0, 0, 0, 0, 0, 0, 0, 0
 
.text
 
.globl C(MaskExceptions)
C(MaskExceptions):
fnstenv fpenv
orl $0x3F,fpenv
fldenv fpenv
 
ret
 
#if 0
.globl C(unmaskexceptions)
C(unmaskexceptions):
fnstenv fpenv
andl $0xFFFFFFE0,fpenv
fldenv fpenv
 
ret
#endif
 
.data
 
.align 4
.globl ceil_cw, single_cw, full_cw, cw, pushed_cw
ceil_cw: .long 0
single_cw: .long 0
full_cw: .long 0
cw: .long 0
pushed_cw: .long 0
 
.text
 
.globl C(Sys_LowFPPrecision)
C(Sys_LowFPPrecision):
fldcw single_cw
 
ret
 
.globl C(Sys_HighFPPrecision)
C(Sys_HighFPPrecision):
fldcw full_cw
 
ret
 
.globl C(Sys_PushFPCW_SetHigh)
C(Sys_PushFPCW_SetHigh):
fnstcw pushed_cw
fldcw full_cw
 
ret
 
.globl C(Sys_PopFPCW)
C(Sys_PopFPCW):
fldcw pushed_cw
 
ret
 
.globl C(Sys_SetFPCW)
C(Sys_SetFPCW):
fnstcw cw
movl cw,%eax
#if id386
andb $0xF0,%ah
orb $0x03,%ah // round mode, 64-bit precision
#endif
movl %eax,full_cw
 
#if id386
andb $0xF0,%ah
orb $0x0C,%ah // chop mode, single precision
#endif
movl %eax,single_cw
 
#if id386
andb $0xF0,%ah
orb $0x08,%ah // ceil mode, single precision
#endif
movl %eax,ceil_cw
 
ret
 
#endif
/contrib/other/sdlquake-1.0.9/sys_linux.c
0,0 → 1,457
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <string.h>
#include <ctype.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <errno.h>
 
#include "quakedef.h"
 
qboolean isDedicated;
 
int nostdout = 0;
 
char *basedir = ".";
char *cachedir = "/tmp";
 
cvar_t sys_linerefresh = {"sys_linerefresh","0"};// set for entity display
 
// =======================================================================
// General routines
// =======================================================================
 
void Sys_DebugNumber(int y, int val)
{
}
 
/*
void Sys_Printf (char *fmt, ...)
{
va_list argptr;
char text[1024];
va_start (argptr,fmt);
vsprintf (text,fmt,argptr);
va_end (argptr);
fprintf(stderr, "%s", text);
Con_Print (text);
}
 
void Sys_Printf (char *fmt, ...)
{
 
va_list argptr;
char text[1024], *t_p;
int l, r;
 
if (nostdout)
return;
 
va_start (argptr,fmt);
vsprintf (text,fmt,argptr);
va_end (argptr);
 
l = strlen(text);
t_p = text;
 
// make sure everything goes through, even though we are non-blocking
while (l)
{
r = write (1, text, l);
if (r != l)
sleep (0);
if (r > 0)
{
t_p += r;
l -= r;
}
}
 
}
*/
 
void Sys_Printf (char *fmt, ...)
{
va_list argptr;
char text[1024];
unsigned char *p;
 
va_start (argptr,fmt);
vsprintf (text,fmt,argptr);
va_end (argptr);
 
if (strlen(text) > sizeof(text))
Sys_Error("memory overwrite in Sys_Printf");
 
if (nostdout)
return;
 
for (p = (unsigned char *)text; *p; p++) {
*p &= 0x7f;
if ((*p > 128 || *p < 32) && *p != 10 && *p != 13 && *p != 9)
printf("[%02x]", *p);
else
putc(*p, stdout);
}
}
 
#if 0
static char end1[] =
"\x1b[?7h\x1b[40m\x1b[2J\x1b[0;1;41m\x1b[1;1H QUAKE: The Doomed Dimension \x1b[33mby \x1b[44mid\x1b[41m Software \x1b[2;1H ---------------------------------------------------------------------------- \x1b[3;1H CALL 1-800-IDGAMES TO ORDER OR FOR TECHNICAL SUPPORT \x1b[4;1H PRICE: $45.00 (PRICES MAY VARY OUTSIDE THE US.) \x1b[5;1H \x1b[6;1H \x1b[37mYes! You only have one fourth of this incredible epic. That is because most \x1b[7;1H of you have paid us nothing or at most, very little. You could steal the \x1b[8;1H game from a friend. But we both know you'll be punished by God if you do. \x1b[9;1H \x1b[33mWHY RISK ETERNAL DAMNATION? CALL 1-800-IDGAMES AND BUY NOW! \x1b[10;1H \x1b[37mRemember, we love you almost as much as He does. \x1b[11;1H \x1b[12;1H \x1b[33mProgramming: \x1b[37mJohn Carmack, Michael Abrash, John Cash \x1b[13;1H \x1b[33mDesign: \x1b[37mJohn Romero, Sandy Petersen, American McGee, Tim Willits \x1b[14;1H \x1b[33mArt: \x1b[37mAdrian Carmack, Kevin Cloud \x1b[15;1H \x1b[33mBiz: \x1b[37mJay Wilbur, Mike Wilson, Donna Jackson \x1b[16;1H \x1b[33mProjects: \x1b[37mShawn Green \x1b[33mSupport: \x1b[37mBarrett Alexander \x1b[17;1H \x1b[33mSound Effects: \x1b[37mTrent Reznor and Nine Inch Nails \x1b[18;1H For other information or details on ordering outside the US, check out the \x1b[19;1H files accompanying QUAKE or our website at http://www.idsoftware.com. \x1b[20;1H \x1b[0;41mQuake is a trademark of Id Software, inc., (c)1996 Id Software, inc. \x1b[21;1H All rights reserved. NIN logo is a registered trademark licensed to \x1b[22;1H Nothing Interactive, Inc. All rights reserved. \x1b[40m\x1b[23;1H\x1b[0m";
static char end2[] =
"\x1b[?7h\x1b[40m\x1b[2J\x1b[0;1;41m\x1b[1;1H QUAKE \x1b[33mby \x1b[44mid\x1b[41m Software \x1b[2;1H ----------------------------------------------------------------------------- \x1b[3;1H \x1b[37mWhy did you quit from the registered version of QUAKE? Did the \x1b[4;1H scary monsters frighten you? Or did Mr. Sandman tug at your \x1b[5;1H little lids? No matter! What is important is you love our \x1b[6;1H game, and gave us your money. Congratulations, you are probably \x1b[7;1H not a thief. \x1b[8;1H Thank You. \x1b[9;1H \x1b[33;44mid\x1b[41m Software is: \x1b[10;1H PROGRAMMING: \x1b[37mJohn Carmack, Michael Abrash, John Cash \x1b[11;1H \x1b[33mDESIGN: \x1b[37mJohn Romero, Sandy Petersen, American McGee, Tim Willits \x1b[12;1H \x1b[33mART: \x1b[37mAdrian Carmack, Kevin Cloud \x1b[13;1H \x1b[33mBIZ: \x1b[37mJay Wilbur, Mike Wilson \x1b[33mPROJECTS MAN: \x1b[37mShawn Green \x1b[14;1H \x1b[33mBIZ ASSIST: \x1b[37mDonna Jackson \x1b[33mSUPPORT: \x1b[37mBarrett Alexander \x1b[15;1H \x1b[33mSOUND EFFECTS AND MUSIC: \x1b[37mTrent Reznor and Nine Inch Nails \x1b[16;1H \x1b[17;1H If you need help running QUAKE refer to the text files in the \x1b[18;1H QUAKE directory, or our website at http://www.idsoftware.com. \x1b[19;1H If all else fails, call our technical support at 1-800-IDGAMES. \x1b[20;1H \x1b[0;41mQuake is a trademark of Id Software, inc., (c)1996 Id Software, inc. \x1b[21;1H All rights reserved. NIN logo is a registered trademark licensed \x1b[22;1H to Nothing Interactive, Inc. All rights reserved. \x1b[23;1H\x1b[40m\x1b[0m";
 
#endif
void Sys_Quit (void)
{
Host_Shutdown();
fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
#if 0
if (registered.value)
printf("%s", end2);
else
printf("%s", end1);
#endif
fflush(stdout);
exit(0);
}
 
void Sys_Init(void)
{
#if id386
Sys_SetFPCW();
#endif
}
 
void Sys_Error (char *error, ...)
{
va_list argptr;
char string[1024];
 
// change stdin to non blocking
fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
va_start (argptr,error);
vsprintf (string,error,argptr);
va_end (argptr);
fprintf(stderr, "Error: %s\n", string);
 
Host_Shutdown ();
exit (1);
 
}
 
void Sys_Warn (char *warning, ...)
{
va_list argptr;
char string[1024];
va_start (argptr,warning);
vsprintf (string,warning,argptr);
va_end (argptr);
fprintf(stderr, "Warning: %s", string);
}
 
/*
============
Sys_FileTime
 
returns -1 if not present
============
*/
int Sys_FileTime (char *path)
{
struct stat buf;
if (stat (path,&buf) == -1)
return -1;
return buf.st_mtime;
}
 
 
void Sys_mkdir (char *path)
{
mkdir (path, 0777);
}
 
int Sys_FileOpenRead (char *path, int *handle)
{
int h;
struct stat fileinfo;
h = open (path, O_RDONLY, 0666);
*handle = h;
if (h == -1)
return -1;
if (fstat (h,&fileinfo) == -1)
Sys_Error ("Error fstating %s", path);
 
return fileinfo.st_size;
}
 
int Sys_FileOpenWrite (char *path)
{
int handle;
 
umask (0);
handle = open(path,O_RDWR | O_CREAT | O_TRUNC
, 0666);
 
if (handle == -1)
Sys_Error ("Error opening %s: %s", path,strerror(errno));
 
return handle;
}
 
int Sys_FileWrite (int handle, void *src, int count)
{
return write (handle, src, count);
}
 
void Sys_FileClose (int handle)
{
close (handle);
}
 
void Sys_FileSeek (int handle, int position)
{
lseek (handle, position, SEEK_SET);
}
 
int Sys_FileRead (int handle, void *dest, int count)
{
return read (handle, dest, count);
}
 
void Sys_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_BINARY | O_CREAT | O_APPEND, 0666);
fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666);
write(fd, data, strlen(data));
close(fd);
}
 
void Sys_EditFile(char *filename)
{
 
char cmd[256];
char *term;
char *editor;
 
term = getenv("TERM");
if (term && !strcmp(term, "xterm"))
{
editor = getenv("VISUAL");
if (!editor)
editor = getenv("EDITOR");
if (!editor)
editor = getenv("EDIT");
if (!editor)
editor = "vi";
sprintf(cmd, "xterm -e %s %s", editor, filename);
system(cmd);
}
 
}
 
double Sys_FloatTime (void)
{
struct timeval tp;
struct timezone tzp;
static int secbase;
gettimeofday(&tp, &tzp);
 
if (!secbase)
{
secbase = tp.tv_sec;
return tp.tv_usec/1000000.0;
}
 
return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
}
 
// =======================================================================
// Sleeps for microseconds
// =======================================================================
 
static volatile int oktogo;
 
void alarm_handler(int x)
{
oktogo=1;
}
 
void Sys_LineRefresh(void)
{
}
 
void floating_point_exception_handler(int whatever)
{
// Sys_Warn("floating point exception\n");
signal(SIGFPE, floating_point_exception_handler);
}
 
char *Sys_ConsoleInput(void)
{
static char text[256];
int len;
fd_set fdset;
struct timeval timeout;
 
if (cls.state == ca_dedicated) {
FD_ZERO(&fdset);
FD_SET(0, &fdset); // stdin
timeout.tv_sec = 0;
timeout.tv_usec = 0;
if (select (1, &fdset, NULL, NULL, &timeout) == -1 || !FD_ISSET(0, &fdset))
return NULL;
 
len = read (0, text, sizeof(text));
if (len < 1)
return NULL;
text[len-1] = 0; // rip off the /n and terminate
 
return text;
}
return NULL;
}
 
#if !id386
void Sys_HighFPPrecision (void)
{
}
 
void Sys_LowFPPrecision (void)
{
}
#endif
 
int main (int c, char **v)
{
 
double time, oldtime, newtime;
quakeparms_t parms;
extern int vcrFile;
extern int recording;
int j;
 
// static char cwd[1024];
 
// signal(SIGFPE, floating_point_exception_handler);
signal(SIGFPE, SIG_IGN);
 
memset(&parms, 0, sizeof(parms));
 
COM_InitArgv(c, v);
parms.argc = com_argc;
parms.argv = com_argv;
 
#ifdef GLQUAKE
parms.memsize = 16*1024*1024;
#else
parms.memsize = 8*1024*1024;
#endif
 
j = COM_CheckParm("-mem");
if (j)
parms.memsize = (int) (Q_atof(com_argv[j+1]) * 1024 * 1024);
parms.membase = malloc (parms.memsize);
 
parms.basedir = basedir;
// caching is disabled by default, use -cachedir to enable
// parms.cachedir = cachedir;
 
fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
 
Host_Init(&parms);
 
Sys_Init();
 
if (COM_CheckParm("-nostdout"))
nostdout = 1;
else {
fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
printf ("Linux Quake -- Version %0.3f\n", LINUX_VERSION);
}
 
oldtime = Sys_FloatTime () - 0.1;
while (1)
{
// find time spent rendering last frame
newtime = Sys_FloatTime ();
time = newtime - oldtime;
 
if (cls.state == ca_dedicated)
{ // play vcrfiles at max speed
if (time < sys_ticrate.value && (vcrFile == -1 || recording) )
{
usleep(1);
continue; // not time to run a server only tic yet
}
time = sys_ticrate.value;
}
 
if (time > sys_ticrate.value*2)
oldtime = newtime;
else
oldtime += time;
 
Host_Frame (time);
 
// graphic debugging aids
if (sys_linerefresh.value)
Sys_LineRefresh ();
}
 
}
 
 
/*
================
Sys_MakeCodeWriteable
================
*/
void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
{
 
int r;
unsigned long addr;
int psize = getpagesize();
 
addr = (startaddr & ~(psize-1)) - psize;
 
// fprintf(stderr, "writable code %lx(%lx)-%lx, length=%lx\n", startaddr,
// addr, startaddr+length, length);
 
r = mprotect((char*)addr, length + startaddr - addr + psize, 7);
 
if (r < 0)
Sys_Error("Protection change failed\n");
 
}
 
/contrib/other/sdlquake-1.0.9/sys_null.c
0,0 → 1,232
/*
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.
 
*/
// sys_null.h -- null system driver to aid porting efforts
 
#include "quakedef.h"
#include "errno.h"
 
/*
===============================================================================
 
FILE IO
 
===============================================================================
*/
 
#define MAX_HANDLES 10
FILE *sys_handles[MAX_HANDLES];
 
int findhandle (void)
{
int i;
for (i=1 ; i<MAX_HANDLES ; i++)
if (!sys_handles[i])
return i;
Sys_Error ("out of handles");
return -1;
}
 
/*
================
filelength
================
*/
int filelength (FILE *f)
{
int pos;
int end;
 
pos = ftell (f);
fseek (f, 0, SEEK_END);
end = ftell (f);
fseek (f, pos, SEEK_SET);
 
return end;
}
 
int Sys_FileOpenRead (char *path, int *hndl)
{
FILE *f;
int i;
i = findhandle ();
 
f = fopen(path, "rb");
if (!f)
{
*hndl = -1;
return -1;
}
sys_handles[i] = f;
*hndl = i;
return filelength(f);
}
 
int Sys_FileOpenWrite (char *path)
{
FILE *f;
int i;
i = findhandle ();
 
f = fopen(path, "wb");
if (!f)
Sys_Error ("Error opening %s: %s", path,strerror(errno));
sys_handles[i] = f;
return i;
}
 
void Sys_FileClose (int handle)
{
fclose (sys_handles[handle]);
sys_handles[handle] = NULL;
}
 
void Sys_FileSeek (int handle, int position)
{
fseek (sys_handles[handle], position, SEEK_SET);
}
 
int Sys_FileRead (int handle, void *dest, int count)
{
return fread (dest, 1, count, sys_handles[handle]);
}
 
int Sys_FileWrite (int handle, void *data, int count)
{
return fwrite (data, 1, count, sys_handles[handle]);
}
 
int Sys_FileTime (char *path)
{
FILE *f;
f = fopen(path, "rb");
if (f)
{
fclose(f);
return 1;
}
return -1;
}
 
void Sys_mkdir (char *path)
{
}
 
 
/*
===============================================================================
 
SYSTEM IO
 
===============================================================================
*/
 
void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
{
}
 
 
void Sys_Error (char *error, ...)
{
va_list argptr;
 
printf ("Sys_Error: ");
va_start (argptr,error);
vprintf (error,argptr);
va_end (argptr);
printf ("\n");
 
exit (1);
}
 
void Sys_Printf (char *fmt, ...)
{
va_list argptr;
va_start (argptr,fmt);
vprintf (fmt,argptr);
va_end (argptr);
}
 
void Sys_Quit (void)
{
exit (0);
}
 
double Sys_FloatTime (void)
{
static double t;
t += 0.1;
return t;
}
 
char *Sys_ConsoleInput (void)
{
return NULL;
}
 
void Sys_Sleep (void)
{
}
 
void Sys_SendKeyEvents (void)
{
}
 
void Sys_HighFPPrecision (void)
{
}
 
void Sys_LowFPPrecision (void)
{
}
 
//=============================================================================
 
void main (int argc, char **argv)
{
static quakeparms_t parms;
 
parms.memsize = 8*1024*1024;
parms.membase = malloc (parms.memsize);
parms.basedir = ".";
 
COM_InitArgv (argc, argv);
 
parms.argc = com_argc;
parms.argv = com_argv;
 
printf ("Host_Init\n");
Host_Init (&parms);
while (1)
{
Host_Frame (0.1);
}
}
 
 
/contrib/other/sdlquake-1.0.9/sys_sdl.c
0,0 → 1,489
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#if !defined(__WIN32__) && !defined(_KOLIBRI)
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/mman.h>
#endif
 
#include "quakedef.h"
 
qboolean isDedicated;
 
int noconinput = 0;
 
char *basedir = ".";
 
cvar_t sys_linerefresh = {"sys_linerefresh","0"};// set for entity display
cvar_t sys_nostdout = {"sys_nostdout","0"};
 
// =======================================================================
// General routines
// =======================================================================
 
void Sys_DebugNumber(int y, int val)
{
}
 
void Sys_Printf (char *fmt, ...)
{
va_list argptr;
char text[1024];
va_start (argptr,fmt);
vsprintf (text,fmt,argptr);
va_end (argptr);
#ifdef _KOLIBRI
__menuet__debug_out(text);
#else
fprintf(stderr, "%s", text);
#endif
//Con_Print (text);
}
 
void Sys_Quit (void)
{
Host_Shutdown();
exit(0);
}
 
void Sys_Init(void)
{
#if id386
Sys_SetFPCW();
#endif
}
 
#if !id386
 
/*
================
Sys_LowFPPrecision
================
*/
void Sys_LowFPPrecision (void)
{
// causes weird problems on Nextstep
}
 
 
/*
================
Sys_HighFPPrecision
================
*/
void Sys_HighFPPrecision (void)
{
// causes weird problems on Nextstep
}
 
#endif // !id386
 
 
void Sys_Error (char *error, ...)
{
va_list argptr;
char string[1024];
 
va_start (argptr,error);
vsprintf (string,error,argptr);
va_end (argptr);
#ifdef _KOLIBRI
__menuet__debug_out("Error: ");
__menuet__debug_out(string);
__menuet__debug_out("\n");
#else
fprintf(stderr, "Error: %s\n", string);
#endif
 
Host_Shutdown ();
exit (1);
 
}
 
void Sys_Warn (char *warning, ...)
{
va_list argptr;
char string[1024];
va_start (argptr,warning);
vsprintf (string,warning,argptr);
va_end (argptr);
#ifdef _KOLIBRI
__menuet__debug_out("Warning: ");
__menuet__debug_out(string);
#else
fprintf(stderr, "Warning: %s", string);
#endif
}
 
/*
===============================================================================
 
FILE IO
 
===============================================================================
*/
 
#define MAX_HANDLES 10
FILE *sys_handles[MAX_HANDLES];
 
int findhandle (void)
{
int i;
for (i=1 ; i<MAX_HANDLES ; i++)
if (!sys_handles[i])
return i;
Sys_Error ("out of handles");
return -1;
}
 
/*
================
Qfilelength
================
*/
static int Qfilelength (FILE *f)
{
int pos;
int end;
 
pos = ftell (f);
fseek (f, 0, SEEK_END);
end = ftell (f);
fseek (f, pos, SEEK_SET);
 
return end;
}
 
int Sys_FileOpenRead (char *path, int *hndl)
{
FILE *f;
int i;
i = findhandle ();
 
f = fopen(path, "rb");
if (!f)
{
*hndl = -1;
return -1;
}
sys_handles[i] = f;
*hndl = i;
return Qfilelength(f);
}
 
int Sys_FileOpenWrite (char *path)
{
FILE *f;
int i;
i = findhandle ();
 
f = fopen(path, "wb");
if (!f)
Sys_Error ("Error opening %s: %s", path,strerror(errno));
sys_handles[i] = f;
return i;
}
 
void Sys_FileClose (int handle)
{
if ( handle >= 0 ) {
fclose (sys_handles[handle]);
sys_handles[handle] = NULL;
}
}
 
void Sys_FileSeek (int handle, int position)
{
if ( handle >= 0 ) {
fseek (sys_handles[handle], position, SEEK_SET);
}
}
 
int Sys_FileRead (int handle, void *dst, int count)
{
char *data;
int size, done;
 
size = 0;
if ( handle >= 0 ) {
data = dst;
while ( count > 0 ) {
done = fread (data, 1, count, sys_handles[handle]);
if ( done == 0 ) {
break;
}
data += done;
count -= done;
size += done;
}
}
return size;
}
 
int Sys_FileWrite (int handle, void *src, int count)
{
char *data;
int size, done;
 
size = 0;
if ( handle >= 0 ) {
data = src;
while ( count > 0 ) {
done = fread (data, 1, count, sys_handles[handle]);
if ( done == 0 ) {
break;
}
data += done;
count -= done;
size += done;
}
}
return size;
}
 
int Sys_FileTime (char *path)
{
FILE *f;
f = fopen(path, "rb");
if (f)
{
fclose(f);
return 1;
}
return -1;
}
 
void Sys_mkdir (char *path)
{
#ifdef __WIN32__
mkdir (path);
#else
mkdir (path, 0777);
#endif
}
 
void Sys_DebugLog(char *file, char *fmt, ...)
{
va_list argptr;
static char data[1024];
FILE *fp;
va_start(argptr, fmt);
vsprintf(data, fmt, argptr);
va_end(argptr);
fp = fopen(file, "a");
fwrite(data, strlen(data), 1, fp);
fclose(fp);
}
 
double Sys_FloatTime (void)
{
#if defined(_KOLIBRI)
static int starttime = 0;
 
if ( ! starttime )
__asm__ __volatile__("int $0x40" : "=a"(starttime) : "a"(26), "b"(9));
 
int curtime;
__asm__ __volatile__("int $0x40" : "=a"(curtime) : "a"(26), "b"(9));
return (curtime-starttime)*0.01;
#elif defined(__WIN32__)
 
static int starttime = 0;
 
if ( ! starttime )
starttime = clock();
 
return (clock()-starttime)*1.0/1024;
 
#else
 
struct timeval tp;
struct timezone tzp;
static int secbase;
gettimeofday(&tp, &tzp);
 
if (!secbase)
{
secbase = tp.tv_sec;
return tp.tv_usec/1000000.0;
}
 
return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
 
#endif
}
 
// =======================================================================
// Sleeps for microseconds
// =======================================================================
 
static volatile int oktogo;
 
void alarm_handler(int x)
{
oktogo=1;
}
 
byte *Sys_ZoneBase (int *size)
{
 
char *QUAKEOPT = getenv("QUAKEOPT");
 
*size = 0xc00000;
if (QUAKEOPT)
{
while (*QUAKEOPT)
if (tolower(*QUAKEOPT++) == 'm')
{
*size = atof(QUAKEOPT) * 1024*1024;
break;
}
}
return malloc (*size);
 
}
 
void Sys_LineRefresh(void)
{
}
 
void Sys_Sleep(void)
{
#ifdef _KOLIBRI
__menuet__delay100(1);
#else
SDL_Delay(1);
#endif
}
 
#ifndef _KOLIBRI
void floating_point_exception_handler(int whatever)
{
// Sys_Warn("floating point exception\n");
signal(SIGFPE, floating_point_exception_handler);
}
#endif
 
void moncontrol(int x)
{
}
 
int main (int c, char **v)
{
 
double time, oldtime, newtime;
quakeparms_t parms;
extern int vcrFile;
extern qboolean recording;
static int frame;
 
moncontrol(0);
 
#ifndef _KOLIBRI
// signal(SIGFPE, floating_point_exception_handler);
signal(SIGFPE, SIG_IGN);
#endif
 
parms.memsize = 8*1024*1024;
parms.membase = malloc (parms.memsize);
parms.basedir = basedir;
parms.cachedir = NULL;
 
COM_InitArgv(c, v);
parms.argc = com_argc;
parms.argv = com_argv;
 
Sys_Init();
 
Host_Init(&parms);
 
Cvar_RegisterVariable (&sys_nostdout);
 
oldtime = Sys_FloatTime () - 0.1;
while (1)
{
// find time spent rendering last frame
newtime = Sys_FloatTime ();
time = newtime - oldtime;
 
if (cls.state == ca_dedicated)
{ // play vcrfiles at max speed
if (time < sys_ticrate.value && (vcrFile == -1 || recording) )
{
#ifdef _KOLIBRI
__menuet__delay100(1);
#else
SDL_Delay (1);
#endif
continue; // not time to run a server only tic yet
}
time = sys_ticrate.value;
}
 
if (time > sys_ticrate.value*2)
oldtime = newtime;
else
oldtime += time;
 
if (++frame > 10)
moncontrol(1); // profile only while we do each Quake frame
Host_Frame (time);
moncontrol(0);
 
// graphic debugging aids
if (sys_linerefresh.value)
Sys_LineRefresh ();
}
 
}
 
 
/*
================
Sys_MakeCodeWriteable
================
*/
void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
{
#ifndef _KOLIBRI
int r;
unsigned long addr;
int psize = getpagesize();
 
fprintf(stderr, "writable code %lx-%lx\n", startaddr, startaddr+length);
 
addr = startaddr & ~(psize-1);
 
r = mprotect((char*)addr, length + startaddr - addr, 7);
 
if (r < 0)
Sys_Error("Protection change failed\n");
#endif
}
 
/contrib/other/sdlquake-1.0.9/sys_sun.c
0,0 → 1,352
/*
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.
 
*/
// sys_sun.h -- Sun system driver
 
#include "quakedef.h"
#include "errno.h"
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/param.h>
#include <fcntl.h>
#include <stddef.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdio.h>
 
qboolean isDedicated;
 
/*
===============================================================================
 
FILE IO
 
===============================================================================
*/
 
#define MAX_HANDLES 10
 
typedef struct
{
FILE *hFile;
char *pMap;
int nLen;
int nPos;
} MEMFILE;
 
MEMFILE sys_handles[MAX_HANDLES];
 
int findhandle (void)
{
int i;
for (i=1 ; i<MAX_HANDLES ; i++)
if (!sys_handles[i].hFile)
return i;
Sys_Error ("out of handles");
return -1;
}
 
/*
================
filelength
================
*/
int filelength (FILE *f)
{
int pos;
int end;
 
pos = ftell (f);
fseek (f, 0, SEEK_END);
end = ftell (f);
fseek (f, pos, SEEK_SET);
 
return end;
}
 
int Sys_FileOpenRead (char *path, int *hndl)
{
FILE *f;
int i;
i = findhandle ();
f = fopen(path, "rb");
if (!f)
{
*hndl = -1;
return -1;
}
sys_handles[i].hFile = f;
sys_handles[i].nLen = filelength(f);
sys_handles[i].nPos = 0;
sys_handles[i].pMap = mmap( 0, sys_handles[i].nLen, PROT_READ, MAP_SHARED, fileno( sys_handles[i].hFile ), 0 );
if (!sys_handles[i].pMap || (sys_handles[i].pMap == (char *)-1))
{
printf( "mmap %s failed!", path );
sys_handles[i].pMap = NULL;
}
 
*hndl = i;
return( sys_handles[i].nLen );
}
 
int Sys_FileOpenWrite (char *path)
{
FILE *f;
int i;
i = findhandle ();
 
f = fopen(path, "wb");
if (!f)
Sys_Error ("Error opening %s: %s", path,strerror(errno));
sys_handles[i].hFile = f;
sys_handles[i].nLen = 0;
sys_handles[i].nPos = 0;
sys_handles[i].pMap = NULL;
return i;
}
 
void Sys_FileClose (int handle)
{
if (sys_handles[handle].pMap)
if (munmap( sys_handles[handle].pMap, sys_handles[handle].nLen ) != 0)
printf( "failed to unmap handle %d\n", handle );
 
fclose (sys_handles[handle].hFile);
sys_handles[handle].hFile = NULL;
}
 
void Sys_FileSeek (int handle, int position)
{
if (sys_handles[handle].pMap)
{
sys_handles[handle].nPos = position;
}
else fseek (sys_handles[handle].hFile, position, SEEK_SET);
}
 
int Sys_FileRead (int handle, void *dest, int count)
{
if (sys_handles[handle].pMap)
{
int nPos = sys_handles[handle].nPos;
if (count < 0) count = 0;
if (nPos + count > sys_handles[handle].nLen)
count = sys_handles[handle].nLen - nPos;
memcpy( dest, &sys_handles[handle].pMap[nPos], count );
sys_handles[handle].nPos = nPos + count;
return( count );
}
else return fread (dest, 1, count, sys_handles[handle].hFile);
}
 
int Sys_FileWrite (int handle, void *data, int count)
{
if (sys_handles[handle].pMap)
Sys_Error( "Attempted to write to read-only file %d!\n", handle );
return fwrite (data, 1, count, sys_handles[handle].hFile);
}
 
int Sys_FileTime (char *path)
{
FILE *f;
f = fopen(path, "rb");
if (f)
{
fclose(f);
return 1;
}
return -1;
}
 
void Sys_mkdir (char *path)
{
mkdir( path, 0777 );
}
 
/*
===============================================================================
 
SYSTEM IO
 
===============================================================================
*/
 
void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
{
 
int r;
unsigned long addr;
int psize = getpagesize();
 
addr = (startaddr & ~(psize-1)) - psize;
 
// fprintf(stderr, "writable code %lx(%lx)-%lx, length=%lx\n", startaddr,
// addr, startaddr+length, length);
 
r = mprotect((char*)addr, length + startaddr - addr + psize, 7);
 
if (r < 0)
Sys_Error("Protection change failed\n");
 
}
 
 
void Sys_Error (char *error, ...)
{
va_list argptr;
 
printf ("Sys_Error: ");
va_start (argptr,error);
vprintf (error,argptr);
va_end (argptr);
printf ("\n");
Host_Shutdown();
exit (1);
}
 
void Sys_Printf (char *fmt, ...)
{
va_list argptr;
va_start (argptr,fmt);
vprintf (fmt,argptr);
va_end (argptr);
}
 
void Sys_Quit (void)
{
Host_Shutdown();
exit (0);
}
 
double Sys_FloatTime (void)
{
struct timeval tp;
struct timezone tzp;
static int secbase;
gettimeofday(&tp, &tzp);
 
if (!secbase)
{
secbase = tp.tv_sec;
return tp.tv_usec/1000000.0;
}
 
return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
}
 
char *Sys_ConsoleInput (void)
{
static char text[256];
int len;
fd_set readfds;
int ready;
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
FD_ZERO(&readfds);
FD_SET(0, &readfds);
ready = select(1, &readfds, 0, 0, &timeout);
if (ready>0)
{
len = read (0, text, sizeof(text));
if (len >= 1)
{
text[len-1] = 0; // rip off the /n and terminate
return text;
}
}
return 0;
}
 
void Sys_Sleep (void)
{
}
 
#if !id386
void Sys_HighFPPrecision (void)
{
}
 
void Sys_LowFPPrecision (void)
{
}
#endif
 
void Sys_Init(void)
{
#if id386
Sys_SetFPCW();
#endif
}
 
//=============================================================================
 
int main (int argc, char **argv)
{
static quakeparms_t parms;
float time, oldtime, newtime;
parms.memsize = 16*1024*1024;
parms.membase = malloc (parms.memsize);
parms.basedir = ".";
parms.cachedir = NULL;
 
COM_InitArgv (argc, argv);
 
parms.argc = com_argc;
parms.argv = com_argv;
 
printf ("Host_Init\n");
Host_Init (&parms);
 
Sys_Init();
 
// unroll the simulation loop to give the video side a chance to see _vid_default_mode
Host_Frame( 0.1 );
VID_SetDefaultMode();
 
oldtime = Sys_FloatTime();
while (1)
{
newtime = Sys_FloatTime();
Host_Frame (newtime - oldtime);
oldtime = newtime;
}
return 0;
}
 
 
 
 
/contrib/other/sdlquake-1.0.9/sys_win.c
0,0 → 1,893
/*
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.
 
*/
// sys_win.c -- Win32 system interface code
 
#include "quakedef.h"
#include "winquake.h"
#include "errno.h"
#include "resource.h"
#include "conproc.h"
 
#define MINIMUM_WIN_MEMORY 0x0880000
#define MAXIMUM_WIN_MEMORY 0x1000000
 
#define CONSOLE_ERROR_TIMEOUT 60.0 // # of seconds to wait on Sys_Error running
// dedicated before exiting
#define PAUSE_SLEEP 50 // sleep time on pause or minimization
#define NOT_FOCUS_SLEEP 20 // sleep time when not focus
 
int starttime;
qboolean ActiveApp, Minimized;
qboolean WinNT;
 
static double pfreq;
static double curtime = 0.0;
static double lastcurtime = 0.0;
static int lowshift;
qboolean isDedicated;
static qboolean sc_return_on_enter = false;
HANDLE hinput, houtput;
 
static char *tracking_tag = "Clams & Mooses";
 
static HANDLE tevent;
static HANDLE hFile;
static HANDLE heventParent;
static HANDLE heventChild;
 
void MaskExceptions (void);
void Sys_InitFloatTime (void);
void Sys_PushFPCW_SetHigh (void);
void Sys_PopFPCW (void);
 
volatile int sys_checksum;
 
 
/*
================
Sys_PageIn
================
*/
void Sys_PageIn (void *ptr, int size)
{
byte *x;
int j, m, n;
 
// touch all the memory to make sure it's there. The 16-page skip is to
// keep Win 95 from thinking we're trying to page ourselves in (we are
// doing that, of course, but there's no reason we shouldn't)
x = (byte *)ptr;
 
for (n=0 ; n<4 ; n++)
{
for (m=0 ; m<(size - 16 * 0x1000) ; m += 4)
{
sys_checksum += *(int *)&x[m];
sys_checksum += *(int *)&x[m + 16 * 0x1000];
}
}
}
 
 
/*
===============================================================================
 
FILE IO
 
===============================================================================
*/
 
#define MAX_HANDLES 10
FILE *sys_handles[MAX_HANDLES];
 
int findhandle (void)
{
int i;
for (i=1 ; i<MAX_HANDLES ; i++)
if (!sys_handles[i])
return i;
Sys_Error ("out of handles");
return -1;
}
 
/*
================
filelength
================
*/
int filelength (FILE *f)
{
int pos;
int end;
int t;
 
t = VID_ForceUnlockedAndReturnState ();
 
pos = ftell (f);
fseek (f, 0, SEEK_END);
end = ftell (f);
fseek (f, pos, SEEK_SET);
 
VID_ForceLockState (t);
 
return end;
}
 
int Sys_FileOpenRead (char *path, int *hndl)
{
FILE *f;
int i, retval;
int t;
 
t = VID_ForceUnlockedAndReturnState ();
 
i = findhandle ();
 
f = fopen(path, "rb");
 
if (!f)
{
*hndl = -1;
retval = -1;
}
else
{
sys_handles[i] = f;
*hndl = i;
retval = filelength(f);
}
 
VID_ForceLockState (t);
 
return retval;
}
 
int Sys_FileOpenWrite (char *path)
{
FILE *f;
int i;
int t;
 
t = VID_ForceUnlockedAndReturnState ();
i = findhandle ();
 
f = fopen(path, "wb");
if (!f)
Sys_Error ("Error opening %s: %s", path,strerror(errno));
sys_handles[i] = f;
VID_ForceLockState (t);
 
return i;
}
 
void Sys_FileClose (int handle)
{
int t;
 
t = VID_ForceUnlockedAndReturnState ();
fclose (sys_handles[handle]);
sys_handles[handle] = NULL;
VID_ForceLockState (t);
}
 
void Sys_FileSeek (int handle, int position)
{
int t;
 
t = VID_ForceUnlockedAndReturnState ();
fseek (sys_handles[handle], position, SEEK_SET);
VID_ForceLockState (t);
}
 
int Sys_FileRead (int handle, void *dest, int count)
{
int t, x;
 
t = VID_ForceUnlockedAndReturnState ();
x = fread (dest, 1, count, sys_handles[handle]);
VID_ForceLockState (t);
return x;
}
 
int Sys_FileWrite (int handle, void *data, int count)
{
int t, x;
 
t = VID_ForceUnlockedAndReturnState ();
x = fwrite (data, 1, count, sys_handles[handle]);
VID_ForceLockState (t);
return x;
}
 
int Sys_FileTime (char *path)
{
FILE *f;
int t, retval;
 
t = VID_ForceUnlockedAndReturnState ();
f = fopen(path, "rb");
 
if (f)
{
fclose(f);
retval = 1;
}
else
{
retval = -1;
}
VID_ForceLockState (t);
return retval;
}
 
void Sys_mkdir (char *path)
{
_mkdir (path);
}
 
 
/*
===============================================================================
 
SYSTEM IO
 
===============================================================================
*/
 
/*
================
Sys_MakeCodeWriteable
================
*/
void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
{
DWORD flOldProtect;
 
if (!VirtualProtect((LPVOID)startaddr, length, PAGE_READWRITE, &flOldProtect))
Sys_Error("Protection change failed\n");
}
 
 
#ifndef _M_IX86
 
void Sys_SetFPCW (void)
{
}
 
void Sys_PushFPCW_SetHigh (void)
{
}
 
void Sys_PopFPCW (void)
{
}
 
void MaskExceptions (void)
{
}
 
#endif
 
/*
================
Sys_Init
================
*/
void Sys_Init (void)
{
LARGE_INTEGER PerformanceFreq;
unsigned int lowpart, highpart;
OSVERSIONINFO vinfo;
 
MaskExceptions ();
Sys_SetFPCW ();
 
if (!QueryPerformanceFrequency (&PerformanceFreq))
Sys_Error ("No hardware timer available");
 
// get 32 out of the 64 time bits such that we have around
// 1 microsecond resolution
lowpart = (unsigned int)PerformanceFreq.LowPart;
highpart = (unsigned int)PerformanceFreq.HighPart;
lowshift = 0;
 
while (highpart || (lowpart > 2000000.0))
{
lowshift++;
lowpart >>= 1;
lowpart |= (highpart & 1) << 31;
highpart >>= 1;
}
 
pfreq = 1.0 / (double)lowpart;
 
Sys_InitFloatTime ();
 
vinfo.dwOSVersionInfoSize = sizeof(vinfo);
 
if (!GetVersionEx (&vinfo))
Sys_Error ("Couldn't get OS info");
 
if ((vinfo.dwMajorVersion < 4) ||
(vinfo.dwPlatformId == VER_PLATFORM_WIN32s))
{
Sys_Error ("WinQuake requires at least Win95 or NT 4.0");
}
 
if (vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
WinNT = true;
else
WinNT = false;
}
 
 
void Sys_Error (char *error, ...)
{
va_list argptr;
char text[1024], text2[1024];
char *text3 = "Press Enter to exit\n";
char *text4 = "***********************************\n";
char *text5 = "\n";
DWORD dummy;
double starttime;
static int in_sys_error0 = 0;
static int in_sys_error1 = 0;
static int in_sys_error2 = 0;
static int in_sys_error3 = 0;
 
if (!in_sys_error3)
{
in_sys_error3 = 1;
VID_ForceUnlockedAndReturnState ();
}
 
va_start (argptr, error);
vsprintf (text, error, argptr);
va_end (argptr);
 
if (isDedicated)
{
va_start (argptr, error);
vsprintf (text, error, argptr);
va_end (argptr);
 
sprintf (text2, "ERROR: %s\n", text);
WriteFile (houtput, text5, strlen (text5), &dummy, NULL);
WriteFile (houtput, text4, strlen (text4), &dummy, NULL);
WriteFile (houtput, text2, strlen (text2), &dummy, NULL);
WriteFile (houtput, text3, strlen (text3), &dummy, NULL);
WriteFile (houtput, text4, strlen (text4), &dummy, NULL);
 
 
starttime = Sys_FloatTime ();
sc_return_on_enter = true; // so Enter will get us out of here
 
while (!Sys_ConsoleInput () &&
((Sys_FloatTime () - starttime) < CONSOLE_ERROR_TIMEOUT))
{
}
}
else
{
// switch to windowed so the message box is visible, unless we already
// tried that and failed
if (!in_sys_error0)
{
in_sys_error0 = 1;
VID_SetDefaultMode ();
MessageBox(NULL, text, "Quake Error",
MB_OK | MB_SETFOREGROUND | MB_ICONSTOP);
}
else
{
MessageBox(NULL, text, "Double Quake Error",
MB_OK | MB_SETFOREGROUND | MB_ICONSTOP);
}
}
 
if (!in_sys_error1)
{
in_sys_error1 = 1;
Host_Shutdown ();
}
 
// shut down QHOST hooks if necessary
if (!in_sys_error2)
{
in_sys_error2 = 1;
DeinitConProc ();
}
 
exit (1);
}
 
void Sys_Printf (char *fmt, ...)
{
va_list argptr;
char text[1024];
DWORD dummy;
if (isDedicated)
{
va_start (argptr,fmt);
vsprintf (text, fmt, argptr);
va_end (argptr);
 
WriteFile(houtput, text, strlen (text), &dummy, NULL);
}
}
 
void Sys_Quit (void)
{
 
VID_ForceUnlockedAndReturnState ();
 
Host_Shutdown();
 
if (tevent)
CloseHandle (tevent);
 
if (isDedicated)
FreeConsole ();
 
// shut down QHOST hooks if necessary
DeinitConProc ();
 
exit (0);
}
 
 
/*
================
Sys_FloatTime
================
*/
double Sys_FloatTime (void)
{
static int sametimecount;
static unsigned int oldtime;
static int first = 1;
LARGE_INTEGER PerformanceCount;
unsigned int temp, t2;
double time;
 
Sys_PushFPCW_SetHigh ();
 
QueryPerformanceCounter (&PerformanceCount);
 
temp = ((unsigned int)PerformanceCount.LowPart >> lowshift) |
((unsigned int)PerformanceCount.HighPart << (32 - lowshift));
 
if (first)
{
oldtime = temp;
first = 0;
}
else
{
// check for turnover or backward time
if ((temp <= oldtime) && ((oldtime - temp) < 0x10000000))
{
oldtime = temp; // so we can't get stuck
}
else
{
t2 = temp - oldtime;
 
time = (double)t2 * pfreq;
oldtime = temp;
 
curtime += time;
 
if (curtime == lastcurtime)
{
sametimecount++;
 
if (sametimecount > 100000)
{
curtime += 1.0;
sametimecount = 0;
}
}
else
{
sametimecount = 0;
}
 
lastcurtime = curtime;
}
}
 
Sys_PopFPCW ();
 
return curtime;
}
 
 
/*
================
Sys_InitFloatTime
================
*/
void Sys_InitFloatTime (void)
{
int j;
 
Sys_FloatTime ();
 
j = COM_CheckParm("-starttime");
 
if (j)
{
curtime = (double) (Q_atof(com_argv[j+1]));
}
else
{
curtime = 0.0;
}
 
lastcurtime = curtime;
}
 
 
char *Sys_ConsoleInput (void)
{
static char text[256];
static int len;
INPUT_RECORD recs[1024];
int count;
int i, dummy;
int ch, numread, numevents;
 
if (!isDedicated)
return NULL;
 
 
for ( ;; )
{
if (!GetNumberOfConsoleInputEvents (hinput, &numevents))
Sys_Error ("Error getting # of console events");
 
if (numevents <= 0)
break;
 
if (!ReadConsoleInput(hinput, recs, 1, &numread))
Sys_Error ("Error reading console input");
 
if (numread != 1)
Sys_Error ("Couldn't read console input");
 
if (recs[0].EventType == KEY_EVENT)
{
if (!recs[0].Event.KeyEvent.bKeyDown)
{
ch = recs[0].Event.KeyEvent.uChar.AsciiChar;
 
switch (ch)
{
case '\r':
WriteFile(houtput, "\r\n", 2, &dummy, NULL);
 
if (len)
{
text[len] = 0;
len = 0;
return text;
}
else if (sc_return_on_enter)
{
// special case to allow exiting from the error handler on Enter
text[0] = '\r';
len = 0;
return text;
}
 
break;
 
case '\b':
WriteFile(houtput, "\b \b", 3, &dummy, NULL);
if (len)
{
len--;
}
break;
 
default:
if (ch >= ' ')
{
WriteFile(houtput, &ch, 1, &dummy, NULL);
text[len] = ch;
len = (len + 1) & 0xff;
}
 
break;
 
}
}
}
}
 
return NULL;
}
 
void Sys_Sleep (void)
{
Sleep (1);
}
 
 
void Sys_SendKeyEvents (void)
{
MSG msg;
 
while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
{
// we always update if there are any event, even if we're paused
scr_skipupdate = 0;
 
if (!GetMessage (&msg, NULL, 0, 0))
Sys_Quit ();
 
TranslateMessage (&msg);
DispatchMessage (&msg);
}
}
 
 
/*
==============================================================================
 
WINDOWS CRAP
 
==============================================================================
*/
 
 
/*
==================
WinMain
==================
*/
void SleepUntilInput (int time)
{
 
MsgWaitForMultipleObjects(1, &tevent, FALSE, time, QS_ALLINPUT);
}
 
 
/*
==================
WinMain
==================
*/
HINSTANCE global_hInstance;
int global_nCmdShow;
char *argv[MAX_NUM_ARGVS];
static char *empty_string = "";
HWND hwnd_dialog;
 
 
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
quakeparms_t parms;
double time, oldtime, newtime;
MEMORYSTATUS lpBuffer;
static char cwd[1024];
int t;
RECT rect;
 
/* previous instances do not exist in Win32 */
if (hPrevInstance)
return 0;
 
global_hInstance = hInstance;
global_nCmdShow = nCmdShow;
 
lpBuffer.dwLength = sizeof(MEMORYSTATUS);
GlobalMemoryStatus (&lpBuffer);
 
if (!GetCurrentDirectory (sizeof(cwd), cwd))
Sys_Error ("Couldn't determine current directory");
 
if (cwd[Q_strlen(cwd)-1] == '/')
cwd[Q_strlen(cwd)-1] = 0;
 
parms.basedir = cwd;
parms.cachedir = NULL;
 
parms.argc = 1;
argv[0] = empty_string;
 
while (*lpCmdLine && (parms.argc < MAX_NUM_ARGVS))
{
while (*lpCmdLine && ((*lpCmdLine <= 32) || (*lpCmdLine > 126)))
lpCmdLine++;
 
if (*lpCmdLine)
{
argv[parms.argc] = lpCmdLine;
parms.argc++;
 
while (*lpCmdLine && ((*lpCmdLine > 32) && (*lpCmdLine <= 126)))
lpCmdLine++;
 
if (*lpCmdLine)
{
*lpCmdLine = 0;
lpCmdLine++;
}
}
}
 
parms.argv = argv;
 
COM_InitArgv (parms.argc, parms.argv);
 
parms.argc = com_argc;
parms.argv = com_argv;
 
isDedicated = (COM_CheckParm ("-dedicated") != 0);
 
if (!isDedicated)
{
hwnd_dialog = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, NULL);
 
if (hwnd_dialog)
{
if (GetWindowRect (hwnd_dialog, &rect))
{
if (rect.left > (rect.top * 2))
{
SetWindowPos (hwnd_dialog, 0,
(rect.left / 2) - ((rect.right - rect.left) / 2),
rect.top, 0, 0,
SWP_NOZORDER | SWP_NOSIZE);
}
}
 
ShowWindow (hwnd_dialog, SW_SHOWDEFAULT);
UpdateWindow (hwnd_dialog);
SetForegroundWindow (hwnd_dialog);
}
}
 
// take the greater of all the available memory or half the total memory,
// but at least 8 Mb and no more than 16 Mb, unless they explicitly
// request otherwise
parms.memsize = lpBuffer.dwAvailPhys;
 
if (parms.memsize < MINIMUM_WIN_MEMORY)
parms.memsize = MINIMUM_WIN_MEMORY;
 
if (parms.memsize < (lpBuffer.dwTotalPhys >> 1))
parms.memsize = lpBuffer.dwTotalPhys >> 1;
 
if (parms.memsize > MAXIMUM_WIN_MEMORY)
parms.memsize = MAXIMUM_WIN_MEMORY;
 
if (COM_CheckParm ("-heapsize"))
{
t = COM_CheckParm("-heapsize") + 1;
 
if (t < com_argc)
parms.memsize = Q_atoi (com_argv[t]) * 1024;
}
 
parms.membase = malloc (parms.memsize);
 
if (!parms.membase)
Sys_Error ("Not enough memory free; check disk space\n");
 
Sys_PageIn (parms.membase, parms.memsize);
 
tevent = CreateEvent(NULL, FALSE, FALSE, NULL);
 
if (!tevent)
Sys_Error ("Couldn't create event");
 
if (isDedicated)
{
if (!AllocConsole ())
{
Sys_Error ("Couldn't create dedicated server console");
}
 
hinput = GetStdHandle (STD_INPUT_HANDLE);
houtput = GetStdHandle (STD_OUTPUT_HANDLE);
 
// give QHOST a chance to hook into the console
if ((t = COM_CheckParm ("-HFILE")) > 0)
{
if (t < com_argc)
hFile = (HANDLE)Q_atoi (com_argv[t+1]);
}
if ((t = COM_CheckParm ("-HPARENT")) > 0)
{
if (t < com_argc)
heventParent = (HANDLE)Q_atoi (com_argv[t+1]);
}
if ((t = COM_CheckParm ("-HCHILD")) > 0)
{
if (t < com_argc)
heventChild = (HANDLE)Q_atoi (com_argv[t+1]);
}
 
InitConProc (hFile, heventParent, heventChild);
}
 
Sys_Init ();
 
// because sound is off until we become active
S_BlockSound ();
 
Sys_Printf ("Host_Init\n");
Host_Init (&parms);
 
oldtime = Sys_FloatTime ();
 
/* main window message loop */
while (1)
{
if (isDedicated)
{
newtime = Sys_FloatTime ();
time = newtime - oldtime;
 
while (time < sys_ticrate.value )
{
Sys_Sleep();
newtime = Sys_FloatTime ();
time = newtime - oldtime;
}
}
else
{
// yield the CPU for a little while when paused, minimized, or not the focus
if ((cl.paused && (!ActiveApp && !DDActive)) || Minimized || block_drawing)
{
SleepUntilInput (PAUSE_SLEEP);
scr_skipupdate = 1; // no point in bothering to draw
}
else if (!ActiveApp && !DDActive)
{
SleepUntilInput (NOT_FOCUS_SLEEP);
}
 
newtime = Sys_FloatTime ();
time = newtime - oldtime;
}
 
Host_Frame (time);
oldtime = newtime;
}
 
/* return success of application */
return TRUE;
}
 
/contrib/other/sdlquake-1.0.9/sys_wina.S
0,0 → 1,116
/*
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.
 
*/
//
// sys_wina.s
// x86 assembly-language Win-dependent routines.
 
#define GLQUAKE 1 // don't include unneeded defs
#include "asm_i386.h"
#include "quakeasm.h"
 
// LATER should be id386-dependent, and have an equivalent C path
 
.data
 
.align 4
fpenv:
.long 0, 0, 0, 0, 0, 0, 0, 0
 
.text
 
.globl C(MaskExceptions)
C(MaskExceptions):
fnstenv fpenv
orl $0x3F,fpenv
fldenv fpenv
 
ret
 
#if 0
.globl C(unmaskexceptions)
C(unmaskexceptions):
fnstenv fpenv
andl $0xFFFFFFE0,fpenv
fldenv fpenv
 
ret
#endif
 
.data
 
.align 4
.globl ceil_cw, single_cw, full_cw, cw, pushed_cw
ceil_cw: .long 0
single_cw: .long 0
full_cw: .long 0
cw: .long 0
pushed_cw: .long 0
 
.text
 
.globl C(Sys_LowFPPrecision)
C(Sys_LowFPPrecision):
fldcw single_cw
 
ret
 
.globl C(Sys_HighFPPrecision)
C(Sys_HighFPPrecision):
fldcw full_cw
 
ret
 
.globl C(Sys_PushFPCW_SetHigh)
C(Sys_PushFPCW_SetHigh):
fnstcw pushed_cw
fldcw full_cw
 
ret
 
.globl C(Sys_PopFPCW)
C(Sys_PopFPCW):
fldcw pushed_cw
 
ret
 
.globl C(Sys_SetFPCW)
C(Sys_SetFPCW):
fnstcw cw
movl cw,%eax
#if id386
andb $0xF0,%ah
orb $0x03,%ah // round mode, 64-bit precision
#endif
movl %eax,full_cw
 
#if id386
andb $0xF0,%ah
orb $0x0C,%ah // chop mode, single precision
#endif
movl %eax,single_cw
 
#if id386
andb $0xF0,%ah
orb $0x08,%ah // ceil mode, single precision
#endif
movl %eax,ceil_cw
 
ret
 
/contrib/other/sdlquake-1.0.9/sys_wind.c
0,0 → 1,325
/*
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.
 
*/
// sys_null.h -- null system driver to aid porting efforts
 
#include "quakedef.h"
#include "winquake.h"
#include "errno.h"
#include <sys\types.h>
#include <sys\timeb.h>
 
 
/*
===============================================================================
 
FILE IO
 
===============================================================================
*/
 
#define MAX_HANDLES 10
FILE *sys_handles[MAX_HANDLES];
 
int findhandle (void)
{
int i;
for (i=1 ; i<MAX_HANDLES ; i++)
if (!sys_handles[i])
return i;
Sys_Error ("out of handles");
return -1;
}
 
/*
================
filelength
================
*/
int filelength (FILE *f)
{
int pos;
int end;
 
pos = ftell (f);
fseek (f, 0, SEEK_END);
end = ftell (f);
fseek (f, pos, SEEK_SET);
 
return end;
}
 
int Sys_FileOpenRead (char *path, int *hndl)
{
FILE *f;
int i;
i = findhandle ();
 
f = fopen(path, "rb");
if (!f)
{
*hndl = -1;
return -1;
}
sys_handles[i] = f;
*hndl = i;
return filelength(f);
}
 
int Sys_FileOpenWrite (char *path)
{
FILE *f;
int i;
i = findhandle ();
 
f = fopen(path, "wb");
if (!f)
Sys_Error ("Error opening %s: %s", path,strerror(errno));
sys_handles[i] = f;
return i;
}
 
void Sys_FileClose (int handle)
{
fclose (sys_handles[handle]);
sys_handles[handle] = NULL;
}
 
void Sys_FileSeek (int handle, int position)
{
fseek (sys_handles[handle], position, SEEK_SET);
}
 
int Sys_FileRead (int handle, void *dest, int count)
{
return fread (dest, 1, count, sys_handles[handle]);
}
 
int Sys_FileWrite (int handle, void *data, int count)
{
return fwrite (data, 1, count, sys_handles[handle]);
}
 
int Sys_FileTime (char *path)
{
FILE *f;
f = fopen(path, "rb");
if (f)
{
fclose(f);
return 1;
}
return -1;
}
 
void Sys_mkdir (char *path)
{
}
 
 
/*
===============================================================================
 
SYSTEM IO
 
===============================================================================
*/
 
void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
{
}
 
 
void Sys_DebugLog(char *file, char *fmt, ...)
{
}
 
void Sys_Error (char *error, ...)
{
va_list argptr;
char text[1024];
 
va_start (argptr,error);
vsprintf (text, error,argptr);
va_end (argptr);
 
// MessageBox(NULL, text, "Error", 0 /* MB_OK */ );
printf ("ERROR: %s\n", text);
 
exit (1);
}
 
void Sys_Printf (char *fmt, ...)
{
va_list argptr;
va_start (argptr,fmt);
vprintf (fmt,argptr);
va_end (argptr);
}
 
void Sys_Quit (void)
{
exit (0);
}
 
double Sys_FloatTime (void)
{
double t;
struct _timeb tstruct;
static int starttime;
 
_ftime( &tstruct );
if (!starttime)
starttime = tstruct.time;
t = (tstruct.time-starttime) + tstruct.millitm*0.001;
return t;
}
 
void Sys_Sleep (void)
{
}
 
 
void Sys_SendKeyEvents (void)
{
}
 
void Sys_HighFPPrecision (void)
{
}
 
void Sys_LowFPPrecision (void)
{
}
 
char *Sys_ConsoleInput (void)
{
static char text[256];
static int len;
INPUT_RECORD recs[1024];
int count;
int i;
int c;
 
// read a line out
while (_kbhit())
{
c = _getch();
putch (c);
if (c == '\r')
{
text[len] = 0;
putch ('\n');
len = 0;
return text;
}
if (c == 8)
{
putch (' ');
putch (c);
len--;
text[len] = 0;
continue;
}
text[len] = c;
len++;
text[len] = 0;
if (len == sizeof(text))
len = 0;
}
 
return NULL;
}
 
 
 
/*
==================
main
 
==================
*/
char *newargv[256];
 
int main (int argc, char **argv)
{
MSG msg;
quakeparms_t parms;
double time, oldtime;
static char cwd[1024];
 
memset (&parms, 0, sizeof(parms));
 
parms.memsize = 16384*1024;
parms.membase = malloc (parms.memsize);
 
_getcwd (cwd, sizeof(cwd));
if (cwd[Q_strlen(cwd)-1] == '\\')
cwd[Q_strlen(cwd)-1] = 0;
parms.basedir = cwd; //"f:/quake";
// parms.basedir = "f:\\quake";
 
COM_InitArgv (argc, argv);
 
// dedicated server ONLY!
if (!COM_CheckParm ("-dedicated"))
{
memcpy (newargv, argv, argc*4);
newargv[argc] = "-dedicated";
argc++;
argv = newargv;
COM_InitArgv (argc, argv);
}
 
parms.argc = argc;
parms.argv = argv;
 
printf ("Host_Init\n");
Host_Init (&parms);
 
oldtime = Sys_FloatTime ();
 
/* main window message loop */
while (1)
{
time = Sys_FloatTime();
if (time - oldtime < sys_ticrate.value )
{
Sleep(1);
continue;
}
 
Host_Frame ( time - oldtime );
oldtime = time;
}
 
/* return success of application */
return TRUE;
}
 
/contrib/other/sdlquake-1.0.9/vgamodes.h
0,0 → 1,599
/*
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.
 
*/
//
// vgamodes.h: VGA mode set tables
//
 
#include "vregset.h"
 
int VGA_InitMode (viddef_t *vid, vmode_t *pcurrentmode);
void VGA_SwapBuffers (viddef_t *vid, vmode_t *pcurrentmode, vrect_t *rects);
void VGA_SetPalette (viddef_t *vid, vmode_t *pcurrentmode,
unsigned char *pal);
 
///////////////////////////////////////////////////////////////////////////
// the following base mode descriptors plus extra data together provide all
// the data needed to do VGA mode sets
///////////////////////////////////////////////////////////////////////////
 
typedef struct {
int vidbuffer;
int *pregset;
} vextra_t;
 
int vrsnull[] = {
VRS_END,
};
 
int vrs320x200x256planar[] = {
//
// switch to linear, non-chain4 mode
//
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 1,
 
VRS_BYTE_OUT, SC_INDEX, MEMORY_MODE,
VRS_BYTE_RMW, SC_DATA, ~0x08, 0x04,
VRS_BYTE_OUT, GC_INDEX, GRAPHICS_MODE,
VRS_BYTE_RMW, GC_DATA, ~0x13, 0x00,
VRS_BYTE_OUT, GC_INDEX, MISCELLANOUS,
VRS_BYTE_RMW, GC_DATA, ~0x02, 0x00,
 
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 3,
 
//
// change the CRTC from doubleword to byte mode
//
VRS_BYTE_OUT, CRTC_INDEX, UNDERLINE,
VRS_BYTE_RMW, CRTC_DATA, ~0x40, 0x00,
VRS_BYTE_OUT, CRTC_INDEX, MODE_CONTROL,
VRS_BYTE_RMW, CRTC_DATA, ~0x00, 0x40,
 
VRS_END,
};
 
int vrs360x200x256planar[] = {
//
// switch to linear, non-chain4 mode
//
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 1,
 
VRS_WORD_OUT, SC_INDEX, 0x0604,
VRS_BYTE_OUT, MISC_OUTPUT, 0x67,
 
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 3,
 
//
// unprotect CRTC0 through CRTC0
//
VRS_BYTE_OUT, CRTC_INDEX, 0x11,
VRS_BYTE_RMW, CRTC_DATA, ~0x80, 0x00,
 
//
// change the CRTC from doubleword to byte mode
//
VRS_BYTE_OUT, CRTC_INDEX, UNDERLINE,
VRS_BYTE_RMW, CRTC_DATA, ~0x40, 0x00,
VRS_BYTE_OUT, CRTC_INDEX, MODE_CONTROL,
VRS_BYTE_RMW, CRTC_DATA, ~0x00, 0x40,
 
//
// set up the CRT Controller
//
VRS_WORD_OUT, CRTC_INDEX, 0x6B00,
VRS_WORD_OUT, CRTC_INDEX, 0x5901,
VRS_WORD_OUT, CRTC_INDEX, 0x5A02,
VRS_WORD_OUT, CRTC_INDEX, 0x8E03,
VRS_WORD_OUT, CRTC_INDEX, 0x5E04,
VRS_WORD_OUT, CRTC_INDEX, 0x8A05,
VRS_WORD_OUT, CRTC_INDEX, 0x3013,
 
VRS_END,
};
 
int vrs320x240x256planar[] = {
//
// switch to linear, non-chain4 mode
//
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 1,
 
VRS_BYTE_OUT, SC_INDEX, MEMORY_MODE,
VRS_BYTE_RMW, SC_DATA, ~0x08, 0x04,
VRS_BYTE_OUT, GC_INDEX, GRAPHICS_MODE,
VRS_BYTE_RMW, GC_DATA, ~0x13, 0x00,
VRS_BYTE_OUT, GC_INDEX, MISCELLANOUS,
VRS_BYTE_RMW, GC_DATA, ~0x02, 0x00,
 
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 3,
 
//
// unprotect CRTC0 through CRTC0
//
VRS_BYTE_OUT, CRTC_INDEX, 0x11,
VRS_BYTE_RMW, CRTC_DATA, ~0x80, 0x00,
 
//
// set up the CRT Controller
//
VRS_WORD_OUT, CRTC_INDEX, 0x0D06,
VRS_WORD_OUT, CRTC_INDEX, 0x3E07,
VRS_WORD_OUT, CRTC_INDEX, 0x4109,
VRS_WORD_OUT, CRTC_INDEX, 0xEA10,
VRS_WORD_OUT, CRTC_INDEX, 0xAC11,
VRS_WORD_OUT, CRTC_INDEX, 0xDF12,
VRS_WORD_OUT, CRTC_INDEX, 0x0014,
VRS_WORD_OUT, CRTC_INDEX, 0xE715,
VRS_WORD_OUT, CRTC_INDEX, 0x0616,
VRS_WORD_OUT, CRTC_INDEX, 0xE317,
 
VRS_END,
};
 
int vrs360x240x256planar[] = {
//
// switch to linear, non-chain4 mode
//
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 1,
 
VRS_WORD_OUT, SC_INDEX, 0x0604,
VRS_BYTE_OUT, MISC_OUTPUT, 0xE7,
 
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 3,
 
//
// unprotect CRTC0 through CRTC0
//
VRS_BYTE_OUT, CRTC_INDEX, 0x11,
VRS_BYTE_RMW, CRTC_DATA, ~0x80, 0x00,
 
//
// set up the CRT Controller
//
VRS_WORD_OUT, CRTC_INDEX, 0x6B00,
VRS_WORD_OUT, CRTC_INDEX, 0x5901,
VRS_WORD_OUT, CRTC_INDEX, 0x5A02,
VRS_WORD_OUT, CRTC_INDEX, 0x8E03,
VRS_WORD_OUT, CRTC_INDEX, 0x5E04,
VRS_WORD_OUT, CRTC_INDEX, 0x8A05,
VRS_WORD_OUT, CRTC_INDEX, 0x0D06,
VRS_WORD_OUT, CRTC_INDEX, 0x3E07,
VRS_WORD_OUT, CRTC_INDEX, 0x4109,
VRS_WORD_OUT, CRTC_INDEX, 0xEA10,
VRS_WORD_OUT, CRTC_INDEX, 0xAC11,
VRS_WORD_OUT, CRTC_INDEX, 0xDF12,
VRS_WORD_OUT, CRTC_INDEX, 0x3013,
VRS_WORD_OUT, CRTC_INDEX, 0x0014,
VRS_WORD_OUT, CRTC_INDEX, 0xE715,
VRS_WORD_OUT, CRTC_INDEX, 0x0616,
VRS_WORD_OUT, CRTC_INDEX, 0xE317,
 
VRS_END,
};
 
int vrs320x350x256planar[] = {
//
// switch to linear, non-chain4 mode
//
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 1,
 
VRS_BYTE_OUT, SC_INDEX, MEMORY_MODE,
VRS_BYTE_RMW, SC_DATA, ~0x08, 0x04,
VRS_BYTE_OUT, GC_INDEX, GRAPHICS_MODE,
VRS_BYTE_RMW, GC_DATA, ~0x10, 0x00,
VRS_BYTE_OUT, GC_INDEX, MISCELLANOUS,
VRS_BYTE_RMW, GC_DATA, ~0x02, 0x00,
VRS_BYTE_OUT, MISC_OUTPUT, 0xA3, // 350-scan-line scan rate
 
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 3,
 
//
// unprotect CRTC0 through CRTC0
//
VRS_BYTE_OUT, CRTC_INDEX, 0x11,
VRS_BYTE_RMW, CRTC_DATA, ~0x80, 0x00,
 
//
// stop scanning each line twice
//
VRS_BYTE_OUT, CRTC_INDEX, MAX_SCAN_LINE,
VRS_BYTE_RMW, CRTC_DATA, ~0x1F, 0x00,
 
//
// change the CRTC from doubleword to byte mode
//
VRS_BYTE_OUT, CRTC_INDEX, UNDERLINE,
VRS_BYTE_RMW, CRTC_DATA, ~0x40, 0x00,
VRS_BYTE_OUT, CRTC_INDEX, MODE_CONTROL,
VRS_BYTE_RMW, CRTC_DATA, ~0x00, 0x40,
 
//
// set the vertical counts for 350-scan-line mode
//
VRS_WORD_OUT, CRTC_INDEX, 0xBF06,
VRS_WORD_OUT, CRTC_INDEX, 0x1F07,
VRS_WORD_OUT, CRTC_INDEX, 0x8310,
VRS_WORD_OUT, CRTC_INDEX, 0x8511,
VRS_WORD_OUT, CRTC_INDEX, 0x5D12,
VRS_WORD_OUT, CRTC_INDEX, 0x6315,
VRS_WORD_OUT, CRTC_INDEX, 0xBA16,
 
VRS_END,
};
 
int vrs360x350x256planar[] = {
//
// switch to linear, non-chain4 mode
//
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 1,
 
VRS_WORD_OUT, SC_INDEX, 0x0604,
VRS_BYTE_OUT, MISC_OUTPUT, 0xA7, // 350-scan-line scan rate
 
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 3,
 
//
// unprotect CRTC0 through CRTC0
//
VRS_BYTE_OUT, CRTC_INDEX, 0x11,
VRS_BYTE_RMW, CRTC_DATA, ~0x80, 0x00,
 
//
// stop scanning each line twice
//
VRS_BYTE_OUT, CRTC_INDEX, MAX_SCAN_LINE,
VRS_BYTE_RMW, CRTC_DATA, ~0x1F, 0x00,
 
//
// change the CRTC from doubleword to byte mode
//
VRS_BYTE_OUT, CRTC_INDEX, UNDERLINE,
VRS_BYTE_RMW, CRTC_DATA, ~0x40, 0x00,
VRS_BYTE_OUT, CRTC_INDEX, MODE_CONTROL,
VRS_BYTE_RMW, CRTC_DATA, ~0x00, 0x40,
 
//
// set the vertical counts for 350-scan-line mode and 360 pixels across
//
VRS_WORD_OUT, CRTC_INDEX, 0x6B00,
VRS_WORD_OUT, CRTC_INDEX, 0x5901,
VRS_WORD_OUT, CRTC_INDEX, 0x5A02,
VRS_WORD_OUT, CRTC_INDEX, 0x8E03,
VRS_WORD_OUT, CRTC_INDEX, 0x5E04,
VRS_WORD_OUT, CRTC_INDEX, 0x8A05,
VRS_WORD_OUT, CRTC_INDEX, 0xBF06,
VRS_WORD_OUT, CRTC_INDEX, 0x1F07,
VRS_WORD_OUT, CRTC_INDEX, 0x8310,
VRS_WORD_OUT, CRTC_INDEX, 0x8511,
VRS_WORD_OUT, CRTC_INDEX, 0x5D12,
VRS_WORD_OUT, CRTC_INDEX, 0x3013,
VRS_WORD_OUT, CRTC_INDEX, 0x6315,
VRS_WORD_OUT, CRTC_INDEX, 0xBA16,
 
VRS_END,
};
 
int vrs320x400x256planar[] = {
//
// switch to linear, non-chain4 mode
//
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 1,
 
 
VRS_BYTE_OUT, SC_INDEX, MEMORY_MODE,
VRS_BYTE_RMW, SC_DATA, ~0x08, 0x04,
VRS_BYTE_OUT, GC_INDEX, GRAPHICS_MODE,
VRS_BYTE_RMW, GC_DATA, ~0x10, 0x00,
VRS_BYTE_OUT, GC_INDEX, MISCELLANOUS,
VRS_BYTE_RMW, GC_DATA, ~0x02, 0x00,
 
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 3,
 
//
// stop scanning each line twice
//
VRS_BYTE_OUT, CRTC_INDEX, MAX_SCAN_LINE,
VRS_BYTE_RMW, CRTC_DATA, ~0x1F, 0x00,
 
//
// change the CRTC from doubleword to byte mode
//
VRS_BYTE_OUT, CRTC_INDEX, UNDERLINE,
VRS_BYTE_RMW, CRTC_DATA, ~0x40, 0x00,
VRS_BYTE_OUT, CRTC_INDEX, MODE_CONTROL,
VRS_BYTE_RMW, CRTC_DATA, ~0x00, 0x40,
 
VRS_END,
};
 
int vrs360x400x256planar[] = {
//
// switch to linear, non-chain4 mode
//
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 1,
 
VRS_WORD_OUT, SC_INDEX, 0x0604,
VRS_BYTE_OUT, MISC_OUTPUT, 0x67,
 
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 3,
 
//
// unprotect CRTC0 through CRTC0
//
VRS_BYTE_OUT, CRTC_INDEX, 0x11,
VRS_BYTE_RMW, CRTC_DATA, ~0x80, 0x00,
 
//
// stop scanning each line twice
//
VRS_BYTE_OUT, CRTC_INDEX, MAX_SCAN_LINE,
VRS_BYTE_RMW, CRTC_DATA, ~0x1F, 0x00,
 
//
// change the CRTC from doubleword to byte mode
//
VRS_BYTE_OUT, CRTC_INDEX, UNDERLINE,
VRS_BYTE_RMW, CRTC_DATA, ~0x40, 0x00,
VRS_BYTE_OUT, CRTC_INDEX, MODE_CONTROL,
VRS_BYTE_RMW, CRTC_DATA, ~0x00, 0x40,
 
//
// set up the CRT Controller
//
VRS_WORD_OUT, CRTC_INDEX, 0x6B00,
VRS_WORD_OUT, CRTC_INDEX, 0x5901,
VRS_WORD_OUT, CRTC_INDEX, 0x5A02,
VRS_WORD_OUT, CRTC_INDEX, 0x8E03,
VRS_WORD_OUT, CRTC_INDEX, 0x5E04,
VRS_WORD_OUT, CRTC_INDEX, 0x8A05,
VRS_WORD_OUT, CRTC_INDEX, 0x3013,
 
VRS_END,
};
 
int vrs320x480x256planar[] = {
//
// switch to linear, non-chain4 mode
//
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 1,
 
VRS_BYTE_OUT, SC_INDEX, MEMORY_MODE,
VRS_BYTE_RMW, SC_DATA, ~0x08, 0x04,
VRS_BYTE_OUT, GC_INDEX, GRAPHICS_MODE,
VRS_BYTE_RMW, GC_DATA, ~0x10, 0x00,
VRS_BYTE_OUT, GC_INDEX, MISCELLANOUS,
VRS_BYTE_RMW, GC_DATA, ~0x02, 0x00,
 
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 3,
 
//
// unprotect CRTC0 through CRTC0
//
VRS_BYTE_OUT, CRTC_INDEX, 0x11,
VRS_BYTE_RMW, CRTC_DATA, ~0x80, 0x00,
 
//
// stop scanning each line twice
//
VRS_BYTE_OUT, CRTC_INDEX, MAX_SCAN_LINE,
VRS_BYTE_RMW, CRTC_DATA, ~0x1F, 0x00,
 
//
// change the CRTC from doubleword to byte mode
//
VRS_BYTE_OUT, CRTC_INDEX, UNDERLINE,
VRS_BYTE_RMW, CRTC_DATA, ~0x40, 0x00,
VRS_BYTE_OUT, CRTC_INDEX, MODE_CONTROL,
VRS_BYTE_RMW, CRTC_DATA, ~0x00, 0x40,
 
//
// set up the CRT Controller
//
VRS_WORD_OUT, CRTC_INDEX, 0x0D06,
VRS_WORD_OUT, CRTC_INDEX, 0x3E07,
VRS_WORD_OUT, CRTC_INDEX, 0xEA10,
VRS_WORD_OUT, CRTC_INDEX, 0xAC11,
VRS_WORD_OUT, CRTC_INDEX, 0xDF12,
VRS_WORD_OUT, CRTC_INDEX, 0xE715,
VRS_WORD_OUT, CRTC_INDEX, 0x0616,
 
VRS_END,
};
 
int vrs360x480x256planar[] = {
//
// switch to linear, non-chain4 mode
//
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 1,
 
VRS_WORD_OUT, SC_INDEX, 0x0604,
VRS_BYTE_OUT, MISC_OUTPUT, 0xE7,
 
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 3,
 
//
// unprotect CRTC0 through CRTC0
//
VRS_BYTE_OUT, CRTC_INDEX, 0x11,
VRS_BYTE_RMW, CRTC_DATA, ~0x80, 0x00,
 
//
// set up the CRT Controller
//
VRS_WORD_OUT, CRTC_INDEX, 0x6B00,
VRS_WORD_OUT, CRTC_INDEX, 0x5901,
VRS_WORD_OUT, CRTC_INDEX, 0x5A02,
VRS_WORD_OUT, CRTC_INDEX, 0x8E03,
VRS_WORD_OUT, CRTC_INDEX, 0x5E04,
VRS_WORD_OUT, CRTC_INDEX, 0x8A05,
VRS_WORD_OUT, CRTC_INDEX, 0x0D06,
VRS_WORD_OUT, CRTC_INDEX, 0x3E07,
VRS_WORD_OUT, CRTC_INDEX, 0x4009,
VRS_WORD_OUT, CRTC_INDEX, 0xEA10,
VRS_WORD_OUT, CRTC_INDEX, 0xAC11,
VRS_WORD_OUT, CRTC_INDEX, 0xDF12,
VRS_WORD_OUT, CRTC_INDEX, 0x3013,
VRS_WORD_OUT, CRTC_INDEX, 0x0014,
VRS_WORD_OUT, CRTC_INDEX, 0xE715,
VRS_WORD_OUT, CRTC_INDEX, 0x0616,
VRS_WORD_OUT, CRTC_INDEX, 0xE317,
 
VRS_END,
};
 
//
// extra VGA-specific data for vgavidmodes
//
vextra_t extra320x200x256linear = {
1, vrsnull
};
vextra_t extra320x200x256planar = {
1, vrs320x200x256planar
};
vextra_t extra360x200x256planar = {
1, vrs360x200x256planar
};
vextra_t extra320x240x256planar = {
1, vrs320x240x256planar
};
vextra_t extra360x240x256planar = {
1, vrs360x240x256planar
};
vextra_t extra320x350x256planar = {
1, vrs320x350x256planar
};
vextra_t extra360x350x256planar = {
1, vrs360x350x256planar
};
vextra_t extra320x400x256planar = {
1, vrs320x400x256planar
};
vextra_t extra360x400x256planar = {
1, vrs360x400x256planar
};
vextra_t extra320x480x256planar = {
1, vrs320x480x256planar
};
vextra_t extra360x480x256planar = {
1, vrs360x480x256planar
};
 
//
// base mode descriptors, in ascending order of number of pixels
//
 
vmode_t vgavidmodes[] = {
{
NULL,
"320x200", " ***** standard VGA modes ***** ",
320, 200, (200.0/320.0)*(320.0/240.0), 320, 0, 1, &extra320x200x256linear,
VGA_InitMode, VGA_SwapBuffers, VGA_SetPalette,
VGA_BeginDirectRect, VGA_EndDirectRect
},
{
NULL,
"320x200", " ***** Mode X-style modes ***** ",
320, 200, (200.0/320.0)*(320.0/240.0), 320, 1, 1, &extra320x200x256planar,
VGA_InitMode, VGA_SwapBuffers, VGA_SetPalette,
VGA_BeginDirectRect, VGA_EndDirectRect
},
{
NULL,
"360x200", NULL, 360, 200, (200.0/360.0)*(320.0/240.0),
384, 1, 1, &extra360x200x256planar, VGA_InitMode,
VGA_SwapBuffers,
VGA_SetPalette, VGA_BeginDirectRect, VGA_EndDirectRect
},
{
NULL,
"320x240", NULL, 320, 240, (240.0/320.0)*(320.0/240.0),
320, 1, 1, &extra320x240x256planar, VGA_InitMode,
VGA_SwapBuffers,
VGA_SetPalette, VGA_BeginDirectRect, VGA_EndDirectRect
},
{
NULL,
"360x240", NULL, 360, 240, (240.0/360.0)*(320.0/240.0),
384, 1, 1, &extra360x240x256planar,
VGA_InitMode, VGA_SwapBuffers, VGA_SetPalette,
VGA_BeginDirectRect, VGA_EndDirectRect
},
{
NULL,
"320x350", NULL, 320, 350, (350.0/320.0)*(320.0/240.0),
320, 1, 1, &extra320x350x256planar, VGA_InitMode,
VGA_SwapBuffers,
VGA_SetPalette, VGA_BeginDirectRect, VGA_EndDirectRect
},
{
NULL,
"360x350", NULL, 360, 350, (350.0/360.0)*(320.0/240.0),
384, 1, 1, &extra360x350x256planar, VGA_InitMode,
VGA_SwapBuffers,
VGA_SetPalette, VGA_BeginDirectRect, VGA_EndDirectRect
},
{
NULL,
"320x400", NULL, 320, 400, (400.0/320.0)*(320.0/240.0), 320,
1, 1, &extra320x400x256planar, VGA_InitMode,
VGA_SwapBuffers,
VGA_SetPalette, VGA_BeginDirectRect, VGA_EndDirectRect
},
{
NULL,
"360x400", NULL, 360, 400, (400.0/360.0)*(320.0/240.0),
384, 1, 1, &extra360x400x256planar, VGA_InitMode,
VGA_SwapBuffers,
VGA_SetPalette, VGA_BeginDirectRect, VGA_EndDirectRect
},
{
NULL,
"320x480", NULL, 320, 480, (480.0/320.0)*(320.0/240.0),
320, 1, 1, &extra320x480x256planar, VGA_InitMode,
VGA_SwapBuffers,
VGA_SetPalette, VGA_BeginDirectRect, VGA_EndDirectRect
},
{
NULL,
"360x480", NULL, 360, 480, (480.0/360.0)*(320.0/240.0),
384, 1, 1, &extra360x480x256planar, VGA_InitMode,
VGA_SwapBuffers,
VGA_SetPalette, VGA_BeginDirectRect, VGA_EndDirectRect
},
};
 
/contrib/other/sdlquake-1.0.9/vid.h
0,0 → 1,85
/*
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.
 
*/
// vid.h -- video driver defs
 
#define VID_CBITS 6
#define VID_GRADES (1 << VID_CBITS)
 
// a pixel can be one, two, or four bytes
typedef byte pixel_t;
 
typedef struct vrect_s
{
int x,y,width,height;
struct vrect_s *pnext;
} vrect_t;
 
typedef struct
{
pixel_t *buffer; // invisible buffer
pixel_t *colormap; // 256 * VID_GRADES size
unsigned short *colormap16; // 256 * VID_GRADES size
int fullbright; // index of first fullbright color
unsigned rowbytes; // may be > width if displayed in a window
unsigned width;
unsigned height;
float aspect; // width / height -- < 0 is taller than wide
int numpages;
int recalc_refdef; // if true, recalc vid-based stuff
pixel_t *conbuffer;
int conrowbytes;
unsigned conwidth;
unsigned conheight;
int maxwarpwidth;
int maxwarpheight;
pixel_t *direct; // direct drawing to framebuffer, if not
// NULL
} viddef_t;
 
extern viddef_t vid; // global video state
extern unsigned short d_8to16table[256];
extern unsigned d_8to24table[256];
extern void (*vid_menudrawfn)(void);
extern void (*vid_menukeyfn)(int key);
 
void VID_SetPalette (unsigned char *palette);
// called at startup and after any gamma correction
 
void VID_ShiftPalette (unsigned char *palette);
// called for bonus and pain flashes, and for underwater color changes
 
void VID_Init (unsigned char *palette);
// Called at startup to set up translation tables, takes 256 8 bit RGB values
// the palette data will go away after the call, so it must be copied off if
// the video driver will need it again
 
void VID_Shutdown (void);
// Called at shutdown
 
void VID_Update (vrect_t *rects);
// flushes the given rectangles from the view buffer to the screen
 
int VID_SetMode (int modenum, unsigned char *palette);
// sets the mode; only used by the Quake engine for resetting to mode 0 (the
// base mode) on memory allocation failures
 
void VID_HandlePause (qboolean pause);
// called only on Win32, when pause happens, so the mouse can be released
 
/contrib/other/sdlquake-1.0.9/vid_dos.c
0,0 → 1,778
/*
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.
 
*/
//
// vid_dos.c: DOS-specific video routines
//
 
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dos.h>
#include <dpmi.h>
#include <go32.h>
 
#include "quakedef.h"
#include "d_local.h"
#include "dosisms.h"
#include "vid_dos.h"
 
int vid_modenum;
vmode_t *pcurrentmode = NULL;
int vid_testingmode, vid_realmode;
double vid_testendtime;
 
cvar_t vid_mode = {"vid_mode","0", false};
cvar_t vid_wait = {"vid_wait","0"};
cvar_t vid_nopageflip = {"vid_nopageflip","0", true};
cvar_t _vid_wait_override = {"_vid_wait_override", "0", true};
cvar_t _vid_default_mode = {"_vid_default_mode","0", true};
cvar_t _vid_default_mode_win = {"_vid_default_mode_win","1", true};
cvar_t vid_config_x = {"vid_config_x","800", true};
cvar_t vid_config_y = {"vid_config_y","600", true};
cvar_t vid_stretch_by_2 = {"vid_stretch_by_2","1", true};
cvar_t _windowed_mouse = {"_windowed_mouse","0", true};
cvar_t vid_fullscreen_mode = {"vid_fullscreen_mode","3", true};
cvar_t vid_windowed_mode = {"vid_windowed_mode","0", true};
cvar_t block_switch = {"block_switch","0", true};
cvar_t vid_window_x = {"vid_window_x", "0", true};
cvar_t vid_window_y = {"vid_window_y", "0", true};
 
int d_con_indirect = 0;
 
int numvidmodes;
vmode_t *pvidmodes;
 
static int firstupdate = 1;
 
extern regs_t regs;
 
void VID_TestMode_f (void);
void VID_NumModes_f (void);
void VID_DescribeCurrentMode_f (void);
void VID_DescribeMode_f (void);
void VID_DescribeModes_f (void);
 
byte vid_current_palette[768]; // save for mode changes
 
 
static qboolean nomodecheck = false;
 
unsigned short d_8to16table[256]; // not used in 8 bpp mode
unsigned d_8to24table[256]; // not used in 8 bpp mode
 
void VID_MenuDraw (void);
void VID_MenuKey (int key);
 
 
/*
================
VID_Init
================
*/
void VID_Init (unsigned char *palette)
{
Cvar_RegisterVariable (&vid_mode);
Cvar_RegisterVariable (&vid_wait);
Cvar_RegisterVariable (&vid_nopageflip);
Cvar_RegisterVariable (&_vid_wait_override);
Cvar_RegisterVariable (&_vid_default_mode);
Cvar_RegisterVariable (&_vid_default_mode_win);
Cvar_RegisterVariable (&vid_config_x);
Cvar_RegisterVariable (&vid_config_y);
Cvar_RegisterVariable (&vid_stretch_by_2);
Cvar_RegisterVariable (&_windowed_mouse);
Cvar_RegisterVariable (&vid_fullscreen_mode);
Cvar_RegisterVariable (&vid_windowed_mode);
Cvar_RegisterVariable (&block_switch);
 
Cmd_AddCommand ("vid_testmode", VID_TestMode_f);
Cmd_AddCommand ("vid_nummodes", VID_NumModes_f);
Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f);
Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f);
Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f);
 
// set up the mode list; note that later inits link in their modes ahead of
// earlier ones, so the standard VGA modes are always first in the list. This
// is important because mode 0 must always be VGA mode 0x13
if (!COM_CheckParm ("-stdvid"))
VID_InitExtra ();
VGA_Init ();
 
vid_testingmode = 0;
 
vid_modenum = vid_mode.value;
 
VID_SetMode (vid_modenum, palette);
 
vid_realmode = vid_modenum;
vid_menudrawfn = VID_MenuDraw;
vid_menukeyfn = VID_MenuKey;
}
 
 
/*
=================
VID_GetModePtr
=================
*/
vmode_t *VID_GetModePtr (int modenum)
{
vmode_t *pv;
 
pv = pvidmodes;
if (!pv)
Sys_Error ("VID_GetModePtr: empty vid mode list");
 
while (modenum--)
{
pv = pv->pnext;
if (!pv)
Sys_Error ("VID_GetModePtr: corrupt vid mode list");
}
 
return pv;
}
 
/*
================
VID_NumModes
================
*/
int VID_NumModes ()
{
return (numvidmodes);
}
 
 
/*
================
VID_ModeInfo
================
*/
char *VID_ModeInfo (int modenum, char **ppheader)
{
static char *badmodestr = "Bad mode number";
vmode_t *pv;
 
pv = VID_GetModePtr (modenum);
 
if (!pv)
{
if (ppheader)
*ppheader = NULL;
return badmodestr;
}
else
{
if (ppheader)
*ppheader = pv->header;
return pv->name;
}
}
 
 
/*
================
VID_SetMode
================
*/
int VID_SetMode (int modenum, unsigned char *palette)
{
int stat;
vmode_t *pnewmode, *poldmode;
 
if ((modenum >= numvidmodes) || (modenum < 0))
{
Cvar_SetValue ("vid_mode", (float)vid_modenum);
 
nomodecheck = true;
Con_Printf ("No such video mode: %d\n", modenum);
nomodecheck = false;
 
if (pcurrentmode == NULL)
{
modenum = 0; // mode hasn't been set yet, so initialize to base
// mode since they gave us an invalid initial mode
}
else
{
return 0;
}
}
 
pnewmode = VID_GetModePtr (modenum);
 
if (pnewmode == pcurrentmode)
return 1; // already in the desired mode
 
// initialize the new mode
poldmode = pcurrentmode;
pcurrentmode = pnewmode;
 
vid.width = pcurrentmode->width;
vid.height = pcurrentmode->height;
vid.aspect = pcurrentmode->aspect;
vid.rowbytes = pcurrentmode->rowbytes;
 
stat = (*pcurrentmode->setmode) (&vid, pcurrentmode);
 
if (stat < 1)
{
if (stat == 0)
{
// real, hard failure that requires resetting the mode
if (!VID_SetMode (vid_modenum, palette)) // restore prior mode
Sys_Error ("VID_SetMode: Unable to set any mode, probably "
"because there's not enough memory available");
Con_Printf ("Failed to set mode %d\n", modenum);
return 0;
}
else if (stat == -1)
{
// not enough memory; just put things back the way they were
pcurrentmode = poldmode;
vid.width = pcurrentmode->width;
vid.height = pcurrentmode->height;
vid.aspect = pcurrentmode->aspect;
vid.rowbytes = pcurrentmode->rowbytes;
return 0;
}
else
{
Sys_Error ("VID_SetMode: invalid setmode return code %d");
}
}
 
(*pcurrentmode->setpalette) (&vid, pcurrentmode, palette);
 
vid_modenum = modenum;
Cvar_SetValue ("vid_mode", (float)vid_modenum);
 
nomodecheck = true;
Con_Printf ("%s\n", VID_ModeInfo (vid_modenum, NULL));
nomodecheck = false;
 
vid.recalc_refdef = 1;
 
return 1;
}
 
 
/*
================
VID_SetPalette
================
*/
void VID_SetPalette (unsigned char *palette)
{
if (palette != vid_current_palette)
Q_memcpy(vid_current_palette, palette, 768);
(*pcurrentmode->setpalette)(&vid, pcurrentmode, vid_current_palette);
}
 
 
/*
================
VID_ShiftPalette
================
*/
void VID_ShiftPalette (unsigned char *palette)
{
 
VID_SetPalette (palette);
}
 
 
/*
================
VID_Shutdown
================
*/
void VID_Shutdown (void)
{
 
regs.h.ah = 0;
regs.h.al = 0x3;
dos_int86(0x10);
 
vid_testingmode = 0;
}
 
 
/*
================
VID_Update
================
*/
void VID_Update (vrect_t *rects)
{
if (firstupdate && _vid_default_mode.value)
{
if(_vid_default_mode.value >= numvidmodes)
Cvar_SetValue ("_vid_default_mode", 0);
 
firstupdate = 0;
Cvar_SetValue ("vid_mode", _vid_default_mode.value);
}
 
(*pcurrentmode->swapbuffers)(&vid, pcurrentmode, rects);
 
if (!nomodecheck)
{
if (vid_testingmode)
{
if (realtime >= vid_testendtime)
{
VID_SetMode (vid_realmode, vid_current_palette);
vid_testingmode = 0;
}
}
else
{
if (vid_mode.value != vid_realmode)
{
VID_SetMode ((int)vid_mode.value, vid_current_palette);
Cvar_SetValue ("vid_mode", (float)vid_modenum);
// so if mode set fails, we don't keep on
// trying to set that mode
vid_realmode = vid_modenum;
}
}
}
}
 
 
/*
=================
VID_NumModes_f
=================
*/
void VID_NumModes_f (void)
{
int nummodes;
 
nummodes = VID_NumModes ();
if (nummodes == 1)
Con_Printf ("%d video mode is available\n", VID_NumModes ());
else
Con_Printf ("%d video modes are available\n", VID_NumModes ());
}
 
 
/*
=================
VID_DescribeCurrentMode_f
=================
*/
void VID_DescribeCurrentMode_f (void)
{
Con_Printf ("%s\n", VID_ModeInfo (vid_modenum, NULL));
}
 
 
/*
=================
VID_DescribeMode_f
=================
*/
void VID_DescribeMode_f (void)
{
int modenum;
modenum = Q_atoi (Cmd_Argv(1));
 
Con_Printf ("%s\n", VID_ModeInfo (modenum, NULL));
}
 
 
/*
=================
VID_DescribeModes_f
=================
*/
void VID_DescribeModes_f (void)
{
int i, nummodes;
char *pinfo, *pheader;
vmode_t *pv;
qboolean na;
 
na = false;
 
nummodes = VID_NumModes ();
for (i=0 ; i<nummodes ; i++)
{
pv = VID_GetModePtr (i);
pinfo = VID_ModeInfo (i, &pheader);
if (pheader)
Con_Printf ("\n%s\n", pheader);
 
if (VGA_CheckAdequateMem (pv->width, pv->height, pv->rowbytes,
(pv->numpages == 1) || vid_nopageflip.value))
{
Con_Printf ("%2d: %s\n", i, pinfo);
}
else
{
Con_Printf ("**: %s\n", pinfo);
na = true;
}
}
 
if (na)
{
Con_Printf ("\n[**: not enough system RAM for mode]\n");
}
}
 
 
/*
=================
VID_GetModeDescription
=================
*/
char *VID_GetModeDescription (int mode)
{
char *pinfo, *pheader;
vmode_t *pv;
 
pv = VID_GetModePtr (mode);
pinfo = VID_ModeInfo (mode, &pheader);
 
if (VGA_CheckAdequateMem (pv->width, pv->height, pv->rowbytes,
(pv->numpages == 1) || vid_nopageflip.value))
{
return pinfo;
}
else
{
return NULL;
}
}
 
 
/*
=================
VID_TestMode_f
=================
*/
void VID_TestMode_f (void)
{
int modenum;
double testduration;
 
if (!vid_testingmode)
{
modenum = Q_atoi (Cmd_Argv(1));
 
if (VID_SetMode (modenum, vid_current_palette))
{
vid_testingmode = 1;
testduration = Q_atof (Cmd_Argv(2));
if (testduration == 0)
testduration = 5.0;
vid_testendtime = realtime + testduration;
}
}
}
 
 
/*
================
D_BeginDirectRect
================
*/
void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
{
 
if (!vid.direct || !pcurrentmode)
return;
 
if ((width > 24) || (height > 24) || (width < 1) || (height < 1))
return;
 
if (width & 0x03)
return;
 
(*pcurrentmode->begindirectrect) (&vid, pcurrentmode, x, y, pbitmap, width,
height);
}
 
 
/*
================
D_EndDirectRect
================
*/
void D_EndDirectRect (int x, int y, int width, int height)
{
 
if (!vid.direct || !pcurrentmode)
return;
 
if ((width > 24) || (height > 24) || (width < 1) || (height < 1))
return;
 
if ((width & 0x03) || (height & 0x03))
return;
 
(*pcurrentmode->enddirectrect) (&vid, pcurrentmode, x, y, width, height);
}
 
 
//===========================================================================
 
extern void M_Menu_Options_f (void);
extern void M_Print (int cx, int cy, char *str);
extern void M_PrintWhite (int cx, int cy, char *str);
extern void M_DrawCharacter (int cx, int line, int num);
extern void M_DrawTransPic (int x, int y, qpic_t *pic);
extern void M_DrawPic (int x, int y, qpic_t *pic);
 
static int vid_line, vid_wmodes, vid_column_size;
 
typedef struct
{
int modenum;
char *desc;
int iscur;
} modedesc_t;
 
#define MAX_COLUMN_SIZE 11
 
#define MAX_MODEDESCS (MAX_COLUMN_SIZE*3)
 
static modedesc_t modedescs[MAX_MODEDESCS];
 
/*
================
VID_MenuDraw
================
*/
void VID_MenuDraw (void)
{
qpic_t *p;
char *ptr;
int nummodes, i, j, column, row, dup;
char temp[100];
 
vid_wmodes = 0;
nummodes = VID_NumModes ();
p = Draw_CachePic ("gfx/vidmodes.lmp");
M_DrawPic ( (320-p->width)/2, 4, p);
 
for (i=0 ; i<nummodes ; i++)
{
if (vid_wmodes < MAX_MODEDESCS)
{
if (i != 1)
{
ptr = VID_GetModeDescription (i);
 
if (ptr)
{
dup = 0;
 
for (j=0 ; j<vid_wmodes ; j++)
{
if (!strcmp (modedescs[j].desc, ptr))
{
if (modedescs[j].modenum != 0)
{
modedescs[j].modenum = i;
dup = 1;
 
if (i == vid_modenum)
modedescs[j].iscur = 1;
}
else
{
dup = 1;
}
 
break;
}
}
 
if (!dup)
{
modedescs[vid_wmodes].modenum = i;
modedescs[vid_wmodes].desc = ptr;
modedescs[vid_wmodes].iscur = 0;
 
if (i == vid_modenum)
modedescs[vid_wmodes].iscur = 1;
 
vid_wmodes++;
}
}
}
}
}
 
vid_column_size = (vid_wmodes + 2) / 3;
 
column = 16;
row = 36;
 
for (i=0 ; i<vid_wmodes ; i++)
{
if (modedescs[i].iscur)
M_PrintWhite (column, row, modedescs[i].desc);
else
M_Print (column, row, modedescs[i].desc);
 
row += 8;
 
if ((i % vid_column_size) == (vid_column_size - 1))
{
column += 13*8;
row = 36;
}
}
 
// line cursor
if (vid_testingmode)
{
sprintf (temp, "TESTING %s",
modedescs[vid_line].desc);
M_Print (13*8, 36 + MAX_COLUMN_SIZE * 8 + 8*4, temp);
M_Print (9*8, 36 + MAX_COLUMN_SIZE * 8 + 8*6,
"Please wait 5 seconds...");
}
else
{
M_Print (9*8, 36 + MAX_COLUMN_SIZE * 8 + 8,
"Press Enter to set mode");
M_Print (6*8, 36 + MAX_COLUMN_SIZE * 8 + 8*3,
"T to test mode for 5 seconds");
ptr = VID_GetModeDescription (vid_modenum);
sprintf (temp, "D to make %s the default", ptr);
M_Print (6*8, 36 + MAX_COLUMN_SIZE * 8 + 8*5, temp);
ptr = VID_GetModeDescription ((int)_vid_default_mode.value);
 
if (ptr)
{
sprintf (temp, "Current default is %s", ptr);
M_Print (7*8, 36 + MAX_COLUMN_SIZE * 8 + 8*6, temp);
}
 
M_Print (15*8, 36 + MAX_COLUMN_SIZE * 8 + 8*8,
"Esc to exit");
 
row = 36 + (vid_line % vid_column_size) * 8;
column = 8 + (vid_line / vid_column_size) * 13*8;
 
M_DrawCharacter (column, row, 12+((int)(realtime*4)&1));
}
}
 
 
/*
================
VID_MenuKey
================
*/
void VID_MenuKey (int key)
{
if (vid_testingmode)
return;
 
switch (key)
{
case K_ESCAPE:
S_LocalSound ("misc/menu1.wav");
M_Menu_Options_f ();
break;
 
case K_UPARROW:
S_LocalSound ("misc/menu1.wav");
vid_line--;
 
if (vid_line < 0)
vid_line = vid_wmodes - 1;
break;
 
case K_DOWNARROW:
S_LocalSound ("misc/menu1.wav");
vid_line++;
 
if (vid_line >= vid_wmodes)
vid_line = 0;
break;
 
case K_LEFTARROW:
S_LocalSound ("misc/menu1.wav");
vid_line -= vid_column_size;
 
if (vid_line < 0)
{
vid_line += ((vid_wmodes + (vid_column_size - 1)) /
vid_column_size) * vid_column_size;
 
while (vid_line >= vid_wmodes)
vid_line -= vid_column_size;
}
break;
 
case K_RIGHTARROW:
S_LocalSound ("misc/menu1.wav");
vid_line += vid_column_size;
 
if (vid_line >= vid_wmodes)
{
vid_line -= ((vid_wmodes + (vid_column_size - 1)) /
vid_column_size) * vid_column_size;
 
while (vid_line < 0)
vid_line += vid_column_size;
}
break;
 
case K_ENTER:
S_LocalSound ("misc/menu1.wav");
VID_SetMode (modedescs[vid_line].modenum, vid_current_palette);
break;
 
case 'T':
case 't':
S_LocalSound ("misc/menu1.wav");
if (VID_SetMode (modedescs[vid_line].modenum, vid_current_palette))
{
vid_testingmode = 1;
vid_testendtime = realtime + 5.0;
}
break;
 
case 'D':
case 'd':
S_LocalSound ("misc/menu1.wav");
firstupdate = 0;
Cvar_SetValue ("_vid_default_mode", vid_modenum);
break;
 
default:
break;
}
}
 
/contrib/other/sdlquake-1.0.9/vid_dos.h
0,0 → 1,83
/*
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.
 
*/
// vid_dos.h: header file for DOS-specific video stuff
 
typedef struct vmode_s {
struct vmode_s *pnext;
char *name;
char *header;
unsigned width;
unsigned height;
float aspect;
unsigned rowbytes;
int planar;
int numpages;
void *pextradata;
int (*setmode)(viddef_t *vid, struct vmode_s *pcurrentmode);
void (*swapbuffers)(viddef_t *vid, struct vmode_s *pcurrentmode,
vrect_t *rects);
void (*setpalette)(viddef_t *vid, struct vmode_s *pcurrentmode,
unsigned char *palette);
void (*begindirectrect)(viddef_t *vid, struct vmode_s *pcurrentmode,
int x, int y, byte *pbitmap, int width,
int height);
void (*enddirectrect)(viddef_t *vid, struct vmode_s *pcurrentmode,
int x, int y, int width, int height);
} vmode_t;
 
// vid_wait settings
#define VID_WAIT_NONE 0
#define VID_WAIT_VSYNC 1
#define VID_WAIT_DISPLAY_ENABLE 2
 
extern int numvidmodes;
extern vmode_t *pvidmodes;
 
extern int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes;
extern byte *VGA_pagebase;
extern vmode_t *VGA_pcurmode;
 
extern cvar_t vid_wait;
extern cvar_t vid_nopageflip;
extern cvar_t _vid_wait_override;
 
extern unsigned char colormap256[32][256];
 
extern void *vid_surfcache;
extern int vid_surfcachesize;
 
void VGA_Init (void);
void VID_InitVESA (void);
void VID_InitExtra (void);
void VGA_WaitVsync (void);
void VGA_ClearVideoMem (int planar);
void VGA_SetPalette(viddef_t *vid, vmode_t *pcurrentmode, unsigned char *pal);
void VGA_SwapBuffersCopy (viddef_t *vid, vmode_t *pcurrentmode,
vrect_t *rects);
qboolean VGA_FreeAndAllocVidbuffer (viddef_t *vid, int allocnewbuffer);
qboolean VGA_CheckAdequateMem (int width, int height, int rowbytes,
int allocnewbuffer);
void VGA_BeginDirectRect (viddef_t *vid, struct vmode_s *pcurrentmode, int x,
int y, byte *pbitmap, int width, int height);
void VGA_EndDirectRect (viddef_t *vid, struct vmode_s *pcurrentmode, int x,
int y, int width, int height);
void VGA_UpdateLinearScreen (void *srcptr, void *destptr, int width,
int height, int srcrowbytes, int destrowbytes);
 
/contrib/other/sdlquake-1.0.9/vid_ext.c
0,0 → 1,795
/*
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.
 
*/
//
// vid_ext.c: extended video modes
// in this implementation, VESA-specific DOS video stuff
//
 
// TODO: make dependencies on vid_vga.c explicit or eliminate them
 
#include <stdlib.h>
#include <dos.h>
 
#include "quakedef.h"
#include "d_local.h"
#include "dosisms.h"
#include "vid_dos.h"
#include <dpmi.h>
 
#define MODE_SUPPORTED_IN_HW 0x0001
#define COLOR_MODE 0x0008
#define GRAPHICS_MODE 0x0010
#define VGA_INCOMPATIBLE 0x0020
#define LINEAR_FRAME_BUFFER 0x0080
 
#define LINEAR_MODE 0x4000
 
#define VESA_DONT_WAIT_VSYNC 0 // when page flipping
#define VESA_WAIT_VSYNC 0x80
 
#define MAX_VESA_MODES 30 // we'll just take the first 30 if there
// are more
typedef struct {
int pages[3]; // either 2 or 3 is valid
int vesamode; // LINEAR_MODE set if linear mode
void *plinearmem; // linear address of start of frame buffer
qboolean vga_incompatible;
} vesa_extra_t;
 
static vmode_t vesa_modes[MAX_VESA_MODES] =
{{NULL, NULL, " ********* VESA modes ********* "}};
static vesa_extra_t vesa_extra[MAX_VESA_MODES];
static char names[MAX_VESA_MODES][10];
 
extern regs_t regs;
 
static int VID_currentpage;
static int VID_displayedpage;
static int *VID_pagelist;
static byte *VID_membase;
static int VID_banked;
 
typedef struct
{
int modenum;
int mode_attributes;
int winasegment;
int winbsegment;
int bytes_per_scanline; // bytes per logical scanline (+16)
int win; // window number (A=0, B=1)
int win_size; // window size (+6)
int granularity; // how finely i can set the window in vid mem (+4)
int width, height; // displayed width and height (+18, +20)
int bits_per_pixel; // er, better be 8, 15, 16, 24, or 32 (+25)
int bytes_per_pixel; // er, better be 1, 2, or 4
int memory_model; // and better be 4 or 6, packed or direct color (+27)
int num_pages; // number of complete frame buffer pages (+29)
int red_width; // the # of bits in the red component (+31)
int red_pos; // the bit position of the red component (+32)
int green_width; // etc.. (+33)
int green_pos; // (+34)
int blue_width; // (+35)
int blue_pos; // (+36)
int pptr;
int pagesize;
int numpages;
} modeinfo_t;
 
static modeinfo_t modeinfo;
 
// all bytes to avoid problems with compiler field packing
typedef struct vbeinfoblock_s {
byte VbeSignature[4];
byte VbeVersion[2];
byte OemStringPtr[4];
byte Capabilities[4];
byte VideoModePtr[4];
byte TotalMemory[2];
byte OemSoftwareRev[2];
byte OemVendorNamePtr[4];
byte OemProductNamePtr[4];
byte OemProductRevPtr[4];
byte Reserved[222];
byte OemData[256];
} vbeinfoblock_t;
 
static int totalvidmem;
static byte *ppal;
qboolean vsync_exists, de_exists;
 
qboolean VID_ExtraGetModeInfo(int modenum);
int VID_ExtraInitMode (viddef_t *vid, vmode_t *pcurrentmode);
void VID_ExtraSwapBuffers (viddef_t *vid, vmode_t *pcurrentmode,
vrect_t *rects);
 
 
/*
================
VGA_BankedBeginDirectRect
================
*/
void VGA_BankedBeginDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode,
int x, int y, byte *pbitmap, int width, int height)
{
 
if (!lvid->direct)
return;
 
regs.x.ax = 0x4f05;
regs.x.bx = 0;
regs.x.dx = VID_displayedpage;
dos_int86(0x10);
 
VGA_BeginDirectRect (lvid, pcurrentmode, x, y, pbitmap, width, height);
 
regs.x.ax = 0x4f05;
regs.x.bx = 0;
regs.x.dx = VID_currentpage;
dos_int86(0x10);
}
 
 
/*
================
VGA_BankedEndDirectRect
================
*/
void VGA_BankedEndDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode,
int x, int y, int width, int height)
{
 
if (!lvid->direct)
return;
 
regs.x.ax = 0x4f05;
regs.x.bx = 0;
regs.x.dx = VID_displayedpage;
dos_int86(0x10);
 
VGA_EndDirectRect (lvid, pcurrentmode, x, y, width, height);
 
regs.x.ax = 0x4f05;
regs.x.bx = 0;
regs.x.dx = VID_currentpage;
dos_int86(0x10);
}
 
 
/*
================
VID_SetVESAPalette
================
*/
void VID_SetVESAPalette (viddef_t *lvid, vmode_t *pcurrentmode,
unsigned char *pal)
{
int i;
byte *pp;
 
UNUSED(lvid);
UNUSED(pcurrentmode);
 
pp = ppal;
 
for (i=0 ; i<256 ; i++)
{
pp[2] = pal[0] >> 2;
pp[1] = pal[1] >> 2;
pp[0] = pal[2] >> 2;
pp += 4;
pal += 3;
}
 
regs.x.ax = 0x4F09;
regs.x.bx = 0;
regs.x.cx = 256;
regs.x.dx = 0;
regs.x.es = ptr2real(ppal) >> 4;
regs.x.di = ptr2real(ppal) & 0xf;
dos_int86(0x10);
 
if (regs.x.ax != 0x4f)
Sys_Error ("Unable to load VESA palette\n");
}
 
 
 
 
/*
================
VID_ExtraFarToLinear
================
*/
void *VID_ExtraFarToLinear (void *ptr)
{
int temp;
 
temp = (int)ptr;
return real2ptr(((temp & 0xFFFF0000) >> 12) + (temp & 0xFFFF));
}
 
 
/*
================
VID_ExtraWaitDisplayEnable
================
*/
void VID_ExtraWaitDisplayEnable ()
{
while ((inportb (0x3DA) & 0x01) == 1)
;
}
 
 
/*
================
VID_ExtraVidLookForState
================
*/
qboolean VID_ExtraVidLookForState (unsigned state, unsigned mask)
{
int i;
double starttime, time;
 
starttime = Sys_FloatTime ();
 
do
{
for (i=0 ; i<100000 ; i++)
{
if ((inportb (0x3DA) & mask) == state)
return true;
}
 
time = Sys_FloatTime ();
} while ((time - starttime) < 0.1);
 
return false;
}
 
 
/*
================
VID_ExtraStateFound
================
*/
qboolean VID_ExtraStateFound (unsigned state)
{
int i, workingstate;
 
workingstate = 0;
 
for (i=0 ; i<10 ; i++)
{
if (!VID_ExtraVidLookForState(workingstate, state))
{
return false;
}
 
workingstate ^= state;
}
 
return true;
}
 
 
/*
================
VID_InitExtra
================
*/
void VID_InitExtra (void)
{
int nummodes;
short *pmodenums;
vbeinfoblock_t *pinfoblock;
__dpmi_meminfo phys_mem_info;
 
pinfoblock = dos_getmemory(sizeof(vbeinfoblock_t));
 
*(long *)pinfoblock->VbeSignature = 'V' + ('B'<<8) + ('E'<<16) + ('2'<<24);
 
// see if VESA support is available
regs.x.ax = 0x4f00;
regs.x.es = ptr2real(pinfoblock) >> 4;
regs.x.di = ptr2real(pinfoblock) & 0xf;
dos_int86(0x10);
 
if (regs.x.ax != 0x4f)
return; // no VESA support
 
if (pinfoblock->VbeVersion[1] < 0x02)
return; // not VESA 2.0 or greater
 
Con_Printf ("VESA 2.0 compliant adapter:\n%s\n",
VID_ExtraFarToLinear (*(byte **)&pinfoblock->OemStringPtr[0]));
 
totalvidmem = *(unsigned short *)&pinfoblock->TotalMemory[0] << 16;
 
pmodenums = (short *)
VID_ExtraFarToLinear (*(byte **)&pinfoblock->VideoModePtr[0]);
 
// find 8 bit modes until we either run out of space or run out of modes
nummodes = 0;
 
while ((*pmodenums != -1) && (nummodes < MAX_VESA_MODES))
{
if (VID_ExtraGetModeInfo (*pmodenums))
{
vesa_modes[nummodes].pnext = &vesa_modes[nummodes+1];
if (modeinfo.width > 999)
{
if (modeinfo.height > 999)
{
sprintf (&names[nummodes][0], "%4dx%4d", modeinfo.width,
modeinfo.height);
names[nummodes][9] = 0;
}
else
{
sprintf (&names[nummodes][0], "%4dx%3d", modeinfo.width,
modeinfo.height);
names[nummodes][8] = 0;
}
}
else
{
if (modeinfo.height > 999)
{
sprintf (&names[nummodes][0], "%3dx%4d", modeinfo.width,
modeinfo.height);
names[nummodes][8] = 0;
}
else
{
sprintf (&names[nummodes][0], "%3dx%3d", modeinfo.width,
modeinfo.height);
names[nummodes][7] = 0;
}
}
 
vesa_modes[nummodes].name = &names[nummodes][0];
vesa_modes[nummodes].width = modeinfo.width;
vesa_modes[nummodes].height = modeinfo.height;
vesa_modes[nummodes].aspect =
((float)modeinfo.height / (float)modeinfo.width) *
(320.0 / 240.0);
vesa_modes[nummodes].rowbytes = modeinfo.bytes_per_scanline;
vesa_modes[nummodes].planar = 0;
vesa_modes[nummodes].pextradata = &vesa_extra[nummodes];
vesa_modes[nummodes].setmode = VID_ExtraInitMode;
vesa_modes[nummodes].swapbuffers = VID_ExtraSwapBuffers;
vesa_modes[nummodes].setpalette = VID_SetVESAPalette;
 
if (modeinfo.mode_attributes & LINEAR_FRAME_BUFFER)
{
// add linear bit to mode for linear modes
vesa_extra[nummodes].vesamode = modeinfo.modenum | LINEAR_MODE;
vesa_extra[nummodes].pages[0] = 0;
vesa_extra[nummodes].pages[1] = modeinfo.pagesize;
vesa_extra[nummodes].pages[2] = modeinfo.pagesize * 2;
vesa_modes[nummodes].numpages = modeinfo.numpages;
 
vesa_modes[nummodes].begindirectrect = VGA_BeginDirectRect;
vesa_modes[nummodes].enddirectrect = VGA_EndDirectRect;
 
phys_mem_info.address = (int)modeinfo.pptr;
phys_mem_info.size = 0x400000;
 
if (__dpmi_physical_address_mapping(&phys_mem_info))
goto NextMode;
 
vesa_extra[nummodes].plinearmem =
real2ptr (phys_mem_info.address);
}
else
{
// banked at 0xA0000
vesa_extra[nummodes].vesamode = modeinfo.modenum;
vesa_extra[nummodes].pages[0] = 0;
vesa_extra[nummodes].plinearmem =
real2ptr(modeinfo.winasegment<<4);
 
vesa_modes[nummodes].begindirectrect =
VGA_BankedBeginDirectRect;
vesa_modes[nummodes].enddirectrect = VGA_BankedEndDirectRect;
vesa_extra[nummodes].pages[1] = modeinfo.pagesize;
vesa_extra[nummodes].pages[2] = modeinfo.pagesize * 2;
vesa_modes[nummodes].numpages = modeinfo.numpages;
}
 
vesa_extra[nummodes].vga_incompatible =
modeinfo.mode_attributes & VGA_INCOMPATIBLE;
 
nummodes++;
}
NextMode:
pmodenums++;
}
 
// add the VESA modes at the start of the mode list (if there are any)
if (nummodes)
{
vesa_modes[nummodes-1].pnext = pvidmodes;
pvidmodes = &vesa_modes[0];
numvidmodes += nummodes;
ppal = dos_getmemory(256*4);
}
 
dos_freememory(pinfoblock);
}
 
 
/*
================
VID_ExtraGetModeInfo
================
*/
qboolean VID_ExtraGetModeInfo(int modenum)
{
char *infobuf;
int numimagepages;
 
infobuf = dos_getmemory(256);
 
regs.x.ax = 0x4f01;
regs.x.cx = modenum;
regs.x.es = ptr2real(infobuf) >> 4;
regs.x.di = ptr2real(infobuf) & 0xf;
dos_int86(0x10);
if (regs.x.ax != 0x4f)
{
return false;
}
else
{
modeinfo.modenum = modenum;
modeinfo.bits_per_pixel = *(char*)(infobuf+25);
modeinfo.bytes_per_pixel = (modeinfo.bits_per_pixel+1)/8;
modeinfo.width = *(short*)(infobuf+18);
modeinfo.height = *(short*)(infobuf+20);
 
// we do only 8-bpp in software
if ((modeinfo.bits_per_pixel != 8) ||
(modeinfo.bytes_per_pixel != 1) ||
(modeinfo.width > MAXWIDTH) ||
(modeinfo.height > MAXHEIGHT))
{
return false;
}
 
modeinfo.mode_attributes = *(short*)infobuf;
 
// we only want color graphics modes that are supported by the hardware
if ((modeinfo.mode_attributes &
(MODE_SUPPORTED_IN_HW | COLOR_MODE | GRAPHICS_MODE)) !=
(MODE_SUPPORTED_IN_HW | COLOR_MODE | GRAPHICS_MODE))
{
return false;
}
 
// we only work with linear frame buffers, except for 320x200, which can
// effectively be linear when banked at 0xA000
if (!(modeinfo.mode_attributes & LINEAR_FRAME_BUFFER))
{
if ((modeinfo.width != 320) || (modeinfo.height != 200))
return false;
}
 
modeinfo.bytes_per_scanline = *(short*)(infobuf+16);
 
modeinfo.pagesize = modeinfo.bytes_per_scanline * modeinfo.height;
 
if (modeinfo.pagesize > totalvidmem)
return false;
 
// force to one page if the adapter reports it doesn't support more pages
// than that, no matter how much memory it has--it may not have hardware
// support for page flipping
numimagepages = *(unsigned char *)(infobuf+29);
 
if (numimagepages <= 0)
{
// wrong, but there seems to be an ATI VESA driver that reports 0
modeinfo.numpages = 1;
}
else if (numimagepages < 3)
{
modeinfo.numpages = numimagepages;
}
else
{
modeinfo.numpages = 3;
}
 
if (*(char*)(infobuf+2) & 5)
{
modeinfo.winasegment = *(unsigned short*)(infobuf+8);
modeinfo.win = 0;
}
else if (*(char*)(infobuf+3) & 5)
{
modeinfo.winbsegment = *(unsigned short*)(infobuf+8);
modeinfo.win = 1;
}
modeinfo.granularity = *(short*)(infobuf+4) * 1024;
modeinfo.win_size = *(short*)(infobuf+6) * 1024;
modeinfo.bits_per_pixel = *(char*)(infobuf+25);
modeinfo.bytes_per_pixel = (modeinfo.bits_per_pixel+1)/8;
modeinfo.memory_model = *(unsigned char*)(infobuf+27);
modeinfo.num_pages = *(char*)(infobuf+29) + 1;
 
modeinfo.red_width = *(char*)(infobuf+31);
modeinfo.red_pos = *(char*)(infobuf+32);
modeinfo.green_width = *(char*)(infobuf+33);
modeinfo.green_pos = *(char*)(infobuf+34);
modeinfo.blue_width = *(char*)(infobuf+35);
modeinfo.blue_pos = *(char*)(infobuf+36);
 
modeinfo.pptr = *(long *)(infobuf+40);
 
#if 0
printf("VID: (VESA) info for mode 0x%x\n", modeinfo.modenum);
printf(" mode attrib = 0x%0x\n", modeinfo.mode_attributes);
printf(" win a attrib = 0x%0x\n", *(unsigned char*)(infobuf+2));
printf(" win b attrib = 0x%0x\n", *(unsigned char*)(infobuf+3));
printf(" win a seg 0x%0x\n", (int) modeinfo.winasegment);
printf(" win b seg 0x%0x\n", (int) modeinfo.winbsegment);
printf(" bytes per scanline = %d\n",
modeinfo.bytes_per_scanline);
printf(" width = %d, height = %d\n", modeinfo.width,
modeinfo.height);
printf(" win = %c\n", 'A' + modeinfo.win);
printf(" win granularity = %d\n", modeinfo.granularity);
printf(" win size = %d\n", modeinfo.win_size);
printf(" bits per pixel = %d\n", modeinfo.bits_per_pixel);
printf(" bytes per pixel = %d\n", modeinfo.bytes_per_pixel);
printf(" memory model = 0x%x\n", modeinfo.memory_model);
printf(" num pages = %d\n", modeinfo.num_pages);
printf(" red width = %d\n", modeinfo.red_width);
printf(" red pos = %d\n", modeinfo.red_pos);
printf(" green width = %d\n", modeinfo.green_width);
printf(" green pos = %d\n", modeinfo.green_pos);
printf(" blue width = %d\n", modeinfo.blue_width);
printf(" blue pos = %d\n", modeinfo.blue_pos);
printf(" phys mem = %x\n", modeinfo.pptr);
#endif
}
 
dos_freememory(infobuf);
 
return true;
}
 
 
/*
================
VID_ExtraInitMode
================
*/
int VID_ExtraInitMode (viddef_t *lvid, vmode_t *pcurrentmode)
{
vesa_extra_t *pextra;
int pageoffset;
 
pextra = pcurrentmode->pextradata;
 
if (vid_nopageflip.value)
lvid->numpages = 1;
else
lvid->numpages = pcurrentmode->numpages;
 
// clean up any old vid buffer lying around, alloc new if needed
if (!VGA_FreeAndAllocVidbuffer (lvid, lvid->numpages == 1))
return -1; // memory alloc failed
 
// clear the screen and wait for the next frame. VGA_pcurmode, which
// VGA_ClearVideoMem relies on, is guaranteed to be set because mode 0 is
// always the first mode set in a session
if (VGA_pcurmode)
VGA_ClearVideoMem (VGA_pcurmode->planar);
 
// set the mode
regs.x.ax = 0x4f02;
regs.x.bx = pextra->vesamode;
dos_int86(0x10);
 
if (regs.x.ax != 0x4f)
return 0;
 
VID_banked = !(pextra->vesamode & LINEAR_MODE);
VID_membase = pextra->plinearmem;
VGA_width = lvid->width;
VGA_height = lvid->height;
VGA_rowbytes = lvid->rowbytes;
 
lvid->colormap = host_colormap;
 
VID_pagelist = &pextra->pages[0];
 
// wait for display enable by default only when triple-buffering on a VGA-
// compatible machine that actually has a functioning display enable status
vsync_exists = VID_ExtraStateFound (0x08);
de_exists = VID_ExtraStateFound (0x01);
 
if (!pextra->vga_incompatible &&
(lvid->numpages == 3) &&
de_exists &&
(_vid_wait_override.value == 0.0))
{
Cvar_SetValue ("vid_wait", (float)VID_WAIT_DISPLAY_ENABLE);
 
VID_displayedpage = 0;
VID_currentpage = 1;
}
else
{
if ((lvid->numpages == 1) && (_vid_wait_override.value == 0.0))
{
Cvar_SetValue ("vid_wait", (float)VID_WAIT_NONE);
VID_displayedpage = VID_currentpage = 0;
}
else
{
Cvar_SetValue ("vid_wait", (float)VID_WAIT_VSYNC);
 
VID_displayedpage = 0;
 
if (lvid->numpages > 1)
VID_currentpage = 1;
else
VID_currentpage = 0;
}
}
 
// TODO: really should be a call to a function
pageoffset = VID_pagelist[VID_displayedpage];
 
regs.x.ax = 0x4f07;
regs.x.bx = 0x80; // wait for vsync so we know page 0 is visible
regs.x.cx = pageoffset % VGA_rowbytes;
regs.x.dx = pageoffset / VGA_rowbytes;
dos_int86(0x10);
 
if (VID_banked)
{
regs.x.ax = 0x4f05;
regs.x.bx = 0;
regs.x.dx = VID_currentpage;
dos_int86(0x10);
 
VGA_pagebase = VID_membase;
}
else
{
VGA_pagebase = VID_membase + VID_pagelist[VID_currentpage];
}
 
if (lvid->numpages > 1)
{
lvid->buffer = VGA_pagebase;
lvid->conbuffer = lvid->buffer;
}
else
{
lvid->rowbytes = lvid->width;
}
 
lvid->direct = VGA_pagebase;
lvid->conrowbytes = lvid->rowbytes;
lvid->conwidth = lvid->width;
lvid->conheight = lvid->height;
 
lvid->maxwarpwidth = WARP_WIDTH;
lvid->maxwarpheight = WARP_HEIGHT;
 
VGA_pcurmode = pcurrentmode;
 
D_InitCaches (vid_surfcache, vid_surfcachesize);
 
return 1;
}
 
 
/*
================
VID_ExtraSwapBuffers
================
*/
void VID_ExtraSwapBuffers (viddef_t *lvid, vmode_t *pcurrentmode,
vrect_t *rects)
{
int pageoffset;
 
UNUSED(rects);
UNUSED(pcurrentmode);
 
pageoffset = VID_pagelist[VID_currentpage];
 
// display the newly finished page
if (lvid->numpages > 1)
{
// page flipped
regs.x.ax = 0x4f07;
if (vid_wait.value != VID_WAIT_VSYNC)
{
if ((vid_wait.value == VID_WAIT_DISPLAY_ENABLE) && de_exists)
VID_ExtraWaitDisplayEnable ();
regs.x.bx = VESA_DONT_WAIT_VSYNC;
}
else
{
regs.x.bx = VESA_WAIT_VSYNC; // double buffered has to wait
}
 
regs.x.cx = pageoffset % VGA_rowbytes;
regs.x.dx = pageoffset / VGA_rowbytes;
dos_int86(0x10);
VID_displayedpage = VID_currentpage;
if (++VID_currentpage >= lvid->numpages)
VID_currentpage = 0;
//
// set the new write window if this is a banked mode; otherwise, set the
// new address to which to write
//
if (VID_banked)
{
regs.x.ax = 0x4f05;
regs.x.bx = 0;
regs.x.dx = VID_currentpage;
dos_int86(0x10);
}
else
{
lvid->direct = lvid->buffer; // direct drawing goes to the
// currently displayed page
lvid->buffer = VID_membase + VID_pagelist[VID_currentpage];
lvid->conbuffer = lvid->buffer;
}
VGA_pagebase = lvid->buffer;
}
else
{
// non-page-flipped
if (vsync_exists && (vid_wait.value == VID_WAIT_VSYNC))
{
VGA_WaitVsync ();
}
 
while (rects)
{
VGA_UpdateLinearScreen (
lvid->buffer + rects->x + (rects->y * lvid->rowbytes),
VGA_pagebase + rects->x + (rects->y * VGA_rowbytes),
rects->width,
rects->height,
lvid->rowbytes,
VGA_rowbytes);
 
rects = rects->pnext;
}
}
}
 
/contrib/other/sdlquake-1.0.9/vid_null.c
0,0 → 1,87
/*
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.
 
*/
// vid_null.c -- null video driver to aid porting efforts
 
#include "quakedef.h"
#include "d_local.h"
 
viddef_t vid; // global video state
 
#define BASEWIDTH 320
#define BASEHEIGHT 200
 
byte vid_buffer[BASEWIDTH*BASEHEIGHT];
short zbuffer[BASEWIDTH*BASEHEIGHT];
byte surfcache[256*1024];
 
unsigned short d_8to16table[256];
unsigned d_8to24table[256];
 
void VID_SetPalette (unsigned char *palette)
{
}
 
void VID_ShiftPalette (unsigned char *palette)
{
}
 
void VID_Init (unsigned char *palette)
{
vid.maxwarpwidth = vid.width = vid.conwidth = BASEWIDTH;
vid.maxwarpheight = vid.height = vid.conheight = BASEHEIGHT;
vid.aspect = 1.0;
vid.numpages = 1;
vid.colormap = host_colormap;
vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
vid.buffer = vid.conbuffer = vid_buffer;
vid.rowbytes = vid.conrowbytes = BASEWIDTH;
d_pzbuffer = zbuffer;
D_InitCaches (surfcache, sizeof(surfcache));
}
 
void VID_Shutdown (void)
{
}
 
void VID_Update (vrect_t *rects)
{
}
 
/*
================
D_BeginDirectRect
================
*/
void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
{
}
 
 
/*
================
D_EndDirectRect
================
*/
void D_EndDirectRect (int x, int y, int width, int height)
{
}
 
 
/contrib/other/sdlquake-1.0.9/vid_sdl.c
0,0 → 1,393
// vid_sdl.h -- sdl video driver
 
#include "SDL.h"
#include "quakedef.h"
#include "d_local.h"
 
viddef_t vid; // global video state
unsigned short d_8to16table[256];
 
// The original defaults
//#define BASEWIDTH 320
//#define BASEHEIGHT 200
// Much better for high resolution displays
#define BASEWIDTH (320*2)
#define BASEHEIGHT (200*2)
 
int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes = 0;
byte *VGA_pagebase;
 
static SDL_Surface *screen = NULL;
 
static qboolean mouse_avail;
static float mouse_x, mouse_y;
static int mouse_oldbuttonstate = 0;
 
// No support for option menus
void (*vid_menudrawfn)(void) = NULL;
void (*vid_menukeyfn)(int key) = NULL;
 
void VID_SetPalette (unsigned char *palette)
{
int i;
SDL_Color colors[256];
 
for ( i=0; i<256; ++i )
{
colors[i].r = *palette++;
colors[i].g = *palette++;
colors[i].b = *palette++;
}
SDL_SetColors(screen, colors, 0, 256);
}
 
void VID_ShiftPalette (unsigned char *palette)
{
VID_SetPalette(palette);
}
 
void VID_Init (unsigned char *palette)
{
int pnum, chunk;
byte *cache;
int cachesize;
Uint8 video_bpp;
Uint16 video_w, video_h;
Uint32 flags;
 
// Load the SDL library
#ifdef _KOLIBRI
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) < 0)
#else
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO|SDL_INIT_CDROM) < 0)
#endif
Sys_Error("VID: Couldn't load SDL: %s", SDL_GetError());
 
// Set up display mode (width and height)
vid.width = BASEWIDTH;
vid.height = BASEHEIGHT;
vid.maxwarpwidth = WARP_WIDTH;
vid.maxwarpheight = WARP_HEIGHT;
if ((pnum=COM_CheckParm("-winsize")))
{
if (pnum >= com_argc-2)
Sys_Error("VID: -winsize <width> <height>\n");
vid.width = Q_atoi(com_argv[pnum+1]);
vid.height = Q_atoi(com_argv[pnum+2]);
if (!vid.width || !vid.height)
Sys_Error("VID: Bad window width/height\n");
}
 
// Set video width, height and flags
flags = (SDL_SWSURFACE|SDL_HWPALETTE);
if ( COM_CheckParm ("-fullscreen") )
flags |= SDL_FULLSCREEN;
 
// Initialize display
if (!(screen = SDL_SetVideoMode(vid.width, vid.height, 8, flags)))
Sys_Error("VID: Couldn't set video mode: %s\n", SDL_GetError());
VID_SetPalette(palette);
SDL_WM_SetCaption("sdlquake","sdlquake");
// now know everything we need to know about the buffer
VGA_width = vid.conwidth = vid.width;
VGA_height = vid.conheight = vid.height;
vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0);
vid.numpages = 1;
vid.colormap = host_colormap;
vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
VGA_pagebase = vid.buffer = screen->pixels;
VGA_rowbytes = vid.rowbytes = screen->pitch;
vid.conbuffer = vid.buffer;
vid.conrowbytes = vid.rowbytes;
vid.direct = 0;
// allocate z buffer and surface cache
chunk = vid.width * vid.height * sizeof (*d_pzbuffer);
cachesize = D_SurfaceCacheForRes (vid.width, vid.height);
chunk += cachesize;
d_pzbuffer = Hunk_HighAllocName(chunk, "video");
if (d_pzbuffer == NULL)
Sys_Error ("Not enough memory for video mode\n");
 
// initialize the cache memory
cache = (byte *) d_pzbuffer
+ vid.width * vid.height * sizeof (*d_pzbuffer);
D_InitCaches (cache, cachesize);
 
// initialize the mouse
SDL_ShowCursor(0);
}
 
void VID_Shutdown (void)
{
SDL_Quit();
}
 
void VID_Update (vrect_t *rects)
{
SDL_Rect *sdlrects;
int n, i;
vrect_t *rect;
 
// Two-pass system, since Quake doesn't do it the SDL way...
 
// First, count the number of rectangles
n = 0;
for (rect = rects; rect; rect = rect->pnext)
++n;
 
// Second, copy them to SDL rectangles and update
if (!(sdlrects = (SDL_Rect *)alloca(n*sizeof(*sdlrects))))
Sys_Error("Out of memory");
i = 0;
for (rect = rects; rect; rect = rect->pnext)
{
sdlrects[i].x = rect->x;
sdlrects[i].y = rect->y;
sdlrects[i].w = rect->width;
sdlrects[i].h = rect->height;
++i;
}
SDL_UpdateRects(screen, n, sdlrects);
}
 
/*
================
D_BeginDirectRect
================
*/
void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
{
Uint8 *offset;
 
 
if (!screen) return;
if ( x < 0 ) x = screen->w+x-1;
offset = (Uint8 *)screen->pixels + y*screen->pitch + x;
while ( height-- )
{
memcpy(offset, pbitmap, width);
offset += screen->pitch;
pbitmap += width;
}
}
 
 
/*
================
D_EndDirectRect
================
*/
void D_EndDirectRect (int x, int y, int width, int height)
{
if (!screen) return;
if (x < 0) x = screen->w+x-1;
SDL_UpdateRect(screen, x, y, width, height);
}
 
 
/*
================
Sys_SendKeyEvents
================
*/
 
void Sys_SendKeyEvents(void)
{
SDL_Event event;
int sym, state;
int modstate;
 
while (SDL_PollEvent(&event))
{
switch (event.type) {
 
case SDL_KEYDOWN:
case SDL_KEYUP:
sym = event.key.keysym.sym;
state = event.key.state;
modstate = SDL_GetModState();
switch(sym)
{
case SDLK_DELETE: sym = K_DEL; break;
case SDLK_BACKSPACE: sym = K_BACKSPACE; break;
case SDLK_F1: sym = K_F1; break;
case SDLK_F2: sym = K_F2; break;
case SDLK_F3: sym = K_F3; break;
case SDLK_F4: sym = K_F4; break;
case SDLK_F5: sym = K_F5; break;
case SDLK_F6: sym = K_F6; break;
case SDLK_F7: sym = K_F7; break;
case SDLK_F8: sym = K_F8; break;
case SDLK_F9: sym = K_F9; break;
case SDLK_F10: sym = K_F10; break;
case SDLK_F11: sym = K_F11; break;
case SDLK_F12: sym = K_F12; break;
case SDLK_BREAK:
case SDLK_PAUSE: sym = K_PAUSE; break;
case SDLK_UP: sym = K_UPARROW; break;
case SDLK_DOWN: sym = K_DOWNARROW; break;
case SDLK_RIGHT: sym = K_RIGHTARROW; break;
case SDLK_LEFT: sym = K_LEFTARROW; break;
case SDLK_INSERT: sym = K_INS; break;
case SDLK_HOME: sym = K_HOME; break;
case SDLK_END: sym = K_END; break;
case SDLK_PAGEUP: sym = K_PGUP; break;
case SDLK_PAGEDOWN: sym = K_PGDN; break;
case SDLK_RSHIFT:
case SDLK_LSHIFT: sym = K_SHIFT; break;
case SDLK_RCTRL:
case SDLK_LCTRL: sym = K_CTRL; break;
case SDLK_RALT:
case SDLK_LALT: sym = K_ALT; break;
case SDLK_KP0:
if(modstate & KMOD_NUM) sym = K_INS;
else sym = SDLK_0;
break;
case SDLK_KP1:
if(modstate & KMOD_NUM) sym = K_END;
else sym = SDLK_1;
break;
case SDLK_KP2:
if(modstate & KMOD_NUM) sym = K_DOWNARROW;
else sym = SDLK_2;
break;
case SDLK_KP3:
if(modstate & KMOD_NUM) sym = K_PGDN;
else sym = SDLK_3;
break;
case SDLK_KP4:
if(modstate & KMOD_NUM) sym = K_LEFTARROW;
else sym = SDLK_4;
break;
case SDLK_KP5: sym = SDLK_5; break;
case SDLK_KP6:
if(modstate & KMOD_NUM) sym = K_RIGHTARROW;
else sym = SDLK_6;
break;
case SDLK_KP7:
if(modstate & KMOD_NUM) sym = K_HOME;
else sym = SDLK_7;
break;
case SDLK_KP8:
if(modstate & KMOD_NUM) sym = K_UPARROW;
else sym = SDLK_8;
break;
case SDLK_KP9:
if(modstate & KMOD_NUM) sym = K_PGUP;
else sym = SDLK_9;
break;
case SDLK_KP_PERIOD:
if(modstate & KMOD_NUM) sym = K_DEL;
else sym = SDLK_PERIOD;
break;
case SDLK_KP_DIVIDE: sym = SDLK_SLASH; break;
case SDLK_KP_MULTIPLY: sym = SDLK_ASTERISK; break;
case SDLK_KP_MINUS: sym = SDLK_MINUS; break;
case SDLK_KP_PLUS: sym = SDLK_PLUS; break;
case SDLK_KP_ENTER: sym = SDLK_RETURN; break;
case SDLK_KP_EQUALS: sym = SDLK_EQUALS; break;
}
// If we're not directly handled and still above 255
// just force it to 0
if(sym > 255) sym = 0;
Key_Event(sym, state);
break;
 
case SDL_MOUSEMOTION:
if ( (event.motion.x != (vid.width/2)) ||
(event.motion.y != (vid.height/2)) ) {
mouse_x = event.motion.xrel*10;
mouse_y = event.motion.yrel*10;
if ( (event.motion.x < ((vid.width/2)-(vid.width/4))) ||
(event.motion.x > ((vid.width/2)+(vid.width/4))) ||
(event.motion.y < ((vid.height/2)-(vid.height/4))) ||
(event.motion.y > ((vid.height/2)+(vid.height/4))) ) {
SDL_WarpMouse(vid.width/2, vid.height/2);
}
}
break;
 
case SDL_QUIT:
CL_Disconnect ();
Host_ShutdownServer(false);
Sys_Quit ();
break;
default:
break;
}
}
}
 
void IN_Init (void)
{
if ( COM_CheckParm ("-nomouse") )
return;
mouse_x = mouse_y = 0.0;
mouse_avail = 1;
}
 
void IN_Shutdown (void)
{
mouse_avail = 0;
}
 
void IN_Commands (void)
{
int i;
int mouse_buttonstate;
if (!mouse_avail) return;
i = SDL_GetMouseState(NULL, NULL);
/* Quake swaps the second and third buttons */
mouse_buttonstate = (i & ~0x06) | ((i & 0x02)<<1) | ((i & 0x04)>>1);
for (i=0 ; i<3 ; i++) {
if ( (mouse_buttonstate & (1<<i)) && !(mouse_oldbuttonstate & (1<<i)) )
Key_Event (K_MOUSE1 + i, true);
 
if ( !(mouse_buttonstate & (1<<i)) && (mouse_oldbuttonstate & (1<<i)) )
Key_Event (K_MOUSE1 + i, false);
}
mouse_oldbuttonstate = mouse_buttonstate;
}
 
void IN_Move (usercmd_t *cmd)
{
if (!mouse_avail)
return;
mouse_x *= sensitivity.value;
mouse_y *= sensitivity.value;
if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
cmd->sidemove += m_side.value * mouse_x;
else
cl.viewangles[YAW] -= m_yaw.value * mouse_x;
if (in_mlook.state & 1)
V_StopPitchDrift ();
if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) {
cl.viewangles[PITCH] += m_pitch.value * mouse_y;
if (cl.viewangles[PITCH] > 80)
cl.viewangles[PITCH] = 80;
if (cl.viewangles[PITCH] < -70)
cl.viewangles[PITCH] = -70;
} else {
if ((in_strafe.state & 1) && noclip_anglehack)
cmd->upmove -= m_forward.value * mouse_y;
else
cmd->forwardmove -= m_forward.value * mouse_y;
}
mouse_x = mouse_y = 0.0;
}
 
/*
================
Sys_ConsoleInput
================
*/
char *Sys_ConsoleInput (void)
{
return 0;
}
/contrib/other/sdlquake-1.0.9/vid_sunx.c
0,0 → 1,1257
/*
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.
 
*/
// vid_x.c -- general x video driver
 
#define _BSD
 
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
#include <X11/extensions/XShm.h>
 
#include "quakedef.h"
#include "d_local.h"
 
cvar_t m_filter = {"m_filter","0", true};
 
qboolean mouse_avail;
int mouse_buttons=3;
int mouse_oldbuttonstate;
int mouse_buttonstate;
float mouse_x, mouse_y;
float old_mouse_x, old_mouse_y;
int p_mouse_x;
int p_mouse_y;
qboolean mouse_grabbed = false; // we grab it when console is up
 
int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar;
byte *VGA_pagebase;
 
// The following X property format is defined in Motif 1.1's
// Xm/MwmUtils.h, but QUAKE should not depend on that header
// file. Note: Motif 1.2 expanded this structure with
// uninteresting fields (to QUAKE) so just stick with the
// smaller Motif 1.1 structure.
 
#define MWM_HINTS_DECORATIONS 2
typedef struct
{
long flags;
long functions;
long decorations;
long input_mode;
} MotifWmHints;
 
#define MAX_COLUMN_SIZE 11
 
#define MAX_MODEDESCS (MAX_COLUMN_SIZE*3)
 
typedef struct
{
int modenum;
int iscur;
char desc[256];
} modedesc_t;
 
extern void M_Menu_Options_f (void);
extern void M_Print (int cx, int cy, char *str);
extern void M_PrintWhite (int cx, int cy, char *str);
extern void M_DrawCharacter (int cx, int line, int num);
extern void M_DrawTransPic (int x, int y, qpic_t *pic);
extern void M_DrawPic (int x, int y, qpic_t *pic);
 
extern int sb_updates;
extern int x_root, y_root; // root window relative mouse coords
 
typedef struct
{
int input;
int output;
} keymap_t;
 
viddef_t vid; // global video state
unsigned short d_8to16table[256];
 
int num_shades=32;
 
int d_con_indirect = 0;
 
int vid_buffersize;
 
#define STD_EVENT_MASK \
( KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \
PointerMotionMask | EnterWindowMask | LeaveWindowMask | VisibilityChangeMask | \
ExposureMask | StructureNotifyMask )
 
qboolean x_fullscreen = true;
Display *x_disp = NULL;
int x_screen, x_screen_width, x_screen_height;
int x_center_width, x_center_height;
int x_std_event_mask = STD_EVENT_MASK;
Window x_win, x_root_win;
qboolean mouse_in_window = false;
int global_dx, global_dy;
 
static qboolean doShm;
static Colormap x_cmap;
static GC x_gc;
static Visual *x_vis;
static XVisualInfo *x_visinfo;
static Atom aHints = 0;
static Atom aWMDelete = 0;
 
static int x_shmeventtype;
//static XShmSegmentInfo x_shminfo;
 
static qboolean oktodraw = false;
 
int XShmQueryExtension(Display *);
int XShmGetEventBase(Display *);
 
int current_framebuffer;
static XImage *x_framebuffer[2] = { 0, 0 };
static XShmSegmentInfo x_shminfo[2];
 
static int verbose=1;
 
static byte current_palette[768];
 
typedef unsigned short PIXEL16;
typedef unsigned long PIXEL24;
static PIXEL16 st2d_8to16table[256];
static PIXEL24 st2d_8to24table[256];
static int shiftmask_fl=0;
static long r_shift,g_shift,b_shift;
static unsigned long r_mask,g_mask,b_mask;
 
void shiftmask_init()
{
unsigned int x;
r_mask=x_vis->red_mask;
g_mask=x_vis->green_mask;
b_mask=x_vis->blue_mask;
for(r_shift=-8,x=1;x<r_mask;x=x<<1)r_shift++;
for(g_shift=-8,x=1;x<g_mask;x=x<<1)g_shift++;
for(b_shift=-8,x=1;x<b_mask;x=x<<1)b_shift++;
shiftmask_fl=1;
}
 
PIXEL16 xlib_rgb16(int r,int g,int b)
{
PIXEL16 p;
if(shiftmask_fl==0) shiftmask_init();
p=0;
 
if(r_shift>0) {
p=(r<<(r_shift))&r_mask;
} else if(r_shift<0) {
p=(r>>(-r_shift))&r_mask;
} else p|=(r&r_mask);
 
if(g_shift>0) {
p|=(g<<(g_shift))&g_mask;
} else if(g_shift<0) {
p|=(g>>(-g_shift))&g_mask;
} else p|=(g&g_mask);
 
if(b_shift>0) {
p|=(b<<(b_shift))&b_mask;
} else if(b_shift<0) {
p|=(b>>(-b_shift))&b_mask;
} else p|=(b&b_mask);
 
return p;
}
 
PIXEL24 xlib_rgb24(int r,int g,int b)
{
PIXEL24 p;
if(shiftmask_fl==0) shiftmask_init();
p=0;
 
if(r_shift>0) {
p=(r<<(r_shift))&r_mask;
} else if(r_shift<0) {
p=(r>>(-r_shift))&r_mask;
} else p|=(r&r_mask);
 
if(g_shift>0) {
p|=(g<<(g_shift))&g_mask;
} else if(g_shift<0) {
p|=(g>>(-g_shift))&g_mask;
} else p|=(g&g_mask);
 
if(b_shift>0) {
p|=(b<<(b_shift))&b_mask;
} else if(b_shift<0) {
p|=(b>>(-b_shift))&b_mask;
} else p|=(b&b_mask);
 
return p;
}
 
void st2_fixup( XImage *framebuf, int x, int y, int width, int height)
{
int xi,yi;
unsigned char *src;
PIXEL16 *dest;
register int count, n;
 
if( (x<0)||(y<0) )return;
 
for (yi = y; yi < (y+height); yi++) {
src = &framebuf->data [yi * framebuf->bytes_per_line];
 
// Duff's Device
count = width;
n = (count + 7) / 8;
dest = ((PIXEL16 *)src) + x+width - 1;
src += x+width - 1;
 
switch (count % 8) {
case 0: do { *dest-- = st2d_8to16table[*src--];
case 7: *dest-- = st2d_8to16table[*src--];
case 6: *dest-- = st2d_8to16table[*src--];
case 5: *dest-- = st2d_8to16table[*src--];
case 4: *dest-- = st2d_8to16table[*src--];
case 3: *dest-- = st2d_8to16table[*src--];
case 2: *dest-- = st2d_8to16table[*src--];
case 1: *dest-- = st2d_8to16table[*src--];
} while (--n > 0);
}
 
// for(xi = (x+width-1); xi >= x; xi--) {
// dest[xi] = st2d_8to16table[src[xi]];
// }
}
}
 
void st3_fixup( XImage *framebuf, int x, int y, int width, int height)
{
int xi,yi;
unsigned char *src;
PIXEL24 *dest;
register int count, n;
 
if( (x<0)||(y<0) )return;
 
for (yi = y; yi < (y+height); yi++) {
src = &framebuf->data [yi * framebuf->bytes_per_line];
 
// Duff's Device
count = width;
n = (count + 7) / 8;
dest = ((PIXEL24 *)src) + x+width - 1;
src += x+width - 1;
 
switch (count % 8) {
case 0: do { *dest-- = st2d_8to24table[*src--];
case 7: *dest-- = st2d_8to24table[*src--];
case 6: *dest-- = st2d_8to24table[*src--];
case 5: *dest-- = st2d_8to24table[*src--];
case 4: *dest-- = st2d_8to24table[*src--];
case 3: *dest-- = st2d_8to24table[*src--];
case 2: *dest-- = st2d_8to24table[*src--];
case 1: *dest-- = st2d_8to24table[*src--];
} while (--n > 0);
}
 
// for(xi = (x+width-1); xi >= x; xi--) {
// dest[xi] = st2d_8to16table[src[xi]];
// }
}
}
 
/*
================
D_BeginDirectRect
================
*/
void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
{
// direct drawing of the "accessing disk" icon isn't supported under Nextstep
}
 
 
/*
================
D_EndDirectRect
================
*/
void D_EndDirectRect (int x, int y, int width, int height)
{
// direct drawing of the "accessing disk" icon isn't supported under Nextstep
}
 
 
/*
=================
VID_Gamma_f
 
Keybinding command
=================
*/
 
byte vid_gamma[256];
 
void VID_Gamma_f (void)
{
 
float g, f, inf;
int i;
 
if (Cmd_Argc () == 2)
{
g = Q_atof (Cmd_Argv(1));
 
for (i=0 ; i<255 ; i++)
{
f = pow ((i+1)/256.0, g);
inf = f*255 + 0.5;
if (inf < 0)
inf = 0;
if (inf > 255)
inf = 255;
vid_gamma[i] = inf;
}
 
VID_SetPalette (current_palette);
 
vid.recalc_refdef = 1; // force a surface cache flush
}
 
}
 
// ========================================================================
// Tragic death handler
// ========================================================================
 
void TragicDeath(int signal_num)
{
//XAutoRepeatOn(x_disp);
VID_Shutdown();
Sys_Error("This death brought to you by the number %d\n", signal_num);
}
 
// ========================================================================
// makes a null cursor
// ========================================================================
 
static Cursor CreateNullCursor(Display *display, Window root)
{
Pixmap cursormask;
XGCValues xgc;
GC gc;
XColor dummycolour;
Cursor cursor;
 
cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
xgc.function = GXclear;
gc = XCreateGC(display, cursormask, GCFunction, &xgc);
XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
dummycolour.pixel = 0;
dummycolour.red = 0;
dummycolour.flags = 04;
cursor = XCreatePixmapCursor(display, cursormask, cursormask,
&dummycolour,&dummycolour, 0,0);
XFreePixmap(display,cursormask);
XFreeGC(display,gc);
return cursor;
}
 
void ResetFrameBuffer(void)
{
 
int mem;
int pwidth;
 
if (x_framebuffer[0])
{
Z_Free(x_framebuffer[0]->data);
// Z_Free(d_pzbuffer);
free(x_framebuffer[0]);
}
 
pwidth = x_visinfo->depth / 8;
if (pwidth == 3) pwidth = 4;
mem = ((vid.width*pwidth+3)&~3) * vid.height;
 
// d_pzbuffer = (unsigned short *) Z_Malloc(vid.width*vid.height*
// sizeof(*d_pzbuffer));
d_pzbuffer = (short *) Hunk_HighAllocName(vid.width*vid.height*
sizeof(*d_pzbuffer), "zbuff");
 
x_framebuffer[0] = XCreateImage( x_disp,
x_vis,
x_visinfo->depth,
ZPixmap,
0,
Z_Malloc(mem),
vid.width, vid.height,
32,
0);
 
if (!x_framebuffer[0])
Sys_Error("VID: XCreateImage failed\n");
 
}
 
void ResetSharedFrameBuffers(void)
{
 
int size;
int key;
int minsize = getpagesize();
int frm;
 
// if (d_pzbuffer)
// Z_Free(d_pzbuffer);
d_pzbuffer = Hunk_HighAllocName(vid.width*vid.height*sizeof(*d_pzbuffer),"zbuff");
 
for (frm=0 ; frm<2 ; frm++)
{
 
// free up old frame buffer memory
 
if (x_framebuffer[frm])
{
XShmDetach(x_disp, &x_shminfo[frm]);
free(x_framebuffer[frm]);
shmdt(x_shminfo[frm].shmaddr);
}
 
// create the image
 
x_framebuffer[frm] = XShmCreateImage( x_disp,
x_vis,
x_visinfo->depth,
ZPixmap,
0,
&x_shminfo[frm],
vid.width,
vid.height );
 
// grab shared memory
 
size = x_framebuffer[frm]->bytes_per_line
* x_framebuffer[frm]->height;
if (size < minsize)
Sys_Error("VID: Window must use at least %d bytes\n", minsize);
 
key = random();
x_shminfo[frm].shmid = shmget((key_t)key, size, IPC_CREAT|0777);
if (x_shminfo[frm].shmid==-1)
Sys_Error("VID: Could not get any shared memory\n");
 
// attach to the shared memory segment
x_shminfo[frm].shmaddr =
(void *) shmat(x_shminfo[frm].shmid, 0, 0);
 
printf("VID: shared memory id=%d, addr=0x%x\n", x_shminfo[frm].shmid,
(int) x_shminfo[frm].shmaddr);
 
x_framebuffer[frm]->data = x_shminfo[frm].shmaddr;
 
// get the X server to attach to it
 
if (!XShmAttach(x_disp, &x_shminfo[frm]))
Sys_Error("VID: XShmAttach() failed\n");
XSync(x_disp, 0);
shmctl(x_shminfo[frm].shmid, IPC_RMID, 0);
 
}
 
}
 
void VID_MenuDraw( void )
{
qpic_t *p;
char *ptr;
int i, j, column, row, dup;
char temp[100];
 
p = Draw_CachePic ("gfx/vidmodes.lmp");
M_DrawPic ( (320-p->width)/2, 4, p);
M_Print (4*8, 36 + MAX_COLUMN_SIZE * 8 + 8, "Video mode switching unavailable");
M_Print (9*8, 36 + MAX_COLUMN_SIZE * 8 + 8*6, "Press any key...");
}
 
void VID_MenuKey( int key ) { M_Menu_Options_f (); }
 
// Called at startup to set up translation tables, takes 256 8 bit RGB values
// the palette data will go away after the call, so it must be copied off if
// the video driver will need it again
 
byte surfcache[1024*1024];
 
//
// VID_SetWindowTitle - set the window and icon titles
//
 
void VID_SetWindowTitle( Window win, char *pszName )
{
XTextProperty textprop;
XWMHints *wmHints;
 
// Setup ICCCM properties
textprop.value = (unsigned char *)pszName;
textprop.encoding = XA_STRING;
textprop.format = 8;
textprop.nitems = strlen(pszName);
wmHints = XAllocWMHints();
wmHints->initial_state = NormalState;
wmHints->flags = StateHint;
XSetWMProperties( x_disp, win, &textprop, &textprop,
// Only put WM_COMMAND property on first window.
com_argv, com_argc, NULL, NULL, NULL );
XFree( wmHints );
 
aWMDelete = XInternAtom( x_disp, "WM_DELETE_WINDOW", False );
XSetWMProtocols( x_disp, win, &aWMDelete, 1 );
}
 
//
// VID_FullScreen - open the window in full screen mode
//
 
qboolean VID_FullScreen( Window win )
{
MotifWmHints hints;
XWindowChanges changes;
 
aHints = XInternAtom( x_disp, "_MOTIF_WM_HINTS", 0 );
if (aHints == None)
{
Con_Printf( "Could not intern X atom for _MOTIF_WM_HINTS." );
return( false );
}
 
hints.flags = MWM_HINTS_DECORATIONS;
hints.decorations = 0; // Absolutely no decorations.
XChangeProperty( x_disp, win, aHints, aHints, 32, PropModeReplace, (unsigned char *)&hints, 4 );
 
changes.x = 0;
changes.y = 0;
changes.width = x_screen_width;
changes.height = x_screen_height;
changes.stack_mode = TopIf;
XConfigureWindow( x_disp, win, CWX | CWY | CWWidth | CWHeight | CWStackMode, &changes);
return( true );
}
 
void VID_Init (unsigned char *palette)
{
 
int pnum, i;
XVisualInfo template;
int num_visuals;
int template_mask;
 
Cmd_AddCommand ("gamma", VID_Gamma_f);
for (i=0 ; i<256 ; i++)
vid_gamma[i] = i;
 
vid.width = 320;
vid.height = 200;
vid.aspect = 1.0;
vid.numpages = 2;
vid.colormap = host_colormap;
vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
//vid.cbits = VID_CBITS;
//vid.grades = VID_GRADES;
 
srandom(getpid());
 
verbose=COM_CheckParm("-verbose");
 
// open the display
x_disp = XOpenDisplay(0);
if (!x_disp)
{
if (getenv("DISPLAY"))
Sys_Error("VID: Could not open display [%s]\n",
getenv("DISPLAY"));
else
Sys_Error("VID: Could not open local display\n");
}
 
x_screen = XDefaultScreen( x_disp );
x_screen_width = WidthOfScreen( ScreenOfDisplay( x_disp, x_screen ) );
x_screen_height = HeightOfScreen( ScreenOfDisplay( x_disp, x_screen ) );
 
x_center_width = x_screen_width/2;
 
x_center_height = x_screen_height/2;
 
Con_Printf( "Using screen %d: %dx%d\n", x_screen, x_screen_width, x_screen_height );
 
x_root_win = XRootWindow( x_disp, x_screen );
 
// catch signals so i can turn on auto-repeat
// we never run full-screen, so no auto-repeat nukage
if (0)
{
struct sigaction sa;
sigaction(SIGINT, 0, &sa);
sa.sa_handler = TragicDeath;
sigaction(SIGINT, &sa, 0);
sigaction(SIGTERM, &sa, 0);
}
 
//XAutoRepeatOff(x_disp);
 
// for debugging only
// XSynchronize(x_disp, True);
 
// check for command-line window size
if ((pnum=COM_CheckParm("-winsize")))
{
if (pnum >= com_argc-2)
Sys_Error("VID: -winsize <width> <height>\n");
vid.width = Q_atoi(com_argv[pnum+1]);
vid.height = Q_atoi(com_argv[pnum+2]);
if (!vid.width || !vid.height)
Sys_Error("VID: Bad window width/height\n");
}
 
template_mask = 0;
 
// specify a visual id
if ((pnum=COM_CheckParm("-visualid")))
{
if (pnum >= com_argc-1)
Sys_Error("VID: -visualid <id#>\n");
template.visualid = Q_atoi(com_argv[pnum+1]);
template_mask = VisualIDMask;
}
 
// If not specified, use default visual
else
{
int screen;
screen = XDefaultScreen(x_disp);
template.visualid =
XVisualIDFromVisual(XDefaultVisual(x_disp, screen));
template_mask = VisualIDMask;
}
 
// pick a visual- warn if more than one was available
x_visinfo = XGetVisualInfo(x_disp, template_mask, &template, &num_visuals);
if (num_visuals > 1)
{
printf("Found more than one visual id at depth %d:\n", template.depth);
for (i=0 ; i<num_visuals ; i++)
printf(" -visualid %d\n", (int)(x_visinfo[i].visualid));
}
else if (num_visuals == 0)
{
if (template_mask == VisualIDMask)
Sys_Error("VID: Bad visual id %d\n", template.visualid);
else
Sys_Error("VID: No visuals at depth %d\n", template.depth);
}
 
if (verbose)
{
printf("Using visualid %d:\n", (int)(x_visinfo->visualid));
printf(" class %d\n", x_visinfo->class);
printf(" screen %d\n", x_visinfo->screen);
printf(" depth %d\n", x_visinfo->depth);
printf(" red_mask 0x%x\n", (int)(x_visinfo->red_mask));
printf(" green_mask 0x%x\n", (int)(x_visinfo->green_mask));
printf(" blue_mask 0x%x\n", (int)(x_visinfo->blue_mask));
printf(" colormap_size %d\n", x_visinfo->colormap_size);
printf(" bits_per_rgb %d\n", x_visinfo->bits_per_rgb);
}
 
x_vis = x_visinfo->visual;
 
// setup attributes for main window
{
int attribmask = CWEventMask | CWColormap | CWBorderPixel;
XSetWindowAttributes attribs;
Colormap tmpcmap;
 
tmpcmap = XCreateColormap(x_disp, XRootWindow(x_disp,
x_visinfo->screen), x_vis, AllocNone);
 
attribs.event_mask = x_std_event_mask;
attribs.border_pixel = 0;
attribs.colormap = tmpcmap;
 
// create the main window
x_win = XCreateWindow( x_disp,
XRootWindow(x_disp, x_visinfo->screen),
0, 0, // x, y
vid.width, vid.height,
0, // borderwidth
x_visinfo->depth,
InputOutput,
x_vis,
attribmask,
&attribs );
 
if (x_visinfo->class != TrueColor)
XFreeColormap(x_disp, tmpcmap);
 
}
 
if (x_visinfo->depth == 8)
{
 
// create and upload the palette
if (x_visinfo->class == PseudoColor)
{
x_cmap = XCreateColormap(x_disp, x_win, x_vis, AllocAll);
VID_SetPalette(palette);
XSetWindowColormap(x_disp, x_win, x_cmap);
}
 
}
 
VID_SetWindowTitle( x_win, "Quake" );
 
// create the GC
{
XGCValues xgcvalues;
int valuemask = GCGraphicsExposures;
xgcvalues.graphics_exposures = False;
x_gc = XCreateGC(x_disp, x_win, valuemask, &xgcvalues );
}
 
// map the window
XMapWindow(x_disp, x_win);
 
// wait for first exposure event
{
XEvent event;
do
{
XNextEvent(x_disp, &event);
if (event.type == Expose && !event.xexpose.count)
oktodraw = true;
} while (!oktodraw);
}
// now safe to draw
 
// even if MITSHM is available, make sure it's a local connection
if (XShmQueryExtension(x_disp))
{
char *displayname;
doShm = true;
displayname = (char *) getenv("DISPLAY");
if (displayname)
{
char *d = displayname;
while (*d && (*d != ':')) d++;
if (*d) *d = 0;
if (!(!strcasecmp(displayname, "unix") || !*displayname))
doShm = false;
}
}
 
if (doShm)
{
x_shmeventtype = XShmGetEventBase(x_disp) + ShmCompletion;
ResetSharedFrameBuffers();
}
else
ResetFrameBuffer();
 
current_framebuffer = 0;
vid.rowbytes = x_framebuffer[0]->bytes_per_line;
vid.buffer = x_framebuffer[0]->data;
vid.conbuffer = x_framebuffer[0]->data;
vid.conrowbytes = vid.rowbytes;
vid.conwidth = vid.width;
vid.conheight = vid.height;
 
vid.maxwarpwidth = WARP_WIDTH;
vid.maxwarpheight = WARP_HEIGHT;
 
D_InitCaches (surfcache, sizeof(surfcache));
// XSynchronize(x_disp, False);
 
vid_menudrawfn = VID_MenuDraw;
vid_menukeyfn = VID_MenuKey;
 
}
 
void VID_ShiftPalette(unsigned char *p)
{
VID_SetPalette(p);
}
 
void VID_SetPalette(unsigned char *palette)
{
 
int i;
XColor colors[256];
 
for(i=0;i<256;i++) {
st2d_8to16table[i]= xlib_rgb16(palette[i*3], palette[i*3+1],palette[i*3+2]);
st2d_8to24table[i]= xlib_rgb24(palette[i*3], palette[i*3+1],palette[i*3+2]);
}
 
if (x_visinfo->class == PseudoColor && x_visinfo->depth == 8)
{
if (palette != current_palette)
memcpy(current_palette, palette, 768);
for (i=0 ; i<256 ; i++)
{
colors[i].pixel = i;
colors[i].flags = DoRed|DoGreen|DoBlue;
colors[i].red = vid_gamma[palette[i*3]] * 257;
colors[i].green = vid_gamma[palette[i*3+1]] * 257;
colors[i].blue = vid_gamma[palette[i*3+2]] * 257;
}
XStoreColors(x_disp, x_cmap, colors, 256);
}
 
}
 
// Called at shutdown
 
void VID_Shutdown (void)
{
Con_Printf("VID_Shutdown\n");
//XAutoRepeatOn(x_disp);
if (mouse_grabbed) {
/* ungrab the pointer */
XUngrabPointer(x_disp, CurrentTime);
XUndefineCursor(x_disp, x_win);
}
XCloseDisplay(x_disp);
}
 
int XLateKey(XKeyEvent *ev)
{
 
int key;
char buf[64];
KeySym keysym;
 
XLookupString(ev, buf, sizeof buf, &keysym, 0);
 
switch(keysym)
{
case XK_Page_Up: key = K_PGUP; break;
case XK_Page_Down: key = K_PGDN; break;
case XK_Home: key = K_HOME; break;
case XK_End: key = K_END; break;
case XK_Left: key = K_LEFTARROW; break;
case XK_Right: key = K_RIGHTARROW; break;
case XK_Down: key = K_DOWNARROW; break;
case XK_Up: key = K_UPARROW; break;
case XK_Escape: key = K_ESCAPE; break;
case XK_Return: key = K_ENTER; break;
case XK_Tab: key = K_TAB; break;
case XK_F1: key = K_F1; break;
case XK_F2: key = K_F2; break;
case XK_F3: key = K_F3; break;
case XK_F4: key = K_F4; break;
case XK_F5: key = K_F5; break;
case XK_F6: key = K_F6; break;
case XK_F7: key = K_F7; break;
case XK_F8: key = K_F8; break;
case XK_F9: key = K_F9; break;
case XK_F10: key = K_F10; break;
case XK_F11: key = K_F11; break;
case XK_F12: key = K_F12; break;
case XK_BackSpace:
case XK_Delete: key = K_BACKSPACE; break;
case XK_Pause: key = K_PAUSE; break;
case XK_Shift_L:
case XK_Shift_R: key = K_SHIFT; break;
case XK_Control_L:
case XK_Control_R: key = K_CTRL; break;
case XK_Alt_L:
case XK_Meta_L:
case XK_Alt_R:
case XK_Meta_R: key = K_ALT; break;
// various other keys on the keyboard
case XK_F27: key = K_HOME; break;
case XK_F29: key = K_PGUP; break;
case XK_F33: key = K_END; break;
case XK_F35: key = K_PGDN; break;
case XK_KP_Insert: key = K_INS; break;
 
default:
key = *buf;
break;
}
 
return key;
 
}
 
struct
{
int key;
int down;
} keyq[64];
int keyq_head=0;
int keyq_tail=0;
 
int config_notify=0;
int config_notify_width;
int config_notify_height;
 
void GetEvent(void)
{
XEvent x_event;
 
XNextEvent(x_disp, &x_event);
switch(x_event.type)
{
case KeyPress:
Key_Event(XLateKey(&x_event.xkey), true);
break;
case KeyRelease:
Key_Event(XLateKey(&x_event.xkey), false);
break;
case ButtonPress:
//printf( "button %d down\n", x_event.xbutton.button );
Key_Event( K_MOUSE1 + x_event.xbutton.button - 1, true );
break;
case ButtonRelease:
//printf( "button %d up\n", x_event.xbutton.button );
Key_Event( K_MOUSE1 + x_event.xbutton.button - 1, false );
break;
case MotionNotify:
if (mouse_avail && mouse_grabbed) {
mouse_x = (float) ((int)x_event.xmotion.x - (int)(vid.width/2));
mouse_y = (float) ((int)x_event.xmotion.y - (int)(vid.height/2));
//printf("m: x=%d,y=%d, mx=%3.2f,my=%3.2f\n",
// x_event.xmotion.x, x_event.xmotion.y, mouse_x, mouse_y);
 
/* move the mouse to the window center again */
XSelectInput(x_disp,x_win, STD_EVENT_MASK & ~PointerMotionMask);
XWarpPointer(x_disp,None,x_win,0,0,0,0, (vid.width/2),(vid.height/2));
XSelectInput(x_disp,x_win, STD_EVENT_MASK);
} else {
mouse_x = (float) (x_event.xmotion.x-p_mouse_x);
mouse_y = (float) (x_event.xmotion.y-p_mouse_y);
p_mouse_x=x_event.xmotion.x;
p_mouse_y=x_event.xmotion.y;
}
break;
 
case ConfigureNotify:
// printf("config notify\n");
config_notify_width = x_event.xconfigure.width;
config_notify_height = x_event.xconfigure.height;
config_notify = 1;
sb_updates = 0;
break;
case Expose:
sb_updates = 0;
break;
case ClientMessage:
if (x_event.xclient.data.l[0] == aWMDelete) Host_Quit_f();
break;
case EnterNotify:
mouse_in_window = true;
break;
case LeaveNotify:
mouse_in_window = false;
break;
 
default:
if (doShm && x_event.type == x_shmeventtype)
oktodraw = true;
}
if (mouse_avail) {
if (key_dest == key_game && !mouse_grabbed && mouse_in_window) {
mouse_grabbed = true;
/* grab the pointer */
XGrabPointer(x_disp,x_win,True,0,GrabModeAsync,
GrabModeAsync,x_win,None,CurrentTime);
// inviso cursor
XDefineCursor(x_disp, x_win, CreateNullCursor(x_disp, x_win));
} else if ((key_dest != key_game || !mouse_in_window) && mouse_grabbed) {
mouse_grabbed = false;
/* ungrab the pointer */
XUngrabPointer(x_disp, CurrentTime);
XUndefineCursor(x_disp, x_win);
}
}
}
 
// flushes the given rectangles from the view buffer to the screen
 
void VID_Update (vrect_t *rects)
{
#if 0
static int count;
static long long s;
long long gethrtime();
 
if (count == 0)
s = gethrtime();
 
if (count++ == 50) {
count = 1;
printf("%lf frames/secs\n", 50.0/((double)(gethrtime()-s) / 1e9));
s = gethrtime();
}
#endif
 
// if the window changes dimension, skip this frame
 
if (config_notify)
{
printf("config notify\n");
config_notify = 0;
vid.width = config_notify_width & ~3;
vid.height = config_notify_height;
 
printf("w = %d, h = %d\n", vid.width, vid.height);
 
if (doShm)
ResetSharedFrameBuffers();
else
ResetFrameBuffer();
vid.rowbytes = x_framebuffer[0]->bytes_per_line;
vid.buffer = x_framebuffer[current_framebuffer]->data;
vid.conbuffer = vid.buffer;
vid.conwidth = vid.width;
vid.conheight = vid.height;
vid.conrowbytes = vid.rowbytes;
vid.recalc_refdef = 1; // force a surface cache flush
return;
}
 
if (doShm)
{
// long long s, gethrtime();
// s = gethrtime();
 
while (rects)
{
printf("update: %d,%d (%d,%d)\n", rects->x, rects->y, rects->width, rects->height);
if (x_visinfo->depth == 16)
st2_fixup( x_framebuffer[current_framebuffer],
rects->x, rects->y, rects->width,
rects->height);
else if (x_visinfo->depth == 24)
st3_fixup( x_framebuffer[current_framebuffer],
rects->x, rects->y, rects->width,
rects->height);
if (!XShmPutImage(x_disp, x_win, x_gc,
x_framebuffer[current_framebuffer], rects->x, rects->y,
rects->x, rects->y, rects->width, rects->height, True))
Sys_Error("VID_Update: XShmPutImage failed\n");
oktodraw = false;
while (!oktodraw) GetEvent();
rects = rects->pnext;
}
// printf("%lf\n", (double)(gethrtime()-s)/1.0e9);
current_framebuffer = !current_framebuffer;
vid.buffer = x_framebuffer[current_framebuffer]->data;
vid.conbuffer = vid.buffer;
XSync(x_disp, False);
}
else
{
while (rects)
{
if (x_visinfo->depth == 16)
st2_fixup( x_framebuffer[current_framebuffer],
rects->x, rects->y, rects->width,
rects->height);
else if (x_visinfo->depth == 24)
st3_fixup( x_framebuffer[current_framebuffer],
rects->x, rects->y, rects->width,
rects->height);
XPutImage(x_disp, x_win, x_gc, x_framebuffer[0], rects->x,
rects->y, rects->x, rects->y, rects->width, rects->height);
rects = rects->pnext;
}
XSync(x_disp, False);
}
}
 
static int dither;
 
void VID_DitherOn(void)
{
if (dither == 0)
{
vid.recalc_refdef = 1;
dither = 1;
}
}
 
void VID_DitherOff(void)
{
if (dither)
{
vid.recalc_refdef = 1;
dither = 0;
}
}
 
void VID_SetDefaultMode( void )
{
}
 
int I_OpenWindow(void)
{
return 0;
}
 
void I_EraseWindow(int window)
{
}
 
void I_DrawCircle(int window, int x, int y, int r)
{
}
 
void I_DisplayWindow(int window)
{
}
 
void Sys_SendKeyEvents(void)
{
// get events from x server
if (x_disp)
{
while (XPending(x_disp)) GetEvent();
while (keyq_head != keyq_tail)
{
Key_Event(keyq[keyq_tail].key, keyq[keyq_tail].down);
keyq_tail = (keyq_tail + 1) & 63;
}
}
}
 
#if 0
char *Sys_ConsoleInput (void)
{
 
static char text[256];
int len;
fd_set readfds;
int ready;
struct timeval timeout;
 
timeout.tv_sec = 0;
timeout.tv_usec = 0;
FD_ZERO(&readfds);
FD_SET(0, &readfds);
ready = select(1, &readfds, 0, 0, &timeout);
 
if (ready>0)
{
len = read (0, text, sizeof(text));
if (len >= 1)
{
text[len-1] = 0; // rip off the /n and terminate
return text;
}
}
 
return 0;
}
#endif
 
void IN_Init (void)
{
Cvar_RegisterVariable (&m_filter);
if ( COM_CheckParm ("-nomouse") )
return;
mouse_x = mouse_y = 0.0;
mouse_avail = 1;
}
 
void IN_Shutdown (void)
{
mouse_avail = 0;
}
 
void IN_Commands (void)
{
int i;
if (!mouse_avail) return;
for (i=0 ; i<mouse_buttons ; i++) {
if ( (mouse_buttonstate & (1<<i)) && !(mouse_oldbuttonstate & (1<<i)) )
Key_Event (K_MOUSE1 + i, true);
 
if ( !(mouse_buttonstate & (1<<i)) && (mouse_oldbuttonstate & (1<<i)) )
Key_Event (K_MOUSE1 + i, false);
}
mouse_oldbuttonstate = mouse_buttonstate;
}
 
void IN_Move (usercmd_t *cmd)
{
if (!mouse_avail)
return;
if (m_filter.value) {
mouse_x = (mouse_x + old_mouse_x) * 0.5;
mouse_y = (mouse_y + old_mouse_y) * 0.5;
}
 
old_mouse_x = mouse_x;
old_mouse_y = mouse_y;
mouse_x *= sensitivity.value;
mouse_y *= sensitivity.value;
if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
cmd->sidemove += m_side.value * mouse_x;
else
cl.viewangles[YAW] -= m_yaw.value * mouse_x;
if (in_mlook.state & 1)
V_StopPitchDrift ();
if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) {
cl.viewangles[PITCH] += m_pitch.value * mouse_y;
if (cl.viewangles[PITCH] > 80)
cl.viewangles[PITCH] = 80;
if (cl.viewangles[PITCH] < -70)
cl.viewangles[PITCH] = -70;
} else {
if ((in_strafe.state & 1) && noclip_anglehack)
cmd->upmove -= m_forward.value * mouse_y;
else
cmd->forwardmove -= m_forward.value * mouse_y;
}
mouse_x = mouse_y = 0.0;
}
/contrib/other/sdlquake-1.0.9/vid_sunxil.c
0,0 → 1,1288
/*
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.
 
*/
// vid_sunxil.c -- uses X to setup windows and XIL to copy images (scaled as needed)
// to screen
 
#define _BSD
#define BYTE_DEFINED 1
 
#include <sys/time.h>
#include <sys/types.h>
#include <errno.h>
#include <thread.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
#include <xil/xil.h>
 
#include "quakedef.h"
#include "d_local.h"
 
#define MIN_WIDTH 320
#define MIN_HEIGHT 200
 
cvar_t _windowed_mouse = {"_windowed_mouse","0", true};
cvar_t m_filter = {"m_filter","0", true};
float old_windowed_mouse;
 
// The following X property format is defined in Motif 1.1's
// Xm/MwmUtils.h, but QUAKE should not depend on that header
// file. Note: Motif 1.2 expanded this structure with
// uninteresting fields (to QUAKE) so just stick with the
// smaller Motif 1.1 structure.
 
#define MWM_HINTS_DECORATIONS 2
typedef struct
{
long flags;
long functions;
long decorations;
long input_mode;
} MotifWmHints;
 
#define MAX_COLUMN_SIZE 11
 
#define MAX_MODEDESCS (MAX_COLUMN_SIZE*3)
 
typedef struct
{
int modenum;
int iscur;
char desc[256];
} modedesc_t;
 
extern void M_Menu_Options_f (void);
extern void M_Print (int cx, int cy, char *str);
extern void M_PrintWhite (int cx, int cy, char *str);
extern void M_DrawCharacter (int cx, int line, int num);
extern void M_DrawTransPic (int x, int y, qpic_t *pic);
extern void M_DrawPic (int x, int y, qpic_t *pic);
 
extern int sb_updates;
 
qboolean mouse_avail;
int mouse_buttons=3;
int mouse_oldbuttonstate;
int mouse_buttonstate;
float mouse_x, mouse_y;
float old_mouse_x, old_mouse_y;
int p_mouse_x;
int p_mouse_y;
 
typedef struct
{
int input;
int output;
} keymap_t;
 
viddef_t vid; // global video state
unsigned short d_8to16table[256];
 
int num_shades=32;
 
int d_con_indirect = 0;
 
int vid_buffersize;
 
#define STD_EVENT_MASK \
( \
StructureNotifyMask | \
KeyPressMask | \
KeyReleaseMask | \
ButtonPressMask | \
ButtonReleaseMask | \
ExposureMask | \
PointerMotionMask | \
FocusChangeMask \
)
 
int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar;
byte *VGA_pagebase;
 
qboolean x_fullscreen = true;
Display *x_disp = NULL;
int x_screen, x_screen_width, x_screen_height;
int x_center_width, x_center_height;
int x_std_event_mask = STD_EVENT_MASK;
Window x_win, x_root_win;
qboolean x_focus = true;
int global_dx, global_dy;
 
 
static Colormap x_cmap;
static GC x_gc;
static Visual *x_vis;
static XVisualInfo *x_visinfo;
static Atom aHints = NULL;
static Atom aWMDelete = NULL;
 
static qboolean oktodraw = false;
static qboolean X11_active = false;
 
 
static int verbose=1;
 
static byte current_palette[768];
 
cvar_t pixel_multiply = {"pixel_multiply", "2", true};
int current_pixel_multiply = 2;
 
#define PM(a) (int)((current_pixel_multiply)?((a)*current_pixel_multiply):(a))
#define MP(a) (int)((current_pixel_multiply)?((a)/current_pixel_multiply):(a))
 
static int render_pipeline[2];
static XilSystemState state;
static XilImage display_image = NULL;
static XilImage quake_image = NULL;
static int use_mt = 0;
static int count_frames = 0;
 
/*
================
D_BeginDirectRect
================
*/
void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
{
// direct drawing of the "accessing disk" icon isn't supported under Nextstep
}
 
 
/*
================
D_EndDirectRect
================
*/
void D_EndDirectRect (int x, int y, int width, int height)
{
// direct drawing of the "accessing disk" icon isnt supported under Nextstep
}
 
 
/*
=================
VID_Gamma_f
 
Keybinding command
=================
*/
 
byte vid_gamma[256];
 
void VID_Gamma_f (void)
{
 
float g, f, inf;
int i;
 
if (Cmd_Argc () == 2) {
g = Q_atof (Cmd_Argv(1));
 
for (i=0 ; i<255 ; i++) {
f = pow ((i+1)/256.0, g);
inf = f*255 + 0.5;
if (inf < 0)
inf = 0;
if (inf > 255)
inf = 255;
vid_gamma[i] = inf;
}
 
VID_SetPalette (current_palette);
 
vid.recalc_refdef = 1; // force a surface cache flush
}
 
}
 
qboolean CheckPixelMultiply (void)
{
int m;
int w, h;
XWindowAttributes wattr;
XWindowChanges chg;
unsigned int value_mask;
int old_pixel;
 
if ((m = (int)pixel_multiply.value) != current_pixel_multiply) {
if (m < 1)
m = 1;
if (m > 4)
m = 4;
 
old_pixel = current_pixel_multiply;
current_pixel_multiply = m;
Cvar_SetValue("pixel_multiply", m);
if(XGetWindowAttributes(x_disp, x_win, & wattr) == 0)
return true; // ???
 
memset(&chg, 0, sizeof(chg));
chg.width = wattr.width/old_pixel * current_pixel_multiply;
chg.height = wattr.height/old_pixel * current_pixel_multiply;
 
if (chg.width < MIN_WIDTH*current_pixel_multiply)
chg.width = MIN_WIDTH*current_pixel_multiply;
if (chg.height < MIN_HEIGHT*current_pixel_multiply)
chg.height = MIN_HEIGHT*current_pixel_multiply;
 
XConfigureWindow(x_disp, x_win, CWWidth | CWHeight, &chg);
 
vid.width = MP(wattr.width) & ~3;
vid.height = MP(wattr.height);
 
if (vid.width < 320)
vid.width = 320;
if (vid.height < 200)
vid.height = 200;
VID_ResetFramebuffer();
 
return true;
}
return false;
}
 
// ========================================================================
// Tragic death handler
// ========================================================================
 
void TragicDeath(int signal_num)
{
//XAutoRepeatOn(x_disp);
XCloseDisplay(x_disp);
Sys_Error("This death brought to you by the number %d\n", signal_num);
}
 
// ========================================================================
// makes a null cursor
// ========================================================================
 
static Cursor CreateNullCursor(Display *display, Window root)
{
Pixmap cursormask;
XGCValues xgc;
GC gc;
XColor dummycolour;
Cursor cursor;
 
cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
xgc.function = GXclear;
gc = XCreateGC(display, cursormask, GCFunction, &xgc);
XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
dummycolour.pixel = 0;
dummycolour.red = 0;
dummycolour.flags = 04;
cursor = XCreatePixmapCursor(display, cursormask, cursormask,
&dummycolour,&dummycolour, 0,0);
XFreePixmap(display,cursormask);
XFreeGC(display,gc);
return cursor;
}
 
 
void VID_MenuDraw( void )
{
qpic_t *p;
char *ptr;
int i, j, column, row, dup;
char temp[100];
 
p = Draw_CachePic ("gfx/vidmodes.lmp");
M_DrawPic ( (320-p->width)/2, 4, p);
M_Print (4*8, 36 + MAX_COLUMN_SIZE * 8 + 8, "Video mode switching unavailable");
M_Print (9*8, 36 + MAX_COLUMN_SIZE * 8 + 8*6, "Press any key...");
}
 
void VID_MenuKey( int key ) { M_Menu_Options_f (); }
 
// Called at startup to set up translation tables, takes 256 8 bit RGB values
// the palette data will go away after the call, so it must be copied off if
// the video driver will need it again
 
byte surfcache[1024*1024];
 
//
// VID_SetWindowTitle - set the window and icon titles
//
 
void VID_SetWindowTitle( Window win, char *pszName )
{
XTextProperty textprop;
XWMHints *wmHints;
 
// Setup ICCCM properties
textprop.value = (unsigned char *)pszName;
textprop.encoding = XA_STRING;
textprop.format = 8;
textprop.nitems = strlen(pszName);
wmHints = XAllocWMHints();
wmHints->initial_state = NormalState;
wmHints->flags = StateHint;
XSetWMProperties( x_disp, win, &textprop, &textprop,
// Only put WM_COMMAND property on first window.
com_argv, com_argc, NULL, NULL, NULL );
XFree( wmHints );
 
aWMDelete = XInternAtom( x_disp, "WM_DELETE_WINDOW", False );
XSetWMProtocols( x_disp, win, &aWMDelete, 1 );
}
 
//
// VID_FullScreen - open the window in full screen mode
//
 
qboolean VID_FullScreen( Window win )
{
MotifWmHints hints;
XWindowChanges changes;
 
aHints = XInternAtom( x_disp, "_MOTIF_WM_HINTS", 0 );
if (aHints == None) {
Con_Printf( "Could not intern X atom for _MOTIF_WM_HINTS." );
return( false );
}
 
hints.flags = MWM_HINTS_DECORATIONS;
hints.decorations = 0; // Absolutely no decorations.
XChangeProperty( x_disp, win, aHints, aHints, 32, PropModeReplace, (unsigned char *)&hints, 4 );
 
changes.x = 0;
changes.y = 0;
changes.width = x_screen_width;
changes.height = x_screen_height;
changes.stack_mode = TopIf;
XConfigureWindow( x_disp, win, CWX | CWY | CWWidth | CWHeight | CWStackMode, &changes);
return( true );
}
 
void VID_Init (unsigned char *palette)
{
 
int pnum, i;
XVisualInfo template;
int num_visuals;
int template_mask;
int w, h;
 
int desired_width=320, desired_height=200;
Cmd_AddCommand ("gamma", VID_Gamma_f);
 
Cvar_RegisterVariable (&pixel_multiply);
 
if (pipe(render_pipeline) < 0)
Sys_Error("VID_Init: pipe");
for (i=0 ; i<256 ; i++)
vid_gamma[i] = i;
 
vid.width = 320;
vid.height = 200;
vid.aspect = 1.0;
vid.numpages = 2;
vid.colormap = host_colormap;
vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
//vid.cbits = VID_CBITS;
//vid.grades = VID_GRADES;
 
srandom(getpid());
 
verbose = COM_CheckParm("-verbose");
count_frames = COM_CheckParm("-count_frames");
 
//
// open the display
//
x_disp = XOpenDisplay(0);
 
if (!x_disp) {
if (getenv("DISPLAY"))
Sys_Error("VID: Could not open display [%s]\n",
getenv("DISPLAY"));
else
Sys_Error("VID: Could not open local display\n");
}
 
x_screen = DefaultScreen( x_disp );
x_screen_width = WidthOfScreen( ScreenOfDisplay( x_disp, x_screen ) );
x_screen_height = HeightOfScreen( ScreenOfDisplay( x_disp, x_screen ) );
 
x_center_width = x_screen_width/2;
 
x_center_height = x_screen_height/2;
 
Con_Printf( "Using screen %d: %dx%d\n", x_screen, x_screen_width, x_screen_height );
 
x_root_win = DefaultRootWindow( x_disp);
 
//XAutoRepeatOff(x_disp);
 
// for debugging only
if (verbose)
XSynchronize(x_disp, True);
 
//
// check for command-line window size
//
if ((pnum=COM_CheckParm("-winsize"))) {
if (pnum >= com_argc-2)
Sys_Error("VID: -winsize <width> <height>\n");
desired_width = Q_atoi(com_argv[pnum+1]);
desired_height = Q_atoi(com_argv[pnum+2]);
if (desired_width < 1 || desired_height < 1)
Sys_Error("VID: Bad window width/height\n");
}
 
template_mask = VisualScreenMask; // make sure we get the right one
template.screen = x_screen;
//
// specify a visual id
//
if ((pnum=COM_CheckParm("-visualid"))) {
if (pnum >= com_argc-1)
Sys_Error("VID: -visualid <id#>\n");
template.visualid = Q_atoi(com_argv[pnum+1]);
template_mask |= VisualIDMask;
} else {
// If not specified, find an 8 bit visual since others don't work
// template.depth = 8;
// template_mask |= VisualDepthMask;
int screen;
screen = XDefaultScreen(x_disp);
template.visualid =
XVisualIDFromVisual(XDefaultVisual(x_disp, screen));
template_mask = VisualIDMask;
}
//
// pick a visual- warn if more than one was available
//
x_visinfo = XGetVisualInfo(x_disp, template_mask, &template, &num_visuals);
if (num_visuals > 1) {
printf("Found more than one visual id at depth %d:\n", template.depth);
for (i=0 ; i<num_visuals ; i++)
printf(" -visualid %d\n", (int)(x_visinfo[i].visualid));
}
else if (num_visuals == 0) {
if (template_mask == VisualIDMask)
Sys_Error("VID: Bad visual id %d\n", template.visualid);
else
Sys_Error("VID: No visuals at depth %d\n", template.depth);
}
 
if (verbose) {
printf("Using visualid %d:\n", (int)(x_visinfo->visualid));
printf(" screen %d\n", x_visinfo->screen);
printf(" red_mask 0x%x\n", (int)(x_visinfo->red_mask));
printf(" green_mask 0x%x\n", (int)(x_visinfo->green_mask));
printf(" blue_mask 0x%x\n", (int)(x_visinfo->blue_mask));
printf(" colormap_size %d\n", x_visinfo->colormap_size);
printf(" bits_per_rgb %d\n", x_visinfo->bits_per_rgb);
}
 
x_vis = x_visinfo->visual;
//
// See if we're going to do pixel multiply
//
if (pixel_multiply.value < 1 || pixel_multiply.value > 4)
Cvar_SetValue("pixel_multiply", 2);
current_pixel_multiply = pixel_multiply.value;
 
w = 320*current_pixel_multiply; // minimum width
h = 200*current_pixel_multiply; // minimum height
if (desired_width < w)
desired_width = w;
if (desired_height < h)
desired_height = h;
 
vid.width = MP(desired_width);
vid.height = MP(desired_height);
 
//
// patch things up so game doesn't fail if window is too small
//
 
if (vid.width < 320)
vid.width = 320;
if (vid.height < 200)
vid.height = 200;
 
//
// see if we're going to use threads
//
if(((sysconf(_SC_NPROCESSORS_ONLN) > 1) || COM_CheckParm("-mt")) &&
(COM_CheckParm("-no_mt") == 0)) {
use_mt = 1;
printf("VID: Using multiple threads!\n");
}
 
// setup attributes for main window
{
int attribmask = CWEventMask | CWColormap | CWBorderPixel;
XSetWindowAttributes attribs;
Colormap tmpcmap;
 
tmpcmap = XCreateColormap(x_disp, XRootWindow(x_disp,
x_visinfo->screen), x_vis, AllocNone);
 
attribs.event_mask = x_std_event_mask;
attribs.border_pixel = 0;
attribs.colormap = tmpcmap;
 
// create the main window
x_win = XCreateWindow( x_disp,
XRootWindow(x_disp, x_visinfo->screen),
0, 0, // x, y
desired_width, desired_height,
0, // borderwidth
x_visinfo->depth,
InputOutput,
x_vis,
attribmask,
&attribs );
 
if (x_visinfo->class != TrueColor)
XFreeColormap(x_disp, tmpcmap);
 
}
 
if (x_visinfo->depth == 8) {
 
// create and upload the palette
if (x_visinfo->class == PseudoColor) {
x_cmap = XCreateColormap(x_disp, x_win, x_vis, AllocAll);
VID_SetPalette(palette);
XSetWindowColormap(x_disp, x_win, x_cmap);
}
 
}
 
VID_SetWindowTitle( x_win, "Quake" );
 
// inviso cursor
XDefineCursor(x_disp, x_win, CreateNullCursor(x_disp, x_win));
 
// create the GC
{
XGCValues xgcvalues;
int valuemask = GCGraphicsExposures;
xgcvalues.graphics_exposures = False;
x_gc = XCreateGC(x_disp, x_win, valuemask, &xgcvalues );
}
 
// map the window
XMapWindow(x_disp, x_win);
XSync(x_disp, True) ; /* wait for map */
//
// wait for first exposure event
//
{
XEvent event;
do{
XNextEvent(x_disp, &event);
if (event.type == Expose && !event.xexpose.count)
oktodraw = true;
} while (!oktodraw);
}
//
// initialize XIL
//
state = xil_open();
if(state == NULL) {
//
// XIL's default error handler will print an error msg on stderr
//
Sys_Error("xil_open failed\n");
}
X11_active = true;
 
VID_ResetFramebuffer();
 
D_InitCaches (surfcache, sizeof(surfcache));
vid_menudrawfn = VID_MenuDraw;
vid_menukeyfn = VID_MenuKey;
}
 
VID_ResetFramebuffer()
{
XilMemoryStorage storage;
 
if (use_mt) {
VID_ResetFramebuffer_MT();
return;
}
 
//printf("VID_ResetFramebuffer: vid.width %d, vid.height %d\n", vid.width, vid.height);
 
xil_destroy(display_image);
 
xil_destroy(quake_image);
 
display_image = xil_create_from_window(state, x_disp, x_win);
quake_image = xil_create(state, vid.width, vid.height, 1, XIL_BYTE);
 
xil_export(quake_image);
if (xil_get_memory_storage(quake_image, &storage) == FALSE)
Sys_Error("xil_get_memory_storage");
xil_import(quake_image, TRUE);
xil_export(quake_image);
 
if (xil_get_memory_storage(quake_image, &storage) == FALSE)
Sys_Error("xil_get_memory_storage");
 
vid.rowbytes = storage.byte.scanline_stride;
vid.buffer = storage.byte.data;
vid.conbuffer = vid.buffer;
vid.conrowbytes = vid.rowbytes;
vid.conwidth = vid.width;
vid.conheight = vid.height;
vid.maxwarpwidth = WARP_WIDTH;
vid.maxwarpheight = WARP_HEIGHT;
vid.recalc_refdef = 1; // force a surface cache flush
 
free(d_pzbuffer);
 
d_pzbuffer = malloc(PM(vid.width)*PM(vid.height)*sizeof(*d_pzbuffer));
//Hunk_HighAllocName(PM(vid.width)*PM(vid.height)*sizeof(*d_pzbuffer),"zbuff");
}
 
VID_ResetFramebuffer_MT()
{
XilMemoryStorage storage;
XilImage drain_renderpipeline();
XilImage old_display_image;
 
void * update_thread();
 
printf("VID_ResetFramebuffer: vid.width %d, vid.height %d\n", vid.width, vid.height);
 
old_display_image = display_image;
 
display_image = xil_create_from_window(state, x_disp, x_win);
if (quake_image == NULL)
if (thr_create(NULL, NULL, update_thread, NULL, THR_NEW_LWP, NULL) != 0)
Sys_Error("VID: thr_create");
quake_image = drain_renderpipeline(quake_image);
 
xil_destroy(old_display_image);
 
free(d_pzbuffer);
 
d_pzbuffer = malloc(PM(vid.width)*PM(vid.height)*sizeof(*d_pzbuffer));
}
 
void VID_ShiftPalette(unsigned char *p)
{
VID_SetPalette(p);
}
 
void VID_SetPalette(unsigned char *palette)
{
 
int i;
XColor colors[256];
 
if (x_visinfo->class == PseudoColor && x_visinfo->depth == 8) {
if (palette != current_palette)
memcpy(current_palette, palette, 768);
for (i=0 ; i<256 ; i++)
{
colors[i].pixel = i;
colors[i].flags = DoRed|DoGreen|DoBlue;
colors[i].red = vid_gamma[palette[i*3]] * 257;
colors[i].green = vid_gamma[palette[i*3+1]] * 257;
colors[i].blue = vid_gamma[palette[i*3+2]] * 257;
}
XStoreColors(x_disp, x_cmap, colors, 256);
}
 
}
 
// Called at shutdown
 
void VID_Shutdown (void)
{
X11_active = false;
Con_Printf("VID_Shutdown\n");
//XAutoRepeatOn(x_disp);
xil_destroy(display_image);
xil_destroy(quake_image);
display_image = NULL;
quake_image = NULL;
XCloseDisplay(x_disp);
}
 
int XLateKey(XKeyEvent *ev)
{
 
int key;
char buf[64];
KeySym keysym;
 
XLookupString(ev, buf, sizeof buf, &keysym, 0);
 
switch(keysym) {
case XK_Page_Up: key = K_PGUP; break;
case XK_Page_Down: key = K_PGDN; break;
case XK_Home: key = K_HOME; break;
case XK_End: key = K_END; break;
case XK_Left: key = K_LEFTARROW; break;
case XK_Right: key = K_RIGHTARROW; break;
case XK_Down: key = K_DOWNARROW; break;
case XK_Up: key = K_UPARROW; break;
case XK_Escape: key = K_ESCAPE; break;
case XK_Return: key = K_ENTER; break;
case XK_Tab: key = K_TAB; break;
case XK_Help:
case XK_F1: key = K_F1; break;
case XK_F2: key = K_F2; break;
case XK_F3: key = K_F3; break;
case XK_F4: key = K_F4; break;
case XK_F5: key = K_F5; break;
case XK_F6: key = K_F6; break;
case XK_F7: key = K_F7; break;
case XK_F8: key = K_F8; break;
case XK_F9: key = K_F9; break;
case XK_F10: key = K_F10; break;
case XK_F11: key = K_F11; break;
case XK_F12: key = K_F12; break;
case XK_BackSpace:
case XK_Delete: key = K_BACKSPACE; break;
case XK_Pause: key = K_PAUSE; break;
case XK_Shift_L:
case XK_Shift_R: key = K_SHIFT; break;
case XK_Control_L:
case XK_Control_R: key = K_CTRL; break;
case XK_Alt_L:
case XK_Meta_L:
case XK_Alt_R:
case XK_Meta_R: key = K_ALT; break;
// various other keys on the keyboard
case XK_F27: key = K_HOME; break;
case XK_F29: key = K_PGUP; break;
case XK_F33: key = K_END; break;
case XK_F35: key = K_PGDN; break;
case XK_Insert:
case XK_KP_Insert: key = K_INS; break;
case XK_F24: key = '-'; break;
case XK_KP_Add: key = '+'; break;
case XK_KP_Subtract: key = '-'; break;
case XK_F25: key = '/'; break;
case XK_F26: key = '*'; break;
 
default:
key = (unsigned char)*buf;
break;
}
 
return key;
 
}
 
struct {
int key;
int down;
} keyq[64];
 
int keyq_head=0;
int keyq_tail=0;
 
int config_notify=0;
int config_notify_width;
int config_notify_height;
 
void GetEvent(void)
{
XEvent x_event;
int b;
 
XNextEvent(x_disp, &x_event);
switch(x_event.type) {
case KeyPress:
Key_Event(XLateKey(&x_event.xkey), true);
break;
case KeyRelease:
Key_Event(XLateKey(&x_event.xkey), false);
break;
 
case MotionNotify:
 
if (_windowed_mouse.value) {
mouse_x = (float) ((int)x_event.xmotion.x - (int)(vid.width/2));
mouse_y = (float) ((int)x_event.xmotion.y - (int)(vid.height/2));
//printf("m: x=%d,y=%d, mx=%3.2f,my=%3.2f\n",
// x_event.xmotion.x, x_event.xmotion.y, mouse_x, mouse_y);
 
/* move the mouse to the window center again */
XSelectInput( x_disp, x_win, x_std_event_mask & ~PointerMotionMask );
XWarpPointer(x_disp,None,x_win,0,0,0,0,
(vid.width/2),(vid.height/2));
XSelectInput( x_disp, x_win, x_std_event_mask );
} else {
mouse_x = (float) (x_event.xmotion.x-p_mouse_x);
mouse_y = (float) (x_event.xmotion.y-p_mouse_y);
p_mouse_x=x_event.xmotion.x;
p_mouse_y=x_event.xmotion.y;
}
break;
 
case ButtonPress:
b=-1;
if (x_event.xbutton.button == 1)
b = 0;
else if (x_event.xbutton.button == 2)
b = 2;
else if (x_event.xbutton.button == 3)
b = 1;
if (b>=0)
mouse_buttonstate |= 1<<b;
break;
 
case ButtonRelease:
b=-1;
if (x_event.xbutton.button == 1)
b = 0;
else if (x_event.xbutton.button == 2)
b = 2;
else if (x_event.xbutton.button == 3)
b = 1;
if (b>=0)
mouse_buttonstate &= ~(1<<b);
break;
case ConfigureNotify:
// printf("config notify\n");
config_notify_width = x_event.xconfigure.width;
config_notify_height = x_event.xconfigure.height;
config_notify = 1;
sb_updates = 0;
break;
case Expose:
sb_updates = 0;
break;
case ClientMessage:
if (x_event.xclient.data.l[0] == aWMDelete) Host_Quit_f();
break;
#if 0
case FocusIn:
printf("FocusIn...\n");
x_focus = true;
break;
case FocusOut:
printf("FocusOut...\n");
x_focus = false;
break;
#endif
}
 
if (old_windowed_mouse != _windowed_mouse.value) {
old_windowed_mouse = _windowed_mouse.value;
 
if (!_windowed_mouse.value) {
/* ungrab the pointer */
XUngrabPointer(x_disp,CurrentTime);
} else {
/* grab the pointer */
XGrabPointer(x_disp,x_win,True,0,GrabModeAsync,
GrabModeAsync,x_win,None,CurrentTime);
}
}
}
 
// flushes the given rectangles from the view buffer to the screen
 
void
VID_Update (vrect_t *rects)
{
void VID_Update_MT(vrect_t *);
 
 
if (count_frames) {
static int count;
static long long s;
long long gethrtime();
 
if (count == 0)
s = gethrtime();
 
if (count++ == 200) {
long long n = gethrtime();
count = 1;
printf("%lf frames/secs\n", 200.0/((double)(n-s) / 1e9));
s = n;
}
}
 
if (use_mt) {
VID_Update_MT(rects);
return;
}
 
// if the window changes dimension, skip this frame
 
if (config_notify) {
int w, h;
XWindowChanges chg;
unsigned int value_mask;
 
w = 320*current_pixel_multiply; // minimum width
h = 200*current_pixel_multiply; // minimum height
if (config_notify_width < w || config_notify_height < h) {
// We must resize the window
memset(&chg, 0, sizeof(chg));
value_mask = 0;
if (config_notify_width < w) {
config_notify_width = chg.width = w;
value_mask |= CWWidth;
}
if (config_notify_height < h) {
config_notify_height = chg.height = h;
value_mask |= CWHeight;
}
if (value_mask)
XConfigureWindow(x_disp, x_win, value_mask, &chg);
}
 
config_notify = 0;
 
vid.width = MP(config_notify_width) & ~3;
vid.height = MP(config_notify_height);
 
if (vid.width < 320)
vid.width = 320;
if (vid.height < 200)
vid.height = 200;
VID_ResetFramebuffer();
 
return;
}
// if pixel multiply changed, skip this frame
if (CheckPixelMultiply())
return;
 
while (rects) { // I've never seen more than one rect?
XilMemoryStorage storage;
 
xil_import(quake_image, TRUE); // let xil control the image
 
if (current_pixel_multiply < 2)
xil_copy(quake_image, display_image);
else
xil_scale(quake_image, display_image, "nearest",
(float)current_pixel_multiply, (float)current_pixel_multiply);
 
xil_export(quake_image); // back to quake
 
if (xil_get_memory_storage(quake_image, &storage) == FALSE)
Sys_Error("xil_get_memory_storage");
 
vid.buffer = storage.byte.data;
vid.conbuffer = vid.buffer;
 
rects = rects->pnext;
}
}
 
void
VID_Update_MT (vrect_t *rects)
{
XilImage sched_update();
 
// if the window changes dimension, skip this frame
 
if (config_notify) {
int w, h;
XWindowChanges chg;
unsigned int value_mask;
 
w = 320*current_pixel_multiply; // minimum width
h = 200*current_pixel_multiply; // minimum height
if (config_notify_width < w || config_notify_height < h) {
// We must resize the window
memset(&chg, 0, sizeof(chg));
value_mask = 0;
if (config_notify_width < w) {
config_notify_width = chg.width = w;
value_mask |= CWWidth;
}
if (config_notify_height < h) {
config_notify_height = chg.height = h;
value_mask |= CWHeight;
}
if (value_mask)
XConfigureWindow(x_disp, x_win, value_mask, &chg);
}
 
config_notify = 0;
 
vid.width = MP(config_notify_width) & ~3;
vid.height = MP(config_notify_height);
 
if (vid.width < 320)
vid.width = 320;
if (vid.height < 200)
vid.height = 200;
VID_ResetFramebuffer_MT();
 
return;
}
// if pixel multiply changed, skip this frame
if (CheckPixelMultiply())
return;
 
quake_image = sched_update(quake_image);
}
 
XilImage
drain_renderpipeline(XilImage old)
{
XilImage new;
 
XilMemoryStorage storage;
if (old)
if (read(render_pipeline[1], &new, sizeof(new)) != sizeof (new)) {
Sys_Error("drain_renderpipeline: read");
xil_destroy(new);
}
 
xil_destroy(old);
 
 
new = xil_create(state, vid.width, vid.height, 1, XIL_BYTE);
if (write(render_pipeline[0], &new, sizeof (new)) != sizeof(new))
Sys_Error("drain_renderpipeline: write");
 
new = xil_create(state, vid.width, vid.height, 1, XIL_BYTE);
 
xil_export(new);
 
if (xil_get_memory_storage(new, &storage) == FALSE)
Sys_Error("xil_get_memory_storage");
 
vid.rowbytes = storage.byte.scanline_stride;
vid.buffer = storage.byte.data;
vid.conbuffer = vid.buffer;
vid.conrowbytes = vid.rowbytes;
vid.conwidth = vid.width;
vid.conheight = vid.height;
vid.maxwarpwidth = WARP_WIDTH;
vid.maxwarpheight = WARP_HEIGHT;
vid.recalc_refdef = 1; // force a surface cache flush
 
return(new);
 
}
 
XilImage
sched_update(XilImage image)
{
XilImage new;
XilMemoryStorage storage;
 
if (write(render_pipeline[1], &image, sizeof(image)) != sizeof (image))
Sys_Error("sched_update:write");
 
if (read(render_pipeline[1], &new, sizeof(new)) != sizeof (new))
Sys_Error("sched_update:read");
 
xil_export(new);
 
if (xil_get_memory_storage(new, &storage) == FALSE)
Sys_Error("xil_get_memory_storage");
 
vid.buffer = storage.byte.data;
vid.conbuffer = vid.buffer;
 
return (new);
}
 
void *update_thread()
{
XilImage image;
 
if (!X11_active)
return;
 
while (read(render_pipeline[0], &image, sizeof (image)) == sizeof(image)) {
 
xil_import(image, TRUE); // let xil control the image
 
if (!display_image)
return;
 
if (current_pixel_multiply < 2)
xil_copy(image, display_image);
else
xil_scale(image, display_image, "nearest",
(float)current_pixel_multiply, (float)current_pixel_multiply);
 
if (write(render_pipeline[0], &image, sizeof (image)) != sizeof(image))
Sys_Error("update_thread: write");
}
}
 
 
static int dither;
 
void VID_DitherOn(void)
{
if (dither == 0) {
vid.recalc_refdef = 1;
dither = 1;
}
}
 
void VID_DitherOff(void)
{
if (dither) {
vid.recalc_refdef = 1;
dither = 0;
}
}
 
void VID_SetDefaultMode( void )
{
}
 
int I_OpenWindow(void)
{
return 0;
}
 
void I_EraseWindow(int window)
{
 
}
 
void I_DrawCircle(int window, int x, int y, int r)
{
}
 
void I_DisplayWindow(int window)
{
}
 
void Sys_SendKeyEvents(void)
{
// get events from x server
if (x_disp) {
while (XPending(x_disp)) GetEvent();
while (keyq_head != keyq_tail) {
Key_Event(keyq[keyq_tail].key, keyq[keyq_tail].down);
keyq_tail = (keyq_tail + 1) & 63;
}
}
}
 
void IN_Init (void)
{
Cvar_RegisterVariable (&_windowed_mouse);
Cvar_RegisterVariable (&m_filter);
if ( COM_CheckParm ("-nomouse") )
return;
mouse_x = mouse_y = 0.0;
mouse_avail = 1;
}
 
void IN_Shutdown (void)
{
mouse_avail = 0;
}
 
void IN_Commands (void)
{
int i;
if (!mouse_avail) return;
for (i=0 ; i<mouse_buttons ; i++) {
if ( (mouse_buttonstate & (1<<i)) && !(mouse_oldbuttonstate & (1<<i)) )
Key_Event (K_MOUSE1 + i, true);
 
if ( !(mouse_buttonstate & (1<<i)) && (mouse_oldbuttonstate & (1<<i)) )
Key_Event (K_MOUSE1 + i, false);
}
mouse_oldbuttonstate = mouse_buttonstate;
}
 
void IN_Move (usercmd_t *cmd)
{
if (!mouse_avail)
return;
if (m_filter.value) {
mouse_x = (mouse_x + old_mouse_x) * 0.5;
mouse_y = (mouse_y + old_mouse_y) * 0.5;
}
 
old_mouse_x = mouse_x;
old_mouse_y = mouse_y;
mouse_x *= sensitivity.value;
mouse_y *= sensitivity.value;
if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
cmd->sidemove += m_side.value * mouse_x;
else
cl.viewangles[YAW] -= m_yaw.value * mouse_x;
if (in_mlook.state & 1)
V_StopPitchDrift ();
if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) {
cl.viewangles[PITCH] += m_pitch.value * mouse_y;
if (cl.viewangles[PITCH] > 80)
cl.viewangles[PITCH] = 80;
if (cl.viewangles[PITCH] < -70)
cl.viewangles[PITCH] = -70;
} else {
if ((in_strafe.state & 1) && noclip_anglehack)
cmd->upmove -= m_forward.value * mouse_y;
else
cmd->forwardmove -= m_forward.value * mouse_y;
}
mouse_x = mouse_y = 0.0;
}
 
//void VID_UnlockBuffer(void) { }
//void VID_LockBuffer(void) { }
 
/contrib/other/sdlquake-1.0.9/vid_svgalib.c
0,0 → 1,1003
/*
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 <termios.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/vt.h>
#include <stdarg.h>
#include <stdio.h>
#include <signal.h>
 
#include <asm/io.h>
 
#include "vga.h"
#include "vgakeyboard.h"
#include "vgamouse.h"
 
#include "quakedef.h"
#include "d_local.h"
 
#define stringify(m) { #m, m }
 
unsigned short d_8to16table[256];
static byte *vid_surfcache;
static int VID_highhunkmark;
 
int num_modes;
vga_modeinfo *modes;
int current_mode;
 
int num_shades=32;
 
struct
{
char *name;
int num;
} mice[] =
{
stringify(MOUSE_MICROSOFT),
stringify(MOUSE_MOUSESYSTEMS),
stringify(MOUSE_MMSERIES),
stringify(MOUSE_LOGITECH),
stringify(MOUSE_BUSMOUSE),
stringify(MOUSE_PS2),
};
 
static unsigned char scantokey[128];
static byte vid_current_palette[768];
 
int num_mice = sizeof (mice) / sizeof(mice[0]);
 
int d_con_indirect = 0;
 
int svgalib_inited=0;
int UseMouse = 1;
int UseDisplay = 1;
int UseKeyboard = 1;
 
int mouserate = MOUSE_DEFAULTSAMPLERATE;
 
cvar_t vid_mode = {"vid_mode","5",false};
cvar_t vid_redrawfull = {"vid_redrawfull","0",false};
cvar_t vid_waitforrefresh = {"vid_waitforrefresh","0",true};
char *framebuffer_ptr;
 
cvar_t mouse_button_commands[3] =
{
{"mouse1","+attack"},
{"mouse2","+strafe"},
{"mouse3","+forward"},
};
 
int mouse_buttons;
int mouse_buttonstate;
int mouse_oldbuttonstate;
float mouse_x, mouse_y;
float old_mouse_x, old_mouse_y;
int mx, my;
 
cvar_t m_filter = {"m_filter","0"};
 
static byte backingbuf[48*24];
 
int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar;
byte *VGA_pagebase;
 
void VGA_UpdatePlanarScreen (void *srcbuffer);
 
void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
{
int i, j, k, plane, reps, repshift, offset, vidpage, off;
 
if (!svgalib_inited || !vid.direct || !vga_oktowrite()) return;
 
if (vid.aspect > 1.5)
{
reps = 2;
repshift = 1;
} else {
reps = 1;
repshift = 0;
}
 
vidpage = 0;
vga_setpage(0);
 
if (VGA_planar)
{
for (plane=0 ; plane<4 ; plane++)
{
// select the correct plane for reading and writing
outb(0x02, 0x3C4);
outb(1 << plane, 0x3C5);
outb(4, 0x3CE);
outb(plane, 0x3CF);
 
for (i=0 ; i<(height << repshift) ; i += reps)
{
for (k=0 ; k<reps ; k++)
{
for (j=0 ; j<(width >> 2) ; j++)
{
backingbuf[(i + k) * 24 + (j << 2) + plane] =
vid.direct[(y + i + k) * VGA_rowbytes +
(x >> 2) + j];
vid.direct[(y + i + k) * VGA_rowbytes + (x>>2) + j] =
pbitmap[(i >> repshift) * 24 +
(j << 2) + plane];
}
}
}
}
} else {
for (i=0 ; i<(height << repshift) ; i += reps)
{
for (j=0 ; j<reps ; j++)
{
offset = x + ((y << repshift) + i + j) * vid.rowbytes;
off = offset % 0x10000;
if ((offset / 0x10000) != vidpage) {
vidpage=offset / 0x10000;
vga_setpage(vidpage);
}
memcpy (&backingbuf[(i + j) * 24],
vid.direct + off, width);
memcpy (vid.direct + off,
&pbitmap[(i >> repshift)*width], width);
}
}
}
}
 
void D_EndDirectRect (int x, int y, int width, int height)
{
int i, j, k, plane, reps, repshift, offset, vidpage, off;
 
if (!svgalib_inited || !vid.direct || !vga_oktowrite()) return;
 
if (vid.aspect > 1.5)
{
reps = 2;
repshift = 1;
} else {
reps = 1;
repshift = 0;
}
 
vidpage = 0;
vga_setpage(0);
 
if (VGA_planar)
{
for (plane=0 ; plane<4 ; plane++)
{
// select the correct plane for writing
outb(2, 0x3C4);
outb(1 << plane, 0x3C5);
outb(4, 0x3CE);
outb(plane, 0x3CF);
 
for (i=0 ; i<(height << repshift) ; i += reps)
{
for (k=0 ; k<reps ; k++)
{
for (j=0 ; j<(width >> 2) ; j++)
{
vid.direct[(y + i + k) * VGA_rowbytes + (x>>2) + j] =
backingbuf[(i + k) * 24 + (j << 2) + plane];
}
}
}
}
} else {
for (i=0 ; i<(height << repshift) ; i += reps)
{
for (j=0 ; j<reps ; j++)
{
offset = x + ((y << repshift) + i + j) * vid.rowbytes;
off = offset % 0x10000;
if ((offset / 0x10000) != vidpage) {
vidpage=offset / 0x10000;
vga_setpage(vidpage);
}
memcpy (vid.direct + off,
&backingbuf[(i +j)*24],
width);
}
}
}
}
 
/*
=================
VID_Gamma_f
 
Keybinding command
=================
*/
void VID_Gamma_f (void)
{
float gamma, f, inf;
unsigned char palette[768];
int i;
 
if (Cmd_Argc () == 2)
{
gamma = Q_atof (Cmd_Argv(1));
 
for (i=0 ; i<768 ; i++)
{
f = pow ( (host_basepal[i]+1)/256.0 , gamma );
inf = f*255 + 0.5;
if (inf < 0)
inf = 0;
if (inf > 255)
inf = 255;
palette[i] = inf;
}
 
VID_SetPalette (palette);
 
vid.recalc_refdef = 1; // force a surface cache flush
}
}
 
void VID_DescribeMode_f (void)
{
int modenum;
modenum = Q_atoi (Cmd_Argv(1));
if ((modenum >= num_modes) || (modenum < 0 ) || !modes[modenum].width)
Con_Printf("Invalid video mode: %d!\n",modenum);
Con_Printf("%d: %d x %d - ",modenum,modes[modenum].width,modes[modenum].height);
if (modes[modenum].bytesperpixel == 0)
Con_Printf("ModeX\n");
else
Con_Printf("%d bpp\n", modes[modenum].bytesperpixel<<3);
}
 
void VID_DescribeModes_f (void)
{
int i;
for (i=0;i<num_modes;i++)
if (modes[i].width) {
Con_Printf("%d: %d x %d - ", i, modes[i].width,modes[i].height);
if (modes[i].bytesperpixel == 0)
Con_Printf("ModeX\n");
else
Con_Printf("%d bpp\n", modes[i].bytesperpixel<<3);
}
}
 
/*
================
VID_NumModes
================
*/
int VID_NumModes ()
{
int i,i1=0;
for (i=0;i<num_modes;i++)
i1+=(modes[i].width?1:0);
return (i1);
}
 
void VID_NumModes_f (void)
{
Con_Printf("%d modes\n",VID_NumModes());
}
 
void VID_Debug_f (void)
{
Con_Printf("mode: %d\n",current_mode);
Con_Printf("height x width: %d x %d\n",vid.height,vid.width);
Con_Printf("bpp: %d\n",modes[current_mode].bytesperpixel*8);
Con_Printf("vid.aspect: %f\n",vid.aspect);
}
 
 
 
void VID_InitModes(void)
{
 
int i;
 
// get complete information on all modes
 
num_modes = vga_lastmodenumber()+1;
modes = Z_Malloc(num_modes * sizeof(vga_modeinfo));
for (i=0 ; i<num_modes ; i++)
{
if (vga_hasmode(i))
Q_memcpy(&modes[i], vga_getmodeinfo(i), sizeof (vga_modeinfo));
else
modes[i].width = 0; // means not available
}
 
// filter for modes i don't support
 
for (i=0 ; i<num_modes ; i++)
{
if (modes[i].bytesperpixel != 1 && modes[i].colors != 256)
modes[i].width = 0;
}
 
}
 
int get_mode(char *name, int width, int height, int depth)
{
 
int i;
int ok, match;
 
match = (!!width) + (!!height)*2 + (!!depth)*4;
 
if (name)
{
i = vga_getmodenumber(name);
if (!modes[i].width)
{
Sys_Printf("Mode [%s] not supported\n", name);
i = G320x200x256;
}
}
else
{
for (i=0 ; i<num_modes ; i++)
if (modes[i].width)
{
ok = (modes[i].width == width)
+ (modes[i].height == height)*2
+ (modes[i].bytesperpixel == depth/8)*4;
if ((ok & match) == ok)
break;
}
if (i==num_modes)
{
Sys_Printf("Mode %dx%d (%d bits) not supported\n",
width, height, depth);
i = G320x200x256;
}
}
 
return i;
 
}
 
int matchmouse(int mouse, char *name)
{
int i;
for (i=0 ; i<num_mice ; i++)
if (!strcmp(mice[i].name, name))
return i;
return mouse;
}
 
#if 0
 
void vtswitch(int newconsole)
{
 
int fd;
struct vt_stat x;
 
// switch consoles and wait until reactivated
fd = open("/dev/console", O_RDONLY);
ioctl(fd, VT_GETSTATE, &x);
ioctl(fd, VT_ACTIVATE, newconsole);
ioctl(fd, VT_WAITACTIVE, x.v_active);
close(fd);
 
}
 
#endif
 
void keyhandler(int scancode, int state)
{
int sc;
 
sc = scancode & 0x7f;
// Con_Printf("scancode=%x (%d%s)\n", scancode, sc, scancode&0x80?"+128":"");
Key_Event(scantokey[sc], state == KEY_EVENTPRESS);
 
}
 
void VID_Shutdown(void)
{
 
if (!svgalib_inited) return;
 
// printf("shutdown graphics called\n");
if (UseKeyboard)
keyboard_close();
if (UseDisplay)
vga_setmode(TEXT);
// printf("shutdown graphics finished\n");
 
svgalib_inited = 0;
 
}
 
void VID_ShiftPalette(unsigned char *p)
{
VID_SetPalette(p);
}
 
void VID_SetPalette(byte *palette)
{
 
static int tmppal[256*3];
int *tp;
int i;
 
if (!svgalib_inited)
return;
 
memcpy(vid_current_palette, palette, sizeof(vid_current_palette));
 
if (vga_getcolors() == 256)
{
 
tp = tmppal;
for (i=256*3 ; i ; i--)
*(tp++) = *(palette++) >> 2;
 
if (UseDisplay && vga_oktowrite())
vga_setpalvec(0, 256, tmppal);
 
}
}
 
int VID_SetMode (int modenum, unsigned char *palette)
{
int bsize, zsize, tsize;
 
if ((modenum >= num_modes) || (modenum < 0) || !modes[modenum].width)
{
Cvar_SetValue ("vid_mode", (float)current_mode);
Con_Printf("No such video mode: %d\n",modenum);
return 0;
}
 
Cvar_SetValue ("vid_mode", (float)modenum);
current_mode=modenum;
 
vid.width = modes[current_mode].width;
vid.height = modes[current_mode].height;
 
VGA_width = modes[current_mode].width;
VGA_height = modes[current_mode].height;
VGA_planar = modes[current_mode].bytesperpixel == 0;
VGA_rowbytes = modes[current_mode].linewidth;
vid.rowbytes = modes[current_mode].linewidth;
if (VGA_planar) {
VGA_bufferrowbytes = modes[current_mode].linewidth * 4;
vid.rowbytes = modes[current_mode].linewidth*4;
}
 
vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0);
vid.colormap = (pixel_t *) host_colormap;
vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
vid.conrowbytes = vid.rowbytes;
vid.conwidth = vid.width;
vid.conheight = vid.height;
vid.numpages = 1;
vid.maxwarpwidth = WARP_WIDTH;
vid.maxwarpheight = WARP_HEIGHT;
 
// alloc zbuffer and surface cache
if (d_pzbuffer) {
D_FlushCaches();
Hunk_FreeToHighMark (VID_highhunkmark);
d_pzbuffer = NULL;
vid_surfcache = NULL;
}
 
bsize = vid.rowbytes * vid.height;
tsize = D_SurfaceCacheForRes (vid.width, vid.height);
zsize = vid.width * vid.height * sizeof(*d_pzbuffer);
 
VID_highhunkmark = Hunk_HighMark ();
 
d_pzbuffer = Hunk_HighAllocName (bsize+tsize+zsize, "video");
 
vid_surfcache = ((byte *)d_pzbuffer) + zsize;
 
vid.conbuffer = vid.buffer = (pixel_t *)(((byte *)d_pzbuffer) + zsize + tsize);
 
D_InitCaches (vid_surfcache, tsize);
 
// get goin'
 
vga_setmode(current_mode);
VID_SetPalette(palette);
 
VGA_pagebase = vid.direct = framebuffer_ptr = (char *) vga_getgraphmem();
// if (vga_setlinearaddressing()>0)
// framebuffer_ptr = (char *) vga_getgraphmem();
if (!framebuffer_ptr)
Sys_Error("This mode isn't hapnin'\n");
 
vga_setpage(0);
 
svgalib_inited=1;
 
vid.recalc_refdef = 1; // force a surface cache flush
 
return 0;
}
 
void VID_Init(unsigned char *palette)
{
 
int i;
int w, h, d;
 
if (svgalib_inited)
return;
 
// Cmd_AddCommand ("gamma", VID_Gamma_f);
 
if (UseDisplay)
{
vga_init();
 
VID_InitModes();
 
Cvar_RegisterVariable (&vid_mode);
Cvar_RegisterVariable (&vid_redrawfull);
Cvar_RegisterVariable (&vid_waitforrefresh);
Cmd_AddCommand("vid_nummodes", VID_NumModes_f);
Cmd_AddCommand("vid_describemode", VID_DescribeMode_f);
Cmd_AddCommand("vid_describemodes", VID_DescribeModes_f);
Cmd_AddCommand("vid_debug", VID_Debug_f);
 
// interpret command-line params
 
w = h = d = 0;
if (getenv("GSVGAMODE"))
current_mode = get_mode(getenv("GSVGAMODE"), w, h, d);
else if (COM_CheckParm("-mode"))
current_mode = get_mode(com_argv[COM_CheckParm("-mode")+1], w, h, d);
else if (COM_CheckParm("-w") || COM_CheckParm("-h")
|| COM_CheckParm("-d"))
{
if (COM_CheckParm("-w"))
w = Q_atoi(com_argv[COM_CheckParm("-w")+1]);
if (COM_CheckParm("-h"))
h = Q_atoi(com_argv[COM_CheckParm("-h")+1]);
if (COM_CheckParm("-d"))
d = Q_atoi(com_argv[COM_CheckParm("-d")+1]);
current_mode = get_mode(0, w, h, d);
}
else
current_mode = G320x200x256;
 
// set vid parameters
VID_SetMode(current_mode, palette);
 
VID_SetPalette(palette);
 
// we do want to run in the background when switched away
vga_runinbackground(1);
}
 
if (COM_CheckParm("-nokbd")) UseKeyboard = 0;
 
if (UseKeyboard)
{
for (i=0 ; i<128 ; i++)
scantokey[i] = ' ';
 
scantokey[42] = K_SHIFT;
scantokey[54] = K_SHIFT;
scantokey[72] = K_UPARROW;
scantokey[103] = K_UPARROW;
scantokey[80] = K_DOWNARROW;
scantokey[108] = K_DOWNARROW;
scantokey[75] = K_LEFTARROW;
scantokey[105] = K_LEFTARROW;
scantokey[77] = K_RIGHTARROW;
scantokey[106] = K_RIGHTARROW;
scantokey[29] = K_CTRL;
scantokey[97] = K_CTRL;
scantokey[56] = K_ALT;
scantokey[100] = K_ALT;
// scantokey[58] = JK_CAPS;
// scantokey[69] = JK_NUM_LOCK;
scantokey[71] = K_HOME;
scantokey[73] = K_PGUP;
scantokey[79] = K_END;
scantokey[81] = K_PGDN;
scantokey[82] = K_INS;
scantokey[83] = K_DEL;
scantokey[1 ] = K_ESCAPE;
scantokey[28] = K_ENTER;
scantokey[15] = K_TAB;
scantokey[14] = K_BACKSPACE;
scantokey[119] = K_PAUSE;
scantokey[57] = ' ';
 
scantokey[102] = K_HOME;
scantokey[104] = K_PGUP;
scantokey[107] = K_END;
scantokey[109] = K_PGDN;
scantokey[110] = K_INS;
scantokey[111] = K_DEL;
 
scantokey[2] = '1';
scantokey[3] = '2';
scantokey[4] = '3';
scantokey[5] = '4';
scantokey[6] = '5';
scantokey[7] = '6';
scantokey[8] = '7';
scantokey[9] = '8';
scantokey[10] = '9';
scantokey[11] = '0';
scantokey[12] = '-';
scantokey[13] = '=';
scantokey[41] = '`';
scantokey[26] = '[';
scantokey[27] = ']';
scantokey[39] = ';';
scantokey[40] = '\'';
scantokey[51] = ',';
scantokey[52] = '.';
scantokey[53] = '/';
scantokey[43] = '\\';
 
scantokey[59] = K_F1;
scantokey[60] = K_F2;
scantokey[61] = K_F3;
scantokey[62] = K_F4;
scantokey[63] = K_F5;
scantokey[64] = K_F6;
scantokey[65] = K_F7;
scantokey[66] = K_F8;
scantokey[67] = K_F9;
scantokey[68] = K_F10;
scantokey[87] = K_F11;
scantokey[88] = K_F12;
scantokey[30] = 'a';
scantokey[48] = 'b';
scantokey[46] = 'c';
scantokey[32] = 'd';
scantokey[18] = 'e';
scantokey[33] = 'f';
scantokey[34] = 'g';
scantokey[35] = 'h';
scantokey[23] = 'i';
scantokey[36] = 'j';
scantokey[37] = 'k';
scantokey[38] = 'l';
scantokey[50] = 'm';
scantokey[49] = 'n';
scantokey[24] = 'o';
scantokey[25] = 'p';
scantokey[16] = 'q';
scantokey[19] = 'r';
scantokey[31] = 's';
scantokey[20] = 't';
scantokey[22] = 'u';
scantokey[47] = 'v';
scantokey[17] = 'w';
scantokey[45] = 'x';
scantokey[21] = 'y';
scantokey[44] = 'z';
 
if (keyboard_init())
Sys_Error("keyboard_init() failed");
keyboard_seteventhandler(keyhandler);
}
 
}
 
void VID_Update(vrect_t *rects)
{
if (!svgalib_inited)
return;
 
if (!vga_oktowrite())
return; // can't update screen if it's not active
 
if (vid_waitforrefresh.value)
vga_waitretrace();
 
if (VGA_planar)
VGA_UpdatePlanarScreen (vid.buffer);
 
else if (vid_redrawfull.value) {
int total = vid.rowbytes * vid.height;
int offset;
 
for (offset=0;offset<total;offset+=0x10000) {
vga_setpage(offset/0x10000);
memcpy(framebuffer_ptr,
vid.buffer + offset,
((total-offset>0x10000)?0x10000:(total-offset)));
}
} else {
int ycount;
int offset;
int vidpage=0;
 
vga_setpage(0);
 
while (rects)
{
ycount = rects->height;
offset = rects->y * vid.rowbytes + rects->x;
while (ycount--)
{
register int i = offset % 0x10000;
if ((offset / 0x10000) != vidpage) {
vidpage=offset / 0x10000;
vga_setpage(vidpage);
}
if (rects->width + i > 0x10000) {
memcpy(framebuffer_ptr + i,
vid.buffer + offset,
0x10000 - i);
vga_setpage(++vidpage);
memcpy(framebuffer_ptr,
vid.buffer + offset + 0x10000 - i,
rects->width - 0x10000 + i);
} else
memcpy(framebuffer_ptr + i,
vid.buffer + offset,
rects->width);
offset += vid.rowbytes;
}
rects = rects->pnext;
}
}
if (vid_mode.value != current_mode)
VID_SetMode ((int)vid_mode.value, vid_current_palette);
}
 
static int dither;
 
void VID_DitherOn(void)
{
if (dither == 0)
{
// R_ViewChanged (&vrect, sb_lines, vid.aspect);
dither = 1;
}
}
 
void VID_DitherOff(void)
{
if (dither)
{
// R_ViewChanged (&vrect, sb_lines, vid.aspect);
dither = 0;
}
}
 
void Sys_SendKeyEvents(void)
{
if (!svgalib_inited)
return;
 
if (UseKeyboard)
while (keyboard_update());
}
 
void Force_CenterView_f (void)
{
cl.viewangles[PITCH] = 0;
}
 
 
void mousehandler(int buttonstate, int dx, int dy)
{
mouse_buttonstate = buttonstate;
mx += dx;
my += dy;
}
 
void IN_Init(void)
{
 
int mtype;
char *mousedev;
int mouserate;
 
if (UseMouse)
{
 
Cvar_RegisterVariable (&mouse_button_commands[0]);
Cvar_RegisterVariable (&mouse_button_commands[1]);
Cvar_RegisterVariable (&mouse_button_commands[2]);
Cvar_RegisterVariable (&m_filter);
Cmd_AddCommand ("force_centerview", Force_CenterView_f);
 
mouse_buttons = 3;
 
mtype = vga_getmousetype();
 
mousedev = "/dev/mouse";
if (getenv("MOUSEDEV")) mousedev = getenv("MOUSEDEV");
if (COM_CheckParm("-mdev"))
mousedev = com_argv[COM_CheckParm("-mdev")+1];
 
mouserate = 1200;
if (getenv("MOUSERATE")) mouserate = atoi(getenv("MOUSERATE"));
if (COM_CheckParm("-mrate"))
mouserate = atoi(com_argv[COM_CheckParm("-mrate")+1]);
 
// printf("Mouse: dev=%s,type=%s,speed=%d\n",
// mousedev, mice[mtype].name, mouserate);
if (mouse_init(mousedev, mtype, mouserate))
{
Con_Printf("No mouse found\n");
UseMouse = 0;
}
else
mouse_seteventhandler(mousehandler);
 
}
 
}
 
void IN_Shutdown(void)
{
if (UseMouse)
mouse_close();
}
 
/*
===========
IN_Commands
===========
*/
void IN_Commands (void)
{
if (UseMouse && cls.state != ca_dedicated)
{
// poll mouse values
while (mouse_update())
;
 
// perform button actions
if ((mouse_buttonstate & MOUSE_LEFTBUTTON) &&
!(mouse_oldbuttonstate & MOUSE_LEFTBUTTON))
Key_Event (K_MOUSE1, true);
else if (!(mouse_buttonstate & MOUSE_LEFTBUTTON) &&
(mouse_oldbuttonstate & MOUSE_LEFTBUTTON))
Key_Event (K_MOUSE1, false);
 
if ((mouse_buttonstate & MOUSE_RIGHTBUTTON) &&
!(mouse_oldbuttonstate & MOUSE_RIGHTBUTTON))
Key_Event (K_MOUSE2, true);
else if (!(mouse_buttonstate & MOUSE_RIGHTBUTTON) &&
(mouse_oldbuttonstate & MOUSE_RIGHTBUTTON))
Key_Event (K_MOUSE2, false);
 
if ((mouse_buttonstate & MOUSE_MIDDLEBUTTON) &&
!(mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON))
Key_Event (K_MOUSE3, true);
else if (!(mouse_buttonstate & MOUSE_MIDDLEBUTTON) &&
(mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON))
Key_Event (K_MOUSE3, false);
 
mouse_oldbuttonstate = mouse_buttonstate;
}
}
 
/*
===========
IN_Move
===========
*/
void IN_MouseMove (usercmd_t *cmd)
{
if (!UseMouse)
return;
 
// poll mouse values
while (mouse_update())
;
 
if (m_filter.value)
{
mouse_x = (mx + old_mouse_x) * 0.5;
mouse_y = (my + old_mouse_y) * 0.5;
}
else
{
mouse_x = mx;
mouse_y = my;
}
old_mouse_x = mx;
old_mouse_y = my;
mx = my = 0; // clear for next update
 
mouse_x *= sensitivity.value;
mouse_y *= sensitivity.value;
 
// add mouse X/Y movement to cmd
if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
cmd->sidemove += m_side.value * mouse_x;
else
cl.viewangles[YAW] -= m_yaw.value * mouse_x;
if (in_mlook.state & 1)
V_StopPitchDrift ();
if ( (in_mlook.state & 1) && !(in_strafe.state & 1))
{
cl.viewangles[PITCH] += m_pitch.value * mouse_y;
if (cl.viewangles[PITCH] > 80)
cl.viewangles[PITCH] = 80;
if (cl.viewangles[PITCH] < -70)
cl.viewangles[PITCH] = -70;
}
else
{
if ((in_strafe.state & 1) && noclip_anglehack)
cmd->upmove -= m_forward.value * mouse_y;
else
cmd->forwardmove -= m_forward.value * mouse_y;
}
}
 
void IN_Move (usercmd_t *cmd)
{
IN_MouseMove(cmd);
}
 
 
/*
================
VID_ModeInfo
================
*/
char *VID_ModeInfo (int modenum)
{
static char *badmodestr = "Bad mode number";
static char modestr[40];
 
if (modenum == 0)
{
sprintf (modestr, "%d x %d, %d bpp",
vid.width, vid.height, modes[current_mode].bytesperpixel*8);
return (modestr);
}
else
{
return (badmodestr);
}
}
 
/contrib/other/sdlquake-1.0.9/vid_vga.c
0,0 → 1,478
/*
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.
 
*/
//
// vid_vga.c: VGA-specific DOS video stuff
//
 
// TODO: proper handling of page-swap failure
 
#include <dos.h>
 
#include "quakedef.h"
#include "d_local.h"
#include "dosisms.h"
#include "vid_dos.h"
#include <dpmi.h>
 
extern regs_t regs;
 
int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes;
byte *VGA_pagebase;
vmode_t *VGA_pcurmode;
 
static int VGA_planar;
static int VGA_numpages;
static int VGA_buffersize;
 
void *vid_surfcache;
int vid_surfcachesize;
 
int VGA_highhunkmark;
 
#include "vgamodes.h"
 
#define NUMVIDMODES (sizeof(vgavidmodes) / sizeof(vgavidmodes[0]))
 
void VGA_UpdatePlanarScreen (void *srcbuffer);
 
static byte backingbuf[48*24];
 
/*
================
VGA_BeginDirectRect
================
*/
void VGA_BeginDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode, int x,
int y, byte *pbitmap, int width, int height)
{
int i, j, k, plane, reps, repshift;
 
if (!lvid->direct)
return;
 
if (lvid->aspect > 1.5)
{
reps = 2;
repshift = 1;
}
else
{
reps = 1;
repshift = 0;
}
 
if (pcurrentmode->planar)
{
for (plane=0 ; plane<4 ; plane++)
{
// select the correct plane for reading and writing
outportb (SC_INDEX, MAP_MASK);
outportb (SC_DATA, 1 << plane);
outportb (GC_INDEX, READ_MAP);
outportb (GC_DATA, plane);
 
for (i=0 ; i<(height << repshift) ; i += reps)
{
for (k=0 ; k<reps ; k++)
{
for (j=0 ; j<(width >> 2) ; j++)
{
backingbuf[(i + k) * 24 + (j << 2) + plane] =
lvid->direct[(y + i + k) * VGA_rowbytes +
(x >> 2) + j];
lvid->direct[(y + i + k) * VGA_rowbytes + (x>>2) + j] =
pbitmap[(i >> repshift) * 24 +
(j << 2) + plane];
}
}
}
}
}
else
{
for (i=0 ; i<(height << repshift) ; i += reps)
{
for (j=0 ; j<reps ; j++)
{
memcpy (&backingbuf[(i + j) * 24],
lvid->direct + x + ((y << repshift) + i + j) *
VGA_rowbytes,
width);
memcpy (lvid->direct + x + ((y << repshift) + i + j) *
VGA_rowbytes,
&pbitmap[(i >> repshift) * width],
width);
}
}
}
}
 
 
/*
================
VGA_EndDirectRect
================
*/
void VGA_EndDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode, int x,
int y, int width, int height)
{
int i, j, k, plane, reps, repshift;
 
if (!lvid->direct)
return;
 
if (lvid->aspect > 1.5)
{
reps = 2;
repshift = 1;
}
else
{
reps = 1;
repshift = 0;
}
 
if (pcurrentmode->planar)
{
for (plane=0 ; plane<4 ; plane++)
{
// select the correct plane for writing
outportb (SC_INDEX, MAP_MASK);
outportb (SC_DATA, 1 << plane);
 
for (i=0 ; i<(height << repshift) ; i += reps)
{
for (k=0 ; k<reps ; k++)
{
for (j=0 ; j<(width >> 2) ; j++)
{
lvid->direct[(y + i + k) * VGA_rowbytes + (x>>2) + j] =
backingbuf[(i + k) * 24 + (j << 2) + plane];
}
}
}
}
}
else
{
for (i=0 ; i<(height << repshift) ; i += reps)
{
for (j=0 ; j<reps ; j++)
{
memcpy (lvid->direct + x + ((y << repshift) + i + j) *
VGA_rowbytes,
&backingbuf[(i + j) * 24],
width);
}
}
}
}
 
 
/*
================
VGA_Init
================
*/
void VGA_Init (void)
{
int i;
 
// link together all the VGA modes
for (i=0 ; i<(NUMVIDMODES - 1) ; i++)
{
vgavidmodes[i].pnext = &vgavidmodes[i+1];
}
 
// add the VGA modes at the start of the mode list
vgavidmodes[NUMVIDMODES-1].pnext = pvidmodes;
pvidmodes = &vgavidmodes[0];
 
numvidmodes += NUMVIDMODES;
}
 
 
/*
================
VGA_WaitVsync
================
*/
void VGA_WaitVsync (void)
{
while ((inportb (0x3DA) & 0x08) == 0)
;
}
 
 
/*
================
VGA_ClearVideoMem
================
*/
void VGA_ClearVideoMem (int planar)
{
 
if (planar)
{
// enable all planes for writing
outportb (SC_INDEX, MAP_MASK);
outportb (SC_DATA, 0x0F);
}
 
Q_memset (VGA_pagebase, 0, VGA_rowbytes * VGA_height);
}
 
/*
================
VGA_FreeAndAllocVidbuffer
================
*/
qboolean VGA_FreeAndAllocVidbuffer (viddef_t *lvid, int allocnewbuffer)
{
int tsize, tbuffersize;
 
if (allocnewbuffer)
{
// alloc an extra line in case we want to wrap, and allocate the z-buffer
tbuffersize = (lvid->rowbytes * (lvid->height + 1)) +
(lvid->width * lvid->height * sizeof (*d_pzbuffer));
}
else
{
// just allocate the z-buffer
tbuffersize = lvid->width * lvid->height * sizeof (*d_pzbuffer);
}
 
tsize = D_SurfaceCacheForRes (lvid->width, lvid->height);
 
tbuffersize += tsize;
 
// see if there's enough memory, allowing for the normal mode 0x13 pixel,
// z, and surface buffers
if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 +
0x10000 * 3) < minimum_memory)
{
Con_Printf ("Not enough memory for video mode\n");
VGA_pcurmode = NULL; // so no further accesses to the buffer are
// attempted, particularly when clearing
return false; // not enough memory for mode
}
 
VGA_buffersize = tbuffersize;
vid_surfcachesize = tsize;
 
if (d_pzbuffer)
{
D_FlushCaches ();
Hunk_FreeToHighMark (VGA_highhunkmark);
d_pzbuffer = NULL;
}
 
VGA_highhunkmark = Hunk_HighMark ();
 
d_pzbuffer = Hunk_HighAllocName (VGA_buffersize, "video");
 
vid_surfcache = (byte *)d_pzbuffer
+ lvid->width * lvid->height * sizeof (*d_pzbuffer);
if (allocnewbuffer)
{
lvid->buffer = (void *)( (byte *)vid_surfcache + vid_surfcachesize);
lvid->conbuffer = lvid->buffer;
}
 
return true;
}
 
 
/*
================
VGA_CheckAdequateMem
================
*/
qboolean VGA_CheckAdequateMem (int width, int height, int rowbytes,
int allocnewbuffer)
{
int tbuffersize;
 
tbuffersize = width * height * sizeof (*d_pzbuffer);
 
if (allocnewbuffer)
{
// alloc an extra line in case we want to wrap, and allocate the z-buffer
tbuffersize += (rowbytes * (height + 1));
}
 
tbuffersize += D_SurfaceCacheForRes (width, height);
 
// see if there's enough memory, allowing for the normal mode 0x13 pixel,
// z, and surface buffers
if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 +
0x10000 * 3) < minimum_memory)
{
return false; // not enough memory for mode
}
 
return true;
}
 
 
/*
================
VGA_InitMode
================
*/
int VGA_InitMode (viddef_t *lvid, vmode_t *pcurrentmode)
{
vextra_t *pextra;
 
pextra = pcurrentmode->pextradata;
 
if (!VGA_FreeAndAllocVidbuffer (lvid, pextra->vidbuffer))
return -1; // memory alloc failed
 
if (VGA_pcurmode)
VGA_ClearVideoMem (VGA_pcurmode->planar);
 
// mode 0x13 is the base for all the Mode X-class mode sets
regs.h.ah = 0;
regs.h.al = 0x13;
dos_int86(0x10);
 
VGA_pagebase = (void *)real2ptr(0xa0000);
lvid->direct = (pixel_t *)VGA_pagebase;
 
// set additional registers as needed
VideoRegisterSet (pextra->pregset);
 
VGA_numpages = 1;
lvid->numpages = VGA_numpages;
 
VGA_width = (lvid->width + 0x1F) & ~0x1F;
VGA_height = lvid->height;
VGA_planar = pcurrentmode->planar;
if (VGA_planar)
VGA_rowbytes = lvid->rowbytes / 4;
else
VGA_rowbytes = lvid->rowbytes;
VGA_bufferrowbytes = lvid->rowbytes;
lvid->colormap = host_colormap;
lvid->fullbright = 256 - LittleLong (*((int *)lvid->colormap + 2048));
 
lvid->maxwarpwidth = WARP_WIDTH;
lvid->maxwarpheight = WARP_HEIGHT;
 
lvid->conbuffer = lvid->buffer;
lvid->conrowbytes = lvid->rowbytes;
lvid->conwidth = lvid->width;
lvid->conheight = lvid->height;
 
VGA_pcurmode = pcurrentmode;
 
VGA_ClearVideoMem (pcurrentmode->planar);
 
if (_vid_wait_override.value)
{
Cvar_SetValue ("vid_wait", (float)VID_WAIT_VSYNC);
}
else
{
Cvar_SetValue ("vid_wait", (float)VID_WAIT_NONE);
}
 
D_InitCaches (vid_surfcache, vid_surfcachesize);
 
return 1;
}
 
 
/*
================
VGA_SetPalette
================
*/
void VGA_SetPalette(viddef_t *lvid, vmode_t *pcurrentmode, unsigned char *pal)
{
int shiftcomponents=2;
int i;
 
UNUSED(lvid);
UNUSED(pcurrentmode);
 
dos_outportb(0x3c8, 0);
for (i=0 ; i<768 ; i++)
outportb(0x3c9, pal[i]>>shiftcomponents);
}
 
 
/*
================
VGA_SwapBuffersCopy
================
*/
void VGA_SwapBuffersCopy (viddef_t *lvid, vmode_t *pcurrentmode,
vrect_t *rects)
{
 
UNUSED(pcurrentmode);
 
// TODO: can write a dword at a time
// TODO: put in ASM
// TODO: copy only specified rectangles
if (VGA_planar)
{
 
// TODO: copy only specified rectangles
 
VGA_UpdatePlanarScreen (lvid->buffer);
}
else
{
while (rects)
{
VGA_UpdateLinearScreen (
lvid->buffer + rects->x + (rects->y * lvid->rowbytes),
VGA_pagebase + rects->x + (rects->y * VGA_rowbytes),
rects->width,
rects->height,
lvid->rowbytes,
VGA_rowbytes);
 
rects = rects->pnext;
}
}
}
 
 
/*
================
VGA_SwapBuffers
================
*/
void VGA_SwapBuffers (viddef_t *lvid, vmode_t *pcurrentmode, vrect_t *rects)
{
UNUSED(lvid);
 
if (vid_wait.value == VID_WAIT_VSYNC)
VGA_WaitVsync ();
 
VGA_SwapBuffersCopy (lvid, pcurrentmode, rects);
}
 
/contrib/other/sdlquake-1.0.9/vid_win.c
0,0 → 1,3343
/*
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.
 
*/
// vid_win.c -- Win32 video driver
 
#include "quakedef.h"
#include "winquake.h"
#include "d_local.h"
#include "resource.h"
 
#define MAX_MODE_LIST 30
#define VID_ROW_SIZE 3
 
qboolean dibonly;
 
extern int Minimized;
 
HWND mainwindow;
 
HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow);
 
int DIBWidth, DIBHeight;
qboolean DDActive;
RECT WindowRect;
DWORD WindowStyle, ExWindowStyle;
 
int window_center_x, window_center_y, window_x, window_y, window_width, window_height;
RECT window_rect;
 
static DEVMODE gdevmode;
static qboolean startwindowed = 0, windowed_mode_set;
static int firstupdate = 1;
static qboolean vid_initialized = false, vid_palettized;
static int lockcount;
static int vid_fulldib_on_focus_mode;
static qboolean force_minimized, in_mode_set, is_mode0x13, force_mode_set;
static int vid_stretched, windowed_mouse;
static qboolean palette_changed, syscolchg, vid_mode_set, hide_window, pal_is_nostatic;
static HICON hIcon;
 
viddef_t vid; // global video state
 
#define MODE_WINDOWED 0
#define MODE_SETTABLE_WINDOW 2
#define NO_MODE (MODE_WINDOWED - 1)
#define MODE_FULLSCREEN_DEFAULT (MODE_WINDOWED + 3)
 
// Note that 0 is MODE_WINDOWED
cvar_t vid_mode = {"vid_mode","0", false};
// Note that 0 is MODE_WINDOWED
cvar_t _vid_default_mode = {"_vid_default_mode","0", true};
// Note that 3 is MODE_FULLSCREEN_DEFAULT
cvar_t _vid_default_mode_win = {"_vid_default_mode_win","3", true};
cvar_t vid_wait = {"vid_wait","0"};
cvar_t vid_nopageflip = {"vid_nopageflip","0", true};
cvar_t _vid_wait_override = {"_vid_wait_override", "0", true};
cvar_t vid_config_x = {"vid_config_x","800", true};
cvar_t vid_config_y = {"vid_config_y","600", true};
cvar_t vid_stretch_by_2 = {"vid_stretch_by_2","1", true};
cvar_t _windowed_mouse = {"_windowed_mouse","0", true};
cvar_t vid_fullscreen_mode = {"vid_fullscreen_mode","3", true};
cvar_t vid_windowed_mode = {"vid_windowed_mode","0", true};
cvar_t block_switch = {"block_switch","0", true};
cvar_t vid_window_x = {"vid_window_x", "0", true};
cvar_t vid_window_y = {"vid_window_y", "0", true};
 
typedef struct {
int width;
int height;
} lmode_t;
 
lmode_t lowresmodes[] = {
{320, 200},
{320, 240},
{400, 300},
{512, 384},
};
 
int vid_modenum = NO_MODE;
int vid_testingmode, vid_realmode;
double vid_testendtime;
int vid_default = MODE_WINDOWED;
static int windowed_default;
 
modestate_t modestate = MS_UNINIT;
 
static byte *vid_surfcache;
static int vid_surfcachesize;
static int VID_highhunkmark;
 
unsigned char vid_curpal[256*3];
 
unsigned short d_8to16table[256];
unsigned d_8to24table[256];
 
int driver = grDETECT,mode;
bool useWinDirect = true, useDirectDraw = true;
MGLDC *mgldc = NULL,*memdc = NULL,*dibdc = NULL,*windc = NULL;
 
typedef struct {
modestate_t type;
int width;
int height;
int modenum;
int mode13;
int stretched;
int dib;
int fullscreen;
int bpp;
int halfscreen;
char modedesc[13];
} vmode_t;
 
static vmode_t modelist[MAX_MODE_LIST];
static int nummodes;
static vmode_t *pcurrentmode;
 
int aPage; // Current active display page
int vPage; // Current visible display page
int waitVRT = true; // True to wait for retrace on flip
 
static vmode_t badmode;
 
static byte backingbuf[48*24];
 
void VID_MenuDraw (void);
void VID_MenuKey (int key);
 
LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void AppActivate(BOOL fActive, BOOL minimize);
 
 
/*
================
VID_RememberWindowPos
================
*/
void VID_RememberWindowPos (void)
{
RECT rect;
 
if (GetWindowRect (mainwindow, &rect))
{
if ((rect.left < GetSystemMetrics (SM_CXSCREEN)) &&
(rect.top < GetSystemMetrics (SM_CYSCREEN)) &&
(rect.right > 0) &&
(rect.bottom > 0))
{
Cvar_SetValue ("vid_window_x", (float)rect.left);
Cvar_SetValue ("vid_window_y", (float)rect.top);
}
}
}
 
 
/*
================
VID_CheckWindowXY
================
*/
void VID_CheckWindowXY (void)
{
 
if (((int)vid_window_x.value > (GetSystemMetrics (SM_CXSCREEN) - 160)) ||
((int)vid_window_y.value > (GetSystemMetrics (SM_CYSCREEN) - 120)) ||
((int)vid_window_x.value < 0) ||
((int)vid_window_y.value < 0))
{
Cvar_SetValue ("vid_window_x", 0.0);
Cvar_SetValue ("vid_window_y", 0.0 );
}
}
 
 
/*
================
VID_UpdateWindowStatus
================
*/
void VID_UpdateWindowStatus (void)
{
 
window_rect.left = window_x;
window_rect.top = window_y;
window_rect.right = window_x + window_width;
window_rect.bottom = window_y + window_height;
window_center_x = (window_rect.left + window_rect.right) / 2;
window_center_y = (window_rect.top + window_rect.bottom) / 2;
 
IN_UpdateClipCursor ();
}
 
 
/*
================
ClearAllStates
================
*/
void ClearAllStates (void)
{
int i;
// send an up event for each key, to make sure the server clears them all
for (i=0 ; i<256 ; i++)
{
Key_Event (i, false);
}
 
Key_ClearStates ();
IN_ClearStates ();
}
 
 
/*
================
VID_CheckAdequateMem
================
*/
qboolean VID_CheckAdequateMem (int width, int height)
{
int tbuffersize;
 
tbuffersize = width * height * sizeof (*d_pzbuffer);
 
tbuffersize += D_SurfaceCacheForRes (width, height);
 
// see if there's enough memory, allowing for the normal mode 0x13 pixel,
// z, and surface buffers
if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 +
0x10000 * 3) < minimum_memory)
{
return false; // not enough memory for mode
}
 
return true;
}
 
 
/*
================
VID_AllocBuffers
================
*/
qboolean VID_AllocBuffers (int width, int height)
{
int tsize, tbuffersize;
 
tbuffersize = width * height * sizeof (*d_pzbuffer);
 
tsize = D_SurfaceCacheForRes (width, height);
 
tbuffersize += tsize;
 
// see if there's enough memory, allowing for the normal mode 0x13 pixel,
// z, and surface buffers
if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 +
0x10000 * 3) < minimum_memory)
{
Con_SafePrintf ("Not enough memory for video mode\n");
return false; // not enough memory for mode
}
 
vid_surfcachesize = tsize;
 
if (d_pzbuffer)
{
D_FlushCaches ();
Hunk_FreeToHighMark (VID_highhunkmark);
d_pzbuffer = NULL;
}
 
VID_highhunkmark = Hunk_HighMark ();
 
d_pzbuffer = Hunk_HighAllocName (tbuffersize, "video");
 
vid_surfcache = (byte *)d_pzbuffer +
width * height * sizeof (*d_pzbuffer);
return true;
}
 
 
void initFatalError(void)
{
MGL_exit();
MGL_fatalError(MGL_errorMsg(MGL_result()));
exit(EXIT_FAILURE);
}
 
 
int VID_Suspend (MGLDC *dc,m_int flags)
{
 
if (flags & MGL_DEACTIVATE)
{
// FIXME: this doesn't currently work on NT
if (block_switch.value && !WinNT)
{
return MGL_NO_DEACTIVATE;
}
 
S_BlockSound ();
S_ClearBuffer ();
 
IN_RestoreOriginalMouseState ();
CDAudio_Pause ();
 
// keep WM_PAINT from trying to redraw
in_mode_set = true;
 
block_drawing = true; // so we don't try to draw while switched away
 
return MGL_NO_SUSPEND_APP;
}
else if (flags & MGL_REACTIVATE)
{
IN_SetQuakeMouseState ();
// fix the leftover Alt from any Alt-Tab or the like that switched us away
ClearAllStates ();
CDAudio_Resume ();
S_UnblockSound ();
 
in_mode_set = false;
 
vid.recalc_refdef = 1;
 
block_drawing = false;
 
return MGL_NO_SUSPEND_APP;
}
 
}
 
 
void registerAllDispDrivers(void)
{
/* Event though these driver require WinDirect, we register
* them so that they will still be available even if DirectDraw
* is present and the user has disable the high performance
* WinDirect modes.
*/
MGL_registerDriver(MGL_VGA8NAME,VGA8_driver);
// MGL_registerDriver(MGL_VGAXNAME,VGAX_driver);
 
/* Register display drivers */
if (useWinDirect)
{
//we don't want VESA 1.X drivers MGL_registerDriver(MGL_SVGA8NAME,SVGA8_driver);
MGL_registerDriver(MGL_LINEAR8NAME,LINEAR8_driver);
 
if (!COM_CheckParm ("-novbeaf"))
MGL_registerDriver(MGL_ACCEL8NAME,ACCEL8_driver);
}
 
if (useDirectDraw)
{
MGL_registerDriver(MGL_DDRAW8NAME,DDRAW8_driver);
}
}
 
 
void registerAllMemDrivers(void)
{
/* Register memory context drivers */
MGL_registerDriver(MGL_PACKED8NAME,PACKED8_driver);
}
 
 
void VID_InitMGLFull (HINSTANCE hInstance)
{
int i, xRes, yRes, bits, vMode, lowres, curmode, temp;
int lowstretchedres, stretchedmode, lowstretched;
uchar *m;
 
// FIXME: NT is checked for because MGL currently has a bug that causes it
// to try to use WinDirect modes even on NT
if (COM_CheckParm("-nowindirect") ||
COM_CheckParm("-nowd") ||
COM_CheckParm("-novesa") ||
WinNT)
{
useWinDirect = false;
}
 
if (COM_CheckParm("-nodirectdraw") || COM_CheckParm("-noddraw") || COM_CheckParm("-nodd"))
useDirectDraw = false;
 
// Initialise the MGL
MGL_unregisterAllDrivers();
registerAllDispDrivers();
registerAllMemDrivers();
MGL_detectGraph(&driver,&mode);
m = MGL_availableModes();
 
if (m[0] != 0xFF)
{
lowres = lowstretchedres = 99999;
lowstretched = 0;
curmode = 0;
 
// find the lowest-res mode, or a mode we can stretch up to and get
// lowest-res that way
for (i = 0; m[i] != 0xFF; i++)
{
MGL_modeResolution(m[i], &xRes, &yRes,&bits);
 
if ((bits == 8) &&
(xRes <= MAXWIDTH) &&
(yRes <= MAXHEIGHT) &&
(curmode < MAX_MODE_LIST))
{
if (m[i] == grVGA_320x200x256)
is_mode0x13 = true;
 
if (!COM_CheckParm("-noforcevga"))
{
if (m[i] == grVGA_320x200x256)
{
mode = i;
break;
}
}
 
if (xRes < lowres)
{
lowres = xRes;
mode = i;
}
 
if ((xRes < lowstretchedres) && ((xRes >> 1) >= 320))
{
lowstretchedres = xRes >> 1;
stretchedmode = i;
}
}
 
curmode++;
}
 
// if there's a mode we can stretch by 2 up to, thereby effectively getting
// a lower-res mode than the lowest-res real but still at least 320x200, that
// will be our default mode
if (lowstretchedres < lowres)
{
mode = stretchedmode;
lowres = lowstretchedres;
lowstretched = 1;
}
 
// build the mode list, leaving room for the low-res stretched mode, if any
nummodes++; // leave room for default mode
 
for (i = 0; m[i] != 0xFF; i++)
{
MGL_modeResolution(m[i], &xRes, &yRes,&bits);
 
if ((bits == 8) &&
(xRes <= MAXWIDTH) &&
(yRes <= MAXHEIGHT) &&
(nummodes < MAX_MODE_LIST))
{
if (i == mode)
{
if (lowstretched)
{
stretchedmode = nummodes;
curmode = nummodes++;
}
else
{
curmode = MODE_FULLSCREEN_DEFAULT;
}
}
else
{
curmode = nummodes++;
}
 
modelist[curmode].type = MS_FULLSCREEN;
modelist[curmode].width = xRes;
modelist[curmode].height = yRes;
sprintf (modelist[curmode].modedesc, "%dx%d", xRes, yRes);
 
if (m[i] == grVGA_320x200x256)
modelist[curmode].mode13 = 1;
else
modelist[curmode].mode13 = 0;
 
modelist[curmode].modenum = m[i];
modelist[curmode].stretched = 0;
modelist[curmode].dib = 0;
modelist[curmode].fullscreen = 1;
modelist[curmode].halfscreen = 0;
modelist[curmode].bpp = 8;
}
}
 
if (lowstretched)
{
modelist[MODE_FULLSCREEN_DEFAULT] = modelist[stretchedmode];
modelist[MODE_FULLSCREEN_DEFAULT].stretched = 1;
modelist[MODE_FULLSCREEN_DEFAULT].width >>= 1;
modelist[MODE_FULLSCREEN_DEFAULT].height >>= 1;
sprintf (modelist[MODE_FULLSCREEN_DEFAULT].modedesc, "%dx%d",
modelist[MODE_FULLSCREEN_DEFAULT].width,
modelist[MODE_FULLSCREEN_DEFAULT].height);
}
 
vid_default = MODE_FULLSCREEN_DEFAULT;
 
temp = m[0];
 
if (!MGL_init(&driver, &temp, ""))
{
initFatalError();
}
}
 
MGL_setSuspendAppCallback(VID_Suspend);
}
 
 
MGLDC *createDisplayDC(int forcemem)
/****************************************************************************
*
* Function: createDisplayDC
* Returns: Pointer to the MGL device context to use for the application
*
* Description: Initialises the MGL and creates an appropriate display
* device context to be used by the GUI. This creates and
* apropriate device context depending on the system being
* compile for, and should be the only place where system
* specific code is required.
*
****************************************************************************/
{
MGLDC *dc;
pixel_format_t pf;
int npages;
 
// Start the specified video mode
if (!MGL_changeDisplayMode(mode))
initFatalError();
 
npages = MGL_availablePages(mode);
 
if (npages > 3)
npages = 3;
 
if (!COM_CheckParm ("-notriplebuf"))
{
if (npages > 2)
{
npages = 2;
}
}
 
if ((dc = MGL_createDisplayDC(npages)) == NULL)
return NULL;
 
if (!forcemem && (MGL_surfaceAccessType(dc)) == MGL_LINEAR_ACCESS && (dc->mi.maxPage > 0))
{
MGL_makeCurrentDC(dc);
memdc = NULL;
}
else
{
// Set up for blitting from a memory buffer
memdc = MGL_createMemoryDC(MGL_sizex(dc)+1,MGL_sizey(dc)+1,8,&pf);
MGL_makeCurrentDC(memdc);
}
 
// Enable page flipping even for even for blitted surfaces
if (forcemem)
{
vid.numpages = 1;
}
else
{
vid.numpages = dc->mi.maxPage + 1;
 
if (vid.numpages > 1)
{
// Set up for page flipping
MGL_setActivePage(dc, aPage = 1);
MGL_setVisualPage(dc, vPage = 0, false);
}
 
if (vid.numpages > 3)
vid.numpages = 3;
}
 
if (vid.numpages == 2)
waitVRT = true;
else
waitVRT = false;
 
return dc;
}
 
 
void VID_InitMGLDIB (HINSTANCE hInstance)
{
WNDCLASS wc;
HDC hdc;
int i;
 
hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_ICON2));
 
/* Register the frame class */
wc.style = 0;
wc.lpfnWndProc = (WNDPROC)MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = 0;
wc.hCursor = LoadCursor (NULL,IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = 0;
wc.lpszClassName = "WinQuake";
 
if (!RegisterClass (&wc) )
Sys_Error ("Couldn't register window class");
 
/* Find the size for the DIB window */
/* Initialise the MGL for windowed operation */
MGL_setAppInstance(hInstance);
registerAllMemDrivers();
MGL_initWindowed("");
 
modelist[0].type = MS_WINDOWED;
modelist[0].width = 320;
modelist[0].height = 240;
strcpy (modelist[0].modedesc, "320x240");
modelist[0].mode13 = 0;
modelist[0].modenum = MODE_WINDOWED;
modelist[0].stretched = 0;
modelist[0].dib = 1;
modelist[0].fullscreen = 0;
modelist[0].halfscreen = 0;
modelist[0].bpp = 8;
 
modelist[1].type = MS_WINDOWED;
modelist[1].width = 640;
modelist[1].height = 480;
strcpy (modelist[1].modedesc, "640x480");
modelist[1].mode13 = 0;
modelist[1].modenum = MODE_WINDOWED + 1;
modelist[1].stretched = 1;
modelist[1].dib = 1;
modelist[1].fullscreen = 0;
modelist[1].halfscreen = 0;
modelist[1].bpp = 8;
 
modelist[2].type = MS_WINDOWED;
modelist[2].width = 800;
modelist[2].height = 600;
strcpy (modelist[2].modedesc, "800x600");
modelist[2].mode13 = 0;
modelist[2].modenum = MODE_WINDOWED + 2;
modelist[2].stretched = 1;
modelist[2].dib = 1;
modelist[2].fullscreen = 0;
modelist[2].halfscreen = 0;
modelist[2].bpp = 8;
 
// automatically stretch the default mode up if > 640x480 desktop resolution
hdc = GetDC(NULL);
 
if ((GetDeviceCaps(hdc, HORZRES) > 640) && !COM_CheckParm("-noautostretch"))
{
vid_default = MODE_WINDOWED + 1;
}
else
{
vid_default = MODE_WINDOWED;
}
 
windowed_default = vid_default;
 
ReleaseDC(NULL,hdc);
 
nummodes = 3; // reserve space for windowed mode
 
DDActive = 0;
}
 
 
/*
=================
VID_InitFullDIB
=================
*/
void VID_InitFullDIB (HINSTANCE hInstance)
{
DEVMODE devmode;
int i, j, modenum, cmodes, existingmode, originalnummodes, lowestres;
int numlowresmodes, bpp, done;
int cstretch, istretch, mstretch;
BOOL stat;
 
// enumerate 8 bpp modes
originalnummodes = nummodes;
modenum = 0;
lowestres = 99999;
 
do
{
stat = EnumDisplaySettings (NULL, modenum, &devmode);
 
if ((devmode.dmBitsPerPel == 8) &&
(devmode.dmPelsWidth <= MAXWIDTH) &&
(devmode.dmPelsHeight <= MAXHEIGHT) &&
(nummodes < MAX_MODE_LIST))
{
devmode.dmFields = DM_BITSPERPEL |
DM_PELSWIDTH |
DM_PELSHEIGHT;
 
if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
DISP_CHANGE_SUCCESSFUL)
{
modelist[nummodes].type = MS_FULLDIB;
modelist[nummodes].width = devmode.dmPelsWidth;
modelist[nummodes].height = devmode.dmPelsHeight;
modelist[nummodes].modenum = 0;
modelist[nummodes].mode13 = 0;
modelist[nummodes].stretched = 0;
modelist[nummodes].halfscreen = 0;
modelist[nummodes].dib = 1;
modelist[nummodes].fullscreen = 1;
modelist[nummodes].bpp = devmode.dmBitsPerPel;
sprintf (modelist[nummodes].modedesc, "%dx%d",
devmode.dmPelsWidth, devmode.dmPelsHeight);
 
// if the width is more than twice the height, reduce it by half because this
// is probably a dual-screen monitor
if (!COM_CheckParm("-noadjustaspect"))
{
if (modelist[nummodes].width > (modelist[nummodes].height << 1))
{
modelist[nummodes].width >>= 1;
modelist[nummodes].halfscreen = 1;
sprintf (modelist[nummodes].modedesc, "%dx%d",
modelist[nummodes].width,
modelist[nummodes].height);
}
}
 
for (i=originalnummodes, existingmode = 0 ; i<nummodes ; i++)
{
if ((modelist[nummodes].width == modelist[i].width) &&
(modelist[nummodes].height == modelist[i].height))
{
existingmode = 1;
break;
}
}
 
if (!existingmode)
{
if (modelist[nummodes].width < lowestres)
lowestres = modelist[nummodes].width;
 
nummodes++;
}
}
}
 
modenum++;
} while (stat);
 
// see if any of them were actually settable; if so, this is our mode list,
// else enumerate all modes; our mode list is whichever ones are settable
// with > 8 bpp
if (nummodes == originalnummodes)
{
modenum = 0;
lowestres = 99999;
 
Con_SafePrintf ("No 8-bpp fullscreen DIB modes found\n");
 
do
{
stat = EnumDisplaySettings (NULL, modenum, &devmode);
 
if ((((devmode.dmPelsWidth <= MAXWIDTH) &&
(devmode.dmPelsHeight <= MAXHEIGHT)) ||
(!COM_CheckParm("-noadjustaspect") &&
(devmode.dmPelsWidth <= (MAXWIDTH*2)) &&
(devmode.dmPelsWidth > (devmode.dmPelsHeight*2)))) &&
(nummodes < MAX_MODE_LIST) &&
(devmode.dmBitsPerPel > 8))
{
devmode.dmFields = DM_BITSPERPEL |
DM_PELSWIDTH |
DM_PELSHEIGHT;
 
if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
DISP_CHANGE_SUCCESSFUL)
{
modelist[nummodes].type = MS_FULLDIB;
modelist[nummodes].width = devmode.dmPelsWidth;
modelist[nummodes].height = devmode.dmPelsHeight;
modelist[nummodes].modenum = 0;
modelist[nummodes].mode13 = 0;
modelist[nummodes].stretched = 0;
modelist[nummodes].halfscreen = 0;
modelist[nummodes].dib = 1;
modelist[nummodes].fullscreen = 1;
modelist[nummodes].bpp = devmode.dmBitsPerPel;
sprintf (modelist[nummodes].modedesc, "%dx%d",
devmode.dmPelsWidth, devmode.dmPelsHeight);
 
// if the width is more than twice the height, reduce it by half because this
// is probably a dual-screen monitor
if (!COM_CheckParm("-noadjustaspect"))
{
if (modelist[nummodes].width > (modelist[nummodes].height*2))
{
modelist[nummodes].width >>= 1;
modelist[nummodes].halfscreen = 1;
sprintf (modelist[nummodes].modedesc, "%dx%d",
modelist[nummodes].width,
modelist[nummodes].height);
}
}
 
for (i=originalnummodes, existingmode = 0 ; i<nummodes ; i++)
{
if ((modelist[nummodes].width == modelist[i].width) &&
(modelist[nummodes].height == modelist[i].height))
{
// pick the lowest available bpp
if (modelist[nummodes].bpp < modelist[i].bpp)
modelist[i] = modelist[nummodes];
 
existingmode = 1;
break;
}
}
 
if (!existingmode)
{
if (modelist[nummodes].width < lowestres)
lowestres = modelist[nummodes].width;
 
nummodes++;
}
}
}
 
modenum++;
} while (stat);
}
 
// see if there are any low-res modes that aren't being reported
numlowresmodes = sizeof(lowresmodes) / sizeof(lowresmodes[0]);
bpp = 8;
done = 0;
 
// first make sure the driver doesn't just answer yes to all tests
devmode.dmBitsPerPel = 8;
devmode.dmPelsWidth = 42;
devmode.dmPelsHeight = 37;
devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
 
if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
DISP_CHANGE_SUCCESSFUL)
{
done = 1;
}
 
while (!done)
{
for (j=0 ; (j<numlowresmodes) && (nummodes < MAX_MODE_LIST) ; j++)
{
devmode.dmBitsPerPel = bpp;
devmode.dmPelsWidth = lowresmodes[j].width;
devmode.dmPelsHeight = lowresmodes[j].height;
devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
 
if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
DISP_CHANGE_SUCCESSFUL)
{
modelist[nummodes].type = MS_FULLDIB;
modelist[nummodes].width = devmode.dmPelsWidth;
modelist[nummodes].height = devmode.dmPelsHeight;
modelist[nummodes].modenum = 0;
modelist[nummodes].mode13 = 0;
modelist[nummodes].stretched = 0;
modelist[nummodes].halfscreen = 0;
modelist[nummodes].dib = 1;
modelist[nummodes].fullscreen = 1;
modelist[nummodes].bpp = devmode.dmBitsPerPel;
sprintf (modelist[nummodes].modedesc, "%dx%d",
devmode.dmPelsWidth, devmode.dmPelsHeight);
 
// we only want the lowest-bpp version of each mode
for (i=originalnummodes, existingmode = 0 ; i<nummodes ; i++)
{
if ((modelist[nummodes].width == modelist[i].width) &&
(modelist[nummodes].height == modelist[i].height) &&
(modelist[nummodes].bpp >= modelist[i].bpp))
{
existingmode = 1;
break;
}
}
 
if (!existingmode)
{
if (modelist[nummodes].width < lowestres)
lowestres = modelist[nummodes].width;
 
nummodes++;
}
}
}
 
switch (bpp)
{
case 8:
bpp = 16;
break;
 
case 16:
bpp = 32;
break;
 
case 32:
done = 1;
break;
}
}
 
// now add the lowest stretch-by-2 pseudo-modes between 320-wide
// (inclusive) and lowest real res (not inclusive)
// don't bother if we have a real VGA mode 0x13 mode
if (!is_mode0x13)
{
for (i=originalnummodes, cstretch=0 ; i<nummodes ; i++)
{
if (((modelist[i].width >> 1) < lowestres) &&
((modelist[i].width >> 1) >= 320))
{
lowestres = modelist[i].width >> 1;
cstretch = 1;
mstretch = i;
}
}
 
if ((nummodes + cstretch) > MAX_MODE_LIST)
cstretch = MAX_MODE_LIST - nummodes;
 
if (cstretch > 0)
{
for (i=(nummodes-1) ; i>=originalnummodes ; i--)
modelist[i+cstretch] = modelist[i];
 
nummodes += cstretch;
istretch = originalnummodes;
 
modelist[istretch] = modelist[mstretch];
modelist[istretch].width >>= 1;
modelist[istretch].height >>= 1;
modelist[istretch].stretched = 1;
sprintf (modelist[istretch].modedesc, "%dx%d",
modelist[istretch].width, modelist[istretch].height);
}
}
 
if (nummodes != originalnummodes)
vid_default = MODE_FULLSCREEN_DEFAULT;
else
Con_SafePrintf ("No fullscreen DIB modes found\n");
}
 
 
/*
=================
VID_NumModes
=================
*/
int VID_NumModes (void)
{
return nummodes;
}
 
/*
=================
VID_GetModePtr
=================
*/
vmode_t *VID_GetModePtr (int modenum)
{
 
if ((modenum >= 0) && (modenum < nummodes))
return &modelist[modenum];
else
return &badmode;
}
 
 
/*
=================
VID_CheckModedescFixup
=================
*/
void VID_CheckModedescFixup (int mode)
{
int x, y, stretch;
 
if (mode == MODE_SETTABLE_WINDOW)
{
modelist[mode].stretched = (int)vid_stretch_by_2.value;
stretch = modelist[mode].stretched;
 
if (vid_config_x.value < (320 << stretch))
vid_config_x.value = 320 << stretch;
 
if (vid_config_y.value < (200 << stretch))
vid_config_y.value = 200 << stretch;
 
x = (int)vid_config_x.value;
y = (int)vid_config_y.value;
sprintf (modelist[mode].modedesc, "%dx%d", x, y);
modelist[mode].width = x;
modelist[mode].height = y;
}
}
 
 
/*
=================
VID_GetModeDescriptionMemCheck
=================
*/
char *VID_GetModeDescriptionMemCheck (int mode)
{
char *pinfo;
vmode_t *pv;
 
if ((mode < 0) || (mode >= nummodes))
return NULL;
 
VID_CheckModedescFixup (mode);
 
pv = VID_GetModePtr (mode);
pinfo = pv->modedesc;
 
if (VID_CheckAdequateMem (pv->width, pv->height))
{
return pinfo;
}
else
{
return NULL;
}
}
 
 
/*
=================
VID_GetModeDescription
=================
*/
char *VID_GetModeDescription (int mode)
{
char *pinfo;
vmode_t *pv;
 
if ((mode < 0) || (mode >= nummodes))
return NULL;
 
VID_CheckModedescFixup (mode);
 
pv = VID_GetModePtr (mode);
pinfo = pv->modedesc;
return pinfo;
}
 
 
/*
=================
VID_GetModeDescription2
 
Tacks on "windowed" or "fullscreen"
=================
*/
char *VID_GetModeDescription2 (int mode)
{
static char pinfo[40];
vmode_t *pv;
 
if ((mode < 0) || (mode >= nummodes))
return NULL;
 
VID_CheckModedescFixup (mode);
 
pv = VID_GetModePtr (mode);
 
if (modelist[mode].type == MS_FULLSCREEN)
{
sprintf(pinfo,"%s fullscreen", pv->modedesc);
}
else if (modelist[mode].type == MS_FULLDIB)
{
sprintf(pinfo,"%s fullscreen", pv->modedesc);
}
else
{
sprintf(pinfo, "%s windowed", pv->modedesc);
}
 
return pinfo;
}
 
 
// KJB: Added this to return the mode driver name in description for console
 
char *VID_GetExtModeDescription (int mode)
{
static char pinfo[40];
vmode_t *pv;
 
if ((mode < 0) || (mode >= nummodes))
return NULL;
 
VID_CheckModedescFixup (mode);
 
pv = VID_GetModePtr (mode);
if (modelist[mode].type == MS_FULLSCREEN)
{
sprintf(pinfo,"%s fullscreen %s",pv->modedesc,
MGL_modeDriverName(pv->modenum));
}
else if (modelist[mode].type == MS_FULLDIB)
{
sprintf(pinfo,"%s fullscreen DIB", pv->modedesc);
}
else
{
sprintf(pinfo, "%s windowed", pv->modedesc);
}
 
return pinfo;
}
 
 
void DestroyDIBWindow (void)
{
 
if (modestate == MS_WINDOWED)
{
// destroy the associated MGL DC's; the window gets reused
if (windc)
MGL_destroyDC(windc);
if (dibdc)
MGL_destroyDC(dibdc);
windc = dibdc = NULL;
}
}
 
 
void DestroyFullscreenWindow (void)
{
 
if (modestate == MS_FULLSCREEN)
{
// destroy the existing fullscreen mode and DC's
if (mgldc)
MGL_destroyDC (mgldc);
if (memdc)
MGL_destroyDC (memdc);
mgldc = memdc = NULL;
}
}
 
 
 
void DestroyFullDIBWindow (void)
{
if (modestate == MS_FULLDIB)
{
ChangeDisplaySettings (NULL, CDS_FULLSCREEN);
 
// Destroy the fullscreen DIB window and associated MGL DC's
if (windc)
MGL_destroyDC(windc);
if (dibdc)
MGL_destroyDC(dibdc);
windc = dibdc = NULL;
}
}
 
 
qboolean VID_SetWindowedMode (int modenum)
{
HDC hdc;
pixel_format_t pf;
qboolean stretched;
int lastmodestate;
LONG wlong;
 
if (!windowed_mode_set)
{
if (COM_CheckParm ("-resetwinpos"))
{
Cvar_SetValue ("vid_window_x", 0.0);
Cvar_SetValue ("vid_window_y", 0.0);
}
 
windowed_mode_set;
}
 
VID_CheckModedescFixup (modenum);
 
DDActive = 0;
lastmodestate = modestate;
 
DestroyFullscreenWindow ();
DestroyFullDIBWindow ();
 
if (windc)
MGL_destroyDC(windc);
if (dibdc)
MGL_destroyDC(dibdc);
windc = dibdc = NULL;
 
// KJB: Signal to the MGL that we are going back to windowed mode
if (!MGL_changeDisplayMode(grWINDOWED))
initFatalError();
 
WindowRect.top = WindowRect.left = 0;
 
WindowRect.right = modelist[modenum].width;
WindowRect.bottom = modelist[modenum].height;
stretched = modelist[modenum].stretched;
 
DIBWidth = modelist[modenum].width;
DIBHeight = modelist[modenum].height;
 
if (stretched)
{
DIBWidth >>= 1;
DIBHeight >>= 1;
}
 
WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU |
WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN;
ExWindowStyle = 0;
AdjustWindowRectEx(&WindowRect, WindowStyle, FALSE, 0);
 
// the first time we're called to set the mode, create the window we'll use
// for the rest of the session
if (!vid_mode_set)
{
mainwindow = CreateWindowEx (
ExWindowStyle,
"WinQuake",
"WinQuake",
WindowStyle,
0, 0,
WindowRect.right - WindowRect.left,
WindowRect.bottom - WindowRect.top,
NULL,
NULL,
global_hInstance,
NULL);
 
if (!mainwindow)
Sys_Error ("Couldn't create DIB window");
 
// tell MGL to use this window for fullscreen modes
MGL_registerFullScreenWindow (mainwindow);
 
vid_mode_set = true;
}
else
{
SetWindowLong(mainwindow, GWL_STYLE, WindowStyle | WS_VISIBLE);
SetWindowLong(mainwindow, GWL_EXSTYLE, ExWindowStyle);
}
 
if (!SetWindowPos (mainwindow,
NULL,
0, 0,
WindowRect.right - WindowRect.left,
WindowRect.bottom - WindowRect.top,
SWP_NOCOPYBITS | SWP_NOZORDER |
SWP_HIDEWINDOW))
{
Sys_Error ("Couldn't resize DIB window");
}
 
if (hide_window)
return true;
 
// position and show the DIB window
VID_CheckWindowXY ();
SetWindowPos (mainwindow, NULL, (int)vid_window_x.value,
(int)vid_window_y.value, 0, 0,
SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME);
 
if (force_minimized)
ShowWindow (mainwindow, SW_MINIMIZE);
else
ShowWindow (mainwindow, SW_SHOWDEFAULT);
 
UpdateWindow (mainwindow);
 
modestate = MS_WINDOWED;
vid_fulldib_on_focus_mode = 0;
 
// because we have set the background brush for the window to NULL
// (to avoid flickering when re-sizing the window on the desktop),
// we clear the window to black when created, otherwise it will be
// empty while Quake starts up.
hdc = GetDC(mainwindow);
PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS);
ReleaseDC(mainwindow, hdc);
 
/* Create the MGL window DC and the MGL memory DC */
if ((windc = MGL_createWindowedDC(mainwindow)) == NULL)
MGL_fatalError("Unable to create Windowed DC!");
 
if ((dibdc = MGL_createMemoryDC(DIBWidth,DIBHeight,8,&pf)) == NULL)
MGL_fatalError("Unable to create Memory DC!");
 
MGL_makeCurrentDC(dibdc);
 
vid.buffer = vid.conbuffer = vid.direct = dibdc->surface;
vid.rowbytes = vid.conrowbytes = dibdc->mi.bytesPerLine;
vid.numpages = 1;
vid.maxwarpwidth = WARP_WIDTH;
vid.maxwarpheight = WARP_HEIGHT;
vid.height = vid.conheight = DIBHeight;
vid.width = vid.conwidth = DIBWidth;
vid.aspect = ((float)vid.height / (float)vid.width) *
(320.0 / 240.0);
 
vid_stretched = stretched;
 
SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon);
SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon);
 
return true;
}
 
 
qboolean VID_SetFullscreenMode (int modenum)
{
 
DDActive = 1;
 
DestroyDIBWindow ();
DestroyFullDIBWindow ();
 
mode = modelist[modenum].modenum;
 
// Destroy old DC's, resetting back to fullscreen mode
if (mgldc)
MGL_destroyDC (mgldc);
if (memdc)
MGL_destroyDC (memdc);
mgldc = memdc = NULL;
 
if ((mgldc = createDisplayDC (modelist[modenum].stretched ||
(int)vid_nopageflip.value)) == NULL)
{
return false;
}
 
modestate = MS_FULLSCREEN;
vid_fulldib_on_focus_mode = 0;
 
vid.buffer = vid.conbuffer = vid.direct = NULL;
vid.maxwarpwidth = WARP_WIDTH;
vid.maxwarpheight = WARP_HEIGHT;
DIBHeight = vid.height = vid.conheight = modelist[modenum].height;
DIBWidth = vid.width = vid.conwidth = modelist[modenum].width;
vid.aspect = ((float)vid.height / (float)vid.width) *
(320.0 / 240.0);
 
vid_stretched = modelist[modenum].stretched;
 
// needed because we're not getting WM_MOVE messages fullscreen on NT
window_x = 0;
window_y = 0;
 
// set the large icon, so the Quake icon will show up in the taskbar
SendMessage (mainwindow, WM_SETICON, (WPARAM)1, (LPARAM)hIcon);
SendMessage (mainwindow, WM_SETICON, (WPARAM)0, (LPARAM)hIcon);
 
// shouldn't be needed, but Kendall needs to let us get the activation
// message for this not to be needed on NT
AppActivate (true, false);
 
return true;
}
 
 
qboolean VID_SetFullDIBMode (int modenum)
{
HDC hdc;
pixel_format_t pf;
int lastmodestate;
 
DDActive = 0;
 
DestroyFullscreenWindow ();
DestroyDIBWindow ();
 
if (windc)
MGL_destroyDC(windc);
if (dibdc)
MGL_destroyDC(dibdc);
windc = dibdc = NULL;
 
// KJB: Signal to the MGL that we are going back to windowed mode
if (!MGL_changeDisplayMode(grWINDOWED))
initFatalError();
 
gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
gdevmode.dmBitsPerPel = modelist[modenum].bpp;
gdevmode.dmPelsWidth = modelist[modenum].width << modelist[modenum].stretched <<
modelist[modenum].halfscreen;
gdevmode.dmPelsHeight = modelist[modenum].height << modelist[modenum].stretched;
gdevmode.dmSize = sizeof (gdevmode);
 
if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
Sys_Error ("Couldn't set fullscreen DIB mode");
 
lastmodestate = modestate;
modestate = MS_FULLDIB;
vid_fulldib_on_focus_mode = modenum;
 
WindowRect.top = WindowRect.left = 0;
 
hdc = GetDC(NULL);
 
WindowRect.right = modelist[modenum].width << modelist[modenum].stretched;
WindowRect.bottom = modelist[modenum].height << modelist[modenum].stretched;
 
ReleaseDC(NULL,hdc);
 
DIBWidth = modelist[modenum].width;
DIBHeight = modelist[modenum].height;
 
WindowStyle = WS_POPUP | WS_SYSMENU | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
ExWindowStyle = 0;
AdjustWindowRectEx(&WindowRect, WindowStyle, FALSE, 0);
 
SetWindowLong(mainwindow, GWL_STYLE, WindowStyle | WS_VISIBLE);
SetWindowLong(mainwindow, GWL_EXSTYLE, ExWindowStyle);
 
if (!SetWindowPos (mainwindow,
NULL,
0, 0,
WindowRect.right - WindowRect.left,
WindowRect.bottom - WindowRect.top,
SWP_NOCOPYBITS | SWP_NOZORDER))
{
Sys_Error ("Couldn't resize DIB window");
}
 
// position and show the DIB window
SetWindowPos (mainwindow, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOSIZE | SWP_SHOWWINDOW | SWP_DRAWFRAME);
ShowWindow (mainwindow, SW_SHOWDEFAULT);
UpdateWindow (mainwindow);
 
// Because we have set the background brush for the window to NULL
// (to avoid flickering when re-sizing the window on the desktop), we
// clear the window to black when created, otherwise it will be
// empty while Quake starts up.
hdc = GetDC(mainwindow);
PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS);
ReleaseDC(mainwindow, hdc);
 
/* Create the MGL window DC and the MGL memory DC */
if ((windc = MGL_createWindowedDC(mainwindow)) == NULL)
MGL_fatalError("Unable to create Fullscreen DIB DC!");
 
if ((dibdc = MGL_createMemoryDC(DIBWidth,DIBHeight,8,&pf)) == NULL)
MGL_fatalError("Unable to create Memory DC!");
 
MGL_makeCurrentDC(dibdc);
 
vid.buffer = vid.conbuffer = vid.direct = dibdc->surface;
vid.rowbytes = vid.conrowbytes = dibdc->mi.bytesPerLine;
vid.numpages = 1;
vid.maxwarpwidth = WARP_WIDTH;
vid.maxwarpheight = WARP_HEIGHT;
vid.height = vid.conheight = DIBHeight;
vid.width = vid.conwidth = DIBWidth;
vid.aspect = ((float)vid.height / (float)vid.width) *
(320.0 / 240.0);
 
vid_stretched = modelist[modenum].stretched;
 
// needed because we're not getting WM_MOVE messages fullscreen on NT
window_x = 0;
window_y = 0;
 
return true;
}
 
 
void VID_RestoreOldMode (int original_mode)
{
static qboolean inerror = false;
 
if (inerror)
return;
 
in_mode_set = false;
inerror = true;
 
// make sure mode set happens (video mode changes)
vid_modenum = original_mode - 1;
 
if (!VID_SetMode (original_mode, vid_curpal))
{
vid_modenum = MODE_WINDOWED - 1;
 
if (!VID_SetMode (windowed_default, vid_curpal))
Sys_Error ("Can't set any video mode");
}
 
inerror = false;
}
 
 
void VID_SetDefaultMode (void)
{
 
if (vid_initialized)
VID_SetMode (0, vid_curpal);
 
IN_DeactivateMouse ();
}
 
 
int VID_SetMode (int modenum, unsigned char *palette)
{
int original_mode, temp, dummy;
qboolean stat;
MSG msg;
HDC hdc;
 
while ((modenum >= nummodes) || (modenum < 0))
{
if (vid_modenum == NO_MODE)
{
if (modenum == vid_default)
{
modenum = windowed_default;
}
else
{
modenum = vid_default;
}
 
Cvar_SetValue ("vid_mode", (float)modenum);
}
else
{
Cvar_SetValue ("vid_mode", (float)vid_modenum);
return 0;
}
}
 
if (!force_mode_set && (modenum == vid_modenum))
return true;
 
// so Con_Printfs don't mess us up by forcing vid and snd updates
temp = scr_disabled_for_loading;
scr_disabled_for_loading = true;
in_mode_set = true;
 
CDAudio_Pause ();
S_ClearBuffer ();
 
if (vid_modenum == NO_MODE)
original_mode = windowed_default;
else
original_mode = vid_modenum;
 
// Set either the fullscreen or windowed mode
if (modelist[modenum].type == MS_WINDOWED)
{
if (_windowed_mouse.value)
{
stat = VID_SetWindowedMode(modenum);
IN_ActivateMouse ();
IN_HideMouse ();
}
else
{
IN_DeactivateMouse ();
IN_ShowMouse ();
stat = VID_SetWindowedMode(modenum);
}
}
else if (modelist[modenum].type == MS_FULLDIB)
{
stat = VID_SetFullDIBMode(modenum);
IN_ActivateMouse ();
IN_HideMouse ();
}
else
{
stat = VID_SetFullscreenMode(modenum);
IN_ActivateMouse ();
IN_HideMouse ();
}
 
window_width = vid.width << vid_stretched;
window_height = vid.height << vid_stretched;
VID_UpdateWindowStatus ();
 
CDAudio_Resume ();
scr_disabled_for_loading = temp;
 
if (!stat)
{
VID_RestoreOldMode (original_mode);
return false;
}
 
if (hide_window)
return true;
 
// now we try to make sure we get the focus on the mode switch, because
// sometimes in some systems we don't. We grab the foreground, then
// finish setting up, pump all our messages, and sleep for a little while
// to let messages finish bouncing around the system, then we put
// ourselves at the top of the z order, then grab the foreground again,
// Who knows if it helps, but it probably doesn't hurt
if (!force_minimized)
SetForegroundWindow (mainwindow);
 
hdc = GetDC(NULL);
 
if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
vid_palettized = true;
else
vid_palettized = false;
 
VID_SetPalette (palette);
 
ReleaseDC(NULL,hdc);
 
vid_modenum = modenum;
Cvar_SetValue ("vid_mode", (float)vid_modenum);
 
if (!VID_AllocBuffers (vid.width, vid.height))
{
// couldn't get memory for this mode; try to fall back to previous mode
VID_RestoreOldMode (original_mode);
return false;
}
 
D_InitCaches (vid_surfcache, vid_surfcachesize);
 
while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
 
Sleep (100);
 
if (!force_minimized)
{
SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0,
SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW |
SWP_NOCOPYBITS);
 
SetForegroundWindow (mainwindow);
}
 
// fix the leftover Alt from any Alt-Tab or the like that switched us away
ClearAllStates ();
 
if (!msg_suppress_1)
Con_SafePrintf ("%s\n", VID_GetModeDescription (vid_modenum));
 
VID_SetPalette (palette);
 
in_mode_set = false;
vid.recalc_refdef = 1;
 
return true;
}
 
void VID_LockBuffer (void)
{
 
if (dibdc)
return;
 
lockcount++;
 
if (lockcount > 1)
return;
 
MGL_beginDirectAccess();
 
if (memdc)
{
// Update surface pointer for linear access modes
vid.buffer = vid.conbuffer = vid.direct = memdc->surface;
vid.rowbytes = vid.conrowbytes = memdc->mi.bytesPerLine;
}
else if (mgldc)
{
// Update surface pointer for linear access modes
vid.buffer = vid.conbuffer = vid.direct = mgldc->surface;
vid.rowbytes = vid.conrowbytes = mgldc->mi.bytesPerLine;
}
 
if (r_dowarp)
d_viewbuffer = r_warpbuffer;
else
d_viewbuffer = (void *)(byte *)vid.buffer;
 
if (r_dowarp)
screenwidth = WARP_WIDTH;
else
screenwidth = vid.rowbytes;
 
if (lcd_x.value)
screenwidth <<= 1;
}
void VID_UnlockBuffer (void)
{
if (dibdc)
return;
 
lockcount--;
 
if (lockcount > 0)
return;
 
if (lockcount < 0)
Sys_Error ("Unbalanced unlock");
 
MGL_endDirectAccess();
 
// to turn up any unlocked accesses
vid.buffer = vid.conbuffer = vid.direct = d_viewbuffer = NULL;
 
}
 
 
int VID_ForceUnlockedAndReturnState (void)
{
int lk;
 
if (!lockcount)
return 0;
 
lk = lockcount;
 
if (dibdc)
{
lockcount = 0;
}
else
{
lockcount = 1;
VID_UnlockBuffer ();
}
 
return lk;
}
 
 
void VID_ForceLockState (int lk)
{
 
if (!dibdc && lk)
{
lockcount = 0;
VID_LockBuffer ();
}
 
lockcount = lk;
}
 
 
void VID_SetPalette (unsigned char *palette)
{
INT i;
palette_t pal[256];
HDC hdc;
 
if (!Minimized)
{
palette_changed = true;
 
// make sure we have the static colors if we're the active app
hdc = GetDC(NULL);
 
if (vid_palettized && ActiveApp)
{
if (GetSystemPaletteUse(hdc) == SYSPAL_STATIC)
{
// switch to SYSPAL_NOSTATIC and remap the colors
SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
syscolchg = true;
pal_is_nostatic = true;
}
}
 
ReleaseDC(NULL,hdc);
 
// Translate the palette values to an MGL palette array and
// set the values.
for (i = 0; i < 256; i++)
{
pal[i].red = palette[i*3];
pal[i].green = palette[i*3+1];
pal[i].blue = palette[i*3+2];
}
 
if (DDActive)
{
if (!mgldc)
return;
 
MGL_setPalette(mgldc,pal,256,0);
MGL_realizePalette(mgldc,256,0,false);
if (memdc)
MGL_setPalette(memdc,pal,256,0);
}
else
{
if (!windc)
return;
 
MGL_setPalette(windc,pal,256,0);
MGL_realizePalette(windc,256,0,false);
if (dibdc)
{
MGL_setPalette(dibdc,pal,256,0);
MGL_realizePalette(dibdc,256,0,false);
}
}
}
 
memcpy (vid_curpal, palette, sizeof(vid_curpal));
 
if (syscolchg)
{
PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM)0, (LPARAM)0);
syscolchg = false;
}
}
 
 
void VID_ShiftPalette (unsigned char *palette)
{
VID_SetPalette (palette);
}
 
 
/*
=================
VID_DescribeCurrentMode_f
=================
*/
void VID_DescribeCurrentMode_f (void)
{
Con_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum));
}
 
 
/*
=================
VID_NumModes_f
=================
*/
void VID_NumModes_f (void)
{
 
if (nummodes == 1)
Con_Printf ("%d video mode is available\n", nummodes);
else
Con_Printf ("%d video modes are available\n", nummodes);
}
 
 
/*
=================
VID_DescribeMode_f
=================
*/
void VID_DescribeMode_f (void)
{
int modenum;
modenum = Q_atoi (Cmd_Argv(1));
 
Con_Printf ("%s\n", VID_GetExtModeDescription (modenum));
}
 
 
/*
=================
VID_DescribeModes_f
=================
*/
void VID_DescribeModes_f (void)
{
int i, lnummodes;
char *pinfo;
qboolean na;
vmode_t *pv;
 
na = false;
 
lnummodes = VID_NumModes ();
 
for (i=0 ; i<lnummodes ; i++)
{
pv = VID_GetModePtr (i);
pinfo = VID_GetExtModeDescription (i);
 
if (VID_CheckAdequateMem (pv->width, pv->height))
{
Con_Printf ("%2d: %s\n", i, pinfo);
}
else
{
Con_Printf ("**: %s\n", pinfo);
na = true;
}
}
 
if (na)
{
Con_Printf ("\n[**: not enough system RAM for mode]\n");
}
}
 
 
/*
=================
VID_TestMode_f
=================
*/
void VID_TestMode_f (void)
{
int modenum;
double testduration;
 
if (!vid_testingmode)
{
modenum = Q_atoi (Cmd_Argv(1));
 
if (VID_SetMode (modenum, vid_curpal))
{
vid_testingmode = 1;
testduration = Q_atof (Cmd_Argv(2));
if (testduration == 0)
testduration = 5.0;
vid_testendtime = realtime + testduration;
}
}
}
 
 
/*
=================
VID_Windowed_f
=================
*/
void VID_Windowed_f (void)
{
 
VID_SetMode ((int)vid_windowed_mode.value, vid_curpal);
}
 
 
/*
=================
VID_Fullscreen_f
=================
*/
void VID_Fullscreen_f (void)
{
 
VID_SetMode ((int)vid_fullscreen_mode.value, vid_curpal);
}
 
 
/*
=================
VID_Minimize_f
=================
*/
void VID_Minimize_f (void)
{
 
// we only support minimizing windows; if you're fullscreen,
// switch to windowed first
if (modestate == MS_WINDOWED)
ShowWindow (mainwindow, SW_MINIMIZE);
}
 
 
 
/*
=================
VID_ForceMode_f
=================
*/
void VID_ForceMode_f (void)
{
int modenum;
double testduration;
 
if (!vid_testingmode)
{
modenum = Q_atoi (Cmd_Argv(1));
 
force_mode_set = 1;
VID_SetMode (modenum, vid_curpal);
force_mode_set = 0;
}
}
 
 
void VID_Init (unsigned char *palette)
{
int i, bestmatch, bestmatchmetric, t, dr, dg, db;
int basenummodes;
byte *ptmp;
 
Cvar_RegisterVariable (&vid_mode);
Cvar_RegisterVariable (&vid_wait);
Cvar_RegisterVariable (&vid_nopageflip);
Cvar_RegisterVariable (&_vid_wait_override);
Cvar_RegisterVariable (&_vid_default_mode);
Cvar_RegisterVariable (&_vid_default_mode_win);
Cvar_RegisterVariable (&vid_config_x);
Cvar_RegisterVariable (&vid_config_y);
Cvar_RegisterVariable (&vid_stretch_by_2);
Cvar_RegisterVariable (&_windowed_mouse);
Cvar_RegisterVariable (&vid_fullscreen_mode);
Cvar_RegisterVariable (&vid_windowed_mode);
Cvar_RegisterVariable (&block_switch);
Cvar_RegisterVariable (&vid_window_x);
Cvar_RegisterVariable (&vid_window_y);
 
Cmd_AddCommand ("vid_testmode", VID_TestMode_f);
Cmd_AddCommand ("vid_nummodes", VID_NumModes_f);
Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f);
Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f);
Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f);
Cmd_AddCommand ("vid_forcemode", VID_ForceMode_f);
Cmd_AddCommand ("vid_windowed", VID_Windowed_f);
Cmd_AddCommand ("vid_fullscreen", VID_Fullscreen_f);
Cmd_AddCommand ("vid_minimize", VID_Minimize_f);
 
if (COM_CheckParm ("-dibonly"))
dibonly = true;
 
VID_InitMGLDIB (global_hInstance);
 
basenummodes = nummodes;
 
if (!dibonly)
VID_InitMGLFull (global_hInstance);
 
// if there are no non-windowed modes, or only windowed and mode 0x13, then use
// fullscreen DIBs as well
if (((nummodes == basenummodes) ||
((nummodes == (basenummodes + 1)) && is_mode0x13)) &&
!COM_CheckParm ("-nofulldib"))
 
{
VID_InitFullDIB (global_hInstance);
}
 
vid.maxwarpwidth = WARP_WIDTH;
vid.maxwarpheight = WARP_HEIGHT;
vid.colormap = host_colormap;
vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
vid_testingmode = 0;
 
// GDI doesn't let us remap palette index 0, so we'll remap color
// mappings from that black to another one
bestmatchmetric = 256*256*3;
 
for (i=1 ; i<256 ; i++)
{
dr = palette[0] - palette[i*3];
dg = palette[1] - palette[i*3+1];
db = palette[2] - palette[i*3+2];
 
t = (dr * dr) + (dg * dg) + (db * db);
 
if (t < bestmatchmetric)
{
bestmatchmetric = t;
bestmatch = i;
 
if (t == 0)
break;
}
}
 
for (i=0, ptmp = vid.colormap ; i<(1<<(VID_CBITS+8)) ; i++, ptmp++)
{
if (*ptmp == 0)
*ptmp = bestmatch;
}
 
if (COM_CheckParm("-startwindowed"))
{
startwindowed = 1;
vid_default = windowed_default;
}
 
if (hwnd_dialog)
DestroyWindow (hwnd_dialog);
 
// sound initialization has to go here, preceded by a windowed mode set,
// so there's a window for DirectSound to work with but we're not yet
// fullscreen so the "hardware already in use" dialog is visible if it
// gets displayed
 
// keep the window minimized until we're ready for the first real mode set
hide_window = true;
VID_SetMode (MODE_WINDOWED, palette);
hide_window = false;
S_Init ();
 
vid_initialized = true;
 
force_mode_set = true;
VID_SetMode (vid_default, palette);
force_mode_set = false;
 
vid_realmode = vid_modenum;
 
VID_SetPalette (palette);
 
vid_menudrawfn = VID_MenuDraw;
vid_menukeyfn = VID_MenuKey;
 
strcpy (badmode.modedesc, "Bad mode");
}
 
 
void VID_Shutdown (void)
{
HDC hdc;
int dummy;
 
if (vid_initialized)
{
if (modestate == MS_FULLDIB)
ChangeDisplaySettings (NULL, CDS_FULLSCREEN);
 
PostMessage (HWND_BROADCAST, WM_PALETTECHANGED, (WPARAM)mainwindow, (LPARAM)0);
PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM)0, (LPARAM)0);
 
AppActivate(false, false);
DestroyDIBWindow ();
DestroyFullscreenWindow ();
DestroyFullDIBWindow ();
 
if (hwnd_dialog)
DestroyWindow (hwnd_dialog);
 
if (mainwindow)
DestroyWindow(mainwindow);
 
MGL_exit();
 
vid_testingmode = 0;
vid_initialized = 0;
}
}
 
 
/*
================
FlipScreen
================
*/
void FlipScreen(vrect_t *rects)
{
HRESULT ddrval;
 
// Flip the surfaces
 
if (DDActive)
{
if (mgldc)
{
if (memdc)
{
while (rects)
{
if (vid_stretched)
{
MGL_stretchBltCoord(mgldc, memdc,
rects->x,
rects->y,
rects->x + rects->width,
rects->y + rects->height,
rects->x << 1,
rects->y << 1,
(rects->x + rects->width) << 1,
(rects->y + rects->height) << 1);
}
else
{
MGL_bitBltCoord(mgldc, memdc,
rects->x, rects->y,
(rects->x + rects->width),
(rects->y + rects->height),
rects->x, rects->y, MGL_REPLACE_MODE);
}
 
rects = rects->pnext;
}
}
 
if (vid.numpages > 1)
{
// We have a flipping surface, so do a hard page flip
aPage = (aPage+1) % vid.numpages;
vPage = (vPage+1) % vid.numpages;
MGL_setActivePage(mgldc,aPage);
MGL_setVisualPage(mgldc,vPage,waitVRT);
}
}
}
else
{
HDC hdcScreen;
 
hdcScreen = GetDC(mainwindow);
 
if (windc && dibdc)
{
MGL_setWinDC(windc,hdcScreen);
 
while (rects)
{
if (vid_stretched)
{
MGL_stretchBltCoord(windc,dibdc,
rects->x, rects->y,
rects->x + rects->width, rects->y + rects->height,
rects->x << 1, rects->y << 1,
(rects->x + rects->width) << 1,
(rects->y + rects->height) << 1);
}
else
{
MGL_bitBltCoord(windc,dibdc,
rects->x, rects->y,
rects->x + rects->width, rects->y + rects->height,
rects->x, rects->y, MGL_REPLACE_MODE);
}
 
rects = rects->pnext;
}
}
 
ReleaseDC(mainwindow, hdcScreen);
}
}
 
 
void VID_Update (vrect_t *rects)
{
vrect_t rect;
RECT trect;
 
if (!vid_palettized && palette_changed)
{
palette_changed = false;
rect.x = 0;
rect.y = 0;
rect.width = vid.width;
rect.height = vid.height;
rect.pnext = NULL;
rects = &rect;
}
 
if (firstupdate)
{
if (modestate == MS_WINDOWED)
{
GetWindowRect (mainwindow, &trect);
 
if ((trect.left != (int)vid_window_x.value) ||
(trect.top != (int)vid_window_y.value))
{
if (COM_CheckParm ("-resetwinpos"))
{
Cvar_SetValue ("vid_window_x", 0.0);
Cvar_SetValue ("vid_window_y", 0.0);
}
 
VID_CheckWindowXY ();
SetWindowPos (mainwindow, NULL, (int)vid_window_x.value,
(int)vid_window_y.value, 0, 0,
SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME);
}
}
 
if ((_vid_default_mode_win.value != vid_default) &&
(!startwindowed || (_vid_default_mode_win.value < MODE_FULLSCREEN_DEFAULT)))
{
firstupdate = 0;
 
if (COM_CheckParm ("-resetwinpos"))
{
Cvar_SetValue ("vid_window_x", 0.0);
Cvar_SetValue ("vid_window_y", 0.0);
}
 
if ((_vid_default_mode_win.value < 0) ||
(_vid_default_mode_win.value >= nummodes))
{
Cvar_SetValue ("_vid_default_mode_win", windowed_default);
}
 
Cvar_SetValue ("vid_mode", _vid_default_mode_win.value);
}
}
 
// We've drawn the frame; copy it to the screen
FlipScreen (rects);
 
if (vid_testingmode)
{
if (realtime >= vid_testendtime)
{
VID_SetMode (vid_realmode, vid_curpal);
vid_testingmode = 0;
}
}
else
{
if ((int)vid_mode.value != vid_realmode)
{
VID_SetMode ((int)vid_mode.value, vid_curpal);
Cvar_SetValue ("vid_mode", (float)vid_modenum);
// so if mode set fails, we don't keep on
// trying to set that mode
vid_realmode = vid_modenum;
}
}
 
// handle the mouse state when windowed if that's changed
if (modestate == MS_WINDOWED)
{
if ((int)_windowed_mouse.value != windowed_mouse)
{
if (_windowed_mouse.value)
{
IN_ActivateMouse ();
IN_HideMouse ();
}
else
{
IN_DeactivateMouse ();
IN_ShowMouse ();
}
 
windowed_mouse = (int)_windowed_mouse.value;
}
}
}
 
 
/*
================
D_BeginDirectRect
================
*/
void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
{
int i, j, reps, repshift;
vrect_t rect;
 
if (!vid_initialized)
return;
 
if (vid.aspect > 1.5)
{
reps = 2;
repshift = 1;
}
else
{
reps = 1;
repshift = 0;
}
 
if (vid.numpages == 1)
{
VID_LockBuffer ();
 
if (!vid.direct)
Sys_Error ("NULL vid.direct pointer");
 
for (i=0 ; i<(height << repshift) ; i += reps)
{
for (j=0 ; j<reps ; j++)
{
memcpy (&backingbuf[(i + j) * 24],
vid.direct + x + ((y << repshift) + i + j) * vid.rowbytes,
width);
memcpy (vid.direct + x + ((y << repshift) + i + j) * vid.rowbytes,
&pbitmap[(i >> repshift) * width],
width);
}
}
 
VID_UnlockBuffer ();
 
rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height << repshift;
rect.pnext = NULL;
 
FlipScreen (&rect);
}
else
{
// unlock if locked
if (lockcount > 0)
MGL_endDirectAccess();
 
// set the active page to the displayed page
MGL_setActivePage (mgldc, vPage);
 
// lock the screen
MGL_beginDirectAccess ();
 
// save from and draw to screen
for (i=0 ; i<(height << repshift) ; i += reps)
{
for (j=0 ; j<reps ; j++)
{
memcpy (&backingbuf[(i + j) * 24],
(byte *)mgldc->surface + x +
((y << repshift) + i + j) * mgldc->mi.bytesPerLine,
width);
memcpy ((byte *)mgldc->surface + x +
((y << repshift) + i + j) * mgldc->mi.bytesPerLine,
&pbitmap[(i >> repshift) * width],
width);
}
}
 
// unlock the screen
MGL_endDirectAccess ();
 
// restore the original active page
MGL_setActivePage (mgldc, aPage);
 
// relock the screen if it was locked
if (lockcount > 0)
MGL_beginDirectAccess();
}
}
 
 
/*
================
D_EndDirectRect
================
*/
void D_EndDirectRect (int x, int y, int width, int height)
{
int i, j, reps, repshift;
vrect_t rect;
 
if (!vid_initialized)
return;
 
if (vid.aspect > 1.5)
{
reps = 2;
repshift = 1;
}
else
{
reps = 1;
repshift = 0;
}
 
if (vid.numpages == 1)
{
VID_LockBuffer ();
 
if (!vid.direct)
Sys_Error ("NULL vid.direct pointer");
 
for (i=0 ; i<(height << repshift) ; i += reps)
{
for (j=0 ; j<reps ; j++)
{
memcpy (vid.direct + x + ((y << repshift) + i + j) * vid.rowbytes,
&backingbuf[(i + j) * 24],
width);
}
}
 
VID_UnlockBuffer ();
 
rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height << repshift;
rect.pnext = NULL;
 
FlipScreen (&rect);
}
else
{
// unlock if locked
if (lockcount > 0)
MGL_endDirectAccess();
 
// set the active page to the displayed page
MGL_setActivePage (mgldc, vPage);
 
// lock the screen
MGL_beginDirectAccess ();
 
// restore to the screen
for (i=0 ; i<(height << repshift) ; i += reps)
{
for (j=0 ; j<reps ; j++)
{
memcpy ((byte *)mgldc->surface + x +
((y << repshift) + i + j) * mgldc->mi.bytesPerLine,
&backingbuf[(i + j) * 24],
width);
}
}
 
// unlock the screen
MGL_endDirectAccess ();
 
// restore the original active page
MGL_setActivePage (mgldc, aPage);
 
// relock the screen if it was locked
if (lockcount > 0)
MGL_beginDirectAccess();
}
}
 
 
//==========================================================================
 
byte scantokey[128] =
{
// 0 1 2 3 4 5 6 7
// 8 9 A B C D E F
0 , 27, '1', '2', '3', '4', '5', '6',
'7', '8', '9', '0', '-', '=', K_BACKSPACE, 9, // 0
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
'o', 'p', '[', ']', 13 , K_CTRL,'a', 's', // 1
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
'\'' , '`', K_SHIFT,'\\', 'z', 'x', 'c', 'v', // 2
'b', 'n', 'm', ',', '.', '/', K_SHIFT,'*',
K_ALT,' ', 0 , K_F1, K_F2, K_F3, K_F4, K_F5, // 3
K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, 0 , K_HOME,
K_UPARROW,K_PGUP,'-',K_LEFTARROW,'5',K_RIGHTARROW,'+',K_END, //4
K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0, 0, K_F11,
K_F12,0 , 0 , 0 , 0 , 0 , 0 , 0, // 5
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, // 6
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7
};
 
/*
=======
MapKey
 
Map from windows to quake keynums
=======
*/
int MapKey (int key)
{
key = (key>>16)&255;
if (key > 127)
return 0;
 
return scantokey[key];
}
 
void AppActivate(BOOL fActive, BOOL minimize)
/****************************************************************************
*
* Function: AppActivate
* Parameters: fActive - True if app is activating
*
* Description: If the application is activating, then swap the system
* into SYSPAL_NOSTATIC mode so that our palettes will display
* correctly.
*
****************************************************************************/
{
HDC hdc;
int i, t;
static BOOL sound_active;
 
ActiveApp = fActive;
 
// messy, but it seems to work
if (vid_fulldib_on_focus_mode)
{
Minimized = minimize;
 
if (Minimized)
ActiveApp = false;
}
 
MGL_appActivate(windc, ActiveApp);
 
if (vid_initialized)
{
// yield the palette if we're losing the focus
hdc = GetDC(NULL);
 
if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
{
if (ActiveApp)
{
if ((modestate == MS_WINDOWED) || (modestate == MS_FULLDIB))
{
if (GetSystemPaletteUse(hdc) == SYSPAL_STATIC)
{
// switch to SYSPAL_NOSTATIC and remap the colors
SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
syscolchg = true;
pal_is_nostatic = true;
}
}
}
else if (pal_is_nostatic)
{
if (GetSystemPaletteUse(hdc) == SYSPAL_NOSTATIC)
{
// switch back to SYSPAL_STATIC and the old mapping
SetSystemPaletteUse(hdc, SYSPAL_STATIC);
syscolchg = true;
}
 
pal_is_nostatic = false;
}
}
 
if (!Minimized)
VID_SetPalette (vid_curpal);
 
scr_fullupdate = 0;
 
ReleaseDC(NULL,hdc);
}
 
// enable/disable sound on focus gain/loss
if (!ActiveApp && sound_active)
{
S_BlockSound ();
S_ClearBuffer ();
sound_active = false;
}
else if (ActiveApp && !sound_active)
{
S_UnblockSound ();
S_ClearBuffer ();
sound_active = true;
}
 
// minimize/restore fulldib windows/mouse-capture normal windows on demand
if (!in_mode_set)
{
if (ActiveApp)
{
if (vid_fulldib_on_focus_mode)
{
if (vid_initialized)
{
msg_suppress_1 = true; // don't want to see normal mode set message
VID_SetMode (vid_fulldib_on_focus_mode, vid_curpal);
msg_suppress_1 = false;
 
t = in_mode_set;
in_mode_set = true;
AppActivate (true, false);
in_mode_set = t;
}
 
IN_ActivateMouse ();
IN_HideMouse ();
}
else if ((modestate == MS_WINDOWED) && _windowed_mouse.value)
{
IN_ActivateMouse ();
IN_HideMouse ();
}
}
 
if (!ActiveApp)
{
if (modestate == MS_FULLDIB)
{
if (vid_initialized)
{
force_minimized = true;
i = vid_fulldib_on_focus_mode;
msg_suppress_1 = true; // don't want to see normal mode set message
VID_SetMode (windowed_default, vid_curpal);
msg_suppress_1 = false;
vid_fulldib_on_focus_mode = i;
force_minimized = false;
 
// we never seem to get WM_ACTIVATE inactive from this mode set, so we'll
// do it manually
t = in_mode_set;
in_mode_set = true;
AppActivate (false, true);
in_mode_set = t;
}
 
IN_DeactivateMouse ();
IN_ShowMouse ();
}
else if ((modestate == MS_WINDOWED) && _windowed_mouse.value)
{
IN_DeactivateMouse ();
IN_ShowMouse ();
}
}
}
}
 
 
/*
================
VID_HandlePause
================
*/
void VID_HandlePause (qboolean pause)
{
 
if ((modestate == MS_WINDOWED) && _windowed_mouse.value)
{
if (pause)
{
IN_DeactivateMouse ();
IN_ShowMouse ();
}
else
{
IN_ActivateMouse ();
IN_HideMouse ();
}
}
}
 
 
/*
===================================================================
 
MAIN WINDOW
 
===================================================================
*/
 
LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
 
/* main window procedure */
LONG WINAPI MainWndProc (
HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
LONG lRet = 0;
int fwKeys, xPos, yPos, fActive, fMinimized, temp;
HDC hdc;
PAINTSTRUCT ps;
static int recursiveflag;
 
switch (uMsg)
{
case WM_CREATE:
break;
 
case WM_SYSCOMMAND:
 
// Check for maximize being hit
switch (wParam & ~0x0F)
{
case SC_MAXIMIZE:
// if minimized, bring up as a window before going fullscreen,
// so MGL will have the right state to restore
if (Minimized)
{
force_mode_set = true;
VID_SetMode (vid_modenum, vid_curpal);
force_mode_set = false;
}
 
VID_SetMode ((int)vid_fullscreen_mode.value, vid_curpal);
break;
 
case SC_SCREENSAVE:
case SC_MONITORPOWER:
if (modestate != MS_WINDOWED)
{
// don't call DefWindowProc() because we don't want to start
// the screen saver fullscreen
break;
}
 
// fall through windowed and allow the screen saver to start
 
default:
if (!in_mode_set)
{
S_BlockSound ();
S_ClearBuffer ();
}
 
lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
 
if (!in_mode_set)
{
S_UnblockSound ();
}
}
break;
 
case WM_MOVE:
window_x = (int) LOWORD(lParam);
window_y = (int) HIWORD(lParam);
VID_UpdateWindowStatus ();
 
if ((modestate == MS_WINDOWED) && !in_mode_set && !Minimized)
VID_RememberWindowPos ();
 
break;
 
case WM_SIZE:
Minimized = false;
if (!(wParam & SIZE_RESTORED))
{
if (wParam & SIZE_MINIMIZED)
Minimized = true;
}
break;
 
case WM_SYSCHAR:
// keep Alt-Space from happening
break;
 
case WM_ACTIVATE:
fActive = LOWORD(wParam);
fMinimized = (BOOL) HIWORD(wParam);
AppActivate(!(fActive == WA_INACTIVE), fMinimized);
 
// fix the leftover Alt from any Alt-Tab or the like that switched us away
ClearAllStates ();
 
if (!in_mode_set)
{
if (windc)
MGL_activatePalette(windc,true);
 
VID_SetPalette(vid_curpal);
}
 
break;
 
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
 
if (!in_mode_set && host_initialized)
SCR_UpdateWholeScreen ();
 
EndPaint(hWnd, &ps);
break;
 
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
if (!in_mode_set)
Key_Event (MapKey(lParam), true);
break;
 
case WM_KEYUP:
case WM_SYSKEYUP:
if (!in_mode_set)
Key_Event (MapKey(lParam), false);
break;
 
// this is complicated because Win32 seems to pack multiple mouse events into
// one update sometimes, so we always check all states and look for events
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
case WM_MOUSEMOVE:
if (!in_mode_set)
{
temp = 0;
 
if (wParam & MK_LBUTTON)
temp |= 1;
 
if (wParam & MK_RBUTTON)
temp |= 2;
 
if (wParam & MK_MBUTTON)
temp |= 4;
 
IN_MouseEvent (temp);
}
break;
 
// JACK: This is the mouse wheel with the Intellimouse
// Its delta is either positive or neg, and we generate the proper
// Event.
case WM_MOUSEWHEEL:
if ((short) HIWORD(wParam) > 0) {
Key_Event(K_MWHEELUP, true);
Key_Event(K_MWHEELUP, false);
} else {
Key_Event(K_MWHEELDOWN, true);
Key_Event(K_MWHEELDOWN, false);
}
break;
// KJB: Added these new palette functions
case WM_PALETTECHANGED:
if ((HWND)wParam == hWnd)
break;
/* Fall through to WM_QUERYNEWPALETTE */
case WM_QUERYNEWPALETTE:
hdc = GetDC(NULL);
 
if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
vid_palettized = true;
else
vid_palettized = false;
 
ReleaseDC(NULL,hdc);
 
scr_fullupdate = 0;
 
if (vid_initialized && !in_mode_set && windc && MGL_activatePalette(windc,false) && !Minimized)
{
VID_SetPalette (vid_curpal);
InvalidateRect (mainwindow, NULL, false);
 
// specifically required if WM_QUERYNEWPALETTE realizes a new palette
lRet = TRUE;
}
break;
 
case WM_DISPLAYCHANGE:
if (!in_mode_set && (modestate == MS_WINDOWED) && !vid_fulldib_on_focus_mode)
{
force_mode_set = true;
VID_SetMode (vid_modenum, vid_curpal);
force_mode_set = false;
}
break;
 
case WM_CLOSE:
// this causes Close in the right-click task bar menu not to work, but right
// now bad things happen if Close is handled in that case (garbage and a
// crash on Win95)
if (!in_mode_set)
{
if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit",
MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES)
{
Sys_Quit ();
}
}
break;
 
case MM_MCINOTIFY:
lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam);
break;
 
default:
/* pass all unhandled messages to DefWindowProc */
lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
break;
}
 
/* return 0 if handled message, 1 if not */
return lRet;
}
 
 
extern void M_Menu_Options_f (void);
extern void M_Print (int cx, int cy, char *str);
extern void M_PrintWhite (int cx, int cy, char *str);
extern void M_DrawCharacter (int cx, int line, int num);
extern void M_DrawTransPic (int x, int y, qpic_t *pic);
extern void M_DrawPic (int x, int y, qpic_t *pic);
 
static int vid_line, vid_wmodes;
 
typedef struct
{
int modenum;
char *desc;
int iscur;
int ismode13;
int width;
} modedesc_t;
 
#define MAX_COLUMN_SIZE 5
#define MODE_AREA_HEIGHT (MAX_COLUMN_SIZE + 6)
#define MAX_MODEDESCS (MAX_COLUMN_SIZE*3)
 
static modedesc_t modedescs[MAX_MODEDESCS];
 
/*
================
VID_MenuDraw
================
*/
void VID_MenuDraw (void)
{
qpic_t *p;
char *ptr;
int lnummodes, i, j, k, column, row, dup, dupmode;
char temp[100];
vmode_t *pv;
modedesc_t tmodedesc;
 
p = Draw_CachePic ("gfx/vidmodes.lmp");
M_DrawPic ( (320-p->width)/2, 4, p);
 
for (i=0 ; i<3 ; i++)
{
ptr = VID_GetModeDescriptionMemCheck (i);
modedescs[i].modenum = modelist[i].modenum;
modedescs[i].desc = ptr;
modedescs[i].ismode13 = 0;
modedescs[i].iscur = 0;
 
if (vid_modenum == i)
modedescs[i].iscur = 1;
}
 
vid_wmodes = 3;
lnummodes = VID_NumModes ();
for (i=3 ; i<lnummodes ; i++)
{
ptr = VID_GetModeDescriptionMemCheck (i);
pv = VID_GetModePtr (i);
 
// we only have room for 15 fullscreen modes, so don't allow
// 360-wide modes, because if there are 5 320-wide modes and
// 5 360-wide modes, we'll run out of space
if (ptr && ((pv->width != 360) || COM_CheckParm("-allow360")))
{
dup = 0;
 
for (j=3 ; j<vid_wmodes ; j++)
{
if (!strcmp (modedescs[j].desc, ptr))
{
dup = 1;
dupmode = j;
break;
}
}
 
if (dup || (vid_wmodes < MAX_MODEDESCS))
{
if (!dup || !modedescs[dupmode].ismode13 || COM_CheckParm("-noforcevga"))
{
if (dup)
{
k = dupmode;
}
else
{
k = vid_wmodes;
}
 
modedescs[k].modenum = i;
modedescs[k].desc = ptr;
modedescs[k].ismode13 = pv->mode13;
modedescs[k].iscur = 0;
modedescs[k].width = pv->width;
 
if (i == vid_modenum)
modedescs[k].iscur = 1;
 
if (!dup)
vid_wmodes++;
}
}
}
}
 
// sort the modes on width (to handle picking up oddball dibonly modes
// after all the others)
for (i=3 ; i<(vid_wmodes-1) ; i++)
{
for (j=(i+1) ; j<vid_wmodes ; j++)
{
if (modedescs[i].width > modedescs[j].width)
{
tmodedesc = modedescs[i];
modedescs[i] = modedescs[j];
modedescs[j] = tmodedesc;
}
}
}
 
 
M_Print (13*8, 36, "Windowed Modes");
 
column = 16;
row = 36+2*8;
 
for (i=0 ; i<3; i++)
{
if (modedescs[i].iscur)
M_PrintWhite (column, row, modedescs[i].desc);
else
M_Print (column, row, modedescs[i].desc);
 
column += 13*8;
}
 
if (vid_wmodes > 3)
{
M_Print (12*8, 36+4*8, "Fullscreen Modes");
 
column = 16;
row = 36+6*8;
 
for (i=3 ; i<vid_wmodes ; i++)
{
if (modedescs[i].iscur)
M_PrintWhite (column, row, modedescs[i].desc);
else
M_Print (column, row, modedescs[i].desc);
 
column += 13*8;
 
if (((i - 3) % VID_ROW_SIZE) == (VID_ROW_SIZE - 1))
{
column = 16;
row += 8;
}
}
}
 
// line cursor
if (vid_testingmode)
{
sprintf (temp, "TESTING %s",
modedescs[vid_line].desc);
M_Print (13*8, 36 + MODE_AREA_HEIGHT * 8 + 8*4, temp);
M_Print (9*8, 36 + MODE_AREA_HEIGHT * 8 + 8*6,
"Please wait 5 seconds...");
}
else
{
M_Print (9*8, 36 + MODE_AREA_HEIGHT * 8 + 8,
"Press Enter to set mode");
M_Print (6*8, 36 + MODE_AREA_HEIGHT * 8 + 8*3,
"T to test mode for 5 seconds");
ptr = VID_GetModeDescription2 (vid_modenum);
 
if (ptr)
{
sprintf (temp, "D to set default: %s", ptr);
M_Print (2*8, 36 + MODE_AREA_HEIGHT * 8 + 8*5, temp);
}
 
ptr = VID_GetModeDescription2 ((int)_vid_default_mode_win.value);
 
if (ptr)
{
sprintf (temp, "Current default: %s", ptr);
M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*6, temp);
}
 
M_Print (15*8, 36 + MODE_AREA_HEIGHT * 8 + 8*8,
"Esc to exit");
 
row = 36 + 2*8 + (vid_line / VID_ROW_SIZE) * 8;
column = 8 + (vid_line % VID_ROW_SIZE) * 13*8;
 
if (vid_line >= 3)
row += 3*8;
 
M_DrawCharacter (column, row, 12+((int)(realtime*4)&1));
}
}
 
 
/*
================
VID_MenuKey
================
*/
void VID_MenuKey (int key)
{
if (vid_testingmode)
return;
 
switch (key)
{
case K_ESCAPE:
S_LocalSound ("misc/menu1.wav");
M_Menu_Options_f ();
break;
 
case K_LEFTARROW:
S_LocalSound ("misc/menu1.wav");
vid_line = ((vid_line / VID_ROW_SIZE) * VID_ROW_SIZE) +
((vid_line + 2) % VID_ROW_SIZE);
 
if (vid_line >= vid_wmodes)
vid_line = vid_wmodes - 1;
break;
 
case K_RIGHTARROW:
S_LocalSound ("misc/menu1.wav");
vid_line = ((vid_line / VID_ROW_SIZE) * VID_ROW_SIZE) +
((vid_line + 4) % VID_ROW_SIZE);
 
if (vid_line >= vid_wmodes)
vid_line = (vid_line / VID_ROW_SIZE) * VID_ROW_SIZE;
break;
 
case K_UPARROW:
S_LocalSound ("misc/menu1.wav");
vid_line -= VID_ROW_SIZE;
 
if (vid_line < 0)
{
vid_line += ((vid_wmodes + (VID_ROW_SIZE - 1)) /
VID_ROW_SIZE) * VID_ROW_SIZE;
 
while (vid_line >= vid_wmodes)
vid_line -= VID_ROW_SIZE;
}
break;
 
case K_DOWNARROW:
S_LocalSound ("misc/menu1.wav");
vid_line += VID_ROW_SIZE;
 
if (vid_line >= vid_wmodes)
{
vid_line -= ((vid_wmodes + (VID_ROW_SIZE - 1)) /
VID_ROW_SIZE) * VID_ROW_SIZE;
 
while (vid_line < 0)
vid_line += VID_ROW_SIZE;
}
break;
 
case K_ENTER:
S_LocalSound ("misc/menu1.wav");
VID_SetMode (modedescs[vid_line].modenum, vid_curpal);
break;
 
case 'T':
case 't':
S_LocalSound ("misc/menu1.wav");
// have to set this before setting the mode because WM_PAINT
// happens during the mode set and does a VID_Update, which
// checks vid_testingmode
vid_testingmode = 1;
vid_testendtime = realtime + 5.0;
 
if (!VID_SetMode (modedescs[vid_line].modenum, vid_curpal))
{
vid_testingmode = 0;
}
break;
 
case 'D':
case 'd':
S_LocalSound ("misc/menu1.wav");
firstupdate = 0;
Cvar_SetValue ("_vid_default_mode_win", vid_modenum);
break;
 
default:
break;
}
}
/contrib/other/sdlquake-1.0.9/vid_x.c
0,0 → 1,1199
/*
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.
 
*/
// vid_x.c -- general x video driver
 
#define _BSD
 
 
#include <ctype.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
#include <X11/extensions/XShm.h>
 
#include "quakedef.h"
#include "d_local.h"
 
cvar_t _windowed_mouse = {"_windowed_mouse","0", true};
cvar_t m_filter = {"m_filter","0", true};
float old_windowed_mouse;
 
qboolean mouse_avail;
int mouse_buttons=3;
int mouse_oldbuttonstate;
int mouse_buttonstate;
float mouse_x, mouse_y;
float old_mouse_x, old_mouse_y;
int p_mouse_x;
int p_mouse_y;
int ignorenext;
int bits_per_pixel;
 
typedef struct
{
int input;
int output;
} keymap_t;
 
viddef_t vid; // global video state
unsigned short d_8to16table[256];
 
int num_shades=32;
 
int d_con_indirect = 0;
 
int vid_buffersize;
 
static qboolean doShm;
static Display *x_disp;
static Colormap x_cmap;
static Window x_win;
static GC x_gc;
static Visual *x_vis;
static XVisualInfo *x_visinfo;
//static XImage *x_image;
 
static int x_shmeventtype;
//static XShmSegmentInfo x_shminfo;
 
static qboolean oktodraw = false;
 
int XShmQueryExtension(Display *);
int XShmGetEventBase(Display *);
 
int current_framebuffer;
static XImage *x_framebuffer[2] = { 0, 0 };
static XShmSegmentInfo x_shminfo[2];
 
static int verbose=0;
 
static byte current_palette[768];
 
static long X11_highhunkmark;
static long X11_buffersize;
 
int vid_surfcachesize;
void *vid_surfcache;
 
void (*vid_menudrawfn)(void);
void (*vid_menukeyfn)(int key);
void VID_MenuKey (int key);
 
typedef unsigned short PIXEL16;
typedef unsigned long PIXEL24;
static PIXEL16 st2d_8to16table[256];
static PIXEL24 st2d_8to24table[256];
static int shiftmask_fl=0;
static long r_shift,g_shift,b_shift;
static unsigned long r_mask,g_mask,b_mask;
 
void shiftmask_init()
{
unsigned int x;
r_mask=x_vis->red_mask;
g_mask=x_vis->green_mask;
b_mask=x_vis->blue_mask;
for(r_shift=-8,x=1;x<r_mask;x=x<<1)r_shift++;
for(g_shift=-8,x=1;x<g_mask;x=x<<1)g_shift++;
for(b_shift=-8,x=1;x<b_mask;x=x<<1)b_shift++;
shiftmask_fl=1;
}
 
PIXEL16 xlib_rgb16(int r,int g,int b)
{
PIXEL16 p;
if(shiftmask_fl==0) shiftmask_init();
p=0;
 
if(r_shift>0) {
p=(r<<(r_shift))&r_mask;
} else if(r_shift<0) {
p=(r>>(-r_shift))&r_mask;
} else p|=(r&r_mask);
 
if(g_shift>0) {
p|=(g<<(g_shift))&g_mask;
} else if(g_shift<0) {
p|=(g>>(-g_shift))&g_mask;
} else p|=(g&g_mask);
 
if(b_shift>0) {
p|=(b<<(b_shift))&b_mask;
} else if(b_shift<0) {
p|=(b>>(-b_shift))&b_mask;
} else p|=(b&b_mask);
 
return p;
}
 
PIXEL24 xlib_rgb24(int r,int g,int b)
{
PIXEL24 p;
if(shiftmask_fl==0) shiftmask_init();
p=0;
 
if(r_shift>0) {
p=(r<<(r_shift))&r_mask;
} else if(r_shift<0) {
p=(r>>(-r_shift))&r_mask;
} else p|=(r&r_mask);
 
if(g_shift>0) {
p|=(g<<(g_shift))&g_mask;
} else if(g_shift<0) {
p|=(g>>(-g_shift))&g_mask;
} else p|=(g&g_mask);
 
if(b_shift>0) {
p|=(b<<(b_shift))&b_mask;
} else if(b_shift<0) {
p|=(b>>(-b_shift))&b_mask;
} else p|=(b&b_mask);
 
return p;
}
 
void st2_fixup( XImage *framebuf, int x, int y, int width, int height)
{
int xi,yi;
unsigned char *src;
PIXEL16 *dest;
register int count, n;
 
if( (x<0)||(y<0) )return;
 
for (yi = y; yi < (y+height); yi++) {
src = &framebuf->data [yi * framebuf->bytes_per_line];
 
// Duff's Device
count = width;
n = (count + 7) / 8;
dest = ((PIXEL16 *)src) + x+width - 1;
src += x+width - 1;
 
switch (count % 8) {
case 0: do { *dest-- = st2d_8to16table[*src--];
case 7: *dest-- = st2d_8to16table[*src--];
case 6: *dest-- = st2d_8to16table[*src--];
case 5: *dest-- = st2d_8to16table[*src--];
case 4: *dest-- = st2d_8to16table[*src--];
case 3: *dest-- = st2d_8to16table[*src--];
case 2: *dest-- = st2d_8to16table[*src--];
case 1: *dest-- = st2d_8to16table[*src--];
} while (--n > 0);
}
 
// for(xi = (x+width-1); xi >= x; xi--) {
// dest[xi] = st2d_8to16table[src[xi]];
// }
}
}
 
void st3_fixup( XImage *framebuf, int x, int y, int width, int height)
{
int xi,yi;
unsigned char *src;
PIXEL24 *dest;
register int count, n;
 
if( (x<0)||(y<0) )return;
 
for (yi = y; yi < (y+height); yi++) {
src = &framebuf->data [yi * framebuf->bytes_per_line];
 
// Duff's Device
count = width;
n = (count + 7) / 8;
dest = ((PIXEL24 *)src) + x+width - 1;
src += x+width - 1;
 
switch (count % 8) {
case 0: do { *dest-- = st2d_8to24table[*src--];
case 7: *dest-- = st2d_8to24table[*src--];
case 6: *dest-- = st2d_8to24table[*src--];
case 5: *dest-- = st2d_8to24table[*src--];
case 4: *dest-- = st2d_8to24table[*src--];
case 3: *dest-- = st2d_8to24table[*src--];
case 2: *dest-- = st2d_8to24table[*src--];
case 1: *dest-- = st2d_8to24table[*src--];
} while (--n > 0);
}
 
// for(xi = (x+width-1); xi >= x; xi--) {
// dest[xi] = st2d_8to16table[src[xi]];
// }
}
}
 
 
// ========================================================================
// Tragic death handler
// ========================================================================
 
void TragicDeath(int signal_num)
{
XAutoRepeatOn(x_disp);
XCloseDisplay(x_disp);
Sys_Error("This death brought to you by the number %d\n", signal_num);
}
 
// ========================================================================
// makes a null cursor
// ========================================================================
 
static Cursor CreateNullCursor(Display *display, Window root)
{
Pixmap cursormask;
XGCValues xgc;
GC gc;
XColor dummycolour;
Cursor cursor;
 
cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
xgc.function = GXclear;
gc = XCreateGC(display, cursormask, GCFunction, &xgc);
XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
dummycolour.pixel = 0;
dummycolour.red = 0;
dummycolour.flags = 04;
cursor = XCreatePixmapCursor(display, cursormask, cursormask,
&dummycolour,&dummycolour, 0,0);
XFreePixmap(display,cursormask);
XFreeGC(display,gc);
return cursor;
}
 
void ResetFrameBuffer(void)
{
int mem;
int pwidth;
 
if (x_framebuffer[0])
{
free(x_framebuffer[0]->data);
free(x_framebuffer[0]);
}
 
if (d_pzbuffer)
{
D_FlushCaches ();
Hunk_FreeToHighMark (X11_highhunkmark);
d_pzbuffer = NULL;
}
X11_highhunkmark = Hunk_HighMark ();
 
// alloc an extra line in case we want to wrap, and allocate the z-buffer
X11_buffersize = vid.width * vid.height * sizeof (*d_pzbuffer);
 
vid_surfcachesize = D_SurfaceCacheForRes (vid.width, vid.height);
 
X11_buffersize += vid_surfcachesize;
 
d_pzbuffer = Hunk_HighAllocName (X11_buffersize, "video");
if (d_pzbuffer == NULL)
Sys_Error ("Not enough memory for video mode\n");
 
vid_surfcache = (byte *) d_pzbuffer
+ vid.width * vid.height * sizeof (*d_pzbuffer);
 
D_InitCaches(vid_surfcache, vid_surfcachesize);
 
pwidth = x_visinfo->depth / 8;
if (pwidth == 3) pwidth = 4;
mem = ((vid.width*pwidth+7)&~7) * vid.height;
 
x_framebuffer[0] = XCreateImage( x_disp,
x_vis,
x_visinfo->depth,
ZPixmap,
0,
malloc(mem),
vid.width, vid.height,
32,
0);
 
if (!x_framebuffer[0])
Sys_Error("VID: XCreateImage failed\n");
 
vid.buffer = (byte*) (x_framebuffer[0]);
vid.conbuffer = vid.buffer;
 
}
 
void ResetSharedFrameBuffers(void)
{
 
int size;
int key;
int minsize = getpagesize();
int frm;
 
if (d_pzbuffer)
{
D_FlushCaches ();
Hunk_FreeToHighMark (X11_highhunkmark);
d_pzbuffer = NULL;
}
 
X11_highhunkmark = Hunk_HighMark ();
 
// alloc an extra line in case we want to wrap, and allocate the z-buffer
X11_buffersize = vid.width * vid.height * sizeof (*d_pzbuffer);
 
vid_surfcachesize = D_SurfaceCacheForRes (vid.width, vid.height);
 
X11_buffersize += vid_surfcachesize;
 
d_pzbuffer = Hunk_HighAllocName (X11_buffersize, "video");
if (d_pzbuffer == NULL)
Sys_Error ("Not enough memory for video mode\n");
 
vid_surfcache = (byte *) d_pzbuffer
+ vid.width * vid.height * sizeof (*d_pzbuffer);
 
D_InitCaches(vid_surfcache, vid_surfcachesize);
 
for (frm=0 ; frm<2 ; frm++)
{
 
// free up old frame buffer memory
 
if (x_framebuffer[frm])
{
XShmDetach(x_disp, &x_shminfo[frm]);
free(x_framebuffer[frm]);
shmdt(x_shminfo[frm].shmaddr);
}
 
// create the image
 
x_framebuffer[frm] = XShmCreateImage( x_disp,
x_vis,
x_visinfo->depth,
ZPixmap,
0,
&x_shminfo[frm],
vid.width,
vid.height );
 
// grab shared memory
 
size = x_framebuffer[frm]->bytes_per_line
* x_framebuffer[frm]->height;
if (size < minsize)
Sys_Error("VID: Window must use at least %d bytes\n", minsize);
 
key = random();
x_shminfo[frm].shmid = shmget((key_t)key, size, IPC_CREAT|0777);
if (x_shminfo[frm].shmid==-1)
Sys_Error("VID: Could not get any shared memory\n");
 
// attach to the shared memory segment
x_shminfo[frm].shmaddr =
(void *) shmat(x_shminfo[frm].shmid, 0, 0);
 
printf("VID: shared memory id=%d, addr=0x%lx\n", x_shminfo[frm].shmid,
(long) x_shminfo[frm].shmaddr);
 
x_framebuffer[frm]->data = x_shminfo[frm].shmaddr;
 
// get the X server to attach to it
 
if (!XShmAttach(x_disp, &x_shminfo[frm]))
Sys_Error("VID: XShmAttach() failed\n");
XSync(x_disp, 0);
shmctl(x_shminfo[frm].shmid, IPC_RMID, 0);
 
}
 
}
 
// Called at startup to set up translation tables, takes 256 8 bit RGB values
// the palette data will go away after the call, so it must be copied off if
// the video driver will need it again
 
void VID_Init (unsigned char *palette)
{
 
int pnum, i;
XVisualInfo template;
int num_visuals;
int template_mask;
ignorenext=0;
vid.width = 320;
vid.height = 200;
vid.maxwarpwidth = WARP_WIDTH;
vid.maxwarpheight = WARP_HEIGHT;
vid.numpages = 2;
vid.colormap = host_colormap;
// vid.cbits = VID_CBITS;
// vid.grades = VID_GRADES;
vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
srandom(getpid());
 
verbose=COM_CheckParm("-verbose");
 
// open the display
x_disp = XOpenDisplay(0);
if (!x_disp)
{
if (getenv("DISPLAY"))
Sys_Error("VID: Could not open display [%s]\n",
getenv("DISPLAY"));
else
Sys_Error("VID: Could not open local display\n");
}
 
// catch signals so i can turn on auto-repeat
 
{
struct sigaction sa;
sigaction(SIGINT, 0, &sa);
sa.sa_handler = TragicDeath;
sigaction(SIGINT, &sa, 0);
sigaction(SIGTERM, &sa, 0);
}
 
XAutoRepeatOff(x_disp);
 
// for debugging only
XSynchronize(x_disp, True);
 
// check for command-line window size
if ((pnum=COM_CheckParm("-winsize")))
{
if (pnum >= com_argc-2)
Sys_Error("VID: -winsize <width> <height>\n");
vid.width = Q_atoi(com_argv[pnum+1]);
vid.height = Q_atoi(com_argv[pnum+2]);
if (!vid.width || !vid.height)
Sys_Error("VID: Bad window width/height\n");
}
if ((pnum=COM_CheckParm("-width"))) {
if (pnum >= com_argc-1)
Sys_Error("VID: -width <width>\n");
vid.width = Q_atoi(com_argv[pnum+1]);
if (!vid.width)
Sys_Error("VID: Bad window width\n");
}
if ((pnum=COM_CheckParm("-height"))) {
if (pnum >= com_argc-1)
Sys_Error("VID: -height <height>\n");
vid.height = Q_atoi(com_argv[pnum+1]);
if (!vid.height)
Sys_Error("VID: Bad window height\n");
}
 
template_mask = 0;
 
// specify a visual id
if ((pnum=COM_CheckParm("-visualid")))
{
if (pnum >= com_argc-1)
Sys_Error("VID: -visualid <id#>\n");
template.visualid = Q_atoi(com_argv[pnum+1]);
template_mask = VisualIDMask;
}
 
// If not specified, use default visual
else
{
int screen;
screen = XDefaultScreen(x_disp);
template.visualid =
XVisualIDFromVisual(XDefaultVisual(x_disp, screen));
template_mask = VisualIDMask;
}
 
// pick a visual- warn if more than one was available
x_visinfo = XGetVisualInfo(x_disp, template_mask, &template, &num_visuals);
if (num_visuals > 1)
{
printf("Found more than one visual id at depth %d:\n", template.depth);
for (i=0 ; i<num_visuals ; i++)
printf(" -visualid %d\n", (int)(x_visinfo[i].visualid));
}
else if (num_visuals == 0)
{
if (template_mask == VisualIDMask)
Sys_Error("VID: Bad visual id %d\n", template.visualid);
else
Sys_Error("VID: No visuals at depth %d\n", template.depth);
}
 
if (verbose)
{
printf("Using visualid %d:\n", (int)(x_visinfo->visualid));
printf(" screen %d\n", x_visinfo->screen);
printf(" red_mask 0x%x\n", (int)(x_visinfo->red_mask));
printf(" green_mask 0x%x\n", (int)(x_visinfo->green_mask));
printf(" blue_mask 0x%x\n", (int)(x_visinfo->blue_mask));
printf(" colormap_size %d\n", x_visinfo->colormap_size);
printf(" bits_per_rgb %d\n", x_visinfo->bits_per_rgb);
}
 
x_vis = x_visinfo->visual;
 
// setup attributes for main window
{
int attribmask = CWEventMask | CWColormap | CWBorderPixel;
XSetWindowAttributes attribs;
Colormap tmpcmap;
tmpcmap = XCreateColormap(x_disp, XRootWindow(x_disp,
x_visinfo->screen), x_vis, AllocNone);
attribs.event_mask = StructureNotifyMask | KeyPressMask
| KeyReleaseMask | ExposureMask | PointerMotionMask |
ButtonPressMask | ButtonReleaseMask;
attribs.border_pixel = 0;
attribs.colormap = tmpcmap;
 
// create the main window
x_win = XCreateWindow( x_disp,
XRootWindow(x_disp, x_visinfo->screen),
0, 0, // x, y
vid.width, vid.height,
0, // borderwidth
x_visinfo->depth,
InputOutput,
x_vis,
attribmask,
&attribs );
XStoreName( x_disp,x_win,"xquake");
 
 
if (x_visinfo->class != TrueColor)
XFreeColormap(x_disp, tmpcmap);
}
 
if (x_visinfo->depth == 8)
{
// create and upload the palette
if (x_visinfo->class == PseudoColor)
{
x_cmap = XCreateColormap(x_disp, x_win, x_vis, AllocAll);
VID_SetPalette(palette);
XSetWindowColormap(x_disp, x_win, x_cmap);
}
}
 
// inviso cursor
XDefineCursor(x_disp, x_win, CreateNullCursor(x_disp, x_win));
 
// create the GC
{
XGCValues xgcvalues;
int valuemask = GCGraphicsExposures;
xgcvalues.graphics_exposures = False;
x_gc = XCreateGC(x_disp, x_win, valuemask, &xgcvalues );
}
 
// map the window
XMapWindow(x_disp, x_win);
 
// wait for first exposure event
{
XEvent event;
do
{
XNextEvent(x_disp, &event);
if (event.type == Expose && !event.xexpose.count)
oktodraw = true;
} while (!oktodraw);
}
// now safe to draw
 
// even if MITSHM is available, make sure it's a local connection
if (XShmQueryExtension(x_disp))
{
char *displayname;
doShm = true;
displayname = (char *) getenv("DISPLAY");
if (displayname)
{
char *d = displayname;
while (*d && (*d != ':')) d++;
if (*d) *d = 0;
if (!(!strcasecmp(displayname, "unix") || !*displayname))
doShm = false;
}
}
 
if (doShm)
{
x_shmeventtype = XShmGetEventBase(x_disp) + ShmCompletion;
ResetSharedFrameBuffers();
}
else
ResetFrameBuffer();
 
current_framebuffer = 0;
vid.rowbytes = x_framebuffer[0]->bytes_per_line;
vid.buffer = x_framebuffer[0]->data;
vid.direct = 0;
vid.conbuffer = x_framebuffer[0]->data;
vid.conrowbytes = vid.rowbytes;
vid.conwidth = vid.width;
vid.conheight = vid.height;
vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0);
 
// XSynchronize(x_disp, False);
 
}
 
void VID_ShiftPalette(unsigned char *p)
{
VID_SetPalette(p);
}
 
 
 
void VID_SetPalette(unsigned char *palette)
{
 
int i;
XColor colors[256];
 
for(i=0;i<256;i++) {
st2d_8to16table[i]= xlib_rgb16(palette[i*3], palette[i*3+1],palette[i*3+2]);
st2d_8to24table[i]= xlib_rgb24(palette[i*3], palette[i*3+1],palette[i*3+2]);
}
 
if (x_visinfo->class == PseudoColor && x_visinfo->depth == 8)
{
if (palette != current_palette)
memcpy(current_palette, palette, 768);
for (i=0 ; i<256 ; i++)
{
colors[i].pixel = i;
colors[i].flags = DoRed|DoGreen|DoBlue;
colors[i].red = palette[i*3] * 257;
colors[i].green = palette[i*3+1] * 257;
colors[i].blue = palette[i*3+2] * 257;
}
XStoreColors(x_disp, x_cmap, colors, 256);
}
 
}
 
// Called at shutdown
 
void VID_Shutdown (void)
{
Con_Printf("VID_Shutdown\n");
XAutoRepeatOn(x_disp);
XCloseDisplay(x_disp);
}
 
int XLateKey(XKeyEvent *ev)
{
 
int key;
char buf[64];
KeySym keysym;
 
key = 0;
 
XLookupString(ev, buf, sizeof buf, &keysym, 0);
 
switch(keysym)
{
case XK_KP_Page_Up:
case XK_Page_Up: key = K_PGUP; break;
 
case XK_KP_Page_Down:
case XK_Page_Down: key = K_PGDN; break;
 
case XK_KP_Home:
case XK_Home: key = K_HOME; break;
 
case XK_KP_End:
case XK_End: key = K_END; break;
 
case XK_KP_Left:
case XK_Left: key = K_LEFTARROW; break;
 
case XK_KP_Right:
case XK_Right: key = K_RIGHTARROW; break;
 
case XK_KP_Down:
case XK_Down: key = K_DOWNARROW; break;
 
case XK_KP_Up:
case XK_Up: key = K_UPARROW; break;
 
case XK_Escape: key = K_ESCAPE; break;
 
case XK_KP_Enter:
case XK_Return: key = K_ENTER; break;
 
case XK_Tab: key = K_TAB; break;
 
case XK_F1: key = K_F1; break;
 
case XK_F2: key = K_F2; break;
 
case XK_F3: key = K_F3; break;
 
case XK_F4: key = K_F4; break;
 
case XK_F5: key = K_F5; break;
 
case XK_F6: key = K_F6; break;
 
case XK_F7: key = K_F7; break;
 
case XK_F8: key = K_F8; break;
 
case XK_F9: key = K_F9; break;
 
case XK_F10: key = K_F10; break;
 
case XK_F11: key = K_F11; break;
 
case XK_F12: key = K_F12; break;
 
case XK_BackSpace: key = K_BACKSPACE; break;
 
case XK_KP_Delete:
case XK_Delete: key = K_DEL; break;
 
case XK_Pause: key = K_PAUSE; break;
 
case XK_Shift_L:
case XK_Shift_R: key = K_SHIFT; break;
 
case XK_Execute:
case XK_Control_L:
case XK_Control_R: key = K_CTRL; break;
 
case XK_Alt_L:
case XK_Meta_L:
case XK_Alt_R:
case XK_Meta_R: key = K_ALT; break;
 
case XK_KP_Begin: key = K_AUX30; break;
 
case XK_Insert:
case XK_KP_Insert: key = K_INS; break;
 
case XK_KP_Multiply: key = '*'; break;
case XK_KP_Add: key = '+'; break;
case XK_KP_Subtract: key = '-'; break;
case XK_KP_Divide: key = '/'; break;
 
#if 0
case 0x021: key = '1';break;/* [!] */
case 0x040: key = '2';break;/* [@] */
case 0x023: key = '3';break;/* [#] */
case 0x024: key = '4';break;/* [$] */
case 0x025: key = '5';break;/* [%] */
case 0x05e: key = '6';break;/* [^] */
case 0x026: key = '7';break;/* [&] */
case 0x02a: key = '8';break;/* [*] */
case 0x028: key = '9';;break;/* [(] */
case 0x029: key = '0';break;/* [)] */
case 0x05f: key = '-';break;/* [_] */
case 0x02b: key = '=';break;/* [+] */
case 0x07c: key = '\'';break;/* [|] */
case 0x07d: key = '[';break;/* [}] */
case 0x07b: key = ']';break;/* [{] */
case 0x022: key = '\'';break;/* ["] */
case 0x03a: key = ';';break;/* [:] */
case 0x03f: key = '/';break;/* [?] */
case 0x03e: key = '.';break;/* [>] */
case 0x03c: key = ',';break;/* [<] */
#endif
 
default:
key = *(unsigned char*)buf;
if (key >= 'A' && key <= 'Z')
key = key - 'A' + 'a';
// fprintf(stdout, "case 0x0%x: key = ___;break;/* [%c] */\n", keysym);
break;
}
 
return key;
}
 
struct
{
int key;
int down;
} keyq[64];
int keyq_head=0;
int keyq_tail=0;
 
int config_notify=0;
int config_notify_width;
int config_notify_height;
void GetEvent(void)
{
XEvent x_event;
int b;
XNextEvent(x_disp, &x_event);
switch(x_event.type) {
case KeyPress:
keyq[keyq_head].key = XLateKey(&x_event.xkey);
keyq[keyq_head].down = true;
keyq_head = (keyq_head + 1) & 63;
break;
case KeyRelease:
keyq[keyq_head].key = XLateKey(&x_event.xkey);
keyq[keyq_head].down = false;
keyq_head = (keyq_head + 1) & 63;
break;
 
case MotionNotify:
if (_windowed_mouse.value) {
mouse_x = (float) ((int)x_event.xmotion.x - (int)(vid.width/2));
mouse_y = (float) ((int)x_event.xmotion.y - (int)(vid.height/2));
//printf("m: x=%d,y=%d, mx=%3.2f,my=%3.2f\n",
// x_event.xmotion.x, x_event.xmotion.y, mouse_x, mouse_y);
 
/* move the mouse to the window center again */
XSelectInput(x_disp,x_win,StructureNotifyMask|KeyPressMask
|KeyReleaseMask|ExposureMask
|ButtonPressMask
|ButtonReleaseMask);
XWarpPointer(x_disp,None,x_win,0,0,0,0,
(vid.width/2),(vid.height/2));
XSelectInput(x_disp,x_win,StructureNotifyMask|KeyPressMask
|KeyReleaseMask|ExposureMask
|PointerMotionMask|ButtonPressMask
|ButtonReleaseMask);
} else {
mouse_x = (float) (x_event.xmotion.x-p_mouse_x);
mouse_y = (float) (x_event.xmotion.y-p_mouse_y);
p_mouse_x=x_event.xmotion.x;
p_mouse_y=x_event.xmotion.y;
}
break;
 
case ButtonPress:
b=-1;
if (x_event.xbutton.button == 1)
b = 0;
else if (x_event.xbutton.button == 2)
b = 2;
else if (x_event.xbutton.button == 3)
b = 1;
if (b>=0)
mouse_buttonstate |= 1<<b;
break;
 
case ButtonRelease:
b=-1;
if (x_event.xbutton.button == 1)
b = 0;
else if (x_event.xbutton.button == 2)
b = 2;
else if (x_event.xbutton.button == 3)
b = 1;
if (b>=0)
mouse_buttonstate &= ~(1<<b);
break;
case ConfigureNotify:
//printf("config notify\n");
config_notify_width = x_event.xconfigure.width;
config_notify_height = x_event.xconfigure.height;
config_notify = 1;
break;
 
default:
if (doShm && x_event.type == x_shmeventtype)
oktodraw = true;
}
if (old_windowed_mouse != _windowed_mouse.value) {
old_windowed_mouse = _windowed_mouse.value;
 
if (!_windowed_mouse.value) {
/* ungrab the pointer */
XUngrabPointer(x_disp,CurrentTime);
} else {
/* grab the pointer */
XGrabPointer(x_disp,x_win,True,0,GrabModeAsync,
GrabModeAsync,x_win,None,CurrentTime);
}
}
}
 
// flushes the given rectangles from the view buffer to the screen
 
void VID_Update (vrect_t *rects)
{
vrect_t full;
 
// if the window changes dimension, skip this frame
 
if (config_notify)
{
fprintf(stderr, "config notify\n");
config_notify = 0;
vid.width = config_notify_width & ~7;
vid.height = config_notify_height;
if (doShm)
ResetSharedFrameBuffers();
else
ResetFrameBuffer();
vid.rowbytes = x_framebuffer[0]->bytes_per_line;
vid.buffer = x_framebuffer[current_framebuffer]->data;
vid.conbuffer = vid.buffer;
vid.conwidth = vid.width;
vid.conheight = vid.height;
vid.conrowbytes = vid.rowbytes;
vid.recalc_refdef = 1; // force a surface cache flush
Con_CheckResize();
Con_Clear_f();
return;
}
 
// force full update if not 8bit
if (x_visinfo->depth != 8) {
extern int scr_fullupdate;
 
scr_fullupdate = 0;
}
 
 
if (doShm)
{
 
while (rects)
{
if (x_visinfo->depth == 16)
st2_fixup( x_framebuffer[current_framebuffer],
rects->x, rects->y, rects->width,
rects->height);
else if (x_visinfo->depth == 24)
st3_fixup( x_framebuffer[current_framebuffer],
rects->x, rects->y, rects->width,
rects->height);
if (!XShmPutImage(x_disp, x_win, x_gc,
x_framebuffer[current_framebuffer], rects->x, rects->y,
rects->x, rects->y, rects->width, rects->height, True))
Sys_Error("VID_Update: XShmPutImage failed\n");
oktodraw = false;
while (!oktodraw) GetEvent();
rects = rects->pnext;
}
current_framebuffer = !current_framebuffer;
vid.buffer = x_framebuffer[current_framebuffer]->data;
vid.conbuffer = vid.buffer;
XSync(x_disp, False);
}
else
{
while (rects)
{
if (x_visinfo->depth == 16)
st2_fixup( x_framebuffer[current_framebuffer],
rects->x, rects->y, rects->width,
rects->height);
else if (x_visinfo->depth == 24)
st3_fixup( x_framebuffer[current_framebuffer],
rects->x, rects->y, rects->width,
rects->height);
XPutImage(x_disp, x_win, x_gc, x_framebuffer[0], rects->x,
rects->y, rects->x, rects->y, rects->width, rects->height);
rects = rects->pnext;
}
XSync(x_disp, False);
}
 
}
 
static int dither;
 
void VID_DitherOn(void)
{
if (dither == 0)
{
vid.recalc_refdef = 1;
dither = 1;
}
}
 
void VID_DitherOff(void)
{
if (dither)
{
vid.recalc_refdef = 1;
dither = 0;
}
}
 
int Sys_OpenWindow(void)
{
return 0;
}
 
void Sys_EraseWindow(int window)
{
}
 
void Sys_DrawCircle(int window, int x, int y, int r)
{
}
 
void Sys_DisplayWindow(int window)
{
}
 
void Sys_SendKeyEvents(void)
{
// get events from x server
if (x_disp)
{
while (XPending(x_disp)) GetEvent();
while (keyq_head != keyq_tail)
{
Key_Event(keyq[keyq_tail].key, keyq[keyq_tail].down);
keyq_tail = (keyq_tail + 1) & 63;
}
}
}
 
#if 0
char *Sys_ConsoleInput (void)
{
 
static char text[256];
int len;
fd_set readfds;
int ready;
struct timeval timeout;
 
timeout.tv_sec = 0;
timeout.tv_usec = 0;
FD_ZERO(&readfds);
FD_SET(0, &readfds);
ready = select(1, &readfds, 0, 0, &timeout);
 
if (ready>0)
{
len = read (0, text, sizeof(text));
if (len >= 1)
{
text[len-1] = 0; // rip off the /n and terminate
return text;
}
}
 
return 0;
}
#endif
 
void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
{
// direct drawing of the "accessing disk" icon isn't supported under Linux
}
 
void D_EndDirectRect (int x, int y, int width, int height)
{
// direct drawing of the "accessing disk" icon isn't supported under Linux
}
 
void IN_Init (void)
{
Cvar_RegisterVariable (&_windowed_mouse);
Cvar_RegisterVariable (&m_filter);
if ( COM_CheckParm ("-nomouse") )
return;
mouse_x = mouse_y = 0.0;
mouse_avail = 1;
}
 
void IN_Shutdown (void)
{
mouse_avail = 0;
}
 
void IN_Commands (void)
{
int i;
if (!mouse_avail) return;
for (i=0 ; i<mouse_buttons ; i++) {
if ( (mouse_buttonstate & (1<<i)) && !(mouse_oldbuttonstate & (1<<i)) )
Key_Event (K_MOUSE1 + i, true);
 
if ( !(mouse_buttonstate & (1<<i)) && (mouse_oldbuttonstate & (1<<i)) )
Key_Event (K_MOUSE1 + i, false);
}
mouse_oldbuttonstate = mouse_buttonstate;
}
 
void IN_Move (usercmd_t *cmd)
{
if (!mouse_avail)
return;
if (m_filter.value) {
mouse_x = (mouse_x + old_mouse_x) * 0.5;
mouse_y = (mouse_y + old_mouse_y) * 0.5;
}
 
old_mouse_x = mouse_x;
old_mouse_y = mouse_y;
mouse_x *= sensitivity.value;
mouse_y *= sensitivity.value;
if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
cmd->sidemove += m_side.value * mouse_x;
else
cl.viewangles[YAW] -= m_yaw.value * mouse_x;
if (in_mlook.state & 1)
V_StopPitchDrift ();
if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) {
cl.viewangles[PITCH] += m_pitch.value * mouse_y;
if (cl.viewangles[PITCH] > 80)
cl.viewangles[PITCH] = 80;
if (cl.viewangles[PITCH] < -70)
cl.viewangles[PITCH] = -70;
} else {
if ((in_strafe.state & 1) && noclip_anglehack)
cmd->upmove -= m_forward.value * mouse_y;
else
cmd->forwardmove -= m_forward.value * mouse_y;
}
mouse_x = mouse_y = 0.0;
}
/contrib/other/sdlquake-1.0.9/view.c
0,0 → 1,1113
/*
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.
 
*/
// view.c -- player eye positioning
 
#include "quakedef.h"
#include "r_local.h"
 
/*
 
The view is allowed to move slightly from it's true position for bobbing,
but if it exceeds 8 pixels linear distance (spherical, not box), the list of
entities sent from the server may not include everything in the pvs, especially
when crossing a water boudnary.
 
*/
 
cvar_t lcd_x = {"lcd_x","0"};
cvar_t lcd_yaw = {"lcd_yaw","0"};
 
cvar_t scr_ofsx = {"scr_ofsx","0", false};
cvar_t scr_ofsy = {"scr_ofsy","0", false};
cvar_t scr_ofsz = {"scr_ofsz","0", false};
 
cvar_t cl_rollspeed = {"cl_rollspeed", "200"};
cvar_t cl_rollangle = {"cl_rollangle", "2.0"};
 
cvar_t cl_bob = {"cl_bob","0.02", false};
cvar_t cl_bobcycle = {"cl_bobcycle","0.6", false};
cvar_t cl_bobup = {"cl_bobup","0.5", false};
 
cvar_t v_kicktime = {"v_kicktime", "0.5", false};
cvar_t v_kickroll = {"v_kickroll", "0.6", false};
cvar_t v_kickpitch = {"v_kickpitch", "0.6", false};
 
cvar_t v_iyaw_cycle = {"v_iyaw_cycle", "2", false};
cvar_t v_iroll_cycle = {"v_iroll_cycle", "0.5", false};
cvar_t v_ipitch_cycle = {"v_ipitch_cycle", "1", false};
cvar_t v_iyaw_level = {"v_iyaw_level", "0.3", false};
cvar_t v_iroll_level = {"v_iroll_level", "0.1", false};
cvar_t v_ipitch_level = {"v_ipitch_level", "0.3", false};
 
cvar_t v_idlescale = {"v_idlescale", "0", false};
 
cvar_t crosshair = {"crosshair", "0", true};
cvar_t cl_crossx = {"cl_crossx", "0", false};
cvar_t cl_crossy = {"cl_crossy", "0", false};
 
cvar_t gl_cshiftpercent = {"gl_cshiftpercent", "100", false};
 
float v_dmg_time, v_dmg_roll, v_dmg_pitch;
 
extern int in_forward, in_forward2, in_back;
 
 
/*
===============
V_CalcRoll
 
Used by view and sv_user
===============
*/
vec3_t forward, right, up;
 
float V_CalcRoll (vec3_t angles, vec3_t velocity)
{
float sign;
float side;
float value;
AngleVectors (angles, forward, right, up);
side = DotProduct (velocity, right);
sign = side < 0 ? -1 : 1;
side = fabs(side);
value = cl_rollangle.value;
// if (cl.inwater)
// value *= 6;
 
if (side < cl_rollspeed.value)
side = side * value / cl_rollspeed.value;
else
side = value;
return side*sign;
}
 
 
/*
===============
V_CalcBob
 
===============
*/
float V_CalcBob (void)
{
float bob;
float cycle;
cycle = cl.time - (int)(cl.time/cl_bobcycle.value)*cl_bobcycle.value;
cycle /= cl_bobcycle.value;
if (cycle < cl_bobup.value)
cycle = M_PI * cycle / cl_bobup.value;
else
cycle = M_PI + M_PI*(cycle-cl_bobup.value)/(1.0 - cl_bobup.value);
 
// bob is proportional to velocity in the xy plane
// (don't count Z, or jumping messes it up)
 
bob = sqrt(cl.velocity[0]*cl.velocity[0] + cl.velocity[1]*cl.velocity[1]) * cl_bob.value;
//Con_Printf ("speed: %5.1f\n", Length(cl.velocity));
bob = bob*0.3 + bob*0.7*sin(cycle);
if (bob > 4)
bob = 4;
else if (bob < -7)
bob = -7;
return bob;
}
 
 
//=============================================================================
 
 
cvar_t v_centermove = {"v_centermove", "0.15", false};
cvar_t v_centerspeed = {"v_centerspeed","500"};
 
 
void V_StartPitchDrift (void)
{
#if 1
if (cl.laststop == cl.time)
{
return; // something else is keeping it from drifting
}
#endif
if (cl.nodrift || !cl.pitchvel)
{
cl.pitchvel = v_centerspeed.value;
cl.nodrift = false;
cl.driftmove = 0;
}
}
 
void V_StopPitchDrift (void)
{
cl.laststop = cl.time;
cl.nodrift = true;
cl.pitchvel = 0;
}
 
/*
===============
V_DriftPitch
 
Moves the client pitch angle towards cl.idealpitch sent by the server.
 
If the user is adjusting pitch manually, either with lookup/lookdown,
mlook and mouse, or klook and keyboard, pitch drifting is constantly stopped.
 
Drifting is enabled when the center view key is hit, mlook is released and
lookspring is non 0, or when
===============
*/
void V_DriftPitch (void)
{
float delta, move;
 
if (noclip_anglehack || !cl.onground || cls.demoplayback )
{
cl.driftmove = 0;
cl.pitchvel = 0;
return;
}
 
// don't count small mouse motion
if (cl.nodrift)
{
if ( fabs(cl.cmd.forwardmove) < cl_forwardspeed.value)
cl.driftmove = 0;
else
cl.driftmove += host_frametime;
if ( cl.driftmove > v_centermove.value)
{
V_StartPitchDrift ();
}
return;
}
delta = cl.idealpitch - cl.viewangles[PITCH];
 
if (!delta)
{
cl.pitchvel = 0;
return;
}
 
move = host_frametime * cl.pitchvel;
cl.pitchvel += host_frametime * v_centerspeed.value;
//Con_Printf ("move: %f (%f)\n", move, host_frametime);
 
if (delta > 0)
{
if (move > delta)
{
cl.pitchvel = 0;
move = delta;
}
cl.viewangles[PITCH] += move;
}
else if (delta < 0)
{
if (move > -delta)
{
cl.pitchvel = 0;
move = -delta;
}
cl.viewangles[PITCH] -= move;
}
}
 
 
 
 
 
/*
==============================================================================
PALETTE FLASHES
==============================================================================
*/
cshift_t cshift_empty = { {130,80,50}, 0 };
cshift_t cshift_water = { {130,80,50}, 128 };
cshift_t cshift_slime = { {0,25,5}, 150 };
cshift_t cshift_lava = { {255,80,0}, 150 };
 
cvar_t v_gamma = {"gamma", "1", true};
 
byte gammatable[256]; // palette is sent through this
 
#ifdef GLQUAKE
byte ramps[3][256];
float v_blend[4]; // rgba 0.0 - 1.0
#endif // GLQUAKE
 
void BuildGammaTable (float g)
{
int i, inf;
if (g == 1.0)
{
for (i=0 ; i<256 ; i++)
gammatable[i] = i;
return;
}
for (i=0 ; i<256 ; i++)
{
inf = 255 * pow ( (i+0.5)/255.5 , g ) + 0.5;
if (inf < 0)
inf = 0;
if (inf > 255)
inf = 255;
gammatable[i] = inf;
}
}
 
/*
=================
V_CheckGamma
=================
*/
qboolean V_CheckGamma (void)
{
static float oldgammavalue;
if (v_gamma.value == oldgammavalue)
return false;
oldgammavalue = v_gamma.value;
BuildGammaTable (v_gamma.value);
vid.recalc_refdef = 1; // force a surface cache flush
return true;
}
 
 
 
/*
===============
V_ParseDamage
===============
*/
void V_ParseDamage (void)
{
int armor, blood;
vec3_t from;
int i;
vec3_t forward, right, up;
entity_t *ent;
float side;
float count;
armor = MSG_ReadByte ();
blood = MSG_ReadByte ();
for (i=0 ; i<3 ; i++)
from[i] = MSG_ReadCoord ();
 
count = blood*0.5 + armor*0.5;
if (count < 10)
count = 10;
 
cl.faceanimtime = cl.time + 0.2; // but sbar face into pain frame
 
cl.cshifts[CSHIFT_DAMAGE].percent += 3*count;
if (cl.cshifts[CSHIFT_DAMAGE].percent < 0)
cl.cshifts[CSHIFT_DAMAGE].percent = 0;
if (cl.cshifts[CSHIFT_DAMAGE].percent > 150)
cl.cshifts[CSHIFT_DAMAGE].percent = 150;
 
if (armor > blood)
{
cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 200;
cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 100;
cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 100;
}
else if (armor)
{
cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 220;
cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 50;
cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 50;
}
else
{
cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 255;
cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 0;
cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 0;
}
 
//
// calculate view angle kicks
//
ent = &cl_entities[cl.viewentity];
VectorSubtract (from, ent->origin, from);
VectorNormalize (from);
AngleVectors (ent->angles, forward, right, up);
 
side = DotProduct (from, right);
v_dmg_roll = count*side*v_kickroll.value;
side = DotProduct (from, forward);
v_dmg_pitch = count*side*v_kickpitch.value;
 
v_dmg_time = v_kicktime.value;
}
 
 
/*
==================
V_cshift_f
==================
*/
void V_cshift_f (void)
{
cshift_empty.destcolor[0] = atoi(Cmd_Argv(1));
cshift_empty.destcolor[1] = atoi(Cmd_Argv(2));
cshift_empty.destcolor[2] = atoi(Cmd_Argv(3));
cshift_empty.percent = atoi(Cmd_Argv(4));
}
 
 
/*
==================
V_BonusFlash_f
 
When you run over an item, the server sends this command
==================
*/
void V_BonusFlash_f (void)
{
cl.cshifts[CSHIFT_BONUS].destcolor[0] = 215;
cl.cshifts[CSHIFT_BONUS].destcolor[1] = 186;
cl.cshifts[CSHIFT_BONUS].destcolor[2] = 69;
cl.cshifts[CSHIFT_BONUS].percent = 50;
}
 
/*
=============
V_SetContentsColor
 
Underwater, lava, etc each has a color shift
=============
*/
void V_SetContentsColor (int contents)
{
switch (contents)
{
case CONTENTS_EMPTY:
case CONTENTS_SOLID:
cl.cshifts[CSHIFT_CONTENTS] = cshift_empty;
break;
case CONTENTS_LAVA:
cl.cshifts[CSHIFT_CONTENTS] = cshift_lava;
break;
case CONTENTS_SLIME:
cl.cshifts[CSHIFT_CONTENTS] = cshift_slime;
break;
default:
cl.cshifts[CSHIFT_CONTENTS] = cshift_water;
}
}
 
/*
=============
V_CalcPowerupCshift
=============
*/
void V_CalcPowerupCshift (void)
{
if (cl.items & IT_QUAD)
{
cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0;
cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 0;
cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 255;
cl.cshifts[CSHIFT_POWERUP].percent = 30;
}
else if (cl.items & IT_SUIT)
{
cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0;
cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255;
cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0;
cl.cshifts[CSHIFT_POWERUP].percent = 20;
}
else if (cl.items & IT_INVISIBILITY)
{
cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 100;
cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 100;
cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 100;
cl.cshifts[CSHIFT_POWERUP].percent = 100;
}
else if (cl.items & IT_INVULNERABILITY)
{
cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 255;
cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255;
cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0;
cl.cshifts[CSHIFT_POWERUP].percent = 30;
}
else
cl.cshifts[CSHIFT_POWERUP].percent = 0;
}
 
/*
=============
V_CalcBlend
=============
*/
#ifdef GLQUAKE
void V_CalcBlend (void)
{
float r, g, b, a, a2;
int j;
 
r = 0;
g = 0;
b = 0;
a = 0;
 
for (j=0 ; j<NUM_CSHIFTS ; j++)
{
if (!gl_cshiftpercent.value)
continue;
 
a2 = ((cl.cshifts[j].percent * gl_cshiftpercent.value) / 100.0) / 255.0;
 
// a2 = cl.cshifts[j].percent/255.0;
if (!a2)
continue;
a = a + a2*(1-a);
//Con_Printf ("j:%i a:%f\n", j, a);
a2 = a2/a;
r = r*(1-a2) + cl.cshifts[j].destcolor[0]*a2;
g = g*(1-a2) + cl.cshifts[j].destcolor[1]*a2;
b = b*(1-a2) + cl.cshifts[j].destcolor[2]*a2;
}
 
v_blend[0] = r/255.0;
v_blend[1] = g/255.0;
v_blend[2] = b/255.0;
v_blend[3] = a;
if (v_blend[3] > 1)
v_blend[3] = 1;
if (v_blend[3] < 0)
v_blend[3] = 0;
}
#endif
 
/*
=============
V_UpdatePalette
=============
*/
#ifdef GLQUAKE
void V_UpdatePalette (void)
{
int i, j;
qboolean new;
byte *basepal, *newpal;
byte pal[768];
float r,g,b,a;
int ir, ig, ib;
qboolean force;
 
V_CalcPowerupCshift ();
new = false;
for (i=0 ; i<NUM_CSHIFTS ; i++)
{
if (cl.cshifts[i].percent != cl.prev_cshifts[i].percent)
{
new = true;
cl.prev_cshifts[i].percent = cl.cshifts[i].percent;
}
for (j=0 ; j<3 ; j++)
if (cl.cshifts[i].destcolor[j] != cl.prev_cshifts[i].destcolor[j])
{
new = true;
cl.prev_cshifts[i].destcolor[j] = cl.cshifts[i].destcolor[j];
}
}
// drop the damage value
cl.cshifts[CSHIFT_DAMAGE].percent -= host_frametime*150;
if (cl.cshifts[CSHIFT_DAMAGE].percent <= 0)
cl.cshifts[CSHIFT_DAMAGE].percent = 0;
 
// drop the bonus value
cl.cshifts[CSHIFT_BONUS].percent -= host_frametime*100;
if (cl.cshifts[CSHIFT_BONUS].percent <= 0)
cl.cshifts[CSHIFT_BONUS].percent = 0;
 
force = V_CheckGamma ();
if (!new && !force)
return;
 
V_CalcBlend ();
 
a = v_blend[3];
r = 255*v_blend[0]*a;
g = 255*v_blend[1]*a;
b = 255*v_blend[2]*a;
 
a = 1-a;
for (i=0 ; i<256 ; i++)
{
ir = i*a + r;
ig = i*a + g;
ib = i*a + b;
if (ir > 255)
ir = 255;
if (ig > 255)
ig = 255;
if (ib > 255)
ib = 255;
 
ramps[0][i] = gammatable[ir];
ramps[1][i] = gammatable[ig];
ramps[2][i] = gammatable[ib];
}
 
basepal = host_basepal;
newpal = pal;
for (i=0 ; i<256 ; i++)
{
ir = basepal[0];
ig = basepal[1];
ib = basepal[2];
basepal += 3;
newpal[0] = ramps[0][ir];
newpal[1] = ramps[1][ig];
newpal[2] = ramps[2][ib];
newpal += 3;
}
 
VID_ShiftPalette (pal);
}
#else // !GLQUAKE
void V_UpdatePalette (void)
{
int i, j;
qboolean new;
byte *basepal, *newpal;
byte pal[768];
int r,g,b;
qboolean force;
 
V_CalcPowerupCshift ();
new = false;
for (i=0 ; i<NUM_CSHIFTS ; i++)
{
if (cl.cshifts[i].percent != cl.prev_cshifts[i].percent)
{
new = true;
cl.prev_cshifts[i].percent = cl.cshifts[i].percent;
}
for (j=0 ; j<3 ; j++)
if (cl.cshifts[i].destcolor[j] != cl.prev_cshifts[i].destcolor[j])
{
new = true;
cl.prev_cshifts[i].destcolor[j] = cl.cshifts[i].destcolor[j];
}
}
// drop the damage value
cl.cshifts[CSHIFT_DAMAGE].percent -= host_frametime*150;
if (cl.cshifts[CSHIFT_DAMAGE].percent <= 0)
cl.cshifts[CSHIFT_DAMAGE].percent = 0;
 
// drop the bonus value
cl.cshifts[CSHIFT_BONUS].percent -= host_frametime*100;
if (cl.cshifts[CSHIFT_BONUS].percent <= 0)
cl.cshifts[CSHIFT_BONUS].percent = 0;
 
force = V_CheckGamma ();
if (!new && !force)
return;
basepal = host_basepal;
newpal = pal;
for (i=0 ; i<256 ; i++)
{
r = basepal[0];
g = basepal[1];
b = basepal[2];
basepal += 3;
for (j=0 ; j<NUM_CSHIFTS ; j++)
{
r += (cl.cshifts[j].percent*(cl.cshifts[j].destcolor[0]-r))>>8;
g += (cl.cshifts[j].percent*(cl.cshifts[j].destcolor[1]-g))>>8;
b += (cl.cshifts[j].percent*(cl.cshifts[j].destcolor[2]-b))>>8;
}
newpal[0] = gammatable[r];
newpal[1] = gammatable[g];
newpal[2] = gammatable[b];
newpal += 3;
}
 
VID_ShiftPalette (pal);
}
#endif // !GLQUAKE
 
 
/*
==============================================================================
VIEW RENDERING
==============================================================================
*/
 
float angledelta (float a)
{
a = anglemod(a);
if (a > 180)
a -= 360;
return a;
}
 
/*
==================
CalcGunAngle
==================
*/
void CalcGunAngle (void)
{
float yaw, pitch, move;
static float oldyaw = 0;
static float oldpitch = 0;
yaw = r_refdef.viewangles[YAW];
pitch = -r_refdef.viewangles[PITCH];
 
yaw = angledelta(yaw - r_refdef.viewangles[YAW]) * 0.4;
if (yaw > 10)
yaw = 10;
if (yaw < -10)
yaw = -10;
pitch = angledelta(-pitch - r_refdef.viewangles[PITCH]) * 0.4;
if (pitch > 10)
pitch = 10;
if (pitch < -10)
pitch = -10;
move = host_frametime*20;
if (yaw > oldyaw)
{
if (oldyaw + move < yaw)
yaw = oldyaw + move;
}
else
{
if (oldyaw - move > yaw)
yaw = oldyaw - move;
}
if (pitch > oldpitch)
{
if (oldpitch + move < pitch)
pitch = oldpitch + move;
}
else
{
if (oldpitch - move > pitch)
pitch = oldpitch - move;
}
oldyaw = yaw;
oldpitch = pitch;
 
cl.viewent.angles[YAW] = r_refdef.viewangles[YAW] + yaw;
cl.viewent.angles[PITCH] = - (r_refdef.viewangles[PITCH] + pitch);
 
cl.viewent.angles[ROLL] -= v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value;
cl.viewent.angles[PITCH] -= v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value;
cl.viewent.angles[YAW] -= v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value;
}
 
/*
==============
V_BoundOffsets
==============
*/
void V_BoundOffsets (void)
{
entity_t *ent;
ent = &cl_entities[cl.viewentity];
 
// absolutely bound refresh reletive to entity clipping hull
// so the view can never be inside a solid wall
 
if (r_refdef.vieworg[0] < ent->origin[0] - 14)
r_refdef.vieworg[0] = ent->origin[0] - 14;
else if (r_refdef.vieworg[0] > ent->origin[0] + 14)
r_refdef.vieworg[0] = ent->origin[0] + 14;
if (r_refdef.vieworg[1] < ent->origin[1] - 14)
r_refdef.vieworg[1] = ent->origin[1] - 14;
else if (r_refdef.vieworg[1] > ent->origin[1] + 14)
r_refdef.vieworg[1] = ent->origin[1] + 14;
if (r_refdef.vieworg[2] < ent->origin[2] - 22)
r_refdef.vieworg[2] = ent->origin[2] - 22;
else if (r_refdef.vieworg[2] > ent->origin[2] + 30)
r_refdef.vieworg[2] = ent->origin[2] + 30;
}
 
/*
==============
V_AddIdle
 
Idle swaying
==============
*/
void V_AddIdle (void)
{
r_refdef.viewangles[ROLL] += v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value;
r_refdef.viewangles[PITCH] += v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value;
r_refdef.viewangles[YAW] += v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value;
}
 
 
/*
==============
V_CalcViewRoll
 
Roll is induced by movement and damage
==============
*/
void V_CalcViewRoll (void)
{
float side;
side = V_CalcRoll (cl_entities[cl.viewentity].angles, cl.velocity);
r_refdef.viewangles[ROLL] += side;
 
if (v_dmg_time > 0)
{
r_refdef.viewangles[ROLL] += v_dmg_time/v_kicktime.value*v_dmg_roll;
r_refdef.viewangles[PITCH] += v_dmg_time/v_kicktime.value*v_dmg_pitch;
v_dmg_time -= host_frametime;
}
 
if (cl.stats[STAT_HEALTH] <= 0)
{
r_refdef.viewangles[ROLL] = 80; // dead view angle
return;
}
 
}
 
 
/*
==================
V_CalcIntermissionRefdef
 
==================
*/
void V_CalcIntermissionRefdef (void)
{
entity_t *ent, *view;
float old;
 
// ent is the player model (visible when out of body)
ent = &cl_entities[cl.viewentity];
// view is the weapon model (only visible from inside body)
view = &cl.viewent;
 
VectorCopy (ent->origin, r_refdef.vieworg);
VectorCopy (ent->angles, r_refdef.viewangles);
view->model = NULL;
 
// allways idle in intermission
old = v_idlescale.value;
v_idlescale.value = 1;
V_AddIdle ();
v_idlescale.value = old;
}
 
/*
==================
V_CalcRefdef
 
==================
*/
void V_CalcRefdef (void)
{
entity_t *ent, *view;
int i;
vec3_t forward, right, up;
vec3_t angles;
float bob;
static float oldz = 0;
 
V_DriftPitch ();
 
// ent is the player model (visible when out of body)
ent = &cl_entities[cl.viewentity];
// view is the weapon model (only visible from inside body)
view = &cl.viewent;
 
// transform the view offset by the model's matrix to get the offset from
// model origin for the view
ent->angles[YAW] = cl.viewangles[YAW]; // the model should face
// the view dir
ent->angles[PITCH] = -cl.viewangles[PITCH]; // the model should face
// the view dir
bob = V_CalcBob ();
// refresh position
VectorCopy (ent->origin, r_refdef.vieworg);
r_refdef.vieworg[2] += cl.viewheight + bob;
 
// never let it sit exactly on a node line, because a water plane can
// dissapear when viewed with the eye exactly on it.
// the server protocol only specifies to 1/16 pixel, so add 1/32 in each axis
r_refdef.vieworg[0] += 1.0/32;
r_refdef.vieworg[1] += 1.0/32;
r_refdef.vieworg[2] += 1.0/32;
 
VectorCopy (cl.viewangles, r_refdef.viewangles);
V_CalcViewRoll ();
V_AddIdle ();
 
// offsets
angles[PITCH] = -ent->angles[PITCH]; // because entity pitches are
// actually backward
angles[YAW] = ent->angles[YAW];
angles[ROLL] = ent->angles[ROLL];
 
AngleVectors (angles, forward, right, up);
 
for (i=0 ; i<3 ; i++)
r_refdef.vieworg[i] += scr_ofsx.value*forward[i]
+ scr_ofsy.value*right[i]
+ scr_ofsz.value*up[i];
V_BoundOffsets ();
// set up gun position
VectorCopy (cl.viewangles, view->angles);
CalcGunAngle ();
 
VectorCopy (ent->origin, view->origin);
view->origin[2] += cl.viewheight;
 
for (i=0 ; i<3 ; i++)
{
view->origin[i] += forward[i]*bob*0.4;
// view->origin[i] += right[i]*bob*0.4;
// view->origin[i] += up[i]*bob*0.8;
}
view->origin[2] += bob;
 
// fudge position around to keep amount of weapon visible
// roughly equal with different FOV
 
#if 0
if (cl.model_precache[cl.stats[STAT_WEAPON]] && strcmp (cl.model_precache[cl.stats[STAT_WEAPON]]->name, "progs/v_shot2.mdl"))
#endif
if (scr_viewsize.value == 110)
view->origin[2] += 1;
else if (scr_viewsize.value == 100)
view->origin[2] += 2;
else if (scr_viewsize.value == 90)
view->origin[2] += 1;
else if (scr_viewsize.value == 80)
view->origin[2] += 0.5;
 
view->model = cl.model_precache[cl.stats[STAT_WEAPON]];
view->frame = cl.stats[STAT_WEAPONFRAME];
view->colormap = vid.colormap;
 
// set up the refresh position
VectorAdd (r_refdef.viewangles, cl.punchangle, r_refdef.viewangles);
 
// smooth out stair step ups
if (cl.onground && ent->origin[2] - oldz > 0)
{
float steptime;
steptime = cl.time - cl.oldtime;
if (steptime < 0)
//FIXME I_Error ("steptime < 0");
steptime = 0;
 
oldz += steptime * 80;
if (oldz > ent->origin[2])
oldz = ent->origin[2];
if (ent->origin[2] - oldz > 12)
oldz = ent->origin[2] - 12;
r_refdef.vieworg[2] += oldz - ent->origin[2];
view->origin[2] += oldz - ent->origin[2];
}
else
oldz = ent->origin[2];
 
if (chase_active.value)
Chase_Update ();
}
 
/*
==================
V_RenderView
 
The player's clipping box goes from (-16 -16 -24) to (16 16 32) from
the entity origin, so any view position inside that will be valid
==================
*/
extern vrect_t scr_vrect;
 
void V_RenderView (void)
{
if (con_forcedup)
return;
 
// don't allow cheats in multiplayer
if (cl.maxclients > 1)
{
Cvar_Set ("scr_ofsx", "0");
Cvar_Set ("scr_ofsy", "0");
Cvar_Set ("scr_ofsz", "0");
}
 
if (cl.intermission)
{ // intermission / finale rendering
V_CalcIntermissionRefdef ();
}
else
{
if (!cl.paused /* && (sv.maxclients > 1 || key_dest == key_game) */ )
V_CalcRefdef ();
}
 
R_PushDlights ();
 
if (lcd_x.value)
{
//
// render two interleaved views
//
int i;
 
vid.rowbytes <<= 1;
vid.aspect *= 0.5;
 
r_refdef.viewangles[YAW] -= lcd_yaw.value;
for (i=0 ; i<3 ; i++)
r_refdef.vieworg[i] -= right[i]*lcd_x.value;
R_RenderView ();
 
vid.buffer += vid.rowbytes>>1;
 
R_PushDlights ();
 
r_refdef.viewangles[YAW] += lcd_yaw.value*2;
for (i=0 ; i<3 ; i++)
r_refdef.vieworg[i] += 2*right[i]*lcd_x.value;
R_RenderView ();
 
vid.buffer -= vid.rowbytes>>1;
 
r_refdef.vrect.height <<= 1;
 
vid.rowbytes >>= 1;
vid.aspect *= 2;
}
else
{
R_RenderView ();
}
 
#ifndef GLQUAKE
if (crosshair.value)
Draw_Character (scr_vrect.x + scr_vrect.width/2 + cl_crossx.value,
scr_vrect.y + scr_vrect.height/2 + cl_crossy.value, '+');
#endif
}
 
//============================================================================
 
/*
=============
V_Init
=============
*/
void V_Init (void)
{
Cmd_AddCommand ("v_cshift", V_cshift_f);
Cmd_AddCommand ("bf", V_BonusFlash_f);
Cmd_AddCommand ("centerview", V_StartPitchDrift);
 
Cvar_RegisterVariable (&lcd_x);
Cvar_RegisterVariable (&lcd_yaw);
 
Cvar_RegisterVariable (&v_centermove);
Cvar_RegisterVariable (&v_centerspeed);
 
Cvar_RegisterVariable (&v_iyaw_cycle);
Cvar_RegisterVariable (&v_iroll_cycle);
Cvar_RegisterVariable (&v_ipitch_cycle);
Cvar_RegisterVariable (&v_iyaw_level);
Cvar_RegisterVariable (&v_iroll_level);
Cvar_RegisterVariable (&v_ipitch_level);
 
Cvar_RegisterVariable (&v_idlescale);
Cvar_RegisterVariable (&crosshair);
Cvar_RegisterVariable (&cl_crossx);
Cvar_RegisterVariable (&cl_crossy);
Cvar_RegisterVariable (&gl_cshiftpercent);
 
Cvar_RegisterVariable (&scr_ofsx);
Cvar_RegisterVariable (&scr_ofsy);
Cvar_RegisterVariable (&scr_ofsz);
Cvar_RegisterVariable (&cl_rollspeed);
Cvar_RegisterVariable (&cl_rollangle);
Cvar_RegisterVariable (&cl_bob);
Cvar_RegisterVariable (&cl_bobcycle);
Cvar_RegisterVariable (&cl_bobup);
 
Cvar_RegisterVariable (&v_kicktime);
Cvar_RegisterVariable (&v_kickroll);
Cvar_RegisterVariable (&v_kickpitch);
BuildGammaTable (1.0); // no gamma yet
Cvar_RegisterVariable (&v_gamma);
}
 
 
/contrib/other/sdlquake-1.0.9/view.h
0,0 → 1,35
/*
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.
 
*/
// view.h
 
extern cvar_t v_gamma;
 
extern byte gammatable[256]; // palette is sent through this
extern byte ramps[3][256];
extern float v_blend[4];
 
extern cvar_t lcd_x;
 
 
void V_Init (void);
void V_RenderView (void);
float V_CalcRoll (vec3_t angles, vec3_t velocity);
void V_UpdatePalette (void);
 
/contrib/other/sdlquake-1.0.9/vregset.c
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.
 
*/
//
// vregset.c: video register-setting interpreter
//
 
#include <dos.h>
#include <conio.h>
 
#include "quakedef.h"
#include "vregset.h"
 
//#define outportb loutportb
 
void loutportb (int port, int val)
{
printf ("port, val: %x %x\n", port, val);
getch ();
}
 
/*
================
VideoRegisterSet
================
*/
void VideoRegisterSet (int *pregset)
{
int port, temp0, temp1, temp2;
 
for ( ;; )
{
switch (*pregset++)
{
case VRS_END:
return;
 
case VRS_BYTE_OUT:
port = *pregset++;
outportb (port, *pregset++);
break;
 
case VRS_BYTE_RMW:
port = *pregset++;
temp0 = *pregset++;
temp1 = *pregset++;
temp2 = inportb (port);
temp2 &= temp0;
temp2 |= temp1;
outportb (port, temp2);
break;
 
case VRS_WORD_OUT:
port = *pregset++;
outportb (port, *pregset & 0xFF);
outportb (port+1, *pregset >> 8);
pregset++;
break;
 
default:
Sys_Error ("VideoRegisterSet: Invalid command\n");
}
}
}
 
/contrib/other/sdlquake-1.0.9/vregset.h
0,0 → 1,56
/*
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.
 
*/
//
// vregset.h: header file for video register-setting interpreter
//
 
//
// registers & subregisters
//
#define MISC_OUTPUT 0x3C2
 
#define SC_INDEX 0x3C4
#define SC_DATA 0x3C5
#define SYNC_RESET 0
#define MAP_MASK 2
#define MEMORY_MODE 4
 
#define GC_INDEX 0x3CE
#define GC_DATA 0x3CF
#define READ_MAP 4
#define GRAPHICS_MODE 5
#define MISCELLANOUS 6
 
#define CRTC_INDEX 0x3D4
#define CRTC_DATA 0x3D5
#define MAX_SCAN_LINE 9
#define UNDERLINE 0x14
#define MODE_CONTROL 0x17
 
//
// register-set commands
//
#define VRS_END 0
#define VRS_BYTE_OUT 1
#define VRS_BYTE_RMW 2
#define VRS_WORD_OUT 3
 
void VideoRegisterSet (int *pregset);
 
/contrib/other/sdlquake-1.0.9/wad.c
0,0 → 1,158
/*
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.
 
*/
// wad.c
 
#include "quakedef.h"
 
int wad_numlumps;
lumpinfo_t *wad_lumps;
byte *wad_base;
 
void SwapPic (qpic_t *pic);
 
/*
==================
W_CleanupName
 
Lowercases name and pads with spaces and a terminating 0 to the length of
lumpinfo_t->name.
Used so lumpname lookups can proceed rapidly by comparing 4 chars at a time
Space padding is so names can be printed nicely in tables.
Can safely be performed in place.
==================
*/
void W_CleanupName (char *in, char *out)
{
int i;
int c;
for (i=0 ; i<16 ; i++ )
{
c = in[i];
if (!c)
break;
if (c >= 'A' && c <= 'Z')
c += ('a' - 'A');
out[i] = c;
}
for ( ; i< 16 ; i++ )
out[i] = 0;
}
 
 
 
/*
====================
W_LoadWadFile
====================
*/
void W_LoadWadFile (char *filename)
{
lumpinfo_t *lump_p;
wadinfo_t *header;
unsigned i;
int infotableofs;
wad_base = COM_LoadHunkFile (filename);
if (!wad_base)
Sys_Error ("W_LoadWadFile: couldn't load %s", filename);
 
header = (wadinfo_t *)wad_base;
if (header->identification[0] != 'W'
|| header->identification[1] != 'A'
|| header->identification[2] != 'D'
|| header->identification[3] != '2')
Sys_Error ("Wad file %s doesn't have WAD2 id\n",filename);
wad_numlumps = LittleLong(header->numlumps);
infotableofs = LittleLong(header->infotableofs);
wad_lumps = (lumpinfo_t *)(wad_base + infotableofs);
for (i=0, lump_p = wad_lumps ; i<wad_numlumps ; i++,lump_p++)
{
lump_p->filepos = LittleLong(lump_p->filepos);
lump_p->size = LittleLong(lump_p->size);
W_CleanupName (lump_p->name, lump_p->name);
if (lump_p->type == TYP_QPIC)
SwapPic ( (qpic_t *)(wad_base + lump_p->filepos));
}
}
 
 
/*
=============
W_GetLumpinfo
=============
*/
lumpinfo_t *W_GetLumpinfo (char *name)
{
int i;
lumpinfo_t *lump_p;
char clean[16];
W_CleanupName (name, clean);
for (lump_p=wad_lumps, i=0 ; i<wad_numlumps ; i++,lump_p++)
{
if (!strcmp(clean, lump_p->name))
return lump_p;
}
Sys_Error ("W_GetLumpinfo: %s not found", name);
return NULL;
}
 
void *W_GetLumpName (char *name)
{
lumpinfo_t *lump;
lump = W_GetLumpinfo (name);
return (void *)(wad_base + lump->filepos);
}
 
void *W_GetLumpNum (int num)
{
lumpinfo_t *lump;
if (num < 0 || num > wad_numlumps)
Sys_Error ("W_GetLumpNum: bad number: %i", num);
lump = wad_lumps + num;
return (void *)(wad_base + lump->filepos);
}
 
/*
=============================================================================
 
automatic byte swapping
 
=============================================================================
*/
 
void SwapPic (qpic_t *pic)
{
pic->width = LittleLong(pic->width);
pic->height = LittleLong(pic->height);
}
/contrib/other/sdlquake-1.0.9/wad.h
0,0 → 1,75
/*
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.
 
*/
// wad.h
 
//===============
// TYPES
//===============
 
#define CMP_NONE 0
#define CMP_LZSS 1
 
#define TYP_NONE 0
#define TYP_LABEL 1
 
#define TYP_LUMPY 64 // 64 + grab command number
#define TYP_PALETTE 64
#define TYP_QTEX 65
#define TYP_QPIC 66
#define TYP_SOUND 67
#define TYP_MIPTEX 68
 
typedef struct
{
int width, height;
byte data[4]; // variably sized
} qpic_t;
 
 
 
typedef struct
{
char identification[4]; // should be WAD2 or 2DAW
int numlumps;
int infotableofs;
} wadinfo_t;
 
typedef struct
{
int filepos;
int disksize;
int size; // uncompressed
char type;
char compression;
char pad1, pad2;
char name[16]; // must be null terminated
} lumpinfo_t;
 
extern int wad_numlumps;
extern lumpinfo_t *wad_lumps;
extern byte *wad_base;
 
void W_LoadWadFile (char *filename);
void W_CleanupName (char *in, char *out);
lumpinfo_t *W_GetLumpinfo (char *name);
void *W_GetLumpName (char *name);
void *W_GetLumpNum (int num);
 
void SwapPic (qpic_t *pic);
/contrib/other/sdlquake-1.0.9/winquake.h
0,0 → 1,114
/*
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.
 
*/
// winquake.h: Win32-specific Quake header file
 
#pragma warning( disable : 4229 ) // mgraph gets this
 
#include <windows.h>
#define WM_MOUSEWHEEL 0x020A
 
#ifndef SERVERONLY
#include <ddraw.h>
#include <dsound.h>
#ifndef GLQUAKE
#include <mgraph.h>
#endif
#endif
 
extern HINSTANCE global_hInstance;
extern int global_nCmdShow;
 
#ifndef SERVERONLY
 
extern LPDIRECTDRAW lpDD;
extern qboolean DDActive;
extern LPDIRECTDRAWSURFACE lpPrimary;
extern LPDIRECTDRAWSURFACE lpFrontBuffer;
extern LPDIRECTDRAWSURFACE lpBackBuffer;
extern LPDIRECTDRAWPALETTE lpDDPal;
extern LPDIRECTSOUND pDS;
extern LPDIRECTSOUNDBUFFER pDSBuf;
 
extern DWORD gSndBufSize;
//#define SNDBUFSIZE 65536
 
void VID_LockBuffer (void);
void VID_UnlockBuffer (void);
 
#endif
 
typedef enum {MS_WINDOWED, MS_FULLSCREEN, MS_FULLDIB, MS_UNINIT} modestate_t;
 
extern modestate_t modestate;
 
extern HWND mainwindow;
extern qboolean ActiveApp, Minimized;
 
extern qboolean WinNT;
 
int VID_ForceUnlockedAndReturnState (void);
void VID_ForceLockState (int lk);
 
void IN_ShowMouse (void);
void IN_DeactivateMouse (void);
void IN_HideMouse (void);
void IN_ActivateMouse (void);
void IN_RestoreOriginalMouseState (void);
void IN_SetQuakeMouseState (void);
void IN_MouseEvent (int mstate);
 
extern qboolean winsock_lib_initialized;
 
extern cvar_t _windowed_mouse;
 
extern int window_center_x, window_center_y;
extern RECT window_rect;
 
extern qboolean mouseinitialized;
extern HWND hwnd_dialog;
 
extern HANDLE hinput, houtput;
 
void IN_UpdateClipCursor (void);
void CenterWindow(HWND hWndCenter, int width, int height, BOOL lefttopjustify);
 
void S_BlockSound (void);
void S_UnblockSound (void);
 
void VID_SetDefaultMode (void);
 
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);
/contrib/other/sdlquake-1.0.9/winquake.rc
0,0 → 1,131
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
 
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
 
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
 
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
 
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
 
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
 
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
 
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
 
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
 
#endif // APSTUDIO_INVOKED
 
 
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
 
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON2 ICON DISCARDABLE "quake.ico"
 
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
 
IDD_DIALOG1 DIALOGEX 0, 0, 62, 21
STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_POPUP
EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CLIENTEDGE
FONT 16, "Times New Roman", 0, 0, 0x1
BEGIN
CTEXT "Starting Quake...",IDC_STATIC,4,6,54,8
END
 
IDD_PROGRESS DIALOGEX 0, 0, 333, 45
STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_POPUP |
WS_VISIBLE
EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CLIENTEDGE
FONT 8, "MS Sans Serif"
BEGIN
LTEXT "Creating 15 bit inverse palette. This is only done once, so just be patient for the next 30-60 seconds.",
IDC_STATIC,7,19,319,10
CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",0x0,7,29,
319,11
LTEXT "Starting Quake...",IDC_STATIC,7,4,54,8
END
 
 
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
 
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE
BEGIN
IDD_DIALOG1, DIALOG
BEGIN
LEFTMARGIN, 4
RIGHTMARGIN, 58
TOPMARGIN, 6
BOTTOMMARGIN, 16
HORZGUIDE, 6
HORZGUIDE, 16
END
END
#endif // APSTUDIO_INVOKED
 
 
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
 
STRINGTABLE DISCARDABLE
BEGIN
IDS_STRING1 "WinQuake"
END
 
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
 
 
 
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
 
 
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
 
/contrib/other/sdlquake-1.0.9/world.c
0,0 → 1,962
/*
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.
 
*/
// world.c -- world query functions
 
#include "quakedef.h"
 
/*
 
entities never clip against themselves, or their owner
 
line of sight checks trace->crosscontent, but bullets don't
 
*/
 
 
typedef struct
{
vec3_t boxmins, boxmaxs;// enclose the test object along entire move
float *mins, *maxs; // size of the moving object
vec3_t mins2, maxs2; // size when clipping against mosnters
float *start, *end;
trace_t trace;
int type;
edict_t *passedict;
} moveclip_t;
 
 
int SV_HullPointContents (hull_t *hull, int num, vec3_t p);
 
/*
===============================================================================
 
HULL BOXES
 
===============================================================================
*/
 
 
static hull_t box_hull;
static dclipnode_t box_clipnodes[6];
static mplane_t box_planes[6];
 
/*
===================
SV_InitBoxHull
 
Set up the planes and clipnodes so that the six floats of a bounding box
can just be stored out and get a proper hull_t structure.
===================
*/
void SV_InitBoxHull (void)
{
int i;
int side;
 
box_hull.clipnodes = box_clipnodes;
box_hull.planes = box_planes;
box_hull.firstclipnode = 0;
box_hull.lastclipnode = 5;
 
for (i=0 ; i<6 ; i++)
{
box_clipnodes[i].planenum = i;
side = i&1;
box_clipnodes[i].children[side] = CONTENTS_EMPTY;
if (i != 5)
box_clipnodes[i].children[side^1] = i + 1;
else
box_clipnodes[i].children[side^1] = CONTENTS_SOLID;
box_planes[i].type = i>>1;
box_planes[i].normal[i>>1] = 1;
}
}
 
 
/*
===================
SV_HullForBox
 
To keep everything totally uniform, bounding boxes are turned into small
BSP trees instead of being compared directly.
===================
*/
hull_t *SV_HullForBox (vec3_t mins, vec3_t maxs)
{
box_planes[0].dist = maxs[0];
box_planes[1].dist = mins[0];
box_planes[2].dist = maxs[1];
box_planes[3].dist = mins[1];
box_planes[4].dist = maxs[2];
box_planes[5].dist = mins[2];
 
return &box_hull;
}
 
 
 
/*
================
SV_HullForEntity
 
Returns a hull that can be used for testing or clipping an object of mins/maxs
size.
Offset is filled in to contain the adjustment that must be added to the
testing object's origin to get a point to use with the returned hull.
================
*/
hull_t *SV_HullForEntity (edict_t *ent, vec3_t mins, vec3_t maxs, vec3_t offset)
{
model_t *model;
vec3_t size;
vec3_t hullmins, hullmaxs;
hull_t *hull;
 
// decide which clipping hull to use, based on the size
if (ent->v.solid == SOLID_BSP)
{ // explicit hulls in the BSP model
if (ent->v.movetype != MOVETYPE_PUSH)
Sys_Error ("SOLID_BSP without MOVETYPE_PUSH");
 
model = sv.models[ (int)ent->v.modelindex ];
 
if (!model || model->type != mod_brush)
Sys_Error ("MOVETYPE_PUSH with a non bsp model");
 
VectorSubtract (maxs, mins, size);
if (size[0] < 3)
hull = &model->hulls[0];
else if (size[0] <= 32)
hull = &model->hulls[1];
else
hull = &model->hulls[2];
 
// calculate an offset value to center the origin
VectorSubtract (hull->clip_mins, mins, offset);
VectorAdd (offset, ent->v.origin, offset);
}
else
{ // create a temp hull from bounding box sizes
 
VectorSubtract (ent->v.mins, maxs, hullmins);
VectorSubtract (ent->v.maxs, mins, hullmaxs);
hull = SV_HullForBox (hullmins, hullmaxs);
VectorCopy (ent->v.origin, offset);
}
 
 
return hull;
}
 
/*
===============================================================================
 
ENTITY AREA CHECKING
 
===============================================================================
*/
 
typedef struct areanode_s
{
int axis; // -1 = leaf node
float dist;
struct areanode_s *children[2];
link_t trigger_edicts;
link_t solid_edicts;
} areanode_t;
 
#define AREA_DEPTH 4
#define AREA_NODES 32
 
static areanode_t sv_areanodes[AREA_NODES];
static int sv_numareanodes;
 
/*
===============
SV_CreateAreaNode
 
===============
*/
areanode_t *SV_CreateAreaNode (int depth, vec3_t mins, vec3_t maxs)
{
areanode_t *anode;
vec3_t size;
vec3_t mins1, maxs1, mins2, maxs2;
 
anode = &sv_areanodes[sv_numareanodes];
sv_numareanodes++;
 
ClearLink (&anode->trigger_edicts);
ClearLink (&anode->solid_edicts);
if (depth == AREA_DEPTH)
{
anode->axis = -1;
anode->children[0] = anode->children[1] = NULL;
return anode;
}
VectorSubtract (maxs, mins, size);
if (size[0] > size[1])
anode->axis = 0;
else
anode->axis = 1;
anode->dist = 0.5 * (maxs[anode->axis] + mins[anode->axis]);
VectorCopy (mins, mins1);
VectorCopy (mins, mins2);
VectorCopy (maxs, maxs1);
VectorCopy (maxs, maxs2);
maxs1[anode->axis] = mins2[anode->axis] = anode->dist;
anode->children[0] = SV_CreateAreaNode (depth+1, mins2, maxs2);
anode->children[1] = SV_CreateAreaNode (depth+1, mins1, maxs1);
 
return anode;
}
 
/*
===============
SV_ClearWorld
 
===============
*/
void SV_ClearWorld (void)
{
SV_InitBoxHull ();
memset (sv_areanodes, 0, sizeof(sv_areanodes));
sv_numareanodes = 0;
SV_CreateAreaNode (0, sv.worldmodel->mins, sv.worldmodel->maxs);
}
 
 
/*
===============
SV_UnlinkEdict
 
===============
*/
void SV_UnlinkEdict (edict_t *ent)
{
if (!ent->area.prev)
return; // not linked in anywhere
RemoveLink (&ent->area);
ent->area.prev = ent->area.next = NULL;
}
 
 
/*
====================
SV_TouchLinks
====================
*/
void SV_TouchLinks ( edict_t *ent, areanode_t *node )
{
link_t *l, *next;
edict_t *touch;
int old_self, old_other;
 
// touch linked edicts
for (l = node->trigger_edicts.next ; l != &node->trigger_edicts ; l = next)
{
next = l->next;
touch = EDICT_FROM_AREA(l);
if (touch == ent)
continue;
if (!touch->v.touch || touch->v.solid != SOLID_TRIGGER)
continue;
if (ent->v.absmin[0] > touch->v.absmax[0]
|| ent->v.absmin[1] > touch->v.absmax[1]
|| ent->v.absmin[2] > touch->v.absmax[2]
|| ent->v.absmax[0] < touch->v.absmin[0]
|| ent->v.absmax[1] < touch->v.absmin[1]
|| ent->v.absmax[2] < touch->v.absmin[2] )
continue;
old_self = pr_global_struct->self;
old_other = pr_global_struct->other;
 
pr_global_struct->self = EDICT_TO_PROG(touch);
pr_global_struct->other = EDICT_TO_PROG(ent);
pr_global_struct->time = sv.time;
PR_ExecuteProgram (touch->v.touch);
 
pr_global_struct->self = old_self;
pr_global_struct->other = old_other;
}
// recurse down both sides
if (node->axis == -1)
return;
if ( ent->v.absmax[node->axis] > node->dist )
SV_TouchLinks ( ent, node->children[0] );
if ( ent->v.absmin[node->axis] < node->dist )
SV_TouchLinks ( ent, node->children[1] );
}
 
 
/*
===============
SV_FindTouchedLeafs
 
===============
*/
void SV_FindTouchedLeafs (edict_t *ent, mnode_t *node)
{
mplane_t *splitplane;
mleaf_t *leaf;
int sides;
int leafnum;
 
if (node->contents == CONTENTS_SOLID)
return;
// add an efrag if the node is a leaf
 
if ( node->contents < 0)
{
if (ent->num_leafs == MAX_ENT_LEAFS)
return;
 
leaf = (mleaf_t *)node;
leafnum = leaf - sv.worldmodel->leafs - 1;
 
ent->leafnums[ent->num_leafs] = leafnum;
ent->num_leafs++;
return;
}
// NODE_MIXED
 
splitplane = node->plane;
sides = BOX_ON_PLANE_SIDE(ent->v.absmin, ent->v.absmax, splitplane);
// recurse down the contacted sides
if (sides & 1)
SV_FindTouchedLeafs (ent, node->children[0]);
if (sides & 2)
SV_FindTouchedLeafs (ent, node->children[1]);
}
 
/*
===============
SV_LinkEdict
 
===============
*/
void SV_LinkEdict (edict_t *ent, qboolean touch_triggers)
{
areanode_t *node;
 
if (ent->area.prev)
SV_UnlinkEdict (ent); // unlink from old position
if (ent == sv.edicts)
return; // don't add the world
 
if (ent->free)
return;
 
// set the abs box
 
#ifdef QUAKE2
if (ent->v.solid == SOLID_BSP &&
(ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2]) )
{ // expand for rotation
float max, v;
int i;
 
max = 0;
for (i=0 ; i<3 ; i++)
{
v =fabs( ent->v.mins[i]);
if (v > max)
max = v;
v =fabs( ent->v.maxs[i]);
if (v > max)
max = v;
}
for (i=0 ; i<3 ; i++)
{
ent->v.absmin[i] = ent->v.origin[i] - max;
ent->v.absmax[i] = ent->v.origin[i] + max;
}
}
else
#endif
{
VectorAdd (ent->v.origin, ent->v.mins, ent->v.absmin);
VectorAdd (ent->v.origin, ent->v.maxs, ent->v.absmax);
}
 
//
// to make items easier to pick up and allow them to be grabbed off
// of shelves, the abs sizes are expanded
//
if ((int)ent->v.flags & FL_ITEM)
{
ent->v.absmin[0] -= 15;
ent->v.absmin[1] -= 15;
ent->v.absmax[0] += 15;
ent->v.absmax[1] += 15;
}
else
{ // because movement is clipped an epsilon away from an actual edge,
// we must fully check even when bounding boxes don't quite touch
ent->v.absmin[0] -= 1;
ent->v.absmin[1] -= 1;
ent->v.absmin[2] -= 1;
ent->v.absmax[0] += 1;
ent->v.absmax[1] += 1;
ent->v.absmax[2] += 1;
}
// link to PVS leafs
ent->num_leafs = 0;
if (ent->v.modelindex)
SV_FindTouchedLeafs (ent, sv.worldmodel->nodes);
 
if (ent->v.solid == SOLID_NOT)
return;
 
// find the first node that the ent's box crosses
node = sv_areanodes;
while (1)
{
if (node->axis == -1)
break;
if (ent->v.absmin[node->axis] > node->dist)
node = node->children[0];
else if (ent->v.absmax[node->axis] < node->dist)
node = node->children[1];
else
break; // crosses the node
}
// link it in
 
if (ent->v.solid == SOLID_TRIGGER)
InsertLinkBefore (&ent->area, &node->trigger_edicts);
else
InsertLinkBefore (&ent->area, &node->solid_edicts);
// if touch_triggers, touch all entities at this node and decend for more
if (touch_triggers)
SV_TouchLinks ( ent, sv_areanodes );
}
 
 
 
/*
===============================================================================
 
POINT TESTING IN HULLS
 
===============================================================================
*/
 
#if !id386
 
/*
==================
SV_HullPointContents
 
==================
*/
int SV_HullPointContents (hull_t *hull, int num, vec3_t p)
{
float d;
dclipnode_t *node;
mplane_t *plane;
 
while (num >= 0)
{
if (num < hull->firstclipnode || num > hull->lastclipnode)
Sys_Error ("SV_HullPointContents: bad node number");
node = hull->clipnodes + num;
plane = hull->planes + node->planenum;
if (plane->type < 3)
d = p[plane->type] - plane->dist;
else
d = DotProduct (plane->normal, p) - plane->dist;
if (d < 0)
num = node->children[1];
else
num = node->children[0];
}
return num;
}
 
#endif // !id386
 
 
/*
==================
SV_PointContents
 
==================
*/
int SV_PointContents (vec3_t p)
{
int cont;
 
cont = SV_HullPointContents (&sv.worldmodel->hulls[0], 0, p);
if (cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN)
cont = CONTENTS_WATER;
return cont;
}
 
int SV_TruePointContents (vec3_t p)
{
return SV_HullPointContents (&sv.worldmodel->hulls[0], 0, p);
}
 
//===========================================================================
 
/*
============
SV_TestEntityPosition
 
This could be a lot more efficient...
============
*/
edict_t *SV_TestEntityPosition (edict_t *ent)
{
trace_t trace;
 
trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, 0, ent);
if (trace.startsolid)
return sv.edicts;
return NULL;
}
 
 
/*
===============================================================================
 
LINE TESTING IN HULLS
 
===============================================================================
*/
 
// 1/32 epsilon to keep floating point happy
#define DIST_EPSILON (0.03125)
 
/*
==================
SV_RecursiveHullCheck
 
==================
*/
qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace)
{
dclipnode_t *node;
mplane_t *plane;
float t1, t2;
float frac;
int i;
vec3_t mid;
int side;
float midf;
 
// check for empty
if (num < 0)
{
if (num != CONTENTS_SOLID)
{
trace->allsolid = false;
if (num == CONTENTS_EMPTY)
trace->inopen = true;
else
trace->inwater = true;
}
else
trace->startsolid = true;
return true; // empty
}
 
if (num < hull->firstclipnode || num > hull->lastclipnode)
Sys_Error ("SV_RecursiveHullCheck: bad node number");
 
//
// find the point distances
//
node = hull->clipnodes + num;
plane = hull->planes + node->planenum;
 
if (plane->type < 3)
{
t1 = p1[plane->type] - plane->dist;
t2 = p2[plane->type] - plane->dist;
}
else
{
t1 = DotProduct (plane->normal, p1) - plane->dist;
t2 = DotProduct (plane->normal, p2) - plane->dist;
}
#if 1
if (t1 >= 0 && t2 >= 0)
return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace);
if (t1 < 0 && t2 < 0)
return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace);
#else
if ( (t1 >= DIST_EPSILON && t2 >= DIST_EPSILON) || (t2 > t1 && t1 >= 0) )
return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace);
if ( (t1 <= -DIST_EPSILON && t2 <= -DIST_EPSILON) || (t2 < t1 && t1 <= 0) )
return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace);
#endif
 
// put the crosspoint DIST_EPSILON pixels on the near side
if (t1 < 0)
frac = (t1 + DIST_EPSILON)/(t1-t2);
else
frac = (t1 - DIST_EPSILON)/(t1-t2);
if (frac < 0)
frac = 0;
if (frac > 1)
frac = 1;
midf = p1f + (p2f - p1f)*frac;
for (i=0 ; i<3 ; i++)
mid[i] = p1[i] + frac*(p2[i] - p1[i]);
 
side = (t1 < 0);
 
// move up to the node
if (!SV_RecursiveHullCheck (hull, node->children[side], p1f, midf, p1, mid, trace) )
return false;
 
#ifdef PARANOID
if (SV_HullPointContents (sv_hullmodel, mid, node->children[side])
== CONTENTS_SOLID)
{
Con_Printf ("mid PointInHullSolid\n");
return false;
}
#endif
if (SV_HullPointContents (hull, node->children[side^1], mid)
!= CONTENTS_SOLID)
// go past the node
return SV_RecursiveHullCheck (hull, node->children[side^1], midf, p2f, mid, p2, trace);
if (trace->allsolid)
return false; // never got out of the solid area
//==================
// the other side of the node is solid, this is the impact point
//==================
if (!side)
{
VectorCopy (plane->normal, trace->plane.normal);
trace->plane.dist = plane->dist;
}
else
{
VectorSubtract (vec3_origin, plane->normal, trace->plane.normal);
trace->plane.dist = -plane->dist;
}
 
while (SV_HullPointContents (hull, hull->firstclipnode, mid)
== CONTENTS_SOLID)
{ // shouldn't really happen, but does occasionally
frac -= 0.1;
if (frac < 0)
{
trace->fraction = midf;
VectorCopy (mid, trace->endpos);
Con_DPrintf ("backup past 0\n");
return false;
}
midf = p1f + (p2f - p1f)*frac;
for (i=0 ; i<3 ; i++)
mid[i] = p1[i] + frac*(p2[i] - p1[i]);
}
 
trace->fraction = midf;
VectorCopy (mid, trace->endpos);
 
return false;
}
 
 
/*
==================
SV_ClipMoveToEntity
 
Handles selection or creation of a clipping hull, and offseting (and
eventually rotation) of the end points
==================
*/
trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end)
{
trace_t trace;
vec3_t offset;
vec3_t start_l, end_l;
hull_t *hull;
 
// fill in a default trace
memset (&trace, 0, sizeof(trace_t));
trace.fraction = 1;
trace.allsolid = true;
VectorCopy (end, trace.endpos);
 
// get the clipping hull
hull = SV_HullForEntity (ent, mins, maxs, offset);
 
VectorSubtract (start, offset, start_l);
VectorSubtract (end, offset, end_l);
 
#ifdef QUAKE2
// rotate start and end into the models frame of reference
if (ent->v.solid == SOLID_BSP &&
(ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2]) )
{
vec3_t a;
vec3_t forward, right, up;
vec3_t temp;
 
AngleVectors (ent->v.angles, forward, right, up);
 
VectorCopy (start_l, temp);
start_l[0] = DotProduct (temp, forward);
start_l[1] = -DotProduct (temp, right);
start_l[2] = DotProduct (temp, up);
 
VectorCopy (end_l, temp);
end_l[0] = DotProduct (temp, forward);
end_l[1] = -DotProduct (temp, right);
end_l[2] = DotProduct (temp, up);
}
#endif
 
// trace a line through the apropriate clipping hull
SV_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, &trace);
 
#ifdef QUAKE2
// rotate endpos back to world frame of reference
if (ent->v.solid == SOLID_BSP &&
(ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2]) )
{
vec3_t a;
vec3_t forward, right, up;
vec3_t temp;
 
if (trace.fraction != 1)
{
VectorSubtract (vec3_origin, ent->v.angles, a);
AngleVectors (a, forward, right, up);
 
VectorCopy (trace.endpos, temp);
trace.endpos[0] = DotProduct (temp, forward);
trace.endpos[1] = -DotProduct (temp, right);
trace.endpos[2] = DotProduct (temp, up);
 
VectorCopy (trace.plane.normal, temp);
trace.plane.normal[0] = DotProduct (temp, forward);
trace.plane.normal[1] = -DotProduct (temp, right);
trace.plane.normal[2] = DotProduct (temp, up);
}
}
#endif
 
// fix trace up by the offset
if (trace.fraction != 1)
VectorAdd (trace.endpos, offset, trace.endpos);
 
// did we clip the move?
if (trace.fraction < 1 || trace.startsolid )
trace.ent = ent;
 
return trace;
}
 
//===========================================================================
 
/*
====================
SV_ClipToLinks
 
Mins and maxs enclose the entire area swept by the move
====================
*/
void SV_ClipToLinks ( areanode_t *node, moveclip_t *clip )
{
link_t *l, *next;
edict_t *touch;
trace_t trace;
 
// touch linked edicts
for (l = node->solid_edicts.next ; l != &node->solid_edicts ; l = next)
{
next = l->next;
touch = EDICT_FROM_AREA(l);
if (touch->v.solid == SOLID_NOT)
continue;
if (touch == clip->passedict)
continue;
if (touch->v.solid == SOLID_TRIGGER)
Sys_Error ("Trigger in clipping list");
 
if (clip->type == MOVE_NOMONSTERS && touch->v.solid != SOLID_BSP)
continue;
 
if (clip->boxmins[0] > touch->v.absmax[0]
|| clip->boxmins[1] > touch->v.absmax[1]
|| clip->boxmins[2] > touch->v.absmax[2]
|| clip->boxmaxs[0] < touch->v.absmin[0]
|| clip->boxmaxs[1] < touch->v.absmin[1]
|| clip->boxmaxs[2] < touch->v.absmin[2] )
continue;
 
if (clip->passedict && clip->passedict->v.size[0] && !touch->v.size[0])
continue; // points never interact
 
// might intersect, so do an exact clip
if (clip->trace.allsolid)
return;
if (clip->passedict)
{
if (PROG_TO_EDICT(touch->v.owner) == clip->passedict)
continue; // don't clip against own missiles
if (PROG_TO_EDICT(clip->passedict->v.owner) == touch)
continue; // don't clip against owner
}
 
if ((int)touch->v.flags & FL_MONSTER)
trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins2, clip->maxs2, clip->end);
else
trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins, clip->maxs, clip->end);
if (trace.allsolid || trace.startsolid ||
trace.fraction < clip->trace.fraction)
{
trace.ent = touch;
if (clip->trace.startsolid)
{
clip->trace = trace;
clip->trace.startsolid = true;
}
else
clip->trace = trace;
}
else if (trace.startsolid)
clip->trace.startsolid = true;
}
// recurse down both sides
if (node->axis == -1)
return;
 
if ( clip->boxmaxs[node->axis] > node->dist )
SV_ClipToLinks ( node->children[0], clip );
if ( clip->boxmins[node->axis] < node->dist )
SV_ClipToLinks ( node->children[1], clip );
}
 
 
/*
==================
SV_MoveBounds
==================
*/
void SV_MoveBounds (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, vec3_t boxmins, vec3_t boxmaxs)
{
#if 0
// debug to test against everything
boxmins[0] = boxmins[1] = boxmins[2] = -9999;
boxmaxs[0] = boxmaxs[1] = boxmaxs[2] = 9999;
#else
int i;
for (i=0 ; i<3 ; i++)
{
if (end[i] > start[i])
{
boxmins[i] = start[i] + mins[i] - 1;
boxmaxs[i] = end[i] + maxs[i] + 1;
}
else
{
boxmins[i] = end[i] + mins[i] - 1;
boxmaxs[i] = start[i] + maxs[i] + 1;
}
}
#endif
}
 
/*
==================
SV_Move
==================
*/
trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, edict_t *passedict)
{
moveclip_t clip;
int i;
 
memset ( &clip, 0, sizeof ( moveclip_t ) );
 
// clip to world
clip.trace = SV_ClipMoveToEntity ( sv.edicts, start, mins, maxs, end );
 
clip.start = start;
clip.end = end;
clip.mins = mins;
clip.maxs = maxs;
clip.type = type;
clip.passedict = passedict;
 
if (type == MOVE_MISSILE)
{
for (i=0 ; i<3 ; i++)
{
clip.mins2[i] = -15;
clip.maxs2[i] = 15;
}
}
else
{
VectorCopy (mins, clip.mins2);
VectorCopy (maxs, clip.maxs2);
}
// create the bounding box of the entire move
SV_MoveBounds ( start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs );
 
// clip to entities
SV_ClipToLinks ( sv_areanodes, &clip );
 
return clip.trace;
}
 
/contrib/other/sdlquake-1.0.9/world.h
0,0 → 1,78
/*
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.
 
*/
// world.h
 
typedef struct
{
vec3_t normal;
float dist;
} plane_t;
 
typedef struct
{
qboolean allsolid; // if true, plane is not valid
qboolean startsolid; // if true, the initial point was in a solid area
qboolean inopen, inwater;
float fraction; // time completed, 1.0 = didn't hit anything
vec3_t endpos; // final position
plane_t plane; // surface normal at impact
edict_t *ent; // entity the surface is on
} trace_t;
 
 
#define MOVE_NORMAL 0
#define MOVE_NOMONSTERS 1
#define MOVE_MISSILE 2
 
 
void SV_ClearWorld (void);
// called after the world model has been loaded, before linking any entities
 
void SV_UnlinkEdict (edict_t *ent);
// call before removing an entity, and before trying to move one,
// so it doesn't clip against itself
// flags ent->v.modified
 
void SV_LinkEdict (edict_t *ent, qboolean touch_triggers);
// Needs to be called any time an entity changes origin, mins, maxs, or solid
// flags ent->v.modified
// sets ent->v.absmin and ent->v.absmax
// if touchtriggers, calls prog functions for the intersected triggers
 
int SV_PointContents (vec3_t p);
int SV_TruePointContents (vec3_t p);
// returns the CONTENTS_* value from the world at the given point.
// does not check any entities at all
// the non-true version remaps the water current contents to content_water
 
edict_t *SV_TestEntityPosition (edict_t *ent);
 
trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, edict_t *passedict);
// mins and maxs are reletive
 
// if the entire move stays in a solid volume, trace.allsolid will be set
 
// if the starting point is in a solid, it will be allowed to move out
// to an open area
 
// nomonsters is used for line of sight or edge testing, where mosnters
// shouldn't be considered solid objects
 
// passedict is explicitly excluded from clipping checks (normally NULL)
/contrib/other/sdlquake-1.0.9/worlda.S
0,0 → 1,144
/*
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.
 
*/
//
// worlda.s
// x86 assembly-language server testing stuff
//
 
#define GLQUAKE 1 // don't include unneeded defs
#include "asm_i386.h"
#include "quakeasm.h"
#include "d_ifacea.h"
 
#if id386
 
.data
 
Ltemp: .long 0
 
.text
 
//----------------------------------------------------------------------
// hull-point test
//----------------------------------------------------------------------
 
#define hull 4+8 // because only partially pushed
#define num 8+4 // because only partially pushed
#define p 12+12 // because only partially pushed
 
.align 4
.globl C(SV_HullPointContents)
C(SV_HullPointContents):
pushl %edi // preserve register variables
movl num(%esp),%eax
testl %eax,%eax
js Lhquickout
 
// float d;
// dclipnode_t *node;
// mplane_t *plane;
 
pushl %ebx
movl hull(%esp),%ebx
 
pushl %ebp
movl p(%esp),%edx
 
movl hu_clipnodes(%ebx),%edi
movl hu_planes(%ebx),%ebp
 
subl %ebx,%ebx
pushl %esi
 
// %ebx: 0
// %eax: num
// %edx: p
// %edi: hull->clipnodes
// %ebp: hull->planes
 
// while (num >= 0)
// {
 
Lhloop:
 
// node = hull->clipnodes + num;
// plane = hull->planes + node->planenum;
// !!! if the size of dclipnode_t changes, the scaling of %eax needs to be
// changed !!!
movl nd_planenum(%edi,%eax,8),%ecx
movl nd_children(%edi,%eax,8),%eax
movl %eax,%esi
rorl $16,%eax
leal (%ecx,%ecx,4),%ecx
 
// if (plane->type < 3)
// d = p[plane->type] - plane->dist;
movb pl_type(%ebp,%ecx,4),%bl
cmpb $3,%bl
jb Lnodot
 
// else
// d = DotProduct (plane->normal, p) - plane->dist;
flds pl_normal(%ebp,%ecx,4)
fmuls 0(%edx)
flds pl_normal+4(%ebp,%ecx,4)
fmuls 4(%edx)
flds pl_normal+8(%ebp,%ecx,4)
fmuls 8(%edx)
fxch %st(1)
faddp %st(0),%st(2)
faddp %st(0),%st(1)
fsubs pl_dist(%ebp,%ecx,4)
jmp Lsub
 
Lnodot:
flds pl_dist(%ebp,%ecx,4)
fsubrs (%edx,%ebx,4)
 
Lsub:
sarl $16,%eax
sarl $16,%esi
 
// if (d < 0)
// num = node->children[1];
// else
// num = node->children[0];
fstps Ltemp
movl Ltemp,%ecx
sarl $31,%ecx
andl %ecx,%esi
xorl $0xFFFFFFFF,%ecx
andl %ecx,%eax
orl %esi,%eax
jns Lhloop
 
// return num;
Lhdone:
popl %esi
popl %ebp
popl %ebx // restore register variables
 
Lhquickout:
popl %edi
 
ret
 
#endif // id386
 
/contrib/other/sdlquake-1.0.9/wq.bat
0,0 → 1,42
@echo off
if x%1==xfast goto fast
if x%1==xsafe goto safe
if x%1==xverysafe goto verysafe
if x%1==xfastvid goto fastvid
if x%1==xfastsnd goto fastsnd
if x%1==xmax goto max
 
echo -------------------------------------------------------------------
echo Options for running WinQuake:
echo wq max: all features on, but doesn't work on all systems
echo wq fast: maximum speed, but doesn't work on all systems
echo wq fastvid: maximum video speed, but safer, probably slower sound
echo wq fastsnd: maximum sound speed, but safer, probably slower video
echo wq safe: very likely to run, but may be slower
echo wq verysafe: almost sure to run, but probably slower, and no sound
echo -------------------------------------------------------------------
goto done
 
:max
winquake -dinput %2 %3 %4 %5 %6 %7 %8 %9
goto done
 
:fast
winquake %2 %3 %4 %5 %6 %7 %8 %9
goto done
 
:fastvid
winquake -wavonly %2 %3 %4 %5 %6 %7 %8 %9
goto done
 
:fastsnd
winquake -nodirectdraw -nowindirect %2 %3 %4 %5 %6 %7 %8 %9
goto done
 
:safe
winquake -nodirectdraw -nowindirect -wavonly %2 %3 %4 %5 %6 %7 %8 %9
goto done
 
:verysafe
winquake -dibonly -nosound -nojoy %2 %3 %4 %5 %6 %7 %8 %9
:done
/contrib/other/sdlquake-1.0.9/wqreadme.txt
0,0 → 1,1119
--------------------------
| wqreadme.txt |
| WinQuake documentation |
| 3/21/97 |
--------------------------
 
WinQuake (WQ) is a native Win32 version of Quake, and will run on
either Win95 or Windows NT 4.0 or later. It is designed to take
advantage of whatever enhanced video, sound, and input capabilities
(such as DirectX or VESA VBE video modes) are present, but has
fallback functionality so it can run on any Win95 or NT 4.0 or later
system, even if neither DirectX nor VESA VBE is available. You may
experience problems running WQ on some systems, because driver and
operating-system support for game functionality are not yet mature
under Win32, and many bugs and incompatibilities remain in those
components. If you encounter what seems to be a bug, first please
check through the list of known problems, below. If your problem
doesn't appear on the list, please fill out and submit the WQ bug
report at http://www.idsoftware.com/contact/.
 
The material accompanying Quake is the reference for all
non-Windows-related matters concerning WinQuake; in terms of gameplay,
WQ is the same as Quake. This file contains Windows-related
information only.
 
The rest of this document is organized as follows:
 
Installing and running WinQuake
Common problems and workarounds
A bit about how WQ video works
Video command-line switches
A bit about how WQ sound works
Sound command-line switches
Notes on networking
Notes on the mouse
Log of changes to documentation
Special thanks
 
 
-----------------------------------
| Installing and running WinQuake |
-----------------------------------
 
In order to run WinQuake, you must first have Quake installed.
Assuming Quake is installed in the standard directory, c:\quake,
unzip the WinQuake zip file into c:\quake. The following files
from the zip file must be present in order for WQ to run:
 
winquake.exe
pmpro16.dll
pmpro32.dll
wdir16.dll
wdir32.dll
wdirnop.com
wdirnop.pif
 
Then you can run WinQuake by making c:\quake the current directory,
typing "winquake" and pressing the Enter key. Alternatively, you can
use wq.bat to run WinQuake. The wq batch file requires one parameter
describing how to configure WQ for performance; just type "wq" to get
a list of the six options. The first of the six options is
 
wq fast
 
This is the same as typing "winquake"; this runs WinQuake in an
aggressive configuration that is likely to yield the best performance
if it runs successfully on your system, but which has a risk of
causing WinQuake or even your system to crash if there are bugs or
incompatibilities in your video or sound drivers. Alternatively, you
can use
 
wq safe
 
to run WinQuake in a conservative configuration, likely to run
on almost all machines with no problems, but possibly with slower
graphics, fewer high-resolution modes, and delayed sound. Or you
can run
 
wq verysafe
 
to run WinQuake in a very conservative configuration that is pretty
much guaranteed to run, but will probably have slow performance, and
will have no sound. Two other options are
 
wq fastvid
 
which has maximum video performance, but greater sound latency (delay
until the sound is heard), and
 
wq fastsnd
 
which uses more conservative video modes, but low-latency sound.
 
(One odd note is that DirectSound has much lower-latency sound than
wave sound, but is currently quite a bit slower overall. Thus you
may find that "wq fastvid" is actually faster, by as much as 5-10%,
than "wq fast"; however, it may not feel faster, because the sound
will lag.)
 
Finally, you can use
 
wq max
 
which is the same as wq fast, but turns on DirectInput, which
provides more responsive mouse control, but does not work properly
on all systems.
 
Note that DirectX is not required for WQ to run, but WQ will
automatically take advantage of DirectSound and DirectDraw if they
are present. If DirectSound is not present, there will generally be
considerable sound latency (sound will become audible several hundred
milliseconds after the event that caused it). Note also that there
are currently no true DirectSound drivers for Windows NT, so WQ will
always run using wave output on NT, and will consequently have lagged
sound. See below for information about obtaining DirectX if you do
not have it.
 
Note that VESA VBE modes aren't required for WQ to run, but WQ will
automatically make VESA modes available if they're present. Your BIOS
may already have VESA VBE 2.0 support built in, but most BIOSes
don't. Worse, some BIOSes do have VESA VBE 2.0 built-in, but have
buggy implementations, which may prevent you from being able to run
the faster configurations of WQ. An easy way to get reliable VESA 2.0
support is by obtaining SciTech Display Doctor; see below for
further information. WQ can also use VBE/AF 1.0 and greater modes;
again, SciTech Display Doctor is the commonest way to get VBE/AF
support.
 
Note that winquake -dedicated completely replaces the old winded
dedicated Win32 server, which is now obsolete.
 
WinQuake normally uses half the physical memory in your system for its
heap, but not less than 8.5 Mb and not more than 16 Mb. You can
override this with "-heapsize n", where n is the amount of memory to
allocate for the heap, in Kb.
 
To use the joystick, you must bring down the console by pressing the
tilde ('~') key, and type "joystick 1<enter>"; you can disable the
joystick with "joystick 0<enter>" at any time. The joystick setting
remains in effect for subsequent WinQuake sessions until changed, so
you only need to do joystick 1 once to enable the joystick. If the
joystick somehow causes problems that keep you from being able to run
WinQuake at all, you can start WinQuake -nojoy to complete disable the
joystick for that session.
 
 
-----------------------------------
| Common problems and workarounds |
-----------------------------------
 
WQ crashes or won't run
-----------------------
 
If WQ refuses to run or crashes on your system, try running
it using "wq safe" or "wq verysafe". Or you can use command-line
switches:
 
winquake -nodirectdraw -nowindirect -wavonly
 
This will almost certainly solve your problem; however, it may result
in lagged sound (a long delay from action to hearing the sound), may
result in fewer or slower high-res video modes, and the mouse may be
somewhat less responsive. If this does work, you can try removing
each of the command-line switches until you identify the one that
fixes the problem, thereby sacrificing as little functionality as
possible.
 
If the above command line does not fix your problems, try:
 
winquake -dibonly -nosound
 
which forces WQ into silent operation with bare-bones video support
and no use of DirectInput for mouse input (the normal Windows mouse
APIs are used instead). Again, if this works, try removing switches
until you identify the needed one.
 
Both of the above command lines are quick fixes. Often, the problem
is caused by outdated or buggy DirectX drivers or code, and can
frequently be completely fixed simply by installing the latest
Microsoft-supplied version of DirectX, which you may be able to find
on http://www.microsoft.com/mediadev/download/directx.exe, although
the availability and location of the DirectX file changes
periodically; note that at last check, this is a 3.4 Mb file. (Be
aware, though, that sometimes Microsoft's DirectX drivers don't
support features that the manufacturers' drivers do support, such as
display refresh rate control.)
 
One known problem of this sort involves the current SB16 drivers from
Creative Labs, which cause WQ to crash on some machines. The
DirectSound drivers from Microsoft, available via the above-mentioned
URL, fix this problem.
 
It can also sometimes help to get the latest Windows drivers for your
video adapter or sound card (although as the SB16 example indicates,
this is not always a good idea), and for video boards that have flash
BIOSes, it can sometimes help to get the latest BIOS upgrade.
 
 
How do I select fullscreen or windowed WQ operation?
----------------------------------------------------
Check out WQ's new, spiffy Video menu, accessible from the Options
menu. There are now two types of modes listed, windowed and
fullscreen. You can make any of these modes the current and/or
default mode, just as in DOS Quake. If you make a windowed mode the
default, WQ will still briefly start up in fullscreen mode, then
switch to windowed; if this is a problem, use the -startwindowed
command-line switch. More complete video control is available
through the console, as described in the "A bit about how WQ video
works" section, below.
 
 
Gee, I wish I could use a mouse to play WQ with in a window
-----------------------------------------------------------
You can! While in a windowed mode, go to the Options menu. At the
bottom, you'll find a new selection that lets you choose to have the
mouse active when you're in a window. Of course, if you do this,
you'll have to use the keyboard (Alt-Tab, the Windows key, Ctrl-Esc,
Alt-Esc, or Shift-Alt-Tab) to switch away from WQ.
 
 
Serial/modem menu is missing
----------------------------
WQ currently does not support direct connect serial or modem play.
 
 
DOS Quake reports unknown variables on startup after running WQ
---------------------------------------------------------------
WQ uses some console variables that do not exist in DOS Quake, and
some of these are automatically archived in config.cfg when you exit
WQ. If you then start DOS Quake, DOS Quake will complain that it
doesn't recognize those variables. You will also lose the settings
of these variables when you return to WQ. Apart from losing the
settings, this is harmless; ignore it.
 
 
Problems running WQ on NT 3.51
------------------------------
NT 3.51 isn't supported by WQ.
 
 
WQ crashes while switching modes or Alt-Tabbing
-----------------------------------------------
So far, all cases of this seem to be tied to Creative Lab's SB16 sound
drivers, and have been fixed by getting the latest DirectX drivers, as
described above. Alternatively, you should be able to fix this either
by not switching modes or Alt-Tabbing, or by running -wavonly to
disable DirectSound support.
 
 
WQ sometimes runs pretty slowly fullscreen
------------------------------------------
There are several possible reasons for this, starting with "You have a
slow computer." Assuming that's not the case, if you don't have
either DirectDraw or SciTech Display Doctor installed (see the "A bit
about how WQ video works" section), it would probably be a good thing
to install one or the other, because slow operation can be a result
of slow copying or stretching of pixels to the screen by a Windows
driver, something that's eliminated by both DirectDraw and Display
Doctor. You can also sometimes get a faster 320x200 mode on Win95 by
doing vid_describemodes, then using vid_mode to select a non-VGA
320x200 mode, as described in the "A bit about how WQ video works"
section.
 
You can also try using a primary sound buffer on Win95 (this doesn't
work on NT) by using the -primarysound command-line switch; this can
improve performance by several percent, but does not work on all
systems, and can result in odd sound effects on some systems when
minimizing WQ or switching the focus away from it. If you use this
switch, please don't report sound bugs; it's in there purely for you
to use if it helps you, and we know it has problems on many systems.
Finally, you can use -wavonly to select wave sound; this will increase
your sound latency (sounds will be heard later than they should), but
allows WQ to run 5-10% faster on some systems. That's about all you
can do to speed up fullscreen WQ on Win95, other than shrinking the
active area of the screen with the screen size control in the Options
menu.
 
NT 4.0 comes with DirectX installed, but doesn't have any resolutions
lower than 640x480. In order to support a lower-resolution 320x240
mode, WQ has NT double each pixel in both directions to get enough
pixels for 640x480. The extra stretching costs some performance, the
result being that NT can seem sluggish on all but high-end Pentiums
and Pentium Pros. (In fact, depending on the quality of your driver's
stretching code, it can sometimes be faster to run WQ at 640x480 than
320x240-stretched on NT.) One thing that can help on NT is switching
to 640x480, then using the Options menu to shrink the active area of
the screen.
 
A common cause of slowness running in a window is having the desktop
run in 16- or 32-bpp mode. WQ is an 8-bpp application, and it slows
things down if pixels have to be translated from 8-bpp to 16- or
32-bpp. (Note that this is generally a problem only when running in a
window; fullscreen apps rarely suffer from this.)
 
 
Sound is sluggish on NT
-----------------------
NT doesn't have any real DirectSound drivers yet, so there's no way to
do quick-response sound on NT. When DirectSound drivers for NT
appear, WQ's sound should automatically be snappier.
 
 
Sound breaks up or gets choppy, especially in menus
---------------------------------------------------
This is generally a sign that WQ's frame rate is too low on your
system. Try reducing resolution or shrinking the active area of the
screen. In some circumstances, it may help to set the console
variable _snd_mixahead to a larger value.
 
 
The color black doesn't change with palette flashes sometimes
-------------------------------------------------------------
Normally, DirectDraw lets WQ change all 256 colors, so when a palette
flash happens, we can change all the colors, including black.
However, on NT DirectDraw currently doesn't allow changing black;
likewise, on both NT and Win95, black can't be changed in a window,
either a normal window or fullscreen. Consequently, in some modes and
in a window, some parts of the WQ screen (such as the sigils on the
status bar and the spray where a shotgun blast hits) stay black when
the palette flashes. There is no workaround.
 
 
Problems can result if Office shortcut bar is running
-----------------------------------------------------
Various odd behaviors, especially with sound, have been reported if
the Office shortcut bar is running while WQ is running. If you
experience odd problems, you might try shutting down the Office
shortcut bar and see if that fixes anything.
 
 
Other apps fail to play sound while WinQuake is running
-------------------------------------------------------
The sound hardware is currently not a fully shareable resource on
Win32. Consequently, while WQ is running, it always has the sound
hardware allocated to itself, to make sure that sound is never lost to
another app. This means that normally (when WQ is using DirectSound),
apps that use wave sound (most non-game apps) will not be able to play
sound while WQ is running, even if WQ is minimized or not the active
app, although other DirectSound apps will be able to play sound when
WQ is not the active app. If WQ is using wave sound rather than
DirectSound (either because -wavonly is used on the command line, or
because there is no DirectSound driver, as is always the case on NT),
then no other app will be able to play any sound while WQ is running,
period.
 
 
WQ doesn't have quite the right colors when itÂ’s not the active app
-------------------------------------------------------------------
We're working on fixing this. But WQ puts everything back again as
soon as it is reactivated, and anyway, when itÂ’s not active, you canÂ’t
actually do anything in WQ, so it doesnÂ’t really matter anyway, right?
 
 
Desktop is weird colors when WQ runs windowed
---------------------------------------------
WQ needs all 256 colors to look right and run fast, which causes it to
have to change some of the 20 colors used to draw the desktop.
 
 
Sometimes Permedia boards crash unless -nowindirect is used
-----------------------------------------------------------
It looks like this is probably a Permedia driver bug, so it might help
if you get the most recent drivers.
 
 
Right-click on WQ button in task bar to close doesnÂ’t work as expected
----------------------------------------------------------------------
In some modes, right-clicking on the WQ task bar button doesn't work
the way you'd expect. We're trying to fix this, but if it's a
problem, don't right-click.
 
 
Screen saver never kicks in when running WQ fullscreen
------------------------------------------------------
It does work windowed, but when WinQuake is fullscreen, it completely
owns the screen and doesn't share it with anyone, even the
screensaver. If you use Alt-Tab to minimize WQ, the screensaver will
then be enabled, so Alt-Tab away from WQ if you're leaving your
computer alone for a while and want the screensaver to be able to kick
in.
 
 
WQ doesnÂ’t work in a window in 16-color mode
--------------------------------------------
ThatÂ’s 16 *colors*, not 16-bpp. If youÂ’re still running a 16-color
desktop, run WQ fullscreen.
 
 
Can't minimize window while mouse active
----------------------------------------
When running in a window with the mouse active as a WQ input device,
there is no easy way to minimize the window, because the system menu
can't be brought up from the keyboard (because some of you use Alt
and Spacebar for playing the game), and the mouse can't be used to
manipulate the window because it's controlling WQ. To minimize, you
can disable the mouse for WQ and use it to minimize the window. Or
on Win95 you can Alt-Tab away from WQ, then use the mouse to
minimize (this doesn't work on NT, where clicking on the window
controls just reactivates WQ). Or you can bind a key to the
vid_minimize command, as in
 
bind m "vid_minimize"
 
and press that key to minimize the window.
 
 
Window controls don't work on NT when mouse enabled
---------------------------------------------------
When running in a window on NT with the mouse enabled (so you can use
the mouse to play WQ), if you Alt-Tab away from WQ, then use the mouse
to click on the WQ system menu control, or the minimize, maximize, or
close controls, the controls are ignored and WQ just reactivates.
 
 
Mouse sometimes vanishes in system menu on Win95
------------------------------------------------
On Win95, if WQ is running in a window with the mouse enabled (so you
can use the mouse to play WQ), if you Alt-Tab away, then click on the
system menu, the menu comes up, but the mouse vanishes. However, you
can still use the keyboard to select system menu items, or to exit
the system menu.
 
 
WQ behaves oddly if Scandisk starts defragmenting
-------------------------------------------------
If WQ is running fullscreen on Win95 when Scandisk starts an automatic
defragging, WQ is forced to minimize, and when it is brought back up,
may either be in a strange mode where it runs one frame for each
keystroke (in which case Alt-Tab generally fixes things), or may hang
the system. We don't know what the problem is right now, but you may
want to make sure you don't leave WQ sitting there fullscreen
overnight if you have automatic defragging.
 
 
Hang reported with zero sound volume
------------------------------------
When sound is turned all the way down via the WQ menus, hangs have
been reported.
 
 
Joystick worked fine with earlier versions of WinQuake but not now
------------------------------------------------------------------
The joystick was enabled by default in earlier versions of
WinQuake, but quite a few people reported serious problems that
forced them to disable the joystick--even some people who didn't
have a joystick attached. Since most people don't have joysticks,
we've decided to disable the joystick by default, and let people
who do want to use it set joystick 1 in the console (WinQuake
remembers this setting, so this only needs to be done once).
 
 
WQ runs very slowly when it has the focus under NT
--------------------------------------------------
In one case, WQ ran very slowly when it had the focus, but fast when
it didn't (obviously this is only visible in windowed modes). The
problem turned out to be that NT had a Sidewinder 3D Pro joystick
driver installed; when the driver was removed, things were fine.
If you see a similar problem, check whether WQ is detecting that
your system has a joystick when you don't think it should; if so,
try doing "joystick 0", or -nojoy on the command line, and see if
that fixes it. If so, there's something flaky in your system
joystick setup.
 
 
Joystick doesn't seem calibrated properly
-----------------------------------------
WQ relies on the information about your joystick stored in the
system registry. If the joystick seems miscalibrated, run the
joystick applet and recalibrate and see if that fixes things.
 
 
Playdemo fails across multiple levels
-------------------------------------
If "record" is used to record a client-side demo, bad things will
happen on playback via playdemo if a level change is recorded.
(Timedemo works fine.) This is unfortunate, but WinQuake
internals make this not fixable without a good chance of
breaking something more important, so it'll have to stay this way.
 
 
Alt-Tab fullscreen only works sometimes
---------------------------------------
I know it seems that way, but actually the trick is that on Win95
it only works if you let go of Tab before you let go of Alt.
This is due to a Windows quirk involving what key sequences are
passed along, so you'll have to work around it by remembering to
let go of Tab first.
 
 
MS-DOS windows get scrunched on Alt-Tab
---------------------------------------
This is a quirk of Windows; when you run WinQuake in a low-res
mode, sometimes when you exit WinQuake or Alt-Tab back to the
desktop, any open MS-DOS windows will be scrunched down to the
size of the low-res mode. There is no known workaround.
 
 
Dprint in progs doesn't work
----------------------------
Dprint means "developer print," so it only works if the developer
console variable is set to 1. It was a bug in earlier versions that
it worked even when developer was set to 0.
 
 
Some DirectDraw modes flicker badly and look wrong
--------------------------------------------------
Page flipping doesn't work properly in some modes on some
systems, particularly when using some DirectDraw modes. You
can work around this by setting the console variable
vid_nopageflip to 1, then setting the desired mode (note
that the vid_nopageflip setting does not take effect until
the next mode set after the setting is changed). Bear in
mind, though, that the vid_nopageflip setting is remembered
until it is explicitly changed again, meaning that once you
change it, it thereafter applies to all modes, even if you
exit and restart WinQuake.
 
 
The Windows key doesn't do anything fullscreen on Win95
-------------------------------------------------------
True. This is a minor bug we haven't figured out how to fix yet.
You'll have to use Ctrl-Esc, Alt-Tab, or Alt-Esc to switch away.
 
 
My default mode is windowed, but WQ goes fullscreen first
---------------------------------------------------------
For internal reasons, WQ has to pick a single mode to always
initialize when it starts up, before it sets whatever default you've
selected. We've chosen fullscreen mode, because that's the way most
people will play. If this is a problem for you, however, you can
run WQ with the -startwindowed command-line parameter.
 
 
Some high-resolution video modes flicker or fail to initialize
--------------------------------------------------------------
We think these problems are all fixed, but if not, they have to
do with triple-buffering in some modes on some DirectDraw drivers.
If you encounter this problem, either don't use the problem modes
or try using the -notriplebuf command-line parameter to turn off
triple buffering. Note, though, that turning off triple-buffering
can reduce performance in some modes, so do this only if needed.
 
 
Right-click doesn't work right on minimized WinQuake
----------------------------------------------------
If you right-click on minimized WinQuake on the task bar, the
Close selection in the right-click menu doesn't work; you have
to restore WQ before you can exit it. Also, the cursor vanishes
over the right-click menu, although it still works.
 
 
The screen briefly blanks when you exit WQ
------------------------------------------
We're trying to fix this, but it's not harmful, just a mite ugly.
 
 
QBENCH doesn't work with WinQuake
---------------------------------
We've had a report that QBENCH doesn't work with WinQuake, but
haven't had a chance to look into it yet.
 
 
MWAVE sound loses focus
-----------------------
We've had a report that on a ThinkPad with MWAVE sound, WQ loses
sound focus (and thus sound) every few seconds.
 
 
Desktop doesn't reset to proper resolution on WQ exit
-----------------------------------------------------
We've had a report that on exiting WQ, the desktop didn't reset
to the proper dimensions. This may be a bug with the Matrox
drivers, but we're not sure. If it's a problem and newer
drivers don't fix it, you can run -dibonly, which solves the
problem but can cost some performance.
 
 
Palette goes bad periodically on #9 Imagine card
------------------------------------------------
There's only one report of this, so maybe it's a flaky board,
or maybe it's a driver bug. Newer drivers might help.
 
 
System with Packard Bell sound card III crashes on CapsLock
-----------------------------------------------------------
This appears to be the result of buggy DirectSound drivers;
-wavonly makes the problem go away.
 
 
Dvorak keyboard mapping ignored
-------------------------------
WQ is hardwired for QWERTY.
 
 
Cursor messed up after running WQ
---------------------------------
This is a Windows driver bug; the driver isn't restoring the
cursor properly on return from fullscreen WQ to the desktop.
Try newer drivers.
 
 
Dedicated server runs very slowly while typing at console
---------------------------------------------------------
When you type at a dedicated server's console, the game runs
very slowly for everyone who's connected.
 
 
Ctrl-Alt-Del on NT sometimes doesn't allow return to WQ
-------------------------------------------------------
This happens on some machines while running WQ fullscreen.
If you experience this problem, the only workaround is not
to press Ctrl-Alt-Del while fullscreen; Alt-Tab away first.
 
 
Many fast Alt-Tabs on Win95 sometimes disable WQ input
------------------------------------------------------
If you Alt-Tab fast lots of times on Win95 with WQ running
fullscreen, sometimes you end up in fullscreen WQ, with the
game not accepting any keyboard input (so there's no way to
exit). The only workaround is to not do lots of fast
Alt-Tabs (why you'd want to, I'm not sure).
 
 
 
----------------------------------
| A bit about how WQ video works |
----------------------------------
 
WQ has the built-in ability to draw into windows (both normal, framed
desktop windows and fullscreen, borderless windows). It also has
built- in support for VGA 320x200 graphics, and supports DirectDraw,
VESA VBE 2.0 and VESA VBE/AF (Accelerator Functions) graphics modes,
if those are available.
 
WQ does not require DirectDraw, but in order for DirectDraw modes to
be available, you must have DirectDraw installed; some systems come
with it preinstalled, but if it's not on your system, you can download
it from http://www.microsoft.com/mediadev/download/directx.exe (the
exact URL may vary), and install it.
 
WQ does not require VESA VBE, but in order for VESA VBE modes to be
available, your graphics card must be VESA VBE 2.0 or VBE/AF
compliant; a VESA driver can either be built into the BIOS of your
graphics card, or loadable via software. If you don't have a VESA VBE
driver, Scitech Display Doctor, available from Scitech Software, will
update most graphics cards to VESA VBE 2.0 and VBE/AF.
 
 
SciTech Display Doctor
----------------------
If you are having problems with your video drivers, or if you would
like to take a shot at improving your video performance in WQ, you may
want to try out SciTech Display Doctor (SDD). SDD works on just about
any graphics card and it can do several things that can make WQ run
better on your system:
 
1. It will update your graphics card to be compatible with VESA VBE
2.0 and VESA VBE/AF (Accelerator Functions). These modes will usually
give you the best performance in WQ (which is often but not always
faster than your current performance).
 
2. It creates low-resolution modes on your graphics card.
Low-resolution video modes (such as 320x240, 400x300 and 512x384)
allow you to adjust the level of detail in WQ so you can get the best
balance between performance and image quality.
 
The latest version of SciTech Display Doctor can be obtained from the
following locations:
 
www: http://www.scitechsoft.com
ftp: ftp.scitechsoft.com
CIS: GO SCITECH
AOL: Keyword SciTech
 
SciTech can be contacted at:
 
email: info@scitechsoft.com
 
SciTech Software, Inc.
505 Wall Street
Chico, CA 95926-1989
916-894-8400
916-894-9069 FAX
 
 
Video modes supported in Win95
------------------------------
What all this means is that on Win95, WQ will always be able to run in
the following modes:
 
1) in a window
2) fullscreen 320x200 VGA mode 0x13
3) fullscreen high-resolution of some sort
 
Category #3 can be any of several configurations. On Win95, if either
DirectDraw or VESA VBE modes are available, then all the DirectDraw
and VESA modes will be presented as high-res choices. (320x200 will
always default to VGA mode 0x13.) In the case that a given resolution
is supported by both DirectDraw and VESA, the VESA mode will be used.
(However, the command-line switch -nowindirect can turn off VESA modes
entirely.) If neither DirectDraw nor VESA modes are available, then
high-resolution modes will be provided by using fullscreen, borderless
windows in whatever resolutions the Windows driver supports, usually
starting at 640x480 and going up.
 
 
Video Modes Supported in Windows NT
-----------------------------------
NT is similar but not identical, because neither VESA VBE modes nor
VGA mode 0x13 are available. On NT, WQ will always be able to run in
the following modes:
 
1) in a window
2) fullscreen high-resolution of some sort
 
On NT, category #2 can be one of two configurations. If DirectDraw
modes are available, then those will be the high-res choices;
otherwise, fullscreen, borderless windows will be used in whatever
resolutions the driver supports, usually starting at 640x480 and going
up. Because there is normally no low-resolution mode such as 320x200
or 320x240 on NT, a pseudo low-res mode is created by rendering at
320x240, then stretching the image by doubling it in each direction
while copying it to a 640x480 screen. However, stretching performance
depends on the driver, and can be slow, so sometimes 640x480 is
actually faster than 320x240 on NT.
 
The bottom line here is that you can generally just use the Video menu
and pick one of the modes and be happy. In some cases, though, you
may need to use command-line switches (described next) to get the
types of modes you want. One useful tip is to go into the console and
do vid_describemodes, which lists all the modes WQ makes available on
your machine given the command-line switches you've used. Each mode
is followed by the name of the internal WQ driver that supports it, so
you can tell which modes are DirectDraw, VESA, and so on, as follows:
 
WINDOWED: WQ runs in a normal window
FULLSCREEN DIB: fullscreen borderless window
FULLSCREEN VGA8.DRV: VGA 320x200 mode
FULLSCREEN DDRAW8.DRV: DirectDraw mode
FULLSCREEN LINEAR8.DRV: VESA VBE 2.0+ mode
FULLSCREEN ACCEL8.DRV: VESA VBE/AF (Accelerator Functions) mode
(note that WQ does not take advantage of
VBE/AF acceleration; so far as WQ is
concerned VBE/AF is the same as normal VBE)
 
You can use vid_mode from the console to set any of these modes. So,
for example, if you see that there are two 320x200 modes (such as one
VGA mode 0x13, normally mode 3, and one VESA mode, normally mode 4),
you can choose the VESA mode, which will often be faster, with
vid_mode 4. (You can make it the default by setting
_vid_default_mode_win to the mode number.)
 
There's more to the windowed modes than you might think. 320x240 is
just what youÂ’d expect, but 640x480 is actually rendered at 320x240
and stretched up to 640x480, because most machines canÂ’t handle the
performance demands of real 640x480 rendering. Likewise, 800x600 is a
stretched 400x300. Actually, though, vid_mode 2 (the 800x600 mode) is
a user-configurable mode. By setting the following console variables,
you can change the characteristics of vid_mode 2:
 
vid_config_x: width of mode 2 window
 
vid_config_y: height of mode 2 window
 
vid_stretch_by_2: whether to render at half-resolution in each
direction and stretch up to the specified size in mode 2, or render at
full resolution.
 
After setting these variables in the console, do a vid_forcemode 2,
and youÂ’ll have the window you specified. Note that after making
these changes, the new resolution will show up as the third windowed
mode in the Video menu.
 
If you don't have WQ mouse play enabled in windowed mode, you can also
go from windowed to fullscreen mode simply by clicking on the maximize
button. The mode switched to is controlled by the vid_fullscreen_mode
console variable, and defaults to mode 3.
 
Other video console commands include:
 
vid_fullscreen: switch to the mode specified by the
vid_fullscreen_mode console variable.
 
vid_windowed: switch to the mode specified by the vid_windowed_mode
console variable.
 
Vid_fullscreen and vid_windowed can be bound to keys, so it's possible
to flip between windowed and fullscreen with a single key press.
 
Also, vid_minimize minimizes the WinQuake window if and only if
WinQuake is running in a windowed mode. You can bind a key to
the commands "vid_windowed; wait; vid_minimize" to minimize WQ
regardless of whether you're running in windowed or fullscreen mode.
 
You can turn off page flipping by setting the console variable
vid_nopageflip to 1, then setting a new mode. (Note that the
vid_nopageflip setting does not take effect until the next mode set.)
Some systems run faster with page flipping turned off; also, page
flipping does not work properly on some adapters, and vid_nopageflip
is a workaround for this. Note that vid_nopageflip is a persistent
variable; it retains its setting until it is explicitly changed again,
even across multiple WinQuake sessions.
 
The vid_forcemode console command sets the specified mode, even if
it's the same as the current mode (normally the mode set only happens
if the new mode differs from the current mode). This is generally
useful only if you've modified the characteristics of video mode 2
(the configurable window) while you're in mode 2, and want to force
the new characteristics to take effect.
 
Whenever you switch to running WinQuake in a window, the window is
placed at the same location it was in the last time WinQuake ran
in a window. You can reset the window position to the upper left
by using the -resetwinpos command-line switch. The window position
is stored in the vid_window_x and vid_window_y console variables.
 
 
 
-------------------------------
| Video command-line switches |
-------------------------------
 
The full list of video-related command-line switches is:
 
-dibonly: WQ will use only windows (both normal, framed windows on the
desktop and fullscreen, borderless windows), not any direct hardware
access modes such as DirectDraw or VESA modes, or even VGA 320x200
mode. This is the closest thing to a guaranteed-to-run fullscreen
mode WQ has.
 
-nowindirect: WQ will not try to use VESA VBE 2.0 modes, or VBE/AF
1.0 or later modes. Note that if there are both DirectDraw and VESA
modes for a given resolution, WQ will normally use the VESA mode;
-nowindirect allows DirectDraw modes to be the preferred choice for
all resolutions except 320x200. This can be useful if WQ is crashing
because of a buggy VESA driver.
 
-nodirectdraw: WQ will not try to use DirectDraw modes. This can be
useful if WQ is crashing because of a buggy DirectDraw driver.
 
-novbeaf: WQ will not try to use VBE/AF 1.0 or later modes.
 
-startwindowed: WQ will come up in a windowed mode, without going
fullscreen even during initialization.
 
-noforcevga: normally, WQ uses VGA mode 0x13 for the default 320x200
mode, even if a DirectDraw or VESA 320x200 mode exists. However,
DirectDraw and VESA modes can be considerably faster than mode 0x13,
because they can set up a linear framebuffer with higher memory
bandwidth. If you specify -noforcevga, the default 320x200 mode in
the menu will be a DirectDraw or VESA mode if one exists. This has no
effect on modes selected via the console variable vid_mode, and if
320x200 is already your video mode, -noforcevga doesn't do anything
until you use the menu to select another mode, then select 320x200
again. (So if your default mode is 320x200 and you then specify
-noforcevga, switch away to some other mode and then back to 320x200
to get the potentially faster 320x200 mode.) The downside to this
switch is that DirectDraw and VESA modes can cause problems in some
systems, due to driver bugs or hardware incompatibilities; if you
experience problems with this switch, don't use it.
 
-noautostretch: don't stretch windowed modes selected with
-startwindowed to double resolution.
 
-nofulldib: don't use fullscreen, borderless windows, even if there
are no DirectDraw or VESA modes available.
 
-allow360: allow listing of 360-wide modes in the video mode menu.
These are normally filtered out to make sure the menu doesn't get too
full, which could cause high-res modes not to be displayed.
 
-notriplebuf: prevent triple-buffered page flipping (rather than double-
buffered). This may result in slower performance, but is a workaround
if you encounter problems with flicker or initialization failure, which
could possibly happen in some modes with some DirectDraw drivers.
 
 
 
----------------------------------
| A bit about how WQ sound works |
----------------------------------
 
WQ can use either DirectSound or Windows wave output to generate
sound. If DirectSound is available, it is used; if not, if wave sound
is available it is used; and if neither is available, there is no
sound. DirectSound results in the best sound quality, and also the
lowest-latency sound; use it if you can, because you will be happier
with the results. (Note, though, that no NT sound drivers yet support
DirectSound.) Wave sound will often have high latency, lagging the
events that generate sound by hundreds of milliseconds on some
machines.
 
You can tell what kind of sound WQ uses on your system by looking at
the startup portion of the console; you will see either "DirectSound
initialized" or "Wave sound initialized" (neither message is printed
if there's no sound). Any sound failure messages will also be printed
in the startup portion of the console.
 
Note that WQ generates sound only when it is the active app, the one
with the input focus.
 
 
 
-------------------------------
| Sound command-line switches |
-------------------------------
 
The full list of sound-related command-line switches is:
 
-wavonly: donÂ’t use DirectSound, but use wave sound if available.
Note that wave sound is generally faster than DirectSound, but has
considerably greater latency. This switch is redundant on NT, because
all sound output on current NT drivers is wave sound.
 
-nosound: donÂ’t output any sound.
 
-primarysound: use DirectSound primary buffer output. This is
generally faster than normal secondary buffer output, but does not
work in some systems, and produces odd sound glitches on minimization
and focus switching in other systems. Use it at your own risk, and
please do not report sound bugs if you're using this switch.
 
-snoforceformat: WQ will not try to force the sound hardware to 11
KHz, 16 bits per sample. This may be useful if DirectSound is failing
for no apparent reason, but generally WQ will produce better sound and
better performance if this switch is not used.
 
 
 
-----------------------
| Notes on networking |
-----------------------
 
The winsock TCP/IP driver will not cause a dial-up internet connection
to automatically start up when Quake is started. If you start Quake
with it inactive, the connection will be activated when you either try
to connect to a server or search for local servers.
 
The local IP address will not always be known at startup. If it is
currently unknown the menu will display "INADDR_ANY". This will be
replaced with the real address when it is known. The IP address will
become known when you try to connect to a server, you search for local
servers, or you start a server.
 
For multi-homed machines (machines with more than one network adapter
and IP adress), you can force WinQuake to bind to a specific IP
address. There is a command line option "-ip" that takes an IP
address as its parameter.
 
 
 
----------------------
| Notes on the mouse |
----------------------
 
If DirectInput is installed and functioning, WinQuake can use it for
mouse input, but does not do so automatically because DirectInput does
not work properly on all systems. DirectInput can be enabled via the
command-line switch -dinput. If DirectInput is not available or is
not enabled, WinQuake uses the normal Windows mouse APIs instead.
DirectInput provides slightly smoother motion; also, it tends to be
more responsive to fast spinning motions, and we recommend that you use
it if it works properly on your system. You can determine if WQ uses
DirectInput on your system when you use -dinput by checking for
"DirectInput initialized" in the startup console text. If not, you
might try installing DirectX 3 (note, though, that as I write this
there is no released DirectInput support for Windows NT, only Win95).
 
 
 
-----------------------------------
| Log of changes to documentation |
-----------------------------------
 
*** WinQuake 0.994 ***
 
Fixed bug where in some cases involving IPX, whenever a new person
entered the game, a current player got dumped.
 
Added DirectInput mouse support, and the -dinput command-line to
enable it.
 
Added -notriplebuf to disable triple buffering to work around
possible problems with some modes on some DirectDraw drivers.
 
Added remembering last window position, and restoring that, rather
than centering the window, whenever WinQuake runs in a window.
Can be reset with the -resetwinpos command-line switch.
 
Added the vid_minimize command, which minimizes WinQuake if and only
if the current mode is windowed.
 
Made it so WinQuake no longer gets suspended when Alt-Tab is used to
switch away from a fullscreen session. The means you can Alt-Tab
away from fullscreen WinQuake without losing a connection to a
Quake server.
 
Added vid_nopageflip console variable to turn off page flipping, and
documented page flipping problems this can be used to work around.
 
Documented that Del-Ctrl-Alt (in that order) causes WinQuake to
fault on Win95.
 
Fixed the winsock TCP/IP driver so it will not cause a dial-up
internet connection to automatically start up when Quake is started.
If you start Quake with the internet connection already active, there
will be no difference. If you start Quake with it inactive, the
connection will be activated when you either try to connect to a
server or search for local servers.
 
The local IP address will not always be known at startup now. If it
is currently unknown the menu will display "INADDR_ANY". This
will be replaced with the real address when it is known. The IP
address will become known when: you try to connect to a server,
you search for local servers, or you start a server.
 
For multi-homed machines (machines with more than one network
adapter and IP adress), you can now force WinQuake to bind to a
specific IP adress. There is a new command line option "-ip" that
takes an IP address as its parameter.
 
Added vid_fullscreen_mode and ability to select that mode by
clicking on the maximize button. Added two commands:
vid_fullscreen to switch to vid_fullscreen_mode, and
vid_windowed to switch to vid_windowed mode.
 
Changed joystick default to disabled; now it only works if the
joystick cvar is set to 1; however, this setting now remains in
effect permanently. Added joystick documentation below.
 
Documented dprint only works if developer set to 1.
 
Documented scrunching of MS-DOS windows on Alt-Tab.
 
Documented that NT versions earlier to 4.0 are not supported.
 
Added DirectInput support for devices such as First Person
Gaming's Assassin controller. All buttons should now
be configurable in WinQuake.
 
Fixed bug where when low-res fullscreen DIB modes selected from
the menu sometimes ran very slowly or produced garbled displays.
 
Fixed bug where 1.06 and earlier save files couldn't be loaded
by WinQuake.
 
Removed "Net play pauses every few seconds" bug; it was determined
not to be a bug, just an artifact of network play.
 
Noted that even when BIOSes do have VESA 2.0 built-in, it's often
so buggy that WinQuake crashes in faster configurations, and that
SciTech Display Doctor is the easiest way to get reliable VESA
support.
 
Added note on Alt-Tab only working if Tab released first.
 
 
*** WinQuake 0.992 ***
 
Implemented force_centerview.
 
Fixed backspace bug in dedicated console.
 
Made "player entering game" messages and "say" messages visible
in dedicated console.
 
Added description of -heapsize (how to change default memory
allocation).
 
Added description of "net play pauses every few seconds" bug.
 
Added description of "playdemo fails across multiple levels" bug.
 
Added hooks for QHost; however, WinQuake won't work with QHost
until a new version of QHost 3.0, which uses the hooks, is
released. QHost 3.0 will not work with WinQuake.
 
Fixed bug where savegame descriptions weren't always terminated
properly.
 
Fixed bug where running -dedicated reset part of config.cfg to
defaults.
 
 
*** WinQuake 0.991 ***
 
Fixed problem with pre-1.07 (DOS) clients connecting to WinQuake.
 
Got rid of "Starting Quake..." dialog when running -dedicated.
 
Added -novbeaf switch to turn off VBE/AF support in case of problems,
and updated documentation.
 
Corrected SciTech's U.S. Mail address in documentation.
 
Added joystick bug decriptions and workarounds.
 
 
 
------------------
| Special thanks |
------------------
 
Special thanks for help with WinQuake to:
 
James Barnes
Kendall Bennett
Raymond Chen
John Colleran
Andrew Goossen
Mike Harrington
Chris Hecker
Todd Laney
Scott Ludwig
...and all the beta testers!
 
======================================================================
End of Document 3/21/97
======================================================================
/contrib/other/sdlquake-1.0.9/zone.c
0,0 → 1,935
/*
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.
 
*/
// Z_zone.c
 
#include "quakedef.h"
 
#define DYNAMIC_SIZE 0xc000
 
#define ZONEID 0x1d4a11
#define MINFRAGMENT 64
 
typedef struct memblock_s
{
int size; // including the header and possibly tiny fragments
int tag; // a tag of 0 is a free block
int id; // should be ZONEID
struct memblock_s *next, *prev;
int pad; // pad to 64 bit boundary
} memblock_t;
 
typedef struct
{
int size; // total bytes malloced, including header
memblock_t blocklist; // start / end cap for linked list
memblock_t *rover;
} memzone_t;
 
void Cache_FreeLow (int new_low_hunk);
void Cache_FreeHigh (int new_high_hunk);
 
 
/*
==============================================================================
 
ZONE MEMORY ALLOCATION
 
There is never any space between memblocks, and there will never be two
contiguous free memblocks.
 
The rover can be left pointing at a non-empty block
 
The zone calls are pretty much only used for small strings and structures,
all big things are allocated on the hunk.
==============================================================================
*/
 
memzone_t *mainzone;
 
void Z_ClearZone (memzone_t *zone, int size);
 
 
/*
========================
Z_ClearZone
========================
*/
void Z_ClearZone (memzone_t *zone, int size)
{
memblock_t *block;
// set the entire zone to one free block
 
zone->blocklist.next = zone->blocklist.prev = block =
(memblock_t *)( (byte *)zone + sizeof(memzone_t) );
zone->blocklist.tag = 1; // in use block
zone->blocklist.id = 0;
zone->blocklist.size = 0;
zone->rover = block;
block->prev = block->next = &zone->blocklist;
block->tag = 0; // free block
block->id = ZONEID;
block->size = size - sizeof(memzone_t);
}
 
 
/*
========================
Z_Free
========================
*/
void Z_Free (void *ptr)
{
memblock_t *block, *other;
if (!ptr)
Sys_Error ("Z_Free: NULL pointer");
 
block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t));
if (block->id != ZONEID)
Sys_Error ("Z_Free: freed a pointer without ZONEID");
if (block->tag == 0)
Sys_Error ("Z_Free: freed a freed pointer");
 
block->tag = 0; // mark as free
other = block->prev;
if (!other->tag)
{ // merge with previous free block
other->size += block->size;
other->next = block->next;
other->next->prev = other;
if (block == mainzone->rover)
mainzone->rover = other;
block = other;
}
other = block->next;
if (!other->tag)
{ // merge the next free block onto the end
block->size += other->size;
block->next = other->next;
block->next->prev = block;
if (other == mainzone->rover)
mainzone->rover = block;
}
}
 
 
/*
========================
Z_Malloc
========================
*/
void *Z_Malloc (int size)
{
void *buf;
Z_CheckHeap (); // DEBUG
buf = Z_TagMalloc (size, 1);
if (!buf)
Sys_Error ("Z_Malloc: failed on allocation of %i bytes",size);
Q_memset (buf, 0, size);
 
return buf;
}
 
void *Z_TagMalloc (int size, int tag)
{
int extra;
memblock_t *start, *rover, *new, *base;
 
if (!tag)
Sys_Error ("Z_TagMalloc: tried to use a 0 tag");
 
//
// scan through the block list looking for the first free block
// of sufficient size
//
size += sizeof(memblock_t); // account for size of block header
size += 4; // space for memory trash tester
size = (size + 7) & ~7; // align to 8-byte boundary
base = rover = mainzone->rover;
start = base->prev;
do
{
if (rover == start) // scaned all the way around the list
return NULL;
if (rover->tag)
base = rover = rover->next;
else
rover = rover->next;
} while (base->tag || base->size < size);
//
// found a block big enough
//
extra = base->size - size;
if (extra > MINFRAGMENT)
{ // there will be a free fragment after the allocated block
new = (memblock_t *) ((byte *)base + size );
new->size = extra;
new->tag = 0; // free block
new->prev = base;
new->id = ZONEID;
new->next = base->next;
new->next->prev = new;
base->next = new;
base->size = size;
}
base->tag = tag; // no longer a free block
mainzone->rover = base->next; // next allocation will start looking here
base->id = ZONEID;
 
// marker for memory trash testing
*(int *)((byte *)base + base->size - 4) = ZONEID;
 
return (void *) ((byte *)base + sizeof(memblock_t));
}
 
 
/*
========================
Z_Print
========================
*/
void Z_Print (memzone_t *zone)
{
memblock_t *block;
Con_Printf ("zone size: %i location: %p\n",mainzone->size,mainzone);
for (block = zone->blocklist.next ; ; block = block->next)
{
Con_Printf ("block:%p size:%7i tag:%3i\n",
block, block->size, block->tag);
if (block->next == &zone->blocklist)
break; // all blocks have been hit
if ( (byte *)block + block->size != (byte *)block->next)
Con_Printf ("ERROR: block size does not touch the next block\n");
if ( block->next->prev != block)
Con_Printf ("ERROR: next block doesn't have proper back link\n");
if (!block->tag && !block->next->tag)
Con_Printf ("ERROR: two consecutive free blocks\n");
}
}
 
 
/*
========================
Z_CheckHeap
========================
*/
void Z_CheckHeap (void)
{
memblock_t *block;
for (block = mainzone->blocklist.next ; ; block = block->next)
{
if (block->next == &mainzone->blocklist)
break; // all blocks have been hit
if ( (byte *)block + block->size != (byte *)block->next)
Sys_Error ("Z_CheckHeap: block size does not touch the next block\n");
if ( block->next->prev != block)
Sys_Error ("Z_CheckHeap: next block doesn't have proper back link\n");
if (!block->tag && !block->next->tag)
Sys_Error ("Z_CheckHeap: two consecutive free blocks\n");
}
}
 
//============================================================================
 
#define HUNK_SENTINAL 0x1df001ed
 
typedef struct
{
int sentinal;
int size; // including sizeof(hunk_t), -1 = not allocated
char name[8];
} hunk_t;
 
byte *hunk_base;
int hunk_size;
 
int hunk_low_used;
int hunk_high_used;
 
qboolean hunk_tempactive;
int hunk_tempmark;
 
void R_FreeTextures (void);
 
/*
==============
Hunk_Check
 
Run consistancy and sentinal trahing checks
==============
*/
void Hunk_Check (void)
{
hunk_t *h;
for (h = (hunk_t *)hunk_base ; (byte *)h != hunk_base + hunk_low_used ; )
{
if (h->sentinal != HUNK_SENTINAL)
Sys_Error ("Hunk_Check: trahsed sentinal");
if (h->size < 16 || h->size + (byte *)h - hunk_base > hunk_size)
Sys_Error ("Hunk_Check: bad size");
h = (hunk_t *)((byte *)h+h->size);
}
}
 
/*
==============
Hunk_Print
 
If "all" is specified, every single allocation is printed.
Otherwise, allocations with the same name will be totaled up before printing.
==============
*/
void Hunk_Print (qboolean all)
{
hunk_t *h, *next, *endlow, *starthigh, *endhigh;
int count, sum;
int totalblocks;
char name[9];
 
name[8] = 0;
count = 0;
sum = 0;
totalblocks = 0;
h = (hunk_t *)hunk_base;
endlow = (hunk_t *)(hunk_base + hunk_low_used);
starthigh = (hunk_t *)(hunk_base + hunk_size - hunk_high_used);
endhigh = (hunk_t *)(hunk_base + hunk_size);
 
Con_Printf (" :%8i total hunk size\n", hunk_size);
Con_Printf ("-------------------------\n");
 
while (1)
{
//
// skip to the high hunk if done with low hunk
//
if ( h == endlow )
{
Con_Printf ("-------------------------\n");
Con_Printf (" :%8i REMAINING\n", hunk_size - hunk_low_used - hunk_high_used);
Con_Printf ("-------------------------\n");
h = starthigh;
}
//
// if totally done, break
//
if ( h == endhigh )
break;
 
//
// run consistancy checks
//
if (h->sentinal != HUNK_SENTINAL)
Sys_Error ("Hunk_Check: trahsed sentinal");
if (h->size < 16 || h->size + (byte *)h - hunk_base > hunk_size)
Sys_Error ("Hunk_Check: bad size");
next = (hunk_t *)((byte *)h+h->size);
count++;
totalblocks++;
sum += h->size;
 
//
// print the single block
//
memcpy (name, h->name, 8);
if (all)
Con_Printf ("%8p :%8i %8s\n",h, h->size, name);
//
// print the total
//
if (next == endlow || next == endhigh ||
strncmp (h->name, next->name, 8) )
{
if (!all)
Con_Printf (" :%8i %8s (TOTAL)\n",sum, name);
count = 0;
sum = 0;
}
 
h = next;
}
 
Con_Printf ("-------------------------\n");
Con_Printf ("%8i total blocks\n", totalblocks);
}
 
/*
===================
Hunk_AllocName
===================
*/
void *Hunk_AllocName (int size, char *name)
{
hunk_t *h;
#ifdef PARANOID
Hunk_Check ();
#endif
 
if (size < 0)
Sys_Error ("Hunk_Alloc: bad size: %i", size);
size = sizeof(hunk_t) + ((size+15)&~15);
if (hunk_size - hunk_low_used - hunk_high_used < size)
Sys_Error ("Hunk_Alloc: failed on %i bytes",size);
h = (hunk_t *)(hunk_base + hunk_low_used);
hunk_low_used += size;
 
Cache_FreeLow (hunk_low_used);
 
memset (h, 0, size);
h->size = size;
h->sentinal = HUNK_SENTINAL;
Q_strncpy (h->name, name, 8);
return (void *)(h+1);
}
 
/*
===================
Hunk_Alloc
===================
*/
void *Hunk_Alloc (int size)
{
return Hunk_AllocName (size, "unknown");
}
 
int Hunk_LowMark (void)
{
return hunk_low_used;
}
 
void Hunk_FreeToLowMark (int mark)
{
if (mark < 0 || mark > hunk_low_used)
Sys_Error ("Hunk_FreeToLowMark: bad mark %i", mark);
memset (hunk_base + mark, 0, hunk_low_used - mark);
hunk_low_used = mark;
}
 
int Hunk_HighMark (void)
{
if (hunk_tempactive)
{
hunk_tempactive = false;
Hunk_FreeToHighMark (hunk_tempmark);
}
 
return hunk_high_used;
}
 
void Hunk_FreeToHighMark (int mark)
{
if (hunk_tempactive)
{
hunk_tempactive = false;
Hunk_FreeToHighMark (hunk_tempmark);
}
if (mark < 0 || mark > hunk_high_used)
Sys_Error ("Hunk_FreeToHighMark: bad mark %i", mark);
memset (hunk_base + hunk_size - hunk_high_used, 0, hunk_high_used - mark);
hunk_high_used = mark;
}
 
 
/*
===================
Hunk_HighAllocName
===================
*/
void *Hunk_HighAllocName (int size, char *name)
{
hunk_t *h;
 
if (size < 0)
Sys_Error ("Hunk_HighAllocName: bad size: %i", size);
 
if (hunk_tempactive)
{
Hunk_FreeToHighMark (hunk_tempmark);
hunk_tempactive = false;
}
 
#ifdef PARANOID
Hunk_Check ();
#endif
 
size = sizeof(hunk_t) + ((size+15)&~15);
 
if (hunk_size - hunk_low_used - hunk_high_used < size)
{
Con_Printf ("Hunk_HighAlloc: failed on %i bytes\n",size);
return NULL;
}
 
hunk_high_used += size;
Cache_FreeHigh (hunk_high_used);
 
h = (hunk_t *)(hunk_base + hunk_size - hunk_high_used);
 
memset (h, 0, size);
h->size = size;
h->sentinal = HUNK_SENTINAL;
Q_strncpy (h->name, name, 8);
 
return (void *)(h+1);
}
 
 
/*
=================
Hunk_TempAlloc
 
Return space from the top of the hunk
=================
*/
void *Hunk_TempAlloc (int size)
{
void *buf;
 
size = (size+15)&~15;
if (hunk_tempactive)
{
Hunk_FreeToHighMark (hunk_tempmark);
hunk_tempactive = false;
}
hunk_tempmark = Hunk_HighMark ();
 
buf = Hunk_HighAllocName (size, "temp");
 
hunk_tempactive = true;
 
return buf;
}
 
/*
===============================================================================
 
CACHE MEMORY
 
===============================================================================
*/
 
typedef struct cache_system_s
{
int size; // including this header
cache_user_t *user;
char name[16];
struct cache_system_s *prev, *next;
struct cache_system_s *lru_prev, *lru_next; // for LRU flushing
} cache_system_t;
 
cache_system_t *Cache_TryAlloc (int size, qboolean nobottom);
 
cache_system_t cache_head;
 
/*
===========
Cache_Move
===========
*/
void Cache_Move ( cache_system_t *c)
{
cache_system_t *new;
 
// we are clearing up space at the bottom, so only allocate it late
new = Cache_TryAlloc (c->size, true);
if (new)
{
// Con_Printf ("cache_move ok\n");
 
Q_memcpy ( new+1, c+1, c->size - sizeof(cache_system_t) );
new->user = c->user;
Q_memcpy (new->name, c->name, sizeof(new->name));
Cache_Free (c->user);
new->user->data = (void *)(new+1);
}
else
{
// Con_Printf ("cache_move failed\n");
 
Cache_Free (c->user); // tough luck...
}
}
 
/*
============
Cache_FreeLow
 
Throw things out until the hunk can be expanded to the given point
============
*/
void Cache_FreeLow (int new_low_hunk)
{
cache_system_t *c;
while (1)
{
c = cache_head.next;
if (c == &cache_head)
return; // nothing in cache at all
if ((byte *)c >= hunk_base + new_low_hunk)
return; // there is space to grow the hunk
Cache_Move ( c ); // reclaim the space
}
}
 
/*
============
Cache_FreeHigh
 
Throw things out until the hunk can be expanded to the given point
============
*/
void Cache_FreeHigh (int new_high_hunk)
{
cache_system_t *c, *prev;
prev = NULL;
while (1)
{
c = cache_head.prev;
if (c == &cache_head)
return; // nothing in cache at all
if ( (byte *)c + c->size <= hunk_base + hunk_size - new_high_hunk)
return; // there is space to grow the hunk
if (c == prev)
Cache_Free (c->user); // didn't move out of the way
else
{
Cache_Move (c); // try to move it
prev = c;
}
}
}
 
void Cache_UnlinkLRU (cache_system_t *cs)
{
if (!cs->lru_next || !cs->lru_prev)
Sys_Error ("Cache_UnlinkLRU: NULL link");
 
cs->lru_next->lru_prev = cs->lru_prev;
cs->lru_prev->lru_next = cs->lru_next;
cs->lru_prev = cs->lru_next = NULL;
}
 
void Cache_MakeLRU (cache_system_t *cs)
{
if (cs->lru_next || cs->lru_prev)
Sys_Error ("Cache_MakeLRU: active link");
 
cache_head.lru_next->lru_prev = cs;
cs->lru_next = cache_head.lru_next;
cs->lru_prev = &cache_head;
cache_head.lru_next = cs;
}
 
/*
============
Cache_TryAlloc
 
Looks for a free block of memory between the high and low hunk marks
Size should already include the header and padding
============
*/
cache_system_t *Cache_TryAlloc (int size, qboolean nobottom)
{
cache_system_t *cs, *new;
// is the cache completely empty?
 
if (!nobottom && cache_head.prev == &cache_head)
{
if (hunk_size - hunk_high_used - hunk_low_used < size)
Sys_Error ("Cache_TryAlloc: %i is greater then free hunk", size);
 
new = (cache_system_t *) (hunk_base + hunk_low_used);
memset (new, 0, sizeof(*new));
new->size = size;
 
cache_head.prev = cache_head.next = new;
new->prev = new->next = &cache_head;
Cache_MakeLRU (new);
return new;
}
// search from the bottom up for space
 
new = (cache_system_t *) (hunk_base + hunk_low_used);
cs = cache_head.next;
do
{
if (!nobottom || cs != cache_head.next)
{
if ( (byte *)cs - (byte *)new >= size)
{ // found space
memset (new, 0, sizeof(*new));
new->size = size;
new->next = cs;
new->prev = cs->prev;
cs->prev->next = new;
cs->prev = new;
Cache_MakeLRU (new);
return new;
}
}
 
// continue looking
new = (cache_system_t *)((byte *)cs + cs->size);
cs = cs->next;
 
} while (cs != &cache_head);
// try to allocate one at the very end
if ( hunk_base + hunk_size - hunk_high_used - (byte *)new >= size)
{
memset (new, 0, sizeof(*new));
new->size = size;
new->next = &cache_head;
new->prev = cache_head.prev;
cache_head.prev->next = new;
cache_head.prev = new;
Cache_MakeLRU (new);
 
return new;
}
return NULL; // couldn't allocate
}
 
/*
============
Cache_Flush
 
Throw everything out, so new data will be demand cached
============
*/
void Cache_Flush (void)
{
while (cache_head.next != &cache_head)
Cache_Free ( cache_head.next->user ); // reclaim the space
}
 
 
/*
============
Cache_Print
 
============
*/
void Cache_Print (void)
{
cache_system_t *cd;
 
for (cd = cache_head.next ; cd != &cache_head ; cd = cd->next)
{
Con_Printf ("%8i : %s\n", cd->size, cd->name);
}
}
 
/*
============
Cache_Report
 
============
*/
void Cache_Report (void)
{
Con_DPrintf ("%4.1f megabyte data cache\n", (hunk_size - hunk_high_used - hunk_low_used) / (float)(1024*1024) );
}
 
/*
============
Cache_Compact
 
============
*/
void Cache_Compact (void)
{
}
 
/*
============
Cache_Init
 
============
*/
void Cache_Init (void)
{
cache_head.next = cache_head.prev = &cache_head;
cache_head.lru_next = cache_head.lru_prev = &cache_head;
 
Cmd_AddCommand ("flush", Cache_Flush);
}
 
/*
==============
Cache_Free
 
Frees the memory and removes it from the LRU list
==============
*/
void Cache_Free (cache_user_t *c)
{
cache_system_t *cs;
 
if (!c->data)
Sys_Error ("Cache_Free: not allocated");
 
cs = ((cache_system_t *)c->data) - 1;
 
cs->prev->next = cs->next;
cs->next->prev = cs->prev;
cs->next = cs->prev = NULL;
 
c->data = NULL;
 
Cache_UnlinkLRU (cs);
}
 
 
 
/*
==============
Cache_Check
==============
*/
void *Cache_Check (cache_user_t *c)
{
cache_system_t *cs;
 
if (!c->data)
return NULL;
 
cs = ((cache_system_t *)c->data) - 1;
 
// move to head of LRU
Cache_UnlinkLRU (cs);
Cache_MakeLRU (cs);
return c->data;
}
 
 
/*
==============
Cache_Alloc
==============
*/
void *Cache_Alloc (cache_user_t *c, int size, char *name)
{
cache_system_t *cs;
 
if (c->data)
Sys_Error ("Cache_Alloc: allready allocated");
if (size <= 0)
Sys_Error ("Cache_Alloc: size %i", size);
 
size = (size + sizeof(cache_system_t) + 15) & ~15;
 
// find memory for it
while (1)
{
cs = Cache_TryAlloc (size, false);
if (cs)
{
strncpy (cs->name, name, sizeof(cs->name)-1);
c->data = (void *)(cs+1);
cs->user = c;
break;
}
// free the least recently used cahedat
if (cache_head.lru_prev == &cache_head)
Sys_Error ("Cache_Alloc: out of memory");
// not enough memory at all
Cache_Free ( cache_head.lru_prev->user );
}
return Cache_Check (c);
}
 
//============================================================================
 
 
/*
========================
Memory_Init
========================
*/
void Memory_Init (void *buf, int size)
{
int p;
int zonesize = DYNAMIC_SIZE;
 
hunk_base = buf;
hunk_size = size;
hunk_low_used = 0;
hunk_high_used = 0;
Cache_Init ();
p = COM_CheckParm ("-zone");
if (p)
{
if (p < com_argc-1)
zonesize = Q_atoi (com_argv[p+1]) * 1024;
else
Sys_Error ("Memory_Init: you must specify a size in KB after -zone");
}
mainzone = Hunk_AllocName (zonesize, "zone" );
Z_ClearZone (mainzone, zonesize);
}
 
/contrib/other/sdlquake-1.0.9/zone.h
0,0 → 1,131
/*
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.
 
*/
/*
memory allocation
 
 
H_??? The hunk manages the entire memory block given to quake. It must be
contiguous. Memory can be allocated from either the low or high end in a
stack fashion. The only way memory is released is by resetting one of the
pointers.
 
Hunk allocations should be given a name, so the Hunk_Print () function
can display usage.
 
Hunk allocations are guaranteed to be 16 byte aligned.
 
The video buffers are allocated high to avoid leaving a hole underneath
server allocations when changing to a higher video mode.
 
 
Z_??? Zone memory functions used for small, dynamic allocations like text
strings from command input. There is only about 48K for it, allocated at
the very bottom of the hunk.
 
Cache_??? Cache memory is for objects that can be dynamically loaded and
can usefully stay persistant between levels. The size of the cache
fluctuates from level to level.
 
To allocate a cachable object
 
 
Temp_??? Temp memory is used for file loading and surface caching. The size
of the cache memory is adjusted so that there is a minimum of 512k remaining
for temp memory.
 
 
------ Top of Memory -------
 
high hunk allocations
 
<--- high hunk reset point held by vid
 
video buffer
 
z buffer
 
surface cache
 
<--- high hunk used
 
cachable memory
 
<--- low hunk used
 
client and server low hunk allocations
 
<-- low hunk reset point held by host
 
startup hunk allocations
 
Zone block
 
----- Bottom of Memory -----
 
 
 
*/
 
void Memory_Init (void *buf, int size);
 
void Z_Free (void *ptr);
void *Z_Malloc (int size); // returns 0 filled memory
void *Z_TagMalloc (int size, int tag);
 
void Z_DumpHeap (void);
void Z_CheckHeap (void);
int Z_FreeMemory (void);
 
void *Hunk_Alloc (int size); // returns 0 filled memory
void *Hunk_AllocName (int size, char *name);
 
void *Hunk_HighAllocName (int size, char *name);
 
int Hunk_LowMark (void);
void Hunk_FreeToLowMark (int mark);
 
int Hunk_HighMark (void);
void Hunk_FreeToHighMark (int mark);
 
void *Hunk_TempAlloc (int size);
 
void Hunk_Check (void);
 
typedef struct cache_user_s
{
void *data;
} cache_user_t;
 
void Cache_Flush (void);
 
void *Cache_Check (cache_user_t *c);
// returns the cached data, and moves to the head of the LRU list
// if present, otherwise returns NULL
 
void Cache_Free (cache_user_t *c);
 
void *Cache_Alloc (cache_user_t *c, int size, char *name);
// Returns NULL if all purgable data was tossed and there still
// wasn't enough room.
 
void Cache_Report (void);