mirror of
https://github.com/nzp-team/dquakeplus.git
synced 2024-11-10 06:31:40 +00:00
CTR: Initial Import
This commit is contained in:
parent
835c932566
commit
8cc00c95a2
61 changed files with 30621 additions and 79 deletions
118
.github/workflows/build-and-release.yml
vendored
Normal file
118
.github/workflows/build-and-release.yml
vendored
Normal file
|
@ -0,0 +1,118 @@
|
|||
name: Build EBOOT and Publish Release
|
||||
on: [push]
|
||||
jobs:
|
||||
Compile-EBOOT:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/main'
|
||||
container:
|
||||
image: pspdev/pspdev
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Get container ready
|
||||
run: |
|
||||
apk add bash zip git gmp mpc1 mpfr4 make
|
||||
- name: Build
|
||||
working-directory: ./
|
||||
run: |
|
||||
cd source/psp/libpspmath
|
||||
make && make install
|
||||
cd ../../../
|
||||
make -f Makefile.psp install
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: psp-nzp-eboot
|
||||
path: ./build/psp/bin/EBOOT.PBP
|
||||
Compile-3DSX:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/main'
|
||||
outputs:
|
||||
o3ds_link: ${{ steps.zip.outputs.zip }}
|
||||
container:
|
||||
image: devkitpro/devkitarm
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install Packages and update picaGL
|
||||
run: |
|
||||
git clone https://github.com/masterfeizz/picaGL.git
|
||||
cd picaGL
|
||||
git checkout revamp
|
||||
mkdir clean
|
||||
make install
|
||||
- name: Build
|
||||
working-directory: ./
|
||||
run: |
|
||||
make -f Makefile.ctr
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ctr-nzp-3dsx
|
||||
path: ./build/3ds/bin/nzportable.3dsx
|
||||
Unify-and-Release:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [Compile-EBOOT, Compile-3DSX]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Wait for GitHub to keep up..
|
||||
run: sleep 2s
|
||||
shell: bash
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: ./
|
||||
- name: Turn Artifacts into .ZIP archives
|
||||
run: |
|
||||
zip -r -j psp-nzp-eboot.zip psp-nzp-eboot/*
|
||||
zip -r -j ctr-nzp-3dsx.zip ctr-nzp-3dsx/*
|
||||
- name: Generate Build Date
|
||||
id: date
|
||||
run: echo "::set-output name=date::$(date +'%Y-%m-%d-%H-%M-%S')"
|
||||
- name: Delete Old Release
|
||||
uses: dev-drprasad/delete-tag-and-release@v0.2.1
|
||||
with:
|
||||
delete_release: true
|
||||
tag_name: bleeding-edge
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: bleeding-edge
|
||||
release_name: Automated Release ${{ steps.date.outputs.date }}
|
||||
body: |
|
||||
This is a **bleeding edge** NZ:P NX/VITA release, stability is not guarenteed.
|
||||
|
||||
To install:
|
||||
- Grab the .ZIP archive for your platform
|
||||
- PSP: Extract the `EBOOT.PBP` to `/PSP/GAME/nzportable/`
|
||||
- 3DS: Extract `nzportable.3dsx` to `/3ds/nzportable/`.
|
||||
draft: true
|
||||
prerelease: false
|
||||
- name: Upload PSP Archive
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./psp-nzp-eboot.zip
|
||||
asset_name: psp-nzp-eboot.zip
|
||||
asset_content_type: application/zip
|
||||
- name: Upload 3DS Archive
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./ctr-nzp-3dsx.zip
|
||||
asset_name: ctr-nzp-3dsx.zip
|
||||
asset_content_type: application/zip
|
||||
- name: Publish Release
|
||||
uses: StuYarrow/publish-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
id: ${{ steps.create_release.outputs.id }}
|
66
.github/workflows/build-eboot-and-release.yml
vendored
66
.github/workflows/build-eboot-and-release.yml
vendored
|
@ -1,66 +0,0 @@
|
|||
name: Build EBOOT and Publish Release
|
||||
on: [push]
|
||||
jobs:
|
||||
Compile-EBOOT:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/main'
|
||||
container:
|
||||
image: pspdev/pspdev
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Get container ready
|
||||
run: |
|
||||
apk add bash zip git gmp mpc1 mpfr4 make
|
||||
- name: Build
|
||||
working-directory: ./
|
||||
run: |
|
||||
cd source/psp/libpspmath
|
||||
make && make install
|
||||
cd ../../../
|
||||
make -f Makefile.psp install
|
||||
- name: Generate Build Date
|
||||
id: date
|
||||
run: echo "::set-output name=date::$(date +'%Y-%m-%d-%H-%M-%S')"
|
||||
- name: Zip EBOOT
|
||||
working-directory: ./build
|
||||
run: |
|
||||
zip -r -j psp-nzp-eboot.zip build/psp/bin/EBOOT.PBP
|
||||
- name: Delete Old Release
|
||||
uses: dev-drprasad/delete-tag-and-release@v0.2.1
|
||||
with:
|
||||
delete_release: true
|
||||
tag_name: bleeding-edge
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: bleeding-edge
|
||||
release_name: Automated Release ${{ steps.date.outputs.date }}
|
||||
body: |
|
||||
This is a **bleeding edge** NZ:P PSP EBOOT release, stability is not guarenteed.
|
||||
|
||||
To install:
|
||||
- Grab the .ZIP archive (psp-nzp-eboot.zip)
|
||||
- Extract the contents of the .ZIP archive to `PSP/GAME/nzportable`.
|
||||
draft: true
|
||||
prerelease: false
|
||||
- name: Upload EBOOT Archive
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./build/psp-nzp-eboot.zip
|
||||
asset_name: psp-nzp-eboot.zip
|
||||
asset_content_type: application/zip
|
||||
- name: Publish Release
|
||||
uses: StuYarrow/publish-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
id: ${{ steps.create_release.outputs.id }}
|
||||
|
265
Makefile.ctr
Normal file
265
Makefile.ctr
Normal file
|
@ -0,0 +1,265 @@
|
|||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
include $(DEVKITARM)/3ds_rules
|
||||
|
||||
TARGET := nzportable
|
||||
BUILD := build
|
||||
SOURCES := source
|
||||
#DATA := data
|
||||
INCLUDES := include
|
||||
ICON := source/ctr/art/icon.png
|
||||
#ROMFS := romfs
|
||||
|
||||
APP_AUTHOR := NZ:P Team
|
||||
APP_TITLE := Nazi Zombies: Portable
|
||||
APP_DESCRIPTION := Call of Duty Zombies remake
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft
|
||||
|
||||
CFLAGS := -g -fpermissive -Wall -O3 -mword-relocations \
|
||||
-fomit-frame-pointer -ffunction-sections \
|
||||
$(ARCH)
|
||||
|
||||
CFLAGS += $(INCLUDE) -DARM11 -D_3DS -DGLQUAKE
|
||||
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||
|
||||
LIBS := -lpicaGL -lctru -lm
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := $(CTRULIB) $(DEVKITPRO)/picaGL
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export TOPDIR := $(CURDIR)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
COMMON_OBJS = chase.c \
|
||||
cl_hud.c \
|
||||
cl_demo.c \
|
||||
cl_input.c \
|
||||
cl_main.c \
|
||||
cl_parse.c \
|
||||
cl_tent.c \
|
||||
cl_slist.c \
|
||||
ctr/bsp_strlcpy.c \
|
||||
cmd.c \
|
||||
ctr/common.c \
|
||||
console.c \
|
||||
crc.c \
|
||||
cvar.c \
|
||||
host.c \
|
||||
host_cmd.c \
|
||||
ctr/keys.c \
|
||||
mathlib.c \
|
||||
matrixlib.c \
|
||||
ctr/menu.c \
|
||||
ctr/net_dgrm.c \
|
||||
ctr/net_udpctr.c \
|
||||
net_loop.c \
|
||||
ctr/net_bsd.c \
|
||||
ctr/net_main.c \
|
||||
net_vcr.c \
|
||||
pr_cmds.c \
|
||||
pr_edict.c \
|
||||
pr_exec.c \
|
||||
ctr/sbar.c \
|
||||
sv_main.c \
|
||||
sv_move.c \
|
||||
sv_phys.c \
|
||||
sv_user.c \
|
||||
view.c \
|
||||
wad.c \
|
||||
world.c \
|
||||
zone.c \
|
||||
ctr/sys_ctr.c \
|
||||
snd_dma.c \
|
||||
snd_mix.c \
|
||||
snd_mem.c \
|
||||
ctr/snd_ctr.c \
|
||||
ctr/in_ctr.c \
|
||||
ctr/cd_null.c \
|
||||
ctr/gl/gl_qmb.c \
|
||||
ctr/gl/gl_decal.c \
|
||||
ctr/gl/gl_draw.c \
|
||||
ctr/gl/gl_fog.c \
|
||||
ctr/gl/gl_mesh.c \
|
||||
ctr/gl/gl_model.c \
|
||||
ctr/gl/gl_refrag.c \
|
||||
ctr/gl/gl_rlight.c \
|
||||
ctr/gl/gl_rmain.c \
|
||||
ctr/gl/gl_rmisc.c \
|
||||
ctr/gl/gl_rsurf.c \
|
||||
ctr/gl/gl_screen.c \
|
||||
ctr/gl/gl_warp.c \
|
||||
ctr/gl/gl_vidctr.c \
|
||||
ctr/r_part.c \
|
||||
ctr/touch_ctr.c \
|
||||
crypter.c
|
||||
|
||||
CFILES := $(COMMON_OBJS)
|
||||
CPPFILES :=
|
||||
SFILES :=
|
||||
PICAFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.v.pica)))
|
||||
SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist)))
|
||||
#BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CXX)
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OFILES_SOURCES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||
|
||||
export OFILES_BIN := $(addsuffix .o,$(BINFILES)) \
|
||||
$(PICAFILES:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.shbin.o)
|
||||
|
||||
export OFILES := $(OFILES_BIN) $(OFILES_SOURCES)
|
||||
|
||||
export HFILES := $(PICAFILES:.v.pica=_shbin.h) $(SHLISTFILES:.shlist=_shbin.h) $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I$(CURDIR)/$(BUILD)
|
||||
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
ifeq ($(strip $(ICON)),)
|
||||
icons := $(wildcard *.png)
|
||||
ifneq (,$(findstring $(TARGET).png,$(icons)))
|
||||
export APP_ICON := $(TOPDIR)/$(TARGET).png
|
||||
else
|
||||
ifneq (,$(findstring icon.png,$(icons)))
|
||||
export APP_ICON := $(TOPDIR)/icon.png
|
||||
endif
|
||||
endif
|
||||
else
|
||||
export APP_ICON := $(TOPDIR)/$(ICON)
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(NO_SMDH)),)
|
||||
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
|
||||
endif
|
||||
|
||||
ifneq ($(ROMFS),)
|
||||
export _3DSXFLAGS += --romfs=$(CURDIR)/$(ROMFS)
|
||||
endif
|
||||
|
||||
.PHONY: $(BUILD) clean all
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
all: $(BUILD)
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@mkdir -p $(BUILD)/ctr
|
||||
@mkdir -p $(BUILD)/ctr/gl
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.ctr
|
||||
@mkdir -p $(BUILD)/3ds
|
||||
@mkdir -p $(BUILD)/3ds/bin/
|
||||
@mv $(BUILD)/*.o $(BUILD)/3ds/
|
||||
@mv $(BUILD)/*.d $(BUILD)/3ds/
|
||||
@mv $(BUILD)/ctr $(BUILD)/3ds/
|
||||
@mv $(BUILD)/$(TARGET).lst $(BUILD)/3ds/
|
||||
@mv $(BUILD)/$(TARGET).map $(BUILD)/3ds/
|
||||
@mv $(TARGET).* $(BUILD)/3ds/bin/
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD)
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(NO_SMDH)),)
|
||||
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
|
||||
else
|
||||
$(OUTPUT).3dsx : $(OUTPUT).elf
|
||||
endif
|
||||
|
||||
$(OFILES_SOURCES) : $(HFILES)
|
||||
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# you need a rule like this for each extension you use as binary data
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o %_bin.h : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# rules for assembling GPU shaders
|
||||
#---------------------------------------------------------------------------------
|
||||
define shader-as
|
||||
$(eval CURBIN := $*.shbin)
|
||||
$(eval DEPSFILE := $(DEPSDIR)/$*.shbin.d)
|
||||
echo "$(CURBIN).o: $< $1" > $(DEPSFILE)
|
||||
echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(CURBIN) | tr . _)`.h
|
||||
echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(CURBIN) | tr . _)`.h
|
||||
echo "extern const u32" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(CURBIN) | tr . _)`.h
|
||||
picasso -o $(CURBIN) $1
|
||||
bin2s $(CURBIN) | $(AS) -o $*.shbin.o
|
||||
endef
|
||||
|
||||
%.shbin.o %_shbin.h : %.v.pica %.g.pica
|
||||
@echo $(notdir $^)
|
||||
@$(call shader-as,$^)
|
||||
|
||||
%.shbin.o %_shbin.h : %.v.pica
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$<)
|
||||
|
||||
%.shbin.o %_shbin.h : %.shlist
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)$(file)))
|
||||
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
18
Makefile.psp
18
Makefile.psp
|
@ -1,4 +1,4 @@
|
|||
#MAKEFLAGS+="-j -l $(shell grep -c ^processor /proc/cpuinfo) "
|
||||
MAKEFLAGS+="-j -l $(shell grep -c ^processor /proc/cpuinfo) "
|
||||
PSPSDK = $(shell psp-config --pspsdk-path)
|
||||
PSPLIBSDIR = $(PSPSDK)/..
|
||||
|
||||
|
@ -127,17 +127,13 @@ clean:
|
|||
rm source/psp/*.o
|
||||
rm source/*.o
|
||||
|
||||
clean-keep-eboot:
|
||||
rm -rf build/exec/
|
||||
rm source/psp/*.o
|
||||
rm source/*.o
|
||||
|
||||
install: EBOOT.PBP
|
||||
mkdir -p build/exec/
|
||||
mv EBOOT.PBP build/
|
||||
mkdir -p build/psp/
|
||||
mkdir -p build/psp/bin
|
||||
mv EBOOT.PBP build/psp/bin/
|
||||
ifeq ($(DEBUG),1)
|
||||
mv *.prx build/exec/
|
||||
mv *.prx build/psp/
|
||||
endif
|
||||
mv *.elf build/exec/
|
||||
mv *.SFO build/exec/
|
||||
mv *.elf build/psp/
|
||||
mv *.SFO build/psp/
|
||||
@echo DONE
|
20
README.md
20
README.md
|
@ -1,7 +1,7 @@
|
|||
# Nazi Zombies: Portable dQuakePlus
|
||||
|
||||
## About
|
||||
This repository contains the PSP engine for NZ:P, based on dQuakePlus and containing optimizations from the NZ:P Team, adQuake, and Xash3D-PSP, as well as NZ:P-specific feature implementation. It has also been modified to build on the latest versions of the [PSPSDK](https://github.com/pspdev/pspsdk).
|
||||
This repository contains the PlayStation Portable and Nintendo 3DS engine for NZ:P, based on dQuakePlus and ctrQuake, containing optimizations from the NZ:P Team, adQuake, and Xash3D-PSP, as well as NZ:P-specific feature implementation. It has also been modified to build on the latest versions of the [PSPSDK](https://github.com/pspdev/pspsdk).
|
||||
|
||||
## Building for PlayStation Portable
|
||||
Building requires a full install of [psptoolchain](https://github.com/pspdev/psptoolchain/). You can either follow the instructions on the GitHub repository or use a Docker container (we recommend [the official one](https://hub.docker.com/r/pspdev/pspdev))!
|
||||
|
@ -19,3 +19,21 @@ make -f Makefile.psp install
|
|||
```
|
||||
|
||||
We also provide a prebuilt EBOOT on the [Releases](https://github.com/nzp-team/dquakeplus/releases/tag/bleeding-edge) page.
|
||||
|
||||
## Building for Nintendo 3DS
|
||||
Building requires a full install of [libctru](https://github.com/devkitPro/libctru). You can either follow the instructions on the GitHub repository or use a Docker container (we recommend [the official one](devkitpro/devkitarm))!
|
||||
|
||||
With the psptoolchain installed, you now need to install the latest `picaGL`, which needs cloned from the official GitHub repository:
|
||||
```bash
|
||||
git clone https://github.com/masterfeizz/picaGL.git -b revamp
|
||||
cd picaGL
|
||||
mkdir clean
|
||||
make install
|
||||
```
|
||||
Now you can navigate to the root of the repository and build the `.3dsx`.
|
||||
|
||||
```bash
|
||||
make -f Makefile.ctr
|
||||
```
|
||||
|
||||
We also provide prebuilt .3dsx files on the [Releases](https://github.com/nzp-team/dquakeplus/releases/tag/bleeding-edge) page.
|
BIN
source/ctr/art/banner.png
Normal file
BIN
source/ctr/art/banner.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 65 KiB |
BIN
source/ctr/art/icon.png
Normal file
BIN
source/ctr/art/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
54
source/ctr/bsp_strlcpy.c
Normal file
54
source/ctr/bsp_strlcpy.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
/* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "strl_fn.h"
|
||||
|
||||
/*
|
||||
* Copy src to string dst of size siz. At most siz-1 characters
|
||||
* will be copied. Always NUL terminates (unless siz == 0).
|
||||
* Returns strlen(src); if retval >= siz, truncation occurred.
|
||||
*/
|
||||
|
||||
size_t
|
||||
q_strlcpy (char *dst, const char *src, size_t siz)
|
||||
{
|
||||
char *d = dst;
|
||||
const char *s = src;
|
||||
size_t n = siz;
|
||||
|
||||
/* Copy as many bytes as will fit */
|
||||
if (n != 0) {
|
||||
while (--n != 0) {
|
||||
if ((*d++ = *s++) == '\0')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not enough room in dst, add NUL and traverse rest of src */
|
||||
if (n == 0) {
|
||||
if (siz != 0)
|
||||
*d = '\0'; /* NUL-terminate dst */
|
||||
while (*s++)
|
||||
;
|
||||
}
|
||||
|
||||
return(s - src - 1); /* count does not include NUL */
|
||||
}
|
55
source/ctr/cd_null.c
Normal file
55
source/ctr/cd_null.c
Normal file
|
@ -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)
|
||||
{
|
||||
}
|
425
source/ctr/client.h
Normal file
425
source/ctr/client.h
Normal file
|
@ -0,0 +1,425 @@
|
|||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public 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];
|
||||
char average; //johnfitz
|
||||
char peak; //johnfitz
|
||||
} lightstyle_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[MAX_SCOREBOARDNAME];
|
||||
float entertime;
|
||||
int points;
|
||||
int maxpoints;
|
||||
int kills;
|
||||
int headshots;
|
||||
} scoreboard_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int destcolor[3];
|
||||
int percent; // 0-256
|
||||
} cshift_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
lt_default, lt_muzzleflash, lt_explosion, lt_rocket,
|
||||
lt_red, lt_blue, lt_redblue, lt_green, NUM_DLIGHTTYPES,
|
||||
lt_explosion2, lt_explosion3, lt_rayred, lt_raygreen
|
||||
} dlighttype_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;
|
||||
qboolean dark; // subtracts light instead of adding
|
||||
vec3_t color; //LordHavoc Lit. Support
|
||||
int type; // color
|
||||
} 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 perks; // Perk icons.
|
||||
int progress_bar; // Perk icons.
|
||||
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
|
||||
vec3_t gun_kick; // temporary kick
|
||||
|
||||
// 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
|
||||
double ctime; // joe: copy of cl.time, to avoid incidents caused by rewind
|
||||
|
||||
|
||||
float last_received_message; // (realtime) for net trouble icon
|
||||
double laser_point_time;
|
||||
|
||||
//
|
||||
// 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
|
||||
entity_t viewent2; // the second 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 float cl_forwardspeed;
|
||||
extern float cl_backspeed;
|
||||
extern float 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 in_tolerance;
|
||||
extern cvar_t in_acceleration;
|
||||
extern cvar_t in_aimassist;
|
||||
extern cvar_t in_analog_strafe;
|
||||
|
||||
extern cvar_t m_pitch;
|
||||
extern cvar_t m_yaw;
|
||||
extern cvar_t m_forward;
|
||||
extern cvar_t m_side;
|
||||
extern cvar_t in_mlook;
|
||||
|
||||
|
||||
#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];
|
||||
extern int cl_numstaticbrushmodels;
|
||||
extern entity_t *cl_staticbrushmodels[MAX_VISEDICTS];
|
||||
|
||||
// model indexes
|
||||
typedef enum modelindex_s
|
||||
{
|
||||
mi_player,
|
||||
mi_eyes,
|
||||
mi_flame0,
|
||||
mi_flame1,
|
||||
mi_flame2,
|
||||
mi_q3torso,
|
||||
mi_q3head,
|
||||
/*
|
||||
mi_vw_light,
|
||||
mi_vw_nail1,
|
||||
mi_vw_nail2,
|
||||
mi_vw_rock1,
|
||||
mi_vw_rock2,
|
||||
mi_vw_shot1,
|
||||
mi_vw_shot2,
|
||||
mi_vw_player,
|
||||
*/
|
||||
NUM_MODELINDEX
|
||||
} modelindex_t;
|
||||
|
||||
extern modelindex_t cl_modelindex[NUM_MODELINDEX];
|
||||
extern char *cl_modelnames[NUM_MODELINDEX];
|
||||
|
||||
//
|
||||
// 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_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);
|
||||
|
||||
qboolean TraceLineN (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal);
|
1744
source/ctr/common.c
Normal file
1744
source/ctr/common.c
Normal file
File diff suppressed because it is too large
Load diff
195
source/ctr/common.h
Normal file
195
source/ctr/common.h
Normal file
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public 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
|
||||
|
||||
|
||||
#ifndef min
|
||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
#ifndef max
|
||||
#define max(a, b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#define bound(a, b, c) ((a) >= (c) ? (a) : (b) < (a) ? (a) : (b) > (c) ? (c) : (b))
|
||||
|
||||
#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);
|
||||
|
||||
#define LittleLong(l) l
|
||||
#define LittleShort(l) l
|
||||
#define LittleFloat(l) 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_strcasecmp (char *s1, char *s2);
|
||||
int Q_strncasecmp (char *s1, char *s2, int n);
|
||||
int Q_atoi (char *str);
|
||||
float Q_atof (char *str);
|
||||
int q_snprintf (char *str, size_t size, const char *format, ...);
|
||||
int q_vsnprintf(char *str, size_t size, const char *format, va_list args);
|
||||
|
||||
//============================================================================
|
||||
|
||||
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;
|
||||
void Q_strncpyz (char *dest, char *src, size_t size); //Diabolickal HLBSP
|
100
source/ctr/dosisms.h
Normal file
100
source/ctr/dosisms.h
Normal file
|
@ -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_
|
||||
|
156
source/ctr/gl/gl_decal.c
Normal file
156
source/ctr/gl/gl_decal.c
Normal file
|
@ -0,0 +1,156 @@
|
|||
|
||||
#include "../../quakedef.h"
|
||||
|
||||
void R_SpawnDecal (vec3_t center, vec3_t normal, vec3_t tangent, int tex, int size, int isbsp)
|
||||
{
|
||||
// naievil -- fixme
|
||||
/*
|
||||
int a;
|
||||
float width, height, depth, d, one_over_w, one_over_h;
|
||||
vec3_t binormal, test = {0.5, 0.5, 0.5};
|
||||
decal_t *dec;
|
||||
|
||||
if (!qmb_initialized)
|
||||
return;
|
||||
|
||||
// allocate decal
|
||||
if (!free_decals)
|
||||
return;
|
||||
|
||||
dec = free_decals;
|
||||
free_decals = dec->next;
|
||||
dec->next = active_decals;
|
||||
active_decals = dec;
|
||||
|
||||
VectorNormalize (test);
|
||||
CrossProduct (normal, test, tangent);
|
||||
|
||||
VectorCopy (center, dec->origin);
|
||||
VectorCopy (tangent, dec->tangent);
|
||||
VectorCopy (normal, dec->normal);
|
||||
VectorNormalize (tangent);
|
||||
VectorNormalize (normal);
|
||||
CrossProduct (normal, tangent, binormal);
|
||||
VectorNormalize (binormal);
|
||||
|
||||
width = RandomMinMax (size * 0.5, size);
|
||||
height = width;
|
||||
depth = width * 0.5;
|
||||
dec->radius = fmax(fmax(width, height), depth);
|
||||
dec->starttime = cl.time;
|
||||
dec->bspdecal = isbsp;
|
||||
dec->die = (isbsp ? 0 : cl.time + r_decaltime.value);
|
||||
dec->texture = tex;
|
||||
|
||||
// Calculate boundary planes
|
||||
d = DotProduct (center, tangent);
|
||||
VectorCopy (tangent, leftPlane.normal);
|
||||
leftPlane.dist = -(width * 0.5 - d);
|
||||
VectorNegate (tangent, tangent);
|
||||
VectorCopy (tangent, rightPlane.normal);
|
||||
VectorNegate (tangent, tangent);
|
||||
rightPlane.dist = -(width * 0.5 + d);
|
||||
|
||||
d = DotProduct (center, binormal);
|
||||
VectorCopy (binormal, bottomPlane.normal);
|
||||
bottomPlane.dist = -(height * 0.5 - d);
|
||||
VectorNegate (binormal, binormal);
|
||||
VectorCopy (binormal, topPlane.normal);
|
||||
VectorNegate (binormal, binormal);
|
||||
topPlane.dist = -(height * 0.5 + d);
|
||||
|
||||
d = DotProduct (center, normal);
|
||||
VectorCopy (normal, backPlane.normal);
|
||||
backPlane.dist = -(depth - d);
|
||||
VectorNegate (normal, normal);
|
||||
VectorCopy (normal, frontPlane.normal);
|
||||
VectorNegate (normal, normal);
|
||||
frontPlane.dist = -(depth + d);
|
||||
|
||||
// Begin with empty mesh
|
||||
dec->vertexCount = 0;
|
||||
dec->triangleCount = 0;
|
||||
|
||||
// Clip decal to bsp
|
||||
DecalWalkBsp_R (dec, cl.worldmodel->nodes);
|
||||
|
||||
// This happens when a decal is to far from any surface or the surface is to steeply sloped
|
||||
if (dec->triangleCount == 0)
|
||||
{ // deallocate decal
|
||||
active_decals = dec->next;
|
||||
dec->next = free_decals;
|
||||
free_decals = dec;
|
||||
return;
|
||||
}
|
||||
|
||||
// Assign texture mapping coordinates
|
||||
one_over_w = 1.0F / width;
|
||||
one_over_h = 1.0F / height;
|
||||
for (a = 0 ; a < dec->vertexCount ; a++)
|
||||
{
|
||||
float s, t;
|
||||
vec3_t v;
|
||||
|
||||
VectorSubtract (dec->vertexArray[a], center, v);
|
||||
s = DotProduct (v, tangent) * one_over_w + 0.5F;
|
||||
t = DotProduct (v, binormal) * one_over_h + 0.5F;
|
||||
dec->texcoordArray[a][0] = s;
|
||||
dec->texcoordArray[a][1] = t;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
//Revamped by blubs
|
||||
void R_SpawnDecalStatic (vec3_t org, int tex, int size)
|
||||
{
|
||||
/*
|
||||
int i;
|
||||
float frac, bestfrac;
|
||||
vec3_t tangent, v, bestorg, normal, bestnormal, org2;
|
||||
vec3_t tempVec;
|
||||
|
||||
if (!qmb_initialized)
|
||||
return;
|
||||
|
||||
VectorClear (bestorg);
|
||||
VectorClear (bestnormal);
|
||||
VectorClear(tempVec);
|
||||
|
||||
bestfrac = 10;
|
||||
for (i = 0 ; i < 26 ; i++)
|
||||
{
|
||||
//Reference: i = 0: check straight up, i = 1: check straight down
|
||||
//1 < i < 10: Check sideways in increments of 45 degrees
|
||||
//9 < i < 18: Check angled 45 degrees down in increments of 45 degrees
|
||||
//17 < i : Check angled 45 degrees up in increments of 45 degrees
|
||||
org2[0] = (((((i - 2) % 8) < 2) || (((i - 2) % 8) == 7)) ? 1 : 0 ) + ((((i - 2) % 8) > 2 && ((i - 2) % 8) < 6) ? -1 : 0 );
|
||||
org2[1] = ((((i - 2) % 8) > 0 && ((i - 2) % 8) < 4) ? 1 : 0 ) + ((((i - 2) % 8) > 4 && ((i - 2) % 8) < 7) ? -1 : 0 );
|
||||
org2[2] = ((i == 0) ? 1 : 0) + ((i == 1) ? -1 : 0) + (((i > 9) && (i < 18)) ? 1 : 0) + ((i > 17) ? -1 : 0);
|
||||
|
||||
VectorCopy(org,tempVec);
|
||||
VectorMA(tempVec, -0.1,org2,tempVec);
|
||||
|
||||
VectorMA (org, 20, org2, org2);
|
||||
TraceLineN (tempVec, org2, v, normal);
|
||||
|
||||
VectorSubtract(org2,tempVec,org2);//goal
|
||||
VectorSubtract(v,tempVec,tempVec);//collision
|
||||
|
||||
if(VectorLength(org2) == 0)
|
||||
return;
|
||||
|
||||
frac = VectorLength(tempVec) / VectorLength(org2);
|
||||
|
||||
if(frac < 1 && frac < bestfrac)
|
||||
{
|
||||
bestfrac = frac;
|
||||
VectorCopy(v,bestorg);
|
||||
VectorCopy(normal, bestnormal);
|
||||
CrossProduct(normal,bestnormal,tangent);
|
||||
}
|
||||
}
|
||||
|
||||
if (bestfrac < 1)
|
||||
R_SpawnDecal (bestorg, bestnormal, tangent, tex, size, 0);
|
||||
*/
|
||||
}
|
2
source/ctr/gl/gl_decal.h
Normal file
2
source/ctr/gl/gl_decal.h
Normal file
|
@ -0,0 +1,2 @@
|
|||
void R_SpawnDecal (vec3_t center, vec3_t normal, vec3_t tangent, int tex, int size, int isbsp);
|
||||
void R_SpawnDecalStatic (vec3_t org, int tex, int size);
|
2338
source/ctr/gl/gl_draw.c
Normal file
2338
source/ctr/gl/gl_draw.c
Normal file
File diff suppressed because it is too large
Load diff
517
source/ctr/gl/gl_fog.c
Normal file
517
source/ctr/gl/gl_fog.c
Normal file
|
@ -0,0 +1,517 @@
|
|||
/*
|
||||
|
||||
Fogging system based on FitzQuake's implementation
|
||||
Now with Quakespasm bits thrown into it!
|
||||
|
||||
*/
|
||||
|
||||
#include "../../quakedef.h"
|
||||
|
||||
//==============================================================================
|
||||
//
|
||||
// GLOBAL FOG
|
||||
//
|
||||
//==============================================================================
|
||||
|
||||
#define DEFAULT_DENSITY 1.0
|
||||
#define DEFAULT_GRAY 0.3
|
||||
|
||||
float density = 1.0;
|
||||
float fog_density_gl;
|
||||
|
||||
float fog_start;
|
||||
float fog_end;
|
||||
float fog_red;
|
||||
float fog_green;
|
||||
float fog_blue;
|
||||
|
||||
float old_density;
|
||||
float old_start;
|
||||
float old_end;
|
||||
float old_red;
|
||||
float old_green;
|
||||
float old_blue;
|
||||
|
||||
float fade_time; //duration of fade
|
||||
float fade_done; //time when fade will be done
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_Update
|
||||
|
||||
update internal variables
|
||||
=============
|
||||
*/
|
||||
void Fog_Update (float start, float end, float red, float green, float blue, float time)
|
||||
{
|
||||
//save previous settings for fade
|
||||
if (time > 0)
|
||||
{
|
||||
//check for a fade in progress
|
||||
if (fade_done > cl.time)
|
||||
{
|
||||
float f;
|
||||
|
||||
f = (fade_done - cl.time) / fade_time;
|
||||
old_start = f * old_start + (1.0 - f) * fog_start;
|
||||
old_end = f * old_end + (1.0 - f) * fog_end;
|
||||
old_red = f * old_red + (1.0 - f) * fog_red;
|
||||
old_green = f * old_green + (1.0 - f) * fog_green;
|
||||
old_blue = f * old_blue + (1.0 - f) * fog_blue;
|
||||
old_density = f * old_density + (1.0 - f) * fog_density_gl;
|
||||
}
|
||||
else
|
||||
{
|
||||
old_start = fog_start;
|
||||
old_end = fog_end;
|
||||
old_red = fog_red;
|
||||
old_green = fog_green;
|
||||
old_blue = fog_blue;
|
||||
old_density = fog_density_gl;
|
||||
}
|
||||
}
|
||||
|
||||
fog_start = start;
|
||||
fog_end = end;
|
||||
fog_red = red;
|
||||
fog_green = green;
|
||||
fog_blue = blue;
|
||||
fade_time = time;
|
||||
fade_done = cl.time + time;
|
||||
fog_density_gl = ((fog_start / fog_end))/3.5;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_ParseServerMessage
|
||||
|
||||
handle an SVC_FOG message from server
|
||||
=============
|
||||
*/
|
||||
void Fog_ParseServerMessage (void)
|
||||
{
|
||||
float start, end, red, green, blue, time;
|
||||
|
||||
start = MSG_ReadByte() / 255.0;
|
||||
end = MSG_ReadByte() / 255.0;
|
||||
red = MSG_ReadByte() / 255.0;
|
||||
green = MSG_ReadByte() / 255.0;
|
||||
blue = MSG_ReadByte() / 255.0;
|
||||
time = MSG_ReadShort() / 100.0;
|
||||
|
||||
Fog_Update (start, end, red, green, blue, time);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_FogCommand_f
|
||||
|
||||
handle the 'fog' console command
|
||||
=============
|
||||
*/
|
||||
void Fog_FogCommand_f (void)
|
||||
{
|
||||
switch (Cmd_Argc())
|
||||
{
|
||||
default:
|
||||
case 1:
|
||||
Con_Printf("usage:\n");
|
||||
Con_Printf(" fog <fade>\n");
|
||||
Con_Printf(" fog <start> <end>\n");
|
||||
Con_Printf(" fog <red> <green> <blue>\n");
|
||||
Con_Printf(" fog <fade> <red> <green> <blue>\n");
|
||||
Con_Printf(" fog <start> <end> <red> <green> <blue>\n");
|
||||
Con_Printf(" fog <start> <end> <red> <green> <blue> <fade>\n");
|
||||
Con_Printf("current values:\n");
|
||||
Con_Printf(" \"start\" is \"%f\"\n", fog_start);
|
||||
Con_Printf(" \"end\" is \"%f\"\n", fog_end);
|
||||
Con_Printf(" \"red\" is \"%f\"\n", fog_red);
|
||||
Con_Printf(" \"green\" is \"%f\"\n", fog_green);
|
||||
Con_Printf(" \"blue\" is \"%f\"\n", fog_blue);
|
||||
Con_Printf(" \"fade\" is \"%f\"\n", fade_time);
|
||||
break;
|
||||
case 2: //TEST
|
||||
Fog_Update(fog_start,
|
||||
fog_end,
|
||||
fog_red,
|
||||
fog_green,
|
||||
fog_blue,
|
||||
atof(Cmd_Argv(1)));
|
||||
break;
|
||||
case 3:
|
||||
Fog_Update(atof(Cmd_Argv(1)),
|
||||
atof(Cmd_Argv(2)),
|
||||
fog_red,
|
||||
fog_green,
|
||||
fog_blue,
|
||||
0.0);
|
||||
break;
|
||||
case 4:
|
||||
Fog_Update(fog_start,
|
||||
fog_end,
|
||||
CLAMP(0.0, atof(Cmd_Argv(1)), 100.0),
|
||||
CLAMP(0.0, atof(Cmd_Argv(2)), 100.0),
|
||||
CLAMP(0.0, atof(Cmd_Argv(3)), 100.0),
|
||||
0.0);
|
||||
break;
|
||||
case 5: //TEST
|
||||
Fog_Update(fog_start,
|
||||
fog_end,
|
||||
CLAMP(0.0, atof(Cmd_Argv(1)), 100.0),
|
||||
CLAMP(0.0, atof(Cmd_Argv(2)), 100.0),
|
||||
CLAMP(0.0, atof(Cmd_Argv(3)), 100.0),
|
||||
atof(Cmd_Argv(4)));
|
||||
break;
|
||||
case 6:
|
||||
Fog_Update(atof(Cmd_Argv(1)),
|
||||
atof(Cmd_Argv(2)),
|
||||
CLAMP(0.0, atof(Cmd_Argv(3)), 100.0),
|
||||
CLAMP(0.0, atof(Cmd_Argv(4)), 100.0),
|
||||
CLAMP(0.0, atof(Cmd_Argv(5)), 100.0),
|
||||
0.0);
|
||||
break;
|
||||
case 7:
|
||||
Fog_Update(atof(Cmd_Argv(1)),
|
||||
atof(Cmd_Argv(2)),
|
||||
CLAMP(0.0, atof(Cmd_Argv(3)), 100.0),
|
||||
CLAMP(0.0, atof(Cmd_Argv(4)), 100.0),
|
||||
CLAMP(0.0, atof(Cmd_Argv(5)), 100.0),
|
||||
atof(Cmd_Argv(6)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_ParseWorldspawn
|
||||
|
||||
called at map load
|
||||
=============
|
||||
*/
|
||||
void Fog_ParseWorldspawn (void)
|
||||
{
|
||||
char key[128], value[4096];
|
||||
const char *data;
|
||||
|
||||
fog_density_gl = DEFAULT_DENSITY;
|
||||
//initially no fog
|
||||
fog_start = 0;
|
||||
old_start = 0;
|
||||
|
||||
fog_end = 4000;
|
||||
old_end = 4000;
|
||||
|
||||
fog_red = 0.0;
|
||||
old_red = 0.0;
|
||||
|
||||
fog_green = 0.0;
|
||||
old_green = 0.0;
|
||||
|
||||
fog_blue = 0.0;
|
||||
old_blue = 0.0;
|
||||
|
||||
fade_time = 0.0;
|
||||
fade_done = 0.0;
|
||||
|
||||
data = COM_Parse(cl.worldmodel->entities);
|
||||
if (!data)
|
||||
return; // error
|
||||
if (com_token[0] != '{')
|
||||
return; // error
|
||||
while (1)
|
||||
{
|
||||
data = COM_Parse(data);
|
||||
if (!data)
|
||||
return; // error
|
||||
if (com_token[0] == '}')
|
||||
break; // end of worldspawn
|
||||
if (com_token[0] == '_')
|
||||
strcpy(key, com_token + 1);
|
||||
else
|
||||
strcpy(key, com_token);
|
||||
while (key[strlen(key)-1] == ' ') // remove trailing spaces
|
||||
key[strlen(key)-1] = 0;
|
||||
data = COM_Parse(data);
|
||||
if (!data)
|
||||
return; // error
|
||||
strcpy(value, com_token);
|
||||
|
||||
if (!strcmp("fog", key))
|
||||
{
|
||||
sscanf(value, "%f %f %f %f %f", &fog_start, &fog_end, &fog_red, &fog_green, &fog_blue);
|
||||
}
|
||||
|
||||
fog_density_gl = ((fog_start / fog_end))/3.5;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_GetColor
|
||||
|
||||
calculates fog color for this frame, taking into account fade times
|
||||
=============
|
||||
*/
|
||||
float *Fog_GetColor (void)
|
||||
{
|
||||
static float c[4]; // = {0.1f, 0.1f, 0.1f, 1.0f}
|
||||
|
||||
float f;
|
||||
int i;
|
||||
|
||||
if (fade_done > cl.time)
|
||||
{
|
||||
f = (fade_done - cl.time) / fade_time;
|
||||
c[0] = f * old_red + (1.0 - f) * fog_red;
|
||||
c[1] = f * old_green + (1.0 - f) * fog_green;
|
||||
c[2] = f * old_blue + (1.0 - f) * fog_blue;
|
||||
c[3] = 1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
c[0] = fog_red;
|
||||
c[1] = fog_green;
|
||||
c[2] = fog_blue;
|
||||
c[3] = 1.0;
|
||||
}
|
||||
|
||||
//find closest 24-bit RGB value, so solid-colored sky can match the fog perfectly
|
||||
for (i=0;i<3;i++)
|
||||
c[i] = (float)(rint(c[i] * 255)) / 255.0f;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
c[i] /= 64.0;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_GetDensity
|
||||
|
||||
returns current density of fog
|
||||
|
||||
=============
|
||||
*/
|
||||
float Fog_GetDensity (void)
|
||||
{
|
||||
float f;
|
||||
|
||||
if (fade_done > cl.time)
|
||||
{
|
||||
f = (fade_done - cl.time) / fade_time;
|
||||
return f * old_density + (1.0 - f) * fog_density_gl;
|
||||
}
|
||||
else
|
||||
return fog_density_gl;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_SetupFrame
|
||||
|
||||
called at the beginning of each frame
|
||||
=============
|
||||
*/
|
||||
void Fog_SetupFrame (void)
|
||||
{
|
||||
glFogfv(GL_FOG_COLOR, Fog_GetColor());
|
||||
glFogf(GL_FOG_DENSITY, 0.2f);
|
||||
glFogf(GL_FOG_START, fog_start);
|
||||
glFogf(GL_FOG_END, fog_end);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_SetColorForSkyS
|
||||
Start called before drawing flat-colored sky
|
||||
Crow_bar*
|
||||
=============
|
||||
*/
|
||||
void Fog_SetColorForSkyS (void)
|
||||
{
|
||||
if (fog_end > 0.0f && r_skyfog.value)
|
||||
{
|
||||
float a = fog_end * 0.00025f;
|
||||
float r = fog_red * 0.01f + (a * 0.25f);
|
||||
float g = fog_green * 0.01f + (a * 0.25f);
|
||||
float b = fog_blue * 0.01f + (a * 0.25f);
|
||||
|
||||
if (a > 1.0f)
|
||||
a = 1.0f;
|
||||
if (r > 1.0f)
|
||||
r = 1.0f;
|
||||
if (g > 1.0f)
|
||||
g = 1.0f;
|
||||
if (b > 1.0f)
|
||||
b = 1.0f;
|
||||
|
||||
glColor4f(r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_GetStart
|
||||
returns current start of fog
|
||||
=============
|
||||
*/
|
||||
float Fog_GetStart (void)
|
||||
{
|
||||
float f;
|
||||
|
||||
if (fade_done > cl.time)
|
||||
{
|
||||
f = (fade_done - cl.time) / fade_time;
|
||||
return f * old_start + (1.0 - f) * fog_start;
|
||||
}
|
||||
else
|
||||
return fog_start;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_GetEnd
|
||||
returns current end of fog
|
||||
=============
|
||||
*/
|
||||
float Fog_GetEnd (void)
|
||||
{
|
||||
float f;
|
||||
|
||||
if (fade_done > cl.time)
|
||||
{
|
||||
f = (fade_done - cl.time) / fade_time;
|
||||
return f * old_start + (1.0 - f) * fog_end;
|
||||
}
|
||||
else
|
||||
return fog_end;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_SetColorForSky
|
||||
End called before drawing flat-colored sky
|
||||
Crow_bar*
|
||||
=============
|
||||
*/
|
||||
void Fog_SetColorForSkyE (void)
|
||||
{
|
||||
if (fog_end > 0.0f && r_skyfog.value)
|
||||
{
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_EnableGFog
|
||||
|
||||
called before drawing stuff that should be fogged
|
||||
=============
|
||||
*/
|
||||
void Fog_EnableGFog (void)
|
||||
{
|
||||
if (!Fog_GetStart() == 0 || !Fog_GetEnd() <= 0) {
|
||||
glEnable(GL_FOG);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_DisableGFog
|
||||
|
||||
called after drawing stuff that should be fogged
|
||||
=============
|
||||
*/
|
||||
void Fog_DisableGFog (void)
|
||||
{
|
||||
if (!Fog_GetStart() == 0 || !Fog_GetEnd() <= 0)
|
||||
glDisable(GL_FOG);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_SetColorForSky
|
||||
|
||||
called before drawing flat-colored sky
|
||||
=============
|
||||
*/
|
||||
/*
|
||||
void Fog_SetColorForSky (void)
|
||||
{
|
||||
float c[3];
|
||||
float f, d;
|
||||
|
||||
if (fade_done > cl.time)
|
||||
{
|
||||
f = (fade_done - cl.time) / fade_time;
|
||||
d = f * old_density + (1.0 - f) * fog_density;
|
||||
c[0] = f * old_red + (1.0 - f) * fog_red;
|
||||
c[1] = f * old_green + (1.0 - f) * fog_green;
|
||||
c[2] = f * old_blue + (1.0 - f) * fog_blue;
|
||||
}
|
||||
else
|
||||
{
|
||||
d = fog_density;
|
||||
c[0] = fog_red;
|
||||
c[1] = fog_green;
|
||||
c[2] = fog_blue;
|
||||
}
|
||||
|
||||
if (d > 0)
|
||||
glColor3fv (c);
|
||||
}
|
||||
*/
|
||||
//==============================================================================
|
||||
//
|
||||
// VOLUMETRIC FOG
|
||||
//
|
||||
//==============================================================================
|
||||
/*
|
||||
|
||||
void Fog_DrawVFog (void){}
|
||||
void Fog_MarkModels (void){}
|
||||
*/
|
||||
//==============================================================================
|
||||
//
|
||||
// INIT
|
||||
//
|
||||
//==============================================================================
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_NewMap
|
||||
|
||||
called whenever a map is loaded
|
||||
=============
|
||||
*/
|
||||
|
||||
void Fog_NewMap (void)
|
||||
{
|
||||
Fog_ParseWorldspawn (); //for global fog
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_Init
|
||||
|
||||
called when quake initializes
|
||||
=============
|
||||
*/
|
||||
void Fog_Init (void)
|
||||
{
|
||||
Cmd_AddCommand ("fog",Fog_FogCommand_f);
|
||||
|
||||
//set up global fog
|
||||
fog_start = 300;
|
||||
fog_end = 4000;
|
||||
fog_red = 0.5;
|
||||
fog_green = 0.5;
|
||||
fog_blue = 0.5;
|
||||
fade_time = 1;
|
||||
fog_density_gl = DEFAULT_DENSITY;
|
||||
fade_time = 1;
|
||||
|
||||
glFogi(GL_FOG_MODE, GL_LINEAR);
|
||||
}
|
318
source/ctr/gl/gl_mesh.c
Normal file
318
source/ctr/gl/gl_mesh.c
Normal file
|
@ -0,0 +1,318 @@
|
|||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public 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);
|
||||
|
||||
BuildTris (); // trifans or lists
|
||||
|
||||
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]];
|
||||
}
|
2130
source/ctr/gl/gl_model.c
Normal file
2130
source/ctr/gl/gl_model.c
Normal file
File diff suppressed because it is too large
Load diff
468
source/ctr/gl/gl_model.h
Normal file
468
source/ctr/gl/gl_model.h
Normal file
|
@ -0,0 +1,468 @@
|
|||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public 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_BLUELIGHT 1
|
||||
#define EF_MUZZLEFLASH 2
|
||||
#define EF_BRIGHTLIGHT 4
|
||||
#define EF_REDLIGHT 8
|
||||
#define EF_ORANGELIGHT 16
|
||||
#define EF_GREENLIGHT 32
|
||||
#define EF_PINKLIGHT 64 // formerly EF_LIGHT
|
||||
#define EF_NODRAW 128
|
||||
#define EF_LIMELIGHT 256 // formerly EF_BRIGHTFIELD
|
||||
#define EF_FULLBRIGHT 512
|
||||
#define EF_CYANLIGHT 1024 // formerly EF_DARKLIGHT
|
||||
#define EF_YELLOWLIGHT 2048 // formerly EF_DARKFIELD
|
||||
#define EF_PURPLELIGHT 4096
|
||||
#define EF_RAYRED 8196 // red trail for porter x2
|
||||
#define EF_RAYGREEN 16384 // green trail for ray gun
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
BRUSH MODELS
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
|
||||
//
|
||||
// in memory representation
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
vec3_t position;
|
||||
} mvertex_t;
|
||||
|
||||
#define SIDE_FRONT 0
|
||||
#define SIDE_BACK 1
|
||||
#define SIDE_ON 2
|
||||
|
||||
|
||||
// plane_t structure
|
||||
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
|
||||
|
||||
#define TEXFLAG_NODRAW 256
|
||||
#define TEXFLAG_LIGHT 512
|
||||
|
||||
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)
|
||||
// vec3_t midpoint;//MHQuake // naievil -- fixme: this guy is causing some kind of rendering issue
|
||||
} 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;
|
||||
unsigned int dlightbits[(MAX_DLIGHTS + 31) >> 5];
|
||||
// int is 32 bits, need an array for MAX_DLIGHTS > 32
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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 2048
|
||||
#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
|
||||
|
||||
|
||||
// some models are special
|
||||
typedef enum
|
||||
{
|
||||
MOD_NORMAL,
|
||||
MOD_PLAYER,
|
||||
MOD_EYES,
|
||||
MOD_FLAME,
|
||||
MOD_THUNDERBOLT,
|
||||
MOD_WEAPON,
|
||||
MOD_LAVABALL,
|
||||
MOD_SPIKE,
|
||||
MOD_SHAMBLER,
|
||||
MOD_SPR,
|
||||
MOD_SPR32,
|
||||
// MOD_GKEY,
|
||||
// MOD_SKEY,
|
||||
} modhint_t;
|
||||
|
||||
typedef struct model_s
|
||||
{
|
||||
char name[MAX_QPATH];
|
||||
qboolean needload; // bmodels and sprites don't cache normally
|
||||
|
||||
modhint_t modhint;
|
||||
|
||||
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
|
||||
|
||||
int bspversion; //Diabolickal HLBSP
|
||||
|
||||
} 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);
|
||||
|
||||
int GL_LoadTexture32 (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha); //Diabolickal HLBSP
|
||||
void BuildGammaTable (float g);
|
||||
int loadtextureimage (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap); //Diabolickal TGA
|
||||
|
||||
#endif // __MODEL__
|
3040
source/ctr/gl/gl_qmb.c
Normal file
3040
source/ctr/gl/gl_qmb.c
Normal file
File diff suppressed because it is too large
Load diff
234
source/ctr/gl/gl_refrag.c
Normal file
234
source/ctr/gl/gl_refrag.c
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
399
source/ctr/gl/gl_rlight.c
Normal file
399
source/ctr/gl/gl_rlight.c
Normal file
|
@ -0,0 +1,399 @@
|
|||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public 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;
|
||||
|
||||
extern cvar_t r_flatlightstyles; //johnfitz
|
||||
|
||||
/*
|
||||
==================
|
||||
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;
|
||||
}
|
||||
//johnfitz -- r_flatlightstyles
|
||||
if (r_flatlightstyles.value == 2)
|
||||
k = cl_lightstyle[j].peak - 'a';
|
||||
else if (r_flatlightstyles.value == 1)
|
||||
k = cl_lightstyle[j].average - 'a';
|
||||
else
|
||||
{
|
||||
k = i % cl_lightstyle[j].length;
|
||||
k = cl_lightstyle[j].map[k] - 'a';
|
||||
}
|
||||
d_lightstylevalue[j] = k*22;
|
||||
//johnfitz
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
DYNAMIC LIGHTS BLEND RENDERING (gl_flashblend 1)
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
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)
|
||||
{
|
||||
#if 0
|
||||
int i, j;
|
||||
float a;
|
||||
vec3_t v;
|
||||
float rad;
|
||||
|
||||
rad = light->radius * 0.35;
|
||||
|
||||
|
||||
VectorSubtract (light->origin, r_origin, v);
|
||||
if (VectorLength (v) < rad)
|
||||
{ // view is inside the dlight
|
||||
AddLightBlend (1, 0.5, 0, light->radius * 0.0003);
|
||||
return;
|
||||
}
|
||||
|
||||
glBegin (GL_TRIANGLE_FAN);
|
||||
//glColor4f(lightcolor[0]/255, lightcolor[1]/255, lightcolor[2]/255, 1.0f);
|
||||
glColor4f (light->color[0]*0.2f,light->color[1]*0.2f,light->color[2]*0.2f, 1.0f);
|
||||
//glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
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 ();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_RenderDlights
|
||||
=============
|
||||
*/
|
||||
void R_RenderDlights (void)
|
||||
{
|
||||
#if 0
|
||||
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 (GL_FALSE);
|
||||
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 (GL_TRUE);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
DYNAMIC LIGHTS
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
=============
|
||||
R_MarkLights -- johnfitz -- rewritten to use LordHavoc's lighting speedup
|
||||
=============
|
||||
*/
|
||||
void R_MarkLights (dlight_t *light, int num, mnode_t *node)
|
||||
{
|
||||
mplane_t *splitplane;
|
||||
msurface_t *surf;
|
||||
vec3_t impact;
|
||||
float dist, l, maxdist;
|
||||
int i, j, s, t;
|
||||
|
||||
start:
|
||||
|
||||
if (node->contents < 0)
|
||||
return;
|
||||
|
||||
splitplane = node->plane;
|
||||
if (splitplane->type < 3)
|
||||
dist = light->origin[splitplane->type] - splitplane->dist;
|
||||
else
|
||||
dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist;
|
||||
|
||||
if (dist > light->radius)
|
||||
{
|
||||
node = node->children[0];
|
||||
goto start;
|
||||
}
|
||||
if (dist < -light->radius)
|
||||
{
|
||||
node = node->children[1];
|
||||
goto start;
|
||||
}
|
||||
|
||||
maxdist = light->radius*light->radius;
|
||||
// mark the polygons
|
||||
surf = cl.worldmodel->surfaces + node->firstsurface;
|
||||
for (i=0 ; i<node->numsurfaces ; i++, surf++)
|
||||
{
|
||||
for (j=0 ; j<3 ; j++)
|
||||
impact[j] = light->origin[j] - surf->plane->normal[j]*dist;
|
||||
// clamp center of light to corner and check brightness
|
||||
l = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
|
||||
s = l+0.5;if (s < 0) s = 0;else if (s > surf->extents[0]) s = surf->extents[0];
|
||||
s = l - s;
|
||||
l = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1];
|
||||
t = l+0.5;if (t < 0) t = 0;else if (t > surf->extents[1]) t = surf->extents[1];
|
||||
t = l - t;
|
||||
// compare to minimum light
|
||||
if ((s*s+t*t+dist*dist) < maxdist)
|
||||
{
|
||||
if (surf->dlightframe != r_dlightframecount) // not dynamic until now
|
||||
{
|
||||
surf->dlightbits[num >> 5] = 1U << (num & 31);
|
||||
surf->dlightframe = r_dlightframecount;
|
||||
}
|
||||
else // already dynamic
|
||||
surf->dlightbits[num >> 5] |= 1U << (num & 31);
|
||||
}
|
||||
}
|
||||
|
||||
if (node->children[0]->contents >= 0)
|
||||
R_MarkLights (light, num, node->children[0]);
|
||||
if (node->children[1]->contents >= 0)
|
||||
R_MarkLights (light, num, 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, i, cl.worldmodel->nodes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
LIGHT SAMPLING
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
mplane_t *lightplane;
|
||||
vec3_t lightspot;
|
||||
vec3_t lightcolor; //johnfitz -- lit support via lordhavoc
|
||||
|
||||
/*
|
||||
=============
|
||||
RecursiveLightPoint -- johnfitz -- replaced entire function for lit support via lordhavoc
|
||||
=============
|
||||
*/
|
||||
int RecursiveLightPoint (vec3_t color, mnode_t *node, vec3_t start, vec3_t end)
|
||||
{
|
||||
float front, back, frac;
|
||||
vec3_t mid;
|
||||
|
||||
loc0:
|
||||
if (node->contents < 0)
|
||||
return false; // didn't hit anything
|
||||
|
||||
// calculate mid point
|
||||
if (node->plane->type < 3)
|
||||
{
|
||||
front = start[node->plane->type] - node->plane->dist;
|
||||
back = end[node->plane->type] - node->plane->dist;
|
||||
}
|
||||
else
|
||||
{
|
||||
front = DotProduct(start, node->plane->normal) - node->plane->dist;
|
||||
back = DotProduct(end, node->plane->normal) - node->plane->dist;
|
||||
}
|
||||
|
||||
// LordHavoc: optimized recursion
|
||||
if ((back < 0) == (front < 0))
|
||||
// return RecursiveLightPoint (color, node->children[front < 0], start, end);
|
||||
{
|
||||
node = node->children[front < 0];
|
||||
goto loc0;
|
||||
}
|
||||
|
||||
frac = front / (front-back);
|
||||
mid[0] = start[0] + (end[0] - start[0])*frac;
|
||||
mid[1] = start[1] + (end[1] - start[1])*frac;
|
||||
mid[2] = start[2] + (end[2] - start[2])*frac;
|
||||
|
||||
// go down front side
|
||||
if (RecursiveLightPoint (color, node->children[front < 0], start, mid))
|
||||
return true; // hit something
|
||||
else
|
||||
{
|
||||
int i, ds, dt;
|
||||
msurface_t *surf;
|
||||
// check for impact on this node
|
||||
VectorCopy (mid, lightspot);
|
||||
lightplane = node->plane;
|
||||
|
||||
surf = cl.worldmodel->surfaces + node->firstsurface;
|
||||
for (i = 0;i < node->numsurfaces;i++, surf++)
|
||||
{
|
||||
if (surf->flags & SURF_DRAWTILED)
|
||||
continue; // no lightmaps
|
||||
|
||||
// ericw -- added double casts to force 64-bit precision.
|
||||
// Without them the zombie at the start of jam3_ericw.bsp was
|
||||
// incorrectly being lit up in SSE builds.
|
||||
ds = (int) ((double) DoublePrecisionDotProduct (mid, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]);
|
||||
dt = (int) ((double) DoublePrecisionDotProduct (mid, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]);
|
||||
|
||||
if (ds < surf->texturemins[0] || dt < surf->texturemins[1])
|
||||
continue;
|
||||
|
||||
ds -= surf->texturemins[0];
|
||||
dt -= surf->texturemins[1];
|
||||
|
||||
if (ds > surf->extents[0] || dt > surf->extents[1])
|
||||
continue;
|
||||
|
||||
if (surf->samples)
|
||||
{
|
||||
// LordHavoc: enhanced to interpolate lighting
|
||||
byte *lightmap;
|
||||
int maps, line3, dsfrac = ds & 15, dtfrac = dt & 15, r00 = 0, g00 = 0, b00 = 0, r01 = 0, g01 = 0, b01 = 0, r10 = 0, g10 = 0, b10 = 0, r11 = 0, g11 = 0, b11 = 0;
|
||||
float scale;
|
||||
line3 = ((surf->extents[0]>>4)+1)*3;
|
||||
|
||||
lightmap = surf->samples + ((dt>>4) * ((surf->extents[0]>>4)+1) + (ds>>4))*3; // LordHavoc: *3 for color
|
||||
|
||||
for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != 255;maps++)
|
||||
{
|
||||
scale = (float) d_lightstylevalue[surf->styles[maps]] * 1.0 / 256.0;
|
||||
r00 += (float) lightmap[ 0] * scale;g00 += (float) lightmap[ 1] * scale;b00 += (float) lightmap[2] * scale;
|
||||
r01 += (float) lightmap[ 3] * scale;g01 += (float) lightmap[ 4] * scale;b01 += (float) lightmap[5] * scale;
|
||||
r10 += (float) lightmap[line3+0] * scale;g10 += (float) lightmap[line3+1] * scale;b10 += (float) lightmap[line3+2] * scale;
|
||||
r11 += (float) lightmap[line3+3] * scale;g11 += (float) lightmap[line3+4] * scale;b11 += (float) lightmap[line3+5] * scale;
|
||||
lightmap += ((surf->extents[0]>>4)+1) * ((surf->extents[1]>>4)+1)*3; // LordHavoc: *3 for colored lighting
|
||||
}
|
||||
|
||||
color[0] += (float) ((int) ((((((((r11-r10) * dsfrac) >> 4) + r10)-((((r01-r00) * dsfrac) >> 4) + r00)) * dtfrac) >> 4) + ((((r01-r00) * dsfrac) >> 4) + r00)));
|
||||
color[1] += (float) ((int) ((((((((g11-g10) * dsfrac) >> 4) + g10)-((((g01-g00) * dsfrac) >> 4) + g00)) * dtfrac) >> 4) + ((((g01-g00) * dsfrac) >> 4) + g00)));
|
||||
color[2] += (float) ((int) ((((((((b11-b10) * dsfrac) >> 4) + b10)-((((b01-b00) * dsfrac) >> 4) + b00)) * dtfrac) >> 4) + ((((b01-b00) * dsfrac) >> 4) + b00)));
|
||||
}
|
||||
return true; // success
|
||||
}
|
||||
|
||||
// go down back side
|
||||
return RecursiveLightPoint (color, node->children[front >= 0], mid, end);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_LightPoint -- johnfitz -- replaced entire function for lit support via lordhavoc
|
||||
=============
|
||||
*/
|
||||
int R_LightPoint (vec3_t p)
|
||||
{
|
||||
vec3_t end;
|
||||
|
||||
if (!cl.worldmodel->lightdata)
|
||||
{
|
||||
lightcolor[0] = lightcolor[1] = lightcolor[2] = 255;
|
||||
return 255;
|
||||
}
|
||||
|
||||
end[0] = p[0];
|
||||
end[1] = p[1];
|
||||
end[2] = p[2] - 8192; //johnfitz -- was 2048
|
||||
|
||||
lightcolor[0] = lightcolor[1] = lightcolor[2] = 0;
|
||||
RecursiveLightPoint (lightcolor, cl.worldmodel->nodes, p, end);
|
||||
return ((lightcolor[0] + lightcolor[1] + lightcolor[2]) * (1.0f / 3.0f));
|
||||
}
|
1882
source/ctr/gl/gl_rmain.c
Normal file
1882
source/ctr/gl/gl_rmain.c
Normal file
File diff suppressed because it is too large
Load diff
516
source/ctr/gl/gl_rmisc.c
Normal file
516
source/ctr/gl/gl_rmisc.c
Normal file
|
@ -0,0 +1,516 @@
|
|||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public 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"
|
||||
|
||||
extern cvar_t r_flatlightstyles;
|
||||
|
||||
int decal_blood1, decal_blood2, decal_blood3, decal_q3blood, decal_burn, decal_mark, decal_glow;
|
||||
int zombie_skins[4];
|
||||
|
||||
/*
|
||||
==================
|
||||
R_InitOtherTextures
|
||||
==================
|
||||
*/
|
||||
void R_InitOtherTextures (void)
|
||||
{
|
||||
//static decals
|
||||
decal_blood1 = loadtextureimage ("textures/decals/blood_splat01", 0, 0, qfalse, qtrue);
|
||||
decal_blood2 = loadtextureimage ("textures/decals/blood_splat02", 0, 0, qfalse, qtrue);
|
||||
decal_blood3 = loadtextureimage ("textures/decals/blood_splat03", 0, 0, qfalse, qtrue);
|
||||
decal_q3blood = loadtextureimage ("textures/decals/blood_stain", 0, 0, qfalse, qtrue);
|
||||
decal_burn = loadtextureimage ("textures/decals/explo_burn01", 0, 0, qfalse, qtrue);
|
||||
decal_mark = loadtextureimage ("textures/decals/particle_burn01", 0, 0, qfalse, qtrue);
|
||||
decal_glow = loadtextureimage ("textures/decals/glow2", 0, 0, qfalse, qtrue);
|
||||
|
||||
// external zombie skins
|
||||
zombie_skins[0] = loadtextureimage ("models/ai/zfull.mdl_0", 0, 0, qtrue, qfalse);
|
||||
zombie_skins[1] = loadtextureimage ("models/ai/zfull.mdl_1", 0, 0, qtrue, qfalse);
|
||||
zombie_skins[2] = loadtextureimage ("models/ai/zfull.mdl_2", 0, 0, qtrue, qfalse);
|
||||
zombie_skins[3] = loadtextureimage ("models/ai/zfull.mdl_3", 0, 0, qtrue, qfalse);
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
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
|
||||
===============
|
||||
*/
|
||||
extern bool new3ds_flag;
|
||||
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 (&r_farclip);
|
||||
|
||||
Cvar_RegisterVariable (&gl_finish);
|
||||
Cvar_RegisterVariable (&gl_clear);
|
||||
Cvar_RegisterVariable (&gl_texsort);
|
||||
|
||||
Cvar_SetValue("gl_clear", 1);
|
||||
|
||||
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);
|
||||
|
||||
Cvar_RegisterVariable (&r_explosiontype);
|
||||
Cvar_RegisterVariable (&r_laserpoint);
|
||||
Cvar_RegisterVariable (&r_part_explosions);
|
||||
Cvar_RegisterVariable (&r_part_trails);
|
||||
Cvar_RegisterVariable (&r_part_sparks);
|
||||
Cvar_RegisterVariable (&r_part_gunshots);
|
||||
Cvar_RegisterVariable (&r_part_blood);
|
||||
Cvar_RegisterVariable (&r_part_telesplash);
|
||||
Cvar_RegisterVariable (&r_part_blobs);
|
||||
Cvar_RegisterVariable (&r_part_lavasplash);
|
||||
Cvar_RegisterVariable (&r_part_flames);
|
||||
Cvar_RegisterVariable (&r_part_lightning);
|
||||
Cvar_RegisterVariable (&r_part_flies);
|
||||
Cvar_RegisterVariable (&r_part_muzzleflash);
|
||||
Cvar_RegisterVariable (&r_flametype);
|
||||
Cvar_RegisterVariable (&r_model_brightness);
|
||||
Cvar_RegisterVariable (&r_skyfog);
|
||||
|
||||
Cvar_RegisterVariable (&r_flatlightstyles);
|
||||
|
||||
R_InitParticles ();
|
||||
R_InitOtherTextures ();
|
||||
R_InitParticleTexture ();
|
||||
|
||||
Sky_Init (); //johnfitz
|
||||
Fog_Init (); //johnfitz
|
||||
|
||||
#ifdef GLTEST
|
||||
Test_Init ();
|
||||
#endif
|
||||
|
||||
playertextures = texture_extension_number;
|
||||
texture_extension_number += 16;
|
||||
|
||||
if (new3ds_flag == true)
|
||||
Cvar_SetValue("r_dynamic", 1);
|
||||
else
|
||||
Cvar_SetValue("r_dynamic", 0);
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
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 = 0xf0;
|
||||
bottom = (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 ();
|
||||
|
||||
Sky_NewMap (); //johnfitz -- skybox in worldspawn
|
||||
Fog_NewMap (); // johnfitz -- global fog in worldspawn
|
||||
|
||||
// identify sky texture
|
||||
skytexturenum = -1;
|
||||
mirrortexturenum = -1;
|
||||
for (i=0 ; i<cl.worldmodel->numtextures ; i++)
|
||||
{
|
||||
if (!cl.worldmodel->textures[i])
|
||||
continue;
|
||||
if (!strncmp(cl.worldmodel->textures[i]->name,"sky",3) )
|
||||
skytexturenum = i;
|
||||
if (!strncmp(cl.worldmodel->textures[i]->name,"window02_1",10) )
|
||||
mirrortexturenum = i;
|
||||
cl.worldmodel->textures[i]->texturechain = NULL;
|
||||
}
|
||||
//R_LoadSkys ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
|
1814
source/ctr/gl/gl_rsurf.c
Normal file
1814
source/ctr/gl/gl_rsurf.c
Normal file
File diff suppressed because it is too large
Load diff
1649
source/ctr/gl/gl_screen.c
Normal file
1649
source/ctr/gl/gl_screen.c
Normal file
File diff suppressed because it is too large
Load diff
182
source/ctr/gl/gl_test.c
Normal file
182
source/ctr/gl/gl_test.c
Normal file
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
#include "../../quakedef.h"
|
||||
|
||||
#ifdef GLTEST
|
||||
|
||||
typedef struct
|
||||
{
|
||||
plane_t *plane;
|
||||
vec3_t origin;
|
||||
vec3_t normal;
|
||||
vec3_t up;
|
||||
vec3_t right;
|
||||
vec3_t reflect;
|
||||
float length;
|
||||
} puff_t;
|
||||
|
||||
#define MAX_PUFFS 64
|
||||
|
||||
puff_t puffs[MAX_PUFFS];
|
||||
|
||||
|
||||
void Test_Init (void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
plane_t junk;
|
||||
plane_t *HitPlane (vec3_t start, vec3_t end)
|
||||
{
|
||||
trace_t trace;
|
||||
|
||||
// fill in a default trace
|
||||
memset (&trace, 0, sizeof(trace_t));
|
||||
trace.fraction = 1;
|
||||
trace.allsolid = true;
|
||||
VectorCopy (end, trace.endpos);
|
||||
|
||||
SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &trace);
|
||||
|
||||
junk = trace.plane;
|
||||
return &junk;
|
||||
}
|
||||
|
||||
void Test_Spawn (vec3_t origin)
|
||||
{
|
||||
int i;
|
||||
puff_t *p;
|
||||
vec3_t temp;
|
||||
vec3_t normal;
|
||||
vec3_t incoming;
|
||||
plane_t *plane;
|
||||
float d;
|
||||
|
||||
for (i=0,p=puffs ; i<MAX_PUFFS ; i++,p++)
|
||||
{
|
||||
if (p->length <= 0)
|
||||
break;
|
||||
}
|
||||
if (i == MAX_PUFFS)
|
||||
return;
|
||||
|
||||
VectorSubtract (r_refdef.vieworg, origin, incoming);
|
||||
VectorSubtract (origin, incoming, temp);
|
||||
plane = HitPlane (r_refdef.vieworg, temp);
|
||||
|
||||
VectorNormalize (incoming);
|
||||
d = DotProduct (incoming, plane->normal);
|
||||
VectorSubtract (vec3_origin, incoming, p->reflect);
|
||||
VectorMA (p->reflect, d*2, plane->normal, p->reflect);
|
||||
|
||||
VectorCopy (origin, p->origin);
|
||||
VectorCopy (plane->normal, p->normal);
|
||||
|
||||
CrossProduct (incoming, p->normal, p->up);
|
||||
|
||||
CrossProduct (p->up, p->normal, p->right);
|
||||
|
||||
p->length = 8;
|
||||
}
|
||||
|
||||
void DrawPuff (puff_t *p)
|
||||
{
|
||||
vec3_t pts[2][3];
|
||||
int i, j;
|
||||
float s, d;
|
||||
|
||||
for (i=0 ; i<2 ; i++)
|
||||
{
|
||||
if (i == 1)
|
||||
{
|
||||
s = 6;
|
||||
d = p->length;
|
||||
}
|
||||
else
|
||||
{
|
||||
s = 2;
|
||||
d = 0;
|
||||
}
|
||||
|
||||
for (j=0 ; j<3 ; j++)
|
||||
{
|
||||
pts[i][0][j] = p->origin[j] + p->up[j]*s + p->reflect[j]*d;
|
||||
pts[i][1][j] = p->origin[j] + p->right[j]*s + p->reflect[j]*d;
|
||||
pts[i][2][j] = p->origin[j] + -p->right[j]*s + p->reflect[j]*d;
|
||||
}
|
||||
}
|
||||
|
||||
glColor3f (1, 0, 0);
|
||||
|
||||
#if 0
|
||||
glBegin (GL_LINES);
|
||||
glVertex3fv (p->origin);
|
||||
glVertex3f (p->origin[0] + p->length*p->reflect[0],
|
||||
p->origin[1] + p->length*p->reflect[1],
|
||||
p->origin[2] + p->length*p->reflect[2]);
|
||||
|
||||
glVertex3fv (pts[0][0]);
|
||||
glVertex3fv (pts[1][0]);
|
||||
|
||||
glVertex3fv (pts[0][1]);
|
||||
glVertex3fv (pts[1][1]);
|
||||
|
||||
glVertex3fv (pts[0][2]);
|
||||
glVertex3fv (pts[1][2]);
|
||||
|
||||
glEnd ();
|
||||
#endif
|
||||
|
||||
glBegin (GL_QUADS);
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
j = (i+1)%3;
|
||||
glVertex3fv (pts[0][j]);
|
||||
glVertex3fv (pts[1][j]);
|
||||
glVertex3fv (pts[1][i]);
|
||||
glVertex3fv (pts[0][i]);
|
||||
}
|
||||
glEnd ();
|
||||
|
||||
glBegin (GL_TRIANGLES);
|
||||
glVertex3fv (pts[1][0]);
|
||||
glVertex3fv (pts[1][1]);
|
||||
glVertex3fv (pts[1][2]);
|
||||
glEnd ();
|
||||
|
||||
p->length -= host_frametime*2;
|
||||
}
|
||||
|
||||
|
||||
void Test_Draw (void)
|
||||
{
|
||||
int i;
|
||||
puff_t *p;
|
||||
|
||||
for (i=0, p=puffs ; i<MAX_PUFFS ; i++,p++)
|
||||
{
|
||||
if (p->length > 0)
|
||||
DrawPuff (p);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
252
source/ctr/gl/gl_vidctr.c
Normal file
252
source/ctr/gl/gl_vidctr.c
Normal file
|
@ -0,0 +1,252 @@
|
|||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public 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 <3ds.h>
|
||||
#include <GL/picaGL.h>
|
||||
#include "../../quakedef.h"
|
||||
|
||||
unsigned d_8to24table[256];
|
||||
unsigned char d_15to8table[65536];
|
||||
|
||||
int texture_mode = GL_LINEAR;
|
||||
|
||||
int texture_extension_number = 1;
|
||||
|
||||
float gldepthmin, gldepthmax;
|
||||
|
||||
cvar_t gl_ztrick = {"gl_ztrick","0"};
|
||||
|
||||
const char *gl_vendor;
|
||||
const char *gl_renderer;
|
||||
const char *gl_version;
|
||||
const char *gl_extensions;
|
||||
|
||||
static float vid_gamma = 1.0;
|
||||
|
||||
qboolean is8bit = false;
|
||||
qboolean isPermedia = true;
|
||||
qboolean gl_mtexable = false;
|
||||
|
||||
/*
|
||||
===============
|
||||
GL_Init
|
||||
===============
|
||||
*/
|
||||
void GL_Init (void)
|
||||
{
|
||||
pglInitEx(0x040000, 0x100000);
|
||||
|
||||
gl_vendor = glGetString (GL_VENDOR);
|
||||
gl_renderer = glGetString (GL_RENDERER);
|
||||
gl_version = glGetString (GL_VERSION);
|
||||
gl_extensions = glGetString (GL_EXTENSIONS);
|
||||
|
||||
glClearDepth (1.0f);
|
||||
glClearColor ((float)(16/255),(float)(32/255),(float)(64/255),1);
|
||||
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);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
|
||||
void GL_BeginRendering (int *x, int *y, int *width, int *height)
|
||||
{
|
||||
*x = *y = 0;
|
||||
*width = 400;
|
||||
*height = 240;
|
||||
}
|
||||
|
||||
|
||||
void GL_EndRendering (void)
|
||||
{
|
||||
// naievil -- this requies the new version of picagl to be used properly
|
||||
//glFinish();
|
||||
pglSwapBuffersEx(1,0);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
// 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 VID_ShiftPalette (unsigned char *palette)
|
||||
{
|
||||
//VID_SetPalette(palette);
|
||||
}
|
||||
|
||||
qboolean VID_Is8bit(void)
|
||||
{
|
||||
return is8bit;
|
||||
}
|
||||
|
||||
static void Check_Gamma (unsigned char *pal)
|
||||
{
|
||||
float f, inf;
|
||||
unsigned char palette[768];
|
||||
int i;
|
||||
|
||||
if ((i = COM_CheckParm("-gamma")) == 0)
|
||||
vid_gamma = 0.7;
|
||||
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));
|
||||
|
||||
BuildGammaTable (vid_gamma); //Diabolickal HLBSP
|
||||
}
|
||||
|
||||
void VID_Init (unsigned char *palette)
|
||||
{
|
||||
int i;
|
||||
char gldir[MAX_OSPATH];
|
||||
int width = 400;
|
||||
int height = 240;
|
||||
|
||||
Cvar_RegisterVariable (&gl_ztrick);
|
||||
|
||||
vid.maxwarpwidth = width;
|
||||
vid.maxwarpheight = height;
|
||||
vid.colormap = host_colormap;
|
||||
vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
|
||||
|
||||
vid.conwidth = 320;
|
||||
|
||||
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 (vid.conheight > height)
|
||||
vid.conheight = height;
|
||||
if (vid.conwidth > width)
|
||||
vid.conwidth = width;
|
||||
|
||||
vid.width = 400;
|
||||
vid.height = 240;
|
||||
|
||||
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);
|
||||
|
||||
Con_SafePrintf ("Video mode %dx%d initialized.\n", width, height);
|
||||
|
||||
vid.recalc_refdef = 1; // force a surface cache flush
|
||||
}
|
||||
|
||||
void VID_Shutdown (void)
|
||||
{
|
||||
}
|
||||
|
||||
void VID_Update (vrect_t *rects)
|
||||
{
|
||||
}
|
785
source/ctr/gl/gl_warp.c
Normal file
785
source/ctr/gl/gl_warp.c
Normal file
|
@ -0,0 +1,785 @@
|
|||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public 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
|
||||
|
||||
int skytexorder[5] = {0,2,1,3,4};
|
||||
int skyimage[5]; // Where sky images are stored
|
||||
char skybox_name[32] = ""; //name of current skybox, or "" if no skybox
|
||||
// cut off down for half skybox
|
||||
char *suf[5] = {"rt", "bk", "lf", "ft", "up" };
|
||||
|
||||
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
|
||||
|
||||
=================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
==================
|
||||
Sky_LoadSkyBox
|
||||
==================
|
||||
*/
|
||||
//char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
|
||||
void Sky_LoadSkyBox(char* name)
|
||||
{
|
||||
if (strcmp(skybox_name, name) == 0)
|
||||
return; //no change
|
||||
|
||||
//turn off skybox if sky is set to ""
|
||||
if (name[0] == '0') {
|
||||
skybox_name[0] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Do sides one way and top another, bottom is not done
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int mark = Hunk_LowMark ();
|
||||
|
||||
if(!(skyimage[i] = loadtextureimage (va("gfx/env/%s%s", name, suf[i]), 0, 0, false, false)) &&
|
||||
!(skyimage[i] = loadtextureimage (va("gfx/env/%s_%s", name, suf[i]), 0, 0, false, false)))
|
||||
{
|
||||
Con_Printf("Sky: %s[%s] not found, used std\n", name, suf[i]);
|
||||
if(!(skyimage[i] = loadtextureimage (va("gfx/env/skybox%s", suf[i]), 0, 0, false, false)))
|
||||
{
|
||||
Sys_Error("STD SKY NOT FOUND!");
|
||||
}
|
||||
|
||||
}
|
||||
Hunk_FreeToLowMark (mark);
|
||||
}
|
||||
|
||||
int mark = Hunk_LowMark ();
|
||||
if(!(skyimage[4] = loadtextureimage (va("gfx/env/%sup", name), 0, 0, false, false)) &&
|
||||
!(skyimage[4] = loadtextureimage (va("gfx/env/%s_up", name), 0, 0, false, false)))
|
||||
{
|
||||
Con_Printf("Sky: %s[%s] not found, used std\n", name, suf[4]);
|
||||
if(!(skyimage[4] = loadtextureimage (va("gfx/env/skybox%s", suf[4]), 0, 0, false, false)))
|
||||
{
|
||||
Sys_Error("STD SKY NOT FOUND!");
|
||||
}
|
||||
|
||||
}
|
||||
Hunk_FreeToLowMark (mark);
|
||||
|
||||
strcpy(skybox_name, name);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sky_NewMap
|
||||
=================
|
||||
*/
|
||||
void Sky_NewMap (void)
|
||||
{
|
||||
char key[128], value[4096];
|
||||
char *data;
|
||||
|
||||
//purge old sky textures
|
||||
//UnloadSkyTexture ();
|
||||
|
||||
//
|
||||
// initially no sky
|
||||
//
|
||||
Sky_LoadSkyBox (""); //not used
|
||||
|
||||
//
|
||||
// read worldspawn (this is so ugly, and shouldn't it be done on the server?)
|
||||
//
|
||||
data = cl.worldmodel->entities;
|
||||
if (!data)
|
||||
return; //FIXME: how could this possibly ever happen? -- if there's no
|
||||
// worldspawn then the sever wouldn't send the loadmap message to the client
|
||||
|
||||
data = COM_Parse(data);
|
||||
|
||||
if (!data) //should never happen
|
||||
return; // error
|
||||
|
||||
if (com_token[0] != '{') //should never happen
|
||||
return; // error
|
||||
|
||||
while (1)
|
||||
{
|
||||
data = COM_Parse(data);
|
||||
|
||||
if (!data)
|
||||
return; // error
|
||||
|
||||
if (com_token[0] == '}')
|
||||
break; // end of worldspawn
|
||||
|
||||
if (com_token[0] == '_')
|
||||
strcpy(key, com_token + 1);
|
||||
else
|
||||
strcpy(key, com_token);
|
||||
while (key[strlen(key)-1] == ' ') // remove trailing spaces
|
||||
key[strlen(key)-1] = 0;
|
||||
|
||||
data = COM_Parse(data);
|
||||
if (!data)
|
||||
return; // error
|
||||
|
||||
strcpy(value, com_token);
|
||||
|
||||
if (!strcmp("sky", key))
|
||||
Sky_LoadSkyBox(value);
|
||||
else if (!strcmp("skyname", key)) //half-life
|
||||
Sky_LoadSkyBox(value);
|
||||
else if (!strcmp("qlsky", key)) //quake lives
|
||||
Sky_LoadSkyBox(value);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sky_SkyCommand_f
|
||||
=================
|
||||
*/
|
||||
void Sky_SkyCommand_f (void)
|
||||
{
|
||||
switch (Cmd_Argc())
|
||||
{
|
||||
case 1:
|
||||
Con_Printf("\"sky\" is \"%s\"\n", skybox_name);
|
||||
break;
|
||||
case 2:
|
||||
Sky_LoadSkyBox(Cmd_Argv(1));
|
||||
break;
|
||||
default:
|
||||
Con_Printf("usage: sky <skyname>\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Sky_Init
|
||||
=============
|
||||
*/
|
||||
void Sky_Init (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
Cmd_AddCommand ("sky",Sky_SkyCommand_f);
|
||||
|
||||
for (i=0; i<5; i++)
|
||||
skyimage[i] = NULL;
|
||||
}
|
||||
|
||||
static 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
|
||||
static 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]
|
||||
static 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}
|
||||
};
|
||||
|
||||
static float skymins[2][6], skymaxs[2][6];
|
||||
|
||||
/*
|
||||
==============
|
||||
R_ClearSkyBox
|
||||
==============
|
||||
*/
|
||||
void R_ClearSkyBox (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0 ; i<5 ; 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
|
||||
==============
|
||||
*/
|
||||
|
||||
float skynormals[5][3] = {
|
||||
{ 1.f, 0.f, 0.f },
|
||||
{ -1.f, 0.f, 0.f },
|
||||
{ 0.f, 1.f, 0.f },
|
||||
{ 0.f, -1.f, 0.f },
|
||||
{ 0.f, 0.f, 1.f }
|
||||
};
|
||||
|
||||
float skyrt[5][3] = {
|
||||
{ 0.f, -1.f, 0.f },
|
||||
{ 0.f, 1.f, 0.f },
|
||||
{ 1.f, 0.f, 0.f },
|
||||
{ -1.f, 0.f, 0.f },
|
||||
{ 0.f, -1.f, 0.f }
|
||||
};
|
||||
|
||||
float skyup[5][3] = {
|
||||
{ 0.f, 0.f, 1.f },
|
||||
{ 0.f, 0.f, 1.f },
|
||||
{ 0.f, 0.f, 1.f },
|
||||
{ 0.f, 0.f, 1.f },
|
||||
{ -1.f, 0.f, 0.f }
|
||||
};
|
||||
|
||||
void R_DrawSkyBox (void)
|
||||
{
|
||||
int i, j, k;
|
||||
vec3_t v;
|
||||
float s, t;
|
||||
|
||||
//Fog_DisableGFog();
|
||||
//Fog_SetColorForSkyS();
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
glDepthMask(GL_FALSE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
float skydepth = 1000.0f;
|
||||
|
||||
for (i=0 ; i<5 ; i++)
|
||||
{
|
||||
const int vertex_count = 4;
|
||||
glvert_t sky_vertices[vertex_count];
|
||||
|
||||
// check if poly needs to be drawn at all
|
||||
float dot = DotProduct(skynormals[i], vpn);
|
||||
// < 0 check would work at fov 90 or less, just guess a value that's high enough?
|
||||
if (dot < -0.25f) continue;
|
||||
|
||||
GL_Bind(skyimage[skytexorder[i]]);
|
||||
|
||||
// if direction is not up, cut "down" vector to zero to only render half cube
|
||||
//float upnegfact = i == 4 ? 1.0f : 0.0f;
|
||||
float upnegfact = 1.0f;
|
||||
|
||||
float skyboxtexsize = 256.f;
|
||||
// move ever so slightly less towards forward to make edges overlap a bit, just to not have shimmering pixels between sky edges
|
||||
float forwardfact = 0.99f;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
sky_vertices[0].s = 0.5f / skyboxtexsize;
|
||||
sky_vertices[0].t = (skyboxtexsize - .5f) / skyboxtexsize;
|
||||
sky_vertices[0].x = r_origin[0] + (forwardfact * skynormals[i][0] - skyrt[i][0] - skyup[i][0] * upnegfact) * skydepth;
|
||||
sky_vertices[0].y = r_origin[1] + (forwardfact * skynormals[i][1] - skyrt[i][1] - skyup[i][1] * upnegfact) * skydepth;
|
||||
sky_vertices[0].z = r_origin[2] + (forwardfact * skynormals[i][2] - skyrt[i][2] - skyup[i][2] * upnegfact) * skydepth;
|
||||
v[0] = sky_vertices[0].x;
|
||||
v[1] = sky_vertices[0].y;
|
||||
v[2] = sky_vertices[0].z;
|
||||
glTexCoord2f (sky_vertices[0].s, sky_vertices[0].t);
|
||||
glVertex3fv (v);
|
||||
|
||||
sky_vertices[1].s = 0.5f / skyboxtexsize;
|
||||
sky_vertices[1].t = 0.5f / skyboxtexsize;
|
||||
sky_vertices[1].x = r_origin[0] + (forwardfact * skynormals[i][0] - skyrt[i][0] + skyup[i][0]) * skydepth;
|
||||
sky_vertices[1].y = r_origin[1] + (forwardfact * skynormals[i][1] - skyrt[i][1] + skyup[i][1]) * skydepth;
|
||||
sky_vertices[1].z = r_origin[2] + (forwardfact * skynormals[i][2] - skyrt[i][2] + skyup[i][2]) * skydepth;
|
||||
v[0] = sky_vertices[1].x;
|
||||
v[1] = sky_vertices[1].y;
|
||||
v[2] = sky_vertices[1].z;
|
||||
glTexCoord2f (sky_vertices[1].s, sky_vertices[1].t);
|
||||
glVertex3fv (v);
|
||||
|
||||
sky_vertices[2].s = (skyboxtexsize - .5f) / skyboxtexsize;
|
||||
sky_vertices[2].t = 0.5f / skyboxtexsize;
|
||||
sky_vertices[2].x = r_origin[0] + (forwardfact * skynormals[i][0] + skyrt[i][0] + skyup[i][0]) * skydepth;
|
||||
sky_vertices[2].y = r_origin[1] + (forwardfact * skynormals[i][1] + skyrt[i][1] + skyup[i][1]) * skydepth;
|
||||
sky_vertices[2].z = r_origin[2] + (forwardfact * skynormals[i][2] + skyrt[i][2] + skyup[i][2]) * skydepth;
|
||||
v[0] = sky_vertices[2].x;
|
||||
v[1] = sky_vertices[2].y;
|
||||
v[2] = sky_vertices[2].z;
|
||||
glTexCoord2f (sky_vertices[2].s, sky_vertices[2].t);
|
||||
glVertex3fv (v);
|
||||
|
||||
sky_vertices[3].s = (skyboxtexsize - .5f) / skyboxtexsize;
|
||||
sky_vertices[3].t = (skyboxtexsize - .5f) / skyboxtexsize;
|
||||
sky_vertices[3].x = r_origin[0] + (forwardfact * skynormals[i][0] + skyrt[i][0] - skyup[i][0] * upnegfact) * skydepth;
|
||||
sky_vertices[3].y = r_origin[1] + (forwardfact * skynormals[i][1] + skyrt[i][1] - skyup[i][1] * upnegfact) * skydepth;
|
||||
sky_vertices[3].z = r_origin[2] + (forwardfact * skynormals[i][2] + skyrt[i][2] - skyup[i][2] * upnegfact) * skydepth;
|
||||
v[0] = sky_vertices[3].x;
|
||||
v[1] = sky_vertices[3].y;
|
||||
v[2] = sky_vertices[3].z;
|
||||
glTexCoord2f (sky_vertices[3].s, sky_vertices[3].t);
|
||||
glVertex3fv (v);
|
||||
|
||||
glEnd();
|
||||
}
|
||||
|
||||
glDepthMask(GL_TRUE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
//Fog_SetColorForSkyE(); //setup for Sky
|
||||
//Fog_EnableGFog(); //setup for Sky
|
||||
}
|
||||
|
||||
//===============================================================
|
||||
|
||||
/*
|
||||
=============
|
||||
R_InitSky
|
||||
|
||||
A sky texture is 256*128, with the right side being a masked overlay
|
||||
==============
|
||||
*/
|
||||
void R_InitSky (miptex_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);
|
||||
}
|
||||
|
51
source/ctr/gl/gl_warp_sin.h
Normal file
51
source/ctr/gl/gl_warp_sin.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
0, 0.19633, 0.392541, 0.588517, 0.784137, 0.979285, 1.17384, 1.3677,
|
||||
1.56072, 1.75281, 1.94384, 2.1337, 2.32228, 2.50945, 2.69512, 2.87916,
|
||||
3.06147, 3.24193, 3.42044, 3.59689, 3.77117, 3.94319, 4.11282, 4.27998,
|
||||
4.44456, 4.60647, 4.76559, 4.92185, 5.07515, 5.22538, 5.37247, 5.51632,
|
||||
5.65685, 5.79398, 5.92761, 6.05767, 6.18408, 6.30677, 6.42566, 6.54068,
|
||||
6.65176, 6.75883, 6.86183, 6.9607, 7.05537, 7.14579, 7.23191, 7.31368,
|
||||
7.39104, 7.46394, 7.53235, 7.59623, 7.65552, 7.71021, 7.76025, 7.80562,
|
||||
7.84628, 7.88222, 7.91341, 7.93984, 7.96148, 7.97832, 7.99036, 7.99759,
|
||||
8, 7.99759, 7.99036, 7.97832, 7.96148, 7.93984, 7.91341, 7.88222,
|
||||
7.84628, 7.80562, 7.76025, 7.71021, 7.65552, 7.59623, 7.53235, 7.46394,
|
||||
7.39104, 7.31368, 7.23191, 7.14579, 7.05537, 6.9607, 6.86183, 6.75883,
|
||||
6.65176, 6.54068, 6.42566, 6.30677, 6.18408, 6.05767, 5.92761, 5.79398,
|
||||
5.65685, 5.51632, 5.37247, 5.22538, 5.07515, 4.92185, 4.76559, 4.60647,
|
||||
4.44456, 4.27998, 4.11282, 3.94319, 3.77117, 3.59689, 3.42044, 3.24193,
|
||||
3.06147, 2.87916, 2.69512, 2.50945, 2.32228, 2.1337, 1.94384, 1.75281,
|
||||
1.56072, 1.3677, 1.17384, 0.979285, 0.784137, 0.588517, 0.392541, 0.19633,
|
||||
9.79717e-16, -0.19633, -0.392541, -0.588517, -0.784137, -0.979285, -1.17384, -1.3677,
|
||||
-1.56072, -1.75281, -1.94384, -2.1337, -2.32228, -2.50945, -2.69512, -2.87916,
|
||||
-3.06147, -3.24193, -3.42044, -3.59689, -3.77117, -3.94319, -4.11282, -4.27998,
|
||||
-4.44456, -4.60647, -4.76559, -4.92185, -5.07515, -5.22538, -5.37247, -5.51632,
|
||||
-5.65685, -5.79398, -5.92761, -6.05767, -6.18408, -6.30677, -6.42566, -6.54068,
|
||||
-6.65176, -6.75883, -6.86183, -6.9607, -7.05537, -7.14579, -7.23191, -7.31368,
|
||||
-7.39104, -7.46394, -7.53235, -7.59623, -7.65552, -7.71021, -7.76025, -7.80562,
|
||||
-7.84628, -7.88222, -7.91341, -7.93984, -7.96148, -7.97832, -7.99036, -7.99759,
|
||||
-8, -7.99759, -7.99036, -7.97832, -7.96148, -7.93984, -7.91341, -7.88222,
|
||||
-7.84628, -7.80562, -7.76025, -7.71021, -7.65552, -7.59623, -7.53235, -7.46394,
|
||||
-7.39104, -7.31368, -7.23191, -7.14579, -7.05537, -6.9607, -6.86183, -6.75883,
|
||||
-6.65176, -6.54068, -6.42566, -6.30677, -6.18408, -6.05767, -5.92761, -5.79398,
|
||||
-5.65685, -5.51632, -5.37247, -5.22538, -5.07515, -4.92185, -4.76559, -4.60647,
|
||||
-4.44456, -4.27998, -4.11282, -3.94319, -3.77117, -3.59689, -3.42044, -3.24193,
|
||||
-3.06147, -2.87916, -2.69512, -2.50945, -2.32228, -2.1337, -1.94384, -1.75281,
|
||||
-1.56072, -1.3677, -1.17384, -0.979285, -0.784137, -0.588517, -0.392541, -0.19633,
|
368
source/ctr/glquake.h
Normal file
368
source/ctr/glquake.h
Normal file
|
@ -0,0 +1,368 @@
|
|||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public 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 _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 bytesperpixel);
|
||||
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
|
||||
|
||||
|
||||
/*
|
||||
---------------------------------
|
||||
half-life Render Modes. Crow_bar
|
||||
---------------------------------
|
||||
*/
|
||||
|
||||
#define TEX_COLOR 1
|
||||
#define TEX_TEXTURE 2
|
||||
#define TEX_GLOW 3
|
||||
#define TEX_SOLID 4
|
||||
#define TEX_ADDITIVE 5
|
||||
#define TEX_LMPOINT 6 //for light point
|
||||
|
||||
#define ISCOLOR(ent) ((ent)->rendermode == TEX_COLOR && ((ent)->rendercolor[0] <= 1|| \
|
||||
(ent)->rendercolor[1] <= 1|| \
|
||||
(ent)->rendercolor[2] <= 1))
|
||||
|
||||
#define ISTEXTURE(ent) ((ent)->rendermode == TEX_TEXTURE && (ent)->renderamt > 0 && (ent)->renderamt <= 1)
|
||||
#define ISGLOW(ent) ((ent)->rendermode == TEX_GLOW && (ent)->renderamt > 0 && (ent)->renderamt <= 1)
|
||||
#define ISSOLID(ent) ((ent)->rendermode == TEX_SOLID && (ent)->renderamt > 0 && (ent)->renderamt <= 1)
|
||||
#define ISADDITIVE(ent) ((ent)->rendermode == TEX_ADDITIVE && (ent)->renderamt > 0 && (ent)->renderamt <= 1)
|
||||
|
||||
#define ISLMPOINT(ent) ((ent)->rendermode == TEX_LMPOINT && ((ent)->rendercolor[0] <= 1|| \
|
||||
(ent)->rendercolor[1] <= 1|| \
|
||||
(ent)->rendercolor[2] <= 1))
|
||||
/*
|
||||
---------------------------------
|
||||
//half-life Render Modes
|
||||
---------------------------------
|
||||
*/
|
||||
|
||||
|
||||
// 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 enum
|
||||
{
|
||||
pm_classic, pm_qmb, pm_quake3, pm_mixed
|
||||
} part_mode_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;
|
||||
|
||||
typedef byte col_t[4];
|
||||
|
||||
typedef struct particle_s
|
||||
{
|
||||
struct particle_s *next;
|
||||
vec3_t org, endorg;
|
||||
col_t color;
|
||||
float growth;
|
||||
vec3_t vel;
|
||||
float ramp;
|
||||
ptype_t type;
|
||||
float rotangle;
|
||||
float rotspeed;
|
||||
float size;
|
||||
float start;
|
||||
float die;
|
||||
byte hit;
|
||||
byte texindex;
|
||||
byte bounces;
|
||||
} 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 r_farclip;
|
||||
extern cvar_t r_skyfog;
|
||||
|
||||
extern cvar_t r_laserpoint;
|
||||
extern cvar_t r_particle_count;
|
||||
extern cvar_t r_part_explosions;
|
||||
extern cvar_t r_part_trails;
|
||||
extern cvar_t r_part_sparks;
|
||||
extern cvar_t r_part_spikes;
|
||||
extern cvar_t r_part_gunshots;
|
||||
extern cvar_t r_part_blood;
|
||||
extern cvar_t r_part_telesplash;
|
||||
extern cvar_t r_part_blobs;
|
||||
extern cvar_t r_part_lavasplash;
|
||||
extern cvar_t r_part_flames;
|
||||
extern cvar_t r_part_lightning;
|
||||
extern cvar_t r_part_flies;
|
||||
extern cvar_t r_bounceparticles;
|
||||
extern cvar_t r_explosiontype;
|
||||
extern cvar_t r_part_muzzleflash;
|
||||
extern cvar_t r_flametype;
|
||||
extern cvar_t r_bounceparticles;
|
||||
extern cvar_t r_decal_blood;
|
||||
extern cvar_t r_decal_bullets;
|
||||
extern cvar_t r_decal_sparks;
|
||||
extern cvar_t r_decal_explosions;
|
||||
extern cvar_t r_coronas;
|
||||
extern cvar_t r_model_brightness;
|
||||
|
||||
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);
|
||||
|
||||
//johnfitz -- fog functions called from outside gl_fog.c
|
||||
void Fog_ParseServerMessage (void);
|
||||
float *Fog_GetColor (void);
|
||||
float Fog_GetDensity (void);
|
||||
void Fog_EnableGFog (void);
|
||||
void Fog_DisableGFog (void);
|
||||
void Fog_StartAdditive (void);
|
||||
void Fog_StopAdditive (void);
|
||||
void Fog_SetupFrame (void);
|
||||
void Fog_NewMap (void);
|
||||
void Fog_Init (void);
|
||||
void Fog_SetupState (void);
|
||||
|
||||
void Sky_Init (void);
|
||||
void Sky_NewMap (void);
|
||||
|
||||
qboolean VID_Is8bit(void);
|
||||
|
||||
|
||||
// naievil -- fixme: none of these work
|
||||
//-----------------------------------------------------
|
||||
void QMB_InitParticles (void);
|
||||
void QMB_ClearParticles (void);
|
||||
void QMB_DrawParticles (void);
|
||||
void QMB_Q3TorchFlame (vec3_t org, float size);
|
||||
void QMB_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count);
|
||||
void QMB_RocketTrail (vec3_t start, vec3_t end, trail_type_t type);
|
||||
void QMB_BlobExplosion (vec3_t org);
|
||||
void QMB_ParticleExplosion (vec3_t org);
|
||||
void QMB_LavaSplash (vec3_t org);
|
||||
void QMB_TeleportSplash (vec3_t org);
|
||||
void QMB_InfernoFlame (vec3_t org);
|
||||
void QMB_StaticBubble (entity_t *ent);
|
||||
void QMB_ColorMappedExplosion (vec3_t org, int colorStart, int colorLength);
|
||||
void QMB_TorchFlame (vec3_t org);
|
||||
void QMB_FlameGt (vec3_t org, float size, float time);
|
||||
void QMB_BigTorchFlame (vec3_t org);
|
||||
void QMB_ShamblerCharge (vec3_t org);
|
||||
void QMB_LightningBeam (vec3_t start, vec3_t end);
|
||||
//void QMB_GenSparks (vec3_t org, byte col[3], float count, float size, float life);
|
||||
void QMB_EntityParticles (entity_t *ent);
|
||||
void QMB_MuzzleFlash (vec3_t org);
|
||||
void QMB_RayFlash (vec3_t org, float weapon);
|
||||
void QMB_MuzzleFlashLG (vec3_t org);
|
||||
void QMB_Q3Gunshot (vec3_t org, int skinnum, float alpha);
|
||||
void QMB_Q3Teleport (vec3_t org, float alpha);
|
||||
void QMB_Q3TorchFlame (vec3_t org, float size);
|
||||
|
||||
extern qboolean qmb_initialized;
|
240
source/ctr/in_ctr.c
Normal file
240
source/ctr/in_ctr.c
Normal file
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public 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_ctr.c -- for the Nintendo 3DS
|
||||
|
||||
#include "../quakedef.h"
|
||||
#include <GL/picaGL.h>
|
||||
#include <3ds.h>
|
||||
|
||||
extern int bind_grab;
|
||||
|
||||
extern bool new3ds_flag;
|
||||
extern bool croshhairmoving;
|
||||
extern float crosshair_opacity;
|
||||
|
||||
extern cvar_t in_analog_strafe;
|
||||
extern cvar_t in_x_axis_adjust;
|
||||
extern cvar_t in_y_axis_adjust;
|
||||
extern cvar_t in_mlook; //Heffo - mlook cvar
|
||||
|
||||
cvar_t in_anub_mode = {"in_anub_mode", "0", true};
|
||||
|
||||
void IN_Init (void)
|
||||
{
|
||||
Cvar_RegisterVariable (&in_analog_strafe);
|
||||
Cvar_RegisterVariable (&in_anub_mode);
|
||||
|
||||
if (new3ds_flag) {
|
||||
Cvar_SetValue("in_anub_mode", 1);
|
||||
}
|
||||
}
|
||||
|
||||
void IN_Shutdown (void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void IN_Commands (void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
float IN_CalcInput(int axis, float speed, float tolerance, float acceleration) {
|
||||
|
||||
float value = ((float) axis / 154.0f);
|
||||
|
||||
if (value == 0.0f) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float abs_value = fabs(value);
|
||||
|
||||
if (abs_value < tolerance) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
abs_value -= tolerance;
|
||||
abs_value /= (1.0f - tolerance);
|
||||
abs_value = powf(abs_value, acceleration);
|
||||
abs_value *= speed;
|
||||
|
||||
if (value < 0.0f) {
|
||||
value = -abs_value;
|
||||
} else {
|
||||
value = abs_value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
extern cvar_t scr_fov;
|
||||
extern int original_fov, final_fov;
|
||||
touchPosition old_touch, cur_touch;
|
||||
void IN_Move (usercmd_t *cmd)
|
||||
{
|
||||
// Touch based viewangles based on Quake2CTR
|
||||
// This was originally based on ctrQuake, however
|
||||
// that implementation was less elegant and had
|
||||
// a weird jerk bug when tapping the screen.
|
||||
if(hidKeysDown() & KEY_TOUCH)
|
||||
hidTouchRead(&old_touch);
|
||||
|
||||
if((hidKeysHeld() & KEY_TOUCH))
|
||||
{
|
||||
hidTouchRead(&cur_touch);
|
||||
|
||||
if(cur_touch.px < 268)
|
||||
{
|
||||
int tx = cur_touch.px - old_touch.px;
|
||||
int ty = cur_touch.py - old_touch.py;
|
||||
|
||||
if(m_pitch.value < 0)
|
||||
ty = -ty;
|
||||
|
||||
cl.viewangles[YAW] -= abs(tx) > 1 ? tx * sensitivity.value * 0.33f : 0;
|
||||
cl.viewangles[PITCH] += abs(ty) > 1 ? ty * sensitivity.value * 0.33f : 0;
|
||||
}
|
||||
|
||||
old_touch = cur_touch;
|
||||
}
|
||||
|
||||
// TODO: Detect circle pad pro?
|
||||
circlePosition left;
|
||||
circlePosition right;
|
||||
|
||||
V_StopPitchDrift();
|
||||
|
||||
// Read the pad states
|
||||
hidCircleRead(&left);
|
||||
hidCstickRead(&right);
|
||||
|
||||
// Convert the inputs to floats in the range [-1, 1].
|
||||
// Implement the dead zone.
|
||||
float speed;
|
||||
float deadZone = in_tolerance.value;
|
||||
float acceleration = in_acceleration.value;
|
||||
float look_x, look_y;
|
||||
|
||||
//
|
||||
// Analog look tweaks
|
||||
//
|
||||
speed = sensitivity.value;
|
||||
|
||||
if (!in_anub_mode.value)
|
||||
speed -= 2;
|
||||
else
|
||||
speed += 8;
|
||||
|
||||
// cut look speed in half when facing enemy, unless mag is empty
|
||||
if ((in_aimassist.value) && (sv_player->v.facingenemy == 1) && cl.stats[STAT_CURRENTMAG] > 0) {
|
||||
speed *= 0.5;
|
||||
}
|
||||
// additionally, slice look speed when ADS/scopes
|
||||
if (cl.stats[STAT_ZOOM] == 1)
|
||||
speed *= 0.5;
|
||||
else if (cl.stats[STAT_ZOOM] == 2)
|
||||
speed *= 0.25;
|
||||
|
||||
// Are we using the left or right stick for looking?
|
||||
if (!in_anub_mode.value) { // Left
|
||||
look_x = IN_CalcInput(left.dx, speed, deadZone, acceleration);
|
||||
look_y = IN_CalcInput(left.dy, speed, deadZone, acceleration);
|
||||
} else { // Right
|
||||
look_x = IN_CalcInput(right.dx, speed, deadZone, acceleration);
|
||||
look_y = IN_CalcInput(right.dy, speed, deadZone, acceleration);
|
||||
}
|
||||
|
||||
const float yawScale = 30.0f;
|
||||
cl.viewangles[YAW] -= yawScale * look_x * host_frametime;
|
||||
|
||||
// Set the pitch.
|
||||
const bool invertPitch = m_pitch.value < 0;
|
||||
const float pitchScale = yawScale * (invertPitch ? 1 : -1);
|
||||
|
||||
cl.viewangles[PITCH] += pitchScale * look_y * host_frametime;
|
||||
|
||||
// Don't look too far up or down.
|
||||
if (cl.viewangles[PITCH] > 80.0f)
|
||||
cl.viewangles[PITCH] = 80.0f;
|
||||
if (cl.viewangles[PITCH] < -70.0f)
|
||||
cl.viewangles[PITCH] = -70.0f;
|
||||
|
||||
// Ability to move with the left nub on NEW model systems
|
||||
float move_x, move_y;
|
||||
float input_x, input_y;
|
||||
|
||||
if (in_anub_mode.value) {
|
||||
input_x = left.dx;
|
||||
input_y = left.dy;
|
||||
} else {
|
||||
input_x = right.dx;
|
||||
input_y = right.dy;
|
||||
}
|
||||
|
||||
cl_backspeed = cl_forwardspeed = cl_sidespeed = sv_player->v.maxspeed;
|
||||
cl_sidespeed *= 0.8;
|
||||
cl_backspeed *= 0.7;
|
||||
|
||||
move_x = IN_CalcInput(input_x, cl_sidespeed, deadZone, acceleration);
|
||||
|
||||
if (input_y > 0)
|
||||
move_y = IN_CalcInput(input_y, cl_forwardspeed, deadZone, acceleration);
|
||||
else
|
||||
move_y = IN_CalcInput(input_y, cl_backspeed, deadZone, acceleration);
|
||||
|
||||
// cypress -- explicitly setting instead of adding so we always prioritize
|
||||
// analog movement over standard bindings if both are at play
|
||||
if (move_x != 0 || move_y != 0) {
|
||||
cmd->sidemove = move_x;
|
||||
cmd->forwardmove = move_y;
|
||||
}
|
||||
|
||||
// crosshair stuff
|
||||
if (input_x < 50 && input_x > -50 && input_y < 50 && input_y > -50) {
|
||||
croshhairmoving = false;
|
||||
|
||||
crosshair_opacity += 22;
|
||||
|
||||
if (crosshair_opacity >= 255)
|
||||
crosshair_opacity = 255;
|
||||
} else {
|
||||
croshhairmoving = true;
|
||||
crosshair_opacity -= 8;
|
||||
if (crosshair_opacity <= 128)
|
||||
crosshair_opacity = 128;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ctr software keyboard courtesy of libctru samples
|
||||
//
|
||||
void IN_SwitchKeyboard(void)
|
||||
{
|
||||
static SwkbdState swkbd;
|
||||
static char console_buffer[64];
|
||||
SwkbdButton button = SWKBD_BUTTON_NONE;
|
||||
|
||||
swkbdInit(&swkbd, SWKBD_TYPE_QWERTY, 2, -1);
|
||||
swkbdSetInitialText(&swkbd, console_buffer);
|
||||
swkbdSetHintText(&swkbd, "Enter Quake console command");
|
||||
swkbdSetButton(&swkbd, SWKBD_BUTTON_RIGHT, "Send", true);
|
||||
button = swkbdInputText(&swkbd, console_buffer, sizeof(console_buffer));
|
||||
|
||||
Cbuf_AddText(va("%s\n", console_buffer));
|
||||
}
|
947
source/ctr/keys.c
Normal file
947
source/ctr/keys.c
Normal file
|
@ -0,0 +1,947 @@
|
|||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public 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];
|
||||
char *dtbindings[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[] =
|
||||
{
|
||||
#ifdef _3DS
|
||||
{"TAB", K_TAB},
|
||||
{"START", K_ESCAPE},
|
||||
{"SELECT", K_SELECT},
|
||||
{"SPACE", K_SPACE},
|
||||
{"BACKSPACE", K_BACKSPACE},
|
||||
{"PADUP", K_UPARROW},
|
||||
{"PADDOWN", K_DOWNARROW},
|
||||
{"PADLEFT", K_LEFTARROW},
|
||||
{"PADRIGHT", K_RIGHTARROW},
|
||||
#else
|
||||
{"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},
|
||||
#endif
|
||||
|
||||
{"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},
|
||||
|
||||
#ifdef _3DS
|
||||
{"ABUTTON", K_AUX1},
|
||||
{"BBUTTON", K_AUX2},
|
||||
{"XBUTTON", K_AUX3},
|
||||
{"YBUTTON", K_AUX4},
|
||||
{"LTRIGGER", K_AUX5},
|
||||
{"ZLTRIGGER", K_AUX6},
|
||||
{"RTRIGGER", K_AUX7},
|
||||
{"ZRTRIGGER", K_AUX8},
|
||||
{"T1", K_AUX9},
|
||||
{"T2", K_AUX10},
|
||||
{"T3", K_AUX11},
|
||||
{"T4", K_AUX12},
|
||||
{"T5", K_AUX13},
|
||||
{"T6", 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},
|
||||
#else
|
||||
{"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},
|
||||
#endif
|
||||
|
||||
{"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
|
||||
====================
|
||||
*/
|
||||
extern qboolean console_enabled;
|
||||
void Key_Console (int key)
|
||||
{
|
||||
char *cmd;
|
||||
|
||||
if (key == K_SELECT)
|
||||
{
|
||||
IN_SwitchKeyboard();
|
||||
return;
|
||||
}
|
||||
|
||||
if (key == K_JOY3 || 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
|
||||
// for clientside cmds
|
||||
if (cls.state == ca_connected){
|
||||
pr_global_struct->CMD_STRING = (key_lines[edit_line-1]+1 - pr_strings);
|
||||
PR_ExecuteProgram (pr_global_struct->ParseClientCommand);
|
||||
}
|
||||
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)
|
||||
{
|
||||
console_enabled = false;
|
||||
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)
|
||||
{
|
||||
console_enabled = false;
|
||||
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_SetDTBinding
|
||||
===================
|
||||
*/
|
||||
void Key_SetDTBinding (int keynum, char *binding)
|
||||
{
|
||||
char *new;
|
||||
int l;
|
||||
|
||||
if (keynum == -1)
|
||||
return;
|
||||
|
||||
// free old bindings
|
||||
if (dtbindings[keynum])
|
||||
{
|
||||
Z_Free (dtbindings[keynum]);
|
||||
dtbindings[keynum] = NULL;
|
||||
}
|
||||
|
||||
// allocate memory for new binding
|
||||
l = Q_strlen (binding);
|
||||
new = Z_Malloc (l+1);
|
||||
Q_strcpy (new, binding);
|
||||
new[l] = 0;
|
||||
dtbindings[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_Binddt_f
|
||||
===================
|
||||
*/
|
||||
void Key_Binddt_f (void)
|
||||
{
|
||||
int i, c, b;
|
||||
char cmd[1024];
|
||||
|
||||
c = Cmd_Argc();
|
||||
|
||||
if (c != 2 && c != 3)
|
||||
{
|
||||
Con_Printf ("binddt <key> [command] : attach a command to a double tap 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 (dtbindings[b])
|
||||
Con_Printf ("\"%s\" = \"%s\"\n", Cmd_Argv(1), dtbindings[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_SetDTBinding (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_WriteDTBindings
|
||||
|
||||
Writes lines containing "binddt key value"
|
||||
============
|
||||
*/
|
||||
void Key_WriteDTBindings (FILE *f)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0 ; i<256 ; i++)
|
||||
if (dtbindings[i])
|
||||
if (*dtbindings[i])
|
||||
fprintf (f, "binddt \"%s\" \"%s\"\n", Key_KeynumToString(i), dtbindings[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[K_SELECT] = 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 ("binddt",Key_Binddt_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!
|
||||
===================
|
||||
*/
|
||||
int lastkey;
|
||||
double lastkeytime;
|
||||
int oldkey;
|
||||
double oldkeytime;
|
||||
void Key_Event (int key, qboolean down)
|
||||
{
|
||||
char *kb;
|
||||
char cmd[1024];
|
||||
|
||||
oldkey = lastkey;
|
||||
keydown[key] = down;
|
||||
lastkey = key;
|
||||
|
||||
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)
|
||||
{
|
||||
oldkeytime = lastkeytime;
|
||||
lastkeytime = Sys_FloatTime();
|
||||
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:
|
||||
case key_menu_pause:
|
||||
M_Keydown (key);
|
||||
break;
|
||||
case key_game:
|
||||
case key_console:
|
||||
console_enabled = false;
|
||||
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 || key_dest == key_menu_pause) && menubound[key])
|
||||
|| (key_dest == key_console && !consolekeys[key])
|
||||
|| (key_dest == key_game && ( !con_forcedup || !consolekeys[key] ) ) )
|
||||
{
|
||||
if (oldkey == key && ((oldkeytime + 0.3) > lastkeytime))
|
||||
{
|
||||
kb = dtbindings[key];
|
||||
if (kb)
|
||||
{
|
||||
if (kb[0] == '+')
|
||||
{ // button commands add keynum as a parm
|
||||
sprintf (cmd, kb, key);
|
||||
Cbuf_AddText (cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
Cbuf_AddText (kb);
|
||||
Cbuf_AddText ("\n");
|
||||
}
|
||||
}
|
||||
oldkey = 0;
|
||||
oldkeytime = 0;
|
||||
lastkeytime = 0;
|
||||
lastkey = 0;
|
||||
}
|
||||
|
||||
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:
|
||||
case key_menu_pause:
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
137
source/ctr/keys.h
Normal file
137
source/ctr/keys.h
Normal file
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public 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
|
||||
|
||||
// naievil -- this is for using the select button for a game key, which is important
|
||||
#define K_SELECT 241
|
||||
|
||||
|
||||
|
||||
typedef enum {key_game, key_console, key_message, key_menu, key_menu_pause} keydest_t;
|
||||
|
||||
extern keydest_t key_dest;
|
||||
extern char *keybindings[256];
|
||||
extern char *dtbindings[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_WriteDTBindings (FILE *f);
|
||||
void Key_ClearStates (void);
|
2415
source/ctr/menu.c
Normal file
2415
source/ctr/menu.c
Normal file
File diff suppressed because it is too large
Load diff
38
source/ctr/menu.h
Normal file
38
source/ctr/menu.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
//
|
||||
// the net drivers should just set the apropriate bits in m_activenet,
|
||||
// instead of having the menu code look through their internal tables
|
||||
//
|
||||
#define MNET_IPX 1
|
||||
#define MNET_TCP 2
|
||||
|
||||
extern int m_activenet;
|
||||
|
||||
//
|
||||
// menus
|
||||
//
|
||||
void M_Init (void);
|
||||
void M_Keydown (int key);
|
||||
void M_Draw (void);
|
||||
void M_ToggleMenu_f (void);
|
||||
|
||||
|
377
source/ctr/model.h
Normal file
377
source/ctr/model.h
Normal file
|
@ -0,0 +1,377 @@
|
|||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public 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
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
vec3_t position;
|
||||
} mvertex_t;
|
||||
|
||||
#define SIDE_FRONT 0
|
||||
#define SIDE_BACK 1
|
||||
#define SIDE_ON 2
|
||||
|
||||
|
||||
// plane_t structure
|
||||
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
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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__
|
134
source/ctr/modelgen.h
Normal file
134
source/ctr/modelgen.h
Normal file
|
@ -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 {
|
||||
int type;
|
||||
} daliasframetype_t;
|
||||
|
||||
typedef struct {
|
||||
int type;
|
||||
} daliasskintype_t;
|
||||
|
||||
#define IDPOLYHEADER (('O'<<24)+('P'<<16)+('D'<<8)+'I')
|
||||
// little-endian "IDPO"
|
||||
|
337
source/ctr/net.h
Normal file
337
source/ctr/net.h
Normal file
|
@ -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 16384
|
||||
#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);
|
93
source/ctr/net_bsd.c
Normal file
93
source/ctr/net_bsd.c
Normal file
|
@ -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;
|
1373
source/ctr/net_dgrm.c
Normal file
1373
source/ctr/net_dgrm.c
Normal file
File diff suppressed because it is too large
Load diff
34
source/ctr/net_dgrm.h
Normal file
34
source/ctr/net_dgrm.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
// net_dgrm.h
|
||||
|
||||
|
||||
int Datagram_Init (void);
|
||||
void Datagram_Listen (qboolean state);
|
||||
void Datagram_SearchForHosts (qboolean xmit);
|
||||
qsocket_t *Datagram_Connect (char *host);
|
||||
qsocket_t *Datagram_CheckNewConnections (void);
|
||||
int Datagram_GetMessage (qsocket_t *sock);
|
||||
int Datagram_SendMessage (qsocket_t *sock, sizebuf_t *data);
|
||||
int Datagram_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data);
|
||||
qboolean Datagram_CanSendMessage (qsocket_t *sock);
|
||||
qboolean Datagram_CanSendUnreliableMessage (qsocket_t *sock);
|
||||
void Datagram_Close (qsocket_t *sock);
|
||||
void Datagram_Shutdown (void);
|
997
source/ctr/net_main.c
Normal file
997
source/ctr/net_main.c
Normal file
|
@ -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
|
39
source/ctr/net_udp.h
Normal file
39
source/ctr/net_udp.h
Normal file
|
@ -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);
|
445
source/ctr/net_udpctr.c
Normal file
445
source/ctr/net_udpctr.c
Normal file
|
@ -0,0 +1,445 @@
|
|||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public 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 "net_udp.h"
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <3ds.h>
|
||||
#include <sys/fcntl.h>
|
||||
|
||||
inline uint32_t htonl(uint32_t hostshort)
|
||||
{
|
||||
return __builtin_bswap32(hostshort);
|
||||
}
|
||||
|
||||
inline uint16_t htons(uint16_t hostshort)
|
||||
{
|
||||
return __builtin_bswap16(hostshort);
|
||||
}
|
||||
|
||||
inline uint32_t ntohl(uint32_t netlong)
|
||||
{
|
||||
return __builtin_bswap32(netlong);
|
||||
}
|
||||
|
||||
inline uint16_t ntohs(uint16_t netshort)
|
||||
{
|
||||
return __builtin_bswap16(netshort);
|
||||
}
|
||||
|
||||
#define SOC_BUFFERSIZE 0x100000
|
||||
#define SOC_ALIGN 0x1000
|
||||
|
||||
static u32 *SOC_buffer = NULL;
|
||||
|
||||
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[15];
|
||||
struct qsockaddr addr;
|
||||
char *colon;
|
||||
int ret;
|
||||
|
||||
if (COM_CheckParm ("-noudp"))
|
||||
return -1;
|
||||
|
||||
SOC_buffer = (u32*)memalign(SOC_ALIGN, SOC_BUFFERSIZE);
|
||||
|
||||
if(SOC_buffer == NULL)
|
||||
{
|
||||
Sys_Error("Failed to allocate SOC_Buffer\n");
|
||||
}
|
||||
ret = socInit(SOC_buffer, SOC_BUFFERSIZE);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
|
||||
free(SOC_buffer);
|
||||
return -1;
|
||||
}
|
||||
myAddr = gethostid();
|
||||
|
||||
// if the quake hostname isn't set, set it to the machine name
|
||||
if (strcmp(hostname.string, "UNNAMED") == 0)
|
||||
{
|
||||
Cvar_Set ("hostname", "3ds");
|
||||
}
|
||||
|
||||
if ((net_controlsocket = UDP_OpenSocket (5000)) == -1) //Passing 0 causes function to fail on 3DS
|
||||
{
|
||||
socExit();
|
||||
free(SOC_buffer);
|
||||
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(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);
|
||||
socExit();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
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;
|
||||
int yes = 1;
|
||||
int rc;
|
||||
|
||||
if ((newsocket = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
|
||||
return -1;
|
||||
|
||||
int flags = fcntl(newsocket, F_GETFL, 0);
|
||||
if ( fcntl(newsocket, F_SETFL, flags | O_NONBLOCK) == -1)
|
||||
goto ErrorReturn;
|
||||
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_addr.s_addr = htonl(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)
|
||||
{
|
||||
char buf[4096];
|
||||
|
||||
if (net_acceptsocket == -1)
|
||||
return -1;
|
||||
|
||||
if (recvfrom(net_acceptsocket, buf, 4096, MSG_PEEK, NULL, NULL) > 0)
|
||||
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 )
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
int UDP_MakeSocketBroadcastCapable (int socket)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
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 )
|
||||
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;
|
||||
}
|
||||
|
||||
//=============================================================================
|
314
source/ctr/r_local.h
Normal file
314
source/ctr/r_local.h
Normal file
|
@ -0,0 +1,314 @@
|
|||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public 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
|
||||
|
||||
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];
|
||||
|
||||
#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
|
851
source/ctr/r_part.c
Normal file
851
source/ctr/r_part.c
Normal file
|
@ -0,0 +1,851 @@
|
|||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public 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 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");
|
||||
|
||||
QMB_InitParticles();
|
||||
}
|
||||
|
||||
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[0] = p->color[1] = p->color[2] = 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
R_EntityParticles
|
||||
===============
|
||||
*/
|
||||
|
||||
#define NUMVERTEXNORMALS 162
|
||||
extern float r_avertexnormals[NUMVERTEXNORMALS][3];
|
||||
vec3_t avelocities[NUMVERTEXNORMALS];
|
||||
float beamlength = 16;
|
||||
vec3_t avelocity = {23, 7, 3};
|
||||
float partstep = 0.01;
|
||||
float timescale = 0.01;
|
||||
|
||||
void R_EntityParticles (entity_t *ent)
|
||||
{
|
||||
int count;
|
||||
int i;
|
||||
particle_t *p;
|
||||
float angle;
|
||||
float sr, sp, sy, cr, cp, cy;
|
||||
vec3_t forward;
|
||||
float dist;
|
||||
|
||||
dist = 64;
|
||||
count = 50;
|
||||
|
||||
if (!avelocities[0][0])
|
||||
{
|
||||
for (i=0 ; i<NUMVERTEXNORMALS*3 ; i++)
|
||||
avelocities[0][i] = (rand()&255) * 0.01;
|
||||
}
|
||||
|
||||
|
||||
for (i=0 ; i<NUMVERTEXNORMALS ; i++)
|
||||
{
|
||||
angle = cl.time * avelocities[i][0];
|
||||
sy = sin(angle);
|
||||
cy = cos(angle);
|
||||
angle = cl.time * avelocities[i][1];
|
||||
sp = sin(angle);
|
||||
cp = cos(angle);
|
||||
angle = cl.time * avelocities[i][2];
|
||||
sr = sin(angle);
|
||||
cr = cos(angle);
|
||||
|
||||
forward[0] = cp*cy;
|
||||
forward[1] = cp*sy;
|
||||
forward[2] = -sp;
|
||||
|
||||
if (!free_particles)
|
||||
return;
|
||||
p = free_particles;
|
||||
free_particles = p->next;
|
||||
p->next = active_particles;
|
||||
active_particles = p;
|
||||
|
||||
p->die = cl.time + 0.01;
|
||||
p->color[0] = p->color[1] = p->color[2] = 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_Clear_Classic_Particles (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_ClearParticles (void)
|
||||
{
|
||||
QMB_ClearParticles ();
|
||||
R_Clear_Classic_Particles();
|
||||
}
|
||||
|
||||
|
||||
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[0] = p->color[1] = p->color[2] = (-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[0] = p->color[1] = p->color[2] = 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[0] = p->color[1] = p->color[2] = 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[0] = p->color[1] = p->color[2] = 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[0] = p->color[1] = p->color[2] = 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
|
||||
|
||||
===============
|
||||
*/
|
||||
|
||||
#define RunParticleEffect(org, dir, color, count) \
|
||||
if (qmb_initialized) \
|
||||
QMB_RunParticleEffect (org, dir, color, count); \
|
||||
else \
|
||||
Run_Classic_ParticleEffect (org, dir, color, count);
|
||||
|
||||
void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count)
|
||||
{
|
||||
if (color == 73 || color == 225)
|
||||
{
|
||||
RunParticleEffect(org, dir, color, count);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (count)
|
||||
{
|
||||
case 10:
|
||||
case 20:
|
||||
case 30:
|
||||
RunParticleEffect(org, dir, color, count);
|
||||
break;
|
||||
default:
|
||||
RunParticleEffect(org, dir, color, count);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
Run_Classic_ParticleEffect
|
||||
===============
|
||||
*/
|
||||
|
||||
void Run_Classic_ParticleEffect (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[0] = p->color[1] = p->color[2] = 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[0] = p->color[1] = p->color[2] = (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[0] = p->color[1] = p->color[2] = 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[0] = p->color[1] = p->color[2] = 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[0] = p->color[1] = p->color[2] = 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[0] = p->color[1] = p->color[2] = 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[0] = p->color[1] = p->color[2] = 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[0] = p->color[1] = p->color[2] = 52 + ((tracercount&4)<<1);
|
||||
else
|
||||
p->color[0] = p->color[1] = p->color[2] = 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[0] = p->color[1] = p->color[2] = 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[0] = p->color[1] = p->color[2] = 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_Classic_DrawParticles
|
||||
===============
|
||||
*/
|
||||
extern cvar_t sv_gravity;
|
||||
|
||||
void R_Classic_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;
|
||||
|
||||
glColor4ubv (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[0] = p->color[1] = p->color[2] = 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[0] = p->color[1] = p->color[2] = 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[0] = p->color[1] = p->color[2] = 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
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_DrawParticles
|
||||
===============
|
||||
*/
|
||||
|
||||
void R_DrawParticles (void)
|
||||
{
|
||||
R_Classic_DrawParticles ();
|
||||
QMB_DrawParticles ();
|
||||
}
|
155
source/ctr/r_shared.h
Normal file
155
source/ctr/r_shared.h
Normal file
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public 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
|
||||
|
||||
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
|
||||
|
||||
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
|
199
source/ctr/render.h
Normal file
199
source/ctr/render.h
Normal file
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public 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;
|
||||
|
||||
// Tomaz - QC Alpha Scale Glow Begin
|
||||
float renderamt;
|
||||
float rendermode;
|
||||
float rendercolor[3];
|
||||
//Crow_bar
|
||||
|
||||
unsigned char scale;
|
||||
struct model_s *model; // NULL = no model
|
||||
char old_model[128]; // 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
|
||||
|
||||
// fenix@io.com: model transform interpolation
|
||||
float translate_start_time;
|
||||
vec3_t origin1;
|
||||
vec3_t origin2;
|
||||
|
||||
float rotate_start_time;
|
||||
vec3_t angles1;
|
||||
vec3_t angles2;
|
||||
|
||||
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
|
||||
|
||||
float frame_start_time;
|
||||
float frame_interval;
|
||||
int pose1;
|
||||
int pose2;
|
||||
|
||||
int modelindex;
|
||||
|
||||
int z_head;
|
||||
int z_larm;
|
||||
int z_rarm;
|
||||
|
||||
} entity_t;
|
||||
|
||||
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;
|
||||
|
||||
float fog_start;
|
||||
float fog_end;
|
||||
float fog_red;
|
||||
float fog_green;
|
||||
float fog_blue;
|
||||
} 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 miptex_s *mt); // called at level load
|
||||
|
||||
void R_AddEfrags (entity_t *ent);
|
||||
void R_RemoveEfrags (entity_t *ent);
|
||||
|
||||
void R_NewMap (void);
|
||||
|
||||
// particles
|
||||
|
||||
typedef enum trail_type_s
|
||||
{
|
||||
ROCKET_TRAIL, GRENADE_TRAIL, BLOOD_TRAIL, TRACER1_TRAIL, SLIGHT_BLOOD_TRAIL,NAIL_TRAIL,
|
||||
TRACER2_TRAIL, VOOR_TRAIL, ALT_ROCKET_TRAIL, LAVA_TRAIL, BUBBLE_TRAIL, NEHAHRA_SMOKE,
|
||||
RAYGREEN_TRAIL, RAYRED_TRAIL
|
||||
} trail_type_t;
|
||||
|
||||
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);
|
335
source/ctr/sbar.c
Normal file
335
source/ctr/sbar.c
Normal file
|
@ -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.
|
||||
|
||||
*/
|
||||
// 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;
|
||||
|
||||
extern qboolean sb_showscores;
|
||||
|
||||
extern 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)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Sbar_DontShowScores
|
||||
|
||||
Tab key up
|
||||
===============
|
||||
*/
|
||||
void Sbar_DontShowScores (void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Sbar_Changed
|
||||
===============
|
||||
*/
|
||||
void Sbar_Changed (void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Sbar_Init
|
||||
===============
|
||||
*/
|
||||
void Sbar_Init (void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// drawing routines are relative to the status bar location
|
||||
|
||||
/*
|
||||
=============
|
||||
Sbar_DrawPic
|
||||
=============
|
||||
*/
|
||||
void Sbar_DrawPic (int x, int y, qpic_t *pic)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Sbar_DrawTransPic
|
||||
=============
|
||||
*/
|
||||
void Sbar_DrawTransPic (int x, int y, qpic_t *pic)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Sbar_DrawCharacter
|
||||
|
||||
Draws one solid graphics character
|
||||
================
|
||||
*/
|
||||
void Sbar_DrawCharacter (int x, int y, int num)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Sbar_DrawString
|
||||
================
|
||||
*/
|
||||
void Sbar_DrawString (int x, int y, char *str)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Sbar_itoa
|
||||
=============
|
||||
*/
|
||||
int Sbar_itoa (int num, char *buf)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
Sbar_DrawNum
|
||||
=============
|
||||
*/
|
||||
void Sbar_DrawNum (int x, int y, int num, int digits, int color)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
int fragsort[MAX_SCOREBOARD];
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
Sbar_SortFrags
|
||||
===============
|
||||
*/
|
||||
void Sbar_SortFrags (void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int Sbar_ColorForMap (int m)
|
||||
{
|
||||
return m < 128 ? m + 8 : m + 8;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Sbar_UpdateScoreboard
|
||||
===============
|
||||
*/
|
||||
void Sbar_UpdateScoreboard (void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
Sbar_SoloScoreboard
|
||||
===============
|
||||
*/
|
||||
void Sbar_SoloScoreboard (void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Sbar_DrawScoreboard
|
||||
===============
|
||||
*/
|
||||
void Sbar_DrawScoreboard (void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
===============
|
||||
Sbar_DrawInventory
|
||||
===============
|
||||
*/
|
||||
void Sbar_DrawInventory (void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
===============
|
||||
Sbar_DrawFrags
|
||||
===============
|
||||
*/
|
||||
void Sbar_DrawFrags (void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
Sbar_DrawFace
|
||||
===============
|
||||
*/
|
||||
void Sbar_DrawFace (void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Sbar_Draw
|
||||
===============
|
||||
*/
|
||||
void Sbar_Draw (void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
==================
|
||||
Sbar_IntermissionNumber
|
||||
|
||||
==================
|
||||
*/
|
||||
void Sbar_IntermissionNumber (int x, int y, int num, int digits, int color)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sbar_DeathmatchOverlay
|
||||
|
||||
==================
|
||||
*/
|
||||
void Sbar_DeathmatchOverlay (void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sbar_DeathmatchOverlay
|
||||
|
||||
==================
|
||||
*/
|
||||
void Sbar_MiniDeathmatchOverlay (void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sbar_IntermissionOverlay
|
||||
|
||||
==================
|
||||
*/
|
||||
void Sbar_IntermissionOverlay (void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
Sbar_FinaleOverlay
|
||||
|
||||
==================
|
||||
*/
|
||||
void Sbar_FinaleOverlay (void)
|
||||
{
|
||||
|
||||
}
|
39
source/ctr/sbar.h
Normal file
39
source/ctr/sbar.h
Normal file
|
@ -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);
|
62
source/ctr/screen.h
Normal file
62
source/ctr/screen.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public 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_UsePrint (int type, int cost, int weapon);
|
||||
qpic_t *GetButtonIcon (char *buttonname);
|
||||
char *GetGrenadeButtonL();
|
||||
|
||||
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);
|
||||
|
||||
extern cvar_t scr_fov;
|
267
source/ctr/server.h
Normal file
267
source/ctr/server.h
Normal file
|
@ -0,0 +1,267 @@
|
|||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public 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;
|
||||
|
||||
int old_points;
|
||||
int old_kills;
|
||||
// joe, from ProQuake: allow clients to connect if they don't have the map
|
||||
qboolean nomap;
|
||||
} 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
|
||||
#define MOVETYPE_BOUNCEMISSILE 11 // bounce w/o gravity
|
||||
#define MOVETYPE_FOLLOW 12 // track movement of aiment
|
||||
|
||||
// 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
|
||||
#define SOLID_CORPSE 5 // 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_BLUELIGHT 1
|
||||
#define EF_MUZZLEFLASH 2
|
||||
#define EF_BRIGHTLIGHT 4
|
||||
#define EF_REDLIGHT 8
|
||||
#define EF_ORANGELIGHT 16
|
||||
#define EF_GREENLIGHT 32
|
||||
#define EF_PINKLIGHT 64 // formerly EF_LIGHT
|
||||
#define EF_NODRAW 128
|
||||
#define EF_LIMELIGHT 256 // formerly EF_BRIGHTFIELD
|
||||
#define EF_FULLBRIGHT 512
|
||||
#define EF_CYANLIGHT 1024 // formerly EF_DARKLIGHT
|
||||
#define EF_YELLOWLIGHT 2048 // formerly EF_DARKFIELD
|
||||
#define EF_PURPLELIGHT 4096
|
||||
#define EF_RAYRED 8196 // red trail for porter x2
|
||||
#define EF_RAYGREEN 16384 // green trail for ray gun
|
||||
|
||||
#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_MoveToOrigin (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
|
97
source/ctr/snd_ctr.c
Normal file
97
source/ctr/snd_ctr.c
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
Copyright (C) 2017 Felipe Izzo
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public 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 <stdio.h>
|
||||
#include <3ds.h>
|
||||
#include "../quakedef.h"
|
||||
|
||||
#define SAMPLE_RATE 22050
|
||||
#define NUM_SAMPLES 2048
|
||||
#define SAMPLE_SIZE 4
|
||||
#define BUFFER_SIZE NUM_SAMPLES*SAMPLE_SIZE
|
||||
|
||||
static int sound_initialized = 0;
|
||||
static byte *audio_buffer;
|
||||
static ndspWaveBuf wave_buf;
|
||||
|
||||
qboolean SNDDMA_Init(void)
|
||||
{
|
||||
sound_initialized = 0;
|
||||
|
||||
if(ndspInit() != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
audio_buffer = linearAlloc(BUFFER_SIZE);
|
||||
|
||||
ndspSetOutputMode(NDSP_OUTPUT_STEREO);
|
||||
ndspChnReset(0);
|
||||
ndspChnWaveBufClear(0);
|
||||
ndspChnSetInterp(0, NDSP_INTERP_LINEAR);
|
||||
ndspChnSetRate(0, (float)SAMPLE_RATE);
|
||||
ndspChnSetFormat(0, NDSP_FORMAT_STEREO_PCM16);
|
||||
|
||||
memset(&wave_buf, 0, sizeof(wave_buf));
|
||||
wave_buf.data_vaddr = audio_buffer;
|
||||
wave_buf.nsamples = BUFFER_SIZE / 4;
|
||||
wave_buf.looping = 1;
|
||||
|
||||
shm = &sn;
|
||||
shm->splitbuffer = 0;
|
||||
shm->samplebits = 16;
|
||||
shm->speed = SAMPLE_RATE;
|
||||
shm->channels = 2;
|
||||
shm->samples = BUFFER_SIZE / 2;
|
||||
shm->samplepos = 0;
|
||||
shm->submission_chunk = 1;
|
||||
shm->buffer = audio_buffer;
|
||||
|
||||
ndspChnWaveBufAdd(0, &wave_buf);
|
||||
|
||||
sound_initialized = 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int SNDDMA_GetDMAPos(void)
|
||||
{
|
||||
if(!sound_initialized)
|
||||
return 0;
|
||||
|
||||
shm->samplepos = ndspChnGetSamplePos(0) / (shm->samplebits / 8);
|
||||
return shm->samplepos;
|
||||
}
|
||||
|
||||
void SNDDMA_Shutdown(void)
|
||||
{
|
||||
if(!sound_initialized)
|
||||
return;
|
||||
|
||||
ndspChnWaveBufClear(0);
|
||||
ndspExit();
|
||||
linearFree(audio_buffer);
|
||||
|
||||
sound_initialized = 0;
|
||||
}
|
||||
|
||||
void SNDDMA_Submit(void)
|
||||
{
|
||||
}
|
10
source/ctr/strl_fn.h
Normal file
10
source/ctr/strl_fn.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
/* header file for BSD strlcat and strlcpy */
|
||||
|
||||
#ifndef __STRLFUNCS_H
|
||||
#define __STRLFUNCS_H
|
||||
|
||||
/* use our own copies of strlcpy and strlcat taken from OpenBSD */
|
||||
extern size_t q_strlcpy (char *dst, const char *src, size_t size);
|
||||
extern size_t q_strlcat (char *dst, const char *src, size_t size);
|
||||
|
||||
#endif /* __STRLFUNCS_H */
|
71
source/ctr/sys.h
Normal file
71
source/ctr/sys.h
Normal file
|
@ -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);
|
||||
|
340
source/ctr/sys_ctr.c
Normal file
340
source/ctr/sys_ctr.c
Normal file
|
@ -0,0 +1,340 @@
|
|||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public 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 "errno.h"
|
||||
#include "touch_ctr.h"
|
||||
|
||||
#include <3ds.h>
|
||||
|
||||
#define TICKS_PER_SEC 268123480.0
|
||||
|
||||
int __stacksize__ = 4 * 1024 * 1024;
|
||||
u32 __ctru_linear_heap_size = 28 * 1024 * 1024;
|
||||
bool new3ds_flag;
|
||||
|
||||
extern void Touch_Init();
|
||||
extern void Touch_Update();
|
||||
|
||||
qboolean isDedicated;
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
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)
|
||||
{
|
||||
mkdir(path, 0777);
|
||||
}
|
||||
|
||||
void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
|
||||
{
|
||||
}
|
||||
|
||||
void Sys_Error (char *error, ...)
|
||||
{
|
||||
consoleInit(GFX_BOTTOM, NULL);
|
||||
|
||||
va_list argptr;
|
||||
|
||||
printf ("Sys_Error: ");
|
||||
va_start (argptr,error);
|
||||
vprintf (error,argptr);
|
||||
va_end (argptr);
|
||||
printf ("\n");
|
||||
|
||||
while(!(hidKeysDown() & KEY_START))
|
||||
hidScanInput();
|
||||
|
||||
Host_Shutdown();
|
||||
|
||||
gfxExit();
|
||||
Sys_Quit();
|
||||
}
|
||||
|
||||
void Sys_Printf (char *fmt, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
|
||||
va_start (argptr,fmt);
|
||||
vprintf (fmt,argptr);
|
||||
va_end (argptr);
|
||||
}
|
||||
|
||||
void Sys_Quit (void)
|
||||
{
|
||||
Host_Shutdown();
|
||||
|
||||
gfxExit();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
double Sys_FloatTime (void)
|
||||
{
|
||||
static u64 initial_tick = 0;
|
||||
|
||||
if(!initial_tick)
|
||||
initial_tick = svcGetSystemTick();
|
||||
|
||||
u64 current_tick = svcGetSystemTick();
|
||||
|
||||
return (current_tick - initial_tick)/TICKS_PER_SEC;
|
||||
}
|
||||
|
||||
char *Sys_ConsoleInput (void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Sys_Sleep (void)
|
||||
{
|
||||
}
|
||||
|
||||
void Sys_DefaultConfig(void)
|
||||
{
|
||||
// naievil -- fixme I didn't do this
|
||||
Cbuf_AddText ("bind ABUTTON +right\n");
|
||||
Cbuf_AddText ("bind BBUTTON +lookdown\n");
|
||||
Cbuf_AddText ("bind XBUTTON +lookup\n");
|
||||
Cbuf_AddText ("bind YBUTTON +left\n");
|
||||
Cbuf_AddText ("bind LTRIGGER +jump\n");
|
||||
Cbuf_AddText ("bind RTRIGGER +attack\n");
|
||||
Cbuf_AddText ("bind PADUP \"impulse 10\"\n");
|
||||
Cbuf_AddText ("bind PADDOWN \"impulse 12\"\n");
|
||||
//Cbuf_AddText ("lookstrafe \"1.000000\"\n");
|
||||
//Cbuf_AddText ("lookspring \"0.000000\"\n");
|
||||
}
|
||||
|
||||
void Sys_SetKeys(u32 keys, u32 state){
|
||||
if( keys & KEY_SELECT)
|
||||
Key_Event(K_SELECT, state);
|
||||
if( keys & KEY_START)
|
||||
Key_Event(K_ESCAPE, state);
|
||||
if( keys & KEY_DUP)
|
||||
Key_Event(K_UPARROW, state);
|
||||
if( keys & KEY_DDOWN)
|
||||
Key_Event(K_DOWNARROW, state);
|
||||
if( keys & KEY_DLEFT)
|
||||
Key_Event(K_LEFTARROW, state);
|
||||
if( keys & KEY_DRIGHT)
|
||||
Key_Event(K_RIGHTARROW, state);
|
||||
if( keys & KEY_Y)
|
||||
Key_Event(K_AUX4, state);
|
||||
if( keys & KEY_X)
|
||||
Key_Event(K_AUX3, state);
|
||||
if( keys & KEY_B)
|
||||
Key_Event(K_AUX2, state);
|
||||
if( keys & KEY_A)
|
||||
Key_Event(K_AUX1, state);
|
||||
if( keys & KEY_L)
|
||||
Key_Event(K_AUX5, state);
|
||||
if( keys & KEY_R)
|
||||
Key_Event(K_AUX7, state);
|
||||
if( keys & KEY_ZL)
|
||||
Key_Event(K_AUX6, state);
|
||||
if( keys & KEY_ZR)
|
||||
Key_Event(K_AUX8, state);
|
||||
}
|
||||
|
||||
void Sys_SendKeyEvents (void)
|
||||
{
|
||||
hidScanInput();
|
||||
|
||||
u32 kDown = hidKeysDown();
|
||||
u32 kUp = hidKeysUp();
|
||||
|
||||
if(kDown)
|
||||
Sys_SetKeys(kDown, true);
|
||||
if(kUp)
|
||||
Sys_SetKeys(kUp, false);
|
||||
|
||||
Touch_Update();
|
||||
}
|
||||
|
||||
void Sys_HighFPPrecision (void)
|
||||
{
|
||||
}
|
||||
|
||||
void Sys_LowFPPrecision (void)
|
||||
{
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
bool game_running;
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
static float time, oldtime;
|
||||
static quakeparms_t parms;
|
||||
new3ds_flag = false;
|
||||
|
||||
osSetSpeedupEnable(true);
|
||||
|
||||
APT_CheckNew3DS(&new3ds_flag);
|
||||
|
||||
gfxInit(GSP_BGR8_OES, GSP_RGB565_OES, false);
|
||||
gfxSetDoubleBuffering(GFX_BOTTOM, false);
|
||||
gfxSwapBuffersGpu();
|
||||
|
||||
uint8_t model;
|
||||
|
||||
cfguInit();
|
||||
CFGU_GetSystemModel(&model);
|
||||
cfguExit();
|
||||
|
||||
if(model != CFG_MODEL_2DS && new3ds_flag == true)
|
||||
gfxSetWide(true);
|
||||
|
||||
chdir("sdmc:/3ds/nzportable");
|
||||
|
||||
if (new3ds_flag == true)
|
||||
parms.memsize = 64 * 1024 * 1024;
|
||||
else
|
||||
parms.memsize = 16 * 1024 * 1024;
|
||||
|
||||
parms.membase = malloc (parms.memsize);
|
||||
parms.basedir = ".";
|
||||
|
||||
COM_InitArgv (argc, argv);
|
||||
|
||||
parms.argc = com_argc;
|
||||
parms.argv = com_argv;
|
||||
|
||||
Host_Init (&parms);
|
||||
Touch_Init();
|
||||
Touch_DrawOverlay();
|
||||
|
||||
oldtime = Sys_FloatTime();
|
||||
|
||||
game_running = true;
|
||||
while (aptMainLoop() && game_running)
|
||||
{
|
||||
time = Sys_FloatTime();
|
||||
Host_Frame (time - oldtime);
|
||||
oldtime = time;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
92
source/ctr/touch_ctr.c
Normal file
92
source/ctr/touch_ctr.c
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
Copyright (C) 2015 Felipe Izzo
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
//FIX ME: load all hardcoded values from file
|
||||
|
||||
#include "../quakedef.h"
|
||||
|
||||
#include <3ds.h>
|
||||
#include "touch_ctr.h"
|
||||
|
||||
u16* touchOverlay;
|
||||
char lastKey = 0;
|
||||
int tmode;
|
||||
u16* tfb;
|
||||
touchPosition oldtouch, touch;
|
||||
u64 tick;
|
||||
|
||||
u64 lastTap = 0;
|
||||
|
||||
int shiftToggle = 0;
|
||||
|
||||
void Touch_Init(){
|
||||
tmode = TMODE_TOUCHPAD; //Start in touchpad Mode
|
||||
tfb = (u16*)gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL);
|
||||
|
||||
//Load overlay files from sdmc for easier testing
|
||||
FILE *texture = fopen("touchOverlay.bin", "rb");
|
||||
if(!texture)
|
||||
Sys_Error("Could not open touchpadOverlay.bin\n");
|
||||
fseek(texture, 0, SEEK_END);
|
||||
int size = ftell(texture);
|
||||
fseek(texture, 0, SEEK_SET);
|
||||
touchOverlay = malloc(size);
|
||||
fread(touchOverlay, 1, size, texture);
|
||||
fclose(texture);
|
||||
}
|
||||
|
||||
void Touch_DrawOverlay()
|
||||
{
|
||||
int x, y;
|
||||
for(x=0; x<320; x++){
|
||||
for(y=0; y<240;y++){
|
||||
tfb[(x*240 + (239 - y))] = touchOverlay[(y*320 + x)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Touch_Update(){
|
||||
if(lastKey){
|
||||
Key_Event(lastKey, false);
|
||||
lastKey = 0;
|
||||
}
|
||||
|
||||
if(hidKeysDown() & KEY_TOUCH){
|
||||
hidTouchRead(&touch);
|
||||
tick = Sys_FloatTime();
|
||||
}
|
||||
|
||||
if(hidKeysUp() & KEY_TOUCH){
|
||||
Touch_ProcessTap();
|
||||
}
|
||||
}
|
||||
|
||||
void Touch_ProcessTap()
|
||||
{
|
||||
if(touch.px > 268 && touch.py > 14 && touch.py < 226)
|
||||
Touch_SideBarTap();
|
||||
}
|
||||
|
||||
void Touch_SideBarTap()
|
||||
{
|
||||
uint16_t y = (touch.py - 14)/42;
|
||||
lastKey = K_AUX9 + y;
|
||||
Key_Event(lastKey, true);
|
||||
}
|
14
source/ctr/touch_ctr.h
Normal file
14
source/ctr/touch_ctr.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef __TOUCH__
|
||||
#define __TOUCH__
|
||||
|
||||
//Touchscreen mode identifiers
|
||||
#define TMODE_TOUCHPAD 1
|
||||
#define TMODE_SETTINGS 2
|
||||
|
||||
void Touch_TouchpadTap();
|
||||
void Touch_ProcessTap();
|
||||
void Touch_DrawOverlay();
|
||||
void Touch_Init();
|
||||
void Touch_Update();
|
||||
|
||||
#endif
|
85
source/ctr/vid.h
Normal file
85
source/ctr/vid.h
Normal file
|
@ -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
|
||||
|
Loading…
Reference in a new issue