mirror of
https://github.com/alliedmodders/hl2sdk.git
synced 2024-12-23 01:59:43 +08:00
Imported tier1 and mathlib code from L4D2 SDK.
This commit is contained in:
parent
5d4df73a21
commit
afaa180bbc
150
linux_sdk/Makefile
Normal file
150
linux_sdk/Makefile
Normal file
@ -0,0 +1,150 @@
|
||||
#
|
||||
# SDK Makefile for x86 Linux
|
||||
#
|
||||
#
|
||||
|
||||
#############################################################################
|
||||
# Developer configurable items
|
||||
#############################################################################
|
||||
|
||||
# the name of the mod binary (_i486.so is appended to the end)
|
||||
NAME = server
|
||||
|
||||
# the location of the vcproj that builds the mod
|
||||
MOD_PROJ = ../game/server/server_scratch-2005.vcproj
|
||||
# the name of the mod configuration (typically <proj name>_<build type><build target>)
|
||||
MOD_CONFIG = Server\(SDK\)_ReleaseWin32
|
||||
|
||||
# the directory the base binaries (tier0_i486.so, etc) are located
|
||||
# this should point to your orange box subfolder of where you have srcds installed.
|
||||
SRCDS_DIR = ~/srcds/orangebox
|
||||
|
||||
# the path to your mods directory
|
||||
# set this so that 'make install' or 'make installrelease' will copy your binary over automatically.
|
||||
GAME_DIR = $(SRCDS_DIR)/scratchmod
|
||||
|
||||
# compiler options (gcc 3.4.1 or above is required - 4.1.2+ recommended)
|
||||
CC = /usr/bin/gcc
|
||||
CPLUS = /usr/bin/g++
|
||||
CLINK = /usr/bin/gcc
|
||||
CPP_LIB = "libstdc++.a libgcc_eh.a"
|
||||
|
||||
# put any compiler flags you want passed here
|
||||
USER_CFLAGS =
|
||||
|
||||
# link flags for your mod, make sure to include any special libraries here
|
||||
LDFLAGS = "-lm -ldl $(LIB_DIR)/particles_i486.a $(LIB_DIR)/dmxloader_i486.a $(LIB_DIR)/mathlib_i486.a tier0_i486.so vstdlib_i486.so $(LIB_DIR)/tier1_i486.a $(LIB_DIR)/tier2_i486.a $(LIB_DIR)/tier3_i486.a $(LIB_DIR)/choreoobjects_i486.a steam_api_i486.so"
|
||||
|
||||
# XERCES 2.6.0 or above ( http://xml.apache.org/xerces-c/ ) is used by the vcproj to makefile converter
|
||||
# it must be installed before being able to run this makefile
|
||||
# if you have xerces installed already you should be able to use the two lines below
|
||||
XERCES_INC_DIR = /usr/include
|
||||
XERCES_LIB_DIR = /usr/lib
|
||||
|
||||
# Change this to true if you want to build debug binaries for everything
|
||||
# The only exception is the mod/game as MOD_CONFIG determines if it's a debug build or not
|
||||
DEBUG = false
|
||||
|
||||
#############################################################################
|
||||
# Things below here shouldn't need to be altered
|
||||
#############################################################################
|
||||
MAKE = make
|
||||
AR = "ar rvs"
|
||||
|
||||
# the dir we want to put binaries we build into
|
||||
BUILD_DIR = .
|
||||
# the place to put object files
|
||||
BUILD_OBJ_DIR = $(BUILD_DIR)/obj
|
||||
|
||||
# the location of the source code
|
||||
SRC_DIR = ..
|
||||
# the location of the Linux static libraries
|
||||
LIB_DIR = $(SRC_DIR)/lib/linux
|
||||
|
||||
# the CPU target for the build, must be i486 for now
|
||||
ARCH = i486
|
||||
ARCH_CFLAGS = -mtune=i686 -march=pentium3 -mmmx -m32
|
||||
|
||||
DEFINES = -D_LINUX -DLINUX -DVPROF_LEVEL=1 -DSWDS -D_finite=finite -Dstricmp=strcasecmp -D_stricmp=strcasecmp \
|
||||
-D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp
|
||||
UNDEF = -Usprintf -Ustrncpy -UPROTECTED_THINGS_ENABLE
|
||||
|
||||
BASE_CFLAGS = -fno-strict-aliasing -Wall -Werror -Wconversion -Wno-non-virtual-dtor -Wno-invalid-offsetof
|
||||
SHLIBEXT = so
|
||||
SHLIBCFLAGS = -fPIC
|
||||
SHLIBLDFLAGS = -shared -Wl,-Map,$@_map.txt -Wl
|
||||
|
||||
# Flags passed to the c compiler
|
||||
CFLAGS = $(DEFINES) $(ARCH_CFLAGS) -O3 $(BASE_CFLAGS)
|
||||
ifdef USER_CFLAGS
|
||||
CFLAGS += $(USER_CFLAGS)
|
||||
endif
|
||||
CFLAGS += $(UNDEF)
|
||||
|
||||
# Debug flags
|
||||
DBG_DEFINES = "-D_DEBUG -DDEBUG"
|
||||
DBG_CFLAGS = "$(DEFINES) $(ARCH_CFLAGS) -g -ggdb $(BASE_CFLAGS) $(UNDEF)"
|
||||
|
||||
# define list passed to make for the sub makefile
|
||||
BASE_DEFINES = CC=$(CC) AR=$(AR) CPLUS=$(CPLUS) CPP_LIB=$(CPP_LIB) DEBUG=$(DEBUG) \
|
||||
BUILD_DIR=$(BUILD_DIR) BUILD_OBJ_DIR=$(BUILD_OBJ_DIR) SRC_DIR=$(SRC_DIR) \
|
||||
LIB_DIR=$(LIB_DIR) SHLIBLDFLAGS=$(SHLIBLDFLAGS) SHLIBEXT=$(SHLIBEXT) \
|
||||
CLINK=$(CLINK) CFLAGS="$(CFLAGS)" DBG_CFLAGS=$(DBG_CFLAGS) LDFLAGS=$(LDFLAGS) \
|
||||
DEFINES="$(DEFINES)" DBG_DEFINES=$(DBG_DEFINES) \
|
||||
ARCH=$(ARCH) SRCDS_DIR=$(SRCDS_DIR) MOD_CONFIG=$(MOD_CONFIG) NAME=$(NAME) \
|
||||
XERCES_INC_DIR=$(XERCES_INC_DIR) XERCES_LIB_DIR=$(XERCES_LIB_DIR)
|
||||
|
||||
# Project Makefile
|
||||
MAKE_SERVER = Makefile.server
|
||||
MAKE_VCPM = Makefile.vcpm
|
||||
MAKE_PLUGIN = Makefile.plugin
|
||||
MAKE_TIER1 = Makefile.tier1
|
||||
MAKE_MATH = Makefile.mathlib
|
||||
MAKE_CHOREO = Makefile.choreo
|
||||
|
||||
all: check vcpm mod
|
||||
|
||||
check:
|
||||
if [ -z "$(CC)" ]; then echo "Compiler not defined."; exit; fi
|
||||
if [ ! -d $(BUILD_DIR) ];then mkdir -p $(BUILD_DIR);fi
|
||||
cd $(BUILD_DIR)
|
||||
if [ ! -e "$(LIB_DIR)/tier1_i486.a" ]; then $(MAKE) tier1;fi
|
||||
if [ ! -e "$(LIB_DIR)/mathlib_i486.a" ]; then $(MAKE) mathlib;fi
|
||||
if [ ! -e "$(LIB_DIR)/choreoobjects_i486.a" ]; then $(MAKE) choreo;fi
|
||||
if [ ! -f "tier0_i486.so" ]; then ln -s $(SRCDS_DIR)/bin/tier0_i486.so .; fi
|
||||
if [ ! -f "vstdlib_i486.so" ]; then ln -s $(SRCDS_DIR)/bin/vstdlib_i486.so .; fi
|
||||
if [ ! -f "steam_api_i486.so" ]; then ln -s $(SRCDS_DIR)/bin/steam_api_i486.so .; fi
|
||||
|
||||
vcpm: check
|
||||
if [ ! -e "vcpm" ]; then $(MAKE) -f $(MAKE_VCPM) $(BASE_DEFINES);fi
|
||||
|
||||
mod: check vcpm
|
||||
./vcpm $(MOD_PROJ)
|
||||
$(MAKE) -f $(MAKE_SERVER) $(BASE_DEFINES)
|
||||
|
||||
plugin: check
|
||||
$(MAKE) -f $(MAKE_PLUGIN) $(BASE_DEFINES)
|
||||
|
||||
tier1:
|
||||
$(MAKE) -f $(MAKE_TIER1) $(BASE_DEFINES)
|
||||
|
||||
mathlib:
|
||||
$(MAKE) -f $(MAKE_MATH) $(BASE_DEFINES)
|
||||
|
||||
choreo:
|
||||
$(MAKE) -f $(MAKE_CHOREO) $(BASE_DEFINES)
|
||||
|
||||
install:
|
||||
cp -f $(NAME)_$(ARCH).$(SHLIBEXT) $(GAME_DIR)/bin/$(NAME)_$(ARCH).$(SHLIBEXT)
|
||||
|
||||
installrelease:
|
||||
cp -f $(NAME)_$(ARCH).$(SHLIBEXT) $(GAME_DIR)/bin/$(NAME)_$(ARCH).$(SHLIBEXT)
|
||||
strip $(GAME_DIR)/bin/$(NAME)_$(ARCH).$(SHLIBEXT)
|
||||
|
||||
clean:
|
||||
$(MAKE) -f $(MAKE_VCPM) $(BASE_DEFINES) clean
|
||||
$(MAKE) -f $(MAKE_PLUGIN) $(BASE_DEFINES) clean
|
||||
$(MAKE) -f $(MAKE_SERVER) $(BASE_DEFINES) clean
|
||||
$(MAKE) -f $(MAKE_TIER1) $(BASE_DEFINES) clean
|
||||
$(MAKE) -f $(MAKE_MATH) $(BASE_DEFINES) clean
|
||||
$(MAKE) -f $(MAKE_CHOREO) $(BASE_DEFINES) clean
|
57
linux_sdk/Makefile.choreo
Normal file
57
linux_sdk/Makefile.choreo
Normal file
@ -0,0 +1,57 @@
|
||||
#
|
||||
# Choreoobjects Static Library Makefile
|
||||
#
|
||||
|
||||
override NAME = choreoobjects
|
||||
|
||||
LIB_SRC_DIR = $(SRC_DIR)/game/shared
|
||||
PUBLIC_SRC_DIR = $(SRC_DIR)/public
|
||||
TIER0_PUBLIC_SRC_DIR = $(SRC_DIR)/public/tier0
|
||||
TIER1_PUBLIC_SRC_DIR = $(SRC_DIR)/public/tier1
|
||||
UTIL_COMMON_SRC_DIR = $(SRC_DIR)/utils/common
|
||||
|
||||
LIB_OBJ_DIR = $(BUILD_OBJ_DIR)/$(NAME)_$(ARCH)
|
||||
|
||||
# Extension of linux static library
|
||||
override SHLIBEXT = a
|
||||
|
||||
INCLUDEDIRS = -I$(LIB_SRC_DIR) -I$(PUBLIC_SRC_DIR) -I$(TIER0_PUBLIC_SRC_DIR) -I$(TIER1_PUBLIC_SRC_DIR) -I$(UTIL_COMMON_SRC_DIR) -D_LIB -DCHOREOOBJECTS_STATIC_LIB
|
||||
|
||||
DO_CC = $(CPLUS) $(INCLUDEDIRS) -DARCH=$(ARCH)
|
||||
|
||||
ifeq "$(DEBUG)" "true"
|
||||
DO_CC += $(DBG_DEFINES) $(DBG_CFLAGS)
|
||||
else
|
||||
DO_CC += -DNDEBUG $(CFLAGS)
|
||||
endif
|
||||
|
||||
DO_CC += -o $@ -c $<
|
||||
|
||||
#####################################################################
|
||||
|
||||
LIB_OBJS= \
|
||||
$(LIB_OBJ_DIR)/choreoactor.o \
|
||||
$(LIB_OBJ_DIR)/choreochannel.o \
|
||||
$(LIB_OBJ_DIR)/choreoevent.o \
|
||||
$(LIB_OBJ_DIR)/choreoscene.o \
|
||||
$(LIB_OBJ_DIR)/sceneimage.o \
|
||||
|
||||
all: dirs $(NAME)_$(ARCH).$(SHLIBEXT)
|
||||
|
||||
dirs:
|
||||
-mkdir -p $(BUILD_OBJ_DIR)
|
||||
-mkdir -p $(LIB_OBJ_DIR)
|
||||
|
||||
$(NAME)_$(ARCH).$(SHLIBEXT): $(LIB_OBJS)
|
||||
$(AR) $(LIB_DIR)/$@ $(LIB_OBJS)
|
||||
|
||||
$(LIB_OBJ_DIR)/%.o: $(LIB_SRC_DIR)/%.cpp
|
||||
$(DO_CC)
|
||||
|
||||
install:
|
||||
cp -f $(NAME)_$(ARCH).$(SHLIBEXT) $(LIB_DIR)/$(NAME)_$(ARCH).$(SHLIBEXT)
|
||||
|
||||
clean:
|
||||
-rm -rf $(LIB_OBJ_DIR)
|
||||
|
||||
|
71
linux_sdk/Makefile.mathlib
Normal file
71
linux_sdk/Makefile.mathlib
Normal file
@ -0,0 +1,71 @@
|
||||
#
|
||||
# Mathlin Static Library Makefile
|
||||
#
|
||||
|
||||
override NAME = mathlib
|
||||
|
||||
LIB_SRC_DIR = $(SRC_DIR)/$(NAME)
|
||||
PUBLIC_SRC_DIR = $(SRC_DIR)/public
|
||||
TIER0_PUBLIC_SRC_DIR = $(SRC_DIR)/public/tier0
|
||||
TIER1_PUBLIC_SRC_DIR = $(SRC_DIR)/public/tier1
|
||||
MATHLIB_PUBLIC_SRC_DIR = $(SRC_DIR)/public/mathlib
|
||||
|
||||
LIB_OBJ_DIR = $(BUILD_OBJ_DIR)/$(NAME)_$(ARCH)
|
||||
|
||||
# Extension of linux static library
|
||||
override SHLIBEXT = a
|
||||
|
||||
INCLUDEDIRS = -I$(PUBLIC_SRC_DIR) -I$(TIER0_PUBLIC_SRC_DIR) -I$(TIER1_PUBLIC_SRC_DIR) -I$(MATHLIB_PUBLIC_SRC_DIR) -D_LIB
|
||||
|
||||
DO_CC = $(CPLUS) $(INCLUDEDIRS) -DARCH=$(ARCH)
|
||||
|
||||
ifeq "$(DEBUG)" "true"
|
||||
DO_CC += $(DBG_DEFINES) $(DBG_CFLAGS)
|
||||
else
|
||||
DO_CC += -DNDEBUG $(CFLAGS)
|
||||
endif
|
||||
|
||||
DO_CC += -o $@ -c $<
|
||||
|
||||
#####################################################################
|
||||
|
||||
LIB_OBJS= \
|
||||
$(LIB_OBJ_DIR)/3dnow.o \
|
||||
$(LIB_OBJ_DIR)/anorms.o \
|
||||
$(LIB_OBJ_DIR)/bumpvects.o \
|
||||
$(LIB_OBJ_DIR)/color_conversion.o \
|
||||
$(LIB_OBJ_DIR)/halton.o \
|
||||
$(LIB_OBJ_DIR)/IceKey.o \
|
||||
$(LIB_OBJ_DIR)/imagequant.o \
|
||||
$(LIB_OBJ_DIR)/lightdesc.o \
|
||||
$(LIB_OBJ_DIR)/mathlib_base.o \
|
||||
$(LIB_OBJ_DIR)/polyhedron.o \
|
||||
$(LIB_OBJ_DIR)/powsse.o \
|
||||
$(LIB_OBJ_DIR)/quantize.o \
|
||||
$(LIB_OBJ_DIR)/randsse.o \
|
||||
$(LIB_OBJ_DIR)/simdvectormatrix.o \
|
||||
$(LIB_OBJ_DIR)/sparse_convolution_noise.o \
|
||||
$(LIB_OBJ_DIR)/sse.o \
|
||||
$(LIB_OBJ_DIR)/sseconst.o \
|
||||
$(LIB_OBJ_DIR)/ssenoise.o \
|
||||
$(LIB_OBJ_DIR)/vector.o \
|
||||
$(LIB_OBJ_DIR)/vmatrix.o \
|
||||
|
||||
all: dirs $(NAME)_$(ARCH).$(SHLIBEXT)
|
||||
|
||||
dirs:
|
||||
-mkdir -p $(BUILD_OBJ_DIR)
|
||||
-mkdir -p $(LIB_OBJ_DIR)
|
||||
|
||||
$(NAME)_$(ARCH).$(SHLIBEXT): $(LIB_OBJS)
|
||||
$(AR) $(LIB_DIR)/$@ $(LIB_OBJS)
|
||||
|
||||
$(LIB_OBJ_DIR)/%.o: $(LIB_SRC_DIR)/%.cpp
|
||||
$(DO_CC)
|
||||
|
||||
install:
|
||||
cp -f $(NAME)_$(ARCH).$(SHLIBEXT) $(LIB_DIR)/$(NAME)_$(ARCH).$(SHLIBEXT)
|
||||
|
||||
clean:
|
||||
-rm -rf $(LIB_OBJ_DIR)
|
||||
|
57
linux_sdk/Makefile.plugin
Normal file
57
linux_sdk/Makefile.plugin
Normal file
@ -0,0 +1,57 @@
|
||||
#
|
||||
# Sample server plugin for SRC engine
|
||||
#
|
||||
# October 2004, alfred@valvesoftware.com
|
||||
#
|
||||
|
||||
override NAME = serverplugin_empty
|
||||
|
||||
PLUGIN_SRC_DIR = $(SRC_DIR)/utils/serverplugin_sample
|
||||
PUBLIC_SRC_DIR = $(SRC_DIR)/public
|
||||
TIER0_PUBLIC_SRC_DIR = $(SRC_DIR)/public/tier0
|
||||
TIER1_PUBLIC_SRC_DIR = $(SRC_DIR)/public/tier1
|
||||
|
||||
PLUGIN_OBJ_DIR = $(BUILD_OBJ_DIR)/serverplugin_empty_$(ARCH)
|
||||
TIER0_OBJ_DIR = $(PLUGIN_OBJ_DIR)/tier0
|
||||
|
||||
INCLUDEDIRS = -I$(PUBLIC_SRC_DIR) -I$(TIER0_PUBLIC_SRC_DIR) -I$(TIER1_PUBLIC_SRC_DIR)
|
||||
LDFLAGS_PLG = -lm -ldl tier0_i486.so vstdlib_i486.so $(LIB_DIR)/mathlib_i486.a $(LIB_DIR)/tier1_i486.a $(LIB_DIR)/tier2_i486.a
|
||||
|
||||
DO_CC = $(CPLUS) $(INCLUDEDIRS) -DARCH=$(ARCH)
|
||||
|
||||
ifeq "$(DEBUG)" "true"
|
||||
DO_CC += $(DBG_DEFINES) $(DBG_CFLAGS)
|
||||
else
|
||||
DO_CC += -DNDEBUG $(CFLAGS)
|
||||
endif
|
||||
|
||||
DO_CC += -o $@ -c $<
|
||||
|
||||
#####################################################################
|
||||
|
||||
PLUGIN_OBJS = \
|
||||
$(PLUGIN_OBJ_DIR)/serverplugin_bot.o \
|
||||
$(PLUGIN_OBJ_DIR)/serverplugin_empty.o \
|
||||
|
||||
TIER0_OBJS = \
|
||||
$(TIER0_OBJ_DIR)/memoverride.o \
|
||||
|
||||
all: dirs $(NAME)_$(ARCH).$(SHLIBEXT)
|
||||
|
||||
dirs:
|
||||
-mkdir -p $(BUILD_OBJ_DIR)
|
||||
-mkdir -p $(PLUGIN_OBJ_DIR)
|
||||
-mkdir -p $(TIER0_OBJ_DIR)
|
||||
|
||||
$(NAME)_$(ARCH).$(SHLIBEXT): $(PLUGIN_OBJS) $(TIER0_OBJS)
|
||||
$(CLINK) -o $(BUILD_DIR)/$@ -m32 $(SHLIBLDFLAGS) $(PLUGIN_OBJS) $(TIER0_OBJS) $(PUBLIC_OBJS) $(CPP_LIB) $(LDFLAGS_PLG) $(CPP_LIB)
|
||||
|
||||
$(PLUGIN_OBJ_DIR)/%.o: $(PLUGIN_SRC_DIR)/%.cpp
|
||||
$(DO_CC)
|
||||
|
||||
$(TIER0_OBJ_DIR)/%.o: $(TIER0_PUBLIC_SRC_DIR)/%.cpp
|
||||
$(DO_CC)
|
||||
|
||||
clean:
|
||||
-rm -rf $(PLUGIN_OBJ_DIR)
|
||||
-rm -f $(NAME)_$(ARCH).$(SHLIBEXT)
|
28
linux_sdk/Makefile.server
Normal file
28
linux_sdk/Makefile.server
Normal file
@ -0,0 +1,28 @@
|
||||
#
|
||||
# wrapper Makefile for auto-generated make files
|
||||
#
|
||||
#
|
||||
|
||||
#############################################################################
|
||||
# PROJECT MAKEFILES
|
||||
#############################################################################
|
||||
MAKE_FILE = Makefile.$(MOD_CONFIG)
|
||||
-include $(MAKE_FILE)
|
||||
|
||||
#############################################################################
|
||||
# The compiler command line for each src code file to compile
|
||||
#############################################################################
|
||||
DO_CC = $(CPLUS) $(INCLUDES) -DARCH=$(ARCH)
|
||||
|
||||
ifeq (_DEBUG,$(findstring _DEBUG,$(CFLAGS)))
|
||||
DO_CC += $(DEFINES) $(DBG_CFLAGS)
|
||||
else
|
||||
DO_CC += $(CFLAGS)
|
||||
endif
|
||||
|
||||
DO_CC += -o $@ -c $<
|
||||
|
||||
clean:
|
||||
rm -rf obj/$(NAME)_$(ARCH)
|
||||
rm -f $(NAME)_$(ARCH).$(SHLIBEXT)
|
||||
|
78
linux_sdk/Makefile.tier1
Normal file
78
linux_sdk/Makefile.tier1
Normal file
@ -0,0 +1,78 @@
|
||||
#
|
||||
# Tier1 Static Library Makefile
|
||||
#
|
||||
|
||||
override NAME = tier1
|
||||
|
||||
LIB_SRC_DIR = $(SRC_DIR)/$(NAME)
|
||||
PUBLIC_SRC_DIR = $(SRC_DIR)/public
|
||||
TIER0_PUBLIC_SRC_DIR = $(SRC_DIR)/public/tier0
|
||||
TIER1_PUBLIC_SRC_DIR = $(SRC_DIR)/public/tier1
|
||||
|
||||
LIB_OBJ_DIR=$(BUILD_OBJ_DIR)/$(NAME)_$(ARCH)
|
||||
|
||||
# Extension of linux static library
|
||||
override SHLIBEXT = a
|
||||
|
||||
INCLUDEDIRS = -I$(PUBLIC_SRC_DIR) -I$(TIER0_PUBLIC_SRC_DIR) -I$(TIER1_PUBLIC_SRC_DIR) -D_LIB -DTIER1_STATIC_LIB
|
||||
|
||||
DO_CC = $(CPLUS) $(INCLUDEDIRS) -DARCH=$(ARCH)
|
||||
|
||||
ifeq "$(DEBUG)" "true"
|
||||
DO_CC += $(DBG_DEFINES) $(DBG_CFLAGS)
|
||||
else
|
||||
DO_CC += -DNDEBUG $(CFLAGS)
|
||||
endif
|
||||
|
||||
DO_CC += -o $@ -c $<
|
||||
|
||||
#####################################################################
|
||||
|
||||
LIB_OBJS= \
|
||||
$(LIB_OBJ_DIR)/bitbuf.o \
|
||||
$(LIB_OBJ_DIR)/byteswap.o \
|
||||
$(LIB_OBJ_DIR)/characterset.o \
|
||||
$(LIB_OBJ_DIR)/checksum_crc.o \
|
||||
$(LIB_OBJ_DIR)/checksum_md5.o \
|
||||
$(LIB_OBJ_DIR)/commandbuffer.o \
|
||||
$(LIB_OBJ_DIR)/convar.o \
|
||||
$(LIB_OBJ_DIR)/datamanager.o \
|
||||
$(LIB_OBJ_DIR)/diff.o \
|
||||
$(LIB_OBJ_DIR)/generichash.o \
|
||||
$(LIB_OBJ_DIR)/interface.o \
|
||||
$(LIB_OBJ_DIR)/KeyValues.o \
|
||||
$(LIB_OBJ_DIR)/mempool.o \
|
||||
$(LIB_OBJ_DIR)/memstack.o \
|
||||
$(LIB_OBJ_DIR)/NetAdr.o \
|
||||
$(LIB_OBJ_DIR)/newbitbuf.o \
|
||||
$(LIB_OBJ_DIR)/processor_detect.o \
|
||||
$(LIB_OBJ_DIR)/rangecheckedvar.o \
|
||||
$(LIB_OBJ_DIR)/stringpool.o \
|
||||
$(LIB_OBJ_DIR)/strtools.o \
|
||||
$(LIB_OBJ_DIR)/tier1.o \
|
||||
$(LIB_OBJ_DIR)/tokenreader.o \
|
||||
$(LIB_OBJ_DIR)/undiff.o \
|
||||
$(LIB_OBJ_DIR)/uniqueid.o \
|
||||
$(LIB_OBJ_DIR)/utlbuffer.o \
|
||||
$(LIB_OBJ_DIR)/utlbufferutil.o \
|
||||
$(LIB_OBJ_DIR)/utlstring.o \
|
||||
$(LIB_OBJ_DIR)/utlsymbol.o \
|
||||
|
||||
all: dirs $(NAME)_$(ARCH).$(SHLIBEXT)
|
||||
|
||||
dirs:
|
||||
-mkdir -p $(BUILD_OBJ_DIR)
|
||||
-mkdir -p $(LIB_OBJ_DIR)
|
||||
|
||||
$(NAME)_$(ARCH).$(SHLIBEXT): $(LIB_OBJS)
|
||||
$(AR) $(LIB_DIR)/$@ $(LIB_OBJS)
|
||||
|
||||
$(LIB_OBJ_DIR)/%.o: $(LIB_SRC_DIR)/%.cpp
|
||||
$(DO_CC)
|
||||
|
||||
install:
|
||||
cp -f $(NAME)_$(ARCH).$(SHLIBEXT) $(LIB_DIR)/$(NAME)_$(ARCH).$(SHLIBEXT)
|
||||
|
||||
clean:
|
||||
-rm -rf $(LIB_OBJ_DIR)
|
||||
|
50
linux_sdk/Makefile.vcpm
Normal file
50
linux_sdk/Makefile.vcpm
Normal file
@ -0,0 +1,50 @@
|
||||
#
|
||||
# VCProject file to Makefile converter
|
||||
#
|
||||
# November 2004, alfred@valvesoftware.com
|
||||
#
|
||||
|
||||
VCPM_SRC_DIR = $(SRC_DIR)/utils/vprojtomake
|
||||
PUBLIC_SRC_DIR = $(SRC_DIR)/public
|
||||
TIER0_PUBLIC_SRC_DIR = $(SRC_DIR)/public/tier0
|
||||
TIER1_PUBLIC_SRC_DIR = $(SRC_DIR)/public/tier1
|
||||
UTIL_COMMON_SRC_DIR = $(SRC_DIR)/utils/common
|
||||
|
||||
VCPM_OBJ_DIR = $(BUILD_OBJ_DIR)/vcpm
|
||||
|
||||
INCLUDEDIRS = -I$(PUBLIC_SRC_DIR) -I$(XERCES_INC_DIR) -I$(TIER0_PUBLIC_SRC_DIR) -I$(TIER1_PUBLIC_SRC_DIR) -I$(UTIL_COMMON_SRC_DIR)
|
||||
LDFLAGS_VC = -lm -ldl -L$(XERCES_LIB_DIR) -lxerces-c tier0_i486.so vstdlib_i486.so $(LIB_DIR)/tier1_i486.a
|
||||
|
||||
DO_CC = $(CPLUS) $(INCLUDEDIRS) -DARCH=$(ARCH)
|
||||
|
||||
ifeq "$(DEBUG)" "true"
|
||||
DO_CC += $(DBG_DEFINES) $(DBG_CFLAGS)
|
||||
else
|
||||
DO_CC += -DNDEBUG $(CFLAGS)
|
||||
endif
|
||||
|
||||
DO_CC += -o $@ -c $<
|
||||
|
||||
#####################################################################
|
||||
|
||||
VCPM_OBJS = \
|
||||
$(VCPM_OBJ_DIR)/makefilecreator.o \
|
||||
$(VCPM_OBJ_DIR)/vprojtomake.o \
|
||||
$(VCPM_OBJ_DIR)/vcprojconvert.o \
|
||||
|
||||
all: dirs vcpm
|
||||
|
||||
dirs:
|
||||
-mkdir -p $(BUILD_OBJ_DIR)
|
||||
-mkdir -p $(VCPM_OBJ_DIR)
|
||||
|
||||
vcpm: $(VCPM_OBJS)
|
||||
$(CLINK) -m32 -o $(BUILD_DIR)/$@ $(VCPM_OBJS) $(CPP_LIB) $(LDFLAGS_VC)
|
||||
|
||||
$(VCPM_OBJ_DIR)/%.o: $(VCPM_SRC_DIR)/%.cpp
|
||||
$(DO_CC)
|
||||
|
||||
clean:
|
||||
-rm -rf $(VCPM_OBJ_DIR)
|
||||
-rm -f vcpm
|
||||
|
193
mathlib/3dnow.cpp
Normal file
193
mathlib/3dnow.cpp
Normal file
@ -0,0 +1,193 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: 3DNow Math primitives.
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#include <math.h>
|
||||
#include <float.h> // Needed for FLT_EPSILON
|
||||
#include "basetypes.h"
|
||||
#include <memory.h>
|
||||
#include "tier0/dbg.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
#include "mathlib/amd3dx.h"
|
||||
#include "mathlib/vector.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4244) // "conversion from 'const int' to 'float', possible loss of data"
|
||||
#pragma warning(disable:4730) // "mixing _m64 and floating point expressions may result in incorrect code"
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 3D Now Implementations of optimized routines:
|
||||
//-----------------------------------------------------------------------------
|
||||
float _3DNow_Sqrt(float x)
|
||||
{
|
||||
Assert( s_bMathlibInitialized );
|
||||
float root = 0.f;
|
||||
#ifdef _WIN32
|
||||
_asm
|
||||
{
|
||||
femms
|
||||
movd mm0, x
|
||||
PFRSQRT (mm1,mm0)
|
||||
punpckldq mm0, mm0
|
||||
PFMUL (mm0, mm1)
|
||||
movd root, mm0
|
||||
femms
|
||||
}
|
||||
#elif defined _LINUX || defined __APPLE__
|
||||
__asm __volatile__( "femms" );
|
||||
__asm __volatile__
|
||||
(
|
||||
"pfrsqrt %y0, %y1 \n\t"
|
||||
"punpckldq %y1, %y1 \n\t"
|
||||
"pfmul %y1, %y0 \n\t"
|
||||
: "=y" (root), "=y" (x)
|
||||
:"0" (x)
|
||||
);
|
||||
__asm __volatile__( "femms" );
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
// NJS FIXME: Need to test Recripricol squareroot performance and accuraccy
|
||||
// on AMD's before using the specialized instruction.
|
||||
float _3DNow_RSqrt(float x)
|
||||
{
|
||||
Assert( s_bMathlibInitialized );
|
||||
|
||||
return 1.f / _3DNow_Sqrt(x);
|
||||
}
|
||||
|
||||
|
||||
float FASTCALL _3DNow_VectorNormalize (Vector& vec)
|
||||
{
|
||||
Assert( s_bMathlibInitialized );
|
||||
float *v = &vec[0];
|
||||
float radius = 0.f;
|
||||
|
||||
if ( v[0] || v[1] || v[2] )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
_asm
|
||||
{
|
||||
mov eax, v
|
||||
femms
|
||||
movq mm0, QWORD PTR [eax]
|
||||
movd mm1, DWORD PTR [eax+8]
|
||||
movq mm2, mm0
|
||||
movq mm3, mm1
|
||||
PFMUL (mm0, mm0)
|
||||
PFMUL (mm1, mm1)
|
||||
PFACC (mm0, mm0)
|
||||
PFADD (mm1, mm0)
|
||||
PFRSQRT (mm0, mm1)
|
||||
punpckldq mm1, mm1
|
||||
PFMUL (mm1, mm0)
|
||||
PFMUL (mm2, mm0)
|
||||
PFMUL (mm3, mm0)
|
||||
movq QWORD PTR [eax], mm2
|
||||
movd DWORD PTR [eax+8], mm3
|
||||
movd radius, mm1
|
||||
femms
|
||||
}
|
||||
#elif defined _LINUX || defined __APPLE__
|
||||
long long a,c;
|
||||
int b,d;
|
||||
memcpy(&a,&vec[0],sizeof(a));
|
||||
memcpy(&b,&vec[2],sizeof(b));
|
||||
memcpy(&c,&vec[0],sizeof(c));
|
||||
memcpy(&d,&vec[2],sizeof(d));
|
||||
|
||||
__asm __volatile__( "femms" );
|
||||
__asm __volatile__
|
||||
(
|
||||
"pfmul %y3, %y3\n\t"
|
||||
"pfmul %y0, %y0 \n\t"
|
||||
"pfacc %y3, %y3 \n\t"
|
||||
"pfadd %y3, %y0 \n\t"
|
||||
"pfrsqrt %y0, %y3 \n\t"
|
||||
"punpckldq %y0, %y0 \n\t"
|
||||
"pfmul %y3, %y0 \n\t"
|
||||
"pfmul %y3, %y2 \n\t"
|
||||
"pfmul %y3, %y1 \n\t"
|
||||
: "=y" (radius), "=y" (c), "=y" (d)
|
||||
: "y" (a), "0" (b), "1" (c), "2" (d)
|
||||
);
|
||||
memcpy(&vec[0],&c,sizeof(c));
|
||||
memcpy(&vec[2],&d,sizeof(d));
|
||||
__asm __volatile__( "femms" );
|
||||
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
}
|
||||
return radius;
|
||||
}
|
||||
|
||||
|
||||
void FASTCALL _3DNow_VectorNormalizeFast (Vector& vec)
|
||||
{
|
||||
_3DNow_VectorNormalize( vec );
|
||||
}
|
||||
|
||||
|
||||
// JAY: This complains with the latest processor pack
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable: 4730)
|
||||
#endif
|
||||
|
||||
float _3DNow_InvRSquared(const float* v)
|
||||
{
|
||||
Assert( s_bMathlibInitialized );
|
||||
float r2 = 1.f;
|
||||
#ifdef _WIN32
|
||||
_asm { // AMD 3DNow only routine
|
||||
mov eax, v
|
||||
femms
|
||||
movq mm0, QWORD PTR [eax]
|
||||
movd mm1, DWORD PTR [eax+8]
|
||||
movd mm2, [r2]
|
||||
PFMUL (mm0, mm0)
|
||||
PFMUL (mm1, mm1)
|
||||
PFACC (mm0, mm0)
|
||||
PFADD (mm1, mm0)
|
||||
PFMAX (mm1, mm2)
|
||||
PFRCP (mm0, mm1)
|
||||
movd [r2], mm0
|
||||
femms
|
||||
}
|
||||
#elif defined _LINUX || defined __APPLE__
|
||||
long long a,c;
|
||||
int b;
|
||||
memcpy(&a,&v[0],sizeof(a));
|
||||
memcpy(&b,&v[2],sizeof(b));
|
||||
memcpy(&c,&v[0],sizeof(c));
|
||||
|
||||
__asm __volatile__( "femms" );
|
||||
__asm __volatile__
|
||||
(
|
||||
"PFMUL %y2, %y2 \n\t"
|
||||
"PFMUL %y3, %y3 \n\t"
|
||||
"PFACC %y2, %y2 \n\t"
|
||||
"PFADD %y2, %y3 \n\t"
|
||||
"PFMAX %y3, %y4 \n\t"
|
||||
"PFRCP %y3, %y2 \n\t"
|
||||
"movq %y2, %y0 \n\t"
|
||||
: "=y" (r2)
|
||||
: "0" (r2), "y" (a), "y" (b), "y" (c)
|
||||
);
|
||||
__asm __volatile__( "femms" );
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
|
||||
return r2;
|
||||
}
|
16
mathlib/3dnow.h
Normal file
16
mathlib/3dnow.h
Normal file
@ -0,0 +1,16 @@
|
||||
//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#ifndef _3DNOW_H
|
||||
#define _3DNOW_H
|
||||
|
||||
float _3DNow_Sqrt(float x);
|
||||
float _3DNow_RSqrt(float x);
|
||||
float FASTCALL _3DNow_VectorNormalize (Vector& vec);
|
||||
void FASTCALL _3DNow_VectorNormalizeFast (Vector& vec);
|
||||
float _3DNow_InvRSquared(const float* v);
|
||||
|
||||
#endif // _3DNOW_H
|
394
mathlib/IceKey.cpp
Normal file
394
mathlib/IceKey.cpp
Normal file
@ -0,0 +1,394 @@
|
||||
// Purpose: C++ implementation of the ICE encryption algorithm.
|
||||
// Taken from public domain code, as written by Matthew Kwan - July 1996
|
||||
// http://www.darkside.com.au/ice/
|
||||
|
||||
#if !defined(_STATIC_LINKED) || defined(_SHARED_LIB)
|
||||
|
||||
#include "mathlib/IceKey.H"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable: 4244)
|
||||
#endif
|
||||
|
||||
/* Structure of a single round subkey */
|
||||
class IceSubkey {
|
||||
public:
|
||||
unsigned long val[3];
|
||||
};
|
||||
|
||||
|
||||
/* The S-boxes */
|
||||
static unsigned long ice_sbox[4][1024];
|
||||
static int ice_sboxes_initialised = 0;
|
||||
|
||||
|
||||
/* Modulo values for the S-boxes */
|
||||
static const int ice_smod[4][4] = {
|
||||
{333, 313, 505, 369},
|
||||
{379, 375, 319, 391},
|
||||
{361, 445, 451, 397},
|
||||
{397, 425, 395, 505}};
|
||||
|
||||
/* XOR values for the S-boxes */
|
||||
static const int ice_sxor[4][4] = {
|
||||
{0x83, 0x85, 0x9b, 0xcd},
|
||||
{0xcc, 0xa7, 0xad, 0x41},
|
||||
{0x4b, 0x2e, 0xd4, 0x33},
|
||||
{0xea, 0xcb, 0x2e, 0x04}};
|
||||
|
||||
/* Permutation values for the P-box */
|
||||
static const unsigned long ice_pbox[32] = {
|
||||
0x00000001, 0x00000080, 0x00000400, 0x00002000,
|
||||
0x00080000, 0x00200000, 0x01000000, 0x40000000,
|
||||
0x00000008, 0x00000020, 0x00000100, 0x00004000,
|
||||
0x00010000, 0x00800000, 0x04000000, 0x20000000,
|
||||
0x00000004, 0x00000010, 0x00000200, 0x00008000,
|
||||
0x00020000, 0x00400000, 0x08000000, 0x10000000,
|
||||
0x00000002, 0x00000040, 0x00000800, 0x00001000,
|
||||
0x00040000, 0x00100000, 0x02000000, 0x80000000};
|
||||
|
||||
/* The key rotation schedule */
|
||||
static const int ice_keyrot[16] = {
|
||||
0, 1, 2, 3, 2, 1, 3, 0,
|
||||
1, 3, 2, 0, 3, 1, 0, 2};
|
||||
|
||||
|
||||
/*
|
||||
* 8-bit Galois Field multiplication of a by b, modulo m.
|
||||
* Just like arithmetic multiplication, except that additions and
|
||||
* subtractions are replaced by XOR.
|
||||
*/
|
||||
|
||||
static unsigned int
|
||||
gf_mult (
|
||||
register unsigned int a,
|
||||
register unsigned int b,
|
||||
register unsigned int m
|
||||
) {
|
||||
register unsigned int res = 0;
|
||||
|
||||
while (b) {
|
||||
if (b & 1)
|
||||
res ^= a;
|
||||
|
||||
a <<= 1;
|
||||
b >>= 1;
|
||||
|
||||
if (a >= 256)
|
||||
a ^= m;
|
||||
}
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Galois Field exponentiation.
|
||||
* Raise the base to the power of 7, modulo m.
|
||||
*/
|
||||
|
||||
static unsigned long
|
||||
gf_exp7 (
|
||||
register unsigned int b,
|
||||
unsigned int m
|
||||
) {
|
||||
register unsigned int x;
|
||||
|
||||
if (b == 0)
|
||||
return (0);
|
||||
|
||||
x = gf_mult (b, b, m);
|
||||
x = gf_mult (b, x, m);
|
||||
x = gf_mult (x, x, m);
|
||||
return (gf_mult (b, x, m));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Carry out the ICE 32-bit P-box permutation.
|
||||
*/
|
||||
|
||||
static unsigned long
|
||||
ice_perm32 (
|
||||
register unsigned long x
|
||||
) {
|
||||
register unsigned long res = 0;
|
||||
register const unsigned long *pbox = ice_pbox;
|
||||
|
||||
while (x) {
|
||||
if (x & 1)
|
||||
res |= *pbox;
|
||||
pbox++;
|
||||
x >>= 1;
|
||||
}
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialise the ICE S-boxes.
|
||||
* This only has to be done once.
|
||||
*/
|
||||
|
||||
static void
|
||||
ice_sboxes_init (void)
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i=0; i<1024; i++) {
|
||||
int col = (i >> 1) & 0xff;
|
||||
int row = (i & 0x1) | ((i & 0x200) >> 8);
|
||||
unsigned long x;
|
||||
|
||||
x = gf_exp7 (col ^ ice_sxor[0][row], ice_smod[0][row]) << 24;
|
||||
ice_sbox[0][i] = ice_perm32 (x);
|
||||
|
||||
x = gf_exp7 (col ^ ice_sxor[1][row], ice_smod[1][row]) << 16;
|
||||
ice_sbox[1][i] = ice_perm32 (x);
|
||||
|
||||
x = gf_exp7 (col ^ ice_sxor[2][row], ice_smod[2][row]) << 8;
|
||||
ice_sbox[2][i] = ice_perm32 (x);
|
||||
|
||||
x = gf_exp7 (col ^ ice_sxor[3][row], ice_smod[3][row]);
|
||||
ice_sbox[3][i] = ice_perm32 (x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create a new ICE key.
|
||||
*/
|
||||
|
||||
IceKey::IceKey (int n)
|
||||
{
|
||||
if (!ice_sboxes_initialised) {
|
||||
ice_sboxes_init ();
|
||||
ice_sboxes_initialised = 1;
|
||||
}
|
||||
|
||||
if (n < 1) {
|
||||
_size = 1;
|
||||
_rounds = 8;
|
||||
} else {
|
||||
_size = n;
|
||||
_rounds = n * 16;
|
||||
}
|
||||
|
||||
_keysched = new IceSubkey[_rounds];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Destroy an ICE key.
|
||||
*/
|
||||
|
||||
IceKey::~IceKey ()
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i=0; i<_rounds; i++)
|
||||
for (j=0; j<3; j++)
|
||||
_keysched[i].val[j] = 0;
|
||||
|
||||
_rounds = _size = 0;
|
||||
|
||||
delete[] _keysched;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The single round ICE f function.
|
||||
*/
|
||||
|
||||
static unsigned long
|
||||
ice_f (
|
||||
register unsigned long p,
|
||||
const IceSubkey *sk
|
||||
) {
|
||||
unsigned long tl, tr; /* Expanded 40-bit values */
|
||||
unsigned long al, ar; /* Salted expanded 40-bit values */
|
||||
|
||||
/* Left half expansion */
|
||||
tl = ((p >> 16) & 0x3ff) | (((p >> 14) | (p << 18)) & 0xffc00);
|
||||
|
||||
/* Right half expansion */
|
||||
tr = (p & 0x3ff) | ((p << 2) & 0xffc00);
|
||||
|
||||
/* Perform the salt permutation */
|
||||
// al = (tr & sk->val[2]) | (tl & ~sk->val[2]);
|
||||
// ar = (tl & sk->val[2]) | (tr & ~sk->val[2]);
|
||||
al = sk->val[2] & (tl ^ tr);
|
||||
ar = al ^ tr;
|
||||
al ^= tl;
|
||||
|
||||
al ^= sk->val[0]; /* XOR with the subkey */
|
||||
ar ^= sk->val[1];
|
||||
|
||||
/* S-box lookup and permutation */
|
||||
return (ice_sbox[0][al >> 10] | ice_sbox[1][al & 0x3ff]
|
||||
| ice_sbox[2][ar >> 10] | ice_sbox[3][ar & 0x3ff]);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Encrypt a block of 8 bytes of data with the given ICE key.
|
||||
*/
|
||||
|
||||
void
|
||||
IceKey::encrypt (
|
||||
const unsigned char *ptext,
|
||||
unsigned char *ctext
|
||||
) const
|
||||
{
|
||||
register int i;
|
||||
register unsigned long l, r;
|
||||
|
||||
l = (((unsigned long) ptext[0]) << 24)
|
||||
| (((unsigned long) ptext[1]) << 16)
|
||||
| (((unsigned long) ptext[2]) << 8) | ptext[3];
|
||||
r = (((unsigned long) ptext[4]) << 24)
|
||||
| (((unsigned long) ptext[5]) << 16)
|
||||
| (((unsigned long) ptext[6]) << 8) | ptext[7];
|
||||
|
||||
for (i = 0; i < _rounds; i += 2) {
|
||||
l ^= ice_f (r, &_keysched[i]);
|
||||
r ^= ice_f (l, &_keysched[i + 1]);
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
ctext[3 - i] = r & 0xff;
|
||||
ctext[7 - i] = l & 0xff;
|
||||
|
||||
r >>= 8;
|
||||
l >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Decrypt a block of 8 bytes of data with the given ICE key.
|
||||
*/
|
||||
|
||||
void
|
||||
IceKey::decrypt (
|
||||
const unsigned char *ctext,
|
||||
unsigned char *ptext
|
||||
) const
|
||||
{
|
||||
register int i;
|
||||
register unsigned long l, r;
|
||||
|
||||
l = (((unsigned long) ctext[0]) << 24)
|
||||
| (((unsigned long) ctext[1]) << 16)
|
||||
| (((unsigned long) ctext[2]) << 8) | ctext[3];
|
||||
r = (((unsigned long) ctext[4]) << 24)
|
||||
| (((unsigned long) ctext[5]) << 16)
|
||||
| (((unsigned long) ctext[6]) << 8) | ctext[7];
|
||||
|
||||
for (i = _rounds - 1; i > 0; i -= 2) {
|
||||
l ^= ice_f (r, &_keysched[i]);
|
||||
r ^= ice_f (l, &_keysched[i - 1]);
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
ptext[3 - i] = r & 0xff;
|
||||
ptext[7 - i] = l & 0xff;
|
||||
|
||||
r >>= 8;
|
||||
l >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set 8 rounds [n, n+7] of the key schedule of an ICE key.
|
||||
*/
|
||||
|
||||
void
|
||||
IceKey::scheduleBuild (
|
||||
unsigned short *kb,
|
||||
int n,
|
||||
const int *keyrot
|
||||
) {
|
||||
int i;
|
||||
|
||||
for (i=0; i<8; i++) {
|
||||
register int j;
|
||||
register int kr = keyrot[i];
|
||||
IceSubkey *isk = &_keysched[n + i];
|
||||
|
||||
for (j=0; j<3; j++)
|
||||
isk->val[j] = 0;
|
||||
|
||||
for (j=0; j<15; j++) {
|
||||
register int k;
|
||||
unsigned long *curr_sk = &isk->val[j % 3];
|
||||
|
||||
for (k=0; k<4; k++) {
|
||||
unsigned short *curr_kb = &kb[(kr + k) & 3];
|
||||
register int bit = *curr_kb & 1;
|
||||
|
||||
*curr_sk = (*curr_sk << 1) | bit;
|
||||
*curr_kb = (*curr_kb >> 1) | ((bit ^ 1) << 15);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the key schedule of an ICE key.
|
||||
*/
|
||||
|
||||
void
|
||||
IceKey::set (
|
||||
const unsigned char *key
|
||||
) {
|
||||
int i;
|
||||
|
||||
if (_rounds == 8) {
|
||||
unsigned short kb[4];
|
||||
|
||||
for (i=0; i<4; i++)
|
||||
kb[3 - i] = (key[i*2] << 8) | key[i*2 + 1];
|
||||
|
||||
scheduleBuild (kb, 0, ice_keyrot);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i=0; i<_size; i++) {
|
||||
int j;
|
||||
unsigned short kb[4];
|
||||
|
||||
for (j=0; j<4; j++)
|
||||
kb[3 - j] = (key[i*8 + j*2] << 8) | key[i*8 + j*2 + 1];
|
||||
|
||||
scheduleBuild (kb, i*8, ice_keyrot);
|
||||
scheduleBuild (kb, _rounds - 8 - i*8, &ice_keyrot[8]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return the key size, in bytes.
|
||||
*/
|
||||
|
||||
int
|
||||
IceKey::keySize () const
|
||||
{
|
||||
return (_size * 8);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return the block size, in bytes.
|
||||
*/
|
||||
|
||||
int
|
||||
IceKey::blockSize () const
|
||||
{
|
||||
return (8);
|
||||
}
|
||||
|
||||
#endif // !_STATIC_LINKED || _SHARED_LIB
|
181
mathlib/anorms.cpp
Normal file
181
mathlib/anorms.cpp
Normal file
@ -0,0 +1,181 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
#if !defined(_STATIC_LINKED) || defined(_SHARED_LIB)
|
||||
|
||||
|
||||
#include "mathlib/vector.h"
|
||||
#include "mathlib/anorms.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
Vector g_anorms[NUMVERTEXNORMALS] =
|
||||
{
|
||||
Vector(-0.525731, 0.000000, 0.850651),
|
||||
Vector(-0.442863, 0.238856, 0.864188),
|
||||
Vector(-0.295242, 0.000000, 0.955423),
|
||||
Vector(-0.309017, 0.500000, 0.809017),
|
||||
Vector(-0.162460, 0.262866, 0.951056),
|
||||
Vector(0.000000, 0.000000, 1.000000),
|
||||
Vector(0.000000, 0.850651, 0.525731),
|
||||
Vector(-0.147621, 0.716567, 0.681718),
|
||||
Vector(0.147621, 0.716567, 0.681718),
|
||||
Vector(0.000000, 0.525731, 0.850651),
|
||||
Vector(0.309017, 0.500000, 0.809017),
|
||||
Vector(0.525731, 0.000000, 0.850651),
|
||||
Vector(0.295242, 0.000000, 0.955423),
|
||||
Vector(0.442863, 0.238856, 0.864188),
|
||||
Vector(0.162460, 0.262866, 0.951056),
|
||||
Vector(-0.681718, 0.147621, 0.716567),
|
||||
Vector(-0.809017, 0.309017, 0.500000),
|
||||
Vector(-0.587785, 0.425325, 0.688191),
|
||||
Vector(-0.850651, 0.525731, 0.000000),
|
||||
Vector(-0.864188, 0.442863, 0.238856),
|
||||
Vector(-0.716567, 0.681718, 0.147621),
|
||||
Vector(-0.688191, 0.587785, 0.425325),
|
||||
Vector(-0.500000, 0.809017, 0.309017),
|
||||
Vector(-0.238856, 0.864188, 0.442863),
|
||||
Vector(-0.425325, 0.688191, 0.587785),
|
||||
Vector(-0.716567, 0.681718, -0.147621),
|
||||
Vector(-0.500000, 0.809017, -0.309017),
|
||||
Vector(-0.525731, 0.850651, 0.000000),
|
||||
Vector(0.000000, 0.850651, -0.525731),
|
||||
Vector(-0.238856, 0.864188, -0.442863),
|
||||
Vector(0.000000, 0.955423, -0.295242),
|
||||
Vector(-0.262866, 0.951056, -0.162460),
|
||||
Vector(0.000000, 1.000000, 0.000000),
|
||||
Vector(0.000000, 0.955423, 0.295242),
|
||||
Vector(-0.262866, 0.951056, 0.162460),
|
||||
Vector(0.238856, 0.864188, 0.442863),
|
||||
Vector(0.262866, 0.951056, 0.162460),
|
||||
Vector(0.500000, 0.809017, 0.309017),
|
||||
Vector(0.238856, 0.864188, -0.442863),
|
||||
Vector(0.262866, 0.951056, -0.162460),
|
||||
Vector(0.500000, 0.809017, -0.309017),
|
||||
Vector(0.850651, 0.525731, 0.000000),
|
||||
Vector(0.716567, 0.681718, 0.147621),
|
||||
Vector(0.716567, 0.681718, -0.147621),
|
||||
Vector(0.525731, 0.850651, 0.000000),
|
||||
Vector(0.425325, 0.688191, 0.587785),
|
||||
Vector(0.864188, 0.442863, 0.238856),
|
||||
Vector(0.688191, 0.587785, 0.425325),
|
||||
Vector(0.809017, 0.309017, 0.500000),
|
||||
Vector(0.681718, 0.147621, 0.716567),
|
||||
Vector(0.587785, 0.425325, 0.688191),
|
||||
Vector(0.955423, 0.295242, 0.000000),
|
||||
Vector(1.000000, 0.000000, 0.000000),
|
||||
Vector(0.951056, 0.162460, 0.262866),
|
||||
Vector(0.850651, -0.525731, 0.000000),
|
||||
Vector(0.955423, -0.295242, 0.000000),
|
||||
Vector(0.864188, -0.442863, 0.238856),
|
||||
Vector(0.951056, -0.162460, 0.262866),
|
||||
Vector(0.809017, -0.309017, 0.500000),
|
||||
Vector(0.681718, -0.147621, 0.716567),
|
||||
Vector(0.850651, 0.000000, 0.525731),
|
||||
Vector(0.864188, 0.442863, -0.238856),
|
||||
Vector(0.809017, 0.309017, -0.500000),
|
||||
Vector(0.951056, 0.162460, -0.262866),
|
||||
Vector(0.525731, 0.000000, -0.850651),
|
||||
Vector(0.681718, 0.147621, -0.716567),
|
||||
Vector(0.681718, -0.147621, -0.716567),
|
||||
Vector(0.850651, 0.000000, -0.525731),
|
||||
Vector(0.809017, -0.309017, -0.500000),
|
||||
Vector(0.864188, -0.442863, -0.238856),
|
||||
Vector(0.951056, -0.162460, -0.262866),
|
||||
Vector(0.147621, 0.716567, -0.681718),
|
||||
Vector(0.309017, 0.500000, -0.809017),
|
||||
Vector(0.425325, 0.688191, -0.587785),
|
||||
Vector(0.442863, 0.238856, -0.864188),
|
||||
Vector(0.587785, 0.425325, -0.688191),
|
||||
Vector(0.688191, 0.587785, -0.425325),
|
||||
Vector(-0.147621, 0.716567, -0.681718),
|
||||
Vector(-0.309017, 0.500000, -0.809017),
|
||||
Vector(0.000000, 0.525731, -0.850651),
|
||||
Vector(-0.525731, 0.000000, -0.850651),
|
||||
Vector(-0.442863, 0.238856, -0.864188),
|
||||
Vector(-0.295242, 0.000000, -0.955423),
|
||||
Vector(-0.162460, 0.262866, -0.951056),
|
||||
Vector(0.000000, 0.000000, -1.000000),
|
||||
Vector(0.295242, 0.000000, -0.955423),
|
||||
Vector(0.162460, 0.262866, -0.951056),
|
||||
Vector(-0.442863, -0.238856, -0.864188),
|
||||
Vector(-0.309017, -0.500000, -0.809017),
|
||||
Vector(-0.162460, -0.262866, -0.951056),
|
||||
Vector(0.000000, -0.850651, -0.525731),
|
||||
Vector(-0.147621, -0.716567, -0.681718),
|
||||
Vector(0.147621, -0.716567, -0.681718),
|
||||
Vector(0.000000, -0.525731, -0.850651),
|
||||
Vector(0.309017, -0.500000, -0.809017),
|
||||
Vector(0.442863, -0.238856, -0.864188),
|
||||
Vector(0.162460, -0.262866, -0.951056),
|
||||
Vector(0.238856, -0.864188, -0.442863),
|
||||
Vector(0.500000, -0.809017, -0.309017),
|
||||
Vector(0.425325, -0.688191, -0.587785),
|
||||
Vector(0.716567, -0.681718, -0.147621),
|
||||
Vector(0.688191, -0.587785, -0.425325),
|
||||
Vector(0.587785, -0.425325, -0.688191),
|
||||
Vector(0.000000, -0.955423, -0.295242),
|
||||
Vector(0.000000, -1.000000, 0.000000),
|
||||
Vector(0.262866, -0.951056, -0.162460),
|
||||
Vector(0.000000, -0.850651, 0.525731),
|
||||
Vector(0.000000, -0.955423, 0.295242),
|
||||
Vector(0.238856, -0.864188, 0.442863),
|
||||
Vector(0.262866, -0.951056, 0.162460),
|
||||
Vector(0.500000, -0.809017, 0.309017),
|
||||
Vector(0.716567, -0.681718, 0.147621),
|
||||
Vector(0.525731, -0.850651, 0.000000),
|
||||
Vector(-0.238856, -0.864188, -0.442863),
|
||||
Vector(-0.500000, -0.809017, -0.309017),
|
||||
Vector(-0.262866, -0.951056, -0.162460),
|
||||
Vector(-0.850651, -0.525731, 0.000000),
|
||||
Vector(-0.716567, -0.681718, -0.147621),
|
||||
Vector(-0.716567, -0.681718, 0.147621),
|
||||
Vector(-0.525731, -0.850651, 0.000000),
|
||||
Vector(-0.500000, -0.809017, 0.309017),
|
||||
Vector(-0.238856, -0.864188, 0.442863),
|
||||
Vector(-0.262866, -0.951056, 0.162460),
|
||||
Vector(-0.864188, -0.442863, 0.238856),
|
||||
Vector(-0.809017, -0.309017, 0.500000),
|
||||
Vector(-0.688191, -0.587785, 0.425325),
|
||||
Vector(-0.681718, -0.147621, 0.716567),
|
||||
Vector(-0.442863, -0.238856, 0.864188),
|
||||
Vector(-0.587785, -0.425325, 0.688191),
|
||||
Vector(-0.309017, -0.500000, 0.809017),
|
||||
Vector(-0.147621, -0.716567, 0.681718),
|
||||
Vector(-0.425325, -0.688191, 0.587785),
|
||||
Vector(-0.162460, -0.262866, 0.951056),
|
||||
Vector(0.442863, -0.238856, 0.864188),
|
||||
Vector(0.162460, -0.262866, 0.951056),
|
||||
Vector(0.309017, -0.500000, 0.809017),
|
||||
Vector(0.147621, -0.716567, 0.681718),
|
||||
Vector(0.000000, -0.525731, 0.850651),
|
||||
Vector(0.425325, -0.688191, 0.587785),
|
||||
Vector(0.587785, -0.425325, 0.688191),
|
||||
Vector(0.688191, -0.587785, 0.425325),
|
||||
Vector(-0.955423, 0.295242, 0.000000),
|
||||
Vector(-0.951056, 0.162460, 0.262866),
|
||||
Vector(-1.000000, 0.000000, 0.000000),
|
||||
Vector(-0.850651, 0.000000, 0.525731),
|
||||
Vector(-0.955423, -0.295242, 0.000000),
|
||||
Vector(-0.951056, -0.162460, 0.262866),
|
||||
Vector(-0.864188, 0.442863, -0.238856),
|
||||
Vector(-0.951056, 0.162460, -0.262866),
|
||||
Vector(-0.809017, 0.309017, -0.500000),
|
||||
Vector(-0.864188, -0.442863, -0.238856),
|
||||
Vector(-0.951056, -0.162460, -0.262866),
|
||||
Vector(-0.809017, -0.309017, -0.500000),
|
||||
Vector(-0.681718, 0.147621, -0.716567),
|
||||
Vector(-0.681718, -0.147621, -0.716567),
|
||||
Vector(-0.850651, 0.000000, -0.525731),
|
||||
Vector(-0.688191, 0.587785, -0.425325),
|
||||
Vector(-0.587785, 0.425325, -0.688191),
|
||||
Vector(-0.425325, 0.688191, -0.587785),
|
||||
Vector(-0.425325, -0.688191, -0.587785),
|
||||
Vector(-0.587785, -0.425325, -0.688191),
|
||||
Vector(-0.688191, -0.587785, -0.425325)
|
||||
};
|
||||
|
||||
#endif // !_STATIC_LINKED || _SHARED_LIB
|
69
mathlib/bumpvects.cpp
Normal file
69
mathlib/bumpvects.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: $
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// $Log: $
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#if !defined(_STATIC_LINKED) || defined(_SHARED_LIB)
|
||||
|
||||
|
||||
#ifdef QUIVER
|
||||
#include "r_local.h"
|
||||
#endif
|
||||
#include "mathlib/bumpvects.h"
|
||||
#include "mathlib/vector.h"
|
||||
#include <assert.h>
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
// z is coming out of the face.
|
||||
|
||||
void GetBumpNormals( const Vector& sVect, const Vector& tVect, const Vector& flatNormal,
|
||||
const Vector& phongNormal, Vector bumpNormals[NUM_BUMP_VECTS] )
|
||||
{
|
||||
Vector tmpNormal;
|
||||
bool leftHanded;
|
||||
int i;
|
||||
|
||||
assert( NUM_BUMP_VECTS == 3 );
|
||||
|
||||
// Are we left or right handed?
|
||||
CrossProduct( sVect, tVect, tmpNormal );
|
||||
if( DotProduct( flatNormal, tmpNormal ) < 0.0f )
|
||||
{
|
||||
leftHanded = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
leftHanded = false;
|
||||
}
|
||||
|
||||
// Build a basis for the face around the phong normal
|
||||
matrix3x4_t smoothBasis;
|
||||
CrossProduct( phongNormal.Base(), sVect.Base(), smoothBasis[1] );
|
||||
VectorNormalize( smoothBasis[1] );
|
||||
CrossProduct( smoothBasis[1], phongNormal.Base(), smoothBasis[0] );
|
||||
VectorNormalize( smoothBasis[0] );
|
||||
VectorCopy( phongNormal.Base(), smoothBasis[2] );
|
||||
|
||||
if( leftHanded )
|
||||
{
|
||||
VectorNegate( smoothBasis[1] );
|
||||
}
|
||||
|
||||
// move the g_localBumpBasis into world space to create bumpNormals
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
VectorIRotate( g_localBumpBasis[i], smoothBasis, bumpNormals[i] );
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !_STATIC_LINKED || _SHARED_LIB
|
645
mathlib/color_conversion.cpp
Normal file
645
mathlib/color_conversion.cpp
Normal file
@ -0,0 +1,645 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Color conversion routines.
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#include <math.h>
|
||||
#include <float.h> // Needed for FLT_EPSILON
|
||||
#include "basetypes.h"
|
||||
#include <memory.h>
|
||||
#include "tier0/dbg.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
#include "mathlib/vector.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gamma conversion support
|
||||
//-----------------------------------------------------------------------------
|
||||
static byte texgammatable[256]; // palette is sent through this to convert to screen gamma
|
||||
|
||||
static float texturetolinear[256]; // texture (0..255) to linear (0..1)
|
||||
static int lineartotexture[1024]; // linear (0..1) to texture (0..255)
|
||||
static int lineartoscreen[1024]; // linear (0..1) to gamma corrected vertex light (0..255)
|
||||
|
||||
// build a lightmap texture to combine with surface texture, adjust for src*dst+dst*src, ramp reprogramming, etc
|
||||
float lineartovertex[4096]; // linear (0..4) to screen corrected vertex space (0..1?)
|
||||
unsigned char lineartolightmap[4096]; // linear (0..4) to screen corrected texture value (0..255)
|
||||
|
||||
static float g_Mathlib_GammaToLinear[256]; // gamma (0..1) to linear (0..1)
|
||||
static float g_Mathlib_LinearToGamma[256]; // linear (0..1) to gamma (0..1)
|
||||
|
||||
// This is aligned to 16-byte boundaries so that we can load it
|
||||
// onto SIMD registers easily if needed (used by SSE version of lightmaps)
|
||||
// TODO: move this into the one DLL that actually uses it, instead of statically
|
||||
// linking it everywhere via mathlib.
|
||||
ALIGN128 float power2_n[256] = // 2**(index - 128) / 255
|
||||
{
|
||||
1.152445441982634800E-041, 2.304890883965269600E-041, 4.609781767930539200E-041, 9.219563535861078400E-041,
|
||||
1.843912707172215700E-040, 3.687825414344431300E-040, 7.375650828688862700E-040, 1.475130165737772500E-039,
|
||||
2.950260331475545100E-039, 5.900520662951090200E-039, 1.180104132590218000E-038, 2.360208265180436100E-038,
|
||||
4.720416530360872100E-038, 9.440833060721744200E-038, 1.888166612144348800E-037, 3.776333224288697700E-037,
|
||||
7.552666448577395400E-037, 1.510533289715479100E-036, 3.021066579430958200E-036, 6.042133158861916300E-036,
|
||||
1.208426631772383300E-035, 2.416853263544766500E-035, 4.833706527089533100E-035, 9.667413054179066100E-035,
|
||||
1.933482610835813200E-034, 3.866965221671626400E-034, 7.733930443343252900E-034, 1.546786088668650600E-033,
|
||||
3.093572177337301200E-033, 6.187144354674602300E-033, 1.237428870934920500E-032, 2.474857741869840900E-032,
|
||||
4.949715483739681800E-032, 9.899430967479363700E-032, 1.979886193495872700E-031, 3.959772386991745500E-031,
|
||||
7.919544773983491000E-031, 1.583908954796698200E-030, 3.167817909593396400E-030, 6.335635819186792800E-030,
|
||||
1.267127163837358600E-029, 2.534254327674717100E-029, 5.068508655349434200E-029, 1.013701731069886800E-028,
|
||||
2.027403462139773700E-028, 4.054806924279547400E-028, 8.109613848559094700E-028, 1.621922769711818900E-027,
|
||||
3.243845539423637900E-027, 6.487691078847275800E-027, 1.297538215769455200E-026, 2.595076431538910300E-026,
|
||||
5.190152863077820600E-026, 1.038030572615564100E-025, 2.076061145231128300E-025, 4.152122290462256500E-025,
|
||||
8.304244580924513000E-025, 1.660848916184902600E-024, 3.321697832369805200E-024, 6.643395664739610400E-024,
|
||||
1.328679132947922100E-023, 2.657358265895844200E-023, 5.314716531791688300E-023, 1.062943306358337700E-022,
|
||||
2.125886612716675300E-022, 4.251773225433350700E-022, 8.503546450866701300E-022, 1.700709290173340300E-021,
|
||||
3.401418580346680500E-021, 6.802837160693361100E-021, 1.360567432138672200E-020, 2.721134864277344400E-020,
|
||||
5.442269728554688800E-020, 1.088453945710937800E-019, 2.176907891421875500E-019, 4.353815782843751100E-019,
|
||||
8.707631565687502200E-019, 1.741526313137500400E-018, 3.483052626275000900E-018, 6.966105252550001700E-018,
|
||||
1.393221050510000300E-017, 2.786442101020000700E-017, 5.572884202040001400E-017, 1.114576840408000300E-016,
|
||||
2.229153680816000600E-016, 4.458307361632001100E-016, 8.916614723264002200E-016, 1.783322944652800400E-015,
|
||||
3.566645889305600900E-015, 7.133291778611201800E-015, 1.426658355722240400E-014, 2.853316711444480700E-014,
|
||||
5.706633422888961400E-014, 1.141326684577792300E-013, 2.282653369155584600E-013, 4.565306738311169100E-013,
|
||||
9.130613476622338300E-013, 1.826122695324467700E-012, 3.652245390648935300E-012, 7.304490781297870600E-012,
|
||||
1.460898156259574100E-011, 2.921796312519148200E-011, 5.843592625038296500E-011, 1.168718525007659300E-010,
|
||||
2.337437050015318600E-010, 4.674874100030637200E-010, 9.349748200061274400E-010, 1.869949640012254900E-009,
|
||||
3.739899280024509800E-009, 7.479798560049019500E-009, 1.495959712009803900E-008, 2.991919424019607800E-008,
|
||||
5.983838848039215600E-008, 1.196767769607843100E-007, 2.393535539215686200E-007, 4.787071078431372500E-007,
|
||||
9.574142156862745000E-007, 1.914828431372549000E-006, 3.829656862745098000E-006, 7.659313725490196000E-006,
|
||||
1.531862745098039200E-005, 3.063725490196078400E-005, 6.127450980392156800E-005, 1.225490196078431400E-004,
|
||||
2.450980392156862700E-004, 4.901960784313725400E-004, 9.803921568627450800E-004, 1.960784313725490200E-003,
|
||||
3.921568627450980300E-003, 7.843137254901960700E-003, 1.568627450980392100E-002, 3.137254901960784300E-002,
|
||||
6.274509803921568500E-002, 1.254901960784313700E-001, 2.509803921568627400E-001, 5.019607843137254800E-001,
|
||||
1.003921568627451000E+000, 2.007843137254901900E+000, 4.015686274509803900E+000, 8.031372549019607700E+000,
|
||||
1.606274509803921500E+001, 3.212549019607843100E+001, 6.425098039215686200E+001, 1.285019607843137200E+002,
|
||||
2.570039215686274500E+002, 5.140078431372548900E+002, 1.028015686274509800E+003, 2.056031372549019600E+003,
|
||||
4.112062745098039200E+003, 8.224125490196078300E+003, 1.644825098039215700E+004, 3.289650196078431300E+004,
|
||||
6.579300392156862700E+004, 1.315860078431372500E+005, 2.631720156862745100E+005, 5.263440313725490100E+005,
|
||||
1.052688062745098000E+006, 2.105376125490196000E+006, 4.210752250980392100E+006, 8.421504501960784200E+006,
|
||||
1.684300900392156800E+007, 3.368601800784313700E+007, 6.737203601568627400E+007, 1.347440720313725500E+008,
|
||||
2.694881440627450900E+008, 5.389762881254901900E+008, 1.077952576250980400E+009, 2.155905152501960800E+009,
|
||||
4.311810305003921500E+009, 8.623620610007843000E+009, 1.724724122001568600E+010, 3.449448244003137200E+010,
|
||||
6.898896488006274400E+010, 1.379779297601254900E+011, 2.759558595202509800E+011, 5.519117190405019500E+011,
|
||||
1.103823438081003900E+012, 2.207646876162007800E+012, 4.415293752324015600E+012, 8.830587504648031200E+012,
|
||||
1.766117500929606200E+013, 3.532235001859212500E+013, 7.064470003718425000E+013, 1.412894000743685000E+014,
|
||||
2.825788001487370000E+014, 5.651576002974740000E+014, 1.130315200594948000E+015, 2.260630401189896000E+015,
|
||||
4.521260802379792000E+015, 9.042521604759584000E+015, 1.808504320951916800E+016, 3.617008641903833600E+016,
|
||||
7.234017283807667200E+016, 1.446803456761533400E+017, 2.893606913523066900E+017, 5.787213827046133800E+017,
|
||||
1.157442765409226800E+018, 2.314885530818453500E+018, 4.629771061636907000E+018, 9.259542123273814000E+018,
|
||||
1.851908424654762800E+019, 3.703816849309525600E+019, 7.407633698619051200E+019, 1.481526739723810200E+020,
|
||||
2.963053479447620500E+020, 5.926106958895241000E+020, 1.185221391779048200E+021, 2.370442783558096400E+021,
|
||||
4.740885567116192800E+021, 9.481771134232385600E+021, 1.896354226846477100E+022, 3.792708453692954200E+022,
|
||||
7.585416907385908400E+022, 1.517083381477181700E+023, 3.034166762954363400E+023, 6.068333525908726800E+023,
|
||||
1.213666705181745400E+024, 2.427333410363490700E+024, 4.854666820726981400E+024, 9.709333641453962800E+024,
|
||||
1.941866728290792600E+025, 3.883733456581585100E+025, 7.767466913163170200E+025, 1.553493382632634000E+026,
|
||||
3.106986765265268100E+026, 6.213973530530536200E+026, 1.242794706106107200E+027, 2.485589412212214500E+027,
|
||||
4.971178824424429000E+027, 9.942357648848857900E+027, 1.988471529769771600E+028, 3.976943059539543200E+028,
|
||||
7.953886119079086300E+028, 1.590777223815817300E+029, 3.181554447631634500E+029, 6.363108895263269100E+029,
|
||||
1.272621779052653800E+030, 2.545243558105307600E+030, 5.090487116210615300E+030, 1.018097423242123100E+031,
|
||||
2.036194846484246100E+031, 4.072389692968492200E+031, 8.144779385936984400E+031, 1.628955877187396900E+032,
|
||||
3.257911754374793800E+032, 6.515823508749587500E+032, 1.303164701749917500E+033, 2.606329403499835000E+033,
|
||||
5.212658806999670000E+033, 1.042531761399934000E+034, 2.085063522799868000E+034, 4.170127045599736000E+034,
|
||||
8.340254091199472000E+034, 1.668050818239894400E+035, 3.336101636479788800E+035, 6.672203272959577600E+035
|
||||
};
|
||||
|
||||
// You can use this to double check the exponent table and assert that
|
||||
// the precomputation is correct.
|
||||
#ifdef DBGFLAG_ASSERT
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning( disable : 4189 ) // disable unused local variable warning
|
||||
#endif
|
||||
#ifdef __GNUC__
|
||||
__attribute__((unused)) static void CheckExponentTable()
|
||||
#else
|
||||
static void CheckExponentTable()
|
||||
#endif
|
||||
{
|
||||
for( int i = 0; i < 256; i++ )
|
||||
{
|
||||
float testAgainst = pow( 2.0f, i - 128 ) / 255.0f;
|
||||
float diff = testAgainst - power2_n[i] ;
|
||||
float relativeDiff = diff / testAgainst;
|
||||
Assert( sizeof(relativeDiff) > 0 && testAgainst == 0 ?
|
||||
power2_n[i] < 1.16E-041 :
|
||||
power2_n[i] == testAgainst );
|
||||
}
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void BuildGammaTable( float gamma, float texGamma, float brightness, int overbright )
|
||||
{
|
||||
int i, inf;
|
||||
float g1, g3;
|
||||
|
||||
// Con_Printf("BuildGammaTable %.1f %.1f %.1f\n", g, v_lightgamma.GetFloat(), v_texgamma.GetFloat() );
|
||||
|
||||
float g = gamma;
|
||||
if (g > 3.0)
|
||||
{
|
||||
g = 3.0;
|
||||
}
|
||||
|
||||
g = 1.0 / g;
|
||||
g1 = texGamma * g;
|
||||
|
||||
if (brightness <= 0.0)
|
||||
{
|
||||
g3 = 0.125;
|
||||
}
|
||||
else if (brightness > 1.0)
|
||||
{
|
||||
g3 = 0.05;
|
||||
}
|
||||
else
|
||||
{
|
||||
g3 = 0.125 - (brightness * brightness) * 0.075;
|
||||
}
|
||||
|
||||
for (i=0 ; i<256 ; i++)
|
||||
{
|
||||
inf = static_cast<int>(255 * pow ( i/255.f, g1 ));
|
||||
if (inf < 0)
|
||||
inf = 0;
|
||||
if (inf > 255)
|
||||
inf = 255;
|
||||
texgammatable[i] = inf;
|
||||
}
|
||||
|
||||
for (i=0 ; i<1024 ; i++)
|
||||
{
|
||||
float f;
|
||||
|
||||
f = i / 1023.0;
|
||||
|
||||
// scale up
|
||||
if (brightness > 1.0)
|
||||
f = f * brightness;
|
||||
|
||||
// shift up
|
||||
if (f <= g3)
|
||||
f = (f / g3) * 0.125;
|
||||
else
|
||||
f = 0.125 + ((f - g3) / (1.0 - g3)) * 0.875;
|
||||
|
||||
// convert linear space to desired gamma space
|
||||
inf = static_cast<int>(255 * pow ( f, g ));
|
||||
|
||||
if (inf < 0)
|
||||
inf = 0;
|
||||
if (inf > 255)
|
||||
inf = 255;
|
||||
lineartoscreen[i] = inf;
|
||||
}
|
||||
|
||||
/*
|
||||
for (i=0 ; i<1024 ; i++)
|
||||
{
|
||||
// convert from screen gamma space to linear space
|
||||
lineargammatable[i] = 1023 * pow ( i/1023.0, v_gamma.GetFloat() );
|
||||
// convert from linear gamma space to screen space
|
||||
screengammatable[i] = 1023 * pow ( i/1023.0, 1.0 / v_gamma.GetFloat() );
|
||||
}
|
||||
*/
|
||||
|
||||
for (i=0 ; i<256 ; i++)
|
||||
{
|
||||
// convert from nonlinear texture space (0..255) to linear space (0..1)
|
||||
texturetolinear[i] = pow( i / 255.f, texGamma );
|
||||
|
||||
// convert from linear space (0..1) to nonlinear (sRGB) space (0..1)
|
||||
g_Mathlib_LinearToGamma[i] = LinearToGammaFullRange( i / 255.f );
|
||||
|
||||
// convert from sRGB gamma space (0..1) to linear space (0..1)
|
||||
g_Mathlib_GammaToLinear[i] = GammaToLinearFullRange( i / 255.f );
|
||||
}
|
||||
|
||||
for (i=0 ; i<1024 ; i++)
|
||||
{
|
||||
// convert from linear space (0..1) to nonlinear texture space (0..255)
|
||||
lineartotexture[i] = static_cast<int>(pow( i / 1023.0, 1.0 / texGamma ) * 255);
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (i=0 ; i<256 ; i++)
|
||||
{
|
||||
float f;
|
||||
|
||||
// convert from nonlinear lightmap space (0..255) to linear space (0..4)
|
||||
// f = (i / 255.0) * sqrt( 4 );
|
||||
f = i * (2.0 / 255.0);
|
||||
f = f * f;
|
||||
|
||||
texlighttolinear[i] = f;
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
float f;
|
||||
float overbrightFactor = 1.0f;
|
||||
|
||||
// Can't do overbright without texcombine
|
||||
// UNDONE: Add GAMMA ramp to rectify this
|
||||
if ( overbright == 2 )
|
||||
{
|
||||
overbrightFactor = 0.5;
|
||||
}
|
||||
else if ( overbright == 4 )
|
||||
{
|
||||
overbrightFactor = 0.25;
|
||||
}
|
||||
|
||||
for (i=0 ; i<4096 ; i++)
|
||||
{
|
||||
// convert from linear 0..4 (x1024) to screen corrected vertex space (0..1?)
|
||||
f = pow ( i/1024.0, 1.0 / gamma );
|
||||
|
||||
lineartovertex[i] = f * overbrightFactor;
|
||||
if (lineartovertex[i] > 1)
|
||||
lineartovertex[i] = 1;
|
||||
|
||||
int nLightmap = RoundFloatToInt( f * 255 * overbrightFactor );
|
||||
nLightmap = clamp( nLightmap, 0, 255 );
|
||||
lineartolightmap[i] = (unsigned char)nLightmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float GammaToLinearFullRange( float gamma )
|
||||
{
|
||||
return pow( gamma, 2.2f );
|
||||
}
|
||||
|
||||
float LinearToGammaFullRange( float linear )
|
||||
{
|
||||
return pow( linear, 1.0f / 2.2f );
|
||||
}
|
||||
|
||||
float GammaToLinear( float gamma )
|
||||
{
|
||||
Assert( s_bMathlibInitialized );
|
||||
if ( gamma < 0.0f )
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if ( gamma >= 0.95f )
|
||||
{
|
||||
// Use GammaToLinearFullRange maybe if you trip this.
|
||||
// X360TEMP
|
||||
// Assert( gamma <= 1.0f );
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
int index = RoundFloatToInt( gamma * 255.0f );
|
||||
Assert( index >= 0 && index < 256 );
|
||||
return g_Mathlib_GammaToLinear[index];
|
||||
}
|
||||
|
||||
float LinearToGamma( float linear )
|
||||
{
|
||||
Assert( s_bMathlibInitialized );
|
||||
if ( linear < 0.0f )
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
if ( linear > 1.0f )
|
||||
{
|
||||
// Use LinearToGammaFullRange maybe if you trip this.
|
||||
Assert( 0 );
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
int index = RoundFloatToInt( linear * 255.0f );
|
||||
Assert( index >= 0 && index < 256 );
|
||||
return g_Mathlib_LinearToGamma[index];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helper functions to convert between sRGB and 360 gamma space
|
||||
//-----------------------------------------------------------------------------
|
||||
float SrgbGammaToLinear( float flSrgbGammaValue )
|
||||
{
|
||||
float x = clamp( flSrgbGammaValue, 0.0f, 1.0f );
|
||||
return ( x <= 0.04045f ) ? ( x / 12.92f ) : ( pow( ( x + 0.055f ) / 1.055f, 2.4f ) );
|
||||
}
|
||||
|
||||
float SrgbLinearToGamma( float flLinearValue )
|
||||
{
|
||||
float x = clamp( flLinearValue, 0.0f, 1.0f );
|
||||
return ( x <= 0.0031308f ) ? ( x * 12.92f ) : ( 1.055f * pow( x, ( 1.0f / 2.4f ) ) ) - 0.055f;
|
||||
}
|
||||
|
||||
float X360GammaToLinear( float fl360GammaValue )
|
||||
{
|
||||
float flLinearValue;
|
||||
|
||||
fl360GammaValue = clamp( fl360GammaValue, 0.0f, 1.0f );
|
||||
if ( fl360GammaValue < ( 96.0f / 255.0f ) )
|
||||
{
|
||||
if ( fl360GammaValue < ( 64.0f / 255.0f ) )
|
||||
{
|
||||
flLinearValue = fl360GammaValue * 255.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
flLinearValue = fl360GammaValue * ( 255.0f * 2.0f ) - 64.0f;
|
||||
flLinearValue += floor( flLinearValue * ( 1.0f / 512.0f ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( fl360GammaValue < ( 192.0f / 255.0f ) )
|
||||
{
|
||||
flLinearValue = fl360GammaValue * ( 255.0f * 4.0f ) - 256.0f;
|
||||
flLinearValue += floor( flLinearValue * ( 1.0f / 256.0f ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
flLinearValue = fl360GammaValue * ( 255.0f * 8.0f ) - 1024.0f;
|
||||
flLinearValue += floor( flLinearValue * ( 1.0f / 128.0f ) );
|
||||
}
|
||||
}
|
||||
|
||||
flLinearValue *= 1.0f / 1023.0f;
|
||||
|
||||
flLinearValue = clamp( flLinearValue, 0.0f, 1.0f );
|
||||
return flLinearValue;
|
||||
}
|
||||
|
||||
float X360LinearToGamma( float flLinearValue )
|
||||
{
|
||||
float fl360GammaValue;
|
||||
|
||||
flLinearValue = clamp( flLinearValue, 0.0f, 1.0f );
|
||||
if ( flLinearValue < ( 128.0f / 1023.0f ) )
|
||||
{
|
||||
if ( flLinearValue < ( 64.0f / 1023.0f ) )
|
||||
{
|
||||
fl360GammaValue = flLinearValue * ( 1023.0f * ( 1.0f / 255.0f ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
fl360GammaValue = flLinearValue * ( ( 1023.0f / 2.0f ) * ( 1.0f / 255.0f ) ) + ( 32.0f / 255.0f );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( flLinearValue < ( 512.0f / 1023.0f ) )
|
||||
{
|
||||
fl360GammaValue = flLinearValue * ( ( 1023.0f / 4.0f ) * ( 1.0f / 255.0f ) ) + ( 64.0f / 255.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
fl360GammaValue = flLinearValue * ( ( 1023.0f /8.0f ) * ( 1.0f / 255.0f ) ) + ( 128.0f /255.0f ); // 1.0 -> 1.0034313725490196078431372549016
|
||||
if ( fl360GammaValue > 1.0f )
|
||||
{
|
||||
fl360GammaValue = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fl360GammaValue = clamp( fl360GammaValue, 0.0f, 1.0f );
|
||||
return fl360GammaValue;
|
||||
}
|
||||
|
||||
float SrgbGammaTo360Gamma( float flSrgbGammaValue )
|
||||
{
|
||||
float flLinearValue = SrgbGammaToLinear( flSrgbGammaValue );
|
||||
float fl360GammaValue = X360LinearToGamma( flLinearValue );
|
||||
return fl360GammaValue;
|
||||
}
|
||||
|
||||
// convert texture to linear 0..1 value
|
||||
float TextureToLinear( int c )
|
||||
{
|
||||
Assert( s_bMathlibInitialized );
|
||||
if (c < 0)
|
||||
return 0;
|
||||
if (c > 255)
|
||||
return 1.0;
|
||||
|
||||
return texturetolinear[c];
|
||||
}
|
||||
|
||||
// convert texture to linear 0..1 value
|
||||
int LinearToTexture( float f )
|
||||
{
|
||||
Assert( s_bMathlibInitialized );
|
||||
int i;
|
||||
i = static_cast<int>(f * 1023); // assume 0..1 range
|
||||
if (i < 0)
|
||||
i = 0;
|
||||
if (i > 1023)
|
||||
i = 1023;
|
||||
|
||||
return lineartotexture[i];
|
||||
}
|
||||
|
||||
|
||||
// converts 0..1 linear value to screen gamma (0..255)
|
||||
int LinearToScreenGamma( float f )
|
||||
{
|
||||
Assert( s_bMathlibInitialized );
|
||||
int i;
|
||||
i = static_cast<int>(f * 1023); // assume 0..1 range
|
||||
if (i < 0)
|
||||
i = 0;
|
||||
if (i > 1023)
|
||||
i = 1023;
|
||||
|
||||
return lineartoscreen[i];
|
||||
}
|
||||
|
||||
void ColorRGBExp32ToVector( const ColorRGBExp32& in, Vector& out )
|
||||
{
|
||||
Assert( s_bMathlibInitialized );
|
||||
// FIXME: Why is there a factor of 255 built into this?
|
||||
out.x = 255.0f * TexLightToLinear( in.r, in.exponent );
|
||||
out.y = 255.0f * TexLightToLinear( in.g, in.exponent );
|
||||
out.z = 255.0f * TexLightToLinear( in.b, in.exponent );
|
||||
}
|
||||
|
||||
#if 0
|
||||
// assumes that the desired mantissa range is 128..255
|
||||
static int VectorToColorRGBExp32_CalcExponent( float in )
|
||||
{
|
||||
int power = 0;
|
||||
|
||||
if( in != 0.0f )
|
||||
{
|
||||
while( in > 255.0f )
|
||||
{
|
||||
power += 1;
|
||||
in *= 0.5f;
|
||||
}
|
||||
|
||||
while( in < 128.0f )
|
||||
{
|
||||
power -= 1;
|
||||
in *= 2.0f;
|
||||
}
|
||||
}
|
||||
|
||||
return power;
|
||||
}
|
||||
|
||||
void VectorToColorRGBExp32( const Vector& vin, ColorRGBExp32 &c )
|
||||
{
|
||||
Vector v = vin;
|
||||
Assert( s_bMathlibInitialized );
|
||||
Assert( v.x >= 0.0f && v.y >= 0.0f && v.z >= 0.0f );
|
||||
int i;
|
||||
float max = v[0];
|
||||
for( i = 1; i < 3; i++ )
|
||||
{
|
||||
// Get the maximum value.
|
||||
if( v[i] > max )
|
||||
{
|
||||
max = v[i];
|
||||
}
|
||||
}
|
||||
|
||||
// figure out the exponent for this luxel.
|
||||
int exponent = VectorToColorRGBExp32_CalcExponent( max );
|
||||
|
||||
// make the exponent fits into a signed byte.
|
||||
if( exponent < -128 )
|
||||
{
|
||||
exponent = -128;
|
||||
}
|
||||
else if( exponent > 127 )
|
||||
{
|
||||
exponent = 127;
|
||||
}
|
||||
|
||||
// undone: optimize with a table
|
||||
float scalar = pow( 2.0f, -exponent );
|
||||
// convert to mantissa x 2^exponent format
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
v[i] *= scalar;
|
||||
// clamp
|
||||
if( v[i] > 255.0f )
|
||||
{
|
||||
v[i] = 255.0f;
|
||||
}
|
||||
}
|
||||
c.r = ( unsigned char )v[0];
|
||||
c.g = ( unsigned char )v[1];
|
||||
c.b = ( unsigned char )v[2];
|
||||
c.exponent = ( signed char )exponent;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// given a floating point number f, return an exponent e such that
|
||||
// for f' = f * 2^e, f is on [128..255].
|
||||
// Uses IEEE 754 representation to directly extract this information
|
||||
// from the float.
|
||||
inline static int VectorToColorRGBExp32_CalcExponent( const float *pin )
|
||||
{
|
||||
// The thing we will take advantage of here is that the exponent component
|
||||
// is stored in the float itself, and because we want to map to 128..255, we
|
||||
// want an "ideal" exponent of 2^7. So, we compute the difference between the
|
||||
// input exponent and 7 to work out the normalizing exponent. Thus if you pass in
|
||||
// 32 (represented in IEEE 754 as 2^5), this function will return 2
|
||||
// (because 32 * 2^2 = 128)
|
||||
if (*pin == 0.0f)
|
||||
return 0;
|
||||
|
||||
unsigned int fbits = *reinterpret_cast<const unsigned int *>(pin);
|
||||
|
||||
// the exponent component is bits 23..30, and biased by +127
|
||||
const unsigned int biasedSeven = 7 + 127;
|
||||
|
||||
signed int expComponent = ( fbits & 0x7F800000 ) >> 23;
|
||||
expComponent -= biasedSeven; // now the difference from seven (positive if was less than, etc)
|
||||
return expComponent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Slightly faster version of the function to turn a float-vector color into
|
||||
/// a compressed-exponent notation 32bit color. However, still not SIMD optimized.
|
||||
/// PS3 developer: note there is a movement of a float onto an int here, which is
|
||||
/// bad on the base registers -- consider doing this as Altivec code, or better yet
|
||||
/// moving it onto the cell.
|
||||
/// \warning: Assumes an IEEE 754 single-precision float representation! Those of you
|
||||
/// porting to an 8080 are out of luck.
|
||||
void VectorToColorRGBExp32( const Vector& vin, ColorRGBExp32 &c )
|
||||
{
|
||||
Assert( s_bMathlibInitialized );
|
||||
Assert( vin.x >= 0.0f && vin.y >= 0.0f && vin.z >= 0.0f );
|
||||
|
||||
// work out which of the channels is the largest ( we will use that to map the exponent )
|
||||
// this is a sluggish branch-based decision tree -- most architectures will offer a [max]
|
||||
// assembly opcode to do this faster.
|
||||
const float *pMax;
|
||||
if (vin.x > vin.y)
|
||||
{
|
||||
if (vin.x > vin.z)
|
||||
{
|
||||
pMax = &vin.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
pMax = &vin.z;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vin.y > vin.z)
|
||||
{
|
||||
pMax = &vin.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
pMax = &vin.z;
|
||||
}
|
||||
}
|
||||
|
||||
// now work out the exponent for this luxel.
|
||||
signed int exponent = VectorToColorRGBExp32_CalcExponent( pMax );
|
||||
|
||||
// make sure the exponent fits into a signed byte.
|
||||
// (in single precision format this is assured because it was a signed byte to begin with)
|
||||
Assert(exponent > -128 && exponent <= 127);
|
||||
|
||||
// promote the exponent back onto a scalar that we'll use to normalize all the numbers
|
||||
float scalar;
|
||||
{
|
||||
unsigned int fbits = (127 - exponent) << 23;
|
||||
scalar = *reinterpret_cast<float *>(&fbits);
|
||||
}
|
||||
|
||||
// we should never need to clamp:
|
||||
Assert(vin.x * scalar <= 255.0f &&
|
||||
vin.y * scalar <= 255.0f &&
|
||||
vin.z * scalar <= 255.0f);
|
||||
|
||||
// This awful construction is necessary to prevent VC2005 from using the
|
||||
// fldcw/fnstcw control words around every float-to-unsigned-char operation.
|
||||
{
|
||||
int red = static_cast<int>(vin.x * scalar);
|
||||
int green = static_cast<int>(vin.y * scalar);
|
||||
int blue = static_cast<int>(vin.z * scalar);
|
||||
|
||||
c.r = red;
|
||||
c.g = green;
|
||||
c.b = blue;
|
||||
}
|
||||
/*
|
||||
c.r = ( unsigned char )(vin.x * scalar);
|
||||
c.g = ( unsigned char )(vin.y * scalar);
|
||||
c.b = ( unsigned char )(vin.z * scalar);
|
||||
*/
|
||||
|
||||
c.exponent = ( signed char )exponent;
|
||||
}
|
||||
|
||||
#endif
|
63
mathlib/datagen.pl
Normal file
63
mathlib/datagen.pl
Normal file
@ -0,0 +1,63 @@
|
||||
#! perl
|
||||
use Text::Wrap;
|
||||
|
||||
# generate output data for noise generators
|
||||
|
||||
srand(31456);
|
||||
|
||||
print <<END
|
||||
//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: static data for noise() primitives.
|
||||
//
|
||||
// \$Workfile: \$
|
||||
// \$NoKeywords: \$
|
||||
//=============================================================================//
|
||||
//
|
||||
// **** DO NOT EDIT THIS FILE. GENERATED BY DATAGEN.PL ****
|
||||
//
|
||||
|
||||
END
|
||||
;
|
||||
|
||||
@perm_a=0..255;
|
||||
|
||||
&fisher_yates_shuffle(\@perm_a);
|
||||
|
||||
$Text::Wrap::Columns=78;
|
||||
$Text::Wrap::break=",";
|
||||
$Text::Wrap::separator=",\n";
|
||||
|
||||
print "static int perm_a[]={\n",wrap(' ',' ',join(",",@perm_a)),"\n};\n\n";
|
||||
&fisher_yates_shuffle(\@perm_a);
|
||||
print "static int perm_b[]={\n",wrap(' ',' ',join(",",@perm_a)),"\n};\n\n";
|
||||
&fisher_yates_shuffle(\@perm_a);
|
||||
print "static int perm_c[]={\n",wrap(' ',' ',join(",",@perm_a)),"\n};\n\n";
|
||||
&fisher_yates_shuffle(\@perm_a);
|
||||
print "static int perm_d[]={\n",wrap(' ',' ',join(",",@perm_a)),"\n};\n\n";
|
||||
|
||||
for ($i=0;$i<256;$i++)
|
||||
{
|
||||
$float_perm=(1.0/255.0)*$perm_a[$i];
|
||||
$perm_a[$i] = sprintf("%f",$float_perm);
|
||||
}
|
||||
&fisher_yates_shuffle(\@perm_a);
|
||||
print "static float impulse_xcoords[]={\n",wrap(' ',' ',join(",",@perm_a)),"\n};\n\n";
|
||||
&fisher_yates_shuffle(\@perm_a);
|
||||
print "static float impulse_ycoords[]={\n",wrap(' ',' ',join(",",@perm_a)),"\n};\n\n";
|
||||
&fisher_yates_shuffle(\@perm_a);
|
||||
print "static float impulse_zcoords[]={\n",wrap(' ',' ',join(",",@perm_a)),"\n};\n\n";
|
||||
|
||||
|
||||
|
||||
# fisher_yates_shuffle( \@array ) : generate a random permutation
|
||||
# of @array in place
|
||||
sub fisher_yates_shuffle {
|
||||
my $array = shift;
|
||||
my $i;
|
||||
for ($i = @$array; --$i; ) {
|
||||
my $j = int rand ($i+1);
|
||||
next if $i == $j;
|
||||
@$array[$i,$j] = @$array[$j,$i];
|
||||
}
|
||||
}
|
30
mathlib/halton.cpp
Normal file
30
mathlib/halton.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#include <halton.h>
|
||||
|
||||
HaltonSequenceGenerator_t::HaltonSequenceGenerator_t(int b)
|
||||
{
|
||||
base=b;
|
||||
fbase=(float) b;
|
||||
seed=1;
|
||||
|
||||
}
|
||||
|
||||
float HaltonSequenceGenerator_t::GetElement(int elem)
|
||||
{
|
||||
int tmpseed=seed;
|
||||
float ret=0.0;
|
||||
float base_inv=1.0/fbase;
|
||||
while(tmpseed)
|
||||
{
|
||||
int dig=tmpseed % base;
|
||||
ret+=((float) dig)*base_inv;
|
||||
base_inv/=fbase;
|
||||
tmpseed/=base;
|
||||
}
|
||||
return ret;
|
||||
}
|
95
mathlib/imagequant.cpp
Normal file
95
mathlib/imagequant.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
#include <quantize.h>
|
||||
|
||||
#define N_EXTRAVALUES 1
|
||||
#define N_DIMENSIONS (3+N_EXTRAVALUES)
|
||||
|
||||
#define PIXEL(x,y,c) Image[4*((x)+((Width*(y))))+c]
|
||||
|
||||
static uint8 Weights[]={5,7,4,8};
|
||||
static int ExtraValueXForms[3*N_EXTRAVALUES]={
|
||||
76,151,28,
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define MAX_QUANTIZE_IMAGE_WIDTH 4096
|
||||
|
||||
void ColorQuantize(uint8 const *Image,
|
||||
int Width,
|
||||
int Height,
|
||||
int flags, int ncolors,
|
||||
uint8 *out_pixels,
|
||||
uint8 *out_palette,
|
||||
int firstcolor)
|
||||
{
|
||||
int Error[MAX_QUANTIZE_IMAGE_WIDTH+1][3][2];
|
||||
struct Sample *s=AllocSamples(Width*Height,N_DIMENSIONS);
|
||||
int x,y,c;
|
||||
for(y=0;y<Height;y++)
|
||||
for(x=0;x<Width;x++)
|
||||
{
|
||||
for(c=0;c<3;c++)
|
||||
NthSample(s,y*Width+x,N_DIMENSIONS)->Value[c]=PIXEL(x,y,c);
|
||||
// now, let's generate extra values to quantize on
|
||||
for(int i=0;i<N_EXTRAVALUES;i++)
|
||||
{
|
||||
int val1=0;
|
||||
for(c=0;c<3;c++)
|
||||
val1+=PIXEL(x,y,c)*ExtraValueXForms[i*3+c];
|
||||
val1>>=8;
|
||||
NthSample(s,y*Width+x,N_DIMENSIONS)->Value[c]=(uint8)
|
||||
(MIN(255,MAX(0,val1)));
|
||||
}
|
||||
}
|
||||
struct QuantizedValue *q=Quantize(s,Width*Height,N_DIMENSIONS,
|
||||
ncolors,Weights,firstcolor);
|
||||
delete[] s;
|
||||
memset(out_palette,0x55,768);
|
||||
for(int p=0;p<256;p++)
|
||||
{
|
||||
struct QuantizedValue *v=FindQNode(q,p);
|
||||
if (v)
|
||||
for(int c=0;c<3;c++)
|
||||
out_palette[p*3+c]=v->Mean[c];
|
||||
}
|
||||
memset(Error,0,sizeof(Error));
|
||||
for(y=0;y<Height;y++)
|
||||
{
|
||||
int ErrorUse=y & 1;
|
||||
int ErrorUpdate=ErrorUse^1;
|
||||
for(x=0;x<Width;x++)
|
||||
{
|
||||
uint8 samp[3];
|
||||
for(c=0;c<3;c++)
|
||||
{
|
||||
int tryc=PIXEL(x,y,c);
|
||||
if (! (flags & QUANTFLAGS_NODITHER))
|
||||
{
|
||||
tryc+=Error[x][c][ErrorUse];
|
||||
Error[x][c][ErrorUse]=0;
|
||||
}
|
||||
samp[c]=(uint8) MIN(255,MAX(0,tryc));
|
||||
}
|
||||
struct QuantizedValue *f=FindMatch(samp,3,Weights,q);
|
||||
out_pixels[Width*y+x]=(uint8) (f->value);
|
||||
if (! (flags & QUANTFLAGS_NODITHER))
|
||||
for(int i=0;i<3;i++)
|
||||
{
|
||||
int newerr=samp[i]-f->Mean[i];
|
||||
int orthog_error=(newerr*3)/8;
|
||||
Error[x+1][i][ErrorUse]+=orthog_error;
|
||||
Error[x][i][ErrorUpdate]=orthog_error;
|
||||
Error[x+1][i][ErrorUpdate]=newerr-2*orthog_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (q) FreeQuantization(q);
|
||||
}
|
||||
|
320
mathlib/lightdesc.cpp
Normal file
320
mathlib/lightdesc.cpp
Normal file
@ -0,0 +1,320 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#include <ssemath.h>
|
||||
#include <lightdesc.h>
|
||||
#include "mathlib.h"
|
||||
|
||||
void LightDesc_t::RecalculateDerivedValues(void)
|
||||
{
|
||||
m_Flags=0;
|
||||
if (m_Attenuation0)
|
||||
m_Flags|=LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION0;
|
||||
if (m_Attenuation1)
|
||||
m_Flags|=LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION1;
|
||||
if (m_Attenuation2)
|
||||
m_Flags|=LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION2;
|
||||
|
||||
if (m_Type==MATERIAL_LIGHT_SPOT)
|
||||
{
|
||||
m_ThetaDot=cos(m_Theta);
|
||||
m_PhiDot=cos(m_Phi);
|
||||
float spread=m_ThetaDot-m_PhiDot;
|
||||
if (spread>1.0e-10)
|
||||
{
|
||||
// note - this quantity is very sensitive to round off error. the sse
|
||||
// reciprocal approximation won't cut it here.
|
||||
OneOver_ThetaDot_Minus_PhiDot=1.0/spread;
|
||||
}
|
||||
else
|
||||
{
|
||||
// hard falloff instead of divide by zero
|
||||
OneOver_ThetaDot_Minus_PhiDot=1.0;
|
||||
}
|
||||
}
|
||||
if (m_Type==MATERIAL_LIGHT_DIRECTIONAL)
|
||||
{
|
||||
// set position to be real far away in the right direction
|
||||
m_Position=m_Direction;
|
||||
m_Position *= 2.0e6;
|
||||
}
|
||||
|
||||
m_RangeSquared=m_Range*m_Range;
|
||||
|
||||
}
|
||||
|
||||
void LightDesc_t::ComputeLightAtPointsForDirectional(
|
||||
const FourVectors &pos, const FourVectors &normal,
|
||||
FourVectors &color, bool DoHalfLambert ) const
|
||||
{
|
||||
FourVectors delta;
|
||||
delta.DuplicateVector(m_Direction);
|
||||
// delta.VectorNormalizeFast();
|
||||
fltx4 strength=delta*normal;
|
||||
if (DoHalfLambert)
|
||||
{
|
||||
strength=AddSIMD(MulSIMD(strength,Four_PointFives),Four_PointFives);
|
||||
}
|
||||
else
|
||||
strength=MaxSIMD(Four_Zeros,delta*normal);
|
||||
|
||||
color.x=AddSIMD(color.x,MulSIMD(strength,ReplicateX4(m_Color.x)));
|
||||
color.y=AddSIMD(color.y,MulSIMD(strength,ReplicateX4(m_Color.y)));
|
||||
color.z=AddSIMD(color.z,MulSIMD(strength,ReplicateX4(m_Color.z)));
|
||||
}
|
||||
|
||||
|
||||
void LightDesc_t::ComputeLightAtPoints( const FourVectors &pos, const FourVectors &normal,
|
||||
FourVectors &color, bool DoHalfLambert ) const
|
||||
{
|
||||
FourVectors delta;
|
||||
Assert((m_Type==MATERIAL_LIGHT_POINT) || (m_Type==MATERIAL_LIGHT_SPOT) || (m_Type==MATERIAL_LIGHT_DIRECTIONAL));
|
||||
switch (m_Type)
|
||||
{
|
||||
case MATERIAL_LIGHT_POINT:
|
||||
case MATERIAL_LIGHT_SPOT:
|
||||
delta.DuplicateVector(m_Position);
|
||||
delta-=pos;
|
||||
break;
|
||||
|
||||
case MATERIAL_LIGHT_DIRECTIONAL:
|
||||
ComputeLightAtPointsForDirectional( pos, normal, color, DoHalfLambert );
|
||||
return;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
fltx4 dist2 = delta*delta;
|
||||
|
||||
dist2=MaxSIMD( Four_Ones, dist2 );
|
||||
|
||||
fltx4 falloff;
|
||||
|
||||
if( m_Flags & LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION0 )
|
||||
{
|
||||
falloff = ReplicateX4(m_Attenuation0);
|
||||
}
|
||||
else
|
||||
falloff= Four_Epsilons;
|
||||
|
||||
if( m_Flags & LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION1 )
|
||||
{
|
||||
falloff=AddSIMD(falloff,MulSIMD(ReplicateX4(m_Attenuation1),SqrtEstSIMD(dist2)));
|
||||
}
|
||||
|
||||
if( m_Flags & LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION2 )
|
||||
{
|
||||
falloff=AddSIMD(falloff,MulSIMD(ReplicateX4(m_Attenuation2),dist2));
|
||||
}
|
||||
|
||||
falloff=ReciprocalEstSIMD(falloff);
|
||||
// Cull out light beyond this radius
|
||||
// now, zero out elements for which dist2 was > range^2. !!speed!! lights should store dist^2 in sse format
|
||||
if (m_Range != 0.f)
|
||||
{
|
||||
fltx4 RangeSquared=ReplicateX4(m_RangeSquared); // !!speed!!
|
||||
falloff=AndSIMD(falloff,CmpLtSIMD(dist2,RangeSquared));
|
||||
}
|
||||
|
||||
delta.VectorNormalizeFast();
|
||||
fltx4 strength=delta*normal;
|
||||
if (DoHalfLambert)
|
||||
{
|
||||
strength=AddSIMD(MulSIMD(strength,Four_PointFives),Four_PointFives);
|
||||
}
|
||||
else
|
||||
strength=MaxSIMD(Four_Zeros,delta*normal);
|
||||
|
||||
switch(m_Type)
|
||||
{
|
||||
case MATERIAL_LIGHT_POINT:
|
||||
// half-lambert
|
||||
break;
|
||||
|
||||
case MATERIAL_LIGHT_SPOT:
|
||||
{
|
||||
fltx4 dot2=SubSIMD(Four_Zeros,delta*m_Direction); // dot position with spot light dir for cone falloff
|
||||
|
||||
|
||||
fltx4 cone_falloff_scale=MulSIMD(ReplicateX4(OneOver_ThetaDot_Minus_PhiDot),
|
||||
SubSIMD(dot2,ReplicateX4(m_PhiDot)));
|
||||
cone_falloff_scale=MinSIMD(cone_falloff_scale,Four_Ones);
|
||||
|
||||
if ((m_Falloff!=0.0) && (m_Falloff!=1.0))
|
||||
{
|
||||
// !!speed!! could compute integer exponent needed by powsimd and store in light
|
||||
cone_falloff_scale=PowSIMD(cone_falloff_scale,m_Falloff);
|
||||
}
|
||||
strength=MulSIMD(cone_falloff_scale,strength);
|
||||
|
||||
// now, zero out lighting where dot2<phidot. This will mask out any invalid results
|
||||
// from pow function, etc
|
||||
fltx4 OutsideMask=CmpGtSIMD(dot2,ReplicateX4(m_PhiDot)); // outside light cone?
|
||||
strength=AndSIMD(OutsideMask,strength);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
strength=MulSIMD(strength,falloff);
|
||||
color.x=AddSIMD(color.x,MulSIMD(strength,ReplicateX4(m_Color.x)));
|
||||
color.y=AddSIMD(color.y,MulSIMD(strength,ReplicateX4(m_Color.y)));
|
||||
color.z=AddSIMD(color.z,MulSIMD(strength,ReplicateX4(m_Color.z)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LightDesc_t::ComputeNonincidenceLightAtPoints( const FourVectors &pos, FourVectors &color ) const
|
||||
{
|
||||
FourVectors delta;
|
||||
Assert((m_Type==MATERIAL_LIGHT_POINT) || (m_Type==MATERIAL_LIGHT_SPOT) || (m_Type==MATERIAL_LIGHT_DIRECTIONAL));
|
||||
switch (m_Type)
|
||||
{
|
||||
case MATERIAL_LIGHT_POINT:
|
||||
case MATERIAL_LIGHT_SPOT:
|
||||
delta.DuplicateVector(m_Position);
|
||||
delta-=pos;
|
||||
break;
|
||||
|
||||
case MATERIAL_LIGHT_DIRECTIONAL:
|
||||
return;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
fltx4 dist2 = delta*delta;
|
||||
|
||||
dist2=MaxSIMD( Four_Ones, dist2 );
|
||||
|
||||
fltx4 falloff;
|
||||
|
||||
if( m_Flags & LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION0 )
|
||||
{
|
||||
falloff = ReplicateX4(m_Attenuation0);
|
||||
}
|
||||
else
|
||||
falloff= Four_Epsilons;
|
||||
|
||||
if( m_Flags & LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION1 )
|
||||
{
|
||||
falloff=AddSIMD(falloff,MulSIMD(ReplicateX4(m_Attenuation1),SqrtEstSIMD(dist2)));
|
||||
}
|
||||
|
||||
if( m_Flags & LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION2 )
|
||||
{
|
||||
falloff=AddSIMD(falloff,MulSIMD(ReplicateX4(m_Attenuation2),dist2));
|
||||
}
|
||||
|
||||
falloff=ReciprocalEstSIMD(falloff);
|
||||
// Cull out light beyond this radius
|
||||
// now, zero out elements for which dist2 was > range^2. !!speed!! lights should store dist^2 in sse format
|
||||
if (m_Range != 0.f)
|
||||
{
|
||||
fltx4 RangeSquared=ReplicateX4(m_RangeSquared); // !!speed!!
|
||||
falloff=AndSIMD(falloff,CmpLtSIMD(dist2,RangeSquared));
|
||||
}
|
||||
|
||||
delta.VectorNormalizeFast();
|
||||
fltx4 strength = Four_Ones;
|
||||
//fltx4 strength=delta;
|
||||
//fltx4 strength = MaxSIMD(Four_Zeros,delta);
|
||||
|
||||
switch(m_Type)
|
||||
{
|
||||
case MATERIAL_LIGHT_POINT:
|
||||
// half-lambert
|
||||
break;
|
||||
|
||||
case MATERIAL_LIGHT_SPOT:
|
||||
{
|
||||
fltx4 dot2=SubSIMD(Four_Zeros,delta*m_Direction); // dot position with spot light dir for cone falloff
|
||||
|
||||
|
||||
fltx4 cone_falloff_scale=MulSIMD(ReplicateX4(OneOver_ThetaDot_Minus_PhiDot),
|
||||
SubSIMD(dot2,ReplicateX4(m_PhiDot)));
|
||||
cone_falloff_scale=MinSIMD(cone_falloff_scale,Four_Ones);
|
||||
|
||||
if ((m_Falloff!=0.0) && (m_Falloff!=1.0))
|
||||
{
|
||||
// !!speed!! could compute integer exponent needed by powsimd and store in light
|
||||
cone_falloff_scale=PowSIMD(cone_falloff_scale,m_Falloff);
|
||||
}
|
||||
strength=MulSIMD(cone_falloff_scale,strength);
|
||||
|
||||
// now, zero out lighting where dot2<phidot. This will mask out any invalid results
|
||||
// from pow function, etc
|
||||
fltx4 OutsideMask=CmpGtSIMD(dot2,ReplicateX4(m_PhiDot)); // outside light cone?
|
||||
strength=AndSIMD(OutsideMask,strength);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
strength=MulSIMD(strength,falloff);
|
||||
color.x=AddSIMD(color.x,MulSIMD(strength,ReplicateX4(m_Color.x)));
|
||||
color.y=AddSIMD(color.y,MulSIMD(strength,ReplicateX4(m_Color.y)));
|
||||
color.z=AddSIMD(color.z,MulSIMD(strength,ReplicateX4(m_Color.z)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LightDesc_t::SetupOldStyleAttenuation( float fQuadraticAttn, float fLinearAttn, float fConstantAttn )
|
||||
{
|
||||
// old-style manually typed quadrtiac coefficients
|
||||
if ( fQuadraticAttn < EQUAL_EPSILON )
|
||||
fQuadraticAttn = 0;
|
||||
|
||||
if ( fLinearAttn < EQUAL_EPSILON)
|
||||
fLinearAttn = 0;
|
||||
|
||||
if ( fConstantAttn < EQUAL_EPSILON)
|
||||
fConstantAttn = 0;
|
||||
|
||||
if ( ( fConstantAttn < EQUAL_EPSILON ) &&
|
||||
( fLinearAttn < EQUAL_EPSILON ) &&
|
||||
( fQuadraticAttn < EQUAL_EPSILON ) )
|
||||
fConstantAttn = 1;
|
||||
|
||||
m_Attenuation2=fQuadraticAttn;
|
||||
m_Attenuation1=fLinearAttn;
|
||||
m_Attenuation0=fConstantAttn;
|
||||
float fScaleFactor = fQuadraticAttn * 10000 + fLinearAttn * 100 + fConstantAttn;
|
||||
|
||||
if ( fScaleFactor > 0 )
|
||||
m_Color *= fScaleFactor;
|
||||
}
|
||||
|
||||
void LightDesc_t::SetupNewStyleAttenuation( float fFiftyPercentDistance,
|
||||
float fZeroPercentDistance )
|
||||
{
|
||||
// new style storing 50% and 0% distances
|
||||
float d50=fFiftyPercentDistance;
|
||||
float d0=fZeroPercentDistance;
|
||||
if (d0<d50)
|
||||
{
|
||||
// !!warning in lib code???!!!
|
||||
Warning("light has _fifty_percent_distance of %f but no zero_percent_distance\n",d50);
|
||||
d0=2.0*d50;
|
||||
}
|
||||
float a=0,b=1,c=0;
|
||||
if (! SolveInverseQuadraticMonotonic(0,1.0,d50,2.0,d0,256.0,a,b,c))
|
||||
{
|
||||
Warning("can't solve quadratic for light %f %f\n",d50,d0);
|
||||
}
|
||||
float v50=c+d50*(b+d50*a);
|
||||
float scale=2.0/v50;
|
||||
a*=scale;
|
||||
b*=scale;
|
||||
c*=scale;
|
||||
m_Attenuation2=a;
|
||||
m_Attenuation1=b;
|
||||
m_Attenuation0=c;
|
||||
}
|
||||
|
407
mathlib/mathlib-2005.vcproj
Normal file
407
mathlib/mathlib-2005.vcproj
Normal file
@ -0,0 +1,407 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="mathlib"
|
||||
ProjectGUID="{884C66F2-7F84-4570-AE6C-B634C1113D69}"
|
||||
RootNamespace="mathlib"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory=".\Debug"
|
||||
IntermediateDirectory=".\Debug"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
CommandLine=""
|
||||
ExcludedFromBuild="false"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UseUnicodeResponseFiles="false"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\public;..\public\tier0;..\public\tier1;..\public\mathlib"
|
||||
PreprocessorDefinitions="WIN32;_WIN32;_DEBUG;DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE"
|
||||
StringPooling="true"
|
||||
MinimalRebuild="true"
|
||||
ExceptionHandling="0"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
BufferSecurityCheck="false"
|
||||
FloatingPointModel="2"
|
||||
TreatWChar_tAsBuiltInType="true"
|
||||
ForceConformanceInForLoopScope="true"
|
||||
RuntimeTypeInfo="true"
|
||||
OpenMP="false"
|
||||
UsePrecompiledHeader="0"
|
||||
ExpandAttributedSource="false"
|
||||
AssemblerOutput="0"
|
||||
AssemblerListingLocation="$(IntDir)/"
|
||||
ObjectFile="$(IntDir)/"
|
||||
ProgramDataBaseFileName="$(IntDir)/"
|
||||
GenerateXMLDocumentationFiles="false"
|
||||
BrowseInformation="0"
|
||||
BrowseInformationFile="$(IntDir)/"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="4"
|
||||
CompileAs="2"
|
||||
ErrorReporting="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
CommandLine=""
|
||||
ExcludedFromBuild="false"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
UseUnicodeResponseFiles="false"
|
||||
OutputFile="..\lib\public\mathlib.lib"
|
||||
SuppressStartupBanner="true"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
SuppressStartupBanner="true"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
SuppressStartupBanner="true"
|
||||
OutputFile="$(OutDir)/mathlib.bsc"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
ExcludedFromBuild="false"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory=".\Release"
|
||||
IntermediateDirectory=".\Release"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
CommandLine=""
|
||||
ExcludedFromBuild="false"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UseUnicodeResponseFiles="false"
|
||||
Optimization="2"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="1"
|
||||
AdditionalIncludeDirectories="..\public;..\public\tier0;..\public\tier1;..\public\mathlib"
|
||||
PreprocessorDefinitions="WIN32;_WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE"
|
||||
StringPooling="true"
|
||||
ExceptionHandling="0"
|
||||
RuntimeLibrary="0"
|
||||
BufferSecurityCheck="false"
|
||||
EnableFunctionLevelLinking="true"
|
||||
FloatingPointModel="2"
|
||||
TreatWChar_tAsBuiltInType="true"
|
||||
ForceConformanceInForLoopScope="true"
|
||||
RuntimeTypeInfo="true"
|
||||
OpenMP="false"
|
||||
UsePrecompiledHeader="0"
|
||||
ExpandAttributedSource="false"
|
||||
AssemblerOutput="0"
|
||||
AssemblerListingLocation="$(IntDir)/"
|
||||
ObjectFile="$(IntDir)/"
|
||||
ProgramDataBaseFileName="$(IntDir)/"
|
||||
GenerateXMLDocumentationFiles="false"
|
||||
BrowseInformation="0"
|
||||
BrowseInformationFile="$(IntDir)/"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="1"
|
||||
CompileAs="2"
|
||||
ErrorReporting="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
CommandLine=""
|
||||
ExcludedFromBuild="false"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
UseUnicodeResponseFiles="false"
|
||||
OutputFile="..\lib\public\mathlib.lib"
|
||||
SuppressStartupBanner="true"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
SuppressStartupBanner="true"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
SuppressStartupBanner="true"
|
||||
OutputFile="$(OutDir)/mathlib.bsc"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
ExcludedFromBuild="false"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\3dnow.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\anorms.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\bumpvects.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\color_conversion.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\halton.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\IceKey.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\imagequant.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\lightdesc.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mathlib_base.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\polyhedron.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\powsse.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\quantize.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\randsse.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\simdvectormatrix.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\sparse_convolution_noise.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\sse.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\sseconst.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ssenoise.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vector.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vmatrix.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Public Header Files"
|
||||
Filter="h"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\public\mathlib\amd3dx.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\mathlib\anorms.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\mathlib\bumpvects.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\mathlib\compressed_3d_unitvec.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\mathlib\compressed_light_cube.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\mathlib\compressed_vector.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\mathlib\halton.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\mathlib\IceKey.H"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\mathlib\lightdesc.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\mathlib\math_pfns.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\mathlib\mathlib.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\mathlib\noise.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\mathlib\polyhedron.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\mathlib\quantize.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\mathlib\simdvectormatrix.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\mathlib\ssemath.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\mathlib\ssequaternion.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\mathlib\vector.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\mathlib\vector2d.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\mathlib\vector4d.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\mathlib\vmatrix.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\mathlib\vplane.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\3dnow.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\noisedata.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\sse.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
4090
mathlib/mathlib_base.cpp
Normal file
4090
mathlib/mathlib_base.cpp
Normal file
File diff suppressed because it is too large
Load Diff
180
mathlib/noisedata.h
Normal file
180
mathlib/noisedata.h
Normal file
@ -0,0 +1,180 @@
|
||||
//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: static data for noise() primitives.
|
||||
//
|
||||
// $Workfile: $
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
//
|
||||
// **** DO NOT EDIT THIS FILE. GENERATED BY DATAGEN.PL ****
|
||||
//
|
||||
|
||||
static const int perm_a[]={
|
||||
66,147,106,213,89,115,239,25,171,175,9,114,141,226,118,128,41,208,4,56,
|
||||
180,248,43,82,246,219,94,245,133,131,222,103,160,130,168,145,238,38,23,6,
|
||||
236,67,99,2,70,232,80,209,1,3,68,65,102,210,13,73,55,252,187,170,22,36,
|
||||
52,181,117,163,46,79,166,224,148,75,113,95,156,185,220,164,51,142,161,35,
|
||||
206,251,45,136,197,190,132,32,218,127,63,27,137,93,242,20,189,108,183,
|
||||
122,139,191,249,253,87,98,69,0,144,64,24,214,97,116,158,42,107,15,53,212,
|
||||
83,111,152,240,74,237,62,77,205,149,26,151,178,204,91,176,234,49,154,203,
|
||||
33,221,125,134,165,124,86,39,37,60,150,157,179,109,110,44,159,153,5,100,
|
||||
10,207,40,186,96,215,143,162,230,184,101,54,174,247,76,59,241,223,192,84,
|
||||
104,78,169,146,138,30,48,85,233,19,29,92,126,17,199,250,31,81,188,225,28,
|
||||
112,88,11,182,173,211,129,194,172,14,120,200,167,135,12,177,227,229,155,
|
||||
201,61,105,195,193,244,235,58,8,196,123,254,16,18,50,121,71,243,90,57,
|
||||
202,119,255,47,7,198,228,21,217,216,231,140,72,34
|
||||
};
|
||||
|
||||
static const int perm_b[]={
|
||||
123,108,201,64,40,75,24,221,137,110,191,142,9,69,230,83,7,247,51,54,115,
|
||||
133,180,248,109,116,62,99,251,55,89,253,65,106,228,167,131,132,58,143,
|
||||
97,102,163,202,149,234,12,117,174,94,121,74,32,113,20,60,159,182,204,29,
|
||||
244,118,3,178,255,38,6,114,36,93,30,134,213,90,245,209,88,232,162,125,
|
||||
84,166,70,136,208,231,27,71,157,80,76,0,170,225,203,176,33,161,196,128,
|
||||
252,236,246,2,138,1,250,197,77,243,218,242,19,164,68,212,14,237,144,63,
|
||||
46,103,177,188,85,223,8,160,222,4,216,219,35,15,44,23,126,127,100,226,
|
||||
235,37,168,101,49,22,11,73,61,135,111,183,72,96,185,239,82,18,50,155,
|
||||
186,153,17,233,146,156,107,5,254,10,192,198,148,207,104,13,124,48,95,
|
||||
129,120,206,199,81,249,91,150,210,119,240,122,194,92,34,28,205,175,227,
|
||||
179,220,140,152,79,26,195,47,66,173,169,241,53,184,187,145,112,238,214,
|
||||
147,98,171,229,200,151,25,67,78,189,217,130,224,57,172,59,41,43,16,105,
|
||||
158,165,21,45,56,141,139,215,190,86,42,52,39,87,181,31,154,193,211
|
||||
};
|
||||
|
||||
static const int perm_c[]={
|
||||
97,65,96,25,122,26,219,85,148,251,102,0,140,130,136,213,138,60,236,52,
|
||||
178,131,115,183,144,78,147,168,39,45,169,70,57,146,67,142,252,216,28,54,
|
||||
86,222,194,200,48,5,205,125,214,56,181,255,196,155,37,218,153,208,66,
|
||||
242,73,248,206,61,62,246,177,2,197,107,162,152,89,41,6,160,94,8,201,38,
|
||||
235,228,165,93,111,239,74,231,121,47,166,221,157,64,77,244,29,105,150,
|
||||
123,190,191,225,118,133,42,10,84,185,159,124,132,240,180,44,1,9,19,99,
|
||||
254,12,207,186,71,234,184,11,20,16,193,139,175,98,59,113,27,170,230,91,
|
||||
187,46,156,249,108,195,171,114,14,188,82,192,233,24,32,241,87,164,90,43,
|
||||
163,245,92,40,215,55,226,15,3,112,158,250,172,22,227,137,35,128,145,247,
|
||||
161,119,80,217,189,81,7,63,202,120,223,83,179,4,106,199,229,95,53,50,33,
|
||||
182,72,143,23,243,75,18,173,141,167,198,204,58,174,237,17,129,238,127,
|
||||
31,101,176,36,30,110,209,34,203,135,232,68,149,49,134,126,212,79,76,117,
|
||||
104,210,211,224,253,100,220,109,116,88,13,151,154,69,21,51,103
|
||||
};
|
||||
|
||||
static const int perm_d[]={
|
||||
94,234,145,235,151,166,187,238,4,5,128,115,87,107,229,175,190,108,218,
|
||||
32,17,220,97,90,122,121,71,109,64,227,225,75,81,19,27,162,3,89,139,69,
|
||||
92,26,48,215,116,191,114,2,104,157,66,39,1,127,96,124,30,0,82,233,219,
|
||||
42,131,173,35,201,182,144,14,98,148,244,160,159,179,91,31,68,119,154,
|
||||
205,113,149,167,44,60,18,228,251,245,43,10,80,15,129,67,181,174,6,45,
|
||||
194,237,213,52,99,232,211,212,164,217,57,153,156,102,134,20,249,132,55,
|
||||
204,65,33,231,85,61,37,163,193,189,170,226,63,168,236,165,224,242,195,
|
||||
41,200,40,70,112,100,36,172,130,74,137,252,243,135,230,161,207,16,146,
|
||||
198,118,150,24,29,250,188,25,209,103,23,105,47,7,46,133,83,184,50,79,
|
||||
110,120,53,253,206,214,9,240,101,147,152,183,254,59,126,216,197,171,51,
|
||||
208,248,202,58,176,28,72,177,185,141,12,11,56,222,86,178,155,223,88,111,
|
||||
73,142,210,138,239,221,199,192,84,93,241,125,76,77,255,95,8,78,247,186,
|
||||
123,196,13,140,180,143,54,106,136,34,62,169,38,117,22,21,49,203,158,246
|
||||
};
|
||||
|
||||
static const float impulse_xcoords[]={
|
||||
0.788235,0.541176,0.972549,0.082353,0.352941,0.811765,0.286275,0.752941,
|
||||
0.203922,0.705882,0.537255,0.886275,0.580392,0.137255,0.800000,0.533333,
|
||||
0.117647,0.447059,0.129412,0.925490,0.086275,0.478431,0.666667,0.568627,
|
||||
0.678431,0.313725,0.321569,0.349020,0.988235,0.419608,0.898039,0.219608,
|
||||
0.243137,0.623529,0.501961,0.772549,0.952941,0.517647,0.949020,0.701961,
|
||||
0.454902,0.505882,0.564706,0.960784,0.207843,0.007843,0.831373,0.184314,
|
||||
0.576471,0.462745,0.572549,0.247059,0.262745,0.694118,0.615686,0.121569,
|
||||
0.384314,0.749020,0.145098,0.717647,0.415686,0.607843,0.105882,0.101961,
|
||||
0.200000,0.807843,0.521569,0.780392,0.466667,0.552941,0.996078,0.627451,
|
||||
0.992157,0.529412,0.407843,0.011765,0.709804,0.458824,0.058824,0.819608,
|
||||
0.176471,0.317647,0.392157,0.223529,0.156863,0.490196,0.325490,0.074510,
|
||||
0.239216,0.164706,0.890196,0.603922,0.921569,0.839216,0.854902,0.098039,
|
||||
0.686275,0.843137,0.152941,0.372549,0.062745,0.474510,0.486275,0.227451,
|
||||
0.400000,0.298039,0.309804,0.274510,0.054902,0.815686,0.647059,0.635294,
|
||||
0.662745,0.976471,0.094118,0.509804,0.650980,0.211765,0.180392,0.003922,
|
||||
0.827451,0.278431,0.023529,0.525490,0.450980,0.725490,0.690196,0.941176,
|
||||
0.639216,0.560784,0.196078,0.364706,0.043137,0.494118,0.796078,0.113725,
|
||||
0.760784,0.729412,0.258824,0.290196,0.584314,0.674510,0.823529,0.905882,
|
||||
0.917647,0.070588,0.862745,0.345098,0.913725,0.937255,0.031373,0.215686,
|
||||
0.768627,0.333333,0.411765,0.423529,0.945098,0.721569,0.039216,0.792157,
|
||||
0.956863,0.266667,0.254902,0.047059,0.294118,0.658824,0.250980,1.000000,
|
||||
0.984314,0.756863,0.027451,0.305882,0.835294,0.513725,0.360784,0.776471,
|
||||
0.611765,0.192157,0.866667,0.858824,0.592157,0.803922,0.141176,0.435294,
|
||||
0.588235,0.619608,0.341176,0.109804,0.356863,0.270588,0.737255,0.847059,
|
||||
0.050980,0.764706,0.019608,0.870588,0.933333,0.784314,0.549020,0.337255,
|
||||
0.631373,0.929412,0.231373,0.427451,0.078431,0.498039,0.968627,0.654902,
|
||||
0.125490,0.698039,0.015686,0.878431,0.713725,0.368627,0.431373,0.874510,
|
||||
0.403922,0.556863,0.443137,0.964706,0.909804,0.301961,0.035294,0.850980,
|
||||
0.882353,0.741176,0.380392,0.133333,0.470588,0.643137,0.282353,0.396078,
|
||||
0.980392,0.168627,0.149020,0.235294,0.670588,0.596078,0.733333,0.160784,
|
||||
0.376471,0.682353,0.545098,0.482353,0.745098,0.894118,0.188235,0.329412,
|
||||
0.439216,0.901961,0.000000,0.600000,0.388235,0.172549,0.090196,0.066667
|
||||
};
|
||||
|
||||
static const float impulse_ycoords[]={
|
||||
0.827451,0.337255,0.941176,0.886275,0.878431,0.239216,0.400000,0.164706,
|
||||
0.490196,0.411765,0.964706,0.349020,0.803922,0.317647,0.647059,0.431373,
|
||||
0.933333,0.156863,0.094118,0.219608,0.039216,0.521569,0.498039,0.705882,
|
||||
0.717647,0.047059,0.631373,0.517647,0.984314,0.847059,0.482353,0.439216,
|
||||
0.250980,0.862745,0.690196,0.913725,0.270588,0.070588,0.027451,0.694118,
|
||||
0.811765,0.000000,0.494118,0.823529,0.800000,0.600000,0.003922,0.443137,
|
||||
0.639216,0.376471,0.031373,0.035294,0.552941,0.215686,0.305882,0.133333,
|
||||
0.564706,0.176471,0.211765,0.874510,0.360784,0.654902,0.223529,0.807843,
|
||||
0.372549,0.137255,0.321569,0.015686,0.007843,0.262745,0.125490,0.078431,
|
||||
0.396078,0.976471,0.929412,1.000000,0.937255,0.509804,0.188235,0.850980,
|
||||
0.831373,0.392157,0.741176,0.541176,0.592157,0.286275,0.345098,0.572549,
|
||||
0.537255,0.725490,0.839216,0.184314,0.772549,0.149020,0.505882,0.423529,
|
||||
0.780392,0.011765,0.890196,0.086275,0.427451,0.023529,0.788235,0.050980,
|
||||
0.760784,0.603922,0.066667,0.643137,0.623529,0.960784,0.172549,0.333333,
|
||||
0.082353,0.290196,0.992157,0.709804,0.894118,0.596078,0.243137,0.752941,
|
||||
0.486275,0.670588,0.949020,0.784314,0.145098,0.560784,0.513725,0.180392,
|
||||
0.580392,0.996078,0.380392,0.556863,0.407843,0.945098,0.117647,0.058824,
|
||||
0.678431,0.129412,0.192157,0.105882,0.968627,0.545098,0.462745,0.227451,
|
||||
0.019608,0.866667,0.674510,0.207843,0.627451,0.819608,0.921569,0.356863,
|
||||
0.447059,0.533333,0.435294,0.341176,0.054902,0.529412,0.235294,0.764706,
|
||||
0.615686,0.043137,0.745098,0.266667,0.501961,0.619608,0.776471,0.450980,
|
||||
0.309804,0.325490,0.200000,0.635294,0.247059,0.698039,0.721569,0.168627,
|
||||
0.854902,0.141176,0.611765,0.525490,0.415686,0.298039,0.254902,0.858824,
|
||||
0.568627,0.329412,0.062745,0.843137,0.588235,0.733333,0.607843,0.478431,
|
||||
0.576471,0.662745,0.470588,0.666667,0.980392,0.113725,0.898039,0.203922,
|
||||
0.294118,0.152941,0.098039,0.909804,0.796078,0.768627,0.713725,0.196078,
|
||||
0.368627,0.419608,0.352941,0.090196,0.749020,0.121569,0.882353,0.278431,
|
||||
0.388235,0.917647,0.701961,0.729412,0.835294,0.258824,0.301961,0.101961,
|
||||
0.792157,0.474510,0.686275,0.658824,0.364706,0.682353,0.458824,0.815686,
|
||||
0.282353,0.160784,0.870588,0.988235,0.756863,0.549020,0.274510,0.384314,
|
||||
0.650980,0.737255,0.901961,0.956863,0.972549,0.584314,0.925490,0.403922,
|
||||
0.074510,0.454902,0.952941,0.109804,0.313725,0.905882,0.231373,0.466667
|
||||
};
|
||||
|
||||
static const float impulse_zcoords[]={
|
||||
0.082353,0.643137,0.415686,0.929412,0.568627,0.509804,0.537255,0.815686,
|
||||
0.698039,0.941176,0.776471,0.752941,0.737255,0.525490,0.498039,0.423529,
|
||||
0.792157,0.125490,0.619608,0.164706,0.368627,0.870588,0.137255,0.372549,
|
||||
0.466667,0.486275,0.501961,0.513725,0.709804,0.576471,0.203922,0.258824,
|
||||
0.152941,0.556863,0.223529,0.047059,0.235294,0.474510,0.764706,0.552941,
|
||||
0.847059,0.145098,0.176471,0.937255,0.654902,0.894118,0.729412,0.054902,
|
||||
0.666667,0.749020,0.262745,0.560784,0.431373,0.286275,0.352941,0.239216,
|
||||
0.156863,0.839216,0.427451,0.949020,0.384314,0.227451,0.180392,0.074510,
|
||||
0.172549,0.356863,0.066667,0.517647,0.447059,0.184314,0.062745,0.670588,
|
||||
0.603922,0.219608,0.270588,0.976471,0.505882,0.627451,0.819608,0.854902,
|
||||
0.843137,0.019608,0.713725,0.035294,0.925490,0.349020,0.866667,0.701961,
|
||||
0.909804,0.811765,0.717647,0.141176,0.917647,0.023529,0.098039,0.803922,
|
||||
0.733333,0.658824,0.827451,0.133333,0.858824,0.800000,0.635294,1.000000,
|
||||
0.078431,0.450980,0.835294,0.321569,0.360784,0.529412,0.725490,0.572549,
|
||||
0.639216,0.341176,0.533333,0.094118,0.149020,0.545098,0.101961,0.901961,
|
||||
0.278431,0.694118,0.521569,0.490196,0.454902,0.329412,0.274510,0.027451,
|
||||
0.745098,0.933333,0.443137,0.168627,0.192157,0.988235,0.070588,0.972549,
|
||||
0.768627,0.400000,0.470588,0.207843,0.215686,0.388235,0.439216,0.780392,
|
||||
0.482353,0.121569,0.964706,0.086275,0.890196,0.337255,0.109804,0.305882,
|
||||
0.113725,0.435294,0.721569,0.772549,0.807843,0.741176,0.254902,0.596078,
|
||||
0.494118,0.317647,0.419608,0.000000,0.188235,0.031373,0.376471,0.380392,
|
||||
0.611765,0.945098,0.411765,0.313725,0.874510,0.588235,0.678431,0.160784,
|
||||
0.007843,0.090196,0.850980,0.788235,0.705882,0.266667,0.309804,0.541176,
|
||||
0.231373,0.129412,0.294118,0.243137,0.913725,0.996078,0.117647,0.478431,
|
||||
0.290196,0.549020,0.682353,0.784314,0.396078,0.831373,0.984314,0.584314,
|
||||
0.039216,0.250980,0.600000,0.392157,0.298039,0.050980,0.364706,0.105882,
|
||||
0.623529,0.886275,0.980392,0.325490,0.247059,0.690196,0.674510,0.960784,
|
||||
0.647059,0.211765,0.882353,0.686275,0.823529,0.058824,0.956863,0.043137,
|
||||
0.345098,0.301961,0.592157,0.862745,0.607843,0.458824,0.282353,0.003922,
|
||||
0.580392,0.760784,0.564706,0.011765,0.968627,0.905882,0.756863,0.952941,
|
||||
0.662745,0.015686,0.898039,0.196078,0.333333,0.992157,0.650980,0.407843,
|
||||
0.796078,0.615686,0.878431,0.921569,0.631373,0.200000,0.403922,0.462745
|
||||
};
|
||||
|
2294
mathlib/polyhedron.cpp
Normal file
2294
mathlib/polyhedron.cpp
Normal file
File diff suppressed because it is too large
Load Diff
39
mathlib/powsse.cpp
Normal file
39
mathlib/powsse.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#include "mathlib/ssemath.h"
|
||||
|
||||
fltx4 Pow_FixedPoint_Exponent_SIMD( const fltx4 & x, int exponent)
|
||||
{
|
||||
fltx4 rslt=Four_Ones; // x^0=1.0
|
||||
int xp=abs(exponent);
|
||||
if (xp & 3) // fraction present?
|
||||
{
|
||||
fltx4 sq_rt=SqrtEstSIMD(x);
|
||||
if (xp & 1) // .25?
|
||||
rslt=SqrtEstSIMD(sq_rt); // x^.25
|
||||
if (xp & 2)
|
||||
rslt=MulSIMD(rslt,sq_rt);
|
||||
}
|
||||
xp>>=2; // strip fraction
|
||||
fltx4 curpower=x; // curpower iterates through x,x^2,x^4,x^8,x^16...
|
||||
|
||||
while(1)
|
||||
{
|
||||
if (xp & 1)
|
||||
rslt=MulSIMD(rslt,curpower);
|
||||
xp>>=1;
|
||||
if (xp)
|
||||
curpower=MulSIMD(curpower,curpower);
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (exponent<0)
|
||||
return ReciprocalEstSIMD(rslt); // pow(x,-b)=1/pow(x,b)
|
||||
else
|
||||
return rslt;
|
||||
}
|
||||
|
678
mathlib/quantize.cpp
Normal file
678
mathlib/quantize.cpp
Normal file
@ -0,0 +1,678 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
#ifndef STDIO_H
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#ifndef STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#ifndef QUANTIZE_H
|
||||
#include <quantize.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
static int current_ndims;
|
||||
static struct QuantizedValue *current_root;
|
||||
static int current_ssize;
|
||||
|
||||
static uint8 *current_weights;
|
||||
|
||||
double SquaredError;
|
||||
|
||||
#define SPLIT_THEN_SORT 1
|
||||
|
||||
#define SQ(x) ((x)*(x))
|
||||
|
||||
static struct QuantizedValue *AllocQValue(void)
|
||||
{
|
||||
struct QuantizedValue *ret=new QuantizedValue;
|
||||
ret->Samples=0;
|
||||
ret->Children[0]=ret->Children[1]=0;
|
||||
ret->NSamples=0;
|
||||
|
||||
ret->ErrorMeasure=new double[current_ndims];
|
||||
ret->Mean=new uint8[current_ndims];
|
||||
ret->Mins=new uint8[current_ndims];
|
||||
ret->Maxs=new uint8[current_ndims];
|
||||
ret->Sums=new int [current_ndims];
|
||||
memset(ret->Sums,0,sizeof(int)*current_ndims);
|
||||
ret->NQuant=0;
|
||||
ret->sortdim=-1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FreeQuantization(struct QuantizedValue *t)
|
||||
{
|
||||
if (t)
|
||||
{
|
||||
delete[] t->ErrorMeasure;
|
||||
delete[] t->Mean;
|
||||
delete[] t->Mins;
|
||||
delete[] t->Maxs;
|
||||
FreeQuantization(t->Children[0]);
|
||||
FreeQuantization(t->Children[1]);
|
||||
delete[] t->Sums;
|
||||
delete[] t;
|
||||
}
|
||||
}
|
||||
|
||||
static int QNumSort(void const *a, void const *b)
|
||||
{
|
||||
int32 as=((struct Sample *) a)->QNum;
|
||||
int32 bs=((struct Sample *) b)->QNum;
|
||||
if (as==bs) return 0;
|
||||
return (as>bs)?1:-1;
|
||||
}
|
||||
|
||||
#if SPLIT_THEN_SORT
|
||||
#else
|
||||
static int current_sort_dim;
|
||||
|
||||
static int samplesort(void const *a, void const *b)
|
||||
{
|
||||
uint8 as=((struct Sample *) a)->Value[current_sort_dim];
|
||||
uint8 bs=((struct Sample *) b)->Value[current_sort_dim];
|
||||
if (as==bs) return 0;
|
||||
return (as>bs)?1:-1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int sortlong(void const *a, void const *b)
|
||||
{
|
||||
// treat the entire vector of values as a long integer for duplicate removal.
|
||||
return memcmp(((struct Sample *) a)->Value,
|
||||
((struct Sample *) b)->Value,current_ndims);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define NEXTSAMPLE(s) ( (struct Sample *) (((uint8 *) s)+current_ssize))
|
||||
#define SAMPLE(s,i) NthSample(s,i,current_ndims)
|
||||
|
||||
static void SetNDims(int n)
|
||||
{
|
||||
current_ssize=sizeof(struct Sample)+(n-1);
|
||||
current_ndims=n;
|
||||
}
|
||||
|
||||
int CompressSamples(struct Sample *s, int nsamples, int ndims)
|
||||
{
|
||||
SetNDims(ndims);
|
||||
qsort(s,nsamples,current_ssize,sortlong);
|
||||
// now, they are all sorted by treating all dimensions as a large number.
|
||||
// we may now remove duplicates.
|
||||
struct Sample *src=s;
|
||||
struct Sample *dst=s;
|
||||
struct Sample *lastdst=dst;
|
||||
dst=NEXTSAMPLE(dst); // copy first sample to get the ball rolling
|
||||
src=NEXTSAMPLE(src);
|
||||
int noutput=1;
|
||||
while(--nsamples) // while some remain
|
||||
{
|
||||
if (memcmp(src->Value,lastdst->Value,current_ndims))
|
||||
{
|
||||
// yikes, a difference has been found!
|
||||
memcpy(dst,src,current_ssize);
|
||||
lastdst=dst;
|
||||
dst=NEXTSAMPLE(dst);
|
||||
noutput++;
|
||||
}
|
||||
else
|
||||
lastdst->Count++;
|
||||
src=NEXTSAMPLE(src);
|
||||
}
|
||||
return noutput;
|
||||
}
|
||||
|
||||
void PrintSamples(struct Sample const *s, int nsamples, int ndims)
|
||||
{
|
||||
SetNDims(ndims);
|
||||
int cnt=0;
|
||||
while(nsamples--)
|
||||
{
|
||||
printf("sample #%d, count=%d, values=\n { ",cnt++,s->Count);
|
||||
for(int d=0;d<ndims;d++)
|
||||
printf("%02x,",s->Value[d]);
|
||||
printf("}\n");
|
||||
s=NEXTSAMPLE(s);
|
||||
}
|
||||
}
|
||||
|
||||
void PrintQTree(struct QuantizedValue const *p,int idlevel)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (p)
|
||||
{
|
||||
for(i=0;i<idlevel;i++)
|
||||
printf(" ");
|
||||
printf("node=%p NSamples=%d value=%d Mean={",p,p->NSamples,p->value);
|
||||
for(i=0;i<current_ndims;i++)
|
||||
printf("%x,",p->Mean[i]);
|
||||
printf("}\n");
|
||||
for(i=0;i<idlevel;i++)
|
||||
printf(" ");
|
||||
printf("Errors={");
|
||||
for(i=0;i<current_ndims;i++)
|
||||
printf("%f,",p->ErrorMeasure[i]);
|
||||
printf("}\n");
|
||||
for(i=0;i<idlevel;i++)
|
||||
printf(" ");
|
||||
printf("Mins={");
|
||||
for(i=0;i<current_ndims;i++)
|
||||
printf("%d,",p->Mins[i]);
|
||||
printf("} Maxs={");
|
||||
for(i=0;i<current_ndims;i++)
|
||||
printf("%d,",p->Maxs[i]);
|
||||
printf("}\n");
|
||||
PrintQTree(p->Children[0],idlevel+2);
|
||||
PrintQTree(p->Children[1],idlevel+2);
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateStats(struct QuantizedValue *v)
|
||||
{
|
||||
// first, find mean
|
||||
int32 Means[MAXDIMS];
|
||||
double Errors[MAXDIMS];
|
||||
double WorstError[MAXDIMS];
|
||||
int i,j;
|
||||
|
||||
memset(Means,0,sizeof(Means));
|
||||
int N=0;
|
||||
for(i=0;i<v->NSamples;i++)
|
||||
{
|
||||
struct Sample *s=SAMPLE(v->Samples,i);
|
||||
N+=s->Count;
|
||||
for(j=0;j<current_ndims;j++)
|
||||
{
|
||||
uint8 v=s->Value[j];
|
||||
Means[j]+=v*s->Count;
|
||||
}
|
||||
}
|
||||
for(j=0;j<current_ndims;j++)
|
||||
{
|
||||
if (N) v->Mean[j]=(uint8) (Means[j]/N);
|
||||
Errors[j]=WorstError[j]=0.;
|
||||
}
|
||||
for(i=0;i<v->NSamples;i++)
|
||||
{
|
||||
struct Sample *s=SAMPLE(v->Samples,i);
|
||||
double c=s->Count;
|
||||
for(j=0;j<current_ndims;j++)
|
||||
{
|
||||
double diff=SQ(s->Value[j]-v->Mean[j]);
|
||||
Errors[j]+=c*diff; // charles uses abs not sq()
|
||||
if (diff>WorstError[j])
|
||||
WorstError[j]=diff;
|
||||
}
|
||||
}
|
||||
v->TotalError=0.;
|
||||
double ErrorScale=1.; // /sqrt((double) (N));
|
||||
for(j=0;j<current_ndims;j++)
|
||||
{
|
||||
v->ErrorMeasure[j]=(ErrorScale*Errors[j]*current_weights[j]);
|
||||
v->TotalError+=v->ErrorMeasure[j];
|
||||
#if SPLIT_THEN_SORT
|
||||
v->ErrorMeasure[j]*=WorstError[j];
|
||||
#endif
|
||||
}
|
||||
v->TotSamples=N;
|
||||
}
|
||||
|
||||
static int ErrorDim;
|
||||
static double ErrorVal;
|
||||
static struct QuantizedValue *ErrorNode;
|
||||
|
||||
static void UpdateWorst(struct QuantizedValue *q)
|
||||
{
|
||||
if (q->Children[0])
|
||||
{
|
||||
// not a leaf node
|
||||
UpdateWorst(q->Children[0]);
|
||||
UpdateWorst(q->Children[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (q->TotalError>ErrorVal)
|
||||
{
|
||||
ErrorVal=q->TotalError;
|
||||
ErrorNode=q;
|
||||
ErrorDim=0;
|
||||
for(int d=0;d<current_ndims;d++)
|
||||
if (q->ErrorMeasure[d]>q->ErrorMeasure[ErrorDim])
|
||||
ErrorDim=d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int FindWorst(void)
|
||||
{
|
||||
ErrorVal=-1.;
|
||||
UpdateWorst(current_root);
|
||||
return (ErrorVal>0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void SubdivideNode(struct QuantizedValue *n, int whichdim)
|
||||
{
|
||||
int NAdded=0;
|
||||
int i;
|
||||
|
||||
#if SPLIT_THEN_SORT
|
||||
// we will try the "split then sort" method. This works by finding the
|
||||
// means for all samples above and below the mean along the given axis.
|
||||
// samples are then split into two groups, with the selection based upon
|
||||
// which of the n-dimensional means the sample is closest to.
|
||||
double LocalMean[MAXDIMS][2];
|
||||
int totsamps[2];
|
||||
for(i=0;i<current_ndims;i++)
|
||||
LocalMean[i][0]=LocalMean[i][1]=0.;
|
||||
totsamps[0]=totsamps[1]=0;
|
||||
uint8 minv=255;
|
||||
uint8 maxv=0;
|
||||
struct Sample *minS=0,*maxS=0;
|
||||
for(i=0;i<n->NSamples;i++)
|
||||
{
|
||||
uint8 v;
|
||||
int whichside=1;
|
||||
struct Sample *sl;
|
||||
sl=SAMPLE(n->Samples,i);
|
||||
v=sl->Value[whichdim];
|
||||
if (v<minv) { minv=v; minS=sl; }
|
||||
if (v>maxv) { maxv=v; maxS=sl; }
|
||||
if (v<n->Mean[whichdim])
|
||||
whichside=0;
|
||||
totsamps[whichside]+=sl->Count;
|
||||
for(int d=0;d<current_ndims;d++)
|
||||
LocalMean[d][whichside]+=
|
||||
sl->Count*sl->Value[d];
|
||||
}
|
||||
|
||||
if (totsamps[0] && totsamps[1])
|
||||
for(i=0;i<current_ndims;i++)
|
||||
{
|
||||
LocalMean[i][0]/=totsamps[0];
|
||||
LocalMean[i][1]/=totsamps[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
// it is possible that the clustering failed to split the samples.
|
||||
// this can happen with a heavily biased sample (i.e. all black
|
||||
// with a few stars). If this happens, we will cluster around the
|
||||
// extrema instead. LocalMean[i][0] will be the point with the lowest
|
||||
// value on the dimension and LocalMean[i][1] the one with the lowest
|
||||
// value.
|
||||
for(int i=0;i<current_ndims;i++)
|
||||
{
|
||||
LocalMean[i][0]=minS->Value[i];
|
||||
LocalMean[i][1]=maxS->Value[i];
|
||||
}
|
||||
}
|
||||
|
||||
// now, we have 2 n-dimensional means. We will label each sample
|
||||
// for which one it is nearer to by using the QNum field.
|
||||
for(i=0;i<n->NSamples;i++)
|
||||
{
|
||||
double dist[2];
|
||||
dist[0]=dist[1]=0.;
|
||||
struct Sample *s=SAMPLE(n->Samples,i);
|
||||
for(int d=0;d<current_ndims;d++)
|
||||
for(int w=0;w<2;w++)
|
||||
dist[w]+=current_weights[d]*SQ(LocalMean[d][w]-s->Value[d]);
|
||||
s->QNum=(dist[0]<dist[1]);
|
||||
}
|
||||
|
||||
|
||||
// hey ho! we have now labelled each one with a candidate bin. Let's
|
||||
// sort the array by moving the 0-labelled ones to the head of the array.
|
||||
n->sortdim=-1;
|
||||
qsort(n->Samples,n->NSamples,current_ssize,QNumSort);
|
||||
for(i=0;i<n->NSamples;i++,NAdded++)
|
||||
if (SAMPLE(n->Samples,i)->QNum)
|
||||
break;
|
||||
|
||||
#else
|
||||
if (whichdim != n->sortdim)
|
||||
{
|
||||
current_sort_dim=whichdim;
|
||||
qsort(n->Samples,n->NSamples,current_ssize,samplesort);
|
||||
n->sortdim=whichdim;
|
||||
}
|
||||
// now, the samples are sorted along the proper dimension. we need
|
||||
// to find the place to cut in order to split the node. this is
|
||||
// complicated by the fact that each sample entry can represent many
|
||||
// samples. What we will do is start at the beginning of the array,
|
||||
// adding samples to the first node, until either the number added
|
||||
// is >=TotSamples/2, or there is only one left.
|
||||
int TotAdded=0;
|
||||
for(;;)
|
||||
{
|
||||
if (NAdded==n->NSamples-1)
|
||||
break;
|
||||
if (TotAdded>=n->TotSamples/2)
|
||||
break;
|
||||
TotAdded+=SAMPLE(n->Samples,NAdded)->Count;
|
||||
NAdded++;
|
||||
}
|
||||
#endif
|
||||
struct QuantizedValue *a=AllocQValue();
|
||||
a->sortdim=n->sortdim;
|
||||
a->Samples=n->Samples;
|
||||
a->NSamples=NAdded;
|
||||
n->Children[0]=a;
|
||||
UpdateStats(a);
|
||||
a=AllocQValue();
|
||||
a->Samples=SAMPLE(n->Samples,NAdded);
|
||||
a->NSamples=n->NSamples-NAdded;
|
||||
a->sortdim=n->sortdim;
|
||||
n->Children[1]=a;
|
||||
UpdateStats(a);
|
||||
}
|
||||
|
||||
static int colorid=0;
|
||||
|
||||
static void Label(struct QuantizedValue *q, int updatecolor)
|
||||
{
|
||||
// fill in max/min values for tree, etc.
|
||||
if (q)
|
||||
{
|
||||
Label(q->Children[0],updatecolor);
|
||||
Label(q->Children[1],updatecolor);
|
||||
if (! q->Children[0]) // leaf node?
|
||||
{
|
||||
if (updatecolor)
|
||||
{
|
||||
q->value=colorid++;
|
||||
for(int j=0;j<q->NSamples;j++)
|
||||
{
|
||||
SAMPLE(q->Samples,j)->QNum=q->value;
|
||||
SAMPLE(q->Samples,j)->qptr=q;
|
||||
}
|
||||
}
|
||||
for(int i=0;i<current_ndims;i++)
|
||||
{
|
||||
q->Mins[i]=q->Mean[i];
|
||||
q->Maxs[i]=q->Mean[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
for(int i=0;i<current_ndims;i++)
|
||||
{
|
||||
q->Mins[i]=MIN(q->Children[0]->Mins[i],q->Children[1]->Mins[i]);
|
||||
q->Maxs[i]=MAX(q->Children[0]->Maxs[i],q->Children[1]->Maxs[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct QuantizedValue *FindQNode(struct QuantizedValue const *q, int32 code)
|
||||
{
|
||||
if (! (q->Children[0]))
|
||||
if (code==q->value) return (struct QuantizedValue *) q;
|
||||
else return 0;
|
||||
else
|
||||
{
|
||||
struct QuantizedValue *found=FindQNode(q->Children[0],code);
|
||||
if (! found) found=FindQNode(q->Children[1],code);
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CheckInRange(struct QuantizedValue *q, uint8 *max, uint8 *min)
|
||||
{
|
||||
if (q)
|
||||
{
|
||||
if (q->Children[0])
|
||||
{
|
||||
// non-leaf node
|
||||
CheckInRange(q->Children[0],q->Maxs, q->Mins);
|
||||
CheckInRange(q->Children[1],q->Maxs, q->Mins);
|
||||
CheckInRange(q->Children[0],max, min);
|
||||
CheckInRange(q->Children[1],max, min);
|
||||
}
|
||||
for (int i=0;i<current_ndims;i++)
|
||||
{
|
||||
if (q->Maxs[i]>max[i]) printf("error1\n");
|
||||
if (q->Mins[i]<min[i]) printf("error2\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct QuantizedValue *Quantize(struct Sample *s, int nsamples, int ndims,
|
||||
int nvalues, uint8 *weights, int firstvalue)
|
||||
{
|
||||
SetNDims(ndims);
|
||||
current_weights=weights;
|
||||
current_root=AllocQValue();
|
||||
current_root->Samples=s;
|
||||
current_root->NSamples=nsamples;
|
||||
UpdateStats(current_root);
|
||||
while(--nvalues)
|
||||
{
|
||||
if (! FindWorst())
|
||||
break; // if <n unique ones, stop now
|
||||
SubdivideNode(ErrorNode,ErrorDim);
|
||||
}
|
||||
colorid=firstvalue;
|
||||
Label(current_root,1);
|
||||
return current_root;
|
||||
}
|
||||
|
||||
double MinimumError(struct QuantizedValue const *q, uint8 const *sample,
|
||||
int ndims, uint8 const *weights)
|
||||
{
|
||||
double err=0;
|
||||
for(int i=0;i<ndims;i++)
|
||||
{
|
||||
int val1;
|
||||
int val2=sample[i];
|
||||
if ((q->Mins[i]<=val2) && (q->Maxs[i]>=val2)) val1=val2;
|
||||
else
|
||||
{
|
||||
val1=(val2<=q->Mins[i])?q->Mins[i]:q->Maxs[i];
|
||||
}
|
||||
err+=weights[i]*SQ(val1-val2);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
double MaximumError(struct QuantizedValue const *q, uint8 const *sample,
|
||||
int ndims, uint8 const *weights)
|
||||
{
|
||||
double err=0;
|
||||
for(int i=0;i<ndims;i++)
|
||||
{
|
||||
int val2=sample[i];
|
||||
int val1=(abs(val2-q->Mins[i])>abs(val2-q->Maxs[i]))?
|
||||
q->Mins[i]:
|
||||
q->Maxs[i];
|
||||
err+=weights[i]*SQ(val2-val1);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// heap (priority queue) routines used for nearest-neghbor searches
|
||||
struct FHeap {
|
||||
int heap_n;
|
||||
double *heap[MAXQUANT];
|
||||
};
|
||||
|
||||
void InitHeap(struct FHeap *h)
|
||||
{
|
||||
h->heap_n=0;
|
||||
}
|
||||
|
||||
|
||||
void UpHeap(int k, struct FHeap *h)
|
||||
{
|
||||
double *tmpk=h->heap[k];
|
||||
double tmpkn=*tmpk;
|
||||
while((k>1) && (tmpkn <= *(h->heap[k/2])))
|
||||
{
|
||||
h->heap[k]=h->heap[k/2];
|
||||
k/=2;
|
||||
}
|
||||
h->heap[k]=tmpk;
|
||||
}
|
||||
|
||||
void HeapInsert(struct FHeap *h,double *elem)
|
||||
{
|
||||
h->heap_n++;
|
||||
h->heap[h->heap_n]=elem;
|
||||
UpHeap(h->heap_n,h);
|
||||
}
|
||||
|
||||
void DownHeap(int k, struct FHeap *h)
|
||||
{
|
||||
double *v=h->heap[k];
|
||||
while(k<=h->heap_n/2)
|
||||
{
|
||||
int j=2*k;
|
||||
if (j<h->heap_n)
|
||||
if (*(h->heap[j]) >= *(h->heap[j+1]))
|
||||
j++;
|
||||
if (*v < *(h->heap[j]))
|
||||
{
|
||||
h->heap[k]=v;
|
||||
return;
|
||||
}
|
||||
h->heap[k]=h->heap[j]; k=j;
|
||||
}
|
||||
h->heap[k]=v;
|
||||
}
|
||||
|
||||
void *RemoveHeapItem(struct FHeap *h)
|
||||
{
|
||||
void *ret=0;
|
||||
if (h->heap_n!=0)
|
||||
{
|
||||
ret=h->heap[1];
|
||||
h->heap[1]=h->heap[h->heap_n];
|
||||
h->heap_n--;
|
||||
DownHeap(1,h);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// now, nearest neighbor finder. Use a heap to traverse the tree, stopping
|
||||
// when there are no nodes with a minimum error < the current error.
|
||||
|
||||
struct FHeap TheQueue;
|
||||
|
||||
#define PUSHNODE(a) { \
|
||||
(a)->MinError=MinimumError(a,sample,ndims,weights); \
|
||||
if ((a)->MinError < besterror) HeapInsert(&TheQueue,&(a)->MinError); \
|
||||
}
|
||||
|
||||
struct QuantizedValue *FindMatch(uint8 const *sample, int ndims,
|
||||
uint8 *weights, struct QuantizedValue *q)
|
||||
{
|
||||
InitHeap(&TheQueue);
|
||||
struct QuantizedValue *bestmatch=0;
|
||||
double besterror=1.0e63;
|
||||
PUSHNODE(q);
|
||||
for(;;)
|
||||
{
|
||||
struct QuantizedValue *test=(struct QuantizedValue *)
|
||||
RemoveHeapItem(&TheQueue);
|
||||
if (! test) break; // heap empty
|
||||
// printf("got pop node =%p minerror=%f\n",test,test->MinError);
|
||||
|
||||
if (test->MinError>besterror) break;
|
||||
if (test->Children[0])
|
||||
{
|
||||
// it's a parent node. put the children on the queue
|
||||
struct QuantizedValue *c1=test->Children[0];
|
||||
struct QuantizedValue *c2=test->Children[1];
|
||||
c1->MinError=MinimumError(c1,sample,ndims,weights);
|
||||
if (c1->MinError < besterror)
|
||||
HeapInsert(&TheQueue,&(c1->MinError));
|
||||
c2->MinError=MinimumError(c2,sample,ndims,weights);
|
||||
if (c2->MinError < besterror)
|
||||
HeapInsert(&TheQueue,&(c2->MinError));
|
||||
}
|
||||
else
|
||||
{
|
||||
// it's a leaf node. This must be a new minimum or the MinError
|
||||
// test would have failed.
|
||||
if (test->MinError < besterror)
|
||||
{
|
||||
bestmatch=test;
|
||||
besterror=test->MinError;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bestmatch)
|
||||
{
|
||||
SquaredError+=besterror;
|
||||
bestmatch->NQuant++;
|
||||
for(int i=0;i<ndims;i++)
|
||||
bestmatch->Sums[i]+=sample[i];
|
||||
}
|
||||
return bestmatch;
|
||||
}
|
||||
|
||||
static void RecalcMeans(struct QuantizedValue *q)
|
||||
{
|
||||
if (q)
|
||||
{
|
||||
if (q->Children[0])
|
||||
{
|
||||
// not a leaf, invoke recursively.
|
||||
RecalcMeans(q->Children[0]);
|
||||
RecalcMeans(q->Children[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// it's a leaf. Set the means
|
||||
if (q->NQuant)
|
||||
{
|
||||
for(int i=0;i<current_ndims;i++)
|
||||
{
|
||||
q->Mean[i]=(uint8) (q->Sums[i]/q->NQuant);
|
||||
q->Sums[i]=0;
|
||||
}
|
||||
q->NQuant=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OptimizeQuantizer(struct QuantizedValue *q, int ndims)
|
||||
{
|
||||
SetNDims(ndims);
|
||||
RecalcMeans(q); // reset q values
|
||||
Label(q,0); // update max/mins
|
||||
}
|
||||
|
||||
|
||||
static void RecalcStats(struct QuantizedValue *q)
|
||||
{
|
||||
if (q)
|
||||
{
|
||||
UpdateStats(q);
|
||||
RecalcStats(q->Children[0]);
|
||||
RecalcStats(q->Children[1]);
|
||||
}
|
||||
}
|
||||
|
||||
void RecalculateValues(struct QuantizedValue *q, int ndims)
|
||||
{
|
||||
SetNDims(ndims);
|
||||
RecalcStats(q);
|
||||
Label(q,0);
|
||||
}
|
109
mathlib/randsse.cpp
Normal file
109
mathlib/randsse.cpp
Normal file
@ -0,0 +1,109 @@
|
||||
//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: generates 4 randum numbers in the range 0..1 quickly, using SIMD
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#include <math.h>
|
||||
#include <float.h> // Needed for FLT_EPSILON
|
||||
#include "basetypes.h"
|
||||
#include <memory.h>
|
||||
#include "tier0/dbg.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
#include "mathlib/vector.h"
|
||||
#include "mathlib/ssemath.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
// see knuth volume 3 for insight.
|
||||
|
||||
class SIMDRandStreamContext
|
||||
{
|
||||
fltx4 m_RandY[55];
|
||||
|
||||
fltx4 *m_pRand_J, *m_pRand_K;
|
||||
|
||||
|
||||
public:
|
||||
void Seed( uint32 seed )
|
||||
{
|
||||
m_pRand_J=m_RandY+23; m_pRand_K=m_RandY+54;
|
||||
for(int i=0;i<55;i++)
|
||||
{
|
||||
for(int j=0;j<4;j++)
|
||||
{
|
||||
SubFloat( m_RandY[i], j) = (seed>>16)/65536.0;
|
||||
seed=(seed+1)*3141592621u;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline fltx4 RandSIMD( void )
|
||||
{
|
||||
// ret= rand[k]+rand[j]
|
||||
fltx4 retval=AddSIMD( *m_pRand_K, *m_pRand_J );
|
||||
|
||||
// if ( ret>=1.0) ret-=1.0
|
||||
fltx4 overflow_mask=CmpGeSIMD( retval, Four_Ones );
|
||||
retval=SubSIMD( retval, AndSIMD( Four_Ones, overflow_mask ) );
|
||||
|
||||
*m_pRand_K = retval;
|
||||
|
||||
// update pointers w/ wrap-around
|
||||
if ( --m_pRand_J < m_RandY )
|
||||
m_pRand_J=m_RandY+54;
|
||||
if ( --m_pRand_K < m_RandY )
|
||||
m_pRand_K=m_RandY+54;
|
||||
|
||||
return retval;
|
||||
}
|
||||
};
|
||||
|
||||
#define MAX_SIMULTANEOUS_RANDOM_STREAMS 32
|
||||
|
||||
static SIMDRandStreamContext s_SIMDRandContexts[MAX_SIMULTANEOUS_RANDOM_STREAMS];
|
||||
|
||||
static volatile int s_nRandContextsInUse[MAX_SIMULTANEOUS_RANDOM_STREAMS];
|
||||
|
||||
void SeedRandSIMD(uint32 seed)
|
||||
{
|
||||
for( int i = 0; i<MAX_SIMULTANEOUS_RANDOM_STREAMS; i++)
|
||||
s_SIMDRandContexts[i].Seed( seed+i );
|
||||
}
|
||||
|
||||
fltx4 RandSIMD( int nContextIndex )
|
||||
{
|
||||
return s_SIMDRandContexts[nContextIndex].RandSIMD();
|
||||
}
|
||||
|
||||
int GetSIMDRandContext( void )
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
for(int i=0; i < (int)NELEMS( s_SIMDRandContexts ); i++)
|
||||
{
|
||||
if ( ! s_nRandContextsInUse[i] ) // available?
|
||||
{
|
||||
// try to take it!
|
||||
if ( ThreadInterlockedAssignIf( &( s_nRandContextsInUse[i]), 1, 0 ) )
|
||||
{
|
||||
return i; // done!
|
||||
}
|
||||
}
|
||||
}
|
||||
Assert(0); // why don't we have enough buffers?
|
||||
ThreadSleep();
|
||||
}
|
||||
}
|
||||
|
||||
void ReleaseSIMDRandContext( int nContext )
|
||||
{
|
||||
s_nRandContextsInUse[ nContext ] = 0;
|
||||
}
|
||||
|
||||
|
||||
fltx4 RandSIMD( void )
|
||||
{
|
||||
return s_SIMDRandContexts[0].RandSIMD();
|
||||
}
|
112
mathlib/simdvectormatrix.cpp
Normal file
112
mathlib/simdvectormatrix.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
//====== Copyright © 1996-2006, Valve Corporation, All rights reserved. =======//
|
||||
//
|
||||
// Purpose: Provide a class (SSE/SIMD only) holding a 2d matrix of class FourVectors,
|
||||
// for high speed processing in tools.
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
|
||||
|
||||
#include "basetypes.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
#include "mathlib/simdvectormatrix.h"
|
||||
#include "mathlib/ssemath.h"
|
||||
#include "tier0/dbg.h"
|
||||
|
||||
void CSIMDVectorMatrix::CreateFromRGBA_FloatImageData(int srcwidth, int srcheight,
|
||||
float const *srcdata )
|
||||
{
|
||||
Assert( srcwidth && srcheight && srcdata );
|
||||
SetSize( srcwidth, srcheight );
|
||||
|
||||
FourVectors *p_write_ptr=m_pData;
|
||||
int n_vectors_per_source_line=(srcwidth >> 2);
|
||||
int ntrailing_pixels_per_source_line=(srcwidth & 3);
|
||||
for(int y=0;y<srcheight;y++)
|
||||
{
|
||||
float const *data_in=srcdata;
|
||||
float *data_out=reinterpret_cast<float *>( p_write_ptr );
|
||||
// copy full input blocks
|
||||
for(int x=0;x<n_vectors_per_source_line;x++)
|
||||
{
|
||||
for(int c=0;c<3;c++)
|
||||
{
|
||||
data_out[0]=data_in[c]; // x0
|
||||
data_out[1]=data_in[4+c]; // x1
|
||||
data_out[2]=data_in[8+c]; // x2
|
||||
data_out[3]=data_in[12+c]; // x3
|
||||
data_out+=4;
|
||||
}
|
||||
data_in += 16;
|
||||
}
|
||||
// now, copy trailing data and pad with copies
|
||||
if (ntrailing_pixels_per_source_line )
|
||||
{
|
||||
for(int c=0;c<3;c++)
|
||||
{
|
||||
for(int cp=0;cp<4; cp++)
|
||||
{
|
||||
int real_cp=MIN( cp, ntrailing_pixels_per_source_line-1 );
|
||||
data_out[4*c+cp]= data_in[c+4*real_cp];
|
||||
}
|
||||
}
|
||||
}
|
||||
// advance ptrs to next line
|
||||
p_write_ptr += m_nPaddedWidth;
|
||||
srcdata += 4 * srcwidth;
|
||||
}
|
||||
}
|
||||
|
||||
void CSIMDVectorMatrix::RaiseToPower( float power )
|
||||
{
|
||||
int nv=NVectors();
|
||||
if ( nv )
|
||||
{
|
||||
int fixed_point_exp=(int) ( 4.0*power );
|
||||
FourVectors *src=m_pData;
|
||||
do
|
||||
{
|
||||
src->x=Pow_FixedPoint_Exponent_SIMD( src->x, fixed_point_exp );
|
||||
src->y=Pow_FixedPoint_Exponent_SIMD( src->y, fixed_point_exp );
|
||||
src->z=Pow_FixedPoint_Exponent_SIMD( src->z, fixed_point_exp );
|
||||
src++;
|
||||
} while (--nv);
|
||||
}
|
||||
}
|
||||
|
||||
CSIMDVectorMatrix & CSIMDVectorMatrix::operator+=( CSIMDVectorMatrix const &src )
|
||||
{
|
||||
Assert( m_nWidth == src.m_nWidth );
|
||||
Assert( m_nHeight == src.m_nHeight );
|
||||
int nv=NVectors();
|
||||
if ( nv )
|
||||
{
|
||||
FourVectors *srcv=src.m_pData;
|
||||
FourVectors *destv=m_pData;
|
||||
do // !! speed !! inline more iters
|
||||
{
|
||||
*( destv++ ) += *( srcv++ );
|
||||
} while ( --nv );
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
CSIMDVectorMatrix & CSIMDVectorMatrix::operator*=( Vector const &src )
|
||||
{
|
||||
int nv=NVectors();
|
||||
if ( nv )
|
||||
{
|
||||
FourVectors scalevalue;
|
||||
scalevalue.DuplicateVector( src );
|
||||
FourVectors *destv=m_pData;
|
||||
do // !! speed !! inline more iters
|
||||
{
|
||||
destv->VProduct( scalevalue );
|
||||
destv++;
|
||||
} while ( --nv );
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
218
mathlib/sparse_convolution_noise.cpp
Normal file
218
mathlib/sparse_convolution_noise.cpp
Normal file
@ -0,0 +1,218 @@
|
||||
//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: noise() primitives.
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#include <math.h>
|
||||
#include "basetypes.h"
|
||||
#include <memory.h>
|
||||
#include "tier0/dbg.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
#include "mathlib/vector.h"
|
||||
#include "mathlib/noise.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
// generate high quality noise based upon "sparse convolution". HIgher quality than perlin noise,
|
||||
// and no direcitonal artifacts.
|
||||
|
||||
#include "noisedata.h"
|
||||
|
||||
#define N_IMPULSES_PER_CELL 5
|
||||
#define NORMALIZING_FACTOR 1.0
|
||||
|
||||
//(0.5/N_IMPULSES_PER_CELL)
|
||||
|
||||
static inline int LatticeCoord(float x)
|
||||
{
|
||||
return ((int) floor(x)) & 0xff;
|
||||
}
|
||||
|
||||
static inline int Hash4D(int ix, int iy, int iz, int idx)
|
||||
{
|
||||
int ret=perm_a[ix];
|
||||
ret=perm_b[(ret+iy) & 0xff];
|
||||
ret=perm_c[(ret+iz) & 0xff];
|
||||
ret=perm_d[(ret+idx) & 0xff];
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define SQ(x) ((x)*(x))
|
||||
|
||||
static float CellNoise( int ix, int iy, int iz, float xfrac, float yfrac, float zfrac,
|
||||
float (*pNoiseShapeFunction)(float) )
|
||||
{
|
||||
float ret=0;
|
||||
for(int idx=0;idx<N_IMPULSES_PER_CELL;idx++)
|
||||
{
|
||||
int coord_idx=Hash4D( ix, iy, iz, idx );
|
||||
float dsq=SQ(impulse_xcoords[coord_idx]-xfrac)+
|
||||
SQ(impulse_ycoords[coord_idx]-yfrac)+
|
||||
SQ(impulse_zcoords[coord_idx]-zfrac);
|
||||
dsq = sqrt( dsq );
|
||||
if (dsq < 1.0 )
|
||||
{
|
||||
ret += (*pNoiseShapeFunction)( 1-dsq );
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
float SparseConvolutionNoise( Vector const &pnt )
|
||||
{
|
||||
return SparseConvolutionNoise( pnt, QuinticInterpolatingPolynomial );
|
||||
}
|
||||
|
||||
float FractalNoise( Vector const &pnt, int n_octaves)
|
||||
{
|
||||
float scale=1.0;
|
||||
float iscale=1.0;
|
||||
float ret=0;
|
||||
float sumscale=0;
|
||||
for(int o=0;o<n_octaves;o++)
|
||||
{
|
||||
Vector p1=pnt;
|
||||
p1 *= scale;
|
||||
ret+=iscale * SparseConvolutionNoise( p1 );
|
||||
sumscale += iscale;
|
||||
scale *= 2.0;
|
||||
iscale *= 0.5;
|
||||
}
|
||||
return ret * ( 1.0/sumscale );
|
||||
}
|
||||
|
||||
float Turbulence( Vector const &pnt, int n_octaves)
|
||||
{
|
||||
float scale=1.0;
|
||||
float iscale=1.0;
|
||||
float ret=0;
|
||||
float sumscale=0;
|
||||
for(int o=0;o<n_octaves;o++)
|
||||
{
|
||||
Vector p1=pnt;
|
||||
p1 *= scale;
|
||||
ret+=iscale * fabs ( 2.0*( SparseConvolutionNoise( p1 )-.5 ) );
|
||||
sumscale += iscale;
|
||||
scale *= 2.0;
|
||||
iscale *= 0.5;
|
||||
}
|
||||
return ret * ( 1.0/sumscale );
|
||||
}
|
||||
|
||||
#ifdef MEASURE_RANGE
|
||||
float fmin1=10000000.0;
|
||||
float fmax1=-1000000.0;
|
||||
#endif
|
||||
|
||||
float SparseConvolutionNoise(Vector const &pnt, float (*pNoiseShapeFunction)(float) )
|
||||
{
|
||||
// computer integer lattice point
|
||||
int ix=LatticeCoord(pnt.x);
|
||||
int iy=LatticeCoord(pnt.y);
|
||||
int iz=LatticeCoord(pnt.z);
|
||||
|
||||
// compute offsets within unit cube
|
||||
float xfrac=pnt.x-floor(pnt.x);
|
||||
float yfrac=pnt.y-floor(pnt.y);
|
||||
float zfrac=pnt.z-floor(pnt.z);
|
||||
|
||||
float sum_out=0.;
|
||||
|
||||
for(int ox=-1; ox<=1; ox++)
|
||||
for(int oy=-1; oy<=1; oy++)
|
||||
for(int oz=-1; oz<=1; oz++)
|
||||
{
|
||||
sum_out += CellNoise( ix+ox, iy+oy, iz+oz,
|
||||
xfrac-ox, yfrac-oy, zfrac-oz,
|
||||
pNoiseShapeFunction );
|
||||
}
|
||||
#ifdef MEASURE_RANGE
|
||||
fmin1=MIN(sum_out,fmin1);
|
||||
fmax1=MAX(sum_out,fmax1);
|
||||
#endif
|
||||
return RemapValClamped( sum_out, .544487, 9.219176, 0.0, 1.0 );
|
||||
}
|
||||
|
||||
|
||||
// Improved Perlin Noise
|
||||
// The following code is the c-ification of Ken Perlin's new noise algorithm
|
||||
// "JAVA REFERENCE IMPLEMENTATION OF IMPROVED NOISE - COPYRIGHT 2002 KEN PERLIN"
|
||||
// as available here: http://mrl.nyu.edu/~perlin/noise/
|
||||
|
||||
float NoiseGradient(int hash, float x, float y, float z)
|
||||
{
|
||||
int h = hash & 15; // CONVERT LO 4 BITS OF HASH CODE
|
||||
float u = h<8 ? x : y; // INTO 12 GRADIENT DIRECTIONS.
|
||||
float v = h<4 ? y : (h==12||h==14 ? x : z);
|
||||
return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
|
||||
}
|
||||
|
||||
int NoiseHashIndex( int i )
|
||||
{
|
||||
static int s_permutation[] =
|
||||
{
|
||||
151,160,137,91,90,15,
|
||||
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
|
||||
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
|
||||
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
|
||||
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
|
||||
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
|
||||
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
|
||||
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
|
||||
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
|
||||
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
|
||||
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
|
||||
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
|
||||
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
|
||||
};
|
||||
|
||||
return s_permutation[ i & 0xff ];
|
||||
}
|
||||
|
||||
float ImprovedPerlinNoise( Vector const &pnt )
|
||||
{
|
||||
float fx = floor(pnt.x);
|
||||
float fy = floor(pnt.y);
|
||||
float fz = floor(pnt.z);
|
||||
|
||||
int X = (int)fx & 255; // FIND UNIT CUBE THAT
|
||||
int Y = (int)fy & 255; // CONTAINS POINT.
|
||||
int Z = (int)fz & 255;
|
||||
|
||||
float x = pnt.x - fx; // FIND RELATIVE X,Y,Z
|
||||
float y = pnt.y - fy; // OF POINT IN CUBE.
|
||||
float z = pnt.z - fz;
|
||||
|
||||
float u = QuinticInterpolatingPolynomial(x); // COMPUTE FADE CURVES
|
||||
float v = QuinticInterpolatingPolynomial(y); // FOR EACH OF X,Y,Z.
|
||||
float w = QuinticInterpolatingPolynomial(z);
|
||||
|
||||
int A = NoiseHashIndex( X ) + Y; // HASH COORDINATES OF
|
||||
int AA = NoiseHashIndex( A ) + Z; // THE 8 CUBE CORNERS,
|
||||
int AB = NoiseHashIndex( A + 1 ) + Z;
|
||||
int B = NoiseHashIndex( X + 1 ) + Y;
|
||||
int BA = NoiseHashIndex( B ) + Z;
|
||||
int BB = NoiseHashIndex( B + 1 ) + Z;
|
||||
|
||||
float g0 = NoiseGradient(NoiseHashIndex(AA ), x , y , z );
|
||||
float g1 = NoiseGradient(NoiseHashIndex(BA ), x-1, y , z );
|
||||
float g2 = NoiseGradient(NoiseHashIndex(AB ), x , y-1, z );
|
||||
float g3 = NoiseGradient(NoiseHashIndex(BB ), x-1, y-1, z );
|
||||
float g4 = NoiseGradient(NoiseHashIndex(AA+1), x , y , z-1 );
|
||||
float g5 = NoiseGradient(NoiseHashIndex(BA+1), x-1, y , z-1 );
|
||||
float g6 = NoiseGradient(NoiseHashIndex(AB+1), x , y-1, z-1 );
|
||||
float g7 = NoiseGradient(NoiseHashIndex(BB+1), x-1, y-1, z-1 );
|
||||
|
||||
// AND ADD BLENDED RESULTS FROM 8 CORNERS OF CUBE
|
||||
float g01 = Lerp( u, g0, g1 );
|
||||
float g23 = Lerp( u, g2, g3 );
|
||||
float g45 = Lerp( u, g4, g5 );
|
||||
float g67 = Lerp( u, g6, g7 );
|
||||
float g0123 = Lerp( v, g01, g23 );
|
||||
float g4567 = Lerp( v, g45, g67 );
|
||||
|
||||
return Lerp( w, g0123,g4567 );
|
||||
}
|
845
mathlib/sse.cpp
Normal file
845
mathlib/sse.cpp
Normal file
@ -0,0 +1,845 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: SSE Math primitives.
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#include <math.h>
|
||||
#include <float.h> // Needed for FLT_EPSILON
|
||||
#include "basetypes.h"
|
||||
#include <memory.h>
|
||||
#include "tier0/dbg.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
#include "mathlib/vector.h"
|
||||
#include "sse.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
static const uint32 _sincos_masks[] = { (uint32)0x0, (uint32)~0x0 };
|
||||
static const uint32 _sincos_inv_masks[] = { (uint32)~0x0, (uint32)0x0 };
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Macros and constants required by some of the SSE assembly:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef _WIN32
|
||||
#define _PS_EXTERN_CONST(Name, Val) \
|
||||
const __declspec(align(16)) float _ps_##Name[4] = { Val, Val, Val, Val }
|
||||
|
||||
#define _PS_EXTERN_CONST_TYPE(Name, Type, Val) \
|
||||
const __declspec(align(16)) Type _ps_##Name[4] = { Val, Val, Val, Val }; \
|
||||
|
||||
#define _EPI32_CONST(Name, Val) \
|
||||
static const __declspec(align(16)) __int32 _epi32_##Name[4] = { Val, Val, Val, Val }
|
||||
|
||||
#define _PS_CONST(Name, Val) \
|
||||
static const __declspec(align(16)) float _ps_##Name[4] = { Val, Val, Val, Val }
|
||||
#elif defined _LINUX || defined __APPLE__
|
||||
#define _PS_EXTERN_CONST(Name, Val) \
|
||||
const __attribute__((aligned(16))) float _ps_##Name[4] = { Val, Val, Val, Val }
|
||||
|
||||
#define _PS_EXTERN_CONST_TYPE(Name, Type, Val) \
|
||||
const __attribute__((aligned(16))) Type _ps_##Name[4] = { Val, Val, Val, Val }; \
|
||||
|
||||
#define _EPI32_CONST(Name, Val) \
|
||||
static const __attribute__((aligned(16))) int32 _epi32_##Name[4] = { Val, Val, Val, Val }
|
||||
|
||||
#define _PS_CONST(Name, Val) \
|
||||
static const __attribute__((aligned(16))) float _ps_##Name[4] = { Val, Val, Val, Val }
|
||||
#endif
|
||||
|
||||
_PS_EXTERN_CONST(am_0, 0.0f);
|
||||
_PS_EXTERN_CONST(am_1, 1.0f);
|
||||
_PS_EXTERN_CONST(am_m1, -1.0f);
|
||||
_PS_EXTERN_CONST(am_0p5, 0.5f);
|
||||
_PS_EXTERN_CONST(am_1p5, 1.5f);
|
||||
_PS_EXTERN_CONST(am_pi, (float)M_PI);
|
||||
_PS_EXTERN_CONST(am_pi_o_2, (float)(M_PI / 2.0));
|
||||
_PS_EXTERN_CONST(am_2_o_pi, (float)(2.0 / M_PI));
|
||||
_PS_EXTERN_CONST(am_pi_o_4, (float)(M_PI / 4.0));
|
||||
_PS_EXTERN_CONST(am_4_o_pi, (float)(4.0 / M_PI));
|
||||
_PS_EXTERN_CONST_TYPE(am_sign_mask, int32, 0x80000000);
|
||||
_PS_EXTERN_CONST_TYPE(am_inv_sign_mask, int32, ~0x80000000);
|
||||
_PS_EXTERN_CONST_TYPE(am_min_norm_pos,int32, 0x00800000);
|
||||
_PS_EXTERN_CONST_TYPE(am_mant_mask, int32, 0x7f800000);
|
||||
_PS_EXTERN_CONST_TYPE(am_inv_mant_mask, int32, ~0x7f800000);
|
||||
|
||||
_EPI32_CONST(1, 1);
|
||||
_EPI32_CONST(2, 2);
|
||||
|
||||
_PS_CONST(sincos_p0, 0.15707963267948963959e1f);
|
||||
_PS_CONST(sincos_p1, -0.64596409750621907082e0f);
|
||||
_PS_CONST(sincos_p2, 0.7969262624561800806e-1f);
|
||||
_PS_CONST(sincos_p3, -0.468175413106023168e-2f);
|
||||
|
||||
#ifdef PFN_VECTORMA
|
||||
void __cdecl _SSE_VectorMA( const float *start, float scale, const float *direction, float *dest );
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SSE implementations of optimized routines:
|
||||
//-----------------------------------------------------------------------------
|
||||
float _SSE_Sqrt(float x)
|
||||
{
|
||||
Assert( s_bMathlibInitialized );
|
||||
float root = 0.f;
|
||||
#ifdef _WIN32
|
||||
_asm
|
||||
{
|
||||
sqrtss xmm0, x
|
||||
movss root, xmm0
|
||||
}
|
||||
#elif defined _LINUX || defined __APPLE__
|
||||
__asm__ __volatile__(
|
||||
"movss %1,%%xmm2\n"
|
||||
"sqrtss %%xmm2,%%xmm1\n"
|
||||
"movss %%xmm1,%0"
|
||||
: "=m" (root)
|
||||
: "m" (x)
|
||||
);
|
||||
#endif
|
||||
return root;
|
||||
}
|
||||
|
||||
// Single iteration NewtonRaphson reciprocal square root:
|
||||
// 0.5 * rsqrtps * (3 - x * rsqrtps(x) * rsqrtps(x))
|
||||
// Very low error, and fine to use in place of 1.f / sqrtf(x).
|
||||
#if 0
|
||||
float _SSE_RSqrtAccurate(float x)
|
||||
{
|
||||
Assert( s_bMathlibInitialized );
|
||||
|
||||
float rroot;
|
||||
_asm
|
||||
{
|
||||
rsqrtss xmm0, x
|
||||
movss rroot, xmm0
|
||||
}
|
||||
|
||||
return (0.5f * rroot) * (3.f - (x * rroot) * rroot);
|
||||
}
|
||||
#else
|
||||
// Intel / Kipps SSE RSqrt. Significantly faster than above.
|
||||
float _SSE_RSqrtAccurate(float a)
|
||||
{
|
||||
float x;
|
||||
float half = 0.5f;
|
||||
float three = 3.f;
|
||||
|
||||
#ifdef _WIN32
|
||||
__asm
|
||||
{
|
||||
movss xmm3, a;
|
||||
movss xmm1, half;
|
||||
movss xmm2, three;
|
||||
rsqrtss xmm0, xmm3;
|
||||
|
||||
mulss xmm3, xmm0;
|
||||
mulss xmm1, xmm0;
|
||||
mulss xmm3, xmm0;
|
||||
subss xmm2, xmm3;
|
||||
mulss xmm1, xmm2;
|
||||
|
||||
movss x, xmm1;
|
||||
}
|
||||
#elif defined _LINUX || defined __APPLE__
|
||||
__asm__ __volatile__(
|
||||
"movss %1, %%xmm3 \n\t"
|
||||
"movss %2, %%xmm1 \n\t"
|
||||
"movss %3, %%xmm2 \n\t"
|
||||
"rsqrtss %%xmm3, %%xmm0 \n\t"
|
||||
"mulss %%xmm0, %%xmm3 \n\t"
|
||||
"mulss %%xmm0, %%xmm1 \n\t"
|
||||
"mulss %%xmm0, %%xmm3 \n\t"
|
||||
"subss %%xmm3, %%xmm2 \n\t"
|
||||
"mulss %%xmm2, %%xmm1 \n\t"
|
||||
"movss %%xmm1, %0 \n\t"
|
||||
: "=m" (x)
|
||||
: "m" (a), "m" (half), "m" (three)
|
||||
);
|
||||
#else
|
||||
#error "Not Implemented"
|
||||
#endif
|
||||
|
||||
return x;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Simple SSE rsqrt. Usually accurate to around 6 (relative) decimal places
|
||||
// or so, so ok for closed transforms. (ie, computing lighting normals)
|
||||
float _SSE_RSqrtFast(float x)
|
||||
{
|
||||
Assert( s_bMathlibInitialized );
|
||||
|
||||
float rroot;
|
||||
#ifdef _WIN32
|
||||
_asm
|
||||
{
|
||||
rsqrtss xmm0, x
|
||||
movss rroot, xmm0
|
||||
}
|
||||
#elif defined _LINUX || defined __APPLE__
|
||||
__asm__ __volatile__(
|
||||
"rsqrtss %1, %%xmm0 \n\t"
|
||||
"movss %%xmm0, %0 \n\t"
|
||||
: "=m" (x)
|
||||
: "m" (rroot)
|
||||
: "%xmm0"
|
||||
);
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
|
||||
return rroot;
|
||||
}
|
||||
|
||||
float FASTCALL _SSE_VectorNormalize (Vector& vec)
|
||||
{
|
||||
Assert( s_bMathlibInitialized );
|
||||
|
||||
// NOTE: This is necessary to prevent an memory overwrite...
|
||||
// sice vec only has 3 floats, we can't "movaps" directly into it.
|
||||
#ifdef _WIN32
|
||||
__declspec(align(16)) float result[4];
|
||||
#elif defined _LINUX || defined __APPLE__
|
||||
__attribute__((aligned(16))) float result[4];
|
||||
#endif
|
||||
|
||||
float *v = &vec[0];
|
||||
|
||||
float radius = 0.f;
|
||||
// Blah, get rid of these comparisons ... in reality, if you have all 3 as zero, it shouldn't
|
||||
// be much of a performance win, considering you will very likely miss 3 branch predicts in a row.
|
||||
if ( v[0] || v[1] || v[2] )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
float *r = &result[0];
|
||||
_asm
|
||||
{
|
||||
mov eax, v
|
||||
mov edx, r
|
||||
#ifdef ALIGNED_VECTOR
|
||||
movaps xmm4, [eax] // r4 = vx, vy, vz, X
|
||||
movaps xmm1, xmm4 // r1 = r4
|
||||
#else
|
||||
movups xmm4, [eax] // r4 = vx, vy, vz, X
|
||||
movaps xmm1, xmm4 // r1 = r4
|
||||
#endif
|
||||
mulps xmm1, xmm4 // r1 = vx * vx, vy * vy, vz * vz, X
|
||||
movhlps xmm3, xmm1 // r3 = vz * vz, X, X, X
|
||||
movaps xmm2, xmm1 // r2 = r1
|
||||
shufps xmm2, xmm2, 1 // r2 = vy * vy, X, X, X
|
||||
addss xmm1, xmm2 // r1 = (vx * vx) + (vy * vy), X, X, X
|
||||
addss xmm1, xmm3 // r1 = (vx * vx) + (vy * vy) + (vz * vz), X, X, X
|
||||
sqrtss xmm1, xmm1 // r1 = sqrt((vx * vx) + (vy * vy) + (vz * vz)), X, X, X
|
||||
movss radius, xmm1 // radius = sqrt((vx * vx) + (vy * vy) + (vz * vz))
|
||||
rcpss xmm1, xmm1 // r1 = 1/radius, X, X, X
|
||||
shufps xmm1, xmm1, 0 // r1 = 1/radius, 1/radius, 1/radius, X
|
||||
mulps xmm4, xmm1 // r4 = vx * 1/radius, vy * 1/radius, vz * 1/radius, X
|
||||
movaps [edx], xmm4 // v = vx * 1/radius, vy * 1/radius, vz * 1/radius, X
|
||||
}
|
||||
#elif defined _LINUX || defined __APPLE__
|
||||
__asm__ __volatile__(
|
||||
#ifdef ALIGNED_VECTOR
|
||||
"movaps %2, %%xmm4 \n\t"
|
||||
"movaps %%xmm4, %%xmm1 \n\t"
|
||||
#else
|
||||
"movups %2, %%xmm4 \n\t"
|
||||
"movaps %%xmm4, %%xmm1 \n\t"
|
||||
#endif
|
||||
"mulps %%xmm4, %%xmm1 \n\t"
|
||||
"movhlps %%xmm1, %%xmm3 \n\t"
|
||||
"movaps %%xmm1, %%xmm2 \n\t"
|
||||
"shufps $1, %%xmm2, %%xmm2 \n\t"
|
||||
"addss %%xmm2, %%xmm1 \n\t"
|
||||
"addss %%xmm3, %%xmm1 \n\t"
|
||||
"sqrtss %%xmm1, %%xmm1 \n\t"
|
||||
"movss %%xmm1, %0 \n\t"
|
||||
"rcpss %%xmm1, %%xmm1 \n\t"
|
||||
"shufps $0, %%xmm1, %%xmm1 \n\t"
|
||||
"mulps %%xmm1, %%xmm4 \n\t"
|
||||
"movaps %%xmm4, %1 \n\t"
|
||||
: "=m" (radius), "=m" (result)
|
||||
: "m" (*v)
|
||||
);
|
||||
#else
|
||||
#error "Not Implemented"
|
||||
#endif
|
||||
vec.x = result[0];
|
||||
vec.y = result[1];
|
||||
vec.z = result[2];
|
||||
|
||||
}
|
||||
|
||||
return radius;
|
||||
}
|
||||
|
||||
void FASTCALL _SSE_VectorNormalizeFast (Vector& vec)
|
||||
{
|
||||
float ool = _SSE_RSqrtAccurate( FLT_EPSILON + vec.x * vec.x + vec.y * vec.y + vec.z * vec.z );
|
||||
|
||||
vec.x *= ool;
|
||||
vec.y *= ool;
|
||||
vec.z *= ool;
|
||||
}
|
||||
|
||||
float _SSE_InvRSquared(const float* v)
|
||||
{
|
||||
float inv_r2 = 1.f;
|
||||
#ifdef _WIN32
|
||||
_asm { // Intel SSE only routine
|
||||
mov eax, v
|
||||
movss xmm5, inv_r2 // x5 = 1.0, 0, 0, 0
|
||||
#ifdef ALIGNED_VECTOR
|
||||
movaps xmm4, [eax] // x4 = vx, vy, vz, X
|
||||
#else
|
||||
movups xmm4, [eax] // x4 = vx, vy, vz, X
|
||||
#endif
|
||||
movaps xmm1, xmm4 // x1 = x4
|
||||
mulps xmm1, xmm4 // x1 = vx * vx, vy * vy, vz * vz, X
|
||||
movhlps xmm3, xmm1 // x3 = vz * vz, X, X, X
|
||||
movaps xmm2, xmm1 // x2 = x1
|
||||
shufps xmm2, xmm2, 1 // x2 = vy * vy, X, X, X
|
||||
addss xmm1, xmm2 // x1 = (vx * vx) + (vy * vy), X, X, X
|
||||
addss xmm1, xmm3 // x1 = (vx * vx) + (vy * vy) + (vz * vz), X, X, X
|
||||
maxss xmm1, xmm5 // x1 = MAX( 1.0, x1 )
|
||||
rcpss xmm0, xmm1 // x0 = 1 / MAX( 1.0, x1 )
|
||||
movss inv_r2, xmm0 // inv_r2 = x0
|
||||
}
|
||||
#elif defined _LINUX || defined __APPLE__
|
||||
__asm__ __volatile__(
|
||||
#ifdef ALIGNED_VECTOR
|
||||
"movaps %1, %%xmm4 \n\t"
|
||||
#else
|
||||
"movups %1, %%xmm4 \n\t"
|
||||
#endif
|
||||
"movaps %%xmm4, %%xmm1 \n\t"
|
||||
"mulps %%xmm4, %%xmm1 \n\t"
|
||||
"movhlps %%xmm1, %%xmm3 \n\t"
|
||||
"movaps %%xmm1, %%xmm2 \n\t"
|
||||
"shufps $1, %%xmm2, %%xmm2 \n\t"
|
||||
"addss %%xmm2, %%xmm1 \n\t"
|
||||
"addss %%xmm3, %%xmm1 \n\t"
|
||||
"maxss %%xmm5, %%xmm1 \n\t"
|
||||
"rcpss %%xmm1, %%xmm0 \n\t"
|
||||
"movss %%xmm0, %0 \n\t"
|
||||
: "=m" (inv_r2)
|
||||
: "m" (*v), "m" (inv_r2)
|
||||
);
|
||||
#else
|
||||
#error "Not Implemented"
|
||||
#endif
|
||||
|
||||
return inv_r2;
|
||||
}
|
||||
|
||||
void _SSE_SinCos(float x, float* s, float* c)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
float t4, t8, t12;
|
||||
|
||||
__asm
|
||||
{
|
||||
movss xmm0, x
|
||||
movss t12, xmm0
|
||||
movss xmm1, _ps_am_inv_sign_mask
|
||||
mov eax, t12
|
||||
mulss xmm0, _ps_am_2_o_pi
|
||||
andps xmm0, xmm1
|
||||
and eax, 0x80000000
|
||||
|
||||
cvttss2si edx, xmm0
|
||||
mov ecx, edx
|
||||
mov t12, esi
|
||||
mov esi, edx
|
||||
add edx, 0x1
|
||||
shl ecx, (31 - 1)
|
||||
shl edx, (31 - 1)
|
||||
|
||||
movss xmm4, _ps_am_1
|
||||
cvtsi2ss xmm3, esi
|
||||
mov t8, eax
|
||||
and esi, 0x1
|
||||
|
||||
subss xmm0, xmm3
|
||||
movss xmm3, _sincos_inv_masks[esi * 4]
|
||||
minss xmm0, xmm4
|
||||
|
||||
subss xmm4, xmm0
|
||||
|
||||
movss xmm6, xmm4
|
||||
andps xmm4, xmm3
|
||||
and ecx, 0x80000000
|
||||
movss xmm2, xmm3
|
||||
andnps xmm3, xmm0
|
||||
and edx, 0x80000000
|
||||
movss xmm7, t8
|
||||
andps xmm0, xmm2
|
||||
mov t8, ecx
|
||||
mov t4, edx
|
||||
orps xmm4, xmm3
|
||||
|
||||
mov eax, s //mov eax, [esp + 4 + 16]
|
||||
mov edx, c //mov edx, [esp + 4 + 16 + 4]
|
||||
|
||||
andnps xmm2, xmm6
|
||||
orps xmm0, xmm2
|
||||
|
||||
movss xmm2, t8
|
||||
movss xmm1, xmm0
|
||||
movss xmm5, xmm4
|
||||
xorps xmm7, xmm2
|
||||
movss xmm3, _ps_sincos_p3
|
||||
mulss xmm0, xmm0
|
||||
mulss xmm4, xmm4
|
||||
movss xmm2, xmm0
|
||||
movss xmm6, xmm4
|
||||
orps xmm1, xmm7
|
||||
movss xmm7, _ps_sincos_p2
|
||||
mulss xmm0, xmm3
|
||||
mulss xmm4, xmm3
|
||||
movss xmm3, _ps_sincos_p1
|
||||
addss xmm0, xmm7
|
||||
addss xmm4, xmm7
|
||||
movss xmm7, _ps_sincos_p0
|
||||
mulss xmm0, xmm2
|
||||
mulss xmm4, xmm6
|
||||
addss xmm0, xmm3
|
||||
addss xmm4, xmm3
|
||||
movss xmm3, t4
|
||||
mulss xmm0, xmm2
|
||||
mulss xmm4, xmm6
|
||||
orps xmm5, xmm3
|
||||
mov esi, t12
|
||||
addss xmm0, xmm7
|
||||
addss xmm4, xmm7
|
||||
mulss xmm0, xmm1
|
||||
mulss xmm4, xmm5
|
||||
|
||||
// use full stores since caller might reload with full loads
|
||||
movss [eax], xmm0
|
||||
movss [edx], xmm4
|
||||
}
|
||||
#elif defined _LINUX || defined __APPLE__
|
||||
// #warning "_SSE_sincos NOT implemented!"
|
||||
#else
|
||||
#error "Not Implemented"
|
||||
#endif
|
||||
}
|
||||
|
||||
float _SSE_cos( float x )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
float temp;
|
||||
__asm
|
||||
{
|
||||
movss xmm0, x
|
||||
movss xmm1, _ps_am_inv_sign_mask
|
||||
andps xmm0, xmm1
|
||||
addss xmm0, _ps_am_pi_o_2
|
||||
mulss xmm0, _ps_am_2_o_pi
|
||||
|
||||
cvttss2si ecx, xmm0
|
||||
movss xmm5, _ps_am_1
|
||||
mov edx, ecx
|
||||
shl edx, (31 - 1)
|
||||
cvtsi2ss xmm1, ecx
|
||||
and edx, 0x80000000
|
||||
and ecx, 0x1
|
||||
|
||||
subss xmm0, xmm1
|
||||
movss xmm6, _sincos_masks[ecx * 4]
|
||||
minss xmm0, xmm5
|
||||
|
||||
movss xmm1, _ps_sincos_p3
|
||||
subss xmm5, xmm0
|
||||
|
||||
andps xmm5, xmm6
|
||||
movss xmm7, _ps_sincos_p2
|
||||
andnps xmm6, xmm0
|
||||
mov temp, edx
|
||||
orps xmm5, xmm6
|
||||
movss xmm0, xmm5
|
||||
|
||||
mulss xmm5, xmm5
|
||||
movss xmm4, _ps_sincos_p1
|
||||
movss xmm2, xmm5
|
||||
mulss xmm5, xmm1
|
||||
movss xmm1, _ps_sincos_p0
|
||||
addss xmm5, xmm7
|
||||
mulss xmm5, xmm2
|
||||
movss xmm3, temp
|
||||
addss xmm5, xmm4
|
||||
mulss xmm5, xmm2
|
||||
orps xmm0, xmm3
|
||||
addss xmm5, xmm1
|
||||
mulss xmm0, xmm5
|
||||
|
||||
movss x, xmm0
|
||||
|
||||
}
|
||||
#elif defined _LINUX || defined __APPLE__
|
||||
// #warning "_SSE_cos NOT implemented!"
|
||||
#else
|
||||
#error "Not Implemented"
|
||||
#endif
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SSE2 implementations of optimized routines:
|
||||
//-----------------------------------------------------------------------------
|
||||
void _SSE2_SinCos(float x, float* s, float* c) // any x
|
||||
{
|
||||
#ifdef _WIN32
|
||||
__asm
|
||||
{
|
||||
movss xmm0, x
|
||||
movaps xmm7, xmm0
|
||||
movss xmm1, _ps_am_inv_sign_mask
|
||||
movss xmm2, _ps_am_sign_mask
|
||||
movss xmm3, _ps_am_2_o_pi
|
||||
andps xmm0, xmm1
|
||||
andps xmm7, xmm2
|
||||
mulss xmm0, xmm3
|
||||
|
||||
pxor xmm3, xmm3
|
||||
movd xmm5, _epi32_1
|
||||
movss xmm4, _ps_am_1
|
||||
|
||||
cvttps2dq xmm2, xmm0
|
||||
pand xmm5, xmm2
|
||||
movd xmm1, _epi32_2
|
||||
pcmpeqd xmm5, xmm3
|
||||
movd xmm3, _epi32_1
|
||||
cvtdq2ps xmm6, xmm2
|
||||
paddd xmm3, xmm2
|
||||
pand xmm2, xmm1
|
||||
pand xmm3, xmm1
|
||||
subss xmm0, xmm6
|
||||
pslld xmm2, (31 - 1)
|
||||
minss xmm0, xmm4
|
||||
|
||||
mov eax, s // mov eax, [esp + 4 + 16]
|
||||
mov edx, c // mov edx, [esp + 4 + 16 + 4]
|
||||
|
||||
subss xmm4, xmm0
|
||||
pslld xmm3, (31 - 1)
|
||||
|
||||
movaps xmm6, xmm4
|
||||
xorps xmm2, xmm7
|
||||
movaps xmm7, xmm5
|
||||
andps xmm6, xmm7
|
||||
andnps xmm7, xmm0
|
||||
andps xmm0, xmm5
|
||||
andnps xmm5, xmm4
|
||||
movss xmm4, _ps_sincos_p3
|
||||
orps xmm6, xmm7
|
||||
orps xmm0, xmm5
|
||||
movss xmm5, _ps_sincos_p2
|
||||
|
||||
movaps xmm1, xmm0
|
||||
movaps xmm7, xmm6
|
||||
mulss xmm0, xmm0
|
||||
mulss xmm6, xmm6
|
||||
orps xmm1, xmm2
|
||||
orps xmm7, xmm3
|
||||
movaps xmm2, xmm0
|
||||
movaps xmm3, xmm6
|
||||
mulss xmm0, xmm4
|
||||
mulss xmm6, xmm4
|
||||
movss xmm4, _ps_sincos_p1
|
||||
addss xmm0, xmm5
|
||||
addss xmm6, xmm5
|
||||
movss xmm5, _ps_sincos_p0
|
||||
mulss xmm0, xmm2
|
||||
mulss xmm6, xmm3
|
||||
addss xmm0, xmm4
|
||||
addss xmm6, xmm4
|
||||
mulss xmm0, xmm2
|
||||
mulss xmm6, xmm3
|
||||
addss xmm0, xmm5
|
||||
addss xmm6, xmm5
|
||||
mulss xmm0, xmm1
|
||||
mulss xmm6, xmm7
|
||||
|
||||
// use full stores since caller might reload with full loads
|
||||
movss [eax], xmm0
|
||||
movss [edx], xmm6
|
||||
}
|
||||
#elif defined _LINUX || defined __APPLE__
|
||||
// #warning "_SSE2_SinCos NOT implemented!"
|
||||
#else
|
||||
#error "Not Implemented"
|
||||
#endif
|
||||
}
|
||||
|
||||
float _SSE2_cos(float x)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
__asm
|
||||
{
|
||||
movss xmm0, x
|
||||
movss xmm1, _ps_am_inv_sign_mask
|
||||
movss xmm2, _ps_am_pi_o_2
|
||||
movss xmm3, _ps_am_2_o_pi
|
||||
andps xmm0, xmm1
|
||||
addss xmm0, xmm2
|
||||
mulss xmm0, xmm3
|
||||
|
||||
pxor xmm3, xmm3
|
||||
movd xmm5, _epi32_1
|
||||
movss xmm4, _ps_am_1
|
||||
cvttps2dq xmm2, xmm0
|
||||
pand xmm5, xmm2
|
||||
movd xmm1, _epi32_2
|
||||
pcmpeqd xmm5, xmm3
|
||||
cvtdq2ps xmm6, xmm2
|
||||
pand xmm2, xmm1
|
||||
pslld xmm2, (31 - 1)
|
||||
|
||||
subss xmm0, xmm6
|
||||
movss xmm3, _ps_sincos_p3
|
||||
minss xmm0, xmm4
|
||||
subss xmm4, xmm0
|
||||
andps xmm0, xmm5
|
||||
andnps xmm5, xmm4
|
||||
orps xmm0, xmm5
|
||||
|
||||
movaps xmm1, xmm0
|
||||
movss xmm4, _ps_sincos_p2
|
||||
mulss xmm0, xmm0
|
||||
movss xmm5, _ps_sincos_p1
|
||||
orps xmm1, xmm2
|
||||
movaps xmm7, xmm0
|
||||
mulss xmm0, xmm3
|
||||
movss xmm6, _ps_sincos_p0
|
||||
addss xmm0, xmm4
|
||||
mulss xmm0, xmm7
|
||||
addss xmm0, xmm5
|
||||
mulss xmm0, xmm7
|
||||
addss xmm0, xmm6
|
||||
mulss xmm0, xmm1
|
||||
movss x, xmm0
|
||||
}
|
||||
#elif defined _LINUX || defined __APPLE__
|
||||
// #warning "_SSE2_cos NOT implemented!"
|
||||
#else
|
||||
#error "Not Implemented"
|
||||
#endif
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
// SSE Version of VectorTransform
|
||||
void VectorTransformSSE(const float *in1, const matrix3x4_t& in2, float *out1)
|
||||
{
|
||||
Assert( s_bMathlibInitialized );
|
||||
Assert( in1 != out1 );
|
||||
|
||||
#ifdef _WIN32
|
||||
__asm
|
||||
{
|
||||
mov eax, in1;
|
||||
mov ecx, in2;
|
||||
mov edx, out1;
|
||||
|
||||
movss xmm0, [eax];
|
||||
mulss xmm0, [ecx];
|
||||
movss xmm1, [eax+4];
|
||||
mulss xmm1, [ecx+4];
|
||||
movss xmm2, [eax+8];
|
||||
mulss xmm2, [ecx+8];
|
||||
addss xmm0, xmm1;
|
||||
addss xmm0, xmm2;
|
||||
addss xmm0, [ecx+12]
|
||||
movss [edx], xmm0;
|
||||
add ecx, 16;
|
||||
|
||||
movss xmm0, [eax];
|
||||
mulss xmm0, [ecx];
|
||||
movss xmm1, [eax+4];
|
||||
mulss xmm1, [ecx+4];
|
||||
movss xmm2, [eax+8];
|
||||
mulss xmm2, [ecx+8];
|
||||
addss xmm0, xmm1;
|
||||
addss xmm0, xmm2;
|
||||
addss xmm0, [ecx+12]
|
||||
movss [edx+4], xmm0;
|
||||
add ecx, 16;
|
||||
|
||||
movss xmm0, [eax];
|
||||
mulss xmm0, [ecx];
|
||||
movss xmm1, [eax+4];
|
||||
mulss xmm1, [ecx+4];
|
||||
movss xmm2, [eax+8];
|
||||
mulss xmm2, [ecx+8];
|
||||
addss xmm0, xmm1;
|
||||
addss xmm0, xmm2;
|
||||
addss xmm0, [ecx+12]
|
||||
movss [edx+8], xmm0;
|
||||
}
|
||||
#elif defined _LINUX || defined __APPLE__
|
||||
// #warning "VectorTransformSSE C implementation only"
|
||||
out1[0] = DotProduct(in1, in2[0]) + in2[0][3];
|
||||
out1[1] = DotProduct(in1, in2[1]) + in2[1][3];
|
||||
out1[2] = DotProduct(in1, in2[2]) + in2[2][3];
|
||||
#else
|
||||
#error "Not Implemented"
|
||||
#endif
|
||||
}
|
||||
|
||||
void VectorRotateSSE( const float *in1, const matrix3x4_t& in2, float *out1 )
|
||||
{
|
||||
Assert( s_bMathlibInitialized );
|
||||
Assert( in1 != out1 );
|
||||
|
||||
#ifdef _WIN32
|
||||
__asm
|
||||
{
|
||||
mov eax, in1;
|
||||
mov ecx, in2;
|
||||
mov edx, out1;
|
||||
|
||||
movss xmm0, [eax];
|
||||
mulss xmm0, [ecx];
|
||||
movss xmm1, [eax+4];
|
||||
mulss xmm1, [ecx+4];
|
||||
movss xmm2, [eax+8];
|
||||
mulss xmm2, [ecx+8];
|
||||
addss xmm0, xmm1;
|
||||
addss xmm0, xmm2;
|
||||
movss [edx], xmm0;
|
||||
add ecx, 16;
|
||||
|
||||
movss xmm0, [eax];
|
||||
mulss xmm0, [ecx];
|
||||
movss xmm1, [eax+4];
|
||||
mulss xmm1, [ecx+4];
|
||||
movss xmm2, [eax+8];
|
||||
mulss xmm2, [ecx+8];
|
||||
addss xmm0, xmm1;
|
||||
addss xmm0, xmm2;
|
||||
movss [edx+4], xmm0;
|
||||
add ecx, 16;
|
||||
|
||||
movss xmm0, [eax];
|
||||
mulss xmm0, [ecx];
|
||||
movss xmm1, [eax+4];
|
||||
mulss xmm1, [ecx+4];
|
||||
movss xmm2, [eax+8];
|
||||
mulss xmm2, [ecx+8];
|
||||
addss xmm0, xmm1;
|
||||
addss xmm0, xmm2;
|
||||
movss [edx+8], xmm0;
|
||||
}
|
||||
#elif defined _LINUX || defined __APPLE__
|
||||
// #warning "VectorRotateSSE C implementation only"
|
||||
out1[0] = DotProduct( in1, in2[0] );
|
||||
out1[1] = DotProduct( in1, in2[1] );
|
||||
out1[2] = DotProduct( in1, in2[2] );
|
||||
#else
|
||||
#error "Not Implemented"
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
void _declspec(naked) _SSE_VectorMA( const float *start, float scale, const float *direction, float *dest )
|
||||
{
|
||||
// FIXME: This don't work!! It will overwrite memory in the write to dest
|
||||
Assert(0);
|
||||
|
||||
Assert( s_bMathlibInitialized );
|
||||
_asm { // Intel SSE only routine
|
||||
mov eax, DWORD PTR [esp+0x04] ; *start, s0..s2
|
||||
mov ecx, DWORD PTR [esp+0x0c] ; *direction, d0..d2
|
||||
mov edx, DWORD PTR [esp+0x10] ; *dest
|
||||
movss xmm2, [esp+0x08] ; x2 = scale, 0, 0, 0
|
||||
#ifdef ALIGNED_VECTOR
|
||||
movaps xmm3, [ecx] ; x3 = dir0,dir1,dir2,X
|
||||
pshufd xmm2, xmm2, 0 ; x2 = scale, scale, scale, scale
|
||||
movaps xmm1, [eax] ; x1 = start1, start2, start3, X
|
||||
mulps xmm3, xmm2 ; x3 *= x2
|
||||
addps xmm3, xmm1 ; x3 += x1
|
||||
movaps [edx], xmm3 ; *dest = x3
|
||||
#else
|
||||
movups xmm3, [ecx] ; x3 = dir0,dir1,dir2,X
|
||||
pshufd xmm2, xmm2, 0 ; x2 = scale, scale, scale, scale
|
||||
movups xmm1, [eax] ; x1 = start1, start2, start3, X
|
||||
mulps xmm3, xmm2 ; x3 *= x2
|
||||
addps xmm3, xmm1 ; x3 += x1
|
||||
movups [edx], xmm3 ; *dest = x3
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef PFN_VECTORMA
|
||||
void _declspec(naked) __cdecl _SSE_VectorMA( const Vector &start, float scale, const Vector &direction, Vector &dest )
|
||||
{
|
||||
// FIXME: This don't work!! It will overwrite memory in the write to dest
|
||||
Assert(0);
|
||||
|
||||
Assert( s_bMathlibInitialized );
|
||||
_asm
|
||||
{
|
||||
// Intel SSE only routine
|
||||
mov eax, DWORD PTR [esp+0x04] ; *start, s0..s2
|
||||
mov ecx, DWORD PTR [esp+0x0c] ; *direction, d0..d2
|
||||
mov edx, DWORD PTR [esp+0x10] ; *dest
|
||||
movss xmm2, [esp+0x08] ; x2 = scale, 0, 0, 0
|
||||
#ifdef ALIGNED_VECTOR
|
||||
movaps xmm3, [ecx] ; x3 = dir0,dir1,dir2,X
|
||||
pshufd xmm2, xmm2, 0 ; x2 = scale, scale, scale, scale
|
||||
movaps xmm1, [eax] ; x1 = start1, start2, start3, X
|
||||
mulps xmm3, xmm2 ; x3 *= x2
|
||||
addps xmm3, xmm1 ; x3 += x1
|
||||
movaps [edx], xmm3 ; *dest = x3
|
||||
#else
|
||||
movups xmm3, [ecx] ; x3 = dir0,dir1,dir2,X
|
||||
pshufd xmm2, xmm2, 0 ; x2 = scale, scale, scale, scale
|
||||
movups xmm1, [eax] ; x1 = start1, start2, start3, X
|
||||
mulps xmm3, xmm2 ; x3 *= x2
|
||||
addps xmm3, xmm1 ; x3 += x1
|
||||
movups [edx], xmm3 ; *dest = x3
|
||||
#endif
|
||||
}
|
||||
}
|
||||
float (__cdecl *pfVectorMA)(Vector& v) = _VectorMA;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
// SSE DotProduct -- it's a smidgen faster than the asm DotProduct...
|
||||
// Should be validated too! :)
|
||||
// NJS: (Nov 1 2002) -NOT- faster. may time a couple cycles faster in a single function like
|
||||
// this, but when inlined, and instruction scheduled, the C version is faster.
|
||||
// Verified this via VTune
|
||||
/*
|
||||
vec_t DotProduct (const vec_t *a, const vec_t *c)
|
||||
{
|
||||
vec_t temp;
|
||||
|
||||
__asm
|
||||
{
|
||||
mov eax, a;
|
||||
mov ecx, c;
|
||||
mov edx, DWORD PTR [temp]
|
||||
movss xmm0, [eax];
|
||||
mulss xmm0, [ecx];
|
||||
movss xmm1, [eax+4];
|
||||
mulss xmm1, [ecx+4];
|
||||
movss xmm2, [eax+8];
|
||||
mulss xmm2, [ecx+8];
|
||||
addss xmm0, xmm1;
|
||||
addss xmm0, xmm2;
|
||||
movss [edx], xmm0;
|
||||
fld DWORD PTR [edx];
|
||||
ret
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
23
mathlib/sse.h
Normal file
23
mathlib/sse.h
Normal file
@ -0,0 +1,23 @@
|
||||
//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#ifndef _SSE_H
|
||||
#define _SSE_H
|
||||
|
||||
float _SSE_Sqrt(float x);
|
||||
float _SSE_RSqrtAccurate(float a);
|
||||
float _SSE_RSqrtFast(float x);
|
||||
float FASTCALL _SSE_VectorNormalize(Vector& vec);
|
||||
void FASTCALL _SSE_VectorNormalizeFast(Vector& vec);
|
||||
float _SSE_InvRSquared(const float* v);
|
||||
void _SSE_SinCos(float x, float* s, float* c);
|
||||
float _SSE_cos( float x);
|
||||
void _SSE2_SinCos(float x, float* s, float* c);
|
||||
float _SSE2_cos(float x);
|
||||
void VectorTransformSSE(const float *in1, const matrix3x4_t& in2, float *out1);
|
||||
void VectorRotateSSE( const float *in1, const matrix3x4_t& in2, float *out1 );
|
||||
|
||||
#endif // _SSE_H
|
1164
mathlib/sseconst.cpp
Normal file
1164
mathlib/sseconst.cpp
Normal file
File diff suppressed because it is too large
Load Diff
105
mathlib/ssenoise.cpp
Normal file
105
mathlib/ssenoise.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Fast low quality noise suitable for real time use
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#include <math.h>
|
||||
#include <float.h> // Needed for FLT_EPSILON
|
||||
#include "basetypes.h"
|
||||
#include <memory.h>
|
||||
#include "tier0/dbg.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
#include "mathlib/vector.h"
|
||||
#include "mathlib/ssemath.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
#include "noisedata.h"
|
||||
|
||||
|
||||
#define MAGIC_NUMBER (1<<15) // gives 8 bits of fraction
|
||||
|
||||
static fltx4 Four_MagicNumbers = { MAGIC_NUMBER, MAGIC_NUMBER, MAGIC_NUMBER, MAGIC_NUMBER };
|
||||
|
||||
|
||||
static ALIGN16 int32 idx_mask[4]= {0xffff, 0xffff, 0xffff, 0xffff};
|
||||
|
||||
#define MASK255 (*((fltx4 *)(& idx_mask )))
|
||||
|
||||
// returns 0..1
|
||||
static inline float GetLatticePointValue( int idx_x, int idx_y, int idx_z )
|
||||
{
|
||||
int ret_idx = perm_a[idx_x & 0xff];
|
||||
ret_idx = perm_b[( idx_y + ret_idx ) & 0xff];
|
||||
ret_idx = perm_c[( idx_z + ret_idx ) & 0xff];
|
||||
return impulse_xcoords[ret_idx];
|
||||
|
||||
}
|
||||
|
||||
fltx4 NoiseSIMD( const fltx4 & x, const fltx4 & y, const fltx4 & z )
|
||||
{
|
||||
// use magic to convert to integer index
|
||||
fltx4 x_idx = AndSIMD( MASK255, AddSIMD( x, Four_MagicNumbers ) );
|
||||
fltx4 y_idx = AndSIMD( MASK255, AddSIMD( y, Four_MagicNumbers ) );
|
||||
fltx4 z_idx = AndSIMD( MASK255, AddSIMD( z, Four_MagicNumbers ) );
|
||||
|
||||
fltx4 lattice000 = Four_Zeros, lattice001 = Four_Zeros, lattice010 = Four_Zeros, lattice011 = Four_Zeros;
|
||||
fltx4 lattice100 = Four_Zeros, lattice101 = Four_Zeros, lattice110 = Four_Zeros, lattice111 = Four_Zeros;
|
||||
|
||||
// FIXME: Converting the input vectors to int indices will cause load-hit-stores (48 bytes)
|
||||
// Converting the indexed noise values back to vectors will cause more (128 bytes)
|
||||
// The noise table could store vectors if we chunked it into 2x2x2 blocks.
|
||||
fltx4 xfrac = Four_Zeros, yfrac = Four_Zeros, zfrac = Four_Zeros;
|
||||
#define DOPASS(i) \
|
||||
{ unsigned int xi = SubInt( x_idx, i ); \
|
||||
unsigned int yi = SubInt( y_idx, i ); \
|
||||
unsigned int zi = SubInt( z_idx, i ); \
|
||||
SubFloat( xfrac, i ) = (xi & 0xff)*(1.0/256.0); \
|
||||
SubFloat( yfrac, i ) = (yi & 0xff)*(1.0/256.0); \
|
||||
SubFloat( zfrac, i ) = (zi & 0xff)*(1.0/256.0); \
|
||||
xi>>=8; \
|
||||
yi>>=8; \
|
||||
zi>>=8; \
|
||||
\
|
||||
SubFloat( lattice000, i ) = GetLatticePointValue( xi,yi,zi ); \
|
||||
SubFloat( lattice001, i ) = GetLatticePointValue( xi,yi,zi+1 ); \
|
||||
SubFloat( lattice010, i ) = GetLatticePointValue( xi,yi+1,zi ); \
|
||||
SubFloat( lattice011, i ) = GetLatticePointValue( xi,yi+1,zi+1 ); \
|
||||
SubFloat( lattice100, i ) = GetLatticePointValue( xi+1,yi,zi ); \
|
||||
SubFloat( lattice101, i ) = GetLatticePointValue( xi+1,yi,zi+1 ); \
|
||||
SubFloat( lattice110, i ) = GetLatticePointValue( xi+1,yi+1,zi ); \
|
||||
SubFloat( lattice111, i ) = GetLatticePointValue( xi+1,yi+1,zi+1 ); \
|
||||
}
|
||||
|
||||
DOPASS( 0 );
|
||||
DOPASS( 1 );
|
||||
DOPASS( 2 );
|
||||
DOPASS( 3 );
|
||||
|
||||
// now, we have 8 lattice values for each of four points as m128s, and interpolant values for
|
||||
// each axis in m128 form in [xyz]frac. Perfom the trilinear interpolation as SIMD ops
|
||||
|
||||
// first, do x interpolation
|
||||
fltx4 l2d00 = AddSIMD( lattice000, MulSIMD( xfrac, SubSIMD( lattice100, lattice000 ) ) );
|
||||
fltx4 l2d01 = AddSIMD( lattice001, MulSIMD( xfrac, SubSIMD( lattice101, lattice001 ) ) );
|
||||
fltx4 l2d10 = AddSIMD( lattice010, MulSIMD( xfrac, SubSIMD( lattice110, lattice010 ) ) );
|
||||
fltx4 l2d11 = AddSIMD( lattice011, MulSIMD( xfrac, SubSIMD( lattice111, lattice011 ) ) );
|
||||
|
||||
// now, do y interpolation
|
||||
fltx4 l1d0 = AddSIMD( l2d00, MulSIMD( yfrac, SubSIMD( l2d10, l2d00 ) ) );
|
||||
fltx4 l1d1 = AddSIMD( l2d01, MulSIMD( yfrac, SubSIMD( l2d11, l2d01 ) ) );
|
||||
|
||||
// final z interpolation
|
||||
fltx4 rslt = AddSIMD( l1d0, MulSIMD( zfrac, SubSIMD( l1d1, l1d0 ) ) );
|
||||
|
||||
// map to 0..1
|
||||
return MulSIMD( Four_Twos, SubSIMD( rslt, Four_PointFives ) );
|
||||
|
||||
|
||||
}
|
||||
|
||||
fltx4 NoiseSIMD( FourVectors const &pos )
|
||||
{
|
||||
return NoiseSIMD( pos.x, pos.y, pos.z );
|
||||
}
|
12
mathlib/vector.cpp
Normal file
12
mathlib/vector.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "mathlib/vector.h"
|
||||
|
||||
Vector vec3_origin(0,0,0);
|
||||
|
1263
mathlib/vmatrix.cpp
Normal file
1263
mathlib/vmatrix.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2521
tier1/KeyValues.cpp
Normal file
2521
tier1/KeyValues.cpp
Normal file
File diff suppressed because it is too large
Load Diff
331
tier1/NetAdr.cpp
Normal file
331
tier1/NetAdr.cpp
Normal file
@ -0,0 +1,331 @@
|
||||
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// NetAdr.cpp: implementation of the CNetAdr class.
|
||||
//
|
||||
//===========================================================================//
|
||||
#if defined( _WIN32 ) && !defined( _X360 )
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "tier0/dbg.h"
|
||||
#include "netadr.h"
|
||||
#include "tier1/strtools.h"
|
||||
|
||||
#if defined( _WIN32 ) && !defined( _X360 )
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <winsock.h>
|
||||
typedef int socklen_t;
|
||||
#elif !defined( _X360 )
|
||||
#include <netinet/in.h> // ntohs()
|
||||
#include <netdb.h> // gethostbyname()
|
||||
#include <sys/socket.h> // getsockname()
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool netadr_t::CompareAdr (const netadr_t &a, bool onlyBase) const
|
||||
{
|
||||
if ( a.type != type )
|
||||
return false;
|
||||
|
||||
if ( type == NA_LOOPBACK )
|
||||
return true;
|
||||
|
||||
if ( type == NA_BROADCAST )
|
||||
return true;
|
||||
|
||||
if ( type == NA_IP )
|
||||
{
|
||||
if ( !onlyBase && (port != a.port) )
|
||||
return false;
|
||||
|
||||
if ( a.ip[0] == ip[0] && a.ip[1] == ip[1] && a.ip[2] == ip[2] && a.ip[3] == ip[3] )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool netadr_t::CompareClassBAdr (const netadr_t &a) const
|
||||
{
|
||||
if ( a.type != type )
|
||||
return false;
|
||||
|
||||
if ( type == NA_LOOPBACK )
|
||||
return true;
|
||||
|
||||
if ( type == NA_IP )
|
||||
{
|
||||
if (a.ip[0] == ip[0] && a.ip[1] == ip[1] )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool netadr_t::CompareClassCAdr (const netadr_t &a) const
|
||||
{
|
||||
if ( a.type != type )
|
||||
return false;
|
||||
|
||||
if ( type == NA_LOOPBACK )
|
||||
return true;
|
||||
|
||||
if ( type == NA_IP )
|
||||
{
|
||||
if (a.ip[0] == ip[0] && a.ip[1] == ip[1] && a.ip[2] == ip[2] )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
// reserved addresses are not routeable, so they can all be used in a LAN game
|
||||
bool netadr_t::IsReservedAdr () const
|
||||
{
|
||||
if ( type == NA_LOOPBACK )
|
||||
return true;
|
||||
|
||||
if ( type == NA_IP )
|
||||
{
|
||||
if ( (ip[0] == 10) || // 10.x.x.x is reserved
|
||||
(ip[0] == 127) || // 127.x.x.x
|
||||
(ip[0] == 172 && ip[1] >= 16 && ip[1] <= 31) || // 172.16.x.x - 172.31.x.x
|
||||
(ip[0] == 192 && ip[1] >= 168) ) // 192.168.x.x
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const char * netadr_t::ToString(bool baseOnly) const
|
||||
{
|
||||
static char s[64];
|
||||
|
||||
Q_strncpy (s, "unknown", sizeof( s ) );
|
||||
|
||||
if (type == NA_LOOPBACK)
|
||||
{
|
||||
Q_strncpy (s, "loopback", sizeof( s ) );
|
||||
}
|
||||
else if (type == NA_BROADCAST)
|
||||
{
|
||||
Q_strncpy (s, "broadcast", sizeof( s ) );
|
||||
}
|
||||
else if (type == NA_IP)
|
||||
{
|
||||
if ( baseOnly)
|
||||
{
|
||||
Q_snprintf (s, sizeof( s ), "%i.%i.%i.%i", ip[0], ip[1], ip[2], ip[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_snprintf (s, sizeof( s ), "%i.%i.%i.%i:%i", ip[0], ip[1], ip[2], ip[3], ntohs(port));
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
bool netadr_t::IsLocalhost() const
|
||||
{
|
||||
// are we 127.0.0.1 ?
|
||||
return (ip[0] == 127) && (ip[1] == 0) && (ip[2] == 0) && (ip[3] == 1);
|
||||
}
|
||||
|
||||
bool netadr_t::IsLoopback() const
|
||||
{
|
||||
// are we useding engine loopback buffers
|
||||
return type == NA_LOOPBACK;
|
||||
}
|
||||
|
||||
void netadr_t::Clear()
|
||||
{
|
||||
ip[0] = ip[1] = ip[2] = ip[3] = 0;
|
||||
port = 0;
|
||||
type = NA_NULL;
|
||||
}
|
||||
|
||||
void netadr_t::SetIP(uint8 b1, uint8 b2, uint8 b3, uint8 b4)
|
||||
{
|
||||
ip[0] = b1;
|
||||
ip[1] = b2;
|
||||
ip[2] = b3;
|
||||
ip[3] = b4;
|
||||
}
|
||||
|
||||
void netadr_t::SetIP(uint unIP)
|
||||
{
|
||||
*((uint*)ip) = BigLong( unIP );
|
||||
}
|
||||
|
||||
void netadr_t::SetType(netadrtype_t newtype)
|
||||
{
|
||||
type = newtype;
|
||||
}
|
||||
|
||||
netadrtype_t netadr_t::GetType() const
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
unsigned short netadr_t::GetPort() const
|
||||
{
|
||||
return BigShort( port );
|
||||
}
|
||||
|
||||
unsigned int netadr_t::GetIP() const
|
||||
{
|
||||
return *(unsigned int *)&ip;;
|
||||
}
|
||||
|
||||
unsigned long netadr_t::addr_ntohl() const
|
||||
{
|
||||
return ntohl( GetIP() );
|
||||
}
|
||||
|
||||
unsigned long netadr_t::addr_htonl() const
|
||||
{
|
||||
return htonl( GetIP() );
|
||||
}
|
||||
|
||||
|
||||
void netadr_t::ToSockadr (struct sockaddr * s) const
|
||||
{
|
||||
Q_memset ( s, 0, sizeof(struct sockaddr));
|
||||
|
||||
if (type == NA_BROADCAST)
|
||||
{
|
||||
((struct sockaddr_in*)s)->sin_family = AF_INET;
|
||||
((struct sockaddr_in*)s)->sin_port = port;
|
||||
((struct sockaddr_in*)s)->sin_addr.s_addr = INADDR_BROADCAST;
|
||||
}
|
||||
else if (type == NA_IP)
|
||||
{
|
||||
((struct sockaddr_in*)s)->sin_family = AF_INET;
|
||||
((struct sockaddr_in*)s)->sin_addr.s_addr = *(int *)&ip;
|
||||
((struct sockaddr_in*)s)->sin_port = port;
|
||||
}
|
||||
else if (type == NA_LOOPBACK )
|
||||
{
|
||||
((struct sockaddr_in*)s)->sin_family = AF_INET;
|
||||
((struct sockaddr_in*)s)->sin_port = port;
|
||||
((struct sockaddr_in*)s)->sin_addr.s_addr = INADDR_LOOPBACK ;
|
||||
}
|
||||
}
|
||||
|
||||
bool netadr_t::SetFromSockadr(const struct sockaddr * s)
|
||||
{
|
||||
if (s->sa_family == AF_INET)
|
||||
{
|
||||
type = NA_IP;
|
||||
*(int *)&ip = ((struct sockaddr_in *)s)->sin_addr.s_addr;
|
||||
port = ((struct sockaddr_in *)s)->sin_port;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Clear();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool netadr_t::IsValid() const
|
||||
{
|
||||
return ( (port !=0 ) && (type != NA_NULL) &&
|
||||
( ip[0] != 0 || ip[1] != 0 || ip[2] != 0 || ip[3] != 0 ) );
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#undef SetPort // get around stupid WINSPOOL.H macro
|
||||
#endif
|
||||
|
||||
void netadr_t::SetPort(unsigned short newport)
|
||||
{
|
||||
port = BigShort( newport );
|
||||
}
|
||||
|
||||
void netadr_t::SetFromString( const char *pch, bool bUseDNS )
|
||||
{
|
||||
Clear();
|
||||
type = NA_IP;
|
||||
|
||||
Assert( pch ); // invalid to call this with NULL pointer; fix your code bug!
|
||||
if ( !pch ) // but let's not crash
|
||||
return;
|
||||
|
||||
|
||||
if ( pch[0] >= '0' && pch[0] <= '9' && strchr( pch, '.' ) )
|
||||
{
|
||||
int n1, n2, n3, n4, n5;
|
||||
int nRes = sscanf( pch, "%d.%d.%d.%d:%d", &n1, &n2, &n3, &n4, &n5 );
|
||||
if ( nRes >= 4 )
|
||||
{
|
||||
SetIP( n1, n2, n3, n4 );
|
||||
}
|
||||
|
||||
if ( nRes == 5 )
|
||||
{
|
||||
SetPort( ( uint16 ) n5 );
|
||||
}
|
||||
}
|
||||
else if ( bUseDNS )
|
||||
{
|
||||
// X360TBD:
|
||||
#if !defined( _X360 )
|
||||
char szHostName[ 256 ];
|
||||
Q_strncpy( szHostName, pch, sizeof(szHostName) );
|
||||
char *pchColon = strchr( szHostName, ':' );
|
||||
if ( pchColon )
|
||||
{
|
||||
*pchColon = 0;
|
||||
}
|
||||
|
||||
// DNS it
|
||||
struct hostent *h = gethostbyname( szHostName );
|
||||
if ( !h )
|
||||
return;
|
||||
|
||||
SetIP( ntohl( *(int *)h->h_addr_list[0] ) );
|
||||
|
||||
if ( pchColon )
|
||||
{
|
||||
SetPort( atoi( ++pchColon ) );
|
||||
}
|
||||
#else
|
||||
Assert( 0 );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool netadr_t::operator<(const netadr_t &netadr) const
|
||||
{
|
||||
if ( *((uint *)netadr.ip) < *((uint *)ip) )
|
||||
return true;
|
||||
else if ( *((uint *)netadr.ip) > *((uint *)ip) )
|
||||
return false;
|
||||
return ( netadr.port < port );
|
||||
}
|
||||
|
||||
|
||||
void netadr_t::SetFromSocket( int hSocket )
|
||||
{
|
||||
#if !defined(_X360)
|
||||
Clear();
|
||||
type = NA_IP;
|
||||
|
||||
struct sockaddr address;
|
||||
int namelen = sizeof(address);
|
||||
if ( getsockname( hSocket, (struct sockaddr *)&address, (socklen_t *)&namelen) == 0 )
|
||||
{
|
||||
SetFromSockadr( &address );
|
||||
}
|
||||
#else
|
||||
Assert(0);
|
||||
#endif
|
||||
}
|
1269
tier1/bitbuf.cpp
Normal file
1269
tier1/bitbuf.cpp
Normal file
File diff suppressed because it is too large
Load Diff
90
tier1/byteswap.cpp
Normal file
90
tier1/byteswap.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
//========= Copyright © 1996-2006, Valve LLC, All rights reserved. ============
|
||||
//
|
||||
// Purpose: Low level byte swapping routines.
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
#include "byteswap.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copy a single field from the input buffer to the output buffer, swapping the bytes if necessary
|
||||
//-----------------------------------------------------------------------------
|
||||
void CByteswap::SwapFieldToTargetEndian( void* pOutputBuffer, void *pData, typedescription_t *pField )
|
||||
{
|
||||
switch ( pField->fieldType )
|
||||
{
|
||||
case FIELD_CHARACTER:
|
||||
SwapBufferToTargetEndian<char>( (char*)pOutputBuffer, (char*)pData, pField->fieldSize );
|
||||
break;
|
||||
|
||||
case FIELD_BOOLEAN:
|
||||
SwapBufferToTargetEndian<bool>( (bool*)pOutputBuffer, (bool*)pData, pField->fieldSize );
|
||||
break;
|
||||
|
||||
case FIELD_SHORT:
|
||||
SwapBufferToTargetEndian<short>( (short*)pOutputBuffer, (short*)pData, pField->fieldSize );
|
||||
break;
|
||||
|
||||
case FIELD_FLOAT:
|
||||
SwapBufferToTargetEndian<uint>( (uint*)pOutputBuffer, (uint*)pData, pField->fieldSize );
|
||||
break;
|
||||
|
||||
case FIELD_INTEGER:
|
||||
SwapBufferToTargetEndian<int>( (int*)pOutputBuffer, (int*)pData, pField->fieldSize );
|
||||
break;
|
||||
|
||||
case FIELD_VECTOR:
|
||||
SwapBufferToTargetEndian<uint>( (uint*)pOutputBuffer, (uint*)pData, pField->fieldSize * 3 );
|
||||
break;
|
||||
|
||||
case FIELD_VECTOR2D:
|
||||
SwapBufferToTargetEndian<uint>( (uint*)pOutputBuffer, (uint*)pData, pField->fieldSize * 2 );
|
||||
break;
|
||||
|
||||
case FIELD_QUATERNION:
|
||||
SwapBufferToTargetEndian<uint>( (uint*)pOutputBuffer, (uint*)pData, pField->fieldSize * 4 );
|
||||
break;
|
||||
|
||||
case FIELD_EMBEDDED:
|
||||
{
|
||||
typedescription_t *pEmbed = pField->td->dataDesc;
|
||||
for ( int i = 0; i < pField->fieldSize; ++i )
|
||||
{
|
||||
SwapFieldsToTargetEndian( (byte*)pOutputBuffer + pEmbed->fieldOffset,
|
||||
(byte*)pData + pEmbed->fieldOffset,
|
||||
pField->td );
|
||||
|
||||
pOutputBuffer = (byte*)pOutputBuffer + pField->fieldSizeInBytes;
|
||||
pData = (byte*)pData + pField->fieldSizeInBytes;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Write a block of fields. Works a bit like the saverestore code.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CByteswap::SwapFieldsToTargetEndian( void *pOutputBuffer, void *pBaseData, datamap_t *pDataMap )
|
||||
{
|
||||
// deal with base class first
|
||||
if ( pDataMap->baseMap )
|
||||
{
|
||||
SwapFieldsToTargetEndian( pOutputBuffer, pBaseData, pDataMap->baseMap );
|
||||
}
|
||||
|
||||
typedescription_t *pFields = pDataMap->dataDesc;
|
||||
int fieldCount = pDataMap->dataNumFields;
|
||||
for ( int i = 0; i < fieldCount; ++i )
|
||||
{
|
||||
typedescription_t *pField = &pFields[i];
|
||||
SwapFieldToTargetEndian( (BYTE*)pOutputBuffer + pField->fieldOffset,
|
||||
(BYTE*)pBaseData + pField->fieldOffset,
|
||||
pField );
|
||||
}
|
||||
}
|
||||
|
41
tier1/characterset.cpp
Normal file
41
tier1/characterset.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: $
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// $Log: $
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
#include <string.h>
|
||||
#include "characterset.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: builds a simple lookup table of a group of important characters
|
||||
// Input : *pParseGroup - pointer to the buffer for the group
|
||||
// *pGroupString - null terminated list of characters to flag
|
||||
//-----------------------------------------------------------------------------
|
||||
void CharacterSetBuild( characterset_t *pSetBuffer, const char *pszSetString )
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
// Test our pointers
|
||||
if ( !pSetBuffer || !pszSetString )
|
||||
return;
|
||||
|
||||
memset( pSetBuffer->set, 0, sizeof(pSetBuffer->set) );
|
||||
|
||||
while ( pszSetString[i] )
|
||||
{
|
||||
pSetBuffer->set[ static_cast<size_t>(pszSetString[i]) ] = 1;
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
180
tier1/checksum_crc.cpp
Normal file
180
tier1/checksum_crc.cpp
Normal file
@ -0,0 +1,180 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Generic CRC functions
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "basetypes.h"
|
||||
#include "commonmacros.h"
|
||||
#include "checksum_crc.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#define CRC32_INIT_VALUE 0xFFFFFFFFUL
|
||||
#define CRC32_XOR_VALUE 0xFFFFFFFFUL
|
||||
|
||||
#define NUM_BYTES 256
|
||||
static const CRC32_t pulCRCTable[NUM_BYTES] =
|
||||
{
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
|
||||
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
|
||||
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
|
||||
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
|
||||
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
|
||||
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
|
||||
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
|
||||
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
|
||||
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
|
||||
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
|
||||
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
|
||||
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
|
||||
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
|
||||
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
|
||||
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
|
||||
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
|
||||
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
|
||||
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
|
||||
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
|
||||
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
|
||||
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
|
||||
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
|
||||
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
|
||||
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
|
||||
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
|
||||
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
|
||||
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
|
||||
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
|
||||
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
|
||||
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
|
||||
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
|
||||
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
|
||||
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
|
||||
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
|
||||
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
|
||||
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
|
||||
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
|
||||
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
|
||||
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||
};
|
||||
|
||||
void CRC32_Init(CRC32_t *pulCRC)
|
||||
{
|
||||
*pulCRC = CRC32_INIT_VALUE;
|
||||
}
|
||||
|
||||
void CRC32_Final(CRC32_t *pulCRC)
|
||||
{
|
||||
*pulCRC ^= CRC32_XOR_VALUE;
|
||||
}
|
||||
|
||||
CRC32_t CRC32_GetTableEntry( unsigned int slot )
|
||||
{
|
||||
return pulCRCTable[(unsigned char)slot];
|
||||
}
|
||||
|
||||
void CRC32_ProcessBuffer(CRC32_t *pulCRC, const void *pBuffer, int nBuffer)
|
||||
{
|
||||
CRC32_t ulCrc = *pulCRC;
|
||||
unsigned char *pb = (unsigned char *)pBuffer;
|
||||
unsigned int nFront;
|
||||
int nMain;
|
||||
|
||||
JustAfew:
|
||||
|
||||
switch (nBuffer)
|
||||
{
|
||||
case 7:
|
||||
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
|
||||
|
||||
case 6:
|
||||
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
|
||||
|
||||
case 5:
|
||||
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
|
||||
|
||||
case 4:
|
||||
ulCrc ^= LittleLong( *(CRC32_t *)pb );
|
||||
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
|
||||
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
|
||||
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
|
||||
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
|
||||
*pulCRC = ulCrc;
|
||||
return;
|
||||
|
||||
case 3:
|
||||
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
|
||||
|
||||
case 2:
|
||||
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
|
||||
|
||||
case 1:
|
||||
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
|
||||
|
||||
case 0:
|
||||
*pulCRC = ulCrc;
|
||||
return;
|
||||
}
|
||||
|
||||
// We may need to do some alignment work up front, and at the end, so that
|
||||
// the main loop is aligned and only has to worry about 8 byte at a time.
|
||||
//
|
||||
// The low-order two bits of pb and nBuffer in total control the
|
||||
// upfront work.
|
||||
//
|
||||
nFront = ((unsigned int)pb) & 3;
|
||||
nBuffer -= nFront;
|
||||
switch (nFront)
|
||||
{
|
||||
case 3:
|
||||
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
|
||||
case 2:
|
||||
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
|
||||
case 1:
|
||||
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
|
||||
}
|
||||
|
||||
nMain = nBuffer >> 3;
|
||||
while (nMain--)
|
||||
{
|
||||
ulCrc ^= LittleLong( *(CRC32_t *)pb );
|
||||
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
|
||||
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
|
||||
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
|
||||
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
|
||||
ulCrc ^= LittleLong( *(CRC32_t *)(pb + 4) );
|
||||
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
|
||||
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
|
||||
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
|
||||
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
|
||||
pb += 8;
|
||||
}
|
||||
|
||||
nBuffer &= 7;
|
||||
goto JustAfew;
|
||||
}
|
271
tier1/checksum_md5.cpp
Normal file
271
tier1/checksum_md5.cpp
Normal file
@ -0,0 +1,271 @@
|
||||
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//===========================================================================//
|
||||
|
||||
#include "basetypes.h"
|
||||
#include "commonmacros.h"
|
||||
#include "checksum_md5.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "tier1/strtools.h"
|
||||
#include "tier0/dbg.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
// The four core functions - F1 is optimized somewhat
|
||||
// #define F1(x, y, z) (x & y | ~x & z)
|
||||
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define F2(x, y, z) F1(z, x, y)
|
||||
#define F3(x, y, z) (x ^ y ^ z)
|
||||
#define F4(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
// This is the central step in the MD5 algorithm.
|
||||
#define MD5STEP(f, w, x, y, z, data, s) \
|
||||
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: The core of the MD5 algorithm, this alters an existing MD5 hash to
|
||||
// reflect the addition of 16 longwords of new data. MD5Update blocks
|
||||
// the data and converts bytes into longwords for this routine.
|
||||
// Input : buf[4] -
|
||||
// in[16] -
|
||||
// Output : static void
|
||||
//-----------------------------------------------------------------------------
|
||||
static void MD5Transform(unsigned int buf[4], unsigned int const in[16])
|
||||
{
|
||||
register unsigned int a, b, c, d;
|
||||
|
||||
a = buf[0];
|
||||
b = buf[1];
|
||||
c = buf[2];
|
||||
d = buf[3];
|
||||
|
||||
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
||||
|
||||
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
||||
|
||||
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
||||
|
||||
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
||||
|
||||
buf[0] += a;
|
||||
buf[1] += b;
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Start MD5 accumulation. Set bit count to 0 and buffer to mysterious initialization constants.
|
||||
|
||||
// Input : *ctx -
|
||||
//-----------------------------------------------------------------------------
|
||||
void MD5Init(MD5Context_t *ctx)
|
||||
{
|
||||
ctx->buf[0] = 0x67452301;
|
||||
ctx->buf[1] = 0xefcdab89;
|
||||
ctx->buf[2] = 0x98badcfe;
|
||||
ctx->buf[3] = 0x10325476;
|
||||
|
||||
ctx->bits[0] = 0;
|
||||
ctx->bits[1] = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Update context to reflect the concatenation of another buffer full of bytes.
|
||||
// Input : *ctx -
|
||||
// *buf -
|
||||
// len -
|
||||
//-----------------------------------------------------------------------------
|
||||
void MD5Update(MD5Context_t *ctx, unsigned char const *buf, unsigned int len)
|
||||
{
|
||||
unsigned int t;
|
||||
|
||||
/* Update bitcount */
|
||||
|
||||
t = ctx->bits[0];
|
||||
if ((ctx->bits[0] = t + ((unsigned int) len << 3)) < t)
|
||||
ctx->bits[1]++; /* Carry from low to high */
|
||||
ctx->bits[1] += len >> 29;
|
||||
|
||||
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
|
||||
|
||||
/* Handle any leading odd-sized chunks */
|
||||
|
||||
if (t)
|
||||
{
|
||||
unsigned char *p = (unsigned char *) ctx->in + t;
|
||||
|
||||
t = 64 - t;
|
||||
if (len < t)
|
||||
{
|
||||
memcpy(p, buf, len);
|
||||
return;
|
||||
}
|
||||
memcpy(p, buf, t);
|
||||
//byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (unsigned int *) ctx->in);
|
||||
buf += t;
|
||||
len -= t;
|
||||
}
|
||||
/* Process data in 64-byte chunks */
|
||||
|
||||
while (len >= 64)
|
||||
{
|
||||
memcpy(ctx->in, buf, 64);
|
||||
//byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (unsigned int *) ctx->in);
|
||||
buf += 64;
|
||||
len -= 64;
|
||||
}
|
||||
|
||||
/* Handle any remaining bytes of data. */
|
||||
memcpy(ctx->in, buf, len);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Final wrapup - pad to 64-byte boundary with the bit pattern
|
||||
// 1 0* (64-bit count of bits processed, MSB-first)
|
||||
// Input : digest[MD5_DIGEST_LENGTH] -
|
||||
// *ctx -
|
||||
//-----------------------------------------------------------------------------
|
||||
void MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5Context_t *ctx)
|
||||
{
|
||||
unsigned count;
|
||||
unsigned char *p;
|
||||
|
||||
/* Compute number of bytes mod 64 */
|
||||
count = (ctx->bits[0] >> 3) & 0x3F;
|
||||
|
||||
/* Set the first char of padding to 0x80. This is safe since there is
|
||||
always at least one byte free */
|
||||
p = ctx->in + count;
|
||||
*p++ = 0x80;
|
||||
|
||||
/* Bytes of padding needed to make 64 bytes */
|
||||
count = 64 - 1 - count;
|
||||
|
||||
/* Pad out to 56 mod 64 */
|
||||
if (count < 8)
|
||||
{
|
||||
/* Two lots of padding: Pad the first block to 64 bytes */
|
||||
memset(p, 0, count);
|
||||
//byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (unsigned int *) ctx->in);
|
||||
|
||||
/* Now fill the next block with 56 bytes */
|
||||
memset(ctx->in, 0, 56);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Pad block to 56 bytes */
|
||||
memset(p, 0, count - 8);
|
||||
}
|
||||
//byteReverse(ctx->in, 14);
|
||||
|
||||
/* Append length in bits and transform */
|
||||
((unsigned int *) ctx->in)[14] = ctx->bits[0];
|
||||
((unsigned int *) ctx->in)[15] = ctx->bits[1];
|
||||
|
||||
MD5Transform(ctx->buf, (unsigned int *) ctx->in);
|
||||
//byteReverse((unsigned char *) ctx->buf, 4);
|
||||
memcpy(digest, ctx->buf, MD5_DIGEST_LENGTH);
|
||||
memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *hash -
|
||||
// hashlen -
|
||||
// Output : char
|
||||
//-----------------------------------------------------------------------------
|
||||
char *MD5_Print( unsigned char *hash, int hashlen )
|
||||
{
|
||||
static char szReturn[64];
|
||||
|
||||
Assert( hashlen <= 32 );
|
||||
|
||||
Q_binarytohex( hash, hashlen, szReturn, sizeof( szReturn ) );
|
||||
return szReturn;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: generate pseudo random number from a seed number
|
||||
// Input : seed number
|
||||
// Output : pseudo random number
|
||||
//-----------------------------------------------------------------------------
|
||||
unsigned int MD5_PseudoRandom(unsigned int nSeed)
|
||||
{
|
||||
MD5Context_t ctx;
|
||||
unsigned char digest[MD5_DIGEST_LENGTH]; // The MD5 Hash
|
||||
|
||||
memset( &ctx, 0, sizeof( ctx ) );
|
||||
|
||||
MD5Init(&ctx);
|
||||
MD5Update(&ctx, (unsigned char*)&nSeed, sizeof(nSeed) );
|
||||
MD5Final(digest, &ctx);
|
||||
|
||||
return *(unsigned int*)(digest+6); // use 4 middle bytes for random value
|
||||
}
|
636
tier1/commandbuffer.cpp
Normal file
636
tier1/commandbuffer.cpp
Normal file
@ -0,0 +1,636 @@
|
||||
//===== Copyright © 1996-2006, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: $
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
|
||||
#include "tier1/CommandBuffer.h"
|
||||
#include "tier1/utlbuffer.h"
|
||||
#include "tier1/strtools.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#define MAX_ALIAS_NAME 32
|
||||
#define MAX_COMMAND_LENGTH 1024
|
||||
|
||||
struct cmdalias_t
|
||||
{
|
||||
cmdalias_t *next;
|
||||
char name[ MAX_ALIAS_NAME ];
|
||||
char *value;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructor, destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CCommandBuffer::CCommandBuffer( ) : m_Commands( 32, 32 )
|
||||
{
|
||||
m_hNextCommand = m_Commands.InvalidIndex();
|
||||
m_nWaitDelayTicks = 1;
|
||||
m_nCurrentTick = 0;
|
||||
m_nLastTickToProcess = -1;
|
||||
m_nArgSBufferSize = 0;
|
||||
m_bIsProcessingCommands = false;
|
||||
m_nMaxArgSBufferLength = ARGS_BUFFER_LENGTH;
|
||||
}
|
||||
|
||||
CCommandBuffer::~CCommandBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Indicates how long to delay when encoutering a 'wait' command
|
||||
//-----------------------------------------------------------------------------
|
||||
void CCommandBuffer::SetWaitDelayTime( int nTickDelay )
|
||||
{
|
||||
Assert( nTickDelay >= 0 );
|
||||
m_nWaitDelayTicks = nTickDelay;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Specifies a max limit of the args buffer. For unittesting. Size == 0 means use default
|
||||
//-----------------------------------------------------------------------------
|
||||
void CCommandBuffer::LimitArgumentBufferSize( int nSize )
|
||||
{
|
||||
if ( nSize > ARGS_BUFFER_LENGTH )
|
||||
{
|
||||
nSize = ARGS_BUFFER_LENGTH;
|
||||
}
|
||||
|
||||
m_nMaxArgSBufferLength = ( nSize == 0 ) ? ARGS_BUFFER_LENGTH : nSize;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Parses argv0 out of the buffer
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CCommandBuffer::ParseArgV0( CUtlBuffer &buf, char *pArgV0, int nMaxLen, const char **pArgS )
|
||||
{
|
||||
pArgV0[0] = 0;
|
||||
*pArgS = NULL;
|
||||
|
||||
if ( !buf.IsValid() )
|
||||
return false;
|
||||
|
||||
int nSize = buf.ParseToken( CCommand::DefaultBreakSet(), pArgV0, nMaxLen );
|
||||
if ( ( nSize <= 0 ) || ( nMaxLen == nSize ) )
|
||||
return false;
|
||||
|
||||
int nArgSLen = buf.TellMaxPut() - buf.TellGet();
|
||||
*pArgS = (nArgSLen > 0) ? (const char*)buf.PeekGet() : NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Insert a command into the command queue
|
||||
//-----------------------------------------------------------------------------
|
||||
void CCommandBuffer::InsertCommandAtAppropriateTime( int hCommand )
|
||||
{
|
||||
int i;
|
||||
Command_t &command = m_Commands[hCommand];
|
||||
for ( i = m_Commands.Head(); i != m_Commands.InvalidIndex(); i = m_Commands.Next(i) )
|
||||
{
|
||||
if ( m_Commands[i].m_nTick > command.m_nTick )
|
||||
break;
|
||||
}
|
||||
m_Commands.LinkBefore( i, hCommand );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Insert a command into the command queue at the appropriate time
|
||||
//-----------------------------------------------------------------------------
|
||||
void CCommandBuffer::InsertImmediateCommand( int hCommand )
|
||||
{
|
||||
m_Commands.LinkBefore( m_hNextCommand, hCommand );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Insert a command into the command queue
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CCommandBuffer::InsertCommand( const char *pArgS, int nCommandSize, int nTick )
|
||||
{
|
||||
if ( nCommandSize >= CCommand::MaxCommandLength() )
|
||||
{
|
||||
Warning( "WARNING: Command too long... ignoring!\n%s\n", pArgS );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add one for null termination
|
||||
if ( m_nArgSBufferSize + nCommandSize + 1 > m_nMaxArgSBufferLength )
|
||||
{
|
||||
Compact();
|
||||
if ( m_nArgSBufferSize + nCommandSize + 1 > m_nMaxArgSBufferLength )
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy( &m_pArgSBuffer[m_nArgSBufferSize], pArgS, nCommandSize );
|
||||
m_pArgSBuffer[m_nArgSBufferSize + nCommandSize] = 0;
|
||||
++nCommandSize;
|
||||
|
||||
int hCommand = m_Commands.Alloc();
|
||||
Command_t &command = m_Commands[hCommand];
|
||||
command.m_nTick = nTick;
|
||||
command.m_nFirstArgS = m_nArgSBufferSize;
|
||||
command.m_nBufferSize = nCommandSize;
|
||||
|
||||
m_nArgSBufferSize += nCommandSize;
|
||||
|
||||
if ( !m_bIsProcessingCommands || ( nTick > m_nCurrentTick ) )
|
||||
{
|
||||
InsertCommandAtAppropriateTime( hCommand );
|
||||
}
|
||||
else
|
||||
{
|
||||
InsertImmediateCommand( hCommand );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns the length of the next command
|
||||
//-----------------------------------------------------------------------------
|
||||
void CCommandBuffer::GetNextCommandLength( const char *pText, int nMaxLen, int *pCommandLength, int *pNextCommandOffset )
|
||||
{
|
||||
int nCommandLength = 0;
|
||||
int nNextCommandOffset;
|
||||
bool bIsQuoted = false;
|
||||
bool bIsCommented = false;
|
||||
for ( nNextCommandOffset=0; nNextCommandOffset < nMaxLen; ++nNextCommandOffset, nCommandLength += bIsCommented ? 0 : 1 )
|
||||
{
|
||||
char c = pText[nNextCommandOffset];
|
||||
if ( !bIsCommented )
|
||||
{
|
||||
if ( c == '"' )
|
||||
{
|
||||
bIsQuoted = !bIsQuoted;
|
||||
continue;
|
||||
}
|
||||
|
||||
// don't break if inside a C++ style comment
|
||||
if ( !bIsQuoted && c == '/' )
|
||||
{
|
||||
bIsCommented = ( nNextCommandOffset < nMaxLen-1 ) && pText[nNextCommandOffset+1] == '/';
|
||||
if ( bIsCommented )
|
||||
{
|
||||
++nNextCommandOffset;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// don't break if inside a quoted string
|
||||
if ( !bIsQuoted && c == ';' )
|
||||
break;
|
||||
}
|
||||
|
||||
// FIXME: This is legacy behavior; should we not break if a \n is inside a quoted string?
|
||||
if ( c == '\n' )
|
||||
break;
|
||||
}
|
||||
|
||||
*pCommandLength = nCommandLength;
|
||||
*pNextCommandOffset = nNextCommandOffset;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Add text to command buffer, return false if it couldn't owing to overflow
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CCommandBuffer::AddText( const char *pText, int nTickDelay )
|
||||
{
|
||||
Assert( nTickDelay >= 0 );
|
||||
|
||||
int nLen = Q_strlen( pText );
|
||||
int nTick = m_nCurrentTick + nTickDelay;
|
||||
|
||||
// Parse the text into distinct commands
|
||||
const char *pCurrentCommand = pText;
|
||||
int nOffsetToNextCommand;
|
||||
for( ; nLen > 0; nLen -= nOffsetToNextCommand+1, pCurrentCommand += nOffsetToNextCommand+1 )
|
||||
{
|
||||
// find a \n or ; line break
|
||||
int nCommandLength;
|
||||
GetNextCommandLength( pCurrentCommand, nLen, &nCommandLength, &nOffsetToNextCommand );
|
||||
if ( nCommandLength <= 0 )
|
||||
continue;
|
||||
|
||||
const char *pArgS;
|
||||
char *pArgV0 = (char*)_alloca( nCommandLength+1 );
|
||||
CUtlBuffer bufParse( pCurrentCommand, nCommandLength, CUtlBuffer::TEXT_BUFFER | CUtlBuffer::READ_ONLY );
|
||||
ParseArgV0( bufParse, pArgV0, nCommandLength+1, &pArgS );
|
||||
if ( pArgV0[0] == 0 )
|
||||
continue;
|
||||
|
||||
// Deal with the special 'wait' command
|
||||
if ( !Q_stricmp( pArgV0, "wait" ) )
|
||||
{
|
||||
int nDelay = pArgS ? atoi( pArgS ) : m_nWaitDelayTicks;
|
||||
nTick += nDelay;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !InsertCommand( pCurrentCommand, nCommandLength, nTick ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Are we in the middle of processing commands?
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CCommandBuffer::IsProcessingCommands()
|
||||
{
|
||||
return m_bIsProcessingCommands;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Delays all queued commands to execute at a later time
|
||||
//-----------------------------------------------------------------------------
|
||||
void CCommandBuffer::DelayAllQueuedCommands( int nDelay )
|
||||
{
|
||||
if ( nDelay <= 0 )
|
||||
return;
|
||||
|
||||
for ( int i = m_Commands.Head(); i != m_Commands.InvalidIndex(); i = m_Commands.Next(i) )
|
||||
{
|
||||
m_Commands[i].m_nTick += nDelay;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Call this to begin iterating over all commands up to flCurrentTime
|
||||
//-----------------------------------------------------------------------------
|
||||
void CCommandBuffer::BeginProcessingCommands( int nDeltaTicks )
|
||||
{
|
||||
if ( nDeltaTicks == 0 )
|
||||
return;
|
||||
|
||||
Assert( !m_bIsProcessingCommands );
|
||||
m_bIsProcessingCommands = true;
|
||||
m_nLastTickToProcess = m_nCurrentTick + nDeltaTicks - 1;
|
||||
|
||||
// Necessary to insert commands while commands are being processed
|
||||
m_hNextCommand = m_Commands.Head();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns the next command
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CCommandBuffer::DequeueNextCommand( )
|
||||
{
|
||||
m_CurrentCommand.Reset();
|
||||
|
||||
Assert( m_bIsProcessingCommands );
|
||||
if ( m_Commands.Count() == 0 )
|
||||
return false;
|
||||
|
||||
int nHead = m_Commands.Head();
|
||||
Command_t &command = m_Commands[ nHead ];
|
||||
if ( command.m_nTick > m_nLastTickToProcess )
|
||||
return false;
|
||||
|
||||
m_nCurrentTick = command.m_nTick;
|
||||
|
||||
// Copy the current command into a temp buffer
|
||||
// NOTE: This is here to avoid the pointers returned by DequeueNextCommand
|
||||
// to become invalid by calling AddText. Is there a way we can avoid the memcpy?
|
||||
if ( command.m_nBufferSize > 0 )
|
||||
{
|
||||
m_CurrentCommand.Tokenize( &m_pArgSBuffer[command.m_nFirstArgS] );
|
||||
}
|
||||
|
||||
m_Commands.Remove( nHead );
|
||||
|
||||
// Necessary to insert commands while commands are being processed
|
||||
m_hNextCommand = m_Commands.Head();
|
||||
|
||||
// Msg("Dequeue : ");
|
||||
// for ( int i = 0; i < nArgc; ++i )
|
||||
// {
|
||||
// Msg("%s ", m_pCurrentArgv[i] );
|
||||
// }
|
||||
// Msg("\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns the next command
|
||||
//-----------------------------------------------------------------------------
|
||||
int CCommandBuffer::DequeueNextCommand( const char **& ppArgv )
|
||||
{
|
||||
DequeueNextCommand();
|
||||
ppArgv = ArgV();
|
||||
return ArgC();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Compacts the command buffer
|
||||
//-----------------------------------------------------------------------------
|
||||
void CCommandBuffer::Compact()
|
||||
{
|
||||
// Compress argvbuffer + argv
|
||||
// NOTE: I'm using this choice instead of calling malloc + free
|
||||
// per command to allocate arguments because I expect to post a
|
||||
// bunch of commands but not have many delayed commands;
|
||||
// avoiding the allocation cost seems more important that the memcpy
|
||||
// cost here since I expect to not have much to copy.
|
||||
m_nArgSBufferSize = 0;
|
||||
|
||||
char pTempBuffer[ ARGS_BUFFER_LENGTH ];
|
||||
for ( int i = m_Commands.Head(); i != m_Commands.InvalidIndex(); i = m_Commands.Next(i) )
|
||||
{
|
||||
Command_t &command = m_Commands[ i ];
|
||||
|
||||
memcpy( &pTempBuffer[m_nArgSBufferSize], &m_pArgSBuffer[command.m_nFirstArgS], command.m_nBufferSize );
|
||||
command.m_nFirstArgS = m_nArgSBufferSize;
|
||||
m_nArgSBufferSize += command.m_nBufferSize;
|
||||
}
|
||||
|
||||
// NOTE: We could also store 2 buffers in the command buffer and switch
|
||||
// between the two to avoid the 2nd memcpy; but again I'm guessing the memory
|
||||
// tradeoff isn't worth it
|
||||
memcpy( m_pArgSBuffer, pTempBuffer, m_nArgSBufferSize );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Call this to finish iterating over all commands
|
||||
//-----------------------------------------------------------------------------
|
||||
void CCommandBuffer::EndProcessingCommands()
|
||||
{
|
||||
Assert( m_bIsProcessingCommands );
|
||||
m_bIsProcessingCommands = false;
|
||||
m_nCurrentTick = m_nLastTickToProcess + 1;
|
||||
m_hNextCommand = m_Commands.InvalidIndex();
|
||||
|
||||
// Extract commands that are before the end time
|
||||
// NOTE: This is a bug for this to
|
||||
int i = m_Commands.Head();
|
||||
if ( i == m_Commands.InvalidIndex() )
|
||||
{
|
||||
m_nArgSBufferSize = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
while ( i != m_Commands.InvalidIndex() )
|
||||
{
|
||||
if ( m_Commands[i].m_nTick >= m_nCurrentTick )
|
||||
break;
|
||||
|
||||
AssertMsgOnce( false, "CCommandBuffer::EndProcessingCommands() called before all appropriate commands were dequeued.\n" );
|
||||
int nNext = i;
|
||||
Msg( "Warning: Skipping command %s\n", m_pArgSBuffer[ m_Commands[i].m_nFirstArgS ] );
|
||||
m_Commands.Remove( i );
|
||||
i = nNext;
|
||||
}
|
||||
|
||||
Compact();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns a handle to the next command to process
|
||||
//-----------------------------------------------------------------------------
|
||||
CommandHandle_t CCommandBuffer::GetNextCommandHandle()
|
||||
{
|
||||
Assert( m_bIsProcessingCommands );
|
||||
return m_Commands.Head();
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/*
|
||||
===============
|
||||
Cmd_Alias_f
|
||||
|
||||
Creates a new command that executes a command string (possibly ; seperated)
|
||||
===============
|
||||
*/
|
||||
void Cmd_Alias_f (void)
|
||||
{
|
||||
cmdalias_t *a;
|
||||
char cmd[MAX_COMMAND_LENGTH];
|
||||
int i, c;
|
||||
char *s;
|
||||
|
||||
if (Cmd_Argc() == 1)
|
||||
{
|
||||
Con_Printf ("Current alias commands:\n");
|
||||
for (a = cmd_alias ; a ; a=a->next)
|
||||
Con_Printf ("%s : %s\n", a->name, a->value);
|
||||
return;
|
||||
}
|
||||
|
||||
s = Cmd_Argv(1);
|
||||
if (strlen(s) >= MAX_ALIAS_NAME)
|
||||
{
|
||||
Con_Printf ("Alias name is too long\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// copy the rest of the command line
|
||||
cmd[0] = 0; // start out with a null string
|
||||
c = Cmd_Argc();
|
||||
for (i=2 ; i< c ; i++)
|
||||
{
|
||||
Q_strncat(cmd, Cmd_Argv(i), sizeof( cmd ), COPY_ALL_CHARACTERS);
|
||||
if (i != c)
|
||||
{
|
||||
Q_strncat (cmd, " ", sizeof( cmd ), COPY_ALL_CHARACTERS );
|
||||
}
|
||||
}
|
||||
Q_strncat (cmd, "\n", sizeof( cmd ), COPY_ALL_CHARACTERS);
|
||||
|
||||
// if the alias already exists, reuse it
|
||||
for (a = cmd_alias ; a ; a=a->next)
|
||||
{
|
||||
if (!strcmp(s, a->name))
|
||||
{
|
||||
if ( !strcmp( a->value, cmd ) ) // Re-alias the same thing
|
||||
return;
|
||||
|
||||
delete[] a->value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!a)
|
||||
{
|
||||
a = (cmdalias_t *)new cmdalias_t;
|
||||
a->next = cmd_alias;
|
||||
cmd_alias = a;
|
||||
}
|
||||
Q_strncpy (a->name, s, sizeof( a->name ) );
|
||||
|
||||
a->value = COM_StringCopy(cmd);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
COMMAND EXECUTION
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
#define MAX_ARGS 80
|
||||
|
||||
static int cmd_argc;
|
||||
static char *cmd_argv[MAX_ARGS];
|
||||
static char *cmd_null_string = "";
|
||||
static const char *cmd_args = NULL;
|
||||
|
||||
cmd_source_t cmd_source;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : void Cmd_Init
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void Cmd_Shutdown( void )
|
||||
{
|
||||
// TODO, cleanup
|
||||
while ( cmd_alias )
|
||||
{
|
||||
cmdalias_t *next = cmd_alias->next;
|
||||
delete cmd_alias->value; // created by StringCopy()
|
||||
delete cmd_alias;
|
||||
cmd_alias = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
Cmd_ExecuteString
|
||||
|
||||
A complete command line has been parsed, so try to execute it
|
||||
FIXME: lookupnoadd the token to speed search?
|
||||
============
|
||||
*/
|
||||
const ConCommandBase *Cmd_ExecuteString (const char *text, cmd_source_t src)
|
||||
{
|
||||
cmdalias_t *a;
|
||||
|
||||
cmd_source = src;
|
||||
Cmd_TokenizeString (text);
|
||||
|
||||
// execute the command line
|
||||
if (!Cmd_Argc())
|
||||
return NULL; // no tokens
|
||||
|
||||
// check alias
|
||||
for (a=cmd_alias ; a ; a=a->next)
|
||||
{
|
||||
if (!Q_strcasecmp (cmd_argv[0], a->name))
|
||||
{
|
||||
Cbuf_InsertText (a->value);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// check ConCommands
|
||||
ConCommandBase const *pCommand = ConCommandBase::FindCommand( cmd_argv[ 0 ] );
|
||||
if ( pCommand && pCommand->IsCommand() )
|
||||
{
|
||||
bool isServerCommand = ( pCommand->IsBitSet( FCVAR_GAMEDLL ) &&
|
||||
// Typed at console
|
||||
cmd_source == src_command &&
|
||||
// Not HLDS
|
||||
!sv.IsDedicated() );
|
||||
|
||||
// Hook to allow game .dll to figure out who type the message on a listen server
|
||||
if ( serverGameClients )
|
||||
{
|
||||
// We're actually the server, so set it up locally
|
||||
if ( sv.IsActive() )
|
||||
{
|
||||
g_pServerPluginHandler->SetCommandClient( -1 );
|
||||
|
||||
#ifndef SWDS
|
||||
// Special processing for listen server player
|
||||
if ( isServerCommand )
|
||||
{
|
||||
g_pServerPluginHandler->SetCommandClient( cl.m_nPlayerSlot );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// We're not the server, but we've been a listen server (game .dll loaded)
|
||||
// forward this command tot he server instead of running it locally if we're still
|
||||
// connected
|
||||
// Otherwise, things like "say" won't work unless you quit and restart
|
||||
else if ( isServerCommand )
|
||||
{
|
||||
if ( cl.IsConnected() )
|
||||
{
|
||||
Cmd_ForwardToServer();
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's a server command, but we're not connected to a server. Don't try to execute it.
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Allow cheat commands in singleplayer, debug, or multiplayer with sv_cheats on
|
||||
#ifndef _DEBUG
|
||||
if ( pCommand->IsBitSet( FCVAR_CHEAT ) )
|
||||
{
|
||||
if ( !Host_IsSinglePlayerGame() && sv_cheats.GetInt() == 0 )
|
||||
{
|
||||
Msg( "Can't use cheat command %s in multiplayer, unless the server has sv_cheats set to 1.\n", pCommand->GetName() );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
(( ConCommand * )pCommand )->Dispatch();
|
||||
return pCommand;
|
||||
}
|
||||
|
||||
// check cvars
|
||||
if ( cv->IsCommand() )
|
||||
{
|
||||
return pCommand;
|
||||
}
|
||||
|
||||
// forward the command line to the server, so the entity DLL can parse it
|
||||
if ( cmd_source == src_command )
|
||||
{
|
||||
if ( cl.IsConnected() )
|
||||
{
|
||||
Cmd_ForwardToServer();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Msg("Unknown command \"%s\"\n", Cmd_Argv(0));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
1287
tier1/convar.cpp
Normal file
1287
tier1/convar.cpp
Normal file
File diff suppressed because it is too large
Load Diff
410
tier1/datamanager.cpp
Normal file
410
tier1/datamanager.cpp
Normal file
@ -0,0 +1,410 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "basetypes.h"
|
||||
#include "datamanager.h"
|
||||
|
||||
DECLARE_POINTER_HANDLE( memhandle_t );
|
||||
|
||||
#define AUTO_LOCK_DM() AUTO_LOCK_( CDataManagerBase, *this )
|
||||
|
||||
CDataManagerBase::CDataManagerBase( unsigned int maxSize )
|
||||
{
|
||||
m_targetMemorySize = maxSize;
|
||||
m_memUsed = 0;
|
||||
m_lruList = m_memoryLists.CreateList();
|
||||
m_lockList = m_memoryLists.CreateList();
|
||||
m_freeList = m_memoryLists.CreateList();
|
||||
m_listsAreFreed = 0;
|
||||
}
|
||||
|
||||
CDataManagerBase::~CDataManagerBase()
|
||||
{
|
||||
Assert( m_listsAreFreed );
|
||||
}
|
||||
|
||||
void CDataManagerBase::NotifySizeChanged( memhandle_t handle, unsigned int oldSize, unsigned int newSize )
|
||||
{
|
||||
Lock();
|
||||
m_memUsed += (int)newSize - (int)oldSize;
|
||||
Unlock();
|
||||
}
|
||||
|
||||
void CDataManagerBase::SetTargetSize( unsigned int targetSize )
|
||||
{
|
||||
m_targetMemorySize = targetSize;
|
||||
}
|
||||
|
||||
unsigned int CDataManagerBase::FlushAllUnlocked()
|
||||
{
|
||||
Lock();
|
||||
|
||||
int nFlush = m_memoryLists.Count( m_lruList );
|
||||
void **pScratch = (void **)_alloca( nFlush * sizeof(void *) );
|
||||
CUtlVector<void *> destroyList( pScratch, nFlush );
|
||||
|
||||
unsigned nBytesInitial = MemUsed_Inline();
|
||||
|
||||
int node = m_memoryLists.Head(m_lruList);
|
||||
while ( node != m_memoryLists.InvalidIndex() )
|
||||
{
|
||||
int next = m_memoryLists.Next(node);
|
||||
m_memoryLists.Unlink( m_lruList, node );
|
||||
destroyList.AddToTail( GetForFreeByIndex( node ) );
|
||||
node = next;
|
||||
}
|
||||
|
||||
Unlock();
|
||||
|
||||
for ( int i = 0; i < nFlush; i++ )
|
||||
{
|
||||
DestroyResourceStorage( destroyList[i] );
|
||||
}
|
||||
|
||||
return ( nBytesInitial - MemUsed_Inline() );
|
||||
}
|
||||
|
||||
unsigned int CDataManagerBase::FlushToTargetSize()
|
||||
{
|
||||
return EnsureCapacity(0);
|
||||
}
|
||||
|
||||
// Frees everything! The LRU AND the LOCKED items. This is only used to forcibly free the resources,
|
||||
// not to make space.
|
||||
|
||||
unsigned int CDataManagerBase::FlushAll()
|
||||
{
|
||||
Lock();
|
||||
|
||||
int nFlush = m_memoryLists.Count( m_lruList ) + m_memoryLists.Count( m_lockList );
|
||||
void **pScratch = (void **)_alloca( nFlush * sizeof(void *) );
|
||||
CUtlVector<void *> destroyList( pScratch, nFlush );
|
||||
|
||||
unsigned result = MemUsed_Inline();
|
||||
int node;
|
||||
int nextNode;
|
||||
|
||||
node = m_memoryLists.Head(m_lruList);
|
||||
while ( node != m_memoryLists.InvalidIndex() )
|
||||
{
|
||||
nextNode = m_memoryLists.Next(node);
|
||||
m_memoryLists.Unlink( m_lruList, node );
|
||||
destroyList.AddToTail( GetForFreeByIndex( node ) );
|
||||
node = nextNode;
|
||||
}
|
||||
|
||||
node = m_memoryLists.Head(m_lockList);
|
||||
while ( node != m_memoryLists.InvalidIndex() )
|
||||
{
|
||||
nextNode = m_memoryLists.Next(node);
|
||||
m_memoryLists.Unlink( m_lockList, node );
|
||||
m_memoryLists[node].lockCount = 0;
|
||||
destroyList.AddToTail( GetForFreeByIndex( node ) );
|
||||
node = nextNode;
|
||||
}
|
||||
|
||||
m_listsAreFreed = false;
|
||||
Unlock();
|
||||
|
||||
for ( int i = 0; i < nFlush; i++ )
|
||||
{
|
||||
DestroyResourceStorage( destroyList[i] );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned int CDataManagerBase::Purge( unsigned int nBytesToPurge )
|
||||
{
|
||||
unsigned int nTargetSize = MemUsed_Inline() - nBytesToPurge;
|
||||
if ( nTargetSize < 0 )
|
||||
nTargetSize = 0;
|
||||
unsigned int nImpliedCapacity = MemTotal_Inline() - nTargetSize;
|
||||
return EnsureCapacity( nImpliedCapacity );
|
||||
}
|
||||
|
||||
|
||||
void CDataManagerBase::DestroyResource( memhandle_t handle )
|
||||
{
|
||||
Lock();
|
||||
unsigned short index = FromHandle( handle );
|
||||
if ( !m_memoryLists.IsValidIndex(index) )
|
||||
{
|
||||
Unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
Assert( m_memoryLists[index].lockCount == 0 );
|
||||
if ( m_memoryLists[index].lockCount )
|
||||
BreakLock( handle );
|
||||
m_memoryLists.Unlink( m_lruList, index );
|
||||
void *p = GetForFreeByIndex( index );
|
||||
Unlock();
|
||||
|
||||
DestroyResourceStorage( p );
|
||||
}
|
||||
|
||||
|
||||
void *CDataManagerBase::LockResource( memhandle_t handle )
|
||||
{
|
||||
AUTO_LOCK_DM();
|
||||
unsigned short memoryIndex = FromHandle(handle);
|
||||
if ( memoryIndex != m_memoryLists.InvalidIndex() )
|
||||
{
|
||||
if ( m_memoryLists[memoryIndex].lockCount == 0 )
|
||||
{
|
||||
m_memoryLists.Unlink( m_lruList, memoryIndex );
|
||||
m_memoryLists.LinkToTail( m_lockList, memoryIndex );
|
||||
}
|
||||
Assert(m_memoryLists[memoryIndex].lockCount != (unsigned short)-1);
|
||||
m_memoryLists[memoryIndex].lockCount++;
|
||||
return m_memoryLists[memoryIndex].pStore;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int CDataManagerBase::UnlockResource( memhandle_t handle )
|
||||
{
|
||||
AUTO_LOCK_DM();
|
||||
unsigned short memoryIndex = FromHandle(handle);
|
||||
if ( memoryIndex != m_memoryLists.InvalidIndex() )
|
||||
{
|
||||
Assert( m_memoryLists[memoryIndex].lockCount > 0 );
|
||||
if ( m_memoryLists[memoryIndex].lockCount > 0 )
|
||||
{
|
||||
m_memoryLists[memoryIndex].lockCount--;
|
||||
if ( m_memoryLists[memoryIndex].lockCount == 0 )
|
||||
{
|
||||
m_memoryLists.Unlink( m_lockList, memoryIndex );
|
||||
m_memoryLists.LinkToTail( m_lruList, memoryIndex );
|
||||
}
|
||||
}
|
||||
return m_memoryLists[memoryIndex].lockCount;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *CDataManagerBase::GetResource_NoLockNoLRUTouch( memhandle_t handle )
|
||||
{
|
||||
AUTO_LOCK_DM();
|
||||
unsigned short memoryIndex = FromHandle(handle);
|
||||
if ( memoryIndex != m_memoryLists.InvalidIndex() )
|
||||
{
|
||||
return m_memoryLists[memoryIndex].pStore;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void *CDataManagerBase::GetResource_NoLock( memhandle_t handle )
|
||||
{
|
||||
AUTO_LOCK_DM();
|
||||
unsigned short memoryIndex = FromHandle(handle);
|
||||
if ( memoryIndex != m_memoryLists.InvalidIndex() )
|
||||
{
|
||||
TouchByIndex( memoryIndex );
|
||||
return m_memoryLists[memoryIndex].pStore;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CDataManagerBase::TouchResource( memhandle_t handle )
|
||||
{
|
||||
AUTO_LOCK_DM();
|
||||
TouchByIndex( FromHandle(handle) );
|
||||
}
|
||||
|
||||
void CDataManagerBase::MarkAsStale( memhandle_t handle )
|
||||
{
|
||||
AUTO_LOCK_DM();
|
||||
unsigned short memoryIndex = FromHandle(handle);
|
||||
if ( memoryIndex != m_memoryLists.InvalidIndex() )
|
||||
{
|
||||
if ( m_memoryLists[memoryIndex].lockCount == 0 )
|
||||
{
|
||||
m_memoryLists.Unlink( m_lruList, memoryIndex );
|
||||
m_memoryLists.LinkToHead( m_lruList, memoryIndex );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CDataManagerBase::BreakLock( memhandle_t handle )
|
||||
{
|
||||
AUTO_LOCK_DM();
|
||||
unsigned short memoryIndex = FromHandle(handle);
|
||||
if ( memoryIndex != m_memoryLists.InvalidIndex() && m_memoryLists[memoryIndex].lockCount )
|
||||
{
|
||||
int nBroken = m_memoryLists[memoryIndex].lockCount;
|
||||
m_memoryLists[memoryIndex].lockCount = 0;
|
||||
m_memoryLists.Unlink( m_lockList, memoryIndex );
|
||||
m_memoryLists.LinkToTail( m_lruList, memoryIndex );
|
||||
|
||||
return nBroken;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CDataManagerBase::BreakAllLocks()
|
||||
{
|
||||
AUTO_LOCK_DM();
|
||||
int nBroken = 0;
|
||||
int node;
|
||||
int nextNode;
|
||||
|
||||
node = m_memoryLists.Head(m_lockList);
|
||||
while ( node != m_memoryLists.InvalidIndex() )
|
||||
{
|
||||
nBroken++;
|
||||
nextNode = m_memoryLists.Next(node);
|
||||
m_memoryLists[node].lockCount = 0;
|
||||
m_memoryLists.Unlink( m_lockList, node );
|
||||
m_memoryLists.LinkToTail( m_lruList, node );
|
||||
node = nextNode;
|
||||
}
|
||||
|
||||
return nBroken;
|
||||
|
||||
}
|
||||
|
||||
unsigned short CDataManagerBase::CreateHandle( bool bCreateLocked )
|
||||
{
|
||||
AUTO_LOCK_DM();
|
||||
int memoryIndex = m_memoryLists.Head(m_freeList);
|
||||
unsigned short list = ( bCreateLocked ) ? m_lockList : m_lruList;
|
||||
if ( memoryIndex != m_memoryLists.InvalidIndex() )
|
||||
{
|
||||
m_memoryLists.Unlink( m_freeList, memoryIndex );
|
||||
m_memoryLists.LinkToTail( list, memoryIndex );
|
||||
}
|
||||
else
|
||||
{
|
||||
memoryIndex = m_memoryLists.AddToTail( list );
|
||||
}
|
||||
|
||||
if ( bCreateLocked )
|
||||
{
|
||||
m_memoryLists[memoryIndex].lockCount++;
|
||||
}
|
||||
|
||||
return memoryIndex;
|
||||
}
|
||||
|
||||
memhandle_t CDataManagerBase::StoreResourceInHandle( unsigned short memoryIndex, void *pStore, unsigned int realSize )
|
||||
{
|
||||
AUTO_LOCK_DM();
|
||||
resource_lru_element_t &mem = m_memoryLists[memoryIndex];
|
||||
mem.pStore = pStore;
|
||||
m_memUsed += realSize;
|
||||
return ToHandle(memoryIndex);
|
||||
}
|
||||
|
||||
void CDataManagerBase::TouchByIndex( unsigned short memoryIndex )
|
||||
{
|
||||
if ( memoryIndex != m_memoryLists.InvalidIndex() )
|
||||
{
|
||||
if ( m_memoryLists[memoryIndex].lockCount == 0 )
|
||||
{
|
||||
m_memoryLists.Unlink( m_lruList, memoryIndex );
|
||||
m_memoryLists.LinkToTail( m_lruList, memoryIndex );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memhandle_t CDataManagerBase::ToHandle( unsigned short index )
|
||||
{
|
||||
unsigned int hiword = m_memoryLists.Element(index).serial;
|
||||
hiword <<= 16;
|
||||
index++;
|
||||
return (memhandle_t)( hiword|index );
|
||||
}
|
||||
|
||||
unsigned int CDataManagerBase::TargetSize()
|
||||
{
|
||||
return MemTotal_Inline();
|
||||
}
|
||||
|
||||
unsigned int CDataManagerBase::AvailableSize()
|
||||
{
|
||||
return MemAvailable_Inline();
|
||||
}
|
||||
|
||||
|
||||
unsigned int CDataManagerBase::UsedSize()
|
||||
{
|
||||
return MemUsed_Inline();
|
||||
}
|
||||
|
||||
// free resources until there is enough space to hold "size"
|
||||
unsigned int CDataManagerBase::EnsureCapacity( unsigned int size )
|
||||
{
|
||||
unsigned nBytesInitial = MemUsed_Inline();
|
||||
while ( MemUsed_Inline() > MemTotal_Inline() || MemAvailable_Inline() < size )
|
||||
{
|
||||
Lock();
|
||||
int lruIndex = m_memoryLists.Head( m_lruList );
|
||||
if ( lruIndex == m_memoryLists.InvalidIndex() )
|
||||
{
|
||||
Unlock();
|
||||
break;
|
||||
}
|
||||
m_memoryLists.Unlink( m_lruList, lruIndex );
|
||||
void *p = GetForFreeByIndex( lruIndex );
|
||||
Unlock();
|
||||
DestroyResourceStorage( p );
|
||||
}
|
||||
return ( nBytesInitial - MemUsed_Inline() );
|
||||
}
|
||||
|
||||
// free this resource and move the handle to the free list
|
||||
void *CDataManagerBase::GetForFreeByIndex( unsigned short memoryIndex )
|
||||
{
|
||||
void *p = NULL;
|
||||
if ( memoryIndex != m_memoryLists.InvalidIndex() )
|
||||
{
|
||||
Assert( m_memoryLists[memoryIndex].lockCount == 0 );
|
||||
|
||||
resource_lru_element_t &mem = m_memoryLists[memoryIndex];
|
||||
unsigned size = GetRealSize( mem.pStore );
|
||||
if ( size > m_memUsed )
|
||||
{
|
||||
ExecuteOnce( Warning( "Data manager 'used' memory incorrect\n" ) );
|
||||
size = m_memUsed;
|
||||
}
|
||||
m_memUsed -= size;
|
||||
p = mem.pStore;
|
||||
mem.pStore = NULL;
|
||||
mem.serial++;
|
||||
m_memoryLists.LinkToTail( m_freeList, memoryIndex );
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
// get a list of everything in the LRU
|
||||
void CDataManagerBase::GetLRUHandleList( CUtlVector< memhandle_t >& list )
|
||||
{
|
||||
for ( int node = m_memoryLists.Tail(m_lruList);
|
||||
node != m_memoryLists.InvalidIndex();
|
||||
node = m_memoryLists.Previous(node) )
|
||||
{
|
||||
list.AddToTail( ToHandle( node ) );
|
||||
}
|
||||
}
|
||||
|
||||
// get a list of everything locked
|
||||
void CDataManagerBase::GetLockHandleList( CUtlVector< memhandle_t >& list )
|
||||
{
|
||||
for ( int node = m_memoryLists.Head(m_lockList);
|
||||
node != m_memoryLists.InvalidIndex();
|
||||
node = m_memoryLists.Next(node) )
|
||||
{
|
||||
list.AddToTail( ToHandle( node ) );
|
||||
}
|
||||
}
|
||||
|
547
tier1/diff.cpp
Normal file
547
tier1/diff.cpp
Normal file
@ -0,0 +1,547 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "tier0/platform.h"
|
||||
#include "tier0/dbg.h"
|
||||
#include "tier1/diff.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
// format of diff output:
|
||||
// 0NN (N=1..127) copy next N literaly
|
||||
//
|
||||
// 1NN (N=1..127) ofs (-128..127) copy next N bytes from original, changin offset by N bytes from
|
||||
// last copy end
|
||||
// 100 N ofs(-32768..32767) copy next N, with larger delta offset
|
||||
// 00 NNNN(1..65535) ofs(-32768..32767) big copy from old
|
||||
// 80 00 NN NN NN big raw copy
|
||||
//
|
||||
// available codes (could be used for additonal compression ops)
|
||||
// long offset form whose offset could have fit in short offset
|
||||
|
||||
// note - this algorithm uses storage equal to 8* the old buffer size. 64k=.5mb
|
||||
|
||||
|
||||
#define MIN_MATCH_LEN 8
|
||||
#define ACCEPTABLE_MATCH_LEN 4096
|
||||
|
||||
struct BlockPtr
|
||||
{
|
||||
BlockPtr *Next;
|
||||
uint8 const *dataptr;
|
||||
};
|
||||
|
||||
template<class T,class V> static inline void AddToHead(T * & head, V * node)
|
||||
{
|
||||
node->Next=head;
|
||||
head=node;
|
||||
}
|
||||
|
||||
void Fail(char const *msg)
|
||||
{
|
||||
Assert(0);
|
||||
}
|
||||
|
||||
void ApplyDiffs(uint8 const *OldBlock, uint8 const *DiffList,
|
||||
int OldSize, int DiffListSize, int &ResultListSize,uint8 *Output,uint32 OutSize)
|
||||
{
|
||||
uint8 const *copy_src=OldBlock;
|
||||
uint8 const *end_of_diff_list=DiffList+DiffListSize;
|
||||
uint8 const *obuf=Output;
|
||||
while(DiffList<end_of_diff_list)
|
||||
{
|
||||
// printf("dptr=%x ",DiffList-d);
|
||||
uint8 op=*(DiffList++);
|
||||
if (op==0)
|
||||
{
|
||||
uint16 copy_sz=DiffList[0]+256*DiffList[1];
|
||||
int copy_ofs=DiffList[2]+DiffList[3]*256;
|
||||
if (copy_ofs>32767)
|
||||
copy_ofs|=0xffff0000;
|
||||
// printf("long cp from %x to %x len=%d\n", copy_src+copy_ofs-OldBlock,Output-obuf,copy_sz);
|
||||
|
||||
memcpy(Output,copy_src+copy_ofs,copy_sz);
|
||||
Output+=copy_sz;
|
||||
copy_src=copy_src+copy_ofs+copy_sz;
|
||||
DiffList+=4;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (op & 0x80)
|
||||
{
|
||||
int copy_sz=op & 0x7f;
|
||||
int copy_ofs;
|
||||
if (copy_sz==0)
|
||||
{
|
||||
copy_sz=DiffList[0];
|
||||
if (copy_sz==0)
|
||||
{
|
||||
// big raw copy
|
||||
copy_sz=DiffList[1]+256*DiffList[2]+65536*DiffList[3];
|
||||
memcpy(Output,DiffList+4,copy_sz);
|
||||
// printf("big rawcopy to %x len=%d\n", Output-obuf,copy_sz);
|
||||
|
||||
DiffList+=copy_sz+4;
|
||||
Output+=copy_sz;
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_ofs=DiffList[1]+(DiffList[2]*256);
|
||||
if (copy_ofs>32767)
|
||||
copy_ofs|=0xffff0000;
|
||||
// printf("long ofs cp from %x to %x len=%d\n", copy_src+copy_ofs-OldBlock,Output-obuf,copy_sz);
|
||||
|
||||
memcpy(Output,copy_src+copy_ofs,copy_sz);
|
||||
Output+=copy_sz;
|
||||
copy_src=copy_src+copy_ofs+copy_sz;
|
||||
DiffList+=3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_ofs=DiffList[0];
|
||||
if (copy_ofs>127)
|
||||
copy_ofs|=0xffffff80;
|
||||
// printf("cp from %x to %x len=%d\n", copy_src+copy_ofs-OldBlock,Output-obuf,copy_sz);
|
||||
|
||||
memcpy(Output,copy_src+copy_ofs,copy_sz);
|
||||
Output+=copy_sz;
|
||||
copy_src=copy_src+copy_ofs+copy_sz;
|
||||
DiffList++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// printf("raw copy %d to %x\n",op & 127,Output-obuf);
|
||||
memcpy(Output,DiffList,op & 127);
|
||||
Output+=op & 127;
|
||||
DiffList+=(op & 127);
|
||||
}
|
||||
}
|
||||
}
|
||||
ResultListSize=Output-obuf;
|
||||
|
||||
}
|
||||
|
||||
static void CopyPending(int len, uint8 const *rawbytes,uint8 * &outbuf, uint8 const *limit)
|
||||
{
|
||||
// printf("copy raw len=%d\n",len);
|
||||
if (len<128)
|
||||
{
|
||||
if (limit-outbuf < len+1)
|
||||
Fail("diff buffer overrun");
|
||||
*(outbuf++)=len;
|
||||
memcpy(outbuf,rawbytes,len);
|
||||
outbuf+=len;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (limit-outbuf < len+5)
|
||||
Fail("diff buffer overrun");
|
||||
*(outbuf++)=0x80;
|
||||
*(outbuf++)=0x00;
|
||||
*(outbuf++)=(len & 255);
|
||||
*(outbuf++)=((len>>8) & 255);
|
||||
*(outbuf++)=((len>>16) & 255);
|
||||
memcpy(outbuf,rawbytes,len);
|
||||
outbuf+=len;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32 hasher(uint8 const *mdata)
|
||||
{
|
||||
// attempt to scramble the bits of h1 and h2 together
|
||||
uint32 ret=0;
|
||||
for(int i=0;i<MIN_MATCH_LEN;i++)
|
||||
{
|
||||
ret=ret<<4;
|
||||
ret+=(*mdata++);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int FindDiffsForLargeFiles(uint8 const *NewBlock, uint8 const *OldBlock,
|
||||
int NewSize, int OldSize, int &DiffListSize,uint8 *Output,
|
||||
uint32 OutSize,
|
||||
int hashsize)
|
||||
{
|
||||
|
||||
int ret=0;
|
||||
if (OldSize!=NewSize)
|
||||
ret=1;
|
||||
// first, build the hash table
|
||||
BlockPtr **HashedMatches=new BlockPtr* [hashsize];
|
||||
memset(HashedMatches,0,sizeof(HashedMatches[0])*hashsize);
|
||||
BlockPtr *Blocks=0;
|
||||
if (OldSize)
|
||||
Blocks=new BlockPtr[OldSize];
|
||||
BlockPtr *FreeList=Blocks;
|
||||
// now, build the hash table
|
||||
uint8 const *walk=OldBlock;
|
||||
if (OldBlock && OldSize)
|
||||
while(walk<OldBlock+OldSize-MIN_MATCH_LEN)
|
||||
{
|
||||
uint32 hash1=hasher(walk);
|
||||
hash1 &=(hashsize-1);
|
||||
BlockPtr *newnode=FreeList;
|
||||
FreeList++;
|
||||
newnode->dataptr=walk;
|
||||
AddToHead(HashedMatches[hash1],newnode);
|
||||
walk++;
|
||||
}
|
||||
else
|
||||
ret=1;
|
||||
// now, we have the hash table which may be used to search. begin the output step
|
||||
int pending_raw_len=0;
|
||||
walk=NewBlock;
|
||||
uint8 *outbuf=Output;
|
||||
uint8 const *lastmatchend=OldBlock;
|
||||
while(walk<NewBlock+NewSize)
|
||||
{
|
||||
int longest=0;
|
||||
BlockPtr *longest_block=0;
|
||||
if (walk<NewBlock+NewSize-MIN_MATCH_LEN)
|
||||
{
|
||||
// check for a match
|
||||
uint32 hash1=hasher(walk);
|
||||
hash1 &= (hashsize-1);
|
||||
// now, find the longest match in the hash table. If we find one >MIN_MATCH_LEN, take it
|
||||
for(BlockPtr *b=HashedMatches[hash1];b;b=b->Next)
|
||||
{
|
||||
// find the match length
|
||||
int match_of=b->dataptr-lastmatchend;
|
||||
if ((match_of>-32768) && (match_of<32767))
|
||||
{
|
||||
int max_mlength=MIN(65535,OldBlock+OldSize-b->dataptr);
|
||||
max_mlength=MIN(max_mlength,NewBlock+NewSize-walk);
|
||||
int i;
|
||||
for(i=0;i<max_mlength;i++)
|
||||
if (walk[i]!=b->dataptr[i])
|
||||
break;
|
||||
if ((i>MIN_MATCH_LEN) && (i>longest))
|
||||
{
|
||||
longest=i;
|
||||
longest_block=b;
|
||||
if (longest>ACCEPTABLE_MATCH_LEN)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// now, we have a match maybe
|
||||
if (longest_block)
|
||||
{
|
||||
if (pending_raw_len) // must output
|
||||
{
|
||||
ret=1;
|
||||
CopyPending(pending_raw_len,walk-pending_raw_len,outbuf,Output+OutSize);
|
||||
pending_raw_len=0;
|
||||
}
|
||||
// now, output copy block
|
||||
int match_of=longest_block->dataptr-lastmatchend;
|
||||
int nremaining=OutSize-(outbuf-Output);
|
||||
|
||||
if (match_of)
|
||||
ret=1;
|
||||
// printf("copy from %x to %x len=%d\n", match_of,outbuf-Output,longest);
|
||||
if (longest>127)
|
||||
{
|
||||
// use really long encoding
|
||||
if (nremaining<5)
|
||||
Fail("diff buff needs increase");
|
||||
*(outbuf++)=00;
|
||||
*(outbuf++)=(longest & 255);
|
||||
*(outbuf++)=((longest>>8) & 255);
|
||||
*(outbuf++)=(match_of & 255);
|
||||
*(outbuf++)=((match_of>>8) & 255);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((match_of>=-128) && (match_of<128))
|
||||
{
|
||||
if (nremaining<2)
|
||||
Fail("diff buff needs increase");
|
||||
*(outbuf++)=128+longest;
|
||||
*(outbuf++)=(match_of&255);
|
||||
}
|
||||
else
|
||||
{
|
||||
// use long encoding
|
||||
if (nremaining<4)
|
||||
Fail("diff buff needs increase");
|
||||
*(outbuf++)=0x80;
|
||||
*(outbuf++)=longest;
|
||||
*(outbuf++)=(match_of & 255);
|
||||
*(outbuf++)=((match_of>>8) & 255);
|
||||
}
|
||||
}
|
||||
lastmatchend=longest_block->dataptr+longest;
|
||||
walk+=longest;
|
||||
}
|
||||
else
|
||||
{
|
||||
walk++;
|
||||
pending_raw_len++;
|
||||
}
|
||||
}
|
||||
// now, flush pending raw copy
|
||||
if (pending_raw_len) // must output
|
||||
{
|
||||
ret=1;
|
||||
CopyPending(pending_raw_len,walk-pending_raw_len,outbuf,Output+OutSize);
|
||||
pending_raw_len=0;
|
||||
}
|
||||
delete[] HashedMatches;
|
||||
if (Blocks)
|
||||
delete[] Blocks;
|
||||
DiffListSize=outbuf-Output;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int FindDiffs(uint8 const *NewBlock, uint8 const *OldBlock,
|
||||
int NewSize, int OldSize, int &DiffListSize,uint8 *Output,uint32 OutSize)
|
||||
{
|
||||
|
||||
int ret=0;
|
||||
if (OldSize!=NewSize)
|
||||
ret=1;
|
||||
// first, build the hash table
|
||||
BlockPtr *HashedMatches[65536];
|
||||
memset(HashedMatches,0,sizeof(HashedMatches));
|
||||
BlockPtr *Blocks=0;
|
||||
if (OldSize)
|
||||
Blocks=new BlockPtr[OldSize];
|
||||
BlockPtr *FreeList=Blocks;
|
||||
// now, build the hash table
|
||||
uint8 const *walk=OldBlock;
|
||||
if (OldBlock && OldSize)
|
||||
while(walk<OldBlock+OldSize-MIN_MATCH_LEN)
|
||||
{
|
||||
uint16 hash1=*((uint16 const *) walk)+*((uint16 const *) walk+2);
|
||||
BlockPtr *newnode=FreeList;
|
||||
FreeList++;
|
||||
newnode->dataptr=walk;
|
||||
AddToHead(HashedMatches[hash1],newnode);
|
||||
walk++;
|
||||
}
|
||||
else
|
||||
ret=1;
|
||||
// now, we have the hash table which may be used to search. begin the output step
|
||||
int pending_raw_len=0;
|
||||
walk=NewBlock;
|
||||
uint8 *outbuf=Output;
|
||||
uint8 const *lastmatchend=OldBlock;
|
||||
while(walk<NewBlock+NewSize)
|
||||
{
|
||||
int longest=0;
|
||||
BlockPtr *longest_block=0;
|
||||
if (walk<NewBlock+NewSize-MIN_MATCH_LEN)
|
||||
{
|
||||
// check for a match
|
||||
uint16 hash1=*((uint16 const *) walk)+*((uint16 const *) walk+2);
|
||||
// now, find the longest match in the hash table. If we find one >MIN_MATCH_LEN, take it
|
||||
for(BlockPtr *b=HashedMatches[hash1];b;b=b->Next)
|
||||
{
|
||||
// find the match length
|
||||
int match_of=b->dataptr-lastmatchend;
|
||||
if ((match_of>-32768) && (match_of<32767))
|
||||
{
|
||||
int max_mlength=MIN(65535,OldBlock+OldSize-b->dataptr);
|
||||
max_mlength=MIN(max_mlength,NewBlock+NewSize-walk);
|
||||
int i;
|
||||
for(i=0;i<max_mlength;i++)
|
||||
if (walk[i]!=b->dataptr[i])
|
||||
break;
|
||||
if ((i>MIN_MATCH_LEN) && (i>longest))
|
||||
{
|
||||
longest=i;
|
||||
longest_block=b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// now, we have a match maybe
|
||||
if (longest_block)
|
||||
{
|
||||
if (pending_raw_len) // must output
|
||||
{
|
||||
ret=1;
|
||||
CopyPending(pending_raw_len,walk-pending_raw_len,outbuf,Output+OutSize);
|
||||
pending_raw_len=0;
|
||||
}
|
||||
// now, output copy block
|
||||
int match_of=longest_block->dataptr-lastmatchend;
|
||||
int nremaining=OutSize-(outbuf-Output);
|
||||
if (match_of)
|
||||
ret=1;
|
||||
if (longest>127)
|
||||
{
|
||||
// use really long encoding
|
||||
if (nremaining<5)
|
||||
Fail("diff buff needs increase");
|
||||
*(outbuf++)=00;
|
||||
*(outbuf++)=(longest & 255);
|
||||
*(outbuf++)=((longest>>8) & 255);
|
||||
*(outbuf++)=(match_of & 255);
|
||||
*(outbuf++)=((match_of>>8) & 255);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((match_of>=-128) && (match_of<128))
|
||||
{
|
||||
if (nremaining<2)
|
||||
Fail("diff buff needs increase");
|
||||
*(outbuf++)=128+longest;
|
||||
*(outbuf++)=(match_of&255);
|
||||
}
|
||||
else
|
||||
{
|
||||
// use long encoding
|
||||
if (nremaining<4)
|
||||
Fail("diff buff needs increase");
|
||||
*(outbuf++)=0x80;
|
||||
*(outbuf++)=longest;
|
||||
*(outbuf++)=(match_of & 255);
|
||||
*(outbuf++)=((match_of>>8) & 255);
|
||||
}
|
||||
}
|
||||
lastmatchend=longest_block->dataptr+longest;
|
||||
walk+=longest;
|
||||
}
|
||||
else
|
||||
{
|
||||
walk++;
|
||||
pending_raw_len++;
|
||||
}
|
||||
}
|
||||
// now, flush pending raw copy
|
||||
if (pending_raw_len) // must output
|
||||
{
|
||||
ret=1;
|
||||
CopyPending(pending_raw_len,walk-pending_raw_len,outbuf,Output+OutSize);
|
||||
pending_raw_len=0;
|
||||
}
|
||||
if (Blocks)
|
||||
delete[] Blocks;
|
||||
DiffListSize=outbuf-Output;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int FindDiffsLowMemory(uint8 const *NewBlock, uint8 const *OldBlock,
|
||||
int NewSize, int OldSize, int &DiffListSize,uint8 *Output,uint32 OutSize)
|
||||
{
|
||||
|
||||
int ret=0;
|
||||
if (OldSize!=NewSize)
|
||||
ret=1;
|
||||
uint8 const *old_data_hash[256];
|
||||
memset(old_data_hash,0,sizeof(old_data_hash));
|
||||
int pending_raw_len=0;
|
||||
uint8 const *walk=NewBlock;
|
||||
uint8 const *oldptr=OldBlock;
|
||||
uint8 *outbuf=Output;
|
||||
uint8 const *lastmatchend=OldBlock;
|
||||
while(walk<NewBlock+NewSize)
|
||||
{
|
||||
while( (oldptr-OldBlock<walk-NewBlock+40) && (oldptr-OldBlock<OldSize-MIN_MATCH_LEN))
|
||||
{
|
||||
uint16 hash1=(oldptr[0]+oldptr[1]+oldptr[2]+oldptr[3]) & (NELEMS(old_data_hash)-1);
|
||||
old_data_hash[hash1]=oldptr;
|
||||
oldptr++;
|
||||
}
|
||||
int longest=0;
|
||||
uint8 const *longest_block=0;
|
||||
if (walk<NewBlock+NewSize-MIN_MATCH_LEN)
|
||||
{
|
||||
// check for a match
|
||||
uint16 hash1=(walk[0]+walk[1]+walk[2]+walk[3]) & (NELEMS(old_data_hash)-1);
|
||||
if (old_data_hash[hash1])
|
||||
{
|
||||
int max_bytes_to_compare=MIN(NewBlock+NewSize-walk,OldBlock+OldSize-old_data_hash[hash1]);
|
||||
int nmatches;
|
||||
for(nmatches=0;nmatches<max_bytes_to_compare;nmatches++)
|
||||
if (walk[nmatches]!=old_data_hash[hash1][nmatches])
|
||||
break;
|
||||
if (nmatches>MIN_MATCH_LEN)
|
||||
{
|
||||
longest_block=old_data_hash[hash1];
|
||||
longest=nmatches;
|
||||
}
|
||||
}
|
||||
}
|
||||
// now, we have a match maybe
|
||||
if (longest_block)
|
||||
{
|
||||
if (pending_raw_len) // must output
|
||||
{
|
||||
ret=1;
|
||||
CopyPending(pending_raw_len,walk-pending_raw_len,outbuf,Output+OutSize);
|
||||
pending_raw_len=0;
|
||||
}
|
||||
// now, output copy block
|
||||
int match_of=longest_block-lastmatchend;
|
||||
int nremaining=OutSize-(outbuf-Output);
|
||||
if (match_of)
|
||||
ret=1;
|
||||
if (longest>127)
|
||||
{
|
||||
// use really long encoding
|
||||
if (nremaining<5)
|
||||
Fail("diff buff needs increase");
|
||||
*(outbuf++)=00;
|
||||
*(outbuf++)=(longest & 255);
|
||||
*(outbuf++)=((longest>>8) & 255);
|
||||
*(outbuf++)=(match_of & 255);
|
||||
*(outbuf++)=((match_of>>8) & 255);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((match_of>=-128) && (match_of<128))
|
||||
{
|
||||
if (nremaining<2)
|
||||
Fail("diff buff needs increase");
|
||||
*(outbuf++)=128+longest;
|
||||
*(outbuf++)=(match_of&255);
|
||||
}
|
||||
else
|
||||
{
|
||||
// use long encoding
|
||||
if (nremaining<4)
|
||||
Fail("diff buff needs increase");
|
||||
*(outbuf++)=0x80;
|
||||
*(outbuf++)=longest;
|
||||
*(outbuf++)=(match_of & 255);
|
||||
*(outbuf++)=((match_of>>8) & 255);
|
||||
}
|
||||
}
|
||||
lastmatchend=longest_block+longest;
|
||||
walk+=longest;
|
||||
}
|
||||
else
|
||||
{
|
||||
walk++;
|
||||
pending_raw_len++;
|
||||
}
|
||||
}
|
||||
// now, flush pending raw copy
|
||||
if (pending_raw_len) // must output
|
||||
{
|
||||
ret=1;
|
||||
CopyPending(pending_raw_len,walk-pending_raw_len,outbuf,Output+OutSize);
|
||||
pending_raw_len=0;
|
||||
}
|
||||
DiffListSize=outbuf-Output;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
303
tier1/generichash.cpp
Normal file
303
tier1/generichash.cpp
Normal file
@ -0,0 +1,303 @@
|
||||
//======= Copyright © 2005, , Valve Corporation, All rights reserved. =========
|
||||
//
|
||||
// Purpose: Variant Pearson Hash general purpose hashing algorithm described
|
||||
// by Cargill in C++ Report 1994. Generates a 16-bit result.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "tier0/basetypes.h"
|
||||
#include "tier0/platform.h"
|
||||
#include "generichash.h"
|
||||
#include <ctype.h>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Table of randomly shuffled values from 0-255 generated by:
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
/*
|
||||
void MakeRandomValues()
|
||||
{
|
||||
int i, j, r;
|
||||
unsigned t;
|
||||
srand( 0xdeadbeef );
|
||||
|
||||
for ( i = 0; i < 256; i++ )
|
||||
{
|
||||
g_nRandomValues[i] = (unsigned )i;
|
||||
}
|
||||
|
||||
for (j = 0; j < 8; j++)
|
||||
{
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
r = rand() & 0xff;
|
||||
t = g_nRandomValues[i];
|
||||
g_nRandomValues[i] = g_nRandomValues[r];
|
||||
g_nRandomValues[r] = t;
|
||||
}
|
||||
}
|
||||
|
||||
printf("static unsigned g_nRandomValues[256] =\n{\n");
|
||||
|
||||
for (i = 0; i < 256; i += 16)
|
||||
{
|
||||
printf("\t");
|
||||
for (j = 0; j < 16; j++)
|
||||
printf(" %3d,", g_nRandomValues[i+j]);
|
||||
printf("\n");
|
||||
}
|
||||
printf("};\n");
|
||||
}
|
||||
*/
|
||||
|
||||
static unsigned g_nRandomValues[256] =
|
||||
{
|
||||
238, 164, 191, 168, 115, 16, 142, 11, 213, 214, 57, 151, 248, 252, 26, 198,
|
||||
13, 105, 102, 25, 43, 42, 227, 107, 210, 251, 86, 66, 83, 193, 126, 108,
|
||||
131, 3, 64, 186, 192, 81, 37, 158, 39, 244, 14, 254, 75, 30, 2, 88,
|
||||
172, 176, 255, 69, 0, 45, 116, 139, 23, 65, 183, 148, 33, 46, 203, 20,
|
||||
143, 205, 60, 197, 118, 9, 171, 51, 233, 135, 220, 49, 71, 184, 82, 109,
|
||||
36, 161, 169, 150, 63, 96, 173, 125, 113, 67, 224, 78, 232, 215, 35, 219,
|
||||
79, 181, 41, 229, 149, 153, 111, 217, 21, 72, 120, 163, 133, 40, 122, 140,
|
||||
208, 231, 211, 200, 160, 182, 104, 110, 178, 237, 15, 101, 27, 50, 24, 189,
|
||||
177, 130, 187, 92, 253, 136, 100, 212, 19, 174, 70, 22, 170, 206, 162, 74,
|
||||
247, 5, 47, 32, 179, 117, 132, 195, 124, 123, 245, 128, 236, 223, 12, 84,
|
||||
54, 218, 146, 228, 157, 94, 106, 31, 17, 29, 194, 34, 56, 134, 239, 246,
|
||||
241, 216, 127, 98, 7, 204, 154, 152, 209, 188, 48, 61, 87, 97, 225, 85,
|
||||
90, 167, 155, 112, 145, 114, 141, 93, 250, 4, 201, 156, 38, 89, 226, 196,
|
||||
1, 235, 44, 180, 159, 121, 119, 166, 190, 144, 10, 91, 76, 230, 221, 80,
|
||||
207, 55, 58, 53, 175, 8, 6, 52, 68, 242, 18, 222, 103, 249, 147, 129,
|
||||
138, 243, 28, 185, 62, 59, 240, 202, 234, 99, 77, 73, 199, 137, 95, 165,
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// String
|
||||
//-----------------------------------------------------------------------------
|
||||
unsigned FASTCALL HashString( const char *pszKey )
|
||||
{
|
||||
const uint8 *k = (const uint8 *)pszKey;
|
||||
unsigned even = 0,
|
||||
odd = 0,
|
||||
n;
|
||||
|
||||
while ((n = *k++) != 0)
|
||||
{
|
||||
even = g_nRandomValues[odd ^ n];
|
||||
if ((n = *k++) != 0)
|
||||
odd = g_nRandomValues[even ^ n];
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return (even << 8) | odd ;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Case-insensitive string
|
||||
//-----------------------------------------------------------------------------
|
||||
unsigned FASTCALL HashStringCaseless( const char *pszKey )
|
||||
{
|
||||
const uint8 *k = (const uint8 *) pszKey;
|
||||
unsigned even = 0,
|
||||
odd = 0,
|
||||
n;
|
||||
|
||||
while ((n = toupper(*k++)) != 0)
|
||||
{
|
||||
even = g_nRandomValues[odd ^ n];
|
||||
if ((n = toupper(*k++)) != 0)
|
||||
odd = g_nRandomValues[even ^ n];
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return (even << 8) | odd;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 32 bit conventional case-insensitive string
|
||||
//-----------------------------------------------------------------------------
|
||||
unsigned FASTCALL HashStringCaselessConventional( const char *pszKey )
|
||||
{
|
||||
unsigned hash = 0xAAAAAAAA; // Alternating 1's and 0's to maximize the effect of the later multiply and add
|
||||
|
||||
for( ; *pszKey ; pszKey++ )
|
||||
{
|
||||
hash = ( ( hash << 5 ) + hash ) + (uint8)tolower(*pszKey);
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// int hash
|
||||
//-----------------------------------------------------------------------------
|
||||
unsigned FASTCALL HashInt( const int n )
|
||||
{
|
||||
register unsigned even, odd;
|
||||
even = g_nRandomValues[n & 0xff];
|
||||
odd = g_nRandomValues[((n >> 8) & 0xff)];
|
||||
|
||||
even = g_nRandomValues[odd ^ (n >> 24)];
|
||||
odd = g_nRandomValues[even ^ (n >> 16) & 0xff];
|
||||
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
|
||||
odd = g_nRandomValues[even ^ (n & 0xff)];
|
||||
|
||||
return (even << 8) | odd;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 4-byte hash
|
||||
//-----------------------------------------------------------------------------
|
||||
unsigned FASTCALL Hash4( const void *pKey )
|
||||
{
|
||||
register const uint32 * p = (const uint32 *) pKey;
|
||||
register unsigned even,
|
||||
odd,
|
||||
n;
|
||||
n = *p;
|
||||
even = g_nRandomValues[n & 0xff];
|
||||
odd = g_nRandomValues[((n >> 8) & 0xff)];
|
||||
|
||||
even = g_nRandomValues[odd ^ (n >> 24)];
|
||||
odd = g_nRandomValues[even ^ (n >> 16) & 0xff];
|
||||
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
|
||||
odd = g_nRandomValues[even ^ (n & 0xff)];
|
||||
|
||||
return (even << 8) | odd;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 8-byte hash
|
||||
//-----------------------------------------------------------------------------
|
||||
unsigned FASTCALL Hash8( const void *pKey )
|
||||
{
|
||||
register const uint32 * p = (const uint32 *) pKey;
|
||||
register unsigned even,
|
||||
odd,
|
||||
n;
|
||||
n = *p;
|
||||
even = g_nRandomValues[n & 0xff];
|
||||
odd = g_nRandomValues[((n >> 8) & 0xff)];
|
||||
|
||||
even = g_nRandomValues[odd ^ (n >> 24)];
|
||||
odd = g_nRandomValues[even ^ (n >> 16) & 0xff];
|
||||
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
|
||||
odd = g_nRandomValues[even ^ (n & 0xff)];
|
||||
|
||||
n = *(p+1);
|
||||
even = g_nRandomValues[odd ^ (n >> 24)];
|
||||
odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)];
|
||||
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
|
||||
odd = g_nRandomValues[even ^ (n & 0xff)];
|
||||
|
||||
return (even << 8) | odd;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 12-byte hash
|
||||
//-----------------------------------------------------------------------------
|
||||
unsigned FASTCALL Hash12( const void *pKey )
|
||||
{
|
||||
register const uint32 * p = (const uint32 *) pKey;
|
||||
register unsigned even,
|
||||
odd,
|
||||
n;
|
||||
n = *p;
|
||||
even = g_nRandomValues[n & 0xff];
|
||||
odd = g_nRandomValues[((n >> 8) & 0xff)];
|
||||
|
||||
even = g_nRandomValues[odd ^ (n >> 24)];
|
||||
odd = g_nRandomValues[even ^ (n >> 16) & 0xff];
|
||||
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
|
||||
odd = g_nRandomValues[even ^ (n & 0xff)];
|
||||
|
||||
n = *(p+1);
|
||||
even = g_nRandomValues[odd ^ (n >> 24)];
|
||||
odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)];
|
||||
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
|
||||
odd = g_nRandomValues[even ^ (n & 0xff)];
|
||||
|
||||
n = *(p+2);
|
||||
even = g_nRandomValues[odd ^ (n >> 24)];
|
||||
odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)];
|
||||
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
|
||||
odd = g_nRandomValues[even ^ (n & 0xff)];
|
||||
|
||||
return (even << 8) | odd;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 16-byte hash
|
||||
//-----------------------------------------------------------------------------
|
||||
unsigned FASTCALL Hash16( const void *pKey )
|
||||
{
|
||||
register const uint32 * p = (const uint32 *) pKey;
|
||||
register unsigned even,
|
||||
odd,
|
||||
n;
|
||||
n = *p;
|
||||
even = g_nRandomValues[n & 0xff];
|
||||
odd = g_nRandomValues[((n >> 8) & 0xff)];
|
||||
|
||||
even = g_nRandomValues[odd ^ (n >> 24)];
|
||||
odd = g_nRandomValues[even ^ (n >> 16) & 0xff];
|
||||
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
|
||||
odd = g_nRandomValues[even ^ (n & 0xff)];
|
||||
|
||||
n = *(p+1);
|
||||
even = g_nRandomValues[odd ^ (n >> 24)];
|
||||
odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)];
|
||||
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
|
||||
odd = g_nRandomValues[even ^ (n & 0xff)];
|
||||
|
||||
n = *(p+2);
|
||||
even = g_nRandomValues[odd ^ (n >> 24)];
|
||||
odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)];
|
||||
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
|
||||
odd = g_nRandomValues[even ^ (n & 0xff)];
|
||||
|
||||
n = *(p+3);
|
||||
even = g_nRandomValues[odd ^ (n >> 24)];
|
||||
odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)];
|
||||
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
|
||||
odd = g_nRandomValues[even ^ (n & 0xff)];
|
||||
|
||||
return (even << 8) | odd;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Arbitrary fixed length hash
|
||||
//-----------------------------------------------------------------------------
|
||||
unsigned FASTCALL HashBlock( const void *pKey, unsigned size )
|
||||
{
|
||||
const uint8 * k = (const uint8 *) pKey;
|
||||
unsigned even = 0,
|
||||
odd = 0,
|
||||
n;
|
||||
|
||||
while (size)
|
||||
{
|
||||
--size;
|
||||
n = *k++;
|
||||
even = g_nRandomValues[odd ^ n];
|
||||
if (size)
|
||||
{
|
||||
--size;
|
||||
n = *k++;
|
||||
odd = g_nRandomValues[even ^ n];
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return (even << 8) | odd;
|
||||
}
|
||||
|
465
tier1/interface.cpp
Normal file
465
tier1/interface.cpp
Normal file
@ -0,0 +1,465 @@
|
||||
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//===========================================================================//
|
||||
#if defined( _WIN32 ) && !defined( _X360 )
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if !defined( DONT_PROTECT_FILEIO_FUNCTIONS )
|
||||
#define DONT_PROTECT_FILEIO_FUNCTIONS // for protected_things.h
|
||||
#endif
|
||||
|
||||
#if defined( PROTECTED_THINGS_ENABLE )
|
||||
#undef PROTECTED_THINGS_ENABLE // from protected_things.h
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "interface.h"
|
||||
#include "basetypes.h"
|
||||
#include "tier0/dbg.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "tier1/strtools.h"
|
||||
#include "tier0/icommandline.h"
|
||||
#include "tier0/dbg.h"
|
||||
#include "tier0/threadtools.h"
|
||||
#ifdef _WIN32
|
||||
#include <direct.h> // getcwd
|
||||
#elif defined _LINUX || defined __APPLE__
|
||||
#define _getcwd getcwd
|
||||
#endif
|
||||
#if defined( _X360 )
|
||||
#include "xbox/xbox_win32stubs.h"
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
// ------------------------------------------------------------------------------------ //
|
||||
// InterfaceReg.
|
||||
// ------------------------------------------------------------------------------------ //
|
||||
InterfaceReg *InterfaceReg::s_pInterfaceRegs = NULL;
|
||||
|
||||
InterfaceReg::InterfaceReg( InstantiateInterfaceFn fn, const char *pName ) :
|
||||
m_pName(pName)
|
||||
{
|
||||
m_CreateFn = fn;
|
||||
m_pNext = s_pInterfaceRegs;
|
||||
s_pInterfaceRegs = this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------ //
|
||||
// CreateInterface.
|
||||
// This is the primary exported function by a dll, referenced by name via dynamic binding
|
||||
// that exposes an opqaue function pointer to the interface.
|
||||
// ------------------------------------------------------------------------------------ //
|
||||
void* CreateInterface( const char *pName, int *pReturnCode )
|
||||
{
|
||||
InterfaceReg *pCur;
|
||||
|
||||
for (pCur=InterfaceReg::s_pInterfaceRegs; pCur; pCur=pCur->m_pNext)
|
||||
{
|
||||
if (strcmp(pCur->m_pName, pName) == 0)
|
||||
{
|
||||
if (pReturnCode)
|
||||
{
|
||||
*pReturnCode = IFACE_OK;
|
||||
}
|
||||
return pCur->m_CreateFn();
|
||||
}
|
||||
}
|
||||
|
||||
if (pReturnCode)
|
||||
{
|
||||
*pReturnCode = IFACE_FAILED;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
#if defined _LINUX || defined __APPLE__
|
||||
// Linux doesn't have this function so this emulates its functionality
|
||||
void *GetModuleHandle(const char *name)
|
||||
{
|
||||
void *handle;
|
||||
|
||||
if( name == NULL )
|
||||
{
|
||||
// hmm, how can this be handled under linux....
|
||||
// is it even needed?
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( (handle=dlopen(name, RTLD_NOW))==NULL)
|
||||
{
|
||||
printf("DLOPEN Error:%s\n",dlerror());
|
||||
// couldn't open this file
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// read "man dlopen" for details
|
||||
// in short dlopen() inc a ref count
|
||||
// so dec the ref count by performing the close
|
||||
dlclose(handle);
|
||||
return handle;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined( _WIN32 ) && !defined( _X360 )
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include "windows.h"
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: returns a pointer to a function, given a module
|
||||
// Input : pModuleName - module name
|
||||
// *pName - proc name
|
||||
//-----------------------------------------------------------------------------
|
||||
static void *Sys_GetProcAddress( const char *pModuleName, const char *pName )
|
||||
{
|
||||
HMODULE hModule = GetModuleHandle( pModuleName );
|
||||
return GetProcAddress( hModule, pName );
|
||||
}
|
||||
|
||||
static void *Sys_GetProcAddress( HMODULE hModule, const char *pName )
|
||||
{
|
||||
return GetProcAddress( hModule, pName );
|
||||
}
|
||||
|
||||
bool Sys_IsDebuggerPresent()
|
||||
{
|
||||
return Plat_IsInDebugSession();
|
||||
}
|
||||
|
||||
struct ThreadedLoadLibaryContext_t
|
||||
{
|
||||
const char *m_pLibraryName;
|
||||
HMODULE m_hLibrary;
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
// wraps LoadLibraryEx() since 360 doesn't support that
|
||||
static HMODULE InternalLoadLibrary( const char *pName )
|
||||
{
|
||||
#if defined(_X360)
|
||||
return LoadLibrary( pName );
|
||||
#else
|
||||
return LoadLibraryEx( pName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH );
|
||||
#endif
|
||||
}
|
||||
unsigned ThreadedLoadLibraryFunc( void *pParam )
|
||||
{
|
||||
ThreadedLoadLibaryContext_t *pContext = (ThreadedLoadLibaryContext_t*)pParam;
|
||||
pContext->m_hLibrary = InternalLoadLibrary(pContext->m_pLibraryName);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
HMODULE Sys_LoadLibrary( const char *pLibraryName )
|
||||
{
|
||||
char str[1024];
|
||||
#if defined( _WIN32 ) && !defined( _X360 )
|
||||
const char *pModuleExtension = ".dll";
|
||||
const char *pModuleAddition = pModuleExtension;
|
||||
#elif defined( _X360 )
|
||||
const char *pModuleExtension = "_360.dll";
|
||||
const char *pModuleAddition = pModuleExtension;
|
||||
#elif defined( _LINUX )
|
||||
const char *pModuleExtension = ".so";
|
||||
const char *pModuleAddition = ".so";
|
||||
#elif defined( __APPLE__ )
|
||||
const char *pModuleExtension = ".dylib";
|
||||
const char *pModuleAddition = ".dylib";
|
||||
#endif
|
||||
Q_strncpy( str, pLibraryName, sizeof(str) );
|
||||
if ( !Q_stristr( str, pModuleExtension ) )
|
||||
{
|
||||
if ( IsX360() )
|
||||
{
|
||||
Q_StripExtension( str, str, sizeof(str) );
|
||||
}
|
||||
Q_strncat( str, pModuleAddition, sizeof(str) );
|
||||
}
|
||||
Q_FixSlashes( str );
|
||||
|
||||
#ifdef _WIN32
|
||||
ThreadedLoadLibraryFunc_t threadFunc = GetThreadedLoadLibraryFunc();
|
||||
if ( !threadFunc )
|
||||
return InternalLoadLibrary( str );
|
||||
|
||||
ThreadedLoadLibaryContext_t context;
|
||||
context.m_pLibraryName = str;
|
||||
context.m_hLibrary = 0;
|
||||
|
||||
ThreadHandle_t h = CreateSimpleThread( ThreadedLoadLibraryFunc, &context );
|
||||
|
||||
#ifdef _X360
|
||||
ThreadSetAffinity( h, XBOX_PROCESSOR_3 );
|
||||
#endif
|
||||
|
||||
unsigned int nTimeout = 0;
|
||||
while( ThreadWaitForObject( h, true, nTimeout ) == TW_TIMEOUT )
|
||||
{
|
||||
nTimeout = threadFunc();
|
||||
}
|
||||
|
||||
ReleaseThreadHandle( h );
|
||||
return context.m_hLibrary;
|
||||
|
||||
#elif defined _LINUX || defined __APPLE__
|
||||
HMODULE ret = dlopen( str, RTLD_NOW );
|
||||
if ( ! ret )
|
||||
{
|
||||
const char *pError = dlerror();
|
||||
if ( pError && ( strstr( pError, "No such file" ) == 0 ) )
|
||||
{
|
||||
Msg( " failed to dlopen %s error=%s\n", str, pError );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Loads a DLL/component from disk and returns a handle to it
|
||||
// Input : *pModuleName - filename of the component
|
||||
// Output : opaque handle to the module (hides system dependency)
|
||||
//-----------------------------------------------------------------------------
|
||||
CSysModule *Sys_LoadModule( const char *pModuleName )
|
||||
{
|
||||
// If using the Steam filesystem, either the DLL must be a minimum footprint
|
||||
// file in the depot (MFP) or a filesystem GetLocalCopy() call must be made
|
||||
// prior to the call to this routine.
|
||||
char szCwd[1024];
|
||||
HMODULE hDLL = NULL;
|
||||
|
||||
if ( !Q_IsAbsolutePath( pModuleName ) )
|
||||
{
|
||||
// full path wasn't passed in, using the current working dir
|
||||
_getcwd( szCwd, sizeof( szCwd ) );
|
||||
if ( IsX360() )
|
||||
{
|
||||
int i = CommandLine()->FindParm( "-basedir" );
|
||||
if ( i )
|
||||
{
|
||||
strcpy( szCwd, CommandLine()->GetParm( i+1 ) );
|
||||
}
|
||||
}
|
||||
if (szCwd[strlen(szCwd) - 1] == '/' || szCwd[strlen(szCwd) - 1] == '\\' )
|
||||
{
|
||||
szCwd[strlen(szCwd) - 1] = 0;
|
||||
}
|
||||
|
||||
char szAbsoluteModuleName[1024];
|
||||
if ( strstr( pModuleName, "bin/") == pModuleName )
|
||||
{
|
||||
// don't make bin/bin path
|
||||
Q_snprintf( szAbsoluteModuleName, sizeof(szAbsoluteModuleName), "%s/%s", szCwd, pModuleName );
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_snprintf( szAbsoluteModuleName, sizeof(szAbsoluteModuleName), "%s/bin/%s", szCwd, pModuleName );
|
||||
}
|
||||
hDLL = Sys_LoadLibrary( szAbsoluteModuleName );
|
||||
}
|
||||
|
||||
if ( !hDLL )
|
||||
{
|
||||
// full path failed, let LoadLibrary() try to search the PATH now
|
||||
hDLL = Sys_LoadLibrary( pModuleName );
|
||||
#if defined( _DEBUG )
|
||||
if ( !hDLL )
|
||||
{
|
||||
// So you can see what the error is in the debugger...
|
||||
#if defined( _WIN32 ) && !defined( _X360 )
|
||||
char *lpMsgBuf;
|
||||
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
|
||||
LocalFree( (HLOCAL)lpMsgBuf );
|
||||
#elif defined( _X360 )
|
||||
Msg( "Failed to load %s:\n", pModuleName );
|
||||
#else
|
||||
Error( "Failed to load %s: %s\n", pModuleName, dlerror() );
|
||||
#endif // _WIN32
|
||||
}
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
// If running in the debugger, assume debug binaries are okay, otherwise they must run with -allowdebug
|
||||
if ( !IsX360() && hDLL &&
|
||||
!CommandLine()->FindParm( "-allowdebug" ) &&
|
||||
!Sys_IsDebuggerPresent() )
|
||||
{
|
||||
if ( Sys_GetProcAddress( hDLL, "BuiltDebug" ) )
|
||||
{
|
||||
Error( "Module %s is a debug build\n", pModuleName );
|
||||
}
|
||||
}
|
||||
|
||||
return reinterpret_cast<CSysModule *>(hDLL);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Unloads a DLL/component from
|
||||
// Input : *pModuleName - filename of the component
|
||||
// Output : opaque handle to the module (hides system dependency)
|
||||
//-----------------------------------------------------------------------------
|
||||
void Sys_UnloadModule( CSysModule *pModule )
|
||||
{
|
||||
if ( !pModule )
|
||||
return;
|
||||
|
||||
HMODULE hDLL = reinterpret_cast<HMODULE>(pModule);
|
||||
|
||||
#ifdef _WIN32
|
||||
FreeLibrary( hDLL );
|
||||
#elif defined(_LINUX) || defined(__APPLE__)
|
||||
dlclose((void *)hDLL);
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: returns a pointer to a function, given a module
|
||||
// Input : module - windows HMODULE from Sys_LoadModule()
|
||||
// *pName - proc name
|
||||
// Output : factory for this module
|
||||
//-----------------------------------------------------------------------------
|
||||
CreateInterfaceFn Sys_GetFactory( CSysModule *pModule )
|
||||
{
|
||||
if ( !pModule )
|
||||
return NULL;
|
||||
|
||||
HMODULE hDLL = reinterpret_cast<HMODULE>(pModule);
|
||||
#ifdef _WIN32
|
||||
return reinterpret_cast<CreateInterfaceFn>(GetProcAddress( hDLL, CREATEINTERFACE_PROCNAME ));
|
||||
#elif defined(_LINUX) || defined(__APPLE__)
|
||||
// Linux gives this error:
|
||||
//../public/interface.cpp: In function `IBaseInterface *(*Sys_GetFactory
|
||||
//(CSysModule *)) (const char *, int *)':
|
||||
//../public/interface.cpp:154: ISO C++ forbids casting between
|
||||
//pointer-to-function and pointer-to-object
|
||||
//
|
||||
// so lets get around it :)
|
||||
return (CreateInterfaceFn)(GetProcAddress( hDLL, CREATEINTERFACE_PROCNAME ));
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: returns the instance of this module
|
||||
// Output : interface_instance_t
|
||||
//-----------------------------------------------------------------------------
|
||||
CreateInterfaceFn Sys_GetFactoryThis( void )
|
||||
{
|
||||
return CreateInterface;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: returns the instance of the named module
|
||||
// Input : *pModuleName - name of the module
|
||||
// Output : interface_instance_t - instance of that module
|
||||
//-----------------------------------------------------------------------------
|
||||
CreateInterfaceFn Sys_GetFactory( const char *pModuleName )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return static_cast<CreateInterfaceFn>( Sys_GetProcAddress( pModuleName, CREATEINTERFACE_PROCNAME ) );
|
||||
#elif defined(_LINUX) || defined(__APPLE__)
|
||||
// see Sys_GetFactory( CSysModule *pModule ) for an explanation
|
||||
return (CreateInterfaceFn)( Sys_GetProcAddress( pModuleName, CREATEINTERFACE_PROCNAME ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: get the interface for the specified module and version
|
||||
// Input :
|
||||
// Output :
|
||||
//-----------------------------------------------------------------------------
|
||||
bool Sys_LoadInterface(
|
||||
const char *pModuleName,
|
||||
const char *pInterfaceVersionName,
|
||||
CSysModule **pOutModule,
|
||||
void **pOutInterface )
|
||||
{
|
||||
CSysModule *pMod = Sys_LoadModule( pModuleName );
|
||||
if ( !pMod )
|
||||
return false;
|
||||
|
||||
CreateInterfaceFn fn = Sys_GetFactory( pMod );
|
||||
if ( !fn )
|
||||
{
|
||||
Sys_UnloadModule( pMod );
|
||||
return false;
|
||||
}
|
||||
|
||||
*pOutInterface = fn( pInterfaceVersionName, NULL );
|
||||
if ( !( *pOutInterface ) )
|
||||
{
|
||||
Sys_UnloadModule( pMod );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( pOutModule )
|
||||
*pOutModule = pMod;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Place this as a singleton at module scope (e.g.) and use it to get the factory from the specified module name.
|
||||
//
|
||||
// When the singleton goes out of scope (.dll unload if at module scope),
|
||||
// then it'll call Sys_UnloadModule on the module so that the refcount is decremented
|
||||
// and the .dll actually can unload from memory.
|
||||
//-----------------------------------------------------------------------------
|
||||
CDllDemandLoader::CDllDemandLoader( char const *pchModuleName ) :
|
||||
m_pchModuleName( pchModuleName ),
|
||||
m_hModule( 0 ),
|
||||
m_bLoadAttempted( false )
|
||||
{
|
||||
}
|
||||
|
||||
CDllDemandLoader::~CDllDemandLoader()
|
||||
{
|
||||
Unload();
|
||||
}
|
||||
|
||||
CreateInterfaceFn CDllDemandLoader::GetFactory()
|
||||
{
|
||||
if ( !m_hModule && !m_bLoadAttempted )
|
||||
{
|
||||
m_bLoadAttempted = true;
|
||||
m_hModule = Sys_LoadModule( m_pchModuleName );
|
||||
}
|
||||
|
||||
if ( !m_hModule )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return Sys_GetFactory( m_hModule );
|
||||
}
|
||||
|
||||
void CDllDemandLoader::Unload()
|
||||
{
|
||||
if ( m_hModule )
|
||||
{
|
||||
Sys_UnloadModule( m_hModule );
|
||||
m_hModule = 0;
|
||||
}
|
||||
}
|
316
tier1/mempool.cpp
Normal file
316
tier1/mempool.cpp
Normal file
@ -0,0 +1,316 @@
|
||||
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//===========================================================================//
|
||||
|
||||
#include "mempool.h"
|
||||
#include <stdio.h>
|
||||
#ifdef __APPLE__
|
||||
#include <sys/malloc.h>
|
||||
#else
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#include <memory.h>
|
||||
#include "tier0/dbg.h"
|
||||
#include <ctype.h>
|
||||
#include "tier1/strtools.h"
|
||||
|
||||
// Should be last include
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
MemoryPoolReportFunc_t CMemoryPool::g_ReportFunc = 0;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Error reporting... (debug only)
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CMemoryPool::SetErrorReportFunc( MemoryPoolReportFunc_t func )
|
||||
{
|
||||
g_ReportFunc = func;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CMemoryPool::CMemoryPool( int blockSize, int numElements, int growMode, const char *pszAllocOwner, int nAlignment )
|
||||
{
|
||||
#ifdef _X360
|
||||
if( numElements > 0 && growMode != GROW_NONE )
|
||||
{
|
||||
numElements = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_nAlignment = ( nAlignment != 0 ) ? nAlignment : 1;
|
||||
Assert( IsPowerOfTwo( m_nAlignment ) );
|
||||
m_BlockSize = blockSize < (int)sizeof(void*) ? sizeof(void*) : blockSize;
|
||||
m_BlockSize = AlignValue( m_BlockSize, m_nAlignment );
|
||||
m_BlocksPerBlob = numElements;
|
||||
m_PeakAlloc = 0;
|
||||
m_GrowMode = growMode;
|
||||
if ( !pszAllocOwner )
|
||||
{
|
||||
pszAllocOwner = __FILE__;
|
||||
}
|
||||
m_pszAllocOwner = pszAllocOwner;
|
||||
Init();
|
||||
AddNewBlob();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Frees the memory contained in the mempool, and invalidates it for
|
||||
// any further use.
|
||||
// Input : *memPool - the mempool to shutdown
|
||||
//-----------------------------------------------------------------------------
|
||||
CMemoryPool::~CMemoryPool()
|
||||
{
|
||||
if (m_BlocksAllocated > 0)
|
||||
{
|
||||
ReportLeaks();
|
||||
}
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Resets the pool
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMemoryPool::Init()
|
||||
{
|
||||
m_NumBlobs = 0;
|
||||
m_BlocksAllocated = 0;
|
||||
m_pHeadOfFreeList = 0;
|
||||
m_BlobHead.m_pNext = m_BlobHead.m_pPrev = &m_BlobHead;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Frees everything
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMemoryPool::Clear()
|
||||
{
|
||||
// Free everything..
|
||||
CBlob *pNext;
|
||||
for( CBlob *pCur = m_BlobHead.m_pNext; pCur != &m_BlobHead; pCur = pNext )
|
||||
{
|
||||
pNext = pCur->m_pNext;
|
||||
free( pCur );
|
||||
}
|
||||
Init();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Reports memory leaks
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CMemoryPool::ReportLeaks()
|
||||
{
|
||||
if (!g_ReportFunc)
|
||||
return;
|
||||
|
||||
g_ReportFunc("Memory leak: mempool blocks left in memory: %d\n", m_BlocksAllocated);
|
||||
|
||||
#ifdef _DEBUG
|
||||
// walk and destroy the free list so it doesn't intefere in the scan
|
||||
while (m_pHeadOfFreeList != NULL)
|
||||
{
|
||||
void *next = *((void**)m_pHeadOfFreeList);
|
||||
memset(m_pHeadOfFreeList, 0, m_BlockSize);
|
||||
m_pHeadOfFreeList = next;
|
||||
}
|
||||
|
||||
g_ReportFunc("Dumping memory: \'");
|
||||
|
||||
for( CBlob *pCur=m_BlobHead.m_pNext; pCur != &m_BlobHead; pCur=pCur->m_pNext )
|
||||
{
|
||||
// scan the memory block and dump the leaks
|
||||
char *scanPoint = (char *)pCur->m_Data;
|
||||
char *scanEnd = pCur->m_Data + pCur->m_NumBytes;
|
||||
bool needSpace = false;
|
||||
|
||||
while (scanPoint < scanEnd)
|
||||
{
|
||||
// search for and dump any strings
|
||||
if ((unsigned)(*scanPoint + 1) <= 256 && isprint(*scanPoint))
|
||||
{
|
||||
g_ReportFunc("%c", *scanPoint);
|
||||
needSpace = true;
|
||||
}
|
||||
else if (needSpace)
|
||||
{
|
||||
needSpace = false;
|
||||
g_ReportFunc(" ");
|
||||
}
|
||||
|
||||
scanPoint++;
|
||||
}
|
||||
}
|
||||
|
||||
g_ReportFunc("\'\n");
|
||||
#endif // _DEBUG
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMemoryPool::AddNewBlob()
|
||||
{
|
||||
MEM_ALLOC_CREDIT_(m_pszAllocOwner);
|
||||
|
||||
int sizeMultiplier;
|
||||
|
||||
if( m_GrowMode == GROW_SLOW )
|
||||
{
|
||||
sizeMultiplier = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_GrowMode == GROW_NONE )
|
||||
{
|
||||
// Can only have one allocation when we're in this mode
|
||||
if( m_NumBlobs != 0 )
|
||||
{
|
||||
Assert( !"CMemoryPool::AddNewBlob: mode == GROW_NONE" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// GROW_FAST and GROW_NONE use this.
|
||||
sizeMultiplier = m_NumBlobs + 1;
|
||||
}
|
||||
|
||||
// maybe use something other than malloc?
|
||||
int nElements = m_BlocksPerBlob * sizeMultiplier;
|
||||
int blobSize = m_BlockSize * nElements;
|
||||
CBlob *pBlob = (CBlob*)malloc( sizeof(CBlob) - 1 + blobSize + ( m_nAlignment - 1 ) );
|
||||
Assert( pBlob );
|
||||
|
||||
// Link it in at the end of the blob list.
|
||||
pBlob->m_NumBytes = blobSize;
|
||||
pBlob->m_pNext = &m_BlobHead;
|
||||
pBlob->m_pPrev = pBlob->m_pNext->m_pPrev;
|
||||
pBlob->m_pNext->m_pPrev = pBlob->m_pPrev->m_pNext = pBlob;
|
||||
|
||||
// setup the free list
|
||||
m_pHeadOfFreeList = AlignValue( pBlob->m_Data, m_nAlignment );
|
||||
Assert (m_pHeadOfFreeList);
|
||||
|
||||
void **newBlob = (void**)m_pHeadOfFreeList;
|
||||
for (int j = 0; j < nElements-1; j++)
|
||||
{
|
||||
newBlob[0] = (char*)newBlob + m_BlockSize;
|
||||
newBlob = (void**)newBlob[0];
|
||||
}
|
||||
|
||||
// null terminate list
|
||||
newBlob[0] = NULL;
|
||||
m_NumBlobs++;
|
||||
}
|
||||
|
||||
|
||||
void* CMemoryPool::Alloc()
|
||||
{
|
||||
return Alloc( m_BlockSize );
|
||||
}
|
||||
|
||||
|
||||
void* CMemoryPool::AllocZero()
|
||||
{
|
||||
return AllocZero( m_BlockSize );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Allocs a single block of memory from the pool.
|
||||
// Input : amount -
|
||||
//-----------------------------------------------------------------------------
|
||||
void *CMemoryPool::Alloc( size_t amount )
|
||||
{
|
||||
void *returnBlock;
|
||||
|
||||
if ( amount > (unsigned int)m_BlockSize )
|
||||
return NULL;
|
||||
|
||||
if( !m_pHeadOfFreeList )
|
||||
{
|
||||
// returning NULL is fine in GROW_NONE
|
||||
if( m_GrowMode == GROW_NONE )
|
||||
{
|
||||
//Assert( !"CMemoryPool::Alloc: tried to make new blob with GROW_NONE" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// overflow
|
||||
AddNewBlob();
|
||||
|
||||
// still failure, error out
|
||||
if( !m_pHeadOfFreeList )
|
||||
{
|
||||
Assert( !"CMemoryPool::Alloc: ran out of memory" );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
m_BlocksAllocated++;
|
||||
m_PeakAlloc = MAX(m_PeakAlloc, m_BlocksAllocated);
|
||||
|
||||
returnBlock = m_pHeadOfFreeList;
|
||||
|
||||
// move the pointer the next block
|
||||
m_pHeadOfFreeList = *((void**)m_pHeadOfFreeList);
|
||||
|
||||
return returnBlock;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Allocs a single block of memory from the pool, zeroes the memory before returning
|
||||
// Input : amount -
|
||||
//-----------------------------------------------------------------------------
|
||||
void *CMemoryPool::AllocZero( size_t amount )
|
||||
{
|
||||
void *mem = Alloc( amount );
|
||||
if ( mem )
|
||||
{
|
||||
V_memset( mem, 0x00, amount );
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Frees a block of memory
|
||||
// Input : *memBlock - the memory to free
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMemoryPool::Free( void *memBlock )
|
||||
{
|
||||
if ( !memBlock )
|
||||
return; // trying to delete NULL pointer, ignore
|
||||
|
||||
#ifdef _DEBUG
|
||||
// check to see if the memory is from the allocated range
|
||||
bool bOK = false;
|
||||
for( CBlob *pCur=m_BlobHead.m_pNext; pCur != &m_BlobHead; pCur=pCur->m_pNext )
|
||||
{
|
||||
if (memBlock >= pCur->m_Data && (char*)memBlock < (pCur->m_Data + pCur->m_NumBytes))
|
||||
{
|
||||
bOK = true;
|
||||
}
|
||||
}
|
||||
Assert (bOK);
|
||||
#endif // _DEBUG
|
||||
|
||||
#ifdef _DEBUG
|
||||
// invalidate the memory
|
||||
memset( memBlock, 0xDD, m_BlockSize );
|
||||
#endif
|
||||
|
||||
m_BlocksAllocated--;
|
||||
|
||||
// make the block point to the first item in the list
|
||||
*((void**)memBlock) = m_pHeadOfFreeList;
|
||||
|
||||
// the list head is now the new block
|
||||
m_pHeadOfFreeList = memBlock;
|
||||
}
|
||||
|
||||
|
300
tier1/memstack.cpp
Normal file
300
tier1/memstack.cpp
Normal file
@ -0,0 +1,300 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#if defined( _WIN32 ) && !defined( _X360 )
|
||||
#define WIN_32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#define VA_COMMIT_FLAGS MEM_COMMIT
|
||||
#define VA_RESERVE_FLAGS MEM_RESERVE
|
||||
#elif defined( _X360 )
|
||||
#define VA_COMMIT_FLAGS (MEM_COMMIT|MEM_NOZERO|MEM_LARGE_PAGES)
|
||||
#define VA_RESERVE_FLAGS (MEM_RESERVE|MEM_LARGE_PAGES)
|
||||
#endif
|
||||
|
||||
#include "tier0/dbg.h"
|
||||
#include "memstack.h"
|
||||
#include "utlmap.h"
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning(disable:4073)
|
||||
#pragma init_seg(lib)
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
MEMALLOC_DEFINE_EXTERNAL_TRACKING(CMemoryStack);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CMemoryStack::CMemoryStack()
|
||||
: m_pNextAlloc( NULL ),
|
||||
m_pCommitLimit( NULL ),
|
||||
m_pAllocLimit( NULL ),
|
||||
m_pBase( NULL ),
|
||||
m_maxSize( 0 ),
|
||||
#if defined (_LINUX) || defined (__APPLE__)
|
||||
m_alignment( 16 )
|
||||
#elif defined(_WIN32)
|
||||
m_alignment( 16 ),
|
||||
m_commitSize( 0 ),
|
||||
m_minCommit( 0 )
|
||||
#endif
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
CMemoryStack::~CMemoryStack()
|
||||
{
|
||||
if ( m_pBase )
|
||||
Term();
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
bool CMemoryStack::Init( unsigned maxSize, unsigned commitSize, unsigned initialCommit, unsigned alignment )
|
||||
{
|
||||
Assert( !m_pBase );
|
||||
|
||||
#ifdef _X360
|
||||
m_bPhysical = false;
|
||||
#endif
|
||||
|
||||
m_maxSize = maxSize;
|
||||
m_alignment = AlignValue( alignment, 4 );
|
||||
|
||||
Assert( m_alignment == alignment );
|
||||
Assert( m_maxSize > 0 );
|
||||
|
||||
#if defined(_WIN32)
|
||||
if ( commitSize != 0 )
|
||||
{
|
||||
m_commitSize = commitSize;
|
||||
}
|
||||
|
||||
unsigned pageSize;
|
||||
|
||||
#ifndef _X360
|
||||
SYSTEM_INFO sysInfo;
|
||||
GetSystemInfo( &sysInfo );
|
||||
Assert( !( sysInfo.dwPageSize & (sysInfo.dwPageSize-1)) );
|
||||
pageSize = sysInfo.dwPageSize;
|
||||
#else
|
||||
pageSize = 64*1024;
|
||||
#endif
|
||||
|
||||
if ( m_commitSize == 0 )
|
||||
{
|
||||
m_commitSize = pageSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_commitSize = AlignValue( m_commitSize, pageSize );
|
||||
}
|
||||
|
||||
m_maxSize = AlignValue( m_maxSize, m_commitSize );
|
||||
|
||||
Assert( m_maxSize % pageSize == 0 && m_commitSize % pageSize == 0 && m_commitSize <= m_maxSize );
|
||||
|
||||
m_pBase = (unsigned char *)VirtualAlloc( NULL, m_maxSize, VA_RESERVE_FLAGS, PAGE_NOACCESS );
|
||||
Assert( m_pBase );
|
||||
m_pCommitLimit = m_pNextAlloc = m_pBase;
|
||||
|
||||
if ( initialCommit )
|
||||
{
|
||||
initialCommit = AlignValue( initialCommit, m_commitSize );
|
||||
Assert( initialCommit < m_maxSize );
|
||||
if ( !VirtualAlloc( m_pCommitLimit, initialCommit, VA_COMMIT_FLAGS, PAGE_READWRITE ) )
|
||||
return false;
|
||||
m_minCommit = initialCommit;
|
||||
m_pCommitLimit += initialCommit;
|
||||
MemAlloc_RegisterExternalAllocation( CMemoryStack, GetBase(), GetSize() );
|
||||
}
|
||||
|
||||
#else
|
||||
m_pBase = (byte *)MemAlloc_AllocAligned( m_maxSize, alignment ? alignment : 1 );
|
||||
m_pNextAlloc = m_pBase;
|
||||
m_pCommitLimit = m_pBase + m_maxSize;
|
||||
#endif
|
||||
|
||||
m_pAllocLimit = m_pBase + m_maxSize;
|
||||
|
||||
return ( m_pBase != NULL );
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
#ifdef _X360
|
||||
bool CMemoryStack::InitPhysical( unsigned size, unsigned alignment )
|
||||
{
|
||||
m_bPhysical = true;
|
||||
|
||||
m_maxSize = m_commitSize = size;
|
||||
m_alignment = AlignValue( alignment, 4 );
|
||||
|
||||
int flags = PAGE_READWRITE;
|
||||
if ( size >= 16*1024*1024 )
|
||||
{
|
||||
flags |= MEM_16MB_PAGES;
|
||||
}
|
||||
else
|
||||
{
|
||||
flags |= MEM_LARGE_PAGES;
|
||||
}
|
||||
m_pBase = (unsigned char *)XPhysicalAlloc( m_maxSize, MAXULONG_PTR, 4096, flags );
|
||||
Assert( m_pBase );
|
||||
m_pNextAlloc = m_pBase;
|
||||
m_pCommitLimit = m_pBase + m_maxSize;
|
||||
m_pAllocLimit = m_pBase + m_maxSize;
|
||||
|
||||
MemAlloc_RegisterExternalAllocation( CMemoryStack, GetBase(), GetSize() );
|
||||
return ( m_pBase != NULL );
|
||||
}
|
||||
#endif
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
void CMemoryStack::Term()
|
||||
{
|
||||
FreeAll();
|
||||
if ( m_pBase )
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
VirtualFree( m_pBase, 0, MEM_RELEASE );
|
||||
#else
|
||||
MemAlloc_FreeAligned( m_pBase );
|
||||
#endif
|
||||
m_pBase = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
int CMemoryStack::GetSize()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return m_pCommitLimit - m_pBase;
|
||||
#else
|
||||
return m_maxSize;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
bool CMemoryStack::CommitTo( byte *pNextAlloc ) RESTRICT
|
||||
{
|
||||
#ifdef _X360
|
||||
if ( m_bPhysical )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
#if defined(_WIN32)
|
||||
unsigned char * pNewCommitLimit = AlignValue( pNextAlloc, m_commitSize );
|
||||
unsigned commitSize = pNewCommitLimit - m_pCommitLimit;
|
||||
|
||||
if ( GetSize() )
|
||||
MemAlloc_RegisterExternalDeallocation( CMemoryStack, GetBase(), GetSize() );
|
||||
|
||||
if( m_pCommitLimit + commitSize > m_pAllocLimit )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !VirtualAlloc( m_pCommitLimit, commitSize, VA_COMMIT_FLAGS, PAGE_READWRITE ) )
|
||||
{
|
||||
Assert( 0 );
|
||||
return false;
|
||||
}
|
||||
m_pCommitLimit = pNewCommitLimit;
|
||||
|
||||
if ( GetSize() )
|
||||
MemAlloc_RegisterExternalAllocation( CMemoryStack, GetBase(), GetSize() );
|
||||
return true;
|
||||
#else
|
||||
Assert( 0 );
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
void CMemoryStack::FreeToAllocPoint( MemoryStackMark_t mark, bool bDecommit )
|
||||
{
|
||||
void *pAllocPoint = m_pBase + mark;
|
||||
Assert( pAllocPoint >= m_pBase && pAllocPoint <= m_pNextAlloc );
|
||||
|
||||
if ( pAllocPoint >= m_pBase && pAllocPoint < m_pNextAlloc )
|
||||
{
|
||||
if ( bDecommit )
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
unsigned char *pDecommitPoint = AlignValue( (unsigned char *)pAllocPoint, m_commitSize );
|
||||
|
||||
if ( pDecommitPoint < m_pBase + m_minCommit )
|
||||
{
|
||||
pDecommitPoint = m_pBase + m_minCommit;
|
||||
}
|
||||
|
||||
unsigned decommitSize = m_pCommitLimit - pDecommitPoint;
|
||||
|
||||
if ( decommitSize > 0 )
|
||||
{
|
||||
MemAlloc_RegisterExternalDeallocation( CMemoryStack, GetBase(), GetSize() );
|
||||
|
||||
VirtualFree( pDecommitPoint, decommitSize, MEM_DECOMMIT );
|
||||
m_pCommitLimit = pDecommitPoint;
|
||||
|
||||
if ( mark > 0 )
|
||||
{
|
||||
MemAlloc_RegisterExternalAllocation( CMemoryStack, GetBase(), GetSize() );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
m_pNextAlloc = (unsigned char *)pAllocPoint;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
void CMemoryStack::FreeAll( bool bDecommit )
|
||||
{
|
||||
if ( m_pBase && m_pCommitLimit - m_pBase > 0 )
|
||||
{
|
||||
if ( bDecommit )
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
MemAlloc_RegisterExternalDeallocation( CMemoryStack, GetBase(), GetSize() );
|
||||
|
||||
VirtualFree( m_pBase, m_pCommitLimit - m_pBase, MEM_DECOMMIT );
|
||||
m_pCommitLimit = m_pBase;
|
||||
#endif
|
||||
}
|
||||
m_pNextAlloc = m_pBase;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
void CMemoryStack::Access( void **ppRegion, unsigned *pBytes )
|
||||
{
|
||||
*ppRegion = m_pBase;
|
||||
*pBytes = ( m_pNextAlloc - m_pBase);
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
void CMemoryStack::PrintContents()
|
||||
{
|
||||
Msg( "Total used memory: %d\n", GetUsed() );
|
||||
Msg( "Total committed memory: %d\n", GetSize() );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
713
tier1/newbitbuf.cpp
Normal file
713
tier1/newbitbuf.cpp
Normal file
@ -0,0 +1,713 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "bitbuf.h"
|
||||
#include "coordsize.h"
|
||||
#include "mathlib/vector.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
#include "tier1/strtools.h"
|
||||
#include "bitvec.h"
|
||||
|
||||
// FIXME: Can't use this until we get multithreaded allocations in tier0 working for tools
|
||||
// This is used by VVIS and fails to link
|
||||
// NOTE: This must be the last file included!!!
|
||||
//#include "tier0/memdbgon.h"
|
||||
|
||||
#ifdef _X360
|
||||
// mandatory ... wary of above comment and isolating, tier0 is built as MT though
|
||||
#include "tier0/memdbgon.h"
|
||||
#endif
|
||||
|
||||
#include "stdio.h"
|
||||
|
||||
void CBitWrite::StartWriting( void *pData, int nBytes, int iStartBit, int nBits )
|
||||
{
|
||||
// Make sure it's dword aligned and padded.
|
||||
Assert( (nBytes % 4) == 0 );
|
||||
Assert(((unsigned long)pData & 3) == 0);
|
||||
Assert( iStartBit == 0 );
|
||||
m_pData = (uint32 *) pData;
|
||||
m_pDataOut = m_pData;
|
||||
m_nDataBytes = nBytes;
|
||||
|
||||
if ( nBits == -1 )
|
||||
{
|
||||
m_nDataBits = nBytes << 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert( nBits <= nBytes*8 );
|
||||
m_nDataBits = nBits;
|
||||
}
|
||||
m_bOverflow = false;
|
||||
m_nOutBufWord = 0;
|
||||
m_nOutBitsAvail = 32;
|
||||
m_pBufferEnd = m_pDataOut + ( nBytes >> 2 );
|
||||
}
|
||||
|
||||
const uint32 CBitBuffer::s_nMaskTable[33] = {
|
||||
0,
|
||||
( 1 << 1 ) - 1,
|
||||
( 1 << 2 ) - 1,
|
||||
( 1 << 3 ) - 1,
|
||||
( 1 << 4 ) - 1,
|
||||
( 1 << 5 ) - 1,
|
||||
( 1 << 6 ) - 1,
|
||||
( 1 << 7 ) - 1,
|
||||
( 1 << 8 ) - 1,
|
||||
( 1 << 9 ) - 1,
|
||||
( 1 << 10 ) - 1,
|
||||
( 1 << 11 ) - 1,
|
||||
( 1 << 12 ) - 1,
|
||||
( 1 << 13 ) - 1,
|
||||
( 1 << 14 ) - 1,
|
||||
( 1 << 15 ) - 1,
|
||||
( 1 << 16 ) - 1,
|
||||
( 1 << 17 ) - 1,
|
||||
( 1 << 18 ) - 1,
|
||||
( 1 << 19 ) - 1,
|
||||
( 1 << 20 ) - 1,
|
||||
( 1 << 21 ) - 1,
|
||||
( 1 << 22 ) - 1,
|
||||
( 1 << 23 ) - 1,
|
||||
( 1 << 24 ) - 1,
|
||||
( 1 << 25 ) - 1,
|
||||
( 1 << 26 ) - 1,
|
||||
( 1 << 27 ) - 1,
|
||||
( 1 << 28 ) - 1,
|
||||
( 1 << 29 ) - 1,
|
||||
( 1 << 30 ) - 1,
|
||||
0x7fffffff,
|
||||
0xffffffff,
|
||||
};
|
||||
|
||||
bool CBitWrite::WriteString( const char *pStr )
|
||||
{
|
||||
if(pStr)
|
||||
{
|
||||
while( *pStr )
|
||||
{
|
||||
WriteChar( * ( pStr++ ) );
|
||||
}
|
||||
}
|
||||
WriteChar( 0 );
|
||||
return !IsOverflowed();
|
||||
}
|
||||
|
||||
|
||||
void CBitWrite::WriteLongLong(int64 val)
|
||||
{
|
||||
uint *pLongs = (uint*)&val;
|
||||
|
||||
// Insert the two DWORDS according to network endian
|
||||
const short endianIndex = 0x0100;
|
||||
byte *idx = (byte*)&endianIndex;
|
||||
WriteUBitLong(pLongs[*idx++], sizeof(long) << 3);
|
||||
WriteUBitLong(pLongs[*idx], sizeof(long) << 3);
|
||||
}
|
||||
|
||||
bool CBitWrite::WriteBits(const void *pInData, int nBits)
|
||||
{
|
||||
unsigned char *pOut = (unsigned char*)pInData;
|
||||
int nBitsLeft = nBits;
|
||||
|
||||
// Bounds checking..
|
||||
if ( ( GetNumBitsWritten() + nBits) > m_nDataBits )
|
||||
{
|
||||
SetOverflowFlag();
|
||||
CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, m_pDebugName );
|
||||
return false;
|
||||
}
|
||||
|
||||
// !! speed!! need fast paths
|
||||
// write remaining bytes
|
||||
while ( nBitsLeft >= 8 )
|
||||
{
|
||||
WriteUBitLong( *pOut, 8, false );
|
||||
++pOut;
|
||||
nBitsLeft -= 8;
|
||||
}
|
||||
|
||||
// write remaining bits
|
||||
if ( nBitsLeft )
|
||||
{
|
||||
WriteUBitLong( *pOut, nBitsLeft, false );
|
||||
}
|
||||
|
||||
return !IsOverflowed();
|
||||
}
|
||||
|
||||
void CBitWrite::WriteBytes( const void *pBuf, int nBytes )
|
||||
{
|
||||
WriteBits(pBuf, nBytes << 3);
|
||||
}
|
||||
|
||||
void CBitWrite::WriteBitCoord (const float f)
|
||||
{
|
||||
int signbit = (f <= -COORD_RESOLUTION);
|
||||
int intval = (int)fabs(f);
|
||||
int fractval = abs((int)(f*COORD_DENOMINATOR)) & (COORD_DENOMINATOR-1);
|
||||
|
||||
|
||||
// Send the bit flags that indicate whether we have an integer part and/or a fraction part.
|
||||
WriteOneBit( intval );
|
||||
WriteOneBit( fractval );
|
||||
|
||||
if ( intval || fractval )
|
||||
{
|
||||
// Send the sign bit
|
||||
WriteOneBit( signbit );
|
||||
|
||||
// Send the integer if we have one.
|
||||
if ( intval )
|
||||
{
|
||||
// Adjust the integers from [1..MAX_COORD_VALUE] to [0..MAX_COORD_VALUE-1]
|
||||
intval--;
|
||||
WriteUBitLong( (unsigned int)intval, COORD_INTEGER_BITS );
|
||||
}
|
||||
|
||||
// Send the fraction if we have one
|
||||
if ( fractval )
|
||||
{
|
||||
WriteUBitLong( (unsigned int)fractval, COORD_FRACTIONAL_BITS );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CBitWrite::WriteBitCoordMP (const float f, bool bIntegral, bool bLowPrecision )
|
||||
{
|
||||
int signbit = (f <= -( bLowPrecision ? COORD_RESOLUTION_LOWPRECISION : COORD_RESOLUTION ));
|
||||
int intval = (int)fabs(f);
|
||||
int fractval = bLowPrecision ?
|
||||
( abs((int)(f*COORD_DENOMINATOR_LOWPRECISION)) & (COORD_DENOMINATOR_LOWPRECISION-1) ) :
|
||||
( abs((int)(f*COORD_DENOMINATOR)) & (COORD_DENOMINATOR-1) );
|
||||
|
||||
bool bInBounds = intval < (1 << COORD_INTEGER_BITS_MP );
|
||||
|
||||
WriteOneBit( bInBounds );
|
||||
|
||||
if ( bIntegral )
|
||||
{
|
||||
// Send the sign bit
|
||||
WriteOneBit( intval );
|
||||
if ( intval )
|
||||
{
|
||||
WriteOneBit( signbit );
|
||||
// Send the integer if we have one.
|
||||
// Adjust the integers from [1..MAX_COORD_VALUE] to [0..MAX_COORD_VALUE-1]
|
||||
intval--;
|
||||
if ( bInBounds )
|
||||
{
|
||||
WriteUBitLong( (unsigned int)intval, COORD_INTEGER_BITS_MP );
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteUBitLong( (unsigned int)intval, COORD_INTEGER_BITS );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Send the bit flags that indicate whether we have an integer part and/or a fraction part.
|
||||
WriteOneBit( intval );
|
||||
// Send the sign bit
|
||||
WriteOneBit( signbit );
|
||||
|
||||
// Send the integer if we have one.
|
||||
if ( intval )
|
||||
{
|
||||
// Adjust the integers from [1..MAX_COORD_VALUE] to [0..MAX_COORD_VALUE-1]
|
||||
intval--;
|
||||
if ( bInBounds )
|
||||
{
|
||||
WriteUBitLong( (unsigned int)intval, COORD_INTEGER_BITS_MP );
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteUBitLong( (unsigned int)intval, COORD_INTEGER_BITS );
|
||||
}
|
||||
}
|
||||
WriteUBitLong( (unsigned int)fractval, bLowPrecision ? COORD_FRACTIONAL_BITS_MP_LOWPRECISION : COORD_FRACTIONAL_BITS );
|
||||
}
|
||||
}
|
||||
|
||||
void CBitWrite::SeekToBit( int nBit )
|
||||
{
|
||||
TempFlush();
|
||||
m_pDataOut = m_pData + ( nBit / 32 );
|
||||
m_nOutBufWord = *( m_pDataOut );
|
||||
m_nOutBitsAvail = 32 - ( nBit & 31 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CBitWrite::WriteBitVec3Coord( const Vector& fa )
|
||||
{
|
||||
int xflag, yflag, zflag;
|
||||
|
||||
xflag = (fa[0] >= COORD_RESOLUTION) || (fa[0] <= -COORD_RESOLUTION);
|
||||
yflag = (fa[1] >= COORD_RESOLUTION) || (fa[1] <= -COORD_RESOLUTION);
|
||||
zflag = (fa[2] >= COORD_RESOLUTION) || (fa[2] <= -COORD_RESOLUTION);
|
||||
|
||||
WriteOneBit( xflag );
|
||||
WriteOneBit( yflag );
|
||||
WriteOneBit( zflag );
|
||||
|
||||
if ( xflag )
|
||||
WriteBitCoord( fa[0] );
|
||||
if ( yflag )
|
||||
WriteBitCoord( fa[1] );
|
||||
if ( zflag )
|
||||
WriteBitCoord( fa[2] );
|
||||
}
|
||||
|
||||
void CBitWrite::WriteBitNormal( float f )
|
||||
{
|
||||
int signbit = (f <= -NORMAL_RESOLUTION);
|
||||
|
||||
// NOTE: Since +/-1 are valid values for a normal, I'm going to encode that as all ones
|
||||
unsigned int fractval = abs( (int)(f*NORMAL_DENOMINATOR) );
|
||||
|
||||
// clamp..
|
||||
if (fractval > NORMAL_DENOMINATOR)
|
||||
fractval = NORMAL_DENOMINATOR;
|
||||
|
||||
// Send the sign bit
|
||||
WriteOneBit( signbit );
|
||||
|
||||
// Send the fractional component
|
||||
WriteUBitLong( fractval, NORMAL_FRACTIONAL_BITS );
|
||||
}
|
||||
|
||||
void CBitWrite::WriteBitVec3Normal( const Vector& fa )
|
||||
{
|
||||
int xflag, yflag;
|
||||
|
||||
xflag = (fa[0] >= NORMAL_RESOLUTION) || (fa[0] <= -NORMAL_RESOLUTION);
|
||||
yflag = (fa[1] >= NORMAL_RESOLUTION) || (fa[1] <= -NORMAL_RESOLUTION);
|
||||
|
||||
WriteOneBit( xflag );
|
||||
WriteOneBit( yflag );
|
||||
|
||||
if ( xflag )
|
||||
WriteBitNormal( fa[0] );
|
||||
if ( yflag )
|
||||
WriteBitNormal( fa[1] );
|
||||
|
||||
// Write z sign bit
|
||||
int signbit = (fa[2] <= -NORMAL_RESOLUTION);
|
||||
WriteOneBit( signbit );
|
||||
}
|
||||
|
||||
void CBitWrite::WriteBitAngle( float fAngle, int numbits )
|
||||
{
|
||||
|
||||
unsigned int shift = GetBitForBitnum(numbits);
|
||||
unsigned int mask = shift - 1;
|
||||
|
||||
int d = (int)( (fAngle / 360.0) * shift );
|
||||
d &= mask;
|
||||
|
||||
WriteUBitLong((unsigned int)d, numbits);
|
||||
}
|
||||
|
||||
bool CBitWrite::WriteBitsFromBuffer( bf_read *pIn, int nBits )
|
||||
{
|
||||
// This could be optimized a little by
|
||||
while ( nBits > 32 )
|
||||
{
|
||||
WriteUBitLong( pIn->ReadUBitLong( 32 ), 32 );
|
||||
nBits -= 32;
|
||||
}
|
||||
|
||||
WriteUBitLong( pIn->ReadUBitLong( nBits ), nBits );
|
||||
return !IsOverflowed() && !pIn->IsOverflowed();
|
||||
}
|
||||
|
||||
void CBitWrite::WriteBitAngles( const QAngle& fa )
|
||||
{
|
||||
// FIXME:
|
||||
Vector tmp( fa.x, fa.y, fa.z );
|
||||
WriteBitVec3Coord( tmp );
|
||||
}
|
||||
|
||||
bool CBitRead::Seek( int nPosition )
|
||||
{
|
||||
bool bSucc = true;
|
||||
if ( nPosition < 0 || nPosition > m_nDataBits)
|
||||
{
|
||||
SetOverflowFlag();
|
||||
bSucc = false;
|
||||
nPosition = m_nDataBits;
|
||||
}
|
||||
int nHead = m_nDataBytes & 3; // non-multiple-of-4 bytes at head of buffer. We put the "round off"
|
||||
// at the head to make reading and detecting the end efficient.
|
||||
|
||||
int nByteOfs = nPosition / 8;
|
||||
if ( ( m_nDataBytes < 4 ) || ( nHead && ( nByteOfs < nHead ) ) )
|
||||
{
|
||||
// partial first dword
|
||||
uint8 const *pPartial = ( uint8 const *) m_pData;
|
||||
if ( m_pData )
|
||||
{
|
||||
m_nInBufWord = *( pPartial++ );
|
||||
if ( nHead > 1 )
|
||||
m_nInBufWord |= ( *pPartial++ ) << 8;
|
||||
if ( nHead > 2 )
|
||||
m_nInBufWord |= ( *pPartial++ ) << 16;
|
||||
}
|
||||
m_pDataIn = ( uint32 const * ) pPartial;
|
||||
m_nInBufWord >>= ( nPosition & 31 );
|
||||
m_nBitsAvail = ( nHead << 3 ) - ( nPosition & 31 );
|
||||
}
|
||||
else
|
||||
{
|
||||
int nAdjPosition = nPosition - ( nHead << 3 );
|
||||
m_pDataIn = reinterpret_cast<uint32 const *> (
|
||||
reinterpret_cast<uint8 const *>( m_pData ) + ( ( nAdjPosition / 32 ) << 2 ) + nHead );
|
||||
if ( m_pData )
|
||||
{
|
||||
m_nBitsAvail = 32;
|
||||
GrabNextDWord();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_nInBufWord = 0;
|
||||
m_nBitsAvail = 1;
|
||||
}
|
||||
m_nInBufWord >>= ( nAdjPosition & 31 );
|
||||
m_nBitsAvail = MIN( m_nBitsAvail, 32 - ( nAdjPosition & 31 ) ); // in case grabnextdword overflowed
|
||||
}
|
||||
return bSucc;
|
||||
}
|
||||
|
||||
|
||||
void CBitRead::StartReading( const void *pData, int nBytes, int iStartBit, int nBits )
|
||||
{
|
||||
// Make sure it's dword aligned and padded.
|
||||
Assert(((unsigned long)pData & 3) == 0);
|
||||
m_pData = (uint32 *) pData;
|
||||
m_pDataIn = m_pData;
|
||||
m_nDataBytes = nBytes;
|
||||
|
||||
if ( nBits == -1 )
|
||||
{
|
||||
m_nDataBits = nBytes << 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert( nBits <= nBytes*8 );
|
||||
m_nDataBits = nBits;
|
||||
}
|
||||
m_bOverflow = false;
|
||||
m_pBufferEnd = reinterpret_cast<uint32 const *> ( reinterpret_cast< uint8 const *> (m_pData) + nBytes );
|
||||
if ( m_pData )
|
||||
Seek( iStartBit );
|
||||
|
||||
}
|
||||
|
||||
bool CBitRead::ReadString( char *pStr, int maxLen, bool bLine, int *pOutNumChars )
|
||||
{
|
||||
Assert( maxLen != 0 );
|
||||
|
||||
bool bTooSmall = false;
|
||||
int iChar = 0;
|
||||
while(1)
|
||||
{
|
||||
char val = ReadChar();
|
||||
if ( val == 0 )
|
||||
break;
|
||||
else if ( bLine && val == '\n' )
|
||||
break;
|
||||
|
||||
if ( iChar < (maxLen-1) )
|
||||
{
|
||||
pStr[iChar] = val;
|
||||
++iChar;
|
||||
}
|
||||
else
|
||||
{
|
||||
bTooSmall = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure it's null-terminated.
|
||||
Assert( iChar < maxLen );
|
||||
pStr[iChar] = 0;
|
||||
|
||||
if ( pOutNumChars )
|
||||
*pOutNumChars = iChar;
|
||||
|
||||
return !IsOverflowed() && !bTooSmall;
|
||||
}
|
||||
|
||||
char* CBitRead::ReadAndAllocateString( bool *pOverflow )
|
||||
{
|
||||
char str[2048];
|
||||
|
||||
int nChars;
|
||||
bool bOverflow = !ReadString( str, sizeof( str ), false, &nChars );
|
||||
if ( pOverflow )
|
||||
*pOverflow = bOverflow;
|
||||
|
||||
// Now copy into the output and return it;
|
||||
char *pRet = new char[ nChars + 1 ];
|
||||
for ( int i=0; i <= nChars; i++ )
|
||||
pRet[i] = str[i];
|
||||
|
||||
return pRet;
|
||||
}
|
||||
|
||||
int64 CBitRead::ReadLongLong( void )
|
||||
{
|
||||
int64 retval;
|
||||
uint *pLongs = (uint*)&retval;
|
||||
|
||||
// Read the two DWORDs according to network endian
|
||||
const short endianIndex = 0x0100;
|
||||
byte *idx = (byte*)&endianIndex;
|
||||
pLongs[*idx++] = ReadUBitLong(sizeof(long) << 3);
|
||||
pLongs[*idx] = ReadUBitLong(sizeof(long) << 3);
|
||||
return retval;
|
||||
}
|
||||
|
||||
void CBitRead::ReadBits(void *pOutData, int nBits)
|
||||
{
|
||||
unsigned char *pOut = (unsigned char*)pOutData;
|
||||
int nBitsLeft = nBits;
|
||||
|
||||
|
||||
// align output to dword boundary
|
||||
while( ((unsigned long)pOut & 3) != 0 && nBitsLeft >= 8 )
|
||||
{
|
||||
*pOut = (unsigned char)ReadUBitLong(8);
|
||||
++pOut;
|
||||
nBitsLeft -= 8;
|
||||
}
|
||||
|
||||
// X360TBD: Can't read dwords in ReadBits because they'll get swapped
|
||||
if ( IsPC() )
|
||||
{
|
||||
// read dwords
|
||||
while ( nBitsLeft >= 32 )
|
||||
{
|
||||
*((unsigned long*)pOut) = ReadUBitLong(32);
|
||||
pOut += sizeof(unsigned long);
|
||||
nBitsLeft -= 32;
|
||||
}
|
||||
}
|
||||
|
||||
// read remaining bytes
|
||||
while ( nBitsLeft >= 8 )
|
||||
{
|
||||
*pOut = ReadUBitLong(8);
|
||||
++pOut;
|
||||
nBitsLeft -= 8;
|
||||
}
|
||||
|
||||
// read remaining bits
|
||||
if ( nBitsLeft )
|
||||
{
|
||||
*pOut = ReadUBitLong(nBitsLeft);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool CBitRead::ReadBytes(void *pOut, int nBytes)
|
||||
{
|
||||
ReadBits(pOut, nBytes << 3);
|
||||
return !IsOverflowed();
|
||||
}
|
||||
|
||||
float CBitRead::ReadBitAngle( int numbits )
|
||||
{
|
||||
float shift = (float)( GetBitForBitnum(numbits) );
|
||||
|
||||
int i = ReadUBitLong( numbits );
|
||||
float fReturn = (float)i * (360.0 / shift);
|
||||
|
||||
return fReturn;
|
||||
}
|
||||
|
||||
// Basic Coordinate Routines (these contain bit-field size AND fixed point scaling constants)
|
||||
float CBitRead::ReadBitCoord (void)
|
||||
{
|
||||
int intval=0,fractval=0,signbit=0;
|
||||
float value = 0.0;
|
||||
|
||||
|
||||
// Read the required integer and fraction flags
|
||||
intval = ReadOneBit();
|
||||
fractval = ReadOneBit();
|
||||
|
||||
// If we got either parse them, otherwise it's a zero.
|
||||
if ( intval || fractval )
|
||||
{
|
||||
// Read the sign bit
|
||||
signbit = ReadOneBit();
|
||||
|
||||
// If there's an integer, read it in
|
||||
if ( intval )
|
||||
{
|
||||
// Adjust the integers from [0..MAX_COORD_VALUE-1] to [1..MAX_COORD_VALUE]
|
||||
intval = ReadUBitLong( COORD_INTEGER_BITS ) + 1;
|
||||
}
|
||||
|
||||
// If there's a fraction, read it in
|
||||
if ( fractval )
|
||||
{
|
||||
fractval = ReadUBitLong( COORD_FRACTIONAL_BITS );
|
||||
}
|
||||
|
||||
// Calculate the correct floating point value
|
||||
value = intval + ((float)fractval * COORD_RESOLUTION);
|
||||
|
||||
// Fixup the sign if negative.
|
||||
if ( signbit )
|
||||
value = -value;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float CBitRead::ReadBitCoordMP( bool bIntegral, bool bLowPrecision )
|
||||
{
|
||||
int intval=0,fractval=0,signbit=0;
|
||||
float value = 0.0;
|
||||
|
||||
bool bInBounds = ReadOneBit() ? true : false;
|
||||
|
||||
if ( bIntegral )
|
||||
{
|
||||
// Read the required integer and fraction flags
|
||||
intval = ReadOneBit();
|
||||
// If we got either parse them, otherwise it's a zero.
|
||||
if ( intval )
|
||||
{
|
||||
// Read the sign bit
|
||||
signbit = ReadOneBit();
|
||||
|
||||
// If there's an integer, read it in
|
||||
// Adjust the integers from [0..MAX_COORD_VALUE-1] to [1..MAX_COORD_VALUE]
|
||||
if ( bInBounds )
|
||||
{
|
||||
value = ReadUBitLong( COORD_INTEGER_BITS_MP ) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = ReadUBitLong( COORD_INTEGER_BITS ) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Read the required integer and fraction flags
|
||||
intval = ReadOneBit();
|
||||
|
||||
// Read the sign bit
|
||||
signbit = ReadOneBit();
|
||||
|
||||
// If we got either parse them, otherwise it's a zero.
|
||||
if ( intval )
|
||||
{
|
||||
if ( bInBounds )
|
||||
{
|
||||
intval = ReadUBitLong( COORD_INTEGER_BITS_MP ) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
intval = ReadUBitLong( COORD_INTEGER_BITS ) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// If there's a fraction, read it in
|
||||
fractval = ReadUBitLong( bLowPrecision ? COORD_FRACTIONAL_BITS_MP_LOWPRECISION : COORD_FRACTIONAL_BITS );
|
||||
|
||||
// Calculate the correct floating point value
|
||||
value = intval + ((float)fractval * ( bLowPrecision ? COORD_RESOLUTION_LOWPRECISION : COORD_RESOLUTION ) );
|
||||
}
|
||||
|
||||
// Fixup the sign if negative.
|
||||
if ( signbit )
|
||||
value = -value;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void CBitRead::ReadBitVec3Coord( Vector& fa )
|
||||
{
|
||||
int xflag, yflag, zflag;
|
||||
|
||||
// This vector must be initialized! Otherwise, If any of the flags aren't set,
|
||||
// the corresponding component will not be read and will be stack garbage.
|
||||
fa.Init( 0, 0, 0 );
|
||||
|
||||
xflag = ReadOneBit();
|
||||
yflag = ReadOneBit();
|
||||
zflag = ReadOneBit();
|
||||
|
||||
if ( xflag )
|
||||
fa[0] = ReadBitCoord();
|
||||
if ( yflag )
|
||||
fa[1] = ReadBitCoord();
|
||||
if ( zflag )
|
||||
fa[2] = ReadBitCoord();
|
||||
}
|
||||
|
||||
float CBitRead::ReadBitNormal (void)
|
||||
{
|
||||
// Read the sign bit
|
||||
int signbit = ReadOneBit();
|
||||
|
||||
// Read the fractional part
|
||||
unsigned int fractval = ReadUBitLong( NORMAL_FRACTIONAL_BITS );
|
||||
|
||||
// Calculate the correct floating point value
|
||||
float value = (float)fractval * NORMAL_RESOLUTION;
|
||||
|
||||
// Fixup the sign if negative.
|
||||
if ( signbit )
|
||||
value = -value;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void CBitRead::ReadBitVec3Normal( Vector& fa )
|
||||
{
|
||||
int xflag = ReadOneBit();
|
||||
int yflag = ReadOneBit();
|
||||
|
||||
if (xflag)
|
||||
fa[0] = ReadBitNormal();
|
||||
else
|
||||
fa[0] = 0.0f;
|
||||
|
||||
if (yflag)
|
||||
fa[1] = ReadBitNormal();
|
||||
else
|
||||
fa[1] = 0.0f;
|
||||
|
||||
// The first two imply the third (but not its sign)
|
||||
int znegative = ReadOneBit();
|
||||
|
||||
float fafafbfb = fa[0] * fa[0] + fa[1] * fa[1];
|
||||
if (fafafbfb < 1.0f)
|
||||
fa[2] = sqrt( 1.0f - fafafbfb );
|
||||
else
|
||||
fa[2] = 0.0f;
|
||||
|
||||
if (znegative)
|
||||
fa[2] = -fa[2];
|
||||
}
|
||||
|
||||
void CBitRead::ReadBitAngles( QAngle& fa )
|
||||
{
|
||||
Vector tmp;
|
||||
ReadBitVec3Coord( tmp );
|
||||
fa.Init( tmp.x, tmp.y, tmp.z );
|
||||
}
|
278
tier1/processor_detect.cpp
Normal file
278
tier1/processor_detect.cpp
Normal file
@ -0,0 +1,278 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: win32 dependant ASM code for CPU capability detection
|
||||
//
|
||||
// $Workfile: $
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#if defined _LINUX || defined __APPLE__
|
||||
|
||||
#include "processor_detect_linux.cpp"
|
||||
|
||||
#elif defined( _X360 )
|
||||
|
||||
bool CheckMMXTechnology(void) { return false; }
|
||||
bool CheckSSETechnology(void) { return false; }
|
||||
bool CheckSSE2Technology(void) { return false; }
|
||||
bool Check3DNowTechnology(void) { return false; }
|
||||
|
||||
#elif defined( _WIN32 ) && !defined( _X360 )
|
||||
|
||||
#pragma optimize( "", off )
|
||||
#pragma warning( disable: 4800 ) //'int' : forcing value to bool 'true' or 'false' (performance warning)
|
||||
|
||||
// stuff from windows.h
|
||||
#ifndef EXCEPTION_EXECUTE_HANDLER
|
||||
#define EXCEPTION_EXECUTE_HANDLER 1
|
||||
#endif
|
||||
|
||||
bool CheckMMXTechnology(void)
|
||||
{
|
||||
int retval = true;
|
||||
unsigned int RegEDX = 0;
|
||||
|
||||
#ifdef CPUID
|
||||
_asm pushad;
|
||||
#endif
|
||||
|
||||
__try
|
||||
{
|
||||
_asm
|
||||
{
|
||||
#ifdef CPUID
|
||||
xor edx, edx // Clue the compiler that EDX is about to be used.
|
||||
#endif
|
||||
mov eax, 1 // set up CPUID to return processor version and features
|
||||
// 0 = vendor string, 1 = version info, 2 = cache info
|
||||
CPUID // code bytes = 0fh, 0a2h
|
||||
mov RegEDX, edx // features returned in edx
|
||||
}
|
||||
}
|
||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
retval = false;
|
||||
}
|
||||
|
||||
// If CPUID not supported, then certainly no MMX extensions.
|
||||
if (retval)
|
||||
{
|
||||
if (RegEDX & 0x800000) // bit 23 is set for MMX technology
|
||||
{
|
||||
__try
|
||||
{
|
||||
// try executing the MMX instruction "emms"
|
||||
_asm EMMS
|
||||
}
|
||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
retval = false;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
retval = false; // processor supports CPUID but does not support MMX technology
|
||||
|
||||
// if retval == 0 here, it means the processor has MMX technology but
|
||||
// floating-point emulation is on; so MMX technology is unavailable
|
||||
}
|
||||
|
||||
#ifdef CPUID
|
||||
_asm popad;
|
||||
#endif
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool CheckSSETechnology(void)
|
||||
{
|
||||
int retval = true;
|
||||
unsigned int RegEDX = 0;
|
||||
|
||||
#ifdef CPUID
|
||||
_asm pushad;
|
||||
#endif
|
||||
|
||||
// Do we have support for the CPUID function?
|
||||
__try
|
||||
{
|
||||
_asm
|
||||
{
|
||||
#ifdef CPUID
|
||||
xor edx, edx // Clue the compiler that EDX is about to be used.
|
||||
#endif
|
||||
mov eax, 1 // set up CPUID to return processor version and features
|
||||
// 0 = vendor string, 1 = version info, 2 = cache info
|
||||
CPUID // code bytes = 0fh, 0a2h
|
||||
mov RegEDX, edx // features returned in edx
|
||||
}
|
||||
}
|
||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
retval = false;
|
||||
}
|
||||
|
||||
// If CPUID not supported, then certainly no SSE extensions.
|
||||
if (retval)
|
||||
{
|
||||
// Do we have support for SSE in this processor?
|
||||
if ( RegEDX & 0x2000000L ) // bit 25 is set for SSE technology
|
||||
{
|
||||
// Make sure that SSE is supported by executing an inline SSE instruction
|
||||
|
||||
// BUGBUG, FIXME - Visual C Version 6.0 does not support SSE inline code YET (No macros from Intel either)
|
||||
// Fix this if VC7 supports inline SSE instructinons like "xorps" as shown below.
|
||||
#if 1
|
||||
__try
|
||||
{
|
||||
_asm
|
||||
{
|
||||
// Attempt execution of a SSE instruction to make sure OS supports SSE FPU context switches
|
||||
xorps xmm0, xmm0
|
||||
// This will work on Win2k+ (Including masking SSE FPU exception to "normalized" values)
|
||||
// This will work on Win98+ (But no "masking" of FPU exceptions provided)
|
||||
}
|
||||
}
|
||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||
#endif
|
||||
|
||||
{
|
||||
retval = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
retval = false;
|
||||
}
|
||||
#ifdef CPUID
|
||||
_asm popad;
|
||||
#endif
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool CheckSSE2Technology(void)
|
||||
{
|
||||
int retval = true;
|
||||
unsigned int RegEDX = 0;
|
||||
|
||||
#ifdef CPUID
|
||||
_asm pushad;
|
||||
#endif
|
||||
|
||||
// Do we have support for the CPUID function?
|
||||
__try
|
||||
{
|
||||
_asm
|
||||
{
|
||||
#ifdef CPUID
|
||||
xor edx, edx // Clue the compiler that EDX is about to be used.
|
||||
#endif
|
||||
mov eax, 1 // set up CPUID to return processor version and features
|
||||
// 0 = vendor string, 1 = version info, 2 = cache info
|
||||
CPUID // code bytes = 0fh, 0a2h
|
||||
mov RegEDX, edx // features returned in edx
|
||||
}
|
||||
}
|
||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
retval = false;
|
||||
}
|
||||
|
||||
// If CPUID not supported, then certainly no SSE extensions.
|
||||
if (retval)
|
||||
{
|
||||
// Do we have support for SSE in this processor?
|
||||
if ( RegEDX & 0x04000000 ) // bit 26 is set for SSE2 technology
|
||||
{
|
||||
// Make sure that SSE is supported by executing an inline SSE instruction
|
||||
|
||||
__try
|
||||
{
|
||||
_asm
|
||||
{
|
||||
// Attempt execution of a SSE2 instruction to make sure OS supports SSE FPU context switches
|
||||
xorpd xmm0, xmm0
|
||||
}
|
||||
}
|
||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||
|
||||
{
|
||||
retval = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
retval = false;
|
||||
}
|
||||
#ifdef CPUID
|
||||
_asm popad;
|
||||
#endif
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool Check3DNowTechnology(void)
|
||||
{
|
||||
int retval = true;
|
||||
unsigned int RegEAX = 0;
|
||||
|
||||
#ifdef CPUID
|
||||
_asm pushad;
|
||||
#endif
|
||||
|
||||
// First see if we can execute CPUID at all
|
||||
__try
|
||||
{
|
||||
_asm
|
||||
{
|
||||
#ifdef CPUID
|
||||
// xor edx, edx // Clue the compiler that EDX is about to be used.
|
||||
#endif
|
||||
mov eax, 0x80000000 // setup CPUID to return whether AMD >0x80000000 function are supported.
|
||||
// 0x80000000 = Highest 0x80000000+ function, 0x80000001 = 3DNow support
|
||||
CPUID // code bytes = 0fh, 0a2h
|
||||
mov RegEAX, eax // result returned in eax
|
||||
}
|
||||
}
|
||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
retval = false;
|
||||
}
|
||||
|
||||
// If CPUID not supported, then there is definitely no 3DNow support
|
||||
if (retval)
|
||||
{
|
||||
// Are there any "higher" AMD CPUID functions?
|
||||
if (RegEAX > 0x80000000L )
|
||||
{
|
||||
__try
|
||||
{
|
||||
_asm
|
||||
{
|
||||
mov eax, 0x80000001 // setup to test for CPU features
|
||||
CPUID // code bytes = 0fh, 0a2h
|
||||
shr edx, 31 // If bit 31 is set, we have 3DNow support!
|
||||
mov retval, edx // Save the return value for end of function
|
||||
}
|
||||
}
|
||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
retval = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// processor supports CPUID but does not support AMD CPUID functions
|
||||
retval = false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CPUID
|
||||
_asm popad;
|
||||
#endif
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#pragma optimize( "", on )
|
||||
|
||||
#endif // _WIN32
|
47
tier1/processor_detect_linux.cpp
Normal file
47
tier1/processor_detect_linux.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: linux dependant ASM code for CPU capability detection
|
||||
//
|
||||
// $Workfile: $
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#define cpuid(in,a,b,c,d) \
|
||||
asm("pushl %%ebx\n\t" "cpuid\n\t" "movl %%ebx,%%esi\n\t" "pop %%ebx": "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (in));
|
||||
|
||||
bool CheckMMXTechnology(void)
|
||||
{
|
||||
unsigned long eax,ebx,edx,unused;
|
||||
cpuid(1,eax,ebx,unused,edx);
|
||||
|
||||
return edx & 0x800000;
|
||||
}
|
||||
|
||||
bool CheckSSETechnology(void)
|
||||
{
|
||||
unsigned long eax,ebx,edx,unused;
|
||||
cpuid(1,eax,ebx,unused,edx);
|
||||
|
||||
return edx & 0x2000000L;
|
||||
}
|
||||
|
||||
bool CheckSSE2Technology(void)
|
||||
{
|
||||
unsigned long eax,ebx,edx,unused;
|
||||
cpuid(1,eax,ebx,unused,edx);
|
||||
|
||||
return edx & 0x04000000;
|
||||
}
|
||||
|
||||
bool Check3DNowTechnology(void)
|
||||
{
|
||||
unsigned long eax, unused;
|
||||
cpuid(0x80000000,eax,unused,unused,unused);
|
||||
|
||||
if ( eax > 0x80000000L )
|
||||
{
|
||||
cpuid(0x80000001,unused,unused,unused,eax);
|
||||
return ( eax & 1<<31 );
|
||||
}
|
||||
return false;
|
||||
}
|
41
tier1/rangecheckedvar.cpp
Normal file
41
tier1/rangecheckedvar.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "rangecheckedvar.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
bool g_bDoRangeChecks = true;
|
||||
|
||||
|
||||
static int g_nDisables = 0;
|
||||
|
||||
|
||||
CDisableRangeChecks::CDisableRangeChecks()
|
||||
{
|
||||
if ( !ThreadInMainThread() )
|
||||
return;
|
||||
g_nDisables++;
|
||||
g_bDoRangeChecks = false;
|
||||
}
|
||||
|
||||
|
||||
CDisableRangeChecks::~CDisableRangeChecks()
|
||||
{
|
||||
if ( !ThreadInMainThread() )
|
||||
return;
|
||||
Assert( g_nDisables > 0 );
|
||||
--g_nDisables;
|
||||
if ( g_nDisables == 0 )
|
||||
{
|
||||
g_bDoRangeChecks = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
334
tier1/stringpool.cpp
Normal file
334
tier1/stringpool.cpp
Normal file
@ -0,0 +1,334 @@
|
||||
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
|
||||
#include "convar.h"
|
||||
#include "tier0/dbg.h"
|
||||
#include "stringpool.h"
|
||||
#include "tier1/strtools.h"
|
||||
#include "generichash.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Comparison function for string sorted associative data structures
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool StrLess( const char * const &pszLeft, const char * const &pszRight )
|
||||
{
|
||||
return ( Q_stricmp( pszLeft, pszRight) < 0 );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CStringPool::CStringPool()
|
||||
: m_Strings( 32, 256, StrLess )
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CStringPool::~CStringPool()
|
||||
{
|
||||
FreeAll();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
unsigned int CStringPool::Count() const
|
||||
{
|
||||
return m_Strings.Count();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
const char * CStringPool::Find( const char *pszValue )
|
||||
{
|
||||
unsigned short i = m_Strings.Find(pszValue);
|
||||
if ( m_Strings.IsValidIndex(i) )
|
||||
return m_Strings[i];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char * CStringPool::Allocate( const char *pszValue )
|
||||
{
|
||||
char *pszNew;
|
||||
|
||||
unsigned short i = m_Strings.Find(pszValue);
|
||||
bool bNew = (i == m_Strings.InvalidIndex());
|
||||
|
||||
if ( !bNew )
|
||||
return m_Strings[i];
|
||||
|
||||
pszNew = strdup( pszValue );
|
||||
|
||||
if ( bNew )
|
||||
m_Strings.Insert( pszNew );
|
||||
|
||||
return pszNew;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CStringPool::FreeAll()
|
||||
{
|
||||
unsigned short i = m_Strings.FirstInorder();
|
||||
while ( i != m_Strings.InvalidIndex() )
|
||||
{
|
||||
free( (void *)m_Strings[i] );
|
||||
i = m_Strings.NextInorder(i);
|
||||
}
|
||||
m_Strings.RemoveAll();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
CCountedStringPool::CCountedStringPool()
|
||||
{
|
||||
MEM_ALLOC_CREDIT();
|
||||
m_HashTable.EnsureCount(HASH_TABLE_SIZE);
|
||||
|
||||
for( int i = 0; i < m_HashTable.Count(); i++ )
|
||||
{
|
||||
m_HashTable[i] = INVALID_ELEMENT;
|
||||
}
|
||||
|
||||
m_FreeListStart = INVALID_ELEMENT;
|
||||
m_Elements.AddToTail();
|
||||
m_Elements[0].pString = NULL;
|
||||
m_Elements[0].nReferenceCount = 0;
|
||||
m_Elements[0].nNextElement = INVALID_ELEMENT;
|
||||
}
|
||||
|
||||
CCountedStringPool::~CCountedStringPool()
|
||||
{
|
||||
FreeAll();
|
||||
}
|
||||
|
||||
void CCountedStringPool::FreeAll()
|
||||
{
|
||||
int i;
|
||||
|
||||
// Reset the hash table:
|
||||
for( i = 0; i < m_HashTable.Count(); i++ )
|
||||
{
|
||||
m_HashTable[i] = INVALID_ELEMENT;
|
||||
}
|
||||
|
||||
// Blow away the free list:
|
||||
m_FreeListStart = INVALID_ELEMENT;
|
||||
|
||||
for( i = 0; i < m_Elements.Count(); i++ )
|
||||
{
|
||||
if( m_Elements[i].pString )
|
||||
{
|
||||
delete [] m_Elements[i].pString;
|
||||
m_Elements[i].pString = NULL;
|
||||
m_Elements[i].nReferenceCount = 0;
|
||||
m_Elements[i].nNextElement = INVALID_ELEMENT;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove all but the invalid element:
|
||||
m_Elements.RemoveAll();
|
||||
m_Elements.AddToTail();
|
||||
m_Elements[0].pString = NULL;
|
||||
m_Elements[0].nReferenceCount = 0;
|
||||
m_Elements[0].nNextElement = INVALID_ELEMENT;
|
||||
}
|
||||
|
||||
|
||||
unsigned short CCountedStringPool::FindStringHandle( const char* pIntrinsic )
|
||||
{
|
||||
if( pIntrinsic == NULL )
|
||||
return INVALID_ELEMENT;
|
||||
|
||||
unsigned short nHashBucketIndex = (HashStringCaseless(pIntrinsic ) %HASH_TABLE_SIZE);
|
||||
unsigned short nCurrentBucket = m_HashTable[ nHashBucketIndex ];
|
||||
|
||||
// Does the bucket already exist?
|
||||
if( nCurrentBucket != INVALID_ELEMENT )
|
||||
{
|
||||
for( ; nCurrentBucket != INVALID_ELEMENT ; nCurrentBucket = m_Elements[nCurrentBucket].nNextElement )
|
||||
{
|
||||
if( !Q_stricmp( pIntrinsic, m_Elements[nCurrentBucket].pString ) )
|
||||
{
|
||||
return nCurrentBucket;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
char* CCountedStringPool::FindString( const char* pIntrinsic )
|
||||
{
|
||||
if( pIntrinsic == NULL )
|
||||
return NULL;
|
||||
|
||||
// Yes, this will be NULL on failure.
|
||||
return m_Elements[FindStringHandle(pIntrinsic)].pString;
|
||||
}
|
||||
|
||||
unsigned short CCountedStringPool::ReferenceStringHandle( const char* pIntrinsic )
|
||||
{
|
||||
if( pIntrinsic == NULL )
|
||||
return INVALID_ELEMENT;
|
||||
|
||||
unsigned short nHashBucketIndex = (HashStringCaseless( pIntrinsic ) % HASH_TABLE_SIZE);
|
||||
unsigned short nCurrentBucket = m_HashTable[ nHashBucketIndex ];
|
||||
|
||||
// Does the bucket already exist?
|
||||
if( nCurrentBucket != INVALID_ELEMENT )
|
||||
{
|
||||
for( ; nCurrentBucket != INVALID_ELEMENT ; nCurrentBucket = m_Elements[nCurrentBucket].nNextElement )
|
||||
{
|
||||
if( !Q_stricmp( pIntrinsic, m_Elements[nCurrentBucket].pString ) )
|
||||
{
|
||||
// Anyone who hits 65k references is permanant
|
||||
if( m_Elements[nCurrentBucket].nReferenceCount < MAX_REFERENCE )
|
||||
{
|
||||
m_Elements[nCurrentBucket].nReferenceCount ++ ;
|
||||
}
|
||||
return nCurrentBucket;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( m_FreeListStart != INVALID_ELEMENT )
|
||||
{
|
||||
nCurrentBucket = m_FreeListStart;
|
||||
m_FreeListStart = m_Elements[nCurrentBucket].nNextElement;
|
||||
}
|
||||
else
|
||||
{
|
||||
nCurrentBucket = m_Elements.AddToTail();
|
||||
}
|
||||
|
||||
m_Elements[nCurrentBucket].nReferenceCount = 1;
|
||||
|
||||
// Insert at the beginning of the bucket:
|
||||
m_Elements[nCurrentBucket].nNextElement = m_HashTable[ nHashBucketIndex ];
|
||||
m_HashTable[ nHashBucketIndex ] = nCurrentBucket;
|
||||
|
||||
m_Elements[nCurrentBucket].pString = new char[Q_strlen( pIntrinsic ) + 1];
|
||||
Q_strcpy( m_Elements[nCurrentBucket].pString, pIntrinsic );
|
||||
|
||||
return nCurrentBucket;
|
||||
}
|
||||
|
||||
|
||||
char* CCountedStringPool::ReferenceString( const char* pIntrinsic )
|
||||
{
|
||||
if(!pIntrinsic)
|
||||
return NULL;
|
||||
|
||||
return m_Elements[ReferenceStringHandle( pIntrinsic)].pString;
|
||||
}
|
||||
|
||||
void CCountedStringPool::DereferenceString( const char* pIntrinsic )
|
||||
{
|
||||
// If we get a NULL pointer, just return
|
||||
if (!pIntrinsic)
|
||||
return;
|
||||
|
||||
unsigned short nHashBucketIndex = (HashStringCaseless( pIntrinsic ) % m_HashTable.Count());
|
||||
unsigned short nCurrentBucket = m_HashTable[ nHashBucketIndex ];
|
||||
|
||||
// If there isn't anything in the bucket, just return.
|
||||
if ( nCurrentBucket == INVALID_ELEMENT )
|
||||
return;
|
||||
|
||||
for( unsigned short previous = INVALID_ELEMENT; nCurrentBucket != INVALID_ELEMENT ; nCurrentBucket = m_Elements[nCurrentBucket].nNextElement )
|
||||
{
|
||||
if( !Q_stricmp( pIntrinsic, m_Elements[nCurrentBucket].pString ) )
|
||||
{
|
||||
// Anyone who hits 65k references is permanant
|
||||
if( m_Elements[nCurrentBucket].nReferenceCount < MAX_REFERENCE )
|
||||
{
|
||||
m_Elements[nCurrentBucket].nReferenceCount --;
|
||||
}
|
||||
|
||||
if( m_Elements[nCurrentBucket].nReferenceCount == 0 )
|
||||
{
|
||||
if( previous == INVALID_ELEMENT )
|
||||
{
|
||||
m_HashTable[nHashBucketIndex] = m_Elements[nCurrentBucket].nNextElement;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Elements[previous].nNextElement = m_Elements[nCurrentBucket].nNextElement;
|
||||
}
|
||||
|
||||
delete [] m_Elements[nCurrentBucket].pString;
|
||||
m_Elements[nCurrentBucket].pString = NULL;
|
||||
m_Elements[nCurrentBucket].nReferenceCount = 0;
|
||||
|
||||
m_Elements[nCurrentBucket].nNextElement = m_FreeListStart;
|
||||
m_FreeListStart = nCurrentBucket;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
previous = nCurrentBucket;
|
||||
}
|
||||
}
|
||||
|
||||
char* CCountedStringPool::HandleToString( unsigned short handle )
|
||||
{
|
||||
return m_Elements[handle].pString;
|
||||
}
|
||||
|
||||
void CCountedStringPool::SpewStrings()
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i < m_Elements.Count(); i++ )
|
||||
{
|
||||
char* string = m_Elements[i].pString;
|
||||
|
||||
Msg("String %d: ref:%d %s", i, m_Elements[i].nReferenceCount, string == NULL? "EMPTY - ok for slot zero only!" : string);
|
||||
}
|
||||
|
||||
Msg("\n%d total counted strings.", m_Elements.Count());
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
CON_COMMAND( test_stringpool, "Tests the class CStringPool" )
|
||||
{
|
||||
CStringPool pool;
|
||||
|
||||
Assert(pool.Count() == 0);
|
||||
|
||||
pool.Allocate("test");
|
||||
Assert(pool.Count() == 1);
|
||||
|
||||
pool.Allocate("test");
|
||||
Assert(pool.Count() == 1);
|
||||
|
||||
pool.Allocate("test2");
|
||||
Assert(pool.Count() == 2);
|
||||
|
||||
Assert( pool.Find("test2") != NULL );
|
||||
Assert( pool.Find("TEST") != NULL );
|
||||
Assert( pool.Find("Test2") != NULL );
|
||||
Assert( pool.Find("test") != NULL );
|
||||
|
||||
pool.FreeAll();
|
||||
Assert(pool.Count() == 0);
|
||||
|
||||
Msg("Pass.");
|
||||
}
|
||||
#endif
|
2015
tier1/strtools.cpp
Normal file
2015
tier1/strtools.cpp
Normal file
File diff suppressed because it is too large
Load Diff
568
tier1/tier1-2005.vcproj
Normal file
568
tier1/tier1-2005.vcproj
Normal file
@ -0,0 +1,568 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="tier1"
|
||||
ProjectGUID="{E1DA8DB8-FB4C-4B14-91A6-98BCED6B9720}"
|
||||
RootNamespace="tier1"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory=".\Debug"
|
||||
IntermediateDirectory=".\Debug"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
CommandLine=""
|
||||
ExcludedFromBuild="false"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UseUnicodeResponseFiles="false"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\public;..\public\tier0;..\public\tier1"
|
||||
PreprocessorDefinitions="WIN32;_WIN32;_DEBUG;DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;TIER1_STATIC_LIB"
|
||||
StringPooling="true"
|
||||
MinimalRebuild="true"
|
||||
ExceptionHandling="0"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
BufferSecurityCheck="false"
|
||||
FloatingPointModel="2"
|
||||
TreatWChar_tAsBuiltInType="true"
|
||||
ForceConformanceInForLoopScope="true"
|
||||
RuntimeTypeInfo="true"
|
||||
OpenMP="false"
|
||||
UsePrecompiledHeader="0"
|
||||
ExpandAttributedSource="false"
|
||||
AssemblerOutput="0"
|
||||
AssemblerListingLocation="$(IntDir)/"
|
||||
ObjectFile="$(IntDir)/"
|
||||
ProgramDataBaseFileName="$(IntDir)/"
|
||||
GenerateXMLDocumentationFiles="false"
|
||||
BrowseInformation="0"
|
||||
BrowseInformationFile="$(IntDir)/"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="4"
|
||||
CompileAs="2"
|
||||
ErrorReporting="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
CommandLine=""
|
||||
ExcludedFromBuild="false"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
UseUnicodeResponseFiles="false"
|
||||
AdditionalDependencies="Rpcrt4.lib"
|
||||
OutputFile="..\lib\public\tier1.lib"
|
||||
SuppressStartupBanner="true"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
SuppressStartupBanner="true"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
SuppressStartupBanner="true"
|
||||
OutputFile="$(OutDir)/tier1.bsc"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
ExcludedFromBuild="false"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory=".\Release"
|
||||
IntermediateDirectory=".\Release"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
CommandLine=""
|
||||
ExcludedFromBuild="false"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UseUnicodeResponseFiles="false"
|
||||
Optimization="2"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="1"
|
||||
AdditionalIncludeDirectories="..\public;..\public\tier0;..\public\tier1"
|
||||
PreprocessorDefinitions="WIN32;_WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;TIER1_STATIC_LIB"
|
||||
StringPooling="true"
|
||||
ExceptionHandling="0"
|
||||
RuntimeLibrary="0"
|
||||
BufferSecurityCheck="false"
|
||||
EnableFunctionLevelLinking="true"
|
||||
FloatingPointModel="2"
|
||||
TreatWChar_tAsBuiltInType="true"
|
||||
ForceConformanceInForLoopScope="true"
|
||||
RuntimeTypeInfo="true"
|
||||
OpenMP="false"
|
||||
UsePrecompiledHeader="0"
|
||||
ExpandAttributedSource="false"
|
||||
AssemblerOutput="0"
|
||||
AssemblerListingLocation="$(IntDir)/"
|
||||
ObjectFile="$(IntDir)/"
|
||||
ProgramDataBaseFileName="$(IntDir)/"
|
||||
GenerateXMLDocumentationFiles="false"
|
||||
BrowseInformation="0"
|
||||
BrowseInformationFile="$(IntDir)/"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="1"
|
||||
CompileAs="2"
|
||||
ErrorReporting="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
CommandLine=""
|
||||
ExcludedFromBuild="false"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
UseUnicodeResponseFiles="false"
|
||||
AdditionalDependencies="Rpcrt4.lib"
|
||||
OutputFile="..\lib\public\tier1.lib"
|
||||
SuppressStartupBanner="true"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
SuppressStartupBanner="true"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
SuppressStartupBanner="true"
|
||||
OutputFile="$(OutDir)/tier1.bsc"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
ExcludedFromBuild="false"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\bitbuf.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\byteswap.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\characterset.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\checksum_crc.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\checksum_md5.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\commandbuffer.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\convar.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\datamanager.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\diff.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\generichash.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\interface.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\KeyValues.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mempool.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\memstack.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\NetAdr.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\newbitbuf.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\processor_detect.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ExceptionHandling="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ExceptionHandling="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\rangecheckedvar.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stringpool.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\strtools.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\tier1.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\tokenreader.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\uniqueid.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\utlbuffer.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\utlbufferutil.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\utlstring.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\utlsymbol.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\public\tier1\bitbuf.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\byteswap.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\callqueue.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\characterset.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\checksum_crc.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\checksum_md5.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\CommandBuffer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\convar.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\datamanager.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\datamap.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\delegates.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\diff.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\fmtstr.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\functors.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\generichash.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\iconvar.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\interface.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\KeyValues.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\lzmaDecoder.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\lzss.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\mempool.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\memstack.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\netadr.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\processor_detect.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\rangecheckedvar.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\refcount.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\smartptr.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\stringpool.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\strtools.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\tier1.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\tokenreader.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\uniqueid.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\utlbidirectionalset.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\utlblockmemory.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\utlbuffer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\utlbufferutil.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\utldict.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\utlenvelope.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\utlfixedmemory.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\utlhandletable.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\utlhash.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\utllinkedlist.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\utlmap.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\utlmemory.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\utlmultilist.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\utlpriorityqueue.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\utlqueue.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\utlrbtree.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\UtlSortVector.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\utlstack.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\utlstring.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\UtlStringMap.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\utlsymbol.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\public\tier1\utlvector.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common\xbox\xboxstubs.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
63
tier1/tier1.cpp
Normal file
63
tier1/tier1.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
//===== Copyright © 2005-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose: A higher level link library for general use in the game and tools.
|
||||
//
|
||||
//===========================================================================//
|
||||
|
||||
#include <tier1/tier1.h>
|
||||
#include "tier0/dbg.h"
|
||||
#include "vstdlib/iprocessutils.h"
|
||||
#include "icvar.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// These tier1 libraries must be set by any users of this library.
|
||||
// They can be set by calling ConnectTier1Libraries or InitDefaultFileSystem.
|
||||
// It is hoped that setting this, and using this library will be the common mechanism for
|
||||
// allowing link libraries to access tier1 library interfaces
|
||||
//-----------------------------------------------------------------------------
|
||||
ICvar *cvar = 0;
|
||||
ICvar *g_pCVar = 0;
|
||||
IProcessUtils *g_pProcessUtils = 0;
|
||||
static bool s_bConnected = false;
|
||||
|
||||
// for utlsortvector.h
|
||||
#ifndef _WIN32
|
||||
void *g_pUtlSortVectorQSortContext = NULL;
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Call this to connect to all tier 1 libraries.
|
||||
// It's up to the caller to check the globals it cares about to see if ones are missing
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConnectTier1Libraries( CreateInterfaceFn *pFactoryList, int nFactoryCount )
|
||||
{
|
||||
// Don't connect twice..
|
||||
if ( s_bConnected )
|
||||
return;
|
||||
|
||||
s_bConnected = true;
|
||||
|
||||
for ( int i = 0; i < nFactoryCount; ++i )
|
||||
{
|
||||
if ( !g_pCVar )
|
||||
{
|
||||
cvar = g_pCVar = ( ICvar * )pFactoryList[i]( CVAR_INTERFACE_VERSION, NULL );
|
||||
}
|
||||
if ( !g_pProcessUtils )
|
||||
{
|
||||
g_pProcessUtils = ( IProcessUtils * )pFactoryList[i]( PROCESS_UTILS_INTERFACE_VERSION, NULL );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DisconnectTier1Libraries()
|
||||
{
|
||||
if ( !s_bConnected )
|
||||
return;
|
||||
|
||||
g_pCVar = cvar = 0;
|
||||
g_pProcessUtils = NULL;
|
||||
s_bConnected = false;
|
||||
}
|
480
tier1/tokenreader.cpp
Normal file
480
tier1/tokenreader.cpp
Normal file
@ -0,0 +1,480 @@
|
||||
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "tokenreader.h"
|
||||
#include "tier0/platform.h"
|
||||
#include "tier1/strtools.h"
|
||||
#include "tier0/dbg.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
TokenReader::TokenReader(void)
|
||||
{
|
||||
m_szFilename[0] = '\0';
|
||||
m_nLine = 1;
|
||||
m_nErrorCount = 0;
|
||||
m_bStuffed = false;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pszFilename -
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool TokenReader::Open(const char *pszFilename)
|
||||
{
|
||||
open(pszFilename, std::ios::in | std::ios::binary );
|
||||
Q_strncpy(m_szFilename, pszFilename, sizeof( m_szFilename ) );
|
||||
m_nLine = 1;
|
||||
m_nErrorCount = 0;
|
||||
m_bStuffed = false;
|
||||
return(is_open() != 0);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void TokenReader::Close()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *error -
|
||||
// Output : const char
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *TokenReader::Error(char *error, ...)
|
||||
{
|
||||
static char szErrorBuf[256];
|
||||
Q_snprintf(szErrorBuf, sizeof( szErrorBuf ), "File %s, line %d: ", m_szFilename, m_nLine);
|
||||
Q_strncat(szErrorBuf, error, sizeof( szErrorBuf ), COPY_ALL_CHARACTERS );
|
||||
m_nErrorCount++;
|
||||
return(szErrorBuf);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : pszStore -
|
||||
// nSize -
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
trtoken_t TokenReader::GetString(char *pszStore, int nSize)
|
||||
{
|
||||
if (nSize <= 0)
|
||||
{
|
||||
return TOKENERROR;
|
||||
}
|
||||
|
||||
char szBuf[1024];
|
||||
|
||||
//
|
||||
// Until we reach the end of this string or run out of room in
|
||||
// the destination buffer...
|
||||
//
|
||||
while (true)
|
||||
{
|
||||
//
|
||||
// Fetch the next batch of text from the file.
|
||||
//
|
||||
get(szBuf, sizeof(szBuf), '\"');
|
||||
if (eof())
|
||||
{
|
||||
return TOKENEOF;
|
||||
}
|
||||
|
||||
if (fail())
|
||||
{
|
||||
// Just means nothing was read (empty string probably "")
|
||||
clear();
|
||||
}
|
||||
|
||||
//
|
||||
// Transfer the text to the destination buffer.
|
||||
//
|
||||
char *pszSrc = szBuf;
|
||||
while ((*pszSrc != '\0') && (nSize > 1))
|
||||
{
|
||||
if (*pszSrc == 0x0d)
|
||||
{
|
||||
//
|
||||
// Newline encountered before closing quote -- unterminated string.
|
||||
//
|
||||
*pszStore = '\0';
|
||||
return TOKENSTRINGTOOLONG;
|
||||
}
|
||||
else if (*pszSrc != '\\')
|
||||
{
|
||||
*pszStore = *pszSrc;
|
||||
pszSrc++;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Backslash sequence - replace with the appropriate character.
|
||||
//
|
||||
pszSrc++;
|
||||
|
||||
if (*pszSrc == 'n')
|
||||
{
|
||||
*pszStore = '\n';
|
||||
}
|
||||
|
||||
pszSrc++;
|
||||
}
|
||||
|
||||
pszStore++;
|
||||
nSize--;
|
||||
}
|
||||
|
||||
if (*pszSrc != '\0')
|
||||
{
|
||||
//
|
||||
// Ran out of room in the destination buffer. Skip to the close-quote,
|
||||
// terminate the string, and exit.
|
||||
//
|
||||
ignore(1024, '\"');
|
||||
*pszStore = '\0';
|
||||
return TOKENSTRINGTOOLONG;
|
||||
}
|
||||
|
||||
//
|
||||
// Check for closing quote.
|
||||
//
|
||||
if (peek() == '\"')
|
||||
{
|
||||
//
|
||||
// Eat the close quote and any whitespace.
|
||||
//
|
||||
get();
|
||||
|
||||
bool bCombineStrings = SkipWhiteSpace();
|
||||
|
||||
//
|
||||
// Combine consecutive quoted strings if the combine strings character was
|
||||
// encountered between the two strings.
|
||||
//
|
||||
if (bCombineStrings && (peek() == '\"'))
|
||||
{
|
||||
//
|
||||
// Eat the open quote and keep parsing this string.
|
||||
//
|
||||
get();
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Done with this string, terminate the string and exit.
|
||||
//
|
||||
*pszStore = '\0';
|
||||
return STRING;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns the next token, allocating enough memory to store the token
|
||||
// plus a terminating NULL.
|
||||
// Input : pszStore - Pointer to a string that will be allocated.
|
||||
// Output : Returns the type of token that was read, or TOKENERROR.
|
||||
//-----------------------------------------------------------------------------
|
||||
trtoken_t TokenReader::NextTokenDynamic(char **ppszStore)
|
||||
{
|
||||
char szTempBuffer[8192];
|
||||
trtoken_t eType = NextToken(szTempBuffer, sizeof(szTempBuffer));
|
||||
|
||||
int len = Q_strlen(szTempBuffer) + 1;
|
||||
*ppszStore = new char [len];
|
||||
Assert( *ppszStore );
|
||||
Q_strncpy(*ppszStore, szTempBuffer, len );
|
||||
|
||||
return(eType);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns the next token.
|
||||
// Input : pszStore - Pointer to a string that will receive the token.
|
||||
// Output : Returns the type of token that was read, or TOKENERROR.
|
||||
//-----------------------------------------------------------------------------
|
||||
trtoken_t TokenReader::NextToken(char *pszStore, int nSize)
|
||||
{
|
||||
char *pStart = pszStore;
|
||||
|
||||
if (!is_open())
|
||||
{
|
||||
return TOKENEOF;
|
||||
}
|
||||
|
||||
//
|
||||
// If they stuffed a token, return that token.
|
||||
//
|
||||
if (m_bStuffed)
|
||||
{
|
||||
m_bStuffed = false;
|
||||
Q_strncpy( pszStore, m_szStuffed, nSize );
|
||||
return m_eStuffed;
|
||||
}
|
||||
|
||||
SkipWhiteSpace();
|
||||
|
||||
if (eof())
|
||||
{
|
||||
return TOKENEOF;
|
||||
}
|
||||
|
||||
if (fail())
|
||||
{
|
||||
return TOKENEOF;
|
||||
}
|
||||
|
||||
char ch = get();
|
||||
|
||||
//
|
||||
// Look for all the valid operators.
|
||||
//
|
||||
switch (ch)
|
||||
{
|
||||
case '@':
|
||||
case ',':
|
||||
case '!':
|
||||
case '+':
|
||||
case '&':
|
||||
case '*':
|
||||
case '$':
|
||||
case '.':
|
||||
case '=':
|
||||
case ':':
|
||||
case '[':
|
||||
case ']':
|
||||
case '(':
|
||||
case ')':
|
||||
case '{':
|
||||
case '}':
|
||||
case '\\':
|
||||
{
|
||||
pszStore[0] = ch;
|
||||
pszStore[1] = 0;
|
||||
return OPERATOR;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Look for the start of a quoted string.
|
||||
//
|
||||
if (ch == '\"')
|
||||
{
|
||||
return GetString(pszStore, nSize);
|
||||
}
|
||||
|
||||
//
|
||||
// Integers consist of numbers with an optional leading minus sign.
|
||||
//
|
||||
if (isdigit(ch) || (ch == '-'))
|
||||
{
|
||||
do
|
||||
{
|
||||
if ( (pszStore - pStart + 1) < nSize )
|
||||
{
|
||||
*pszStore = ch;
|
||||
pszStore++;
|
||||
}
|
||||
|
||||
ch = get();
|
||||
if (ch == '-')
|
||||
{
|
||||
return TOKENERROR;
|
||||
}
|
||||
} while (isdigit(ch));
|
||||
|
||||
//
|
||||
// No identifier characters are allowed contiguous with numbers.
|
||||
//
|
||||
if (isalpha(ch) || (ch == '_'))
|
||||
{
|
||||
return TOKENERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Put back the non-numeric character for the next call.
|
||||
//
|
||||
putback(ch);
|
||||
*pszStore = '\0';
|
||||
return INTEGER;
|
||||
}
|
||||
|
||||
//
|
||||
// Identifiers consist of a consecutive string of alphanumeric
|
||||
// characters and underscores.
|
||||
//
|
||||
while ( isalpha(ch) || isdigit(ch) || (ch == '_') )
|
||||
{
|
||||
if ( (pszStore - pStart + 1) < nSize )
|
||||
{
|
||||
*pszStore = ch;
|
||||
pszStore++;
|
||||
}
|
||||
|
||||
ch = get();
|
||||
}
|
||||
|
||||
//
|
||||
// Put back the non-identifier character for the next call.
|
||||
//
|
||||
putback(ch);
|
||||
*pszStore = '\0';
|
||||
return IDENT;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : ttype -
|
||||
// *pszToken -
|
||||
//-----------------------------------------------------------------------------
|
||||
void TokenReader::IgnoreTill(trtoken_t ttype, const char *pszToken)
|
||||
{
|
||||
trtoken_t _ttype;
|
||||
char szBuf[1024];
|
||||
|
||||
while(1)
|
||||
{
|
||||
_ttype = NextToken(szBuf, sizeof(szBuf));
|
||||
if(_ttype == TOKENEOF)
|
||||
return;
|
||||
if(_ttype == ttype)
|
||||
{
|
||||
if(IsToken(pszToken, szBuf))
|
||||
{
|
||||
Stuff(ttype, pszToken);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : ttype -
|
||||
// pszToken -
|
||||
//-----------------------------------------------------------------------------
|
||||
void TokenReader::Stuff(trtoken_t eType, const char *pszToken)
|
||||
{
|
||||
m_eStuffed = eType;
|
||||
Q_strncpy(m_szStuffed, pszToken, sizeof( m_szStuffed ) );
|
||||
m_bStuffed = true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : ttype -
|
||||
// pszToken -
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool TokenReader::Expecting(trtoken_t ttype, const char *pszToken)
|
||||
{
|
||||
char szBuf[1024];
|
||||
if (NextToken(szBuf, sizeof(szBuf)) != ttype || !IsToken(pszToken, szBuf))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : pszStore -
|
||||
// Output :
|
||||
//-----------------------------------------------------------------------------
|
||||
trtoken_t TokenReader::PeekTokenType(char *pszStore, int maxlen )
|
||||
{
|
||||
if (!m_bStuffed)
|
||||
{
|
||||
m_eStuffed = NextToken(m_szStuffed, sizeof(m_szStuffed));
|
||||
m_bStuffed = true;
|
||||
}
|
||||
|
||||
if (pszStore)
|
||||
{
|
||||
Q_strncpy(pszStore, m_szStuffed, maxlen );
|
||||
}
|
||||
|
||||
return(m_eStuffed);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Gets the next non-whitespace character from the file.
|
||||
// Input : ch - Receives the character.
|
||||
// Output : Returns true if the whitespace contained the combine strings
|
||||
// character '\', which is used to merge consecutive quoted strings.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool TokenReader::SkipWhiteSpace(void)
|
||||
{
|
||||
bool bCombineStrings = false;
|
||||
|
||||
while (true)
|
||||
{
|
||||
char ch = get();
|
||||
|
||||
if ((ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == 0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch == '+')
|
||||
{
|
||||
bCombineStrings = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch == '\n')
|
||||
{
|
||||
m_nLine++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (eof())
|
||||
{
|
||||
return(bCombineStrings);
|
||||
}
|
||||
|
||||
//
|
||||
// Check for the start of a comment.
|
||||
//
|
||||
if (ch == '/')
|
||||
{
|
||||
if (peek() == '/')
|
||||
{
|
||||
ignore(1024, '\n');
|
||||
m_nLine++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// It is a worthy character. Put it back.
|
||||
//
|
||||
putback(ch);
|
||||
return(bCombineStrings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
94
tier1/undiff.cpp
Normal file
94
tier1/undiff.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// UnDiff - Apply difference block
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "tier0/platform.h"
|
||||
#include "tier0/dbg.h"
|
||||
#include "tier1/diff.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
void ApplyDiffs(uint8 const *OldBlock, uint8 const *DiffList,
|
||||
int OldSize, int DiffListSize, int &ResultListSize,uint8 *Output,uint32 OutSize)
|
||||
{
|
||||
uint8 const *copy_src=OldBlock;
|
||||
uint8 const *end_of_diff_list=DiffList+DiffListSize;
|
||||
uint8 const *obuf=Output;
|
||||
while(DiffList<end_of_diff_list)
|
||||
{
|
||||
// printf("dptr=%x ",DiffList-d);
|
||||
uint8 op=*(DiffList++);
|
||||
if (op==0)
|
||||
{
|
||||
uint16 copy_sz=DiffList[0]+256*DiffList[1];
|
||||
int copy_ofs=DiffList[2]+DiffList[3]*256;
|
||||
if (copy_ofs>32767)
|
||||
copy_ofs|=0xffff0000;
|
||||
// printf("long cp from %x to %x len=%d\n", copy_src+copy_ofs-OldBlock,Output-obuf,copy_sz);
|
||||
|
||||
memcpy(Output,copy_src+copy_ofs,copy_sz);
|
||||
Output+=copy_sz;
|
||||
copy_src=copy_src+copy_ofs+copy_sz;
|
||||
DiffList+=4;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (op & 0x80)
|
||||
{
|
||||
int copy_sz=op & 0x7f;
|
||||
int copy_ofs;
|
||||
if (copy_sz==0)
|
||||
{
|
||||
copy_sz=DiffList[0];
|
||||
if (copy_sz==0)
|
||||
{
|
||||
// big raw copy
|
||||
copy_sz=DiffList[1]+256*DiffList[2]+65536*DiffList[3];
|
||||
memcpy(Output,DiffList+4,copy_sz);
|
||||
// printf("big rawcopy to %x len=%d\n", Output-obuf,copy_sz);
|
||||
|
||||
DiffList+=copy_sz+4;
|
||||
Output+=copy_sz;
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_ofs=DiffList[1]+(DiffList[2]*256);
|
||||
if (copy_ofs>32767)
|
||||
copy_ofs|=0xffff0000;
|
||||
// printf("long ofs cp from %x to %x len=%d\n", copy_src+copy_ofs-OldBlock,Output-obuf,copy_sz);
|
||||
|
||||
memcpy(Output,copy_src+copy_ofs,copy_sz);
|
||||
Output+=copy_sz;
|
||||
copy_src=copy_src+copy_ofs+copy_sz;
|
||||
DiffList+=3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_ofs=DiffList[0];
|
||||
if (copy_ofs>127)
|
||||
copy_ofs|=0xffffff80;
|
||||
// printf("cp from %x to %x len=%d\n", copy_src+copy_ofs-OldBlock,Output-obuf,copy_sz);
|
||||
|
||||
memcpy(Output,copy_src+copy_ofs,copy_sz);
|
||||
Output+=copy_sz;
|
||||
copy_src=copy_src+copy_ofs+copy_sz;
|
||||
DiffList++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// printf("raw copy %d to %x\n",op & 127,Output-obuf);
|
||||
memcpy(Output,DiffList,op & 127);
|
||||
Output+=op & 127;
|
||||
DiffList+=(op & 127);
|
||||
}
|
||||
}
|
||||
}
|
||||
ResultListSize=Output-obuf;
|
||||
|
||||
}
|
177
tier1/uniqueid.cpp
Normal file
177
tier1/uniqueid.cpp
Normal file
@ -0,0 +1,177 @@
|
||||
//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
// Unique ID generation
|
||||
//=============================================================================//
|
||||
|
||||
#include "tier0/platform.h"
|
||||
|
||||
#ifdef IS_WINDOWS_PC
|
||||
#include <windows.h> // UUIDCreate
|
||||
#else
|
||||
#include "checksum_crc.h"
|
||||
#endif
|
||||
#include "tier1/uniqueid.h"
|
||||
#include "tier1/utlbuffer.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Creates a new unique id
|
||||
//-----------------------------------------------------------------------------
|
||||
void CreateUniqueId( UniqueId_t *pDest )
|
||||
{
|
||||
#ifdef IS_WINDOWS_PC
|
||||
Assert( sizeof( UUID ) == sizeof( *pDest ) );
|
||||
UuidCreate( (UUID *)pDest );
|
||||
#else
|
||||
// X360/linux TBD: Need a real UUID Implementation
|
||||
Q_memset( pDest, 0, sizeof( UniqueId_t ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Creates a new unique id from a string representation of one
|
||||
//-----------------------------------------------------------------------------
|
||||
bool UniqueIdFromString( UniqueId_t *pDest, const char *pBuf, int nMaxLen )
|
||||
{
|
||||
if ( nMaxLen == 0 )
|
||||
{
|
||||
nMaxLen = Q_strlen( pBuf );
|
||||
}
|
||||
|
||||
char *pTemp = (char*)stackalloc( nMaxLen + 1 );
|
||||
V_strncpy( pTemp, pBuf, nMaxLen + 1 );
|
||||
--nMaxLen;
|
||||
while( (nMaxLen >= 0) && isspace( pTemp[nMaxLen] ) )
|
||||
{
|
||||
--nMaxLen;
|
||||
}
|
||||
pTemp[ nMaxLen + 1 ] = 0;
|
||||
|
||||
while( *pTemp && isspace( *pTemp ) )
|
||||
{
|
||||
++pTemp;
|
||||
}
|
||||
|
||||
#ifdef IS_WINDOWS_PC
|
||||
Assert( sizeof( UUID ) == sizeof( *pDest ) );
|
||||
|
||||
if ( RPC_S_OK != UuidFromString( (unsigned char *)pTemp, (UUID *)pDest ) )
|
||||
{
|
||||
InvalidateUniqueId( pDest );
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
// X360TBD: Need a real UUID Implementation
|
||||
// For now, use crc to generate a unique ID from the UUID string.
|
||||
Q_memset( pDest, 0, sizeof( UniqueId_t ) );
|
||||
if ( nMaxLen > 0 )
|
||||
{
|
||||
CRC32_t crc;
|
||||
CRC32_Init( &crc );
|
||||
CRC32_ProcessBuffer( &crc, pBuf, nMaxLen );
|
||||
CRC32_Final( &crc );
|
||||
Q_memcpy( pDest, &crc, sizeof( CRC32_t ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sets an object ID to be an invalid state
|
||||
//-----------------------------------------------------------------------------
|
||||
void InvalidateUniqueId( UniqueId_t *pDest )
|
||||
{
|
||||
Assert( pDest );
|
||||
memset( pDest, 0, sizeof( UniqueId_t ) );
|
||||
}
|
||||
|
||||
bool IsUniqueIdValid( const UniqueId_t &id )
|
||||
{
|
||||
UniqueId_t invalidId;
|
||||
memset( &invalidId, 0, sizeof( UniqueId_t ) );
|
||||
return !IsUniqueIdEqual( invalidId, id );
|
||||
}
|
||||
|
||||
bool IsUniqueIdEqual( const UniqueId_t &id1, const UniqueId_t &id2 )
|
||||
{
|
||||
return memcmp( &id1, &id2, sizeof( UniqueId_t ) ) == 0;
|
||||
}
|
||||
|
||||
void UniqueIdToString( const UniqueId_t &id, char *pBuf, int nMaxLen )
|
||||
{
|
||||
pBuf[ 0 ] = 0;
|
||||
|
||||
// X360TBD: Need a real UUID Implementation
|
||||
#ifdef IS_WINDOWS_PC
|
||||
UUID *self = ( UUID * )&id;
|
||||
|
||||
unsigned char *outstring = NULL;
|
||||
|
||||
UuidToString( self, &outstring );
|
||||
if ( outstring && *outstring )
|
||||
{
|
||||
Q_strncpy( pBuf, (const char *)outstring, nMaxLen );
|
||||
RpcStringFree( &outstring );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CopyUniqueId( const UniqueId_t &src, UniqueId_t *pDest )
|
||||
{
|
||||
memcpy( pDest, &src, sizeof( UniqueId_t ) );
|
||||
}
|
||||
|
||||
bool Serialize( CUtlBuffer &buf, const UniqueId_t &src )
|
||||
{
|
||||
// X360TBD: Need a real UUID Implementation
|
||||
#ifdef IS_WINDOWS_PC
|
||||
if ( buf.IsText() )
|
||||
{
|
||||
UUID *pId = ( UUID * )&src;
|
||||
|
||||
unsigned char *outstring = NULL;
|
||||
|
||||
UuidToString( pId, &outstring );
|
||||
if ( outstring && *outstring )
|
||||
{
|
||||
buf.PutString( (const char *)outstring );
|
||||
RpcStringFree( &outstring );
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.PutChar( '\0' );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.Put( &src, sizeof(UniqueId_t) );
|
||||
}
|
||||
return buf.IsValid();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Unserialize( CUtlBuffer &buf, UniqueId_t &dest )
|
||||
{
|
||||
if ( buf.IsText() )
|
||||
{
|
||||
int nTextLen = buf.PeekStringLength();
|
||||
char *pBuf = (char*)stackalloc( nTextLen );
|
||||
buf.GetString( pBuf, nTextLen );
|
||||
UniqueIdFromString( &dest, pBuf, nTextLen );
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.Get( &dest, sizeof(UniqueId_t) );
|
||||
}
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
|
||||
|
1753
tier1/utlbuffer.cpp
Normal file
1753
tier1/utlbuffer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
561
tier1/utlbufferutil.cpp
Normal file
561
tier1/utlbufferutil.cpp
Normal file
@ -0,0 +1,561 @@
|
||||
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// $Header: $
|
||||
// $NoKeywords: $
|
||||
//
|
||||
// Serialization buffer
|
||||
//===========================================================================//
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable : 4514)
|
||||
#endif
|
||||
|
||||
#include "tier1/utlbufferutil.h"
|
||||
#include "tier1/utlbuffer.h"
|
||||
#include "mathlib/vector.h"
|
||||
#include "mathlib/vector2d.h"
|
||||
#include "mathlib/vector4d.h"
|
||||
#include "mathlib/vmatrix.h"
|
||||
#include "Color.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include "tier1/utlstring.h"
|
||||
#include "tier1/strtools.h"
|
||||
#include "tier1/characterset.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// For serialization, set the delimiter rules
|
||||
//-----------------------------------------------------------------------------
|
||||
CUtlCharConversion *s_pConv = NULL;
|
||||
const char *s_pUtlBufferUtilArrayDelim = NULL;
|
||||
void SetSerializationDelimiter( CUtlCharConversion *pConv )
|
||||
{
|
||||
s_pConv = pConv;
|
||||
}
|
||||
|
||||
void SetSerializationArrayDelimiter( const char *pDelimiter )
|
||||
{
|
||||
s_pUtlBufferUtilArrayDelim = pDelimiter;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Serialize a floating point number in text mode in a readably friendly fashion
|
||||
//-----------------------------------------------------------------------------
|
||||
static void SerializeFloat( CUtlBuffer &buf, float f )
|
||||
{
|
||||
Assert( buf.IsText() );
|
||||
|
||||
// FIXME: Print this in a way that we never lose precision
|
||||
char pTemp[256];
|
||||
int nLen = Q_snprintf( pTemp, sizeof(pTemp), "%.10f", f );
|
||||
while ( nLen > 0 && pTemp[nLen-1] == '0' )
|
||||
{
|
||||
--nLen;
|
||||
pTemp[nLen] = 0;
|
||||
}
|
||||
if ( nLen > 0 && pTemp[nLen-1] == '.' )
|
||||
{
|
||||
--nLen;
|
||||
pTemp[nLen] = 0;
|
||||
}
|
||||
buf.PutString( pTemp );
|
||||
}
|
||||
|
||||
static void SerializeFloats( CUtlBuffer &buf, int nCount, const float *pFloats )
|
||||
{
|
||||
for ( int i = 0; i < nCount; ++i )
|
||||
{
|
||||
SerializeFloat( buf, pFloats[i] );
|
||||
if ( i != nCount-1 )
|
||||
{
|
||||
buf.PutChar( ' ' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Serialization methods for basic types
|
||||
//-----------------------------------------------------------------------------
|
||||
bool Serialize( CUtlBuffer &buf, const bool &src )
|
||||
{
|
||||
if ( buf.IsText() )
|
||||
{
|
||||
buf.Printf( "%d", src );
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.PutChar( src );
|
||||
}
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
bool Unserialize( CUtlBuffer &buf, bool &dest )
|
||||
{
|
||||
if ( buf.IsText() )
|
||||
{
|
||||
int nValue = 0;
|
||||
int nRetVal = buf.Scanf( "%d", &nValue );
|
||||
dest = ( nValue != 0 );
|
||||
return (nRetVal == 1) && buf.IsValid();
|
||||
}
|
||||
|
||||
dest = ( buf.GetChar( ) != 0 );
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
|
||||
bool Serialize( CUtlBuffer &buf, const int &src )
|
||||
{
|
||||
if ( buf.IsText() )
|
||||
{
|
||||
buf.Printf( "%d", src );
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.PutInt( src );
|
||||
}
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
bool Unserialize( CUtlBuffer &buf, int &dest )
|
||||
{
|
||||
if ( buf.IsText() )
|
||||
{
|
||||
int nRetVal = buf.Scanf( "%d", &dest );
|
||||
return (nRetVal == 1) && buf.IsValid();
|
||||
}
|
||||
|
||||
dest = buf.GetInt( );
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
bool Serialize( CUtlBuffer &buf, const float &src )
|
||||
{
|
||||
if ( buf.IsText() )
|
||||
{
|
||||
SerializeFloat( buf, src );
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.PutFloat( src );
|
||||
}
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
bool Unserialize( CUtlBuffer &buf, float &dest )
|
||||
{
|
||||
if ( buf.IsText() )
|
||||
{
|
||||
// FIXME: Print this in a way that we never lose precision
|
||||
int nRetVal = buf.Scanf( "%f", &dest );
|
||||
return (nRetVal == 1) && buf.IsValid();
|
||||
}
|
||||
|
||||
dest = buf.GetFloat( );
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Attribute types related to vector math
|
||||
//-----------------------------------------------------------------------------
|
||||
bool Serialize( CUtlBuffer &buf, const Vector2D &src )
|
||||
{
|
||||
if ( buf.IsText() )
|
||||
{
|
||||
SerializeFloats( buf, 2, src.Base() );
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.PutFloat( src.x );
|
||||
buf.PutFloat( src.y );
|
||||
}
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
bool Unserialize( CUtlBuffer &buf, Vector2D &dest )
|
||||
{
|
||||
if ( buf.IsText() )
|
||||
{
|
||||
// FIXME: Print this in a way that we never lose precision
|
||||
int nRetVal = buf.Scanf( "%f %f", &dest.x, &dest.y );
|
||||
return (nRetVal == 2) && buf.IsValid();
|
||||
}
|
||||
|
||||
dest.x = buf.GetFloat( );
|
||||
dest.y = buf.GetFloat( );
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
bool Serialize( CUtlBuffer &buf, const Vector &src )
|
||||
{
|
||||
if ( buf.IsText() )
|
||||
{
|
||||
SerializeFloats( buf, 3, src.Base() );
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.PutFloat( src.x );
|
||||
buf.PutFloat( src.y );
|
||||
buf.PutFloat( src.z );
|
||||
}
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
bool Unserialize( CUtlBuffer &buf, Vector &dest )
|
||||
{
|
||||
if ( buf.IsText() )
|
||||
{
|
||||
// FIXME: Print this in a way that we never lose precision
|
||||
int nRetVal = buf.Scanf( "%f %f %f", &dest.x, &dest.y, &dest.z );
|
||||
return (nRetVal == 3) && buf.IsValid();
|
||||
}
|
||||
|
||||
dest.x = buf.GetFloat( );
|
||||
dest.y = buf.GetFloat( );
|
||||
dest.z = buf.GetFloat( );
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
bool Serialize( CUtlBuffer &buf, const Vector4D &src )
|
||||
{
|
||||
if ( buf.IsText() )
|
||||
{
|
||||
SerializeFloats( buf, 4, src.Base() );
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.PutFloat( src.x );
|
||||
buf.PutFloat( src.y );
|
||||
buf.PutFloat( src.z );
|
||||
buf.PutFloat( src.w );
|
||||
}
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
bool Unserialize( CUtlBuffer &buf, Vector4D &dest )
|
||||
{
|
||||
if ( buf.IsText() )
|
||||
{
|
||||
// FIXME: Print this in a way that we never lose precision
|
||||
int nRetVal = buf.Scanf( "%f %f %f %f", &dest.x, &dest.y, &dest.z, &dest.w );
|
||||
return (nRetVal == 4) && buf.IsValid();
|
||||
}
|
||||
|
||||
dest.x = buf.GetFloat( );
|
||||
dest.y = buf.GetFloat( );
|
||||
dest.z = buf.GetFloat( );
|
||||
dest.w = buf.GetFloat( );
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
bool Serialize( CUtlBuffer &buf, const QAngle &src )
|
||||
{
|
||||
if ( buf.IsText() )
|
||||
{
|
||||
SerializeFloats( buf, 3, src.Base() );
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.PutFloat( src.x );
|
||||
buf.PutFloat( src.y );
|
||||
buf.PutFloat( src.z );
|
||||
}
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
bool Unserialize( CUtlBuffer &buf, QAngle &dest )
|
||||
{
|
||||
if ( buf.IsText() )
|
||||
{
|
||||
// FIXME: Print this in a way that we never lose precision
|
||||
int nRetVal = buf.Scanf( "%f %f %f", &dest.x, &dest.y, &dest.z );
|
||||
return (nRetVal == 3) && buf.IsValid();
|
||||
}
|
||||
|
||||
dest.x = buf.GetFloat( );
|
||||
dest.y = buf.GetFloat( );
|
||||
dest.z = buf.GetFloat( );
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
bool Serialize( CUtlBuffer &buf, const Quaternion &src )
|
||||
{
|
||||
if ( buf.IsText() )
|
||||
{
|
||||
SerializeFloats( buf, 4, &src.x );
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.PutFloat( src.x );
|
||||
buf.PutFloat( src.y );
|
||||
buf.PutFloat( src.z );
|
||||
buf.PutFloat( src.w );
|
||||
}
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
bool Unserialize( CUtlBuffer &buf, Quaternion &dest )
|
||||
{
|
||||
if ( buf.IsText() )
|
||||
{
|
||||
// FIXME: Print this in a way that we never lose precision
|
||||
int nRetVal = buf.Scanf( "%f %f %f %f", &dest.x, &dest.y, &dest.z, &dest.w );
|
||||
return (nRetVal == 4) && buf.IsValid();
|
||||
}
|
||||
|
||||
dest.x = buf.GetFloat( );
|
||||
dest.y = buf.GetFloat( );
|
||||
dest.z = buf.GetFloat( );
|
||||
dest.w = buf.GetFloat( );
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
bool Serialize( CUtlBuffer &buf, const VMatrix &src )
|
||||
{
|
||||
if ( buf.IsText() )
|
||||
{
|
||||
buf.Printf( "\n" );
|
||||
SerializeFloats( buf, 4, src[0] );
|
||||
buf.Printf( "\n" );
|
||||
SerializeFloats( buf, 4, src[1] );
|
||||
buf.Printf( "\n" );
|
||||
SerializeFloats( buf, 4, src[2] );
|
||||
buf.Printf( "\n" );
|
||||
SerializeFloats( buf, 4, src[3] );
|
||||
buf.Printf( "\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.Put( &src, sizeof(VMatrix) );
|
||||
}
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
bool Unserialize( CUtlBuffer &buf, VMatrix &dest )
|
||||
{
|
||||
if ( !buf.IsValid() )
|
||||
return false;
|
||||
|
||||
if ( buf.IsText() )
|
||||
{
|
||||
int nRetVal = buf.Scanf( "%f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f",
|
||||
&dest[ 0 ][ 0 ], &dest[ 0 ][ 1 ], &dest[ 0 ][ 2 ], &dest[ 0 ][ 3 ],
|
||||
&dest[ 1 ][ 0 ], &dest[ 1 ][ 1 ], &dest[ 1 ][ 2 ], &dest[ 1 ][ 3 ],
|
||||
&dest[ 2 ][ 0 ], &dest[ 2 ][ 1 ], &dest[ 2 ][ 2 ], &dest[ 2 ][ 3 ],
|
||||
&dest[ 3 ][ 0 ], &dest[ 3 ][ 1 ], &dest[ 3 ][ 2 ], &dest[ 3 ][ 3 ] );
|
||||
return (nRetVal == 16);
|
||||
}
|
||||
|
||||
buf.Get( &dest, sizeof(VMatrix) );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Color attribute
|
||||
//-----------------------------------------------------------------------------
|
||||
bool Serialize( CUtlBuffer &buf, const Color &src )
|
||||
{
|
||||
if ( buf.IsText() )
|
||||
{
|
||||
buf.Printf( "%d %d %d %d", src[0], src[1], src[2], src[3] );
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.PutUnsignedChar( src[0] );
|
||||
buf.PutUnsignedChar( src[1] );
|
||||
buf.PutUnsignedChar( src[2] );
|
||||
buf.PutUnsignedChar( src[3] );
|
||||
}
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
bool Unserialize( CUtlBuffer &buf, Color &dest )
|
||||
{
|
||||
if ( buf.IsText() )
|
||||
{
|
||||
int r = 0, g = 0, b = 0, a = 255;
|
||||
int nRetVal = buf.Scanf( "%d %d %d %d", &r, &g, &b, &a );
|
||||
dest.SetColor( r, g, b, a );
|
||||
return (nRetVal == 4) && buf.IsValid();
|
||||
}
|
||||
|
||||
dest[0] = buf.GetUnsignedChar( );
|
||||
dest[1] = buf.GetUnsignedChar( );
|
||||
dest[2] = buf.GetUnsignedChar( );
|
||||
dest[3] = buf.GetUnsignedChar( );
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
/*
|
||||
//-----------------------------------------------------------------------------
|
||||
// Object ID attribute
|
||||
//-----------------------------------------------------------------------------
|
||||
bool Serialize( CUtlBuffer &buf, const DmObjectId_t &src )
|
||||
{
|
||||
return g_pDataModel->Serialize( buf, src );
|
||||
}
|
||||
|
||||
bool Unserialize( CUtlBuffer &buf, DmObjectId_t &dest )
|
||||
{
|
||||
return g_pDataModel->Unserialize( buf, &dest );
|
||||
}
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Binary buffer attribute
|
||||
//-----------------------------------------------------------------------------
|
||||
bool Serialize( CUtlBuffer &buf, const CUtlBinaryBlock &src )
|
||||
{
|
||||
int nLength = src.Length();
|
||||
if ( !buf.IsText() )
|
||||
{
|
||||
buf.PutInt( nLength );
|
||||
if ( nLength != 0 )
|
||||
{
|
||||
buf.Put( src.Get(), nLength );
|
||||
}
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
// Writes out uuencoded binaries
|
||||
for ( int i = 0; i < nLength; ++i )
|
||||
{
|
||||
if ( (i % 40) == 0 )
|
||||
{
|
||||
buf.PutChar( '\n' );
|
||||
}
|
||||
|
||||
char b1 = src[i] & 0xF;
|
||||
char b2 = src[i] >> 4;
|
||||
|
||||
char c1 = ( b1 <= 9 ) ? b1 + '0' : b1 - 10 + 'A';
|
||||
char c2 = ( b2 <= 9 ) ? b2 + '0' : b2 - 10 + 'A';
|
||||
|
||||
buf.PutChar( c2 );
|
||||
buf.PutChar( c1 );
|
||||
}
|
||||
|
||||
buf.PutChar( '\n' );
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
static int CountBinaryBytes( CUtlBuffer &buf, int *pEndGet )
|
||||
{
|
||||
// This counts the number of bytes in the uuencoded text
|
||||
int nStartGet = buf.TellGet();
|
||||
buf.EatWhiteSpace();
|
||||
*pEndGet = buf.TellGet();
|
||||
int nByteCount = 0;
|
||||
while ( buf.IsValid() )
|
||||
{
|
||||
char c1 = buf.GetChar();
|
||||
char c2 = buf.GetChar();
|
||||
|
||||
bool bIsNum1 = ( c1 >= '0' ) && ( c1 <= '9' );
|
||||
bool bIsNum2 = ( c2 >= '0' ) && ( c2 <= '9' );
|
||||
|
||||
bool bIsAlpha1 = (( c1 >= 'A' ) && ( c1 <= 'F' )) || (( c1 >= 'a' ) && ( c1 <= 'f' ));
|
||||
bool bIsAlpha2 = (( c2 >= 'A' ) && ( c2 <= 'F' )) || (( c2 >= 'a' ) && ( c2 <= 'f' ));
|
||||
|
||||
if ( !(bIsNum1 || bIsAlpha1) || !(bIsNum2 || bIsAlpha2) )
|
||||
break;
|
||||
|
||||
buf.EatWhiteSpace();
|
||||
*pEndGet = buf.TellGet();
|
||||
++nByteCount;
|
||||
}
|
||||
buf.SeekGet( CUtlBuffer::SEEK_HEAD, nStartGet );
|
||||
return nByteCount;
|
||||
}
|
||||
|
||||
inline static unsigned char HexCharToInt( int c1 )
|
||||
{
|
||||
if (( c1 >= '0' ) && ( c1 <= '9' ))
|
||||
return c1 - '0';
|
||||
|
||||
if (( c1 >= 'A' ) && ( c1 <= 'F' ))
|
||||
return 10 + c1 - 'A';
|
||||
|
||||
if (( c1 >= 'a' ) && ( c1 <= 'f' ))
|
||||
return 10 + c1 - 'a';
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
bool Unserialize( CUtlBuffer &buf, CUtlBinaryBlock &dest )
|
||||
{
|
||||
if ( !buf.IsText() )
|
||||
{
|
||||
int nLen = buf.GetInt( );
|
||||
dest.SetLength( nLen );
|
||||
if ( dest.Length() != 0 )
|
||||
{
|
||||
buf.Get( dest.Get(), dest.Length() );
|
||||
}
|
||||
|
||||
if ( nLen != dest.Length() )
|
||||
{
|
||||
buf.SeekGet( CUtlBuffer::SEEK_CURRENT, nLen - dest.Length() );
|
||||
return false;
|
||||
}
|
||||
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
int nEndGet;
|
||||
int nByteCount = CountBinaryBytes( buf, &nEndGet );
|
||||
if ( nByteCount < 0 )
|
||||
return false;
|
||||
|
||||
buf.EatWhiteSpace();
|
||||
int nDest = 0;
|
||||
dest.SetLength( nByteCount );
|
||||
while( buf.TellGet() < nEndGet )
|
||||
{
|
||||
char c1 = buf.GetChar();
|
||||
char c2 = buf.GetChar();
|
||||
|
||||
unsigned char b1 = HexCharToInt( c1 );
|
||||
unsigned char b2 = HexCharToInt( c2 );
|
||||
if ( b1 == 0xFF || b2 == 0xFF )
|
||||
return false;
|
||||
|
||||
dest[ nDest++ ] = b2 | ( b1 << 4 );
|
||||
buf.EatWhiteSpace();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// String attribute
|
||||
//-----------------------------------------------------------------------------
|
||||
bool Serialize( CUtlBuffer &buf, const CUtlString &src )
|
||||
{
|
||||
buf.PutDelimitedString( s_pConv, src.Get() );
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
bool Unserialize( CUtlBuffer &buf, CUtlString &dest )
|
||||
{
|
||||
int nLen = buf.PeekDelimitedStringLength( s_pConv );
|
||||
dest.SetLength( nLen - 1 ); // -1 because the length returned includes space for \0
|
||||
buf.GetDelimitedString( s_pConv, dest.Get(), nLen );
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
334
tier1/utlstring.cpp
Normal file
334
tier1/utlstring.cpp
Normal file
@ -0,0 +1,334 @@
|
||||
//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. =======
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "tier1/utlstring.h"
|
||||
#include "tier1/strtools.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Base class, containing simple memory management
|
||||
//-----------------------------------------------------------------------------
|
||||
CUtlBinaryBlock::CUtlBinaryBlock( int growSize, int initSize ) : m_Memory( growSize, initSize )
|
||||
{
|
||||
m_nActualLength = 0;
|
||||
}
|
||||
|
||||
CUtlBinaryBlock::CUtlBinaryBlock( void* pMemory, int nSizeInBytes, int nInitialLength ) : m_Memory( (unsigned char*)pMemory, nSizeInBytes )
|
||||
{
|
||||
m_nActualLength = nInitialLength;
|
||||
}
|
||||
|
||||
CUtlBinaryBlock::CUtlBinaryBlock( const void* pMemory, int nSizeInBytes ) : m_Memory( (const unsigned char*)pMemory, nSizeInBytes )
|
||||
{
|
||||
m_nActualLength = nSizeInBytes;
|
||||
}
|
||||
|
||||
CUtlBinaryBlock::CUtlBinaryBlock( const CUtlBinaryBlock& src )
|
||||
{
|
||||
Set( src.Get(), src.Length() );
|
||||
}
|
||||
|
||||
void CUtlBinaryBlock::Get( void *pValue, int nLen ) const
|
||||
{
|
||||
Assert( nLen > 0 );
|
||||
if ( m_nActualLength < nLen )
|
||||
{
|
||||
nLen = m_nActualLength;
|
||||
}
|
||||
|
||||
if ( nLen > 0 )
|
||||
{
|
||||
memcpy( pValue, m_Memory.Base(), nLen );
|
||||
}
|
||||
}
|
||||
|
||||
void CUtlBinaryBlock::SetLength( int nLength )
|
||||
{
|
||||
Assert( !m_Memory.IsReadOnly() );
|
||||
|
||||
m_nActualLength = nLength;
|
||||
if ( nLength > m_Memory.NumAllocated() )
|
||||
{
|
||||
int nOverFlow = nLength - m_Memory.NumAllocated();
|
||||
m_Memory.Grow( nOverFlow );
|
||||
|
||||
// If the reallocation failed, clamp length
|
||||
if ( nLength > m_Memory.NumAllocated() )
|
||||
{
|
||||
m_nActualLength = m_Memory.NumAllocated();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
if ( m_Memory.NumAllocated() > m_nActualLength )
|
||||
{
|
||||
memset( ( ( char * )m_Memory.Base() ) + m_nActualLength, 0xEB, m_Memory.NumAllocated() - m_nActualLength );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CUtlBinaryBlock::Set( const void *pValue, int nLen )
|
||||
{
|
||||
Assert( !m_Memory.IsReadOnly() );
|
||||
|
||||
if ( !pValue )
|
||||
{
|
||||
nLen = 0;
|
||||
}
|
||||
|
||||
SetLength( nLen );
|
||||
|
||||
if ( m_nActualLength )
|
||||
{
|
||||
if ( ( ( const char * )m_Memory.Base() ) >= ( ( const char * )pValue ) + nLen ||
|
||||
( ( const char * )m_Memory.Base() ) + m_nActualLength <= ( ( const char * )pValue ) )
|
||||
{
|
||||
memcpy( m_Memory.Base(), pValue, m_nActualLength );
|
||||
}
|
||||
else
|
||||
{
|
||||
memmove( m_Memory.Base(), pValue, m_nActualLength );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CUtlBinaryBlock &CUtlBinaryBlock::operator=( const CUtlBinaryBlock &src )
|
||||
{
|
||||
Assert( !m_Memory.IsReadOnly() );
|
||||
Set( src.Get(), src.Length() );
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
bool CUtlBinaryBlock::operator==( const CUtlBinaryBlock &src ) const
|
||||
{
|
||||
if ( src.Length() != Length() )
|
||||
return false;
|
||||
|
||||
return !memcmp( src.Get(), Get(), Length() );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Simple string class.
|
||||
//-----------------------------------------------------------------------------
|
||||
CUtlString::CUtlString()
|
||||
{
|
||||
}
|
||||
|
||||
CUtlString::CUtlString( const char *pString )
|
||||
{
|
||||
Set( pString );
|
||||
}
|
||||
|
||||
CUtlString::CUtlString( const CUtlString& string )
|
||||
{
|
||||
Set( string.Get() );
|
||||
}
|
||||
|
||||
// Attaches the string to external memory. Useful for avoiding a copy
|
||||
CUtlString::CUtlString( void* pMemory, int nSizeInBytes, int nInitialLength ) : m_Storage( pMemory, nSizeInBytes, nInitialLength )
|
||||
{
|
||||
}
|
||||
|
||||
CUtlString::CUtlString( const void* pMemory, int nSizeInBytes ) : m_Storage( pMemory, nSizeInBytes )
|
||||
{
|
||||
}
|
||||
|
||||
void CUtlString::Set( const char *pValue )
|
||||
{
|
||||
Assert( !m_Storage.IsReadOnly() );
|
||||
int nLen = pValue ? Q_strlen(pValue) + 1 : 0;
|
||||
m_Storage.Set( pValue, nLen );
|
||||
}
|
||||
|
||||
// Returns strlen
|
||||
int CUtlString::Length() const
|
||||
{
|
||||
return m_Storage.Length() ? m_Storage.Length() - 1 : 0;
|
||||
}
|
||||
|
||||
// Sets the length (used to serialize into the buffer )
|
||||
void CUtlString::SetLength( int nLen )
|
||||
{
|
||||
Assert( !m_Storage.IsReadOnly() );
|
||||
|
||||
// Add 1 to account for the NULL
|
||||
m_Storage.SetLength( nLen > 0 ? nLen + 1 : 0 );
|
||||
}
|
||||
|
||||
const char *CUtlString::Get( ) const
|
||||
{
|
||||
if ( m_Storage.Length() == 0 )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
return reinterpret_cast< const char* >( m_Storage.Get() );
|
||||
}
|
||||
|
||||
// Converts to c-strings
|
||||
CUtlString::operator const char*() const
|
||||
{
|
||||
return Get();
|
||||
}
|
||||
|
||||
char *CUtlString::Get()
|
||||
{
|
||||
Assert( !m_Storage.IsReadOnly() );
|
||||
|
||||
if ( m_Storage.Length() == 0 )
|
||||
{
|
||||
// In general, we optimise away small mallocs for empty strings
|
||||
// but if you ask for the non-const bytes, they must be writable
|
||||
// so we can't return "" here, like we do for the const version - jd
|
||||
m_Storage.SetLength( 1 );
|
||||
m_Storage[ 0 ] = '\0';
|
||||
}
|
||||
|
||||
return reinterpret_cast< char* >( m_Storage.Get() );
|
||||
}
|
||||
|
||||
CUtlString &CUtlString::operator=( const CUtlString &src )
|
||||
{
|
||||
Assert( !m_Storage.IsReadOnly() );
|
||||
m_Storage = src.m_Storage;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CUtlString &CUtlString::operator=( const char *src )
|
||||
{
|
||||
Assert( !m_Storage.IsReadOnly() );
|
||||
Set( src );
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool CUtlString::operator==( const CUtlString &src ) const
|
||||
{
|
||||
return m_Storage == src.m_Storage;
|
||||
}
|
||||
|
||||
bool CUtlString::operator==( const char *src ) const
|
||||
{
|
||||
return ( strcmp( Get(), src ) == 0 );
|
||||
}
|
||||
|
||||
CUtlString &CUtlString::operator+=( const CUtlString &rhs )
|
||||
{
|
||||
Assert( !m_Storage.IsReadOnly() );
|
||||
|
||||
const int lhsLength( Length() );
|
||||
const int rhsLength( rhs.Length() );
|
||||
const int requestedLength( lhsLength + rhsLength );
|
||||
|
||||
SetLength( requestedLength );
|
||||
const int allocatedLength( Length() );
|
||||
const int copyLength( allocatedLength - lhsLength < rhsLength ? allocatedLength - lhsLength : rhsLength );
|
||||
memcpy( Get() + lhsLength, rhs.Get(), copyLength );
|
||||
m_Storage[ allocatedLength ] = '\0';
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CUtlString &CUtlString::operator+=( const char *rhs )
|
||||
{
|
||||
Assert( !m_Storage.IsReadOnly() );
|
||||
|
||||
const int lhsLength( Length() );
|
||||
const int rhsLength( Q_strlen( rhs ) );
|
||||
const int requestedLength( lhsLength + rhsLength );
|
||||
|
||||
SetLength( requestedLength );
|
||||
const int allocatedLength( Length() );
|
||||
const int copyLength( allocatedLength - lhsLength < rhsLength ? allocatedLength - lhsLength : rhsLength );
|
||||
memcpy( Get() + lhsLength, rhs, copyLength );
|
||||
m_Storage[ allocatedLength ] = '\0';
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CUtlString &CUtlString::operator+=( char c )
|
||||
{
|
||||
Assert( !m_Storage.IsReadOnly() );
|
||||
|
||||
int nLength = Length();
|
||||
SetLength( nLength + 1 );
|
||||
m_Storage[ nLength ] = c;
|
||||
m_Storage[ nLength+1 ] = '\0';
|
||||
return *this;
|
||||
}
|
||||
|
||||
CUtlString &CUtlString::operator+=( int rhs )
|
||||
{
|
||||
Assert( !m_Storage.IsReadOnly() );
|
||||
Assert( sizeof( rhs ) == 4 );
|
||||
|
||||
char tmpBuf[ 12 ]; // Sufficient for a signed 32 bit integer [ -2147483648 to +2147483647 ]
|
||||
Q_snprintf( tmpBuf, sizeof( tmpBuf ), "%d", rhs );
|
||||
tmpBuf[ sizeof( tmpBuf ) - 1 ] = '\0';
|
||||
|
||||
return operator+=( tmpBuf );
|
||||
}
|
||||
|
||||
CUtlString &CUtlString::operator+=( double rhs )
|
||||
{
|
||||
Assert( !m_Storage.IsReadOnly() );
|
||||
|
||||
char tmpBuf[ 256 ]; // How big can doubles be??? Dunno.
|
||||
Q_snprintf( tmpBuf, sizeof( tmpBuf ), "%lg", rhs );
|
||||
tmpBuf[ sizeof( tmpBuf ) - 1 ] = '\0';
|
||||
|
||||
return operator+=( tmpBuf );
|
||||
}
|
||||
|
||||
int CUtlString::Format( const char *pFormat, ... )
|
||||
{
|
||||
Assert( !m_Storage.IsReadOnly() );
|
||||
|
||||
char tmpBuf[ 4096 ]; //< Nice big 4k buffer, as much memory as my first computer had, a Radio Shack Color Computer
|
||||
|
||||
va_list marker;
|
||||
|
||||
va_start( marker, pFormat );
|
||||
#ifdef _WIN32
|
||||
int len = _vsnprintf( tmpBuf, sizeof( tmpBuf ) - 1, pFormat, marker );
|
||||
#elif defined _LINUX || defined __APPLE__
|
||||
int len = vsnprintf( tmpBuf, sizeof( tmpBuf ) - 1, pFormat, marker );
|
||||
#else
|
||||
#error "define vsnprintf type."
|
||||
#endif
|
||||
va_end( marker );
|
||||
|
||||
// Len < 0 represents an overflow
|
||||
if( len < 0 )
|
||||
{
|
||||
len = sizeof( tmpBuf ) - 1;
|
||||
tmpBuf[sizeof( tmpBuf ) - 1] = 0;
|
||||
}
|
||||
|
||||
Set( tmpBuf );
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Strips the trailing slash
|
||||
//-----------------------------------------------------------------------------
|
||||
void CUtlString::StripTrailingSlash()
|
||||
{
|
||||
if ( IsEmpty() )
|
||||
return;
|
||||
|
||||
int nLastChar = Length() - 1;
|
||||
char c = m_Storage[ nLastChar ];
|
||||
if ( c == '\\' || c == '/' )
|
||||
{
|
||||
m_Storage[ nLastChar ] = 0;
|
||||
m_Storage.SetLength( m_Storage.Length() - 1 );
|
||||
}
|
||||
}
|
||||
|
397
tier1/utlsymbol.cpp
Normal file
397
tier1/utlsymbol.cpp
Normal file
@ -0,0 +1,397 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Defines a symbol table
|
||||
//
|
||||
// $Header: $
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable:4514)
|
||||
#endif
|
||||
|
||||
#include "utlsymbol.h"
|
||||
#include "KeyValues.h"
|
||||
#include "tier0/threadtools.h"
|
||||
#include "tier0/memdbgon.h"
|
||||
#include "stringpool.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#define INVALID_STRING_INDEX CStringPoolIndex( 0xFFFF, 0xFFFF )
|
||||
|
||||
#define MIN_STRING_POOL_SIZE 2048
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// globals
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CUtlSymbolTableMT* CUtlSymbol::s_pSymbolTable = 0;
|
||||
bool CUtlSymbol::s_bAllowStaticSymbolTable = true;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// symbol methods
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CUtlSymbol::Initialize()
|
||||
{
|
||||
// If this assert fails, then the module that this call is in has chosen to disallow
|
||||
// use of the static symbol table. Usually, it's to prevent confusion because it's easy
|
||||
// to accidentally use the global symbol table when you really want to use a specific one.
|
||||
Assert( s_bAllowStaticSymbolTable );
|
||||
|
||||
// necessary to allow us to create global symbols
|
||||
static bool symbolsInitialized = false;
|
||||
if (!symbolsInitialized)
|
||||
{
|
||||
s_pSymbolTable = new CUtlSymbolTableMT;
|
||||
symbolsInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Singleton to delete table on exit from module
|
||||
//-----------------------------------------------------------------------------
|
||||
class CCleanupUtlSymbolTable
|
||||
{
|
||||
public:
|
||||
~CCleanupUtlSymbolTable()
|
||||
{
|
||||
delete CUtlSymbol::s_pSymbolTable;
|
||||
CUtlSymbol::s_pSymbolTable = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
static CCleanupUtlSymbolTable g_CleanupSymbolTable;
|
||||
|
||||
CUtlSymbolTableMT* CUtlSymbol::CurrTable()
|
||||
{
|
||||
Initialize();
|
||||
return s_pSymbolTable;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// string->symbol->string
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CUtlSymbol::CUtlSymbol( const char* pStr )
|
||||
{
|
||||
m_Id = CurrTable()->AddString( pStr );
|
||||
}
|
||||
|
||||
const char* CUtlSymbol::String( ) const
|
||||
{
|
||||
return CurrTable()->String(m_Id);
|
||||
}
|
||||
|
||||
void CUtlSymbol::DisableStaticSymbolTable()
|
||||
{
|
||||
s_bAllowStaticSymbolTable = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// checks if the symbol matches a string
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool CUtlSymbol::operator==( const char* pStr ) const
|
||||
{
|
||||
if (m_Id == UTL_INVAL_SYMBOL)
|
||||
return false;
|
||||
return strcmp( String(), pStr ) == 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// symbol table stuff
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline const char* CUtlSymbolTable::StringFromIndex( const CStringPoolIndex &index ) const
|
||||
{
|
||||
Assert( index.m_iPool < m_StringPools.Count() );
|
||||
Assert( index.m_iOffset < m_StringPools[index.m_iPool]->m_TotalLen );
|
||||
|
||||
return &m_StringPools[index.m_iPool]->m_Data[index.m_iOffset];
|
||||
}
|
||||
|
||||
|
||||
bool CUtlSymbolTable::CLess::operator()( const CStringPoolIndex &i1, const CStringPoolIndex &i2 ) const
|
||||
{
|
||||
// Need to do pointer math because CUtlSymbolTable is used in CUtlVectors, and hence
|
||||
// can be arbitrarily moved in memory on a realloc. Yes, this is portable. In reality,
|
||||
// right now at least, because m_LessFunc is the first member of CUtlRBTree, and m_Lookup
|
||||
// is the first member of CUtlSymbolTabke, this == pTable
|
||||
CUtlSymbolTable *pTable = (CUtlSymbolTable *)( (byte *)this - offsetof(CUtlSymbolTable::CTree, m_LessFunc) ) - offsetof(CUtlSymbolTable, m_Lookup );
|
||||
const char* str1 = (i1 == INVALID_STRING_INDEX) ? pTable->m_pUserSearchString :
|
||||
pTable->StringFromIndex( i1 );
|
||||
const char* str2 = (i2 == INVALID_STRING_INDEX) ? pTable->m_pUserSearchString :
|
||||
pTable->StringFromIndex( i2 );
|
||||
|
||||
if ( !pTable->m_bInsensitive )
|
||||
return strcmp( str1, str2 ) < 0;
|
||||
else
|
||||
return strcmpi( str1, str2 ) < 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// constructor, destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CUtlSymbolTable::CUtlSymbolTable( int growSize, int initSize, bool caseInsensitive ) :
|
||||
m_Lookup( growSize, initSize ), m_bInsensitive( caseInsensitive ), m_StringPools( 8 )
|
||||
{
|
||||
}
|
||||
|
||||
CUtlSymbolTable::~CUtlSymbolTable()
|
||||
{
|
||||
// Release the stringpool string data
|
||||
RemoveAll();
|
||||
}
|
||||
|
||||
|
||||
CUtlSymbol CUtlSymbolTable::Find( const char* pString ) const
|
||||
{
|
||||
if (!pString)
|
||||
return CUtlSymbol();
|
||||
|
||||
// Store a special context used to help with insertion
|
||||
m_pUserSearchString = pString;
|
||||
|
||||
// Passing this special invalid symbol makes the comparison function
|
||||
// use the string passed in the context
|
||||
UtlSymId_t idx = m_Lookup.Find( INVALID_STRING_INDEX );
|
||||
|
||||
#ifdef _DEBUG
|
||||
m_pUserSearchString = NULL;
|
||||
#endif
|
||||
|
||||
return CUtlSymbol( idx );
|
||||
}
|
||||
|
||||
|
||||
int CUtlSymbolTable::FindPoolWithSpace( int len ) const
|
||||
{
|
||||
for ( int i=0; i < m_StringPools.Count(); i++ )
|
||||
{
|
||||
StringPool_t *pPool = m_StringPools[i];
|
||||
|
||||
if ( (pPool->m_TotalLen - pPool->m_SpaceUsed) >= len )
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Finds and/or creates a symbol based on the string
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CUtlSymbol CUtlSymbolTable::AddString( const char* pString )
|
||||
{
|
||||
if (!pString)
|
||||
return CUtlSymbol( UTL_INVAL_SYMBOL );
|
||||
|
||||
CUtlSymbol id = Find( pString );
|
||||
|
||||
if (id.IsValid())
|
||||
return id;
|
||||
|
||||
int len = strlen(pString) + 1;
|
||||
|
||||
// Find a pool with space for this string, or allocate a new one.
|
||||
int iPool = FindPoolWithSpace( len );
|
||||
if ( iPool == -1 )
|
||||
{
|
||||
// Add a new pool.
|
||||
int newPoolSize = MAX( len, MIN_STRING_POOL_SIZE );
|
||||
StringPool_t *pPool = (StringPool_t*)malloc( sizeof( StringPool_t ) + newPoolSize - 1 );
|
||||
pPool->m_TotalLen = newPoolSize;
|
||||
pPool->m_SpaceUsed = 0;
|
||||
iPool = m_StringPools.AddToTail( pPool );
|
||||
}
|
||||
|
||||
// Copy the string in.
|
||||
StringPool_t *pPool = m_StringPools[iPool];
|
||||
Assert( pPool->m_SpaceUsed < 0xFFFF ); // This should never happen, because if we had a string > 64k, it
|
||||
// would have been given its entire own pool.
|
||||
|
||||
unsigned short iStringOffset = pPool->m_SpaceUsed;
|
||||
|
||||
memcpy( &pPool->m_Data[pPool->m_SpaceUsed], pString, len );
|
||||
pPool->m_SpaceUsed += len;
|
||||
|
||||
// didn't find, insert the string into the vector.
|
||||
CStringPoolIndex index;
|
||||
index.m_iPool = iPool;
|
||||
index.m_iOffset = iStringOffset;
|
||||
|
||||
UtlSymId_t idx = m_Lookup.Insert( index );
|
||||
return CUtlSymbol( idx );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Look up the string associated with a particular symbol
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const char* CUtlSymbolTable::String( CUtlSymbol id ) const
|
||||
{
|
||||
if (!id.IsValid())
|
||||
return "";
|
||||
|
||||
Assert( m_Lookup.IsValidIndex((UtlSymId_t)id) );
|
||||
return StringFromIndex( m_Lookup[id] );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Remove all symbols in the table.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CUtlSymbolTable::RemoveAll()
|
||||
{
|
||||
m_Lookup.Purge();
|
||||
|
||||
for ( int i=0; i < m_StringPools.Count(); i++ )
|
||||
free( m_StringPools[i] );
|
||||
|
||||
m_StringPools.RemoveAll();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pFileName -
|
||||
// Output : FileNameHandle_t
|
||||
//-----------------------------------------------------------------------------
|
||||
FileNameHandle_t CUtlFilenameSymbolTable::FindOrAddFileName( const char *pFileName )
|
||||
{
|
||||
if ( !pFileName )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// find first
|
||||
FileNameHandle_t hFileName = FindFileName( pFileName );
|
||||
if ( hFileName )
|
||||
{
|
||||
return hFileName;
|
||||
}
|
||||
|
||||
// Fix slashes+dotslashes and make lower case first..
|
||||
char fn[ MAX_PATH ];
|
||||
Q_strncpy( fn, pFileName, sizeof( fn ) );
|
||||
Q_RemoveDotSlashes( fn );
|
||||
#ifdef _WIN32
|
||||
strlwr( fn );
|
||||
#endif
|
||||
|
||||
// Split the filename into constituent parts
|
||||
char basepath[ MAX_PATH ];
|
||||
Q_ExtractFilePath( fn, basepath, sizeof( basepath ) );
|
||||
char filename[ MAX_PATH ];
|
||||
Q_strncpy( filename, fn + Q_strlen( basepath ), sizeof( filename ) );
|
||||
|
||||
// not found, lock and look again
|
||||
FileNameHandleInternal_t handle;
|
||||
m_lock.LockForWrite();
|
||||
handle.path = m_StringPool.FindStringHandle( basepath );
|
||||
handle.file = m_StringPool.FindStringHandle( filename );
|
||||
if ( handle.path && handle.file )
|
||||
{
|
||||
// found
|
||||
m_lock.UnlockWrite();
|
||||
return *( FileNameHandle_t * )( &handle );
|
||||
}
|
||||
|
||||
// safely add it
|
||||
handle.path = m_StringPool.ReferenceStringHandle( basepath );
|
||||
handle.file = m_StringPool.ReferenceStringHandle( filename );
|
||||
m_lock.UnlockWrite();
|
||||
|
||||
return *( FileNameHandle_t * )( &handle );
|
||||
}
|
||||
|
||||
FileNameHandle_t CUtlFilenameSymbolTable::FindFileName( const char *pFileName )
|
||||
{
|
||||
if ( !pFileName )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Fix slashes+dotslashes and make lower case first..
|
||||
char fn[ MAX_PATH ];
|
||||
Q_strncpy( fn, pFileName, sizeof( fn ) );
|
||||
Q_RemoveDotSlashes( fn );
|
||||
#ifdef _WIN32
|
||||
strlwr( fn );
|
||||
#endif
|
||||
|
||||
// Split the filename into constituent parts
|
||||
char basepath[ MAX_PATH ];
|
||||
Q_ExtractFilePath( fn, basepath, sizeof( basepath ) );
|
||||
char filename[ MAX_PATH ];
|
||||
Q_strncpy( filename, fn + Q_strlen( basepath ), sizeof( filename ) );
|
||||
|
||||
FileNameHandleInternal_t handle;
|
||||
|
||||
m_lock.LockForRead();
|
||||
handle.path = m_StringPool.FindStringHandle(basepath);
|
||||
handle.file = m_StringPool.FindStringHandle(filename);
|
||||
m_lock.UnlockRead();
|
||||
|
||||
if ( handle.path == 0 || handle.file == 0 )
|
||||
return NULL;
|
||||
|
||||
return *( FileNameHandle_t * )( &handle );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : handle -
|
||||
// Output : const char
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CUtlFilenameSymbolTable::String( const FileNameHandle_t& handle, char *buf, int buflen )
|
||||
{
|
||||
buf[ 0 ] = 0;
|
||||
|
||||
FileNameHandleInternal_t *internal = ( FileNameHandleInternal_t * )&handle;
|
||||
if ( !internal )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_lock.LockForRead();
|
||||
const char *path = m_StringPool.HandleToString(internal->path);
|
||||
const char *fn = m_StringPool.HandleToString(internal->file);
|
||||
m_lock.UnlockRead();
|
||||
|
||||
if ( !path || !fn )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Q_strncpy( buf, path, buflen );
|
||||
Q_strncat( buf, fn, buflen, COPY_ALL_CHARACTERS );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CUtlFilenameSymbolTable::RemoveAll()
|
||||
{
|
||||
m_StringPool.FreeAll();
|
||||
}
|
||||
|
||||
void CUtlFilenameSymbolTable::SpewStrings()
|
||||
{
|
||||
m_lock.LockForRead();
|
||||
m_StringPool.SpewStrings();
|
||||
m_lock.UnlockRead();
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user